Squashed 'deps/nostalgia/' changes from 89ae226b..9676ea59

9676ea59 [turbine/glfw] Fix programmatic shutdown to invoke shutdownHandler
de8ac106 [turbine/glfw] Fix closing when no shutdown handler is set
88a6cd59 [turbine/glfw] Treat close window event like other events with regard to a mandatory refresh period
cd43fb7f [turbine,studio] Fix confirm app close pop up to work with Ctrl-Q
136f4224 [nostalgia] Update release notes
e773d6f0 [studio] Rename StudioContext to Context
7da2f68d [nostalgia/sample_project] Add assets
d20889ae [nostalgia/gfx/studio] Update for Ox changes
50c8302f [ox] Rename itoa to intToStr
d8195d30 [olympic,nostalgia] Address unsafe buffer warnings
a8c1387d [ox] Address unsafe buffer warnings
ff1e8f26 [studio] Add popup to warn about UUID duplication
d4329981 [studio,nostalgia] Cleanup
00034543 [studio,nostalgia/gfx/studio] Cleanup
8c6b2234 [olympic/util] Make pkg-gba script check return code of subprocesses
aad4b8a4 [studio] Cleanup
7cab1331 [keel] Add ability to log UUID duplication
640ac85d [nostalgia/gfx/studio/palette] Make page rename dialog accept on enter if input focused
b8d76586 [nostalgia/studio] Update generated icondata.cpp with Clang fix
2503bb3b [nostalgia/sample_project] Update type descriptors
e5dd448f [turbine,studio] Make Studio confirm with user before closing app if any unsaved changes
4770bb6a [olympic/util] Cleanup
c0bac696 [nostalgia/gfx/studio/paletteeditor] Fix color number key range
95f7c334 [studio] Change Studio font
535d8876 [keel] Cleanup
845e4332 [turbine] Fix Mac build
5169a607 [turbine] Disable useless window icon on Mac, it causes GLFW warning
8f03af99 [keel] Style updates
ee63a4a1 [keel] Cleanup

git-subtree-dir: deps/nostalgia
git-subtree-split: 9676ea59787215b01498dfa82f88d426363b3cfd
This commit is contained in:
2025-05-07 00:11:20 -05:00
parent ec6cf92c47
commit ce53be9271
140 changed files with 22045 additions and 402 deletions

View File

@@ -15,7 +15,18 @@
namespace keel {
ox::Error init(
keel::Context &ctx,
Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName,
DuplicateSet &duplicateSet) noexcept;
ox::Result<ox::UPtr<Context>> init(
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName,
DuplicateSet &duplicateSet) noexcept;
ox::Error init(
Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName) noexcept;

View File

@@ -29,13 +29,14 @@ OX_MODEL_BEGIN(PreloadPtr)
OX_MODEL_FIELD(preloadAddr)
OX_MODEL_END()
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&addr) noexcept;
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::StringViewCR path) noexcept;
ox::Result<std::size_t> getPreloadAddr(Context &ctx, ox::FileAddress const&addr) noexcept;
ox::Result<std::size_t> getPreloadAddr(Context &ctx, ox::StringViewCR path) noexcept;
void createUuidMapping(Context &ctx, ox::StringViewCR filePath, ox::UUID const&uuid) noexcept;
ox::Error buildUuidMap(Context &ctx) noexcept;
// map of UUIDs to paths
using DuplicateSet = ox::HashMap<ox::UUID, ox::Vector<ox::String>>;
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::StringViewCR path) noexcept;
@@ -87,8 +88,8 @@ constexpr auto makeLoader(Context &ctx) {
}
template<typename T>
ox::Result<keel::AssetRef<T>> readObjFile(
keel::Context &ctx,
ox::Result<AssetRef<T>> readObjFile(
Context &ctx,
ox::StringViewCR assetId,
bool const forceLoad) noexcept {
static constexpr auto load = [](
@@ -135,11 +136,11 @@ ox::Result<keel::AssetRef<T>> readObjNoCache(
#endif
ox::Error reloadAsset(keel::Context &ctx, ox::StringViewCR assetId) noexcept;
ox::Error reloadAsset(Context &ctx, ox::StringViewCR assetId) noexcept;
template<typename T>
ox::Result<keel::AssetRef<T>> readObj(
keel::Context &ctx,
ox::Result<AssetRef<T>> readObj(
Context &ctx,
ox::StringViewCR assetId,
[[maybe_unused]] bool forceLoad = false) noexcept {
#ifndef OX_BARE_METAL
@@ -150,8 +151,8 @@ ox::Result<keel::AssetRef<T>> readObj(
}
template<typename T>
ox::Result<keel::AssetRef<T>> readObj(
keel::Context &ctx,
ox::Result<AssetRef<T>> readObj(
Context &ctx,
ox::FileAddress const&file,
[[maybe_unused]] bool forceLoad = false) noexcept {
#ifndef OX_BARE_METAL
@@ -169,7 +170,7 @@ ox::Result<keel::AssetRef<T>> readObj(
template<typename T>
ox::Error writeObj(
keel::Context &ctx,
Context &ctx,
ox::FileAddress const&file,
T const&obj,
ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
@@ -177,6 +178,8 @@ ox::Error writeObj(
return ctx.rom->write(file, objBuff.data(), objBuff.size());
}
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs, DuplicateSet &duplicateSet) noexcept;
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept;
ox::Result<ox::UPtr<ox::FileSystem>> loadRomFs(ox::StringViewCR path) noexcept;

View File

@@ -32,6 +32,7 @@ class WrapT: public Wrap {
[[nodiscard]]
virtual constexpr T &obj() noexcept = 0;
[[nodiscard]]
ox::UAnyPtr moveToCopy() noexcept final {
return new T{std::move(obj())};
}
@@ -46,14 +47,17 @@ class WrapRef final: public WrapT<T> {
public:
constexpr explicit WrapRef(T &obj): m_obj{obj} {}
[[nodiscard]]
ox::CStringView typeName() const noexcept override {
return ox::ModelTypeName_v<T>;
}
[[nodiscard]]
int typeVersion() const noexcept override {
return ox::ModelTypeVersion_v<T>;
}
[[nodiscard]]
constexpr T &obj() noexcept override {
return m_obj;
}
@@ -72,14 +76,17 @@ class WrapInline final: public WrapT<T> {
constexpr explicit WrapInline(Args &&...args): m_obj(ox::forward<Args>(args)...) {
}
[[nodiscard]]
ox::CStringView typeName() const noexcept override {
return ox::ModelTypeName_v<T>;
}
[[nodiscard]]
int typeVersion() const noexcept override {
return ox::ModelTypeVersion_v<T>;
}
[[nodiscard]]
constexpr T &obj() noexcept override {
return m_obj;
}
@@ -197,22 +204,17 @@ class ConverterFunc final: public BaseConverter {
class Converter {
private:
ox::AllocAlias<BaseConverter> m_buff{};
BaseConverter *m_conv{};
public:
template<auto Func>
static Converter make() noexcept {
Converter out;
static_assert(sizeof(ConverterFunc<Func>) <= sizeof(out.m_buff));
out.m_conv = new (out.m_buff.data()) ConverterFunc<Func>{};
new (out.m_buff.data()) ConverterFunc<Func>{};
return out;
}
constexpr Converter() {}
Converter(Converter const &other) noexcept:
m_buff{other.m_buff},
m_conv{m_buff.data()} {}
[[nodiscard]]
BaseConverter const *converter() const noexcept {
return m_conv;
BaseConverter const &converter() const noexcept {
return *m_buff.data();
}
};

View File

@@ -36,7 +36,7 @@ ox::Result<ox::ModelObject> readAsset(ox::TypeStore &ts, ox::BufferView buff) no
return ox::readClaw(ts, buff);
}
ox::Result<ox::StringView> readAssetTypeId(ox::BufferView buff) noexcept {
ox::Result<ox::StringView> readAssetTypeId(ox::BufferView const buff) noexcept {
const auto err = readUuidHeader(buff).error;
const auto offset = err ? 0u : K1HdrSz;
if (offset >= buff.size()) [[unlikely]] {

View File

@@ -6,21 +6,24 @@
namespace keel {
ox::Error init(
keel::Context &ctx,
static ox::Error init(
Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName) noexcept {
ox::StringViewCR appName,
DuplicateSet *duplicateSet) noexcept {
ctx.appName = appName;
std::ignore = setRomFs(ctx, std::move(fs));
std::ignore = duplicateSet ?
setRomFs(ctx, std::move(fs), *duplicateSet) :
setRomFs(ctx, std::move(fs));
#ifndef OX_BARE_METAL
auto const&mods = modules();
for (auto &mod : mods) {
// register type converters
for (auto c : mod->converters()) {
for (auto const c : mod->converters()) {
ctx.converters.emplace_back(c);
}
// register pack transforms
for (auto c : mod->packTransforms()) {
for (auto const c : mod->packTransforms()) {
ctx.packTransforms.emplace_back(c);
}
}
@@ -28,6 +31,30 @@ ox::Error init(
return {};
}
ox::Error init(
Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName,
DuplicateSet &duplicateSet) noexcept {
return init(ctx, std::move(fs), appName, &duplicateSet);
}
ox::Result<ox::UPtr<Context>> init(
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName,
DuplicateSet &duplicateSet) noexcept {
auto ctx = ox::make_unique<Context>();
OX_RETURN_ERROR(keel::init(*ctx, std::move(fs), appName, &duplicateSet));
return ctx;
}
ox::Error init(
Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::StringViewCR appName) noexcept {
return init(ctx, std::move(fs), appName, nullptr);
}
ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept {
auto ctx = ox::make_unique<Context>();
OX_RETURN_ERROR(keel::init(*ctx, std::move(fs), appName));

View File

@@ -47,7 +47,7 @@ void createUuidMapping(Context &ctx, ox::StringViewCR filePath, ox::UUID const&u
ctx.uuidToPath[uuid.toString()] = filePath;
}
static ox::Error buildUuidMap(Context &ctx, ox::StringViewCR path) noexcept {
static ox::Error buildUuidMap(Context &ctx, ox::StringViewCR path, DuplicateSet *duplicates) noexcept {
OX_REQUIRE(files, ctx.rom->ls(path));
for (auto const&f : files) {
OX_REQUIRE_M(filePath, ox::join("/", ox::Array<ox::StringView, 2>{path, f}));
@@ -58,22 +58,31 @@ static ox::Error buildUuidMap(Context &ctx, ox::StringViewCR path) noexcept {
ctx.rom->read(filePath, 0, buff.size(), buff));
auto const [uuid, err] = readUuidHeader(buff);
if (!err) {
createUuidMapping(ctx, filePath, uuid);
// check for duplication
if (duplicates && ctx.uuidToPath[uuid.toString()].len()) {
auto &dl = (*duplicates)[uuid];
if (dl.empty()) {
dl.emplace_back(ctx.uuidToPath[uuid.toString()]);
}
dl.emplace_back(filePath);
} else {
createUuidMapping(ctx, filePath, uuid);
}
}
} else if (stat.fileType == ox::FileType::Directory) {
if (!beginsWith(f, ".")) {
OX_RETURN_ERROR(buildUuidMap(ctx, filePath));
OX_RETURN_ERROR(buildUuidMap(ctx, filePath, duplicates));
}
}
}
return {};
}
ox::Error buildUuidMap(Context &ctx) noexcept {
static ox::Error buildUuidMap(Context &ctx, DuplicateSet *duplicates) noexcept {
if (!ctx.rom) {
return ox::Error(1, "No ROM FS");
return ox::Error{1, "No ROM FS"};
}
return buildUuidMap(ctx, "");
return buildUuidMap(ctx, "", duplicates);
}
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::StringViewCR path) noexcept {
@@ -199,7 +208,7 @@ namespace keel {
static void clearUuidMap(Context&) noexcept {
}
ox::Error buildUuidMap(Context&) noexcept {
static ox::Error buildUuidMap(Context&, DuplicateSet*) noexcept {
return {};
}
@@ -249,10 +258,16 @@ ox::Error reloadAsset(keel::Context&, ox::StringView) noexcept {
namespace keel {
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs, DuplicateSet &duplicateSet) noexcept {
ctx.rom = std::move(fs);
clearUuidMap(ctx);
return buildUuidMap(ctx, &duplicateSet);
}
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept {
ctx.rom = std::move(fs);
clearUuidMap(ctx);
return buildUuidMap(ctx);
return buildUuidMap(ctx, nullptr);
}
ox::Result<ox::UPtr<ox::FileSystem>> loadRomFs(ox::StringViewCR path) noexcept {

View File

@@ -6,13 +6,11 @@
#include <ox/clargs/clargs.hpp>
#include <ox/fs/fs.hpp>
#include <ox/logconn/def.hpp>
#include <ox/logconn/logconn.hpp>
#include <ox/oc/write.hpp>
#include <keel/keel.hpp>
static ox::Error writeFileBuff(ox::StringView path, ox::BufferView const buff) noexcept {
static ox::Error writeFileBuff(ox::StringViewCR path, ox::BufferView const &buff) noexcept {
try {
std::ofstream f(std::string(toStdStringView(path)), std::ios::binary);
f.write(buff.data(), static_cast<intptr_t>(buff.size()));
@@ -22,7 +20,7 @@ static ox::Error writeFileBuff(ox::StringView path, ox::BufferView const buff) n
return {};
}
static ox::Result<ox::Buffer> readFileBuff(ox::StringView path) noexcept {
static ox::Result<ox::Buffer> readFileBuff(ox::StringViewCR path) noexcept {
std::ifstream file(std::string(toStdStringView(path)), std::ios::binary | std::ios::ate);
if (!file.good()) {
oxErrorf("Could not find OxFS file: {}", path);
@@ -42,7 +40,7 @@ static ox::Result<ox::Buffer> readFileBuff(ox::StringView path) noexcept {
static ox::Error generateTypes(ox::TypeStore &ts) noexcept {
for (auto const mod : keel::modules()) {
for (auto gen : mod->types()) {
for (auto const gen : mod->types()) {
OX_RETURN_ERROR(gen(ts));
}
}
@@ -50,14 +48,27 @@ static ox::Error generateTypes(ox::TypeStore &ts) noexcept {
}
static ox::Error pack(
ox::StringView argSrc,
ox::StringView argRomBin,
ox::StringView argManifest,
ox::StringView projectDataDir) noexcept {
ox::StringViewCR argSrc,
ox::StringViewCR argRomBin,
ox::StringViewCR argManifest,
ox::StringViewCR projectDataDir) noexcept {
ox::Buffer dstBuff(32 * ox::units::MB);
OX_RETURN_ERROR(ox::FileSystem32::format(dstBuff.data(), dstBuff.size()));
ox::FileSystem32 dst(dstBuff);
OX_REQUIRE(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack"));
keel::DuplicateSet duplicateSet;
OX_REQUIRE(ctx, keel::init(
ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack", duplicateSet));
if (duplicateSet.size()) {
oxErr("Multiple files have the same UUID:\n");
for (auto const &k : duplicateSet.keys()) {
oxErrf("\n\t{}:\n", k.toString());
for (auto const &v : duplicateSet[k]) {
oxErrf("\t\t{}\n", v);
}
}
oxErr("\n");
std::exit(1);
}
keel::TypeStore ts(*ctx->rom, ox::sfmt("{}/type_descriptors", projectDataDir));
OX_RETURN_ERROR(generateTypes(ts));
keel::Manifest manifest;
@@ -82,10 +93,10 @@ static ox::Error pack(
}
ox::Error run(
[[maybe_unused]] ox::StringView project,
[[maybe_unused]] ox::StringView appName,
ox::StringView projectDataDir,
ox::SpanView<ox::CString> argv) noexcept {
[[maybe_unused]] ox::StringView const project,
[[maybe_unused]] ox::StringView const appName,
ox::StringView const projectDataDir,
ox::SpanView<ox::CString> const argv) noexcept {
ox::ClArgs const args(argv);
auto const argSrc = args.getString("src", "");
auto const argRomBin = args.getString("rom-bin", "");

View File

@@ -11,13 +11,12 @@
namespace keel {
static ox::Error pathToInode(
keel::Context &ctx,
ox::FileSystem &dest,
Context &ctx,
ox::FileSystem const &dest,
ox::ModelObject &obj) noexcept {
auto &o = obj;
OX_REQUIRE(typeVal, o.at("type"));
OX_REQUIRE(typeVal, obj.at("type"));
auto const type = static_cast<ox::FileAddressType>(typeVal->get<int8_t>());
OX_REQUIRE(dataVal, o.at("data"));
OX_REQUIRE(dataVal, obj.at("data"));
auto &data = dataVal->get<ox::ModelUnion>();
ox::String path;
switch (type) {
@@ -47,13 +46,17 @@ static ox::Error pathToInode(
}
static ox::Error transformFileAddressesObj(
keel::Context &ctx, ox::FileSystem &dest, ox::ModelObject &obj) noexcept;
Context &ctx,
ox::FileSystem const &dest,
ox::ModelObject &obj) noexcept;
static ox::Error transformFileAddressesVec(
keel::Context &ctx, ox::FileSystem &dest, ox::ModelValueVector &v) noexcept;
Context &ctx,
ox::FileSystem const &dest,
ox::ModelValueVector &v) noexcept;
static ox::Error transformFileAddresses(
keel::Context &ctx,
ox::FileSystem &dest,
Context &ctx,
ox::FileSystem const &dest,
ox::ModelValue &v) noexcept {
if (v.type() == ox::ModelValue::Type::Object) {
auto &obj = v.get<ox::ModelObject>();
@@ -66,8 +69,8 @@ static ox::Error transformFileAddresses(
}
static ox::Error transformFileAddressesVec(
keel::Context &ctx,
ox::FileSystem &dest,
Context &ctx,
ox::FileSystem const &dest,
ox::ModelValueVector &v) noexcept {
for (auto &f : v) {
OX_RETURN_ERROR(transformFileAddresses(ctx, dest, f));
@@ -80,13 +83,13 @@ static ox::Error transformFileAddressesVec(
* @return error
*/
static ox::Error transformFileAddressesObj(
keel::Context &ctx,
ox::FileSystem &dest,
Context &ctx,
ox::FileSystem const &dest,
ox::ModelObject &obj) noexcept {
if (obj.typeName() == "net.drinkingtea.ox.FileAddress" && obj.typeVersion() == 1) {
return pathToInode(ctx, dest, obj);
}
for (auto &f : obj) {
for (auto const &f : obj) {
auto &v = f->value;
OX_RETURN_ERROR(transformFileAddresses(ctx, dest, v));
}
@@ -111,7 +114,7 @@ static ox::Error performPackTransforms(
static ox::Error doTransformations(
Manifest &manifest,
keel::Context &ctx,
Context &ctx,
ox::TypeStore &ts,
ox::FileSystem &dest,
ox::StringViewCR filePath) noexcept {
@@ -134,7 +137,7 @@ static ox::Error doTransformations(
// transformations need to be done after the copy to the new FS is complete
static ox::Error transformClaw(
Manifest &manifest,
keel::Context &ctx,
Context &ctx,
ox::TypeStore &ts,
ox::FileSystem &dest,
ox::StringViewCR path) noexcept {
@@ -200,7 +203,7 @@ static ox::Error copy(
ox::Error pack(
Manifest &manifest,
keel::Context &ctx,
Context &ctx,
ox::TypeStore &ts,
ox::FileSystem &dest) noexcept {
OX_RETURN_ERROR(copy(manifest, *ctx.rom, dest, "/"));

View File

@@ -15,8 +15,8 @@ static ox::Result<BaseConverter const*> findConverter(
ox::StringViewCR dstTypeName,
int const dstTypeVersion) noexcept {
for (auto const&c : converters) {
if (c.converter()->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
return c.converter();
if (c.converter().matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
return &c.converter();
}
}
return ox::Error{1, "Could not find converter"};
@@ -46,14 +46,14 @@ static ox::Result<ox::UPtr<Wrap>> convert(
}
// try to chain multiple converters
for (auto const&subConverter : converters) {
if (!subConverter.converter()->dstMatches(dstTypeName, dstTypeVersion)) {
if (!subConverter.converter().dstMatches(dstTypeName, dstTypeVersion)) {
continue;
}
const auto [intermediate, chainErr] =
convert(ctx, converters, src, srcTypeName, srcTypeVersion,
subConverter.converter()->srcTypeName(), subConverter.converter()->srcTypeVersion());
subConverter.converter().srcTypeName(), subConverter.converter().srcTypeVersion());
if (!chainErr) {
return subConverter.converter()->convertPtrToPtr(ctx, *intermediate);
return subConverter.converter().convertPtrToPtr(ctx, *intermediate);
}
}
return ox::Error{1, "Could not convert between types"};