[nostalgia] Add support for asset UUID headers
This commit is contained in:
parent
2b821b73ff
commit
1b7b6e306e
@ -11,9 +11,9 @@
|
||||
|
||||
namespace nostalgia {
|
||||
|
||||
static bool modulesLoaded = false;
|
||||
void loadModules() noexcept {
|
||||
static bool done = false;
|
||||
if (done) {
|
||||
if (modulesLoaded) {
|
||||
return;
|
||||
}
|
||||
const ox::Array<foundation::Module*, 2> mods = {
|
||||
@ -23,7 +23,7 @@ void loadModules() noexcept {
|
||||
for (const auto m : mods) {
|
||||
foundation::registerModule(m);
|
||||
}
|
||||
done = true;
|
||||
modulesLoaded = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -87,8 +87,8 @@ void setBgCbb(Context *ctx, unsigned bgIdx, unsigned cbb) noexcept;
|
||||
/**
|
||||
* @param section describes which section of the selected TileSheetSpace to use (e.g. MEM_PALLETE_BG[section])
|
||||
*/
|
||||
ox::Error loadBgTileSheet(Context *ctx, unsigned cbb, const ox::FileAddress &tilesheet,
|
||||
const ox::FileAddress &palette = nullptr) noexcept;
|
||||
ox::Error loadBgTileSheet(Context *ctx, unsigned cbb, const ox::FileAddress &tilesheetAddr,
|
||||
const ox::FileAddress &paletteAddr = nullptr) noexcept;
|
||||
|
||||
ox::Error loadSpriteTileSheet(Context *ctx,
|
||||
const ox::FileAddress &tilesheetAddr,
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <ox/model/model.hpp>
|
||||
|
||||
#include <nostalgia/foundation/asset.hpp>
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
|
||||
#include "gfx.hpp"
|
||||
@ -39,8 +40,8 @@ ox::Vector<foundation::PackTransform> CoreModule::packTransforms() const noexcep
|
||||
return {
|
||||
// convert tilesheets to CompactTileSheets
|
||||
[](foundation::Context *ctx, ox::Buffer *buff) -> ox::Error {
|
||||
oxRequire(hdr, ox::readClawHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(hdr.typeName, hdr.typeVersion, hdr.typeParams);
|
||||
oxRequire(hdr, foundation::readAssetHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
|
||||
if (typeId == ox::buildTypeId<TileSheetV1>() ||
|
||||
typeId == ox::buildTypeId<TileSheetV2>() ||
|
||||
typeId == ox::buildTypeId<TileSheet>()) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
add_library(
|
||||
NostalgiaFoundation
|
||||
foundation.hpp
|
||||
asset.cpp
|
||||
media.cpp
|
||||
module.cpp
|
||||
typeconv.cpp
|
||||
@ -20,6 +20,8 @@ install(
|
||||
FILES
|
||||
assetmanager.hpp
|
||||
context.hpp
|
||||
foundation.hpp
|
||||
asset.hpp
|
||||
media.hpp
|
||||
module.hpp
|
||||
typeconv.hpp
|
||||
|
47
src/nostalgia/foundation/asset.cpp
Normal file
47
src/nostalgia/foundation/asset.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "asset.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const ox::Buffer &buff) noexcept {
|
||||
return readUuidHeader(buff.data(), buff.size());
|
||||
}
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const char *buff, std::size_t buffLen) noexcept {
|
||||
if (buffLen < 40) {
|
||||
return OxError(1, "Insufficient data contain complete Nostalgia header");
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
ox::Result<ox::ModelObject> readAsset(ox::TypeStore *ts, const ox::Buffer &buff) noexcept {
|
||||
std::size_t offset = 0;
|
||||
if (!readUuidHeader(buff).error) {
|
||||
offset = 40; // the size of N1 headers
|
||||
}
|
||||
return ox::readClaw(ts, buff.data() + offset, buff.size() - offset);
|
||||
}
|
||||
|
||||
ox::Result<AssetHdr> readAssetHeader(const char *buff, std::size_t buffLen) noexcept {
|
||||
AssetHdr out;
|
||||
const auto err = readUuidHeader(buff, buffLen).moveTo(&out.uuid);
|
||||
const auto offset = err ? 0 : 40;
|
||||
buff = buff + offset;
|
||||
buffLen = buffLen - offset;
|
||||
oxReturnError(ox::readClawHeader(buff, buffLen).moveTo(&out.clawHdr));
|
||||
return out;
|
||||
}
|
||||
|
||||
ox::Result<AssetHdr> readAssetHeader(const ox::Buffer &buff) noexcept {
|
||||
return readAssetHeader(buff.data(), buff.size());
|
||||
}
|
||||
|
||||
}
|
42
src/nostalgia/foundation/asset.hpp
Normal file
42
src/nostalgia/foundation/asset.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 <nostalgia/foundation/context.hpp>
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Result<ox::UUID> readUuidHeader(const ox::Buffer &buff) noexcept;
|
||||
|
||||
ox::Result<ox::UUID> readUuidHeader(const char *buff, std::size_t buffLen) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<T> readAsset(const ox::Buffer &buff) noexcept {
|
||||
std::size_t offset = 0;
|
||||
const auto err = readUuidHeader(buff).error;
|
||||
if (!err) {
|
||||
offset = 40; // the size of N1 headers
|
||||
}
|
||||
return ox::readClaw<T>(buff.data() + offset, buff.size() - offset);
|
||||
}
|
||||
|
||||
ox::Result<ox::ModelObject> readAsset(ox::TypeStore *ts, const ox::Buffer &buff) noexcept;
|
||||
|
||||
struct AssetHdr {
|
||||
ox::UUID uuid;
|
||||
ox::ClawHeader clawHdr;
|
||||
};
|
||||
|
||||
ox::Result<AssetHdr> readAssetHeader(const char *buff, std::size_t buffLen) noexcept;
|
||||
|
||||
ox::Result<AssetHdr> readAssetHeader(const ox::Buffer &buff) noexcept;
|
||||
|
||||
}
|
@ -12,10 +12,13 @@
|
||||
|
||||
#include <nostalgia/foundation/context.hpp>
|
||||
|
||||
#include "asset.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
|
||||
// Pointer to preloaded data that can be stored in FS in place of the actual
|
||||
// data.
|
||||
struct PreloadPtr {
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.PreloadPtr";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
@ -30,11 +33,13 @@ ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, const ox::FileA
|
||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, ox::CRStringView file) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<foundation::AssetRef<T>> readObj([[maybe_unused]] foundation::Context *ctx, [[maybe_unused]] ox::CRStringView path,
|
||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||
ox::Result<foundation::AssetRef<T>> 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<T> {
|
||||
auto [obj, err] = ox::readClaw<T>(buff);
|
||||
auto [obj, err] = readAsset<T>(buff);
|
||||
if (err) {
|
||||
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
||||
return err;
|
||||
@ -68,8 +73,10 @@ ox::Result<foundation::AssetRef<T>> readObj([[maybe_unused]] foundation::Context
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Result<foundation::AssetRef<T>> readObj(foundation::Context *ctx, const ox::FileAddress &file,
|
||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||
ox::Result<foundation::AssetRef<T>> readObj(
|
||||
foundation::Context *ctx,
|
||||
const ox::FileAddress &file,
|
||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
oxRequire(path, file.getPath());
|
||||
return readObj<T>(ctx, ox::StringView(path), forceLoad);
|
||||
@ -84,8 +91,11 @@ ox::Result<foundation::AssetRef<T>> readObj(foundation::Context *ctx, const ox::
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeObj(foundation::Context *ctx, const ox::FileAddress &file, const T &obj,
|
||||
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
|
||||
ox::Error writeObj(
|
||||
foundation::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());
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ class Module {
|
||||
Module &operator=(const Module&) noexcept = delete;
|
||||
Module &operator=(Module&&) noexcept = delete;
|
||||
constexpr virtual ~Module() noexcept = default;
|
||||
|
||||
[[nodiscard]]
|
||||
virtual ox::Vector<TypeDescGenerator> types() const noexcept;
|
||||
[[nodiscard]]
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <ox/claw/read.hpp>
|
||||
|
||||
#include "media.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
@ -52,8 +53,8 @@ ox::Result<ox::UniquePtr<Wrap>> convert(
|
||||
const ox::Buffer &srcBuffer,
|
||||
ox::CRStringView dstTypeName,
|
||||
int dstTypeVersion) noexcept {
|
||||
oxRequire(hdr, ox::readClawHeader(srcBuffer));
|
||||
return convert(ctx, srcBuffer, hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion);
|
||||
oxRequire(hdr, readAssetHeader(srcBuffer));
|
||||
return convert(ctx, srcBuffer, hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, dstTypeName, dstTypeVersion);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <ox/claw/write.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
#include "media.hpp"
|
||||
|
||||
namespace nostalgia::foundation {
|
||||
|
||||
@ -135,7 +136,7 @@ class Converter: public BaseConverter {
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) const noexcept final {
|
||||
oxRequireM(src, ox::readClaw<SrcType>(srcBuff));
|
||||
oxRequireM(src, readAsset<SrcType>(srcBuff));
|
||||
auto dst = makeWrap<DstType>();
|
||||
oxReturnError(convert(ctx, &src, wrapCast<DstType>(dst.get())));
|
||||
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
|
||||
@ -176,8 +177,9 @@ ox::Result<ox::Buffer> convertBuffToBuff(foundation::Context *ctx, const ox::Buf
|
||||
|
||||
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>
|
||||
auto transformRule(foundation::Context *ctx, ox::Buffer *buff) -> ox::Error {
|
||||
oxRequire(hdr, ox::readClawHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(hdr.typeName, hdr.typeVersion, hdr.typeParams);
|
||||
oxRequire(hdr, readAssetHeader(*buff));
|
||||
const auto typeId = ox::buildTypeId(
|
||||
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
|
||||
if (typeId == ox::buildTypeId<From>()) {
|
||||
oxReturnError(foundation::convertBuffToBuff<To>(ctx, *buff, fmt).moveTo(buff));
|
||||
}
|
||||
|
@ -13,7 +13,11 @@
|
||||
|
||||
static ox::Error run(int argc, const char **argv) noexcept {
|
||||
ox::trace::init();
|
||||
#ifdef OX_USE_STDLIB
|
||||
// GBA doesn't need the modules and calling this doubles the size of the
|
||||
// binary.
|
||||
nostalgia::loadModules();
|
||||
#endif
|
||||
if (argc < 2) {
|
||||
oxErr("Please provide path to project directory or OxFS file.\n");
|
||||
return OxError(1);
|
||||
|
@ -22,7 +22,7 @@ ox::String configPath(const core::Context *ctx) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<T> readConfig(core::Context *ctx, ox::CRStringView name) noexcept {
|
||||
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto path = ox::sfmt("/{}.json", name);
|
||||
ox::PassThroughFS fs(configPath(ctx));
|
||||
const auto [buff, err] = fs.read(path);
|
||||
@ -41,7 +41,7 @@ ox::Result<T> readConfig(core::Context *ctx) noexcept {
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeConfig(core::Context *ctx, ox::CRStringView name, T *data) noexcept {
|
||||
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto path = ox::sfmt("/{}.json", name);
|
||||
ox::PassThroughFS fs(configPath(ctx));
|
||||
if (const auto err = fs.mkdir("/", true)) {
|
||||
@ -66,8 +66,9 @@ ox::Error writeConfig(core::Context *ctx, T *data) noexcept {
|
||||
template<typename T, typename Func>
|
||||
void openConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
oxAssert(name != "", "Config type has no TypeName");
|
||||
const auto c = readConfig<T>(ctx, name);
|
||||
f(&c.value);
|
||||
const auto [c, err] = readConfig<T>(ctx, name);
|
||||
oxLogError(err);
|
||||
f(&c);
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
@ -79,9 +80,10 @@ void openConfig(core::Context *ctx, Func f) noexcept {
|
||||
template<typename T, typename Func>
|
||||
void editConfig(core::Context *ctx, const auto &name, Func f) noexcept {
|
||||
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
||||
auto c = readConfig<T>(ctx, name);
|
||||
f(&c.value);
|
||||
oxLogError(writeConfig(ctx, name, &c.value));
|
||||
auto [c, err] = readConfig<T>(ctx, name);
|
||||
oxLogError(err);
|
||||
f(&c);
|
||||
oxLogError(writeConfig(ctx, name, &c));
|
||||
}
|
||||
|
||||
template<typename T, typename Func>
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <ox/std/hashmap.hpp>
|
||||
|
||||
#include <nostalgia/core/typestore.hpp>
|
||||
#include <nostalgia/foundation/media.hpp>
|
||||
|
||||
#include "nostalgiastudio_export.h"
|
||||
|
||||
@ -129,9 +130,9 @@ template<typename T>
|
||||
ox::Result<T> Project::loadObj(const ox::String &path) const noexcept {
|
||||
oxRequire(buff, loadBuff(path));
|
||||
if constexpr (ox::is_same_v<T, ox::ModelObject>) {
|
||||
return ox::readClaw(&m_typeStore, buff);
|
||||
return foundation::readAsset(&m_typeStore, buff);
|
||||
} else {
|
||||
return ox::readClaw<T>(buff);
|
||||
return foundation::readAsset<T>(buff);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ static ox::Error doTransformations(foundation::Context *ctx, ox::TypeStore *ts,
|
||||
oxReturnError(tr(ctx, &buff));
|
||||
}
|
||||
// transform FileAddresses
|
||||
oxRequireM(obj, ox::readClaw(ts, buff));
|
||||
oxRequireM(obj, foundation::readAsset(ts, buff));
|
||||
oxReturnError(transformFileAddressesObj(dest, &obj));
|
||||
oxReturnError(ox::writeClaw(&obj).moveTo(&buff));
|
||||
// write file to dest
|
||||
@ -165,7 +165,7 @@ static ox::Error preloadObj(
|
||||
GbaPreloader *pl, ox::CRStringView path) noexcept {
|
||||
// load file
|
||||
oxRequireM(buff, romFs->read(path));
|
||||
oxRequireM(obj, ox::readClaw(ts, buff));
|
||||
oxRequireM(obj, foundation::readAsset(ts, buff));
|
||||
if (obj.type()->preloadable) {
|
||||
oxOutf("preloading {}\n", path);
|
||||
// preload
|
||||
|
Loading…
Reference in New Issue
Block a user