[nostalgia] Integrate Ox Preloader
This commit is contained in:
@@ -17,6 +17,7 @@ class AssetManager;
|
||||
template<typename T>
|
||||
class AssetRef;
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
template<typename T>
|
||||
class AssetContainer {
|
||||
|
||||
@@ -260,5 +261,36 @@ class AssetManager {
|
||||
}
|
||||
}
|
||||
};
|
||||
#else
|
||||
template<typename T>
|
||||
class AssetRef: public ox::SignalHandler {
|
||||
private:
|
||||
T &m_obj;
|
||||
|
||||
public:
|
||||
explicit constexpr AssetRef(T &obj) noexcept: m_obj(obj) {
|
||||
}
|
||||
|
||||
constexpr const T *get() const noexcept {
|
||||
return &m_obj;
|
||||
}
|
||||
|
||||
constexpr const T &operator*() const & noexcept {
|
||||
return &m_obj;
|
||||
}
|
||||
|
||||
constexpr const T &&operator*() const && noexcept {
|
||||
return &m_obj;
|
||||
}
|
||||
|
||||
constexpr const T *operator->() const noexcept {
|
||||
return &m_obj;
|
||||
}
|
||||
|
||||
explicit constexpr operator bool() const noexcept {
|
||||
return m_obj;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -91,6 +91,7 @@ class Context {
|
||||
ox::UniquePtr<BaseClipboardObject> clipboard;
|
||||
#else
|
||||
bool running = true;
|
||||
std::size_t preloadSectionOffset = 0;
|
||||
#endif
|
||||
protected:
|
||||
#ifndef OX_BARE_METAL
|
||||
|
||||
@@ -37,13 +37,31 @@ static void initTimer() noexcept {
|
||||
REG_IE = REG_IE | Int_timer0;
|
||||
}
|
||||
|
||||
static ox::Result<std::size_t> findPreloadSection() noexcept {
|
||||
// put the header in the wrong order to prevent mistaking this code for the
|
||||
// media section
|
||||
constexpr auto headerP2 = "D_HEADER________";
|
||||
constexpr auto headerP1 = "NOSTALGIA_PRELOA";
|
||||
constexpr auto headerP1Len = ox_strlen(headerP2);
|
||||
constexpr auto headerP2Len = ox_strlen(headerP1);
|
||||
constexpr auto headerLen = headerP1Len + headerP2Len;
|
||||
for (auto current = MEM_ROM; current < reinterpret_cast<char*>(0x0a000000); current += headerLen) {
|
||||
if (ox_memcmp(current, headerP1, headerP1Len) == 0 &&
|
||||
ox_memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) {
|
||||
return reinterpret_cast<std::size_t>(current + headerLen);
|
||||
}
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
ox::Result<ox::UniquePtr<Context>> init(ox::UniquePtr<ox::FileSystem> fs, const char *appName) noexcept {
|
||||
auto ctx = ox::make_unique<Context>();
|
||||
ctx->rom = std::move(fs);
|
||||
ctx->appName = std::move(appName);
|
||||
ctx->appName = appName;
|
||||
oxReturnError(initGfx(ctx.get()));
|
||||
initTimer();
|
||||
initIrq();
|
||||
oxReturnError(findPreloadSection().moveTo(&ctx->preloadSectionOffset));
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,8 @@ ox::Error loadSpritePalette(Context *ctx, unsigned cbb, const ox::FileAddress &p
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void puts(Context *ctx, int column, int row, const char *str) noexcept {
|
||||
for (int i = 0; str[i]; i++) {
|
||||
setTile(ctx, 0, column + i, row, static_cast<uint8_t>(charMap[static_cast<int>(str[i])]));
|
||||
const auto c = charMap[static_cast<unsigned>(str[i])];
|
||||
setTile(ctx, 0, column + i, row, static_cast<uint8_t>(c));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/mc/read.hpp>
|
||||
#include <ox/preloader/preloader.hpp>
|
||||
#include <ox/std/std.hpp>
|
||||
|
||||
#include "../media.hpp"
|
||||
@@ -14,11 +15,11 @@ namespace nostalgia::core {
|
||||
ox::Result<char*> loadRom(const char*) noexcept {
|
||||
// put the header in the wrong order to prevent mistaking this code for the
|
||||
// media section
|
||||
constexpr auto headerP2 = "_HEADER_________";
|
||||
constexpr auto headerP1 = "NOSTALGIA_MEDIA";
|
||||
constexpr auto headerP1Len = 15;
|
||||
constexpr auto headerP2Len = 16;
|
||||
constexpr auto headerLen = headerP1Len + headerP2Len + 1;
|
||||
constexpr auto headerP2 = "HEADER__________";
|
||||
constexpr auto headerP1 = "NOSTALGIA_MEDIA_";
|
||||
constexpr auto headerP1Len = ox_strlen(headerP2);
|
||||
constexpr auto headerP2Len = ox_strlen(headerP1);
|
||||
constexpr auto headerLen = headerP1Len + headerP2Len;
|
||||
for (auto current = MEM_ROM; current < reinterpret_cast<char*>(0x0a000000); current += headerLen) {
|
||||
if (ox_memcmp(current, headerP1, headerP1Len) == 0 &&
|
||||
ox_memcmp(current + headerP1Len, headerP2, headerP2Len) == 0) {
|
||||
@@ -31,4 +32,12 @@ ox::Result<char*> loadRom(const char*) noexcept {
|
||||
void unloadRom(char*) noexcept {
|
||||
}
|
||||
|
||||
ox::Result<std::size_t> getPreloadAddr(Context *ctx, const ox::FileAddress &file) noexcept {
|
||||
oxRequire(stat, ctx->rom->stat(file));
|
||||
oxRequire(buff, ctx->rom->directAccess(file));
|
||||
PreloadPtr p;
|
||||
oxReturnError(ox::readMC(buff, stat.size, &p));
|
||||
return p.preloadAddr + ctx->preloadSectionOffset;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,14 +8,28 @@
|
||||
|
||||
#include <ox/claw/claw.hpp>
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/model/metadata.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
struct PreloadPtr {
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.PreloadPtr";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
uint32_t preloadAddr = 0;
|
||||
};
|
||||
|
||||
oxModelBegin(PreloadPtr)
|
||||
oxModelField(preloadAddr)
|
||||
oxModelEnd()
|
||||
|
||||
ox::Result<std::size_t> getPreloadAddr(Context *ctx, const ox::FileAddress &file) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, bool forceLoad = false) noexcept {
|
||||
ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file,
|
||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||
#ifndef OX_BARE_METAL
|
||||
constexpr auto readConvert = [](const ox::Buffer &buff) -> ox::Result<T> {
|
||||
auto [obj, err] = ox::readClaw<T>(buff);
|
||||
@@ -43,12 +57,17 @@ ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, bool
|
||||
return std::move(cached);
|
||||
}
|
||||
#else
|
||||
return OxError(1);
|
||||
if constexpr(ox::preloadable<T>::value) {
|
||||
return AssetRef<T>{*reinterpret_cast<T*>(getPreloadAddr(ctx, file))};
|
||||
} else {
|
||||
return OxError(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error writeObj(Context *ctx, const ox::FileAddress &file, const T &obj, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
|
||||
ox::Error writeObj(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());
|
||||
}
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Result<ox::UniquePtr<ox::DescriptorType>> TypeStore::loadDescriptor(const ox::String &name, int version) noexcept {
|
||||
ox::Result<ox::UniquePtr<ox::DescriptorType>> TypeStore::loadDescriptor(ox::CRStringView typeId) noexcept {
|
||||
constexpr auto descPath = "/.nostalgia/type_descriptors";
|
||||
auto path = ox::sfmt("{}/{};{}", descPath, name, version);
|
||||
auto path = ox::sfmt("{}/{}", descPath, typeId);
|
||||
oxRequire(buff, m_fs->read(path));
|
||||
auto dt = ox::make_unique<ox::DescriptorType>();
|
||||
oxReturnError(ox::readClaw<ox::DescriptorType>(buff, dt.get()));
|
||||
return dt;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class TypeStore: public ox::TypeStore {
|
||||
}
|
||||
|
||||
protected:
|
||||
ox::Result<ox::UniquePtr<ox::DescriptorType>> loadDescriptor(const ox::String &name, int version) noexcept override;
|
||||
ox::Result<ox::UniquePtr<ox::DescriptorType>> loadDescriptor(ox::CRStringView typeId) noexcept override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -32,4 +32,8 @@ void unloadRom(char *rom) noexcept {
|
||||
ox::safeDelete(rom);
|
||||
}
|
||||
|
||||
ox::Result<void*> findPreloadSection() noexcept {
|
||||
return OxError(1, "findPreloadSection is unsupported on this platform");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user