147 lines
3.7 KiB
C++
147 lines
3.7 KiB
C++
/*
|
|
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <ox/std/defines.hpp>
|
|
|
|
#include <ox/claw/claw.hpp>
|
|
#include <ox/fs/fs.hpp>
|
|
#include <ox/model/metadata.hpp>
|
|
|
|
|
|
#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<std::size_t> getPreloadAddr(keel::Context *ctx, const ox::FileAddress &file) noexcept;
|
|
ox::Result<std::size_t> getPreloadAddr(keel::Context *ctx, ox::CRStringView file) noexcept;
|
|
|
|
#ifndef OX_BARE_METAL
|
|
|
|
template<typename T>
|
|
ox::Result<keel::AssetRef<T>> readObjFile(
|
|
keel::Context *ctx,
|
|
ox::StringView assetId,
|
|
bool forceLoad) noexcept {
|
|
constexpr auto readConvert = [](Context *ctx, const ox::Buffer &buff) -> ox::Result<T> {
|
|
auto [obj, err] = readAsset<T>(buff);
|
|
if (err) {
|
|
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
|
return err;
|
|
}
|
|
oxReturnError(convert<T>(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<T>(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<typename T>
|
|
ox::Result<keel::AssetRef<T>> readObjNoCache(
|
|
keel::Context *ctx,
|
|
ox::CRStringView assetId) noexcept {
|
|
if constexpr(ox::preloadable<T>::value) {
|
|
oxRequire(addr, getPreloadAddr(ctx, assetId));
|
|
return keel::AssetRef<T>(reinterpret_cast<const T*>(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<typename T>
|
|
ox::Result<keel::AssetRef<T>> readObj(
|
|
keel::Context *ctx,
|
|
ox::CRStringView assetId,
|
|
[[maybe_unused]] bool forceLoad = false) noexcept {
|
|
#ifndef OX_BARE_METAL
|
|
return readObjFile<T>(ctx, assetId, forceLoad);
|
|
#else
|
|
return readObjNoCache<T>(ctx, assetId);
|
|
#endif
|
|
}
|
|
|
|
template<typename T>
|
|
ox::Result<keel::AssetRef<T>> readObj(
|
|
keel::Context *ctx,
|
|
const ox::FileAddress &file,
|
|
[[maybe_unused]] bool forceLoad = false) noexcept {
|
|
#ifndef OX_BARE_METAL
|
|
oxRequire(assetId, file.getPath());
|
|
return readObj<T>(ctx, ox::StringView(assetId), forceLoad);
|
|
#else
|
|
if constexpr(ox::preloadable<T>::value) {
|
|
oxRequire(addr, getPreloadAddr(ctx, file));
|
|
return keel::AssetRef<T>(reinterpret_cast<const T*>(addr));
|
|
} else {
|
|
return OxError(1);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
template<typename T>
|
|
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<ox::FileSystem> fs) noexcept;
|
|
|
|
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::CRStringView path) noexcept;
|
|
|
|
ox::Result<char*> loadRom(ox::CRStringView path = "") noexcept;
|
|
|
|
void unloadRom(char*) noexcept;
|
|
|
|
}
|