From 0f383adcdc02cad8dfb435ce73c1fe1c0c4b5bd6 Mon Sep 17 00:00:00 2001 From: Daniel Hader Date: Fri, 28 Aug 2026 21:27:29 -0500 Subject: sprite proof of concept and improved display control bit flagging --- source/util.hpp | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 116 insertions(+), 11 deletions(-) (limited to 'source/util.hpp') 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(static_cast(mode) | static_cast(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(0x04000000); - *display_control = mode | layer; +static inline void set_display_control(const DisplayControlFlags &flags) { + static volatile u16* const display_control = reinterpret_cast(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 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(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(0x06000000); volatile_copy(&blocks[block][index], &entry); } +static inline void set_obj_attributes(u32 index, const ObjectAttributes &attr) { + volatile ObjectAttributes *const attrs = reinterpret_cast(0x07000000); + volatile_copy(&attrs[index], &attr); +} + #endif -- cgit v1.2.3