summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libgcnmultiboot.s419
1 files changed, 255 insertions, 164 deletions
diff --git a/src/libgcnmultiboot.s b/src/libgcnmultiboot.s
index dbf70ccf8..5ecc7d2f9 100644
--- a/src/libgcnmultiboot.s
+++ b/src/libgcnmultiboot.s
@@ -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]
+ @ If there is no interrupt handler, skip counter manipulation
+ ldr r1, [r0, GCMB_STRUCT_SERIAL_INTR_HANDLER]
+ cmp r1, 0
+ beq GameCubeMultiBoot_Main_SkipCounters
+ @ Increment the second counter
+ ldrb r1, [r0, GCMB_STRUCT_COUNTER2]
adds r1, 0x1
- strb r1, [r0, 0x1]
- ldrb r1, [r0, 0x2]
- cmp r1, 0x2
- beq _082DEDF4
+ 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]
+ ldrh r2, [r3, OFFSET_REG_IME - 0x200]
+ @ Disable all interrupts
movs r1, 0
- strh r1, [r3, #OFFSET_REG_IME - 0x200]
- ldrb r1, [r0]
+ 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 _082DEDA8
+ bgt GameCubeMultiBoot_Main_SkipCounter1Inc
adds r1, 0x1
- strb r1, [r0]
-_082DEDA8:
- strh r2, [r3, #OFFSET_REG_IME - 0x200]
-_082DEDAA:
+ 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
- ldrb r1, [r0, 0x2]
- cmp r1, 0
- bne _082DEDF6
- ldr r1, [r0, #GCMB_STRUCT_CUR_DEST_PTR]
- ldr r2, [r0, #GCMB_STRUCT_BASE_DEST_PTR]
+ @ 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