Go Back   The PokéCommunity Forums > ROM Hacking > Research & Development
Reload this Page Research Reverse Engineering Pokemon White 2 Game Code

Notices
For all updates, view the main page.

Research & Development Got a well-founded knack with ROM hacking? Love reverse-engineering the Pokémon games? Or perhaps you love your assembly language. This is the spot for polling and gathering your ideas, and then implementing them! Share your hypothesis, get ideas from others, and collaborate to create!
Research & Development programs in this forum are subject to moderator approval before they are displayed.



Reply
 
Thread Tools
  #1    
Old October 28th, 2014 (12:30 PM). Edited October 31st, 2014 by pichu2000.
pichu2000 pichu2000 is offline
 
Join Date: Nov 2005
Gender:
Posts: 153
POKEMON WHITE 2 REVERSE ENGINEERING






Hi, I'm back!
After a lot of silent backstage work I decided to share with you my research about Pokemon White 2 Game original code.
I decided to analyze White 2 because it's more structured than DPP, HGSS and also because Bond of projectpokemon gives a good database to start. I use IDA pro SDK 6.1 + a little plugin developed by Ludde and edited by me to generate pseudocode from ARM Thumb instructions (It's not perfect but It's very useful)
But now no more chatting!

Basic Idea

Like other NDS Rom games, W2 uses arm9.bin file to execute main game code and overlays files to load additional functions/structures. There is in particular a table that give us the loading addresses for each overlay (We have overlapping addresses, so we can't use a unique binary file to analyze all the overlays)
I try to divide the assembly file in "logical" blocks, and each block have a general structure and a series of functions.
Note: It may be contains mistakes!
Now, the arm9.bin file can be divided in these different "structure-functions" block (We uses as base address: 0x2000000, that is the main RAM address)

Quote:
Legend:
o.h = Original C file Header
s.f = Save File

  • 0x2000400 - 0x20057F0 Nintendo DS Generic OS Functions
  • 0x20057F0 - 0x2006D64 Sound Generic Functions
  • 0x2006D64 - 0x2006EE8 Microphone Sound Handler (o.h. snd_mic.c)
  • 0x2006EE8 - 0x2006FC8 Background Music Information Handler (o.h. bgm_info.c)
  • 0x2006FC8 - 0x20070F0 Sound Stream Handler (o.h. snd_strm.c)
  • 0x20070F0 - 0x2007710 Save Control Handler(o.h. save_control.c)
  • 0x2007710 - 0x2007D4C Single Box Handler (s.f Block 0)
  • 0x2007D4C - 0x2007E0C All Box Handler (o.h. box_savedata.c, s.f Block 0 - 23)
  • 0x2007E0C - 0x2007FD0 Perap Cry Handler(o.h. perapvoice.c, s.f Block 36)
  • 0x2007FD0 - 0x200898C Item Save Data (o.h. myitem_savedata.c, s.f Block 24)
  • 0x200898C - 0x2008B08 Configuration? Handler (o.h. config.c)
  • 0x2008B08 - 0x2008C1C Player Status Handler(o.h. mystatus.c)
  • 0x2008C1C - 0x2008DA0 Play Time Handler(o.h. playtime.c)
  • 0x2008DA0 - 0x2008EF4 Game Status?(s.f Block 27)
  • 0x2008EF4 - 0x2009184 Trainer Location Status Handler(s.f Block 28)
  • 0x2009184 - 0x20092C8 Timer Handler(s.f Block 33)
  • 0x20092C8 - 0x20093D0 Real Time Clock Handler(s.f Block 37)
  • 0x20093D0 - 0x200965C Trainer Card Signature Handler(s.f Block 38)
  • 0x200965C - 0x2009854 Mail Handler(o.h. mail.c, s.f Block 40)
  • 0x2009854 - 0x2009930 CGear Handler(s.f Block 32)
  • 0x2009930 - 0x2009B50 Unknown Handler(s.f Block 35)
  • 0x2009B50 - 0x2009E58 Unity Tower Handler(s.f Block 29)
  • 0x2009E58 - 0x200A4B8 Wifi List?(s.f Block 30)
  • 0x200A4B8 - 0x200A5F0 Unknown Handler(s.f Block 31)
  • 0x200A5F0 - 0x200AC58 Mistery Gift Handler(s.f Block 34)
  • 0x200AC58 - 0x200AF74 Musical Information Handler(s.f Block 42)
  • 0x200AF74 - 0x200AFBC Unknown Handler(s.f Block 43)
  • 0x200AFBC - 0x200B488 Unknown Handler(s.f Block 44)
  • 0x200B488 - 0x200B4FC Unknown Handler(s.f Block 46)
  • 0x200B924 - 0x200BA84 Tournament Handler(s.f Block 47)
  • 0x200BA84 - 0x200BB00 Unknown Handler(s.f Block 48)
  • 0x200BB00 - 0x200C210 Battle Record Handler (o.h. battle_rec.c)
  • 0x200C210 - 0x200C3A8 Battle Box Handler(s.f Block 49)
  • 0x200C3A8 - 0x200C598 Day Care Handler(s.f Block 50)
  • 0x200C598 - 0x200C7A0 High Link Handler(s.f Block 53)
  • 0x200C7A0 - 0x200CCA0 Trainer Card Handler(s.f Block 52)
  • 0x200CCA0 - 0x200CE50 Musical Distro Handler (o.h. musical_dist_save.c)
  • 0x200CE8C - 0x200DCEC Pokedex Handler (s.f Block 54)
  • 0x200DCEC - 0x200DE34 Overworld Handler(s.f Block 55)
  • 0x200DE34 - 0x200E0F0 Gds Profile Handler (o.h. gds_profile.c)
  • 0x200E0F0 - 0x200E2FC Unknown Handler(s.f Block 56)
  • 0x200E2FC - 0x200E5A8 Unknown Handler(s.f Block 57)
  • 0x200E5A8 - 0x200E7F0 Unknown Handler(s.f Block 58)
  • 0x200E7F0 - 0x200E8BC Battle Subway (o.h. bsubway_savedata.c)
  • 0x200E8BC - 0x200EC00 Symbol Save Handler(o.h. symbol_save.c, s.f Block 60)
  • 0x200EC00 - 0x200EE20 Unknown Handler(s.f Block 61)
  • 0x200EE20 - 0x200EF48 Battle Examination Handler(o.h. battle_examination.c)
  • 0x200EF48 - 0x200EFC4 Unknown Handler
  • 0x200EFC4 - 0x200F128 Pokemon Trade Handler(s.f Block 65)
  • 0x200F128 - 0x200F164 Unknown Handler
  • 0x200F164 - 0x200F29C Unknown Handler(s.f Block 63)
  • 0x200F29C - 0x200F3B8 Record Handler(s.f Block 61)
  • 0x200F3B8 - 0x200F6E4 Unknown Handler(s.f Block 64)
  • 0x200F6E4 - 0x200F8F4 Hollow Handler(s.f Block 66)
  • 0x200F8F4 - 0x200FB54 Medals Handler(s.f Block 68)
  • 0x200FB54 - 0x200FE80 Unknown Handler(s.f Block 41)
  • 0x200FE80 - 0x200FF40 Unknown Handler
  • 0x200FF40 - 0x200FFFC Unknown Handler
  • 0x200FFFC - 0x2010230 Join Avenue Handler(s.f Block 67)
  • 0x2010230 - 0x20105C8 Key Data Handler(s.f Block 69)
  • 0x20105C8 - 0x20108CC Pokewood Handler (o.h. pokewood_rec.c)
  • 0x20108CC - 0x2010CA0 Save Control Handler
  • 0x2010CA0 - 0x2010DC0 Medals Handler
  • 0x2010DC0 - 0x2010FF4 Unknown Handler(s.f Block 70)
  • 0x2010FF4 - 0x20112FC Unknown Handler(s.f Block 71)
  • 0x20112FC - 0x20114A4 Unknown Handler(s.f Block 72)
  • 0x20114A4 - 0x20116C0 Cygnus Save Control Handler(o.h. cygnus_save_control.c)
  • 0x20116C0 - 0x2012908 Net Error Handler(o.h. net_err.c)
  • 0x2012908 - 0x2012EE0 Wifi Dwc Handler(o.h. wih_dwc.c)
  • 0x2012EE0 - 0x20130B4 Net Save Handler(o.h. net_save.c)
  • 0x20130B4 - 0x2014498 Game Beacon Accessor Handler (o.h. game_beacon_accessor.c)
  • 0x2014498 - 0x2014D1C Link Festival Handler (o.h. link_festival.c)
  • 0x2014D1C - 0x201587C Festival Mission Handler (o.h. fest_mission.c)
  • 0x201587C - 0x2015A88 Script Virtual Machine Handler (o.h. vm.c)
  • 0x2015A88 - 0x2015AE0 Season Info Handler
  • 0x2015AE0 - 0x2016440 NSBCA Animation Handler (o.h. ica_anime.c)
  • 0x2016440 - 0x2016510 NSBTX to CLWK Converter Handler (o.h. nsbtx_to_clwk.c)
  • 0x20168F0 - 0x2016CB4 Process System Handler (o.h. procsys.c)
  • 0x2016CB4 - 0x2016EE8 Game Event Handler (o.h. game_event.c)
  • 0x2016EE8 - 0x2017C60 Game Data Handler (o.h. game_data.c)
  • 0x2017C60 - 0x20186E0 Battle Setup Handler (o.h. btl_setup.c)
  • 0x20186E0 - 0x2018FE8 Zone Data Handler (o.h. zonedata.c)
  • 0x20191C0 - 0x201931C Event Flag Handler (s.f. Block 45)
  • 0x201931C - 0x201937C Field Status Handler (o.h. field_status.c)
  • 0x201937C - 0x2019A14 Game Event Executions Functions
  • 0x2019A14 - 0x201C2D8 Multi Cell Sequence Handler (o.h. mcss.c)
  • 0x201C2D8 - 0x201F0A8 Pokemon Tool Handler (o.h. poketool.c)
  • 0x201F0A8 - 0x201F780 Narc 106 Related Functions First Block
  • 0x201F780 - 0x201F9A8 Pokemon Regulation Handler (o.h. poke_regulation.c)
  • 0x201F9A8 - 0x201FD24 Narc 106 Related Functions Sec Block
  • 0x201FD24 - 0x202125C Pokemon Party Handler(o.h. pokeparty.c, s.f Block 26)
  • 0x202125C - 0x20219A0 Pokemon Moves Handler(o.h. waza_tool.c)
  • 0x20219A0 - 0x2022D84 Print System Handler (o.h. printsys.c)
  • 0x2022D84 - 0x2024200 Graphic Font Handler (o.h. gf_font.c)
  • 0x2024200 - 0x2024CAC Word Set Handler (o.h. wordset.c)
  • 0x2024CAC - 0x2024F18 Bitmap Windows Functions First Block
  • 0x2024F18 - 0x20250AC Bitmap Menu Work Handler (o.h. bmp_menuwork.c)
  • 0x20250AC - 0x202571C Bitmap Menu Handler (o.h. bmp_menu.c)
  • 0x202571C - 0x2026554 Bitmap Menu List Handler (o.h. bmp_menulist.c)
  • 0x2026554 - 0x2026628 Bitmap Cursor Handler (o.h. bmp_cursor.c)
  • 0x2026628 - 0x2026D0C Item Functions
  • 0x2026D0C - 0x2027E30 Palette Animation Handler (o.h. palanm.c)
  • 0x2027E30 - 0x2029994 Wipe Handler (o.h. wipe.c)
  • 0x2029994 - 0x202A0F8 PMSI Parameter Handler (o.h. pmsi_par.c)
  • 0x202A0F8 - 0x202A284 PMS Word Handler (o.h. pms_word.c)
  • 0x202A284 - 0x202A300 Unknown Handler (s.f. Block 39)
  • 0x202A300 - 0x202AC68 Information Windows Handler (o.h. infowin.c)
  • 0x202AC68 - 0x202AE88 Actor Tool Handler (o.h. actor_tool.c)
  • 0x202AE88 - 0x202B488 Bitmap Oam Handler (o.h. bmp_oam.c)
  • 0x202B488 - 0x202B5D0 Region Functions
  • 0x202B5D0 - 0x202B67C Trainer Type Functions
  • 0x202B67C - 0x202BB90 Cursor Move Handler (o.h. cursor_move.c)
  • 0x202BB90 - 0x202BFC0 Game Communication Handler (o.h. game_comm.c)
  • 0x202BFC0 - 0x202D728 Game Beacon Handler (o.h. game_beacon.c)
  • 0x202D728 - 0x202D804 Beacon Status Handler (o.h. beacon_status.c)


Next time we start analyze each single block (we try to analyze)
If you wanna help, you're welcome, but I advice you: it's very hard work!
Reply With Quote
  #2    
Old October 29th, 2014 (06:51 PM). Edited October 29th, 2014 by Bond697.
Bond697 Bond697 is offline
 
Join Date: Oct 2008
Gender:
Posts: 28
the gen 5 games are C, not C++, and there are no classes. also, those addresses are wrong- they're missing a 0 or something.

e:
you're going to want this: http://hack.thundaga.com/hacking_stuff.7z

arm9-white2_decompressed_U.idb is the most useful thing.
Reply With Quote
  #3    
Old October 30th, 2014 (01:36 AM). Edited October 30th, 2014 by pichu2000.
pichu2000 pichu2000 is offline
 
Join Date: Nov 2005
Gender:
Posts: 153
Quote originally posted by Bond697:
the gen 5 games are C, not C++, and there are no classes. also, those addresses are wrong- they're missing a 0 or something.

e:
you're going to want this: http://hack.thundaga.com/hacking_stuff.7z

arm9-white2_decompressed_U.idb is the most useful thing.
Hi Bond, I've already your database (I work hardly on it for 1-2 years, finding a bunch of new functions).
I know that White 2 uses only a series of structures, with functions that operate in these structures. I called it wrongly "classes", it's only a naming convention.
I fixed the addresses, thanks!
Reply With Quote
  #4    
Old October 31st, 2014 (12:56 PM). Edited October 31st, 2014 by pichu2000.
pichu2000 pichu2000 is offline
 
Join Date: Nov 2005
Gender:
Posts: 153
Hi, guys!
As I promise, we start analyze ASM blocks from binary file of White 2 code.
For now we skip the first two "sections" (I wanna start with some "easy" to understand)
As I define previously, from offset 0x2006D64 to 0x2006EE8 we have all the functions linked with original snd_mic.c source file.
In particular we have:

0x2006D64 SNDMIC_AllocBlock
0x2006DE4 SNDMIC_DSI_27047C0
0x2006DEC SNDMIC_FreeBlock
0x2006E0C SNDMIC_SetWord_020
0x2006E3C SNDMIC_CheckWord_020
0x2006E54 _DSIMIC_StartAutoSampling
0x2006E80 _SNDMIC_StartAutoSampling
0x2006EC0 SNDMIC_PerapVoice_Table004_UpdateSpecific
0x2006ED4 SNDMIC_GetWord_024_01F

1) SNDMIC_AllocBlock

Spoiler:
The first function is usually the "constructor" (a particular function that initialize the structure)
The original ASM code of this function is:

Spoiler:


PUSH {R3-R7,LR} ; marker
LDR R7, =aSnd_mic_c ; "snd_mic.c"
MOVS R1, #0x59 ; 'Y'
STR R1, [SP] ; marker
MOVS R1, #0x28 ; '(' ; blockLength
MOVS R2, #0 ; clearBlock
MOVS R3, R7 ; pSourceFile
MOVS R5, R0
MOVS R6, #0
BL MEM_AllocBlock

MOVS R1, #0 ; data
MOVS R2, #0x28 ; '(' ; size
MOVS R4, R0
BLX MEM_CpuAllocBlock8

MOVS R0, #0x5F ; '_'
STR R0, [SP] ; marker
LDR R1, =0x2014 ; blockLength
MOVS R0, R5 ; blkGroupID
MOVS R2, #0 ; clearBlock
MOVS R3, R7 ; pSourceFile
BL MEM_AllocBlock

LDR R2, =0x2014 ; size
MOVS R1, #0 ; data
MOVS R5, R0
BLX MEM_CpuAllocBlock8

STR R5, [R4,#0x24]
MOVS R0, #1 ; status
MOVS R5, #1
BL PM_SetAmp

MOVS R0, #2 ; status
BL PM_SetAmpGainAsync

LDR R1, [R4,#0x20]
MOVS R0, #1
BICS R1, R0
MOVS R0, R1
ORRS R0, R5
STR R0, [R4,#0x20]
BL MIC_Init

BL OS_CheckIsDSI

CMP R0, #1
BNE loc_2006DCE

LDR R1, =aFBfCNg ; "F~¦üF~C~nâ"
MOVS R0, R6
BLX DSI_27047C0

loc_2006DCE
LDR R0, =micBlock
STR R4, [R0]
POP {R3-R7,PC}


Now we analyze step by step the ARM-to-PseudoCode conversion (I move some istructions from the original position to other to make a more clear traslation)

Quote:
PUSH {R3-R7,LR}


This operation pushes the registers used by the function onto the stack. We can skip during conversion, because this operation is "invisible" at pseudocode level

Quote:
MOVS R1, #0x59
STR R1, [SP]

This sequence saves onto the head of the stack the Hex Value 0x59. It's like a "temp" variable declaration, so we can traslate like

(unsigned long)SP = 0x59

Quote:
LDR R7, =aSnd_mic_c
MOVS R1, #0x28 ;
MOVS R2, #0
MOVS R3, R7
MOVS R5, R0
MOVS R6, #0
BL MEM_AllocBlock
This sequence calls the MEM_AllocBlock function, that have this signature:

Quote:
int* MEM_AllocBlock(int blkGroupID, u32 blockLength, bool clearBlock, string *pSourceFile)
So we have:

R4 = MEM_AllocBlock(R0,0x28,0,aSnd_mic_c)

Quote:
MOVS R1, #0
MOVS R2, #0x28
MOVS R4, R0
BLX MEM_CpuAllocBlock8


This sequence calls the Mem_CpuAllocBlock8 function, that have this signature:

Quote:
void MEM_CpuAllocBlock8(void *destination, u8 data, u32 size)
So we have:

MEM_CpuAllocBlock8(R4, 0, 0x28);

Quote:
MOVS R1, #0x5F
STR R1, [SP]
LDR R1, =0x2014
MOVS R0, R5
MOVS R2, #0
MOVS R3, R7
BL MEM_AllocBlock
LDR R2, =0x2014 ; size
MOVS R1, #0 ; data
MOVS R5, R0
BLX MEM_CpuAllocBlock8
STR R5, [R4,#0x24]


This sequence is similar to the previous ones, so we can translate directly:

unsigned long)SP = 0x5F
R5 = MEM_AllocBlock(R0,0x2014,0,aSnd_mic_c)
MEM_CpuAllocBlock8(R5,0,0x2014)
(unsigned long)R4+0x24 = R5;


Quote:
MOVS R0, #1
BL PM_SetAmp
This sequence calles the PM_SetAmp functions, which signature is

Quote:
u32 PM_SetAmp(PMAmpSwitch status)
So we have:

R0 = PM_SetAmp(1)
Quote:
MOVS R0, #2
BL PM_SetAmpGainAsync


This sequence calles the PM_SetAmp functions, which signature is

Quote:
u32 PM_SetAmpGainAsync(PMAmpGain status)
So we have:

R0 = PM_SetAmpGainAsync(2)

Quote:
LDR R1, [R4,#0x20]
MOVS R0, #1
BICS R1, R0
MOVS R0, R1
ORRS R0, R5
STR R0, [R4,#0x20]


This sequence make ALU operation on R4 + 0x20 value
We can traslate:

(unsigned long)R4+0x20 = (unsigned long)R4+0x20 &~ 1 | 1;

Quote:
BL MIC_Init
This sequence call the MIC_Init function, without parameters

Quote:
BL OS_CheckIsDSI
CMP R0, #1
BNE loc_2006DCE

LDR R1, =aFBfCNg
MOVS R0, R6
BLX SNDMIC_DSI_27047C0

loc_2006DCE
LDR R0, =micBlock
STR R4, [R0]
POP {R3-R7,PC}


This sequence perform an If, based on the result of OS_CheckIsDSI function
We can traslate as:

R0 = OS_CheckIsDSI()
if (R0 == 1)
DSI_27047C0(0, &aFBfCNg)
micBlock = R4


The final SNDMIC_AllocBlock code is (with some semplification and reordering):

Quote:
void SNDMIC_AllocBlock(int groupID)
{
temp = 0x59

//Alloc block into memory filled with 00, with size of 0x28 byte
micBlock = MEM_CpuAllocBlock8(MEM_AllocBlock(groupID,0x28,0,aSnd_mic_c), 0, 0x28);

temp = 0x5F
micBlock.field_20 = micBlock.field_20 &~ 1 | 1;

//Alloc block into memory filled with 00, with size of 0x2014 byte and save pointer into field_24 of micBlock structure)
micBlock.field_24 = MEM_CpuAllocBlock8(MEM_AllocBlock(groupID,0x2014,0,aSnd_mic_c),0,0x2014)

//Turn on the NDS Amplificator system?
PM_SetAmp(1)

//Set the gain of the NDS Amplificatore system?
PM_SetAmpGainAsync(2)

MicInit()

//Call a DSI function. I don't know what this part really do.
if (OS_CheckIsDSI == 1)
SNDMIC_DSI_27047C0(0, &aFBfCNg)
}



2) SNDMIC_FreeBlock

Spoiler:
The next function is the "destructor" (a particular function that destroy the structure and free the memory)
The original ASM code of this function is:

Spoiler:

PUSH {R4,LR}
MOVS R0, #0
BL PM_SetAmp
LDR R4, =micBlock
LDR R0, [R4]
LDR R0, [R0,#0x24]
BL MEM_FreeBlock

LDR R0, [R4]
BL MEM_FreeBlock

POP {R4,PC}


I'm not going to repeat the step by step analysis (It's very simple)
I give you directly the pseudocode:

Quote:

void SNDMIC_FreeBlock()
{
//Turn off the NDS Amplificator.
PM_SetAmp(0)

//Free the field_24 block.
MEM_FreeBlock(micBlock.field_24)

//Free the entire block.
MEM_FreeBlock(micBlock)
}



As you can see, most of the code is little obscure yet, so I appreciate any suggestion on what it really do.
I stop here for now, because I wanna know If this approach is useful for you or not.
Stay tuned!
Reply With Quote
Reply
Quick Reply

Sponsored Links

You may also like.. (Beta)
Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are UTC -8. The time now is 03:04 AM.