mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-11-16 19:47:35 +01:00
Sync libgcnmultiboot
This commit is contained in:
parent
c98fbb5ca6
commit
dc44548e43
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user