summaryrefslogtreecommitdiff
path: root/src/replay.S
diff options
context:
space:
mode:
Diffstat (limited to 'src/replay.S')
-rw-r--r--src/replay.S799
1 files changed, 799 insertions, 0 deletions
diff --git a/src/replay.S b/src/replay.S
new file mode 100644
index 0000000..8c3f6c7
--- /dev/null
+++ b/src/replay.S
@@ -0,0 +1,799 @@
+# Fucking Nintendo, how do they work
+
+.extern IOS_Open
+.extern IOS_Close
+.extern IOS_Read
+.extern IOS_Write
+.extern OSGetTime
+.extern OSTicksToCalendarTime
+.extern OSReport
+.extern CurrentWorld
+.extern CurrentLevel
+.extern CurrentStartedArea
+.extern CurrentStartedEntrance
+.extern snprintf
+.extern GetSomeGlobalClass
+.extern SomeUnknownClass5408
+.extern SomeWipeClass
+.extern continueFromReplayHookStart
+.extern continueFromReplayEndHook
+.extern returnFromRecorder
+.extern QueryGlobal5758
+.extern GetRandomSeed
+.extern Player_ID
+.extern Player_Powerup
+.extern Player_Flags
+.extern EGG__Heap__alloc__FUliPv
+.extern EGG__Heap__free__FPvPv
+.extern GameHeap2
+.extern EggControllerClassPtrMaybe
+.extern GameMgr
+.extern StrangeReplayValue1
+.extern StrangeReplayValue2
+.extern StrangeReplayValue3
+.extern WiimotePtr1
+.extern Player_ID
+.extern RandomSeed
+
+.set sp, 1
+
+# mode 1 = read, 2 = write?
+
+.text
+.align 4
+
+.global replayStart
+.global replayEnd
+.global replayRecord
+
+.global luigiOverride
+luigiOverride:
+ #blr
+ lis r3, Player_ID@h
+ ori r3, r3, Player_ID@l
+ li r4, 1
+ stw r4, 0(r3)
+ blr
+
+.global getAndSaveRandomSeed
+getAndSaveRandomSeed: # b from 8091F930
+ lis r3, RandomSeed@h
+ ori r3, r3, RandomSeed@l
+ lwz r3, 0(r3)
+ lis r4, saveRandomSeed@h
+ ori r4, r4, saveRandomSeed@l
+ stw r3, 0(r4)
+
+ mr r4, r3
+ lis r3, str_gotSeed@h
+ ori r3, r3, str_gotSeed@l
+ crclr 4*cr1+eq
+ bl OSReport
+
+ lwz r0, 0x74(sp)
+ mtlr r0
+ addi sp, sp, 0x70
+ blr
+
+
+replayStart: # b from 809246E0
+ bl OSGetTime
+ lis r5, replayTime@h
+ ori r5, r5, replayTime@l
+ bl OSTicksToCalendarTime
+
+ li r29, 0
+ li r30, 0
+
+replayStartLoop:
+
+ lis r3, str_replayFileNameBuffer@h
+ ori r3, r3, str_replayFileNameBuffer@l
+
+ li r4, 64
+
+ lis r5, str_replayFileNameFormat@h
+ ori r5, r5, str_replayFileNameFormat@l
+
+ lis r6, CurrentWorld@h
+ ori r6, r6, CurrentWorld@l
+ lbz r6, 0(r6)
+ addi r6, r6, 1
+
+ lis r7, CurrentLevel@h
+ ori r7, r7, CurrentLevel@l
+ lbz r7, 0(r7)
+ addi r7, r7, 1
+
+ lis r8, replayTime_hour@h
+ ori r8, r8, replayTime_hour@l
+ lwz r8, 0(r8)
+
+ lis r9, replayTime_min@h
+ ori r9, r9, replayTime_min@l
+ lwz r9, 0(r9)
+
+ mr r10, r29
+
+ crclr 4*cr1+eq
+ bl snprintf
+
+ lis r4, str_replayFileNameBuffer@h
+ ori r4, r4, str_replayFileNameBuffer@l
+ lis r3, str_startMsg@h
+ ori r3, r3, str_startMsg@l
+ crclr 4*cr1+eq
+ bl OSReport
+
+ lis r3, str_replayFileNameBuffer@h
+ ori r3, r3, str_replayFileNameBuffer@l
+
+ li r4, 0x602 # O_WRITE | O_CREAT | O_TRUNC
+
+ bl IOS_Open
+
+ cmpwi r3, 0
+ blt iosOpenFail
+
+ lis r4, replayHandles@h
+ ori r4, r4, replayHandles@l
+ stwx r3, r4, r30
+
+ mr r4, r3
+ lis r3, str_iosOpenMsg@h
+ ori r3, r3, str_iosOpenMsg@l
+ crclr 4*cr1+eq
+ bl OSReport
+
+ # now write the header
+ lis r4, replayHeaders@h
+ ori r4, r4, replayHeaders@l
+ lwzx r4, r4, r30
+
+ lis r6, CurrentWorld@h
+ ori r6, r6, CurrentWorld@l
+ lis r7, CurrentLevel@h
+ ori r7, r7, CurrentLevel@l
+ lis r8, CurrentStartedArea@h
+ ori r8, r8, CurrentStartedArea@l # WRONG
+ lis r9, CurrentStartedEntrance@h
+ ori r9, r9, CurrentStartedEntrance@l # WRONG
+
+ lbz r6, 0(r6)
+ lbz r7, 0(r7)
+
+ stb r6, 0(r4)
+ stb r7, 1(r4)
+ stb r8, 2(r4)
+ stb r9, 3(r4)
+
+ lis r3, saveRandomSeed@h
+ ori r3, r3, saveRandomSeed@l
+ lwz r3, 0(r3)
+ stw r3, 4(r4)
+
+ # player ID specific stuff
+ mr r5, r29
+ slwi r5, r5, 2
+
+ lis r3, Player_ID@h
+ ori r3, r3, Player_ID@l
+ lwzx r3, r3, r5
+ slwi r6, r3, 2 # store this so we can get the powerup and flags
+ stw r3, 0x10(r4)
+
+ lis r3, Player_Powerup@h
+ ori r3, r3, Player_Powerup@l
+ lwzx r3, r3, r6
+ stw r3, 0x14(r4)
+
+ lis r3, Player_Flags@h
+ ori r3, r3, Player_Flags@l
+ lwzx r3, r3, r6
+ stw r3, 0x18(r4)
+
+ lis r3, GameMgr@h
+ ori r3, r3, GameMgr@l
+ lwz r3, 0(r3)
+ lbz r3, 0x380(r3)
+ stb r3, 0x21(r4)
+
+ # now set up variables
+ lis r4, replayFrameCounts@h
+ ori r4, r4, replayFrameCounts@l
+ li r3, 0
+ stwx r3, r4, r30
+
+ lis r3, replayFlags@h
+ ori r3, r3, replayFlags@l
+ li r4, 1
+ not r0, r4
+ lhz r4, 0(r3)
+ clrlwi r0, r0, 16
+ and r4, r4, r0
+ slwi r5, r29, 1 # player ID * 2
+ sthx r4, r3, r5
+
+ li r3, 0
+ lis r4, keepTiltValues@h
+ ori r4, r4, keepTiltValues@l
+ stwx r3, r4, r30
+
+ lis r4, replayDataBufferSize@h
+ ori r4, r4, replayDataBufferSize@l
+ lwz r3, 0(r4)
+
+ # alloc the memory
+ li r4, 4
+ lis r5, GameHeap2@h
+ ori r5, r5, GameHeap2@l
+ lwz r5, 0(r5)
+ bl EGG__Heap__alloc__FUliPv
+
+ lis r4, replayDataBuffers@h
+ ori r4, r4, replayDataBuffers@l
+ stwx r3, r4, r30
+
+ lis r4, replayDataBufferPointers@h
+ ori r4, r4, replayDataBufferPointers@l
+ stwx r3, r4, r30
+
+ mr r4, r3
+ lis r3, str_bufferObtained@h
+ ori r3, r3, str_bufferObtained@l
+ crclr 4*cr1+eq
+ bl OSReport
+
+ b startNextReplay
+
+iosOpenFail:
+ mr r4, r3
+ lis r3, str_iosOpenFailed@h
+ ori r3, r3, str_iosOpenFailed@l
+ crclr 4*cr1+eq
+ bl OSReport
+
+startNextReplay:
+
+ # the loop
+ addi r29, r29, 1
+ addi r30, r30, 4
+ cmpwi r29, 4
+ blt replayStartLoop
+
+ # and done!
+ li r3, 1
+ b continueFromReplayHookStart # 809246E4
+
+
+
+magicalReplayCheck:
+ stwu sp, -0x10(sp)
+ mflr r0
+ stw r0, 0x14(sp)
+ stw r31, 0x0C(sp)
+ mr r31, r3
+
+ bl GetSomeGlobalClass
+
+ lwz r0, 0x1D0(r3)
+ cmpwi r0, 2
+ bne no_flag_20
+
+ ori r31, r31, 0x20
+ b done_flag_20
+
+no_flag_20:
+ li r4, 0x20
+ not r4, r4
+ and r31, r31, r4
+
+done_flag_20:
+ lis r3, SomeUnknownClass5408@h # 8042A578
+ ori r3, r3, SomeUnknownClass5408@l
+ lwz r3, 0(r3)
+ lbz r3, 4(r3)
+
+ cmpwi r3, 0
+ beq no_flag_40
+
+ ori r31, r31, 0x40
+ b done_flag_40
+
+no_flag_40:
+ li r4, 0x40
+ not r4, r4
+ and r31, r31, r4
+
+done_flag_40:
+ lis r3, SomeWipeClass@h # 8042A720
+ ori r3, r3, SomeWipeClass@l
+ lwz r3, 0(r3)
+ lwz r12, 0(r3)
+ lwz r12, 0x10(r12)
+ mtctr r12
+ bctrl
+
+ subi r0, r3, 1
+ cntlzw r0, r0
+ srwi. r0, r0, 5
+ beq set_flag_2
+
+ li r4, 2
+ not r4, r4
+ and r31, r31, r4
+ b done_flag_2
+
+set_flag_2:
+ ori r31, r31, 2
+
+done_flag_2:
+ li r3, 1
+ bl QueryGlobal5758
+
+ cmpwi r3, 0
+ beq no_flag_4
+
+ ori r31, r31, 4
+ b done_flag_4
+
+no_flag_4:
+ li r4, 4
+ not r4, r4
+ and r31, r31, r4
+
+done_flag_4:
+ li r3, 4
+ bl QueryGlobal5758
+
+ cmpwi r3, 0
+ beq no_flag_100
+
+ ori r31, r31, 0x100
+ b done_flag_100
+
+no_flag_100:
+ li r4, 0x100
+ not r4, r4
+ and r31, r31, r4
+
+done_flag_100:
+ li r3, 2
+ bl QueryGlobal5758
+
+ cmpwi r3, 0
+ beq no_flag_8
+
+ ori r31, r31, 8
+ b done_flag_8
+
+no_flag_8:
+ li r4, 8
+ not r4, r4
+ and r31, r31, r4
+
+done_flag_8:
+ # okay, we're done
+ mr r3, r31
+
+ lwz r0, 0x14(sp)
+ lwz r31, 0x0C(sp)
+ mtlr r0
+ addi sp, sp, 0x10
+ blr
+
+
+
+
+
+replayEnd: # bl from 80102238
+ stwu sp, -0x20(sp)
+ mflr r0
+ stw r0, 0x24(sp)
+ stw r31, 0x1C(sp)
+ stw r30, 0x18(sp)
+ stw r29, 0x14(sp)
+
+ cmpwi r3, 1
+ bne justLeave
+
+ li r29, 0
+ li r30, 0
+
+replayEndLoop:
+ lis r31, replayHandles@h
+ ori r31, r31, replayHandles@l
+ add r31, r31, r30 # becomes a pointer to the handle, not the handle itself
+
+ lwz r3, 0(r31)
+ cmpwi r3, 0
+ beq dontEndThisReplay
+
+ lis r4, replayHeaders@h
+ ori r4, r4, replayHeaders@l
+ lwzx r4, r4, r30
+ li r5, 0x40
+ bl IOS_Write
+
+ lwz r3, 0(r31)
+ lis r4, replayDataBuffers@h
+ ori r4, r4, replayDataBuffers@l
+ lwzx r4, r4, r30
+ lis r5, replayDataBufferPointers@h # calc written size
+ ori r5, r5, replayDataBufferPointers@l
+ lwzx r5, r5, r30
+ subf r5, r4, r5
+ bl IOS_Write
+
+ lwz r3, 0(r31)
+ lis r4, replayFooter@h
+ ori r4, r4, replayFooter@l
+ li r5, 4
+ bl IOS_Write
+
+ lwz r3, 0(r31)
+ bl IOS_Close
+
+ li r3, 0
+ stw r3, 0(r31)
+
+ lis r4, replayDataBuffers@h
+ ori r4, r4, replayDataBuffers@l
+ lwzx r3, r4, r30
+ li r4, 0
+ bl EGG__Heap__free__FPvPv
+
+ lis r4, replayDataBuffers@h
+ ori r4, r4, replayDataBuffers@l
+ li r0, 0
+ stwx r0, r4, r30
+
+ lis r3, str_endMsg@h
+ ori r3, r3, str_endMsg@l
+ lis r4, replayFrameCounts@h
+ ori r4, r4, replayFrameCounts@l
+ lwzx r4, r4, r30
+ crclr 4*cr1+eq
+ bl OSReport
+
+ # before we leave, set the flag again
+ lis r3, replayFlags@h
+ ori r3, r3, replayFlags@l
+ add r3, r3, r29
+ add r3, r3, r29
+ lhz r4, 0(r3)
+ ori r4, r4, 1
+ sth r4, 0(r3)
+
+dontEndThisReplay:
+
+ # now loop
+ addi r29, r29, 1
+ addi r30, r30, 4
+ cmpwi r29, 4
+ blt replayEndLoop
+
+ li r3, 1
+
+justLeave:
+
+ lwz r0, 0x24(sp)
+ lwz r31, 0x1C(sp)
+ lwz r30, 0x18(sp)
+ lwz r29, 0x14(sp)
+ mtlr r0
+ addi sp, sp, 0x20
+ blr
+ #b continueFromReplayEndHook # 8010223C
+
+
+
+
+replayRecord:
+ # fun shit.
+ stwu sp, -0x10(sp)
+ mflr r0
+ stw r0, 0x14(sp)
+ stw r31, 0xC(sp)
+ stw r30, 8(sp)
+
+ li r30, 0
+
+recordLoop:
+ # get the controller class
+ lis r31, EggControllerClassPtrMaybe@h
+ ori r31, r31, EggControllerClassPtrMaybe@l
+ lwz r31, 0(r31)
+ slwi r3, r30, 2
+ addi r3, r3, 4
+ lwzx r31, r31, r3
+
+ # get player number
+ mr r4, r30
+
+ lis r3, replayFlags@h
+ ori r3, r3, replayFlags@l
+ add r3, r3, r4
+ add r3, r3, r4 # get pointer to flags
+ lhz r3, 0(r3)
+
+ bl magicalReplayCheck
+ lwz r5, 4(r31)
+ lis r4, replayFlags@h
+ ori r4, r4, replayFlags@l
+ add r4, r4, r5
+ add r4, r4, r5
+ sth r3, 0(r4)
+
+ #mr r4, r3
+ #lis r3, str_debugFlags@h
+ #ori r3, r3, str_debugFlags@l
+ #crclr 4*cr1+eq
+ #bl OSReport
+
+ #lis r3, replayFlags@h
+ #ori r3, r3, replayFlags@l
+ #lhz r3, 0(r3)
+ cmpwi r3, 0
+ bne goToNextRecorder
+
+ # set this to player number * 4
+ # r31 is our controller class
+ lwz r9, 4(r31)
+ slwi r9, r9, 2
+
+ lis r3, replayFrameCounts@h
+ ori r3, r3, replayFrameCounts@l
+ lwzx r4, r3, r9
+ addi r4, r4, 1
+ stwx r4, r3, r9
+
+ # put together the data
+ # first grab a pointer
+ lis r7, replayDataBufferPointers@h
+ ori r7, r7, replayDataBufferPointers@l
+ lwzx r6, r7, r9
+
+ cmpwi r6, 0
+ beq goToNextRecorder
+
+ # first off, grab the initial flags
+ li r3, 0
+
+ lbz r4, 0x8C(r31) # shake flag
+ cmpwi r4, 1
+ bne dontShake
+ oris r3, r3, 0x2000
+dontShake:
+
+ # now do the tilt stuff
+ lis r4, keepTiltValues@h
+ ori r4, r4, keepTiltValues@l
+ lwzx r0, r4, r9 # last value
+ lhz r5, 0x8E(r31) # new value
+ stwx r5, r4, r9 # store new value
+ cmpw r5, r0
+ beq tiltDidntChange
+ oris r3, r3, 0x80
+tiltDidntChange:
+
+ # ok, so we decided that, now write the flags + weird value + etc!
+ stw r3, 0(r6)
+
+ # calculate the weird value
+ li r3, 0
+
+ lis r10, StrangeReplayValue1@h
+ ori r10, r10, StrangeReplayValue1@l
+ lhz r10, 0(r10)
+ slwi r10, r10, 16
+ or r3, r3, r10
+
+ lis r10, StrangeReplayValue2@h
+ ori r10, r10, StrangeReplayValue2@l
+ lbz r10, 0(r10)
+ slwi r10, r10, 8
+ or r3, r3, r10
+
+ lis r10, StrangeReplayValue3@h
+ ori r10, r10, StrangeReplayValue3@l
+ lbz r10, 0(r10)
+ or r3, r3, r10
+
+ stw r3, 4(r6)
+
+ # buttons
+ lwz r3, 0xC(r31)
+ li r4, 0x0F0F
+ and r3, r3, r4
+ stw r3, 8(r6)
+
+ addi r6, r6, 0xC # we wrote 0xC bytes
+
+ # now the tilt segment
+ beq dontWriteTilt
+ sth r5, 0(r6)
+ li r3, 0
+ sth r3, 2(r6)
+ addi r6, r6, 4
+
+dontWriteTilt:
+ # are we done now?!
+ # I hope so.
+
+ lis r7, replayDataBufferPointers@h
+ ori r7, r7, replayDataBufferPointers@l
+ stwx r6, r7, r9
+
+ # before we do this. check if we should end the replay
+ # the raw button presses are at 0x18 in the Wiimote class
+ lis r5, WiimotePtr1@h
+ ori r5, r5, WiimotePtr1@l
+ lwzx r3, r5, r9
+ lwz r3, 0x18(r3)
+ li r4, 0x0400 # B button mask
+ and. r3, r3, r4
+ beq goToNextRecorder
+
+ # end it!
+ li r3, 1
+ bl replayEnd
+ b leaveRecordLoop
+
+goToNextRecorder:
+
+ addi r30, r30, 1
+ cmpwi r30, 4
+ blt recordLoop
+
+leaveRecordLoop:
+
+ lwz r31, 0xC(sp)
+ lwz r30, 8(sp)
+ lwz r0, 0x14(sp)
+ mtlr r0
+ addi sp, sp, 0x10
+ blr
+
+
+.data
+
+replayFlags: .short 1, 1, 1, 1
+.align 4
+
+replayHandles: .long 0, 0, 0, 0
+
+replayFrameCounts: .long 0, 0, 0, 0
+
+replayTime:
+replayTime_sec: .long 0
+replayTime_min: .long 0
+replayTime_hour: .long 0
+replayTime_mday: .long 0
+replayTime_mon: .long 0
+replayTime_year: .long 0
+replayTime_wday: .long 0
+replayTime_yday: .long 0
+replayTime_msec: .long 0
+replayTime_usec: .long 0
+
+str_replayFileNameFormat:
+ .string "file/Replay_%02d-%02d_from_%02d-%02d_p%d.bin"
+
+str_replayFileNameBuffer:
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+ .byte 0,0,0,0,0,0,0,0
+
+str_startMsg:
+ .string "*** Replay Recorder by Treeki -- Starting to record. Filename: %s\n"
+
+str_iosOpenMsg:
+ .string "*** Replay Recorder -- IOS_Open returned: %d\n"
+
+str_iosOpenFailed:
+ .string "*** Replay Recorder -- IOS_Open failed! It returned: %d -- The replay will not be saved.\n"
+
+str_bufferObtained:
+ .string "*** Replay Recorder -- Allocated replay buffer at %p\n"
+
+str_endMsg:
+ .string "*** Replay Recorder -- Recording complete. %d frames saved.\n"
+
+str_debugFlags:
+ .string "DEBUG:%04x\n"
+
+str_gotSeed:
+ .string "Got random seed: %08x\n"
+
+.align 4
+
+replayHeaders:
+ .long replayHeader0
+ .long replayHeader1
+ .long replayHeader2
+ .long replayHeader3
+
+replayHeader0:
+replayHeader0_world: .byte 0
+replayHeader0_level: .byte 0
+replayHeader0_area: .byte 0
+replayHeader0_entrance: .byte 0
+replayHeader0_seed: .long 0
+replayHeader0_padding08: .long 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader0_playerID: .long 0
+replayHeader0_powerup: .long 0
+replayHeader0_playerFlg: .long 0
+replayHeader0_padding1C: .long 0xFFFFFFFF
+replayHeader0_padding20: .byte 0xFF
+replayHeader0_switchFlg: .byte 0
+replayHeader0_padding22: .byte 0xFF, 0xFF
+replayHeader0_padding24: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader0_padding30: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader1:
+replayHeader1_world: .byte 0
+replayHeader1_level: .byte 0
+replayHeader1_area: .byte 0
+replayHeader1_entrance: .byte 0
+replayHeader1_seed: .long 0
+replayHeader1_padding08: .long 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader1_playerID: .long 0
+replayHeader1_powerup: .long 0
+replayHeader1_playerFlg: .long 0
+replayHeader1_padding1C: .long 0xFFFFFFFF
+replayHeader1_padding20: .byte 0xFF
+replayHeader1_switchFlg: .byte 0
+replayHeader1_padding22: .byte 0xFF, 0xFF
+replayHeader1_padding24: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader1_padding30: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader2:
+replayHeader2_world: .byte 0
+replayHeader2_level: .byte 0
+replayHeader2_area: .byte 0
+replayHeader2_entrance: .byte 0
+replayHeader2_seed: .long 0
+replayHeader2_padding08: .long 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader2_playerID: .long 0
+replayHeader2_powerup: .long 0
+replayHeader2_playerFlg: .long 0
+replayHeader2_padding1C: .long 0xFFFFFFFF
+replayHeader2_padding20: .byte 0xFF
+replayHeader2_switchFlg: .byte 0
+replayHeader2_padding22: .byte 0xFF, 0xFF
+replayHeader2_padding24: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader2_padding30: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader3:
+replayHeader3_world: .byte 0
+replayHeader3_level: .byte 0
+replayHeader3_area: .byte 0
+replayHeader3_entrance: .byte 0
+replayHeader3_seed: .long 0
+replayHeader3_padding08: .long 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader3_playerID: .long 0
+replayHeader3_powerup: .long 0
+replayHeader3_playerFlg: .long 0
+replayHeader3_padding1C: .long 0xFFFFFFFF
+replayHeader3_padding20: .byte 0xFF
+replayHeader3_switchFlg: .byte 0
+replayHeader3_padding22: .byte 0xFF, 0xFF
+replayHeader3_padding24: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+replayHeader3_padding30: .long 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
+
+# header size is 0x40 bytes
+
+replayFooter: .long 0xFFFFFFFF
+
+replayDataBuffers: .long 0, 0, 0, 0
+replayDataBufferPointers: .long 0, 0, 0, 0
+replayDataBufferSize: .long 0x80000
+
+saveRandomSeed: .long 0
+
+
+keepTiltValues: .long 0, 0, 0, 0
+