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

8 Commits

Author SHA1 Message Date
f9928df187 argparse: use replace raw char* strings with string views 2024-04-08 02:22:23 +10:00
d69eec8dcf argparse: fix not setting required 2024-04-07 21:24:29 +10:00
e53f988e46 Merge branch 'refs/heads/tmxlite' 2024-04-07 13:05:33 +10:00
bc930b8ca4 Update README.md 2024-04-07 12:59:52 +10:00
8961343558 fix zlib build 2024-04-07 09:53:46 +10:00
f8a6b976c9 gzip support for miniz 2024-04-07 09:41:19 +10:00
a7617f3a3a tmxlite: further cleanup 2024-03-28 22:15:57 +11:00
1db1797a27 gitattributes: vendor c sources 2024-03-28 16:45:50 +11:00
34 changed files with 411 additions and 288 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*.c linguist-vendored

View File

@@ -1,43 +1,39 @@
# tmx2gba # # tmx2gba #
tmx2gba is a simple command line utility that converts [Tiled](http://www.mapeditor.org/) .tmx maps to Game Boy Advance formatted charmaps. tmx2gba is a simple command line utility that converts [Tiled](http://www.mapeditor.org/) .tmx maps to Game Boy Advance formatted charmaps.
Originally developed for my own personal use, I've thrown it up in case this is of use to anyone else.
If you find a bug, please open an issue.
Enjoy!
### Features ### ### Features ###
* Exports to raw binary that can be easily memcpy'd into VRAM. * Export raw charmaps that can be easily memcpy'd into VRAM.
* Preserves tile flipping. * Preserves tile flipping.
* Supports per-tile palette specification. * Supports per-tile palette specification.
* Custom collision layer support. * Custom collision layer support.
* Support for objects with id mapping.
### How do I use it? ### ## Usage ##
``` ```
tmx2gba [-h] [-r offset] [-lyc name] [-p 0-15] <-i inpath> <-o outpath> tmx2gba [-hv] [-r offset] [-lyc name] [-p 0-15] [-m name;id] <-i inpath> <-o outpath>
``` ```
| Command | Required | Notes | | Command | Required | Notes |
|--------------|----------|-----------------------------------------------------------------------| |--------------|----------|------------------------------------------------------------------------------------|
| -h | N/A | Display help & command info. | | -h | N/A | Display help & command info |
| -v | No | Display version & quit. | | -v | No | Display version & quit |
| -l (name) | No | Name of layer to use (default first layer in TMX). | | -l (name) | No | Name of layer to use (default first layer in TMX) |
| -y (name) | No | Layer for palette mappings. | | -y (name) | No | Layer for palette mappings |
| -c (name) | No | Output a separate 8bit collision map of the specified layer. | | -c (name) | No | Output a separate 8bit collision map of the specified layer |
| -r (offset) | No | Offset tile indices (default 0). | | -r (offset) | No | Offset tile indices (default 0) |
| -p (0-15) | No | Select which palette to use for 4-bit tilesets. | | -p (0-15) | No | Select which palette to use for 4-bit tilesets |
| -m (name;id) | No | Map an object name to an ID, will enable object exports. | | -m (name;id) | No | Map an object name to an ID, will enable object exports |
| -i (path) | *Yes* | Path to input TMX file. | | -i (path) | *Yes* | Path to input TMX file |
| -o (path) | *Yes* | Path to output files. | | -o (path) | *Yes* | Path to output files |
| -f <file> | No | Command line instructions list for easy integration with buildscripts | | -f <file> | No | Flag file containing command-line arguments for easy integration with buildscripts |
### How do I build it? ### ## Building ##
Dependencies for building are CMake 3.x and a C++11 compliant compiler, Dependencies for building are CMake 3.15 and a C++20 compliant compiler,
all other dependencies are in-tree so you should be able to build with: all other dependencies are in-tree so you should be able to build with:
```bash ```bash
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
make -C build -j$(nproc --all) cmake --build build
``` ```
Optionally, you may install it to use it system wide: Optionally, you may install it to use it system wide:
@@ -45,10 +41,8 @@ Optionally, you may install it to use it system wide:
sudo cmake --install build sudo cmake --install build
``` ```
Which will copy the tmx2gba executable to /usr/local/bin/tmx2gba by default, 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: `--prefix /usr` can be used to override install location.
```bash
sudo cmake --install build --prefix /usr
```
If you're a devkitPro user and would prefer to keep all your development tools compartmentalised 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). 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 The build scripts will respect your `DEVKITPRO` environment variable but if not set will install to
@@ -63,32 +57,11 @@ sudo cmake --install build
* Add support for multi-SBB prepared charmaps. * Add support for multi-SBB prepared charmaps.
* Check if this works for NDS as well. * Check if this works for NDS as well.
* Compression support. * Compression support.
* Support for less common TMX formats.
### License ### ## License ##
[tmx2gba](https://github.com/ScrelliCopter/tmx2gba) is licensed under the zlib license. [tmx2gba](https://github.com/ScrelliCopter/tmx2gba) is licensed under the [Zlib license](COPYING.txt).
[RapidXML](http://rapidxml.sourceforge.net/) is licensed under the Boost & MIT licenses. - A modified [tmxlite](https://github.com/fallahn/tmxlite) is licensed under the [Zlib license](ext/tmxlite/LICENSE).
[René Nyffenegger's base64.cpp](https://github.com/ReneNyffenegger/cpp-base64) is licensed under the zlib license. - [pugixml](https://pugixml.org/) is licensed under the [MIT license](ext/pugixml/LICENSE.md).
[miniz](https://github.com/richgel999/miniz) is public domain software. - [René Nyffenegger's base64.cpp](https://github.com/ReneNyffenegger/cpp-base64) is licensed under the [Zlib license](ext/base64/LICENSE).
[ultragetopt](https://github.com/kevinoid/ultragetopt) is licensed under the MIT license. - [miniz](https://github.com/richgel999/miniz) is licensed under the [MIT license](ext/miniz/LICENSE).
- [ZStandard](https://facebook.github.io/zstd/) is licensed under the [BSD 3-clause license](ext/zstd/LICENSE).
```
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
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.
```

19
ext/base64/LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright © 2004-2017 by René Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author 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 source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
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 source code.
3. This notice may not be removed or altered from any source distribution.

View File

@@ -1,17 +1,41 @@
project(tmxlite VERSION 1.3.1) project(tmxlite VERSION 1.3.1)
# includes the list of source files in the src directory add_library(${PROJECT_NAME} STATIC
set(PROJECT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src) include/tmxlite/Config.hpp
file(GLOB PROJECT_SRC ${PROJECT_DIR}/*.cpp) include/tmxlite/FreeFuncs.hpp
file(GLOB PROJECT_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/tmxlite/*.hpp) include/tmxlite/ImageLayer.hpp
file(GLOB PROJECT_HEADERS_INL ${CMAKE_CURRENT_SOURCE_DIR}/include/tmxlite/*.inl) include/tmxlite/Layer.hpp
file(GLOB PROJECT_HEADERS_DETAIL ${CMAKE_CURRENT_SOURCE_DIR}/include/tmxlite/detail/*.hpp) include/tmxlite/LayerGroup.hpp
list(APPEND PROJECT_SRC ${PROJECT_HEADERS} ${PROJECT_HEADERS_INL} ${PROJECT_HEADERS_DETAIL}) include/tmxlite/Map.hpp
include/tmxlite/Object.hpp
include/tmxlite/ObjectGroup.hpp
include/tmxlite/ObjectTypes.hpp
include/tmxlite/Property.hpp
include/tmxlite/TileLayer.hpp
include/tmxlite/Tileset.hpp
include/tmxlite/Types.hpp
include/tmxlite/Types.inl
include/tmxlite/detail/Log.hpp
add_library(${PROJECT_NAME} STATIC ${PROJECT_SRC}) src/FreeFuncs.cpp
src/ImageLayer.cpp
src/Map.cpp
src/Object.cpp
src/ObjectGroup.cpp
src/Property.cpp
src/TileLayer.cpp
src/LayerGroup.cpp
src/Tileset.cpp
src/ObjectTypes.cpp)
if (NOT USE_ZLIB)
target_sources(${PROJECT_NAME} PRIVATE
include/tmxlite/detail/gzip.hpp
src/detail/gzip.cpp)
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES set_target_properties(${PROJECT_NAME} PROPERTIES
CXX_STANDARD 14 CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON) CXX_STANDARD_REQUIRED ON)
target_include_directories(${PROJECT_NAME} PUBLIC target_include_directories(${PROJECT_NAME} PUBLIC

13
ext/tmxlite/LICENSE Normal file
View File

@@ -0,0 +1,13 @@
(c)Matt Marchant & contributors 2016 - 2021 http://trederia.blogspot.com
tmxlite - Zlib license.
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:
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.
Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
This notice may not be removed or altered from any source distribution.

View File

@@ -27,9 +27,8 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/detail/Android.hpp> #include "tmxlite/detail/Log.hpp"
#include <tmxlite/detail/Log.hpp> #include "tmxlite/Types.hpp"
#include <tmxlite/Types.hpp>
#include <string> #include <string>
#include <sstream> #include <sstream>
@@ -96,17 +95,8 @@ namespace tmx
outPath = outPath.substr(0, result); outPath = outPath.substr(0, result);
} }
} }
// this does only work on windows
#ifndef __ANDROID__
return outPath + '/' + path; return outPath + '/' + path;
#endif
// todo: make resolveFilePath work with subfolders on
// android - currently only the root folder is working
#ifdef __ANDROID__
return path;
#endif
} }
static inline std::string getFilePath(const std::string& path) static inline std::string getFilePath(const std::string& path)

View File

@@ -27,9 +27,9 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Config.hpp> #include "tmxlite/Config.hpp"
#include <tmxlite/Layer.hpp> #include "tmxlite/Layer.hpp"
#include <tmxlite/Types.hpp> #include "tmxlite/Types.hpp"
namespace tmx namespace tmx
{ {

View File

@@ -27,9 +27,9 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Config.hpp> #include "tmxlite/Config.hpp"
#include <tmxlite/Property.hpp> #include "tmxlite/Property.hpp"
#include <tmxlite/Types.hpp> #include "tmxlite/Types.hpp"
#include <string> #include <string>
#include <memory> #include <memory>

View File

@@ -26,9 +26,9 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Config.hpp> #include "tmxlite/Config.hpp"
#include <tmxlite/Layer.hpp> #include "tmxlite/Layer.hpp"
#include <tmxlite/Types.hpp> #include "tmxlite/Types.hpp"
#include <vector> #include <vector>

View File

@@ -27,11 +27,11 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Tileset.hpp> #include "tmxlite/Tileset.hpp"
#include <tmxlite/Layer.hpp> #include "tmxlite/Layer.hpp"
#include <tmxlite/Property.hpp> #include "tmxlite/Property.hpp"
#include <tmxlite/Types.hpp> #include "tmxlite/Types.hpp"
#include <tmxlite/Object.hpp> #include "tmxlite/Object.hpp"
#include <string> #include <string>
#include <vector> #include <vector>

View File

@@ -27,9 +27,9 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Config.hpp> #include "tmxlite/Config.hpp"
#include <tmxlite/Property.hpp> #include "tmxlite/Property.hpp"
#include <tmxlite/Types.hpp> #include "tmxlite/Types.hpp"
#include <string> #include <string>
#include <vector> #include <vector>

View File

@@ -27,9 +27,9 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Config.hpp> #include "tmxlite/Config.hpp"
#include <tmxlite/Layer.hpp> #include "tmxlite/Layer.hpp"
#include <tmxlite/Object.hpp> #include "tmxlite/Object.hpp"
#include <vector> #include <vector>

View File

@@ -26,7 +26,7 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Property.hpp> #include "tmxlite/Property.hpp"
#include <string> #include <string>
#include <vector> #include <vector>

View File

@@ -27,8 +27,8 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Config.hpp> #include "tmxlite/Config.hpp"
#include <tmxlite/Types.hpp> #include "tmxlite/Types.hpp"
#include <string> #include <string>
#include <cassert> #include <cassert>

View File

@@ -27,8 +27,8 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Layer.hpp> #include "tmxlite/Layer.hpp"
#include <tmxlite/Types.hpp> #include "tmxlite/Types.hpp"
namespace tmx namespace tmx
{ {

View File

@@ -27,9 +27,9 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Config.hpp> #include "tmxlite/Config.hpp"
#include <tmxlite/Property.hpp> #include "tmxlite/Property.hpp"
#include <tmxlite/ObjectGroup.hpp> #include "tmxlite/ObjectGroup.hpp"
#include <string> #include <string>
#include <vector> #include <vector>

View File

@@ -27,7 +27,7 @@ source distribution.
#pragma once #pragma once
#include <tmxlite/Config.hpp> #include "tmxlite/Config.hpp"
#include <cstdint> #include <cstdint>
#include <ostream> #include <ostream>

View File

@@ -1,53 +0,0 @@
/*********************************************************************
Matt Marchant 2016
http://trederia.blogspot.com
tmxlite - Zlib license.
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 ANDROID_INC_HPP_
#define ANDROID_INC_HPP_
#ifdef __ANDROID__
#include <string>
#include <sstream>
#include <cstdlib>
namespace std
{
template <typename T>
std::string to_string(T value)
{
std::ostringstream os;
os << value;
return os.str();
}
}
#define STOI(str) std::strtol(str.c_str(), 0, 10)
#else
#define STOI(str) std::stoi(str)
#endif // __ANDROID__
#endif // ANDROID_INC_HPP_

View File

@@ -43,18 +43,6 @@ source distribution.
#include <windows.h> #include <windows.h>
#endif //_MSC_VER #endif //_MSC_VER
#ifdef __ANDROID__
#include <android/log.h>
#include <cstring>
#define LOG_TAG "TMXlite-Debug"
//#define ALOG(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#endif // __ANDROID__
namespace tmx namespace tmx
{ {
/*! /*!
@@ -105,23 +93,10 @@ namespace tmx
{ {
if (type == Type::Error) if (type == Type::Error)
{ {
#ifdef __ANDROID__
int outstringLength = outstring.length();
char outstring_chararray[outstringLength+1];
std::strcpy(outstring_chararray, outstring.c_str());
LOGE("%s",outstring_chararray);
#endif
std::cerr << outstring << std::endl; std::cerr << outstring << std::endl;
} }
else else
{ {
#ifdef __ANDROID__
int outstringLength = outstring.length();
char outstring_chararray[outstringLength+1];
std::strcpy(outstring_chararray, outstring.c_str());
LOGI("%s", outstring_chararray);
#endif
std::cout << outstring << std::endl; std::cout << outstring << std::endl;
} }
const std::size_t maxBuffer = 30; const std::size_t maxBuffer = 30;
@@ -140,13 +115,11 @@ namespace tmx
std::ofstream file("output.log", std::ios::app); std::ofstream file("output.log", std::ios::app);
if (file.good()) if (file.good())
{ {
#ifndef __ANDROID__
std::time_t time = std::time(nullptr); std::time_t time = std::time(nullptr);
auto tm = *std::localtime(&time); auto tm = *std::localtime(&time);
//put_time isn't implemented by the ndk versions of the stl //put_time isn't implemented by the ndk versions of the stl
file.imbue(std::locale()); file.imbue(std::locale());
file << std::put_time(&tm, "%d/%m/%y-%H:%M:%S: "); file << std::put_time(&tm, "%d/%m/%y-%H:%M:%S: ");
#endif //__ANDROID__
file << outstring << std::endl; file << outstring << std::endl;
file.close(); file.close();
} }

View File

@@ -0,0 +1,39 @@
// gzip.hpp - portable memory miniz based gzip reader
// SPDX-License-Identifier: Zlib
// SPDX-FileCopyrightText: (c) 2024 a dinosaur
#ifndef GZIP_HPP
#define GZIP_HPP
#include "miniz.h"
#include <cstdint>
#include <span>
class GZipReader
{
static constexpr uint8_t
FTEXT = 1, FHCRC = 1<<1, FEXTRA = 1<<2, FNAME = 1<<3, FCOMMENT = 1<<4;
static constexpr uint8_t XFL_BEST = 2, XFL_FASTEST = 4;
tinfl_decompressor mState;
std::span<const uint8_t>::iterator mIt;
size_t mSourceLen, mBytesRead;
uint32_t mModificationTime, mCrc, mInputSize, mComputedCrc;
uint16_t crc16;
uint8_t mFlags, mXflags, mOsId;
public:
GZipReader() noexcept;
constexpr size_t SourceLength() const noexcept { return mSourceLen; }
constexpr uint32_t OutputLength() const noexcept { return mInputSize; }
bool OpenMemory(const std::span<const uint8_t> source) noexcept;
bool Read(std::span<uint8_t> out) noexcept;
bool Check() const noexcept;
};
#endif//GZIP_HPP

View File

@@ -25,15 +25,14 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include "tmxlite/FreeFuncs.hpp"
#include "tmxlite/Types.hpp"
#include "tmxlite/detail/Log.hpp"
#ifndef USE_ZLIB #ifndef USE_ZLIB
# include "miniz.h" # include "miniz.h"
#else #else
# include <zlib.h> # include <zlib.h>
#endif #endif
#include <tmxlite/FreeFuncs.hpp>
#include <tmxlite/Types.hpp>
#include <tmxlite/detail/Log.hpp>
#include <cstring> #include <cstring>
bool tmx::decompress(const char* source, std::vector<unsigned char>& dest, std::size_t inSize, std::size_t expectedSize) bool tmx::decompress(const char* source, std::vector<unsigned char>& dest, std::size_t inSize, std::size_t expectedSize)

View File

@@ -25,10 +25,11 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include "tmxlite/ImageLayer.hpp"
#include "tmxlite/FreeFuncs.hpp"
#include "tmxlite/detail/Log.hpp"
#include <pugixml.hpp> #include <pugixml.hpp>
#include <tmxlite/ImageLayer.hpp>
#include <tmxlite/FreeFuncs.hpp>
#include <tmxlite/detail/Log.hpp>
using namespace tmx; using namespace tmx;

View File

@@ -25,13 +25,14 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include "tmxlite/LayerGroup.hpp"
#include "tmxlite/FreeFuncs.hpp"
#include "tmxlite/ObjectGroup.hpp"
#include "tmxlite/ImageLayer.hpp"
#include "tmxlite/TileLayer.hpp"
#include "tmxlite/detail/Log.hpp"
#include <pugixml.hpp> #include <pugixml.hpp>
#include <tmxlite/LayerGroup.hpp>
#include <tmxlite/FreeFuncs.hpp>
#include <tmxlite/ObjectGroup.hpp>
#include <tmxlite/ImageLayer.hpp>
#include <tmxlite/TileLayer.hpp>
#include <tmxlite/detail/Log.hpp>
using namespace tmx; using namespace tmx;

View File

@@ -25,16 +25,15 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include <pugixml.hpp> #include "tmxlite/Map.hpp"
#include <tmxlite/Map.hpp> #include "tmxlite/FreeFuncs.hpp"
#include <tmxlite/FreeFuncs.hpp> #include "tmxlite/ObjectGroup.hpp"
#include <tmxlite/ObjectGroup.hpp> #include "tmxlite/ImageLayer.hpp"
#include <tmxlite/ImageLayer.hpp> #include "tmxlite/TileLayer.hpp"
#include <tmxlite/TileLayer.hpp> #include "tmxlite/LayerGroup.hpp"
#include <tmxlite/LayerGroup.hpp> #include "tmxlite/detail/Log.hpp"
#include <tmxlite/detail/Log.hpp>
#include <tmxlite/detail/Android.hpp>
#include <pugixml.hpp>
#include <queue> #include <queue>
using namespace tmx; using namespace tmx;
@@ -136,8 +135,8 @@ bool Map::parseMapNode(const pugi::xml_node& mapNode)
return reset(); return reset();
} }
m_version.upper = STOI(attribString.substr(0, pointPos)); m_version.upper = std::stoi(attribString.substr(0, pointPos));
m_version.lower = STOI(attribString.substr(pointPos + 1)); m_version.lower = std::stoi(attribString.substr(pointPos + 1));
m_class = mapNode.attribute("class").as_string(); m_class = mapNode.attribute("class").as_string();

View File

@@ -25,13 +25,13 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include <pugixml.hpp> #include "tmxlite/Object.hpp"
#include <tmxlite/Object.hpp> #include "tmxlite/FreeFuncs.hpp"
#include <tmxlite/FreeFuncs.hpp> #include "tmxlite/Map.hpp"
#include <tmxlite/Map.hpp> #include "tmxlite/Tileset.hpp"
#include <tmxlite/Tileset.hpp> #include "tmxlite/detail/Log.hpp"
#include <tmxlite/detail/Log.hpp>
#include <pugixml.hpp>
#include <sstream> #include <sstream>
using namespace tmx; using namespace tmx;

View File

@@ -25,10 +25,11 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include "tmxlite/FreeFuncs.hpp"
#include "tmxlite/ObjectGroup.hpp"
#include "tmxlite/detail/Log.hpp"
#include <pugixml.hpp> #include <pugixml.hpp>
#include <tmxlite/FreeFuncs.hpp>
#include <tmxlite/ObjectGroup.hpp>
#include <tmxlite/detail/Log.hpp>
using namespace tmx; using namespace tmx;

View File

@@ -24,10 +24,11 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include "tmxlite/FreeFuncs.hpp"
#include "tmxlite/ObjectTypes.hpp"
#include "tmxlite/detail/Log.hpp"
#include <pugixml.hpp> #include <pugixml.hpp>
#include <tmxlite/FreeFuncs.hpp>
#include <tmxlite/ObjectTypes.hpp>
#include <tmxlite/detail/Log.hpp>
using namespace tmx; using namespace tmx;

View File

@@ -25,10 +25,11 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include "tmxlite/Property.hpp"
#include "tmxlite/detail/Log.hpp"
#include "tmxlite/FreeFuncs.hpp"
#include <pugixml.hpp> #include <pugixml.hpp>
#include <tmxlite/Property.hpp>
#include <tmxlite/detail/Log.hpp>
#include <tmxlite/FreeFuncs.hpp>
using namespace tmx; using namespace tmx;

View File

@@ -25,13 +25,18 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include <pugixml.hpp>
#include <zstd.h>
#include "base64.h" #include "base64.h"
#include "tmxlite/FreeFuncs.hpp" #include "tmxlite/FreeFuncs.hpp"
#include "tmxlite/TileLayer.hpp" #include "tmxlite/TileLayer.hpp"
#include "tmxlite/detail/Log.hpp" #include "tmxlite/detail/Log.hpp"
#ifndef USE_ZLIB
# include "tmxlite/detail/gzip.hpp"
#endif
#include <pugixml.hpp>
#include <zstd.h>
#include <sstream> #include <sstream>
#include <span>
using namespace tmx; using namespace tmx;
@@ -139,8 +144,18 @@ void TileLayer::parseBase64(const pugi::xml_node& node)
break; break;
case CompressionType::GZip: case CompressionType::GZip:
#ifndef USE_ZLIB #ifndef USE_ZLIB
Logger::log("Library must be built with USE_ZLIB for GZip compression", Logger::Type::Error); {
byteData.resize(expectedSize);
const auto source = std::span(reinterpret_cast<const uint8_t*>(dataString.data()), dataString.size());
GZipReader reader;
if (!reader.OpenMemory(source) || !reader.Read(byteData) || !reader.Check())
{
LOG("Failed to decompress layer data, node skipped.", Logger::Type::Error);
return {}; return {};
}
}
break;
#endif #endif
//[[fallthrough]]; //[[fallthrough]];
case CompressionType::Zlib: case CompressionType::Zlib:

View File

@@ -25,11 +25,11 @@ and must not be misrepresented as being the original software.
source distribution. source distribution.
*********************************************************************/ *********************************************************************/
#include <pugixml.hpp> #include "tmxlite/Tileset.hpp"
#include <tmxlite/Tileset.hpp> #include "tmxlite/FreeFuncs.hpp"
#include <tmxlite/FreeFuncs.hpp> #include "tmxlite/detail/Log.hpp"
#include <tmxlite/detail/Log.hpp>
#include <pugixml.hpp>
#include <ctype.h> #include <ctype.h>
using namespace tmx; using namespace tmx;

View File

@@ -0,0 +1,125 @@
// gzip.cpp - portable memory miniz based gzip reader
// SPDX-License-Identifier: Zlib
// SPDX-FileCopyrightText: (c) 2024 a dinosaur
#include "tmxlite/detail/gzip.hpp"
#include <string_view>
GZipReader::GZipReader() noexcept :
mSourceLen(0), mBytesRead(0),
mModificationTime(0), mCrc(0), mInputSize(0), mComputedCrc(0),
crc16(0), mFlags(0), mXflags(0), mOsId(0)
{
tinfl_init(&mState);
mComputedCrc = static_cast<uint32_t>(mz_crc32(0, nullptr, 0));
}
bool GZipReader::OpenMemory(const std::span<const uint8_t> source) noexcept
{
if (source.size() < 20)
return false;
auto it = std::cbegin(source), end = std::cend(source);
constexpr uint8_t magic[2] = { 0x1F, 0x8B };
if (*it++ != magic[0] || *it++ != magic[1])
return false;
constexpr uint8_t CM_DEFLATE = 8;
uint8_t compression = *it++;
if (compression != CM_DEFLATE)
return false;
mFlags = *it++;
mModificationTime = *it++;
mModificationTime |= *it++ << 8;
mModificationTime |= *it++ << 16;
mModificationTime |= *it++ << 24;
mXflags = *it++;
mOsId = *it++;
if (mFlags & FEXTRA)
{
// Skip "extra" field
if (it + 2 >= end)
return false;
uint16_t extraLen = *it++;
extraLen = *it++ << 8;
if (it + extraLen >= end)
return false;
it += extraLen;
}
if (mFlags & FNAME)
{
// Skip null-terminated name string
do
{
if (++it == end)
return false;
} while (*it != '\0');
if (++it == end)
return false;
}
if (mFlags & FCOMMENT)
{
// Skip null-terminated comment string
do
{
if (++it == end)
return false;
} while (*it != '\0');
if (++it == end)
return false;
}
if (mFlags & FHCRC)
{
if (it + 2 >= end)
return false;
crc16 = *it++;
crc16 |= *it++;
}
mIt = it;
mSourceLen = end - it - 8;
it += mSourceLen;
mCrc = *it++;
mCrc |= *it++ << 8;
mCrc |= *it++ << 16;
mCrc |= *it++ << 24;
mInputSize = *it++;
mInputSize |= *it++ << 8;
mInputSize |= *it++ << 16;
mInputSize |= *it++ << 24;
return true;
}
bool GZipReader::Read(std::span<uint8_t> out) noexcept
{
size_t outLen = out.size();
auto res = tinfl_decompress(&mState,
static_cast<const mz_uint8*>(&*mIt), &mSourceLen,
static_cast<mz_uint8*>(out.data()), static_cast<mz_uint8*>(out.data()), &outLen,
TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
if (res != TINFL_STATUS_DONE)
return false;
mIt += outLen;
mBytesRead += outLen;
mComputedCrc = static_cast<uint32_t>(mz_crc32(static_cast<mz_ulong>(mComputedCrc), out.data(), outLen));
return true;
}
bool GZipReader::Check() const noexcept
{
if (mComputedCrc != mCrc)
return false;
if (static_cast<uint32_t>(mBytesRead & UINT32_MAX) != mInputSize)
return false;
return true;
}

View File

@@ -23,7 +23,7 @@ void ArgParse::Options::ShowShortUsage(const std::string_view name, std::ostream
out << "Usage: " << name; out << "Usage: " << name;
for (const auto& it : options) for (const auto& it : options)
{ {
if (it.argumentName) if (!it.argumentName.empty())
{ {
// Option with argument // Option with argument
it.required it.required
@@ -55,8 +55,8 @@ void ArgParse::Options::ShowHelpUsage(const std::string_view name, std::ostream&
out << ">" << std::endl; out << ">" << std::endl;
// Determine the alignment width from the longest argument // Determine the alignment width from the longest argument
auto paramLength = [](const Option& p) -> int { return p.argumentName auto paramLength = [](const Option& p) -> int { return !p.argumentName.empty()
? static_cast<int>(std::strlen(p.argumentName) + 3) ? static_cast<int>(p.argumentName.length() + 3)
: 1; }; : 1; };
auto longestParam = std::max_element(options.begin(), options.end(), auto longestParam = std::max_element(options.begin(), options.end(),
[=](auto a, auto b) -> bool { return paramLength(a) < paramLength(b); }); [=](auto a, auto b) -> bool { return paramLength(a) < paramLength(b); });
@@ -67,7 +67,8 @@ void ArgParse::Options::ShowHelpUsage(const std::string_view name, std::ostream&
{ {
auto decorateArgument = [=] { return " <" + std::string(it.argumentName) + "> "; }; auto decorateArgument = [=] { return " <" + std::string(it.argumentName) + "> "; };
out << " -" << it.flag out << " -" << it.flag
<< std::left << std::setw(alignWidth) << std::setfill('-') << (it.argumentName ? decorateArgument() : " ") << std::left << std::setw(alignWidth) << std::setfill('-')
<< (!it.argumentName.empty() ? decorateArgument() : " ")
<< " " << it.helpString << std::endl; << " " << it.helpString << std::endl;
} }
out << std::flush; out << std::flush;
@@ -99,7 +100,7 @@ ArgParse::ParseCtrl ArgParse::ParserState::Next(const std::string_view token)
const auto opt = getOption(flagChar); const auto opt = getOption(flagChar);
if (opt.has_value()) if (opt.has_value())
{ {
bool expect = opt.value().get().argumentName != nullptr; bool expect = !opt.value().get().argumentName.empty();
if (token.length() <= 2) if (token.length() <= 2)
{ {
expectArg = expect; expectArg = expect;

View File

@@ -16,18 +16,18 @@ namespace ArgParse
{ {
struct Option struct Option
{ {
const char* argumentName; std::string_view argumentName;
const char* helpString; std::string_view helpString;
char flag; char flag;
bool required; bool required;
static constexpr Option Optional(char flag, const char* name, const char* help) static constexpr Option Optional(char flag, const std::string_view name, const std::string_view help)
{ {
return { name, help, flag, false }; return { name, help, flag, false };
} }
static constexpr Option Required(char flag, const char* name, const char* help) static constexpr Option Required(char flag, const std::string_view name, const std::string_view help)
{ {
return { name, help, flag, false }; return { name, help, flag, true };
} }
}; };

View File

@@ -26,8 +26,8 @@ using ArgParse::Option;
static const ArgParse::Options options = static const ArgParse::Options options =
{ {
Option::Optional('h', nullptr, "Display this help & command info"), Option::Optional('h', {}, "Display this help & command info"),
Option::Optional('v', nullptr, "Display version & quit"), Option::Optional('v', {}, "Display version & quit"),
Option::Optional('l', "name", "Name of layer to use (default first layer in TMX)"), Option::Optional('l', "name", "Name of layer to use (default first layer in TMX)"),
Option::Optional('y', "name", "Layer for palette mappings"), Option::Optional('y', "name", "Layer for palette mappings"),
Option::Optional('c', "name", "Output a separate 8bit collision map of the specified layer"), Option::Optional('c', "name", "Output a separate 8bit collision map of the specified layer"),