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.
Krawall GBA modplayer on GitHub
krawall source code released
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.
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.
-
- Site Admin
- Posts: 2003
- Joined: Tue Aug 09, 2005 3:21 am
- Location: UK
- Contact:
Re: Krawall GBA modplayer on GitHub
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.
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 :-
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
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: Select all
.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
Code: Select all
/*
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
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
Re: Krawall GBA modplayer on GitHub
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
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
Who is online
Users browsing this forum: No registered users and 0 guests