挂海论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
 友情提示:文字/图片广告均非网站意见,请担保交易勿直接付款,由此产生的责任自负
玩游戏来117游戏网(H5不下载也能玩手游传奇,吃鸡,竞技都有)不懂社区·好资源不错过·各位资源站大佬欢迎来采集搬运IOS签名/udid证书出售/送证书加群1040456405 ██【我要租此广告位】██
... .
查看: 6792|回复: 5
打印 上一主题 下一主题

[讨论交流] 教你游戏中怎么写屏

[复制链接]
3正式会员
253/300

253

积分

143

主题

4

听众
已帮网友解决0 个问题
好评
0
贡献
110
海币
1188
交易币
0
跳转到指定楼层
楼主
发表于 2015-4-22 14:06:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提醒:若下载的软件是收费的"请不要付款",可能是骗子,请立即联系本站举报,执意要付款被骗后本站概不负责。(任何交易请走第三方中介,请勿直接付款交易以免被骗!切记).

友情提示:文字/图片广告均非本站意见,请担保交易勿直接付款,由此产生的责任自负!!!↑↑


说明:本文只适合刚入门不久的盆友,对于还未入门或入门已久的大牛来说本文形同粪草敬请飘过。
关于游戏写屏我们最早看到的可能是传奇2时代的 工具,数字显血这个东西。同类还有在传奇的聊天窗口中显示 启动、关闭等模拟系统的信息。我大概的总结了一下写屏的技巧,事实上常见的有以下几种手段。
1.通过模拟收包函数,模拟一个收到系统发来的消息,让客户端自己将这个消息的文字显示出来
2.通过常说的写屏call来输出文字
3.通过hook  d3dx 设备的函数来将文字绘制出来
前面两种方法有一定的局限性,比如说你可能不能通过前面两种办法来绘制一个图像到游戏中指定的位置,或者其他我们未想到的情况等等。所以第三种方式可能对于我们来说灵活性更大一些。
hook d3dx写屏这个事实上并不是什么新东西,若干年前论坛里面就已经有源码了。自己搜索一下看看就知道了。既然如此我为什么还要在此多此一举的啰嗦呢。简单说我只是对一些新手盆友做
一些详细点的解释,使你明白那些源码为什么要那样做。还有更深层点的是补充说明一下那些源码还欠缺一些东西。
实际上d3dx游戏里面,要写屏只要拿到那个设备对象,在上面直接画出字或者其他东西来就行了,那个设备对象是由CreateDevice这个函数得到的
的,但是你只hook这一个函数的话,虽然能得到设备对象但是你画上字以后会被游戏清除掉,你不停的画不停的被清除就出现闪烁的问题。所以牛人们就想到Present这个函数,hook了这个函数当游戏调用
这个函数的时候再画字就解决了这个问题了,那么整理一下得到下面两点(以下都以d3d9为例)。
1.hook CreateDevice得到设备对象地址
2.hook Present 进行绘制自己的东西(事实上还有其他的函数比如说EndScene这个函数也可以的)
但是很遗憾的是我们要hook的两个函数,在d3d9.dll里面都不是导出函数,你不能简单的通过GetProcAddress来取得。CreateDevice是IDirect3D9这个对象里面的函数,
或者我们简单的理解为这个类里面的一个私有函数就行。 Present 是IDirect3DDevice9这个对象里面的一个函数。这样的话我们就可以整理一下,
1.首先hook  Direct3DCreate9 得到IDirect3D9 这个对象,然后通过这个对象找出CreateDevice 这个函数的地址
2. hook  CreateDevice  得到 IDirect3DDevice9 ,通过IDirect3DDevice9  找到  Present这个函数的地址
3.hook  Present 画字
有了这些你去看源码你就一看就懂了他为什么要那样搞了,至于这些对象的申明Directx 开发包里面有,把库放到你程序里面就行了。


有了上面这些你拿源码搞搞编译一下就可以实现你要的东西了,但是有一个问题,你所你搜到的那些源码这样的处理方式都一样的必须要在游戏还没调用Direct3DCreate9  
这个函数之前就要hook上,否则的话就失效了。因为只有这样他才会触发你的hook. 那么接下来的问题是。如果我想在游戏运行了一段时间才去hook写字怎么办呢?
1.在你的dll里面使用CreateWindow来创建一个窗口
2.使用Direct3DCreate9得到一个IDirect3D9 对象(比如说命名为d3dpp)
3.使用 d3dpp.CreateDevice 来创建一个IDirect3DDevice9对象到你自己创建的那个窗口上
经过上面三个步骤,你就可以得到Present 这个函数的地址 hook上就行了,也就是最终只要这么一个钩子就可以了


综上所述,我们最终的目的就是要找出Present  这个函数的地址。后面这种方式是对现在本论坛里面现有代码的一点补充。至于源码的话我就不贴出来了,论坛里面有。后面补充的这种得到Present函数地址的 方式可以去参考CE6.2或者后面版版本的源码,在DXHookBase这个文件夹下的DXHookBase.cpp里面,GetAddresses这个函数就是了。


联系我时,请说是在 挂海论坛 上看到的,谢谢!



上一篇:激战2根据血量找基址为何找不到
下一篇:用什么工具来查看游戏启动的命令
免责声明:
1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关。一切关于该内容及资源商业行为与www.52ghai.com无关。

2、本站提供的一切资源内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。

3、本站信息来自第三方用户,非本站自制,版权归原作者享有,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

4、如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵犯你版权的,请邮件与我们联系删除(邮箱:xhzlw@foxmail.com),本站将立即改正。

4中级会员
356/600

356

积分

106

主题

9

听众
已帮网友解决0 个问题
好评
0
贡献
250
海币
5042
交易币
0
沙发
发表于 2015-4-22 14:07:10 | 只看该作者
主要对于 HOOK Present 后 如何使用 和 如何对画面的保存!!
3正式会员
253/300

253

积分

143

主题

4

听众
已帮网友解决0 个问题
好评
0
贡献
110
海币
1188
交易币
0
板凳
 楼主| 发表于 2015-4-22 14:07:36 | 只看该作者
Mangosoft 发表于 2015-4-22 14:07
主要对于 HOOK Present 后 如何使用 和 如何对画面的保存!!

你HOOK了,Present 后是可以得到IDirect3DDevice9 这个对象的的指针的,比如说这个指针你的名字叫都d3ddp 那么就d3ddp->GetBackBuffer得到缓冲区表面,然后D3DXSaveSurfaceToFileInMemory 保存下来。
再比如画字的话,D3DXCreateFont()函数创建一个字体对象比如名为MenuFont,然后MenuFont.DrawTextA()这样画出来就行了。很好理解。我上面说主要是
怎么 获得IDirect3DDevice9 这个对象,怎么获得Present  这个地址

93

积分

23

主题

3

听众
已帮网友解决0 个问题
好评
0
贡献
70
海币
2539
交易币
0
地板
发表于 2015-4-22 14:08:11 | 只看该作者
不至于那么麻烦 放两个我写的函数吧
//present的偏移自己决定
//主要给你们一下createfont和drawmytext的方法
ID3DXFont* _stdcall CreateMyFont12(LPDIRECT3DDEVICE9 pDxdevice,int model)
{

//    pDxdevice->BeginScene();//开始绘制
    //
    //
    D3DXFONT_DESCA lf;
    ZeroMemory(&lf, sizeof(D3DXFONT_DESCA));
    if (model==1)
    {
        lf.Height = 16; //字体高度
        lf.Width = 8; // 字体宽度
        lf.Weight = 100;  
    }
    if(model==2){
        lf.Height = 20; //字体高度
        lf.Width =10; // 字体宽度
        lf.Weight = 100;  
    }
    if(model==3){
        lf.Height = 18; //字体高度
        lf.Width =9; // 字体宽度
        lf.Weight = 100;  
    }
    if (model==4)
    {
        lf.Height = 22; //字体高度
        lf.Width =11; // 字体宽度
        lf.Weight = 100;  
    }
        if (model==5)
    {
        lf.Height = 6; //字体高度
        lf.Width =3; // 字体宽度
        lf.Weight = 10;  
    }
    lf.Italic = false;
    lf.CharSet = DEFAULT_CHARSET;
    strcpy(lf.FaceName, "微软雅黑"); // 字型
    ID3DXFont* font=NULL;
    if(D3D_OK!=D3DXCreateFontIndirect(pDxdevice, &lf, &font)) //创建字体对象
        return 0;

    return font;
}
BOOL _stdcall DrawMyText(LPDIRECT3DDEVICE9 pDxdevice,TCHAR* strText ,int nbuf,int x,int y,ID3DXFont* myFont,int colorINT)
{

    RECT myrect;
    myrect.top=y;  //文本块的y坐标
    myrect.left=x; //文本块的左坐标
    myrect.right=500+myrect.left;
    myrect.bottom=500+myrect.top;

    pDxdevice->BeginScene();//开始绘制
    switch(colorINT){
    case 1:    myFont->DrawText(NULL,strText,nbuf,&myrect, DT_TOP | DT_LEFT,D3DCOLOR_XRGB(227,23,13));break;//红色
    case 2: myFont->DrawText(NULL,strText,nbuf,&myrect, DT_TOP | DT_LEFT,D3DCOLOR_XRGB(255,255,255));break;
    case 3: myFont->DrawText(NULL,strText,nbuf,&myrect, DT_TOP | DT_LEFT,D3DCOLOR_XRGB(3,168,158));break; //欢迎字体
    case 4: myFont->DrawText(NULL,strText,nbuf,&myrect, DT_TOP | DT_LEFT,D3DCOLOR_XRGB(0,191,255));break;
    case 5: myFont->DrawText(NULL,strText,nbuf,&myrect, DT_TOP | DT_LEFT,D3DCOLOR_XRGB(255,250,250));break; //白色
    case 6: myFont->DrawText(NULL,strText,nbuf,&myrect, DT_TOP | DT_LEFT,D3DCOLOR_XRGB(30,144,255));break;
    }
    pDxdevice->EndScene();
    return true;
}

直接在present的hook里调用就行了,对了 顺便说一句,如果游戏全屏了 记得切出去的自己释放掉资源,否则会因为丢失设备的原因导致游戏白屏。
3正式会员
203/300

203

积分

69

主题

6

听众
已帮网友解决0 个问题
好评
0
贡献
134
海币
7279
交易币
0
5#
发表于 2015-4-22 14:08:36 | 只看该作者
直接读内存 取 LPDIRECT3DDEVICE9 pDxdevice   设备接口  替换虚函数  

或者直接用偏移 jmp 也行  

5

积分

1

主题

5

听众
已帮网友解决0 个问题
好评
0
贡献
4
海币
246
交易币
0
6#
发表于 2015-4-22 15:26:23 | 只看该作者
rg9695c36 发表于 2015-4-22 14:08
不至于那么麻烦 放两个我写的函数吧
//present的偏移自己决定
//主要给你们一下createfont和drawmytext ...

大神,我遇到的问题就是,切换分辨率设备丢失,导致卡死的,能详细解说一下这个问题吗??
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明|Archiver|手机版|小黑屋|挂海论坛

GMT+8, 2025-4-5 05:42 , Processed in 0.098118 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.2

本站资源来自互联网用户收集发布,如有侵权请邮件与我们联系处理。xhzlw@foxmail.com

快速回复 返回顶部 返回列表