Documentation

@ `rsrt0`: The Rust Runtime 0.
@ This file is the boot point for a Rust program.
@ It performs all necessary setup before calling into main.

.global __start
.arm

@ @ @
@ ROM header. This is required to make a game work at all. The header contains
@ some logo data, game metadata, and a CRC check. The given check value is for
@ the blank metadata provided. If you want to alter the metadata use the
@ gbafix utility, which will also correctly update the CRC check for you.
@ @ @

__start: b init
@ Logo Data
.byte 0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21,0x3d,0x84,0x82
.byte 0x0a,0x84,0xe4,0x09,0xad,0x11,0x24,0x8b,0x98,0xc0,0x81
.byte 0x7f,0x21,0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20,0x10
.byte 0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec,0x58,0xc7,0xe8,0x33
.byte 0x82,0xe3,0xce,0xbf,0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09
.byte 0xc1,0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc,0x9f,0x84
.byte 0x4d,0x73,0xa3,0xca,0x9a,0x61,0x58,0x97,0xa3,0x27,0xfc
.byte 0x03,0x98,0x76,0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56
.byte 0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd,0xff,0x52,0xfe
.byte 0x03,0x6f,0x95,0x30,0xf1,0x97,0xfb,0xc0,0x85,0x60,0xd6
.byte 0x80,0x25,0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2,0xf9
.byte 0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44,0x78,0x00,0x90,0xcb
.byte 0x88,0x11,0x3a,0x94,0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c
.byte 0xaf,0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72,0x21,0xd4
.byte 0xf8,0x07
@ Game Title (12), Game Code (4), Maker Code (2)
.space 18
@ you just put 0x96 here
.byte 0x96
@ Main Unit Code (1), Device Type (1), Reserved (7), Version (1)
.space 10
@ Compliment Check.
.byte 0x51
@ Reserved Area
.space 2

init:
  @ Set address of user IRQ handler
  ldr r0, =bios_interrupt_handler
  ldr r1, =0x03FFFFFC
  str r0, [r1]

  @ set IRQ stack pointer
  mov r0, #0x12
  msr CPSR_c, r0
  ldr sp, =0x3007fa0

  @ set user stack pointer
  mov r0, #0x1f
  msr CPSR_c, r0
  ldr sp, =0x3007f00

  @ copy .data section to IWRAM
  ldr r0, =__data_rom_address     @ source address
  ldr r1, =__data_iwram_start   @ destination address
  ldr r2, =__data_iwram_end
  subs r2, r1             @ length
  @ these instructions are only executed if r2 is nonzero
  @ (i.e. don't bother copying an empty .data section)
  addne r2, #3
  asrne r2, #2
  addne r2, #0x04000000
  swine 0xb0000

  @ jump to user code
  ldr r0, =main
  bx r0

@ @ @
@ Interrupt Handler. Just clears the interrupt and returns. This is very basic,
@ and cannot be configured from Rust, but it lets us at least halt the CPU
@ while waiting for vblank.
@ @ @

bios_interrupt_handler:
  @ respond to all possible interrupt types
  mov r1, #0xFF

  @ respond in the mirror of the bios flags, just behind the base of MMIO
  mov r0, #0x04000000
  strh r1, [r0, #-8]

  @ respond in the standard flags
  add  r0,  r0, #0x200
  strh r1, [r0, #2]
  bx lr

/*
.arm
.global MainIrqHandler
.align 4, 0
MainIrqHandler:
  @ Load base I/O register address
  mov r2, #0x04000000
  add r2, r2, #0x200

  @ Save IRQ stack pointer and IME
  mrs r0, spsr
  ldrh r1, [r2, #8]
  stmdb sp!, {r0-r2,lr}

  @ Disable all interrupts by writing to IME
  @ r2 (0x4000200) can be used as we only care about bit 0 being unset
  strh r2, [r2, #8]

  @ Acknowledge all received interrupts that were enabled in IE
  ldr r3, [r2, #0]
  and r0, r3, r3, lsr #16
  strh r0, [r2, #2]

  @ Switch from IRQ mode to system mode
  @ cpsr_c = 0b000_10010u8 | 0b000_01101u8
  mrs r2, cpsr
  orr r2, r2, #0xD
  msr cpsr_c, r2

  @ Jump to user specified IRQ handler
  ldr r2, =__IRQ_HANDLER
  ldr r1, [r2]
  stmdb sp!, {lr}
  adr lr, .Lreturn
  bx r1
.Lreturn:
  ldmia sp!, {lr}

  @ Switch from ??? mode to IRQ mode, disable IRQ
  @ cpsr_c = ( !0b000_01101u8 & cpsr_c ) | 0b100_10010u8
  mrs r2, cpsr
  bic r2, r2, #0xD
  orr r2, r2, #0x92
  msr cpsr_c, r2

  @ Restore IRQ stack pointer and IME
  ldmia sp!, {r0-r2,lr}
  strh r1, [r2, #8]
  msr spsr_cf, r0

  @ Return to BIOS IRQ handler
  bx lr
  .pool
*/