[nostalgia/tools] Add NostalgiaPack library
This commit is contained in:
		@@ -12,6 +12,7 @@ target_link_libraries(
 | 
				
			|||||||
		OxMetalClaw
 | 
							OxMetalClaw
 | 
				
			||||||
		NostalgiaCommon
 | 
							NostalgiaCommon
 | 
				
			||||||
		NostalgiaCore
 | 
							NostalgiaCore
 | 
				
			||||||
 | 
							NostalgiaPack
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install(
 | 
					install(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@
 | 
				
			|||||||
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
					 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <array>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
#include <QColor>
 | 
					#include <QColor>
 | 
				
			||||||
#include <QImage>
 | 
					#include <QImage>
 | 
				
			||||||
@@ -14,155 +15,42 @@
 | 
				
			|||||||
#include <nostalgia/common/point.hpp>
 | 
					#include <nostalgia/common/point.hpp>
 | 
				
			||||||
#include <ox/clargs/clargs.hpp>
 | 
					#include <ox/clargs/clargs.hpp>
 | 
				
			||||||
#include <ox/fs/fs.hpp>
 | 
					#include <ox/fs/fs.hpp>
 | 
				
			||||||
 | 
					#include <ox/std/units.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "pack/pack.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace std;
 | 
					using namespace std;
 | 
				
			||||||
using namespace ox;
 | 
					using namespace ox;
 | 
				
			||||||
using namespace nostalgia::core;
 | 
					using namespace nostalgia::core;
 | 
				
			||||||
using namespace nostalgia::common;
 | 
					using namespace nostalgia::common;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t *loadFileBuff(QString path, ::size_t *sizeOut = nullptr) {
 | 
					ox::ValErr<std::vector<uint8_t>> loadFileBuff(QString path, ::size_t *sizeOut = nullptr) {
 | 
				
			||||||
	auto file = fopen(path.toUtf8(), "rb");
 | 
						auto file = fopen(path.toUtf8(), "rb");
 | 
				
			||||||
	if (file) {
 | 
						if (file) {
 | 
				
			||||||
		fseek(file, 0, SEEK_END);
 | 
							fseek(file, 0, SEEK_END);
 | 
				
			||||||
		const auto size = ftell(file);
 | 
							const auto size = ftell(file);
 | 
				
			||||||
		rewind(file);
 | 
							rewind(file);
 | 
				
			||||||
		auto buff = new uint8_t[size];
 | 
							std::vector<uint8_t> buff(size);
 | 
				
			||||||
		auto itemsRead = fread(buff, size, 1, file);
 | 
							auto itemsRead = fread(buff.data(), buff.size(), 1, file);
 | 
				
			||||||
		fclose(file);
 | 
							fclose(file);
 | 
				
			||||||
		if (sizeOut) {
 | 
							if (sizeOut) {
 | 
				
			||||||
			*sizeOut = itemsRead ? size : 0;
 | 
								*sizeOut = itemsRead ? size : 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return buff;
 | 
							return buff;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return nullptr;
 | 
							return {{}, OxError(1)};
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint16_t toGbaColor(QColor c) {
 | 
					 | 
				
			||||||
	auto r = static_cast<uint32_t>(c.red()) >> 3;
 | 
					 | 
				
			||||||
	auto g = static_cast<uint32_t>(c.green()) >> 3;
 | 
					 | 
				
			||||||
	auto b = static_cast<uint32_t>(c.blue()) >> 3;
 | 
					 | 
				
			||||||
	return (r << 10) | (g << 5) | (b << 0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int pointToIdx(int w, int x, int y) {
 | 
					 | 
				
			||||||
	const auto colLength = 64;
 | 
					 | 
				
			||||||
	const auto rowLength = (w / 8) * colLength;
 | 
					 | 
				
			||||||
	const auto colStart = colLength * (x / 8);
 | 
					 | 
				
			||||||
	const auto rowStart = rowLength * (y / 8);
 | 
					 | 
				
			||||||
	const auto colOffset = x % 8;
 | 
					 | 
				
			||||||
	const auto rowOffset = (y % 8) * 8;
 | 
					 | 
				
			||||||
	return colStart + colOffset + rowStart + rowOffset;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int run(ClArgs args) {
 | 
					int run(ClArgs args) {
 | 
				
			||||||
	Error err = 0;
 | 
						QString argSrc = args.getString("src").c_str();
 | 
				
			||||||
	int argInode = args.getInt("inode");
 | 
						QString argDst = args.getString("dst").c_str();
 | 
				
			||||||
	QString argInPath = args.getString("img").c_str();
 | 
						std::array<uint8_t, 32 * ox::units::MB> buff;
 | 
				
			||||||
	QString argFsPath = args.getString("fs").c_str();
 | 
						ox::FileSystem32::format(buff.data(), buff.size());
 | 
				
			||||||
	auto argCompact = args.getBool("c");
 | 
						ox::PassThroughFS src(argSrc.toUtf8());
 | 
				
			||||||
	auto argTiles = args.getInt("tiles");
 | 
						ox::FileSystem32 dst(ox::FileStore32(buff.data(), buff.size()));
 | 
				
			||||||
	auto argBpp = args.getInt("bpp");
 | 
						oxReturnError(nostalgia::pack(&src, &dst));
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
	QImage src(argInPath);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!src.isNull()) {
 | 
					 | 
				
			||||||
		if (argTiles == 0) {
 | 
					 | 
				
			||||||
			argTiles = (src.width() * src.height()) / 64;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (argBpp != 4 && argBpp != 8) {
 | 
					 | 
				
			||||||
			argBpp = 8;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		QMap<QRgb, int> colors;
 | 
					 | 
				
			||||||
		const auto imgDataBuffSize = sizeof(GbaImageData) + 1 + argTiles * 64;
 | 
					 | 
				
			||||||
		QVector<uint8_t> imgDataBuff(imgDataBuffSize);
 | 
					 | 
				
			||||||
		memset(imgDataBuff.data(), 0, imgDataBuffSize);
 | 
					 | 
				
			||||||
		auto id = reinterpret_cast<GbaImageData*>(imgDataBuff.data());
 | 
					 | 
				
			||||||
		id->header.bpp = argBpp;
 | 
					 | 
				
			||||||
		id->header.tileCount = argTiles;
 | 
					 | 
				
			||||||
		int colorId = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// copy pixels as color ids
 | 
					 | 
				
			||||||
		for (int x = 0; x < src.width(); x++) {
 | 
					 | 
				
			||||||
			for (int y = 0; y < src.height(); y++) {
 | 
					 | 
				
			||||||
				auto destI = pointToIdx(src.width(), x, y);
 | 
					 | 
				
			||||||
				if (destI <= argTiles * 64) {
 | 
					 | 
				
			||||||
					auto c = src.pixel(x, y);
 | 
					 | 
				
			||||||
					// assign color a color id for the palette
 | 
					 | 
				
			||||||
					if (!colors.contains(c)) {
 | 
					 | 
				
			||||||
						colors[c] = colorId;
 | 
					 | 
				
			||||||
						colorId++;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					// set pixel color
 | 
					 | 
				
			||||||
					if (argBpp == 4) {
 | 
					 | 
				
			||||||
						if (destI % 2) { // is odd number pixel
 | 
					 | 
				
			||||||
							id->tiles[destI / 2] |= colors[c] << 4;
 | 
					 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							id->tiles[destI / 2] |= colors[c];
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						id->tiles[destI] = colors[c];
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// store colors in palette with the corresponding color id
 | 
					 | 
				
			||||||
		for (auto key : colors.keys()) {
 | 
					 | 
				
			||||||
			auto colorId = colors[key];
 | 
					 | 
				
			||||||
			id->pal[colorId] = toGbaColor(key);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		size_t fsBuffSize;
 | 
					 | 
				
			||||||
		auto fsBuff = loadFileBuff(argFsPath, &fsBuffSize);
 | 
					 | 
				
			||||||
		if (fsBuff && !err) {
 | 
					 | 
				
			||||||
			auto fs = FileSystem32(FileStore32(fsBuff, fsBuffSize));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (fs.valid()) {
 | 
					 | 
				
			||||||
				const auto sizeNeeded = fs.size() + fs.spaceNeeded(imgDataBuffSize);
 | 
					 | 
				
			||||||
				if (sizeNeeded > fsBuffSize) {
 | 
					 | 
				
			||||||
					auto newBuff = new uint8_t[sizeNeeded];
 | 
					 | 
				
			||||||
					memcpy(newBuff, fsBuff, fsBuffSize);
 | 
					 | 
				
			||||||
					delete[] fsBuff;
 | 
					 | 
				
			||||||
					fsBuff = newBuff;
 | 
					 | 
				
			||||||
					fsBuffSize = sizeNeeded;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				fsBuff = fs.buff(); // update fsBuff pointer in case there is a new buff
 | 
					 | 
				
			||||||
				err |= fs.write(argInode, imgDataBuff.data(), imgDataBuffSize);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (!err) {
 | 
					 | 
				
			||||||
					if (argCompact) {
 | 
					 | 
				
			||||||
						FileStore32(fsBuff, fsBuffSize).compact();
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
					auto fsFile = fopen(argFsPath.toUtf8(), "wb");
 | 
					 | 
				
			||||||
					if (fsFile) {
 | 
					 | 
				
			||||||
						err = fwrite(fsBuff, fs.size(), 1, fsFile) != 1;
 | 
					 | 
				
			||||||
						err |= fclose(fsFile);
 | 
					 | 
				
			||||||
						if (err) {
 | 
					 | 
				
			||||||
							cerr << "Could not write to file system file.\n";
 | 
					 | 
				
			||||||
						}
 | 
					 | 
				
			||||||
					} else {
 | 
					 | 
				
			||||||
						err = 2;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				} else {
 | 
					 | 
				
			||||||
					err = 3;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				err = 4;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (fsBuff) {
 | 
					 | 
				
			||||||
			delete[] fsBuff;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		err = 5;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return err;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, const char **args) {
 | 
					int main(int argc, const char **args) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
add_library(
 | 
					add_library(
 | 
				
			||||||
	Pack SHARED
 | 
						NostalgiaPack SHARED
 | 
				
			||||||
		imgconv.cpp
 | 
							imgconv.cpp
 | 
				
			||||||
		pack.cpp
 | 
							pack.cpp
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
target_link_libraries(
 | 
					target_link_libraries(
 | 
				
			||||||
	Pack
 | 
						NostalgiaPack
 | 
				
			||||||
		Qt5::Widgets
 | 
							Qt5::Widgets
 | 
				
			||||||
		OxClArgs
 | 
							OxClArgs
 | 
				
			||||||
		OxFS
 | 
							OxFS
 | 
				
			||||||
@@ -18,7 +18,7 @@ target_link_libraries(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
install(
 | 
					install(
 | 
				
			||||||
	TARGETS
 | 
						TARGETS
 | 
				
			||||||
		Pack
 | 
							NostalgiaPack
 | 
				
			||||||
	LIBRARY DESTINATION
 | 
						LIBRARY DESTINATION
 | 
				
			||||||
		${NOSTALGIA_DIST_LIB}/nostalgia
 | 
							${NOSTALGIA_DIST_LIB}/nostalgia
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,11 +56,13 @@ namespace {
 | 
				
			|||||||
	return colors.size();
 | 
						return colors.size();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ox::Error pngToGba(QString argInPath, int argTiles, int argBpp) {
 | 
					[[nodiscard]] std::vector<char> pngToGba(QString argInPath, int argTiles, int argBpp) {
 | 
				
			||||||
	ox::Error err = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	QImage src(argInPath);
 | 
						QImage src(argInPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (src.isNull()) {
 | 
				
			||||||
 | 
							return {};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (argTiles == 0) {
 | 
						if (argTiles == 0) {
 | 
				
			||||||
		argTiles = (src.width() * src.height()) / 64;
 | 
							argTiles = (src.width() * src.height()) / 64;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -70,9 +72,8 @@ ox::Error pngToGba(QString argInPath, int argTiles, int argBpp) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	QMap<QRgb, int> colors;
 | 
						QMap<QRgb, int> colors;
 | 
				
			||||||
	const auto imgDataBuffSize = sizeof(core::GbaImageData) + 1 + argTiles * 64;
 | 
						const auto imgDataBuffSize = sizeof(core::GbaImageData) + 1 + argTiles * 64;
 | 
				
			||||||
	auto imgDataBuff = std::make_unique<uint8_t[]>(imgDataBuffSize);
 | 
						std::vector<char> imgDataBuff(imgDataBuffSize);
 | 
				
			||||||
	memset(imgDataBuff.get(), 0, imgDataBuffSize);
 | 
						auto id = new (imgDataBuff.data()) core::GbaImageData;
 | 
				
			||||||
	auto id = reinterpret_cast<core::GbaImageData*>(imgDataBuff.get());
 | 
					 | 
				
			||||||
	id->header.bpp = argBpp;
 | 
						id->header.bpp = argBpp;
 | 
				
			||||||
	id->header.tileCount = argTiles;
 | 
						id->header.tileCount = argTiles;
 | 
				
			||||||
	int colorId = 0;
 | 
						int colorId = 0;
 | 
				
			||||||
@@ -82,7 +83,7 @@ ox::Error pngToGba(QString argInPath, int argTiles, int argBpp) {
 | 
				
			|||||||
		for (int y = 0; y < src.height(); y++) {
 | 
							for (int y = 0; y < src.height(); y++) {
 | 
				
			||||||
			auto destI = pointToIdx(src.width(), x, y);
 | 
								auto destI = pointToIdx(src.width(), x, y);
 | 
				
			||||||
			if (destI <= argTiles * 64) {
 | 
								if (destI <= argTiles * 64) {
 | 
				
			||||||
				auto c = src.pixel(x, y);
 | 
									const auto c = src.pixel(x, y);
 | 
				
			||||||
				// assign color a color id for the palette
 | 
									// assign color a color id for the palette
 | 
				
			||||||
				if (!colors.contains(c)) {
 | 
									if (!colors.contains(c)) {
 | 
				
			||||||
					colors[c] = colorId;
 | 
										colors[c] = colorId;
 | 
				
			||||||
@@ -107,7 +108,8 @@ ox::Error pngToGba(QString argInPath, int argTiles, int argBpp) {
 | 
				
			|||||||
	  auto colorId = colors[key];
 | 
						  auto colorId = colors[key];
 | 
				
			||||||
	  id->pal[colorId] = toGbaColor(key);
 | 
						  id->pal[colorId] = toGbaColor(key);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return err;
 | 
					
 | 
				
			||||||
 | 
						return imgDataBuff;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace nostalgia {
 | 
					namespace nostalgia {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ox::Error pngToGba(QString argInPath, int argTiles, int argBpp = -1);
 | 
					[[nodiscard]] std::vector<char> pngToGba(QString argInPath, int argTiles, int argBpp = -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,11 +14,18 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace nostalgia {
 | 
					namespace nostalgia {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[nodiscard]] static constexpr bool endsWith(std::string_view str, std::string_view ending) {
 | 
					[[nodiscard]] static constexpr bool endsWith(std::string_view str, std::string_view ending) {
 | 
				
			||||||
	return str.size() >= ending.size() && str.substr(str.size() - ending.size()) == ending;
 | 
						return str.size() >= ending.size() && str.substr(str.size() - ending.size()) == ending;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// stub for now
 | 
					/**
 | 
				
			||||||
 | 
					 * Convert path references to inodes to save space
 | 
				
			||||||
 | 
					 * @param buff buffer holding file
 | 
				
			||||||
 | 
					 * @return error
 | 
				
			||||||
 | 
					 * stub for now
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
ox::Error pathToInode(std::vector<char>*) {
 | 
					ox::Error pathToInode(std::vector<char>*) {
 | 
				
			||||||
	return OxError(0);
 | 
						return OxError(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -28,6 +35,34 @@ ox::Error toMetalClaw(std::vector<char>*) {
 | 
				
			|||||||
	return OxError(0);
 | 
						return OxError(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// claw file transformations are broken out because path to inode
 | 
				
			||||||
 | 
					// transformations need to be done after the copy to the new FS is complete
 | 
				
			||||||
 | 
					ox::Error transformClaw(ox::FileSystem32 *dest, std::string path) {
 | 
				
			||||||
 | 
						// copy
 | 
				
			||||||
 | 
						dest->ls(path.c_str(), [dest, path](const char *name, ox::InodeId_t) {
 | 
				
			||||||
 | 
							auto stat = dest->stat(path.c_str());
 | 
				
			||||||
 | 
							oxReturnError(stat.error);
 | 
				
			||||||
 | 
							if (stat.value.fileType == ox::FileType_Directory) {
 | 
				
			||||||
 | 
								const auto dir = path + name + '/';
 | 
				
			||||||
 | 
								oxReturnError(transformClaw(dest, dir));
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								// do transforms
 | 
				
			||||||
 | 
								if (endsWith(path, ".claw")) {
 | 
				
			||||||
 | 
									// load file
 | 
				
			||||||
 | 
									std::vector<char> buff(stat.value.size);
 | 
				
			||||||
 | 
									oxReturnError(dest->read(path.c_str(), buff.data(), buff.size()));
 | 
				
			||||||
 | 
									// do transformations
 | 
				
			||||||
 | 
									oxReturnError(pathToInode(&buff));
 | 
				
			||||||
 | 
									oxReturnError(toMetalClaw(&buff));
 | 
				
			||||||
 | 
									// write file to dest
 | 
				
			||||||
 | 
									oxReturnError(dest->write(path.c_str(), buff.data(), buff.size()));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return OxError(0);
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						return OxError(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ox::Error copy(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path) {
 | 
					ox::Error copy(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path) {
 | 
				
			||||||
	// copy
 | 
						// copy
 | 
				
			||||||
	src->ls(path.c_str(), [src, dest, path](const char *name, ox::InodeId_t) {
 | 
						src->ls(path.c_str(), [src, dest, path](const char *name, ox::InodeId_t) {
 | 
				
			||||||
@@ -38,16 +73,19 @@ ox::Error copy(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path)
 | 
				
			|||||||
			oxReturnError(dest->mkdir(dir.c_str()));
 | 
								oxReturnError(dest->mkdir(dir.c_str()));
 | 
				
			||||||
			oxReturnError(copy(src, dest, dir));
 | 
								oxReturnError(copy(src, dest, dir));
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			std::vector<char> buff(stat.value.size);
 | 
								std::vector<char> buff;
 | 
				
			||||||
			// load file
 | 
					 | 
				
			||||||
			oxReturnError(src->read(path.c_str(), buff.data(), buff.size()));
 | 
					 | 
				
			||||||
			// do transforms
 | 
								// do transforms
 | 
				
			||||||
			if (endsWith(path, ".claw")) {
 | 
								if (endsWith(path, ".png")) {
 | 
				
			||||||
				oxReturnError(pathToInode(&buff));
 | 
									// load file from full path and transform
 | 
				
			||||||
				oxReturnError(toMetalClaw(&buff));
 | 
					 | 
				
			||||||
			} else if (endsWith(path, ".png")) {
 | 
					 | 
				
			||||||
				const auto fullPath = src->basePath() + path;
 | 
									const auto fullPath = src->basePath() + path;
 | 
				
			||||||
				oxReturnError(pngToGba(fullPath.c_str(), 0, 0));
 | 
									buff = pngToGba(fullPath.c_str(), 0, 0);
 | 
				
			||||||
 | 
									if (!buff.size()) {
 | 
				
			||||||
 | 
										return OxError(1);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// load file
 | 
				
			||||||
 | 
									buff.resize(stat.value.size);
 | 
				
			||||||
 | 
									oxReturnError(src->read(path.c_str(), buff.data(), buff.size()));
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// write file to dest
 | 
								// write file to dest
 | 
				
			||||||
			oxReturnError(dest->write(path.c_str(), buff.data(), buff.size()));
 | 
								oxReturnError(dest->write(path.c_str(), buff.data(), buff.size()));
 | 
				
			||||||
@@ -58,3 +96,11 @@ ox::Error copy(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ox::Error pack(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path) {
 | 
				
			||||||
 | 
						oxReturnError(copy(src, dest, path));
 | 
				
			||||||
 | 
						oxReturnError(transformClaw(dest, path));
 | 
				
			||||||
 | 
						return OxError(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace nostalgia {
 | 
					namespace nostalgia {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ox::Error copy(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path = "/");
 | 
					ox::Error pack(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path = "/");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user