1. MAIN.EXE 入口初始化
触发:DOS 装载 MZ 后跳到 CS:IP
接口:EXE entry
后续:初始化运行环境,准备资源文件名表、图形驱动接口和剧本状态。
confirmed-static这张图只画 MAIN.EXE 内部视角:入口之后通过 DOS/TFDED/资源加载接口取得数据,再由 SNR 指令驱动地图和战场逻辑。带 runtime-open 的节点是下一步需要 trace 闭合的地方。
触发:DOS 装载 MZ 后跳到 CS:IP
接口:EXE entry
后续:初始化运行环境,准备资源文件名表、图形驱动接口和剧本状态。
confirmed-static触发:剧情或地图需要加载 SNR、PMAP、MMAP、SMAP、HEX、存档等文件
接口:DOS INT 21h / 文件服务
后续:把 R3 数据读入 MAIN 的缓冲区;压缩块再交给解码/展开逻辑。
confirmed-resource-names / runtime-entry-open触发:地图底图、人物、战场 tile、动画帧需要展开到画面缓冲区
接口:INT 62h / TFDED request block
后续:TFDED 返回展开后的图像数据,MAIN 再叠加单位、标签、触发区域或 UI。
confirmed-interface / details-open触发:当前剧情指针推进到下一条 opcode
接口:SNR opcode dispatcher
后续:根据 opcode 显示对白、切换 PMAP/MMAP/SMAP/ZMAP、写剧情变量或进入战斗。
runtime-open触发:SNR 指令要求进入地图或战场
接口:scene_kind branch
后续:0x10/0x20/0x2F 进入 MMAP/PMAP/SMAP;0x30 进入 ZMAP 战场初始化。
confirmed-front-model / main-branch-open触发:进入战场首帧
接口:MAIN battle state write
后续:CF6A 记录回合、天气、胜利条件等;D076 写入 45 个作战单位槽位。
confirmed-cluster / field-open触发:回合推进、区域触发、单挑、撤退、援军/伏兵出现
接口:round/event handlers
后续:写入或修改 D076,播放对白/单挑/移动/水火机关,然后重绘战场。
runtime-open触发:攻击、策略、恢复、混乱、反击等需要判定
接口:far call helper / local formula
后续:更新兵力、士气、异常状态、行动状态,并触发动画/消息。
confirmed-offset / callers-open触发:战场结束、剧情分支、人物加入/离队、道具奖励
接口:ESAVE/MSAVE writeback
后续:写回 ESAVE/MSAVE,恢复 SNR 指针,进入下一段剧情或地图。
runtime-open中断接口 runtime-entry-open
AH=3Dh/3Fh/42h/3Eh 等候选图形接口 confirmed-interface
int 62h;以及旧分析中的 call 0000:6B2C / call 0CF6:0000 桥接far call confirmed-static-signature
call far 0CF6:0FA0far call confirmed-offset
call far 0CF6:3DE0far call strong-static-candidate
call far 1CF2:3FD8far call static-candidate
call far 1CF2:4138far call static-candidate
call far 1CF2:6B38内存结构 confirmed-structure / field-open
DS:D076 + slot * 0x0E内存结构 confirmed-anchor / field-open
DS:CF6A| 节点 | 入口/接口 | 参数 | 后续处理 | 证据等级 |
|---|---|---|---|---|
| 1. MAIN.EXE 入口初始化 启动 · DOS 装载 MZ 后跳到 CS:IP | MZ header CS:IPEXE entry | DOS PSP / 环境MAIN.EXE load image重定位后的段地址 | 初始化运行环境,准备资源文件名表、图形驱动接口和剧本状态。 | confirmed-static MZ header 与 relocation table 已解析;原版 headerBytes = 0x6A00。 |
| 2. 读取 R3 资源文件 资源 · 剧情或地图需要加载 SNR、PMAP、MMAP、SMAP、HEX、存档等文件 | AH=3Dh/3Fh/42h/3Eh 等文件打开、读、seek、关闭路径候选DOS INT 21h / 文件服务 | 文件名指针读写缓冲区长度文件偏移 | 把 R3 数据读入 MAIN 的缓冲区;压缩块再交给解码/展开逻辑。 | confirmed-resource-names / runtime-entry-open MAIN 内置 A:SNRxD.R3、A:SNRxM.R3、PMAP.R3、MMAP.R3、SMAP.R3、HEXZMAP.R3 等资源名表。 |
| 3. 调用 TFDED 图形展开/搬运 图形 · 地图底图、人物、战场 tile、动画帧需要展开到画面缓冲区 | int 62h、call 0000:6B2C、call 0CF6:0000 相关桥接INT 62h / TFDED request block | 请求块地址资源 index目标显存/缓冲区图像尺寸或 entry index | TFDED 返回展开后的图像数据,MAIN 再叠加单位、标签、触发区域或 UI。 | confirmed-interface / details-open 旧 exe-analysis 与 P1 过渡审计均把 TFDED 作为图形展开接口;已有 int62/request block 线索。 |
| 4. 执行 SNR 剧本指令 剧本 · 当前剧情指针推进到下一条 opcode | dispatcher 函数待从 SNRxD/SNRxM 模板引用反查SNR opcode dispatcher | 当前 SNR 指针opcode参数 bytes当前章节/节/场状态 | 根据 opcode 显示对白、切换 PMAP/MMAP/SMAP/ZMAP、写剧情变量或进入战斗。 | runtime-open 前端已稳定解析 0x09/0x11/0x2E/0x36 等剧本指令;MAIN 侧 dispatcher 尚需 trace 闭合。 |
| 5. 根据 scene_kind 切换游戏画面 转场 · SNR 指令要求进入地图或战场 | scene_kind 0x10/0x20/0x2F/0x30 分支候选scene_kind branch | scene_kindscene_id地图 entry当前城市/地点 | 0x10/0x20/0x2F 进入 MMAP/PMAP/SMAP;0x30 进入 ZMAP 战场初始化。 | confirmed-front-model / main-branch-open P1 scene_kind 模型已把四类画面与资源簇绑定。 |
| 6. ZMAP 初始化写入 CF6A/D076 战场 · 进入战场首帧 | D076 / CF6A 高命中函数窗口MAIN battle state write | 战场编号部署表友军/敌军/我军槽位战场全局状态 | CF6A 记录回合、天气、胜利条件等;D076 写入 45 个作战单位槽位。 | confirmed-cluster / field-open D076/CF6A 静态引用聚类已完成;字段仍需逐 offset 运行时确认。 |
| 7. 回合事件与剧情触发 战场 · 回合推进、区域触发、单挑、撤退、援军/伏兵出现 | CF6A 回合字段 + D076 单位状态写入函数候选round/event handlers | 当前回合触发区域单位槽位目标坐标事件参数 | 写入或修改 D076,播放对白/单挑/移动/水火机关,然后重绘战场。 | runtime-open 补丁锚点已确认天气、混乱、策略、反击等战斗机制;回合事件 handler 待命名。 |
| 8. 战斗判定调用 战斗 · 攻击、策略、恢复、混乱、反击等需要判定 | 0CF6:3DE0 随机、0x02779B 天气、0x030D88 策略成功、0x030FAE 反击等锚点far call helper / local formula | 施放者单位目标单位天气地形士气/智力/等级随机值 | 更新兵力、士气、异常状态、行动状态,并触发动画/消息。 | confirmed-offset / callers-open 前辈补丁与本地字节窗口均可验证这些机制入口。 |
| 9. 胜败结算与存档写回 回写 · 战场结束、剧情分支、人物加入/离队、道具奖励 | 战场结束返回 SNR 的写回链待 traceESAVE/MSAVE writeback | CF6A 胜利状态/过关经验D076 单位结果剧情变量人物与道具表 | 写回 ESAVE/MSAVE,恢复 SNR 指针,进入下一段剧情或地图。 | runtime-open ESAVE/MSAVE 结构已建索引;胜利前后 diff 是下一步验证方式。 |
游戏含义:剧情文本、对白、地图切换、战场进入都从 SNR 指令流出发。找到 dispatcher 后,0x09/0x11/0x2E/0x36 才能从“前端解析规则”升级为 MAIN 运行规则。
当前证据:
还需要确认:
怎么核对:在一个 PMAP->MMAP->ZMAP->PMAP 的完整剧情链中,记录 opcode、scene_kind、scene_id、后续打开的 R3 文件。
游戏含义:我军/友军/敌军部署、第 N 回合援军、伏兵、撤退、单挑后移动、水火机关,最终都要落到 CF6A/D076 或战场覆盖状态。
当前证据:
还需要确认:
怎么核对:进入战场首帧、回合事件前后、撤退移动每步、胜利返回前后 dump CF6A/D076。
游戏含义:室内剧情、城市地图、行军大地图不是独立文件展示,而是 MAIN 根据 SNR 当前状态切换的三种地图态。
当前证据:
还需要确认:
怎么核对:选择一个城市进出:MMAP 选城 -> SMAP 城内 -> 商店 -> PMAP 官邸,对照文件读取和当前城市字段。
游戏含义:战场胜利、人物加入/离队、道具奖励、剧情分支开关都必须写回 ESAVE/MSAVE,否则下一段剧情无法延续。
当前证据:
还需要确认:
怎么核对:做“胜利前/胜利后”“加入前/加入后”“获得道具前/后”的存档二进制 diff。
| scene_kind | 游戏画面 | 玩家看到的内容 | MAIN.EXE 资源/状态 | 验证方向 |
|---|---|---|---|---|
0x10 | MMAP | 大地图/行军/自走地图态 | MMAP.R3MMAPBGPL.R3BBKSDAT1.R3 | SNR 0x09/0x11 后应出现 MMAP 底图、地点/城市、行军或自走状态相关读取。 |
0x20 | PMAP | 剧情平面地图/室内外剧情地图态 | PMAP.R3SMAPBGPL.R3BAKDATA.R3FACEDAT.R3 | SNR 0x09/0x11 后应出现 PMAP 地图 entry、人物立绘/头像/对白资源读取。 |
0x2F | SMAP | 城市/店铺/室内交互地图态 | SMAP.R3SMAPBGPL.R3BBKSDAT1.R3BAKDATA.R3 | SNR 0x2E 当前城市与 0x09/0x11 场景切换后,应能 trace 到 SMAP entry 和商店库存候选。 |
0x30 | ZMAP | 战场地图/回合制战斗态 | HEXZCHR.R3HEXZMAP/HEXZCHP/HEXGRP 等战场资源族CF6AD076 | 进入战场后应能 trace 到 HEX 资源读取,并看到 CF6A 战场上下文、D076 单位槽位被初始化。 |
| 接口 | 证据等级 | 游戏含义 | 调用点/窗口 | 下一步验证 |
|---|---|---|---|---|
R3 entry/index 加载调用call far 0CF6:0FA0 | confirmed-static-signature | 按资源 index 选择 R3 entry,是 MAIN 从“要进哪个地图/战场”落到“读取哪块资源数据”的关键接口候选。 | 0x014617 index=0 BAKDATA.R30x014640 index=150x01469A index=1 BBKSDAT1.R30x0146CA index=2 SMAPBGPL.R30x0146EA index=3 MMAPBGPL.R30x01472E index=4 MMAP.R30x014746 index=3 MMAPBGPL.R30x01476A index=3 MMAPBGPL.R30x014796 index=7 SSCCHR1.R30x0147AA index=8 SSCCHR2.R3 | 在 PMAP/MMAP/SMAP/ZMAP 转场时记录调用前 push imm8,建立 index 到 R3 entry 的映射表。 |
随机数/判定 helpercall far 0CF6:3DE0 | confirmed-offset | 策略成功、混乱、反击、恢复浮动等机制会经过随机或阈值判定;补丁锚点能把这些游戏表现和机器码窗口对应起来。 | 0x02149D0x024D740x024D7F0x024D8B0x0255DC0x0256250x0258F20x0259040x0259460x02778D | 分别触发策略、反击、混乱、天气/恢复,把调用点和返回值记录到机制表。 |
CF6A 天气/战场字段读取 helpercall far 1CF2:3FD8 | strong-static-candidate | 多处 `push CF6A` 后调用该 helper,附近存在 `cmp al,0x2` 的天气判断模式,是水火策略和回合天气闭合的重点入口。 | 0x02D27C0x02D80D0x02DEA90x02FE460x02FEF80x030D4D | 进入战场后 dump CF6A,并在晴/雨切换时对照 helper 返回值。 |
CF6A 战场状态 helpercall far 1CF2:4138 / 1CF2:6B38 | static-candidate | 战场全局状态读取/检查入口候选,可能控制战场事件是否进入某个分支。 | 0x0268670x0275E00x03044D0x02B1610x02B2080x02B6200x02B6440x02B66B0x0268390x028352 | 在回合事件、胜败结算、区域触发前后对照 CF6A 字段变化。 |
D076 45 槽作战单位块DS:D076 + slot * 0x0E | confirmed-structure / field-open | 我军、友军、敌军、援军、伏兵、撤退、坐标移动最终都应落在单位槽位字段变化上。 | 0x0268580x03145F0x028AFB0x02661B0x026BEA0x026F9C0x0270D40x027705 | 战场初始、回合援军、撤退移动、单挑后移动四种场景分别 dump 45×0x0E。 |
静态命中 103 处,归入 2 个函数/窗口。
当前最强字段:+03/+04 坐标、+09 登场/撤退、+0B 兵种/类别、+0D 战斗标志位。
| Offset | 字段候选 | 状态 | 证据 |
|---|---|---|---|
0x00 | 人物/单位编号候选 | reference-derived | 前辈资料称每槽含人物编号;当前静态聚类尚未把 +00 与具体读写函数闭合。 |
0x01 | 战场槽位/阵营相关候选 | static-candidate | D076 聚类多处出现 +01;可能与槽位、阵营、可控性或显示标签有关。 |
0x02 | 人物/兵种/登场辅助候选 | static-candidate | D076 聚类多处出现 +02;需用初始化 trace 区分人物编号、兵种编号或状态索引。 |
0x03 | X 坐标候选 | strong-static-candidate | D076 高命中窗口反复出现 +03,且与 +04 成对,符合单位坐标字段。 |
0x04 | Y 坐标候选 | strong-static-candidate | D076 高命中窗口反复出现 +04,且与 +03 成对,符合单位坐标字段。 |
0x05 | 目标/移动/方向候选 | static-candidate | D076 聚类出现 +05/+06,与坐标窗口相邻;可能参与目标坐标或移动状态。 |
0x06 | 目标坐标/路径状态候选 | static-candidate | 多个移动相关窗口出现 +06;需用强制移动/撤退 trace 验证。 |
0x08 | 目标/AI 辅助候选 | static-candidate | D076 聚类出现 +08;可能参与目标选择、AI 或行动状态。 |
0x09 | 登场/撤退/行动状态候选 | strong-static-candidate | P0 聚类已标出 +09;与援军出现、撤退、行动状态最相关。 |
0x0A | 异常/行动/标志位候选 | strong-static-candidate | D076 聚类多处出现 +0A;混乱、行动结束、显示状态都可能落在这里。 |
0x0B | 兵种/阵营/AI 类别候选 | strong-static-candidate | 反击逻辑读取 `[si+0x0B]` 判断兵种/类别;这是补丁锚点支撑的强候选。 |
0x0C | 士气/统御/恢复相关候选 | static-plus-patch-candidate | 恢复逻辑窗口出现 `[si+0x0C]`;可能是统御、士气或单位能力相关字段。 |
0x0D | 战斗标志位候选 | strong-static-candidate | 反击逻辑设置 `[si+0x0D] & 0x40`;至少包含反击或战斗标志位。 |
Trace 读法:
静态命中 33 处,归入 4 个函数/窗口。
当前最强字段:+02 当前回合、+03 限制回合、+04 天气、+24 过关经验候选。
| Offset | 字段候选 | 状态 | 证据 |
|---|---|---|---|
0x00 | 战场编号/状态头候选 | reference-derived | CF6A 是战场全局块首址;头部字段需进入战场时 dump 才能确认。 |
0x02 | 当前回合候选 | reference-derived | 前辈资料与当前 P1 验证计划均把 +02 作为回合候选。 |
0x03 | 限制回合候选 | reference-derived | 前辈资料与当前 P1 验证计划均把 +03 作为限制回合候选。 |
0x04 | 天气候选 | patch-anchor-supported | 天气推进补丁锚点可定位回合天气流程;+04 是优先验证字段。 |
0x24 | 过关经验候选 | reference-derived | 前辈资料指出 CF6A+24 附近与过关经验有关;需反查胜利结算函数确认。 |
Trace 读法:
它像战场的总账本:当前回合、限制回合、天气、战场状态、胜利经验都优先从这里找证据。
需要确认:+02 当前回合、+03 限制回合、+04 天气、+24 过关经验。
它像战场上的 45 个单位格:谁在场、属于哪方、坐标在哪里、是否登场/撤退/混乱,都要在这里落地。
需要确认:+03/+04 坐标、+09 登场/撤退、+0B 兵种/阵营、+0D 标志位。
这些不是单纯画在前端的效果。剧本触发后,MAIN 要么写单位结构,要么写战场覆盖状态,再由资源帧和地图重绘表现出来。
| # | 状态块 | 函数窗口 | 游戏侧优先解释 | 字段线索 | 代表调用 |
|---|---|---|---|---|---|
| 1 | DS:D076 战场单位块 | 0x026858-0x026B4Ewin_026888 · 命中 9 | 可能接触单位坐标字段 +03/+04 可能接触异常/行动/标志位字段 +0A/+0D | di+0x03×1di+0x0C×1di+0x0E×1di+0x0F×4si+0x01×3si+0x03×3 | 0x02685D->0CF6:7CE60x026867->1CF2:41380x02688E->1CF2:40AA |
| 2 | DS:D076 战场单位块 | 0x03145F-0x031513win_03148F · 命中 5 | 可能读取或写入单位登场/撤退/行动状态字段 +09 可能接触单位坐标字段 +03/+04 可能接触异常/行动/标志位字段 +0A/+0D 可能接触兵种/阵营/AI 类别字段 +0B | di+0x1F×1di+0x25×1si+0x02×3si+0x04×1si+0x08×3si+0x09×3 | 0x0314B4->1CF2:40F60x0314F4->1CF2:409C0x031503->1CF2:AFB2 |
| 3 | DS:D076 战场单位块 | 0x02661B-0x026711win_02664B · 命中 3 | 可能接触单位坐标字段 +03/+04 | di+0x03×1di+0x04×1di+0x28×1si+0x02×2si+0x03×2si+0x04×2 | 0x026625->1CF2:45CE0x02662D->1CF2:40300x02664E->1CF2:740A |
| 4 | DS:CF6A 战场全局上下文 | 0x02B12F-0x02B236win_02B15F · 命中 3 | 调用 1CF2:4138,疑似读取战场上下文布尔/状态 | di+0x0B×1di+0x10×1di+0x15×1di+0x16×1di+0x18×1di+0x1C×1 | 0x02B142->0CF6:77500x02B152->0CF6:7CE60x02B161->1CF2:4138 |
| 5 | DS:D076 战场单位块 | 0x027705-0x027798win_027735 · 命中 3 | 可能接触单位坐标字段 +03/+04 可能接触异常/行动/标志位字段 +0A/+0D | di+0x01×3di+0x02×1di+0x03×1di+0x08×1di+0x0A×1si+0x04×1 | 0x027707->1CF2:2F560x027720->0CF6:32420x02773B->1CF2:4062 |
| 6 | DS:D076 战场单位块 | 0x028AFB-0x028C1Ewin_028B2B · 命中 4 | 可能接触单位坐标字段 +03/+04 | di+0x03×1di+0x06×1di+0x12×2si+0x06×1si+0x18×1si+0x19×1 | 0x028B31->1CF2:40E80x028B3D->1CF2:81AE0x028B74->1CF2:40E8 |
| 7 | DS:D076 战场单位块 | 0x02DFA0-0x02E103win_02DFD0 · 命中 3 | 可能接触单位坐标字段 +03/+04 | di+0x03×1si+0x02×4si+0x03×1si+0x06×1si+0x0E×1si+0x16×1 | 0x02DFA6->1CF2:AFB20x02DFB2->1CF2:95840x02DFBE->1CF2:AF74 |
| 8 | DS:CF6A 战场全局上下文 | 0x02B5EE-0x02B699win_02B61E · 命中 3 | 调用 1CF2:4138,疑似读取战场上下文布尔/状态 | di+0x03×1di+0x05×1di+0x0A×1di+0x0F×1si+0x03×5si+0x06×1 | 0x02B5FB->0CF6:37980x02B603->1CF2:40BC0x02B60D->1CF2:40E8 |
MAIN.EXE 静态已提取出 25 组默认库存候选,并且可以映射到 BAKDATA 道具表。
还没有最终绑定到具体城市/店铺,需要用进城、进商店时的运行 trace 来确认。
SNR 的 0x2E 当前城市/地点,是把 MMAP 城市、SMAP 城内、商店库存、PMAP 官邸串起来的关键线索。
存档样本已确认两类家族:剧情进度与武将资料。MSAVE 人物/单位表模型为 384 × 18 bytes。
接下来要做胜利前后、入队前后、获得道具前后的二进制 diff。
当前差异家族数:2
| 场景 | 推荐战场/状态 | 要 dump 的东西 | 闭合目标 |
|---|---|---|---|
| CF6A 回合/天气/胜利经验字段闭合 | 任一早期短战场 + 一个有天气变化/胜利结算的战场 | DS:CF6A 至 DS:CF6A+0x40当前 SNR 指令指针候选ESAVE/MSAVE 写入前后 | 确认 +02 当前回合、+03 限制回合、+04 天气、+24 过关经验候选,并标注读写函数。 |
| D076 初始部署/默认出战/友军敌军槽位闭合 | 信都、兖州、宛I、陈仓、雒II | D076 45 槽完整 45*0x0ECF6A 战场编号字段候选当前 scene_kind / scene_id | 确认每槽 0x0E 字段里的人物、阵营、坐标、兵种/类别、登场状态,并解释前端“部署污染”的运行时边界。 |
| 第 N 回合援军/伏兵/撤退事件闭合 | 许昌I第12回合、雒II第2/13回合、瓦口关I第3回合、瓦口关II第7回合 | CF6A 回合字段D076 45 槽差异当前 SNR opcode 与 refs 范围 | 把第 N 回合出现、伏兵、撤退、对白分支拆成共同 dispatcher 与具体 handler。 |
| 移动/撤退/强制移动路径闭合 | 虎牢关吕布撤退、界桥赵云出场、界桥文丑单挑后移动、南阳曹仁撤退 | D076 坐标字段 +03/+04 候选目标坐标/路径字段 +05/+06 候选地形/移动力读取窗口 | 确认路径由 MAIN 计算还是由剧本提供,区分撤退符号、单位图标与移动线的运行时来源。 |
| 攻防伤害公式闭合 | 固定人物/固定地形/固定兵种的一次普通攻击 | 人物固定资料字段D076 单位状态字段兵种/地形/宝物修正读取窗口 | 把 4000、140、等级+10、士气、地形、兵种、宝物修正串成可复算公式。 |
| 火攻/水攻/落石/桥/城门/地形变化闭合 | 长沙水攻、南郡水攻、博望坡火攻、邺II/邺III火势蔓延 | HEXZCHR entry41/42 帧选择战场地图状态/覆盖层候选SNR opcode refs | 确认水火资源帧、是否保留、是否逐回合累积或递减,并把前端渲染规则回写为 MAIN 运行时证据。 |
| SNR 指令执行入口和 opcode dispatcher 闭合 | 任一 PMAP->MMAP->ZMAP->PMAP 完整转场链 | 当前 SNR 文件名模板替换结果当前 opcode byte当前指令指针/segmentscene_kind / scene_id | 定位 opcode 分派结构,把 0x09/0x11/0x2E/0x36 等常见指令绑定到 MAIN handler。 |
对应 Markdown:docs/generated/main-exe/MAIN_EXE_P2_RUNTIME_CLOSURE.md。结构化数据:docs/generated/main-exe/main-exe-p2-runtime-closure.json。