From ab2e6e5ea2bf59b2d8c7e0892348f941e6bba2c9 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Thu, 13 Apr 2017 04:38:59 -0500 Subject: [PATCH] Implement nost-pack tool --- src/common/bounds.cpp | 2 +- src/common/bounds.hpp | 7 +-- src/common/point.cpp | 2 +- src/common/point.hpp | 7 +-- src/core/core.cpp | 2 +- src/core/core.hpp | 2 +- src/core/gba/gba.hpp | 28 +++++++++ src/core/gba/gfx.cpp | 12 +--- src/core/gfx.hpp | 2 +- src/core/qt/gfx.cpp | 2 +- src/tools/CMakeLists.txt | 5 +- src/tools/pack.cpp | 124 ++++++++++++++++++++++++++++++++++++++- 12 files changed, 165 insertions(+), 30 deletions(-) create mode 100644 src/core/gba/gba.hpp diff --git a/src/common/bounds.cpp b/src/common/bounds.cpp index 9d5f8b25..ebb43441 100644 --- a/src/common/bounds.cpp +++ b/src/common/bounds.cpp @@ -7,7 +7,7 @@ */ #include "bounds.hpp" -namespace wombat { +namespace nostalgia { namespace common { Bounds::Bounds() { diff --git a/src/common/bounds.hpp b/src/common/bounds.hpp index f92119bc..adc9c230 100644 --- a/src/common/bounds.hpp +++ b/src/common/bounds.hpp @@ -5,12 +5,11 @@ * 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/. */ -#ifndef NOSTALGIA_COMMON_BOUNDS_HPP -#define NOSTALGIA_COMMON_BOUNDS_HPP +#pragma once #include "point.hpp" -namespace wombat { +namespace nostalgia { namespace common { class Bounds { @@ -40,5 +39,3 @@ class Bounds { } } - -#endif diff --git a/src/common/point.cpp b/src/common/point.cpp index 6750562f..098942a5 100644 --- a/src/common/point.cpp +++ b/src/common/point.cpp @@ -7,7 +7,7 @@ */ #include "point.hpp" -namespace wombat { +namespace nostalgia { namespace common { Point::Point() { diff --git a/src/common/point.hpp b/src/common/point.hpp index 63206382..c7e89b74 100644 --- a/src/common/point.hpp +++ b/src/common/point.hpp @@ -5,10 +5,9 @@ * 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/. */ -#ifndef NOSTALGIA_COMMON_POINT_HPP -#define NOSTALGIA_COMMON_POINT_HPP +#pragma once -namespace wombat { +namespace nostalgia { namespace common { class Point { @@ -58,5 +57,3 @@ class Point { } } - -#endif diff --git a/src/core/core.cpp b/src/core/core.cpp index 0f987afb..5b00ff84 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -11,7 +11,7 @@ namespace nostalgia { namespace core { -ox::std::Error init() { +ox::Error init() { auto err = initGfx(); return err; } diff --git a/src/core/core.hpp b/src/core/core.hpp index 5f803ee1..f56c0a3c 100644 --- a/src/core/core.hpp +++ b/src/core/core.hpp @@ -12,7 +12,7 @@ namespace nostalgia { namespace core { -ox::std::Error init(); +ox::Error init(); } } diff --git a/src/core/gba/gba.hpp b/src/core/gba/gba.hpp new file mode 100644 index 00000000..3bfe4265 --- /dev/null +++ b/src/core/gba/gba.hpp @@ -0,0 +1,28 @@ +/* + * Copyright 2016-2017 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/. + */ + +#pragma once + +namespace nostalgia { +namespace core { + +typedef struct { uint32_t data[8]; } Tile, Tile4; +// d-tile: double-sized tile (8bpp) +typedef struct { uint32_t data[16]; } Tile8; +// tile block: 32x16 tiles, 16x16 d-tiles +typedef unsigned short Pallete[256]; +typedef Tile CharBlock[512]; +typedef Tile8 CharBlock8[256]; + +struct GbaImageData { + Pallete pal; + uint8_t tiles[1]; +}; + +} +} diff --git a/src/core/gba/gfx.cpp b/src/core/gba/gfx.cpp index ae903b2b..4f511635 100644 --- a/src/core/gba/gfx.cpp +++ b/src/core/gba/gfx.cpp @@ -10,26 +10,18 @@ #include #include "addresses.hpp" #include "media.hpp" +#include "gba.hpp" #include "dirt.h" namespace nostalgia { namespace core { using namespace ox::fs; -using namespace ox::std; - -typedef struct { uint32_t data[8]; } Tile, Tile4; -// d-tile: double-sized tile (8bpp) -typedef struct { uint32_t data[16]; } Tile8; -// tile block: 32x16 tiles, 16x16 d-tiles -typedef struct { unsigned short data[256]; } Pallete; -typedef Tile CharBlock[512]; -typedef Tile8 CharBlock8[256]; #define TILE_ADDR ((CharBlock*) 0x06000000) #define TILE8_ADDR ((CharBlock8*) 0x06000000) -ox::std::Error initGfx() { +ox::Error initGfx() { /* Sprite Mode ----\ */ /* ---\| */ /* Background 0 -\|| */ diff --git a/src/core/gfx.hpp b/src/core/gfx.hpp index 157680a3..d6d6af48 100644 --- a/src/core/gfx.hpp +++ b/src/core/gfx.hpp @@ -12,7 +12,7 @@ namespace nostalgia { namespace core { -ox::std::Error initGfx(); +ox::Error initGfx(); } } diff --git a/src/core/qt/gfx.cpp b/src/core/qt/gfx.cpp index 5aad0858..8b7c08d0 100644 --- a/src/core/qt/gfx.cpp +++ b/src/core/qt/gfx.cpp @@ -11,7 +11,7 @@ namespace nostalgia { namespace core { -ox::std::Error initGfx() { +ox::Error initGfx() { return 0; } diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 5de07b64..9e4f481b 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -10,10 +10,11 @@ add_executable(nost-pack pack.cpp) target_link_libraries( nost-pack Qt5::Widgets - NostalgiaCore - ${OxStd_LIBRARY} ${OxClArgs_LIBRARY} ${OxFS_LIBRARY} + ${OxStd_LIBRARY} + NostalgiaCommon + NostalgiaCore ) set(CMAKE_INCLUDE_CURRENT_DIR OFF) diff --git a/src/tools/pack.cpp b/src/tools/pack.cpp index 4728bd54..0724e9db 100644 --- a/src/tools/pack.cpp +++ b/src/tools/pack.cpp @@ -6,10 +6,130 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include #include +#include +#include +#include #include +#include + +using namespace std; +using namespace ox; +using namespace ox::clargs; +using namespace ox::fs; +using namespace nostalgia::core; +using namespace nostalgia::common; + +uint8_t *loadFileBuff(QString path, ::size_t *sizeOut = nullptr) { + auto file = fopen(path.toUtf8(), "rb"); + if (file) { + fseek(file, 0, SEEK_END); + const auto size = ftell(file); + rewind(file); + auto buff = new uint8_t[size]; + auto itemsRead = fread(buff, size, 1, file); + fclose(file); + if (sizeOut) { + *sizeOut = itemsRead ? size : 0; + } + return buff; + } else { + return nullptr; + } +} + +uint16_t toGbaColor(QColor c) { + auto r = ((uint32_t) c.red()) >> 3; + auto g = ((uint32_t) c.green()) >> 3; + auto b = ((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) { + Error err = 0; + QString inPath = args.getString("img").c_str(); + QString fsPath = args.getString("fs").c_str(); + auto compact = args.getBool("c"); + QMap colors; + QImage src(inPath); + const auto imgDataBuffSize = sizeof(Pallete) + src.width() * src.height(); + uint8_t imgDataBuff[imgDataBuffSize]; + GbaImageData *id = (GbaImageData*) imgDataBuff; + int colorId = 0; + + if (!src.isNull()) { + + // copy pixels as color ids + for (int x = 0; x < src.colorCount(); x++) { + for (int y = 0; y < src.colorCount(); y++) { + auto destI = pointToIdx(src.width(), x, y); + auto c = src.pixel(x, y); + if (!colors.contains(c)) { + colors[c] = colorId; + colorId++; + } + ((uint8_t*) &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(fsPath, &fsBuffSize); + if (fsBuff && !err) { + auto fs = createFileSystem(fsBuff, fsBuffSize); + + if (fs) { + fs = expandCopyCleanup(fs, fs->size() + fs->spaceNeeded(imgDataBuffSize)); + fsBuff = fs->buff(); // update fsBuff pointer in case there is a new buff + err |= fs->write(1, imgDataBuff, imgDataBuffSize); + + if (compact) { + fs->resize(); + } + + auto fsFile = fopen(fsPath.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; + } + + delete fs; + } else { + err = 3; + } + } + + delete[] fsBuff; + } else { + err = 4; + } + + return err; +} int main(int argc, const char **args) { - QImage src("charset.png"); - return 0; + return run(ClArgs(argc, args)); }