[nostalgia/core] Expand conversion system to allow raw-to-raw

This commit is contained in:
Gary Talent 2022-02-17 21:29:46 -06:00
parent fba203a1e7
commit b87c2f0c50
5 changed files with 129 additions and 122 deletions

View File

@ -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<typename T>
constexpr ox::Error modelRead(T *io, GbaTileMapTarget *t) noexcept {
io->template setTypeInfo<GbaTileMapTarget>();
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

View File

@ -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<Color16> colors;
};
struct TileSheetV1 {
struct Palette {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette";
static constexpr auto TypeVersion = 1;
ox::Vector<Color16> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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;

View File

@ -47,6 +47,12 @@ ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, bool
#endif
}
template<typename T>
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<ox::UniquePtr<ox::FileSystem>> loadRomFs(const char *path) noexcept;
ox::Result<char*> loadRom(const char *path = "") noexcept;

View File

@ -4,55 +4,53 @@
#include <ox/std/defines.hpp>
#ifndef OX_BARE_METAL
#include <ox/claw/read.hpp>
#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<TileSheetV1>(pV1Buff));
auto v2 = static_cast<TileSheet*>(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<NostalgiaGraphic, TileSheet> {
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<NostalgiaPalette, Palette> {
ox::Error convert(NostalgiaPalette *src, Palette *dst) noexcept final {
dst->colors = std::move(src->colors);
return OxError(0);
}
};
template<typename Src>
struct ToCompactTileSheetConverter: public Converter<Src, CompactTileSheet> {
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<ox::UniquePtr<Converter>, 1> converters;
converters.emplace_back(new TileSheetV1ToV2Converter());
ox::Vector<ox::UniquePtr<BaseConverter>, 4> converters;
converters.emplace_back(new NostalgiaGraphicToTileSheetConverter());
converters.emplace_back(new NostalgiaPaletteToPaletteConverter());
converters.emplace_back(new ToCompactTileSheetConverter<NostalgiaGraphic>());
converters.emplace_back(new ToCompactTileSheetConverter<TileSheet>());
return converters;
}();
static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept -> ox::Result<Converter*> {
static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept -> ox::Result<BaseConverter*> {
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
}

View File

@ -8,10 +8,58 @@
#include <ox/std/error.hpp>
#include <ox/std/string.hpp>
#include <ox/claw/write.hpp>
#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<typename SrcType, typename DstType>
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<SrcType>(pV1Buff));
auto dst = static_cast<DstType*>(pV2);
return convert(&src, dst);
}
};
ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept;
template<typename T>
ox::Error convert(const ox::Buffer &srcBuffer, T *dstObj) noexcept {
return convert((srcBuffer, T::TypeName, T::TypeVersion, &dstObj));
}
template<typename T>
ox::Result<ox::Buffer> 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<typename T>
ox::Error convert(ox::Buffer *buff) noexcept {
return convert<T>(*buff).moveTo(buff);
}
}