View unanswered posts | View active topics It is currently Mon Oct 22, 2018 10:27 am



Reply to topic  [ 4 posts ] 
 Krawall GBA modplayer on GitHub 
Author Message

Joined: Thu Aug 22, 2013 10:03 am
Posts: 2
Hello everyone!

I've finally gotten around to putting Krawall on GitHub: http://knzl.de/krawall/
I've updated it to work with the latest version of devkitARM.

Cheers,
Seb.


Thu Aug 22, 2013 10:16 am
Profile

Joined: Sun Sep 15, 2013 12:22 pm
Posts: 1
Hi.

Is there any chance to put things together so Krawall can be used with devkitARM?

Actually there are some people like myself, who jump to GBA developement from tim to time.


Sun Sep 15, 2013 12:29 pm
Profile
Site Admin

Joined: Tue Aug 09, 2005 3:21 am
Posts: 1291
Location: UK
I had the impression this was devkitARM ready although I see there appear to be a lack of binaries available.

I just had a quick look at the sources in github and I have a couple of observations.

There's a note in the TODO that says "Look into devkitPro's crt0 and make sure that a) multiple interrupts are possible and b) IRQ_TIMER1 is not interrupted by any other interrupt (Otherwise, there may be audible clicks). The devkitARM crt0 used for GBA doesn't have anything to do with interrupts - I have a particular dislike for end users messing with startup code as a general rule. The devkitAdvance way of doing things there basically meant that every GBA project had it's own crt0 with some horrendous number of potential variations which obviously has it's issues. With devkitARM we use a standard crt0 which copies sections to RAM as needed, clears BSS and initialises global constructors before jumping to main.

Code:
   .section   ".init"
   .global     _start
   .align
   .arm
@---------------------------------------------------------------------------------
_start:
@---------------------------------------------------------------------------------
   b   rom_header_end

   .fill   156,1,0         @ Nintendo Logo Character Data (8000004h)
   .fill   16,1,0         @ Game Title
   .byte   0x30,0x31      @ Maker Code (80000B0h)
   .byte   0x96         @ Fixed Value (80000B2h)
   .byte   0x00         @ Main Unit Code (80000B3h)
   .byte   0x00         @ Device Type (80000B4h)
   .fill   7,1,0         @ unused
   .byte   0x00         @ Software Version No (80000BCh)
   .byte   0xf0         @ Complement Check (80000BDh)
   .byte   0x00,0x00          @ Checksum (80000BEh)

@---------------------------------------------------------------------------------
rom_header_end:
@---------------------------------------------------------------------------------
   b   start_vector         @ This branch must be here for proper
                  @ positioning of the following header.

   .GLOBAL   __boot_method, __slave_number
@---------------------------------------------------------------------------------
__boot_method:
@---------------------------------------------------------------------------------
   .byte   0            @ boot method (0=ROM boot, 3=Multiplay boot)
@---------------------------------------------------------------------------------
__slave_number:
@---------------------------------------------------------------------------------
   .byte   0            @ slave # (1=slave#1, 2=slave#2, 3=slave#3)

   .byte   0             @ reserved
   .byte   0             @ reserved
   .word   0                @ reserved
   .word   0            @ reserved
   .word   0                @ reserved
   .word   0                @ reserved
   .word   0                @ reserved
   .word   0                @ reserved

    .global     start_vector
    .align
@---------------------------------------------------------------------------------
start_vector:
@---------------------------------------------------------------------------------
   mov   r0, #0x4000000         @ REG_BASE
   str   r0, [r0, #0x208]

   mov   r0, #0x12         @ Switch to IRQ Mode
   msr   cpsr, r0
   ldr   sp, =__sp_irq         @ Set IRQ stack
   mov   r0, #0x1f         @ Switch to System Mode
   msr   cpsr, r0
   ldr   sp, =__sp_usr         @ Set user stack

@---------------------------------------------------------------------------------
@ Enter Thumb mode
@---------------------------------------------------------------------------------
   add   r0, pc, #1
   bx   r0

   .thumb

   ldr   r0, =__text_start
   lsl   r0, #5            @ Was code compiled at 0x08000000 or higher?
   bcs     DoEWRAMClear         @ yes, you can not run it in external WRAM

   mov     r0, pc
   lsl     r0, #5            @ Are we running from ROM (0x8000000 or higher) ?
   bcc     SkipEWRAMClear         @ No, so no need to do a copy.

@---------------------------------------------------------------------------------
@ We were started in ROM, silly emulators. :P
@ So we need to copy to ExWRAM.
@---------------------------------------------------------------------------------
   mov   r2, #2
   lsl   r2, r2, #24         @ r2= 0x02000000
   ldr   r3, =__end__         @ last ewram address
   sub   r3, r2            @ r3= actual binary size
   mov   r6, r2            @ r6= 0x02000000
   lsl   r1, r2, #2         @ r1= 0x08000000

   bl   CopyMem

   bx   r6            @ Jump to the code to execute

@---------------------------------------------------------------------------------
DoEWRAMClear:               @ Clear External WRAM to 0x00
@---------------------------------------------------------------------------------
   mov   r1, #0x40
   lsl   r1, #12            @ r1 = 0x40000
   lsl   r0, r1, #7         @ r0 = 0x2000000
   bl   ClearMem

@---------------------------------------------------------------------------------
SkipEWRAMClear:               @ Clear Internal WRAM to 0x00
@---------------------------------------------------------------------------------

@---------------------------------------------------------------------------------
@ Clear BSS section to 0x00
@---------------------------------------------------------------------------------
   ldr   r0, =__bss_start__
   ldr   r1, =__bss_end__
   sub   r1, r0
   bl   ClearMem

@---------------------------------------------------------------------------------
@ Clear SBSS section to 0x00
@---------------------------------------------------------------------------------
   ldr   r0, =__sbss_start__
   ldr   r1, =__sbss_end__
   sub   r1, r0
   bl   ClearMem

@---------------------------------------------------------------------------------
@ Copy initialized data (data section) from LMA to VMA (ROM to RAM)
@---------------------------------------------------------------------------------
   ldr   r1, =__data_lma
   ldr   r2, =__data_start__
   ldr   r4, =__data_end__
   bl   CopyMemChk

@---------------------------------------------------------------------------------
@ Copy internal work ram (iwram section) from LMA to VMA (ROM to RAM)
@---------------------------------------------------------------------------------
   ldr   r1,= __iwram_lma
   ldr   r2,= __iwram_start__
   ldr   r4,= __iwram_end__
   bl   CopyMemChk

@---------------------------------------------------------------------------------
@ Copy internal work ram overlay 0 (iwram0 section) from LMA to VMA (ROM to RAM)
@---------------------------------------------------------------------------------
   ldr   r2,= __load_stop_iwram0
   ldr   r1,= __load_start_iwram0
   sub   r3, r2, r1         @ Is there any data to copy?
   beq   CIW0Skip         @ no

   ldr   r2,= __iwram_overlay_start
   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

@---------------------------------------------------------------------------------
CEW0Skip:
@---------------------------------------------------------------------------------
@ set heap end
@---------------------------------------------------------------------------------
   ldr   r1, =fake_heap_end
   ldr   r0, =__eheap_end
   str   r0, [r1]
@---------------------------------------------------------------------------------
@ global constructors
@---------------------------------------------------------------------------------
   ldr   r3, =__libc_init_array
   bl   _blx_r3_stub
@---------------------------------------------------------------------------------
@ Jump to user code
@---------------------------------------------------------------------------------
   mov   r0, #0            @ int argc
   mov   r1, #0            @ char   *argv[]
   ldr   r3, =main
   bl   _blx_r3_stub
@---------------------------------------------------------------------------------
@ Clear memory to 0x00 if length != 0
@---------------------------------------------------------------------------------
@ r0 = Start Address
@ r1 = Length
@---------------------------------------------------------------------------------
ClearMem:
@---------------------------------------------------------------------------------
   mov   r2,#3            @ These   commands are used in cases where
   add   r1,r2            @ the length is   not a multiple of 4,
   bic   r1,r2            @ even though it should be.

   beq   ClearMX            @ Length is zero so exit

   mov   r2,#0
@---------------------------------------------------------------------------------
ClrLoop:
@---------------------------------------------------------------------------------
   stmia   r0!, {r2}
   sub   r1,#4
   bne   ClrLoop
@---------------------------------------------------------------------------------
ClearMX:
@---------------------------------------------------------------------------------
   bx   lr

@---------------------------------------------------------------------------------
_blx_r3_stub:
@---------------------------------------------------------------------------------
   bx   r3

@---------------------------------------------------------------------------------
@ 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?
@---------------------------------------------------------------------------------
@ Copy memory
@---------------------------------------------------------------------------------
@ r1 = Source Address
@ r2 = Dest Address
@ r3 = Length
@---------------------------------------------------------------------------------
CopyMem:
@---------------------------------------------------------------------------------
   mov   r0, #3            @ These commands are used in cases where
   add   r3, r0            @ the length is not a multiple   of 4,
   bic   r3, r0            @ even   though it should be.
   beq   CIDExit            @ Length is zero so exit

@---------------------------------------------------------------------------------
CIDLoop:
@---------------------------------------------------------------------------------
   ldmia   r1!, {r0}
   stmia   r2!, {r0}
   sub   r3, #4
   bne   CIDLoop
@---------------------------------------------------------------------------------
CIDExit:
@---------------------------------------------------------------------------------
   bx   lr

   .align
   .pool
   .end


The IRQ dispatcher is in libgba where it belongs, allowing the freedom to supply a custom dispatcher without messing with system files. It was designed to allow multiple interrupts but to default to standard single interrupts. Essentially any IRQ handler which should be interruptible simply re-enables interrupts on entry. Here's the dispatcher code :-

Code:
/*

   libgba interrupt dispatcher routines

   Copyright 2003-2007 by Dave Murphy.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA.

   Please report all bugs and problems through the bug tracker at
   "http://sourceforge.net/tracker/?group_id=114505&atid=668551".


*/

@---------------------------------------------------------------------------------
   .section   .iwram,"ax",%progbits
   .extern   IntrTable
   .code 32

   .global   IntrMain
@---------------------------------------------------------------------------------
IntrMain:
@---------------------------------------------------------------------------------
   mov   r3, #0x4000000      @ REG_BASE
   ldr   r2, [r3,#0x200]      @ Read   REG_IE

   ldr   r1, [r3, #0x208]   @ r1 = IME
   str   r3, [r3, #0x208]   @ disable IME
   mrs   r0, spsr
   stmfd   sp!, {r0-r1,r3,lr}   @ {spsr, IME, REG_BASE, lr_irq}

   and   r1, r2,   r2, lsr #16   @ r1 =   IE & IF

   ldrh   r2, [r3, #-8]      @\mix up with BIOS irq flags at 3007FF8h,
   orr   r2, r2, r1      @ aka mirrored at 3FFFFF8h, this is required
   strh   r2, [r3, #-8]      @/when using the (VBlank)IntrWait functions

   ldr   r2,=IntrTable
   add   r3,r3,#0x200

@---------------------------------------------------------------------------------
findIRQ:
@---------------------------------------------------------------------------------
   ldr   r0, [r2, #4]      @ Interrupt mask
   cmp   r0,#0
   beq   no_handler
   ands   r0, r0, r1
   bne   jump_intr
   add   r2, r2, #8
   b   findIRQ

@---------------------------------------------------------------------------------
no_handler:
@---------------------------------------------------------------------------------
   strh   r1, [r3, #0x02]      @ IF Clear
   ldmfd   sp!, {r0-r1,r3,lr}   @ {spsr, IME, REG_BASE, lr_irq}
   str   r1, [r3, #0x208]   @ restore REG_IME
   mov   pc,lr

@---------------------------------------------------------------------------------
jump_intr:
@---------------------------------------------------------------------------------
   ldr   r2, [r2]      @ user IRQ handler address
   cmp   r2, #0
   beq   no_handler

@---------------------------------------------------------------------------------
got_handler:
@---------------------------------------------------------------------------------

   mrs   r1, cpsr
   bic   r1, r1, #0xdf      @ \__
   orr   r1, r1, #0x1f      @ /  --> Enable IRQ & FIQ. Set CPU mode to System.
   msr   cpsr,r1

   strh   r0, [r3, #0x02]      @ IF Clear
   
   push   {lr}
   adr   lr, IntrRet
   bx   r2

@---------------------------------------------------------------------------------
IntrRet:
@---------------------------------------------------------------------------------
   pop   {lr}
   mov   r3, #0x4000000      @ REG_BASE
   str   r3, [r3, #0x208]   @ disable IME

   mrs   r3, cpsr
   bic   r3, r3, #0xdf      @ \__
   orr   r3, r3, #0x92      @ /  --> Disable IRQ. Enable FIQ. Set CPU mode to IRQ.
   msr   cpsr, r3

   ldmfd   sp!, {r0-r1,r3,lr}   @ {spsr, IME, REG_BASE, lr_irq}
   str   r1, [r3, #0x208]   @ restore REG_IME
   msr   spsr, r0      @ restore spsr
   mov   pc,lr

   .pool
   .end


This was designed so that an interruptible dispatcher could simply start with REG_IME = 1 although it should probably mask REG_IE as well if there's a risk that it could interrupt itself. There were some issues doing that automatically although I've forgotten what now - the last time I even looked at that code was sometime in 2007 when I fixed the interrupt nesting!

It uses a table of masks and function pointers to allow a sort of priority if multiple interrupts occurred simultaneously. Interrupts would be serviced in the order they were set using irqSet(mask, function) although in testing I could never get this to happen. Either I just failed in attempting to provoke simultaneous interrupts or the GBA hardware just doesn't allow it - never really figured that one out.

Advising people to use cygwin to compile the windows binaries isn't a great idea - a cygwin install will interfere with an msys install and vice versa. I chose msys to provide unix like tools for the devkitPro toolchains mainly because the mingw/msys combination was designed to produce native windows code rather than the peculiar hybrid you get with cygwin and the corresponding issues you end up with when you have multiple cygwin dlls in various places.

In theory it should be possible to get cmake working with msys/mingw so I might have a look at doing that when I get a bit of time

_________________
Help keep devkitPro toolchains free, Donate today

devkitPro IRC support
Personal Blog


Mon Sep 16, 2013 11:34 pm
Profile ICQ WWW

Joined: Thu Aug 22, 2013 10:03 am
Posts: 2
Hi WinterMute!

Thanks for your elaborate feedback.

What you wrote about interrupts and how they're handled in devkitPro makes sense. I didn't look at how interrupts are handled with devkitPro,
hence my remark on the TODO was written with having "the old way" in mind. I'll rephrase it and (if I may) link to your post so someone giving it a go doesn't start hacking at the wrong place.

I wasn't aware of the Cygwin-issue. Cygwin may not be required for building at all, because CMake is pretty much self-contained.

Cheers,
seb


Mon Oct 14, 2013 12:24 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 4 posts ] 

Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
  Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.
Get devkitPro at SourceForge.net. Fast, secure and Free Open Source software downloads