查看完整版本: 修改z.dat简明指南

weyl 2008-1-18 21:48

修改z.dat简明指南

[font=宋体][size=2]z.dat文件是《金庸群侠传》的主程序文件。对它的修改可以改变原版中很多功能,甚至增添一些功能。

[/size][/font][font=宋体][size=2]论坛上有很多已有的修改方法,许多时候你只要照着做就行了。但是如果你认为你的水平足够高,足够有耐心,想自己进行一些独特的修改,你可以参考一下这篇文章,也许它可以让你少走一些弯路。如果你做出一些优秀的修改,希望能够放上来与大家共享。


[/size][/font][font=宋体][size=2][b]什么时候需要修改z.dat文件?
[/b]由于游泳的鱼增添了50指令系统,可以做出很多特殊的效果。因此当你想到一个功能的时候,可以先想想能否用事件实现。尽管50指令集并不易懂,但是比起十六进制和汇编代码,可读性强了很多。
当你确定你所要实现的功能不能用事件实现的话,就可以试着修改z.dat文件。下面我会举出一些例子,由浅入深进行说明。


[/size][/font][size=2][font=宋体][b]准备工作
[/b]首先你要有游戏的原版文件,之后用游泳的鱼发布的新版z.dat替换掉原版,推荐使用0.72版,这是目前的最新版,而且短时间内似乎没有更新的迹象。同时,你可能需要场景贴图合并文件,还有手动增加一个atk024.wav。
论坛上有一份注释过的z.dat反汇编说明,阅读这些注释,你可以获得游戏的很多信息,并节省你自己分析的时间。

你还需要如下软件:
[b]IDA 5.2[/b],反汇编文件需要它打开。
[b]OllyDBG[/b],翻译十六进制代码与汇编指令。z.dat是DOS程序,难以直接调试,OllyDBG只能发挥翻译指令的作用。
[b]UltraEdit[/b],[b]WinHex[/b],两者都是十六进制编辑器,功能基本相同,看个人使用习惯选用。因为不能直接进行调试,所以很多时候需要先用OllyDBG翻译指令为十六进制代码,再手动写入文件里。[/font]
[/size][font=宋体][size=2][b]C32Asm[/b]可以代替上面两个软件的功能,尽管我还不习惯使用,但推荐这个。
[b]Fish修改器[/b],一些已知的修改,测试需要的不同存档,用此修改。
[color=red]另外,需要你有汇编语言基础,至少你要能看懂汇编指令的含义,了解内存中数据的保存方式,知道我下面所用到的一些名词。[/color]如果你发现有些地方难以理解,首先要做的可能是学习汇编,而不是提问。



[/size][/font][font=宋体][size=2][b]修改方法及实例
[/b]

[/size][/font][font=宋体][size=2][b]一、替换
[/b]
这是指不必修改代码,仅仅修改相关数据即可。代码长度并不会变化。

[b]1、数值替换[/b]

例1:改变中毒效果,使中毒损血增加。

经过研读z.dat文件及相关注释,认为以下语句控制中毒损血程度:

[/size][/font][font=宋体][size=2][color=darkslateblue]dseg02:0003C603                 mov     esi, 0Ah
dseg02:0003C60F                 mov     eax, edx
dseg02:0003C611                 sar     edx, 1Fh
dseg02:0003C614                 idiv    esi
[/color]
中毒损血=中毒程度/10,即十六进制0A,改掉0A所在位置即可。

[b]2、地址替换[/b]

例2:去掉“用毒”的显示,在原位置显示“道德”。

在代码中可以找到:

[color=darkslateblue]dseg02:000231D3                 movsx   eax, word_901AA[ebx] ; 用毒能力[/color]

对应十六进制代码:0F BF 83 [color=red]AA 01 09 00[/color]

但是修改之后发现没有效果。这是因为在编译时凡是用到地址的部分,代码段所写的地址是无效的,程序在运行时会在“重定位表”中寻找真实的地址。

[color=red]AA 01 09 00[/color]从地址[color=red]231D6[/color]开始,那么减掉20000,在重定位表中查找“[color=red]031D6[/color]”,你可能找到:

[/size][/font][font=宋体][size=2][color=darkslateblue]        Target : Internal reference
                Object(8)  #02
                Offset(32) 0021005E
        Source : 32-bit offset fixup (32-bits)
                           2.000031D6[/color]

上面的[color=red]0021005E[/color]才是“用毒”的真实地址。

在z.dat里查找[color=red]5E002100[/color],你会找到:

[color=darkslateblue]07 10[/color][color=red] D6 01[/color] [color=darkslateblue]02[/color] [color=red]5E 00 21 00[/color]

07,10,02都是标志位,D6 01就是1D6,与你地址的后3位相同,不必怀疑,就是它了。那么把后面的[color=red]5E 00 21[/color]改为[color=red]70 00 21[/color],保存,进游戏看看效果。


[b]二、改写指令[/b]

这类修改通常指新的指令比原来的指令要短,不够的地方可以用nop占位,无需改写空白部分。

[/size][/font][font=宋体][size=2]例3:使升级增加属性固定

研读升级段代码:

[/size][/font][color=darkslateblue][font=宋体][size=2].........
dseg02:0003B7CA                 cmp     word_901C4[eax], 5Ah ; 资质
dseg02:0003B7D2                 jge     short loc_3B7D8
[/size][/font][font=宋体][size=2][color=red]dseg02:0003B7D4                 push    5
[/color]dseg02:0003B7D6                 jmp     short loc_3B7DA
dseg02:0003B7D8
dseg02:0003B7D8 loc_3B7D8:                              ; CODE XREF: sub_3B6BE+114j
[color=red]dseg02:0003B7D8                 push    6[/color]               ; randmax
dseg02:0003B7DA
dseg02:0003B7DA loc_3B7DA:                              ; CODE XREF: sub_3B6BE+EEj
dseg02:0003B7DA                                         ; sub_3B6BE+FCj ...
[/size][/font][font=宋体][size=2][color=red]dseg02:0003B7DA                 call    random??
[/color][/size][/font][font=宋体][size=2][color=red]dseg02:0003B7DF                 add     esp, 4
[/color][/size][/font][font=宋体][size=2][color=red]dseg02:0003B7E2                 lea     [b]edi[/b], [eax+1]
[/color].........
[color=red]dseg02:0003B89C                 add     word_901A2[ebx], [b]di[/b][/color]; 攻击力
.........
[/size][/font][/color]
[font=宋体][size=2]之前的大段代码是根据资质,将一个数压入栈,之后调用随机数过程,清栈,令edi=eax+1,di是edi的低位部分。
[/size][/font][font=宋体][size=2]通常call的返回值在eax里面,那么利用这一点,将刚才入栈的值直接取回到eax。另外我们发现random(x)过程会返回0~x-1中的某个值,为使与原版效果相同,再将eax减1。

[/size][/font][font=宋体][size=2][color=darkslateblue]dseg02:0003B7DA                 pop     eax
dseg02:0003B7DB                 dec     eax[/color]

原版的call指令是5字节,add指令3字节,修改之后的两个指令只有2字节,长度不够的地方用6个nop(90)填补。


[/size][/font][font=宋体][size=2][b]三、增加指令
[/b]
增加显示功能,改写伤害公式等都属于这方面。特点是修改的代码比原代码要长。

首先你要研究原来的代码,找一个适合的地方,改写为call指令或jmp指令。
最好你改写的地方[color=red]没有地址的调用,没有对栈的操作,没有跳转指令,只有对寄存器的操作[/color]。还要足够长,至少5个字节。

在z.dat的空白位置,添加你的指令。你所用到的寄存器根据具体情况决定是否先要将原值入栈。如果添加了地址调用还要改写重定位表。在游泳的鱼发布的新版z.dat中重定位表有大量剩余空间,这是为何推荐使用新版的原因。最后根据根据情况把原来替换掉的指令写在新加程序段的开头或结尾。

例4:完全解除等级上限

先参考一下这里:[/size][/font][url=http://www.txdx.net/viewthread.php?tid=393071&extra=page%3D1][font=宋体][size=2]http://www.txdx.net/viewthread.php?tid=393071&extra=page%3D1[/size][/font][/url]

[font=宋体][size=2]研读升级部分指令:

[/size][/font][font=宋体][size=2][color=darkslateblue].........[/color]
[/size][/font][color=darkslateblue][font=宋体][size=2]dseg02:0003B6CE                 mov     esi, [esp+10h+arg_0]
dseg02:0003B6D2                 [/size][/font][font=宋体][size=2][color=red]imul    eax, esi, 0B6h
[/color]dseg02:0003B6D8                 movsx   edx, word_9016A[eax] ; 等级
dseg02:0003B6DF                 mov     ax, word_9016C[eax] ; 经验值[/size][/font][/color]
[font=宋体][size=2][color=red][b]这里利用ecx,esi计算经验值所在地址,后面要用到[/b][/color]
[/size][/font][font=宋体][size=2][color=darkslateblue].........[/color]
[/size][/font][font=宋体][size=2][color=darkslateblue]dseg02:0003B6FA loc_3B6FA:                              ; CODE XREF: sub_3B6BE+5Aj
dseg02:0003B6FA                 mov     bx, word_9016C[ebx] ; 经验值[/color]
[color=#483d8b][/color]
[/size][/font][color=darkslateblue][font=宋体][size=2][color=red]dseg02:0003B701                 cmp     bx, word_5458E[eax*2] ; 升级经验列表
[/color][/size][/font][color=red][font=宋体][size=2][b]修改此句为
[/b][i]dseg02:0003B701                 sub     bx, word_5458E[eax*2] ; cmp指令不改变bx,但sub指令会将差值送入bx[/i][/size][/font][/color][/color]
[i][color=#ff0000][/color][/i]
[font=宋体][size=2][color=darkslateblue][color=red]dseg02:0003B709                 jb      short loc_3B70E
dseg02:0003B70B                 lea     ecx, [eax+1]
[/color][b][color=red]以上2句占据5字节,可以容纳call指令,修改此2句为[/color][/b]
[i][color=red]dseg02:0003B709                 call    XXXXXXXX[/color][/i][/color]
[color=darkslateblue][/color]
[/size][/font][font=宋体][size=2][color=darkslateblue]dseg02:0003B70E
dseg02:0003B70E loc_3B70E:                              ; CODE XREF: sub_3B6BE+4Bj
dseg02:0003B70E                 inc     eax[/color]
[color=darkslateblue].........[/color]
[color=#483d8b][/color]
[color=red][b]选择适合的空白处添加:[/b][/color]
[/size][/font][font=宋体][size=2][color=red][i]XXXXXXXX:
jb     +12                         ;根据比较结果是否跳转12字节到ret
push   edx                         ;保存edx的值,在原有程序段中,ebx,ecx,eax都被使用过,所以利用edx
imul   edx, esi, 0B6h              ;利用edx,esi计算经验值所在地址
lea    ecx, [eax+01]               ;重复原指令
mov    word_9016C[edx], bx         ;将减后的经验值送入原地址,这句还要添加重定位表
pop    edx                         ;恢复edx的值
ret                                ;返回[/i][/color]

[/size][/font][font=宋体][size=2]你可以试着在头脑中运行改前和改后的程序,看看除了添加的效果之外是否完全一致。


[/size][/font][font=宋体][size=2][b]后记[/b]

修改并不是一件容易的事情,在修改前你最好想一想,要怎样修改,改成什么样子。而在设计汇编的时候,要想到你在使用的寄存器是否在后面会被原来的程序使用。通常代码写错的结果会导致游戏错误而跳出,但是更多时候可能是没有效果。不要灰心,上面所提到的一些实例已经包括了修改z.dat的大部分技术,操作正确就一定可以成功。


[b]常见指令解析[/b]

以下是一些指令的提示(我想到的话会补充)。

1、移位指令和修改方案

[/size][/font][font=宋体][size=2][color=darkslateblue]mov     eax, ebx
shl     eax, 2
sub     eax, ebx
[/color]
实际上是eax=ebx*3,可以用

[/size][/font][font=宋体][size=2][color=darkslateblue]imul    eax, ebx, 3
[/color]
代替,这样3就可以改为别的数字。


2、自加指令和修改方案

[/size][/font][font=宋体][size=2][color=darkslateblue]add     eax, eax
[/color]
实际上是eax=eax*2,这个指令仅有两个字节,可以改成移1位指令、空指令和清除指令(xor),相当于2可以改为1、0和0.5。如果想获得更大的自由度,必须添加转向指令,参考增加指令部分。


3、绘制黑色矩形

以下程序段用于绘制游戏中特有的那种“黑色矩形”,就是你打开“状态”看到的那样。

[/size][/font][font=宋体][size=2][color=darkslateblue]push    3
push    offset array_VRAM
push    0
push    0FFh            ; 以上3个不必管
push    0C8h            ; 高度
push    0D2h            ; 宽度
push    0               ; 起点的纵坐标位置
push    37h             ; 起点的横坐标位置
call    sub_2CEBF
add     esp, 20h        ; 清栈
[/color]

4、显示字符串

以下程序段用于显示游戏中的字符串。

[/size][/font][font=宋体][size=2][color=darkslateblue]push    10h
push    705h
push    offset array_VRAM
push    offset byte_C07C4  ; 字串的地址,修改此处需要改重定位表
push    23h             ; 字串纵坐标位置
push    6Bh             ; 字串横坐标位置
call    draw_string     ; 显示字符串
add     esp, 18h        ; 清栈
[/color]



[/size][/font]

[[i] 本帖最后由 scarscc 于 2008-6-13 22:35 编辑 [/i]]

junbao1111 2008-1-18 22:32

高深啊,谢谢!

黄顺坤 2008-1-19 10:17

恩,用FOSAM看了看,不懂

獨孤劍 2008-1-19 15:40

這東西太難了啦....不會

wzhx1994927 2008-1-19 15:45

搬着板凳自己坐下看...

柳无色 2008-1-19 20:02

很有用,太感谢LZ了[s:06]

君子一剑 2008-1-20 03:12

[s:04] 看来我可以练左右互抽了[s:03]

512935486 2008-1-20 13:45

能不能讲的更明白些,我是菜鸟不大明白[s:04]

jack100200 2008-1-29 23:33

学习中,谢谢楼主的热心!!!

神算仙 2008-5-1 16:54

好像很深奥,让我慢慢研究[s:11]

zc1028 2008-5-1 16:59

[s:16] [s:16] [s:16]

[table=100%,#cbb48a][tr][td][size=9pt][发帖际遇]: [url=http://www.txdx.net/event.php]zc1028看到神仙姐姐蜡像,叩了一千个响头,蒲团被磕破了,发现里面有银两4.
[/url][/font][/td][/tr][/table]

xianglongdaoke 2008-5-16 17:43

不错不错~~~~~~顶~

[table=100%,#cbb48a][tr][td][size=9pt][发帖际遇]: [url=http://www.txdx.net/event.php]xianglongdaoke遭太岳四侠打劫,落荒而逃中丢失银两1.
[/url][/font][/td][/tr][/table]

彭城快驴 2008-6-13 22:25

LZ,请问创建人物时满属性的秘码的地址在哪里修改啊?

找遍论坛也没找到相关的介绍,多谢[s:06]

weyl 2008-6-13 22:31

我最近总结了一个新的“常见问题集合”,去看看吧

彭城快驴 2008-6-13 22:36

怎么形容内心的感受呢,LZ简直就是活菩萨啊!

wuguanran 2008-6-17 00:14

做个三国再战菠萝的修改器啊/....期待中///...[s:06] [s:06]

littleboy85 2008-7-20 16:57

这学期刚开始接触汇编,产生了极大的兴趣……
这个东西似乎很适合我……

[table=100%,#cbb48a][tr][td][size=9pt][发帖际遇]: [url=http://www.txdx.net/event.php]littleboy85看到神仙姐姐蜡像,叩了一千个响头,蒲团被磕破了,发现里面有银两3.
[/url][/font][/td][/tr][/table]

410410410 2008-7-20 17:07

这是什么啊 狂汗不已`

weyl 2008-7-20 17:39

[quote]原帖由 [i]littleboy85[/i] 于 2008-7-20 16:57 发表 [url=http://www.txdx.net/redirect.php?goto=findpost&pid=1153147&ptid=393162][img]http://www.txdx.net/images/common/back.gif[/img][/url]
这学期刚开始接触汇编,产生了极大的兴趣……
这个东西似乎很适合我…… [/quote]

欢迎

txdx字数补丁

[table=100%,#cbb48a][tr][td][size=9pt][发帖际遇]: [url=http://www.txdx.net/event.php]weyl帮张无忌翻译小昭写的情书,得到辛苦费银两19.
[/url][/font][/td][/tr][/table]

王风 2008-8-7 18:08

多谢讲解

原来制作游戏也是一门学问,以前以为很好弄呢。向游戏的制作者们致敬,他们太辛苦了。

XYJKFOX 2008-9-7 15:14

经过对Z.DAT的简单修改研究,再来拜读大大的指南,深有体会啊,大家要认真研究每一个字,字字珠玑,含义深刻!

62093072 2008-9-8 20:22

回复 1# 的帖子

太深奥了[s:04] 看不懂啊[s:07]

有病 2008-9-30 21:00

希望楼主把心得作成电子书

weyl 2008-9-30 21:05

建议不错,可惜我不会啊

[table=100%,#cbb48a][tr][td][size=9pt][发帖际遇]: [url=http://www.txdx.net/event.php]暑假期间,weyl在洛阳绿竹巷报名参加《任盈盈琴箫兴趣班》初级课程,缴纳报名费银两30。
[/url][/font][/td][/tr][/table]

terryymk 2008-12-29 20:27

深奥莫测!谢谢教导!

piao7700 2009-1-2 00:48

学习学习,支持楼主
页: [1]
查看完整版本: 修改z.dat简明指南