快捷键

首先是一些TA中和快捷键相关的几个结构的地址:
511DE8 TA中的主要结构,包含了TA所用到的各种基本数据,包括声音、爆炸、内存中的3do、地图、单位、玩家、遭遇战/联网、地图feature等等的大杂烩结构。
51fbd0[16e] TA的按键消息阀口
51FBD0 是TA显示界面所用的结构。

TA窗体的回调函数MsgProc地址是 0x4c1d50
其中对键盘组合按键的的处理例程是调用0x485e90来统一处理的

显示鼠标下单位的属性是调用 0x42bf40
F1帮助 0x4942e0
处理+shootall等类似的option command: 0x417B50
属性设置窗体 0x430f00
ctrl+a 内部的键盘码a1 处理流程4963CE
ctrl+s 内部键盘码b3 处理流程4964dc
ctrl+z 内部键盘码BA 处理流程496413
ctrl+f 内部键盘码a6 处理流程4963d8
ctrl+c 内部键盘码a3 处理流程4963fe

TA的快捷键先被MsgProc处理为一种内部消息。在窗口回调中的键盘输入处理是,把有对应快捷键的输入放入消息闸门。之后在游戏的主循环时,会随着主循环而调用到一个专门处理快捷键的函数。
4c1b20 插入按键到阀门
4c1ab0 从阀门读出按键

这个消息阀门中主要是玩家在游戏中的各种输入,比如F1查看单位帮助、选择单位、单击单位控制界面、发送消息、结盟等

渠道中消息的类型以内部编码区分。内部编码实则是键盘输入的virtual-key code, 但若同时按下ctrl/alt则会变的古怪, 具体算法未知。
可在处理快捷键的函数中的0x495eb7处记录eax值得到内部编码。不确定算法,但插入阀门中的数据在插入后仍会遭到修改

要更改TA快捷键,需要处理的类型分为两类
在内部有固定函数处理的快捷键 (ctrl_s/ctrl_c/ctrl_f/ctrl_f这4个是单独处理),可以在进入对应的call 语句时(如ctrl+s的4964dc),修改目标call为call自己的新快捷键代码。
利用(Ctrl_G)这样的category来选中特定category的单位类型的,则是在一个固定的流程里处理的,每个ctrl_?对应的ecx都不一样,可以修改快捷键函数中,根据内部编码switch jmp到目标函数的switch 表中,改掉对应内部编码所对应的地址即可,需注意,这儿所跳转过去的代码,最后不能是retn返回,而该是jmp 到这个大switch的return 部分, 004965CE

TA中大量应用全局变量,导致刚开始分析时的难度倍增,但在已分析过相关数据的地方又是事倍功半的。
大部分数据结果为序列性的数组,这样使数据可轻松得无限扩充。又TA中大部分情况都会写入log文档,希望查找的code目标多半可以猜想到附近的debug信息条目故直接用字符串参考可快速定位。
TA中对带+号的特殊Command的处理,多是依赖switch的 。或用if else配合一种结构数组,这个数组的元素结构多为
{
char * string;
void * func;
}
一个指向描述当前大概情况字符串的string指针
一个指向处理当前情况函数的func指针
例如
+switchalt的处理流程为4b5cc0收到用户输入,调用4c1d50处理+switchalt到渠道.之后480770捕获到+switchalt,根据内部编码switch为调用417B50的code.
417b50中一步步比较输入的字符串,直到遇到相同的+switchalt,接着调用 “+switchalt"指针后4字节的函数地址处理了它。
4b5cc0->
4c1d50->闸门->
480770 , switch to->
417b50==”+switchalt" func

而对于选兵快捷键的处理则比较细节
sub_0_48BE00 ctrl_Z, 例程为:
首先读取char 511DE8[2a42], 乘以0x20得tmp1; 以它乘以0xa0得tmp2.
511de8[tmp1+ tmp2* 2+ 1b32h+ 67h]处指向的即为本玩家单位的数组起始,而511de8[tmp1+ tmp2* 2+ 1b32h+ 6bh]指向本玩家单位数组的结束
每个单位的结构大小为118h. ctrl+Z会挨个读取所选单位的种类二轮,第一轮把被选中的单位挑选出来,保存在一个local变量里。
继而在第二轮进行单位类型是否为存活的判定,每个单位依次判定二恒定数据(20h/40h)、一浮点属性、数个必须属性是否实在、目标单位的内部名词是否存在于local变量中,全符合条件时,则把这个单位的选中状态设置为选中

sub_0_48C030 ctrl_s的流程是 :
读取511de8[14357h]和511de8[1435b]作为UnitBegin和UnitEnd。(对应ctrl_z的 511de8[tmp1+ tmp2* 2+ 1b32h+ 67h]与511de8[tmp1+ tmp2* 2+ 1b32h+ 6bh]

接着循环的修改所有单位的已选择状态,清空所有已选择单位.
其后调用一个子函数,把那些属性要求不被ctrl_S选择到的单位,保存为一数组(覆盖已选择单位数组)返回,但这个判断必需要
short int 511de8[37ebe]==865h& char 511deb[2bee]==e0h才会多这个判断。正常时这个子函数返回0,不然会返回1且赋值511de8[37ebe]= 10h
完成后它挨个读取每个单位的结构,进行单位存活的判断
二恒定数据(20h/40h)/数个必须属性是否实在/判断单位的
ctrl_s相比ctrl+Z多了是否存在本屏幕的判断。

[110h]==40000000h的意义与[113h]==40h是一样的,是指单位被选中了。

选中目标单位的code为:
or edx, 10h
mov ebx, 1
mov [ecx+110h], edx
mov esi, dword_0_511DE8
ctrl_s相对ctrl_z更稳健,只在最起码有一个单位被选中后才设置一标志位,此标志位未设置则不进入清理函数,比ctrl_z更有效率 /:^]

保存已选中单位到本地变量
sub esp,40h
push ebx
xor eax, eax
mov ecx, 10h
lea edi, [esp+ 14h]
rep stosd
mov eax, [511DE8h]
mov eax, [eax+ 14357h]
1:
mov ecx, [eax+ 110h]
shr ecx, 4
test cl, 1
jz 2
mov cx, [eax+ 0a6h]
mov ebx, 1
and ecx, 0ffffh
mov esi, ecx
and ecx, 1fh
shr esi, 5
shl ebx, cl
mov ecx, [esp+ esi* 4+ 14h]
2:
add eax, 118h
cmp eax, edi
jbe 1
pop ebx

判断是否之前已被选中的代码:
push ecx
movzx ax, word ptr [ecx+0A6h]
mov edi, 1
mov ecx, eax
and ecx, 1Fh
shl edi, cl
shr eax, 5
test [esp+eax*4+14h], edi
pop ecx
jz short loc_0_48BEED

此只选中本屏幕内相同单位的ctrl_z修改版尚不能工作:
8B 0D E8 1D 51 00 53 55 33 DB 8B 81 57 43 01 00 8B 91 5B 43 01 00 56 3B C2 57 83 EC 40 53 33 C0
B9 10 00 00 00 8D 7C 24 18 F3 AB A1 E8 1D 51 00 8B 80 57 43 01 00 8B 88 10 01 00 00 C1 E9 04 F6
C1 01 74 20 66 8B 88 A6 00 00 00 BB 01 00 00 00 81 E1 FF FF 00 00 8B F1 83 E1 1F C1 EE 05 D3 E3
8B 4C B4 14 05 18 01 00 00 3B C7 76 C9 5B 6A 00 E8 FA 5C 00 00 8B 35 E8 1D 51 00 33 ED 8B 86 67
43 01 00 8B BE 5F 43 01 00 85 C0 0F 8E A7 00 00 00 33 C9 66 8B 0F 8B C1 C1 E0 03 2B C1 8B 8E 57
43 01 00 8D 04 80 8B 94 C1 10 01 00 00 8D 0C C1 F6 C2 20 74 71 D9 81 04 01 00 00 D8 1D 58 D7 4F
00 DF E0 F6 C4 40 74 5E 8B 81 FB 00 00 00 85 C0 75 54 8B 81 86 00 00 00 85 C0 74 09 F6 80 13 01
00 00 40 74 41 8A 81 FF 00 00 00 3A 86 42 2A 00 00 75 33 51 66 0F B7 81 A6 00 00 00 BF 01 00 00
00 8B C8 83 E1 1F D3 E7 C1 E8 05 85 7C 84 14 59 74 14 83 CA 10 BB 01 00 00 00 89 91 10 01 00 00
8B 35 E8 1D 51 00 8B 86 67 43 01 00 45 83 C7 02 3B E8 0F 8C 59 FF FF FF 85 DB 74 20 E8 3D 97 00
00 8B 0D E8 1D 51 00 66 C7 81 9C 7E 03 00 00 00 A1 E8 1D 51 00 80 88 BE 7E 03 00 10 5F 5E 5D 5B
C3

只选中带武器单位的ctrl_s, 修改目标 4964dc
8B 15 E8 1D 51 00 33 C9 83 EC 40 8A 8A 42 2A 00 00 8B C1 53 C1 E0 05 03 C1 03 D1 55 56 8D 04 80
57 B9 10 00 00 00 8D 7C 24 10 8D AC 42 63 1B 00 00 33 C0 F3 AB 8B 55 67 8B 7D 6B 8B C2 3B C7 77
3F 8B 88 10 01 00 00 C1 E9 04 F6 C1 01 74 28 66 8B 88 A6 00 00 00 BB 01 00 00 00 81 E1 FF FF 00
00 8B F1 83 E1 1F C1 EE 05 D3 E3 8B 4C B4 10 8D 74 B4 10 0B CB 89 0E 05 18 01 00 00 3B C7 76 C1
6A 00 E8 E9 5E 00 00 3B D7 0F 87 86 00 00 00 BE 00 00 00 40 8B 9A 10 01 00 00 F6 C3 20 74 6D D9
82 04 01 00 00 D8 1D 58 D7 4F 00 DF E0 F6 C4 40 74 5A 8B 82 FB 00 00 00 85 C0 75 50 8B 82 86 00
00 00 85 C0 74 08 85 B0 10 01 00 00 74 3E 66 8B 82 A6 00 00 00 BF 01 00 00 00 25 FF FF 00 00 8B
C8 83 E1 1F D3 E7 C1 E8 05 85 7C 84 10 74 1D 8A 82 FF 00 00 00 8B 3D EB 1D 51 00 3A 82 42 2A 00
00 74 09 83 CB 10 89 9A 10 01 00 00 8B 45 6B 81 C2 18 01 00 00 3B D0 0F 86 77 FF FF FF 8B 15 E8
1D 51 00 66 C7 82 9C 7E 03 00 00 00 E8 52 99 00 00 A1 E8 1D 51 00 5F 5E 5D 80 88 BE 7E 03 00 10
5B 83 C4 40 C3
ctrl_z 496413

忘了是什么功能的一段binary:
8B 0D E8 1D 51 00 53 55 33 DB 8B 81 57 43 01 00 8B 91 5B 43 01 00 56 3B C2 57 77 23 B9 2F FF FF
FF 8B A8 10 01 00 00 05 18 01 00 00 23 E9 89 68 F8 8B 15 E8 1D 51 00 3B 82 5B 43 01 00 76 E2 6A
00 E8 2A 3D F6 FF 68 EE EF 52 00 E8 00 AC F5 FF A3 F6 EF 52 00 8B 35 E8 1D 51 00 90 90 90 33 ED
8B 86 67 43 01 00 8B BE 5F 43 01 00 85 C0 0F 8E B2 00 00 00 33 C9 66 8B 0F 8B C1 C1 E0 03 2B C1
8B 8E 57 43 01 00 8D 04 80 8B 94 C1 10 01 00 00 8D 0C C1 F6 C2 20 74 7A D9 81 04 01 00 00 D8 1D
58 D7 4F 00 DF E0 F6 C4 40 74 67 8B 81 FB 00 00 00 85 C0 75 5D 8B 81 86 00 00 00 85 C0 74 09 F6
80 13 01 00 00 40 74 4A 8A 81 FF 00 00 00 3A 86 42 2A 00 00 75 3C 60 66 8B 81 A6 00 00 00 BB 01
00 00 00 25 FF FF 00 00 8B C8 83 E1 1F D3 E3 C1 E8 05 8B 15 F6 EF 52 00 85 1C 82 61 74 14 83 CA
10 BB 01 00 00 00 89 91 10 01 00 00 8B 35 E8 1D 51 00 8B 86 67 43 01 00 45 83 C7 02 3B E8 0F 8C
50 FF FF FF 85 DB 74 20 E8 33 77 F6 FF 8B 0D E8 1D 51 00 66 C7 81 9C 7E 03 00 00 00 A1 E8 1D 51
00 80 88 BE 7E 03 00 10 5F 5E 5D 5B C3

What you should do:
Add a section for add these bin code,you can used Stud_PE(or other PE editor) to do this.Remeber the section need be excutable/write/read
Copy that bin code into new section,you can do this by ollydby(recommend!),goto new section,and selecet enough space,then bin paste.
Relocating “CTRL_W” string address,infact TOTALA.EXE hadn’t “CTRL_W”,you should add it and change 52EFEE to new “CTRl_W” address
And relocating 3 call’s address, there should be “491d70”/ “488c50”/ “495860”
At last,goto
4964dc, change that call be “call bin code start”,for example,I add bin code start at 52e000,thus change to “call 52e000”.
Now,your ctrl_s selecet all weapon units in screen.

选择同屏幕相同单位:
Just 2 call,needn’t change other,just Relocating call to 491d70/485860.Other no diffrent.
8B 15 E8 1D 51 00 33 C9 83 EC 40 8A 8A 42 2A 00 00 8B C1 53 C1 E0 05 03 C1 03 D1 55 56 8D 04 80
57 B9 10 00 00 00 8D 7C 24 10 8D AC 42 63 1B 00 00 33 C0 F3 AB 8B 55 67 8B 7D 6B 8B C2 3B C7 77
3F 8B 88 10 01 00 00 C1 E9 04 F6 C1 01 74 28 66 8B 88 A6 00 00 00 BB 01 00 00 00 81 E1 FF FF 00
00 8B F1 83 E1 1F C1 EE 05 D3 E3 8B 4C B4 10 8D 74 B4 10 0B CB 89 0E 05 18 01 00 00 3B C7 76 C1
60 6A 00 E8 E8 3C F6 FF 61 3B D7 0F 87 19 01 00 00 60 8B 35 E8 1D 51 00 33 ED 8B 86 67 43 01 00
8B BE 5F 43 01 00 85 C0 0F 8E 88 00 00 00 33 C9 66 8B 0F 8B C1 C1 E0 03 2B C1 8B 8E 57 43 01 00
8D 04 80 8B 94 C1 10 01 00 00 8D 0C C1 F6 C2 20 74 52 D9 81 04 01 00 00 D8 1D 58 D7 4F 00 DF E0
F6 C4 40 74 3F 8B 81 FB 00 00 00 85 C0 75 35 8B 81 86 00 00 00 85 C0 74 09 F6 80 13 01 00 00 40
74 22 8A 81 FF 00 00 00 3A 86 42 2A 00 00 75 14 83 CA 10 BB 01 00 00 00 89 91 10 01 00 00 8B 35
E8 1D 51 00 8B 86 67 43 01 00 45 83 C7 02 3B E8 0F 8C 78 FF FF FF 61 8B 9A 10 01 00 00 F6 C3 20
74 5B D9 82 04 01 00 00 D8 1D 58 D7 4F 00 DF E0 F6 C4 40 74 48 8B 82 FB 00 00 00 85 C0 75 3E 8B
82 86 00 00 00 85 C0 74 08 85 B0 10 01 00 00 74 2C 66 8B 82 A6 00 00 00 BF 01 00 00 00 25 FF FF
00 00 8B C8 83 E1 1F D3 E7 C1 E8 05 85 7C 84 10 75 0B 83 E3 EF 90 90 89 9A 10 01 00 00 8B 45 6B
81 C2 18 01 00 00 3B D0 76 8D 8B 15 E8 1D 51 00 66 C7 82 9C 7E 03 00 00 00 E8 A2 76 F6 FF A1 E8
1D 51 00 5F 5E 5D 80 88 BE 7E 03 00 10 5B 83 C4 40 C3
SWeaponA1.rar (482 KB)
Sctrl_z.rar (482 KB)
ctrl_f.rar (482 KB)

看到贵站办的不错,想换二个链接,不知道可行,可以的话,可直接去我站提交,就可以通过:
站名1:注册香港公司 网址:www.hkatreg.net.cn
站名2: 注册公司 网址:www.postdream.org
站名3:注册海外公司 网址:www.51companyfinancing.com

只选中空闲工厂的CTRL+F

先调用原始的ctrl+f流程,sub_0_48BF30得到所有工程被选中的初步结果

然后只在被选中的单位中查找。找到的第一个空闲的,又是被选中单位后,切换屏幕到被选中单位,并且之后碰到的所有单位都直接取消选中状态。被选中的单位不空闲时,设置它们为不被选中。

修改为:
;原始的键盘流程里处理CTRL_F按下的代码样子是:
lea eax, [ebp-69h]
lea ecx, [esp+240h+Str2]
push eax
push offset aCtrl_C ; “CTRL_%c”
push ecx ; Dest
call _sprintf
add esp, 0Ch
lea edx, [esp+240h+Str2]
push esi ; ShiftDown
push edx ; Str2
call sub_0_48BF30
jmp loc_0_4965CE

把它最后的jmp到结束键盘流程的代码,改成jmp 到我们自己的代码, 我的地址是0x4fb92a
然后
;__________________ own code:
004FB92A > \8B5424 F8 mov edx,dword ptr ss:[esp-8]
004FB92E . 60 pushad
004FB92F . 66:8B42 04 mov ax,word ptr ds:[edx+4]
004FB933 . 66:3D 5F46 cmp ax,465F
004FB937 . 75 7B jnz short CTRL_Fla.004FB9B4
004FB939 . 8B1D E81D5100 mov ebx,dword ptr ds:[511DE8]
004FB93F . 90 nop
004FB940 . 90 nop
004FB941 . 90 nop
004FB942 . 33C9 xor ecx,ecx
004FB944 . 8A8B 422A0000 mov cl,byte ptr ds:[ebx+2A42]
004FB94A . 8BC1 mov eax,ecx
004FB94C . C1E0 05 shl eax,5
004FB94F . 03C1 add eax,ecx
004FB951 . 8D1480 lea edx,dword ptr ds:[eax+eax4]
004FB954 . 8BC3 mov eax,ebx
004FB956 . 03C1 add eax,ecx
004FB958 . 8D8C50 631B00>lea ecx,dword ptr ds:[eax+edx
2+1B63>
004FB95F . 8B9450 CA1B00>mov edx,dword ptr ds:[eax+edx*2+1BCA>
004FB966 > 8B41 6B mov eax,dword ptr ds:[ecx+6B]
004FB969 . 3BD0 cmp edx,eax
004FB96B . 77 47 ja short CTRL_Fla.004FB9B4
004FB96D . 8B82 10010000 mov eax,dword ptr ds:[edx+110]
004FB973 . 83E0 10 and eax,10
004FB976 . 83F8 10 cmp eax,10
004FB979 . 75 31 jnz short CTRL_Fla.004FB9AC
004FB97B . 83FB 01 cmp ebx,1
004FB97E . 75 09 jnz short CTRL_Fla.004FB989
004FB980 . EB 22 jmp short CTRL_Fla.004FB9A4
004FB982 90 nop
004FB983 90 nop
004FB984 90 nop
004FB985 90 nop
004FB986 90 nop
004FB987 90 nop
004FB988 90 nop
004FB989 > 8BBA 8A000000 mov edi,dword ptr ds:[edx+8A]
004FB98F . 83FF 00 cmp edi,0
004FB992 . 74 10 je short CTRL_Fla.004FB9A4
004FB994 . 838A 10010000>or dword ptr ds:[edx+110],10
004FB99B . BB 01000000 mov ebx,1
004FB9A0 . EB 0A jmp short CTRL_Fla.004FB9AC
004FB9A2 90 nop
004FB9A3 90 nop
004FB9A4 > 83A2 10010000>and dword ptr ds:[edx+110],FFFFFFE0
004FB9AB . 90 nop
004FB9AC > 81C2 18010000 add edx,118
004FB9B2 .^ EB B2 jmp short CTRL_Fla.004FB966
004FB9B4 > 61 popad
004FB9B5 .^ E9 14ACF9FF jmp CTRL_Fla.004965CE

binary:
8B 54 24 F8 60 66 8B 42 04 66 3D 5F 46 75 7B 8B 1D E8 1D 51 00 90 90 90 33 C9 8A 8B 42 2A 00 00
8B C1 C1 E0 05 03 C1 8D 14 80 8B C3 03 C1 8D 8C 50 63 1B 00 00 8B 94 50 CA 1B 00 00 8B 41 6B 3B
D0 77 47 8B 82 10 01 00 00 83 E0 10 83 F8 10 75 31 83 FB 01 75 09 EB 22 90 90 90 90 90 90 90 8B
BA 8A 00 00 00 83 FF 00 74 10 83 8A 10 01 00 00 10 BB 01 00 00 00 EB 0A 90 90 83 A2 10 01 00 00
E0 90 81 C2 18 01 00 00 EB B2 61 E9 14 AC F9 FF
CTRL_FlastIdle.rar (482 KB)

TA excess II主程序,不能搞局的,哈哈
crF.rar (964 KB)

晕晕的:6_292: 看不懂

上传修复BUG的一个演示
excessII_CF.rar (965 KB)

建议修正AI的行为,
目前的AI行为是完成后返回原地待命
建议改为完成后停止立刻待命

听不懂 /:^|
还有bug只能下次解决了

TA的AI行为是这样的
发现远处有个目标,跑过去干掉,跑回来,
我想改为干掉后就停在那里。。

影响太小了。如果可能还是放精力在TA3D的兼容性优化上更好更合理

附上录象机源代码中比较有帮助的一个

#ifndef tamemH
#define tamemH

#include <dsound.h>

#pragma pack(1)

struct PlayerStruct;
struct PlayerInfoStruct;
struct UnitStruct;
struct UnitOrdersStruct;
struct WeaponStruct;
struct MapFileStruct;
struct UnitDefStruct;
struct GafAnimStruct;
struct Object3doStruct;
struct PrimitiveStruct;
struct PrimitiveInfoStruct;
struct ProjectileStruct;
struct FeatureDefStruct;
struct FXGafStruct;
struct FeatureStruct;
struct WreckageInfoStruct;
struct DebrisStruct;
struct Unk1Struct;
struct Point3;
struct SmokeListNode;
struct ParticleSystemStruct;
struct SmokeListNode;
struct ParticleBase;
struct SmokeGraphics;
struct RadarPicStruct;
struct DSoundStruct;

struct Point3{
	int x;
	int y;
	int z;
};

struct PlayerStruct{
  char PlayerActive;
  char data1[11];
  char PlayerNum;
  char data2[26];
  PlayerInfoStruct *PlayerInfo;
  char Name[30];
  char SecondName[30];
  UnitStruct *FirstUnitS; //0x67 // first of this element at TAdmem 1bca
  UnitStruct *EndUnitS;// 0x6b //
  char data5[213];
  short NumUnits;
  char data6[5];
}; //0x14a

struct WeaponStruct {
  char WeaponName[0x20];
  char WeaponDescription[0x40];
  int Unkn1;
  char data3[20];
  GafAnimStruct *LandExplodeAsGFX;
  GafAnimStruct *WaterExplodeAsGFX;
  char data4[86];
  short Damage; //d6
  short AOE;
  float EdgeEffectivnes;
  short Range;
  char data5[21];
  float ShakeMagnitude;
  char data6[17];
  unsigned char ID;
  char data8[1];
  char RenderType;
  char data7[8];
};  //0x115

struct ExplosionStruct{
	DebrisStruct *Debris;
	short Frame;
	char data2[6];
	FXGafStruct *FXGaf;
	char data3[12];
	int XPos;
	int ZPos;
	int YPos;
	char data4[36];
	short XTurn; //0x4c
	short ZTurn;
	short YTurn;
	char data5[2];
};//0x54

struct DebrisStruct{
	char data1[0x24];
	Point3 *Vertices;
	Unk1Struct *Unk;
	char data2[8];
};//0x34

struct Unk1Struct{
	char data1[0x18];
	FXGafStruct *Texture;
	char data2[0x4];
};//0x20

struct FXGafStruct{
	short Frames;
	char data1[6];
	char Name[0x20];
	int FramePointers[1];
};

struct DSoundStruct{
	char data1[0x24];
	LPDIRECTSOUND Directsound;
	LPDIRECTSOUNDBUFFER DirectsoundBuffer;
	char data2[0xC];
	LPDIRECTSOUNDBUFFER DirectsoundBuffer2;
};

struct TAdynmemStruct{
	char data21[0x10];
	DSoundStruct *DSound;
	char GUIDatas[0x1B4F];

	PlayerStruct Players[10];	//0x1B63 , end at 0x2851
   
   char ScreenData0[0x1F1]
   char cCurrentPlayerID;  //2a42 be read on ctrl+?, count a structs that size 165(0xa5)*2= 0x14a
	char ScreenData1[0x24b]; 
	short BuildPosX; //0x2C8E
	short BuildPosY;
	int BuildPosRealX; //0x2C92
	int Height;
	int BuildPosRealY;
	int unk1;
	int Height2;

	char data22[0x6];

	short MouseMapPosX;  //0x2CAC
	char data16[6];
	short MouseMapPosY;  //0x2CB4
	char data23[4];
	unsigned short MouseOverUnit; //0x2CBA
	char data17[0x8];
	short BuildNum;  //0x2CC4,  unitindex for selected unit to build
	char BuildSpotState; //0x40=notoktobuild
	char data18[0x2C];

	WeaponStruct Weapons[256];  //0x2CF3  size=0x11500
	//char data7[4];
	int NumProjectiles;
	ProjectileStruct *Projectiles; //0x141F7
	char data13[0x10];
	WreckageInfoStruct *WreckageInfo; //0x1420B
	char data14[0x24];
	int FeatureMapSizeX; //0x14233
	int FeatureMapSizeY; //0x14237
	char data7[0x18];
	int NumFeatureDefs;
	char data15[0x18];
	FeatureDefStruct *FeatureDef; //0x1426F
	char data8[8];
	LPVOID	*EyeBallMemory;  //0x1427B
	char data12[8];
	FeatureStruct *Features; //0x14287
	char data3[0x40];
	tagRECT MinimapRect;//0x142CB
	RadarPicStruct *RadarFinal; //0x142DB
	RadarPicStruct *RadarMapped;  //0x142DF
	RadarPicStruct *RadarPicture;  //0x142E3
	char data20[4];
	short RadarPicSizeX;  //0x142EB
	short RadarPicSizeY;  //0x142ED
	char data25[4];
	int CirclePointer;//0x142F3 //used in drawcircle funktion, able set to unit struct, it work fine.
	char data19[0x28];
	int MapX;	//0x1431f
	int MapY;   //0x14323
	int MapXScrollingTo; //0x14327
	int MapYScrollingTo; //0x1432B
	char data24[0x28];
	UnitStruct *Units; //0x14357
	LPVOID Unk1;
	short *HotUnits;//0x1435F
	short *HotRadarUnits;
	int NumHotUnits; //0x14367
	int NumHotRadarUnits;
	char data5[0x2c];
	UnitDefStruct *UnitDef;  //0x1439b
	char data11[0x57C];
	int NumExplosions; //0x1491B
	//char data9[0x6270];
	ExplosionStruct Explosions[300]; //0x1491F
	LPVOID Unk2; //0x1AB8F
	char data10[0x1DEB4];
   //43 4F 52 4D 41 49 4E 32 2E 47 55 49 00 00 00 00


	int GameTime; //0x38A47
	char data6[0x79E];
	MapFileStruct *MapFile; //0x391E9
};

struct WreckageInfoStruct{
	int unk1;
	LPVOID unk2;
	int XPos;
	int ZPos;
	int YPos;
	char data1[0xC];
	short ZTurn;
	short XTurn;
	short YTurn;
	char data2[0xA];
};

struct FeatureStruct{
	char data1[8];
	short FeatureDefIndex;
	short WreckageInfoIndex;
	char data2[1];
}; //0xD

struct FeatureDefStruct {
	char Name[0x20];
	char data1[0x60];
	char Description[20];
	char Data2[108];
}; //0x100

struct ProjectileStruct {
	WeaponStruct *Weapon;
	int XPos;
	int ZPos;
	int YPos;
	int XPosStart;
	int ZPosStart;
	int YPosStart;
	int XSpeed;
	int ZSpeed;
	int YSpeed;
	char data1[14];
	short XTurn;
	short ZTurn;
	short YTurn;
	char data2[45];
	struct {
		bool unk1 : 1;
		bool Inactive : 1;
		char unk2 : 6;
	} Inactive;
	char data3[1];
}; //0x6B

struct MapFileStruct{
	char data[0x204];
	char TNTFile[MAX_PATH];
};

struct PlayerInfoStruct{
	char MapName[0x20];
	char data1[0x76];
   char PlayerColor;
};

struct UnitDefStruct {
  char Name[0x20];
  char UnitName[0x20];
  char UnitDescription[0x40];
  char ObjectName[0x20];
  char Side[3];
  char data5[0xA7];
  short FootX;  //0x14A
  short FootY;  //0x14C
  char *YardMap;
  char data6[0x6E];
  WeaponStruct *ExplodeAs;
  WeaponStruct *SelfeDestructAs;
  char data7[0x81];
}; //0x249

struct UnitStruct {
  int IsUnit;
  char data1[12];
  WeaponStruct *Weapon1;
  char data2[11];
  char Builder;
  char data3[12];
  WeaponStruct *Weapon2;
  char data4[24];
  WeaponStruct *Weapon3;
  char data5[16];
  UnitOrdersStruct *UnitOrders;  //5c
  char UnitState;
  char data6[3];
  unsigned short ZTurn;
  unsigned short XTurn;
  unsigned short YTurn;
  int XPos; //0x6A
  int ZPos;
  int YPos;
  short XGridPos;
  short YGridPos;
  short XLargeGridPos;
  short YLargeGridPos;
  char data8[4];
  LPVOID UnkPTR1;
  char data15[4];
  int unknow; //?0x86 经常为0,即经常越过Selected的 0x40 000 000判断 
  UnitStruct *FirstUnit; //?0x8a 建造目标! 
  UnitDefStruct *UnitType; //0x92
  PlayerStruct *Owner; //?
  LPVOID UnkPTR2;
  Object3doStruct *Object3do;
  char data6[6]; 
  int internalID;// 0xa6 在单位进行category对号时使用,categoryList[ID>> 5]==1>> (ID& 1f)则单位录属 category 
  char data6a[0x18]
  short Kills;
  char data17[50];
  PlayerStruct *Owner2; //?
  char data16[6];
  char HealthPerA;  //health in percent
  char HealthPerB;  //health in percent, changes slower (?)
  char data19[2];//似为某个有效位, ctrl+?里使用,为0则 跳过 单位是否被选中的判断,意为单位无法被选中? 
  unsigned char RecentDamage;  //0xFA
  unsigned char Height;
  char data10[8];
  int Nanoframe;
  short Health;
  float unknow; //似为某个有效位,ctrl+?里面使用,和flt_0_4FD758比较产生溢出则被跳过 
  int UnitSelected; // 0x110, 0xff& (UnitSelect>>24)==40h,很少判断到, UnitSelect& 0xff==0x20则为被取消(死亡?) , UnitSelect& 0xff==0x10也为被选中. ? 
  char data11[4];
}; //0x118

struct Object3doStruct {
	short NumParts;
	char data1[2];
	int TimeVisible;
	char data2[4];
	UnitStruct *ThisUnit;
	LPVOID *UnkPTR1;
	LPVOID *UnkPTR2;
	char data3[6];
	PrimitiveStruct *BaseObject;

};

struct PrimitiveInfoStruct{
	char data1[28];
	char *Name;

};

struct PrimitiveStruct{
	PrimitiveInfoStruct *PrimitiveInfo;
	int XPos;
	int ZPos;
	int YPos;
	unsigned short XTurn;
	unsigned short ZTurn;
	unsigned short YTurn;
	char data3[18];
	struct {
	bool Visible: 1;
   bool unk1 : 7;
	} Visible;
	char data2[1];
	PrimitiveStruct *SiblingObject;
	PrimitiveStruct *ChildObject;
	PrimitiveStruct *ParrentObject;
}; //0x36


struct UnitOrdersStruct {
  struct ??? * s1;
  struct ??? * s2; 
  char data1[22];
  UnitOrdersStruct *ThisPTR;
  //char data2[2];
  int PosX;
  int PosZ;
  int PosY;
  char data3[6];
  char FootPrint;
  char data4[12];
  struct {
   char unk1 : 4;
   bool ThisStart : 1;
   char unk2 : 3;
  } ThisStart;
  char data5[6];
  UnitOrdersStruct *NextOrder;
};

struct GafAnimStruct {


};

struct RadarPicStruct{
	int XSize;
	int YSize;
	int Unk1;
	LPVOID *PixelPTR;
};

struct ParticleSystemStruct{
	LPVOID DrawFunc; //4FD5F8 wake or smoke?; 4FD638 - Smoke1, 4FD618 - Smoke2; 4FD5B8, 4FD5A8 - Nanolath; 4FD5D8 - fire; //?
	char data1[8];
	int Type; //1 smoke, 2 wake, 6 nano, 7 fire
	SmokeGraphics* firstDraw;		//0 om denna partikel ej 鋜 aktiv (?)
	SmokeGraphics* lastDraw;			//rita alla fram till men inte denna ?
	LPVOID *Unk;				//? inte f鰎 sista ?
	char data2[48];
};//76

struct ParticleBase{
	char data[8];
	ParticleSystemStruct **particles;		
	char data2[8];
	ParticleSystemStruct **ParticlePTRArray;
	int SmokeParticleStructSize; //? 76
	int maxParticles; //? 1000
	int curParticles;			//antalet aktiva i arrayen men de 鋜 inte n鰀v鋘digtvis i ordning
};

struct SmokeGraphics{
	FXGafStruct* gaf;
	int XPos,ZPos,YPos;
	int unknown;
	int frame;
	int unknown2;
	int MoreSubs;  //0 ifall inga fler subparticles efter denna
};//0x20

/*struct SmokeListNode{
	SmokeParticleStruct* next;
	SmokeParticleStruct* me;
};*///?

struct Category
{
   PTR CategroyName;
   PTR CategroyList;       
};// 0x8

#pragma pack()

#endif

这段代码是干嘛的:6_273:

我记得在TAuniverse上有一份xon_dll的原代码

修复了ctrl_f的一个糟糕bug。
taexcess.rar (963 KB)
Excess II NoCDt1e2t.rar (483 KB)