烂大街

 找回密码
 立即注册
搜索
热搜: cf
查看: 744|回复: 6

[游戏补丁] CF1.0窗口化改法,授人以渔

[复制链接]

该用户从未签到

1

主题

12

回帖

1317

积分

金牌嫖友

Rank: 6Rank: 6

UID
459
马尼
1265 枚
贡献
13 次
信誉
0 点
在线时间
6 小时
注册时间
2023-12-25
最后登录
2024-5-23
发表于 2024-2-28 23:21:20 | 显示全部楼层 |阅读模式
本帖最后由 MotherShip 于 2024-2-28 23:29 编辑

我看我这窗口化补丁被人搬来搬去,干脆发个改法,免得哪个服要是改了游戏主程序就不能用了。



搞窗口化分几步,首先1.0不是真d3d全屏,它只是强行改了系统分辨率,然后跑了个相同分辨率的无边框窗口


然后切屏幕会卡死,也就是停止渲染,那么我们分几步走


  • 修改窗口样式:




patch crossfirebase.dll 10001120位置的函数(如果是游戏内的地址就是1F1120)
找到这段汇编,是一段改窗口样式的汇编
  1. mov eax,dword ptr ds:[eax+2E981C]
  2. push 94000000
  3. push FFFFFFF0
  4. push eax
  5. call dword ptr ds:[<&SetWindowLongA>]
复制代码
将原来的94000000(无边框窗口)改为94CF0000即可

  • 去掉设置分辨率为800*600


patch crossfirebase.dll 10001120位置的函数(如果是游戏内的地址就是1F1120)

伪C代码:

  1. pfVar1 = ChangeDisplaySettingsA;
  2. //... 不重要,略
  3.    iVar2 = ChangeDisplaySettingsA(&stack0xfffffea0, 2);
  4.    if (iVar2 == 0) {
  5.       iVar2 = pfVar1(&pdStack348, 4);
  6.       if (iVar2 == 0) {
  7.          goto code_r0x10001295;
  8.       }
  9.    }
  10.    sub_10001BAC();
  11.    return;
复制代码


重点是这里有2次改分辨率,应该是探测了一次能否改为原分辨率,能改就改成800*600

第二次改分辨率不直观,代码先把改分辨率函数的地址扔给了寄存器(伪C代码识别成了把函数指针扔给临时变量),再调寄存器的函数,不过调试器的提示会帮还
原。

找到对应反汇编:

  1. push 4
  2. lea edx,dword ptr ss:[esp+10]
  3. push edx
  4. call esi
复制代码


NOP填充即可

  • 去掉失焦时不渲染


patch crossfire.exe的监听事件的窗口过程函数62D4F0


伪C代码:

  1.       case 0x1c:
  2.          if (dword_6E937C == 0) {
  3.             if (dword_6E9840 == 0) {
  4.                if (param_3 == 0) {
  5.                   if (dword_6E9838 == 0) {
  6.                      dword_6E9838 = 1;
  7.                      dword_6E9834 = 1;
  8.                      (*(func**)(*dword_6E6E88 + 0xb8))(0);
  9.                      (*(func**)(*dword_6E6E88 + 0xb0))(1);
  10.                      (*(func**)(*dword_6E6E88 + 0x1c))(6, 0);
  11.                      OutputDebugStringA("<font color="#ff0000">Losing focus.. shutting down renderer.\n</font>");
  12.                      sub_5CDAD0(1, 0);
  13.                      sub_622870();
  14.                      if ((dword_6E983C == 0) && (iVar2 = sub_583B70(), *(char*)(iVar2 + 0x12a) != '\0')) {
  15.                         sub_583B70();
  16.                         sub_5834B0();
  17.                      }
  18.                      (*(func**)(*dword_6E6E88 + 0xb8))(1);
  19.                   }
  20.                }
复制代码

看这个调试日志就知道,失去焦点时候会暂停掉游戏渲染引擎,直接干掉if块里所有函数调用就行,先找到汇编:

  1. push crossfire.690554
  2. call dword ptr ds:[<&OutputDebugStringA>]
复制代码

这里690954就是日志内容的常量位置,继续寻找上下文,因为if块里的内容是从两次赋值开始,一次函数指针调用结束,往上往下找到这些汇编,用nop填充即可:

  1. ; 约等于开头的赋值
  2. mov dword ptr ds:[6E9838],1
  3. mov dword ptr ds:[6E9834],1
  4. ; 三次基于地址+偏移的函数调用
  5. push 0
  6. mov eax,dword ptr ds:[6E6E88]
  7. mov edx,dword ptr ds:[eax]
  8. mov ecx,dword ptr ds:[6E6E88]
  9. mov eax,dword ptr ds:[edx+B8]
  10. call eax
  11. push 1
  12. mov ecx,dword ptr ds:[6E6E88]
  13. mov edx,dword ptr ds:[ecx]
  14. mov ecx,dword ptr ds:[6E6E88]
  15. mov eax,dword ptr ds:[edx+B0]
  16. call eax
  17. push 0
  18. push 6
  19. mov ecx,dword ptr ds:[6E6E88]
  20. mov edx,dword ptr ds:[ecx]
  21. mov ecx,dword ptr ds:[6E6E88]
  22. mov eax,dword ptr ds:[edx+1C]
  23. call eax
  24. ; 打日志
  25. push crossfire.690554
  26. call dword ptr ds:[<&OutputDebugStringA>]
  27. ; 5CDAD0函数的调用
  28. push 0
  29. push 1
  30. call <crossfire.begin of sub_5CDAD0>
  31. ; 以下略,参考伪C代码
  32. add esp,8
  33. mov ecx,dword ptr ds:[6E92E4]
  34. call <crossfire.begin of sub_622870>
  35. cmp dword ptr ds:[6E983C],0
  36. jne crossfire.62D9A5
  37. call <crossfire.begin of sub_583B70>
  38. mov dword ptr ss:[ebp-3FC],eax
  39. mov ecx,dword ptr ss:[ebp-3FC]
  40. mov dl,byte ptr ds:[ecx+12A]
  41. mov byte ptr ss:[ebp-3FD],dl
  42. movzx eax,byte ptr ss:[ebp-3FD]
  43. test eax,eax
  44. je crossfire.62D9A5
  45. call <crossfire.begin of sub_583B70>
  46. mov ecx,eax
  47. call <crossfire.begin of sub_5834B0>
  48. ; 约等于最后的函数指针调用
  49. push 1
  50. mov ecx,dword ptr ds:[6E6E88]
  51. mov edx,dword ptr ds:[ecx]
  52. mov ecx,dword ptr ds:[6E6E88]
  53. mov eax,dword ptr ds:[edx+B8]
  54. call eax
复制代码


  • 去掉鼠标基于屏幕坐标锁定,改为基于游戏窗口左上角坐标锁定,patch crossfire.exe的事件循环函数62F7A0


伪C代码:

  1.             if ((dword_6DDB30 != 0) && (dword_6E9838 == 0)) {
  2.                qStack20 = (double)(&iStack108, pdStack12[0x11]);
  3.                pdStack24 = (dword*)0x63043c;
  4.                GetWindowRect();
  5.                pdStack24 = (dword*)((iStack96 - iStack104) / 2);
  6.                pdStack28 = (dword*)((iStack100 - iStack108) / 2);
  7.                piStack32 = (int32_t*)0x63045a;
  8.                SetCursorPos();
  9.             }
复制代码

GetWindowRect()获取游戏窗口4个点,然后SetCursorPos()锁在屏幕左上角+游戏宽高/2的地方

对应汇编:

  1. mov edx,dword ptr ss:[ebp-8]
  2. mov eax,dword ptr ds:[edx+44]
  3. push eax
  4. call dword ptr ds:[<&GetWindowRect>]
  5. mov eax,dword ptr ss:[ebp-5C]
  6. sub eax,dword ptr ss:[ebp-64]
  7. cdq
  8. sub eax,edx
  9. sar eax,1
  10. push eax
  11. mov eax,dword ptr ss:[ebp-60]
  12. sub eax,dword ptr ss:[ebp-68]
  13. cdq
  14. sub eax,edx
  15. sar eax,1
  16. push eax
  17. call dword ptr ds:[<&SetPhysicalCursorPos>]
复制代码


找到对应汇编,GetWindowRect调用结束后,EBP+偏移的这四个栈上地址分别是窗口的左上角、右下角的x y坐标位置。

这里直接改成这样(注意,把sub改成mov之后,后面的修改不能用逐行汇编,需要先选中原来的cdq、sub、sar三个语句,然后直接按汇编的注释改16进制):
  1. <div align="left"><font color="rgb(51, 51, 51)"><font face="黑体" size="2">
  2. </font></font></div><font face="黑体">mov eax,dword ptr ss:[ebp-5C]
  3. ; 把窗口左上角Y坐标覆盖到eax寄存器,而不是原先的用来做减法
  4. mov eax,dword ptr ss:[ebp-64]
  5. ; X坐标+300像素,16进制05 2C 01 00 00
  6. add eax,12C
  7. push eax
  8. mov eax,dword ptr ss:[ebp-60]
  9. ; 把窗口左上角X坐标覆盖到eax寄存器,而不是原先的用来做减法
  10. mov eax,dword ptr ss:[ebp-68]
  11. ; X坐标+400像素,16进制05 90 01 00 00
  12. add eax,190
  13. push eax
  14. call dword ptr ds:[<&SetPhysicalCursorPos>]</font>
复制代码



就可以强制把鼠标锁在窗口左上角+横向右移400,纵向下移300的地方,这样只是默认分辨率下锁在中间其实只要距离边框够远就不会被甩出去,所以也懒得想怎么算中点了(可能字节数也不够)



直接把markdown丢过来之后排版乱七八糟的,富文本编辑器果然不行啊.jpg

评分

参与人数 1马尼 +1000 收起 理由
admin + 1000 我都穷了

查看全部评分

回复

使用道具 举报

该用户从未签到

3

主题

70

回帖

3673

积分

论坛元老

Rank: 8Rank: 8

UID
735
马尼
2596 枚
贡献
333 次
信誉
0 点
在线时间
49 小时
注册时间
2024-2-1
最后登录
2024-4-17
发表于 2024-2-29 00:00:17 来自手机 | 显示全部楼层
……膜拜大佬
回复

使用道具 举报

该用户从未签到

0

主题

37

回帖

1828

积分

金牌嫖友

Rank: 6Rank: 6

UID
952
马尼
1080 枚
贡献
237 次
信誉
5 点
在线时间
23 小时
注册时间
2024-2-26
最后登录
2024-10-30
发表于 2024-2-29 03:42:00 来自手机 | 显示全部楼层
可以附上改好的文件嘛?
回复

使用道具 举报

该用户从未签到

4

主题

23

回帖

7582

积分

论坛元老

Rank: 8Rank: 8

UID
965
马尼
7420 枚
贡献
45 次
信誉
0 点
在线时间
14 小时
注册时间
2024-2-28
最后登录
2024-5-29
发表于 2024-2-29 07:39:53 | 显示全部楼层
jhfyvc 发表于 2024-2-29 03:42
可以附上改好的文件嘛?

CF1.0窗口化补丁
https://suime.cn/thread-428-1-1.html
(出处: 烂大街)
回复

使用道具 举报

  • TA的每日心情
    开心
    昨天 09:59
  •  成长值: 1060

    7

    主题

    100

    回帖

    1万

    积分

    永久VIP

    Rank: 9Rank: 9Rank: 9

    UID
    629
    马尼
    15199 枚
    贡献
    289 次
    信誉
    0 点
    在线时间
    263 小时
    注册时间
    2024-1-17
    最后登录
    2024-11-22
    发表于 2024-2-29 09:17:52 | 显示全部楼层
    太帅了兄弟
    回复

    使用道具 举报

    该用户从未签到

    29

    主题

    188

    回帖

    1万

    积分

    论坛神仙

    Rank: 9Rank: 9Rank: 9

    UID
    106
    马尼
    10208 枚
    贡献
    223 次
    信誉
    0 点
    在线时间
    198 小时
    注册时间
    2023-10-3
    最后登录
    2024-11-4
    发表于 2024-2-29 09:25:02 | 显示全部楼层
    jhfyvc 发表于 2024-2-29 03:42
    可以附上改好的文件嘛?

    https://suime.cn/thread-388-1-1.html 免费不收马尼
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    28

    回帖

    251

    积分

    中级嫖友

    Rank: 3Rank: 3

    UID
    885
    马尼
    190 枚
    贡献
    11 次
    信誉
    0 点
    在线时间
    7 小时
    注册时间
    2024-2-20
    最后登录
    2024-3-15
    发表于 2024-2-29 09:36:32 | 显示全部楼层
    牛逼大佬
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    Archiver|手机版|小黑屋|烂大街

    GMT+8, 2024-11-23 04:09 , Processed in 0.786588 second(s), 28 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

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