• 如何把ASM技术应用到口袋改版ROM中

    2009-06-17

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/liuyanghejerry-logs/41137917.html

    ASM代码在脚本中的应用 当我们写的脚本被编译器编译之后,它将转化为游戏能够识别的16进制命令.这些命令都是游戏在设计时本身就默认存在的,凭借这一强大的命令库,我们能够实现很多东西.但假如我们要的命令根本不存在呢?在回答这个问题之前我们需要稍稍了解下ASM了.GBA的运行原理和电脑很类似,它也是由一个处理器来执行各种运算并依靠内存来临时储存数据,同时也有自己的显卡等设备.在电脑上,我们知道处理器最终是在运行机器码,而机器码则是用汇编代码编译的.汇编可以认为是人写的最底层的程序代码.对于GBA也是一样,ROM在运行时也会被解释为机器码.而通过汇编语言,我们同样可以写出机器码.我们通常说的ASM,就是指自己写汇编代码编译成机器码嵌入ROM. 《口袋》的GBA系列作品绝对是被研究最多的GBA游戏,这使得我们能够破译游戏是如何调用原始的机器码.这样,就能够自由的在游戏中调用自己写的汇编程序了. 因为汇编程序是能够访问到GBA底层的,所以我们可以通过对数据的操作创造出新的命令.而在脚本中呼出ASM代码,就能够使用自己创造的命令了. 那么如何在脚本中呼出ASM代码呢?我们通常只需要一个命令:callasm. 格式: callasm 0x[地址] 这里的地址指的是嵌入ASM代码的ROM地址. 我们假设位于0x80000有一段我们之前写好转换的ASM代码,它实现了"改变对话中字的颜色"这一功能.于是: #org @1 lock faceplayer callasm 0x80000 message @2 MSG_NORMAL release end

    如上,我们呼叫ASM代码完成了一个功能,表面看来就像special命令一样. 注1:有时需要不止1次呼叫ASM代码以实现特定的过程,比如我们在message命令后再次呼叫另一个ASM代码以换回文字颜色. 注2:ASM代码有两种,其中的THUMB模式最为常见.呼叫THUMB模式的ASM代码需要给ASM地址+1,如callasm 0x80001.这是必须的,否则便会出错. 下面,我们以我写的一个时间读取ASM为例,演示如何把转换好的ASM应用到实际. 首先明确一下时间读取ASM的作用. 我们都知道火叶中没有内置时钟,所以也没有和时间相关的事件.那我们想把事件和时间关联,怎么办呢?这里我提供一个方法:依靠游戏进行时间(即累计游戏时间). 但新的问题出现了,火叶中没有读取累计游戏时间的命令啊. 本次的ASM代码即可实现它,并将小时数存入了变量0x800D中. 小小的看一下源码吧: .text .align 2 .thumb .thumb_func .global asm1 main: ;FR_ONLY push {r0-r1, lr} ldr r0, .PLAYER_DATA ;读取玩家信息 ldr r0, [r0] ldr r1, .VAR1 ldrh r0, [r0, #0xE] ;找到并读取其中的游戏时间小时数 strh r0, [r1] ;存入变量 pop {r0-r1, pc} .align 2 .PLAYER_DATA: .word 0x0300500C .VAR1: .word 0x020270B6 + (0x800D * 2) 编译得到: 03B5034800680349C089088003BDC0460C500003D0700302 通常的ASM代码我们都能得到这种的,所以不必操心如何编译. 现在打开16进制工具载入ROM. 选一处空闲位置,把ASM代码复制进去.复制时要注意两点: 1.复制一定要用覆盖的方式,而不是插入.否则会导致后面的数据整体偏移,游戏运行时必然会出错.我习惯用的是WinHex,大家如果用UE的话也一定注意,如果缺少这项功能的话可以先插入再在其附近删除等量空位,保证没有偏移. 2.由于THUMB模式要求,ASM代码的起始地址末位必须是0,4,8,C之一.如0x80000可以,而0x80003不行(这和前面说的+1不矛盾,这里指的是实际地址而不是呼叫地址) 记下ASM代码的位置. 现在开始编写相应的脚本. 我们依靠ASM代码得到的小时数是存在变量中的,实际使用时可以直接用它做计算.这里为了简明,我们用对话把小时数显示. 不过变量值是无法直接显示出来的,我们需要借助一个buffer系的命令.该组命令是用来将游戏内部信息转换为外部信息的,比如将PM内部编号转化为名称. #org @1 lock faceplayer callasm 0x[地址]+1'注意了,HEX插入的地址必须+1,这是THUMB模式必须的 buffernumber 0x00 0x800D'buffernumber命令可以把HEX换成DEC message @2 0x2 release end #org @2 = You've been playing for [buffer1] hours!' [buffer1] 表示第一个被buffernumber转换的值

    现在我们用XSE写入这段脚本,并用一个人物触发脚本: 果然,我们的ASM代码成功的读取了游戏时间!

    分享到:

    历史上的今天:

    C++学习手记 2009-06-17