[nostalgia/core] Cleanup graphics API

This commit is contained in:
Gary Talent 2023-12-21 21:18:31 -06:00
parent 8395128efa
commit d29118d783
8 changed files with 268 additions and 288 deletions

View File

@ -13,8 +13,6 @@
namespace nostalgia::core { namespace nostalgia::core {
extern ox::Array<char, 128> charMap;
struct Sprite { struct Sprite {
bool enabled = false; bool enabled = false;
int x = 0; int x = 0;
@ -41,11 +39,35 @@ oxModelBegin(Sprite)
oxModelField(priority) oxModelField(priority)
oxModelEnd() oxModelEnd()
ox::Error loadBgPalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept;
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
bool loadDefaultPalette = false) noexcept;
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
bool loadDefaultPalette = false) noexcept;
void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, uint8_t tile) noexcept;
void clearBg(Context &ctx, uint_t bgIdx) noexcept;
[[nodiscard]] [[nodiscard]]
uint8_t bgStatus(Context &ctx) noexcept; uint8_t bgStatus(Context &ctx) noexcept;
void setBgStatus(Context &ctx, uint32_t status) noexcept; void setBgStatus(Context &ctx, uint32_t status) noexcept;
[[nodiscard]]
bool bgStatus(Context &ctx, unsigned bg) noexcept; bool bgStatus(Context &ctx, unsigned bg) noexcept;
void setBgStatus(Context &ctx, unsigned bg, bool status) noexcept; void setBgStatus(Context &ctx, unsigned bg, bool status) noexcept;
@ -54,34 +76,19 @@ void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbb) noexcept;
void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept; void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept;
/**
* @param section describes which section of the selected TileSheetSpace to use (e.g. MEM_PALLETE_BG[section])
*/
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
ox::FileAddress const&paletteAddr = nullptr) noexcept;
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
ox::FileAddress const&paletteAddr) noexcept;
ox::Error initConsole(Context &ctx) noexcept;
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept;
void setTile(Context &ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept;
void clearTileLayer(Context &ctx, unsigned bgIdx) noexcept;
void hideSprite(Context &ctx, unsigned) noexcept; void hideSprite(Context &ctx, unsigned) noexcept;
void showSprite(Context &ctx, unsigned) noexcept; void showSprite(Context &ctx, unsigned) noexcept;
void setSprite(Context &c, uint_t idx, Sprite const&s) noexcept; void setSprite(Context &c, uint_t idx, Sprite const&s) noexcept;
[[nodiscard]]
uint_t spriteCount(Context &ctx) noexcept;
ox::Error initConsole(Context &ctx) noexcept;
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept;
} }
namespace nostalgia::core::gl { namespace nostalgia::core::gl {

View File

@ -8,10 +8,15 @@
namespace nostalgia::core { namespace nostalgia::core {
struct BgCbbData {
unsigned bpp = 4;
};
class Context { class Context {
public: public:
turbine::Context &turbineCtx; turbine::Context &turbineCtx;
ox::Array<BgCbbData, 4> cbbData;
explicit Context(turbine::Context &tctx) noexcept; explicit Context(turbine::Context &tctx) noexcept;
Context(Context &other) noexcept = delete; Context(Context &other) noexcept = delete;

View File

@ -10,7 +10,6 @@
#include <teagba/gfx.hpp> #include <teagba/gfx.hpp>
#include <teagba/registers.hpp> #include <teagba/registers.hpp>
#include <keel/media.hpp>
#include <turbine/turbine.hpp> #include <turbine/turbine.hpp>
#include <nostalgia/core/color.hpp> #include <nostalgia/core/color.hpp>
@ -22,11 +21,6 @@
namespace nostalgia::core { namespace nostalgia::core {
struct BgCbbData {
unsigned bpp = 4;
};
static ox::Array<BgCbbData, 4> g_cbbData;
constexpr auto GbaTileColumns = 32; constexpr auto GbaTileColumns = 32;
constexpr auto GbaTileRows = 32; constexpr auto GbaTileRows = 32;
@ -41,17 +35,23 @@ struct GbaTileMapTarget {
static constexpr auto TypeVersion = CompactTileSheet::TypeVersion; static constexpr auto TypeVersion = CompactTileSheet::TypeVersion;
BgCbbData *cbbData = nullptr; BgCbbData *cbbData = nullptr;
ox::FileAddress defaultPalette; ox::FileAddress defaultPalette;
GbaPaletteTarget pal;
volatile uint16_t *tileMap = nullptr; volatile uint16_t *tileMap = nullptr;
}; };
constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaPaletteTarget> auto *t) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaPaletteTarget> auto *t) noexcept {
oxReturnError(io->template setTypeInfo<Palette>()); oxReturnError(io->template setTypeInfo<Palette>());
if (t->palette) {
const auto colorHandler = [t](std::size_t i, const Color16 *c) { const auto colorHandler = [t](std::size_t i, const Color16 *c) {
t->palette[i] = *c; t->palette[i] = *c;
return OxError(0); return ox::Error{};
}; };
return io->template field<Color16, decltype(colorHandler)>("colors", colorHandler); return io->template field<Color16, decltype(colorHandler)>("colors", colorHandler);
} else {
constexpr auto colorHandler = [](std::size_t, const Color16*) {
return ox::Error{};
};
return io->template field<Color16, decltype(colorHandler)>("colors", colorHandler);
}
} }
constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaTileMapTarget> auto *t) noexcept { constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaTileMapTarget> auto *t) noexcept {
@ -73,11 +73,87 @@ constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaTileMapTarget> auto *t)
ox::Error initGfx(Context&, InitParams const&) noexcept { ox::Error initGfx(Context&, InitParams const&) noexcept {
for (auto bgCtl = &REG_BG0CTL; bgCtl <= &REG_BG3CTL; bgCtl += 2) { for (auto bgCtl = &REG_BG0CTL; bgCtl <= &REG_BG3CTL; bgCtl += 2) {
teagba::bgSetSbb(bgCtl, 28); teagba::bgSetSbb(*bgCtl, 28);
} }
return {}; return {};
} }
ox::Error loadBgPalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
auto &rom = ctx.rom();
GbaPaletteTarget const palTarget{.palette = MEM_BG_PALETTE};
oxRequire(palStat, rom.stat(paletteAddr));
oxRequire(pal, rom.directAccess(paletteAddr));
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &palTarget));
return {};
}
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
auto &rom = ctx.rom();
GbaPaletteTarget const palTarget{.palette = MEM_SPRITE_PALETTE};
oxRequire(palStat, rom.stat(paletteAddr));
oxRequire(pal, rom.directAccess(paletteAddr));
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &palTarget));
return {};
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
bool loadDefaultPalette) noexcept {
auto &rom = ctx.rom();
oxRequire(tsStat, rom.stat(tilesheetAddr));
oxRequire(ts, rom.directAccess(tilesheetAddr));
GbaTileMapTarget target{
.cbbData = &ctx.cbbData[cbb],
.defaultPalette = {},
.tileMap = MEM_BG_TILES[cbb].data(),
};
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
// update bpp of all bgs with the updated cbb
const auto bpp = ctx.cbbData[cbb].bpp;
teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
if (teagba::bgCbb(bgCtl) == cbb) {
teagba::bgSetBpp(bgCtl, bpp);
}
});
if (loadDefaultPalette && target.defaultPalette) {
oxReturnError(loadBgPalette(ctx, target.defaultPalette));
}
return {};
}
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
bool loadDefaultPalette) noexcept {
auto &rom = ctx.rom();
oxRequire(tsStat, ctx.rom().stat(tilesheetAddr));
oxRequire(ts, rom.directAccess(tilesheetAddr));
GbaTileMapTarget target{
.defaultPalette = {},
.tileMap = MEM_SPRITE_TILES,
};
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
if (loadDefaultPalette && target.defaultPalette) {
oxReturnError(loadSpritePalette(ctx, target.defaultPalette));
}
return {};
}
void setBgTile(Context&, uint_t bgIdx, int column, int row, uint8_t tile) noexcept {
const auto tileIdx = static_cast<std::size_t>(row * GbaTileColumns + column);
MEM_BG_MAP[bgIdx][tileIdx] = tile;
}
void clearBg(Context&, uint_t bgIdx) noexcept {
memset(MEM_BG_MAP[bgIdx].data(), 0, GbaTileRows * GbaTileColumns);
}
uint8_t bgStatus(Context&) noexcept { uint8_t bgStatus(Context&) noexcept {
return (REG_DISPCTL >> 8u) & 0b1111u; return (REG_DISPCTL >> 8u) & 0b1111u;
} }
@ -97,11 +173,11 @@ void setBgStatus(Context&, unsigned bg, bool status) noexcept {
REG_DISPCTL = REG_DISPCTL | ((REG_DISPCTL & ~mask) | mask); REG_DISPCTL = REG_DISPCTL | ((REG_DISPCTL & ~mask) | mask);
} }
void setBgCbb(Context&, unsigned bgIdx, unsigned cbb) noexcept { void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbb) noexcept {
auto &bgCtl = regBgCtl(bgIdx); auto &bgCtl = regBgCtl(bgIdx);
const auto &cbbData = g_cbbData[cbb]; const auto &cbbData = ctx.cbbData[cbb];
teagba::bgSetBpp(&bgCtl, cbbData.bpp); teagba::bgSetBpp(bgCtl, cbbData.bpp);
teagba::bgSetCbb(&bgCtl, cbb); teagba::bgSetCbb(bgCtl, cbb);
} }
void setBgPriority(Context&, uint_t bgIdx, uint_t priority) noexcept { void setBgPriority(Context&, uint_t bgIdx, uint_t priority) noexcept {
@ -109,111 +185,6 @@ void setBgPriority(Context&, uint_t bgIdx, uint_t priority) noexcept {
bgCtl = (bgCtl & 0b1111'1111'1111'1100u) | (priority & 0b11); bgCtl = (bgCtl & 0b1111'1111'1111'1100u) | (priority & 0b11);
} }
static ox::Error loadBgTileSheet(
ox::MemFS const&rom,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
ox::FileAddress const&paletteAddr) noexcept {
oxRequire(tsStat, rom.stat(tilesheetAddr));
oxRequire(ts, rom.directAccess(tilesheetAddr));
GbaTileMapTarget target;
target.pal.palette = MEM_BG_PALETTE;
target.cbbData = &g_cbbData[cbb];
target.tileMap = MEM_BG_TILES[cbb].data();
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
// load external palette if available
if (paletteAddr) {
oxRequire(palStat, rom.stat(paletteAddr));
oxRequire(pal, rom.directAccess(paletteAddr));
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &target.pal));
}
// update bpp of all bgs with the updated cbb
const auto bpp = g_cbbData[cbb].bpp;
teagba::iterateBgCtl([bpp, cbb](auto bgCtl) {
if (teagba::bgCbb(bgCtl) == cbb) {
teagba::bgSetBpp(bgCtl, bpp);
}
});
return {};
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
ox::FileAddress const&tilesheetAddr,
ox::FileAddress const&paletteAddr) noexcept {
auto &rom = ctx.rom();
return loadBgTileSheet(rom, cbb, tilesheetAddr, paletteAddr);
}
ox::Error loadSpriteTileSheet(
Context &ctx,
ox::FileAddress const&tilesheetAddr,
ox::FileAddress const&paletteAddr) noexcept {
auto &rom = ctx.rom();
oxRequire(tsStat, ctx.rom().stat(tilesheetAddr));
oxRequire(ts, rom.directAccess(tilesheetAddr));
GbaTileMapTarget target;
target.pal.palette = MEM_SPRITE_PALETTE;
target.tileMap = MEM_SPRITE_TILES;
oxReturnError(ox::readMC(ts, static_cast<std::size_t>(tsStat.size), &target));
// load external palette if available
if (paletteAddr) {
oxRequire(palStat, ctx.rom().stat(paletteAddr));
oxRequire(pal, rom.directAccess(paletteAddr));
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &target.pal));
}
return {};
}
ox::Error loadBgPalette(Context &ctx, unsigned, ox::FileAddress const&paletteAddr) noexcept {
auto &rom = ctx.rom();
GbaPaletteTarget target;
target.palette = MEM_BG_PALETTE;
oxRequire(palStat, ctx.rom().stat(paletteAddr));
oxRequire(pal, rom.directAccess(paletteAddr));
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &target));
return {};
}
ox::Error loadSpritePalette(Context &ctx, unsigned cbb, ox::FileAddress const&paletteAddr) noexcept {
auto &rom = ctx.rom();
GbaPaletteTarget target;
target.palette = &MEM_SPRITE_PALETTE[cbb];
oxRequire(palStat, rom.stat(paletteAddr));
oxRequire(pal, rom.directAccess(paletteAddr));
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &target));
return {};
}
ox::Error initConsole(Context &ctx) noexcept {
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.ng");
constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal");
setBgStatus(ctx, 0b0001);
oxReturnError(loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr));
setBgCbb(ctx, 0, 0);
return {};
}
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept {
const auto col = static_cast<unsigned>(column);
for (auto i = 0u; i < str.bytes(); i++) {
const auto c = charMap[static_cast<std::size_t>(str[i])];
setTile(ctx, 0, static_cast<int>(col + i), row, static_cast<uint8_t>(c));
}
}
void setTile(Context&, unsigned bgIdx, int column, int row, uint8_t tile) noexcept {
const auto tileIdx = static_cast<std::size_t>(row * GbaTileColumns + column);
MEM_BG_MAP[bgIdx][tileIdx] = tile;
}
// Do NOT use Context in the GBA version of this function.
void clearTileLayer(Context&, unsigned bgIdx) noexcept {
memset(MEM_BG_MAP[bgIdx].data(), 0, GbaTileRows * GbaTileColumns);
}
[[maybe_unused]]
void hideSprite(Context&, unsigned idx) noexcept { void hideSprite(Context&, unsigned idx) noexcept {
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow"); //oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
teagba::addSpriteUpdate({ teagba::addSpriteUpdate({
@ -222,7 +193,6 @@ void hideSprite(Context&, unsigned idx) noexcept {
}); });
} }
[[maybe_unused]]
void showSprite(Context&, unsigned idx) noexcept { void showSprite(Context&, unsigned idx) noexcept {
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow"); //oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
teagba::addSpriteUpdate({ teagba::addSpriteUpdate({
@ -249,4 +219,8 @@ void setSprite(Context&, uint_t idx, Sprite const&s) noexcept {
}); });
} }
uint_t spriteCount(Context&) noexcept {
return 128;
}
} }

View File

@ -31,7 +31,7 @@ void panic(const char *file, int line, const char *panicMsg, ox::Error const&err
oxIgnoreError(initGfx(*ctx, {})); oxIgnoreError(initGfx(*ctx, {}));
oxIgnoreError(initConsole(*ctx)); oxIgnoreError(initConsole(*ctx));
setBgStatus(*ctx, 0, true); setBgStatus(*ctx, 0, true);
clearTileLayer(*ctx, 0); clearBg(*ctx, 0);
ox::BString<23> serr = "Error code: "; ox::BString<23> serr = "Error code: ";
serr += static_cast<int64_t>(err); serr += static_cast<int64_t>(err);
puts(*ctx, 32 + 1, 1, "SADNESS..."); puts(*ctx, 32 + 1, 1, "SADNESS...");

View File

@ -7,7 +7,7 @@
namespace nostalgia::core { namespace nostalgia::core {
// map ASCII values to the nostalgia charset // map ASCII values to the nostalgia charset
ox::Array<char, 128> charMap = { constexpr ox::Array<char, 128> charMap = {
0, 0,
0, 0,
0, 0,
@ -137,4 +137,29 @@ ox::Array<char, 128> charMap = {
50, // ~ 50, // ~
}; };
ox::Error initConsole(Context &ctx) noexcept {
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.ng");
constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal");
setBgStatus(ctx, 0b0001);
setBgCbb(ctx, 0, 0);
oxReturnError(loadBgTileSheet(ctx, 0, TilesheetAddr));
return loadBgPalette(ctx, PaletteAddr);
}
void puts(
Context &ctx,
int const column,
int const row,
ox::CRStringView str) noexcept {
auto const col = static_cast<uint_t>(column);
for (auto i = 0u; i < str.bytes(); ++i) {
setBgTile(
ctx,
0,
static_cast<int>(col + i),
row,
static_cast<uint8_t>(charMap[static_cast<uint8_t>(str[i])]));
}
}
} }

View File

@ -19,11 +19,11 @@
namespace nostalgia::core { namespace nostalgia::core {
namespace renderer {
constexpr auto Scale = 1; constexpr auto Scale = 1;
constexpr auto PriorityScale = 0.01f; constexpr auto PriorityScale = 0.01f;
namespace renderer {
Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {} Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {}
void Drawer::draw(turbine::Context &tctx) noexcept { void Drawer::draw(turbine::Context &tctx) noexcept {
@ -98,7 +98,7 @@ constexpr ox::CStringView spritefshadTmpl = R"glsl(
if (outColor.a == 0) { if (outColor.a == 0) {
discard; discard;
} }
})glsl";; })glsl";
[[nodiscard]] [[nodiscard]]
static constexpr auto bgVertexRow(uint_t x, uint_t y) noexcept { static constexpr auto bgVertexRow(uint_t x, uint_t y) noexcept {
@ -338,8 +338,7 @@ static void drawSprites(Context &ctx, ox::Size const&renderSz) noexcept {
static void loadPalette( static void loadPalette(
GLuint shaderPgrm, GLuint shaderPgrm,
Palette const&pal, Palette const&pal) noexcept {
bool firstIsTransparent) noexcept {
static constexpr std::size_t ColorCnt = 256; static constexpr std::size_t ColorCnt = 256;
ox::Array<GLfloat, ColorCnt * 4> palette{}; ox::Array<GLfloat, ColorCnt * 4> palette{};
for (auto i = 0u; const auto c : pal.colors) { for (auto i = 0u; const auto c : pal.colors) {
@ -348,41 +347,13 @@ static void loadPalette(
palette[i++] = bluef(c); palette[i++] = bluef(c);
palette[i++] = 255; palette[i++] = 255;
} }
if (firstIsTransparent) { // make first color transparent
palette[3] = 0; palette[3] = 0;
}
glUseProgram(shaderPgrm); glUseProgram(shaderPgrm);
const auto uniformPalette = static_cast<GLint>(glGetUniformLocation(shaderPgrm, "fPalette")); const auto uniformPalette = static_cast<GLint>(glGetUniformLocation(shaderPgrm, "fPalette"));
glUniform4fv(uniformPalette, ColorCnt, palette.data()); glUniform4fv(uniformPalette, ColorCnt, palette.data());
} }
static void loadBgPalette(Context &ctx, Palette const&pal) noexcept {
loadPalette(ctx.bgShader, pal, true);
}
static void loadSpritePalette(Context &ctx, Palette const&pal) noexcept {
loadPalette(ctx.spriteShader, pal, true);
}
static void loadBgTexture(
Context &ctx,
uint_t cbbIdx,
const void *pixels,
int w,
int h) noexcept {
oxTracef("nostalgia.core.gfx.gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbbIdx, w, h);
ctx.cbbs[cbbIdx].tex = createTexture(w, h, pixels);
}
static void loadSpriteTexture(
Context &ctx,
const void *pixels,
int w,
int h) noexcept {
oxTracef("nostalgia.core.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", w, h);
ctx.spriteBlocks.tex = createTexture(w, h, pixels);
}
static void setSprite( static void setSprite(
Context &ctx, Context &ctx,
uint_t const idx, uint_t const idx,
@ -493,8 +464,7 @@ struct TileSheetData {
} }
}; };
static ox::Result<TileSheetData> loadTileSheet( static ox::Result<TileSheetData> normalizeTileSheet(
Context &ctx,
CompactTileSheet const&tilesheet) noexcept { CompactTileSheet const&tilesheet) noexcept {
const uint_t bytesPerTile = tilesheet.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2; const uint_t bytesPerTile = tilesheet.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
const auto tiles = tilesheet.pixels.size() / bytesPerTile; const auto tiles = tilesheet.pixels.size() / bytesPerTile;
@ -513,71 +483,93 @@ static ox::Result<TileSheetData> loadTileSheet(
pixels[i * 2 + 1] = tilesheet.pixels[i] >> 4; pixels[i * 2 + 1] = tilesheet.pixels[i] >> 4;
} }
} }
renderer::loadSpriteTexture(ctx, pixels.data(), width, height);
return TileSheetData{std::move(pixels), width, height}; return TileSheetData{std::move(pixels), width, height};
} }
ox::Error loadBgPalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx);
oxRequire(palette, readObj<Palette>(kctx, paletteAddr));
renderer::loadPalette(ctx.bgShader, *palette);
return {};
}
ox::Error loadSpritePalette(
Context &ctx,
ox::FileAddress const&paletteAddr) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx);
oxRequire(palette, readObj<Palette>(kctx, paletteAddr));
renderer::loadPalette(ctx.spriteShader, *palette);
return {};
}
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
uint_t cbb, uint_t cbb,
ox::FileAddress const&tilesheetAddr, ox::FileAddress const&tilesheetAddr,
ox::FileAddress const&paletteAddr) noexcept { bool loadDefaultPalette) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx); auto &kctx = keelCtx(ctx.turbineCtx);
oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr)); oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
oxRequire(palette, readObj<Palette>(kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette)); oxRequire(tsd, normalizeTileSheet(*tilesheet));
oxRequire(tsd, loadTileSheet(ctx, *tilesheet).to([](TileSheetData const&t) -> TileSheetData { oxTracef("nostalgia.core.gfx.gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbb, tsd.width, tsd.height);
return { ctx.cbbs[cbb].tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
.pixels = resizeTileSheetData(t.pixels, t.size(), Scale), if (loadDefaultPalette) {
.width = t.width * Scale, oxReturnError(loadBgPalette(ctx, tilesheet->defaultPalette));
.height = t.height * Scale, }
};
}));
renderer::loadBgTexture(ctx, cbb, tsd.pixels.data(), tsd.width, tsd.height);
renderer::loadBgPalette(ctx, *palette);
return {}; return {};
} }
ox::Error loadSpriteTileSheet( ox::Error loadSpriteTileSheet(
Context &ctx, Context &ctx,
ox::FileAddress const&tilesheetAddr, ox::FileAddress const&tilesheetAddr,
ox::FileAddress const&paletteAddr) noexcept { bool loadDefaultPalette) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx); auto &kctx = keelCtx(ctx.turbineCtx);
oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr)); oxRequire(tilesheet, readObj<CompactTileSheet>(kctx, tilesheetAddr));
oxRequire(palette, readObj<Palette>(kctx, paletteAddr ? paletteAddr : tilesheet->defaultPalette)); oxRequire(tsd, normalizeTileSheet(*tilesheet));
oxRequire(tsd, loadTileSheet(ctx, *tilesheet)); oxTracef("nostalgia.core.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height);
renderer::loadSpriteTexture(ctx, tsd.pixels.data(), tsd.width, tsd.height); ctx.spriteBlocks.tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
renderer::loadSpritePalette(ctx, *palette); if (loadDefaultPalette) {
oxReturnError(loadSpritePalette(ctx, tilesheet->defaultPalette));
}
return {}; return {};
} }
ox::Error initConsole(Context &ctx) noexcept { void setBgTile(
constexpr ox::FileAddress TilesheetAddr = ox::StringLiteral("/TileSheets/Charset.ng"); Context &ctx,
constexpr ox::FileAddress PaletteAddr = ox::StringLiteral("/Palettes/Charset.npal"); uint_t bgIdx,
setBgStatus(ctx, 0b0001); int column,
setBgCbb(ctx, 0, 0); int row,
return loadBgTileSheet(ctx, 0, TilesheetAddr, PaletteAddr); uint8_t tile) noexcept {
} oxTracef(
"nostalgia.core.gfx.setBgTile",
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept { "bgIdx: {}, column: {}, row: {}, tile: {}",
const auto col = static_cast<uint_t>(column); bgIdx, column, row, tile);
for (auto i = 0u; i < str.bytes(); ++i) { const auto z = static_cast<uint_t>(bgIdx);
setTile( const auto y = static_cast<uint_t>(row);
ctx, const auto x = static_cast<uint_t>(column);
0, const auto i = renderer::bgVertexRow(x, y);
static_cast<int>(col + i), auto &cbb = ctx.cbbs[z];
row, const auto vbo = &cbb.vertices[i * renderer::BgVertexVboLength];
static_cast<uint8_t>(charMap[static_cast<uint8_t>(str[i])])); const auto ebo = &cbb.elements[i * renderer::BgVertexEboLength];
}
}
void setBgCbb(Context &ctx, uint_t bgIdx, uint_t cbbIdx) noexcept {
auto &bg = ctx.backgrounds[bgIdx]; auto &bg = ctx.backgrounds[bgIdx];
bg.cbbIdx = cbbIdx; renderer::setTileBufferObject(
static_cast<uint_t>(i * renderer::BgVertexVboRows),
static_cast<float>(x),
static_cast<float>(y),
static_cast<float>(tile),
bg.priority,
vbo,
ebo);
cbb.updated = true;
} }
void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept { void clearBg(Context &ctx, uint_t bgIdx) noexcept {
auto &bg = ctx.backgrounds[bgIdx]; auto &cbb = ctx.cbbs[static_cast<std::size_t>(bgIdx)];
bg.priority = static_cast<float>(priority & 0b11); initBackgroundBufferObjects(cbb);
cbb.updated = true;
auto &bg = ctx.backgrounds[static_cast<std::size_t>(bgIdx)];
bg.priority = 0;
} }
uint8_t bgStatus(Context &ctx) noexcept { uint8_t bgStatus(Context &ctx) noexcept {
@ -602,13 +594,14 @@ void setBgStatus(Context &ctx, uint_t bg, bool status) noexcept {
ctx.backgrounds[bg].enabled = status; ctx.backgrounds[bg].enabled = status;
} }
void setBgCbb(Context &ctx, uint_t bgIdx, uint_t cbbIdx) noexcept {
auto &bg = ctx.backgrounds[bgIdx];
bg.cbbIdx = cbbIdx;
}
void clearTileLayer(Context &ctx, uint_t bgIdx) noexcept { void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept {
auto &cbb = ctx.cbbs[static_cast<std::size_t>(bgIdx)]; auto &bg = ctx.backgrounds[bgIdx];
initBackgroundBufferObjects(cbb); bg.priority = static_cast<float>(priority & 0b11);
cbb.updated = true;
auto &bg = ctx.backgrounds[static_cast<std::size_t>(bgIdx)];
bg.priority = 0;
} }
void hideSprite(Context &ctx, uint_t idx) noexcept { void hideSprite(Context &ctx, uint_t idx) noexcept {
@ -629,33 +622,8 @@ void setSprite(Context &ctx, uint_t idx, Sprite const&sprite) noexcept {
renderer::setSprite(ctx, idx, s); renderer::setSprite(ctx, idx, s);
} }
void setTile( uint_t spriteCount(Context &ctx) noexcept {
Context &ctx, return ctx.spriteCount;
uint_t bgIdx,
int column,
int row,
uint8_t tile) noexcept {
oxTracef(
"nostalgia.core.gfx.setTile",
"bgIdx: {}, column: {}, row: {}, tile: {}",
bgIdx, column, row, tile);
const auto z = static_cast<uint_t>(bgIdx);
const auto y = static_cast<uint_t>(row);
const auto x = static_cast<uint_t>(column);
const auto i = renderer::bgVertexRow(x, y);
auto &cbb = ctx.cbbs[z];
const auto vbo = &cbb.vertices[i * renderer::BgVertexVboLength];
const auto ebo = &cbb.elements[i * renderer::BgVertexEboLength];
auto &bg = ctx.backgrounds[bgIdx];
renderer::setTileBufferObject(
static_cast<uint_t>(i * renderer::BgVertexVboRows),
static_cast<float>(x),
static_cast<float>(y),
static_cast<float>(tile),
bg.priority,
vbo,
ebo);
cbb.updated = true;
} }
namespace gl { namespace gl {

View File

@ -17,8 +17,8 @@ ox::Error Scene::setupDisplay(core::Context &ctx) const noexcept {
return OxError(1, "Scene has no palettes"); return OxError(1, "Scene has no palettes");
} }
auto const&palette = m_sceneStatic.palettes[0]; auto const&palette = m_sceneStatic.palettes[0];
oxReturnError(core::loadBgTileSheet( oxReturnError(core::loadBgTileSheet(ctx, 0, m_sceneStatic.tilesheet));
ctx, 0, m_sceneStatic.tilesheet, palette)); oxReturnError(core::loadBgPalette(ctx, palette));
// disable all backgrounds // disable all backgrounds
core::setBgStatus(ctx, 0); core::setBgStatus(ctx, 0);
for (auto layerNo = 0u; auto const&layer : m_sceneStatic.tileMapIdx) { for (auto layerNo = 0u; auto const&layer : m_sceneStatic.tileMapIdx) {
@ -39,10 +39,10 @@ void Scene::setupLayer(
const auto width = m_sceneStatic.rows[layerNo]; const auto width = m_sceneStatic.rows[layerNo];
for (auto const&tile : layer) { for (auto const&tile : layer) {
const auto tile8 = static_cast<uint8_t>(tile); const auto tile8 = static_cast<uint8_t>(tile);
core::setTile(ctx, layerNo, x, y, tile8); core::setBgTile(ctx, layerNo, x, y, tile8);
core::setTile(ctx, layerNo, x + 1, y, tile8 + 1); core::setBgTile(ctx, layerNo, x + 1, y, tile8 + 1);
core::setTile(ctx, layerNo, x, y + 1, tile8 + 2); core::setBgTile(ctx, layerNo, x, y + 1, tile8 + 2);
core::setTile(ctx, layerNo, x + 1, y + 1, tile8 + 3); core::setBgTile(ctx, layerNo, x + 1, y + 1, tile8 + 3);
x += 2; x += 2;
if (x >= width * 2) { if (x >= width * 2) {
x = 0; x = 0;

View File

@ -14,25 +14,6 @@ static int spriteX{};
static int spriteY{}; static int spriteY{};
static bool s_paused = false; static bool s_paused = false;
static int sceneUpdateHandler(turbine::Context&) noexcept {
constexpr auto sleepTime = 16;
if (s_paused) {
return sleepTime;
}
// do stuff
return sleepTime;
}
static void sceneKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool down) noexcept {
if (down) {
if (key == turbine::Key::Alpha_Q) {
turbine::requestShutdown(tctx);
} else if (key == turbine::Key::Alpha_P) {
s_paused = !s_paused;
}
}
}
[[maybe_unused]] [[maybe_unused]]
static int testUpdateHandler(turbine::Context &tctx) noexcept { static int testUpdateHandler(turbine::Context &tctx) noexcept {
auto &cctx = *turbine::applicationData<core::Context>(tctx); auto &cctx = *turbine::applicationData<core::Context>(tctx);
@ -82,7 +63,6 @@ static void testKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool d
} }
} }
[[maybe_unused]] [[maybe_unused]]
static ox::Error runTest(turbine::Context &tctx) { static ox::Error runTest(turbine::Context &tctx) {
constexpr ox::FileAddress TileSheetAddr = ox::StringLiteral("/TileSheets/Charset.ng"); constexpr ox::FileAddress TileSheetAddr = ox::StringLiteral("/TileSheets/Charset.ng");
@ -90,7 +70,8 @@ static ox::Error runTest(turbine::Context &tctx) {
oxRequireM(cctx, core::init(tctx)); oxRequireM(cctx, core::init(tctx));
turbine::setApplicationData(tctx, cctx.get()); turbine::setApplicationData(tctx, cctx.get());
oxRequire(tsStat, turbine::rom(tctx)->stat(PaletteAddr)); oxRequire(tsStat, turbine::rom(tctx)->stat(PaletteAddr));
oxReturnError(core::loadSpriteTileSheet(*cctx, TileSheetAddr, PaletteAddr)); oxReturnError(core::loadSpriteTileSheet(*cctx, TileSheetAddr));
oxReturnError(core::loadSpritePalette(*cctx, PaletteAddr));
oxReturnError(core::initConsole(*cctx)); oxReturnError(core::initConsole(*cctx));
core::puts(*cctx, 10, 9, "DOPENESS!!!"); core::puts(*cctx, 10, 9, "DOPENESS!!!");
turbine::setUpdateHandler(tctx, testUpdateHandler); turbine::setUpdateHandler(tctx, testUpdateHandler);
@ -101,6 +82,26 @@ static ox::Error runTest(turbine::Context &tctx) {
return turbine::run(tctx); return turbine::run(tctx);
} }
static int sceneUpdateHandler(turbine::Context&) noexcept {
constexpr auto sleepTime = 16;
if (s_paused) {
return sleepTime;
}
// do stuff
return sleepTime;
}
static void sceneKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool down) noexcept {
if (down) {
if (key == turbine::Key::Alpha_Q) {
turbine::requestShutdown(tctx);
} else if (key == turbine::Key::Alpha_P) {
s_paused = !s_paused;
}
}
}
[[maybe_unused]] [[maybe_unused]]
static ox::Error runScene(turbine::Context &tctx) { static ox::Error runScene(turbine::Context &tctx) {
constexpr ox::FileAddress SceneAddr = ox::StringLiteral("/Scenes/Chester.nscn"); constexpr ox::FileAddress SceneAddr = ox::StringLiteral("/Scenes/Chester.nscn");