1
0
mirror of https://github.com/ScrelliCopter/tmx2gba.git synced 2025-02-21 03:29:25 +11:00

Compare commits

3 Commits

Author SHA1 Message Date
6050224a65 uncringe comments somewhat 2023-09-15 14:14:04 +10:00
c351da76d1 Break out body of licence text 2023-09-15 14:14:04 +10:00
c65a607b61 option for building with asan 2023-09-15 14:14:04 +10:00
8 changed files with 67 additions and 143 deletions

View File

@@ -3,6 +3,7 @@ project(tmx2gba)
# Options # Options
option(TMX2GBA_DKP_INSTALL "Install into DEVKITPRO prefix" OFF) option(TMX2GBA_DKP_INSTALL "Install into DEVKITPRO prefix" OFF)
option(ASAN "Enable address sanitiser" OFF)
# C++11 & C99 # C++11 & C99
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
@@ -16,6 +17,11 @@ else()
add_compile_options(-Wall) add_compile_options(-Wall)
endif() endif()
if (ASAN)
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
add_link_options(-fsanitize=address -shared-libasan)
endif()
# Libraries # Libraries
add_subdirectory(ext/base64) add_subdirectory(ext/base64)
add_subdirectory(ext/miniz) add_subdirectory(ext/miniz)

17
COPYING.txt Normal file
View File

@@ -0,0 +1,17 @@
Copyright (C) 2015-2022 a dinosaur
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

View File

@@ -1,30 +1,9 @@
/* tmx2gba.cpp /* tmx2gba.cpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
Copyright (C) 2015-2022 a dinosaur
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "tmxreader.hpp" #include "tmxreader.hpp"
#include "tmxlayer.hpp" #include "tmxlayer.hpp"
#include "tmxobject.hpp" #include "tmxobject.hpp"
#include <iostream> #include <iostream>
#include <iomanip>
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <map> #include <map>
@@ -95,7 +74,7 @@ void ParseArgs(int argc, char** argv, Arguments& p)
bool CheckArgs(const Arguments& params) bool CheckArgs(const Arguments& params)
{ {
// Check my paranoia. // Check my paranoia
if (params.inPath.empty()) if (params.inPath.empty())
{ {
std::cerr << "No input file specified." << std::endl; std::cerr << "No input file specified." << std::endl;
@@ -235,7 +214,7 @@ int main(int argc, char** argv)
if (!CheckArgs(p)) if (!CheckArgs(p))
return -1; return -1;
// Object mappings. // Object mappings
std::map<std::string, uint32_t> objMapping; std::map<std::string, uint32_t> objMapping;
if (p.objExport) if (p.objExport)
{ {
@@ -262,7 +241,7 @@ int main(int argc, char** argv)
} }
} }
// Open & read input file. // Open & read input file
TmxReader tmx; TmxReader tmx;
std::ifstream fin(p.inPath); std::ifstream fin(p.inPath);
if (!fin.is_open()) if (!fin.is_open())
@@ -272,7 +251,7 @@ int main(int argc, char** argv)
} }
tmx.Open(fin); tmx.Open(fin);
// Get layers. // Get layers
if (tmx.GetLayerCount() == 0) if (tmx.GetLayerCount() == 0)
{ {
std::cerr << "No layers found." << std::endl; std::cerr << "No layers found." << std::endl;
@@ -294,7 +273,7 @@ int main(int argc, char** argv)
return -1; return -1;
} }
// Open output files. // Open output files
std::ofstream foutS(p.outPath + ".s"); std::ofstream foutS(p.outPath + ".s");
std::ofstream foutH(p.outPath + ".h"); std::ofstream foutH(p.outPath + ".h");
if (!foutS.is_open() || !foutH.is_open()) if (!foutS.is_open() || !foutH.is_open())
@@ -308,7 +287,7 @@ int main(int argc, char** argv)
if (slashPos != -1) if (slashPos != -1)
name = name.substr(slashPos + 1); name = name.substr(slashPos + 1);
// Write header guards. // Write header guards
std::string guard = "TMX2GBA_" + name; std::string guard = "TMX2GBA_" + name;
for (auto& c: guard) for (auto& c: guard)
c = static_cast<char>(toupper(c)); c = static_cast<char>(toupper(c));
@@ -319,7 +298,7 @@ int main(int argc, char** argv)
foutH << "#define " << name << "Height " << tmx.GetHeight() << std::endl; foutH << "#define " << name << "Height " << tmx.GetHeight() << std::endl;
foutH << std::endl; foutH << std::endl;
// Convert to GBA-friendly charmap data. // Convert to GBA-friendly charmap data
const uint32_t* gfxTiles = layerGfx->GetData(); const uint32_t* gfxTiles = layerGfx->GetData();
const uint32_t* palTiles = (layerPal == nullptr) ? nullptr : layerPal->GetData(); const uint32_t* palTiles = (layerPal == nullptr) ? nullptr : layerPal->GetData();
std::vector<uint16_t> charDat; std::vector<uint16_t> charDat;
@@ -336,7 +315,7 @@ int main(int argc, char** argv)
flags |= (read & TmxLayer::FLIP_HORZ) ? 0x4 : 0x0; flags |= (read & TmxLayer::FLIP_HORZ) ? 0x4 : 0x0;
flags |= (read & TmxLayer::FLIP_VERT) ? 0x8 : 0x0; flags |= (read & TmxLayer::FLIP_VERT) ? 0x8 : 0x0;
// Determine palette ID. // Determine palette ID
uint32_t idx = 0; uint32_t idx = 0;
if (palTiles != nullptr) if (palTiles != nullptr)
idx = tmx.LidFromGid((*palTiles++) & ~TmxLayer::FLIP_MASK); idx = tmx.LidFromGid((*palTiles++) & ~TmxLayer::FLIP_MASK);
@@ -347,7 +326,7 @@ int main(int argc, char** argv)
charDat.push_back(tile | (static_cast<uint16_t>(flags) << 8)); charDat.push_back(tile | (static_cast<uint16_t>(flags) << 8));
} }
// Save out charmap. // Write out charmap
foutH << "#define " << name << "TilesLen " << charDat.size() * 2 << std::endl; foutH << "#define " << name << "TilesLen " << charDat.size() * 2 << std::endl;
foutH << "extern const unsigned short " << name << "Tiles[" << charDat.size() << "];" << std::endl; foutH << "extern const unsigned short " << name << "Tiles[" << charDat.size() << "];" << std::endl;
foutH << std::endl; foutH << std::endl;
@@ -360,7 +339,7 @@ int main(int argc, char** argv)
WriteArray<uint16_t>(foutS, charDat); WriteArray<uint16_t>(foutS, charDat);
foutS << std::endl; foutS << std::endl;
// Convert collision map & save it out. // Convert collision map & write it out
if (layerCls != nullptr) if (layerCls != nullptr)
{ {
std::vector<uint8_t> vucCollisionDat; std::vector<uint8_t> vucCollisionDat;
@@ -373,7 +352,7 @@ int main(int argc, char** argv)
vucCollisionDat.push_back(ucTile); vucCollisionDat.push_back(ucTile);
} }
// Try to nicely append "_collision" to the output name. // Try to nicely append "_collision" to the output name
std::string path; std::string path;
size_t extPos = p.outPath.find_last_of('.'); size_t extPos = p.outPath.find_last_of('.');
if (extPos != std::string::npos) if (extPos != std::string::npos)
@@ -381,7 +360,7 @@ int main(int argc, char** argv)
else else
path = p.outPath + "_collision"; path = p.outPath + "_collision";
// Save it out. // Write collision
foutH << "#define " << name << "CollisionLen " << vucCollisionDat.size() << std::endl; foutH << "#define " << name << "CollisionLen " << vucCollisionDat.size() << std::endl;
foutH << "extern const unsigned char " << name << "Collision[" << vucCollisionDat.size() << "];" << std::endl; foutH << "extern const unsigned char " << name << "Collision[" << vucCollisionDat.size() << "];" << std::endl;
foutH << std::endl; foutH << std::endl;
@@ -413,7 +392,7 @@ int main(int argc, char** argv)
objDat.push_back((int)(y * 256.0f)); objDat.push_back((int)(y * 256.0f));
} }
// Save it out. // Write objects
foutH << "#define " << name << "ObjCount " << objDat.size() / 3 << std::endl; foutH << "#define " << name << "ObjCount " << objDat.size() / 3 << std::endl;
foutH << "#define " << name << "ObjdatLen " << objDat.size() * sizeof(int) << std::endl; foutH << "#define " << name << "ObjdatLen " << objDat.size() * sizeof(int) << std::endl;
foutH << "extern const unsigned int " << name << "Objdat[" << objDat.size() << "];" << std::endl; foutH << "extern const unsigned int " << name << "Objdat[" << objDat.size() << "];" << std::endl;

View File

@@ -1,24 +1,4 @@
/* tmxlayer.cpp /* tmxlayer.hpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
Copyright (C) 2015-2022 a dinosaur
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef TMXLAYER_H #ifndef TMXLAYER_H
#define TMXLAYER_H #define TMXLAYER_H

View File

@@ -1,24 +1,4 @@
/* tmxobject.cpp /* tmxobject.cpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
Copyright (C) 2015-2022 a dinosaur
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef TMXOBJECT_H #ifndef TMXOBJECT_H
#define TMXOBJECT_H #define TMXOBJECT_H

View File

@@ -1,24 +1,4 @@
/* tmxreader.cpp /* tmxreader.cpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
Copyright (C) 2015-2022 a dinosaur
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "tmxreader.hpp" #include "tmxreader.hpp"
#include "tmxtileset.hpp" #include "tmxtileset.hpp"
@@ -34,12 +14,12 @@
TmxReader::~TmxReader() TmxReader::~TmxReader()
{ {
// Delete old tilesets. // Delete old tilesets
for (auto pTileset : mTilesets) for (auto pTileset : mTilesets)
delete pTileset; delete pTileset;
mTilesets.clear(); mTilesets.clear();
// Delete old layers. // Delete old layers
for (auto pLay : mLayers) for (auto pLay : mLayers)
delete pLay; delete pLay;
mLayers.clear(); mLayers.clear();
@@ -57,10 +37,10 @@ bool TmxReader::DecodeMap(uint32_t* aOut, size_t aOutSize, const std::string& aB
std::size_t endOff = std::distance(end, aBase64Dat.rend()) - begOff; std::size_t endOff = std::distance(end, aBase64Dat.rend()) - begOff;
auto trimmed = aBase64Dat.substr(begOff, endOff); auto trimmed = aBase64Dat.substr(begOff, endOff);
// Decode base64 string. // Decode base64 string
std::string decoded = base64_decode(trimmed); std::string decoded = base64_decode(trimmed);
// Decompress compressed data. // Decompress compressed data
auto dstSize = static_cast<mz_ulong>(aOutSize); auto dstSize = static_cast<mz_ulong>(aOutSize);
int res = uncompress( int res = uncompress(
(unsigned char*)aOut, (unsigned char*)aOut,
@@ -82,17 +62,17 @@ void TmxReader::ReadTileset(rapidxml::xml_node<>* aXNode)
const char* source = ""; const char* source = "";
uint32_t firstGid = 0; uint32_t firstGid = 0;
// Read name. // Read name
xAttrib = aXNode->first_attribute("name"); xAttrib = aXNode->first_attribute("name");
if (xAttrib != nullptr) if (xAttrib != nullptr)
name = xAttrib->value(); name = xAttrib->value();
// Read source. // Read source
xAttrib = aXNode->first_attribute("source"); xAttrib = aXNode->first_attribute("source");
if (xAttrib != nullptr) if (xAttrib != nullptr)
source = xAttrib->value(); source = xAttrib->value();
// Read first global ID. // Read first global ID
xAttrib = aXNode->first_attribute("firstgid"); xAttrib = aXNode->first_attribute("firstgid");
if (xAttrib != nullptr) if (xAttrib != nullptr)
firstGid = std::stoul(xAttrib->value()); firstGid = std::stoul(xAttrib->value());
@@ -108,26 +88,26 @@ void TmxReader::ReadLayer(rapidxml::xml_node<>* aXNode)
int height = 0; int height = 0;
uint32_t* tileDat = nullptr; uint32_t* tileDat = nullptr;
// Read name. // Read name
xAttrib = aXNode->first_attribute("name"); xAttrib = aXNode->first_attribute("name");
if (xAttrib != nullptr) if (xAttrib != nullptr)
name = xAttrib->value(); name = xAttrib->value();
// Read width. // Read width
xAttrib = aXNode->first_attribute("width"); xAttrib = aXNode->first_attribute("width");
if (xAttrib != nullptr) if (xAttrib != nullptr)
width = std::stoi(xAttrib->value()); width = std::stoi(xAttrib->value());
// Read height. // Read height
xAttrib = aXNode->first_attribute("height"); xAttrib = aXNode->first_attribute("height");
if (xAttrib != nullptr) if (xAttrib != nullptr)
height = std::stoi(xAttrib->value()); height = std::stoi(xAttrib->value());
// Read tile data. // Read tile data
auto xData = aXNode->first_node("data"); auto xData = aXNode->first_node("data");
if (xData != nullptr) if (xData != nullptr)
{ {
// TODO: don't assume base64 & zlib. // TODO: don't assume base64 & zlib
tileDat = new uint32_t[width * height]; tileDat = new uint32_t[width * height];
if (!DecodeMap(tileDat, width * height * sizeof(uint32_t), std::string(xData->value()))) if (!DecodeMap(tileDat, width * height * sizeof(uint32_t), std::string(xData->value())))
{ {
@@ -151,17 +131,17 @@ void TmxReader::ReadObjects(rapidxml::xml_node<>* aXNode)
float x = 0.0f; float x = 0.0f;
float y = 0.0f; float y = 0.0f;
// Read name. // Read name
xAttrib = xNode->first_attribute("name"); xAttrib = xNode->first_attribute("name");
if (xAttrib != nullptr) if (xAttrib != nullptr)
name = xAttrib->value(); name = xAttrib->value();
// Read X pos. // Read X pos
xAttrib = xNode->first_attribute("x"); xAttrib = xNode->first_attribute("x");
if (xAttrib != nullptr) if (xAttrib != nullptr)
x = std::stof(xAttrib->value()); x = std::stof(xAttrib->value());
// Read Y pos. // Read Y pos
xAttrib = xNode->first_attribute("y"); xAttrib = xNode->first_attribute("y");
if (xAttrib != nullptr) if (xAttrib != nullptr)
y = std::stof(xAttrib->value()); y = std::stof(xAttrib->value());
@@ -172,44 +152,44 @@ void TmxReader::ReadObjects(rapidxml::xml_node<>* aXNode)
void TmxReader::Open(std::istream& aIn) void TmxReader::Open(std::istream& aIn)
{ {
// Delete old tilesets. // Delete old tilesets
for (auto tileset : mTilesets) for (auto tileset : mTilesets)
delete tileset; delete tileset;
mTilesets.clear(); mTilesets.clear();
// Delete old layers. // Delete old layers
for (auto layer : mLayers) for (auto layer : mLayers)
delete layer; delete layer;
mLayers.clear(); mLayers.clear();
mGidTable.clear(); mGidTable.clear();
// Read string into a buffer. // Read string into a buffer
std::stringstream buf; std::stringstream buf;
buf << aIn.rdbuf(); buf << aIn.rdbuf();
std::string strXml = buf.str(); std::string strXml = buf.str();
buf.clear(); buf.clear();
// Parse document. // Parse document
rapidxml::xml_document<> xDoc; rapidxml::xml_document<> xDoc;
xDoc.parse<0>((char*)strXml.c_str()); xDoc.parse<0>((char*)strXml.c_str());
// Get map node. // Get map node
auto xMap = xDoc.first_node("map"); auto xMap = xDoc.first_node("map");
if (xMap == nullptr) if (xMap == nullptr)
return; return;
// Read map attribs. // Read map attribs
rapidxml::xml_attribute<>* xAttrib = nullptr; rapidxml::xml_attribute<>* xAttrib = nullptr;
if ((xAttrib = xMap->first_attribute("width")) != nullptr) if ((xAttrib = xMap->first_attribute("width")) != nullptr)
mWidth = std::stoi(xAttrib->value()); mWidth = std::stoi(xAttrib->value());
if ((xAttrib = xMap->first_attribute("height")) != nullptr) if ((xAttrib = xMap->first_attribute("height")) != nullptr)
mHeight = std::stoi(xAttrib->value()); mHeight = std::stoi(xAttrib->value());
// Read nodes. // Read nodes
for (auto xNode = xMap->first_node(); xNode != nullptr; xNode = xNode->next_sibling()) for (auto xNode = xMap->first_node(); xNode != nullptr; xNode = xNode->next_sibling())
{ {
// Read layer nodes. // Read layer nodes
if (strcmp(xNode->name(), "layer") == 0) if (strcmp(xNode->name(), "layer") == 0)
ReadLayer(xNode); ReadLayer(xNode);
else else
@@ -220,7 +200,7 @@ void TmxReader::Open(std::istream& aIn)
ReadObjects(xNode); ReadObjects(xNode);
} }
// Generate global id table. // Generate global id table
for (auto tileset : mTilesets) for (auto tileset : mTilesets)
mGidTable.push_back(tileset->GetFirstGid()); mGidTable.push_back(tileset->GetFirstGid());
std::sort(mGidTable.rbegin(), mGidTable.rend()); std::sort(mGidTable.rbegin(), mGidTable.rend());

View File

@@ -1,3 +1,5 @@
/* tmxreader.hpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
#ifndef TMXREADER_H #ifndef TMXREADER_H
#define TMXREADER_H #define TMXREADER_H

View File

@@ -1,24 +1,4 @@
/* tmxtileset.cpp /* tmxtileset.hpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
Copyright (C) 2015-2022 a dinosaur
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef TMXTILESET_H #ifndef TMXTILESET_H
#define TMXTILESET_H #define TMXTILESET_H