Set up IRQ handling: 080000C0 mov r0,#$12 //\ 080000C4 msr cpsr_fc,r0 //| 080000C8 ldr r13,[pc,#$28] [$080000F8] //} Set stack pointer for IRQ mode 080000CC mov r0,#$1F //| 080000D0 msr cpsr_fc,r0 /// 080000D4 ldr r13,[pc,#$18] [$080000F4] // Set stack pointer for System mode 080000D8 ldr r1,[pc,#$1C] [$080000FC] //\ 080000DC add r0,pc,#$20 [$08000104] //} Set IRQ user handler to $08000104 080000E0 str r0,[r1] /// 080000E4 ldr r1,[pc,#$14] [$08000100] //\ 080000E8 mov lr,pc //} BL to $08000230 and switch to THUMB 080000EC bx r1 /// 080000F0 b -$28 [$080000C0] 080000F4 dcd $03007E60 080000F8 dcd $03007FA0 080000FC dcd $03007FFC 08000100 dcd $08000231 Load IRQ user handler: 08000AAC push {r4,lr} //\ 08000AAE add sp,-#$04 //} Save return and allocate a word of the stack 08000AB0 ldr r1,[pc,#$1C] [$08000AD0] // Load source address 08000AB2 ldr r4,[pc,#$20] [$08000AD4] // Load destination address 08000AB4 mov r3,#$80 //\ 08000AB6 lsl r3,r3,#$02 //} Load size 08000AB8 mov r0,#$10 //\ 08000ABA str r0,[sp] //} 16-bit 08000ABC mov r0,#$03 // Use DMA 3 08000ABE mov r2,r4 08000AC0 bl $2458 [$08002F1C] // All-purpose DMA routine 08000AC4 ldr [pc,#$10] [$08000AD8] //\ 08000AC6 str r4,[r0] //} Update IRQ user handler address 08000AC8 add sp,#$04 //\ 08000ACA pop {r4} //| 08000ACC pop {r0} //} Deallocate a word of the stack and return 08000ACE bx r0 /// 08000AD0 dcd $08000104 08000AD4 dcd $03000BE8 08000AD8 dcd $03007FFC IRQ BIOS handler: 00000018 b $00 [$00000020] // IRQ vector 00000128 stmfd r13!,{r0-r3,r12,lr} // Save return 0000012C mov r0,#$04000000 //\ 00000130 add lr,pc [$00000030] //} BL to [IRQ user handler] 00000134 ldr pc,[r0,-#$04] /// 00000138 ldmfd r13!,{r0-r3,r12,lr} //\ 0000013C subs pc,lr,#$04 //} Return IRQ user handler: 08000104 mov r3,#$04000000 //\ 08000108 add r3,r3,#$0200 //| 0800010C ldr r2,[r3] //| 08000110 ldrh r1,[r3,#$08] //} Save IRQ status and spsr 08000114 mrs r0,spsr //| 08000118 stmfd r13!,{r0-r3,lr} /// 0800011C mov r0,#$01 //\ 08000120 strh r0,[r3,#$08] //} Master enable IRQs 08000124 and r1,r2,r2,lsr #$10 // Load enabled IRQs & requested IRQs 08000128 mov r12,#$00 //\ 0800012C ands r0,r1,#$2000 //| 08000130 strneb r0,[r3,-#$017C] //} Disable sound and infinate loop if gamepack removed 08000134 bne -$8 [$08000134] /// 08000138 mov r12,#$00 //\ 0800013C ands r0,r1,#$0400 //} Handle DMA 2 IRQ 08000140 bne $7C [$080001C4] /// 08000144 add r12,r12,#$04 //\ 08000148 ands r0,r1,#$01 //} Handle V-Blank IRQ 0800014C bne $70 [$080001C4] /// 08000150 add r12,r12,#$04 //\ 08000154 ands r0,r1,#$02 //} Handle H-Blank IRQ 08000158 bne $64 [$080001C4] /// 0800015C add r12,r12,#$04 //\ 08000160 ands r0,r1,#$04 //} Handle V-Count IRQ 08000164 bne $58 [$080001C4] /// 08000168 add r12,r12,#$04 //\ 0800016C ands r0,r1,#$08 //} Handle Timer 0 IRQ 08000170 bne $4C [$080001C4] /// 08000174 add r12,r12,#$04 //\ 08000178 ands r0,r1,#$10 //} Handle Timer 1 IRQ 0800017C bne $40 [$080001C4] /// 08000180 add r12,r12,#$04 //\ 08000184 ands r0,r1,#$20 //} Handle Timer 2 IRQ 08000188 bne $34 [$080001C4] /// 0800018C add r12,r12,#$04 //\ 08000190 ands r0,r1,#$40 //} Handle Timer 3 IRQ 08000194 bne $28 [$080001C4] /// 08000198 add r12,r12,#$04 //\ 0800019C ands r0,r1,#$0100 //} Handle DMA 0 IRQ 080001A0 bne $1C [$080001C4] /// 080001A4 add r12,r12,#$04 //\ 080001A8 ands r0,r1,#$0200 //} Handle DMA 1 IRQ 080001AC bne $10 [$080001C4] /// 080001B0 add r12,r12,#$04 //\ 080001B4 ands r0,r1,#$0800 //} Handle DMA 3 IRQ 080001B8 bne $04 [$080001C4] /// 080001BC add r12,r12,#$04 //\ 080001C0 ands r0,r1,#$1000 //} Handle Keypad IRQ 080001C4 strh r0,[r3,#$2] // Set current IRQ as only requested IRQ 080001C8 ldr r1,[pc,#$58] [$08000228] //\ 080001CC bic r2,r2,r0 //} Reset enabled IRQs for only DMA 2 and Game Pak 080001D0 and r1,r1,r2 //} Clearing the current IRQ 080001D4 strh r1,[r3] /// 080001D8 mrs r3,cpsr //\ 080001DC bic r3,r3,#$DF //| 080001E0 orr r3,r3,#$1F //} Clear IRQ disable flags and switch to System mode 080001E4 msr cpsr_fc,r3 /// 080001E8 ldr r1,[pc,#$3C] [$0800022C] //\ 080001EC add r1,r1,r12 //| 080001F0 ldr r0,[r1] //| 080001F4 stmfd r13!,{lr} //} Save lr and BL to [$080A5224+r12] 080001F8 add lr,pc //| 080001FC bx r0 /// ____________________________ |IRQ ROM pointer| |V-Blank 08000B5D | |H-Blank 08000BA5 | |V-Count 08000BE5 | |Timer 0 08000C25 | |Timer 1 08000C25 | |Timer 2 08000C25 | |Timer 3 08000C25 | |DMA 0 08000C25 | |DMA 1 08000C25 | |DMA 2 080030B9 | |DMA 3 08000C25 | |Keypad 08000C25 | ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ 08000200 ldmfd r13!,{lr} // Restore lr 08000204 mrs r3,cpsr //\ 08000208 bic r3,r3,#$DF //| 0800020C orr r3,r3,#$92 //} Set IRQ disable flag and switch to IRQ mode 08000210 msr cpsr_fc,r3 /// 08000214 ldmfd r13!,{r0-r3,lr} //\ 08000218 strh r2,[r3] //| 0800021C strh r1,[r3,#$08] //} Restore spsr and IRQ status 08000220 msr spsr_fc,r0 //| 08000224 bx lr /// 08000228 dcd $00002400 0800022C dcd $080A5224 V-Blank: 08000B5C push {lr} // Save return 08000B5E ldr r0,[pc,#$1C] [$08000B7C] //\ 08000B60 ldr r0,[r0] //| 08000B62 cmp r0,#$00 //} If V-Blank Code Pointer, BL to it 08000B64 beq $02 [$08000B6A] //| 08000B66 bl $0A28C2 [$080A342C] /// 08000B6A ldr r1,[pc,#$14] [$08000B80] //\ 08000B6C ldrh r0,[r1] //| 08000B6E mov r2,#$01 //| 08000B70 orr r0,r2 //} Request V-Blank IRQ 08000B72 strh r0,[r1] /// 08000B74 ldr r0,[pc,#$0C] [$08000B84] //\ 08000B76 strh r2,[r0] //} Set V-Blank Happened Flag 08000B78 pop {r0} //\ 08000B7A bx r0 //} Return 08000B7C dcd $030019C4 08000B80 dcd $04000202 08000B84 dcd $03000BE6 H-Blank: 08000BA4 push {lr} // Save return 08000BA6 ldr [pc,#$18] [$08000BC0] //\ 08000BA8 ldr r0,[r0] //| 08000BAA cmp r0,#$00 //} If H-Blank Code Pointer, BL to it 08000BAC beq $02 [$08000BB2] //| 08000BAE bl $0A287A [$080A342C] /// 08000BB2 ldr r0,[pc,#$10] [$08000BC4] //\ 08000BB4 ldrh r1,[r0] //| 08000BB6 mov r2,#$02 //} Request H-Blank IRQ 08000BB8 orr r1,r2 //| 08000BBA strh r1,[r0] /// 08000BBC pop {r0} //\ 08000BBE bx r0 //} Return 08000BC0 dcd $030019C8 08000BC4 dcd $04000202 V-Count: 08000BE4 push {lr} // Save return 08000BE6 ldr [pc,#$18] [$08000C00] //\ 08000BE8 ldr r0,[r0] //| 08000BEA cmp r0,#$00 //} If V-Count Code Pointer, BL to it 08000BEC beq $02 [$08000BF2] //| 08000BEE bl $0A283A [$080A342C] /// 08000BF2 ldr r0,[pc,#$10] [$08000C04] //\ 08000BF4 ldrh r1,[r0] //| 08000BF6 mov r2,#$04 //} Request V-Count IRQ 08000BF8 orr r1,r2 //| 08000BFA strh r1,[r0] /// 08000BFC pop {r0} //\ 08000BFE bx r0 //} Return 08000C00 dcd $030019CC 08000C04 dcd $04000202 DMA 2: 080030B8 push {r4,lr} // Save return 080030BA ldr r3,[pc,#$44] [$08003100] //\ 080030BC ldrb r0,[r3,#$10] //| 080030BE add r0,#$01 //} Increment $030019E0 (current frame) 080030C0 strb r0,[r3,#$10] /// 080030C2 lsl r0,r0,#$18 //\ 080030C4 lsr r0,r0,#$18 //| 080030C6 ldrb r1,[r3,#$0E] //} If not reached $030019DE (length), return 080030C8 cmp r0,r1 //| 080030CA bne $2A [$080030F8] /// 080030CC ldr r0,[pc,#$34] [$08003104] //\ 080030CE ldr r1,[pc,#$38] [$08003108] //} Perform DMA 1 and 2 080030D0 str r1,[r0] //} Fixed destination, 32-bit 080030D2 add r0,#$0C //} 4 writes 080030D4 str r1,[r0] /// 080030D6 ldr r2,[pc,#$34] [$0800310C] //\ 080030D8 mov r4,#$A0 //| 080030DA lsl r4,r4,#$03 //| 080030DC mov r0,r4 //} Perform DMA 1 and 2 080030DE strh r0,[r2] //} Fixed source, 32-bit 080030E0 ldr r1,[pc,#$2C] [$08003110] //| 080030E2 strh r0,[r1] /// 080030E4 mov r4,#$B6 //\ 080030E6 lsl r4,r4,#$08 //} Perform DMA 1 080030E8 mov r0,r4 //} Repeat, 32-bit, SndFifo 080030EA strh r0,[r2] /// 080030EC mov r2,#$F6 //\ 080030EE lsl r2,r2,#$08 //} Perform DMA 2 080030F0 mov r0,r2 //} Repeat, 32-bit, SndFifo, IRQ 080030F2 strh r0,[r1] /// 080030F4 mov r0,#$00 //\ 080030F6 strb r0,[r3,#$10] //} Reset $030019E0 (current frame) to $00 080030F8 pop {r4} //\ 080030FA pop {r0} //} Return 080030FC bx r0 /// 080030FE dcw $0000 08003100 dcd $030019D0 08003104 dcd $040000C4 08003108 dcd $84400004 0800310C dcd $040000C6 08003110 dcd $040000D2 Others: 08000C24 bx lr // Return