diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1862ee3..7a5161b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ add_executable(tmx2gba tmxobject.hpp tmxreader.hpp tmxreader.cpp tmxtileset.hpp - swriter.hpp + swriter.hpp swriter.cpp headerwriter.hpp headerwriter.cpp tmx2gba.cpp) diff --git a/src/swriter.cpp b/src/swriter.cpp new file mode 100644 index 0000000..1b468de --- /dev/null +++ b/src/swriter.cpp @@ -0,0 +1,163 @@ +/* swwriter.cpp - Copyright (C) 2024 a dinosaur (zlib, see COPYING.txt) */ + +#include "swriter.hpp" +#include +#include + +#define GNU_STYLE 0 +#define MASM_STYLE 1 + +#define HEX_STYLE GNU_STYLE + + +static inline constexpr char HexU(uint8_t h) { return "0123456789ABCDEF"[h >> 4]; } +static inline constexpr char HexL(uint8_t l) { return "0123456789ABCDEF"[l & 15]; } + +#if HEX_STYLE == GNU_STYLE +template static void CHex(std::ostream& s, T x); +template <> void CHex(std::ostream& s, uint8_t x) +{ + if (x > 9) s << "0x"; + if (x > 15) s << HexU(x); + s << HexL(x); +} +template <> void CHex(std::ostream& s, uint16_t x) +{ + if (x > 9) s << "0x"; + if (x > 4095) s << HexU(static_cast(x >> 8)); + if (x > 255) s << HexL(static_cast(x >> 8)); + if (x > 15) s << HexU(static_cast(x)); + s << HexL(static_cast(x)); +} +template <> void CHex(std::ostream& s, uint32_t x) +{ + if (x > 9) s << "0x"; + if (x > 0xFFFFFFF) s << HexU(static_cast(x >> 24)); + if (x > 0xFFFFFF) s << HexL(static_cast(x >> 24)); + if (x > 0xFFFFF) s << HexU(static_cast(x >> 16)); + if (x > 65535) s << HexL(static_cast(x >> 16)); + if (x > 4095) s << HexU(static_cast(x >> 8)); + if (x > 255) s << HexL(static_cast(x >> 8)); + if (x > 15) s << HexU(static_cast(x)); + s << HexL(static_cast(x)); +} +#elif HEX_STYLE == MASM_STYLE +template static void MHex(std::ostream& s, T x); +template <> void MHex(std::ostream& s, uint8_t x) +{ + if (x > 159) s << "0"; + if (x > 15) s << HexU(x); else if (x > 9) s << "0"; + s << HexL(x); + if (x > 9) s << "h"; +} +template <> void MHex(std::ostream& s, uint16_t x) +{ + if (x > 40959) s << "0"; + if (x > 4095) s << HexU(static_cast(x >> 8)); else if (x > 2559) s << "0"; + if (x > 255) s << HexL(static_cast(x >> 8)); else if (x > 159) s << "0"; + if (x > 15) s << HexU(static_cast(x)); else if (x > 9) s << "0"; + s << HexL(static_cast(x)); + if (x > 9) s << "h"; +} +template <> void MHex(std::ostream& s, uint32_t x) +{ + if (x > 0x9FFFFFFF) s << "0"; + if (x > 0xFFFFFFF) s << HexU(static_cast(x >> 24)); else if (x > 0x9FFFFFF) s << "0"; + if (x > 0xFFFFFF) s << HexL(static_cast(x >> 24)); else if (x > 0x9FFFFF) s << "0"; + if (x > 0xFFFFF) s << HexU(static_cast(x >> 16)); else if (x > 655359) s << "0"; + if (x > 65535) s << HexL(static_cast(x >> 16)); else if (x > 40959) s << "0"; + if (x > 4095) s << HexU(static_cast(x >> 8)); else if (x > 2559) s << "0"; + if (x > 255) s << HexL(static_cast(x >> 8)); else if (x > 159) s << "0"; + if (x > 15) s << HexU(static_cast(x)); else if (x > 9) s << "0"; + s << HexL(static_cast(x)); + if (x > 9) s << "h"; +} +#else +# error "Unknown hex style" +#endif + + +template static constexpr const std::string_view DataType(); +template <> constexpr const std::string_view DataType() { return ".byte"; } +template <> constexpr const std::string_view DataType() { return ".hword"; } +template <> constexpr const std::string_view DataType() { return ".word"; } + +template +static void WriteArrayDetail(std::ostream& s, const I beg, const I end, int perCol) +{ + typedef typename std::iterator_traits::value_type Element; + + int col = 0; + for (auto it = beg;;) + { + if (col == 0) + s << "\t" << DataType() << " "; + + const Element e = *it; +#if HEX_STYLE == MASM_STYLE + MHex(s, e); +#elif HEX_STYLE == GNU_STYLE + CHex(s, e); +#endif + + if (++it == end) + break; + + if (++col < perCol) + { + s << ","; + } + else + { + s << std::endl; + col = 0; + } + } + s << std::endl; +} + + +void SWriter::WriteSymbol(const std::string_view suffix) +{ + if (writes++ != 0) + stream << std::endl; + stream << "\t.section .rodata" << std::endl; + stream << "\t.align 2" << std::endl; + stream << "\t.global " << mName << suffix << std::endl; + stream << "\t.hidden " << mName << suffix << std::endl; + stream << mName << suffix << ":" << std::endl; +} + +void SWriter::WriteArray(const std::string_view suffix, std::span data, int numCols) +{ + WriteSymbol(suffix); + WriteArrayDetail(stream, data.begin(), data.end(), numCols); +} + +void SWriter::WriteArray(const std::string_view suffix, std::span data, int numCols) +{ + WriteSymbol(suffix); + WriteArrayDetail(stream, data.begin(), data.end(), numCols); +} + +void SWriter::WriteArray(const std::string_view suffix, std::span data, int numCols) +{ + WriteSymbol(suffix); + WriteArrayDetail(stream, data.begin(), data.end(), numCols); +} + + +SWriter::~SWriter() +{ + if (stream.is_open()) + { + stream.close(); + } +} + +bool SWriter::Open(const std::filesystem::path& path, const std::string_view name) +{ + mName = name; + stream.open(path); + return stream.is_open(); +} diff --git a/src/swriter.hpp b/src/swriter.hpp index 186d169..e261027 100644 --- a/src/swriter.hpp +++ b/src/swriter.hpp @@ -1,4 +1,4 @@ -/* swwriter.hpp - Copyright (C) 2015-2024 a dinosaur (zlib, see COPYING.txt) */ +/* swwriter.hpp - Copyright (C) 2024 a dinosaur (zlib, see COPYING.txt) */ #ifndef SWRITER_HPP #define SWRITER_HPP @@ -7,83 +7,26 @@ #include #include #include +#include #include -#include - -namespace GccIsDumb -{ - template constexpr const char* DatType(); - template <> constexpr const char* DatType() { return ".byte"; } - template <> constexpr const char* DatType() { return ".hword"; } - template <> constexpr const char* DatType() { return ".word"; } -} +#include class SWriter { std::ofstream stream; + std::string mName; int writes = 0; - template - static void WriteArray(std::ostream& aOut, const std::vector& aDat, int aPerCol = 16) - { - int col = 0; - - aOut.setf(std::ios::hex, std::ios::basefield); - aOut.setf(std::ios::showbase); - - size_t i = 0; - for (T element : aDat) - { - if (col == 0) - aOut << "\t" << GccIsDumb::DatType() << " "; - - aOut << std::hex << static_cast(element); - - if (i < aDat.size() - 1) - { - if (++col < aPerCol) - { - aOut << ","; - } - else - { - aOut << "" << std::endl; - col = 0; - } - } - - ++i; - } - } + void WriteSymbol(const std::string_view suffix); public: - [[nodiscard]] bool Open(const std::filesystem::path& path) - { - stream.open(path); - return stream.is_open(); - } + ~SWriter(); - ~SWriter() - { - if (stream.is_open()) - { - stream.close(); - } - } + bool Open(const std::filesystem::path& path, const std::string_view name); - template - void WriteArray(const std::string_view name, T data) - { - if (writes++ != 0) - stream << std::endl; - stream << "\t.section .rodata" << std::endl; - stream << "\t.align 2" << std::endl; - stream << "\t.global " << name << "Tiles" << std::endl; - stream << "\t.hidden " << name << "Tiles" << std::endl; - stream << name << "Tiles" << ":" << std::endl; - WriteArray(stream, data); - stream << std::endl; - } + void WriteArray(const std::string_view suffix, std::span data, int numCols = 16); + void WriteArray(const std::string_view suffix, std::span data, int numCols = 16); + void WriteArray(const std::string_view suffix, std::span data, int numCols = 16); }; #endif//SWRITER_HPP diff --git a/src/tmx2gba.cpp b/src/tmx2gba.cpp index e82ed4e..392fdd2 100644 --- a/src/tmx2gba.cpp +++ b/src/tmx2gba.cpp @@ -204,7 +204,7 @@ int main(int argc, char** argv) // Open output files SWriter outS; HeaderWriter outH; - if (!outS.Open(p.outPath + ".s")) + if (!outS.Open(p.outPath + ".s", name)) { std::cerr << "Failed to create output file \"" << p.outPath << ".s\"."; return 1; @@ -219,13 +219,13 @@ int main(int argc, char** argv) const uint32_t* gfxTiles = layerGfx->GetData(); const uint32_t* palTiles = (layerPal == nullptr) ? nullptr : layerPal->GetData(); std::vector charDat; - size_t numTiles = static_cast(layerGfx->GetWidth()) * static_cast(layerGfx->GetHeight()); + const size_t numTiles = static_cast(layerGfx->GetWidth()) * static_cast(layerGfx->GetHeight()); charDat.reserve(numTiles); for (size_t i = 0; i < numTiles; ++i) { uint32_t read = (*gfxTiles++); - uint16_t tile = std::max(0, tmx.LidFromGid(read & ~TmxLayer::FLIP_MASK) + p.offset); + uint16_t tile = std::max(0, static_cast(tmx.LidFromGid(read & ~TmxLayer::FLIP_MASK)) + p.offset); uint8_t flags = 0x0; // Get flipped! @@ -271,7 +271,7 @@ int main(int argc, char** argv) // Write collision outH.WriteCollision(collisionDat); - outS.WriteArray("Collision", collisionDat); + outS.WriteArray("Collision", collisionDat, 32); } if (!p.objMappings.empty())