让引擎适应游戏是一件很麻烦的事情。
据说微软曾经为了一个游戏《猎鹿人》运行不了就推迟了Windows XP SP2一个测试版本的发布。当然我们这些做山寨游戏的不能跟微软比。如果你看过《Windows编程启示录》(这本书的名字听起来很高深,但纯粹是一本八卦集锦)的话,你也能体会到微软很多时候的无奈。其实Windows不是那么糟糕的系统,把它搞乱的是那些糟糕的软件。
1. 《苍龙逐日》的错误语句
看过复刻版事件部分源码的朋友应该知道我在3号指令那里写了一段注释:- //这里应该是原本z文件的bug, 如果不处于当前场景, 在连坐标值一起修改时, 并不会同时
- //对S数据进行修改. 而<苍龙逐日>中有几条语句无意中符合了这个bug而造成正确的结果
复制代码 这个错误实在很令人抓狂。因为它仅仅出现了三四次,而且全都是邪线。
2. 《再破菠萝》的跳转口
在内场景主循环中处理跳转口的语句是在《笑梦游记》之后才弄清楚的。原版处理跳转的逻辑实在是莫名其妙,如果能一切重新开始,那么我会选择用一个指令进行跳转,但是在复刻原版和MOD的时候,你必须去适应已有的事件。- if ((sx = RScence[CurScence].JumpX1) and (sy = RScence[CurScence].JumpY1)) and (RScence[CurScence].JumpScence >= 0) then
- begin
- PreScence := CurScence;
- CurScence := Rscence[CurScence].JumpScence;
- if RScence[PreScence].MainEntranceX1 <> 0 then
- begin
- Sx := RScence[CurScence].EntranceX;
- Sy := RScence[CurScence].EntranceY;
- end
- else
- begin
- Sx := RScence[CurScence].JumpX2;
- Sy := RScence[CurScence].JumpY2;
- end;
- InitialScence;
- Drawscence;
- ShowScenceName(CurScence);
- CheckEvent3;
- end;
复制代码 至今甚至很多制作人也没能完全弄清原版的逻辑。
3. 内存相关指令
50指令中的25和26都是内存相关指令,在内存的诸多应用被破译之后,这两个指令的相关事件也多了起来。而复刻版无疑是不能支持这两个指令的。
源码中50指令的25和26部分都是特殊处理,在26指令中有一个类似下面的列表:- $1D295E: x50[e5] := CurScence;
- $1D295A: x50[e5] := Sx;
- $1D295C: x50[e5] := Sy;
- $1C0B88: x50[e5] := Mx;
- $1C0B8C: x50[e5] := My;
- //$1D2956: x50[e5] := Cx;
- //$1D2958: x50[e5] := Cy;
- $05B53A: x50[e5] := 1;
- $0544F2: x50[e5] := Sface;
- $1E6ED6: x50[e5] := x50[28100];
- $556DA: x50[e5] := Ax;
- $556DC: x50[e5] := Ay;
复制代码 而在25指令中,情况更加复杂,因为部分指令是直接读取内存获得物品的信息。
4. 特殊子程
在没有复刻版之前,一些特殊功能的子程是通过带参数的50 43来实现的。其中最重要的应用是新的获取物品和新的对话。
在测试《笑梦游记》的复刻的时候,我发现跳转时代的执行效率非常低,后来经调试锁定问题在新的获取物品指令上。这个指令似乎是直接读内存,在DOS版中效率很高,但是在复刻版中由于执行机制变得效率极低。后来我在43指令中添加了一个列表,即如果发现要执行的子程是“获取物品”,就直接用2号指令代替,因为2号指令我扩充过功能,更加强于50指令编写的事件,更重要的是效率更高。
在猪3中的这个列表似乎更复杂了。
5. 直接执行内部子程
这个就是50 49指令。我认为在我添加的9个50指令中,49指令是最伟大的(吹吹牛)。而在我的说明书中的那个任意转换场景的例子,实际上包含了非常复杂的汇编原理。
但是相比25、26和43,49指令是绝对没可能移植的,甚至给出一个列表也是非常麻烦,因为参数的个数就是很棘手的问题。所以如果你的MOD真的使用了50 49指令,那么在不修改事件的前提下进行移植,基本上是不可能完成的任务。
所幸50 49还未传开。
下面就是50 49的源码,以此记念这个特殊时期的产物。- ; 调用系统子程
- _instruct_32_31_CallProcedure proc near ; DATA XREF: dseg02:0005D0C8o
- pusha
- mov eax, [esp+20h+arg_4]
- shl eax, 10h
- xor ebx, ebx
- mov bx, [esp+20h+arg_0]
- add eax, ebx
- add eax, (offset set_textmode-20000h)
- mov ebp, eax
- mov ecx, [esp+20h+arg_8]
- mov esi, [esp+20h+arg_C]
- imul edi, esi, 4
- cmp esi, 0
- jz short loc_5E6A8
- loc_5E698:
- movsx eax, ds:word_120000[ecx*2] ; 变量空间
- push eax
- inc ecx
- dec esi
- cmp esi, 0
- jnz short loc_5E698
- loc_5E6A8:
- call ebp
- add esp, edi
- mov ecx, [esp+24h+arg_C]
- mov ds:word_120000[ecx*2], ax ; 变量空间
- popa
- retn
复制代码
[ 本帖最后由 weyl 于 2009-9-9 01:42 编辑 ] |