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

7 Commits

11 changed files with 164 additions and 164 deletions

37
.github/workflows/cmake.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: CMake
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}

View File

@@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project(tmx2gba)
cmake_minimum_required(VERSION "3.5" FATAL_ERROR)
project(tmx2gba VERSION "0.3")
# Options
option(TMX2GBA_DKP_INSTALL "Install into DEVKITPRO prefix" OFF)
option(ASAN "Enable address sanitiser" OFF)
# C++11 & C99
set(CMAKE_CXX_STANDARD 11)
@@ -13,6 +17,11 @@ else()
add_compile_options(-Wall)
endif()
if (ASAN)
add_compile_options(-fsanitize=address -fno-omit-frame-pointer)
add_link_options(-fsanitize=address -shared-libasan)
endif()
# Libraries
add_subdirectory(ext/base64)
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

@@ -20,6 +20,7 @@ tmx2gba [-h] [-r offset] [-lyc name] [-p 0-15] <-i inpath> <-o outpath>
| Command | Required | Notes |
|--------------|----------|-----------------------------------------------------------------------|
| -h | N/A | Display help & command info. |
| -v | No | Display version & quit. |
| -l (name) | No | Name of layer to use (default first layer in TMX). |
| -y (name) | No | Layer for palette mappings. |
| -c (name) | No | Output a separate 8bit collision map of the specified layer. |
@@ -35,13 +36,27 @@ tmx2gba [-h] [-r offset] [-lyc name] [-p 0-15] <-i inpath> <-o outpath>
Dependencies for building are CMake 3.x and a C++11 compliant compiler,
all other dependencies are in-tree so you should be able to build with:
```bash
cmake -B build
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -C build -j$(nproc --all)
```
Optionally, to make it convenient for my dkp projects:
Optionally, you may install it to use it system wide:
```bash
sudo cp tmx2gba $DEVKITPRO/tools/bin/tmx2gba
sudo cmake --install build
```
Which will copy the tmx2gba executable to /usr/local/bin/tmx2gba by default,
if you prefer to use /usr for some reason you may specify a prefix like so:
```bash
sudo cmake --install build --prefix /usr
```
If you're a devkitPro user and would prefer to keep all your development tools compartmentalised
you may optionally install to the tools directory with the `TMX2GBA_DKP_INSTALL` option (OFF by default).
The build scripts will respect your `DEVKITPRO` environment variable but if not set will install to
`/opt/devkitpro/tools/bin/tmx2gba` directly, the `--prefix` argument has no effect in this mode.
```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release -DTMX2GBA_DKP_INSTALL:BOOL=ON
cmake --build build
sudo cmake --install build
```
### Todo list ###
@@ -58,7 +73,7 @@ sudo cp tmx2gba $DEVKITPRO/tools/bin/tmx2gba
[ultragetopt](https://github.com/kevinoid/ultragetopt) is licensed under the MIT license.
```
Copyright (C) 2015-2022 a dinosaur
Copyright (C) 2015-2023 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

View File

@@ -9,3 +9,14 @@ target_link_libraries(tmx2gba
External::miniz
External::rapidxml
External::ultragetopt)
if (TMX2GBA_DKP_INSTALL)
if (DEFINED ENV{DEVKITPRO})
set(TMX2GBA_INSTALL_DESTINATION "$ENV{DEVKITPRO}/tools/bin")
else()
set(TMX2GBA_INSTALL_DESTINATION /opt/devkitpro/tools/bin)
endif()
else()
set(TMX2GBA_INSTALL_DESTINATION bin)
endif()
install(TARGETS tmx2gba RUNTIME DESTINATION "${TMX2GBA_INSTALL_DESTINATION}")

View File

@@ -1,30 +1,9 @@
/* tmx2gba.cpp
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.
*/
/* tmx2gba.cpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
#include "tmxreader.hpp"
#include "tmxlayer.hpp"
#include "tmxobject.hpp"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <map>
@@ -36,8 +15,10 @@
const std::string helpUsage = "Usage: tmx2gba [-h] [-f file] [-r offset] [-lyc name] [-p 0-15] [-m name;id] <-i inpath> <-o outpath>";
const std::string helpShort = "Run 'tmx2gba -h' to view all available options.";
const std::string versionStr = "tmx2gba version 0.3, (c) 2015-2022 a dinosaur";
const std::string helpFull = R"(
-h ------------ Display this help & command info.
-v ------------ Display version & quit.
-l <name> ----- Name of layer to use (default first layer in TMX).
-y <name> ----- Layer for palette mappings.
-c <name> ----- Output a separate 8bit collision map of the specified layer.
@@ -50,7 +31,7 @@ const std::string helpFull = R"(
struct Arguments
{
bool help = false;
bool help = false, showVersion = false;
std::string inPath, outPath;
std::string layer, collisionlay, paletteLay;
std::string flagFile;
@@ -64,13 +45,16 @@ void ParseArgs(int argc, char** argv, Arguments& p)
{
int opt;
optreset = 1;
while ((opt = getopt(argc, argv, "hr:l:c:p:y:m:i:o:f:")) > 0)
while ((opt = getopt(argc, argv, "hvr:l:c:p:y:m:i:o:f:")) > 0)
{
switch (opt)
{
case ('h'):
p.help = true;
return;
case ('v'):
p.showVersion = true;
return;
case ('l'): p.layer = optarg; break;
case ('c'): p.collisionlay = optarg; break;
@@ -95,7 +79,7 @@ void ParseArgs(int argc, char** argv, Arguments& p)
bool CheckArgs(const Arguments& params)
{
// Check my paranoia.
// Check my paranoia
if (params.inPath.empty())
{
std::cerr << "No input file specified." << std::endl;
@@ -167,6 +151,11 @@ int main(int argc, char** argv)
std::cout << helpUsage << std::endl << helpFull << std::endl;
return 0;
}
if (p.showVersion)
{
std::cout << versionStr << std::endl;
return 0;
}
if (!p.flagFile.empty())
{
@@ -235,7 +224,7 @@ int main(int argc, char** argv)
if (!CheckArgs(p))
return -1;
// Object mappings.
// Object mappings
std::map<std::string, uint32_t> objMapping;
if (p.objExport)
{
@@ -262,7 +251,7 @@ int main(int argc, char** argv)
}
}
// Open & read input file.
// Open & read input file
TmxReader tmx;
std::ifstream fin(p.inPath);
if (!fin.is_open())
@@ -272,7 +261,7 @@ int main(int argc, char** argv)
}
tmx.Open(fin);
// Get layers.
// Get layers
if (tmx.GetLayerCount() == 0)
{
std::cerr << "No layers found." << std::endl;
@@ -294,7 +283,7 @@ int main(int argc, char** argv)
return -1;
}
// Open output files.
// Open output files
std::ofstream foutS(p.outPath + ".s");
std::ofstream foutH(p.outPath + ".h");
if (!foutS.is_open() || !foutH.is_open())
@@ -308,7 +297,7 @@ int main(int argc, char** argv)
if (slashPos != -1)
name = name.substr(slashPos + 1);
// Write header guards.
// Write header guards
std::string guard = "TMX2GBA_" + name;
for (auto& c: guard)
c = static_cast<char>(toupper(c));
@@ -319,7 +308,7 @@ int main(int argc, char** argv)
foutH << "#define " << name << "Height " << tmx.GetHeight() << 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* palTiles = (layerPal == nullptr) ? nullptr : layerPal->GetData();
std::vector<uint16_t> charDat;
@@ -336,7 +325,7 @@ int main(int argc, char** argv)
flags |= (read & TmxLayer::FLIP_HORZ) ? 0x4 : 0x0;
flags |= (read & TmxLayer::FLIP_VERT) ? 0x8 : 0x0;
// Determine palette ID.
// Determine palette ID
uint32_t idx = 0;
if (palTiles != nullptr)
idx = tmx.LidFromGid((*palTiles++) & ~TmxLayer::FLIP_MASK);
@@ -347,7 +336,7 @@ int main(int argc, char** argv)
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 << "extern const unsigned short " << name << "Tiles[" << charDat.size() << "];" << std::endl;
foutH << std::endl;
@@ -360,7 +349,7 @@ int main(int argc, char** argv)
WriteArray<uint16_t>(foutS, charDat);
foutS << std::endl;
// Convert collision map & save it out.
// Convert collision map & write it out
if (layerCls != nullptr)
{
std::vector<uint8_t> vucCollisionDat;
@@ -373,7 +362,7 @@ int main(int argc, char** argv)
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;
size_t extPos = p.outPath.find_last_of('.');
if (extPos != std::string::npos)
@@ -381,7 +370,7 @@ int main(int argc, char** argv)
else
path = p.outPath + "_collision";
// Save it out.
// Write collision
foutH << "#define " << name << "CollisionLen " << vucCollisionDat.size() << std::endl;
foutH << "extern const unsigned char " << name << "Collision[" << vucCollisionDat.size() << "];" << std::endl;
foutH << std::endl;
@@ -413,7 +402,7 @@ int main(int argc, char** argv)
objDat.push_back((int)(y * 256.0f));
}
// Save it out.
// Write objects
foutH << "#define " << name << "ObjCount " << objDat.size() / 3 << std::endl;
foutH << "#define " << name << "ObjdatLen " << objDat.size() * sizeof(int) << std::endl;
foutH << "extern const unsigned int " << name << "Objdat[" << objDat.size() << "];" << std::endl;

View File

@@ -1,27 +1,7 @@
/* 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
#define TMXLAYER_H
#ifndef TMXLAYER_HPP
#define TMXLAYER_HPP
#include <string>
#include <cstdint>
@@ -51,4 +31,4 @@ private:
uint32_t* mTileDat;
};
#endif//TMXLAYER_H
#endif//TMXLAYER_HPP

View File

@@ -1,27 +1,7 @@
/* tmxobject.cpp
/* tmxobject.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 TMXOBJECT_H
#define TMXOBJECT_H
#ifndef TMXOBJECT_HPP
#define TMXOBJECT_HPP
#include <string>
#include <utility>
@@ -42,4 +22,4 @@ private:
float mX, mY;
};
#endif//TMXOBJECT_H
#endif//TMXOBJECT_HPP

View File

@@ -1,24 +1,4 @@
/* tmxreader.cpp
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.
*/
/* tmxreader.cpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
#include "tmxreader.hpp"
#include "tmxtileset.hpp"
@@ -34,12 +14,12 @@
TmxReader::~TmxReader()
{
// Delete old tilesets.
// Delete old tilesets
for (auto pTileset : mTilesets)
delete pTileset;
mTilesets.clear();
// Delete old layers.
// Delete old layers
for (auto pLay : mLayers)
delete pLay;
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;
auto trimmed = aBase64Dat.substr(begOff, endOff);
// Decode base64 string.
// Decode base64 string
std::string decoded = base64_decode(trimmed);
// Decompress compressed data.
// Decompress compressed data
auto dstSize = static_cast<mz_ulong>(aOutSize);
int res = uncompress(
(unsigned char*)aOut,
@@ -82,17 +62,17 @@ void TmxReader::ReadTileset(rapidxml::xml_node<>* aXNode)
const char* source = "";
uint32_t firstGid = 0;
// Read name.
// Read name
xAttrib = aXNode->first_attribute("name");
if (xAttrib != nullptr)
name = xAttrib->value();
// Read source.
// Read source
xAttrib = aXNode->first_attribute("source");
if (xAttrib != nullptr)
source = xAttrib->value();
// Read first global ID.
// Read first global ID
xAttrib = aXNode->first_attribute("firstgid");
if (xAttrib != nullptr)
firstGid = std::stoul(xAttrib->value());
@@ -108,26 +88,26 @@ void TmxReader::ReadLayer(rapidxml::xml_node<>* aXNode)
int height = 0;
uint32_t* tileDat = nullptr;
// Read name.
// Read name
xAttrib = aXNode->first_attribute("name");
if (xAttrib != nullptr)
name = xAttrib->value();
// Read width.
// Read width
xAttrib = aXNode->first_attribute("width");
if (xAttrib != nullptr)
width = std::stoi(xAttrib->value());
// Read height.
// Read height
xAttrib = aXNode->first_attribute("height");
if (xAttrib != nullptr)
height = std::stoi(xAttrib->value());
// Read tile data.
// Read tile data
auto xData = aXNode->first_node("data");
if (xData != nullptr)
{
// TODO: don't assume base64 & zlib.
// TODO: don't assume base64 & zlib
tileDat = new uint32_t[width * height];
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 y = 0.0f;
// Read name.
// Read name
xAttrib = xNode->first_attribute("name");
if (xAttrib != nullptr)
name = xAttrib->value();
// Read X pos.
// Read X pos
xAttrib = xNode->first_attribute("x");
if (xAttrib != nullptr)
x = std::stof(xAttrib->value());
// Read Y pos.
// Read Y pos
xAttrib = xNode->first_attribute("y");
if (xAttrib != nullptr)
y = std::stof(xAttrib->value());
@@ -172,44 +152,44 @@ void TmxReader::ReadObjects(rapidxml::xml_node<>* aXNode)
void TmxReader::Open(std::istream& aIn)
{
// Delete old tilesets.
// Delete old tilesets
for (auto tileset : mTilesets)
delete tileset;
mTilesets.clear();
// Delete old layers.
// Delete old layers
for (auto layer : mLayers)
delete layer;
mLayers.clear();
mGidTable.clear();
// Read string into a buffer.
// Read string into a buffer
std::stringstream buf;
buf << aIn.rdbuf();
std::string strXml = buf.str();
buf.clear();
// Parse document.
// Parse document
rapidxml::xml_document<> xDoc;
xDoc.parse<0>((char*)strXml.c_str());
// Get map node.
// Get map node
auto xMap = xDoc.first_node("map");
if (xMap == nullptr)
return;
// Read map attribs.
// Read map attribs
rapidxml::xml_attribute<>* xAttrib = nullptr;
if ((xAttrib = xMap->first_attribute("width")) != nullptr)
mWidth = std::stoi(xAttrib->value());
if ((xAttrib = xMap->first_attribute("height")) != nullptr)
mHeight = std::stoi(xAttrib->value());
// Read nodes.
// Read nodes
for (auto xNode = xMap->first_node(); xNode != nullptr; xNode = xNode->next_sibling())
{
// Read layer nodes.
// Read layer nodes
if (strcmp(xNode->name(), "layer") == 0)
ReadLayer(xNode);
else
@@ -220,7 +200,7 @@ void TmxReader::Open(std::istream& aIn)
ReadObjects(xNode);
}
// Generate global id table.
// Generate global id table
for (auto tileset : mTilesets)
mGidTable.push_back(tileset->GetFirstGid());
std::sort(mGidTable.rbegin(), mGidTable.rend());

View File

@@ -1,5 +1,7 @@
#ifndef TMXREADER_H
#define TMXREADER_H
/* tmxreader.hpp - Copyright (C) 2015-2022 a dinosaur (zlib, see COPYING.txt) */
#ifndef TMXREADER_HPP
#define TMXREADER_HPP
#include <istream>
#include <vector>
@@ -45,4 +47,4 @@ private:
};
#endif//TMXREADER_H
#endif//TMXREADER_HPP

View File

@@ -1,27 +1,7 @@
/* 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
#define TMXTILESET_H
#ifndef TMXTILESET_HPP
#define TMXTILESET_HPP
#include <string>
#include <cstdint>
@@ -46,4 +26,4 @@ private:
};
#endif//TMXTILESET_H
#endif//TMXTILESET_HPP