diff --git a/src/nostalgia/core/gba/gfx.cpp b/src/nostalgia/core/gba/gfx.cpp index 42d63348..23a0a270 100644 --- a/src/nostalgia/core/gba/gfx.cpp +++ b/src/nostalgia/core/gba/gfx.cpp @@ -29,8 +29,8 @@ struct GbaPaletteTarget { }; struct GbaTileMapTarget { - static constexpr auto TypeName = TileSheet::TypeName; - static constexpr auto TypeVersion = TileSheet::TypeVersion; + static constexpr auto TypeName = CompactTileSheet::TypeName; + static constexpr auto TypeVersion = CompactTileSheet::TypeVersion; volatile uint16_t *bgCtl = nullptr; ox::FileAddress defaultPalette; GbaPaletteTarget pal; @@ -51,10 +51,7 @@ template constexpr ox::Error modelRead(T *io, GbaTileMapTarget *t) noexcept { io->template setTypeInfo(); uint8_t bpp; - int dummy; oxReturnError(io->field("bpp", &bpp)); - oxReturnError(io->field("rows", &dummy)); - oxReturnError(io->field("columns", &dummy)); constexpr auto Bpp8 = 1 << 7; if (t->bgCtl) { *t->bgCtl = (28 << 8) | 1; @@ -65,7 +62,6 @@ constexpr ox::Error modelRead(T *io, GbaTileMapTarget *t) noexcept { } } oxReturnError(io->field("defaultPalette", &t->defaultPalette)); - oxReturnError(io->field("pal", &t->pal)); uint16_t intermediate = 0; const auto handleTileMap = [t, &intermediate](std::size_t i, uint8_t *tile) { if (i & 1) { // i is odd diff --git a/src/nostalgia/core/gfx.hpp b/src/nostalgia/core/gfx.hpp index 8db44fd0..4f2a8b41 100644 --- a/src/nostalgia/core/gfx.hpp +++ b/src/nostalgia/core/gfx.hpp @@ -29,13 +29,20 @@ enum class TileSheetSpace { Sprite }; -struct Palette { +struct NostalgiaPalette { static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaPalette"; static constexpr auto TypeVersion = 1; ox::Vector colors; }; -struct TileSheetV1 { +struct Palette { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette"; + static constexpr auto TypeVersion = 1; + ox::Vector colors; +}; + +// Predecessor to TileSheet, kept for backward compatibility +struct NostalgiaGraphic { static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaGraphic"; static constexpr auto TypeVersion = 1; int8_t bpp = 0; @@ -45,69 +52,6 @@ struct TileSheetV1 { ox::FileAddress defaultPalette; Palette pal; ox::Vector pixels; - - [[nodiscard]] - constexpr uint8_t getPixel4Bpp(std::size_t idx) const noexcept { - oxAssert(bpp == 4, "TileSheetV1::getPixel4Bpp: wrong bpp"); - if (idx & 1) { - return this->pixels[idx / 2] >> 4; - } else { - return this->pixels[idx / 2] & 0b0000'1111; - } - } - - [[nodiscard]] - constexpr uint8_t getPixel8Bpp(std::size_t idx) const noexcept { - oxAssert(bpp == 8, "TileSheetV1::getPixel8Bpp: wrong bpp"); - return this->pixels[idx]; - } - - [[nodiscard]] - constexpr auto getPixel(std::size_t idx) const noexcept { - if (this->bpp == 4) { - return getPixel4Bpp(idx); - } else { - return getPixel8Bpp(idx); - } - } - - [[nodiscard]] - constexpr auto getPixel4Bpp(const geo::Point &pt) const noexcept { - oxAssert(bpp == 4, "TileSheetV1::getPixel4Bpp: wrong bpp"); - const auto idx = ptToIdx(pt, this->columns); - return getPixel4Bpp(idx); - } - - [[nodiscard]] - constexpr auto getPixel8Bpp(const geo::Point &pt) const noexcept { - oxAssert(bpp == 8, "TileSheetV1::getPixel8Bpp: wrong bpp"); - const auto idx = ptToIdx(pt, this->columns); - return getPixel8Bpp(idx); - } - - [[nodiscard]] - constexpr auto getPixel(const geo::Point &pt) const noexcept { - const auto idx = ptToIdx(pt, this->columns); - return getPixel(idx); - } - - constexpr void setPixel(uint64_t idx, uint8_t palIdx) noexcept { - auto &pixel = this->pixels[idx / 2]; - if (bpp == 4) { - if (idx & 1) { - pixel = (pixel & 0b0000'1111) | (palIdx << 4); - } else { - pixel = (pixel & 0b1111'0000) | (palIdx); - } - } else { - pixel = palIdx; - } - } - - constexpr void setPixel(const geo::Point &pt, uint8_t palIdx) noexcept { - const auto idx = ptToIdx(pt, this->columns); - setPixel(idx, palIdx); - } }; struct TileSheet { @@ -115,7 +59,7 @@ struct TileSheet { struct SubSheet { static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet"; - static constexpr auto TypeVersion = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet"; + static constexpr auto TypeVersion = 1; ox::BString<32> name; std::size_t begin = 0; std::size_t size = 0; @@ -125,11 +69,9 @@ struct TileSheet { }; static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet"; - static constexpr auto TypeVersion = 2; + static constexpr auto TypeVersion = 1; int8_t bpp = 0; - // rows and columns are really only used by TileSheetEditor ox::FileAddress defaultPalette; - Palette pal; ox::Vector pixels; SubSheet subsheet; @@ -243,11 +185,23 @@ struct TileSheet { } }; +struct CompactTileSheet { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet"; + static constexpr auto TypeVersion = 1; + int8_t bpp = 0; + ox::FileAddress defaultPalette; + ox::Vector pixels; +}; + +oxModelBegin(NostalgiaPalette) + oxModelField(colors) +oxModelEnd() + oxModelBegin(Palette) oxModelField(colors) oxModelEnd() -oxModelBegin(TileSheetV1) +oxModelBegin(NostalgiaGraphic) oxModelField(bpp) oxModelField(rows) oxModelField(columns) @@ -256,14 +210,6 @@ oxModelBegin(TileSheetV1) oxModelField(pixels) oxModelEnd() -oxModelBegin(TileSheet) - oxModelField(bpp) - oxModelField(defaultPalette) - oxModelField(pal) - oxModelField(pixels) - oxModelField(subsheet) -oxModelEnd() - oxModelBegin(TileSheet::SubSheet) oxModelField(name); oxModelField(begin); @@ -273,6 +219,19 @@ oxModelBegin(TileSheet::SubSheet) oxModelField(subsheets) oxModelEnd() +oxModelBegin(TileSheet) + oxModelField(bpp) + oxModelField(defaultPalette) + oxModelField(pixels) + oxModelField(subsheet) +oxModelEnd() + +oxModelBegin(CompactTileSheet) + oxModelField(bpp) + oxModelField(defaultPalette) + oxModelField(pixels) +oxModelEnd() + struct Sprite { unsigned idx = 0; unsigned x = 0; diff --git a/src/nostalgia/core/media.hpp b/src/nostalgia/core/media.hpp index b1d43bab..8c055518 100644 --- a/src/nostalgia/core/media.hpp +++ b/src/nostalgia/core/media.hpp @@ -47,6 +47,12 @@ ox::Result> readObj(Context *ctx, const ox::FileAddress &file, bool #endif } +template +ox::Error writeObj(Context *ctx, const ox::FileAddress &file, T &obj, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept { + oxRequire(objBuff, ox::writeClaw(&obj, fmt)); + return ctx->rom-write(file, objBuff); +} + ox::Result> loadRomFs(const char *path) noexcept; ox::Result loadRom(const char *path = "") noexcept; diff --git a/src/nostalgia/core/typeconv.cpp b/src/nostalgia/core/typeconv.cpp index d85e8917..6335fdae 100644 --- a/src/nostalgia/core/typeconv.cpp +++ b/src/nostalgia/core/typeconv.cpp @@ -4,55 +4,53 @@ #include -#ifndef OX_BARE_METAL #include #include "typeconv.hpp" namespace nostalgia::core { -struct Converter { - virtual bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept = 0; - - virtual ~Converter() noexcept = default; - - virtual ox::Error convert(const ox::Buffer &pV1Buff, void *pV2) noexcept = 0; -}; - -struct TileSheetV1ToV2Converter: public Converter { - constexpr TileSheetV1ToV2Converter() noexcept = default; - - virtual ~TileSheetV1ToV2Converter() noexcept = default; - - bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept final { - return srcTypeName == TileSheetV1::TypeName - && srcTypeVersion == TileSheetV1::TypeVersion - && dstTypeName == TileSheet::TypeName - && dstTypeVersion == TileSheet::TypeVersion; - } - - ox::Error convert(const ox::Buffer &pV1Buff, void *pV2) noexcept final { - oxRequire(v1, ox::readClaw(pV1Buff)); - auto v2 = static_cast(pV2); - v2->bpp = v1.bpp; - v2->subsheet.name = "Root"; - v2->subsheet.rows = v1.rows; - v2->subsheet.columns = v1.columns; - v2->subsheet.size = v1.pixels.size(); - v2->defaultPalette = v1.defaultPalette; - v2->pal = v1.pal; - v2->pixels = std::move(v1.pixels); +struct NostalgiaGraphicToTileSheetConverter: public Converter { + ox::Error convert(NostalgiaGraphic *src, TileSheet *dst) noexcept final { + dst->bpp = src->bpp; + dst->subsheet.name = "Root"; + dst->subsheet.rows = src->rows; + dst->subsheet.columns = src->columns; + dst->subsheet.size = src->pixels.size(); + dst->defaultPalette = std::move(src->defaultPalette); + dst->pixels = std::move(src->pixels); return OxError(0); } }; +struct NostalgiaPaletteToPaletteConverter: public Converter { + ox::Error convert(NostalgiaPalette *src, Palette *dst) noexcept final { + dst->colors = std::move(src->colors); + return OxError(0); + } +}; + +template +struct ToCompactTileSheetConverter: public Converter { + ox::Error convert(Src *src, CompactTileSheet *dst) noexcept final { + dst->bpp = src->bpp; + dst->defaultPalette = std::move(src->defaultPalette); + dst->pixels = std::move(src->pixels); + return OxError(0); + } +}; + +#ifndef OX_BARE_METAL static const auto converters = [] { - ox::Vector, 1> converters; - converters.emplace_back(new TileSheetV1ToV2Converter()); + ox::Vector, 4> converters; + converters.emplace_back(new NostalgiaGraphicToTileSheetConverter()); + converters.emplace_back(new NostalgiaPaletteToPaletteConverter()); + converters.emplace_back(new ToCompactTileSheetConverter()); + converters.emplace_back(new ToCompactTileSheetConverter()); return converters; }(); -static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept -> ox::Result { +static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept -> ox::Result { for (auto &c : converters) { if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) { return c.get(); @@ -64,8 +62,8 @@ static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, con ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept { oxRequire(hdr, ox::readClawHeader(srcBuffer)); oxRequire(c, findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion)); - return c->convert(srcBuffer, dstObj); -} - + return c->convertRaw(srcBuffer, dstObj); } #endif + +} diff --git a/src/nostalgia/core/typeconv.hpp b/src/nostalgia/core/typeconv.hpp index c6b63012..01438d89 100644 --- a/src/nostalgia/core/typeconv.hpp +++ b/src/nostalgia/core/typeconv.hpp @@ -8,10 +8,58 @@ #include #include +#include + #include "gfx.hpp" namespace nostalgia::core { +struct BaseConverter { + virtual ~BaseConverter() noexcept = default; + + virtual bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept = 0; + + virtual ox::Error convertRaw(const ox::Buffer &pV1Buff, void *pV2) noexcept = 0; +}; + +template +struct Converter: public BaseConverter{ + bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept override { + return srcTypeName == SrcType::TypeName + && dstTypeName == DstType::TypeName + && srcTypeVersion == SrcType::TypeVersion + && dstTypeVersion == DstType::TypeVersion; + } + + virtual ox::Error convert(SrcType*, DstType*) noexcept { + return OxError(1); + } + + ox::Error convertRaw(const ox::Buffer &pV1Buff, void *pV2) noexcept override { + oxRequireM(src, ox::readClaw(pV1Buff)); + auto dst = static_cast(pV2); + return convert(&src, dst); + } +}; + ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept; +template +ox::Error convert(const ox::Buffer &srcBuffer, T *dstObj) noexcept { + return convert((srcBuffer, T::TypeName, T::TypeVersion, &dstObj)); +} + +template +ox::Result convert(const ox::Buffer &srcBuffer, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept { + T dstObj; + oxReturnError(convert(srcBuffer, T::TypeName, T::TypeVersion, &dstObj)); + return ox::writeClaw(&dstObj, fmt); +} + +template +ox::Error convert(ox::Buffer *buff) noexcept { + return convert(*buff).moveTo(buff); + +} + }