Hi,
I am trying gba dev with natu on a macOS arm64 machine with macports.
Following the instructions on https://natu.exelo.tl, using arm-none-eabi-gcc I encounter an assembler include problem (which does not appears with devkitARM version of arm-none-eabi-gcc). In order to compile, I need to fix natu/private/acsl.nim
with AcslAsmFlags = "-Wa,-I"
instead of AcslAsmFlags = "-I"
.
After that, both natu-examples
and xniq
compile fine and the gba files can be run with mGBA.
However, when I try the same gba files on a DSI with GBArunner2, the emulator only gives me white or black screen whereas the itch.io version of xqni.gba works fine.
Hope this helps. Thank you for releasing natu !
N.
% nim --version
Nim Compiler Version 1.6.10 [MacOSX: arm64]
Compiled at 2022-12-20
Copyright (c) 2006-2021 by Andreas Rumpf
active boot switches: -d:release
% arm-none-eabi-gcc -v
Using built-in specs.
COLLECT_GCC=arm-none-eabi-gcc
COLLECT_LTO_WRAPPER=/opt/local/libexec/gcc/arm-none-eabi/12.2.0/lto-wrapper
Target: arm-none-eabi
Configured with: /opt/local/var/macports/build/_opt_bblocal_var_buildworker_ports_build_ports_cross_arm-none-eabi-gcc/arm-none-eabi-gcc/work/gcc-12.2.0/configure --prefix=/opt/local --target=arm-none-eabi --infodir=/opt/local/share/info --mandir=/opt/local/share/man --datarootdir=/opt/local/share/arm-none-eabi-gcc --with-system-zlib --with-gmp=/opt/local --with-mpfr=/opt/local --with-mpc=/opt/local --enable-stage1-checking --enable-multilib --disable-libcc1 --with-newlib --with-libgloss --enable-interwork --disable-newlib-supplied-syscalls --with-multilib-list=rmprofile --enable-languages=c,c++
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 12.2.0 (GCC)
Oh, thanks for the heads up! The
-Wa,-I
thing was a known issue with the Arm GNU Toolchain (they forgot to compile GCC with the flag that forwards include paths to the assembler), but I thought they'd have fixed it by now. Here was the bug report: https://bugs.linaro.org/show_bug.cgi?id=5835Weirdly
maxmod.nim
also uses-I
instead of-Wl,-I
... did you have to change that too or did it somehow work with no problems?I wasn't aware about the GBARunner2 issues but I'll take a look soon. The itch version was probably built with devkitARM's gcc + linker scripts + startfiles so there may be a discrepancy there.
Nope, for
maxmod.nim
you have to keep-I
for it to compile correctly.Concerning the GBARunner2 issues, I just checked that ROMs produced by
https://github.com/AntonioND/gba-bootstrap
. They seem to be compatible with mGBA but not with GBARunner2. Maybe something to fix intogba_crt0.s
orgba_cart.ld
? I don't have a real GBA with me this week to check against real hardware.
Found what is missing in
gba-boostrap/template/source/main.c
for it to work with GBARunner2 : IRQ handler should be initialized and VBlank IRQ enabled. I can fix my natu simple graphic test by adding:irq.init() irq.enable(iiVBlank) dispstat.vblankIrq = true
According to
natu/irq.nim
the last line is supposed to be handled insideirq.enable
but the relevant code is missing 😅 :var ie* {.importc:"(*(volatile NU16*)(0x4000200))", nodecl.}: set[IrqIndex] ## "Interrupt Enable" register. ## ## Setting a bit allows an interrupt to be received. But nothing will ## happen unless the relevant bit to request the interrupt is also set, ## e.g. `dispcnt.vblankIrq = true`. ## ## .. note:: ## `irq.put <#put,IrqIndex,FnPtr>`_ or `irq.enable <#enable,IrqIndex>`_ will take care of this for you.
Adding
dispstat.vblankIrq = true
toxniq
replace white screen by blank screen but still no game with GBARunner2.
Hey, I've pushed the
-Wa,-I
fix!The
dispstat.vblankIrq = true
line actually is done for you input/enable
by reading the location of the bit from thesenders
array and flipping it on. This is something I ported from libtonc, it's done this way because the GBA has bits scattered all over the place in different registers to enable different IRQs, and this is a nice data-centric way of solving it across the board.GBARunner2 indeed seems to do better when VBlank is enabled, I did some tests last night.
First I tried the
main.c
from gba-bootstrap:
- ❌︎ Using vanilla gcc + gba-bootstrap --> white screen
- ❌︎ Using devkitARM's gcc, makefile, linkerscript, crt0 --> white screen
Then I tried a more typical example, linked against libtonc, using
VBlankIntrWait
for the main loop:#include <tonc.h> int main(int argc, char *argv[]) { REG_DISPCNT = DCNT_MODE(3) | DCNT_BG2; irq_init(NULL); irq_enable(II_VBLANK); uint i = 240*80; u16 c = 0; while (1) { VBlankIntrWait(); m3_mem[0][i % (240*160)] = c; // plot pixel at new location i++; c++; } return 0; }Result:
- ✔︎ using vanilla gcc + gba-bootstrap --> Works!
- ✔︎ using devkitARM's gcc, makefile, linkerscript, crt0 --> Works!
Then I tried some other more recent Natu games:
- ❌︎ HEXES --> black screen
- ❌︎ A Rushed Hack Job --> black screen
- ❌︎ Recent Goodboy build --> white screen
And the Natu examples:
- ✔︎ anim_coins --> works
- ✔︎ anim_sprite --> works
- ❌︎ goodboy_gallery --> white screen
- ❌︎ hello_world --> white screen
- ✔︎ move_sprite --> works
- ❓︎ mystify --> kinda works but only visible in the lower half the screen
- ❌︎ play_music --> white screen
- ✔︎ bg_regions --> works
- ✔︎ test_sram --> works
And some other homebrew games from the GBA Jam 2022:
- ✔︎ Attack on Voxelberg (devkitARM) --> Works!
- ❌︎ Chocolate Hunter Runa (devkitARM + Butano) --> White screen
- ❌︎ Coin Fall (devkitAdvance 🥴︎) --> White screen
- ❓︎ Bugtris (devkitARM) --> Shows splash screens, goes black before reaching title screen
- ❌︎ Collie defense (devkitARM + Butano) --> White screen
- ❌︎ Gnoq (Zig) --> White screen
- ✔︎ Lane (agbrs) --> Works!
- ❓︎ Hero Core (devkitARM) --> Works but no sound
- ✔︎ Ravenia (devkitARM + gbsenpai) --> Works!
And the GBA Jam 2021:
- ✔︎ Varooom 3D (devkitARM + Butano) --> Works!
- ✔︎ 587 Squadron Advance (devkitARM) --> Works!
- ✔︎ Dungeon Advance (devkitARM + gbsenpai) -> Works!
- ✔︎ Feline (devkitARM + Butano) --> Works!
- ✔︎ Knight Owls (devkitARM + Butano) --> Works!
- ✔︎ Pipe Spin (devkitARM) --> Works (with minor graphical bugs)
- ✔︎ Tigermoth (devkitARM) --> Works!
- ✔︎ Solar Guard (devkitARM + Butano) --> Works!
- ❌︎ uCity Advance (libugba - similar base to gba-bootstrap) --> white screen
It's kinda hard to draw a conclusion from the above, only that GBARunner2 doesn't seem to work with most homebrew titles made in the last year. It hates busy loops, and doesn't seem to like games made in 2022 that use Maxmod - although games built a year ago using Maxmod, such as xniq and the Goodboy demo, seemed to work just fine, so maybe the version of GCC has something to do with it? Back then Natu was still using devkitARM, whose GCC tends to be a few months behind mainline GCC, so maybe that's why uCity was affected before all the others.
I've created an issue on the GBARunner2 repo: https://github.com/Gericom/GBARunner2/issues/297
Hopefully the situation will improve! In the meantime I can only suggest to not rely on it for the time being, or see how far you get using VBlankIntrWait() and no audio?
Oups, sorry about the
dispstat
setter, I am using natu to learn Nim at the same time and I might have missed some stuff. So what would be the proper way to enableiiVBlank
?Thanks for the detailled tests. For the Natu examples that do not work:
- goodboy_gallery -> has an IRQ handler
irq.put(iiVBlank, onVBlank)
- play_music -> has an IRQ handler
irq.put(iiVBlank, maxmod.vblank)
- hello_world -> does not enable iiVBlank
It turns out my simple examples trying to set a dummy IRQ handler for iiVBlank with
irq.put
does not work either for me witharm-none-eabi-gcc
12.2.0 andnim
1.6.10. This might explain maxmod not working either.I will avoid GBARunner2 and turn to another solution for the time being.
So what would be the proper way to enable iiVBlank?
If you don't want a handler and just want to enable VBlank so you can use
VBlankIntrWait
, then it's as simple as: import theirq
module (which automatically callsirq.init()
for you) then callirq.enable(iiVBlank)
.
irq.put
is just for if you want to set a handler, but also enables the interrupt for convenience.