标题: DOS版三国志英杰传的研究心得——肆, 另一块记录人物数据的地址
性别:未知-离线 漫漫苦短

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 45
编号 545816
注册 2023-12-25


发表于 2025-3-13 19:19 资料 短消息 只看该作者
DOS版三国志英杰传的研究心得——肆

上一章简单分析了部队在战场上的数据,先回顾一下。

QUOTE:
以D076为首项,D(14)为公差,2D(45)为项数的一个十六进制下的等差数列中的一个地址值

按照上一章的分析这其中记录了人物代码、战场代码、仇人代码、撤退标志、AI类型、士气值、策略值等等信息,但显然,这不能完全概述其中的任一人物的全部信息,例如一个人物的等级经验兵种、还有武力智力统御力这三个一直被玩家拿来比较综合素质的数值,还有这个部队的名字等等信息,这些都没有在部队战场上的数据中,但实际上又不能不在战场上使用,例如部队在战场使用策略获得经验升级,不能不依靠等级经验兵种,部队也需要用武力智力统御力这三者计算在战场上的攻击力防御力和策略值的数据,那么这些数据又是记录在哪里?

可以想象应该是有新的一块数据是记录于此的,这块数据记为人物的固有数据(虽然等级经验兵种等等这些数据都是有变动的),如果依照部队在战场上的数据记录的特点,那么每一个人物的都是有对应的一个的首地址,也就是说这些地址的应该也是以X为首项,Y为公差,Z为项数的一个十六进制下的等差数列中的一个地址值。那么XYZ对应的十六进制值究竟是什么?


顶部
性别:未知-离线 漫漫苦短

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 45
编号 545816
注册 2023-12-25


发表于 2025-4-13 19:19 资料 短消息 只看该作者
一、人物数据所在位置

根据上一章的内容,战场数据共630字节大小,并且分成14×45字节,战场数据这块上最多只能存下45个人物的数据,但英杰传的人物远远不止45个,实际上在BAKDATA.R3中一共保存了384个人物的初始数据(包括以兵种命名的部队或只在剧情中才出现的人物),也就是说在DS段还有一块能保存384个人物数据的内存空间,而对于每个人物都对应唯一的人物代码。

并且上一章还粗略分析了每只部队战场数据的各个偏移的含义,偏移+0的就是保存2字节大小的人物代码,换句话说,就是每只部队战场数据偏移+0的人物代码的来源就是人物数据所在内存空间对应人物代码,而这人物代码的分配也是和每只部队战场数据偏移+2的战场代码一样是按照顺序进行分配了,但在人物数据这部分的人物代码并不是从0开始,而是从0x200(512)开始的,而战场数据的那块数据的人物代码确实是从0开始的,也就是说,人物数据的人物代码 = 战场数据的人物代码 + 0x200(512),至于具体的细节后文再解析。

扯远了,本章开头的XYZ对应的值是什么才是本节的重点,Z其实已经透露出来了,就是0x180(384),而对应的人物代码的范围就是0200 - 0379,0200就是劉備,0201是关羽,0204是曹操,0208是吕布,0200 - 02FF一共256个人物都是具体姓名的人物,从0300 - 035F是以兵种命名的部队,而0360 - 0379是这部分人物就很杂乱了,比如道具屋0376,李明0377,总之一共384个。

而XY,还是在汇编中找这类似战场数据中这部分代码的,从而对应人物数据的XY。

seg002:7746 B0 0E                          mov     al, 0Eh
seg002:7748 F6 66 FF                       mul     [bp+var_1]                              ; 部队战场代码
seg002:774B 05 76 D0                       add     ax, 0D076h

在代码找到了这两个部分的汇编代码,相似度很高吧,当然只是举出两个例子,arg_0的值还是以0xD076为首项,0xD(14)为公差,0x2D(45)为项数的一个十六进制下的等差数列中的一个地址值,两个部分的汇编代码sub_22F6A和sub_23098这两个函数的具体内容这章也会大致介绍。

seg002:6E7C 8B 76 06                       mov     si, [bp+arg_0]
seg002:6E7F 8A 44 0C                       mov     al, [si+0Ch]
seg002:6E82 50                             push    ax
seg002:6E83 6B 04 2C                       imul    ax, [si], 2Ch                      ; [si]获取战场数据的首地址对应的人物代码,并且乘0x2C(44),并且传给AX
seg002:6E86 05 16 68                       add     ax, 6816h
seg002:6E89 50                             push    ax                                      ; 人物数据的首地址
seg002:6E8A 9A 0A 60 F6 1C                 call    sub_22F6A



seg002:6E98 8B 76 06                       mov     si, [bp+arg_0]
seg002:6E9B 8A 44 0C                       mov     al, [si+0Ch]
seg002:6E9E 50                             push    ax
seg002:6E9F 6B 04 2C                       imul    ax, [si], 2Ch                   ; [si]获取战场数据的首地址对应的人物代码,并且乘0x2C(44),并且传给AX
seg002:6EA2 05 16 68                       add     ax, 6816h
seg002:6EA5 50                             push    ax                                      ; 人物数据的首地址
seg002:6EA6 9A 38 61 F6 1C                 call    sub_23098

seg002:6E83-seg002:6E86/seg002:6E9F-seg002:6EA2,与seg002:7746-seg002:774B的地址计算方法很相似吧,seg002:6E7F/seg002:6E9B都是获取战场数据的一个方法,可以见上一章回忆一下。

所以X对应的十六进制就是0x6816,Y对应的十六进制就是0x2C,这也是龙吟前辈曾经提到的44字节,对比战场数据的Y为0xE,每一个人物都差了44-14=30(0x2C-0xE)字节大小,Z相差更大,用Y×Z就可以算出人物数据占了多大的内存空间,这两块数据占用的内存大小差距相当大。

总结人物数据的首地址为以0x6816为首项,0x2C(44)为公差,0x180(384)为项数的一个十六进制下的等差数列中的一个地址值。


顶部
性别:男-离线 神雕小侠

Rank: 3Rank: 3Rank: 3
组别 士兵
级别 忠义校尉
功绩 2
帖子 245
编号 44352
注册 2005-7-27


发表于 2025-4-14 12:35 资料 短消息 只看该作者
兄弟有没有看过之前龙吟前辈的分析,我感觉您的这些研究成功跟他的应该会有一些交集
顶部
性别:未知-离线 漫漫苦短

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 45
编号 545816
注册 2023-12-25


发表于 2025-4-14 18:18 资料 短消息 只看该作者
回复 #3 神雕小侠 的帖子

岂止说是有交集,龙吟前辈简直是我的领路人,我一开始就是对着他的《三国志英杰传分析结果》来分析,还有周瑜前辈的全补丁的修改方法等等资料,目前关于他们的这些研究成果大部分都找到了程序中对应的位置,不过还是有很多内容要分析的,其实我汇编分析能力也不强,也只是站在巨人的肩膀上。
顶部
性别:未知-离线 漫漫苦短

Rank: 1
组别 百姓
级别 在野武将
功绩 0
帖子 45
编号 545816
注册 2023-12-25


发表于 2025-4-19 19:19 资料 短消息 只看该作者
二、人物数据的重要属性——兵种(1)

毫无疑问,人物数据占用的内存空间远大于战场数据的空间,本章分析的内容的篇幅也会比上一章长,分析人物数据中的44字节数据中大部分内容代表的含义。

每个人物的人物代码都是占用2字节的,上一节已经说了战场数据和人物数据的人物代码上的联系,但我想先从其他的数据开始讲起。如果说想从这44字节中挑出最重要的一项属性来说明,我认为这项属性就是每个人物的兵种代码,兵种代码虽然只占用的1个字节,但还是至关重要的,它在偏移+020处,sub_23A2C函数就是它的Get方法,arg_0的值都是以0x6816为首项,0x2C(44)为公差,0x180(384)为项数的一个十六进制下的等差数列中的一个地址值。

seg001:6ACC                sub_23A2C proc far
seg001:6ACC
seg001:6ACC                arg_0           = word ptr  6
seg001:6ACC
seg001:6ACC 55                             push    bp
seg001:6ACD 8B EC                          mov     bp, sp
seg001:6ACF 8B 5E 06                       mov     bx, [bp+arg_0]
seg001:6AD2 8A 47 20                       mov     al, [bx+20h]
seg001:6AD5 C9                             leave
seg001:6AD6 CA 02 00                       retf    2
seg001:6AD6                sub_23A2C endp

这是根据人物数据的首地址来获取对应的兵种代码,那么有没有方法根据部队战场数据的首地址来获取对应的兵种代码,其实根据上一节的计算我们就能看出,通过人物代码,可以将战场数据的首地址转化成人物数据的首地址,于是就有了sub_3628C函数,arg_0的值都是以0xD076为首项,0xD(14)为公差,0x2D(45)为项数的一个十六进制下的等差数列中的一个地址值。

seg002:936C                sub_3628C proc far
seg002:936C
seg002:936C                arg_0           = word ptr  6
seg002:936C
seg002:936C 55                             push    bp
seg002:936D 8B EC                          mov     bp, sp
seg002:936F 8B 5E 06                       mov     bx, [bp+arg_0]
seg002:9372 6B 07 2C                       imul    ax, [bx], 44
seg002:9375 05 16 68                       add     ax, 6816h
seg002:9378 50                             push    ax
seg002:9379 9A CC 6A F6 1C                 call    sub_23A2C
seg002:937E C9                             leave
seg002:937F CA 02 00                       retf    2
seg002:937F               sub_3628C endp

从理论上来说sub_3628C这个函数是不需要调用sub_23A2C函数,因为在seg002:9375这句就已经求出人物数据的首地址,再根据之前的seg001:6ACF-seg001:6AD2的汇编代码稍改就可以求出兵种代码。

但实际上有可能人物数据的内存空间是甲设计结构,而战场数据的内存空间又是乙设计的,数据之间的逻辑是丙等人设计的,如果说甲设计的人物数据的内存空间结构发生变化,对应乙丙等人的汇编代码有可能出现多处改动,这是没有必要的,所以最好的方式就是就是提供一个类似接口的方法,比如一个调用函数(本例的sub_23A2C),这样无论甲设计的人物数据的内存空间结构发生怎样的变化,只要甲给定一个函数,乙丙等人根据这个函数,就是实现直接获取甲设计的的人物数据其中一项属性。

在此之前,封剑尘和孝直前辈都分别提到过——兵种顺序(及代码)DOS版英杰传兵种攻防、兵力、移动力、策略修改,可能大部分人只知道兵种名称,却不知对应的兵种代码,下一节就探究兵种名称和兵种代码的内在逻辑。
顶部

正在浏览此帖的会员 - 共 1 人在线




当前时区 GMT+8, 现在时间是 2025-4-23 19:05
京ICP备2023018092号 轩辕春秋 2003-2023 www.xycq.org.cn

Powered by Discuz! 5.0.0 2001-2006 Comsenz Inc.
Processed in 0.010758 second(s), 9 queries , Gzip enabled

清除 Cookies - 联系我们 - 轩辕春秋 - Archiver - WAP