命令15,目的是建设城堡。
代码1:复制地图数据,每个郡的地图尺寸为13列*12行,偶数列的每行顶头排列,奇数列的每行下移半个高度排列。所以一共有13*12=156=0x9C个字节存放。每个字节是资源类型,00~06不等,分别代表树林、草原、水、城堡、主城、山等信息。地图数据在ES段开始的0偏移处,第N个郡的数据就是N*0x9C,这些数据会复制到DS的0xB13A处。
def province_map_copy_data_to_b13a():
current_provnice_offset = Data.get_current_province_offset_from_339A()
province_no = Data.get_province_no_by_province_offset(current_provnice_offset)
Data.SetWordToOffset(Data.DSBUF,Data.GetWordFromOffset(Data.DSBUF,0xbe9a),0xbe06) # 0002d5c0
# every province mini map has 0x9c bytes
minimap_offset = province_no*0x9c
Data.SetWordToOffset(Data.DSBUF,minimap_offset,0xbe04) # 0002d5c8
# 这里实际从ds复制
Data.copy_from_es_offset_to_ds_offset(minimap_offset,0xb13a,0x9c,1) # 0002d5d0
代码2:0x820C处存放着11个郡名称的文字描述,每个郡对应郡名称的编号在郡偏移+0x22处。
current_province_offset = Data.get_current_province_offset_from_339A()
description_offset = 0x820c+Data.DSBUF[current_province_offset+0x22]*2 # 0002d68A
Helper.draw_text_with_format([0x839D,Data.GetWordFromOffset(Data.DSBUF,description_offset)])
代码3:在屏幕右侧显示小地图,位置是(0x40,0x27),尺寸是13*4和12*2,即宽52高24,然后三国2会纵向拉伸1倍。
这个代码很难翻译,所以我构造了一个CpuRegister类,来逐行复刻IDA反编译出来的解码、操作显存的操作。EGA模式下,有4个plane,需要逐字节读写。最后组合这4个plane的bit,构造出一个调色板索引。依据此索引,在pygame.image上做set,即可得到图片。
代码4:屏幕左侧大地图,与小地图原理类似。
代码5:建造城堡的地方,地图块资源类型大于等于3的无法建设城堡,分别是:水、山、主城、已有的城堡。城堡建设完成后,在对应的0xB13A开始的线性地址中,更改数据编号为5(代表城堡),同时修改ES地址段的相应位置数据。黄金减5000,城堡数+1。
Data.officer_set_can_do_action_status(officer_offset)
Data.DSBUF[0xb13a + r * 13 + col] = 5
self.command15_build_chengbao_draw_full_map()
current_province_offset = Data.get_current_province_offset_from_339A()
province_no = Data.get_province_no_by_province_offset(current_province_offset)
Data.ESBUF[province_no * 0x9c + r * 13 + col] = 5 # write back the new state to es buffer
gold = Data.GetWordFromOffset(Data.DSBUF, current_province_offset + 8)
gold -= 5000
Data.SetWordToOffset(Data.DSBUF, gold, current_province_offset + 8)
Data.DSBUF[current_province_offset + 0x1a] += 1
[ 本帖最后由 juqiang 于 2025-11-28 07:07 编辑 ]