[FE8] Gaiden Style Promotion Gains ASM Hack

Paste the following at 0x2BD50 in a hex editor of your choice:

F0 B5 04 1C 08 1C ED F7 75 FB 06 1C 0B 23 F1 5C 12 22 A3 5C 8B 42 01 D2 C9 1A 5B 18 13 21 71 5C 8B 42 00 DD 0B 1C A3 54 00 27 0C 23 DB 19 F1 5C 14 22 D2 19 A3 56 8B 42 01 D2 C9 1A 5B 18 14 21 C9 19 71 5C 8B 42 00 DD 0B 1C A3 54 01 37 04 2F EB DD 00 27 28 21 2C 22 C9 19 D2 19 63 5C B2 5C 93 42 00 DA 62 54 01 37 07 2F F3 DD 66 60 A8 6A 08 21 09 04 01 40 00 29 0E D1 01 21 09 02 08 40 B2 6A 11 40 00 28 FE D1 00 29 0A D0 20 7A 14 28 02 DD 14 38 20 72 04 E0 00 21 01 20 20 72 61 72 FF E7 F0 BC 01 BC 00 47

This was based on @Crazycolorz5’s ASM hack that made promotion gains draw from class bases. This hack compares the character’s current stat to the base stat of the class they’re promoting to. If it’s lower, it is raised to match the stat, and is otherwise left alone.

I’m still very new to ASM hacking in general so if you find any bugs (which is very likely), please let me know and I’ll see what I can do.

EDIT: It didn’t work for some reason so I undid some of the deleted code I thought was harmless. Should work now.

EDIT #2: I figured out what went wrong. It works and is also smaller now.

7 Likes

I was planning to do this one, but I thank you for making this one nonetheless!

I better try this out.

Source would be nice as well if you don’t mind

Here’s the source. It’s essentially just the original with a few lines edited and some omitted. I literally learned how to ASM about 5 hours ago so I just left alone what I didn’t understand (I probably could’ve removed some unnecessary code but hey, at least it works for now).

EDIT: Changed to reflect the dump changes.

EDIT #2: Again, changed to reflect the dump. Last time, I swear. Parenthesis are my personal comments.

.thumb
.org 0x19190
getMaxHP:

.org 0x19444
getClass:

//r0 = RAM data
//r1 = class to change to
.org 0x2BD50
push {r4-r7, lr}
mov r4,r0 //r4 = RAM data
mov r0, r1
bl getClass //get a pointer to class to change to.
mov r6, r0 //r6 = new class

//Do max HP separately.
mov r3, #0xB //base HP
ldrb r1, [r6, r3] //class base HP

mov r2, #0x12 //RAM Max HP
ldrb r3, [r4, r2] //Current max HP
cmp r3, r1 //compares current max HP to class base HP
bhs DontAddHp
sub r1, r3 //r1 = what to add
add r3, r1 //adds
DontAddHp:

//Check if exceeds cap [It breaks once I remove this. I dunno why.]
mov r1, #0x13
ldrb r1, [r6, r1]
cmp r3, r1
ble belowMaxHP
mov r3, r1
belowMaxHP:
strb r3, [r4, r2]

//Now loop through the other stats.
mov r7, #0x0

statChangeLoop:
//First calc deltaStat
mov r3, #0xC
add r3, r7
ldrb r1, [r6, r3] //class base

//Now get the current stat from RAM.
mov r2, #0x14 //strength offset
add r2, r7
ldsb r3, [r4, r2] //current stat
cmp r3, r1 //compares current stat to class base
bhs DontAddStat
sub r1, r3 //r1 = amount to add
add r3, r1 //adds
DontAddStat:

//Now check it against the cap [Breaks here too. There’s something essential in here but idk what.]
mov r1, #0x14
add r1, r7
ldrb r1, [r6, r1]
cmp r3, r1
ble dontOverwrite
mov r3, r1
dontOverwrite:
strb r3, [r4, r2]

//loop
add r7, #0x1
cmp r7, #0x4
ble statChangeLoop

mov r7, #0x0
weaponLevelLoop:
mov r1, #0x28 //Sword level in ram
mov r2, #0x2C //Sword level in class ROM
add r1, r7
add r2, r7
ldrb r3, [r4, r1] //Current wlvl
ldrb r2, [r6, r2] //New base
cmp r3, r2
bge continue
strb r2, [r4, r1] //Base was higher, so store that.
continue:
add r7, #0x1 //Otherwise don’t change it.
cmp r7, #0x7
ble weaponLevelLoop

//store the new class pointer to unit
str r6, [r4, #0x4]

//Now if it’s an unpromoted class changing to a promoted class,
//Or if the old class has the lv10 cap skill,
//Reset level and EXP.
ldr r0, [r5, #0x28] //Old class skills
mov r1, #0x08 //Max level 10
lsl r1, #0x10
and r1, r0
cmp r1, #0x0
bne resetLevel
mov r1, #0x01 //Promoted
lsl r1, #0x08
and r0, r1 //Promoted status of old class
ldr r2, [r6, #0x28] //New class skills
and r1, r2 //Promoted status of new class
cmp r0, #0x0
bne depromoteCheck //If old class was promoted…
cmp r1, #0x0
beq end //Going from unpromoted to unpromoted

ldrb r0, [r4, #0x8] //Level
cmp r0, #0x14
ble resetLevel
sub r0, #0x14
strb r0, [r4, #0x8]
b end

resetLevel:

mov r1,#0x0 //New EXP
mov r0,#0x1 //New Level
strb r0,[r4,#0x8]
strb r1,[r4,#0x9]
b end

//return
end:
pop {r4-r7}
pop {r0}
bx r0

.org 0x02BEA0

5 Likes

Oh hey, nice to see ASM from new people. Nice work!