📄 boot.s
字号:
bl CopyMem
CIW0Skip:
@ Copy external work ram (ewram section) from LMA to VMA (ROM to RAM)
ldr r1,=__ewram_lma
ldr r2,=__ewram_start
ldr r4,=__ewram_end
bl CopyMemChk
@ Copy external work ram overlay 0 (ewram0 section) from LMA to VMA (ROM to RAM)
ldr r2,=__load_stop_ewram0
ldr r1,=__load_start_ewram0
sub r3,r2,r1 @ Is there any data to copy?
beq CEW0Skip @ no
ldr r2,=__ewram_overlay_start
bl CopyMem
CEW0Skip:
@ Jump to user code
mov r0,#0 @ int argc
mov r1,#0 @ char *argv[]
ldr r3,=start_vector
mov lr,r3 @ Set start_vector as return address
.ifdef __CPPSupport
ldr r3,=main
.else
ldr r3,=AgbMain
.endif
bx r3
.GLOBAL __FarFunction,__FarProcedure
.THUMB_FUNC
__FarFunction:
.THUMB_FUNC
__FarProcedure:
bx r0
nop
nop @ This nop is here to allow unmapped memory to be used as
@ as a delay of almost 1 sec with a 1 cycle resolution.
@ Read this for technical info:
@ http://www.devrs.com/gba/files/gbadevfaqs.php#RepeatUses
@ Clear memory to 0x00 if length != 0
@ r0 = Start Address
@ r1 = Length
ClearMem:
cmp r1,#0 @ Is length zero?
beq ClearMX @ yes, exit
.ifdef __DMACopyClear
ldr r2,reg_base
lsr r1,#2 @ r1 = (length/4) & 0xffff
adr r3,fill_val
str r3,[r2,#0x4] @ Set source address (fill value)
str r0,[r2,#0x8] @ Set destination address (fill dest address)
strh r1,[r2,#0xc] @ Set DMA length
ldr r1,=0x8500 @ dma_clrb
strh r1,[r2,#0xe] @ Start DMA
.else
mov r2,#0
ClrLoop:
stmia r0!,{r2}
sub r1,#4
bne ClrLoop
.endif
ClearMX:
bx lr
@ Copy memory if length != 0
@ r1 = Source Address
@ r2 = Dest Address
@ r4 = Dest Address + Length
CopyMemChk:
sub r3,r4,r2 @ Is there any data to copy?
beq CIDExit @ no
@ Copy memory
@ r1 = Source Address
@ r2 = Dest Address
@ r3 = Length
CopyMem:
.ifdef __DMACopyClear
ldr r0,reg_base
lsr r3,#2 @ r3 = (length/4) & 0xffff
str r1,[r0,#0x4] @ Set source address
str r2,[r0,#0x8] @ Set destination address
strh r3,[r0,#0xc] @ Set DMA length
ldr r3,=0x8400 @ dma_copy
strh r3,[r0,#0xe] @ Start DMA
.else
CIDLoop:
ldmia r1!,{r0}
stmia r2!,{r0}
sub r3,#4
bne CIDLoop
.endif
CIDExit:
If_Undefined_Reference__rename_main_or_AgbMain_to_each_other_in_your_C_file:
bx lr
.ALIGN
.ifdef __DMACopyClear
fill_val: .word 0
reg_base: .word 0x040000d0
.endif
.ALIGN
.POOL
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ Interrupt Processing @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
.ifdef __ISRinIWRAM
.SECTION .iwram
.endif
.EXTERN IntrTable
.EXTERN InterruptProcess
.GLOBAL intr_main
.ALIGN
.ARM
@ NOTE: Ifyou copy the following code (start: intr_main -
@ end: intr_main_end) to internal WRAM then do not forget
@ to copy everything between these two labels. The .POOL
@ data must be copied since it is used by intr_main.
@ NOTE2: If __ISRinIWRAM is defined then the copy to
@ IWRAM is done automatically for you.
.ifdef __InterruptSupport
.ifdef __FastInterrupts
intr_main:
ldr r0,=InterruptProcess
bx r0
.endif
.ifdef __SingleInterrupts
intr_main:
@ Single interrupts support
mov r3, #0x4000000 @ REG_BASE
ldr r2, [r3,#0x200]! @ Read REG_IE
and r1, r2, r2, lsr #16 @ r1 = IE & IF
ldr r2, =IntrTable
ands r0, r1, #1 @ V-Blank Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #2 @ H-Blank Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #4 @ V Counter Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #8 @ Timer 0 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x10 @ Timer 1 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x20 @ Timer 2 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x40 @ Timer 3 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x80 @ Serial Communication Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x100 @ DMA0 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x200 @ DMA1 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x400 @ DMA2 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x800 @ DMA3 Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x1000 @ Key Interrupt
bne jump_intr
add r2, r2, #4
ands r0, r1, #0x2000 @ Cart Interrupt
.ifdef __HandleCartInterrupt
strneb r0, [r3, #0x84 - 0x200] @ Stop sound if cart removed (REG_SOUNDCNT_X)
loop: bne loop @ Infinite loop if cart removed
.endif
jump_intr:
strh r0, [r3, #2] @ IF Clear
ldr r0, [r2] @ Jump to user IRQ process
bx r0
.endif
.ifdef __MultipleInterrupts
intr_main:
@ Multiple interrupts support
mov r2, #0x4000000 @ REG_BASE
ldr r3, [r2,#0x200]! @ r2 = IE : r3 = IF|IE
ldrh r1, [r2, #0x8] @ r1 = IME
mrs r0, spsr
stmfd sp!, {r0-r2,lr} @ {spsr, IME, REG_IE, lr} // IF|IE
mov r0, #1 @ IME = 1 (To permit multiple interrupts if
@ an interrupt occurs)
strh r0, [r2, #0x8]
and r1, r3, r3, lsr #16 @ r1 = IE & IF
ldr r12, =IntrTable
ands r0, r1, #1 @ V-blank interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #2 @ H-blank interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #4 @ V-counter interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #8 @ Timer 0 interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x10 @ Timer 1 interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x20 @ Timer 2 interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x40 @ Timer 3 interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x80 @ Serial Communication Interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x100 @ DMA 0 interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x200 @ DMA 1 interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x400 @ DMA 2 interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x800 @ DMA 3 interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x1000 @ Key interrupt
bne jump_intr
add r12,r12, #4
ands r0, r1, #0x2000 @ Cart interrupt
.ifdef __HandleCartInterrupt
strneb r0, [r2, #0x84 - 0x200] @ Stop sound if cart removed (REG_SOUNDCNT_X)
loop: bne loop @ Infinite loop if cart removed
.endif
jump_intr:
strh r0, [r2, #2] @ Clear IF
@ Enable multiple interrupts & switch to system
@ mode if __SwitchToUserStack is defined.
mrs r3, cpsr
.ifdef __SwitchToUserStack
bic r3, r3, #0xdf @ \__
orr r3, r3, #0x1f @ / --> Enable IRQ & FIQ. Set CPU mode to System.
.else
bic r3, r3, #0xc0 @ Enable IRQ & FIQ
.endif
msr cpsr, r3
ldr r0, [r12]
stmfd sp!, {lr}
adr lr, IntrRet
bx r0
IntrRet:
ldmfd sp!, {lr}
@ Disable multiple interrupts & switch to IRQ Mode
@ if __SwitchToUserStack is defined.
mrs r3, cpsr
.ifdef __SwitchToUserStack
bic r3, r3, #0xdf @ \__
orr r3, r3, #0x92 @ / --> Disable IRQ. Enable FIQ. Set CPU mode to IRQ.
.else
orr r3, r3, #0x80 @ Disable IRQ.
.endif
msr cpsr, r3
ldmfd sp!, {r0-r2,lr} @ {spsr, IME, REG_IE, lr} //IF|IE
@ strh r3, [r2] @ set IE
strh r1, [r2, #0x8] @ restore REG_IME
msr spsr, r0 @ restore spsr
bx lr
.endif
.ALIGN
.POOL @ Ifyou copy the intr_main routine, above, to internal
@ RAM then copy the pool data as well because IntrTable
@ address is stored here. Use intr_main_end as last address+1.
intr_main_end:
.endif
.ALIGN
.POOL
.END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -