Aug 25, 2010

[转]DS ROM深度HACK教程--动态调试操作挂钩篇

原文地址:http://www.ndsbbs.com/read.php?tid=180038

最近因为方向键坏掉~又想玩RY传说~于是开始着手研究DS的操作挂钩~
简单点说~就是把RY传说这个本来不能用触摸的游戏改成全程触摸版~

〇,修改必备
1,必备工具:IDEAS模拟器(本人用的1020版~因为速度比1024快~),16位修改器,静态反汇编工具,编译工具
之所以要IDEAS是因为在主流模拟器里只有IDEAS提供免费的调试功能~虽然十分的简陋(可以说啥功能都没有)~但是总比没有要强几倍~
16位修改器和静态反汇编工具~本人推荐用CT2的那个专为DS ROM优化后的版本~那个版本直接支持ARM指令反汇编~

一,思路分析
要挂钩操作无疑要做以下几件事情
1,找到按键的程序可识别地址
2,找到触摸屏的程序可识别地址
3,找到合适的地方下断
为了解决前2项问题~首先想到的最简单的方法当然是用EC直接搜~

二,EC搜索
相信有一定模糊搜索基础的人可以很快找到方案来搜索按键判定和触摸判定~也就是说~这个步骤理论上来说应该是一点难度没有的可以快速解决的~可是事实上的情形却复杂的多~
1,按键部分:用EC顺利搜索出几个地址表现出按键的变化~但是试着锁定后发现~无论哪一个都无法对游戏内容产生影响~也就是说用EC搜到的这几个变量仅仅是程序可表现的~而非程序可识别的~简单点说就是你可以看他来判断按了啥键~但是不能通过改变他来改变按的键~
2,触摸部分:用EC直接啥都搜不到~
在按键和触摸2个方面皆碰壁~给人的唯一结论是~用这种只就其表不问其根的方法来搜索本质就行不通~于是下面俺开始介绍文章的正式部分~
通过DEBUGGER来动态调试ROM~

三,关于DS的输入识别所必须具备的知识
别以为这个只是科普讲座~这个可是后面DEBUG过程中最重要的依据~所以请仔细看过这段~

DS是由2个处理器同时处理程序的系统~ARM9为主处理器~ARM7为协处理器~ARM9用来处理游戏的绝大部分信息~而ARM7辅助处理声音~I/O等一些底层信息~
关于ARM9和ARM7的分工我暂不多说~但是需要注意的是~在很多底层方面的东西ARM9是无法正常访问的~

接着说说DS的按键和触摸屏输入的过程~
按键部分~DS有一个16位的只读按键寄存器~其作用就是识别按键并将按键信息存放其内~而这个寄存器映射在内存空间上的地址是0x04000130 意思就是说~游戏只要检查这个地址的值~就可以很轻松的判定所按的键了~
不 过事实上还少许有一点麻烦的部分~就是这个寄存器所对应的键并不是DS上的全部键~X,Y键并未被对应在这个寄存器中~而是另外一个入口为 0x04000136的只读寄存器~有趣的是~这个寄存器除了对应X,Y键以外~还对应了触摸屏的状态~也就是说要检查触摸屏也是要访问这个寄存器的~

或许你会说~那么只要检查这2个寄存器岂不就可以很轻松的获得按键和触屏信息了~
但是事实上有2点问题~
1,这2个寄存器都是只读寄存器~也就是说虽然可以得到信息~但是仍然改不了~
2,最烦躁的问题在于~0x04000136这个寄存器是仅能由ARM7访问的~而通常游戏的程序是写在ARM9当中的~……

因此现在面临的问题就是:X,Y,触摸屏无法通过ARM9访问~
那么现在那么多DS游戏又是怎样访问这些部分的呢~
其实很简单~在ARM7程序中会有一部分代码专门用来处理这个寄存器~并将按键和触摸信息插入一个叫IPC的共享内存结构中上报给ARM9
也就是说这样问题就转换到了寻找IPC地址和按键识别程序所处地址了~

四,调试程序必备知识
这一段不同于上面一段主要介绍理论~这部分主要要介绍的是调试一个程序所常常会用到的一些操作技巧~

作为一个调试器(DEBUGGER)最重要的几个功能在于:
1,跟踪 2,下断点 3,动态修改状态
然而IDEAS提供的这个免费DEBUGGER很不幸的少了最方便的一个功能~下断~……
这无疑会给我们的工作带来很多不必要的麻烦~但是这些麻烦往往也并非不可解决~

接下来我要讲讲调试最基础操作~跟踪~所具有的一些技巧~
1,步入:简单的来说就是顺着程序的正常流程一条一条的往下执行~这个流程包括跳转和调用~这是任何一个调试器都肯定具备的功能~(IDEAS对应快捷键F8)
2,步过:这个在大致上~和上面一种差不多~但是有个很根本的区别:步过的话在碰到调用指令的时候并不会跟踪进入所调用的函数~而是一次执行完该函数~在调用指令的物理下一行才停止下来~事实上这种跟踪模式比起步入来说~用的更加广泛~
但是十分不幸的是~……IDEAS又没有步过功能~……所以这时候我们就要找到代替手段~

IDEAS除了步入以外~唯一提供的一个功能是~运行到指定行~(对应F6)
这个功能可以简单的理解为在光标所指定的地方下一个断点~然后放程序运行~当运行到指定地方的时候~自然就会被断下~这个功能是唯一取代下断的方法~不过遗憾的是~这样全程序就只能下一个断点~很多逻辑结构就无从分清~
另外这个功能还可以用来事先步过~在跟踪看到调用命令时(ARM里的调用命令是bl *****)将光标指定到该命令下一行~然后F6~然后就顺利步过了~

五,开始着手实际调试吧~
对于一个刚刚上手的程序~我们对其结构~特征地址~重要子程序~重要内存标示~都一无所知~所以我们需要选择一个尽量单纯的和确定性的地方开始我们的调试~
按照经验来说~最符合这个条件的地方便是程序的开头~

先试试一路步过~让程序跑跑会怎样~
一 路F8,F6~在顺利通过几个调用指令后~出现了异常情况~:某个调用指令一步过后游戏的开头LOGO便播出来了~这便说明~OP的处理程序在这里调用的 那个子程序之中~因为OP中有识别A键跳过LOGO的功能~所以就是说在这段OP程序里肯定能找到我们需要找的按键识别程序~
记下这个调用指令的地址和调用的地址~重置调试器~直接F6到该指令~然后F8步入~

继续对于子程序内的代码步过~发现需要的内容后便步入~并一路记录进入的地址~
最后可以找到一个子程序~在LOGO显示出来后~游戏调用这个子程序~对其直接步过的话~进入一段时间的延时~而且延时中途可以按键取消~
很显然这个就是我们要找的程序了~

大致记录一路过来的地址~大致会像这样~:
2000bec OP LOGO

206e1c8 bl 0x0206e24c ;r12=3ff(调用26b30),亮屏

206e1dc logo1
206e3ec
206e47c blt 0x0206E440 按键延时
最后这行的调用便是延迟部分了~

六,寻找按键输入识别程序
刚才的部分我们找到了开头LOGO里的延时程序~接下来我们要从这段程序里找到按键识别用的程序~
前面之所以要从开头下手~就是因为在这段相对单纯的LOGO处理程序里找我们的目标~肯定比在游戏进程中找要来的简单的多~

要找东西~就要有明确的标志来告诉我们~要找的东西究竟是还未到~还是已经过了~因为这次我们是在延迟程序里搜按键的处理程序~所以当然是看延迟是否跳过来判断按键处理程序的位置了~

具体的操作比较有意思:
从 延迟程序开始~一路往下F8~看到bl,blt等调用指令的时候停住~把光标落到下一行准备步过~这个时候按住模拟器设定的DS的A键位~然后再按下 F6~然后松开A键~这样~如果按键识别程序是在步过的这个调用里的话~那么马上F5放开程序任其运行~应该游戏就马上跳过LOGO了~相反~如果说要找 的那程序不在这段调用里~那么F5放行后~应该还照常有一段延迟~LOGO才过去~
因此很方便就能判定按键识别程序是否在这某个调用里~一路用这个方法找进去~并且记录下地址~应该就能像以下这样~
206e440: bl 0x02026b30 ;call 按键检测
2026b6c: bl 0x02026c54 ;检测按键·里
2026c5c: bl 0x01ff84f0 ;检测按键·里2
读键部分:
1ff84f0(20a1ff0): ldr r2,0x04000130
....
1ff84f8(20a1ff8): ldrh r12,[r2]
最终发现~就是以上的最后一行~在对于按键的检测起作用~这行的意思是:
把r2寄存器所指定的地址的内容读入r12寄存器~而r2的内容就是上面那行所指定的0x0400130
这样便清晰了~这条就是读按键寄存器4000130来检查按键的语句了~
无疑~只要在这里下断放入我们的修改程序~虽然不能改变4000130的内容~但是只要窜改r12的内容~对于后面程序的影响也无异于改按键了~所以这个地址就是我们HACK ROM的入口地址了~请一定记住~

但是相信稍微有点DS程序经验的人看到这个地址一定会觉得十分的奇怪~按道理来说~DS的内存空间是从地址0x02000000开始的~但是这个程序的地址却是0x01ff84f8~居然在内存空间之前~
其 实这个地址所在的区域叫做ITCM 简单的说~就是DS所提供的一块高速缓存~因为只靠一味提高CPU主频速度来增加代码的运行速度~只能导致严重的发热和耗电问题~这个对于掌机是十分不利 的~所以滑头的老N在DS里提供了大量的高速缓存部分用以存放一些需要频繁访问的内容~以上这段按键识别命令无疑符合这个前提~所以被载入了ITCM而非 内存中~
那么这段代码本来如果要线性载入会被载入哪里呢?~这个问题关系到修改ROM的时候要在ROM文件的哪里来找这个代码的问题~
解决方法是~随意找一段该部分的16进制代码~然后在CT2中搜索~搜到后~切换到反汇编模式~这时候看到的这个代码前面对应的地址就是线性载入时候对应的地址了~俺前面那个记录里括号里的(20a1ff8)就是这个线性地址~

不过这样只是解决了除了X,Y以外的其他按键的问题~那么X,Y和触摸屏的问题如何解决呢?~

接着我们顺便看看刚才找到的那段识别按键的代码~
01ff84f0: ldr r2,0x4000130
01ff84f4: ldr r1,0x27fffa8
01ff84f8: ldrh r12,[r2]
01ff84fc: ldrh r3,[r1]
这里的第1和第3行就是刚才分析的读4000130的代码~相信大家都注意到这里第2和第4行~形式和1~3差不多~功能就是读取0x027fffa8这个地址的内容到r3~
基于这里是按键识别程序~而且4000130只能读出部分按键~不难猜测出~这个27fffa8定然是用来读取剩下的X,Y按键的地址~
继续分析这个地址~27fffa8~和4000130一样~都不在正常的内存空间之内~但是4000130是I/O寄存器~而这个27fffa8所在的地方是DS内一段ARM7与ARM9共享的内存区域~也就是说~这里的数据通常都是用于ARM7和ARM9通信之用的~
那么结合我前面介绍的基本知识~不难得出结论~这个27fffa8所在的地方必然是通信用IPC结构的地址~

用上面的方法~我们无法找到触摸的识别程序或者识别地址~因为游戏里没有任何一个部分会对触摸进行实际响应~
但是通过上面的部分~我们找到了IPC结构的地址~这个非常重要~因为X,Y键信息是和触摸屏信息一起被放入IPC的~所以触摸信息必然在27fffa8周围~
(而且最重要的一点在于~似乎不同ROM~不同游戏所用的IPC结构都是一模一样的~也就是说在共享内存中的地址都是一样~这个对于其他ROM的调试来说~无疑是找到了一条超便利的捷径~)

通过按下X,Y键~观察IPC中的数据变化~很快找到了按键与那个地址内容的对应情况~但是让人十分费解的一点是~无论如何点击触摸屏~对于该块数据都毫无影响~
难道说是之前的推论错误嘛?~显然应该不是这个原因~真正的原因在于~由于RY传说从头到尾都没有使用过触摸屏~所以这个功能根本一开始就被封印了~……

七,研究触摸~就需要研究能触摸的游戏~
刚才的研究无疑收获不浅~相当多有用的信息都顺利得到~甚至可以说除了触摸以外的所有问题都顺利解决了~但是无法忽视的是~那个结果确实也给人当头一棒~:
RY传说压根就没有触摸识别程序~……

为了确认这点~并且深度研究触摸的作用过程~当然我们首先需要的就是一款能够触摸的游戏~我选用的是过去的一款电击文库~因为是单纯的电子小说~所以代码应该相对比较简单~而且该游戏是支持全程触摸的~

打开游戏~随意运行下后暂停在开始的标题菜单选项那里~其实放哪里都无所谓~只是我觉得这里因为只要不点中选项可以一直保持状态~所以很方便~
先F5放行~随意点住触摸屏上一个点~然后F4暂停~因为刚才我们已经找到IPC地址了~所以这次当然省掉了不少麻烦的步骤~直接将内存观测窗切到27fff80来观察一下这部分数据~
就算一次看不出来~多点几次也能很快发现~原本在RY传说里对应XY识别的27fffa8,a9两格之后是一串00的~但是这次后面4格里却有了数据~
在不点触摸屏的时候是 00 00 00 06 而当点住后便是 ** ** ** 01 上面**之处的数据稍微分析下可以发现 *a b* cd 01 里面 ba 组成X轴坐标 cd 组成Y轴坐标~而最后那个01当然就是指的触摸屏被按下的状态~

到此~关于触摸的IPC也找到了~欣然以为问题都解决了?~可是面前还有个超严峻的问题~……RY传说的触摸屏可是被关闭的啊~……
为了解决这个问题~俺的第一反映是去ARM7里找答案~

八,对于ARM7的种种研究
因为要研究触摸屏~所以依旧使用电子小说的ROM~将调试器切换到ARM7模式~F5放行一下~不同于ARM9~并不会有什么明显的反映~

随意暂停一下~会发现有很大几率程序会停在BIOS段里的一个返回指令bx lr上~而且虽然lr寄存器有值~但是无论怎么F8~都无法继续跟踪~这种现象叫做软中断简称swi~是底层程序所惯用的一种手段~暂时不用深究~

偶尔暂停会停在可以跟踪的地方~这时候一路遇见bl就F6步过~遇见bx lr就F8跟出~应该很快就可以跟踪到一个循环执行的程序~找到循环后记下其实和循环跳转的地址~然后再多试几次暂停~

非常奇怪的是有一点~似乎暂停后跟踪到的主循环~还有很多不同版本~……可能几次跟踪出来的循环的地址和内容都不同~而且每一个循环都无疑是最外层主循环~没有跳转出去的指令~

因为之前已经记录下地址~所以用F6分别到不同的循环进行功能考察~
具 体做法其实也很简单~因为ARM7是直接访问硬件~然后把信息写入IPC的~所以只用故意窜改IPC的内容和实际不符合~然后观察何时被修正回来~就知道 起作用的指令在哪里了~因为我们要考察的是触摸屏~所以选择了27fffad这个地址~因为这个地址在没有触摸的时候为06有的时候为01~
在循环之初把该地址强制设定为01~然后对每一个bl调用都F6步过~因为现在的状况是没有触摸的~所以一旦到达触摸判定的程序~必然会导致该地址由01变成06~

对于几个循环都分别测试后~发现了很奇怪的结论~
大多循环在循环的过程中01都会变成06~但是时机却完全没有一点规律~在每一个bl处都有可能会变掉~……
不过有奇怪的当然也会有正常的~在找到的几个循环里有一个~他的01到06的切换是非常严格的符合在某个调用语句内的~顺着这个调用一路找~最终不难找到了ARM7真正的识别触摸屏的程序~
3804628(238C7D8)~3804678

3804634: bl 37fcccc   ;key

380465c: bl 3804b74   ;touch
3804c18: bl 380516c   ;touch code to 380a878
28055c4: ldr r1,40001c0
38055c8: ldrh r0,[r1] ;read touch by reg
这个循环不但处理触摸~按键的处理也在这里完成~无疑~这个循环就是ARM7的输入处理程序了~

因此抱着试一试的心态~俺把这个电子小说的ARM7给替换了RY传说原本的ARM7~然后调试替换后的RY传说的ROM~

游戏在载入后存档处有点不顺(卡在初始存档那)~这个是换ARM7在模拟器上经常出现的症状~而且我们在乎的也不是这个~于是无视就可以了~

进 入调试模式~看IPC~……非常遗憾~在本应该是触摸信息的那个地方依旧是一串00~……于是~继而切换到ARM7调试模式~找到刚才的那个输入处理循 环~F6~下断~等着程序暂停到那里方便研究~可是一等不停~二等不停~……事实上就是根本不会停在那里~……结论是~这个循环压根就没被执行~……
为什么?~明明这个ARM7在之前的ROM里会很好的处理触摸~为啥在RY传说里就根本不执行那段了呢?~

于 是俺找到原RY传说的ARM7~对一些特征指令进行搜索后惊讶的发现~虽然地址和极小部分细节不同~但是其实原ARM7里也有处理触摸的那段程序~不仅如 此~可以说2个ARM7除了一些无关紧要的细节和程序对应的地址有差异以外~根本就是一模一样的~……也就是说决定那段代码是否运行的~是ARM7的代码 之外的其他某些原因~……

为了搞清这个外因是什么~我们再回到对电子小说的ROM的研究~
之前研究ARM7~一直是从中途来找循环的~这次我们从开头开始~
因为ARM7的代码十分有趣~虽然刚进入程序的时候是被载入在2380000开头的区域的~但是跟踪一段后~会发现前面的部分为类似解压的功能~将真正的arm7代码载入到3800000开头的一段区域里~
继续跟踪一段后~终于进入了主循环~这次的主循环是真正意义上的ARM7根循环~不同于前面找到的那些~某种程度上只是中断调用~
让我们看看主循环的代码~除了几个无关紧要的数据处理程序外~有一个调用十分有趣~这段代码里起作用的只有一句~
3804502: swi 0x06
这个swi语句~就俺来说是十分陌生的~上网GOOGLE了一番后得知~这个就是ARM的软中断调用指令~而swi 06具体对应的功能是swiHalt~也就是暂停~……
也就是说对于主循环来说~他真正在做的事情~只是维护少部分数据~然后暂停进程~并进入等待~等待其他中断处理程序给他解禁~……

事到如此~貌似一点进展都没有~依旧没能搞清楚~究竟是什么原因导致重要的触摸循环没被执行~但是事到如此~却有个非常暴力的解决方法~:在ARM7主循环里强制插入对触摸识别程序的调用~

3803c90(0238be78):读输入循环
3803cc4(0238beac):调用读TOUCH
37f842c(02380614):主循环开头
37f8450(0238063c):主循环结束跳转
具体做法倒是比较简单~把主循环的循环跳转指令依照上先前记录的数据(括号里是线性载入地址~也就是ROM文件里的线性地址)~重新定位到识别触摸的程序调用那里~然后把调用的下一行改成跳转~重新指回主循环的开头~

因为不同ROM的ARM7文件本质上都是一样的~但是随意替换会导致模拟器或者烧录卡的兼容问题~所以俺修改的是RY传说的原始ARM7~

到 现在~之前说的3个问题~按键识别地址~触摸识别地址~下断地址~以及中途出现的新问题~触摸被关闭的问题~全部解决~这样用ARM汇编简单的写段将屏幕 不同区域和按键进行对位的小程序~然后插到arm9的空白部分~设定好跳转后~配合之前修改的arm7~打包成新ROM~

放到IDEAS 上运行~BINGO!~一切顺利~顺利的用触摸屏控制按键~正准备烧到机器上玩的时候~随手用NO$GBA运行了一下~……结果只有一个字~艹!~……居 然完完全全的一点用没有~……触摸部分依旧被完全关闭……然后俺又不甘心的给烧到了卡上……果然还是没用……触摸依然不行~……结论只有一个~因为 ARM7的作用机理十分复杂~强制对其进行暴力修改~虽然在某些模拟器上可以正常运作~但是在实际DS上却是无法行的通的~……

九,回到ARM9~换个思路找出路~
受到刚才ARM7修改的打击~只好重新将思路转回ARM9~因为还是触摸问题~所以依旧是研究电子小说的ROM~

用刚才在ARM7曾用过的找触摸程序的改27fffad的方法~来跟踪arm9代码~因为有之前的种种经验~这次很顺利的找到了触摸的IPC改变前后~在ARM9执行的程序~
2000d84: bl 0x0200b070 ;key & touch
200b128: bl 0x0204e1a8 ;touch->
204e1b4: bl 0x0204ddf0 ;touch-->
从最后一行的那里跟入~会发现204ddf处所对应的程序是一个类似死循环的部分~
204ddf0: ldr r1,0x2094568
204ddf4: ldrh r2,[r1+0x36]
204ddf8: ands r2,r2,r0
204ddfc: bne 0x0204ddf4
204de00: bx lr
以上就是这个子程序的完整代码~唯一的功能只有不断的检查某个内存的值~不符合则继续循环~……
然而奇怪的是~这个程序明明只有读取没有写入~应该不会改变任何内存的值~也就是说这个循环应该永远不可能跳出的啊~可是事实上在bx lr处按F6却顺利出来了~而且就是在出来的这个时候~IPC上被强制改错的触摸值~也会被修正过来~
因此推测出这个程序的功能是等待ARM7的触摸识别程序处理完而已~
在这里等待~就表示在这不久前面就会是从ARM9发向ARM7的读触摸的请求~
因此回到外层的子程序里~留心一点~不难发现~在这层里有按键处理程序~而且整个的大致结构和RY传说的按键处理程序几乎一模一样~只有一个非常显著的区别~就是在程序尾处多了以下几个调用~
200b120: bl 0x0204e200
200b124: mov r0,r4
200b128: bl 0x0204e1a8
显然~最下面的第二个调用就是刚才跟踪进去的那个~用于等待ARM7处理结束的程序~那么很自然的就能推测出~第一个调用的功能向ARM7发送读触摸请求的了~

对于这个程序步入跟踪~得到一下的内容~
200b120: bl 0x0204e200 ;FIFO SEND
204e21c: bl 0x0204c458 ;FIFO SEND->
204c490: ldr r2,0x4000184
204c4e8: ldr r1,0x4000188
程序里分别使用了4000184和4000188这2个接口~看是4打头的就该知道~这2个是I/O接口的寄存器了~而实际上这2个寄存器正是FIFO队列的2个重要寄存器~
关于这个FIFO队列~要说清楚比较麻烦~但是这里只需要搞清楚一点~就是FIFO的用途是ARM7和ARM9的相互通信~这样程序就明了了~204c458这段程序无疑就是向ARM7发送触摸请求的代码了~

十,完事具备~只欠东风
事情到这里~问题都已经解决了~
1,按键的修改:除了X,Y键以外的~在将按键寄存器读入r12的时候~修改r12的值实现按键修改~而X,Y键则可以直接修改IPC上对应的地址~
2,触摸的识别:直接检测IPC上触摸对应的地址~
3,合适的断点:当然只能是在将4000130读入r12的这一句处~因为是要修改r12~所以若不在这里就一点意义都没有了~
4,触摸屏解封:调用其他rom里的FIFO处理程序向ARM7发送触摸请求~

现在就是要实际完成ROM修改的时候了~

主要介绍下如何给触摸屏解封~:
1,首先是从电子小说的ROM中提取FIFO处理程序~地址是204c458的这段程序~值得注意的是他还调用了2个子程序~一次都要提取出来~
2,在自己的修改代码里调用提取出来的程序~值得注意的是~这个子程序是带参数传递的~调用的时候别忘了~
3,设置一个等待程序~用来等待ARM7处理结束~因为原本的标识位涉及到很复杂的工作~所以俺放弃了原程序的等待程序~而是事先给IPC的触摸位赋错值~然后检测何时被更正~来判定ARM7是否执行完成~
4,还原环境~因为FIFO程序比较复杂~基本改变了从r0到r14的所有寄存器~所以在前面的工作都完成后~为了后面的不受到影响~一定要还原之前的环境~

之后的代码便是简单的捣弄下各个数据之间的转换~完成按键到触摸的映射就可以了~

等待程序r_wait的代码如下:
S:
stmdb r13!,{r0-r7}
ldr r0,ab1
L:
ldrb r1,[r0]
cmp r1,#0x0
beq L

ldmia r13!,{r0-r7}
bx lr
ab1: .long 0x027fffad

主程序main1的代码如下:
S:
stmdb r13!,{r0-r12,r14}
ldr r0,ab1
mov r1,#0x0
strb r1,[r0]

mov r4,r0
mov r0,#0x6
mov r1,#0x3000000
mov r2,#0x0
bl FIFO_snd
mov r0,r4
bl r_wait
ldmia r13!,{r0-r12,r14}

ldrh r12,[r2]
stmdb r13!,{r0-r7}
ldr r0,ab1
ldrb r1,[r0]
cmp r1,#0x01
bne ed1

ldr r0,ab2
ldrh r1,[r0]
mov r3,r1,lsr #0x4
and r3,#0xff
ldr r0,ab3
ldrb r4,[r0]
ldrb r5,x1
ldrb r6,x2

cmp r4,r5
bcs row2
row1:
cmp r3,r5
bcs c2
c1:
ldrh r12,cm1
b ed1
c2:
cmp r3,r6
bcs c3
ldrh r12,cm2
b ed1
c3:
ldrh r12,cm3
b ed1
row2:
cmp r4,r6
bcs row3
cmp r3,r5
bcs c5
c4:
ldrh r12,cm4
b ed1
c5:
cmp r3,r6
bcs c6
ldrh r12,cm5
b ed1
c6:
ldrh r12,cm6
b ed1
row3:
cmp r3,r5
bcs c8
c7:
ldr r0,ab4
mov r1,#0x24
str r1,[r0]
b ed1
c8:
cmp r3,r6
bcs c9
ldrh r12,cm7
b ed1
c9:
ldr r0,ab4
mov r1,#0x28
str r1,[r0]

ed1:
ldmia r13!,{r0-r7}
b 1ff84fc

ab1: .long 0x027fffad
ab2: .long 0x027fffab
ab3: .long 0x027fffac
ab4: .long 0x027fffa9
x1: .byte 0x50
x2: .byte 0xb0
y1: .byte 0x50
y2: .byte 0xb0
cm1: .int 0x03fd
cm2: .int 0x03bf
cm3: .int 0x02ff
cm4: .int 0x03df
cm5: .int 0x03fe
cm6: .int 0x03ef
cm7: .int 0x037f

代码全部写完也编译好了后~接下来就要LINK链接了~因为格式很不规范~所以么办法用程序来链接~只能手动来完成~
先 用DOS的COPY命令将主要程序main1.o 提取出来的FIFO程序FIFO_snd.o 一同提取出来的FIFO_snd所调用的2个子程序sx2.o 等待程序r_wait.o 全部顺序合成一个文件~然后用CT2打开~找到每个bl调用指令~然后把调用指令的调用地址全部修改正确~这个部分就算完成了~

最后将之 前完成的那整段程序~全部插入到ARM9文件的空白处(这还不能乱插……程序有点大~势必要覆盖掉一部分东西~找个都是无用信息的地方给塞进去~)~俺插 的是2092800处~然后在20a1ff8处改成跳转到我们代码的指令~(需要注意的是这里实际是被载入到1ff84f8~所以计算跳转差量的时候要用 这个值)~再把我们插入的代码的回跳指令指向那个的下一行~一切就算修改完成了~

十一,完成~
把这个修改好的ARM9文件~替换原ROM里的ARM9~然后打包运行~所有模拟器~DS实机~皆运行无误~修改成功!~

0 comments:

Twitter Delicious Facebook Digg Stumbleupon Favorites More

 
Powered by Blogger