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

refactor tmxmap

This commit is contained in:
2024-04-11 07:16:13 +10:00
parent fcb9eceec3
commit 6a6d589817

View File

@@ -37,32 +37,39 @@ enum class Compression { NONE, GZIP, ZLIB, ZSTD, INVALID };
}
[[nodiscard]] static bool Decompress(Compression compression, std::span<uint32_t> out, const std::string_view decoded)
[[nodiscard]] static bool DecodeBase64(
std::vector<uint32_t>& out, size_t numTiles,
const std::string_view base64, Compression compression)
{
//FIXME: lmao what is big endian
auto decoded = base64_decode(TrimWhitespace(base64));
if (decoded.empty()) { return false; }
const std::span source(reinterpret_cast<const uint8_t*>(decoded.data()), decoded.size());
std::span destination(reinterpret_cast<uint8_t*>(out.data()), sizeof(uint32_t) * out.size());
//FIXME: lmao what is big endian
switch (compression)
{
case Compression::GZIP:
#ifndef USE_ZLIB
{
out.resize(numTiles);
GZipReader reader;
if (!reader.OpenMemory(source) || !reader.Read(destination) || !reader.Check())
if (!reader.OpenMemory(source) ||
!reader.Read({ reinterpret_cast<uint8_t*>(out.data()), sizeof(uint32_t) * numTiles }) ||
!reader.Check())
return false;
return true;
}
#endif
case Compression::ZLIB:
{
out.resize(numTiles);
// Decompress gzip/zlib data with zlib/zlib data miniz
z_stream s =
{
.next_in = const_cast<Bytef*>(source.data()),
.avail_in = static_cast<unsigned int>(source.size()),
.next_out = static_cast<Bytef*>(destination.data()),
.avail_out = static_cast<unsigned int>(destination.size()),
.next_out = reinterpret_cast<Bytef*>(out.data()),
.avail_out = static_cast<unsigned int>(sizeof(uint32_t) * numTiles),
.zalloc = nullptr, .zfree = nullptr, .opaque = nullptr
};
#ifdef USE_ZLIB
@@ -78,16 +85,29 @@ enum class Compression { NONE, GZIP, ZLIB, ZSTD, INVALID };
}
case Compression::ZSTD:
{
out.resize(numTiles);
auto res = ZSTD_decompress(
destination.data(), destination.size(),
reinterpret_cast<void*>(out.data()),
sizeof(uint32_t) * numTiles,
source.data(), source.size());
return !ZSTD_isError(res);
}
// Define all labels to shut up linters
case Compression::NONE:
{
out.reserve(numTiles);
const auto end = source.end();
for (auto it = source.begin(); it < end - 3;)
{
uint32_t tile = *it++;
tile |= static_cast<uint32_t>(*it++) << 8u;
tile |= static_cast<uint32_t>(*it++) << 16u;
tile |= static_cast<uint32_t>(*it++) << 24u;
out.emplace_back(tile);
}
return true;
}
case Compression::INVALID:
//default:
return false;
default: return false;
}
}
@@ -123,32 +143,13 @@ void TmxMap::ReadLayer(const pugi::xml_node& xNode)
auto encoding = EncodingFromStr(xData.attribute("encoding").value());
if (encoding == Encoding::BASE64)
{
// Decode base64 string
auto decoded = base64_decode(TrimWhitespace(xData.child_value()));
if (decoded.empty())
const std::string_view base64(xData.child_value());
if (base64.empty())
return;
auto compression = CompressionFromStr(xData.attribute("compression").value());
if (compression == Compression::GZIP || compression == Compression::ZLIB || compression == Compression::ZSTD)
{
tileDat.resize(numTiles);
if (!Decompress(compression, tileDat, decoded))
return;
}
else if (compression == Compression::NONE)
{
tileDat.reserve(numTiles);
const auto end = decoded.end();
for (auto it = decoded.begin(); it < end - 3;)
{
uint32_t tile = static_cast<uint32_t>(static_cast<uint8_t>(*it++));
tile |= static_cast<uint32_t>(static_cast<uint8_t>(*it++)) << 8u;
tile |= static_cast<uint32_t>(static_cast<uint8_t>(*it++)) << 16u;
tile |= static_cast<uint32_t>(static_cast<uint8_t>(*it++)) << 24u;
tileDat.emplace_back(tile);
}
}
else { return; }
const auto compression = CompressionFromStr(xData.attribute("compression").value());
if (compression == Compression::INVALID || !DecodeBase64(tileDat, numTiles, base64, compression))
return;
}
else if (encoding == Encoding::XML)
{