View Single Post
Old April 29th, 2012 (8:52 PM). Edited April 29th, 2012 by Chaos Rush.
Chaos Rush's Avatar
Chaos Rush Chaos Rush is offline
im sexy and i know it
Join Date: May 2007
Location: Taylor Swift
Gender: Male
Nature: Adamant
Posts: 1,296

Okay, this is my first ASM-related thing. Basically, I have figured out how to alter a Pokemon's index number, while not letting it turn into a bad egg.

First of all, in a Ruby rom, place this routine somewhere. We'll call this "JPAN Routine 1":

.align 2
.global newroutine

main: PUSH {R0-R7,LR} LDR R5, var_8004 LDRH R5, [R5, #0x0] LDR R4, party_addr MOV R6, #0x64 LDR R7, New_poke_addr MUL R5, R6 ADD R4, R4, R5 B decrypt .hword 0x0000 var_8004: .word 0x0202E8CC party_addr: .word 0x03004360 New_poke_addr: .word 0x0203F400

decrypt: LDR R0, [R4, #0x0] PUSH {R0} LDR R1, [R4,#0x4] EOR R1, R0 STR R1, [R7, #0x0] LDRH R1, [R4, #0x1C] STRH R1, [R7, #0x6] MOV R2, #0x20 ADD R0, R2, R4 MOV R2, #0x18 ADD R1, R2, R7 MOV R2, #0xC LDR R5, [R7, #0x0]

decrypt_loop: LDR R3, [R0, #0x0] EOR R3, R5 STR R3, [R1, #0x0] ADD R1, #0x4 ADD R0, #0x4 SUB R2, #0x1 CMP R2, #0x0 BNE decrypt_loop POP {R0} MOV R1, #0x18 MOV R2, #0xC0 LSL R2, R2, #0x18 CMP R2, R0 BHI lower_than_c SUB R0, R0, R2

lower_than_c: LSR R2, R2, #0x1 CMP R2, R0 BCS lower_than_6 SUB R0, R0, R2 LSL R0, R0, #0x0

lower_than_6: SWI #0x6 ADD R0, R1, #0x0 MOV R1, #6 SWI #0x6

g_in_first: CMP R0, #0x0 BNE g_in_second MOV R2, #0x18 B g_final

g_in_second: CMP r1, #0x1 BGT g_in_third MOV R2, #0x24 B g_final

g_in_third: MOV R2, #1 AND R2, R1 CMP R2, #1 BEQ g_in_fourth MOV R2, #0x30 B g_final

g_in_fourth: MOV R2, #0x3C

g_final: ADD R2, R7, R2 STR R2, [R7, #0x8]

m_in_first: CMP R0, #0x3 BNE m_in_second MOV R2, #0x18 B m_final

m_in_second: CMP R1, #0x4 BLT m_in_third MOV R2, #0x24 B m_final

m_in_third: MOV R2, #0x1 AND R2, R1 CMP R2, #0x1 BNE m_in_fourth MOV R2, #0x30 B m_final

m_in_fourth: MOV R2, #0x3C

m_final: ADD R2, R7, R2 STR R2, [R7,#0x14] a_first: CMP R0, #0x1 BGT a_second CMP R0, #0x0 BEQ a_lesser_second MOV R2, #0x18 B a_final

a_second: MOV R3, #0x2 BEQ a_greater_second CMP R1, #0x3 BEQ a_greater_second CMP R1, #0x0 BEQ a_greater_third CMP R1, #0x5 BEQ a_greater_third MOV R2, #0x3C B a_final

a_greater_second: MOV R2, #0x24 B a_final

a_greater_third: MOV R2, #0x30 B a_final

a_lesser_second: CMP R1, #0x1 BGT a_lesser_third MOV R2, #0x24 B a_final

a_lesser_third: MOV R2, #0x1 AND R2, R1 CMP R2, #0x2 BNE a_lesser_fourth MOV R2, #0x30 B a_final

a_lesser_fourth: MOV R2, #0x3C

a_final: ADD R2, R7, R2 STR R2, [R7,#0xC]

e_first: CMP R0, #0x2 BLT e_second CMP R0, #0x2 BGT e_greater_second MOV R2, #0x18 B e_final

e_second: CMP R1, #0x2 BEQ e_lesser_second CMP R1, #0x3 BEQ e_lesser_second CMP R1, #0x0 BEQ e_lesser_third CMP R1, #0x5 BEQ e_lesser_third MOV R2, #0x3C B e_final

e_lesser_second: MOV R2, #0x24 B e_final

e_lesser_third: MOV R2, #0x30 B e_final

e_greater_second: CMP R1, #0x5 BLT e_greater_third MOV R2, #0x24 B e_final

e_greater_third: MOV R2, #1 AND R2, R1 CMP R2, #0 BEQ e_greater_fourth MOV R2, #0x30 B e_final

e_greater_fourth: MOV R2, #0x3C

e_final: ADD R2, R7, R2 STR R2, [R7,#0x10] POP {R0-R7,PC}

It is a modified version of JPAN's decryption routine, which I changed so that it works with Ruby.

Next, put this next code somewhere in the rom. It is also by JPAN, so we'll call it, "JPAN Routine 2":


.align 2
.global nextroutine

main: push {r0-r7, lr} ldr r5, var_8004 ldrh r5, [r5, #0x0] ldr r4, Party_addr mov r6, #0x64 ldr r7, new_store_addr mul r5, r6 add r4, r4, r5 b calc_checksum .hword 0x0000 var_8004: .word 0x0202E8CC Party_addr: .word 0x03004360 new_store_addr: .word 0x0203f400

calc_checksum: mov r2, #0x1c add r0, r4, r2 mov r2, #0x18 add r1, r7, r2 mov r5, #0x0

checksum_add: ldrh r3, [r1, #0x0] add r5, r3, r5 add r1, #0x2 sub r2, #0x1 cmp r2, #0x0 bhi checksum_add lsl r5, r5, #0x10 lsr r5, r5, #0x10 strh r5, [r0, #0x0] sub r1, #0x30 add r0, #0x4 mov r2, #0xc ldr r5, [r7, #0x0]

store_loop: ldr r3, [r1, #0x0] eor r3, r5 str r3, [r0, #0x0] add r0, #0x4 add r1, #0x4 sub r2, #0x1 cmp r2, #0x0 bhi store_loop pop {r0-r7, pc}

Both of the routines above were written by JPAN, I just modified it so that it works on Pokemon Ruby.

However, here is a custom routine made by me (and might I say, my first ASM routine ever). Insert this into free space:

.align 2
.global newroutine

main: push {r0-r3, lr} ldr r0, .POOP ldr r0, [r0] ldr r1, .var_8005 ldrh r3, [r1] mov r1, r3 str r1, [r0] strh r1, [r0] pop {r0-r3,pc}

.align 2 .POOP: .word 0x0203f408 .var_8005: .word 0x0202E8CE

What this routine does is, is changes the first Pokemon of your party to whatever value you stored in 0x8005. It only works however, if you called JPAN's first routine before it, and if you call JPAN's second routine after my routine.

Now that you've inserted JPAN's routines and my own routine, here is how you apply them: In any script (like a signpost), place this:

callasm 0x(offset of JPAN Routine 1, +1)
setvar 0x8005 0x(index number of the Pokemon that it will change into)
callasm 0x(offset of my routine, +1)
callasm 0x(offset of JPAN Routine 2, +1)

Now you can easily alter the first Pokemon of your party to anything you want. For example, this is what my signpost looks like:

#org 0x14D808
callasm 0x8C00001
setvar 0x8005 0x9
callasm 0x8C001C1
callasm 0x8C00141
msgbox 0x816AE50 MSG_SIGN '"I just changed the first Pokémon\n..."

'--------- ' Strings '--------- #org 0x16AE50 = I just changed the first Pokémon\nof your party into a Blastoise.\lDeal with it.

This will change the first Pokemon of my party into Blastoise (0x9 is Blastoise's hex number). Let's try it out.

The reason why this might be useful is that I can now do form changes in my 649 Project, and I can "fake" more than 5 evolutions by having certain Pokemon switch into a different index number (but identical stat-wise), such as a second Eevee that can evolve into Leafeon or Glaceon. Hopefully this is useful to some other people as well.


My projects:
Untitled Pokémon fangame (pictured above) | Final Fantasy II NES retranslation | Mother 1/EarthBound Beginnings Color Restoration for GBA
Non-Pokémon hacks I support:
Sonic Classic Heroes
Sonic 3 Complete
Reply With Quote