Sync libgcnmultiboot

This commit is contained in:
GriffinR 2021-11-02 20:28:17 -04:00
parent c98fbb5ca6
commit dc44548e43

View File

@ -4,11 +4,36 @@
.include "asm/macros.inc"
.include "constants/constants.inc"
.equiv GCMB_STRUCT_COUNTER1, 0x00
.equiv GCMB_STRUCT_COUNTER2, 0x01
.equiv GCMB_STRUCT_MBPROGRESS, 0x02
.equiv GCMB_STRUCT_SAVEDVCOUNT, 0x03
.equiv GCMB_STRUCT_KEYA, 0x04
.equiv GCMB_STRUCT_KEYB, 0x08
.equiv GCMB_STRUCT_KEYC, 0x0C
.equiv GCMB_STRUCT_BOOT_KEY, 0x10
.equiv GCMB_STRUCT_IMAGE_SIZE, 0x12
.equiv GCMB_STRUCT_SESSION_KEY, 0x14
.equiv GCMB_STRUCT_HASH_VAL, 0x18
.equiv GCMB_STRUCT_KEYC_DERIVATION, 0x1C
.equiv GCMB_STRUCT_BASE_DEST_PTR, 0x20
.equiv GCMB_STRUCT_CUR_DEST_PTR, 0x24
.equiv GCMB_STRUCT_SERIAL_INTR_HANDLER, 0x28
.equiv ROM_HEADER_NINTENDO_LOGO_OFFSET, 0x4
.equiv ROM_HEADER_NINTENDO_LOGO_OFFSET, 0x04
.equiv ROM_HEADER_NINTENDO_LOGO_LENGTH, 0x98
.equiv ROM_HEADER_NINTENDO_LOGO_END, 0xA0
.equiv MBPROGRESS_NONE, 0x00
.equiv MBPROGRESS_LOGO_CORRECT, 0x01
.equiv MBPROGRESS_READY_TO_BOOT, 0x02
.equiv GCMB_MAGIC_BOOTKEY_HASHVAL, 0xBB
.equiv GCMB_MAGIC_BOOTKEY, 0xBB
.equiv GCMB_MAGIC_COUNTER2, 0xCC
.equiv GCMB_MAGIC_KEYA, 0xDD
.equiv GCMB_MAGIC_KEYB, 0xEE
.equiv GCMB_MAGIC_KEYCDERIVATION, 0xFF
.syntax unified
@ -22,7 +47,7 @@ GameCubeMultiBoot_Hash: @ 82DED70
movs r2, 0x20
GameCubeMultiBoot_Hash_Loop:
lsrs r3, #1
lsrs r3, 1
bcc GameCubeMultiBoot_Hash_SkipEor
eors r3, r4
@ -37,137 +62,177 @@ GameCubeMultiBoot_Hash_SkipEor:
thumb_func_start GameCubeMultiBoot_Main
@ void GameCubeMultiBoot_Main(struct GameCubeMultiBoot *mb);
GameCubeMultiBoot_Main: @ 82DED84
ldr r1, [r0, #GCMB_STRUCT_SERIAL_INTR_HANDLER]
cmp r1, #0
beq _082DEDAA
ldrb r1, [r0, 0x1]
adds r1, 0x1
strb r1, [r0, 0x1]
ldrb r1, [r0, 0x2]
cmp r1, 0x2
beq _082DEDF4
ldr r3, pool_InterruptRegs
ldrh r2, [r3, #OFFSET_REG_IME - 0x200]
movs r1, 0
strh r1, [r3, #OFFSET_REG_IME - 0x200]
ldrb r1, [r0]
cmp r1, 0xA
bgt _082DEDA8
adds r1, 0x1
strb r1, [r0]
_082DEDA8:
strh r2, [r3, #OFFSET_REG_IME - 0x200]
_082DEDAA:
bcs GameCubeMultiBoot_Init
ldrb r1, [r0, 0x2]
@ If there is no interrupt handler, skip counter manipulation
ldr r1, [r0, GCMB_STRUCT_SERIAL_INTR_HANDLER]
cmp r1, 0
bne _082DEDF6
ldr r1, [r0, #GCMB_STRUCT_CUR_DEST_PTR]
ldr r2, [r0, #GCMB_STRUCT_BASE_DEST_PTR]
beq GameCubeMultiBoot_Main_SkipCounters
@ Increment the second counter
ldrb r1, [r0, GCMB_STRUCT_COUNTER2]
adds r1, 0x1
strb r1, [r0, GCMB_STRUCT_COUNTER2]
@ If there is nothing more to do, bail out
ldrb r1, [r0, GCMB_STRUCT_MBPROGRESS]
cmp r1, MBPROGRESS_READY_TO_BOOT
beq GameCubeMultiBoot_Main_Return
@ Save current interrupt master register value
ldr r3, pool_InterruptRegs
ldrh r2, [r3, OFFSET_REG_IME - 0x200]
@ Disable all interrupts
movs r1, 0
strh r1, [r3, OFFSET_REG_IME - 0x200]
@ Increment the first counter, if it's less than or equal to 10.
ldrb r1, [r0, GCMB_STRUCT_COUNTER1]
cmp r1, 0xA
bgt GameCubeMultiBoot_Main_SkipCounter1Inc
adds r1, 0x1
strb r1, [r0, GCMB_STRUCT_COUNTER1]
GameCubeMultiBoot_Main_SkipCounter1Inc:
@ Load the saved interrupt master register value (re-enables interrupts if they were enabled before)
strh r2, [r3, OFFSET_REG_IME - 0x200]
GameCubeMultiBoot_Main_SkipCounters:
@ Initialise multiboot structures if required
bcs GameCubeMultiBoot_Init
@ Skip this section (check Nintendo logo) if the check has already passed
ldrb r1, [r0, GCMB_STRUCT_MBPROGRESS]
cmp r1, MBPROGRESS_NONE
bne GameCubeMultiBoot_Main_SkipLogoCheck
@ Bail out if no multiboot image data has been transferred yet
ldr r1, [r0, GCMB_STRUCT_CUR_DEST_PTR]
ldr r2, [r0, GCMB_STRUCT_BASE_DEST_PTR]
subs r1, r2
beq _082DEE76
cmp r1, 0xA0
bcc _082DEE76
beq GameCubeMultiBoot_Main_Return2
@ Also bail out if not enough data has been transferred
cmp r1, ROM_HEADER_NINTENDO_LOGO_END
bcc GameCubeMultiBoot_Main_Return2
@ Compare the Nintendo logo of the transferred multiboot image header, with the one in the ROM image of the inserted cart
push {r4-r6}
movs r1, 0x98
adds r2, #ROM_HEADER_NINTENDO_LOGO_OFFSET
movs r1, ROM_HEADER_NINTENDO_LOGO_LENGTH
adds r2, ROM_HEADER_NINTENDO_LOGO_OFFSET
ldr r4, pool_NintendoLogo
_082DEDC6:
GameCubeMultiBoot_Main_LogoCmpLoop:
ldm r2!, {r5}
ldm r4!, {r6}
cmp r5, r6
bne _082DEDDC
bne GameCubeMultiBoot_Main_LogoCmpEnd
subs r1, 0x4
bne _082DEDC6
bne GameCubeMultiBoot_Main_LogoCmpLoop
ldm r2!, {r5}
ldm r4!, {r6}
eors r5, r6
lsrs r5, #8
str r2, [r0, #GCMB_STRUCT_BASE_DEST_PTR]
_082DEDDC:
lsrs r5, 8
str r2, [r0, GCMB_STRUCT_BASE_DEST_PTR]
GameCubeMultiBoot_Main_LogoCmpEnd:
pop {r4-r6}
@ Throw everything away if the logo data didn't match
bne GameCubeMultiBoot_Init
movs r1, 0x1
strb r1, [r0, 0x2]
ldr r1, [r0, 0x4]
ldr r2, [r0, 0x8]
@ Logo matched, set the relevent multiboot progress bit
movs r1, MBPROGRESS_LOGO_CORRECT
strb r1, [r0, GCMB_STRUCT_MBPROGRESS]
@ XOR together KeyA and KeyB to get the initial multiboot image checksum value
ldr r1, [r0, GCMB_STRUCT_KEYA]
ldr r2, [r0, GCMB_STRUCT_KEYB]
eors r1, r2
str r1, [r0, 0x18]
str r1, [r0, GCMB_STRUCT_HASH_VAL]
@ ...also use it as the initial value for the image encryption session key. Algorithm is the same as the GBA BIOS multiboot: sessionkey = (initialvalue * 0x6177614b) + 1
ldr r2, pool_Kawa
muls r1, r2
adds r1, 0x1
str r1, [r0, 0x14]
_082DEDF4:
str r1, [r0, GCMB_STRUCT_SESSION_KEY]
GameCubeMultiBoot_Main_Return:
bx lr
_082DEDF6:
ldr r1, [r0, #GCMB_STRUCT_CUR_DEST_PTR]
GameCubeMultiBoot_Main_SkipLogoCheck:
@ If this code is executed, then the logo check has passed, and the data being transferred in is encrypted.
@ Set up registers.
ldr r1, [r0, GCMB_STRUCT_CUR_DEST_PTR]
mov r12, r1
ldr r3, [r0, 0x18]
ldr r3, [r0, GCMB_STRUCT_HASH_VAL]
push {r4-r7}
ldr r4, [r0, #GCMB_STRUCT_BASE_DEST_PTR]
ldr r4, [r0, GCMB_STRUCT_BASE_DEST_PTR]
ldr r5, pool_Kawa
ldr r6, [r0, 0x14]
ldr r6, [r0, GCMB_STRUCT_SESSION_KEY]
ldr r7, pool_HashVal
_082DEE06:
GameCubeMultiBoot_Main_ImageDecryptHashLoop:
@ If there's no more data, break out of the loop
cmp r4, r12
bcs _082DEE26
bcs GameCubeMultiBoot_Main_ImageDecryptHashEnd
@ Get the next uint32
ldr r1, [r4]
@ Decrypt the ciphertext: plaintext = (ciphertext ^ sessionkey) + hashval
eors r1, r6
adds r1, r3
@ Save the current uint32 of plaintext and advance the pointer
stm r4!, {r1}
@ Advance the hashval with this uint32 of plaintext -- this is the same code as GameCubeMultiBoot_Hash.
eors r3, r1
movs r2, 0x20
_082DEE16:
lsrs r3, #1
bcc _082DEE1C
GameCubeMultiBoot_Main_HashLoop:
lsrs r3, 1
bcc GameCubeMultiBoot_Main_HashSkipEor
eors r3, r7
_082DEE1C:
GameCubeMultiBoot_Main_HashSkipEor:
subs r2, 0x1
bne _082DEE16
bne GameCubeMultiBoot_Main_HashLoop
@ Advance the sessionkey with the usual algorithm: sessionkey = (sessionkey * 0x6177614b) + 1
muls r6, r5
adds r6, 0x1
b _082DEE06
_082DEE26:
str r4, [r0, #GCMB_STRUCT_BASE_DEST_PTR]
str r6, [r0, 0x14]
b GameCubeMultiBoot_Main_ImageDecryptHashLoop
GameCubeMultiBoot_Main_ImageDecryptHashEnd:
@ Save the new pointer, sessionkey, hashval
str r4, [r0, GCMB_STRUCT_BASE_DEST_PTR]
str r6, [r0, GCMB_STRUCT_SESSION_KEY]
pop {r4-r7}
str r3, [r0, 0x18]
ldrh r1, [r0, 0x12]
cmp r1, #0
bne _082DEE76
ldr r1, [r0, #GCMB_STRUCT_CUR_DEST_PTR]
ldr r2, [r0, #GCMB_STRUCT_BASE_DEST_PTR]
str r3, [r0, GCMB_STRUCT_HASH_VAL]
@ Bail out if the image size is unknown
ldrh r1, [r0, GCMB_STRUCT_IMAGE_SIZE]
cmp r1, 0
bne GameCubeMultiBoot_Main_Return2
@ Bail out if no image data has been transferred
ldr r1, [r0, GCMB_STRUCT_CUR_DEST_PTR]
ldr r2, [r0, GCMB_STRUCT_BASE_DEST_PTR]
cmp r1, r2
bne _082DEE76
ldr r1, [r0, 0xC]
cmp r1, #0
beq _082DEE60
ldrh r1, [r0, 0x10]
cmp r1, #0
beq _082DEDF4
bne GameCubeMultiBoot_Main_Return2
@ If KeyC hasn't been generated yet, go generate it
ldr r1, [r0, GCMB_STRUCT_KEYC]
cmp r1, 0
beq GameCubeMultiBoot_Main_GenerateKeyC
@ If the other side hasn't sent its boot key yet, bail out
ldrh r1, [r0, GCMB_STRUCT_BOOT_KEY]
cmp r1, 0
beq GameCubeMultiBoot_Main_Return
@ Save off LR so it doesn't get clobbered by the upcoming function call
mov r12, lr
movs r1, 0xBB
ldr r3, [r0, 0xC]
@ Generate the real boot key, which is the checksum of a hardcoded value and KeyC
movs r1, GCMB_MAGIC_BOOTKEY_HASHVAL
ldr r3, [r0, GCMB_STRUCT_KEYC]
bl GameCubeMultiBoot_Hash
ldrh r1, [r0, 0x10]
ldrh r1, [r0, GCMB_STRUCT_BOOT_KEY]
@ Restore the saved LR value
mov lr, r12
@ Compare the two boot keys (real and passed in), if they don't match then throw everything away
subs r1, r3
bne GameCubeMultiBoot_Init
movs r1, 0x2
strb r1, [r0, 0x2]
@ The two boot keys matched, tell the caller that the image is ready to boot
movs r1, MBPROGRESS_READY_TO_BOOT
strb r1, [r0, GCMB_STRUCT_MBPROGRESS]
@ Nothing more to do, return.
bx lr
_082DEE60:
GameCubeMultiBoot_Main_GenerateKeyC:
@ Save off LR so it doesn't get clobbered by the upcoming function call
mov r12, lr
ldrb r1, [r0, 0x3]
lsls r1, #24
@ KeyC = (SavedVCount << 24) - 1
ldrb r1, [r0, GCMB_STRUCT_SAVEDVCOUNT]
lsls r1, 24
subs r1, 0x1
str r1, [r0, 0xC]
str r1, [r0, GCMB_STRUCT_KEYC]
@ Hash the KeyC with the multiboot image checksum to generate the KeyC derivation material to be sent to the other side of the link
bl GameCubeMultiBoot_Hash
lsls r3, #8
adds r3, 0xFF
str r3, [r0, 0x1C]
@ Make sure the sent KeyC derivation material contains a magic value so that the other side can detect it
lsls r3, 8
adds r3, GCMB_MAGIC_KEYCDERIVATION
@ Save off the KeyC derivation material and return to caller
str r3, [r0, GCMB_STRUCT_KEYC_DERIVATION]
bx r12
_082DEE76:
GameCubeMultiBoot_Main_Return2:
bx lr
thumb_func_end GameCubeMultiBoot_Main
@ -182,12 +247,15 @@ pool_NintendoLogo: .4byte RomHeaderNintendoLogo
thumb_func_start GameCubeMultiBoot_ExecuteProgram
@ void GameCubeMultiBoot_ExecuteProgram(struct GameCubeMultiBoot *mb);
GameCubeMultiBoot_ExecuteProgram: @ 82DEE84
ldrb r1, [r0, 0x2]
cmp r1, 0x2
@ If there's no multiboot image ready, just return to caller
ldrb r1, [r0, GCMB_STRUCT_MBPROGRESS]
cmp r1, MBPROGRESS_READY_TO_BOOT
bne GameCubeMultiBoot_ExecuteProgram_Fail
@ Disable interrupts
ldr r3, pool_InterruptRegs
movs r1, #0
strh r1, [r3, #OFFSET_REG_IME - 0x200]
movs r1, 0
strh r1, [r3, OFFSET_REG_IME - 0x200]
@ Jump to the real entry point of the multiboot image (past the image header), in ARM mode
ldr r1, pool_MultiBootLoadAddr
adds r1, 0xC0
bx r1
@ -201,25 +269,25 @@ GameCubeMultiBoot_Init: @ 82DEE98
ldr r3, pool_InterruptRegs
@ Save IME register.
ldrh r2, [r3, #OFFSET_REG_IME - 0x200]
ldrh r2, [r3, OFFSET_REG_IME - 0x200]
@ Disable interrupts.
movs r1, 0
strh r1, [r3, #OFFSET_REG_IME - 0x200]
strh r1, [r3, OFFSET_REG_IME - 0x200]
@ Set the handler to the "Stop" routine.
@ Unless the first command that is received is a device reset command, the
@ "Stop" routine will be executed and no further commands will be processed.
adr r3, GcMbIntrHandler_Stop
str r3, [r0, #GCMB_STRUCT_SERIAL_INTR_HANDLER]
str r3, [r0, GCMB_STRUCT_SERIAL_INTR_HANDLER]
ldrb r3, [r0, 0x3]
push {r3}
ldrb r3, [r0, 0x1]
push {r0,r3}
adds r3, r0, #0
adds r3, #GCMB_STRUCT_BASE_DEST_PTR
adds r3, r0, 0
adds r3, GCMB_STRUCT_BASE_DEST_PTR
@ clear all but the last 3 fields of the struct
GameCubeMultiBoot_Init_ClearStructLoop:
@ -261,7 +329,7 @@ GameCubeMultiBoot_Init_ClearStructLoop:
strh r1, [r3, OFFSET_REG_IE - 0x200]
@ Restore IME register.
strh r2, [r3, #OFFSET_REG_IME - 0x200]
strh r2, [r3, OFFSET_REG_IME - 0x200]
bx lr
thumb_func_end GameCubeMultiBoot_Init
@ -275,11 +343,11 @@ GameCubeMultiBoot_HandleSerialInterrupt: @ 82DEEE2
ldrh r1, [r3, OFFSET_REG_JOYCNT - 0x120]
strh r1, [r3, OFFSET_REG_JOYCNT - 0x120]
movs r2, #0
movs r2, 0
strb r2, [r0]
ldr r2, [r0, #GCMB_STRUCT_SERIAL_INTR_HANDLER]
cmp r2, #0
ldr r2, [r0, GCMB_STRUCT_SERIAL_INTR_HANDLER]
cmp r2, 0
beq GameCubeMultiBoot_HandleSerialInterruptDone
lsrs r1, 1 @ was a device reset command received?
@ -297,7 +365,7 @@ GcMbIntrHandler_Stop:
strh r2, [r3, OFFSET_REG_JOYSTAT - 0x120]
GameCubeMultiBoot_SetInterruptHandler:
str r2, [r0, #GCMB_STRUCT_SERIAL_INTR_HANDLER]
str r2, [r0, GCMB_STRUCT_SERIAL_INTR_HANDLER]
GameCubeMultiBoot_ReadVCount:
ldr r3, pool_RegDispstat
@ -308,19 +376,25 @@ GameCubeMultiBoot_HandleSerialInterruptDone:
bx lr
GameCubeMultiBoot_BeginHandshake:
@ Throw away anything that got sent
ldr r1, [r3, OFFSET_REG_JOY_RECV - 0x120]
@ Send the game code, the other side of the link must send back the same game code
ldr r1, pool_RubyUSAGameCode
str r1, [r3, OFFSET_REG_JOY_TRANS - 0x120]
movs r1, 0x10
strh r1, [r3, OFFSET_REG_JOYSTAT - 0x120]
ldrb r1, [r0, 0x3]
strb r1, [r0, 0x9]
ldrb r1, [r0, 0x2]
@ Use the saved VCount value to provide 8 bits of entropy for KeyB
ldrb r1, [r0, GCMB_STRUCT_SAVEDVCOUNT]
strb r1, [r0, GCMB_STRUCT_KEYB + 1]
@ If a multiboot image has been transferred at least enough such that the Nintendo logo check has passed, stop everything.
ldrb r1, [r0, GCMB_STRUCT_MBPROGRESS]
cmp r1, 0
bne GcMbIntrHandler_Stop
@ Set the image destination pointers.
ldr r1, pool_MultiBootLoadAddr
str r1, [r0, #GCMB_STRUCT_BASE_DEST_PTR]
str r1, [r0, #GCMB_STRUCT_CUR_DEST_PTR]
str r1, [r0, GCMB_STRUCT_BASE_DEST_PTR]
str r1, [r0, GCMB_STRUCT_CUR_DEST_PTR]
@ Set the new interrupt handler.
adr r2, GcMbIntrHandler_CheckGameCodeSent
b GameCubeMultiBoot_SetInterruptHandler
@ -347,149 +421,166 @@ GameCubeMultiBoot_CheckHandshakeResponse:
ldr r2, pool_RubyUSAGameCode
cmp r1, r2
bne GcMbIntrHandler_Stop @ stop if the GameCube didn't reply with the same game code
ldrb r1, [r0, 0x3]
strb r1, [r0, 0xB]
adr r2, GcMbIntrHandler_82DEF44
@ Use the saved VCount value to provide another 8 bits of entropy for KeyB.
ldrb r1, [r0, GCMB_STRUCT_SAVEDVCOUNT]
strb r1, [r0, GCMB_STRUCT_KEYB + 3]
adr r2, GcMbIntrHandler_ReceiveKeyA
b GameCubeMultiBoot_SetInterruptHandler
.align 2, 0
GcMbIntrHandler_82DEF44: @ 82DEF44
GcMbIntrHandler_ReceiveKeyA: @ 82DEF44
lsrs r1, 1 @ is receive complete?
bcc GcMbIntrHandler_Stop @ branch if not
ldr r1, [r3, OFFSET_REG_JOY_RECV - 0x120]
@ make sure top 8 bits of the received value is the KeyA magic number, stop if KeyA is invalid
lsrs r2, r1, 24
cmp r2, 0xDD
cmp r2, GCMB_MAGIC_KEYA
bne GcMbIntrHandler_Stop
str r1, [r0, 0x4]
ldrb r1, [r0, 0x1]
strb r1, [r0, 0xA]
@ save received KeyA
str r1, [r0, GCMB_STRUCT_KEYA]
@ use the second GameCubeMultiBoot_Main() counter as another 8 bits of entropy for KeyB
ldrb r1, [r0, GCMB_STRUCT_COUNTER2]
strb r1, [r0, GCMB_STRUCT_KEYB + 2]
movs r2, 0
movs r3, 0
ldr r1, [r0, 0x8]
ldr r1, [r0, GCMB_STRUCT_KEYB]
lsrs r1, 8
_082DEF5E:
@ make sure KeyB is valid (other side of the link is supposed to check KeyB too), if it's not then change the byte that was just set so it is
GameCubeMultiBoot_KeyBCheckLoop:
lsrs r1, 1
adcs r2, r3
cmp r1, 0
bne _082DEF5E
bne GameCubeMultiBoot_KeyBCheckLoop
cmp r2, 0xE
bgt _082DEF70
bgt GameCubeMultiBoot_KeyBSaveNewByte
cmp r2, 0x7
bge _082DEF72
bge GameCubeMultiBoot_KeyBCheckEnd
movs r1, 0xFF
_082DEF70:
strb r1, [r0, 0xA]
_082DEF72:
ldr r1, [r0, 0x8]
adds r1, 0xEE
GameCubeMultiBoot_KeyBSaveNewByte:
strb r1, [r0, GCMB_STRUCT_KEYB + 2]
GameCubeMultiBoot_KeyBCheckEnd:
@ add in the KeyB magic number and send off KeyB
ldr r1, [r0, GCMB_STRUCT_KEYB]
adds r1, GCMB_MAGIC_KEYB
ldr r3, pool_SerialRegs
str r1, [r3, OFFSET_REG_JOY_TRANS - 0x120]
movs r1, 0x30
strh r1, [r3, OFFSET_REG_JOYSTAT - 0x120]
adr r2, GcMbIntrHandler_82DEF84
@ set new interrupt handler
adr r2, GcMbIntrHandler_CheckKeyBSent
b GameCubeMultiBoot_SetInterruptHandler
.align 2, 0
GcMbIntrHandler_82DEF84: @ 82DEF84
GcMbIntrHandler_CheckKeyBSent: @ 82DEF84
lsls r1, 31
bcc GcMbIntrHandler_Stop @ stop if send failed
bmi _082DEF94 @ branch if receive is complete
adr r2, GcMbIntrHandler_82DEF90
bmi GameCubeMultiBoot_CheckImageSizeResponse @ branch if receive is complete
adr r2, GcMbIntrHandler_CheckImageSizeResponse
b GameCubeMultiBoot_SetInterruptHandler
.align 2, 0
GcMbIntrHandler_82DEF90: @ 82DEF90
GcMbIntrHandler_CheckImageSizeResponse: @ 82DEF90
lsrs r1, 1 @ is receive complete?
bcc GcMbIntrHandler_Stop @ branch if not
_082DEF94:
GameCubeMultiBoot_CheckImageSizeResponse:
ldr r1, [r3, OFFSET_REG_JOY_RECV - 0x120]
ldr r2, _082DF034
ldr r2, GameCubeMultiBoot_MaximumImageSizeUInt32s
cmp r1, r2
bhs GcMbIntrHandler_Stop
adds r1, 0x1
adds r1, r1
strh r1, [r0, 0x12]
ldrb r1, [r0, 0x2]
strh r1, [r0, GCMB_STRUCT_IMAGE_SIZE]
ldrb r1, [r0, GCMB_STRUCT_MBPROGRESS]
cmp r1, 0
_082DEFA6:
GcMbIntrHandler_StopIfNotEqual:
bne GcMbIntrHandler_Stop
ldr r1, pool_MultiBootLoadAddr
str r1, [r0, #GCMB_STRUCT_BASE_DEST_PTR]
str r1, [r0, #GCMB_STRUCT_CUR_DEST_PTR]
adr r2, GcMbIntrHandler_82DEFB4
str r1, [r0, GCMB_STRUCT_BASE_DEST_PTR]
str r1, [r0, GCMB_STRUCT_CUR_DEST_PTR]
adr r2, GcMbIntrHandler_CheckImageResponse
b GameCubeMultiBoot_SetInterruptHandler
.align 2, 0
GcMbIntrHandler_82DEFB4: @ 82DEFB4
GcMbIntrHandler_CheckImageResponse: @ 82DEFB4
lsrs r1, 1 @ is receive complete?
bcc GcMbIntrHandler_Stop @ branch if not
ldr r2, [r0, #GCMB_STRUCT_CUR_DEST_PTR]
ldr r2, [r0, GCMB_STRUCT_CUR_DEST_PTR]
movs r1, 0x4
ands r1, r2
adds r1, 0x8
lsls r1, 2
strh r1, [r3, OFFSET_REG_JOYSTAT - 0x120]
@ get the recieved uint32
ldr r1, [r3, OFFSET_REG_JOY_RECV - 0x120]
@ put it in the current destination pointer and advance that pointer
stm r2!, {r1}
str r2, [r0, #GCMB_STRUCT_CUR_DEST_PTR]
ldrh r1, [r0, 0x12]
@ save off the advanced pointer
str r2, [r0, GCMB_STRUCT_CUR_DEST_PTR]
@ decrease the image size (in uint32s)
ldrh r1, [r0, GCMB_STRUCT_IMAGE_SIZE]
subs r1, 0x1
strh r1, [r0, 0x12]
strh r1, [r0, GCMB_STRUCT_IMAGE_SIZE]
@ branch away if the transfer is not yet complete
bne GameCubeMultiBoot_ReadVCount
_082DEFD2:
ldrb r1, [r0, 0x1]
GcMbIntrHandler_SendCounter2:
@ send counter2 with magic number
ldrb r1, [r0, GCMB_STRUCT_COUNTER2]
lsls r1, 8
adds r1, 0xCC
adds r1, GCMB_MAGIC_COUNTER2
str r1, [r3, OFFSET_REG_JOY_TRANS - 0x120]
adr r2, _082DEFE0
adr r2, GcMbIntrHandler_CheckCounter2Sent
b GameCubeMultiBoot_SetInterruptHandler
.align 2, 0
_082DEFE0:
GcMbIntrHandler_CheckCounter2Sent:
lsls r1, 31
_082DEFE2:
bcc GcMbIntrHandler_Stop
ldr r1, [r0, 0x1C]
GcMbIntrHandler_StopIfSendFailed:
bcc GcMbIntrHandler_Stop @ stop if send failed
@ if KeyC derivation value has not yet been generated, send Counter2 again, otherwise, send KeyC derivation
ldr r1, [r0, GCMB_STRUCT_KEYC_DERIVATION]
cmp r1, 0
beq _082DEFD2
beq GcMbIntrHandler_SendCounter2
str r1, [r3, OFFSET_REG_JOY_TRANS - 0x120]
adr r2, GcMbIntrHandler_82DEFF0
adr r2, GcMbIntrHandler_CheckKeyCDerivationSent
b GameCubeMultiBoot_SetInterruptHandler
.align 2, 0
GcMbIntrHandler_82DEFF0: @ 82DEFF0
GcMbIntrHandler_CheckKeyCDerivationSent: @ 82DEFF0
lsls r1, 31
bcc _082DEFE2 @ branch if send failed
bmi _082DF000 @ branch if receive is complete
adr r2, GcMbIntrHandler_82DEFFC
bcc GcMbIntrHandler_StopIfSendFailed @ branch if send failed
bmi GameCubeMultiBoot_CheckBootKeyResponse @ branch if receive is complete
adr r2, GcMbIntrHandler_CheckBootKeyResponse
b GameCubeMultiBoot_SetInterruptHandler
.align 2, 0
GcMbIntrHandler_82DEFFC: @ 82DEFFC
GcMbIntrHandler_CheckBootKeyResponse: @ 82DEFFC
lsrs r1, 1 @ is receive complete?
bcc _082DEFE2 @ branch if not
bcc GcMbIntrHandler_StopIfSendFailed @ branch if not
_082DF000:
GameCubeMultiBoot_CheckBootKeyResponse:
ldr r1, [r3, OFFSET_REG_JOY_RECV - 0x120]
@ make sure received boot key contains expected magic number, stop if not
lsrs r2, r1, 24
cmp r2, 0xBB
bne _082DEFA6
strh r1, [r0, 0x10]
adr r2, GcMbIntrHandler_82DF010
cmp r2, GCMB_MAGIC_BOOTKEY
bne GcMbIntrHandler_StopIfNotEqual
@ save received bootkey to be checked in GameCubeMultiBoot_Main()
strh r1, [r0, GCMB_STRUCT_BOOT_KEY]
@ stop if anything more gets sent
adr r2, GcMbIntrHandler_StopUnconditionally
b GameCubeMultiBoot_SetInterruptHandler
.align 2, 0
GcMbIntrHandler_82DF010: @ 82DF010
GcMbIntrHandler_StopUnconditionally: @ 82DF010
b GcMbIntrHandler_Stop
thumb_func_end GameCubeMultiBoot_HandleSerialInterrupt
@ -500,11 +591,11 @@ GameCubeMultiBoot_Quit: @ 82DF012
ldr r3, pool_InterruptRegs
@ Save IME register.
ldrh r2, [r3, #OFFSET_REG_IME - 0x200]
ldrh r2, [r3, OFFSET_REG_IME - 0x200]
@ Disable interrupts.
movs r1, 0
strh r1, [r3, #OFFSET_REG_IME - 0x200]
strh r1, [r3, OFFSET_REG_IME - 0x200]
ldr r3, pool_SerialRegs
@ -528,14 +619,14 @@ GameCubeMultiBoot_Quit: @ 82DF012
strh r1, [r3, OFFSET_REG_IE - 0x200]
@ Restore IME register.
strh r2, [r3, #OFFSET_REG_IME - 0x200]
strh r2, [r3, OFFSET_REG_IME - 0x200]
bx lr
thumb_func_end GameCubeMultiBoot_Quit
.align 2, 0
_082DF034: .4byte 0x4000
GameCubeMultiBoot_MaximumImageSizeUInt32s: .4byte 0x4000
pool_InterruptRegs: .4byte REG_BASE + 0x200