diff --git a/src/nostalgia/core/gfx.hpp b/src/nostalgia/core/gfx.hpp index 4f2a8b41..c840a0e4 100644 --- a/src/nostalgia/core/gfx.hpp +++ b/src/nostalgia/core/gfx.hpp @@ -61,8 +61,8 @@ struct TileSheet { static constexpr auto TypeName = "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; + uint64_t begin = 0; + uint64_t size = 0; int rows = 1; int columns = 1; ox::Vector subsheets; diff --git a/src/nostalgia/core/media.hpp b/src/nostalgia/core/media.hpp index 8c055518..6721c4d9 100644 --- a/src/nostalgia/core/media.hpp +++ b/src/nostalgia/core/media.hpp @@ -23,7 +23,7 @@ ox::Result> readObj(Context *ctx, const ox::FileAddress &file, bool if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) { return err; } - oxReturnError(convert(buff, T::TypeName, T::TypeVersion, &obj)); + oxReturnError(convert(buff, &obj)); } return obj; }; diff --git a/src/nostalgia/core/typeconv.cpp b/src/nostalgia/core/typeconv.cpp index 6335fdae..61810575 100644 --- a/src/nostalgia/core/typeconv.cpp +++ b/src/nostalgia/core/typeconv.cpp @@ -30,9 +30,8 @@ struct NostalgiaPaletteToPaletteConverter: public Converter -struct ToCompactTileSheetConverter: public Converter { - ox::Error convert(Src *src, CompactTileSheet *dst) noexcept final { +struct TileSheetToCompactTileSheetConverter: public Converter { + ox::Error convert(TileSheet *src, CompactTileSheet *dst) noexcept final { dst->bpp = src->bpp; dst->defaultPalette = std::move(src->defaultPalette); dst->pixels = std::move(src->pixels); @@ -42,11 +41,10 @@ struct ToCompactTileSheetConverter: public Converter { #ifndef OX_BARE_METAL static const auto converters = [] { - ox::Vector, 4> converters; + ox::Vector, 3> converters; converters.emplace_back(new NostalgiaGraphicToTileSheetConverter()); converters.emplace_back(new NostalgiaPaletteToPaletteConverter()); - converters.emplace_back(new ToCompactTileSheetConverter()); - converters.emplace_back(new ToCompactTileSheetConverter()); + converters.emplace_back(new TileSheetToCompactTileSheetConverter()); return converters; }(); @@ -59,11 +57,25 @@ static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, con return OxError(1, "Could not find converter"); }; -ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept { +ox::Result convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, ox::ClawFormat fmt) noexcept { oxRequire(hdr, ox::readClawHeader(srcBuffer)); - oxRequire(c, findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion)); - return c->convertRaw(srcBuffer, dstObj); + auto [c, err] = findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion); + if (!err) { // try to chain multiple converters + return c->convertBuffToBuff(srcBuffer); + } + for (const auto &subConverter : converters) { + if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) { + continue; + } + const auto [intermediateBuff, chainErr] = + convert(srcBuffer, subConverter->srcTypeName(), subConverter->srcTypeVersion(), fmt); + if (!chainErr) { + return subConverter->convertBuffToBuff(intermediateBuff, fmt); + } + } + return OxError(1, "Could not convert between types"); } + #endif } diff --git a/src/nostalgia/core/typeconv.hpp b/src/nostalgia/core/typeconv.hpp index 01438d89..88a6acee 100644 --- a/src/nostalgia/core/typeconv.hpp +++ b/src/nostalgia/core/typeconv.hpp @@ -17,14 +17,42 @@ namespace nostalgia::core { struct BaseConverter { virtual ~BaseConverter() noexcept = default; + virtual ox::String srcTypeName() noexcept = 0; + + virtual int srcTypeVersion() noexcept = 0; + + virtual bool srcMatches(const ox::String &srcTypeName, int srcTypeVersion) noexcept = 0; + + virtual bool dstMatches(const ox::String &dstTypeName, int dstTypeVersion) noexcept = 0; + 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; + + virtual ox::Result convertBuffToBuff(const ox::Buffer &srcBuff, ox::ClawFormat dstFmt = ox::ClawFormat::Metal) noexcept = 0; }; template struct Converter: public BaseConverter{ - bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept override { + ox::String srcTypeName() noexcept final { + return SrcType::TypeName; + } + + int srcTypeVersion() noexcept final { + return SrcType::TypeVersion; + } + + bool srcMatches(const ox::String &srcTypeName, int srcTypeVersion) noexcept final { + return srcTypeName == DstType::TypeName + && srcTypeVersion == DstType::TypeVersion; + } + + bool dstMatches(const ox::String &dstTypeName, int dstTypeVersion) noexcept final { + return dstTypeName == DstType::TypeName + && dstTypeVersion == DstType::TypeVersion; + } + + bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept final { return srcTypeName == SrcType::TypeName && dstTypeName == DstType::TypeName && srcTypeVersion == SrcType::TypeVersion @@ -40,26 +68,26 @@ struct Converter: public BaseConverter{ auto dst = static_cast(pV2); return convert(&src, dst); } + + ox::Result convertBuffToBuff(const ox::Buffer &srcBuff, ox::ClawFormat dstFmt) noexcept final { + DstType dst; + oxReturnError(convertRaw(srcBuff, &dst)); + oxRequireM(out, ox::writeClaw(&dst, dstFmt)); + return out; + } }; -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)); -} +ox::Result convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept; 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); + return convert(srcBuffer, T::TypeName, T::TypeVersion, fmt); } template -ox::Error convert(ox::Buffer *buff) noexcept { - return convert(*buff).moveTo(buff); - +ox::Error convert(const ox::Buffer &buff, T *outObj) noexcept { + oxRequireM(outBuff, convert(buff)); + return ox::readClaw(outBuff).moveTo(outObj); } } diff --git a/src/nostalgia/tools/pack/pack.cpp b/src/nostalgia/tools/pack/pack.cpp index bcfd4536..c7d8883e 100644 --- a/src/nostalgia/tools/pack/pack.cpp +++ b/src/nostalgia/tools/pack/pack.cpp @@ -36,7 +36,7 @@ static ox::Error doTransformations(ox::FileSystem *dest, const ox::String &fileP // load file oxRequireM(buff, dest->read(filePath.c_str())); if (filePath.endsWith(".ng")) { - oxReturnError(core::convert(&buff)); + oxReturnError(core::convert(buff).moveTo(&buff)); } // do transformations oxReturnError(pathToInode(buff).moveTo(&buff));