[keel] Add manifest to pack output

This commit is contained in:
Gary Talent 2024-09-14 20:47:54 -05:00
parent 3b8eaef36b
commit 0cc6757c57
7 changed files with 82 additions and 31 deletions

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ imgui.ini
*.sav *.sav
studio_state.json studio_state.json
tags tags
*-manifest.json

View File

@ -28,8 +28,12 @@ project_name = sys.argv[2]
bin = f'./build/{host_env}-{current_build}/bin/' bin = f'./build/{host_env}-{current_build}/bin/'
project_bin = f'build/gba-release/bin/{project_name}.bin' project_bin = f'build/gba-release/bin/{project_name}.bin'
project_gba = f'{project_name}.gba' project_gba = f'{project_name}.gba'
project_manifest = f'{project_name}-manifest.json'
shutil.copyfile(project_bin, project_gba) shutil.copyfile(project_bin, project_gba)
subprocess.run([ subprocess.run([
f'{bin}/{project_name}-pack', '-src', project_dir, '-rom-bin', project_gba]) f'{bin}/{project_name}-pack',
'-src', project_dir,
'-rom-bin', project_gba,
'-manifest', project_manifest])
subprocess.run(['gbafix', project_gba]) subprocess.run(['gbafix', project_gba])

View File

@ -57,8 +57,6 @@ ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::CRStringView uuid) noex
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept; ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept;
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
namespace detail { namespace detail {

View File

@ -12,6 +12,31 @@
namespace keel { namespace keel {
struct ManifestEntry {
static constexpr auto TypeName = "net.drinkingtea.keel.ManifestEntry";
static constexpr auto TypeVersion = 1;
uint64_t inode{};
bool preloaded{};
ox::String type;
};
oxModelBegin(ManifestEntry)
oxModelField(inode)
oxModelField(preloaded)
oxModelField(type)
oxModelEnd()
struct Manifest {
static constexpr auto TypeName = "net.drinkingtea.keel.Manifest";
static constexpr auto TypeVersion = 1;
ox::HashMap<ox::String, ManifestEntry> files;
};
oxModelBegin(Manifest)
oxModelField(files)
oxModelEnd()
class Context; class Context;
struct GbaPlatSpec { struct GbaPlatSpec {
@ -113,6 +138,7 @@ ox::Error preloadObj(
// 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
template<typename PlatSpec> template<typename PlatSpec>
ox::Error preloadDir( ox::Error preloadDir(
Manifest &manifest,
ox::TypeStore &ts, ox::TypeStore &ts,
ox::FileSystem &romFs, ox::FileSystem &romFs,
ox::Preloader<PlatSpec> &pl, ox::Preloader<PlatSpec> &pl,
@ -125,13 +151,14 @@ ox::Error preloadDir(
oxRequire(stat, romFs.stat(filePath)); oxRequire(stat, romFs.stat(filePath));
if (stat.fileType == ox::FileType::Directory) { if (stat.fileType == ox::FileType::Directory) {
auto const dir = ox::sfmt("{}{}/", path, name); auto const dir = ox::sfmt("{}{}/", path, name);
oxReturnError(preloadDir(ts, romFs, pl, dir)); oxReturnError(preloadDir(manifest, ts, romFs, pl, dir));
} else { } else {
auto const err = preloadObj(ts, romFs, pl, filePath); auto const err = preloadObj(ts, romFs, pl, filePath);
if (err) { if (err) {
oxErrf("\033[31;1;1mCould not preload {}:\n\t{}\n", filePath, toStr(err)); oxErrf("\033[31;1;1mCould not preload {}:\n\t{}\n", filePath, toStr(err));
return err; return err;
} }
manifest.files[filePath].preloaded = true;
} }
} }
return {}; return {};
@ -162,11 +189,15 @@ ox::Error appendBinary(ox::Buffer &binBuff, ox::SpanView<char> const&fsBuff, ox:
} }
template<typename PlatSpec> template<typename PlatSpec>
ox::Error preload(ox::TypeStore &ts, ox::FileSystem &src, ox::Preloader<PlatSpec> &pl) noexcept { ox::Error preload(
Manifest &manifest,
ox::TypeStore &ts,
ox::FileSystem &src,
ox::Preloader<PlatSpec> &pl) noexcept {
oxOut("Preloading\n"); oxOut("Preloading\n");
return detail::preloadDir(ts, src, pl, "/"); return detail::preloadDir(manifest, ts, src, pl, "/");
} }
ox::Error pack(keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept; ox::Error pack(Manifest &manifest, keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept;
} }

View File

@ -154,18 +154,6 @@ ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexce
#endif #endif
} }
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
oxRequireM(typeId, readAssetTypeId(clawData));
for (auto const tr : packTransforms(ctx)) {
bool changed{};
oxReturnError(tr(ctx, clawData, typeId).moveTo(changed));
if (changed) {
oxReturnError(readAssetTypeId(clawData).moveTo(typeId));
}
}
return {};
}
ox::Error reloadAsset(keel::Context &ctx, ox::StringView assetId) noexcept { ox::Error reloadAsset(keel::Context &ctx, ox::StringView assetId) noexcept {
ox::UUIDStr uuidStr; ox::UUIDStr uuidStr;
if (beginsWith(assetId, "uuid://")) { if (beginsWith(assetId, "uuid://")) {

View File

@ -8,6 +8,7 @@
#include <ox/fs/fs.hpp> #include <ox/fs/fs.hpp>
#include <ox/logconn/def.hpp> #include <ox/logconn/def.hpp>
#include <ox/logconn/logconn.hpp> #include <ox/logconn/logconn.hpp>
#include <ox/oc/write.hpp>
#include <keel/keel.hpp> #include <keel/keel.hpp>
@ -48,16 +49,21 @@ static ox::Error generateTypes(ox::TypeStore &ts) noexcept {
return {}; return {};
} }
static ox::Error pack(ox::StringView argSrc, ox::StringView argRomBin, ox::StringView projectDataDir) noexcept { static ox::Error pack(
ox::StringView argSrc,
ox::StringView argRomBin,
ox::StringView argManifest,
ox::StringView projectDataDir) 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::FileSystem32 dst(dstBuff); ox::FileSystem32 dst(dstBuff);
oxRequire(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack")); oxRequire(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack"));
keel::TypeStore ts(*ctx->rom, ox::sfmt("{}/type_descriptors", projectDataDir)); keel::TypeStore ts(*ctx->rom, ox::sfmt("{}/type_descriptors", projectDataDir));
oxReturnError(generateTypes(ts)); oxReturnError(generateTypes(ts));
oxReturnError(keel::pack(*ctx, ts, dst)); keel::Manifest manifest;
oxReturnError(keel::pack(manifest, *ctx, ts, dst));
oxRequireM(pl, keel::GbaPreloader::make()); oxRequireM(pl, keel::GbaPreloader::make());
oxReturnError(preload(ts, dst, *pl)); oxReturnError(preload(manifest, ts, dst, *pl));
oxReturnError(dst.resize()); oxReturnError(dst.resize());
// resize buffer // resize buffer
oxRequire(dstSize, dst.size()); oxRequire(dstSize, dst.size());
@ -70,6 +76,8 @@ static ox::Error pack(ox::StringView argSrc, ox::StringView argRomBin, ox::Strin
oxReturnError(appendBinary(romBuff, dstBuff, *pl)); oxReturnError(appendBinary(romBuff, dstBuff, *pl));
oxOutf("Final ROM buff size: {} bytes\n", romBuff.size()); oxOutf("Final ROM buff size: {} bytes\n", romBuff.size());
oxReturnError(writeFileBuff(argRomBin, romBuff)); oxReturnError(writeFileBuff(argRomBin, romBuff));
oxRequire(manifestJson, ox::writeOC(manifest));
oxReturnError(writeFileBuff(argManifest, manifestJson));
return {}; return {};
} }
@ -77,6 +85,7 @@ static ox::Error run(int argc, char const**argv, ox::StringView projectDataDir)
ox::ClArgs const args(argc, argv); ox::ClArgs const args(argc, argv);
auto const argSrc = args.getString("src", ""); auto const argSrc = args.getString("src", "");
auto const argRomBin = args.getString("rom-bin", ""); auto const argRomBin = args.getString("rom-bin", "");
auto const argManifest = args.getString("manifest", "");
if (argSrc == "") { if (argSrc == "") {
oxErr("\033[31;1;1merror:\033[0m must specify a source directory\n"); oxErr("\033[31;1;1merror:\033[0m must specify a source directory\n");
return OxError(1, "must specify a source directory"); return OxError(1, "must specify a source directory");
@ -85,7 +94,7 @@ static ox::Error run(int argc, char const**argv, ox::StringView projectDataDir)
oxErr("\033[31;1;1merror:\033[0m must specify a path for ROM file\n"); oxErr("\033[31;1;1merror:\033[0m must specify a path for ROM file\n");
return OxError(1, "must specify a path for preload file"); return OxError(1, "must specify a path for preload file");
} }
return pack(argSrc, argRomBin, projectDataDir); return pack(argSrc, argRomBin, argManifest, projectDataDir);
} }
namespace olympic { namespace olympic {

View File

@ -6,7 +6,6 @@
#include <ox/model/modelvalue.hpp> #include <ox/model/modelvalue.hpp>
#include <keel/media.hpp> #include <keel/media.hpp>
#include <keel/pack.hpp> #include <keel/pack.hpp>
namespace keel { namespace keel {
@ -85,7 +84,21 @@ static ox::Error transformFileAddressesObj(
return {}; return {};
} }
static ox::Error performPackTransforms(ManifestEntry &entry, Context &ctx, ox::Buffer &clawData) noexcept {
oxRequireM(typeId, readAssetTypeId(clawData));
for (auto const tr : packTransforms(ctx)) {
bool changed{};
oxReturnError(tr(ctx, clawData, typeId).moveTo(changed));
if (changed) {
oxReturnError(readAssetTypeId(clawData).moveTo(typeId));
}
}
entry.type = ox::String{typeId};
return {};
}
static ox::Error doTransformations( static ox::Error doTransformations(
Manifest &manifest,
keel::Context &ctx, keel::Context &ctx,
ox::TypeStore &ts, ox::TypeStore &ts,
ox::FileSystem &dest, ox::FileSystem &dest,
@ -94,7 +107,7 @@ static ox::Error doTransformations(
oxRequire(s, dest.stat(filePath)); oxRequire(s, dest.stat(filePath));
// do transformations // do transformations
oxRequireM(buff, dest.read(s.inode)); oxRequireM(buff, dest.read(s.inode));
oxReturnError(keel::performPackTransforms(ctx, buff)); oxReturnError(keel::performPackTransforms(manifest.files[filePath], ctx, buff));
// transform FileAddresses // transform FileAddresses
oxRequireM(obj, keel::readAsset(ts, buff)); oxRequireM(obj, keel::readAsset(ts, buff));
oxOutf("transforming {}\n", filePath); oxOutf("transforming {}\n", filePath);
@ -108,6 +121,7 @@ static ox::Error doTransformations(
// claw file transformations are broken out from copy because path to inode // claw file transformations are broken out from copy 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( static ox::Error transformClaw(
Manifest &manifest,
keel::Context &ctx, keel::Context &ctx,
ox::TypeStore &ts, ox::TypeStore &ts,
ox::FileSystem &dest, ox::FileSystem &dest,
@ -120,9 +134,9 @@ static ox::Error transformClaw(
oxRequire(stat, dest.stat(filePath)); oxRequire(stat, dest.stat(filePath));
if (stat.fileType == ox::FileType::Directory) { if (stat.fileType == ox::FileType::Directory) {
auto const dir = ox::sfmt("{}{}/", path, name); auto const dir = ox::sfmt("{}{}/", path, name);
oxReturnError(transformClaw(ctx, ts, dest, dir)); oxReturnError(transformClaw(manifest, ctx, ts, dest, dir));
} else { } else {
auto const err = doTransformations(ctx, ts, dest, filePath); auto const err = doTransformations(manifest, ctx, ts, dest, filePath);
if (err) { if (err) {
oxErrf("\033[31;1;1mCould not do transformations for {}:\n\t{}\n", filePath, toStr(err)); oxErrf("\033[31;1;1mCould not do transformations for {}:\n\t{}\n", filePath, toStr(err));
return err; return err;
@ -133,6 +147,7 @@ static ox::Error transformClaw(
} }
static ox::Error copy( static ox::Error copy(
Manifest &manifest,
ox::FileSystem &src, ox::FileSystem &src,
ox::FileSystem &dest, ox::FileSystem &dest,
ox::CRStringView path, ox::CRStringView path,
@ -149,7 +164,7 @@ static ox::Error copy(
oxRequire(stat, src.stat(currentFile)); oxRequire(stat, src.stat(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 + '/', childLogPrefix)); oxReturnError(copy(manifest, src, dest, currentFile + '/', childLogPrefix));
} else { } else {
// load file // load file
oxOutf("{}copying file: {}...", childLogPrefix, currentFile); oxOutf("{}copying file: {}...", childLogPrefix, currentFile);
@ -161,15 +176,20 @@ static ox::Error copy(
// write file to dest // write file to dest
oxReturnError(dest.write(currentFile, buff)); oxReturnError(dest.write(currentFile, buff));
status = "OK"; status = "OK";
oxRequire(stat, dest.stat(currentFile));
manifest.files[currentFile] = {
.inode = stat.inode,
.type = ox::String{keel::readAssetTypeId(buff).or_value({})},
};
} }
} }
return {}; return {};
} }
ox::Error pack(keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept { ox::Error pack(Manifest &manifest, keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept {
oxReturnError(copy(*ctx.rom, dest, "/")); oxReturnError(copy(manifest, *ctx.rom, dest, "/"));
oxOut("Doing transforms\n"); oxOut("Doing transforms\n");
oxReturnError(transformClaw(ctx, ts, dest, "/")); oxReturnError(transformClaw(manifest, ctx, ts, dest, "/"));
return {}; return {};
} }