[keel] Make Keel preload functions templates to allow for different plat specs
This commit is contained in:
		@@ -165,71 +165,6 @@ static ox::Error copyFS(ox::FileSystem *src, ox::FileSystem *dest) noexcept {
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// transformations need to be done after the copy to the new FS is complete
 | 
			
		||||
static ox::Error preloadObj(
 | 
			
		||||
		ox::TypeStore *ts, ox::FileSystem *romFs,
 | 
			
		||||
		GbaPreloader *pl, ox::CRStringView path) noexcept {
 | 
			
		||||
	// load file
 | 
			
		||||
	oxRequireM(buff, romFs->read(path));
 | 
			
		||||
	oxRequireM(obj, keel::readAsset(ts, buff));
 | 
			
		||||
	if (obj.type()->preloadable) {
 | 
			
		||||
		oxOutf("preloading {}\n", path);
 | 
			
		||||
		// preload
 | 
			
		||||
		oxRequire(a, pl->startAlloc(ox::sizeOf<GbaPlatSpec>(&obj)));
 | 
			
		||||
		const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
 | 
			
		||||
		oxReturnError(pl->endAlloc());
 | 
			
		||||
		oxReturnError(err);
 | 
			
		||||
		const keel::PreloadPtr p{.preloadAddr = static_cast<uint32_t>(a)};
 | 
			
		||||
		oxReturnError(ox::writeMC(&p).moveTo(&buff));
 | 
			
		||||
	} else {
 | 
			
		||||
		// strip the Claw header (it is not needed after preloading) and write back out to dest fs
 | 
			
		||||
		oxReturnError(ox::writeMC(&obj).moveTo(&buff));
 | 
			
		||||
	}
 | 
			
		||||
	oxReturnError(romFs->write(path, buff.data(), buff.size()));
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// claw file transformations are broken out because path to inode
 | 
			
		||||
// transformations need to be done after the copy to the new FS is complete
 | 
			
		||||
static ox::Error preloadDir(ox::TypeStore *ts, ox::FileSystem *romFs, GbaPreloader *pl, ox::CRStringView path) noexcept {
 | 
			
		||||
	// copy
 | 
			
		||||
	oxTracef("pack::preload", "path: {}", path);
 | 
			
		||||
	oxRequire(fileList, romFs->ls(path));
 | 
			
		||||
	for (const auto &name : fileList) {
 | 
			
		||||
		const auto filePath = ox::sfmt("{}{}", path, name);
 | 
			
		||||
		oxRequire(stat, romFs->stat(filePath));
 | 
			
		||||
		if (stat.fileType == ox::FileType::Directory) {
 | 
			
		||||
			const auto dir = ox::sfmt("{}{}/", path, name);
 | 
			
		||||
			oxReturnError(preloadDir(ts, romFs, pl, dir));
 | 
			
		||||
		} else {
 | 
			
		||||
			oxReturnError(preloadObj(ts, romFs, pl, filePath));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ox::Error padbin(ox::BufferWriter *w, unsigned factor) noexcept {
 | 
			
		||||
	return w->write(nullptr, factor - w->buff().size() % factor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, GbaPreloader *pl) noexcept {
 | 
			
		||||
	constexpr ox::StringView mediaHdr   = "KEEL_MEDIA_HEADER_______________";
 | 
			
		||||
	constexpr ox::StringView preloadHdr = "KEEL_PRELOAD_HEADER_____________";
 | 
			
		||||
	constexpr auto hdrSize = 32u;
 | 
			
		||||
	static_assert(mediaHdr.bytes() == hdrSize);
 | 
			
		||||
	static_assert(preloadHdr.bytes() == hdrSize);
 | 
			
		||||
	ox::BufferWriter w(binBuff);
 | 
			
		||||
	oxReturnError(padbin(&w, hdrSize));
 | 
			
		||||
	oxReturnError(w.write(mediaHdr.data(), mediaHdr.bytes()));
 | 
			
		||||
	oxReturnError(w.write(fsBuff->data(), fsBuff->size()));
 | 
			
		||||
	oxReturnError(padbin(&w, hdrSize));
 | 
			
		||||
	oxReturnError(w.write(preloadHdr.data(), preloadHdr.bytes()));
 | 
			
		||||
	const auto &plBuff = pl->buff();
 | 
			
		||||
	oxReturnError(pl->offsetPtrs(binBuff->size()));
 | 
			
		||||
	oxReturnError(w.write(plBuff.data(), plBuff.size()));
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error pack(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept {
 | 
			
		||||
	oxReturnError(copyFS(ctx->rom.get(), dest));
 | 
			
		||||
	oxOut("Doing transforms\n");
 | 
			
		||||
@@ -237,11 +172,6 @@ ox::Error pack(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noex
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error preload(ox::TypeStore *ts, ox::FileSystem *src, GbaPreloader *pl) noexcept {
 | 
			
		||||
	oxOut("Preloading\n");
 | 
			
		||||
	return preloadDir(ts, src, pl, "/");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,9 @@
 | 
			
		||||
#include <ox/fs/fs.hpp>
 | 
			
		||||
#include <ox/preloader/preloader.hpp>
 | 
			
		||||
 | 
			
		||||
#include "asset.hpp"
 | 
			
		||||
#include "media.hpp"
 | 
			
		||||
 | 
			
		||||
namespace keel {
 | 
			
		||||
 | 
			
		||||
class Context;
 | 
			
		||||
@@ -76,10 +79,88 @@ struct GbaPlatSpec {
 | 
			
		||||
 | 
			
		||||
using GbaPreloader = ox::Preloader<GbaPlatSpec>;
 | 
			
		||||
 | 
			
		||||
ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, GbaPreloader *pl) noexcept;
 | 
			
		||||
namespace detail {
 | 
			
		||||
// transformations need to be done after the copy to the new FS is complete
 | 
			
		||||
template<typename PlatSpec>
 | 
			
		||||
ox::Error preloadObj(
 | 
			
		||||
		ox::TypeStore *ts,
 | 
			
		||||
		ox::FileSystem *romFs,
 | 
			
		||||
		ox::Preloader<PlatSpec> *pl,
 | 
			
		||||
		ox::CRStringView path) noexcept {
 | 
			
		||||
	// load file
 | 
			
		||||
	oxRequireM(buff, romFs->read(path));
 | 
			
		||||
	oxRequireM(obj, keel::readAsset(ts, buff));
 | 
			
		||||
	if (obj.type()->preloadable) {
 | 
			
		||||
		oxOutf("preloading {}\n", path);
 | 
			
		||||
		// preload
 | 
			
		||||
		oxRequire(a, pl->startAlloc(ox::sizeOf<GbaPlatSpec>(&obj)));
 | 
			
		||||
		const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
 | 
			
		||||
		oxReturnError(pl->endAlloc());
 | 
			
		||||
		oxReturnError(err);
 | 
			
		||||
		const keel::PreloadPtr p{.preloadAddr = static_cast<uint32_t>(a)};
 | 
			
		||||
		oxReturnError(ox::writeMC(&p).moveTo(&buff));
 | 
			
		||||
	} else {
 | 
			
		||||
		// strip the Claw header (it is not needed after preloading) and write back out to dest fs
 | 
			
		||||
		oxReturnError(ox::writeMC(&obj).moveTo(&buff));
 | 
			
		||||
	}
 | 
			
		||||
	oxReturnError(romFs->write(path, buff.data(), buff.size()));
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// claw file transformations are broken out because path to inode
 | 
			
		||||
// transformations need to be done after the copy to the new FS is complete
 | 
			
		||||
template<typename PlatSpec>
 | 
			
		||||
ox::Error preloadDir(
 | 
			
		||||
		ox::TypeStore *ts,
 | 
			
		||||
		ox::FileSystem *romFs,
 | 
			
		||||
		ox::Preloader<PlatSpec> *pl,
 | 
			
		||||
		ox::CRStringView path) noexcept {
 | 
			
		||||
	// copy
 | 
			
		||||
	oxTracef("pack::preload", "path: {}", path);
 | 
			
		||||
	oxRequire(fileList, romFs->ls(path));
 | 
			
		||||
	for (const auto &name : fileList) {
 | 
			
		||||
		const auto filePath = ox::sfmt("{}{}", path, name);
 | 
			
		||||
		oxRequire(stat, romFs->stat(filePath));
 | 
			
		||||
		if (stat.fileType == ox::FileType::Directory) {
 | 
			
		||||
			const auto dir = ox::sfmt("{}{}/", path, name);
 | 
			
		||||
			oxReturnError(preloadDir(ts, romFs, pl, dir));
 | 
			
		||||
		} else {
 | 
			
		||||
			oxReturnError(preloadObj(ts, romFs, pl, filePath));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename PlatSpec>
 | 
			
		||||
ox::Error appendBinary(ox::Buffer *binBuff, ox::Buffer *fsBuff, ox::Preloader<PlatSpec> *pl) noexcept {
 | 
			
		||||
	constexpr auto padbin = [](ox::BufferWriter *w, unsigned factor) noexcept -> ox::Error {
 | 
			
		||||
		return w->write(nullptr, factor - w->buff().size() % factor);
 | 
			
		||||
	};
 | 
			
		||||
	constexpr ox::StringView mediaHdr   = "KEEL_MEDIA_HEADER_______________";
 | 
			
		||||
	constexpr ox::StringView preloadHdr = "KEEL_PRELOAD_HEADER_____________";
 | 
			
		||||
	constexpr auto hdrSize = 32u;
 | 
			
		||||
	static_assert(mediaHdr.bytes() == hdrSize);
 | 
			
		||||
	static_assert(preloadHdr.bytes() == hdrSize);
 | 
			
		||||
	ox::BufferWriter w(binBuff);
 | 
			
		||||
	oxReturnError(padbin(&w, hdrSize));
 | 
			
		||||
	oxReturnError(w.write(mediaHdr.data(), mediaHdr.bytes()));
 | 
			
		||||
	oxReturnError(w.write(fsBuff->data(), fsBuff->size()));
 | 
			
		||||
	oxReturnError(padbin(&w, hdrSize));
 | 
			
		||||
	oxReturnError(w.write(preloadHdr.data(), preloadHdr.bytes()));
 | 
			
		||||
	oxReturnError(pl->offsetPtrs(binBuff->size()));
 | 
			
		||||
	const auto &plBuff = pl->buff();
 | 
			
		||||
	oxReturnError(w.write(plBuff.data(), plBuff.size()));
 | 
			
		||||
	return {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename PlatSpec>
 | 
			
		||||
ox::Error preload(ox::TypeStore *ts, ox::FileSystem *src, ox::Preloader<PlatSpec> *pl) noexcept {
 | 
			
		||||
	oxOut("Preloading\n");
 | 
			
		||||
	return detail::preloadDir(ts, src, pl, "/");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ox::Error pack(keel::Context *ctx, ox::TypeStore *ts, ox::FileSystem *dest) noexcept;
 | 
			
		||||
 | 
			
		||||
ox::Error preload(ox::TypeStore *ts, ox::FileSystem *src, GbaPreloader *pl) noexcept;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user