gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

ASM > Multiboot & Burst Boot

#4257 - arundel - Wed Mar 26, 2003 1:56 am

Hi everybody. You may find this little piece of code useful. It should work with goldroad and maybe GAS (Intel syntax). Most of it has been writen by Martin Korth. However it was written for the a22i (at&t syntax) assembler, which is the assembler build into his no$gba emulator. Since only a few people use this assembler (too bad Martin discontinued the shareware version. stupid crackers :[) I changed the syntax. Works great.

Code:
@arm
@textarea $02000000                    ;Set origin to external WRAM
 b   rom_start                          ;rom entry point
 @dcd   0x051AEFF24,0x021A29A69,0x00A82843D,0x0AD09E484,0x0988B2411   ;nintendo
 @dcd   0x0217F81C0,0x019BE52A3,0x020CE0993,0x04A4A4610,0x0EC3127F8   ;logo
 @dcd   0x033E8C758,0x0BFCEE382,0x094DFF485,0x0C1094BCE,0x0C08A5694   ;one byte
 @dcd   0x0FCA77213,0x0734D849F,0x0619ACAA3,0x027A39758,0x0769803FC   ;wrong and the
 @dcd   0x061C71D23,0x056AE0403,0x0008438BF,0x0FD0EA740,0x003FE52FF   ;gba won't initialise
 @dcd   0x0F130956F,0x085C0FB97,0x02580D660,0x003BE63A9,0x0E2384E01   ;the game
 @dcd   0x0FF34A2F9,0x044033EBB,0x0CB900078,0x0943A1188,0x0637CC065   ;
 @dcd   0x0AF3CF087,0x08BE425D6,0x072AC0A38,0x007F8D421               ;
 @dcb   "TITLE HERE  "                  ;title (12 bytes)
 @dcb   "MB  ",  0,0                    ;game code (4 bytes), maker code (2 bytes)
 @dcb   0x96,0,0                        ;fixed value 96h, main unit code, device type
 @dcb   0,0,0,0,0,0,0                   ;reserved (7 bytes)
 @dcb   0                               ;software version number
 @dcb   0                               ;header checksum (set by .fix)
 @dcb   0,0                             ;reserved (2 bytes)

 b   wram_start                         ;multiboot ram entry point
 @dcb   0,0                             ;multiboot reserved bytes (destroyed by BIOS)
 @dcb   0,0                             ;blank padded (32bit alignment)


^^Multiboot Header^^

Code:
 msg_boot @dcb "BOOT"                   ;reply prepared for boot
 msg_okay @dcb "OKAY"                   ;reply prepared to receive length/bytes
 msg_brst @dcb "BRST"                   ;ID sent by PC (XBOO)

irq_handler:                           ;interrupt handler (note: r0-r3 are pushed by BIOS)
 mov   r1,0x4000000                     ;get I/O base address,
 ldr   r0,[r1,0x200]                    ;read IE and IF,
 and   r0,r0,r0,lsr 16                  ;isolate occurred AND enabled irqs,
 add   r3,r1,0x200                      ;and acknowledge these in IF
 strh   r0,[r3,2]
 ldrh   r3,[r1,-8]                      ;mix up with BIOS irq flags at 3007FF8h,
 orr   r3,r3,r0                         ;aka mirrored at 3FFFFF8h, this is required
 strh   r3,[r1,-8]                      ;when using the (VBlank-)IntrWait functions
 and   r3,r0,0x80                       ;IE/IF.7 SIO
 cmp   r3,0x80                          ;check if it's a burst boot interrupt
 ldreq  r2,[r1,0x120]                   ;SIODATA32 (if interrupt caused by serial transfer,
 ldreq  r3,[msg_brst]                   ;and if received data is "BRST",
 cmpeq  r2,r3                           ;then jump to burst boot)
 beq   burst_boot
 ;... insert your own interrupt handler code here ...
 bx    lr                               ;return to the BIOS interrupt handler

burst_boot:                            ;requires incoming r1=4000000h
 ;... if your program uses DMA, disable any active DMA transfers here ...
 ldr   r4,[msg_okay]                    ;tell SIO to receive length/bytes
 bl   sio_transfer
 mov   r2,r0                            ;now r2 holds length
 mov   r3,0x3000000                     ;the destination for the actual burst loader
 mov   r4,0                             ;reply will be ignored while getting the burst loader

lop:                                   ;this loop will download the burst loader and do a crc checking
 bl   sio_transfer                      ;download burst loader to 3000000h and up
 stmia r3!,[r0]                         ;store recieved data in r3 and do a writeback on 3000000h
 add   r4,r4,r0                         ;add every new data segemnt together (crc)
 subs  r2,r2,4                          ;correct the length
 bhi   lop                              ;loop while not all the data has been sent/received
 bl   sio_transfer                      ;exchange crc values to ensure correct transfer
 b    0x3000000                         ;now start the actual burst loader and let it download your program to external WRAM ($02000000)

sio_transfer:                          ;This routine is for sending/receiving data                     
                                       ;(32bit, normal mode, external clock/timing)
 str   r4,[r1,0x120]                    ;what shall be send to the PC
 ldr   r0,[r1,0x128]                    ;pop some value?
 orr   r0,r0,0x80                       ;?
 str   r0,[r1,0x128]                    ;change some value?
 .wait:                                 ;Here we wait until the transfer is complete
  ldr   r0,[r1,0x128]                  ;PC will set $04000128 to $80 when it finishes transfer
  tst   r0,0x80
  bne   wait
  ldr   r0,[r1,0x120]                  ;get the data the PC sent us (saved at $04000120-$04000128)
bx   lr

init_interrupts:
 mov  r4,0x04000000                     ;base address for below I/O registers
 ldr  r0,=irq_handler                   ;install IRQ handler address
 str  r0,[r4,-4]                        ;bios will call funktion at 3FFFFFC upon any interrupt
 mov  r0,0x0008                         ;enable generating vblank irqs
 strh r0,[r4,0x4]                       ;DISPSTAT
 mrs  r0,cpsr                           ;?
 bic  r0,r0,0x80                        ;cpu interrupt enable (clear i-flag)
 msr  cpsr,r0                           ;?
 mov  r0,0
 str  r0,[r4,0x134]                     ;init SIO normal mode, external clock,
 ldr  r0,=0x5080                        ;32bit, IRQ enable, transfer started
 str  r0,[r4,0x128]                     ;output "BOOT" (indicate burst boot prepared)
 ldr  r0,[msg_boot]
 str  r0,[r4,0x120]                     ;SIODATA32
 mov  r0,1                              ;interrupt master enable
 str  r0,[r4,0x208]                     ;IME=1
 mov  r0,0x81                           ;enable execution of vblank IRQs,
 str  r0,[r4,0x200]                     ;?
 bx   lr


^^Burst Boot^^

Code:
download_rom_to_wram:
 mov   r1,0x08000000                    ;ROM (source)
 mov   r2,0x02000000                    ;WRAM (destination)
 mov   r3,0x100                         ;amount (256 kbyte)
 .copyloop:
  ldmia   r1!,{r4-r7}                  ;multiple ldr
  stmia   r2!,{r4-r7}                  ;multiple str
  subs   r3,r3,1
 bne   copyloop
 sub   r15,lr,0x08000000-0x02000000     ;set new value for r15 (PC)


^^Copy Rom to WRAM^^

Code:
rom_start:                             ;entry for Cartridge (ROM)
 bl   download_rom_to_wram              ;download ROM to WRAM and return
wram_start:                            ;entry for Multiboot (WRAM)
 mov   r0,$0fe                          ;Reset all registers except
 swi   $10000                           ;external WRAM (02000000)
 bl   init_interrupts
@pool
@endarea


^^Main Routine^^


Puhhh...
_________________
http://www.nausicaa.net

#5900 - Jason Wilkins - Mon May 12, 2003 3:54 pm

I was wondering, what is this Burst Boot you talk about, and why is it so useful?

How would I use this code you have posted?
_________________
http://devkitadv.sourceforge.net

#5914 - torne - Mon May 12, 2003 7:36 pm

Burst Boot is a backdoor that the no$gba developer suggested; it's to allow you to download one game after another through a PC multiboot cable and play them without rebooting. Basically, it just listens for a certain magic string, then when it receives it, stops the current program, downloads the data into ewram over the previous binary, and just jumps back to the start, thus avoiding having to reset the gba or watch the nintendo logo again. So as long as all the PD roms you are using support it, testing stuff via mb cable is fast =)

The whole multiboot protocol is documented in the no$gba manual, and the code posted in this thread by the kind arundel is a translation from a22i assembler syntax into goldroad syntax of the example implementation.

It might be a nice thing to add into devkitadvance, if you like it, Jason. =)

Torne

#5917 - Jason Wilkins - Mon May 12, 2003 7:57 pm

Ok, this would be awesome then because DevKit Advance currently has about 60 test ROMs produced by my testsuite project, and will only get more in the future. A great number of tests can be done as multiboot programs, so I could develop a script to string them together and test them all very quickly.

Although, I could probably do something similar by concatenating a bunch of MB images into a cart and having each one load the next one when its finished.

I'm not completely sure yet, but has given me another option.
_________________
http://devkitadv.sourceforge.net