summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.txt10
-rw-r--r--GNUmakefile30
-rw-r--r--README.html11
-rw-r--r--agbx/GNUmakefile5
-rw-r--r--agbx/include-private/agbx/priv.h9
-rw-r--r--agbx/include/agbx/bs.h8
-rw-r--r--agbx/include/agbx/gfx.h12
-rw-r--r--agbx/source/bs/done.c22
-rw-r--r--agbx/source/gfx/flip.c17
-rw-r--r--agbx/source/gfx/plot.c10
-rw-r--r--agbx/source/gfx/setpx.c21
-rw-r--r--agbx/source/key/getkeymap.c2
-rw-r--r--demo/demo.c35
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)) {}
}
}