mirror of
https://github.com/ScrelliCopter/tmx2gba.git
synced 2025-02-21 03:29:25 +11:00
refactor tmxmap
This commit is contained in:
@@ -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());
|
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)
|
switch (compression)
|
||||||
{
|
{
|
||||||
case Compression::GZIP:
|
case Compression::GZIP:
|
||||||
#ifndef USE_ZLIB
|
#ifndef USE_ZLIB
|
||||||
{
|
{
|
||||||
|
out.resize(numTiles);
|
||||||
GZipReader reader;
|
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 false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
case Compression::ZLIB:
|
case Compression::ZLIB:
|
||||||
{
|
{
|
||||||
|
out.resize(numTiles);
|
||||||
// Decompress gzip/zlib data with zlib/zlib data miniz
|
// Decompress gzip/zlib data with zlib/zlib data miniz
|
||||||
z_stream s =
|
z_stream s =
|
||||||
{
|
{
|
||||||
.next_in = const_cast<Bytef*>(source.data()),
|
.next_in = const_cast<Bytef*>(source.data()),
|
||||||
.avail_in = static_cast<unsigned int>(source.size()),
|
.avail_in = static_cast<unsigned int>(source.size()),
|
||||||
.next_out = static_cast<Bytef*>(destination.data()),
|
.next_out = reinterpret_cast<Bytef*>(out.data()),
|
||||||
.avail_out = static_cast<unsigned int>(destination.size()),
|
.avail_out = static_cast<unsigned int>(sizeof(uint32_t) * numTiles),
|
||||||
.zalloc = nullptr, .zfree = nullptr, .opaque = nullptr
|
.zalloc = nullptr, .zfree = nullptr, .opaque = nullptr
|
||||||
};
|
};
|
||||||
#ifdef USE_ZLIB
|
#ifdef USE_ZLIB
|
||||||
@@ -78,16 +85,29 @@ enum class Compression { NONE, GZIP, ZLIB, ZSTD, INVALID };
|
|||||||
}
|
}
|
||||||
case Compression::ZSTD:
|
case Compression::ZSTD:
|
||||||
{
|
{
|
||||||
|
out.resize(numTiles);
|
||||||
auto res = ZSTD_decompress(
|
auto res = ZSTD_decompress(
|
||||||
destination.data(), destination.size(),
|
reinterpret_cast<void*>(out.data()),
|
||||||
|
sizeof(uint32_t) * numTiles,
|
||||||
source.data(), source.size());
|
source.data(), source.size());
|
||||||
return !ZSTD_isError(res);
|
return !ZSTD_isError(res);
|
||||||
}
|
}
|
||||||
// Define all labels to shut up linters
|
|
||||||
case Compression::NONE:
|
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:
|
case Compression::INVALID:
|
||||||
//default:
|
default: return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,33 +143,14 @@ void TmxMap::ReadLayer(const pugi::xml_node& xNode)
|
|||||||
auto encoding = EncodingFromStr(xData.attribute("encoding").value());
|
auto encoding = EncodingFromStr(xData.attribute("encoding").value());
|
||||||
if (encoding == Encoding::BASE64)
|
if (encoding == Encoding::BASE64)
|
||||||
{
|
{
|
||||||
// Decode base64 string
|
const std::string_view base64(xData.child_value());
|
||||||
auto decoded = base64_decode(TrimWhitespace(xData.child_value()));
|
if (base64.empty())
|
||||||
if (decoded.empty())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto compression = CompressionFromStr(xData.attribute("compression").value());
|
const auto compression = CompressionFromStr(xData.attribute("compression").value());
|
||||||
if (compression == Compression::GZIP || compression == Compression::ZLIB || compression == Compression::ZSTD)
|
if (compression == Compression::INVALID || !DecodeBase64(tileDat, numTiles, base64, compression))
|
||||||
{
|
|
||||||
tileDat.resize(numTiles);
|
|
||||||
if (!Decompress(compression, tileDat, decoded))
|
|
||||||
return;
|
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; }
|
|
||||||
}
|
|
||||||
else if (encoding == Encoding::XML)
|
else if (encoding == Encoding::XML)
|
||||||
{
|
{
|
||||||
tileDat.reserve(numTiles);
|
tileDat.reserve(numTiles);
|
||||||
|
|||||||
Reference in New Issue
Block a user