From 5e43eff6318b52cbcdbdba59b3c0005d9fd30518 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 12 Feb 2023 22:13:32 -0600 Subject: [PATCH] [nostalgia] Add UUID to file path mapping --- src/nostalgia/core/glfw/core.cpp | 4 +- src/nostalgia/foundation/asset.cpp | 4 +- src/nostalgia/foundation/assetmanager.hpp | 23 +++---- src/nostalgia/foundation/context.hpp | 3 + src/nostalgia/foundation/foundation.hpp | 4 +- src/nostalgia/foundation/media.cpp | 30 +++++++++ src/nostalgia/foundation/media.hpp | 77 ++++++++++++++++------- src/nostalgia/tools/pack.cpp | 2 +- 8 files changed, 105 insertions(+), 42 deletions(-) diff --git a/src/nostalgia/core/glfw/core.cpp b/src/nostalgia/core/glfw/core.cpp index 4033e8db..1f8bf401 100644 --- a/src/nostalgia/core/glfw/core.cpp +++ b/src/nostalgia/core/glfw/core.cpp @@ -15,14 +15,14 @@ namespace nostalgia::core { ox::Result> init(ox::UPtr fs, ox::CRStringView appName) noexcept { - auto ctx = foundation::init(std::move(fs), appName); + oxRequireM(ctx, foundation::init(std::move(fs), appName)); const auto id = ox::make(); ctx->setWindowerData(id); using namespace std::chrono; id->startTime = duration_cast(system_clock::now().time_since_epoch()).count(); glfwInit(); oxReturnError(initGfx(ctx.get())); - return ctx; + return std::move(ctx); } ox::Error run(Context *ctx) noexcept { diff --git a/src/nostalgia/foundation/asset.cpp b/src/nostalgia/foundation/asset.cpp index bbc4d1d9..6d15d049 100644 --- a/src/nostalgia/foundation/asset.cpp +++ b/src/nostalgia/foundation/asset.cpp @@ -17,9 +17,7 @@ ox::Result readUuidHeader(const char *buff, std::size_t buffLen) noexc if (ox_memcmp(buff, "N1;", 3) != 0) { return OxError(2, "No Nostalgia header data"); } - ox::UUID out; - oxReturnError(out.fromString(ox::StringView(buff + 3, 36))); - return out; + return ox::UUID::fromString(ox::StringView(buff + 3, 36)); } ox::Result readAsset(ox::TypeStore *ts, const ox::Buffer &buff) noexcept { diff --git a/src/nostalgia/foundation/assetmanager.hpp b/src/nostalgia/foundation/assetmanager.hpp index b32e41a7..aaab6147 100644 --- a/src/nostalgia/foundation/assetmanager.hpp +++ b/src/nostalgia/foundation/assetmanager.hpp @@ -28,6 +28,7 @@ class AssetContainer { ox::Signal updated; private: + ox::UUID uuid; T m_obj; mutable int m_references = 0; @@ -190,14 +191,14 @@ class AssetManager { ox::HashMap>> m_cache; public: - ox::Result> getAsset(const ox::String &path) const noexcept { - auto out = m_cache.at(path); + ox::Result> getAsset(const ox::String &assetId) const noexcept { + auto out = m_cache.at(assetId); oxReturnError(out); return AssetRef(out.value->get()); } - ox::Result> setAsset(const ox::String &path, const T &obj) noexcept { - auto &p = m_cache[path]; + ox::Result> setAsset(const ox::String &assetId, const T &obj) noexcept { + auto &p = m_cache[assetId]; if (!p) { p = ox::make_unique>(obj); } else { @@ -207,8 +208,8 @@ class AssetManager { return AssetRef(p.get()); } - ox::Result> setAsset(const ox::String &path, T &&obj) noexcept { - auto &p = m_cache[path]; + ox::Result> setAsset(const ox::String &assetId, T &&obj) noexcept { + auto &p = m_cache[assetId]; if (!p) { p = ox::make_unique>(obj); } else { @@ -221,7 +222,7 @@ class AssetManager { void gc() noexcept final { for (const auto &ack : m_cache.keys()) { auto &ac = m_cache[ack]; - if (ac->references()) { + if (!ac->references()) { m_cache.erase(ack); } } @@ -243,15 +244,15 @@ class AssetManager { public: template - ox::Result> getAsset(const ox::String &path) noexcept { + ox::Result> getAsset(const ox::String &assetId) noexcept { auto m = getTypeManager(); - return m->getAsset(path); + return m->getAsset(assetId); } template - ox::Result> setAsset(const ox::String &path, const T &obj) noexcept { + ox::Result> setAsset(const ox::String &assetId, const T &obj) noexcept { auto m = getTypeManager(); - return m->setAsset(path, obj); + return m->setAsset(assetId, obj); } void gc() noexcept { diff --git a/src/nostalgia/foundation/context.hpp b/src/nostalgia/foundation/context.hpp index 24add52d..a127b553 100644 --- a/src/nostalgia/foundation/context.hpp +++ b/src/nostalgia/foundation/context.hpp @@ -21,6 +21,9 @@ class Context { ox::StringView appName = "Nostalgia Foundation App"; #ifndef OX_BARE_METAL AssetManager assetManager; + bool useUuids = false; + ox::HashMap pathToUuid; + ox::HashMap uuidToPath; ox::Vector converters; ox::Vector packTransforms; #else diff --git a/src/nostalgia/foundation/foundation.hpp b/src/nostalgia/foundation/foundation.hpp index a6f3df5e..a5e60787 100644 --- a/src/nostalgia/foundation/foundation.hpp +++ b/src/nostalgia/foundation/foundation.hpp @@ -7,15 +7,17 @@ #include #include "context.hpp" +#include "media.hpp" #include "module.hpp" namespace nostalgia::foundation { template -ox::UPtr init(ox::UPtr &&fs, ox::CRStringView appName) noexcept { +ox::Result> init(ox::UPtr &&fs, ox::CRStringView appName) noexcept { auto ctx = ox::make_unique(); ctx->rom = std::move(fs); ctx->appName = appName; + oxReturnError(buildUuidMap(ctx.get())); auto mods = modules(); if (mods) { for (auto &mod : *mods) { diff --git a/src/nostalgia/foundation/media.cpp b/src/nostalgia/foundation/media.cpp index f07b8370..b16f4091 100644 --- a/src/nostalgia/foundation/media.cpp +++ b/src/nostalgia/foundation/media.cpp @@ -40,6 +40,32 @@ ox::Result findPreloadSection() noexcept { return OxError(1, "findPreloadSection is unsupported on this platform"); } +static ox::Error buildUuidMap(Context *ctx, ox::CRStringView path) noexcept { + oxRequire(files, ctx->rom->ls(path)); + for (const auto &f : files) { + oxRequire(filePath, ox::join("/", ox::Array{path, f})); + oxRequire(stat, ctx->rom->stat(filePath)); + if (stat.fileType == ox::FileType::NormalFile) { + oxRequire(data, ctx->rom->read(filePath)); + oxRequire(hdr, readAssetHeader(data)); + ctx->pathToUuid[filePath] = hdr.uuid; + ctx->uuidToPath[hdr.uuid.toString()] = filePath; + } else if (stat.fileType == ox::FileType::Directory) { + if (!beginsWith(f, ".")) { + oxReturnError(buildUuidMap(ctx, filePath)); + } + } + } + return {}; +} + +ox::Error buildUuidMap(Context *ctx) noexcept { + if (!ctx->rom) { + return OxError(1, "No ROM FS"); + } + return buildUuidMap(ctx, ""); +} + } #else @@ -50,6 +76,10 @@ ox::Result findPreloadSection() noexcept { namespace nostalgia::foundation { +ox::Error buildUuidMap(Context*) noexcept { + return {}; +} + ox::Result loadRom(ox::CRStringView) noexcept { // put the header in the wrong order to prevent mistaking this code for the // media section diff --git a/src/nostalgia/foundation/media.hpp b/src/nostalgia/foundation/media.hpp index b6f6d5ff..1f50dbcf 100644 --- a/src/nostalgia/foundation/media.hpp +++ b/src/nostalgia/foundation/media.hpp @@ -10,9 +10,9 @@ #include #include -#include #include "asset.hpp" +#include "context.hpp" #include "typeconv.hpp" namespace nostalgia::foundation { @@ -32,13 +32,14 @@ oxModelEnd() ox::Result getPreloadAddr(foundation::Context *ctx, const ox::FileAddress &file) noexcept; ox::Result getPreloadAddr(foundation::Context *ctx, ox::CRStringView file) noexcept; -template -ox::Result> readObj( - [[maybe_unused]] foundation::Context *ctx, - [[maybe_unused]] ox::CRStringView path, - [[maybe_unused]] bool forceLoad = false) noexcept { #ifndef OX_BARE_METAL - const auto readConvert = [ctx](const ox::Buffer &buff) -> ox::Result { + +template +ox::Result> readObjFile( + foundation::Context *ctx, + ox::CRStringView assetId, + bool forceLoad) noexcept { + constexpr auto readConvert = [](Context *ctx, const ox::Buffer &buff) -> ox::Result { auto [obj, err] = readAsset(buff); if (err) { if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) { @@ -48,27 +49,55 @@ ox::Result> readObj( } return std::move(obj); }; - if (forceLoad) { - oxRequire(buff, ctx->rom->read(path)); - oxRequire(obj, readConvert(buff)); - oxRequire(cached, ctx->assetManager.setAsset(path, obj)); - return std::move(cached); + ox::StringView path; + if (ctx->useUuids) { + path = ctx->uuidToPath[assetId]; } else { - auto [cached, err] = ctx->assetManager.getAsset(path); - if (err) { - oxRequire(buff, ctx->rom->read(path)); - oxRequire(obj, readConvert(buff)); - oxReturnError(ctx->assetManager.setAsset(path, obj).moveTo(&cached)); - } - return std::move(cached); + path = assetId; } + if (forceLoad) { + oxRequire(buff, ctx->rom->read(assetId)); + oxRequire(obj, readConvert(ctx, buff)); + oxRequire(cached, ctx->assetManager.setAsset(assetId, obj)); + return cached; + } else { + auto [cached, err] = ctx->assetManager.getAsset(assetId); + if (err) { + oxRequire(buff, ctx->rom->read(assetId)); + oxRequire(obj, readConvert(ctx, buff)); + oxReturnError(ctx->assetManager.setAsset(assetId, obj).moveTo(&cached)); + } + return cached; + } +} + #else + +template +ox::Result> readObjNoCache( + foundation::Context *ctx, + ox::CRStringView assetId) noexcept { if constexpr(ox::preloadable::value) { - oxRequire(addr, getPreloadAddr(ctx, path)); + oxRequire(addr, getPreloadAddr(ctx, assetId)); return foundation::AssetRef(reinterpret_cast(addr)); } else { return OxError(1); } +} + +#endif + +ox::Error buildUuidMap(Context *ctx) noexcept; + +template +ox::Result> readObj( + [[maybe_unused]] foundation::Context *ctx, + [[maybe_unused]] ox::CRStringView assetId, + [[maybe_unused]] bool forceLoad = false) noexcept { +#ifndef OX_BARE_METAL + return readObjFile(ctx, assetId, forceLoad); +#else + return readObjNoCache(ctx, assetId); #endif } @@ -78,8 +107,8 @@ ox::Result> readObj( const ox::FileAddress &file, [[maybe_unused]] bool forceLoad = false) noexcept { #ifndef OX_BARE_METAL - oxRequire(path, file.getPath()); - return readObj(ctx, ox::StringView(path), forceLoad); + oxRequire(assetId, file.getPath()); + return readObj(ctx, ox::StringView(assetId), forceLoad); #else if constexpr(ox::preloadable::value) { oxRequire(addr, getPreloadAddr(ctx, file)); @@ -100,9 +129,9 @@ ox::Error writeObj( return ctx->rom->write(file, objBuff.data(), objBuff.size()); } -ox::Result> loadRomFs(ox::CRStringView path) noexcept; +ox::Result> loadRomFs(ox::CRStringView assetId) noexcept; -ox::Result loadRom(ox::CRStringView path = "") noexcept; +ox::Result loadRom(ox::CRStringView assetId = "") noexcept; void unloadRom(char*) noexcept; diff --git a/src/nostalgia/tools/pack.cpp b/src/nostalgia/tools/pack.cpp index 5f78a311..8eb54744 100644 --- a/src/nostalgia/tools/pack.cpp +++ b/src/nostalgia/tools/pack.cpp @@ -69,7 +69,7 @@ static ox::Error run(const ox::ClArgs &args) noexcept { ox::Buffer dstBuff(32 * ox::units::MB); oxReturnError(ox::FileSystem32::format(dstBuff.data(), dstBuff.size())); ox::FileSystem32 dst(ox::FileStore32(dstBuff.data(), dstBuff.size())); - const auto ctx = foundation::init(ox::make_unique(argSrc), "nost-pack"); + oxRequire(ctx, foundation::init(ox::make_unique(argSrc), "nost-pack")); core::TypeStore ts(ctx->rom.get()); oxReturnError(generateTypes(&ts)); oxReturnError(pack(ctx.get(), &ts, &dst));