diff --git a/src/nostalgia/core/module.cpp b/src/nostalgia/core/module.cpp index 02f2b0e0..3ed67326 100644 --- a/src/nostalgia/core/module.cpp +++ b/src/nostalgia/core/module.cpp @@ -15,6 +15,17 @@ namespace nostalgia::core { CoreModule CoreModule::mod; +ox::Vector CoreModule::types() const noexcept { + return { + foundation::generateTypeDesc, + foundation::generateTypeDesc, + foundation::generateTypeDesc, + foundation::generateTypeDesc, + foundation::generateTypeDesc, + foundation::generateTypeDesc, + }; +} + ox::Vector CoreModule::converters() const noexcept { return { &nostalgiaPaletteToPaletteConverter, @@ -33,7 +44,8 @@ ox::Vector CoreModule::packTransforms() const noexcep if (typeId == ox::buildTypeId() || typeId == ox::buildTypeId() || typeId == ox::buildTypeId()) { - oxReturnError(foundation::convertBuffToBuff(ctx, *buff, ox::ClawFormat::Metal).moveTo(buff)); + oxReturnError(foundation::convertBuffToBuff( + ctx, *buff, ox::ClawFormat::Metal).moveTo(buff)); } return {}; }, diff --git a/src/nostalgia/core/module.hpp b/src/nostalgia/core/module.hpp index 7c3859cd..2258da12 100644 --- a/src/nostalgia/core/module.hpp +++ b/src/nostalgia/core/module.hpp @@ -20,6 +20,8 @@ class CoreModule: public foundation::Module { public: static CoreModule mod; [[nodiscard]] + ox::Vector types() const noexcept override; + [[nodiscard]] ox::Vector converters() const noexcept override; [[nodiscard]] ox::Vector packTransforms() const noexcept override; diff --git a/src/nostalgia/foundation/module.cpp b/src/nostalgia/foundation/module.cpp index aeb8353e..f1e75845 100644 --- a/src/nostalgia/foundation/module.cpp +++ b/src/nostalgia/foundation/module.cpp @@ -18,6 +18,10 @@ const ox::Vector *modules() noexcept { } +ox::Vector Module::types() const noexcept { + return {}; +} + ox::Vector Module::converters() const noexcept { return {}; } diff --git a/src/nostalgia/foundation/module.hpp b/src/nostalgia/foundation/module.hpp index 642cbe89..9dd83896 100644 --- a/src/nostalgia/foundation/module.hpp +++ b/src/nostalgia/foundation/module.hpp @@ -5,11 +5,19 @@ #pragma once #include +#include #include "typeconv.hpp" namespace nostalgia::foundation { +using TypeDescGenerator = ox::Error(*)(ox::TypeStore*); + +template +ox::Error generateTypeDesc(ox::TypeStore *ts) noexcept { + return ox::buildTypeDef(ts).error; +} + class Module { public: constexpr Module() noexcept = default; @@ -19,6 +27,8 @@ class Module { Module &operator=(Module&&) noexcept = delete; constexpr virtual ~Module() noexcept = default; [[nodiscard]] + virtual ox::Vector types() const noexcept; + [[nodiscard]] virtual ox::Vector converters() const noexcept; [[nodiscard]] virtual ox::Vector packTransforms() const noexcept; diff --git a/src/nostalgia/foundation/typeconv.hpp b/src/nostalgia/foundation/typeconv.hpp index b2da2acb..ab5fb67b 100644 --- a/src/nostalgia/foundation/typeconv.hpp +++ b/src/nostalgia/foundation/typeconv.hpp @@ -19,6 +19,28 @@ class Wrap { virtual ~Wrap() = default; }; +template +class WrapIndirect: public Wrap { + private: + T *m_obj = nullptr; + + public: + template + constexpr explicit WrapIndirect(Args &&...args): m_obj(ox::forward(args)...) { + } + + [[nodiscard]] + constexpr auto obj() const noexcept { + return &m_obj; + } + + [[nodiscard]] + constexpr auto obj() noexcept { + return &m_obj; + } + +}; + template class WrapInline: public Wrap { private: diff --git a/src/nostalgia/scene/scenemodule.cpp b/src/nostalgia/scene/scenemodule.cpp index 8f4533cd..93a7d69b 100644 --- a/src/nostalgia/scene/scenemodule.cpp +++ b/src/nostalgia/scene/scenemodule.cpp @@ -4,12 +4,20 @@ #include +#include "scenestatic.hpp" #include "scenemodule.hpp" namespace nostalgia::scene { SceneModule SceneModule::mod; +ox::Vector SceneModule::types() const noexcept { + return { + foundation::generateTypeDesc, + foundation::generateTypeDesc, + }; +} + ox::Vector SceneModule::converters() const noexcept { return { &sceneDocToSceneStaticConverter, diff --git a/src/nostalgia/scene/scenemodule.hpp b/src/nostalgia/scene/scenemodule.hpp index 30c4c8cc..867eb85d 100644 --- a/src/nostalgia/scene/scenemodule.hpp +++ b/src/nostalgia/scene/scenemodule.hpp @@ -17,6 +17,8 @@ class SceneModule: public foundation::Module { public: static SceneModule mod; [[nodiscard]] + ox::Vector types() const noexcept override; + [[nodiscard]] ox::Vector converters() const noexcept override; [[nodiscard]] ox::Vector packTransforms() const noexcept override; diff --git a/src/nostalgia/tools/pack.cpp b/src/nostalgia/tools/pack.cpp index 8968c170..5f78a311 100644 --- a/src/nostalgia/tools/pack.cpp +++ b/src/nostalgia/tools/pack.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "pack/pack.hpp" @@ -44,6 +45,15 @@ static ox::Result readFileBuff(ox::CRStringView path) noexcept { } } +static ox::Error generateTypes(ox::TypeStore *ts) noexcept { + for (const auto mod : *foundation::modules()) { + for (auto gen : mod->types()) { + oxReturnError(gen(ts)); + } + } + return {}; +} + static ox::Error run(const ox::ClArgs &args) noexcept { loadModules(); const auto argSrc = args.getString("src", ""); @@ -61,6 +71,7 @@ static ox::Error run(const ox::ClArgs &args) noexcept { ox::FileSystem32 dst(ox::FileStore32(dstBuff.data(), dstBuff.size())); const auto ctx = foundation::init(ox::make_unique(argSrc), "nost-pack"); core::TypeStore ts(ctx->rom.get()); + oxReturnError(generateTypes(&ts)); oxReturnError(pack(ctx.get(), &ts, &dst)); oxRequireM(pl, GbaPreloader::make()); oxReturnError(preload(&ts, &dst, pl.get())); diff --git a/src/nostalgia/tools/pack/pack.cpp b/src/nostalgia/tools/pack/pack.cpp index 0ee9fcba..83e06713 100644 --- a/src/nostalgia/tools/pack/pack.cpp +++ b/src/nostalgia/tools/pack/pack.cpp @@ -7,8 +7,6 @@ #include #include -#include -#include #include #include "pack.hpp" @@ -36,28 +34,43 @@ static ox::Error pathToInode(ox::FileSystem *dest, ox::ModelObject *obj) noexcep return data.set(2, s.inode); } -/** - * Convert path references in Claw data to inodes to save space - * @param buff buffer holding file - * @return error - */ -static ox::Error transformFileAddresses(ox::FileSystem *dest, ox::ModelObject *obj) noexcept { - for (auto &f : *obj) { - auto &v = f->value; - if (v.type() != ox::ModelValue::Type::Object) { - continue; - } - auto &o = v.get(); - if (o.typeName() == "net.drinkingtea.ox.FileAddress" && o.typeVersion() == 1) { - oxReturnError(pathToInode(dest, &o)); - } else { - oxReturnError(transformFileAddresses(dest, &o)); - } +static ox::Error transformFileAddressesObj(ox::FileSystem *dest, ox::ModelObject *obj) noexcept; +static ox::Error transformFileAddressesVec(ox::FileSystem *dest, ox::ModelValueVector *v) noexcept; + +static ox::Error transformFileAddresses(ox::FileSystem *dest, ox::ModelValue *v) noexcept { + if (v->type() == ox::ModelValue::Type::Object) { + auto &obj = v->get(); + return transformFileAddressesObj(dest, &obj); + } else if (v->type() == ox::ModelValue::Type::Vector) { + auto &vec = v->get(); + return transformFileAddressesVec(dest, &vec); } return {}; } -static ox::Error doTransformations(foundation::Context *ctx, core::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView filePath) noexcept { +static ox::Error transformFileAddressesVec(ox::FileSystem *dest, ox::ModelValueVector *v) noexcept { + for (auto &f : *v) { + oxReturnError(transformFileAddresses(dest, &f)); + } + return {}; +} + +/** + * Convert path references in Claw data to inodes to save space + * @return error + */ +static ox::Error transformFileAddressesObj(ox::FileSystem *dest, ox::ModelObject *obj) noexcept { + if (obj->typeName() == "net.drinkingtea.ox.FileAddress" && obj->typeVersion() == 1) { + return pathToInode(dest, obj); + } + for (auto &f : *obj) { + auto &v = f->value; + oxReturnError(transformFileAddresses(dest, &v)); + } + return {}; +} + +static ox::Error doTransformations(foundation::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView filePath) noexcept { // load file oxRequire(s, dest->stat(filePath)); // do transformations @@ -67,7 +80,7 @@ static ox::Error doTransformations(foundation::Context *ctx, core::TypeStore *ts } // transform FileAddresses oxRequireM(obj, ox::readClaw(ts, buff)); - oxReturnError(transformFileAddresses(dest, &obj)); + oxReturnError(transformFileAddressesObj(dest, &obj)); oxReturnError(ox::writeClaw(&obj).moveTo(&buff)); // write file to dest oxReturnError(dest->write(s.inode, buff.data(), buff.size())); @@ -76,7 +89,7 @@ static ox::Error doTransformations(foundation::Context *ctx, core::TypeStore *ts // claw file transformations are broken out from copy because path to inode // transformations need to be done after the copy to the new FS is complete -static ox::Error transformClaw(foundation::Context *ctx, core::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView path) noexcept { +static ox::Error transformClaw(foundation::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView path) noexcept { // copy oxTracef("pack::transformClaw", "path: {}", path); oxRequire(fileList, dest->ls(path)); @@ -108,9 +121,8 @@ struct VerificationPair { } }; -static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringView path) noexcept { +static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringView path, ox::Vector *verificationPairs) noexcept { oxOutf("copying directory: {}\n", path); - ox::Vector verificationPairs; // copy oxRequire(fileList, src->ls(path)); for (const auto &name : fileList) { @@ -122,7 +134,7 @@ static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringVie oxRequire(stat, src->stat(currentFile)); if (stat.fileType == ox::FileType::Directory) { oxReturnError(dest->mkdir(currentFile, true)); - oxReturnError(copy(src, dest, currentFile + '/')); + oxReturnError(copy(src, dest, currentFile + '/', verificationPairs)); } else { // load file oxRequireM(buff, src->read(currentFile)); @@ -130,10 +142,17 @@ static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringVie oxOutf("writing {}\n", currentFile); oxReturnError(dest->write(currentFile, buff.data(), buff.size())); oxReturnError(verifyFile(dest, currentFile, buff)); - verificationPairs.emplace_back(std::move(currentFile), std::move(buff)); + verificationPairs->emplace_back(std::move(currentFile), std::move(buff)); } } + return {}; +} + +static ox::Error copyFS(ox::FileSystem *src, ox::FileSystem *dest) noexcept { + ox::Vector verificationPairs; + oxReturnError(copy(src, dest, "/", &verificationPairs)); // verify all at once in addition to right after the files are written + oxOutf("Verifying completed destination\n"); for (const auto &v : verificationPairs) { oxReturnError(verifyFile(dest, v.path, v.buff)); } @@ -141,11 +160,14 @@ static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringVie } // transformations need to be done after the copy to the new FS is complete -static ox::Error preloadObj(core::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRStringView path) noexcept { +static ox::Error preloadObj( + ox::TypeStore *ts, ox::FileSystem *romFs, + GbaPreloader *pl, ox::CRStringView path) noexcept { // load file oxRequireM(buff, romFs->read(path)); oxRequireM(obj, ox::readClaw(ts, buff)); if (obj.type()->preloadable) { + oxOutf("preloading {}\n", path); // preload oxRequire(a, pl->startAlloc(ox::sizeOf(&obj))); const auto err = ox::preload(pl, &obj); @@ -163,7 +185,7 @@ static ox::Error preloadObj(core::TypeStore *ts, ox::FileSystem *romFs, GbaPrelo // claw file transformations are broken out because path to inode // transformations need to be done after the copy to the new FS is complete -static ox::Error preloadDir(core::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRStringView path) noexcept { +static ox::Error preloadDir(ox::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRStringView path) noexcept { // copy oxTracef("pack::preload", "path: {}", path); oxRequire(fileList, romFs->ls(path)); @@ -202,14 +224,15 @@ ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, GbaPreloader *pl return {}; } -ox::Error pack(foundation::Context *ctx, core::TypeStore *ts, ox::FileSystem *dest) noexcept { - oxReturnError(copy(ctx->rom.get(), dest, "/")); - oxReturnError(ox::buildTypeDef(ts)); +ox::Error pack(foundation::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept { + oxReturnError(copyFS(ctx->rom.get(), dest)); + oxOut("Doing transforms\n"); oxReturnError(transformClaw(ctx, ts, dest, "/")); return {}; } -ox::Error preload(core::TypeStore *ts, ox::FileSystem *src, GbaPreloader *pl) noexcept { +ox::Error preload(ox::TypeStore *ts, ox::FileSystem *src, GbaPreloader *pl) noexcept { + oxOut("Preloading\n"); return preloadDir(ts, src, pl, "/"); } diff --git a/src/nostalgia/tools/pack/pack.hpp b/src/nostalgia/tools/pack/pack.hpp index 0d4690ae..390fa335 100644 --- a/src/nostalgia/tools/pack/pack.hpp +++ b/src/nostalgia/tools/pack/pack.hpp @@ -11,10 +11,6 @@ namespace foundation { class Context; } -namespace core { -class TypeStore; -} - struct GbaPlatSpec { using PtrType = uint32_t; using size_t = uint32_t; @@ -95,8 +91,8 @@ using GbaPreloader = ox::Preloader; ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, GbaPreloader *pl) noexcept; -auto pack(foundation::Context *ctx, core::TypeStore *ts, ox::FileSystem *dest) noexcept -> ox::Error; +auto pack(foundation::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept -> ox::Error; -auto preload(core::TypeStore *ts, ox::FileSystem *src, GbaPreloader *ph) noexcept -> ox::Error; +auto preload(ox::TypeStore *ts, ox::FileSystem *src, GbaPreloader *ph) noexcept -> ox::Error; }