diff options
-rw-r--r-- | CHANGELOG.txt | 10 | ||||
-rw-r--r-- | GNUmakefile | 30 | ||||
-rw-r--r-- | README.html | 11 | ||||
-rw-r--r-- | agbx/GNUmakefile | 5 | ||||
-rw-r--r-- | agbx/include-private/agbx/priv.h | 9 | ||||
-rw-r--r-- | agbx/include/agbx/bs.h | 8 | ||||
-rw-r--r-- | agbx/include/agbx/gfx.h | 12 | ||||
-rw-r--r-- | agbx/source/bs/done.c | 22 | ||||
-rw-r--r-- | agbx/source/gfx/flip.c | 17 | ||||
-rw-r--r-- | agbx/source/gfx/plot.c | 10 | ||||
-rw-r--r-- | agbx/source/gfx/setpx.c | 21 | ||||
-rw-r--r-- | agbx/source/key/getkeymap.c | 2 | ||||
-rw-r--r-- | demo/demo.c | 35 |
13 files changed, 108 insertions, 84 deletions
diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ba7ef29..6e810c1 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,13 @@ +# 2.0 + +* Update readme; +* Remove the root makefile; +* Use digit seperators; +* Fix setpx1; +* Add function for flipping pages; +* Add nodiscard to the get functions; +* Make setpx take the address of the video page; + # 1.1 * Fix version number not being updated; diff --git a/GNUmakefile b/GNUmakefile deleted file mode 100644 index 720486a..0000000 --- a/GNUmakefile +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2022 Gabriel Jensen. -# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. -# If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -ifeq ($(DEBUG),) -DEBUG := false -endif - -.PHONY: agbx clean demo install purge - -agbx: - $(MAKE) -C$(@) DEBUG=$(DEBUG) - -demo: agbx - $(MAKE) -C$(@) - -install: agbx - mkdir -pvm755 "$(HDRDIR)/agbx" - mkdir -pvm755 "$(LIBDIR)" - install -vm644 "agbx/include/agbx/"*".h" "$(HDRDIR)/agbx" - install -vm755 "agbx/libagbx.a" "$(LIBDIR)" - -clean: - $(MAKE) -Cagbx clean - $(MAKE) -Cdemo clean - -purge: - $(MAKE) -Cagbx purge - $(MAKE) -Cdemo purge - diff --git a/README.html b/README.html index b3e4cff..e0876be 100644 --- a/README.html +++ b/README.html @@ -1,5 +1,14 @@ <!DOCTYPE html> <html> - <h1>AGBX</h1> + <h1>AGBx</h1> <p>Framework for development on the Game Boy Advance.</p> + <h2>Building</h2> + <p>As the Game Boy Advance uses an ARM (ARM7TDMI) processor, AGBx requires an ARM cross-compiler.</p> + <p>For GCC, the appropriate package is <i>arm-none-eabi-gcc</i> on Arch Linux and <i>gcc-arm-none-eabi</i> on Debian. Clang supports supports cross-compilation by default, and this platform can be set via the <i>--target=arm-none-eabi</i> option.</p> + <p>The used cross-compiler can be configured in the makefiles, however, it must be GCC-compatible..</p> + <p>Debug mode can be enabled by setting <i>DEBUG=true</i> when invoking make.</p> + <br /> + <p>The provided makefiles are for GNU Make (hence the filename of <i>GNUmakefile</i>) and depend on it's extensions.</p> + <h3>Demo</h3> + <p>The demo uses <a href="https://mandelbrot.dk/agbsum">agbsum</a> (<a href="https://mandelbrot.dk/pkgbuild_agbsum">pkgbuild</a>) for patching the demo image header checksum so that it isn't rejected by the bootloader. This patch isn't always required, however, and the makefile (at <i>demo/GNUmakefile</i>) can be modified to skip it.</p> </html> diff --git a/agbx/GNUmakefile b/agbx/GNUmakefile index f0f2bdf..fb83fa5 100644 --- a/agbx/GNUmakefile +++ b/agbx/GNUmakefile @@ -2,14 +2,17 @@ # This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. # If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. +ifneq ($(DEBUG),) ifneq ($(DEBUG),false) ifneq ($(DEBUG),true) $(error Invalid value \"$(DEBUG)\" for DEBUG) endif endif +endif # TOOLS +AS := arm-none-eabi-as CC := clang -target arm-none-eabi #CC := arm-none-eabi-gcc OBJCOPY := arm-none-eabi-objcopy @@ -25,6 +28,7 @@ CFLAGS := \ -Wpedantic \ -ffreestanding \ -fno-builtin \ + -fno-strict-aliasing \ -mcpu=arm7tdmi \ -mthumb \ -mtune=arm7tdmi \ @@ -50,6 +54,7 @@ OBJS := \ source/bs/done.o \ source/bs/get.o \ source/bs/set.o \ + source/gfx/flip.o \ source/gfx/plot.o \ source/gfx/setpx.o \ source/key/getkeymap.o \ diff --git a/agbx/include-private/agbx/priv.h b/agbx/include-private/agbx/priv.h index 867ec07..3f55813 100644 --- a/agbx/include-private/agbx/priv.h +++ b/agbx/include-private/agbx/priv.h @@ -36,13 +36,8 @@ ); \ } -#define __agbx_setpx1(_px,_col) { \ - agbx_i20 const addr = 0x6000000u + _px; \ - __agbx_set8(addr,_col); \ -} - -#define __agbx_setpx2(_px,_col) { \ - agbx_i20 const addr = 0x6000000u + _px * 0x2u; /* We multiply it by two as each pixel takes up two bytes. */ \ +#define __agbx_setpx2(_vaddr,_px,_col) { \ + agbx_i20 const addr = _vaddr + _px * 0x2u; /* We multiply it by two as each pixel takes up two bytes. */ \ __agbx_set10(addr,_col); \ } diff --git a/agbx/include/agbx/bs.h b/agbx/include/agbx/bs.h index 8d93698..617e328 100644 --- a/agbx/include/agbx/bs.h +++ b/agbx/include/agbx/bs.h @@ -26,13 +26,13 @@ typedef enum { agbx_err_max = 0xFFu, } agbx_err; -constexpr agbx_i40 agbx_ver = 0x1u; +constexpr agbx_i40 agbx_ver = 0x2u; [[noreturn]] void agbx_done(agbx_err err); -agbx_i10 agbx_get10(agbx_i20 addr); -agbx_i20 agbx_get20(agbx_i20 addr); -agbx_i8 agbx_get8( agbx_i20 addr); +[[nodiscard]] agbx_i10 agbx_get10(agbx_i20 addr); +[[nodiscard]] agbx_i20 agbx_get20(agbx_i20 addr); +[[nodiscard]] agbx_i8 agbx_get8( agbx_i20 addr); void agbx_set10(agbx_i20 addr,agbx_i10 val); void agbx_set20(agbx_i20 addr,agbx_i20 val); diff --git a/agbx/include/agbx/gfx.h b/agbx/include/agbx/gfx.h index 31c3778..579e20a 100644 --- a/agbx/include/agbx/gfx.h +++ b/agbx/include/agbx/gfx.h @@ -9,11 +9,13 @@ #include <agbx/bs.h> -void agbx_setpx1(agbx_i10 px,agbx_i8 col); -void agbx_setpx2(agbx_i10 px,agbx_i10 col); +agbx_i20 agbx_flip(void); -agbx_i10 agbx_plot3(agbx_i8 x, agbx_i8 y,agbx_i10 col); -agbx_i10 agbx_plot4(agbx_i8 x, agbx_i8 y,agbx_i8 col); -agbx_i10 agbx_plot5(agbx_i8 x, agbx_i8 y,agbx_i10 col); +void agbx_setpx1(agbx_i20 vaddr,agbx_i10 px,agbx_i8 col); +void agbx_setpx2(agbx_i20 vaddr,agbx_i10 px,agbx_i10 col); + +agbx_i10 agbx_plot3(agbx_i8 x,agbx_i8 y,agbx_i10 col); +agbx_i10 agbx_plot4(agbx_i8 x,agbx_i8 y,agbx_i8 col); +agbx_i10 agbx_plot5(agbx_i8 x,agbx_i8 y,agbx_i10 col); #endif diff --git a/agbx/source/bs/done.c b/agbx/source/bs/done.c index 2616d80..6d56cb0 100644 --- a/agbx/source/bs/done.c +++ b/agbx/source/bs/done.c @@ -16,20 +16,20 @@ void agbx_done(agbx_err const _err) { __builtin_unreachable(); } /* Display the barcode-like error message: */ - agbx_set10(0x4000000u,0x403u); + agbx_set10(0x400'0000u,0x403u); agbx_i10 err[0x8u]; for (agbx_i8 pos = 0x0u;pos != 0x8u;++pos) {err[pos] = (agbx_i8)_err >> pos & 0x1u ? 0x19u : 0x0u;} for (agbx_i10 pos = 0x0u;pos != 0x9600u;pos += 0xF0u) { - agbx_setpx2(pos, err[0x0u]); - agbx_setpx2(pos + 0x1u,err[0x1u]); - agbx_setpx2(pos + 0x2u,err[0x2u]); - agbx_setpx2(pos + 0x3u,err[0x3u]); - agbx_setpx2(pos + 0x4u,err[0x4u]); - agbx_setpx2(pos + 0x5u,err[0x5u]); - agbx_setpx2(pos + 0x6u,err[0x6u]); - agbx_setpx2(pos + 0x7u,err[0x7u]); - agbx_setpx2(pos + 0x8u,0x0u); - agbx_setpx2(pos + 0x9u,0x19u); + agbx_setpx2(0x600'0000u,pos, err[0x0u]); + agbx_setpx2(0x600'0000u,pos + 0x1u,err[0x1u]); + agbx_setpx2(0x600'0000u,pos + 0x2u,err[0x2u]); + agbx_setpx2(0x600'0000u,pos + 0x3u,err[0x3u]); + agbx_setpx2(0x600'0000u,pos + 0x4u,err[0x4u]); + agbx_setpx2(0x600'0000u,pos + 0x5u,err[0x5u]); + agbx_setpx2(0x600'0000u,pos + 0x6u,err[0x6u]); + agbx_setpx2(0x600'0000u,pos + 0x7u,err[0x7u]); + agbx_setpx2(0x600'0000u,pos + 0x8u,0x0u); + agbx_setpx2(0x600'0000u,pos + 0x9u,0x19u); } __asm__ ( "swi 0x2\n" diff --git a/agbx/source/gfx/flip.c b/agbx/source/gfx/flip.c new file mode 100644 index 0000000..92b8939 --- /dev/null +++ b/agbx/source/gfx/flip.c @@ -0,0 +1,17 @@ +/* + Copyright 2022 Gabriel Jensen. + This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. + If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. +*/ + +#include <agbx/priv.h> + +#include <agbx/gfx.h> + +agbx_i20 agbx_flip(void) { + agbx_i10 dispcnt = agbx_get10(0x400'0000u); + dispcnt ^= 0b10000u; + agbx_set10(0x400'0000u,dispcnt); + if (dispcnt & 0x10000u) {return 0x600'A000u;} + return 0x600'0000u; +} diff --git a/agbx/source/gfx/plot.c b/agbx/source/gfx/plot.c index 2146c54..cc41d38 100644 --- a/agbx/source/gfx/plot.c +++ b/agbx/source/gfx/plot.c @@ -13,7 +13,7 @@ agbx_i10 agbx_plot3(agbx_i8 const _x,agbx_i8 const _y,agbx_i10 const _col) { if (_x >= 0xF0u || _y >= 0xA0u) {agbx_done(agbx_err_pos2big);} #endif agbx_i10 const px = _y * 0xF0u + _x; - __agbx_setpx2(px,_col) + __agbx_setpx2(0x600'0000u,px,_col) return px; } @@ -21,8 +21,9 @@ agbx_i10 agbx_plot4(agbx_i8 const _x,agbx_i8 const _y,agbx_i8 const _col) { #if defined(__agbx_dbg) if (_x >= 0xF0u || _y >= 0xA0u) {agbx_done(agbx_err_pos2big);} #endif + agbx_i20 const vaddr = 0x600'0000u + (agbx_get10(0x400'0000u) >> 0x4u & 0x1u) * 0xA000u; agbx_i10 const px = _y * 0xF0u + _x; - __agbx_setpx1(px,_col) + agbx_setpx1(vaddr,px,_col); return px; } @@ -30,7 +31,8 @@ agbx_i10 agbx_plot5(agbx_i8 const _x,agbx_i8 const _y,agbx_i10 const _col) { #if defined(__agbx_dbg) if (_x >= 0xA0u || _y >= 0x80u) {agbx_done(agbx_err_pos2big);} #endif - agbx_i10 const px = _y * 0xA0u + _x; - __agbx_setpx2(px,_col) + agbx_i20 const vaddr = 0x600'0000u + (agbx_get10(0x400'0000u) >> 0x4u & 0x1u) * 0xA000u; + agbx_i10 const px = _y * 0xF0u + _x; + __agbx_setpx2(vaddr,px,_col) return px; } diff --git a/agbx/source/gfx/setpx.c b/agbx/source/gfx/setpx.c index 563fd3b..b2c5c2d 100644 --- a/agbx/source/gfx/setpx.c +++ b/agbx/source/gfx/setpx.c @@ -8,19 +8,24 @@ #include <agbx/gfx.h> -void agbx_setpx1(agbx_i10 const _px,agbx_i8 const _col) { +void agbx_setpx1(agbx_i20 const _vaddr,agbx_i10 const _px,agbx_i8 const _col) { #if defined(__agbx_dbg) - agbx_i10 const dispcnt = agbx_get10(0x4000000u); + agbx_i10 const dispcnt = agbx_get10(0x400'0000u); agbx_i8 const md = dispcnt & 0x7u; - if (md == 0x3u || md == 0x5u) {agbx_done(agbx_err_badmd);} - if (_px >= 0x9600u) {agbx_done(agbx_err_px2big);} + if (md != 0x4u) {agbx_done(agbx_err_badmd);} + if (_px >= 0x9600u) {agbx_done(agbx_err_px2big);} #endif - __agbx_setpx1(_px,_col) + /* We can only write halfwords to VRAM, so we load the adjacent pixel value and combine it into a halfword. */ + agbx_i20 const addr = _vaddr + _px - (_px & 0x1u) * 0x1u; + agbx_i10 col; + if (_px & 0x1u) {col = (agbx_i10)agbx_get8(addr) | (agbx_i10)_col << 0x8u;} + else {col = (agbx_i10)agbx_get8(addr + 0x1u) << 0x8u | (agbx_i10)_col;} + __agbx_set10(addr,col) } -void agbx_setpx2(agbx_i10 const _px,agbx_i10 const _col) { +void agbx_setpx2(agbx_i20 const _vaddr,agbx_i10 const _px,agbx_i10 const _col) { #if defined(__agbx_dbg) - agbx_i10 const dispcnt = agbx_get10(0x4000000u); + agbx_i10 const dispcnt = agbx_get10(0x400'0000u); agbx_i8 const md = dispcnt & 0x7u; if (md == 0x4u) {agbx_done(agbx_err_badmd);} if (md == 0x5u) { @@ -31,5 +36,5 @@ void agbx_setpx2(agbx_i10 const _px,agbx_i10 const _col) { if (_px >= 0x9600u) {agbx_done(agbx_err_px2big);} } #endif - __agbx_setpx2(_px,_col) + __agbx_setpx2(_vaddr,_px,_col) } diff --git a/agbx/source/key/getkeymap.c b/agbx/source/key/getkeymap.c index 457bf42..fe24c6c 100644 --- a/agbx/source/key/getkeymap.c +++ b/agbx/source/key/getkeymap.c @@ -10,6 +10,6 @@ agbx_keymap agbx_getkeymap(void) { agbx_keymap map; - map._keys = agbx_get10(0x4000130u); + map._keys = agbx_get10(0x400'0130u); return map; } diff --git a/demo/demo.c b/demo/demo.c index 9784ec2..d82e333 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -2,12 +2,15 @@ #include <agbx/gfx.h> agbx_err agbx_main(void) { - agbx_set10(0x4000000u,0x403u); + agbx_set10(0x500'0000u,0x0u); + agbx_set10(0x500'0002u,0x19u); + agbx_set10(0x500'0004u,0xFFFFu); + agbx_set10(0x400'0000u,0x404u); struct { agbx_i8 x; agbx_i8 y; } pos = {.x = 0x0u,.y = 0x0u,}; - agbx_setpx2(0x0u,0xFFFFu); + agbx_setpx1(0x600'0000u,0x0u,0x2u); for (;;) { agbx_keymap const keymap = agbx_getkeymap(); if (agbx_chkkey(keymap,agbx_key_b)) { @@ -16,40 +19,46 @@ agbx_err agbx_main(void) { if (agbx_chkkey(keymap,agbx_key_a)) { return agbx_err_ok; } + if (agbx_chkkey(keymap,agbx_key_l)) { + agbx_plot4(pos.x,pos.y,0x1u); + agbx_flip(); + agbx_plot4(pos.x,pos.y,0x2u); + while (agbx_chkkey(agbx_getkeymap(),agbx_key_l)) {} + continue; + } typeof (pos) const prevpos = pos; - agbx_key key; - if (agbx_chkkey(keymap,agbx_key_pade)) { + agbx_key key = agbx_key_pade; + if (agbx_chkkey(keymap,key)) { if (pos.x != 0xEFu) { - key = agbx_key_pade; ++pos.x; goto drw; } } - if (agbx_chkkey(keymap,agbx_key_padn)) { + key = agbx_key_padn; + if (agbx_chkkey(keymap,key)) { if (pos.y != 0x0u) { - key = agbx_key_padn; --pos.y; goto drw; } } - if (agbx_chkkey(keymap,agbx_key_pads)) { + key = agbx_key_pads; + if (agbx_chkkey(keymap,key)) { if (pos.y != 0x9Fu) { - key = agbx_key_pads; ++pos.y; goto drw; } } - if (agbx_chkkey(keymap,agbx_key_padw)) { + key = agbx_key_padw; + if (agbx_chkkey(keymap,key)) { if (pos.x != 0x0u) { - key = agbx_key_padw; --pos.x; goto drw; } } continue; drw:; - agbx_plot3(prevpos.x,prevpos.y,0x19u); - agbx_plot3(pos.x,pos.y,0xFFFFu); + agbx_plot4(prevpos.x,prevpos.y,0x1u); + agbx_plot4(pos.x,pos.y,0x2u); while (agbx_chkkey(agbx_getkeymap(),key)) {} } } |