Skip to content

Commit

Permalink
Deduplicate some of the MPQ handling
Browse files Browse the repository at this point in the history
Reuse libmpq functions where possible instead of our own.
  • Loading branch information
glebm committed Sep 10, 2023
1 parent 0f77cc3 commit 16a6fc6
Show file tree
Hide file tree
Showing 14 changed files with 82 additions and 130 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/s390x_qemu_big_endian_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:

- name: Run tests
run: >
docker run --rm --interactive --mount type=bind,source=$(pwd),target=/host s390x/alpine sh -c
docker run run --platform linux/s390x --rm --interactive --mount type=bind,source=$(pwd),target=/host s390x/alpine sh -c
"
apk add --update-cache g++ ninja cmake ccache sdl2-dev sdl2_image-dev fmt-dev libpng-dev bzip2-dev gtest-dev wget &&
cd /host &&
Expand Down
4 changes: 2 additions & 2 deletions 3rdParty/libmpq/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ include(functions/FetchContent_MakeAvailableExcludeFromAll)

include(FetchContent)
FetchContent_Declare(libmpq
URL https://github.com/diasurgical/libmpq/archive/34ace76ecb18c3c72300a6b8352ca0c96333488d.tar.gz
URL_HASH MD5=e76ab7e4f9dfd7f96c152dd7d8418fee
URL https://github.com/diasurgical/libmpq/archive/2cf61ebd1ce78082e20dc1e23bd9d66aec7fc0d5.tar.gz
URL_HASH MD5=073d634575465e57d679a7498a666fe3
)
FetchContent_MakeAvailableExcludeFromAll(libmpq)

Expand Down
1 change: 1 addition & 0 deletions Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ endif()
if(SUPPORTS_MPQ)
list(APPEND libdevilutionx_DEPS libmpq)
list(APPEND libdevilutionx_SRCS
mpq/mpq_common.cpp
mpq/mpq_reader.cpp
mpq/mpq_sdl_rwops.cpp
mpq/mpq_writer.cpp)
Expand Down
65 changes: 8 additions & 57 deletions Source/encrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ namespace devilution {

namespace {

struct TDataInfo {
std::byte *srcData;
uint32_t srcOffset;
std::byte *destData;
uint32_t destOffset;
uint32_t size;
};

unsigned int PkwareBufferRead(char *buf, unsigned int *size, void *param) // NOLINT(readability-non-const-parameter)
{
auto *pInfo = reinterpret_cast<TDataInfo *>(param);
Expand All @@ -43,65 +51,8 @@ void PkwareBufferWrite(char *buf, unsigned int *size, void *param) // NOLINT(rea
pInfo->destOffset += *size;
}

const std::array<std::array<uint32_t, 256>, 5> hashtable = []() {
uint32_t seed = 0x00100001;
std::array<std::array<uint32_t, 256>, 5> ret = {};

for (int i = 0; i < 256; i++) {
for (int j = 0; j < 5; j++) { // NOLINT(modernize-loop-convert)
seed = (125 * seed + 3) % 0x2AAAAB;
uint32_t ch = (seed & 0xFFFF);
seed = (125 * seed + 3) % 0x2AAAAB;
ret[j][i] = ch << 16 | (seed & 0xFFFF);
}
}
return ret;
}();

} // namespace

void Decrypt(uint32_t *castBlock, uint32_t size, uint32_t key)
{
uint32_t seed = 0xEEEEEEEE;
for (uint32_t i = 0; i < (size >> 2); i++) {
uint32_t t = SDL_SwapLE32(*castBlock);
seed += hashtable[4][(key & 0xFF)];
t ^= seed + key;
*castBlock = t;
seed += t + (seed << 5) + 3;
castBlock++;
key = (((key << 0x15) ^ 0xFFE00000) + 0x11111111) | (key >> 0x0B);
}
}

void Encrypt(uint32_t *castBlock, uint32_t size, uint32_t key)
{
uint32_t seed = 0xEEEEEEEE;
for (unsigned i = 0; i < (size >> 2); i++) {
uint32_t ch = *castBlock;
uint32_t t = ch;
seed += hashtable[4][(key & 0xFF)];
t ^= seed + key;
*castBlock = SDL_SwapLE32(t);
castBlock++;
seed += ch + (seed << 5) + 3;
key = (((key << 0x15) ^ 0xFFE00000) + 0x11111111) | (key >> 0x0B);
}
}

uint32_t Hash(const char *s, int type)
{
uint32_t seed1 = 0x7FED7FED;
uint32_t seed2 = 0xEEEEEEEE;
while (s != nullptr && (*s != '\0')) {
int8_t ch = *s++;
ch = toupper(ch);
seed1 = hashtable[type][ch] ^ (seed1 + seed2);
seed2 += ch + seed1 + (seed2 << 5) + 3;
}
return seed1;
}

uint32_t PkwareCompress(std::byte *srcData, uint32_t size)
{
std::unique_ptr<char[]> ptr = std::make_unique<char[]>(CMP_BUFFER_SIZE);
Expand Down
11 changes: 0 additions & 11 deletions Source/encrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,6 @@

namespace devilution {

struct TDataInfo {
std::byte *srcData;
uint32_t srcOffset;
std::byte *destData;
uint32_t destOffset;
uint32_t size;
};

void Decrypt(uint32_t *castBlock, uint32_t size, uint32_t key);
void Encrypt(uint32_t *castBlock, uint32_t size, uint32_t key);
uint32_t Hash(const char *s, int type);
uint32_t PkwareCompress(std::byte *srcData, uint32_t size);
void PkwareDecompress(std::byte *inBuff, uint32_t recvSize, int maxBytes);

Expand Down
2 changes: 1 addition & 1 deletion Source/engine/assets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ SDL_RWops *OpenOptionalRWops(const std::string &path)

bool FindMpqFile(std::string_view filename, MpqArchive **archive, uint32_t *fileNumber)
{
const MpqArchive::FileHash fileHash = MpqArchive::CalculateFileHash(filename);
const MpqFileHash fileHash = CalculateMpqFileHash(filename);
const auto at = [=](std::optional<MpqArchive> &src) -> bool {
if (src && src->GetFileNumber(fileHash, *fileNumber)) {
*archive = &(*src);
Expand Down
3 changes: 2 additions & 1 deletion Source/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "utils/utf8.hpp"

#ifndef UNPACKED_MPQS
#include "mpq/mpq_common.hpp"
#include "mpq/mpq_reader.hpp"
#endif

Expand Down Expand Up @@ -201,7 +202,7 @@ bool AreExtraFontsOutOfDate(const std::string &path)
bool AreExtraFontsOutOfDate(MpqArchive &archive)
{
const char filename[] = "fonts\\VERSION";
const MpqArchive::FileHash fileHash = MpqArchive::CalculateFileHash(filename);
const MpqFileHash fileHash = CalculateMpqFileHash(filename);
uint32_t fileNumber;
if (!archive.GetFileNumber(fileHash, fileNumber))
return true;
Expand Down
18 changes: 18 additions & 0 deletions Source/mpq/mpq_common.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "mpq/mpq_common.hpp"

#include <string_view>

#include <libmpq/mpq.h>

namespace devilution {

#if !defined(UNPACKED_MPQS) || !defined(UNPACKED_SAVES)
MpqFileHash CalculateMpqFileHash(std::string_view filename)
{
MpqFileHash fileHash;
libmpq__file_hash_s(filename.data(), filename.size(), &fileHash[0], &fileHash[1], &fileHash[2]);
return fileHash;
}
#endif

} // namespace devilution
8 changes: 8 additions & 0 deletions Source/mpq/mpq_common.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include <array>
#include <cstddef>
#include <cstdint>
#include <string_view>

#include "utils/endian.hpp"

Expand Down Expand Up @@ -87,4 +89,10 @@ struct MpqBlockEntry {
};
#pragma pack(pop)

using MpqFileHash = std::array<std::uint32_t, 3>;

#if !defined(UNPACKED_MPQS) || !defined(UNPACKED_SAVES)
MpqFileHash CalculateMpqFileHash(std::string_view filename);
#endif

} // namespace devilution
9 changes: 1 addition & 8 deletions Source/mpq/mpq_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,6 @@ const char *MpqArchive::ErrorMessage(int32_t errorCode)
return libmpq__strerror(errorCode);
}

MpqArchive::FileHash MpqArchive::CalculateFileHash(std::string_view filename)
{
FileHash fileHash;
libmpq__file_hash_s(filename.data(), filename.size(), &fileHash[0], &fileHash[1], &fileHash[2]);
return fileHash;
}

MpqArchive &MpqArchive::operator=(MpqArchive &&other) noexcept
{
path_ = std::move(other.path_);
Expand All @@ -57,7 +50,7 @@ MpqArchive::~MpqArchive()
libmpq__archive_close(archive_);
}

bool MpqArchive::GetFileNumber(MpqArchive::FileHash fileHash, uint32_t &fileNumber)
bool MpqArchive::GetFileNumber(MpqFileHash fileHash, uint32_t &fileNumber)
{
return libmpq__file_number_from_hash(archive_, fileHash[0], fileHash[1], fileHash[2], &fileNumber) == 0;
}
Expand Down
7 changes: 3 additions & 4 deletions Source/mpq/mpq_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <string_view>
#include <vector>

#include "mpq/mpq_common.hpp"

// Forward-declare so that we can avoid exposing libmpq.
struct mpq_archive;
using mpq_archive_s = struct mpq_archive;
Expand All @@ -24,9 +26,6 @@ class MpqArchive {

static const char *ErrorMessage(int32_t errorCode);

using FileHash = std::array<std::uint32_t, 3>;
static FileHash CalculateFileHash(std::string_view filename);

MpqArchive(MpqArchive &&other) noexcept
: path_(std::move(other.path_))
, archive_(other.archive_)
Expand All @@ -40,7 +39,7 @@ class MpqArchive {
~MpqArchive();

// Returns false if the file does not exit.
bool GetFileNumber(FileHash fileHash, uint32_t &fileNumber);
bool GetFileNumber(MpqFileHash fileHash, uint32_t &fileNumber);

std::unique_ptr<std::byte[]> ReadFile(std::string_view filename, std::size_t &fileSize, int32_t &error);

Expand Down
Loading

0 comments on commit 16a6fc6

Please sign in to comment.