Compare commits
No commits in common. "4ddf7a88c94805603ae341347fe98eb7d7f276d9" and "1cc3549d008fe12f63d8782ffff6fda1ce56a8b4" have entirely different histories.
4ddf7a88c9
...
1cc3549d00
2
deps/ox/src/ox/claw/test/tests.cpp
vendored
2
deps/ox/src/ox/claw/test/tests.cpp
vendored
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#undef NDEBUG
|
#undef NDEBUG
|
||||||
|
|
||||||
#include <cassert>
|
#include <assert.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
7
deps/ox/src/ox/claw/write.hpp
vendored
7
deps/ox/src/ox/claw/write.hpp
vendored
@ -93,14 +93,7 @@ Result<String> writeClawHeader(T *t, ClawFormat fmt) noexcept {
|
|||||||
|
|
||||||
Result<Buffer> writeClaw(auto *t, ClawFormat fmt = ClawFormat::Metal) {
|
Result<Buffer> writeClaw(auto *t, ClawFormat fmt = ClawFormat::Metal) {
|
||||||
oxRequire(header, detail::writeClawHeader(t, fmt));
|
oxRequire(header, detail::writeClawHeader(t, fmt));
|
||||||
#ifdef OX_USE_STDLIB
|
|
||||||
oxRequire(data, fmt == ClawFormat::Metal ? writeMC(t) : writeOC(t));
|
oxRequire(data, fmt == ClawFormat::Metal ? writeMC(t) : writeOC(t));
|
||||||
#else
|
|
||||||
if (fmt != ClawFormat::Metal) {
|
|
||||||
return OxError(1, "OC is not supported in this build");
|
|
||||||
}
|
|
||||||
oxRequire(data, writeMC(t));
|
|
||||||
#endif
|
|
||||||
Buffer out(header.len() + data.size());
|
Buffer out(header.len() + data.size());
|
||||||
memcpy(out.data(), header.data(), header.len());
|
memcpy(out.data(), header.data(), header.len());
|
||||||
memcpy(out.data() + header.len(), data.data(), data.size());
|
memcpy(out.data() + header.len(), data.data(), data.size());
|
||||||
|
@ -319,7 +319,7 @@ Error FileStoreTemplate<size_t>::read(InodeId_t id, void *out, FsSize_t outSize,
|
|||||||
// error check
|
// error check
|
||||||
if (!src.valid()) {
|
if (!src.valid()) {
|
||||||
oxTracef("ox::fs::FileStoreTemplate::read::fail", "Could not find requested item: {}", id);
|
oxTracef("ox::fs::FileStoreTemplate::read::fail", "Could not find requested item: {}", id);
|
||||||
return OxError(1, "Could not find requested item");
|
return OxError(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto srcData = m_buffer->template dataOf<uint8_t>(src);
|
auto srcData = m_buffer->template dataOf<uint8_t>(src);
|
||||||
|
2
deps/ox/src/ox/mc/write.hpp
vendored
2
deps/ox/src/ox/mc/write.hpp
vendored
@ -342,7 +342,7 @@ constexpr Error MetalClawWriter::field(const char*, T *val, std::size_t len) noe
|
|||||||
|
|
||||||
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||||
ModelHandlerInterface handler{&writer};
|
ModelHandlerInterface handler{&writer};
|
||||||
handler.setTypeInfo<T>("List", 0, {}, static_cast<int>(len));
|
handler.setTypeInfo<T>("List", 0, {}, len);
|
||||||
|
|
||||||
// write the array
|
// write the array
|
||||||
for (std::size_t i = 0; i < len; i++) {
|
for (std::size_t i = 0; i < len; i++) {
|
||||||
|
10
deps/ox/src/ox/model/desctypes.hpp
vendored
10
deps/ox/src/ox/model/desctypes.hpp
vendored
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
#include "optype.hpp"
|
#include "optype.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include "typenamecatcher.hpp"
|
|
||||||
|
|
||||||
namespace ox {
|
namespace ox {
|
||||||
|
|
||||||
@ -27,15 +26,8 @@ using FieldName = String;
|
|||||||
|
|
||||||
using TypeParamPack = Vector<String>;
|
using TypeParamPack = Vector<String>;
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr auto buildTypeId() noexcept {
|
|
||||||
constexpr auto name = requireModelTypeName<T>();
|
|
||||||
constexpr auto version = requireModelTypeVersion<T>();
|
|
||||||
return ox::sfmt("{};{}", name, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr auto buildTypeId(CRStringView name, int version,
|
static constexpr auto buildTypeId(CRStringView name, int version,
|
||||||
const TypeParamPack &typeParams = {}) noexcept {
|
const TypeParamPack &typeParams) noexcept {
|
||||||
String tp;
|
String tp;
|
||||||
if (typeParams.size()) {
|
if (typeParams.size()) {
|
||||||
tp = "#";
|
tp = "#";
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
|
|
||||||
#project packages
|
#project packages
|
||||||
|
|
||||||
add_subdirectory(appmodules)
|
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
add_subdirectory(foundation)
|
|
||||||
add_subdirectory(geo)
|
add_subdirectory(geo)
|
||||||
add_subdirectory(scene)
|
add_subdirectory(scene)
|
||||||
add_subdirectory(world)
|
add_subdirectory(world)
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
add_library(
|
|
||||||
NostalgiaAppModules OBJECT
|
|
||||||
appmodules.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT MSVC)
|
|
||||||
target_compile_options(NostalgiaAppModules PRIVATE -Wsign-conversion)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(
|
|
||||||
NostalgiaAppModules PUBLIC
|
|
||||||
NostalgiaCore
|
|
||||||
NostalgiaFoundation
|
|
||||||
NostalgiaScene
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
appmodules.hpp
|
|
||||||
DESTINATION
|
|
||||||
include/nostalgia/appmodules
|
|
||||||
)
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ox/std/array.hpp>
|
|
||||||
|
|
||||||
#include <nostalgia/foundation/module.hpp>
|
|
||||||
|
|
||||||
#include <nostalgia/core/module.hpp>
|
|
||||||
#include <nostalgia/scene/scenemodule.hpp>
|
|
||||||
|
|
||||||
namespace nostalgia {
|
|
||||||
|
|
||||||
void loadModules() noexcept {
|
|
||||||
static bool done = false;
|
|
||||||
if (done) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const ox::Array<foundation::Module*, 2> mods = {
|
|
||||||
&core::CoreModule::mod,
|
|
||||||
&scene::SceneModule::mod,
|
|
||||||
};
|
|
||||||
for (const auto m : mods) {
|
|
||||||
foundation::registerModule(m);
|
|
||||||
}
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace nostalgia {
|
|
||||||
|
|
||||||
void loadModules() noexcept;
|
|
||||||
|
|
||||||
}
|
|
@ -1,7 +1,8 @@
|
|||||||
add_library(
|
add_library(
|
||||||
NostalgiaCore-Common OBJECT
|
NostalgiaCore-Common OBJECT
|
||||||
gfx.cpp
|
gfx.cpp
|
||||||
module.cpp
|
media.cpp
|
||||||
|
typeconv.cpp
|
||||||
typestore.cpp
|
typestore.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ add_library(
|
|||||||
NostalgiaCore-Headless
|
NostalgiaCore-Headless
|
||||||
headless/core.cpp
|
headless/core.cpp
|
||||||
headless/gfx.cpp
|
headless/gfx.cpp
|
||||||
|
headless/media.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(NostalgiaCore)
|
add_library(NostalgiaCore)
|
||||||
@ -21,6 +23,7 @@ if(NOT NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
|
|||||||
glfw/gfx.cpp
|
glfw/gfx.cpp
|
||||||
userland/gfx.cpp
|
userland/gfx.cpp
|
||||||
userland/gfx_opengl.cpp
|
userland/gfx_opengl.cpp
|
||||||
|
userland/media.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
NostalgiaCore PUBLIC
|
NostalgiaCore PUBLIC
|
||||||
@ -41,6 +44,7 @@ else()
|
|||||||
gba/gfx.cpp
|
gba/gfx.cpp
|
||||||
gba/irq.arm.cpp
|
gba/irq.arm.cpp
|
||||||
gba/irq.s
|
gba/irq.s
|
||||||
|
gba/media.cpp
|
||||||
gba/panic.cpp
|
gba/panic.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
@ -55,7 +59,8 @@ endif()
|
|||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
NostalgiaCore-Common PUBLIC
|
NostalgiaCore-Common PUBLIC
|
||||||
NostalgiaFoundation
|
OxClaw
|
||||||
|
OxFS
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
@ -74,6 +79,7 @@ endif()
|
|||||||
|
|
||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
|
assetmanager.hpp
|
||||||
clipboard.hpp
|
clipboard.hpp
|
||||||
color.hpp
|
color.hpp
|
||||||
config.hpp
|
config.hpp
|
||||||
@ -83,6 +89,7 @@ install(
|
|||||||
event.hpp
|
event.hpp
|
||||||
gfx.hpp
|
gfx.hpp
|
||||||
input.hpp
|
input.hpp
|
||||||
|
media.hpp
|
||||||
typeconv.hpp
|
typeconv.hpp
|
||||||
typestore.hpp
|
typestore.hpp
|
||||||
DESTINATION
|
DESTINATION
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -10,7 +10,7 @@
|
|||||||
#include <ox/std/hashmap.hpp>
|
#include <ox/std/hashmap.hpp>
|
||||||
#include <ox/std/utility.hpp>
|
#include <ox/std/utility.hpp>
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
class AssetManager;
|
class AssetManager;
|
||||||
|
|
@ -1,15 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
#include <ox/model/desctypes.hpp>
|
|
||||||
#include <ox/std/buffer.hpp>
|
#include <ox/std/buffer.hpp>
|
||||||
|
|
||||||
#include <nostalgia/foundation/context.hpp>
|
#include "assetmanager.hpp"
|
||||||
|
|
||||||
#include "event.hpp"
|
#include "event.hpp"
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
|
|
||||||
@ -21,14 +19,15 @@ namespace nostalgia::core {
|
|||||||
|
|
||||||
class BaseClipboardObject {
|
class BaseClipboardObject {
|
||||||
public:
|
public:
|
||||||
virtual ~BaseClipboardObject() noexcept = default;
|
virtual ~BaseClipboardObject() = default;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
virtual ox::String typeId() const noexcept = 0;
|
virtual ox::String typeId() const noexcept = 0;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr auto typeMatch(auto name, auto version) const noexcept {
|
constexpr auto typeMatch(auto name, auto version) const noexcept {
|
||||||
return typeId() == ox::buildTypeId(name, version);
|
auto inId = ox::sfmt("{};{}", name, version);
|
||||||
|
return typeId() == inId;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,7 +35,7 @@ template<typename T>
|
|||||||
class ClipboardObject: public BaseClipboardObject {
|
class ClipboardObject: public BaseClipboardObject {
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::String typeId() const noexcept final {
|
ox::String typeId() const noexcept final {
|
||||||
return ox::buildTypeId(T::TypeName, T::TypeVersion);
|
return ox::sfmt("{};{}", T::TypeName, T::TypeVersion);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,7 +46,7 @@ struct BgCbbData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// User Input Output
|
// User Input Output
|
||||||
class Context: public foundation::Context {
|
class Context {
|
||||||
friend constexpr void setApplicationData(Context *ctx, void *applicationData) noexcept;
|
friend constexpr void setApplicationData(Context *ctx, void *applicationData) noexcept;
|
||||||
template<typename T>
|
template<typename T>
|
||||||
friend constexpr T *applicationData(Context *ctx) noexcept;
|
friend constexpr T *applicationData(Context *ctx) noexcept;
|
||||||
@ -69,7 +68,7 @@ class Context: public foundation::Context {
|
|||||||
const struct CompactTileSheet &tilesheetAddr) noexcept;
|
const struct CompactTileSheet &tilesheetAddr) noexcept;
|
||||||
friend ox::Error run(Context *ctx) noexcept;
|
friend ox::Error run(Context *ctx) noexcept;
|
||||||
friend void shutdown(Context *ctx) noexcept;
|
friend void shutdown(Context *ctx) noexcept;
|
||||||
friend ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> fs, ox::CRStringView appName) noexcept;
|
friend ox::Result<ox::UniquePtr<Context>> init(ox::UniquePtr<ox::FileSystem> fs, ox::CRStringView appName) noexcept;
|
||||||
friend ox::String getClipboardText(Context *ctx) noexcept;
|
friend ox::String getClipboardText(Context *ctx) noexcept;
|
||||||
friend uint64_t ticksMs(Context *ctx) noexcept;
|
friend uint64_t ticksMs(Context *ctx) noexcept;
|
||||||
friend uint8_t bgStatus(Context *ctx) noexcept;
|
friend uint8_t bgStatus(Context *ctx) noexcept;
|
||||||
@ -94,13 +93,17 @@ class Context: public foundation::Context {
|
|||||||
friend void hideSprite(Context *ctx, unsigned idx) noexcept;
|
friend void hideSprite(Context *ctx, unsigned idx) noexcept;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ox::UniquePtr<ox::FileSystem> rom;
|
||||||
ox::Vector<Drawer*, 5> drawers;
|
ox::Vector<Drawer*, 5> drawers;
|
||||||
|
ox::StringView appName = "Nostalgia";
|
||||||
|
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
|
AssetManager assetManager;
|
||||||
int uninterruptedRefreshes = 3;
|
int uninterruptedRefreshes = 3;
|
||||||
ox::UPtr<BaseClipboardObject> clipboard;
|
ox::UniquePtr<BaseClipboardObject> clipboard;
|
||||||
#else
|
#else
|
||||||
bool running = true;
|
bool running = true;
|
||||||
|
std::size_t preloadSectionOffset = 0;
|
||||||
#endif
|
#endif
|
||||||
protected:
|
protected:
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
|
|
||||||
|
#include "assetmanager.hpp"
|
||||||
#include "clipboard.hpp"
|
#include "clipboard.hpp"
|
||||||
#include "consts.hpp"
|
#include "consts.hpp"
|
||||||
#include "event.hpp"
|
#include "event.hpp"
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
#include "input.hpp"
|
#include "input.hpp"
|
||||||
#include "module.hpp"
|
#include "media.hpp"
|
||||||
#include "typeconv.hpp"
|
#include "typeconv.hpp"
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
#include <ox/mc/mc.hpp>
|
#include <ox/mc/mc.hpp>
|
||||||
#include <ox/std/array.hpp>
|
#include <ox/std/array.hpp>
|
||||||
|
|
||||||
#include <nostalgia/foundation/media.hpp>
|
#include <nostalgia/core/media.hpp>
|
||||||
#include <nostalgia/core/context.hpp>
|
|
||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
|
|
||||||
#include "addresses.hpp"
|
#include "addresses.hpp"
|
||||||
@ -130,7 +129,7 @@ ox::Error initConsole(Context *ctx) noexcept {
|
|||||||
setBgStatus(ctx, 0b0001);
|
setBgStatus(ctx, 0b0001);
|
||||||
if (!ctx) {
|
if (!ctx) {
|
||||||
ctx = new (ox_alloca(sizeof(Context))) Context();
|
ctx = new (ox_alloca(sizeof(Context))) Context();
|
||||||
oxRequire(rom, foundation::loadRom());
|
oxRequire(rom, loadRom());
|
||||||
ox::FileStore32 fs(rom, 32 * ox::units::MB);
|
ox::FileStore32 fs(rom, 32 * ox::units::MB);
|
||||||
auto romFs = new (ox_alloca(sizeof(ox::FileSystem32))) ox::FileSystem32(fs);
|
auto romFs = new (ox_alloca(sizeof(ox::FileSystem32))) ox::FileSystem32(fs);
|
||||||
new (&ctx->rom) ox::UniquePtr<ox::FileSystem>(romFs);
|
new (&ctx->rom) ox::UniquePtr<ox::FileSystem>(romFs);
|
||||||
|
50
src/nostalgia/core/gba/media.cpp
Normal file
50
src/nostalgia/core/gba/media.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ox/mc/read.hpp>
|
||||||
|
#include <ox/std/std.hpp>
|
||||||
|
|
||||||
|
#include "../media.hpp"
|
||||||
|
|
||||||
|
#include "addresses.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
ox::Result<char*> loadRom(ox::CRStringView) 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 = 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 current + headerLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OxError(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unloadRom(char*) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<std::size_t> getPreloadAddr(Context *ctx, ox::CRStringView path) noexcept {
|
||||||
|
oxRequire(stat, ctx->rom->stat(path));
|
||||||
|
oxRequire(buff, static_cast<ox::MemFS*>(ctx->rom.get())->directAccess(path));
|
||||||
|
PreloadPtr p;
|
||||||
|
oxReturnError(ox::readMC(buff, stat.size, &p));
|
||||||
|
return p.preloadAddr + ctx->preloadSectionOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<std::size_t> getPreloadAddr(Context *ctx, const ox::FileAddress &file) noexcept {
|
||||||
|
oxRequire(stat, ctx->rom->stat(file));
|
||||||
|
oxRequire(buff, static_cast<ox::MemFS*>(ctx->rom.get())->directAccess(file));
|
||||||
|
PreloadPtr p;
|
||||||
|
oxReturnError(ox::readMC(buff, stat.size, &p));
|
||||||
|
return p.preloadAddr + ctx->preloadSectionOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -101,7 +101,14 @@ struct TileSheet {
|
|||||||
name(pName), columns(pColumns), rows(pRows), pixels(std::move(pPixels)) {
|
name(pName), columns(pColumns), rows(pRows), pixels(std::move(pPixels)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr SubSheet &operator=(const SubSheet &other) noexcept = default;
|
constexpr SubSheet &operator=(const SubSheet &other) noexcept {
|
||||||
|
name = other.name;
|
||||||
|
columns = other.columns;
|
||||||
|
rows = other.rows;
|
||||||
|
subsheets = other.subsheets;
|
||||||
|
pixels = other.pixels;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr SubSheet &operator=(SubSheet &&other) noexcept {
|
constexpr SubSheet &operator=(SubSheet &&other) noexcept {
|
||||||
name = std::move(other.name);
|
name = std::move(other.name);
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#include <nostalgia/foundation/foundation.hpp>
|
|
||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
#include <nostalgia/core/input.hpp>
|
#include <nostalgia/core/input.hpp>
|
||||||
#include <nostalgia/core/userland/gfx.hpp>
|
#include <nostalgia/core/userland/gfx.hpp>
|
||||||
@ -14,8 +13,10 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> fs, ox::CRStringView appName) noexcept {
|
ox::Result<ox::UniquePtr<Context>> init(ox::UniquePtr<ox::FileSystem> fs, ox::CRStringView appName) noexcept {
|
||||||
auto ctx = foundation::init<Context>(std::move(fs), appName);
|
auto ctx = ox::make_unique<Context>();
|
||||||
|
ctx->rom = std::move(fs);
|
||||||
|
ctx->appName = appName;
|
||||||
const auto id = ox::make<GlfwImplData>();
|
const auto id = ox::make<GlfwImplData>();
|
||||||
ctx->setWindowerData(id);
|
ctx->setWindowerData(id);
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
18
src/nostalgia/core/headless/media.cpp
Normal file
18
src/nostalgia/core/headless/media.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ox/std/std.hpp>
|
||||||
|
|
||||||
|
#include "../media.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
ox::Result<char*> loadRom(ox::CRStringView) noexcept {
|
||||||
|
return OxError(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void unloadRom(char*) noexcept {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
src/nostalgia/core/media.cpp
Normal file
24
src/nostalgia/core/media.cpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "media.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::CRStringView path) noexcept {
|
||||||
|
const auto lastDot = ox_lastIndexOf(path, '.');
|
||||||
|
const auto fsExt = lastDot != -1 ? path.substr(static_cast<std::size_t>(lastDot)) : "";
|
||||||
|
if (ox_strcmp(fsExt, ".oxfs") == 0) {
|
||||||
|
oxRequire(rom, core::loadRom(path));
|
||||||
|
return {ox::make_unique<ox::FileSystem32>(rom, 32 * ox::units::MB, unloadRom)};
|
||||||
|
} else {
|
||||||
|
#ifdef OX_HAS_PASSTHROUGHFS
|
||||||
|
return {ox::make_unique<ox::PassThroughFS>(path)};
|
||||||
|
#else
|
||||||
|
return OxError(2);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -10,11 +10,10 @@
|
|||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
#include <ox/model/metadata.hpp>
|
#include <ox/model/metadata.hpp>
|
||||||
|
|
||||||
#include <nostalgia/foundation/context.hpp>
|
#include "context.hpp"
|
||||||
|
|
||||||
#include "typeconv.hpp"
|
#include "typeconv.hpp"
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
struct PreloadPtr {
|
struct PreloadPtr {
|
||||||
static constexpr auto TypeName = "net.drinkingtea.ox.PreloadPtr";
|
static constexpr auto TypeName = "net.drinkingtea.ox.PreloadPtr";
|
||||||
@ -26,20 +25,20 @@ oxModelBegin(PreloadPtr)
|
|||||||
oxModelField(preloadAddr)
|
oxModelField(preloadAddr)
|
||||||
oxModelEnd()
|
oxModelEnd()
|
||||||
|
|
||||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, const ox::FileAddress &file) noexcept;
|
ox::Result<std::size_t> getPreloadAddr(Context *ctx, const ox::FileAddress &file) noexcept;
|
||||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, ox::CRStringView file) noexcept;
|
ox::Result<std::size_t> getPreloadAddr(Context *ctx, ox::CRStringView file) noexcept;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<foundation::AssetRef<T>> readObj([[maybe_unused]] foundation::Context *ctx, [[maybe_unused]] ox::CRStringView path,
|
ox::Result<AssetRef<T>> readObj([[maybe_unused]] Context *ctx, [[maybe_unused]] ox::CRStringView path,
|
||||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
const auto readConvert = [ctx](const ox::Buffer &buff) -> ox::Result<T> {
|
constexpr auto readConvert = [](const ox::Buffer &buff) -> ox::Result<T> {
|
||||||
auto [obj, err] = ox::readClaw<T>(buff);
|
auto [obj, err] = ox::readClaw<T>(buff);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
oxReturnError(convert<T>(ctx, buff, &obj));
|
oxReturnError(convert<T>(buff, &obj));
|
||||||
}
|
}
|
||||||
return std::move(obj);
|
return std::move(obj);
|
||||||
};
|
};
|
||||||
@ -60,7 +59,7 @@ ox::Result<foundation::AssetRef<T>> readObj([[maybe_unused]] foundation::Context
|
|||||||
#else
|
#else
|
||||||
if constexpr(ox::preloadable<T>::value) {
|
if constexpr(ox::preloadable<T>::value) {
|
||||||
oxRequire(addr, getPreloadAddr(ctx, path));
|
oxRequire(addr, getPreloadAddr(ctx, path));
|
||||||
return foundation::AssetRef<T>(reinterpret_cast<const T*>(addr));
|
return AssetRef<T>(reinterpret_cast<const T*>(addr));
|
||||||
} else {
|
} else {
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
@ -68,7 +67,7 @@ ox::Result<foundation::AssetRef<T>> readObj([[maybe_unused]] foundation::Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<foundation::AssetRef<T>> readObj(foundation::Context *ctx, const ox::FileAddress &file,
|
ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file,
|
||||||
[[maybe_unused]] bool forceLoad = false) noexcept {
|
[[maybe_unused]] bool forceLoad = false) noexcept {
|
||||||
#ifndef OX_BARE_METAL
|
#ifndef OX_BARE_METAL
|
||||||
oxRequire(path, file.getPath());
|
oxRequire(path, file.getPath());
|
||||||
@ -76,7 +75,7 @@ ox::Result<foundation::AssetRef<T>> readObj(foundation::Context *ctx, const ox::
|
|||||||
#else
|
#else
|
||||||
if constexpr(ox::preloadable<T>::value) {
|
if constexpr(ox::preloadable<T>::value) {
|
||||||
oxRequire(addr, getPreloadAddr(ctx, file));
|
oxRequire(addr, getPreloadAddr(ctx, file));
|
||||||
return foundation::AssetRef<T>(reinterpret_cast<const T*>(addr));
|
return AssetRef<T>(reinterpret_cast<const T*>(addr));
|
||||||
} else {
|
} else {
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
@ -84,7 +83,7 @@ ox::Result<foundation::AssetRef<T>> readObj(foundation::Context *ctx, const ox::
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Error writeObj(foundation::Context *ctx, const ox::FileAddress &file, const T &obj,
|
ox::Error writeObj(Context *ctx, const ox::FileAddress &file, const T &obj,
|
||||||
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
|
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
|
||||||
oxRequire(objBuff, ox::writeClaw(&obj, fmt));
|
oxRequire(objBuff, ox::writeClaw(&obj, fmt));
|
||||||
return ctx->rom->write(file, objBuff.data(), objBuff.size());
|
return ctx->rom->write(file, objBuff.data(), objBuff.size());
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ox/model/model.hpp>
|
|
||||||
|
|
||||||
#include <nostalgia/foundation/module.hpp>
|
|
||||||
|
|
||||||
#include "gfx.hpp"
|
|
||||||
#include "typeconv.hpp"
|
|
||||||
|
|
||||||
#include "module.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::core {
|
|
||||||
|
|
||||||
CoreModule CoreModule::mod;
|
|
||||||
|
|
||||||
ox::Vector<foundation::BaseConverter*> CoreModule::converters() const noexcept {
|
|
||||||
return {
|
|
||||||
&nostalgiaPaletteToPaletteConverter,
|
|
||||||
&nostalgiaGraphicToTileSheetConverter,
|
|
||||||
&tileSheetToCompactTileSheetConverter,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Vector<foundation::PackTransform> CoreModule::packTransforms() const noexcept {
|
|
||||||
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);
|
|
||||||
if (typeId == ox::buildTypeId<TileSheet>() ||
|
|
||||||
typeId == ox::buildTypeId<NostalgiaGraphic>()) {
|
|
||||||
oxReturnError(foundation::convertBuffToBuff<core::CompactTileSheet>(ctx, *buff, ox::ClawFormat::Metal).moveTo(buff));
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <nostalgia/foundation/module.hpp>
|
|
||||||
|
|
||||||
#include "typeconv.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::core {
|
|
||||||
|
|
||||||
class CoreModule: public foundation::Module {
|
|
||||||
private:
|
|
||||||
mutable NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter;
|
|
||||||
mutable NostalgiaGraphicToTileSheetConverter nostalgiaGraphicToTileSheetConverter;
|
|
||||||
mutable TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static CoreModule mod;
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::Vector<foundation::BaseConverter*> converters() const noexcept override;
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
ox::Vector<studio::EditorMaker> StudioModule::editors(core::Context *ctx) noexcept {
|
ox::Vector<studio::EditorMaker> Module::editors(core::Context *ctx) noexcept {
|
||||||
return {
|
return {
|
||||||
{
|
{
|
||||||
{"ng"},
|
{"ng"},
|
||||||
@ -32,7 +32,7 @@ ox::Vector<studio::EditorMaker> StudioModule::editors(core::Context *ctx) noexce
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> StudioModule::itemMakers(core::Context*) noexcept {
|
ox::Vector<ox::UniquePtr<studio::ItemMaker>> Module::itemMakers(core::Context*) noexcept {
|
||||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> out;
|
ox::Vector<ox::UniquePtr<studio::ItemMaker>> out;
|
||||||
out.emplace_back(ox::make<studio::ItemMakerT<core::TileSheet>>("Tile Sheet", "TileSheets", "ng"));
|
out.emplace_back(ox::make<studio::ItemMakerT<core::TileSheet>>("Tile Sheet", "TileSheets", "ng"));
|
||||||
out.emplace_back(ox::make<studio::ItemMakerT<core::Palette>>("Palette", "Palettes", "npal"));
|
out.emplace_back(ox::make<studio::ItemMakerT<core::Palette>>("Palette", "Palettes", "npal"));
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
class StudioModule: public studio::Module {
|
class Module: public studio::Module {
|
||||||
public:
|
public:
|
||||||
ox::Vector<studio::EditorMaker> editors(core::Context *ctx) noexcept override;
|
ox::Vector<studio::EditorMaker> editors(core::Context *ctx) noexcept override;
|
||||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> itemMakers(core::Context*) noexcept override;
|
ox::Vector<ox::UniquePtr<studio::ItemMaker>> itemMakers(core::Context*) noexcept override;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
#include <nostalgia/core/media.hpp>
|
||||||
#include <ox/std/memory.hpp>
|
#include <ox/std/memory.hpp>
|
||||||
|
|
||||||
#include "paletteeditor.hpp"
|
#include "paletteeditor.hpp"
|
||||||
@ -19,7 +19,7 @@ ox::Result<PaletteEditorImGui*> PaletteEditorImGui::make(Context *ctx, ox::CRStr
|
|||||||
out->m_itemPath = path;
|
out->m_itemPath = path;
|
||||||
const auto lastSlash = std::find(out->m_itemPath.rbegin(), out->m_itemPath.rend(), '/').offset();
|
const auto lastSlash = std::find(out->m_itemPath.rbegin(), out->m_itemPath.rend(), '/').offset();
|
||||||
out->m_itemName = out->m_itemPath.substr(lastSlash + 1);
|
out->m_itemName = out->m_itemPath.substr(lastSlash + 1);
|
||||||
oxRequire(pal, foundation::readObj<Palette>(out->m_ctx, ox::FileAddress(out->m_itemPath.c_str())));
|
oxRequire(pal, core::readObj<Palette>(out->m_ctx, ox::FileAddress(out->m_itemPath.c_str())));
|
||||||
out->m_pal = *pal;
|
out->m_pal = *pal;
|
||||||
return out.release();
|
return out.release();
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <lodepng.h>
|
#include <lodepng.h>
|
||||||
|
|
||||||
#include <nostalgia/foundation/media.hpp>
|
#include <nostalgia/core/media.hpp>
|
||||||
#include <nostalgia/geo/point.hpp>
|
#include <nostalgia/geo/point.hpp>
|
||||||
|
|
||||||
#include "tilesheeteditor-imgui.hpp"
|
#include "tilesheeteditor-imgui.hpp"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -9,7 +9,7 @@
|
|||||||
#include <ox/std/memory.hpp>
|
#include <ox/std/memory.hpp>
|
||||||
|
|
||||||
#include <nostalgia/core/clipboard.hpp>
|
#include <nostalgia/core/clipboard.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
#include <nostalgia/core/media.hpp>
|
||||||
|
|
||||||
#include "tilesheeteditormodel.hpp"
|
#include "tilesheeteditormodel.hpp"
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -23,7 +23,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
|||||||
static const Palette s_defaultPalette;
|
static const Palette s_defaultPalette;
|
||||||
TileSheet m_img;
|
TileSheet m_img;
|
||||||
TileSheet::SubSheetIdx m_activeSubsSheetIdx;
|
TileSheet::SubSheetIdx m_activeSubsSheetIdx;
|
||||||
foundation::AssetRef<Palette> m_pal;
|
AssetRef<Palette> m_pal;
|
||||||
studio::UndoStack m_undoStack;
|
studio::UndoStack m_undoStack;
|
||||||
class DrawCommand *m_ongoingDrawCommand = nullptr;
|
class DrawCommand *m_ongoingDrawCommand = nullptr;
|
||||||
bool m_updated = false;
|
bool m_updated = false;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nostalgia/core/consts.hpp>
|
#include <nostalgia/core/consts.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
#include <nostalgia/core/media.hpp>
|
||||||
#include <nostalgia/geo/point.hpp>
|
#include <nostalgia/geo/point.hpp>
|
||||||
|
|
||||||
#include "tilesheeteditorview.hpp"
|
#include "tilesheeteditorview.hpp"
|
||||||
|
92
src/nostalgia/core/typeconv.cpp
Normal file
92
src/nostalgia/core/typeconv.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ox/claw/read.hpp>
|
||||||
|
|
||||||
|
#include "gfx.hpp"
|
||||||
|
|
||||||
|
#include "typeconv.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
struct NostalgiaGraphicToTileSheetConverter: public Converter<NostalgiaGraphic, TileSheet> {
|
||||||
|
ox::Error convert(NostalgiaGraphic *src, TileSheet *dst) noexcept final {
|
||||||
|
dst->bpp = src->bpp;
|
||||||
|
dst->subsheet.name = "Root";
|
||||||
|
dst->subsheet.rows = src->rows;
|
||||||
|
dst->subsheet.columns = src->columns;
|
||||||
|
dst->defaultPalette = std::move(src->defaultPalette);
|
||||||
|
dst->subsheet.pixels = std::move(src->pixels);
|
||||||
|
return OxError(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NostalgiaPaletteToPaletteConverter: public Converter<NostalgiaPalette, Palette> {
|
||||||
|
ox::Error convert(NostalgiaPalette *src, Palette *dst) noexcept final {
|
||||||
|
dst->colors = std::move(src->colors);
|
||||||
|
return OxError(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TileSheetToCompactTileSheetConverter: public Converter<TileSheet, CompactTileSheet> {
|
||||||
|
ox::Error convert(TileSheet *src, CompactTileSheet *dst) noexcept final {
|
||||||
|
dst->bpp = src->bpp;
|
||||||
|
dst->defaultPalette = std::move(src->defaultPalette);
|
||||||
|
dst->pixels = src->pixels();
|
||||||
|
return OxError(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef OX_BARE_METAL
|
||||||
|
|
||||||
|
static const auto converters = [] {
|
||||||
|
ox::Vector<ox::UniquePtr<BaseConverter>, 3> converters;
|
||||||
|
converters.emplace_back(ox::make<NostalgiaGraphicToTileSheetConverter>());
|
||||||
|
converters.emplace_back(ox::make<NostalgiaPaletteToPaletteConverter>());
|
||||||
|
converters.emplace_back(ox::make<TileSheetToCompactTileSheetConverter>());
|
||||||
|
return converters;
|
||||||
|
}();
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static auto findConverter(ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||||
|
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept -> ox::Result<BaseConverter*> {
|
||||||
|
for (auto &c : converters) {
|
||||||
|
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
|
||||||
|
return c.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OxError(1, "Could not find converter");
|
||||||
|
};
|
||||||
|
|
||||||
|
static ox::Result<ox::UniquePtr<Wrap>> convert(const ox::Buffer &srcBuffer,
|
||||||
|
ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||||
|
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept {
|
||||||
|
// look for direct converter
|
||||||
|
auto [c, err] = findConverter(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion);
|
||||||
|
if (!err) {
|
||||||
|
return c->convertBuffToPtr(srcBuffer);
|
||||||
|
}
|
||||||
|
// try to chain multiple converters
|
||||||
|
for (const auto &subConverter : converters) {
|
||||||
|
if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto [intermediate, chainErr] =
|
||||||
|
convert(srcBuffer, srcTypeName, srcTypeVersion,
|
||||||
|
subConverter->srcTypeName(), subConverter->srcTypeVersion());
|
||||||
|
if (!chainErr) {
|
||||||
|
return subConverter->convertPtrToPtr(intermediate.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OxError(1, "Could not convert between types");
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<ox::UniquePtr<Wrap>> convert(const ox::Buffer &srcBuffer, ox::CRStringView dstTypeName, int dstTypeVersion) noexcept {
|
||||||
|
oxRequire(hdr, ox::readClawHeader(srcBuffer));
|
||||||
|
return convert(srcBuffer, hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
@ -1,46 +1,152 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/std/def.hpp>
|
#include <ox/std/def.hpp>
|
||||||
|
#include <ox/std/error.hpp>
|
||||||
#include <nostalgia/foundation/typeconv.hpp>
|
#include <ox/std/optional.hpp>
|
||||||
|
#include <ox/std/string.hpp>
|
||||||
#include "context.hpp"
|
#include <ox/claw/read.hpp>
|
||||||
#include "gfx.hpp"
|
#include <ox/claw/write.hpp>
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
// Type converters
|
class Wrap {
|
||||||
|
public:
|
||||||
struct NostalgiaPaletteToPaletteConverter: public foundation::Converter<NostalgiaPalette, Palette> {
|
virtual ~Wrap() = default;
|
||||||
ox::Error convert(foundation::Context*, NostalgiaPalette *src, Palette *dst) noexcept final {
|
|
||||||
dst->colors = std::move(src->colors);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NostalgiaGraphicToTileSheetConverter: public foundation::Converter<NostalgiaGraphic, TileSheet> {
|
template<typename T>
|
||||||
ox::Error convert(foundation::Context*, NostalgiaGraphic *src, TileSheet *dst) noexcept final {
|
class WrapInline: public Wrap {
|
||||||
dst->bpp = src->bpp;
|
private:
|
||||||
dst->subsheet.name = "Root";
|
T m_obj;
|
||||||
dst->subsheet.rows = src->rows;
|
|
||||||
dst->subsheet.columns = src->columns;
|
public:
|
||||||
dst->defaultPalette = std::move(src->defaultPalette);
|
constexpr WrapInline() = default;
|
||||||
dst->subsheet.pixels = std::move(src->pixels);
|
|
||||||
return {};
|
template<typename... Args>
|
||||||
|
constexpr explicit WrapInline(Args &&...args): m_obj(ox::forward<Args>(args)...) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr auto obj() noexcept {
|
||||||
|
return &m_obj;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TileSheetToCompactTileSheetConverter: public foundation::Converter<TileSheet, CompactTileSheet> {
|
template<typename T, typename... Args>
|
||||||
ox::Error convert(foundation::Context*, TileSheet *src, CompactTileSheet *dst) noexcept final {
|
constexpr auto makeWrap(Args &&...args) noexcept {
|
||||||
dst->bpp = src->bpp;
|
return ox::make_unique<WrapInline<T>>(ox::forward<Args>(args)...);
|
||||||
dst->defaultPalette = std::move(src->defaultPalette);
|
|
||||||
dst->pixels = src->pixels();
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr auto wrapCast(auto ptr) noexcept {
|
||||||
|
return static_cast<WrapInline<T>*>(ptr)->obj();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BaseConverter {
|
||||||
|
virtual ~BaseConverter() noexcept = default;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
virtual ox::StringView srcTypeName() noexcept = 0;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
virtual int srcTypeVersion() noexcept = 0;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
virtual bool srcMatches(ox::CRStringView srcTypeName, int srcTypeVersion) const noexcept = 0;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
|
||||||
|
|
||||||
|
virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(Wrap *src) noexcept = 0;
|
||||||
|
|
||||||
|
virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(const ox::Buffer &srcBuff) noexcept = 0;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
inline bool matches(ox::CRStringView srcTypeName, int srcTypeVersion,
|
||||||
|
ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept {
|
||||||
|
return srcMatches(srcTypeName, srcTypeVersion)
|
||||||
|
&& dstMatches(dstTypeName, dstTypeVersion);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename SrcType, typename DstType>
|
||||||
|
struct Converter: public BaseConverter {
|
||||||
|
|
||||||
|
virtual ox::Error convert(SrcType*, DstType*) noexcept = 0;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
ox::StringView srcTypeName() noexcept final {
|
||||||
|
return ox::requireModelTypeName<SrcType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
int srcTypeVersion() noexcept final {
|
||||||
|
return ox::requireModelTypeVersion<SrcType>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool srcMatches(ox::CRStringView srcTypeName, int srcTypeVersion) const noexcept final {
|
||||||
|
static constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>();
|
||||||
|
static constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>();
|
||||||
|
return ox_strcmp(srcTypeName, SrcTypeName) == 0
|
||||||
|
&& srcTypeVersion == SrcTypeVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept final {
|
||||||
|
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||||
|
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||||
|
return ox_strcmp(dstTypeName, DstTypeName) == 0
|
||||||
|
&& dstTypeVersion == DstTypeVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(Wrap *src) noexcept final {
|
||||||
|
auto dst = makeWrap<DstType>();
|
||||||
|
oxReturnError(convert(wrapCast<SrcType>(src), wrapCast<DstType>(dst.get())));
|
||||||
|
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(const ox::Buffer &srcBuff) noexcept final {
|
||||||
|
oxRequireM(src, ox::readClaw<SrcType>(srcBuff));
|
||||||
|
auto dst = makeWrap<DstType>();
|
||||||
|
oxReturnError(convert(&src, wrapCast<DstType>(dst.get())));
|
||||||
|
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
ox::Result<ox::UniquePtr<Wrap>> convert(const ox::Buffer &srcBuffer,
|
||||||
|
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept;
|
||||||
|
|
||||||
|
template<typename DstType>
|
||||||
|
ox::Result<DstType> convert(const ox::Buffer &srcBuffer) noexcept {
|
||||||
|
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||||
|
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||||
|
oxRequire(out, convert(srcBuffer, DstTypeName, DstTypeVersion));
|
||||||
|
return wrapCast<DstType>(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstType>
|
||||||
|
ox::Error convert(const ox::Buffer &buff, DstType *outObj) noexcept {
|
||||||
|
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||||
|
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||||
|
oxRequire(outPtr, convert(buff, DstTypeName, DstTypeVersion));
|
||||||
|
*outObj = std::move(*wrapCast<DstType>(outPtr.get()));
|
||||||
|
return OxError(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DstType>
|
||||||
|
ox::Result<ox::Buffer> convertBuffToBuff(const ox::Buffer &srcBuffer, ox::ClawFormat fmt) noexcept {
|
||||||
|
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
||||||
|
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
||||||
|
oxRequire(out, convert(srcBuffer, DstTypeName, DstTypeVersion));
|
||||||
|
return ox::writeClaw<DstType>(wrapCast<DstType>(out.get()), fmt);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "typestore.hpp"
|
#include "typestore.hpp"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
#include <nostalgia/core/media.hpp>
|
||||||
|
|
||||||
#include "gfx.hpp"
|
#include "gfx.hpp"
|
||||||
|
|
||||||
|
39
src/nostalgia/core/userland/media.cpp
Normal file
39
src/nostalgia/core/userland/media.cpp
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <ox/std/trace.hpp>
|
||||||
|
|
||||||
|
#include "../media.hpp"
|
||||||
|
|
||||||
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
ox::Result<char*> loadRom(ox::CRStringView path) noexcept {
|
||||||
|
std::ifstream file(std::string(toStdStringView(path)), std::ios::binary | std::ios::ate);
|
||||||
|
if (!file.good()) {
|
||||||
|
oxErrorf("Could not find ROM file: {}", path);
|
||||||
|
return OxError(1, "Could not find ROM file");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const auto size = file.tellg();
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
auto buff = new char[static_cast<std::size_t>(size)];
|
||||||
|
file.read(buff, size);
|
||||||
|
return buff;
|
||||||
|
} catch (const std::ios_base::failure &e) {
|
||||||
|
oxErrorf("Could not read ROM file: {}", e.what());
|
||||||
|
return OxError(2, "Could not read ROM file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void unloadRom(char *rom) noexcept {
|
||||||
|
ox::safeDelete(rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Result<void*> findPreloadSection() noexcept {
|
||||||
|
return OxError(1, "findPreloadSection is unsupported on this platform");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,26 +0,0 @@
|
|||||||
|
|
||||||
add_library(
|
|
||||||
NostalgiaFoundation
|
|
||||||
foundation.hpp
|
|
||||||
media.cpp
|
|
||||||
module.cpp
|
|
||||||
typeconv.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(
|
|
||||||
NostalgiaFoundation PUBLIC
|
|
||||||
OxClaw
|
|
||||||
OxEvent
|
|
||||||
OxFS
|
|
||||||
OxModel
|
|
||||||
OxStd
|
|
||||||
)
|
|
||||||
install(
|
|
||||||
FILES
|
|
||||||
media.hpp
|
|
||||||
module.hpp
|
|
||||||
typeconv.hpp
|
|
||||||
DESTINATION
|
|
||||||
include/nostalgia/core
|
|
||||||
)
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
|
||||||
#include <ox/std/memory.hpp>
|
|
||||||
#include <ox/std/stringview.hpp>
|
|
||||||
|
|
||||||
#include "assetmanager.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
class Context;
|
|
||||||
using PackTransform = ox::Error(*)(Context*, ox::Buffer *clawData);
|
|
||||||
|
|
||||||
class Context {
|
|
||||||
public:
|
|
||||||
ox::UPtr<ox::FileSystem> rom;
|
|
||||||
ox::StringView appName = "Nostalgia Foundation App";
|
|
||||||
#ifndef OX_BARE_METAL
|
|
||||||
AssetManager assetManager;
|
|
||||||
ox::Vector<class BaseConverter*> converters;
|
|
||||||
ox::Vector<PackTransform> packTransforms;
|
|
||||||
#else
|
|
||||||
std::size_t preloadSectionOffset = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
constexpr Context() noexcept = default;
|
|
||||||
Context(const Context&) noexcept = delete;
|
|
||||||
Context(Context&&) noexcept = delete;
|
|
||||||
Context &operator=(const Context&) noexcept = delete;
|
|
||||||
Context &operator=(Context&&) noexcept = delete;
|
|
||||||
constexpr virtual ~Context() noexcept = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ox/std/memory.hpp>
|
|
||||||
|
|
||||||
#include "context.hpp"
|
|
||||||
#include "module.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
template<typename Ctx = foundation::Context>
|
|
||||||
ox::UPtr<Ctx> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept {
|
|
||||||
auto ctx = ox::make_unique<Ctx>();
|
|
||||||
ctx->rom = std::move(fs);
|
|
||||||
ctx->appName = appName;
|
|
||||||
auto mods = modules();
|
|
||||||
if (mods) {
|
|
||||||
for (auto &mod : *mods) {
|
|
||||||
// register type converters
|
|
||||||
for (auto c : mod->converters()) {
|
|
||||||
ctx->converters.emplace_back(c);
|
|
||||||
}
|
|
||||||
// register pack transforms
|
|
||||||
for (auto c : mod->packTransforms()) {
|
|
||||||
ctx->packTransforms.emplace_back(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "media.hpp"
|
|
||||||
|
|
||||||
#ifndef OX_BARE_METAL
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include <ox/std/trace.hpp>
|
|
||||||
|
|
||||||
#include <nostalgia/foundation/media.hpp>
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
ox::Result<char*> loadRom(ox::CRStringView path) noexcept {
|
|
||||||
std::ifstream file(std::string(toStdStringView(path)), std::ios::binary | std::ios::ate);
|
|
||||||
if (!file.good()) {
|
|
||||||
oxErrorf("Could not find ROM file: {}", path);
|
|
||||||
return OxError(1, "Could not find ROM file");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const auto size = file.tellg();
|
|
||||||
file.seekg(0, std::ios::beg);
|
|
||||||
auto buff = new char[static_cast<std::size_t>(size)];
|
|
||||||
file.read(buff, size);
|
|
||||||
return buff;
|
|
||||||
} catch (const std::ios_base::failure &e) {
|
|
||||||
oxErrorf("Could not read ROM file: {}", e.what());
|
|
||||||
return OxError(2, "Could not read ROM file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void unloadRom(char *rom) noexcept {
|
|
||||||
ox::safeDelete(rom);
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<void*> findPreloadSection() noexcept {
|
|
||||||
return OxError(1, "findPreloadSection is unsupported on this platform");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "context.hpp"
|
|
||||||
|
|
||||||
#define MEM_ROM reinterpret_cast<char*>(0x0800'0000)
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
ox::Result<char*> loadRom(ox::CRStringView) 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 = 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 current + headerLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OxError(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unloadRom(char*) noexcept {
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, ox::CRStringView path) noexcept {
|
|
||||||
oxRequire(stat, ctx->rom->stat(path));
|
|
||||||
oxRequire(buff, static_cast<ox::MemFS*>(ctx->rom.get())->directAccess(path));
|
|
||||||
PreloadPtr p;
|
|
||||||
oxReturnError(ox::readMC(buff, stat.size, &p));
|
|
||||||
return p.preloadAddr + ctx->preloadSectionOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<std::size_t> getPreloadAddr(foundation::Context *ctx, const ox::FileAddress &file) noexcept {
|
|
||||||
oxRequire(stat, ctx->rom->stat(file));
|
|
||||||
oxRequire(buff, static_cast<ox::MemFS*>(ctx->rom.get())->directAccess(file));
|
|
||||||
PreloadPtr p;
|
|
||||||
oxReturnError(ox::readMC(buff, stat.size, &p));
|
|
||||||
return p.preloadAddr + ctx->preloadSectionOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::CRStringView path) noexcept {
|
|
||||||
const auto lastDot = ox_lastIndexOf(path, '.');
|
|
||||||
const auto fsExt = lastDot != -1 ? path.substr(static_cast<std::size_t>(lastDot)) : "";
|
|
||||||
if (ox_strcmp(fsExt, ".oxfs") == 0) {
|
|
||||||
oxRequire(rom, loadRom(path));
|
|
||||||
return {ox::make_unique<ox::FileSystem32>(rom, 32 * ox::units::MB, unloadRom)};
|
|
||||||
} else {
|
|
||||||
#ifdef OX_HAS_PASSTHROUGHFS
|
|
||||||
return {ox::make_unique<ox::PassThroughFS>(path)};
|
|
||||||
#else
|
|
||||||
return OxError(2);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "module.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
static ox::Vector<const Module*> mods;
|
|
||||||
|
|
||||||
void registerModule(const Module *mod) noexcept {
|
|
||||||
mods.emplace_back(mod);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
const ox::Vector<const Module*> *modules() noexcept {
|
|
||||||
return &mods;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ox::Vector<foundation::BaseConverter*> Module::converters() const noexcept {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Vector<PackTransform> Module::packTransforms() const noexcept {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ox/std/vector.hpp>
|
|
||||||
|
|
||||||
#include "typeconv.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
class Module {
|
|
||||||
public:
|
|
||||||
constexpr Module() noexcept = default;
|
|
||||||
Module(const Module&) noexcept = delete;
|
|
||||||
Module(Module&&) noexcept = delete;
|
|
||||||
Module &operator=(const Module&) noexcept = delete;
|
|
||||||
Module &operator=(Module&&) noexcept = delete;
|
|
||||||
constexpr virtual ~Module() noexcept = default;
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual ox::Vector<foundation::BaseConverter*> converters() const noexcept;
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual ox::Vector<PackTransform> packTransforms() const noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
void registerModule(const Module *mod) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
const ox::Vector<const foundation::Module*> *modules() noexcept;
|
|
||||||
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ox/claw/read.hpp>
|
|
||||||
|
|
||||||
#include "typeconv.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
#ifndef OX_BARE_METAL
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
static auto findConverter(foundation::Context *ctx,
|
|
||||||
ox::CRStringView srcTypeName, int srcTypeVersion,
|
|
||||||
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept -> ox::Result<BaseConverter*> {
|
|
||||||
for (auto &c : ctx->converters) {
|
|
||||||
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OxError(1, "Could not find converter");
|
|
||||||
};
|
|
||||||
|
|
||||||
static ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer,
|
|
||||||
ox::CRStringView srcTypeName, int srcTypeVersion,
|
|
||||||
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept {
|
|
||||||
// look for direct converter
|
|
||||||
auto [c, err] = findConverter(ctx, srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion);
|
|
||||||
if (!err) {
|
|
||||||
return c->convertBuffToPtr(nullptr, srcBuffer);
|
|
||||||
}
|
|
||||||
// try to chain multiple converters
|
|
||||||
for (const auto &subConverter : ctx->converters) {
|
|
||||||
if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto [intermediate, chainErr] =
|
|
||||||
convert(ctx, srcBuffer, srcTypeName, srcTypeVersion,
|
|
||||||
subConverter->srcTypeName(), subConverter->srcTypeVersion());
|
|
||||||
if (!chainErr) {
|
|
||||||
return subConverter->convertPtrToPtr(ctx, intermediate.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return OxError(1, "Could not convert between types");
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
@ -1,165 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ox/std/def.hpp>
|
|
||||||
#include <ox/std/error.hpp>
|
|
||||||
#include <ox/std/string.hpp>
|
|
||||||
#include <ox/claw/read.hpp>
|
|
||||||
#include <ox/claw/write.hpp>
|
|
||||||
|
|
||||||
#include "context.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::foundation {
|
|
||||||
|
|
||||||
class Wrap {
|
|
||||||
public:
|
|
||||||
virtual ~Wrap() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class WrapInline: public Wrap {
|
|
||||||
private:
|
|
||||||
T m_obj;
|
|
||||||
|
|
||||||
public:
|
|
||||||
constexpr WrapInline() = default;
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
constexpr explicit WrapInline(Args &&...args): m_obj(ox::forward<Args>(args)...) {
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
constexpr auto obj() noexcept {
|
|
||||||
return &m_obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
|
||||||
constexpr auto makeWrap(Args &&...args) noexcept {
|
|
||||||
return ox::make_unique<WrapInline<T>>(ox::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr auto wrapCast(auto ptr) noexcept {
|
|
||||||
return static_cast<WrapInline<T>*>(ptr)->obj();
|
|
||||||
}
|
|
||||||
|
|
||||||
class BaseConverter {
|
|
||||||
public:
|
|
||||||
virtual ~BaseConverter() noexcept = default;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual ox::StringView srcTypeName() noexcept = 0;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual int srcTypeVersion() noexcept = 0;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual bool srcMatches(ox::CRStringView srcTypeName, int srcTypeVersion) const noexcept = 0;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
|
|
||||||
|
|
||||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(foundation::Context *ctx, Wrap *src) noexcept = 0;
|
|
||||||
|
|
||||||
virtual ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) noexcept = 0;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
inline bool matches(ox::CRStringView srcTypeName, int srcTypeVersion,
|
|
||||||
ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept {
|
|
||||||
return srcMatches(srcTypeName, srcTypeVersion)
|
|
||||||
&& dstMatches(dstTypeName, dstTypeVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename SrcType, typename DstType>
|
|
||||||
class Converter: public BaseConverter {
|
|
||||||
public:
|
|
||||||
virtual ox::Error convert(foundation::Context *ctx, SrcType*, DstType*) noexcept = 0;
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::StringView srcTypeName() noexcept final {
|
|
||||||
return ox::requireModelTypeName<SrcType>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
int srcTypeVersion() noexcept final {
|
|
||||||
return ox::requireModelTypeVersion<SrcType>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
bool srcMatches(ox::CRStringView srcTypeName, int srcTypeVersion) const noexcept final {
|
|
||||||
static constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>();
|
|
||||||
static constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>();
|
|
||||||
return ox_strcmp(srcTypeName, SrcTypeName) == 0
|
|
||||||
&& srcTypeVersion == SrcTypeVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept final {
|
|
||||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
|
||||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
|
||||||
return ox_strcmp(dstTypeName, DstTypeName) == 0
|
|
||||||
&& dstTypeVersion == DstTypeVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<ox::UniquePtr<Wrap>> convertPtrToPtr(foundation::Context *ctx, Wrap *src) noexcept final {
|
|
||||||
auto dst = makeWrap<DstType>();
|
|
||||||
oxReturnError(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(dst.get())));
|
|
||||||
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Result<ox::UniquePtr<Wrap>> convertBuffToPtr(foundation::Context *ctx, const ox::Buffer &srcBuff) noexcept final {
|
|
||||||
oxRequireM(src, ox::readClaw<SrcType>(srcBuff));
|
|
||||||
auto dst = makeWrap<DstType>();
|
|
||||||
oxReturnError(convert(ctx, &src, wrapCast<DstType>(dst.get())));
|
|
||||||
return ox::Result<ox::UniquePtr<Wrap>>(std::move(dst));
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
ox::Result<ox::UniquePtr<Wrap>> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer,
|
|
||||||
ox::CRStringView dstTypeName, int dstTypeVersion) noexcept;
|
|
||||||
|
|
||||||
template<typename DstType>
|
|
||||||
ox::Result<DstType> convert(foundation::Context *ctx, const ox::Buffer &srcBuffer) noexcept {
|
|
||||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
|
||||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
|
||||||
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
|
||||||
return wrapCast<DstType>(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstType>
|
|
||||||
ox::Error convert(foundation::Context *ctx, const ox::Buffer &buff, DstType *outObj) noexcept {
|
|
||||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
|
||||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
|
||||||
oxRequire(outPtr, convert(ctx, buff, DstTypeName, DstTypeVersion));
|
|
||||||
*outObj = std::move(*wrapCast<DstType>(outPtr.get()));
|
|
||||||
return OxError(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DstType>
|
|
||||||
ox::Result<ox::Buffer> convertBuffToBuff(foundation::Context *ctx, const ox::Buffer &srcBuffer, ox::ClawFormat fmt) noexcept {
|
|
||||||
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
|
|
||||||
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
|
|
||||||
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
|
|
||||||
return ox::writeClaw<DstType>(wrapCast<DstType>(out.get()), fmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
if (typeId == ox::buildTypeId<From>()) {
|
|
||||||
oxReturnError(foundation::convertBuffToBuff<To>(ctx, *buff, fmt).moveTo(buff));
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -22,8 +22,8 @@ endif()
|
|||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
nostalgia
|
nostalgia
|
||||||
NostalgiaAppModules
|
NostalgiaWorld
|
||||||
OxLogConn
|
NostalgiaCore
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
|
@ -1,32 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nostalgia/core/core.hpp>
|
#include <nostalgia/core/core.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
|
||||||
|
|
||||||
using namespace nostalgia;
|
using namespace nostalgia;
|
||||||
|
|
||||||
static int spriteX = 72;
|
static int spriteX = 72;
|
||||||
static int spriteY = 64;
|
static int spriteY = 64;
|
||||||
static ox::StringView sprites = "nostalgia";
|
|
||||||
static bool paused = false;
|
|
||||||
|
|
||||||
static int updateHandler(core::Context *ctx) noexcept {
|
static int updateHandler(core::Context *ctx) noexcept {
|
||||||
constexpr auto sleepTime = 16;
|
|
||||||
if (paused) {
|
|
||||||
return sleepTime;
|
|
||||||
}
|
|
||||||
int xmod = 0;
|
int xmod = 0;
|
||||||
int ymod = 0;
|
int ymod = 0;
|
||||||
if (buttonDown(ctx, core::Alpha_D) || buttonDown(ctx, core::GamePad_Right)) {
|
if (core::buttonDown(ctx, core::Alpha_D) || core::buttonDown(ctx, core::GamePad_Right)) {
|
||||||
xmod = 2;
|
xmod = 2;
|
||||||
} else if (buttonDown(ctx, core::Alpha_A) || buttonDown(ctx, core::GamePad_Left)) {
|
} else if (core::buttonDown(ctx, core::Alpha_A) || core::buttonDown(ctx, core::GamePad_Left)) {
|
||||||
xmod = -2;
|
xmod = -2;
|
||||||
}
|
}
|
||||||
if (buttonDown(ctx, core::Alpha_S) || buttonDown(ctx, core::GamePad_Down)) {
|
if (core::buttonDown(ctx, core::Alpha_S) || core::buttonDown(ctx, core::GamePad_Down)) {
|
||||||
ymod = 2;
|
ymod = 2;
|
||||||
} else if (buttonDown(ctx, core::Alpha_W) || buttonDown(ctx, core::GamePad_Up)) {
|
} else if (core::buttonDown(ctx, core::Alpha_W) || core::buttonDown(ctx, core::GamePad_Up)) {
|
||||||
ymod = -2;
|
ymod = -2;
|
||||||
}
|
}
|
||||||
if (!xmod && !ymod) {
|
if (!xmod && !ymod) {
|
||||||
@ -34,21 +27,17 @@ static int updateHandler(core::Context *ctx) noexcept {
|
|||||||
}
|
}
|
||||||
spriteX += xmod;
|
spriteX += xmod;
|
||||||
spriteY += ymod;
|
spriteY += ymod;
|
||||||
//constexpr ox::StringView sprites = "nostalgia";
|
constexpr ox::StringView s = "nostalgia";
|
||||||
for (unsigned i = 0; i < sprites.len(); ++i) {
|
for (unsigned i = 0; s[i]; ++i) {
|
||||||
const auto c = static_cast<unsigned>(sprites[i] - ('a' - 1));
|
const auto c = static_cast<unsigned>(s[i] - ('a' - 1));
|
||||||
core::setSprite(ctx, i, spriteX + 8 * (static_cast<int>(i) + 1), spriteY, c, 0, 0, 0);
|
core::setSprite(ctx, i, spriteX + 8 * (static_cast<int>(i) + 1), spriteY, c);
|
||||||
}
|
}
|
||||||
return sleepTime;
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyEventHandler(core::Context *ctx, core::Key key, bool down) noexcept {
|
static void keyEventHandler(core::Context *ctx, core::Key key, bool down) noexcept {
|
||||||
if (down) {
|
if (down && key == core::Key::Alpha_Q) {
|
||||||
if (key == core::Key::Alpha_Q) {
|
|
||||||
core::shutdown(ctx);
|
core::shutdown(ctx);
|
||||||
} else if (key == core::Key::Alpha_P) {
|
|
||||||
paused = !paused;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/logconn/logconn.hpp>
|
|
||||||
|
|
||||||
#include <nostalgia/core/core.hpp>
|
#include <nostalgia/core/core.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
|
||||||
|
|
||||||
#include <nostalgia/appmodules/appmodules.hpp>
|
|
||||||
|
|
||||||
#include "app.hpp"
|
#include "app.hpp"
|
||||||
|
|
||||||
static ox::Error run(int argc, const char **argv) noexcept {
|
static ox::Error run(int argc, const char **argv) noexcept {
|
||||||
ox::trace::init();
|
ox::trace::init();
|
||||||
nostalgia::loadModules();
|
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
oxErr("Please provide path to project directory or OxFS file.\n");
|
oxErr("Please provide path to project directory or OxFS file.\n");
|
||||||
return OxError(1);
|
return OxError(1);
|
||||||
}
|
}
|
||||||
const auto path = argv[1];
|
const auto path = argv[1];
|
||||||
oxRequireM(fs, nostalgia::foundation::loadRomFs(path));
|
oxRequireM(fs, nostalgia::core::loadRomFs(path));
|
||||||
return run(std::move(fs));
|
return run(std::move(fs));
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv) {
|
int main(int argc, const char **argv) {
|
||||||
#ifdef DEBUG
|
|
||||||
ox::LoggerConn loggerConn;
|
|
||||||
const auto loggerErr = loggerConn.initConn("Nostalgia Player");
|
|
||||||
if (loggerErr) {
|
|
||||||
oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.file, loggerErr.line);
|
|
||||||
} else {
|
|
||||||
ox::trace::setLogger(&loggerConn);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
const auto err = run(argc, argv);
|
const auto err = run(argc, argv);
|
||||||
oxAssert(err, "Something went wrong...");
|
oxAssert(err, "Something went wrong...");
|
||||||
return static_cast<int>(err);
|
return static_cast<int>(err);
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
add_library(
|
add_library(
|
||||||
NostalgiaScene
|
NostalgiaScene
|
||||||
scene.cpp
|
scene.cpp
|
||||||
scenemodule.cpp
|
|
||||||
typeconv.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
@ -14,8 +12,6 @@ target_link_libraries(
|
|||||||
install(
|
install(
|
||||||
FILES
|
FILES
|
||||||
scene.hpp
|
scene.hpp
|
||||||
scenemodule.hpp
|
|
||||||
typeconv.hpp
|
|
||||||
DESTINATION
|
DESTINATION
|
||||||
include/nostalgia/scene
|
include/nostalgia/scene
|
||||||
)
|
)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
|
#include <ox/preloader/preloader.hpp>
|
||||||
#include <ox/std/error.hpp>
|
#include <ox/std/error.hpp>
|
||||||
#include <ox/std/types.hpp>
|
#include <ox/std/types.hpp>
|
||||||
#include <ox/std/vector.hpp>
|
#include <ox/std/vector.hpp>
|
||||||
@ -13,17 +14,17 @@ namespace nostalgia::scene {
|
|||||||
|
|
||||||
struct TileDoc {
|
struct TileDoc {
|
||||||
|
|
||||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.TileDoc";
|
|
||||||
constexpr static auto TypeVersion = 1;
|
|
||||||
constexpr static auto Preloadable = true;
|
constexpr static auto Preloadable = true;
|
||||||
|
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.Tile";
|
||||||
|
constexpr static auto TypeVersion = 1;
|
||||||
|
|
||||||
ox::String sheetIdx;
|
uint16_t sheetIdx = 0;
|
||||||
uint8_t type = 0;
|
uint8_t type = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
oxModelBegin(TileDoc)
|
oxModelBegin(TileDoc)
|
||||||
oxModelFieldRename(sheet_idx, sheetIdx);
|
oxModelField(sheetIdx);
|
||||||
oxModelField(type);
|
oxModelField(type);
|
||||||
oxModelEnd()
|
oxModelEnd()
|
||||||
|
|
||||||
@ -33,9 +34,9 @@ struct SceneDoc {
|
|||||||
using TileMapLayer = ox::Vector<TileMapRow>;
|
using TileMapLayer = ox::Vector<TileMapRow>;
|
||||||
using TileMap = ox::Vector<TileMapLayer>;
|
using TileMap = ox::Vector<TileMapLayer>;
|
||||||
|
|
||||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.SceneDoc";
|
|
||||||
constexpr static auto TypeVersion = 1;
|
|
||||||
constexpr static auto Preloadable = true;
|
constexpr static auto Preloadable = true;
|
||||||
|
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.Scene";
|
||||||
|
constexpr static auto TypeVersion = 1;
|
||||||
|
|
||||||
ox::FileAddress tilesheet;
|
ox::FileAddress tilesheet;
|
||||||
ox::FileAddress palette;
|
ox::FileAddress palette;
|
||||||
@ -49,11 +50,7 @@ oxModelBegin(SceneDoc)
|
|||||||
oxModelField(tiles)
|
oxModelField(tiles)
|
||||||
oxModelEnd()
|
oxModelEnd()
|
||||||
|
|
||||||
struct Scene {
|
struct SceneInstance {
|
||||||
|
|
||||||
constexpr static auto TypeName = "net.drinkingtea.nostalgia.scene.Scene";
|
|
||||||
constexpr static auto TypeVersion = 1;
|
|
||||||
constexpr static auto Preloadable = true;
|
|
||||||
|
|
||||||
struct Tile {
|
struct Tile {
|
||||||
uint16_t &tileMapIdx;
|
uint16_t &tileMapIdx;
|
||||||
@ -66,8 +63,8 @@ struct Scene {
|
|||||||
struct Layer {
|
struct Layer {
|
||||||
uint16_t &columns;
|
uint16_t &columns;
|
||||||
uint16_t &rows;
|
uint16_t &rows;
|
||||||
uint16_t *tileMapIdx = nullptr;
|
uint16_t *tileMapIdx;
|
||||||
uint8_t *tileType = nullptr;
|
uint8_t *tileType;
|
||||||
constexpr Layer(uint16_t &pColumns,
|
constexpr Layer(uint16_t &pColumns,
|
||||||
uint16_t &pRows,
|
uint16_t &pRows,
|
||||||
uint16_t *pTileMapIdx,
|
uint16_t *pTileMapIdx,
|
||||||
@ -93,15 +90,6 @@ struct Scene {
|
|||||||
constexpr Layer layer(std::size_t i) noexcept {
|
constexpr Layer layer(std::size_t i) noexcept {
|
||||||
return {columns[i], rows[i], tileMapIdx[i].data(), tileType[i].data()};
|
return {columns[i], rows[i], tileMapIdx[i].data(), tileType[i].data()};
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
oxModelBegin(Scene)
|
|
||||||
oxModelField(layers)
|
|
||||||
oxModelField(columns)
|
|
||||||
oxModelField(rows)
|
|
||||||
oxModelFieldRename(tile_map_idx, tileMapIdx)
|
|
||||||
oxModelFieldRename(tile_type, tileType)
|
|
||||||
oxModelEnd()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ox/model/model.hpp>
|
|
||||||
|
|
||||||
#include "scenemodule.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::scene {
|
|
||||||
|
|
||||||
SceneModule SceneModule::mod;
|
|
||||||
|
|
||||||
ox::Vector<foundation::BaseConverter*> SceneModule::converters() const noexcept {
|
|
||||||
return {
|
|
||||||
&sceneToSceneInstaceConverter,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Vector<foundation::PackTransform> SceneModule::packTransforms() const noexcept {
|
|
||||||
return {
|
|
||||||
foundation::transformRule<SceneDoc, Scene>,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <nostalgia/foundation/module.hpp>
|
|
||||||
|
|
||||||
#include "typeconv.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::scene {
|
|
||||||
|
|
||||||
class SceneModule: public foundation::Module {
|
|
||||||
private:
|
|
||||||
mutable SceneDocToSceneConverter sceneToSceneInstaceConverter;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static SceneModule mod;
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::Vector<foundation::BaseConverter*> converters() const noexcept override;
|
|
||||||
[[nodiscard]]
|
|
||||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "typeconv.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::scene {
|
|
||||||
|
|
||||||
// Type converters
|
|
||||||
|
|
||||||
ox::Error SceneDocToSceneConverter::convert(foundation::Context*, SceneDoc *, Scene *) noexcept {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <nostalgia/foundation/typeconv.hpp>
|
|
||||||
|
|
||||||
#include "scene.hpp"
|
|
||||||
|
|
||||||
namespace nostalgia::scene {
|
|
||||||
|
|
||||||
struct SceneDocToSceneConverter: public foundation::Converter<SceneDoc, Scene> {
|
|
||||||
ox::Error convert(foundation::Context*, SceneDoc *src, Scene *dst) noexcept final;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -15,8 +15,6 @@ add_executable(
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
nostalgia-studio
|
nostalgia-studio
|
||||||
OxClArgs
|
OxClArgs
|
||||||
OxLogConn
|
|
||||||
NostalgiaAppModules
|
|
||||||
NostalgiaStudio
|
NostalgiaStudio
|
||||||
NostalgiaCore-Studio
|
NostalgiaCore-Studio
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@ -13,7 +13,7 @@ namespace nostalgia {
|
|||||||
[[maybe_unused]] // GCC warns about the existence of this "unused" constexpr list in a header file...
|
[[maybe_unused]] // GCC warns about the existence of this "unused" constexpr list in a header file...
|
||||||
constexpr auto BuiltinModules = {
|
constexpr auto BuiltinModules = {
|
||||||
[] {
|
[] {
|
||||||
return ox::make_unique<core::StudioModule>();
|
return ox::make_unique<core::Module>();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,28 +4,6 @@
|
|||||||
|
|
||||||
#include "configio.hpp"
|
#include "configio.hpp"
|
||||||
|
|
||||||
namespace nostalgia::studio {
|
|
||||||
|
|
||||||
constexpr auto ConfigDir = [] {
|
|
||||||
switch (ox::defines::OS) {
|
|
||||||
case ox::OS::Darwin:
|
|
||||||
return "{}/Library/Preferences/{}";
|
|
||||||
case ox::OS::DragonFlyBSD:
|
|
||||||
case ox::OS::FreeBSD:
|
|
||||||
case ox::OS::Linux:
|
|
||||||
case ox::OS::NetBSD:
|
|
||||||
case ox::OS::OpenBSD:
|
|
||||||
return "{}/.config/{}";
|
|
||||||
case ox::OS::Windows:
|
|
||||||
return R"({}/AppData/Local/{})";
|
|
||||||
case ox::OS::BareMetal:
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
|
|
||||||
ox::String configPath(const core::Context *ctx) noexcept {
|
|
||||||
const auto homeDir = std::getenv(ox::defines::OS == ox::OS::Windows ? "USERPROFILE" : "HOME");
|
|
||||||
return ox::sfmt(ConfigDir, homeDir, ctx->appName);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
#include <ox/model/typenamecatcher.hpp>
|
#include <ox/model/typenamecatcher.hpp>
|
||||||
#include <ox/oc/oc.hpp>
|
#include <ox/oc/oc.hpp>
|
||||||
@ -17,20 +20,44 @@
|
|||||||
|
|
||||||
namespace nostalgia::studio {
|
namespace nostalgia::studio {
|
||||||
|
|
||||||
[[nodiscard]]
|
constexpr auto ConfigDir = [] {
|
||||||
ox::String configPath(const core::Context *ctx) noexcept;
|
switch (ox::defines::OS) {
|
||||||
|
case ox::OS::Darwin:
|
||||||
|
return "{}/Library/Preferences/{}";
|
||||||
|
case ox::OS::DragonFlyBSD:
|
||||||
|
case ox::OS::FreeBSD:
|
||||||
|
case ox::OS::Linux:
|
||||||
|
case ox::OS::NetBSD:
|
||||||
|
case ox::OS::OpenBSD:
|
||||||
|
return "{}/.config/{}";
|
||||||
|
case ox::OS::Windows:
|
||||||
|
return R"({}/AppData/Local/{})";
|
||||||
|
case ox::OS::BareMetal:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Result<T> readConfig(core::Context *ctx, ox::CRStringView name) noexcept {
|
ox::Result<T> readConfig(core::Context *ctx, ox::CRStringView name) noexcept {
|
||||||
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
||||||
const auto path = ox::sfmt("/{}.json", name);
|
const auto homeDir = std::getenv(ox::defines::OS == ox::OS::Windows ? "USERPROFILE" : "HOME");
|
||||||
ox::PassThroughFS fs(configPath(ctx));
|
const auto configPath = ox::sfmt(ConfigDir, homeDir, ctx->appName).toStdString();
|
||||||
const auto [buff, err] = fs.read(path);
|
const auto path = ox::sfmt("{}/{}.json", configPath, name).toStdString();
|
||||||
if (err) {
|
std::ifstream file(path, std::ios::binary | std::ios::ate);
|
||||||
oxErrf("Could not read config file: {}\n", toStr(err));
|
if (!file.good()) {
|
||||||
return err;
|
oxErrf("Could not find config file: {}\n", path);
|
||||||
|
return OxError(1, "Could not find config file");
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
const auto size = file.tellg();
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
ox::Buffer buff(static_cast<std::size_t>(size));
|
||||||
|
file.read(buff.data(), size);
|
||||||
return ox::readOC<T>(buff);
|
return ox::readOC<T>(buff);
|
||||||
|
} catch (const std::ios_base::failure &e) {
|
||||||
|
oxErrf("Could not read config file: {}\n", e.what());
|
||||||
|
return OxError(2, "Could not read config file");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -40,17 +67,19 @@ ox::Result<T> readConfig(core::Context *ctx) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ox::Error writeConfig(core::Context *ctx, ox::CRStringView name, T *data) noexcept {
|
ox::Error writeConfig(core::Context *ctx, const auto &name, T *data) noexcept {
|
||||||
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
oxAssert(ox_strcmp(name, ""), "Config type has no TypeName");
|
||||||
const auto path = ox::sfmt("/{}.json", name);
|
const auto homeDir = std::getenv(ox::defines::OS == ox::OS::Windows ? "USERPROFILE" : "HOME");
|
||||||
ox::PassThroughFS fs(configPath(ctx));
|
const auto configPath = ox::sfmt(ConfigDir, homeDir, ctx->appName);
|
||||||
if (const auto err = fs.mkdir("/", true)) {
|
const auto path = ox::sfmt("{}.json", name);
|
||||||
|
ox::PassThroughFS fs(configPath);
|
||||||
|
if (auto err = fs.mkdir("/", true)) {
|
||||||
oxErrf("Could not create config directory: {}\n", toStr(err));
|
oxErrf("Could not create config directory: {}\n", toStr(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
oxRequireM(buff, ox::writeOC(data));
|
oxRequireM(buff, ox::writeOC(data));
|
||||||
buff.back().value = '\n';
|
buff.back().value = '\n';
|
||||||
if (const auto err = fs.write(path, buff.data(), buff.size())) {
|
if (auto err = fs.write(path, buff.data(), buff.size())) {
|
||||||
oxErrf("Could not read config file: {}\n", toStr(err));
|
oxErrf("Could not read config file: {}\n", toStr(err));
|
||||||
return OxError(2, "Could not read config file");
|
return OxError(2, "Could not read config file");
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ void BaseEditor::exportFile() {
|
|||||||
void BaseEditor::keyStateChanged(core::Key, bool) {
|
void BaseEditor::keyStateChanged(core::Key, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseEditor::close() const {
|
void BaseEditor::close() {
|
||||||
this->closed.emit(itemName());
|
this->closed.emit(itemName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
|
|||||||
|
|
||||||
virtual void keyStateChanged(core::Key key, bool down);
|
virtual void keyStateChanged(core::Key key, bool down);
|
||||||
|
|
||||||
void close() const;
|
void close();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save changes to item being edited.
|
* Save changes to item being edited.
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/logconn/logconn.hpp>
|
|
||||||
#include <ox/std/trace.hpp>
|
#include <ox/std/trace.hpp>
|
||||||
|
|
||||||
#include <nostalgia/appmodules/appmodules.hpp>
|
|
||||||
#include <nostalgia/core/core.hpp>
|
#include <nostalgia/core/core.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
|
||||||
|
|
||||||
#include "lib/context.hpp"
|
#include "lib/context.hpp"
|
||||||
#include "studioapp.hpp"
|
#include "studioapp.hpp"
|
||||||
@ -56,10 +53,9 @@ static ox::Error run(ox::UniquePtr<ox::FileSystem> fs) noexcept {
|
|||||||
|
|
||||||
static ox::Error run(int argc, const char **argv) noexcept {
|
static ox::Error run(int argc, const char **argv) noexcept {
|
||||||
ox::trace::init();
|
ox::trace::init();
|
||||||
loadModules();
|
|
||||||
if (argc >= 2) {
|
if (argc >= 2) {
|
||||||
const auto path = argv[1];
|
const auto path = argv[1];
|
||||||
oxRequireM(fs, foundation::loadRomFs(path));
|
oxRequireM(fs, core::loadRomFs(path));
|
||||||
return run(std::move(fs));
|
return run(std::move(fs));
|
||||||
} else {
|
} else {
|
||||||
return run(ox::UniquePtr<ox::FileSystem>(nullptr));
|
return run(ox::UniquePtr<ox::FileSystem>(nullptr));
|
||||||
@ -69,15 +65,6 @@ static ox::Error run(int argc, const char **argv) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv) {
|
int main(int argc, const char **argv) {
|
||||||
#ifdef DEBUG
|
|
||||||
ox::LoggerConn loggerConn;
|
|
||||||
const auto loggerErr = loggerConn.initConn("Nostalgia Studio");
|
|
||||||
if (loggerErr) {
|
|
||||||
oxErrf("Could not connect to logger: {}\n", toStr(loggerErr));
|
|
||||||
} else {
|
|
||||||
ox::trace::setLogger(&loggerConn);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
const auto err = nostalgia::run(argc, argv);
|
const auto err = nostalgia::run(argc, argv);
|
||||||
oxAssert(err, "Something went wrong...");
|
oxAssert(err, "Something went wrong...");
|
||||||
return static_cast<int>(err);
|
return static_cast<int>(err);
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include <nostalgia/core/core.hpp>
|
#include <nostalgia/core/core.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
|
||||||
|
|
||||||
#include "lib/configio.hpp"
|
#include "lib/configio.hpp"
|
||||||
#include "builtinmodules.hpp"
|
#include "builtinmodules.hpp"
|
||||||
@ -83,7 +82,7 @@ void StudioUI::handleKeyEvent(core::Key key, bool down) noexcept {
|
|||||||
m_newMenu.open();
|
m_newMenu.open();
|
||||||
break;
|
break;
|
||||||
case core::Key::Alpha_O:
|
case core::Key::Alpha_O:
|
||||||
m_taskRunner.add(ox::make<FileDialogManager>(this, &StudioUI::openProject));
|
m_taskRunner.add(new FileDialogManager(this, &StudioUI::openProject));
|
||||||
break;
|
break;
|
||||||
case core::Key::Alpha_Q:
|
case core::Key::Alpha_Q:
|
||||||
core::shutdown(m_ctx);
|
core::shutdown(m_ctx);
|
||||||
@ -135,7 +134,7 @@ void StudioUI::drawMenu() noexcept {
|
|||||||
m_newMenu.open();
|
m_newMenu.open();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Open Project...", "Ctrl+O")) {
|
if (ImGui::MenuItem("Open Project...", "Ctrl+O")) {
|
||||||
m_taskRunner.add(ox::make<FileDialogManager>(this, &StudioUI::openProject));
|
m_taskRunner.add(new FileDialogManager(this, &StudioUI::openProject));
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Save", "Ctrl+S", false, m_activeEditor && m_activeEditor->unsavedChanges())) {
|
if (ImGui::MenuItem("Save", "Ctrl+S", false, m_activeEditor && m_activeEditor->unsavedChanges())) {
|
||||||
m_activeEditor->save();
|
m_activeEditor->save();
|
||||||
@ -241,19 +240,19 @@ void StudioUI::loadEditorMaker(const studio::EditorMaker &editorMaker) noexcept
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StudioUI::loadModule(studio::Module *mod) noexcept {
|
void StudioUI::loadModule(studio::Module *module) noexcept {
|
||||||
for (const auto &editorMaker : mod->editors(m_ctx)) {
|
for (auto &editorMaker : module->editors(m_ctx)) {
|
||||||
loadEditorMaker(editorMaker);
|
loadEditorMaker(editorMaker);
|
||||||
}
|
}
|
||||||
for (auto &im : mod->itemMakers(m_ctx)) {
|
for (auto &im : module->itemMakers(m_ctx)) {
|
||||||
m_newMenu.addItemMaker(std::move(im));
|
m_newMenu.addItemMaker(std::move(im));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void StudioUI::loadModules() noexcept {
|
void StudioUI::loadModules() noexcept {
|
||||||
for (auto &moduleMaker : BuiltinModules) {
|
for (auto &moduleMaker : BuiltinModules) {
|
||||||
const auto mod = moduleMaker();
|
const auto module = moduleMaker();
|
||||||
loadModule(mod.get());
|
loadModule(module.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +284,7 @@ void StudioUI::save() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Error StudioUI::openProject(ox::CRStringView path) noexcept {
|
ox::Error StudioUI::openProject(ox::CRStringView path) noexcept {
|
||||||
oxRequireM(fs, foundation::loadRomFs(path));
|
oxRequireM(fs, core::loadRomFs(path));
|
||||||
m_ctx->rom = std::move(fs);
|
m_ctx->rom = std::move(fs);
|
||||||
core::setWindowTitle(m_ctx, ox::sfmt("Nostalgia Studio - {}", path));
|
core::setWindowTitle(m_ctx, ox::sfmt("Nostalgia Studio - {}", path));
|
||||||
m_project = ox::make_unique<studio::Project>(m_ctx->rom.get(), path);
|
m_project = ox::make_unique<studio::Project>(m_ctx->rom.get(), path);
|
||||||
@ -325,7 +324,7 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
|
|||||||
if (err) {
|
if (err) {
|
||||||
return OxError(1, "There is no editor for this file extension");
|
return OxError(1, "There is no editor for this file extension");
|
||||||
}
|
}
|
||||||
editor = ox::make<ClawEditor>(path, std::move(obj));
|
editor = new ClawEditor(path, std::move(obj));
|
||||||
} else {
|
} else {
|
||||||
const auto err = m_editorMakers[ext](path).moveTo(&editor);
|
const auto err = m_editorMakers[ext](path).moveTo(&editor);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -65,7 +65,7 @@ class StudioUI: public ox::SignalHandler {
|
|||||||
|
|
||||||
void loadEditorMaker(const studio::EditorMaker &editorMaker) noexcept;
|
void loadEditorMaker(const studio::EditorMaker &editorMaker) noexcept;
|
||||||
|
|
||||||
void loadModule(studio::Module *mod) noexcept;
|
void loadModule(studio::Module *module) noexcept;
|
||||||
|
|
||||||
void loadModules() noexcept;
|
void loadModules() noexcept;
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@ add_executable(nost-pack pack.cpp)
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
nost-pack
|
nost-pack
|
||||||
OxClArgs
|
OxClArgs
|
||||||
OxLogConn
|
|
||||||
NostalgiaPack
|
NostalgiaPack
|
||||||
NostalgiaAppModules
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
|
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#include <ox/clargs/clargs.hpp>
|
#include <ox/clargs/clargs.hpp>
|
||||||
#include <ox/fs/fs.hpp>
|
#include <ox/fs/fs.hpp>
|
||||||
#include <ox/logconn/logconn.hpp>
|
|
||||||
|
|
||||||
#include <nostalgia/appmodules/appmodules.hpp>
|
|
||||||
#include <nostalgia/core/typestore.hpp>
|
#include <nostalgia/core/typestore.hpp>
|
||||||
#include <nostalgia/foundation/foundation.hpp>
|
|
||||||
|
|
||||||
#include "pack/pack.hpp"
|
#include "pack/pack.hpp"
|
||||||
|
|
||||||
@ -45,7 +42,7 @@ static ox::Result<ox::Buffer> readFileBuff(ox::CRStringView path) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error run(const ox::ClArgs &args) noexcept {
|
static ox::Error run(const ox::ClArgs &args) noexcept {
|
||||||
loadModules();
|
ox::trace::init();
|
||||||
const auto argSrc = args.getString("src", "");
|
const auto argSrc = args.getString("src", "");
|
||||||
const auto argRomBin = args.getString("rom-bin", "");
|
const auto argRomBin = args.getString("rom-bin", "");
|
||||||
if (argSrc == "") {
|
if (argSrc == "") {
|
||||||
@ -58,10 +55,10 @@ static ox::Error run(const ox::ClArgs &args) noexcept {
|
|||||||
}
|
}
|
||||||
ox::Buffer dstBuff(32 * ox::units::MB);
|
ox::Buffer dstBuff(32 * ox::units::MB);
|
||||||
oxReturnError(ox::FileSystem32::format(dstBuff.data(), dstBuff.size()));
|
oxReturnError(ox::FileSystem32::format(dstBuff.data(), dstBuff.size()));
|
||||||
|
ox::PassThroughFS src(argSrc);
|
||||||
ox::FileSystem32 dst(ox::FileStore32(dstBuff.data(), dstBuff.size()));
|
ox::FileSystem32 dst(ox::FileStore32(dstBuff.data(), dstBuff.size()));
|
||||||
const auto ctx = foundation::init(ox::make_unique<ox::PassThroughFS>(argSrc), "nost-pack");
|
core::TypeStore ts(&src);
|
||||||
core::TypeStore ts(ctx->rom.get());
|
oxReturnError(pack(&ts, &src, &dst));
|
||||||
oxReturnError(pack(ctx.get(), &ts, &dst));
|
|
||||||
oxRequireM(pl, GbaPreloader::make());
|
oxRequireM(pl, GbaPreloader::make());
|
||||||
oxReturnError(preload(&ts, &dst, pl.get()));
|
oxReturnError(preload(&ts, &dst, pl.get()));
|
||||||
oxReturnError(dst.resize());
|
oxReturnError(dst.resize());
|
||||||
@ -81,16 +78,6 @@ static ox::Error run(const ox::ClArgs &args) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char **args) {
|
int main(int argc, const char **args) {
|
||||||
ox::trace::init();
|
|
||||||
#ifdef DEBUG
|
|
||||||
ox::LoggerConn loggerConn;
|
|
||||||
const auto loggerErr = loggerConn.initConn("nost-pack");
|
|
||||||
if (loggerErr) {
|
|
||||||
oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.file, loggerErr.line);
|
|
||||||
} else {
|
|
||||||
ox::trace::setLogger(&loggerConn);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
const auto err = run(ox::ClArgs(argc, args));
|
const auto err = run(ox::ClArgs(argc, args));
|
||||||
oxAssert(err, "pack failed");
|
oxAssert(err, "pack failed");
|
||||||
return static_cast<int>(err);
|
return static_cast<int>(err);
|
||||||
|
@ -7,7 +7,6 @@ add_library(
|
|||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
NostalgiaPack PUBLIC
|
NostalgiaPack PUBLIC
|
||||||
NostalgiaCore-Headless
|
NostalgiaCore-Headless
|
||||||
NostalgiaFoundation
|
|
||||||
OxPreloader
|
OxPreloader
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/claw/read.hpp>
|
#include <ox/claw/read.hpp>
|
||||||
@ -8,8 +8,9 @@
|
|||||||
#include <ox/model/modelvalue.hpp>
|
#include <ox/model/modelvalue.hpp>
|
||||||
|
|
||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
|
#include <nostalgia/core/media.hpp>
|
||||||
|
#include <nostalgia/core/typeconv.hpp>
|
||||||
#include <nostalgia/core/typestore.hpp>
|
#include <nostalgia/core/typestore.hpp>
|
||||||
#include <nostalgia/foundation/media.hpp>
|
|
||||||
|
|
||||||
#include "pack.hpp"
|
#include "pack.hpp"
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ static ox::Error pathToInode(ox::FileSystem *dest, ox::ModelObject *obj) noexcep
|
|||||||
case ox::FileAddressType::None:
|
case ox::FileAddressType::None:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
oxRequire(s, dest->stat(path));
|
oxRequire(s, dest->stat(ox::StringView(path)));
|
||||||
oxReturnError(o["type"].set(static_cast<int8_t>(ox::FileAddressType::Inode)));
|
oxReturnError(o["type"].set(static_cast<int8_t>(ox::FileAddressType::Inode)));
|
||||||
return data.set(2, s.inode);
|
return data.set(2, s.inode);
|
||||||
}
|
}
|
||||||
@ -41,7 +42,7 @@ static ox::Error pathToInode(ox::FileSystem *dest, ox::ModelObject *obj) noexcep
|
|||||||
* @param buff buffer holding file
|
* @param buff buffer holding file
|
||||||
* @return error
|
* @return error
|
||||||
*/
|
*/
|
||||||
static ox::Error transformFileAddresses(ox::FileSystem *dest, ox::ModelObject *obj) noexcept {
|
static ox::Error transformObj(ox::FileSystem *dest, ox::ModelObject *obj) noexcept {
|
||||||
for (auto &f : *obj) {
|
for (auto &f : *obj) {
|
||||||
auto &v = f->value;
|
auto &v = f->value;
|
||||||
if (v.type() != ox::ModelValue::Type::Object) {
|
if (v.type() != ox::ModelValue::Type::Object) {
|
||||||
@ -51,32 +52,33 @@ static ox::Error transformFileAddresses(ox::FileSystem *dest, ox::ModelObject *o
|
|||||||
if (o.typeName() == "net.drinkingtea.ox.FileAddress" && o.typeVersion() == 1) {
|
if (o.typeName() == "net.drinkingtea.ox.FileAddress" && o.typeVersion() == 1) {
|
||||||
oxReturnError(pathToInode(dest, &o));
|
oxReturnError(pathToInode(dest, &o));
|
||||||
} else {
|
} else {
|
||||||
oxReturnError(transformFileAddresses(dest, &o));
|
oxReturnError(transformObj(dest, &o));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error doTransformations(foundation::Context *ctx, core::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView filePath) noexcept {
|
static ox::Error doTransformations(core::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView filePath) noexcept {
|
||||||
|
if (endsWith(filePath, ".ng") || endsWith(filePath, ".npal")) {
|
||||||
// load file
|
// load file
|
||||||
oxRequire(s, dest->stat(filePath));
|
oxRequire(s, dest->stat(filePath));
|
||||||
// do transformations
|
|
||||||
oxRequireM(buff, dest->read(s.inode));
|
oxRequireM(buff, dest->read(s.inode));
|
||||||
for (auto tr : ctx->packTransforms) {
|
if (endsWith(filePath, ".ng")) {
|
||||||
oxReturnError(tr(ctx, &buff));
|
oxReturnError(core::convertBuffToBuff<core::CompactTileSheet>(buff, ox::ClawFormat::Metal).moveTo(&buff));
|
||||||
}
|
}
|
||||||
// transform FileAddresses
|
|
||||||
oxRequireM(obj, ox::readClaw(ts, buff));
|
oxRequireM(obj, ox::readClaw(ts, buff));
|
||||||
oxReturnError(transformFileAddresses(dest, &obj));
|
// do transformations
|
||||||
|
oxReturnError(transformObj(dest, &obj));
|
||||||
oxReturnError(ox::writeClaw(&obj).moveTo(&buff));
|
oxReturnError(ox::writeClaw(&obj).moveTo(&buff));
|
||||||
// write file to dest
|
// write file to dest
|
||||||
oxReturnError(dest->write(s.inode, buff.data(), buff.size()));
|
oxReturnError(dest->write(s.inode, buff.data(), buff.size()));
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// claw file transformations are broken out from copy because path to inode
|
// claw file transformations are broken out because path to inode
|
||||||
// transformations need to be done after the copy to the new FS is complete
|
// transformations need to be done after the copy to the new FS is complete
|
||||||
static ox::Error transformClaw(foundation::Context *ctx, core::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView path) noexcept {
|
static ox::Error transformClaw(core::TypeStore *ts, ox::FileSystem *dest, ox::CRStringView path) noexcept {
|
||||||
// copy
|
// copy
|
||||||
oxTracef("pack::transformClaw", "path: {}", path);
|
oxTracef("pack::transformClaw", "path: {}", path);
|
||||||
oxRequire(fileList, dest->ls(path));
|
oxRequire(fileList, dest->ls(path));
|
||||||
@ -85,9 +87,9 @@ static ox::Error transformClaw(foundation::Context *ctx, core::TypeStore *ts, ox
|
|||||||
oxRequire(stat, dest->stat(filePath));
|
oxRequire(stat, dest->stat(filePath));
|
||||||
if (stat.fileType == ox::FileType::Directory) {
|
if (stat.fileType == ox::FileType::Directory) {
|
||||||
const auto dir = ox::sfmt("{}{}/", path, name);
|
const auto dir = ox::sfmt("{}{}/", path, name);
|
||||||
oxReturnError(transformClaw(ctx, ts, dest, dir));
|
oxReturnError(transformClaw(ts, dest, dir));
|
||||||
} else {
|
} else {
|
||||||
oxReturnError(doTransformations(ctx, ts, dest, filePath));
|
oxReturnError(doTransformations(ts, dest, filePath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
@ -119,7 +121,7 @@ static ox::Error copy(ox::FileSystem *src, ox::FileSystem *dest, ox::CRStringVie
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
oxOutf("reading {}\n", currentFile);
|
oxOutf("reading {}\n", currentFile);
|
||||||
oxRequire(stat, src->stat(currentFile));
|
oxRequire(stat, src->stat(ox::StringView(currentFile)));
|
||||||
if (stat.fileType == ox::FileType::Directory) {
|
if (stat.fileType == ox::FileType::Directory) {
|
||||||
oxReturnError(dest->mkdir(currentFile, true));
|
oxReturnError(dest->mkdir(currentFile, true));
|
||||||
oxReturnError(copy(src, dest, currentFile + '/'));
|
oxReturnError(copy(src, dest, currentFile + '/'));
|
||||||
@ -151,7 +153,7 @@ static ox::Error preloadObj(core::TypeStore *ts, ox::FileSystem *romFs, GbaPrelo
|
|||||||
const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
|
const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
|
||||||
oxReturnError(pl->endAlloc());
|
oxReturnError(pl->endAlloc());
|
||||||
oxReturnError(err);
|
oxReturnError(err);
|
||||||
const foundation::PreloadPtr p{.preloadAddr = static_cast<uint32_t>(a)};
|
const core::PreloadPtr p{.preloadAddr = static_cast<uint32_t>(a)};
|
||||||
oxReturnError(ox::writeMC(&p).moveTo(&buff));
|
oxReturnError(ox::writeMC(&p).moveTo(&buff));
|
||||||
} else {
|
} else {
|
||||||
// strip the Claw header (it is not needed after preloading) and write back out to dest fs
|
// strip the Claw header (it is not needed after preloading) and write back out to dest fs
|
||||||
@ -169,7 +171,7 @@ static ox::Error preloadDir(core::TypeStore *ts, ox::FileSystem *romFs, GbaPrelo
|
|||||||
oxRequire(fileList, romFs->ls(path));
|
oxRequire(fileList, romFs->ls(path));
|
||||||
for (const auto &name : fileList) {
|
for (const auto &name : fileList) {
|
||||||
const auto filePath = ox::sfmt("{}{}", path, name);
|
const auto filePath = ox::sfmt("{}{}", path, name);
|
||||||
oxRequire(stat, romFs->stat(filePath));
|
oxRequire(stat, romFs->stat(ox::StringView(filePath)));
|
||||||
if (stat.fileType == ox::FileType::Directory) {
|
if (stat.fileType == ox::FileType::Directory) {
|
||||||
const auto dir = ox::sfmt("{}{}/", path, name);
|
const auto dir = ox::sfmt("{}{}/", path, name);
|
||||||
oxReturnError(preloadDir(ts, romFs, pl, dir));
|
oxReturnError(preloadDir(ts, romFs, pl, dir));
|
||||||
@ -202,10 +204,10 @@ ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, GbaPreloader *pl
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error pack(foundation::Context *ctx, core::TypeStore *ts, ox::FileSystem *dest) noexcept {
|
ox::Error pack(core::TypeStore *ts, ox::FileSystem *src, ox::FileSystem *dest) noexcept {
|
||||||
oxReturnError(copy(ctx->rom.get(), dest, "/"));
|
oxReturnError(copy(src, dest, "/"));
|
||||||
oxReturnError(ox::buildTypeDef<core::CompactTileSheet>(ts));
|
oxReturnError(ox::buildTypeDef<core::CompactTileSheet>(ts));
|
||||||
oxReturnError(transformClaw(ctx, ts, dest, "/"));
|
oxReturnError(transformClaw(ts, dest, "/"));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2016 - 2023 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
|
||||||
#include <ox/preloader/preloader.hpp>
|
#include <ox/preloader/preloader.hpp>
|
||||||
|
|
||||||
namespace nostalgia {
|
namespace nostalgia {
|
||||||
|
|
||||||
namespace foundation {
|
|
||||||
class Context;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
class TypeStore;
|
class TypeStore;
|
||||||
}
|
}
|
||||||
@ -95,7 +90,7 @@ using GbaPreloader = ox::Preloader<GbaPlatSpec>;
|
|||||||
|
|
||||||
ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, GbaPreloader *pl) noexcept;
|
ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, GbaPreloader *pl) noexcept;
|
||||||
|
|
||||||
auto pack(foundation::Context *ctx, core::TypeStore *ts, ox::FileSystem *dest) noexcept -> ox::Error;
|
auto pack(core::TypeStore *ts, ox::FileSystem *src, ox::FileSystem *dest) noexcept -> ox::Error;
|
||||||
|
|
||||||
auto preload(core::TypeStore *ts, ox::FileSystem *src, GbaPreloader *ph) noexcept -> ox::Error;
|
auto preload(core::TypeStore *ts, ox::FileSystem *src, GbaPreloader *ph) noexcept -> ox::Error;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user