[FE14] Misc Notes on Fates

The code below has some issues so don’t use for now.

If you just want the prep screen without having to go to castle (i.e. before castle is unlocked), you can set the below in paragon:
image


WIP CODE

Making use of the ‘add ev:: commands’ hack from the above post, here is a new command to allow skip castle while still saving between chapters

https://cdn.discordapp.com/attachments/354835401904619531/995162616395731057/Skipcastlewithsave.mp4

    ev::ChapterSetSkipChapterSaveCastle(1); //original, skip both save and castle
    ev::ChapterSetSkipCastleWithSave(1); //new, save and then skip castle

Default behaviour:
if 0x1000000 set, skip save and castle and go to next chapter (used for e.g. endgame part 1->2)
else if 0x800 set, skip save and go to castle (used for castle defense?)

New behaviour:
if 0x1000000 set, skip castle
if 0x800 set, skip save

magikoopa hooks:

ReplaceevChapterSetSkipChapterSave:
    type: symbol
    addr: 0x426428
    sym: SkipCastleWithSave

ReplaceBeforeSaveRoutine:
    type: branch
    addr: 0x1b66fc
    link: false
    func: CheckSkipCastle

ReplaceAfterSaveRoutine:
    type: symbol
    addr: 0x53a1ac
    sym: PostSaveRoutine

asm (includes the callroutine ev:: code from prev post because it’s all part of the same expansion of event commands):

.align 4
.global AddNewEVCommands
AddNewEVCommands:
@ copying the rest i guess but instead of r4 + whatever we'll just use our own address????
ldr r0, =aCallRoutine
ldr r0, [r0]
tst r0, #1
bne 0x42e44c
ldr r0, =aCallRoutine
blx __cxa_guard_acquire
cmp r0, #0
beq 0x42e44c
ldr r2, =CallRoutine @new event routine.
ldr r0, =0x716e98
mov r3, #1
ldr r1, =aCallRoutineString
bl cmvm__CmCFunction__CmCFunction

ldr r0, =aSkipCastleRoutine
ldr r0, [r0]
tst r0, #1
bne 0x42e44c
ldr r0, =aSkipCastleRoutine
blx __cxa_guard_acquire
cmp r0, #0
beq 0x42e44c
ldr r2, =anonymous_namespace__ChapterSetSkipChapterSaveCastle @this is the original one
ldr r0, =0x716e98
mov r3, #1
ldr r1, =aSkipCastleRoutineString
bl cmvm__CmCFunction__CmCFunction
pop {r4, lr}
b 0x103d04

.pool
aCallRoutine:
andeq r0, r0, r0
aCallRoutineString:
.string "ev::CallRoutine"
aSkipCastleRoutine:
andeq r0, r0, r0
aSkipCastleRoutineString:
.string "ev::ChapterSetSkipCastleWithSave"

.align 4

CallRoutine:
push {r3-r7, lr} @why r3?
@r0 is the parent proc, r1 is the routine to call, r2 is -1 if not passing parent proc, and 0 if yes
mov r12, r1
ldr r4, [r0, #4] @r0 is parent proc. r0+4 is the pointer to the $0 variables.
cmp r2, #0
beq PassProc
blt NoPassProc
@otherwise use it as a string pointer?
mov r0, r2
bl Proc__FindByName
b PassProc

NoPassProc:
@if not passing proc
ldr r0, [r4]
ldr r1, [r4, #4]
ldr r2, [r4, #8]
ldr r3, [r4, #12]
b EndCallRoutine

PassProc:
@if passing proc
ldr r1, [r4]
ldr r2, [r4, #4]
ldr r3, [r4, #8]

EndCallRoutine:
blx r12
pop {r3-r7, pc}

.global SkipCastleWithSave
SkipCastleWithSave:
cmp r1, #0
push {r4, lr}
bl GameUserData__Get
ldr r1, [r0, #0x28]
beq clearSkipBit
orr r1, #0x800 @normally used to go to castle without saving
orr r1, #0x1000000 @and the bit for skip castle+save
b 0x3af27c
clearSkipBit:
bic r1, #0x800
bic r1, #0x1000000
b 0x3af27c

.global CheckSkipCastle
CheckSkipCastle: @checks if 0x1000000 and 0x800 are both set and if so skips castle and save, else just save, we'll skip the castle later in postsaveroutine
cmp r5, #0
beq 0x1b6724
mov r0, r7
b 0x1b6700

.global PostSaveRoutine
PostSaveRoutine:
push {r4, lr}
mov r4, r0
bl GameUserData__Get
ldr r1, [r0, #0x28]
tst r1, #0x1000000
beq NoSkipCastle
mov r0, r4
pop {r4, lr}
mov r1, #6
b ProcInst__Jump

NoSkipCastle:
pop {r4, pc}
.pool
2 Likes