/* * Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved. */ #pragma once #include #include #include #include #include "asset.hpp" #include "context.hpp" #include "typeconv.hpp" namespace keel { // Pointer to preloaded data that can be stored in FS in place of the actual // data. struct PreloadPtr { static constexpr auto TypeName = "net.drinkingtea.keel.PreloadPtr"; static constexpr auto TypeVersion = 2; uint64_t preloadAddr = 0; }; oxModelBegin(PreloadPtr) oxModelField(preloadAddr) oxModelEnd() ox::Result getPreloadAddr(keel::Context *ctx, const ox::FileAddress &file) noexcept; ox::Result getPreloadAddr(keel::Context *ctx, ox::CRStringView file) noexcept; #ifndef OX_BARE_METAL template ox::Result> readObjFile( keel::Context *ctx, ox::StringView 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) { return err; } oxReturnError(convert(ctx, buff, &obj)); } return std::move(obj); }; ox::StringView path; ox::UUIDStr uuidStr; if (beginsWith(assetId, "uuid://")) { assetId = assetId.substr(7); path = ctx->uuidToPath[assetId]; } else { path = assetId; uuidStr = ctx->pathToUuid[path].toString(); assetId = uuidStr; } if (forceLoad) { oxRequire(buff, ctx->rom->read(path)); 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(path)); oxRequire(obj, readConvert(ctx, buff)); oxReturnError(ctx->assetManager.setAsset(assetId, obj).moveTo(&cached)); } return cached; } } #else template ox::Result> readObjNoCache( keel::Context *ctx, ox::CRStringView assetId) noexcept { if constexpr(ox::preloadable::value) { oxRequire(addr, getPreloadAddr(ctx, assetId)); return keel::AssetRef(reinterpret_cast(addr)); } else { return OxError(1); } } #endif void createUuidMapping(Context *ctx, const ox::String &filePath, const ox::UUID &uuid) noexcept; ox::Error buildUuidMap(Context *ctx) noexcept; template ox::Result> readObj( keel::Context *ctx, ox::CRStringView assetId, [[maybe_unused]] bool forceLoad = false) noexcept { #ifndef OX_BARE_METAL return readObjFile(ctx, assetId, forceLoad); #else return readObjNoCache(ctx, assetId); #endif } template ox::Result> readObj( keel::Context *ctx, const ox::FileAddress &file, [[maybe_unused]] bool forceLoad = false) noexcept { #ifndef OX_BARE_METAL oxRequire(assetId, file.getPath()); return readObj(ctx, ox::StringView(assetId), forceLoad); #else if constexpr(ox::preloadable::value) { oxRequire(addr, getPreloadAddr(ctx, file)); return keel::AssetRef(reinterpret_cast(addr)); } else { return OxError(1); } #endif } template ox::Error writeObj( keel::Context *ctx, const ox::FileAddress &file, const T &obj, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept { oxRequire(objBuff, ox::writeClaw(&obj, fmt)); return ctx->rom->write(file, objBuff.data(), objBuff.size()); } ox::Error setRomFs(Context *ctx, ox::UPtr fs) noexcept; ox::Result> loadRomFs(ox::CRStringView path) noexcept; ox::Result loadRom(ox::CRStringView path = "") noexcept; void unloadRom(char*) noexcept; }