diff options
Diffstat (limited to 'asm/libgcnmultiboot.s')
-rw-r--r-- | asm/libgcnmultiboot.s | 641 |
1 files changed, 0 insertions, 641 deletions
diff --git a/asm/libgcnmultiboot.s b/asm/libgcnmultiboot.s deleted file mode 100644 index 91bc1890c..000000000 --- a/asm/libgcnmultiboot.s +++ /dev/null @@ -1,641 +0,0 @@ -@ This library can be used to download and execute a multi-boot image from -@ a GameCube using the JOY Bus protocol over the link cable. - - .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, 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 - - .text - - thumb_func_start GameCubeMultiBoot_Hash -GameCubeMultiBoot_Hash: @ 81DCB38 - push {r4,lr} - ldr r4, pool_HashVal - eors r3, r1 - movs r2, 0x20 - -GameCubeMultiBoot_Hash_Loop: - lsrs r3, 1 - bcc GameCubeMultiBoot_Hash_SkipEor - - eors r3, r4 - -GameCubeMultiBoot_Hash_SkipEor: - subs r2, 0x1 - bne GameCubeMultiBoot_Hash_Loop - - pop {r4,pc} - thumb_func_end GameCubeMultiBoot_Hash - - thumb_func_start GameCubeMultiBoot_Main -@ void GameCubeMultiBoot_Main(struct GameCubeMultiBoot *mb)@ -GameCubeMultiBoot_Main: @ 81DCB4C - @ 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, 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 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, ROM_HEADER_NINTENDO_LOGO_LENGTH - adds r2, ROM_HEADER_NINTENDO_LOGO_OFFSET - ldr r4, pool_NintendoLogo -GameCubeMultiBoot_Main_LogoCmpLoop: - ldm r2!, {r5} - ldm r4!, {r6} - cmp r5, r6 - bne GameCubeMultiBoot_Main_LogoCmpEnd - subs r1, 0x4 - bne GameCubeMultiBoot_Main_LogoCmpLoop - ldm r2!, {r5} - ldm r4!, {r6} - eors r5, r6 - 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 - @ 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, 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, GCMB_STRUCT_SESSION_KEY] -GameCubeMultiBoot_Main_Return: - bx lr -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, GCMB_STRUCT_HASH_VAL] - push {r4-r7} - ldr r4, [r0, GCMB_STRUCT_BASE_DEST_PTR] - ldr r5, pool_Kawa - ldr r6, [r0, GCMB_STRUCT_SESSION_KEY] - ldr r7, pool_HashVal -GameCubeMultiBoot_Main_ImageDecryptHashLoop: - @ If there's no more data, break out of the loop - cmp r4, r12 - 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 -GameCubeMultiBoot_Main_HashLoop: - lsrs r3, 1 - bcc GameCubeMultiBoot_Main_HashSkipEor - eors r3, r7 -GameCubeMultiBoot_Main_HashSkipEor: - subs r2, 0x1 - bne GameCubeMultiBoot_Main_HashLoop - @ Advance the sessionkey with the usual algorithm: sessionkey = (sessionkey * 0x6177614b) + 1 - muls r6, r5 - adds r6, 0x1 - 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, 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 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 - @ 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, 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 - @ 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 -GameCubeMultiBoot_Main_GenerateKeyC: - @ Save off LR so it doesn't get clobbered by the upcoming function call - mov r12, lr - @ KeyC = (SavedVCount << 24) - 1 - ldrb r1, [r0, GCMB_STRUCT_SAVEDVCOUNT] - lsls r1, 24 - subs r1, 0x1 - 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 - @ 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 -GameCubeMultiBoot_Main_Return2: - bx lr - thumb_func_end GameCubeMultiBoot_Main - - .align 2, 0 - -pool_HashVal: .4byte 0xa1c1 - -pool_Kawa: .ascii "Kawa" @ name of BIOS developer - -pool_NintendoLogo: .4byte RomHeaderNintendoLogo - - thumb_func_start GameCubeMultiBoot_ExecuteProgram -@ void GameCubeMultiBoot_ExecuteProgram(struct GameCubeMultiBoot *mb)@ -GameCubeMultiBoot_ExecuteProgram: @ 81DCC4C - @ 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] - @ 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 -GameCubeMultiBoot_ExecuteProgram_Fail: - bx lr - thumb_func_end GameCubeMultiBoot_ExecuteProgram - - thumb_func_start GameCubeMultiBoot_Init -@ void GameCubeMultiBoot_Init(struct GameCubeMultiBoot *mb)@ -GameCubeMultiBoot_Init: @ 81DCC60 - ldr r3, pool_InterruptRegs - -@ Save IME register. - ldrh r2, [r3, OFFSET_REG_IME - 0x200] - -@ Disable interrupts. - movs r1, 0 - 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] - - ldrb r3, [r0, 0x3] - push {r3} - ldrb r3, [r0, 0x1] - push {r0,r3} - - adds r3, r0, 0 - adds r3, GCMB_STRUCT_BASE_DEST_PTR - -@ clear all but the last 3 fields of the struct -GameCubeMultiBoot_Init_ClearStructLoop: - stm r0!, {r1} - cmp r0, r3 - blo GameCubeMultiBoot_Init_ClearStructLoop - - pop {r0,r3} - lsrs r3, 1 - strb r3, [r0, 0x3] - pop {r3} - strb r3, [r0, 0x1] - - ldr r3, pool_SerialRegs - -@ Turn off JOY Bus mode. - lsls r0, r3, 10 - strh r0, [r3, OFFSET_REG_RCNT - 0x120] - -@ Turn on JOY Bus mode. - movs r0, 0xC0 - lsls r0, 8 - strh r0, [r3, OFFSET_REG_RCNT - 0x120] - -@ Init JOY Bus registers. - movs r0, 0x47 - strh r0, [r3, OFFSET_REG_JOYCNT - 0x120] - strh r1, [r3, OFFSET_REG_JOYSTAT - 0x120] - - ldr r3, pool_InterruptRegs - -@ Acknowledge serial interrupt. - movs r0, INTR_FLAG_SERIAL - strh r0, [r3, OFFSET_REG_IF - 0x200] - -@ Enable serial interrupt. - ldrh r1, [r3, OFFSET_REG_IE - 0x200] - orrs r1, r0 - strh r1, [r3, OFFSET_REG_IE - 0x200] - -@ Restore IME register. - strh r2, [r3, OFFSET_REG_IME - 0x200] - - bx lr - thumb_func_end GameCubeMultiBoot_Init - - non_word_aligned_thumb_func_start GameCubeMultiBoot_HandleSerialInterrupt -@ void GameCubeMultiBoot_HandleSerialInterrupt(struct GameCubeMultiBoot *mb)@ -GameCubeMultiBoot_HandleSerialInterrupt: @ 81DCCAA - ldr r3, pool_SerialRegs - -@ Acknowledge reset/receive/send flags. - ldrh r1, [r3, OFFSET_REG_JOYCNT - 0x120] - strh r1, [r3, OFFSET_REG_JOYCNT - 0x120] - - movs r2, 0 - strb r2, [r0] - - ldr r2, [r0, GCMB_STRUCT_SERIAL_INTR_HANDLER] - cmp r2, 0 - beq GameCubeMultiBoot_HandleSerialInterruptDone - - lsrs r1, 1 @ was a device reset command received? - bcs GameCubeMultiBoot_BeginHandshake @ branch if so - - mov pc, r2 - - .align 2, 0 - -@ Zero the status and the interrupt handler pointer. -@ Commands from the GameCube will not be processed after this is executed -@ unless GameCubeMultiBoot_Init() is called again. -GcMbIntrHandler_Stop: - movs r2, 0 - strh r2, [r3, OFFSET_REG_JOYSTAT - 0x120] - -GameCubeMultiBoot_SetInterruptHandler: - str r2, [r0, GCMB_STRUCT_SERIAL_INTR_HANDLER] - -GameCubeMultiBoot_ReadVCount: - ldr r3, pool_RegDispstat - ldrh r1, [r3, OFFSET_REG_VCOUNT - OFFSET_REG_DISPSTAT] - strb r1, [r0, 0x3] - -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] - @ 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] - @ Set the new interrupt handler. - adr r2, GcMbIntrHandler_CheckGameCodeSent - b GameCubeMultiBoot_SetInterruptHandler - - .align 2, 0 - -GcMbIntrHandler_CheckGameCodeSent: @ 81DCCEC - lsls r1, 31 - bcc GcMbIntrHandler_Stop @ stop if send failed - bmi GameCubeMultiBoot_CheckHandshakeResponse @ branch if receive is complete - -@ If the response hasn't been fully received yet, -@ check again upon the next interrupt. - adr r2, GcMbIntrHandler_CheckHandshakeResponse - b GameCubeMultiBoot_SetInterruptHandler - - .align 2, 0 - -GcMbIntrHandler_CheckHandshakeResponse: @ 81DCCF8 - lsrs r1, 1 @ is receive complete? - bcc GcMbIntrHandler_Stop @ stop if not - -GameCubeMultiBoot_CheckHandshakeResponse: - ldr r1, [r3, OFFSET_REG_JOY_RECV - 0x120] - ldr r2, pool_RubyUSAGameCode - cmp r1, r2 - bne GcMbIntrHandler_Stop @ stop if the GameCube didn't reply with the same game code - @ 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_ReceiveKeyA: @ 81DCD0C - 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, GCMB_MAGIC_KEYA - bne GcMbIntrHandler_Stop - @ 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, GCMB_STRUCT_KEYB] - lsrs r1, 8 - @ 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 GameCubeMultiBoot_KeyBCheckLoop - cmp r2, 0xE - bgt GameCubeMultiBoot_KeyBSaveNewByte - cmp r2, 0x7 - bge GameCubeMultiBoot_KeyBCheckEnd - movs r1, 0xFF -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] - @ set new interrupt handler - adr r2, GcMbIntrHandler_CheckKeyBSent - b GameCubeMultiBoot_SetInterruptHandler - - .align 2, 0 - -GcMbIntrHandler_CheckKeyBSent: @ 81DCD4C - lsls r1, 31 - bcc GcMbIntrHandler_Stop @ stop if send failed - bmi GameCubeMultiBoot_CheckImageSizeResponse @ branch if receive is complete - adr r2, GcMbIntrHandler_CheckImageSizeResponse - b GameCubeMultiBoot_SetInterruptHandler - - .align 2, 0 - -GcMbIntrHandler_CheckImageSizeResponse: @ 81DCD58 - lsrs r1, 1 @ is receive complete? - bcc GcMbIntrHandler_Stop @ branch if not -GameCubeMultiBoot_CheckImageSizeResponse: - ldr r1, [r3, OFFSET_REG_JOY_RECV - 0x120] - ldr r2, GameCubeMultiBoot_MaximumImageSizeUInt32s - cmp r1, r2 - bhs GcMbIntrHandler_Stop - adds r1, 0x1 - adds r1, r1 - strh r1, [r0, GCMB_STRUCT_IMAGE_SIZE] - ldrb r1, [r0, GCMB_STRUCT_MBPROGRESS] - cmp r1, 0 -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_CheckImageResponse - b GameCubeMultiBoot_SetInterruptHandler - - .align 2, 0 - -GcMbIntrHandler_CheckImageResponse: @ 81DCD7C - lsrs r1, 1 @ is receive complete? - bcc GcMbIntrHandler_Stop @ branch if not - 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} - @ 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, GCMB_STRUCT_IMAGE_SIZE] - @ branch away if the transfer is not yet complete - bne GameCubeMultiBoot_ReadVCount - -GcMbIntrHandler_SendCounter2: - @ send counter2 with magic number - ldrb r1, [r0, GCMB_STRUCT_COUNTER2] - lsls r1, 8 - adds r1, GCMB_MAGIC_COUNTER2 - str r1, [r3, OFFSET_REG_JOY_TRANS - 0x120] - adr r2, GcMbIntrHandler_CheckCounter2Sent - b GameCubeMultiBoot_SetInterruptHandler - - .align 2, 0 - -GcMbIntrHandler_CheckCounter2Sent: - lsls r1, 31 - -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 GcMbIntrHandler_SendCounter2 - str r1, [r3, OFFSET_REG_JOY_TRANS - 0x120] - adr r2, GcMbIntrHandler_CheckKeyCDerivationSent - b GameCubeMultiBoot_SetInterruptHandler - - .align 2, 0 - -GcMbIntrHandler_CheckKeyCDerivationSent: @ 81DCDB8 - lsls r1, 31 - 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_CheckBootKeyResponse: @ 81DCDC4 - lsrs r1, 1 @ is receive complete? - bcc GcMbIntrHandler_StopIfSendFailed @ branch if not - -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, 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_StopUnconditionally: @ 81DCDD8 - b GcMbIntrHandler_Stop - - thumb_func_end GameCubeMultiBoot_HandleSerialInterrupt - - non_word_aligned_thumb_func_start GameCubeMultiBoot_Quit -@ void GameCubeMultiBoot_Quit()@ -GameCubeMultiBoot_Quit: @ 81DCDDA - ldr r3, pool_InterruptRegs - -@ Save IME register. - ldrh r2, [r3, OFFSET_REG_IME - 0x200] - -@ Disable interrupts. - movs r1, 0 - strh r1, [r3, OFFSET_REG_IME - 0x200] - - ldr r3, pool_SerialRegs - -@ Acknowledge all JOYCNT flags. - movs r0, 0x7 - strh r0, [r3, OFFSET_REG_JOYCNT - 0x120] - -@ Turn off JOY Bus mode. - lsls r0, r3, 10 - strh r0, [r3, OFFSET_REG_RCNT - 0x120] @ store 0x8000 - - ldr r3, pool_InterruptRegs - -@ Acknowledge serial interrupt. - movs r0, INTR_FLAG_SERIAL - strh r0, [r3, OFFSET_REG_IF - 0x200] - -@ Disable serial interrupt. - ldrh r1, [r3, OFFSET_REG_IE - 0x200] - bics r1, r0 - strh r1, [r3, OFFSET_REG_IE - 0x200] - -@ Restore IME register. - strh r2, [r3, OFFSET_REG_IME - 0x200] - - bx lr - thumb_func_end GameCubeMultiBoot_Quit - - .align 2, 0 - -GameCubeMultiBoot_MaximumImageSizeUInt32s: .4byte 0x00004000 - -pool_InterruptRegs: .4byte REG_BASE + 0x200 - -pool_SerialRegs: .4byte REG_BASE + 0x120 - -pool_RegDispstat: .4byte REG_DISPSTAT - -pool_RubyUSAGameCode: .ascii "AXVE" - -pool_MultiBootLoadAddr: .4byte EWRAM_START - - .align 2, 0 @ Don't pad with nop. |