[nostalgia] Add new pack library to bundle project into OxFS

This commit is contained in:
Gary Talent 2019-03-30 17:06:22 -05:00
parent 941d714630
commit 6baa9a251c
5 changed files with 232 additions and 0 deletions

View File

@ -0,0 +1,24 @@
add_library(
Pack SHARED
imgconv.cpp
pack.cpp
)
target_link_libraries(
Pack
Qt5::Widgets
OxClArgs
OxFS
OxStd
OxMetalClaw
NostalgiaCommon
NostalgiaCore
)
install(
TARGETS
Pack
LIBRARY DESTINATION
${NOSTALGIA_DIST_LIB}/nostalgia
)

View File

@ -0,0 +1,113 @@
/*
* Copyright 2015 - 2019 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <QColor>
#include <QImage>
#include <QMap>
#include <nostalgia/core/gba/gba.hpp>
#include <nostalgia/core/core.hpp>
#include "imgconv.hpp"
namespace nostalgia {
namespace {
[[nodiscard]] uint16_t toGbaColor(QColor c) {
const auto r = static_cast<uint32_t>(c.red()) >> 3;
const auto g = static_cast<uint32_t>(c.green()) >> 3;
const auto b = static_cast<uint32_t>(c.blue()) >> 3;
return (r << 10) | (g << 5) | (b << 0);
}
[[nodiscard]] 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;
}
}
[[nodiscard]] static int countColors(const QImage &img, int argTiles) {
QMap<QRgb, bool> colors;
// copy pixels as color ids
for (int x = 0; x < img.width(); x++) {
for (int y = 0; y < img.height(); y++) {
auto destI = pointToIdx(img.width(), x, y);
if (destI <= argTiles * 64) {
auto c = img.pixel(x, y);
// assign color a color id for the palette
if (!colors.contains(c)) {
colors[c] = true;
}
}
}
}
return colors.size();
}
ox::Error pngToGba(QString argInPath, int argTiles, int argBpp) {
ox::Error err = 0;
QImage src(argInPath);
if (argTiles == 0) {
argTiles = (src.width() * src.height()) / 64;
}
if (argBpp != 4 && argBpp != 8) {
argBpp = countColors(src, argTiles) > 16 ? 8 : 4;
}
QMap<QRgb, int> colors;
const auto imgDataBuffSize = sizeof(core::GbaImageData) + 1 + argTiles * 64;
auto imgDataBuff = std::make_unique<uint8_t[]>(imgDataBuffSize);
memset(imgDataBuff.get(), 0, imgDataBuffSize);
auto id = reinterpret_cast<core::GbaImageData*>(imgDataBuff.get());
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);
}
return err;
}
}

View File

@ -0,0 +1,18 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <QString>
#include <ox/std/error.hpp>
#include <ox/std/types.hpp>
namespace nostalgia {
ox::Error pngToGba(QString argInPath, int argTiles, int argBpp = -1);
}

View File

@ -0,0 +1,60 @@
/*
* Copyright 2015 - 2019 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <string_view>
#include <vector>
#include "imgconv.hpp"
#include "pack.hpp"
namespace nostalgia {
[[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;
}
// stub for now
ox::Error pathToInode(std::vector<char> *buff) {
return OxError(0);
}
// stub for now
ox::Error toMetalClaw(std::vector<char> *buff) {
return OxError(0);
}
ox::Error copy(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path) {
// copy
src->ls(path.c_str(), [src, dest, path](const char *name, ox::InodeId_t inode) {
auto stat = src->stat(path.c_str());
oxReturnError(stat.error);
if (stat.value.fileType == ox::FileType_Directory) {
const auto dir = path + name + '/';
oxReturnError(dest->mkdir(dir.c_str()));
oxReturnError(copy(src, dest, dir));
} else {
std::vector<char> buff(stat.value.size);
// load file
oxReturnError(src->read(path.c_str(), buff.data(), buff.size()));
// do transforms
if (endsWith(path, ".claw")) {
oxReturnError(pathToInode(&buff));
oxReturnError(toMetalClaw(&buff));
} else if (endsWith(path, ".png")) {
const auto fullPath = src->basePath() + path;
oxReturnError(pngToGba(fullPath.c_str(), 0, 0));
}
// write file to dest
oxReturnError(dest->write(path.c_str(), buff.data(), buff.size()));
}
return OxError(0);
});
return OxError(0);
}
}

View File

@ -0,0 +1,17 @@
/*
* Copyright 2015 - 2018 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <string>
#include <ox/fs/fs.hpp>
namespace nostalgia {
ox::Error copy(ox::PassThroughFS *src, ox::FileSystem32 *dest, std::string path = "/");
}