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实机~皆运行无误~修改成功!~

Aug 24, 2010

[转]不求人!DIY 自己找寻 NDS 游戏金手指密码_2 (ARDS 条件判断式指令)

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

前 言
在第一篇教程推出后,有朋友反映了一个问题,就是使用过 HasteDS ,发现连系模拟器后,
0x02000000 的定址不准确。
另外有朋友说所用的烧录卡不支援金手指,只能使用作弊补丁。
有关 HasteDS 定址问题,大家可转用其他习惯使用的搜寻工具来搜寻作弊码,
而作弊补丁是以工具对修改后的 Rom 比较原 Rom 后产生的文件,
使用者只需以补丁工具使用该作弊补丁文件写入到原 Rom 即可,
本文(或往后的续篇)将不会详述及示范补丁工具的使用,只示范修改 Rom 的例子,
有关补丁工具的使用,请大家在网上查找一下,很容易就能找到补丁工具及使用说明的了。

另外有朋友向本人介绍一个搜寻工具 Renegade v1.67
优点 - 是支援 No$gba 2.4a、搜寻选项及过滤条件很多,与及可以在该工具使用金手指码...
缺点 - (个人认为)是界面复杂及太多与 NDS 无关的功能选项。
有兴趣使用的朋友可在网上找来测试使用。

本来前天就已写好这第二篇的内容,示范把作弊码找出后转为 DipStar 金手指,
并配合 Slot-2 卡使用,及验证 HasteDS 定址的准确性,当完成原稿及截图后,
在版区看到有另外的热心朋友曾发布修改教程,用的是 GM8,从回帖中也看到此作弊修改工具,
颇受大家欢迎,也很多朋友长期使用这个,而且,似乎更多朋友对静态修改感兴趣,
因此,本人把已写好的原稿及截取的图片删除,重新编写本篇内容,题材也改变了,
不进行验证 HasteDS 定址的准确性了。(反正验证后的结果就是确定间中会出现定址错误),
DipStar 范例也不要了,有使用支援 DipStar 烧录卡的玩家,应该早已懂得使用的了。




Action Replay DS 条 件 判 断 式 指 令
依照第一篇教程的范例,相信学习者都已懂得自己找寻作弊码了,
但若果只能单调地反覆不停对记忆体写入数据,显然不足以应付不同情况下的使用需要,
幸好 ARDS 提供条件判断式指令,这就令 ARDS 金手指的应用范围大大提高,
现在就先来介绍一些常用的条件判断式指令。

9XXXXXXX ZZZZYYYY ( 等 于 )

这是条件断判式指令中最常用的一个,检查 0XXXXXXX 位址上的值是否等如 YYYY

使用场合:
1.依按键值来启动作弊码 (这里的 "作弊码" 狭义解作 "直接写入记忆体" 的金手指码)。
2.当变量达到指定的值才启动作弊码。

使用例子:94000130 000001BB  检查使用者是否按下 Select + L + Up 键
220031C0 000000FF  把 1 Byte 数据 0xFF 写入到位址 0x020031C0
D0000000 00000000  结束

指令原型:if YYYY == (not(ZZZZ) & [XXXXXXXX])
指令意思:假如 2 byte 数据 YYYY 等如 not(ZZZZ) & XXXXXXXX 位址上的 2 byte 数据。

== 是 "等如" 的意思,not& 是运算符,& 也等同 AND,用法如下:

Not 参数只有一个,用来把真假值反转,
Not(1) = 0
Not(0) = 1

AND 的参数有两个,要两个都为真值结果才会是真,否则就是假。
1 AND 1 = 1
1 AND 0 = 0
0 AND 1 = 0
0 AND 0 = 0

就以上面的例子 94000130 000001BB 来详细说明,
4000130 即是位址 0x04000130 ,也就是键盘I/O影射区的位址,
0x01BB 是 Select + L + Up 的按键值。
NOT(0000) = FFFF  
(不要误认为应该是 1111 ,因为 0x0000 是 16 bit,二进位是 0000000000000000,
反转成为 1111111111111111,转换为十进位是 65535,转换为十六进位就是 FFFF。)
FFFF 的二进位表示式是 1111111111111111
01BB 的二进位表示式是 0000000110111011
FFFF01BB 进行 AND 运算,如下:
1111111111111111 (0xFFFF)
0000000110111011 (0x01BB)
-------------------------    
0000000110111011 (0x01BB)

如果执行指令 94000130 000001BB 时,使用者是按了 Select + L + Up 键的话,
代入数值 01BB == (not(0000) & 01BB)
就合乎了 YYYY == (not(ZZZZ) & [XXXXXXXX]) 的比较条件,所以能执行下面其他的指令。

好像挺复杂般,其实不然,大家只要把 9XXXXXXX ZZZZYYYY 理解成这样:
( 在 ZZZZ0000 的情况下 )
假如 2 byte 数据 YYYY == (等于) 位址 0XXXXXXX 上的 2 byte 数据,
就执行其下的指令。
这样去理解是否立即简单了许多呢?

本例子中的 D0000000 00000000 用作条件判断式指令下的结束,
作用是载入先前的执行状态 (如果不存在,就保持在上面指令执行时的状态),
很多朋友都曾见过这类金手指,都是以这个或是 D2000000 00000000 作结束的,
由于作出比较时,得到的结果会影响状态位,所以当一个比较条件下其他的指令中,
又包含条件判断指令,这时候状态位对指令的执行权会作出影响,
所以就要决定因应状态位的应用,而决定使用不同的结束指令。
D2000000 00000000 它的其中一个作用是结束时清空状态位、偏移值及 C 码设定。
C 码配合的话 Dx 的值作为设置,挺复杂的说,由于不常用,故对于 C 码及 Dx 的配合,
就不予以解说了。

好像又越说越乱了,大家除非像编程般的运用他们,才要彻底的理解他们的分别及作用,
否则一般使用上,习惯以 D2000000 00000000 作为条件判断式指令下的结束就可以了。


*** 下面的指令不再以上面那种麻烦的方式作详述,只以最简单、最易理解的方式去说明***


3XXXXXXX YYYYYYYY ( 大 于 )
假如 4 byte 数据 YYYYYYYY > (大于) 位址 0XXXXXXX 上的 4 byte 数据

4XXXXXXX YYYYYYYY ( 小 于 )
假如 4 byte 数据 YYYYYYYY < (小于) 位址 0XXXXXXX 上的 4 byte 数据

5XXXXXXX YYYYYYYY ( 等 于 )
假如 4 byte 数据 YYYYYYYY == (等于) 位址 0XXXXXXX 上的 4 byte 数据

6XXXXXXX YYYYYYYY ( 不 等 于 )
假如 4 byte 数据 YYYYYYYY != (不等于) 位址 0XXXXXXX 上的 4 byte 数据

7XXXXXXX ZZZZYYYY ( 大 于 )
( 在 ZZZZ0000 的情况下 )
假如 2 byte 数据 YYYY > (大于) 位址 0XXXXXXX 上的 2 byte 数据

8XXXXXXX ZZZZYYYY ( 小 于 )
( 在 ZZZZ0000 的情况下 )
假如 2 byte 数据 YYYY < (小于) 位址 0XXXXXXX 上的 2 byte 数据

AXXXXXXX ZZZZYYYY ( 不 等 于 )
( 在 ZZZZ0000 的情况下 )
假如 2 byte 数据 YYYY != (不等于) 位址 0XXXXXXX 上的 2 byte 数据

BXXXXXXX 00000000 ( 读取记忆体数据设为偏移值 )
把位址 0x0XXXXXXX 上的 4 byte 数据,读取成为偏移值

这个是很实用的一个指令,希望大家能了解及活用它。

使用场合:
1.如果在游戏中要锁定很多变量值(例如道具、收集品)时,用这个很方便的。
2.如果同一变量的位置不固定时,先找出变化位址的存放点,用 B 码读取成为偏移值,
(其实个人认为这个称为变量基址才更贴切,以这个变量基址 + 偏移值访问不同的变量)
就不怕下次再玩时,作弊码失效的了。

使用例子:
(以 Mario Kart DS 的作弊功能 "按 X 获得道具 <雷暴>" 来说明)
Press X for Thunderbolt
923d629a 00000400  读取 (被游戏程序处理过的)按键值来作判断
6217bc2c 00000000  假如位址 0x0217BC2C 上的值不等于 0x00000000  
b217bc2c 00000000  在位址 0x0217BC2C 读取 4 byte 数据作为偏移值 (变量基址)
2000004c 00000008  到变量基址 + 0x4C 偏移值的位址,写入 1 byte 数据 0x08
20000054 00000001  到变量基址 + 0x54 偏移值的位址,写入 1 byte 数据 0x01
d2000000 00000000  结束

补充:
1.在本例子的游戏中查看位址 0x023d629a 的值,当按下不同的键,这个值就会改变的。
2.使用 B 码后,如未遇到结束指令,其后的 "直接写入记忆体指令" ,
都会一直以变量基址 + 偏移来定址及写入的。 

EXXXXXXX YYYYYYYY
从现时的指令位置 + 8 的位址,读取 YYYYYYYY byte 数据到 0x0XXXXXXX + 偏移值的位址上。

FXXXXXXX YYYYYYYY
从偏移值的位址,读取 YYYYYYYY byte 数据复制到位址 0x0XXXXXXX
使用 F 码前,需要先使用 D3DCB 码以取得偏移值。
D3000000 ZZZZZZZZ  设 4 byte 数据 ZZZZZZZZ 为偏移值。
DC000000 ZZZZZZZZ  偏移值 = 偏移值 + ZZZZZZZZ (offset = offset + ZZZZZZZZ)

活用上面的条件判断式指令,一般的应用上来说,是够用有余的了,就说到这里好了。




p.s. 本来跟部份朋友说了将在本篇中讲述修改 Rom 的,不过写完上面这些巳实在太累了,只能留待下一篇才继续了,抱歉!

阅读推荐——RFC2285 - Benchmarking Terminology for LAN Switching Devices

RFC2285 - Benchmarking Terminology for LAN Switching Devices

了解一下LAN设备测试中的术语。

Aug 22, 2010

[转]【新手入门】不求人!DIY 自己找寻 NDS 游戏金手指密码_1 (基本修改)

原帖地址:http://www.ndsbbs.com/read.php?tid=119029

【新手入门】不求人!DIY 自己找寻 NDS 游戏金手指密码_1 (基本修改)

很多人都喜欢使用金手指密码,无论是为了令游戏难度降低也好,或是希望在某些游戏中的收集品全部齐全也好,或是希望能出现一些游戏中原本不会出现的特殊情况也好(例如 MoonJump),总之就是想透过金手指来获得一些乐趣,虽则有朋友认为玩游戏应该用实力,不该借助作弊码的帮助,有些更说使用金手指会令游戏性降低,怎样也好,对于应否使用金手指,并不是本文的主旨,总之喜欢的就使用,不喜欢的不使用就可以,随各位喜好。

好了!言归正传,开始运用工具来找寻金手指密码 (作弊码)。

使用工具:
1)NDS 模拟器 (例如 DeSmuME / iDeaS / No$gba)
2)HasteDS   (一个用作搜寻作弊码的工具)

模拟器方面由于 DeSmuME 0.6.0 及 No$gba 2.4a 现时对游戏的支援度较高,建议使用此两种模拟器来找寻。HasteDS 原本是一个日文介面的程序,本人已把其繁体中文化,各位可以于本帖提供的连结下载。

【 找 寻 步 骤 】
1.先执行模拟器,并载入游戏,然后才执行 HasteDS。(由于 HasteDS 与模拟器的连系原理是搜寻记忆体中的字串/数据,如果未有载入游戏,视乎使用的模拟器,有可能连系不到,或连系后的记忆体位址是错误的。)

2.HasteDS 的搜寻模式,可分为‘输入值’及‘与旧值作比较’,‘输入参数值’是在游戏中,直接看到的数字,‘与旧值作比较’通常用于能源棒或其他不是数字显示的变量。本例子中,在游戏画面见到时间是 1800,在 HasteDS 中参考过“输入参数格式”后,输入 M1800,就会在下面的列表出现很多合乎搜寻条件之位址,但实在太多,不知哪个才是,回到游戏中待时间被减去一些后,依照看到的数字再次输入搜寻,合乎条件的记录便会减少,几次之后,通常就会只剩下 1 笔或几笔记录,就可以进行作弊码测试。

3.在列表中对作弊码按滑鼠一下,HasteDS 的记忆体检视区会立即跳到该位址行,我们可以对其修改,使用 [ 修改写入记忆体 ] 功能写入位址值及资料值就可以进行修改,然后回到游戏中,看看数字是否成为自己修改的那样;另一个测试方法是把列表中的作弊码,用滑鼠双按,就会自动把作弊码添加到左面的【 检 查 作 弊 码 】区,然后把“自动锁定作弊码”功能选取,回到游戏看看是否数字被锁定不再减少。

4.好了!作弊码找到了,相信很多朋友都希望能在 DS 主机上使用而不是只用于模拟器,那就要进行下面的格式转换,由于现在找到的是 Raw Code,对于 Raw Code 的意义,网上有很多说明,大家只要明白 Raw Code 就是最原始状态的码就成了,既然是最原始,就是未有加密,未有加入不同金手指功能所支援的判断码,因此 Raw Code 只要稍加转换,就能用于所有支援金手指功能的(甚至不支援金手指的)烧录卡上,由于 R4 烧录卡现已支援,现在就简单一点以 R4 作为范例说明。 (转为 R4 支援的 Action Replay DS 格式金手指密码)刚才找到的金手指密码位址是 0x0211BCEE ,0x 是十六进位的意思,如果数值中含有英文字,当然一看就明白,如果全是数字,又没特别注明的话,会很容易混淆的,所以最好用 0x 注明,刚才锁定的数字是 0x0302 ,在记忆体检视区看到的不是 02 03 么?为何会交换了位置?由于变量值的存放是由最低位开始、最高位在最后面的,由此例如 0x01020304 存放在档案、或在记忆体时,位置就会是 04 03 02 01,大家可以用 Windows 自带的【小算盘】,以 16 进位的模式下,输入 0302,然后切换为 10 进位的话,就会见到该数值是 770 的了。由于之前在测试中用了不少时间,所以现在被锁定的的数字并不是全满的,为了美观一点,我们就把数值定为第一次搜寻时,时间全满的值 1800 (0x0708)。
Action Replay DS 金手指密码可分为“条件判断式指令”及“直接写入记忆体指令”,此例子中只需使用简单的“直接写入记忆体指令”就可以,指令格式是:

0XXXXXXX YYYYYYYY  把 4 byte 数据 YYYYYYYY 写入到位址 XXXXXXX 上。
1XXXXXXX 0000YYYY  把 2 byte 数据 YYYY   写入到位址 XXXXXXX 上。
2XXXXXXX 000000YY  把 1 byte 数据 YY    写入到位址 XXXXXXX 上。

为了不会错误地把不想修改的数据也修改覆盖掉,请注意使用适当的使用 0 1 2 作头码,
参照以上格式,刚才找到的作弊码就可以写成 1211BCEE 00000708,用 R4 官网提供的 Cheat Code Editor 加入此密码到金手指数据库 usrcheat.dat 内,然后复制到烧录卡上就可以在游戏中使用此金手指密码。

【 备 注 】
1.有关 HasteDS 的使用,本文只举出一个简单的例子,其他的功能例如‘跳到指定位址’、‘汇出记忆体数据’,和‘与旧值作比较’之搜寻方式,或界面上的其他未提及的设定,这些看界面就已经知道是用来做什么的了,在此就不多说明了,如有需要大家可自行尝试。

2.如想更详细的了解 HasteDS 有关输入参数格式的标准与限制,可参看下载的档案中,内里的 HasteDS_manual.htm。

3.HasteDS 可支援找寻的模拟器,就如 HasteDS 界面上看到的,但实际支援的版本没有注明,本人只试过 DeSmuME 0.6.0 及 No$gba 2.4a 免费版,这些暂时来说的已是最新版本了。

4.本文作为一个入门级的找寻金手指范例,只适合新手看的,对于动态分配记忆体给变量的游戏,即是找到的密码下次再玩就巳经失效,或想依照找到的密码,对游戏 Rom 作静态修改,把运算该变量的指令修改,以求达到与锁定记忆体位址方式有相同效果的做法并未提及,
有兴趣者请自行研究。


下载 HasteDS v1.12 (繁体中文版)
http://www.veevee.net/koch/hack/hasteDS.rar

口袋妖怪 银灵

首先,我不是口袋饭。玩儿这个只是为了打发时间。但是……这剧情……和没有差不了多少了。

Aug 15, 2010

口袋妖怪 空之援助队

……
这就是我要说的。

本身对这类游戏不是很感兴趣。抱着试试的心态玩儿了这游戏,结果,觉得很无聊。

Aug 8, 2010

心灵传说

说实话,比那个什么风雨传说好多了。不过,情节依然没什么意思。不知道是不是因为提供了地图的原因,场景做的很大,但是东西却不多。感觉像是在跑地图玩儿。

我觉得RPG做重要的还是剧情。剧情差,其他再好也没意思。

Aug 6, 2010

勇者斗恶龙怪物篇 Joker2

说来DQ也是日本国民RPG,其外传性质的怪物篇应该感觉不差。

我没有玩过第一作,看到电玩巴士那么高的评价,下载一个Joker2想体验一下。

结果很失望啊,基本就是小学生水平的剧情,感觉和PSP的怪物猎人差不多,不过就是武器合成系统变成了怪物交配系统。确实很无聊啊。不明白啊,这种游戏也能火?

那中文版的翻译……基本看得很不爽。

总的来说,不是fans就不推荐大家玩这个了。

Twitter Delicious Facebook Digg Stumbleupon Favorites More

 
Powered by Blogger