Compare commits

...

3 Commits

Author SHA1 Message Date
f6ef2b5acb [turbine,nostalgia] Make memory regions cast to bounded ox::Arrays
All checks were successful
Build / build (push) Successful in 1m16s
2025-06-29 23:32:36 -05:00
bf958a4a6e [teagba] Make memory regions cast to bounded ox::Arrays 2025-06-29 23:32:11 -05:00
6a70e478a6 [nostalgia/gfx] Cleanup 2025-06-29 17:46:13 -05:00
4 changed files with 43 additions and 49 deletions

View File

@@ -5,6 +5,8 @@
#pragma once #pragma once
#include <ox/std/array.hpp> #include <ox/std/array.hpp>
#include <ox/std/span.hpp>
#include <ox/std/units.hpp>
#include <ox/std/types.hpp> #include <ox/std/types.hpp>
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
@@ -49,7 +51,7 @@ using BgCtl = uint16_t;
#define REG_BG3CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000e) #define REG_BG3CTL *reinterpret_cast<volatile BgCtl*>(0x0400'000e)
[[nodiscard]] [[nodiscard]]
inline volatile BgCtl &regBgCtl(uintptr_t bgIdx) noexcept { inline volatile BgCtl &regBgCtl(uintptr_t const bgIdx) noexcept {
return *reinterpret_cast<volatile BgCtl*>(0x0400'0008 + 2 * bgIdx); return *reinterpret_cast<volatile BgCtl*>(0x0400'0008 + 2 * bgIdx);
} }
@@ -60,7 +62,7 @@ inline volatile BgCtl &regBgCtl(uintptr_t bgIdx) noexcept {
#define REG_BG3HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001c) #define REG_BG3HOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001c)
[[nodiscard]] [[nodiscard]]
inline volatile uint32_t &regBgHofs(auto bgIdx) noexcept { volatile uint32_t &regBgHofs(auto const bgIdx) noexcept {
return *reinterpret_cast<volatile uint32_t*>(0x0400'0010 + 4 * bgIdx); return *reinterpret_cast<volatile uint32_t*>(0x0400'0010 + 4 * bgIdx);
} }
@@ -71,7 +73,7 @@ inline volatile uint32_t &regBgHofs(auto bgIdx) noexcept {
#define REG_BG3VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001e) #define REG_BG3VOFS *reinterpret_cast<volatile uint32_t*>(0x0400'001e)
[[nodiscard]] [[nodiscard]]
inline volatile uint32_t &regBgVofs(auto bgIdx) noexcept { volatile uint32_t &regBgVofs(auto const bgIdx) noexcept {
return *reinterpret_cast<volatile uint32_t*>(0x0400'0012 + 4 * bgIdx); return *reinterpret_cast<volatile uint32_t*>(0x0400'0012 + 4 * bgIdx);
} }
@@ -83,25 +85,23 @@ inline volatile uint32_t &regBgVofs(auto bgIdx) noexcept {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// Memory Addresses // Memory Addresses
#define MEM_EWRAM_BEGIN reinterpret_cast<uint8_t*>(0x0200'0000) #define MEM_EWRAM (*reinterpret_cast<ox::Array<uint16_t, 0x0203'FFFF - 0x0200'0000>*>(0x0200'0000))
#define MEM_EWRAM_END reinterpret_cast<uint8_t*>(0x0203'FFFF)
#define MEM_IWRAM_BEGIN reinterpret_cast<uint8_t*>(0x0300'0000) #define MEM_IWRAM (*reinterpret_cast<ox::Array<uint8_t, 0x0300'7FFF - 0x0300'0000>*>(0x0300'0000))
#define MEM_IWRAM_END reinterpret_cast<uint8_t*>(0x0300'7FFF)
#define REG_BLNDCTL *reinterpret_cast<uint16_t*>(0x0400'0050) #define REG_BLNDCTL *reinterpret_cast<uint16_t*>(0x0400'0050)
#define MEM_BG_PALETTE reinterpret_cast<uint16_t*>(0x0500'0000) using Palette = ox::Array<uint16_t, 128>;
#define MEM_SPRITE_PALETTE reinterpret_cast<uint16_t*>(0x0500'0200) #define MEM_BG_PALETTE (*reinterpret_cast<::Palette*>(0x0500'0000))
#define MEM_SPRITE_PALETTE (*reinterpret_cast<::Palette*>(0x0500'0200))
using BgMapTile = ox::Array<uint16_t, 8192>; using BgMapTile = ox::Array<uint16_t, 8192>;
#define MEM_BG_TILES reinterpret_cast<BgMapTile*>(0x0600'0000) #define MEM_BG_TILES (*reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'0000))
#define MEM_BG_MAP reinterpret_cast<BgMapTile*>(0x0600'e000) #define MEM_BG_MAP (*reinterpret_cast<ox::Array<BgMapTile, 4>*>(0x0600'e000))
#define MEM_SPRITE_TILES reinterpret_cast<uint16_t*>(0x0601'0000) #define MEM_SPRITE_TILES (*reinterpret_cast<ox::Array<uint16_t, 32 * ox::units::KB>*>(0x0601'0000))
#define MEM_OAM reinterpret_cast<uint64_t*>(0x0700'0000) #define MEM_OAM (*reinterpret_cast<ox::Array<uint64_t, 64>*>(0x0700'0000))
#define MEM_ROM reinterpret_cast<char*>(0x0800'0000) #define MEM_ROM (*reinterpret_cast<ox::Array<char, 32 * ox::units::MB>*>(0x0700'0000))
#define MEM_SRAM reinterpret_cast<char*>(0x0e00'0000) #define MEM_SRAM (*reinterpret_cast<ox::Array<char, 64 * ox::units::KB>*>(0x0e00'0000))
#define MEM_SRAM_SIZE 65535

View File

@@ -35,11 +35,6 @@ class Context {
Context(Context const &&other) noexcept = delete; Context(Context const &&other) noexcept = delete;
virtual ~Context() noexcept = default; virtual ~Context() noexcept = default;
[[nodiscard]]
ox::MemFS const &rom() const noexcept {
return static_cast<ox::MemFS const&>(*turbine::rom(turbineCtx));
}
}; };
void safeDelete(Context *ctx) noexcept { void safeDelete(Context *ctx) noexcept {
@@ -81,7 +76,7 @@ ox::Error loadBgPalette(
if (palette.pages.empty()) { if (palette.pages.empty()) {
return {}; return {};
} }
auto const paletteMem = MEM_BG_PALETTE + palBank * 16; auto const paletteMem = ox::Span{MEM_BG_PALETTE} + palBank * 16;
for (auto i = 0u; i < colorCnt(palette, page); ++i) { for (auto i = 0u; i < colorCnt(palette, page); ++i) {
paletteMem[i] = color(palette, page, i); paletteMem[i] = color(palette, page, i);
} }
@@ -95,9 +90,8 @@ ox::Error loadSpritePalette(
if (palette.pages.empty()) { if (palette.pages.empty()) {
return {}; return {};
} }
auto const paletteMem = MEM_SPRITE_PALETTE;
for (auto i = 0u; i < colorCnt(palette, page); ++i) { for (auto i = 0u; i < colorCnt(palette, page); ++i) {
paletteMem[i] = color(palette, page, i); MEM_SPRITE_PALETTE[i] = color(palette, page, i);
} }
return {}; return {};
} }
@@ -240,7 +234,7 @@ ox::Error loadSpriteTileSheet(
Context &ctx, Context &ctx,
TileSheetSet const &set) noexcept { TileSheetSet const &set) noexcept {
auto const bpp = static_cast<unsigned>(set.bpp); auto const bpp = static_cast<unsigned>(set.bpp);
OX_RETURN_ERROR(loadTileSheetSet(ctx, {MEM_SPRITE_TILES, 32 * ox::units::KB}, set)); OX_RETURN_ERROR(loadTileSheetSet(ctx, MEM_SPRITE_TILES, set));
setSpritesBpp(bpp); setSpritesBpp(bpp);
return {}; return {};
} }
@@ -349,9 +343,9 @@ void panic(char const *file, int line, char const *panicMsg, ox::Error const &er
using namespace nostalgia::gfx; using namespace nostalgia::gfx;
// reset heap to make sure we have enough memory to allocate context data // reset heap to make sure we have enough memory to allocate context data
OX_ALLOW_UNSAFE_BUFFERS_BEGIN OX_ALLOW_UNSAFE_BUFFERS_BEGIN
auto const heapBegin = reinterpret_cast<char*>(MEM_EWRAM_BEGIN); auto const heapBegin = reinterpret_cast<char*>(MEM_EWRAM.data());
auto const heapSz = (MEM_EWRAM_END - MEM_EWRAM_BEGIN) / 2; auto const heapSz = MEM_EWRAM.size() / 2;
auto const heapEnd = reinterpret_cast<char*>(MEM_EWRAM_BEGIN + heapSz); auto const heapEnd = reinterpret_cast<char*>(MEM_EWRAM.data() + heapSz);
ox::heapmgr::initHeap(heapBegin, heapEnd); ox::heapmgr::initHeap(heapBegin, heapEnd);
OX_ALLOW_UNSAFE_BUFFERS_END OX_ALLOW_UNSAFE_BUFFERS_END
auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap(); auto tctx = turbine::init(keel::loadRomFs("").unwrap(), "Nostalgia").unwrap();

View File

@@ -453,7 +453,7 @@ static void drawBackgrounds(
} }
} }
static void drawSprites(Context &ctx, ox::Size const&renderSz) noexcept { static void drawSprites(Context &ctx, ox::Size const &renderSz) noexcept {
glUseProgram(ctx.spriteShader); glUseProgram(ctx.spriteShader);
auto &sb = ctx.spriteBlocks; auto &sb = ctx.spriteBlocks;
auto const uniformXScale = glGetUniformLocation(ctx.bgShader, "vXScale"); auto const uniformXScale = glGetUniformLocation(ctx.bgShader, "vXScale");
@@ -481,7 +481,7 @@ static void loadPalette(
ox::Array<GLfloat, 1024> &palette, ox::Array<GLfloat, 1024> &palette,
size_t const palOffset, size_t const palOffset,
GLuint const shaderPgrm, GLuint const shaderPgrm,
CompactPalette const&pal, CompactPalette const &pal,
size_t const page = 0) noexcept { size_t const page = 0) noexcept {
static constexpr std::size_t ColorCnt = 256; static constexpr std::size_t ColorCnt = 256;
for (auto i = palOffset; auto const c : pal.pages[page]) { for (auto i = palOffset; auto const c : pal.pages[page]) {
@@ -500,7 +500,7 @@ static void loadPalette(
static void setSprite( static void setSprite(
Context &ctx, Context &ctx,
uint_t const idx, uint_t const idx,
Sprite const&s) noexcept { Sprite const &s) noexcept {
// Tonc Table 8.4 // Tonc Table 8.4
struct Sz { uint_t x{}, y{}; }; struct Sz { uint_t x{}, y{}; };
static constexpr ox::Array<Sz, 12> dimensions{ static constexpr ox::Array<Sz, 12> dimensions{
@@ -574,7 +574,7 @@ static void setSprite(
} }
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params) noexcept { ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const &params) noexcept {
auto ctx = ox::make_unique<Context>(tctx, params); auto ctx = ox::make_unique<Context>(tctx, params);
auto const bgVshad = ox::sfmt(renderer::bgvshadTmpl, gl::GlslVersion); auto const bgVshad = ox::sfmt(renderer::bgvshadTmpl, gl::GlslVersion);
auto const bgFshad = ox::sfmt(renderer::bgfshadTmpl, gl::GlslVersion); auto const bgFshad = ox::sfmt(renderer::bgfshadTmpl, gl::GlslVersion);
@@ -604,7 +604,7 @@ struct TileSheetData {
}; };
static ox::Result<TileSheetData> normalizeTileSheet static ox::Result<TileSheetData> normalizeTileSheet
(CompactTileSheet const&ts) noexcept { (CompactTileSheet const &ts) noexcept {
const uint_t bytesPerTile = ts.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2; const uint_t bytesPerTile = ts.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
auto const tiles = ts.pixels.size() / bytesPerTile; auto const tiles = ts.pixels.size() / bytesPerTile;
constexpr int width = 8; constexpr int width = 8;
@@ -632,7 +632,7 @@ static ox::Result<TileSheetData> normalizeTileSheet
ox::Error loadBgPalette( ox::Error loadBgPalette(
Context &ctx, Context &ctx,
size_t const palBank, size_t const palBank,
CompactPalette const&palette, CompactPalette const &palette,
size_t const page) noexcept { size_t const page) noexcept {
renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, palette, page); renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, palette, page);
return {}; return {};
@@ -640,7 +640,7 @@ ox::Error loadBgPalette(
ox::Error loadSpritePalette( ox::Error loadSpritePalette(
Context &ctx, Context &ctx,
CompactPalette const&palette, CompactPalette const &palette,
size_t const page) noexcept { size_t const page) noexcept {
ox::Array<GLfloat, 1024> pal; ox::Array<GLfloat, 1024> pal;
renderer::loadPalette(pal, 0, ctx.spriteShader, palette, page); renderer::loadPalette(pal, 0, ctx.spriteShader, palette, page);
@@ -649,14 +649,14 @@ ox::Error loadSpritePalette(
static ox::Result<TileSheetData> buildSetTsd( static ox::Result<TileSheetData> buildSetTsd(
Context const &ctx, Context const &ctx,
TileSheetSet const&set) noexcept { TileSheetSet const &set) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx); auto &kctx = keelCtx(ctx.turbineCtx);
TileSheetData setTsd; TileSheetData setTsd;
setTsd.width = TileWidth; setTsd.width = TileWidth;
for (auto const&entry : set.entries) { for (auto const &entry : set.entries) {
OX_REQUIRE(tilesheet, readObj<CompactTileSheet>(kctx, entry.tilesheet)); OX_REQUIRE(tilesheet, readObj<CompactTileSheet>(kctx, entry.tilesheet));
OX_REQUIRE(tsd, normalizeTileSheet(*tilesheet)); OX_REQUIRE(tsd, normalizeTileSheet(*tilesheet));
for (auto const&s : entry.sections) { for (auto const &s : entry.sections) {
auto const size = s.tiles * PixelsPerTile; auto const size = s.tiles * PixelsPerTile;
for (auto i = 0; i < size; ++i) { for (auto i = 0; i < size; ++i) {
auto const srcIdx = static_cast<size_t>(i) + static_cast<size_t>(s.begin * PixelsPerTile); auto const srcIdx = static_cast<size_t>(i) + static_cast<size_t>(s.begin * PixelsPerTile);
@@ -669,7 +669,7 @@ static ox::Result<TileSheetData> buildSetTsd(
} }
static void copyPixels( static void copyPixels(
CompactTileSheet const&ts, CompactTileSheet const &ts,
ox::Span<uint32_t> const dst, ox::Span<uint32_t> const dst,
size_t const srcPxIdx, size_t const srcPxIdx,
size_t const pxlCnt) noexcept { size_t const pxlCnt) noexcept {
@@ -704,7 +704,7 @@ void clearCbbs(Context &ctx) noexcept {
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
unsigned const cbb, unsigned const cbb,
CompactTileSheet const&ts, CompactTileSheet const &ts,
size_t const dstTileIdx, size_t const dstTileIdx,
size_t const srcTileIdx, size_t const srcTileIdx,
size_t const tileCnt) noexcept { size_t const tileCnt) noexcept {
@@ -728,8 +728,8 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
uint_t const cbb, uint_t const cbb,
CompactTileSheet const&ts, CompactTileSheet const &ts,
ox::Optional<unsigned> const&paletteBank) noexcept { ox::Optional<unsigned> const &paletteBank) noexcept {
auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4))); auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4)));
auto const tiles = ts.pixels.size() / bytesPerTile; auto const tiles = ts.pixels.size() / bytesPerTile;
OX_RETURN_ERROR(loadBgTileSheet(ctx, cbb, ts, 0, 0, tiles)); OX_RETURN_ERROR(loadBgTileSheet(ctx, cbb, ts, 0, 0, tiles));
@@ -742,7 +742,7 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
unsigned const cbb, unsigned const cbb,
TileSheetSet const&set) noexcept { TileSheetSet const &set) noexcept {
OX_REQUIRE(setTsd, buildSetTsd(ctx, set)); OX_REQUIRE(setTsd, buildSetTsd(ctx, set));
ctx.cbbs[cbb].tex = renderer::createTexture(setTsd.width, setTsd.height, setTsd.pixels.data()); ctx.cbbs[cbb].tex = renderer::createTexture(setTsd.width, setTsd.height, setTsd.pixels.data());
return {}; return {};
@@ -750,7 +750,7 @@ ox::Error loadBgTileSheet(
ox::Error loadSpriteTileSheet( ox::Error loadSpriteTileSheet(
Context &ctx, Context &ctx,
CompactTileSheet const&ts, CompactTileSheet const &ts,
bool const loadDefaultPalette) noexcept { bool const loadDefaultPalette) noexcept {
OX_REQUIRE(tsd, normalizeTileSheet(ts)); OX_REQUIRE(tsd, normalizeTileSheet(ts));
oxTracef("nostalgia.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height); oxTracef("nostalgia.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height);
@@ -763,7 +763,7 @@ ox::Error loadSpriteTileSheet(
ox::Error loadSpriteTileSheet( ox::Error loadSpriteTileSheet(
Context &ctx, Context &ctx,
TileSheetSet const&set) noexcept { TileSheetSet const &set) noexcept {
OX_REQUIRE(setTsd, buildSetTsd(ctx, set)); OX_REQUIRE(setTsd, buildSetTsd(ctx, set));
ctx.spriteBlocks.tex = renderer::createTexture(setTsd.width, setTsd.height, setTsd.pixels.data()); ctx.spriteBlocks.tex = renderer::createTexture(setTsd.width, setTsd.height, setTsd.pixels.data());
return {}; return {};
@@ -774,7 +774,7 @@ void setBgTile(
uint_t const bgIdx, uint_t const bgIdx,
int const column, int const column,
int const row, int const row,
BgTile const&tile) noexcept { BgTile const &tile) noexcept {
oxTracef( oxTracef(
"nostalgia.gfx.setBgTile", "nostalgia.gfx.setBgTile",
"bgIdx: {}, column: {}, row: {}, tile: {}, palBank: {}", "bgIdx: {}, column: {}, row: {}, tile: {}, palBank: {}",
@@ -853,7 +853,7 @@ void showSprite(Context &ctx, uint_t const idx) noexcept {
renderer::setSprite(ctx, idx, s); renderer::setSprite(ctx, idx, s);
} }
void setSprite(Context &ctx, uint_t const idx, Sprite const&sprite) noexcept { void setSprite(Context &ctx, uint_t const idx, Sprite const &sprite) noexcept {
auto &s = ctx.spriteStates[idx]; auto &s = ctx.spriteStates[idx];
s = sprite; s = sprite;
renderer::setSprite(ctx, idx, s); renderer::setSprite(ctx, idx, s);
@@ -869,7 +869,7 @@ ox::Size drawSize(int const scale) noexcept {
return {240 * scale, 160 * scale}; return {240 * scale, 160 * scale};
} }
void draw(Context &ctx, ox::Size const&renderSz) noexcept { void draw(Context &ctx, ox::Size const &renderSz) noexcept {
glViewport(0, 0, renderSz.width, renderSz.height); glViewport(0, 0, renderSz.width, renderSz.height);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND); glEnable(GL_BLEND);

View File

@@ -50,7 +50,7 @@ OX_ALLOW_UNSAFE_BUFFERS_BEGIN
constexpr auto headerP1Len = ox::strlen(headerP2); constexpr auto headerP1Len = ox::strlen(headerP2);
constexpr auto headerP2Len = ox::strlen(headerP1); constexpr auto headerP2Len = ox::strlen(headerP1);
constexpr auto headerLen = headerP1Len + headerP2Len; constexpr auto headerLen = headerP1Len + headerP2Len;
for (auto current = MEM_ROM; current < reinterpret_cast<char*>(0x0a000000); current += headerLen) { for (auto current = MEM_ROM.data(); current < reinterpret_cast<char*>(0x0a000000); current += headerLen) {
if (memcmp(current, headerP1, headerP1Len) == 0 && if (memcmp(current, headerP1, headerP1Len) == 0 &&
memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) { memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) {
return reinterpret_cast<std::size_t>(current + headerLen); return reinterpret_cast<std::size_t>(current + headerLen);