| 补充下游戏里的计算代码 
 
 先列出汇编代码,这段代码全是计算,看得倍儿晕,我用IDA转成C才看懂,C代码贴在后面了。汇编代码只做几个注释。
 
 4272C5函数只会依次根据人物的坐标计算位置,并不会对20000个字节依次计算。
 
 004272C5  /$  55            PUSH EBP
 004272C6  |.  8BEC          MOV EBP,ESP
 004272C8  |.  83EC 10       SUB ESP,10
 004272CB  |.  56            PUSH ESI
 004272CC  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]              读取人物的横坐标
 004272CF  |.  33C9          XOR ECX,ECX
 004272D1  |.  66:8B08       MOV CX,WORD PTR DS:[EAX]
 004272D4  |.  C1E1 03       SHL ECX,3
 004272D7  |.  66:894D F0    MOV WORD PTR SS:[EBP-10],CX
 004272DB  |.  8B55 0C       MOV EDX,DWORD PTR SS:[EBP+C]              读取人物的纵坐标
 004272DE  |.  33C0          XOR EAX,EAX
 004272E0  |.  66:8B02       MOV AX,WORD PTR DS:[EDX]
 004272E3  |.  6BC0 F8       IMUL EAX,EAX,-8
 004272E6  |.  66:8945 FC    MOV WORD PTR SS:[EBP-4],AX
 004272EA  |.  8B4D F0       MOV ECX,DWORD PTR SS:[EBP-10]
 004272ED  |.  81E1 FFFF0000 AND ECX,0FFFF
 004272F3  |.  8B55 FC       MOV EDX,DWORD PTR SS:[EBP-4]
 004272F6  |.  81E2 FFFF0000 AND EDX,0FFFF
 004272FC  |.  03CA          ADD ECX,EDX
 004272FE  |.  66:894D F8    MOV WORD PTR SS:[EBP-8],CX
 00427302  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
 00427305  |.  33C9          XOR ECX,ECX
 00427307  |.  66:8B08       MOV CX,WORD PTR DS:[EAX]
 0042730A  |.  8B55 0C       MOV EDX,DWORD PTR SS:[EBP+C]
 0042730D  |.  33C0          XOR EAX,EAX
 0042730F  |.  66:8B02       MOV AX,WORD PTR DS:[EDX]
 00427312  |.  03C8          ADD ECX,EAX
 00427314  |.  C1E1 02       SHL ECX,2
 00427317  |.  8B55 10       MOV EDX,DWORD PTR SS:[EBP+10]
 0042731A  |.  81E2 FFFF0000 AND EDX,0FFFF
 00427320  |.  C1E2 03       SHL EDX,3
 00427323  |.  2BCA          SUB ECX,EDX
 00427325  |.  66:894D F4    MOV WORD PTR SS:[EBP-C],CX
 00427329  |.  8B75 F8       MOV ESI,DWORD PTR SS:[EBP-8]
 0042732C  |.  81E6 FFFF0000 AND ESI,0FFFF
 00427332  |.  6A 08         PUSH 8                                   ; /Arg1 = 00000008
 00427334  |.  E8 7DF8FFFF   CALL 00426BB6
 00427339  |.  83C4 04       ADD ESP,4
 0042733C  |.  25 FFFF0000   AND EAX,0FFFF
 00427341  |.  C1E0 03       SHL EAX,3
 00427344  |.  99            CDQ
 00427345  |.  2BC2          SUB EAX,EDX
 00427347  |.  D1F8          SAR EAX,1
 00427349  |.  8D4406 F8     LEA EAX,DWORD PTR DS:[ESI+EAX-8]
 0042734D  |.  66:8945 F8    MOV WORD PTR SS:[EBP-8],AX
 00427351  |.  33C9          XOR ECX,ECX
 00427353  |.  66:8B0D B4CE4>MOV CX,WORD PTR DS:[49CEB4]              49CEB4=60
 0042735A  |.  C1E1 03       SHL ECX,3
 0042735D  |.  66:8B55 F8    MOV DX,WORD PTR SS:[EBP-8]
 00427361  |.  66:2BD1       SUB DX,CX
 00427364  |.  66:8955 F8    MOV WORD PTR SS:[EBP-8],DX
 00427368  |.  33C0          XOR EAX,EAX
 0042736A  |.  66:A1 B6CE490>MOV AX,WORD PTR DS:[49CEB6]              49CEB6=25
 00427370  |.  8D0CC5 F8FFFF>LEA ECX,DWORD PTR DS:[EAX*8-8]
 00427377  |.  66:8B55 F4    MOV DX,WORD PTR SS:[EBP-C]
 0042737B  |.  66:2BD1       SUB DX,CX
 0042737E  |.  66:8955 F4    MOV WORD PTR SS:[EBP-C],DX
 00427382  |.  8B45 08       MOV EAX,DWORD PTR SS:[EBP+8]
 00427385  |.  66:8B4D F8    MOV CX,WORD PTR SS:[EBP-8]
 00427389  |.  66:8908       MOV WORD PTR DS:[EAX],CX
 0042738C  |.  8B55 0C       MOV EDX,DWORD PTR SS:[EBP+C]
 0042738F  |.  66:8B45 F4    MOV AX,WORD PTR SS:[EBP-C]
 00427393  |.  66:8902       MOV WORD PTR DS:[EDX],AX
 00427396  |.  5E            POP ESI
 00427397  |.  8BE5          MOV ESP,EBP
 00427399  |.  5D            POP EBP
 0042739A  \.  C3            RETN
 
 
 49CEB4和49CEB6的值在这里改。但改了人物也只有垂直或水平方向的偏移。
 00429828  |.  66:C745 F8 3C>MOV WORD PTR SS:[EBP-8],3C
 0042982E  |.  66:C745 F4 19>MOV WORD PTR SS:[EBP-C],19
 
 0042984F  |.  66:8B4D F4    MOV CX,WORD PTR SS:[EBP-C]
 00429853  |.  66:890D B6CE4>MOV WORD PTR DS:[49CEB6],CX
 0042985A  |.  66:8B55 F8    MOV DX,WORD PTR SS:[EBP-8]
 0042985E  |.  66:8915 B4CE4>MOV WORD PTR DS:[49CEB4],DX
 
 
 
 =======================================
 
 int16 cdecl sub_4272C5(int a1, int a2, int16 a3)
 
 int16 result; // ax@1
 int16 v4; // ST0C_2@1
 
 v4 = 4 *(a2 + a1)-8 * a3-(8 * word_49CEB6 - 8);
 a1 = -8*a2 + 8*a1 + 8 * (unsigned __int16)sub_426BB6(8) / 2 - 8 - 8 * word_49CEB4;
 result = v4;
 a2 = v4;
 return result;
 }
 
 其中
 a1=游戏里横坐标
 a2=游戏里纵坐标
 
 a3=0
 (unsigned __int16)sub_426BB6(8)的输出值是0C8H,也就是200。(这两个值是否浮动还未知。)
 
 word_49CEB6=19H。
 word_49CEB4=3CH。
 
 
 所以计算得到的公式:
 设bmp里横坐标为x  (0<x<640)
 纵坐标为y  (0<y<400)
 游戏里横坐标为a
 纵坐标为b
 
 
 x= 4*(b + a)-8*0-(8*25-8)
 
 y= -8*b + 8*a + 8*200/2-8-8*60
 
 ==>化简得:
 x=(a-b)*8+312
 y=(a+b)*4-216
 
 这个就是最终公式了。
 
 但是不知为什么,算出来的a和b与地形编辑器里的坐标不一样,有点误差。当然大体上对了,常数误差而已。
 因为我在游戏里看到的bmp坐标(点击人物后在49CED8,49CEDC显示)和画图软件中查看的坐标不同。
 所以这个公式现在还只供参考。
 不过要是改成直坐标,那就是非常简单了。
 
 [ 本帖最后由 WHITESHIP 于 2013-2-15 13:32 编辑 ]
 |