You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
4.3 KiB

#include "mpq/mpq_reader.hpp"
10 months ago
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string_view>
#include <libmpq/mpq.h>
namespace devilution {
std::optional<MpqArchive> MpqArchive::Open(const char *path, int32_t &error)
{
mpq_archive_s *archive;
error = libmpq__archive_open(&archive, path, -1);
if (error != 0) {
if (error == LIBMPQ_ERROR_EXIST)
error = 0;
return std::nullopt;
}
return MpqArchive { std::string(path), archive };
}
std::optional<MpqArchive> MpqArchive::Clone(int32_t &error)
{
mpq_archive_s *copy;
error = libmpq__archive_dup(archive_, path_.c_str(), &copy);
if (error != 0)
return std::nullopt;
return MpqArchive { path_, copy };
}
const char *MpqArchive::ErrorMessage(int32_t errorCode)
{
return libmpq__strerror(errorCode);
}
MpqArchive &MpqArchive::operator=(MpqArchive &&other) noexcept
{
path_ = std::move(other.path_);
if (archive_ != nullptr)
libmpq__archive_close(archive_);
archive_ = other.archive_;
Add dun_render_benchmark Results from a single run (a bit noisy) on my machine: ``` tools/build_and_run_benchmark.py dun_render_benchmark ``` ``` ------------------------------------------------------------------------------------------------------------------------ Benchmark Time CPU Iterations UserCounters... ------------------------------------------------------------------------------------------------------------------------ DunRenderBenchmark/LeftTriangle_Solid_FullyLit 98297 ns 98282 ns 8840 items_per_second=15.1096M/s DunRenderBenchmark/LeftTriangle_Solid_FullyDark 124727 ns 124701 ns 6973 items_per_second=11.9085M/s DunRenderBenchmark/LeftTriangle_Solid_PartiallyLit 514869 ns 514747 ns 1700 items_per_second=2.88491M/s DunRenderBenchmark/LeftTriangle_Transparent_FullyLit 520312 ns 520216 ns 1682 items_per_second=2.85458M/s DunRenderBenchmark/LeftTriangle_Transparent_FullyDark 524440 ns 524331 ns 1664 items_per_second=2.83218M/s DunRenderBenchmark/LeftTriangle_Transparent_PartiallyLit 532300 ns 532162 ns 1647 items_per_second=2.7905M/s DunRenderBenchmark/RightTriangle_Solid_FullyLit 92387 ns 92363 ns 8840 items_per_second=16.7275M/s DunRenderBenchmark/RightTriangle_Solid_FullyDark 85680 ns 85662 ns 9884 items_per_second=18.0361M/s DunRenderBenchmark/RightTriangle_Solid_PartiallyLit 538347 ns 538250 ns 1626 items_per_second=2.87041M/s DunRenderBenchmark/RightTriangle_Transparent_FullyLit 548800 ns 548760 ns 1598 items_per_second=2.81544M/s DunRenderBenchmark/RightTriangle_Transparent_FullyDark 540450 ns 540369 ns 1620 items_per_second=2.85916M/s DunRenderBenchmark/RightTriangle_Transparent_PartiallyLit 555061 ns 555003 ns 1575 items_per_second=2.78377M/s DunRenderBenchmark/TransparentSquare_Solid_FullyLit 700849 ns 700751 ns 1320 items_per_second=3.68176M/s DunRenderBenchmark/TransparentSquare_Solid_FullyDark 664927 ns 664872 ns 1389 items_per_second=3.88045M/s DunRenderBenchmark/TransparentSquare_Solid_PartiallyLit 1131702 ns 1131559 ns 822 items_per_second=2.28004M/s DunRenderBenchmark/TransparentSquare_Transparent_FullyLit 1022384 ns 1022267 ns 916 items_per_second=2.5238M/s DunRenderBenchmark/TransparentSquare_Transparent_FullyDark 1023193 ns 1023057 ns 900 items_per_second=2.52185M/s DunRenderBenchmark/TransparentSquare_Transparent_PartiallyLit 1033573 ns 1033496 ns 895 items_per_second=2.49638M/s DunRenderBenchmark/Square_Solid_FullyLit 53532 ns 53524 ns 10000 items_per_second=30.8272M/s DunRenderBenchmark/Square_Solid_FullyDark 41993 ns 41987 ns 19794 items_per_second=47.1573M/s DunRenderBenchmark/Square_Solid_PartiallyLit 842772 ns 842615 ns 1108 items_per_second=1.56655M/s DunRenderBenchmark/Square_Transparent_FullyLit 834105 ns 834026 ns 1119 items_per_second=1.58269M/s DunRenderBenchmark/Square_Transparent_FullyDark 831912 ns 831823 ns 1122 items_per_second=1.58688M/s DunRenderBenchmark/Square_Transparent_PartiallyLit 924638 ns 924536 ns 1010 items_per_second=1.42774M/s DunRenderBenchmark/LeftTrapezoid_Solid_FullyLit 33728 ns 33725 ns 24962 items_per_second=18.8583M/s DunRenderBenchmark/LeftTrapezoid_Solid_FullyDark 31088 ns 31085 ns 27444 items_per_second=20.4601M/s DunRenderBenchmark/LeftTrapezoid_Solid_PartiallyLit 268792 ns 268768 ns 3254 items_per_second=1.97196M/s DunRenderBenchmark/LeftTrapezoid_Transparent_FullyLit 277990 ns 277965 ns 3140 items_per_second=1.90672M/s DunRenderBenchmark/LeftTrapezoid_Transparent_FullyDark 268952 ns 268912 ns 3250 items_per_second=1.9709M/s DunRenderBenchmark/LeftTrapezoid_Transparent_PartiallyLit 288869 ns 288826 ns 3056 items_per_second=1.83501M/s DunRenderBenchmark/RightTrapezoid_Solid_FullyLit 29581 ns 29576 ns 28347 items_per_second=21.0984M/s DunRenderBenchmark/RightTrapezoid_Solid_FullyDark 25315 ns 25312 ns 32250 items_per_second=24.6523M/s DunRenderBenchmark/RightTrapezoid_Solid_PartiallyLit 259977 ns 259960 ns 3312 items_per_second=2.0003M/s DunRenderBenchmark/RightTrapezoid_Transparent_FullyLit 263079 ns 263056 ns 3322 items_per_second=1.97677M/s DunRenderBenchmark/RightTrapezoid_Transparent_FullyDark 259849 ns 259824 ns 3364 items_per_second=2.00136M/s DunRenderBenchmark/RightTrapezoid_Transparent_PartiallyLit 279623 ns 279594 ns 3127 items_per_second=1.85984M/s ```
2 years ago
other.archive_ = nullptr;
tmp_buf_ = std::move(other.tmp_buf_);
return *this;
}
MpqArchive::~MpqArchive()
{
if (archive_ != nullptr)
libmpq__archive_close(archive_);
}
bool MpqArchive::GetFileNumber(MpqFileHash fileHash, uint32_t &fileNumber)
{
return libmpq__file_number_from_hash(archive_, fileHash[0], fileHash[1], fileHash[2], &fileNumber) == 0;
}
std::unique_ptr<std::byte[]> MpqArchive::ReadFile(std::string_view filename, std::size_t &fileSize, int32_t &error)
{
std::unique_ptr<std::byte[]> result;
std::uint32_t fileNumber;
error = libmpq__file_number_s(archive_, filename.data(), filename.size(), &fileNumber);
if (error != 0)
return result;
libmpq__off_t unpackedSize;
error = libmpq__file_size_unpacked(archive_, fileNumber, &unpackedSize);
if (error != 0)
return result;
error = OpenBlockOffsetTable(fileNumber, filename);
if (error != 0)
return result;
result = std::make_unique<std::byte[]>(static_cast<size_t>(unpackedSize));
const std::size_t blockSize = GetBlockSize(fileNumber, 0, error);
if (error != 0)
return result;
std::vector<std::uint8_t> &tmp = GetTemporaryBuffer(blockSize);
if (error != 0)
return result;
error = libmpq__file_read_with_filename_and_temporary_buffer_s(
archive_, fileNumber, filename.data(), filename.size(), reinterpret_cast<std::uint8_t *>(result.get()), unpackedSize,
tmp.data(), static_cast<libmpq__off_t>(blockSize), nullptr);
if (error != 0) {
result = nullptr;
CloseBlockOffsetTable(fileNumber);
return result;
}
CloseBlockOffsetTable(fileNumber);
fileSize = static_cast<size_t>(unpackedSize);
return result;
}
int32_t MpqArchive::ReadBlock(uint32_t fileNumber, uint32_t blockNumber, uint8_t *out, size_t outSize)
{
std::vector<std::uint8_t> &tmpBuf = GetTemporaryBuffer(outSize);
return libmpq__block_read_with_temporary_buffer(
archive_, fileNumber, blockNumber, out, static_cast<libmpq__off_t>(outSize),
tmpBuf.data(), outSize,
/*transferred=*/nullptr);
}
std::size_t MpqArchive::GetUnpackedFileSize(uint32_t fileNumber, int32_t &error)
{
libmpq__off_t unpackedSize;
error = libmpq__file_size_unpacked(archive_, fileNumber, &unpackedSize);
return static_cast<size_t>(unpackedSize);
}
uint32_t MpqArchive::GetNumBlocks(uint32_t fileNumber, int32_t &error)
{
uint32_t numBlocks;
error = libmpq__file_blocks(archive_, fileNumber, &numBlocks);
return numBlocks;
}
int32_t MpqArchive::OpenBlockOffsetTable(uint32_t fileNumber, std::string_view filename)
{
return libmpq__block_open_offset_with_filename_s(archive_, fileNumber, filename.data(), filename.size());
}
int32_t MpqArchive::CloseBlockOffsetTable(uint32_t fileNumber)
{
return libmpq__block_close_offset(archive_, fileNumber);
}
// Requires the block offset table to be open
std::size_t MpqArchive::GetBlockSize(uint32_t fileNumber, uint32_t blockNumber, int32_t &error)
{
libmpq__off_t blockSize;
error = libmpq__block_size_unpacked(archive_, fileNumber, blockNumber, &blockSize);
return static_cast<size_t>(blockSize);
}
bool MpqArchive::HasFile(std::string_view filename) const
{
std::uint32_t fileNumber;
int32_t error = libmpq__file_number_s(archive_, filename.data(), filename.size(), &fileNumber);
return error == 0;
}
} // namespace devilution