summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorDaniel Hader <[email protected]>2026-08-28 21:27:29 -0500
committerDaniel Hader <[email protected]>2026-08-28 21:27:29 -0500
commit0f383adcdc02cad8dfb435ce73c1fe1c0c4b5bd6 (patch)
tree917569ca76e2160595f071c0c07834e3244ff6cd /source
parent77e153f99cb279c1deb5b257fb54c7fdbdd4bc19 (diff)
sprite proof of concept and improved display control bit flaggingHEADmain
Diffstat (limited to 'source')
-rw-r--r--source/main.cpp29
-rw-r--r--source/util.hpp127
2 files changed, 144 insertions, 12 deletions
diff --git a/source/main.cpp b/source/main.cpp
index 21d1c26..116094c 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -8,6 +8,7 @@ void bad_vsync() {
}
int main() {
+ // background control
auto bg_flags = BGControlFlags()
.set_charblock_base(0)
.set_screenblock_base(28)
@@ -16,6 +17,7 @@ int main() {
set_bg_control(0, bg_flags);
set_bg_offsets(0, 0, 0);
+ // background tiles
const Tile4 tiles[2] = {
{{0x11111111, 0x01111111, 0x01111111, 0x01111111, 0x01111111, 0x01111111, 0x01111111, 0x00000001}},
{{0x00000000, 0x00100100, 0x01100110, 0x00011000, 0x00011000, 0x01100110, 0x00100100, 0x00000000}},
@@ -24,11 +26,13 @@ int main() {
set_tile(0, 0, tiles[0]);
set_tile(0, 1, tiles[1]);
+ // background tiles
set_bg_palette(0, 1, Color::from_rgb(31, 0, 0));
set_bg_palette(1, 1, Color::from_rgb( 0, 31, 0));
set_bg_palette(2, 1, Color::from_rgb( 0, 0, 31));
set_bg_palette(3, 1, Color::from_rgb(16, 16, 16));
+ // background screen entries
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 32*32; j++) {
auto screen_entry = ScreenEntry()
@@ -38,7 +42,30 @@ int main() {
}
}
- set_display_control(Mode0, BG0);
+ // object palettes
+ set_obj_palette(0, 1, Color::from_rgb(0, 0, 0));
+ set_obj_palette(0, 2, Color::from_rgb(31, 31, 0));
+
+ // object attributes
+ auto obj_attr = ObjectAttributes()
+ .set_size(ObjectAttributes::Size_16x16)
+ .set_tile_index(0)
+ .set_palette_bank(0)
+ .set_x(50).set_y(50);
+
+ set_obj_attributes(0, obj_attr);
+
+ Tile4 obj_tile = {0x01230123, 0x01230123, 0x01230123, 0x01230123, 0x01230123, 0x01230123, 0x01230123, 0x01230123};
+ for (u32 i = 0; i < 4; i++) {
+ set_tile(4, i, obj_tile);
+ }
+
+ auto display_control_flags = DisplayControlFlags()
+ .set_mode(0)
+ .enable_layer(BG0)
+ .enable_layer(Obj)
+ .set_1d_object_mapping(1);
+ set_display_control(display_control_flags);
s16 x = 0, y = 0;
while (1) {
diff --git a/source/util.hpp b/source/util.hpp
index 88a29ca..c034fe5 100644
--- a/source/util.hpp
+++ b/source/util.hpp
@@ -24,18 +24,40 @@ enum DisplayControlLayer : u16 {
BG1 = 0x0200,
BG2 = 0x0400,
BG3 = 0x0800,
- BG4 = 0x1000,
+ Obj = 0x1000,
};
-typedef u16 DisplayControlFlags;
+struct DisplayControlFlags {
+ u16 data;
-constexpr DisplayControlFlags operator|(DisplayControlMode mode, DisplayControlLayer layer) {
- return static_cast<DisplayControlFlags>(static_cast<u16>(mode) | static_cast<u16>(layer));
-}
+ enum Layer : u16 {
+ BG0 = 0x0100,
+ BG1 = 0x0200,
+ BG2 = 0x0400,
+ BG3 = 0x0800,
+ Obj = 0x1000,
+ };
+
+ constexpr DisplayControlFlags() : data(0) {}
+ constexpr DisplayControlFlags &set_mode(u16 mode) {
+ assert(mode < 6);
+ this->data = (this->data & ~0x0007) | mode;
+ return *this;
+ }
+ constexpr DisplayControlFlags &enable_layer(u16 layer) {
+ this->data |= layer;
+ return *this;
+ }
+ constexpr DisplayControlFlags &set_1d_object_mapping(u16 enabled) {
+ this->data = (this->data & ~0x0040) | ((!!enabled) << 6);
+ return *this;
+ }
+ constexpr operator u16() const { return data; }
+};
-static inline void set_display_control(DisplayControlMode mode, DisplayControlLayer layer) {
- static volatile DisplayControlFlags* const display_control = reinterpret_cast<DisplayControlFlags*>(0x04000000);
- *display_control = mode | layer;
+static inline void set_display_control(const DisplayControlFlags &flags) {
+ static volatile u16* const display_control = reinterpret_cast<volatile u16*>(0x04000000);
+ *display_control = flags;
}
enum BGControlColorMode : u16 {
@@ -134,9 +156,9 @@ struct ScreenEntry {
constexpr ScreenEntry() : data(0) {}
- constexpr ScreenEntry &set_tile_index(u16 tid) {
- assert(tid < 1024);
- this->data = (this->data & ~0x03ff) | tid;
+ constexpr ScreenEntry &set_tile_index(u16 index) {
+ assert(index < 1024);
+ this->data = (this->data & ~0x03ff) | index;
return *this;
}
@@ -161,6 +183,80 @@ struct ScreenEntry {
typedef ScreenEntry ScreenBlock[1024];
+struct ObjectAttributes {
+ u16 attr0, attr1, attr2, _fill;
+
+ enum ObjectMode : u16 {
+ ModeDefault = 0x0000,
+ ModeHidden = 0x0020,
+ ModeAffine = 0x0010,
+ ModeDouble = 0x0030,
+ };
+
+ enum GraphicsMode : u16 {
+ GraphicsDefault = 0x0000,
+ GraphicsBlend = 0x0400,
+ GraphicsWindow = 0x0800,
+ };
+
+ enum Size : u16 {
+ Size_8x8 = 0x0000,
+ Size_16x16 = 0x0001,
+ Size_32x32 = 0x0002,
+ Size_64x64 = 0x0003,
+ Size_16x8 = 0x0100,
+ Size_32x8 = 0x0101,
+ Size_32x16 = 0x0102,
+ Size_32x64 = 0x0103,
+ Size_8x16 = 0x0200,
+ Size_8x32 = 0x0201,
+ Size_16x32 = 0x0202,
+ Size_64x32 = 0x0203,
+ };
+
+ constexpr ObjectAttributes() : attr0(0), attr1(0), attr2(0), _fill(0) {}
+
+ constexpr ObjectAttributes &set_x(u16 x) {
+ assert(x < 256);
+ this->attr1 = (this->attr1 & ~0x000f) | x;
+ return *this;
+ }
+
+ constexpr ObjectAttributes &set_y(u16 y) {
+ assert(y < 256);
+ this->attr0 = (this->attr0 & ~0x000f) | y;
+ return *this;
+ }
+
+ constexpr ObjectAttributes &set_object_mode(ObjectMode mode) {
+ this->attr0 = (this->attr0 & ~0x0030) | mode;
+ return *this;
+ }
+
+ constexpr ObjectAttributes &set_graphics_mode(GraphicsMode mode) {
+ this->attr0 = (this->attr0 & ~0x00c0) | mode;
+ return *this;
+ }
+
+ constexpr ObjectAttributes &set_size(Size size) {
+ this->attr0 = (this->attr0 & ~0xc000) | ((size & 0x0300) << 6);
+ this->attr1 = (this->attr1 & ~0xc000) | ((size & 0x0003) << 14);
+ return *this;
+ }
+
+ constexpr ObjectAttributes &set_tile_index(u16 index) {
+ assert(index < 1024);
+ this->attr2 = (this->attr2 & ~0x003f) | index;
+ return *this;
+ }
+
+ constexpr ObjectAttributes &set_palette_bank(u16 bank) {
+ assert(bank < 16);
+ this->attr2 = (this->attr2 & ~0xf000) | (bank << 12);
+ return *this;
+ }
+};
+
template <typename T>
static inline void volatile_copy(volatile T* dst, const T* src) {
using U = std::conditional_t<(sizeof(T) % sizeof(u32) == 0) && (alignof(T) % alignof(u32) == 0), u32, u16>;
@@ -184,10 +280,19 @@ static inline void set_bg_palette(u32 bank, u32 index, const Color &color) {
volatile_copy(&banks[bank][index], &color);
}
+static inline void set_obj_palette(u32 bank, u32 index, const Color &color) {
+ volatile PaletteBank *const banks = reinterpret_cast<volatile PaletteBank*>(0x05000200);
+ volatile_copy(&banks[bank][index], &color);
+}
static inline void set_screen_entry(u32 block, u32 index, const ScreenEntry &entry) {
volatile ScreenBlock *const blocks = reinterpret_cast<volatile ScreenBlock*>(0x06000000);
volatile_copy(&blocks[block][index], &entry);
}
+static inline void set_obj_attributes(u32 index, const ObjectAttributes &attr) {
+ volatile ObjectAttributes *const attrs = reinterpret_cast<volatile ObjectAttributes*>(0x07000000);
+ volatile_copy(&attrs[index], &attr);
+}
+
#endif