2016-09-03 04:51:16 +02:00
@ 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.
2015-11-27 10:33:50 +01:00
2016-11-01 16:29:13 +01:00
.include " asm/ m a c r o s . i n c "
.include " constants/ c o n s t a n t s . i n c "
2016-09-03 08:11:29 +02:00
2021-11-03 01:28:17 +01:00
.equiv GCMB_ S T R U C T _ C O U N T E R 1 , 0 x00
.equiv GCMB_ S T R U C T _ C O U N T E R 2 , 0 x01
.equiv GCMB_ S T R U C T _ M B P R O G R E S S , 0 x02
.equiv GCMB_ S T R U C T _ S A V E D V C O U N T , 0 x03
.equiv GCMB_ S T R U C T _ K E Y A , 0 x04
.equiv GCMB_ S T R U C T _ K E Y B , 0 x08
.equiv GCMB_ S T R U C T _ K E Y C , 0 x0 C
.equiv GCMB_ S T R U C T _ B O O T _ K E Y , 0 x10
.equiv GCMB_ S T R U C T _ I M A G E _ S I Z E , 0 x12
.equiv GCMB_ S T R U C T _ S E S S I O N _ K E Y , 0 x14
.equiv GCMB_ S T R U C T _ H A S H _ V A L , 0 x18
.equiv GCMB_ S T R U C T _ K E Y C _ D E R I V A T I O N , 0 x1 C
2016-09-03 08:11:29 +02:00
.equiv GCMB_ S T R U C T _ B A S E _ D E S T _ P T R , 0 x20
.equiv GCMB_ S T R U C T _ C U R _ D E S T _ P T R , 0 x24
.equiv GCMB_ S T R U C T _ S E R I A L _ I N T R _ H A N D L E R , 0 x28
2021-11-03 01:28:17 +01:00
.equiv ROM_ H E A D E R _ N I N T E N D O _ L O G O _ O F F S E T , 0 x04
.equiv ROM_ H E A D E R _ N I N T E N D O _ L O G O _ L E N G T H , 0 x98
.equiv ROM_ H E A D E R _ N I N T E N D O _ L O G O _ E N D , 0 x A 0
.equiv MBPROGRESS_ N O N E , 0 x00
.equiv MBPROGRESS_ L O G O _ C O R R E C T , 0 x01
.equiv MBPROGRESS_ R E A D Y _ T O _ B O O T , 0 x02
.equiv GCMB_ M A G I C _ B O O T K E Y _ H A S H V A L , 0 x B B
.equiv GCMB_ M A G I C _ B O O T K E Y , 0 x B B
.equiv GCMB_ M A G I C _ C O U N T E R 2 , 0 x C C
.equiv GCMB_ M A G I C _ K E Y A , 0 x D D
.equiv GCMB_ M A G I C _ K E Y B , 0 x E E
.equiv GCMB_ M A G I C _ K E Y C D E R I V A T I O N , 0 x F F
2016-09-03 08:11:29 +02:00
.syntax unified
.text
2015-11-27 10:33:50 +01:00
thumb_ f u n c _ s t a r t G a m e C u b e M u l t i B o o t _ H a s h
2021-12-22 02:46:59 +01:00
GameCubeMultiBoot_Hash :
2015-10-06 16:00:49 +02:00
push { r4 ,l r }
2015-11-27 10:33:50 +01:00
ldr r4 , p o o l _ H a s h V a l
2015-10-06 16:00:49 +02:00
eors r3 , r1
movs r2 , 0 x20
2015-11-27 10:33:50 +01:00
2016-09-03 08:11:29 +02:00
GameCubeMultiBoot_Hash_Loop :
2021-11-03 01:28:17 +01:00
lsrs r3 , 1
2016-09-03 08:11:29 +02:00
bcc G a m e C u b e M u l t i B o o t _ H a s h _ S k i p E o r
2015-11-27 10:33:50 +01:00
2015-10-06 16:00:49 +02:00
eors r3 , r4
2015-11-27 10:33:50 +01:00
2016-09-03 08:11:29 +02:00
GameCubeMultiBoot_Hash_SkipEor :
2015-10-06 16:00:49 +02:00
subs r2 , 0 x1
2016-09-03 08:11:29 +02:00
bne G a m e C u b e M u l t i B o o t _ H a s h _ L o o p
2015-11-27 10:33:50 +01:00
2015-10-06 16:00:49 +02:00
pop { r4 ,p c }
2015-11-27 10:33:50 +01:00
thumb_ f u n c _ e n d G a m e C u b e M u l t i B o o t _ H a s h
2015-10-06 16:00:49 +02:00
2015-11-27 10:33:50 +01:00
thumb_ f u n c _ s t a r t G a m e C u b e M u l t i B o o t _ M a i n
2016-09-03 04:51:16 +02:00
@ void GameCubeMultiBoot_Main(struct GameCubeMultiBoot *mb);
2021-12-22 02:46:59 +01:00
GameCubeMultiBoot_Main :
2021-11-03 01:28:17 +01:00
@ If there is no interrupt handler, skip counter manipulation
ldr r1 , [ r0 , G C M B _ S T R U C T _ S E R I A L _ I N T R _ H A N D L E R ]
cmp r1 , 0
beq G a m e C u b e M u l t i B o o t _ M a i n _ S k i p C o u n t e r s
@ Increment the second counter
ldrb r1 , [ r0 , G C M B _ S T R U C T _ C O U N T E R 2 ]
2015-10-06 16:00:49 +02:00
adds r1 , 0 x1
2021-11-03 01:28:17 +01:00
strb r1 , [ r0 , G C M B _ S T R U C T _ C O U N T E R 2 ]
@ If there is nothing more to do, bail out
ldrb r1 , [ r0 , G C M B _ S T R U C T _ M B P R O G R E S S ]
cmp r1 , M B P R O G R E S S _ R E A D Y _ T O _ B O O T
beq G a m e C u b e M u l t i B o o t _ M a i n _ R e t u r n
@ Save current interrupt master register value
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ I n t e r r u p t R e g s
2021-11-03 01:28:17 +01:00
ldrh r2 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
@ Disable all interrupts
2015-10-06 16:00:49 +02:00
movs r1 , 0
2021-11-03 01:28:17 +01:00
strh r1 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
@ Increment the first counter, if it's less than or equal to 10.
ldrb r1 , [ r0 , G C M B _ S T R U C T _ C O U N T E R 1 ]
2015-10-06 16:00:49 +02:00
cmp r1 , 0 x A
2021-11-03 01:28:17 +01:00
bgt G a m e C u b e M u l t i B o o t _ M a i n _ S k i p C o u n t e r1 I n c
2015-10-06 16:00:49 +02:00
adds r1 , 0 x1
2021-11-03 01:28:17 +01:00
strb r1 , [ r0 , G C M B _ S T R U C T _ C O U N T E R 1 ]
GameCubeMultiBoot_Main_SkipCounter1Inc :
@ Load the saved interrupt master register value (re-enables interrupts if they were enabled before)
strh r2 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
GameCubeMultiBoot_Main_SkipCounters :
@ Initialise multiboot structures if required
2015-11-27 10:33:50 +01:00
bcs G a m e C u b e M u l t i B o o t _ I n i t
2021-11-03 01:28:17 +01:00
@ Skip this section (check Nintendo logo) if the check has already passed
ldrb r1 , [ r0 , G C M B _ S T R U C T _ M B P R O G R E S S ]
cmp r1 , M B P R O G R E S S _ N O N E
bne G a m e C u b e M u l t i B o o t _ M a i n _ S k i p L o g o C h e c k
@ Bail out if no multiboot image data has been transferred yet
ldr r1 , [ r0 , G C M B _ S T R U C T _ C U R _ D E S T _ P T R ]
ldr r2 , [ r0 , G C M B _ S T R U C T _ B A S E _ D E S T _ P T R ]
2015-10-06 16:00:49 +02:00
subs r1 , r2
2021-11-03 01:28:17 +01:00
beq G a m e C u b e M u l t i B o o t _ M a i n _ R e t u r n 2
@ Also bail out if not enough data has been transferred
cmp r1 , R O M _ H E A D E R _ N I N T E N D O _ L O G O _ E N D
bcc G a m e C u b e M u l t i B o o t _ M a i n _ R e t u r n 2
@ Compare the Nintendo logo of the transferred multiboot image header, with the one in the ROM image of the inserted cart
2015-10-06 16:00:49 +02:00
push { r4 - r6 }
2021-11-03 01:28:17 +01:00
movs r1 , R O M _ H E A D E R _ N I N T E N D O _ L O G O _ L E N G T H
adds r2 , R O M _ H E A D E R _ N I N T E N D O _ L O G O _ O F F S E T
2015-11-27 10:33:50 +01:00
ldr r4 , p o o l _ N i n t e n d o L o g o
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_Main_LogoCmpLoop :
2015-10-06 16:00:49 +02:00
ldm r2 ! , { r5 }
ldm r4 ! , { r6 }
cmp r5 , r6
2021-11-03 01:28:17 +01:00
bne G a m e C u b e M u l t i B o o t _ M a i n _ L o g o C m p E n d
2015-10-06 16:00:49 +02:00
subs r1 , 0 x4
2021-11-03 01:28:17 +01:00
bne G a m e C u b e M u l t i B o o t _ M a i n _ L o g o C m p L o o p
2015-10-06 16:00:49 +02:00
ldm r2 ! , { r5 }
ldm r4 ! , { r6 }
eors r5 , r6
2021-11-03 01:28:17 +01:00
lsrs r5 , 8
str r2 , [ r0 , G C M B _ S T R U C T _ B A S E _ D E S T _ P T R ]
GameCubeMultiBoot_Main_LogoCmpEnd :
2015-10-06 16:00:49 +02:00
pop { r4 - r6 }
2021-11-03 01:28:17 +01:00
@ Throw everything away if the logo data didn't match
2015-11-27 10:33:50 +01:00
bne G a m e C u b e M u l t i B o o t _ I n i t
2021-11-03 01:28:17 +01:00
@ Logo matched, set the relevent multiboot progress bit
movs r1 , M B P R O G R E S S _ L O G O _ C O R R E C T
strb r1 , [ r0 , G C M B _ S T R U C T _ M B P R O G R E S S ]
@ XOR together KeyA and KeyB to get the initial multiboot image checksum value
ldr r1 , [ r0 , G C M B _ S T R U C T _ K E Y A ]
ldr r2 , [ r0 , G C M B _ S T R U C T _ K E Y B ]
2015-10-06 16:00:49 +02:00
eors r1 , r2
2021-11-03 01:28:17 +01:00
str r1 , [ r0 , G C M B _ S T R U C T _ H A S H _ V A L ]
@ ...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
2015-11-27 10:33:50 +01:00
ldr r2 , p o o l _ K a w a
2015-10-06 16:00:49 +02:00
muls r1 , r2
adds r1 , 0 x1
2021-11-03 01:28:17 +01:00
str r1 , [ r0 , G C M B _ S T R U C T _ S E S S I O N _ K E Y ]
GameCubeMultiBoot_Main_Return :
2015-10-06 16:00:49 +02:00
bx l r
2021-11-03 01:28:17 +01:00
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 , G C M B _ S T R U C T _ C U R _ D E S T _ P T R ]
2015-10-06 16:00:49 +02:00
mov r12 , r1
2021-11-03 01:28:17 +01:00
ldr r3 , [ r0 , G C M B _ S T R U C T _ H A S H _ V A L ]
2015-10-06 16:00:49 +02:00
push { r4 - r7 }
2021-11-03 01:28:17 +01:00
ldr r4 , [ r0 , G C M B _ S T R U C T _ B A S E _ D E S T _ P T R ]
2015-11-27 10:33:50 +01:00
ldr r5 , p o o l _ K a w a
2021-11-03 01:28:17 +01:00
ldr r6 , [ r0 , G C M B _ S T R U C T _ S E S S I O N _ K E Y ]
2015-11-27 10:33:50 +01:00
ldr r7 , p o o l _ H a s h V a l
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_Main_ImageDecryptHashLoop :
@ If there's no more data, break out of the loop
2015-10-06 16:00:49 +02:00
cmp r4 , r12
2021-11-03 01:28:17 +01:00
bcs G a m e C u b e M u l t i B o o t _ M a i n _ I m a g e D e c r y p t H a s h E n d
@ Get the next uint32
2015-10-06 16:00:49 +02:00
ldr r1 , [ r4 ]
2021-11-03 01:28:17 +01:00
@ Decrypt the ciphertext: plaintext = (ciphertext ^ sessionkey) + hashval
2015-10-06 16:00:49 +02:00
eors r1 , r6
adds r1 , r3
2021-11-03 01:28:17 +01:00
@ Save the current uint32 of plaintext and advance the pointer
2015-10-06 16:00:49 +02:00
stm r4 ! , { r1 }
2021-11-03 01:28:17 +01:00
@ Advance the hashval with this uint32 of plaintext -- this is the same code as GameCubeMultiBoot_Hash.
2015-10-06 16:00:49 +02:00
eors r3 , r1
movs r2 , 0 x20
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_Main_HashLoop :
lsrs r3 , 1
bcc G a m e C u b e M u l t i B o o t _ M a i n _ H a s h S k i p E o r
2015-10-06 16:00:49 +02:00
eors r3 , r7
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_Main_HashSkipEor :
2015-10-06 16:00:49 +02:00
subs r2 , 0 x1
2021-11-03 01:28:17 +01:00
bne G a m e C u b e M u l t i B o o t _ M a i n _ H a s h L o o p
@ Advance the sessionkey with the usual algorithm: sessionkey = (sessionkey * 0x6177614b) + 1
2015-10-06 16:00:49 +02:00
muls r6 , r5
adds r6 , 0 x1
2021-11-03 01:28:17 +01:00
b G a m e C u b e M u l t i B o o t _ M a i n _ I m a g e D e c r y p t H a s h L o o p
GameCubeMultiBoot_Main_ImageDecryptHashEnd :
@ Save the new pointer, sessionkey, hashval
str r4 , [ r0 , G C M B _ S T R U C T _ B A S E _ D E S T _ P T R ]
str r6 , [ r0 , G C M B _ S T R U C T _ S E S S I O N _ K E Y ]
2015-10-06 16:00:49 +02:00
pop { r4 - r7 }
2021-11-03 01:28:17 +01:00
str r3 , [ r0 , G C M B _ S T R U C T _ H A S H _ V A L ]
@ Bail out if the image size is unknown
ldrh r1 , [ r0 , G C M B _ S T R U C T _ I M A G E _ S I Z E ]
cmp r1 , 0
bne G a m e C u b e M u l t i B o o t _ M a i n _ R e t u r n 2
@ Bail out if no image data has been transferred
ldr r1 , [ r0 , G C M B _ S T R U C T _ C U R _ D E S T _ P T R ]
ldr r2 , [ r0 , G C M B _ S T R U C T _ B A S E _ D E S T _ P T R ]
2015-10-06 16:00:49 +02:00
cmp r1 , r2
2021-11-03 01:28:17 +01:00
bne G a m e C u b e M u l t i B o o t _ M a i n _ R e t u r n 2
@ If KeyC hasn't been generated yet, go generate it
ldr r1 , [ r0 , G C M B _ S T R U C T _ K E Y C ]
cmp r1 , 0
beq G a m e C u b e M u l t i B o o t _ M a i n _ G e n e r a t e K e y C
@ If the other side hasn't sent its boot key yet, bail out
ldrh r1 , [ r0 , G C M B _ S T R U C T _ B O O T _ K E Y ]
cmp r1 , 0
beq G a m e C u b e M u l t i B o o t _ M a i n _ R e t u r n
@ Save off LR so it doesn't get clobbered by the upcoming function call
2015-10-06 16:00:49 +02:00
mov r12 , l r
2021-11-03 01:28:17 +01:00
@ Generate the real boot key, which is the checksum of a hardcoded value and KeyC
movs r1 , G C M B _ M A G I C _ B O O T K E Y _ H A S H V A L
ldr r3 , [ r0 , G C M B _ S T R U C T _ K E Y C ]
2015-11-27 10:33:50 +01:00
bl G a m e C u b e M u l t i B o o t _ H a s h
2021-11-03 01:28:17 +01:00
ldrh r1 , [ r0 , G C M B _ S T R U C T _ B O O T _ K E Y ]
@ Restore the saved LR value
2015-10-06 16:00:49 +02:00
mov l r , r12
2021-11-03 01:28:17 +01:00
@ Compare the two boot keys (real and passed in), if they don't match then throw everything away
2015-10-06 16:00:49 +02:00
subs r1 , r3
2015-11-27 10:33:50 +01:00
bne G a m e C u b e M u l t i B o o t _ I n i t
2021-11-03 01:28:17 +01:00
@ The two boot keys matched, tell the caller that the image is ready to boot
movs r1 , M B P R O G R E S S _ R E A D Y _ T O _ B O O T
strb r1 , [ r0 , G C M B _ S T R U C T _ M B P R O G R E S S ]
@ Nothing more to do, return.
2015-10-06 16:00:49 +02:00
bx l r
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_Main_GenerateKeyC :
@ Save off LR so it doesn't get clobbered by the upcoming function call
2015-10-06 16:00:49 +02:00
mov r12 , l r
2021-11-03 01:28:17 +01:00
@ KeyC = (SavedVCount << 24) - 1
ldrb r1 , [ r0 , G C M B _ S T R U C T _ S A V E D V C O U N T ]
lsls r1 , 2 4
2015-10-06 16:00:49 +02:00
subs r1 , 0 x1
2021-11-03 01:28:17 +01:00
str r1 , [ r0 , G C M B _ S T R U C T _ K E Y C ]
@ Hash the KeyC with the multiboot image checksum to generate the KeyC derivation material to be sent to the other side of the link
2015-11-27 10:33:50 +01:00
bl G a m e C u b e M u l t i B o o t _ H a s h
2021-11-03 01:28:17 +01:00
@ Make sure the sent KeyC derivation material contains a magic value so that the other side can detect it
lsls r3 , 8
adds r3 , G C M B _ M A G I C _ K E Y C D E R I V A T I O N
@ Save off the KeyC derivation material and return to caller
str r3 , [ r0 , G C M B _ S T R U C T _ K E Y C _ D E R I V A T I O N ]
2015-10-06 16:00:49 +02:00
bx r12
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_Main_Return2 :
2015-10-06 16:00:49 +02:00
bx l r
2015-11-27 10:33:50 +01:00
thumb_ f u n c _ e n d G a m e C u b e M u l t i B o o t _ M a i n
2015-10-06 16:00:49 +02:00
.align 2 , 0
2015-11-27 10:33:50 +01:00
pool_HashVal : .4byte 0xa1c1
2016-09-03 04:51:16 +02:00
pool_Kawa : .ascii " Kawa " @ name of BIOS developer
2015-11-27 10:33:50 +01:00
pool_NintendoLogo : .4byte R o m H e a d e r N i n t e n d o L o g o
thumb_ f u n c _ s t a r t G a m e C u b e M u l t i B o o t _ E x e c u t e P r o g r a m
2016-09-03 04:51:16 +02:00
@ void GameCubeMultiBoot_ExecuteProgram(struct GameCubeMultiBoot *mb);
2021-12-22 02:46:59 +01:00
GameCubeMultiBoot_ExecuteProgram :
2021-11-03 01:28:17 +01:00
@ If there's no multiboot image ready, just return to caller
ldrb r1 , [ r0 , G C M B _ S T R U C T _ M B P R O G R E S S ]
cmp r1 , M B P R O G R E S S _ R E A D Y _ T O _ B O O T
2016-09-03 08:11:29 +02:00
bne G a m e C u b e M u l t i B o o t _ E x e c u t e P r o g r a m _ F a i l
2021-11-03 01:28:17 +01:00
@ Disable interrupts
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ I n t e r r u p t R e g s
2021-11-03 01:28:17 +01:00
movs r1 , 0
strh r1 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
@ Jump to the real entry point of the multiboot image (past the image header), in ARM mode
2015-11-27 10:33:50 +01:00
ldr r1 , p o o l _ M u l t i B o o t L o a d A d d r
2015-10-06 16:00:49 +02:00
adds r1 , 0 x C 0
bx r1
2016-09-03 08:11:29 +02:00
GameCubeMultiBoot_ExecuteProgram_Fail :
2015-10-06 16:00:49 +02:00
bx l r
2015-11-27 10:33:50 +01:00
thumb_ f u n c _ e n d G a m e C u b e M u l t i B o o t _ E x e c u t e P r o g r a m
thumb_ f u n c _ s t a r t G a m e C u b e M u l t i B o o t _ I n i t
2016-09-03 04:51:16 +02:00
@ void GameCubeMultiBoot_Init(struct GameCubeMultiBoot *mb);
2021-12-22 02:46:59 +01:00
GameCubeMultiBoot_Init :
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ I n t e r r u p t R e g s
2016-09-03 04:51:16 +02:00
@ Save IME register.
2021-11-03 01:28:17 +01:00
ldrh r2 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
2015-10-06 16:00:49 +02:00
2016-09-03 04:51:16 +02:00
@ Disable interrupts.
2015-10-06 16:00:49 +02:00
movs r1 , 0
2021-11-03 01:28:17 +01:00
strh r1 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
2015-11-27 10:33:50 +01:00
2016-09-03 04:51:16 +02:00
@ 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.
2015-11-27 10:33:50 +01:00
adr r3 , G c M b I n t r H a n d l e r _ S t o p
2021-11-03 01:28:17 +01:00
str r3 , [ r0 , G C M B _ S T R U C T _ S E R I A L _ I N T R _ H A N D L E R ]
2015-11-27 10:33:50 +01:00
2015-10-06 16:00:49 +02:00
ldrb r3 , [ r0 , 0 x3 ]
push { r3 }
ldrb r3 , [ r0 , 0 x1 ]
push { r0 ,r3 }
2015-11-27 10:33:50 +01:00
2021-11-03 01:28:17 +01:00
adds r3 , r0 , 0
adds r3 , G C M B _ S T R U C T _ B A S E _ D E S T _ P T R
2015-11-27 10:33:50 +01:00
2016-09-03 04:51:16 +02:00
@ clear all but the last 3 fields of the struct
2016-09-03 08:11:29 +02:00
GameCubeMultiBoot_Init_ClearStructLoop :
2015-10-06 16:00:49 +02:00
stm r0 ! , { r1 }
cmp r0 , r3
2016-09-03 08:11:29 +02:00
blo G a m e C u b e M u l t i B o o t _ I n i t _ C l e a r S t r u c t L o o p
2015-11-27 10:33:50 +01:00
2015-10-06 16:00:49 +02:00
pop { r0 ,r3 }
lsrs r3 , 1
strb r3 , [ r0 , 0 x3 ]
pop { r3 }
strb r3 , [ r0 , 0 x1 ]
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ S e r i a l R e g s
2016-09-03 04:51:16 +02:00
@ Turn off JOY Bus mode.
2015-10-06 16:00:49 +02:00
lsls r0 , r3 , 1 0
2015-11-27 10:33:50 +01:00
strh r0 , [ r3 , O F F S E T _ R E G _ R C N T - 0 x12 0 ]
2016-09-03 04:51:16 +02:00
@ Turn on JOY Bus mode.
2015-10-06 16:00:49 +02:00
movs r0 , 0 x C 0
lsls r0 , 8
2015-11-27 10:33:50 +01:00
strh r0 , [ r3 , O F F S E T _ R E G _ R C N T - 0 x12 0 ]
2016-09-03 04:51:16 +02:00
@ Init JOY Bus registers.
2015-10-06 16:00:49 +02:00
movs r0 , 0 x47
2015-11-27 10:33:50 +01:00
strh r0 , [ r3 , O F F S E T _ R E G _ J O Y C N T - 0 x12 0 ]
strh r1 , [ r3 , O F F S E T _ R E G _ J O Y S T A T - 0 x12 0 ]
ldr r3 , p o o l _ I n t e r r u p t R e g s
2016-09-03 04:51:16 +02:00
@ Acknowledge serial interrupt.
2015-11-27 10:33:50 +01:00
movs r0 , I N T R _ F L A G _ S E R I A L
strh r0 , [ r3 , O F F S E T _ R E G _ I F - 0 x20 0 ]
2016-09-03 04:51:16 +02:00
@ Enable serial interrupt.
2015-11-27 10:33:50 +01:00
ldrh r1 , [ r3 , O F F S E T _ R E G _ I E - 0 x20 0 ]
2015-10-06 16:00:49 +02:00
orrs r1 , r0
2015-11-27 10:33:50 +01:00
strh r1 , [ r3 , O F F S E T _ R E G _ I E - 0 x20 0 ]
2016-09-03 04:51:16 +02:00
@ Restore IME register.
2021-11-03 01:28:17 +01:00
strh r2 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
2015-11-27 10:33:50 +01:00
2015-10-06 16:00:49 +02:00
bx l r
2015-11-27 10:33:50 +01:00
thumb_ f u n c _ e n d G a m e C u b e M u l t i B o o t _ I n i t
non_ w o r d _ a l i g n e d _ t h u m b _ f u n c _ s t a r t G a m e C u b e M u l t i B o o t _ H a n d l e S e r i a l I n t e r r u p t
2016-09-03 04:51:16 +02:00
@ void GameCubeMultiBoot_HandleSerialInterrupt(struct GameCubeMultiBoot *mb);
2021-12-22 02:46:59 +01:00
GameCubeMultiBoot_HandleSerialInterrupt :
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ S e r i a l R e g s
2016-09-03 04:51:16 +02:00
@ Acknowledge reset/receive/send flags.
2015-11-27 10:33:50 +01:00
ldrh r1 , [ r3 , O F F S E T _ R E G _ J O Y C N T - 0 x12 0 ]
strh r1 , [ r3 , O F F S E T _ R E G _ J O Y C N T - 0 x12 0 ]
2015-10-06 16:00:49 +02:00
2021-11-03 01:28:17 +01:00
movs r2 , 0
2015-10-06 16:00:49 +02:00
strb r2 , [ r0 ]
2015-11-27 10:33:50 +01:00
2021-11-03 01:28:17 +01:00
ldr r2 , [ r0 , G C M B _ S T R U C T _ S E R I A L _ I N T R _ H A N D L E R ]
cmp r2 , 0
2015-11-27 10:33:50 +01:00
beq G a m e C u b e M u l t i B o o t _ H a n d l e S e r i a l I n t e r r u p t D o n e
2016-09-03 04:51:16 +02:00
lsrs r1 , 1 @ was a device reset command received?
bcs G a m e C u b e M u l t i B o o t _ B e g i n H a n d s h a k e @ branch if so
2015-11-27 10:33:50 +01:00
2015-10-06 16:00:49 +02:00
mov p c , r2
2015-11-27 10:33:50 +01:00
.align 2 , 0
2016-09-03 04:51:16 +02:00
@ 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.
2015-11-27 10:33:50 +01:00
GcMbIntrHandler_Stop :
2015-10-06 16:00:49 +02:00
movs r2 , 0
2015-11-27 10:33:50 +01:00
strh r2 , [ r3 , O F F S E T _ R E G _ J O Y S T A T - 0 x12 0 ]
GameCubeMultiBoot_SetInterruptHandler :
2021-11-03 01:28:17 +01:00
str r2 , [ r0 , G C M B _ S T R U C T _ S E R I A L _ I N T R _ H A N D L E R ]
2015-11-27 10:33:50 +01:00
GameCubeMultiBoot_ReadVCount :
ldr r3 , p o o l _ R e g D i s p s t a t
ldrh r1 , [ r3 , O F F S E T _ R E G _ V C O U N T - O F F S E T _ R E G _ D I S P S T A T ]
2015-10-06 16:00:49 +02:00
strb r1 , [ r0 , 0 x3 ]
2015-11-27 10:33:50 +01:00
GameCubeMultiBoot_HandleSerialInterruptDone :
2015-10-06 16:00:49 +02:00
bx l r
2015-11-27 10:33:50 +01:00
GameCubeMultiBoot_BeginHandshake :
2021-11-03 01:28:17 +01:00
@ Throw away anything that got sent
2015-11-27 10:33:50 +01:00
ldr r1 , [ r3 , O F F S E T _ R E G _ J O Y _ R E C V - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
@ Send the game code, the other side of the link must send back the same game code
2015-11-27 10:33:50 +01:00
ldr r1 , p o o l _ R u b y U S A G a m e C o d e
str r1 , [ r3 , O F F S E T _ R E G _ J O Y _ T R A N S - 0 x12 0 ]
2015-10-06 16:00:49 +02:00
movs r1 , 0 x10
2015-11-27 10:33:50 +01:00
strh r1 , [ r3 , O F F S E T _ R E G _ J O Y S T A T - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
@ Use the saved VCount value to provide 8 bits of entropy for KeyB
ldrb r1 , [ r0 , G C M B _ S T R U C T _ S A V E D V C O U N T ]
strb r1 , [ r0 , G C M B _ S T R U C T _ K E Y B + 1 ]
@ If a multiboot image has been transferred at least enough such that the Nintendo logo check has passed, stop everything.
ldrb r1 , [ r0 , G C M B _ S T R U C T _ M B P R O G R E S S ]
2015-10-06 16:00:49 +02:00
cmp r1 , 0
2015-11-27 10:33:50 +01:00
bne G c M b I n t r H a n d l e r _ S t o p
2021-11-03 01:28:17 +01:00
@ Set the image destination pointers.
2015-11-27 10:33:50 +01:00
ldr r1 , p o o l _ M u l t i B o o t L o a d A d d r
2021-11-03 01:28:17 +01:00
str r1 , [ r0 , G C M B _ S T R U C T _ B A S E _ D E S T _ P T R ]
str r1 , [ r0 , G C M B _ S T R U C T _ C U R _ D E S T _ P T R ]
@ Set the new interrupt handler.
2015-11-27 10:33:50 +01:00
adr r2 , G c M b I n t r H a n d l e r _ C h e c k G a m e C o d e S e n t
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
.align 2 , 0
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_CheckGameCodeSent :
2015-10-06 16:00:49 +02:00
lsls r1 , 3 1
2016-09-03 04:51:16 +02:00
bcc G c M b I n t r H a n d l e r _ S t o p @ stop if send failed
bmi G a m e C u b e M u l t i B o o t _ C h e c k H a n d s h a k e R e s p o n s e @ branch if receive is complete
2015-11-27 10:33:50 +01:00
2016-09-03 04:51:16 +02:00
@ If the response hasn't been fully received yet,
@ check again upon the next interrupt.
2015-11-27 10:33:50 +01:00
adr r2 , G c M b I n t r H a n d l e r _ C h e c k H a n d s h a k e R e s p o n s e
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
.align 2 , 0
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_CheckHandshakeResponse :
2016-09-03 04:51:16 +02:00
lsrs r1 , 1 @ is receive complete?
bcc G c M b I n t r H a n d l e r _ S t o p @ stop if not
2015-11-27 10:33:50 +01:00
GameCubeMultiBoot_CheckHandshakeResponse :
ldr r1 , [ r3 , O F F S E T _ R E G _ J O Y _ R E C V - 0 x12 0 ]
ldr r2 , p o o l _ R u b y U S A G a m e C o d e
2015-10-06 16:00:49 +02:00
cmp r1 , r2
2016-09-03 04:51:16 +02:00
bne G c M b I n t r H a n d l e r _ S t o p @ stop if the GameCube didn't reply with the same game code
2021-11-03 01:28:17 +01:00
@ Use the saved VCount value to provide another 8 bits of entropy for KeyB.
ldrb r1 , [ r0 , G C M B _ S T R U C T _ S A V E D V C O U N T ]
strb r1 , [ r0 , G C M B _ S T R U C T _ K E Y B + 3 ]
adr r2 , G c M b I n t r H a n d l e r _ R e c e i v e K e y A
2015-11-27 10:33:50 +01:00
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
2015-10-06 16:00:49 +02:00
2015-11-27 10:33:50 +01:00
.align 2 , 0
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_ReceiveKeyA :
2016-09-03 04:51:16 +02:00
lsrs r1 , 1 @ is receive complete?
bcc G c M b I n t r H a n d l e r _ S t o p @ branch if not
2015-11-27 10:33:50 +01:00
ldr r1 , [ r3 , O F F S E T _ R E G _ J O Y _ R E C V - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
@ make sure top 8 bits of the received value is the KeyA magic number, stop if KeyA is invalid
2015-10-06 16:00:49 +02:00
lsrs r2 , r1 , 2 4
2021-11-03 01:28:17 +01:00
cmp r2 , G C M B _ M A G I C _ K E Y A
2015-11-27 10:33:50 +01:00
bne G c M b I n t r H a n d l e r _ S t o p
2021-11-03 01:28:17 +01:00
@ save received KeyA
str r1 , [ r0 , G C M B _ S T R U C T _ K E Y A ]
@ use the second GameCubeMultiBoot_Main() counter as another 8 bits of entropy for KeyB
ldrb r1 , [ r0 , G C M B _ S T R U C T _ C O U N T E R 2 ]
strb r1 , [ r0 , G C M B _ S T R U C T _ K E Y B + 2 ]
2015-10-06 16:00:49 +02:00
movs r2 , 0
movs r3 , 0
2021-11-03 01:28:17 +01:00
ldr r1 , [ r0 , G C M B _ S T R U C T _ K E Y B ]
2015-10-06 16:00:49 +02:00
lsrs r1 , 8
2021-11-03 01:28:17 +01:00
@ 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 :
2015-10-06 16:00:49 +02:00
lsrs r1 , 1
adcs r2 , r3
cmp r1 , 0
2021-11-03 01:28:17 +01:00
bne G a m e C u b e M u l t i B o o t _ K e y B C h e c k L o o p
2015-10-06 16:00:49 +02:00
cmp r2 , 0 x E
2021-11-03 01:28:17 +01:00
bgt G a m e C u b e M u l t i B o o t _ K e y B S a v e N e w B y t e
2015-10-06 16:00:49 +02:00
cmp r2 , 0 x7
2021-11-03 01:28:17 +01:00
bge G a m e C u b e M u l t i B o o t _ K e y B C h e c k E n d
2015-10-06 16:00:49 +02:00
movs r1 , 0 x F F
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_KeyBSaveNewByte :
strb r1 , [ r0 , G C M B _ S T R U C T _ K E Y B + 2 ]
GameCubeMultiBoot_KeyBCheckEnd :
@ add in the KeyB magic number and send off KeyB
ldr r1 , [ r0 , G C M B _ S T R U C T _ K E Y B ]
adds r1 , G C M B _ M A G I C _ K E Y B
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ S e r i a l R e g s
str r1 , [ r3 , O F F S E T _ R E G _ J O Y _ T R A N S - 0 x12 0 ]
2015-10-06 16:00:49 +02:00
movs r1 , 0 x30
2015-11-27 10:33:50 +01:00
strh r1 , [ r3 , O F F S E T _ R E G _ J O Y S T A T - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
@ set new interrupt handler
adr r2 , G c M b I n t r H a n d l e r _ C h e c k K e y B S e n t
2015-11-27 10:33:50 +01:00
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
.align 2 , 0
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_CheckKeyBSent :
2015-10-06 16:00:49 +02:00
lsls r1 , 3 1
2016-09-03 04:51:16 +02:00
bcc G c M b I n t r H a n d l e r _ S t o p @ stop if send failed
2021-11-03 01:28:17 +01:00
bmi G a m e C u b e M u l t i B o o t _ C h e c k I m a g e S i z e R e s p o n s e @ branch if receive is complete
adr r2 , G c M b I n t r H a n d l e r _ C h e c k I m a g e S i z e R e s p o n s e
2015-11-27 10:33:50 +01:00
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
.align 2 , 0
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_CheckImageSizeResponse :
2016-09-03 04:51:16 +02:00
lsrs r1 , 1 @ is receive complete?
bcc G c M b I n t r H a n d l e r _ S t o p @ branch if not
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_CheckImageSizeResponse :
2015-11-27 10:33:50 +01:00
ldr r1 , [ r3 , O F F S E T _ R E G _ J O Y _ R E C V - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
ldr r2 , G a m e C u b e M u l t i B o o t _ M a x i m u m I m a g e S i z e U I n t 3 2 s
2015-10-06 16:00:49 +02:00
cmp r1 , r2
2015-11-27 10:33:50 +01:00
bhs G c M b I n t r H a n d l e r _ S t o p
2015-10-06 16:00:49 +02:00
adds r1 , 0 x1
adds r1 , r1
2021-11-03 01:28:17 +01:00
strh r1 , [ r0 , G C M B _ S T R U C T _ I M A G E _ S I Z E ]
ldrb r1 , [ r0 , G C M B _ S T R U C T _ M B P R O G R E S S ]
2015-10-06 16:00:49 +02:00
cmp r1 , 0
2021-11-03 01:28:17 +01:00
GcMbIntrHandler_StopIfNotEqual :
2015-11-27 10:33:50 +01:00
bne G c M b I n t r H a n d l e r _ S t o p
ldr r1 , p o o l _ M u l t i B o o t L o a d A d d r
2021-11-03 01:28:17 +01:00
str r1 , [ r0 , G C M B _ S T R U C T _ B A S E _ D E S T _ P T R ]
str r1 , [ r0 , G C M B _ S T R U C T _ C U R _ D E S T _ P T R ]
adr r2 , G c M b I n t r H a n d l e r _ C h e c k I m a g e R e s p o n s e
2015-11-27 10:33:50 +01:00
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
.align 2 , 0
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_CheckImageResponse :
2016-09-03 04:51:16 +02:00
lsrs r1 , 1 @ is receive complete?
bcc G c M b I n t r H a n d l e r _ S t o p @ branch if not
2021-11-03 01:28:17 +01:00
ldr r2 , [ r0 , G C M B _ S T R U C T _ C U R _ D E S T _ P T R ]
2015-10-06 16:00:49 +02:00
movs r1 , 0 x4
ands r1 , r2
adds r1 , 0 x8
lsls r1 , 2
2015-11-27 10:33:50 +01:00
strh r1 , [ r3 , O F F S E T _ R E G _ J O Y S T A T - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
@ get the recieved uint32
2015-11-27 10:33:50 +01:00
ldr r1 , [ r3 , O F F S E T _ R E G _ J O Y _ R E C V - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
@ put it in the current destination pointer and advance that pointer
2015-10-06 16:00:49 +02:00
stm r2 ! , { r1 }
2021-11-03 01:28:17 +01:00
@ save off the advanced pointer
str r2 , [ r0 , G C M B _ S T R U C T _ C U R _ D E S T _ P T R ]
@ decrease the image size (in uint32s)
ldrh r1 , [ r0 , G C M B _ S T R U C T _ I M A G E _ S I Z E ]
2015-10-06 16:00:49 +02:00
subs r1 , 0 x1
2021-11-03 01:28:17 +01:00
strh r1 , [ r0 , G C M B _ S T R U C T _ I M A G E _ S I Z E ]
@ branch away if the transfer is not yet complete
2015-11-27 10:33:50 +01:00
bne G a m e C u b e M u l t i B o o t _ R e a d V C o u n t
2021-11-03 01:28:17 +01:00
GcMbIntrHandler_SendCounter2 :
@ send counter2 with magic number
ldrb r1 , [ r0 , G C M B _ S T R U C T _ C O U N T E R 2 ]
2015-10-06 16:00:49 +02:00
lsls r1 , 8
2021-11-03 01:28:17 +01:00
adds r1 , G C M B _ M A G I C _ C O U N T E R 2
2015-11-27 10:33:50 +01:00
str r1 , [ r3 , O F F S E T _ R E G _ J O Y _ T R A N S - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
adr r2 , G c M b I n t r H a n d l e r _ C h e c k C o u n t e r2 S e n t
2015-11-27 10:33:50 +01:00
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
2015-10-06 16:00:49 +02:00
.align 2 , 0
2015-11-27 10:33:50 +01:00
2021-11-03 01:28:17 +01:00
GcMbIntrHandler_CheckCounter2Sent :
2015-10-06 16:00:49 +02:00
lsls r1 , 3 1
2015-11-27 10:33:50 +01:00
2021-11-03 01:28:17 +01:00
GcMbIntrHandler_StopIfSendFailed :
bcc G c M b I n t r H a n d l e r _ S t o p @ stop if send failed
@ if KeyC derivation value has not yet been generated, send Counter2 again, otherwise, send KeyC derivation
ldr r1 , [ r0 , G C M B _ S T R U C T _ K E Y C _ D E R I V A T I O N ]
2015-10-06 16:00:49 +02:00
cmp r1 , 0
2021-11-03 01:28:17 +01:00
beq G c M b I n t r H a n d l e r _ S e n d C o u n t e r2
2015-11-27 10:33:50 +01:00
str r1 , [ r3 , O F F S E T _ R E G _ J O Y _ T R A N S - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
adr r2 , G c M b I n t r H a n d l e r _ C h e c k K e y C D e r i v a t i o n S e n t
2015-11-27 10:33:50 +01:00
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
.align 2 , 0
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_CheckKeyCDerivationSent :
2015-10-06 16:00:49 +02:00
lsls r1 , 3 1
2021-11-03 01:28:17 +01:00
bcc G c M b I n t r H a n d l e r _ S t o p I f S e n d F a i l e d @ branch if send failed
bmi G a m e C u b e M u l t i B o o t _ C h e c k B o o t K e y R e s p o n s e @ branch if receive is complete
adr r2 , G c M b I n t r H a n d l e r _ C h e c k B o o t K e y R e s p o n s e
2015-11-27 10:33:50 +01:00
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
2015-10-06 16:00:49 +02:00
.align 2 , 0
2015-11-27 10:33:50 +01:00
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_CheckBootKeyResponse :
2016-09-03 04:51:16 +02:00
lsrs r1 , 1 @ is receive complete?
2021-11-03 01:28:17 +01:00
bcc G c M b I n t r H a n d l e r _ S t o p I f S e n d F a i l e d @ branch if not
2015-11-27 10:33:50 +01:00
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_CheckBootKeyResponse :
2015-11-27 10:33:50 +01:00
ldr r1 , [ r3 , O F F S E T _ R E G _ J O Y _ R E C V - 0 x12 0 ]
2021-11-03 01:28:17 +01:00
@ make sure received boot key contains expected magic number, stop if not
2015-10-06 16:00:49 +02:00
lsrs r2 , r1 , 2 4
2021-11-03 01:28:17 +01:00
cmp r2 , G C M B _ M A G I C _ B O O T K E Y
bne G c M b I n t r H a n d l e r _ S t o p I f N o t E q u a l
@ save received bootkey to be checked in GameCubeMultiBoot_Main()
strh r1 , [ r0 , G C M B _ S T R U C T _ B O O T _ K E Y ]
@ stop if anything more gets sent
adr r2 , G c M b I n t r H a n d l e r _ S t o p U n c o n d i t i o n a l l y
2015-11-27 10:33:50 +01:00
b G a m e C u b e M u l t i B o o t _ S e t I n t e r r u p t H a n d l e r
.align 2 , 0
2021-12-22 02:46:59 +01:00
GcMbIntrHandler_StopUnconditionally :
2015-11-27 10:33:50 +01:00
b G c M b I n t r H a n d l e r _ S t o p
thumb_ f u n c _ e n d G a m e C u b e M u l t i B o o t _ H a n d l e S e r i a l I n t e r r u p t
non_ w o r d _ a l i g n e d _ t h u m b _ f u n c _ s t a r t G a m e C u b e M u l t i B o o t _ Q u i t
2016-09-03 04:51:16 +02:00
@ void GameCubeMultiBoot_Quit();
2021-12-22 02:46:59 +01:00
GameCubeMultiBoot_Quit :
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ I n t e r r u p t R e g s
2016-09-03 04:51:16 +02:00
@ Save IME register.
2021-11-03 01:28:17 +01:00
ldrh r2 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
2015-11-27 10:33:50 +01:00
2016-09-03 04:51:16 +02:00
@ Disable interrupts.
2015-10-06 16:00:49 +02:00
movs r1 , 0
2021-11-03 01:28:17 +01:00
strh r1 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ S e r i a l R e g s
2016-09-03 04:51:16 +02:00
@ Acknowledge all JOYCNT flags.
2015-10-06 16:00:49 +02:00
movs r0 , 0 x7
2015-11-27 10:33:50 +01:00
strh r0 , [ r3 , O F F S E T _ R E G _ J O Y C N T - 0 x12 0 ]
2016-09-03 04:51:16 +02:00
@ Turn off JOY Bus mode.
2015-10-06 16:00:49 +02:00
lsls r0 , r3 , 1 0
2016-09-03 04:51:16 +02:00
strh r0 , [ r3 , O F F S E T _ R E G _ R C N T - 0 x12 0 ] @ store 0x8000
2015-11-27 10:33:50 +01:00
ldr r3 , p o o l _ I n t e r r u p t R e g s
2016-09-03 04:51:16 +02:00
@ Acknowledge serial interrupt.
2015-11-27 10:33:50 +01:00
movs r0 , I N T R _ F L A G _ S E R I A L
strh r0 , [ r3 , O F F S E T _ R E G _ I F - 0 x20 0 ]
2016-09-03 04:51:16 +02:00
@ Disable serial interrupt.
2015-11-27 10:33:50 +01:00
ldrh r1 , [ r3 , O F F S E T _ R E G _ I E - 0 x20 0 ]
2015-10-06 16:00:49 +02:00
bics r1 , r0
2015-11-27 10:33:50 +01:00
strh r1 , [ r3 , O F F S E T _ R E G _ I E - 0 x20 0 ]
2016-09-03 04:51:16 +02:00
@ Restore IME register.
2021-11-03 01:28:17 +01:00
strh r2 , [ r3 , O F F S E T _ R E G _ I M E - 0 x20 0 ]
2015-11-27 10:33:50 +01:00
2015-10-06 16:00:49 +02:00
bx l r
2015-11-27 10:33:50 +01:00
thumb_ f u n c _ e n d G a m e C u b e M u l t i B o o t _ Q u i t
2015-10-06 16:00:49 +02:00
.align 2 , 0
2015-11-27 10:33:50 +01:00
2021-11-03 01:28:17 +01:00
GameCubeMultiBoot_MaximumImageSizeUInt32s : .4byte 0x4000
2015-11-27 10:33:50 +01:00
pool_InterruptRegs : .4byte R E G _ B A S E + 0x200
pool_SerialRegs : .4byte R E G _ B A S E + 0x120
pool_RegDispstat : .4byte R E G _ D I S P S T A T
pool_RubyUSAGameCode : .ascii " AXVE "
pool_MultiBootLoadAddr : .4byte E W R A M _ S T A R T
2016-09-03 08:11:29 +02:00
.align 2 , 0 @ Don't pad with nop.