diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..e69de29bb
diff --git a/3rdParty/PKWare/CMakeLists.txt b/3rdParty/PKWare/CMakeLists.txt
deleted file mode 100644
index 99f9783b2..000000000
--- a/3rdParty/PKWare/CMakeLists.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-add_library(PKWare STATIC
- explode.cpp
- implode.cpp)
-target_include_directories(PKWare PUBLIC .)
diff --git a/3rdParty/PKWare/Makefile b/3rdParty/PKWare/Makefile
deleted file mode 100644
index 377b29a23..000000000
--- a/3rdParty/PKWare/Makefile
+++ /dev/null
@@ -1,59 +0,0 @@
-VC5_DIR ?= $(HOME)/DevStudio_5.10/VC
-
-# The $(VS6_DIR) directory is a copy of the "Microsoft Visual Studio" directory.
-#
-# To get a working setup on Linux or other "portable" copies of VS,
-# the following DLLs have to be copied to the
-# $(VS6_DIR)/VC98/Bin directory.
-#
-# - $(VS6_DIR)/Common/MSDev98/Bin/MSPDB60.DLL
-#
-# And to the $(VC5_DIR)/bin directory.
-#
-# - $(VC5_DIR)/SharedIDE/bin/MSDIS100.DLL
-# - $(VC5_DIR)/SharedIDE/bin/MSPDB50.DLL
-VS6_DIR ?= $(HOME)/VS6
-
-VC6_DIR = $(VS6_DIR)/VC98
-
-VC6_BIN_DIR = $(VC6_DIR)/Bin
-VC6_INC_DIR = $(VC6_DIR)/Include
-VC6_LIB_DIR = $(VC6_DIR)/Lib
-
-VC5_LIB_DIR = $(VC5_DIR)/lib
-
-IDE_DIR ?= $(VS6_DIR)/Common/MSDev98
-IDE_BIN_DIR = $(IDE_DIR)/bin
-ifeq ($(OS),Windows_NT)
- CL = $(VC6_BIN_DIR)/CL.EXE
- RC = $(IDE_BIN_DIR)/RC.EXE
- VC5_LINK = $(VC5_DIR)/bin/link.exe
- VC6_LINK = $(VC6_BIN_DIR)/link.exe
-else
- CL = wine $(VC6_BIN_DIR)/CL.EXE
- RC = wine $(IDE_BIN_DIR)/RC.EXE
- VC5_LINK = wine $(VC5_DIR)/bin/link.exe
- VC6_LINK = wine $(VC6_BIN_DIR)/link.exe
-endif
-
-CFLAGS=/nologo /c /GX /W3 /O1 /I $(VC6_INC_DIR) /FD /MT /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /YX /Gm /Zi
-LINKFLAGS=/nologo /subsystem:windows /machine:I386 /incremental:no
-
-VC_LINK=$(VC5_LINK)
-LINKFLAGS+= /LIBPATH:$(VC5_LIB_DIR)
-
-all: pkware.lib
-
-PKWARE_SRC=$(sort $(wildcard *.cpp))
-PKWARE_OBJS=$(PKWARE_SRC:.cpp=.obj)
-
-pkware.lib: $(PKWARE_OBJS)
- $(VC_LINK) -lib /OUT:$@ $^ /nologo
-
-%.obj: %.cpp
- $(CL) $(CFLAGS) /Fo$@ $<
-
-clean:
- @$(RM) -v $(PKWARE_OBJS) pkware.lib vc60.{idb,pch,pdb}
-
-.PHONY: clean all
diff --git a/3rdParty/PKWare/PKWare.vcxproj b/3rdParty/PKWare/PKWare.vcxproj
deleted file mode 100644
index 5d7772459..000000000
--- a/3rdParty/PKWare/PKWare.vcxproj
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Release
- Win32
-
-
-
-
-
-
-
-
-
-
- 15.0
- {C7F9F3B4-2F7C-4672-9586-94D8BA0950B6}
- Win32Proj
- PKWare
- 10.0.17763.0
-
-
-
- StaticLibrary
- true
- v141
- Unicode
-
-
- StaticLibrary
- false
- v141
- true
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
- .\WinDebug\
- .\WinDebug\
-
-
- false
- .\WinRel
- .\WinRel
-
-
-
- NotUsing
- Level3
- Disabled
- true
- WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
- true
- MultiThreadedDebug
-
-
- Windows
- true
-
-
-
-
- NotUsing
- Level3
- MaxSpeed
- true
- true
- true
- WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
- true
- MultiThreaded
-
-
- Windows
- true
- true
- true
-
-
-
-
-
-
\ No newline at end of file
diff --git a/3rdParty/PKWare/PKWare.vcxproj.filters b/3rdParty/PKWare/PKWare.vcxproj.filters
deleted file mode 100644
index 5bcd9e7ec..000000000
--- a/3rdParty/PKWare/PKWare.vcxproj.filters
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
- {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
-
-
- {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
- rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
-
-
-
-
- Source Files
-
-
- Source Files
-
-
-
-
- Header Files
-
-
-
\ No newline at end of file
diff --git a/3rdParty/PKWare/Pkware.dsp b/3rdParty/PKWare/Pkware.dsp
deleted file mode 100644
index ebdaeba03..000000000
--- a/3rdParty/PKWare/Pkware.dsp
+++ /dev/null
@@ -1,100 +0,0 @@
-# Microsoft Developer Studio Project File - Name="Pkware" - Package Owner=<4>
-# Microsoft Developer Studio Generated Build File, Format Version 6.00
-# ** DO NOT EDIT **
-
-# TARGTYPE "Win32 (x86) Static Library" 0x0104
-
-CFG=Pkware - Win32 Debug
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-!MESSAGE use the Export Makefile command and run
-!MESSAGE
-!MESSAGE NMAKE /f "Pkware.mak".
-!MESSAGE
-!MESSAGE You can specify a configuration when running NMAKE
-!MESSAGE by defining the macro CFG on the command line. For example:
-!MESSAGE
-!MESSAGE NMAKE /f "Pkware.mak" CFG="Pkware - Win32 Debug"
-!MESSAGE
-!MESSAGE Possible choices for configuration are:
-!MESSAGE
-!MESSAGE "Pkware - Win32 Release" (based on "Win32 (x86) Static Library")
-!MESSAGE "Pkware - Win32 Debug" (based on "Win32 (x86) Static Library")
-!MESSAGE
-
-# Begin Project
-# PROP AllowPerConfigDependencies 0
-# PROP Scc_ProjName ""
-# PROP Scc_LocalPath ""
-CPP=cl.exe
-RSC=rc.exe
-
-!IF "$(CFG)" == "Pkware - Win32 Release"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 0
-# PROP BASE Output_Dir "WinRel"
-# PROP BASE Intermediate_Dir "WinRel"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 0
-# PROP Output_Dir "WinRel"
-# PROP Intermediate_Dir "WinRel"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD BASE RSC /l 0x409 /d "NDEBUG"
-# ADD RSC /l 0x409 /d "NDEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ELSEIF "$(CFG)" == "Pkware - Win32 Debug"
-
-# PROP BASE Use_MFC 0
-# PROP BASE Use_Debug_Libraries 1
-# PROP BASE Output_Dir "WinDebug"
-# PROP BASE Intermediate_Dir "WinDebug"
-# PROP BASE Target_Dir ""
-# PROP Use_MFC 0
-# PROP Use_Debug_Libraries 1
-# PROP Output_Dir "WinDebug"
-# PROP Intermediate_Dir "WinDebug"
-# PROP Target_Dir ""
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
-# ADD BASE RSC /l 0x409 /d "_DEBUG"
-# ADD RSC /l 0x409 /d "_DEBUG"
-BSC32=bscmake.exe
-# ADD BASE BSC32 /nologo
-# ADD BSC32 /nologo
-LIB32=link.exe -lib
-# ADD BASE LIB32 /nologo
-# ADD LIB32 /nologo
-
-!ENDIF
-
-# Begin Target
-
-# Name "Pkware - Win32 Release"
-# Name "Pkware - Win32 Debug"
-# Begin Group "Source Files"
-
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-# Begin Source File
-
-SOURCE=.\explode.cpp
-# End Source File
-# Begin Source File
-
-SOURCE=.\implode.cpp
-# End Source File
-# End Group
-# Begin Group "Header Files"
-
-# PROP Default_Filter "h;hpp;hxx;hm;inl"
-# End Group
-# End Target
-# End Project
diff --git a/3rdParty/PKWare/explode.cpp b/3rdParty/PKWare/explode.cpp
deleted file mode 100644
index 2702c4bfe..000000000
--- a/3rdParty/PKWare/explode.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-/*****************************************************************************/
-/* explode.cpp Copyright (c) Ladislav Zezula 2003 */
-/*---------------------------------------------------------------------------*/
-/* Implode function of PKWARE Data Compression library */
-/*---------------------------------------------------------------------------*/
-/* Date Ver Who Comment */
-/* -------- ---- --- ------- */
-/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
-/* 08.04.03 1.01 Lad Renamed to explode.cpp to be compatible with pkware */
-/* 02.05.03 1.01 Lad Stress test done */
-/* 22.04.10 1.01 Lad Documented */
-/*****************************************************************************/
-
-#include
-#include
-
-#include "pkware.h"
-
-#define PKDCL_OK 0
-#define PKDCL_STREAM_END 1 // All data from the input stream is read
-#define PKDCL_NEED_DICT 2 // Need more data (dictionary)
-#define PKDCL_CONTINUE 10 // Internal flag, not returned to user
-#define PKDCL_GET_INPUT 11 // Internal flag, not returned to user
-
-static char CopyrightPkware[] = "PKWARE Data Compression Library for Win32\r\n"
- "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
- "Patent No. 5,051,745\r\n"
- "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
- "Version 1.11\r\n";
-
-//-----------------------------------------------------------------------------
-// Tables
-
-static unsigned char DistBits[] =
-{
- 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
-};
-
-static unsigned char DistCode[] =
-{
- 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
- 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
- 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
- 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
-};
-
-static unsigned char ExLenBits[] =
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
-};
-
-static unsigned short LenBase[] =
-{
- 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
- 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
-};
-
-static unsigned char LenBits[] =
-{
- 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
-};
-
-static unsigned char LenCode[] =
-{
- 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
-};
-
-static unsigned char ChBitsAsc[] =
-{
- 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
- 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
- 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
- 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
- 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
- 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
- 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
-};
-
-static unsigned short ChCodeAsc[] =
-{
- 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
- 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
- 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
- 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
- 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
- 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
- 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
- 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
- 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
- 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
- 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
- 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
- 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
- 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
- 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
- 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
- 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
- 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
- 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
- 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
- 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
- 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
- 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
- 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
- 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
- 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
- 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
- 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
- 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
- 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
- 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
- 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
-};
-
-//-----------------------------------------------------------------------------
-// Local functions
-
-static void PKWAREAPI GenDecodeTabs(
- unsigned char * positions, // [out] Table of positions
- unsigned char * start_indexes, // [in] Table of start indexes
- unsigned char * length_bits, // [in] Table of lengths. Each length is stored as number of bits
- size_t elements) // [in] Number of elements in start_indexes and length_bits
-{
- unsigned int index;
- unsigned int length;
- size_t i;
-
- for(i = 0; i < elements; i++)
- {
- length = 1 << length_bits[i]; // Get the length in bytes
-
- for(index = start_indexes[i]; index < 0x100; index += length)
- {
- positions[index] = (unsigned char)i;
- }
- }
-}
-
-static void PKWAREAPI GenAscTabs(TDcmpStruct * pWork)
-{
- unsigned short * pChCodeAsc = &ChCodeAsc[0xFF];
- unsigned int acc, add;
- unsigned short count;
-
- for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--)
- {
- unsigned char * pChBitsAsc = pWork->ChBitsAsc + count;
- unsigned char bits_asc = *pChBitsAsc;
-
- if(bits_asc <= 8)
- {
- add = (1 << bits_asc);
- acc = *pChCodeAsc;
-
- do
- {
- pWork->offs2C34[acc] = (unsigned char)count;
- acc += add;
- }
- while(acc < 0x100);
- }
- else if((acc = (*pChCodeAsc & 0xFF)) != 0)
- {
- pWork->offs2C34[acc] = 0xFF;
-
- if(*pChCodeAsc & 0x3F)
- {
- bits_asc -= 4;
- *pChBitsAsc = bits_asc;
-
- add = (1 << bits_asc);
- acc = *pChCodeAsc >> 4;
- do
- {
- pWork->offs2D34[acc] = (unsigned char)count;
- acc += add;
- }
- while(acc < 0x100);
- }
- else
- {
- bits_asc -= 6;
- *pChBitsAsc = bits_asc;
-
- add = (1 << bits_asc);
- acc = *pChCodeAsc >> 6;
- do
- {
- pWork->offs2E34[acc] = (unsigned char)count;
- acc += add;
- }
- while(acc < 0x80);
- }
- }
- else
- {
- bits_asc -= 8;
- *pChBitsAsc = bits_asc;
-
- add = (1 << bits_asc);
- acc = *pChCodeAsc >> 8;
- do
- {
- pWork->offs2EB4[acc] = (unsigned char)count;
- acc += add;
- }
- while(acc < 0x100);
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Removes given number of bits in the bit buffer. New bits are reloaded from
-// the input buffer, if needed.
-// Returns: PKDCL_OK: Operation was successful
-// PKDCL_STREAM_END: There are no more bits in the input buffer
-
-static int PKWAREAPI WasteBits(TDcmpStruct * pWork, unsigned int nBits)
-{
- // If number of bits required is less than number of (bits in the buffer) ?
- if(nBits <= pWork->extra_bits)
- {
- pWork->extra_bits -= nBits;
- pWork->bit_buff >>= nBits;
- return PKDCL_OK;
- }
-
- // Load input buffer if necessary
- pWork->bit_buff >>= pWork->extra_bits;
- if(pWork->in_pos == pWork->in_bytes)
- {
- pWork->in_pos = sizeof(pWork->in_buff);
- if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0)
- return PKDCL_STREAM_END;
- pWork->in_pos = 0;
- }
-
- // Update bit buffer
- pWork->bit_buff |= (pWork->in_buff[pWork->in_pos++] << 8);
- pWork->bit_buff >>= (nBits - pWork->extra_bits);
- pWork->extra_bits = (pWork->extra_bits - nBits) + 8;
- return PKDCL_OK;
-}
-
-//-----------------------------------------------------------------------------
-// Decodes next literal from the input (compressed) data.
-// Returns : 0x000: One byte 0x00
-// 0x001: One byte 0x01
-// ...
-// 0x0FF: One byte 0xFF
-// 0x100: Repetition, length of 0x02 bytes
-// 0x101: Repetition, length of 0x03 bytes
-// ...
-// 0x304: Repetition, length of 0x206 bytes
-// 0x305: End of stream
-// 0x306: Error
-
-static unsigned int PKWAREAPI DecodeLit(TDcmpStruct * pWork)
-{
- unsigned int extra_length_bits; // Number of bits of extra literal length
- unsigned int length_code; // Length code
- unsigned int value;
-
- // Test the current bit in byte buffer. If is not set, simply return the next 8 bits.
- if(pWork->bit_buff & 1)
- {
- // Remove one bit from the input data
- if(WasteBits(pWork, 1))
- return 0x306;
-
- // The next 8 bits hold the index to the length code table
- length_code = pWork->LengthCodes[pWork->bit_buff & 0xFF];
-
- // Remove the apropriate number of bits
- if(WasteBits(pWork, pWork->LenBits[length_code]))
- return 0x306;
-
- // Are there some extra bits for the obtained length code ?
- if((extra_length_bits = pWork->ExLenBits[length_code]) != 0)
- {
- unsigned int extra_length = pWork->bit_buff & ((1 << extra_length_bits) - 1);
-
- if(WasteBits(pWork, extra_length_bits))
- {
- if((length_code + extra_length) != 0x10E)
- return 0x306;
- }
- length_code = pWork->LenBase[length_code] + extra_length;
- }
-
- // In order to distinguish uncompressed byte from repetition length,
- // we have to add 0x100 to the length.
- return length_code + 0x100;
- }
-
- // Remove one bit from the input data
- if(WasteBits(pWork, 1))
- return 0x306;
-
- // If the binary compression type, read 8 bits and return them as one byte.
- if(pWork->ctype == CMP_BINARY)
- {
- unsigned int uncompressed_byte = pWork->bit_buff & 0xFF;
-
- if(WasteBits(pWork, 8))
- return 0x306;
- return uncompressed_byte;
- }
-
- // When ASCII compression ...
- if(pWork->bit_buff & 0xFF)
- {
- value = pWork->offs2C34[pWork->bit_buff & 0xFF];
-
- if(value == 0xFF)
- {
- if(pWork->bit_buff & 0x3F)
- {
- if(WasteBits(pWork, 4))
- return 0x306;
-
- value = pWork->offs2D34[pWork->bit_buff & 0xFF];
- }
- else
- {
- if(WasteBits(pWork, 6))
- return 0x306;
-
- value = pWork->offs2E34[pWork->bit_buff & 0x7F];
- }
- }
- }
- else
- {
- if(WasteBits(pWork, 8))
- return 0x306;
-
- value = pWork->offs2EB4[pWork->bit_buff & 0xFF];
- }
-
- return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value;
-}
-
-//-----------------------------------------------------------------------------
-// Decodes the distance of the repetition, backwards relative to the
-// current output buffer position
-
-static unsigned int PKWAREAPI DecodeDist(TDcmpStruct * pWork, unsigned int rep_length)
-{
- unsigned int dist_pos_code; // Distance position code
- unsigned int dist_pos_bits; // Number of bits of distance position
- unsigned int distance; // Distance position
-
- // Next 2-8 bits in the input buffer is the distance position code
- dist_pos_code = pWork->DistPosCodes[pWork->bit_buff & 0xFF];
- dist_pos_bits = pWork->DistBits[dist_pos_code];
- if(WasteBits(pWork, dist_pos_bits))
- return 0;
-
- if(rep_length == 2)
- {
- // If the repetition is only 2 bytes length,
- // then take 2 bits from the stream in order to get the distance
- distance = (dist_pos_code << 2) | (pWork->bit_buff & 0x03);
- if(WasteBits(pWork, 2))
- return 0;
- }
- else
- {
- // If the repetition is more than 2 bytes length,
- // then take "dsize_bits" bits in order to get the distance
- distance = (dist_pos_code << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask);
- if(WasteBits(pWork, pWork->dsize_bits))
- return 0;
- }
- return distance + 1;
-}
-
-static unsigned int PKWAREAPI Expand(TDcmpStruct * pWork)
-{
- unsigned int next_literal; // Literal decoded from the compressed data
- unsigned int result; // Value to be returned
- unsigned int copyBytes; // Number of bytes to copy to the output buffer
-
- pWork->outputPos = 0x1000; // Initialize output buffer position
-
- // Decode the next literal from the input data.
- // The returned literal can either be an uncompressed byte (next_literal < 0x100)
- // or an encoded length of the repeating byte sequence that
- // is to be copied to the current buffer position
- while((result = next_literal = DecodeLit(pWork)) < 0x305)
- {
- // If the literal is greater than 0x100, it holds length
- // of repeating byte sequence
- // literal of 0x100 means repeating sequence of 0x2 bytes
- // literal of 0x101 means repeating sequence of 0x3 bytes
- // ...
- // literal of 0x305 means repeating sequence of 0x207 bytes
- if(next_literal >= 0x100)
- {
- unsigned char * source;
- unsigned char * target;
- unsigned int rep_length; // Length of the repetition, in bytes
- unsigned int minus_dist; // Backward distance to the repetition, relative to the current buffer position
-
- // Get the length of the repeating sequence.
- // Note that the repeating block may overlap the current output position,
- // for example if there was a sequence of equal bytes
- rep_length = next_literal - 0xFE;
-
- // Get backward distance to the repetition
- if((minus_dist = DecodeDist(pWork, rep_length)) == 0)
- {
- result = 0x306;
- break;
- }
-
- // Target and source pointer
- target = &pWork->out_buff[pWork->outputPos];
- source = target - minus_dist;
-
- // Update buffer output position
- pWork->outputPos += rep_length;
-
- // Copy the repeating sequence
- while(rep_length-- > 0)
- *target++ = *source++;
- }
- else
- {
- pWork->out_buff[pWork->outputPos++] = (unsigned char)next_literal;
- }
-
- // Flush the output buffer, if number of extracted bytes has reached the end
- if(pWork->outputPos >= 0x2000)
- {
- // Copy decompressed data into user buffer
- copyBytes = 0x1000;
- pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param);
-
- // Now copy the decompressed data to the first half of the buffer.
- // This is needed because the decompression might reuse them as repetitions.
- // Note that if the output buffer overflowed previously, the extra decompressed bytes
- // are stored in "out_buff_overflow", and they will now be
- // within decompressed part of the output buffer.
- memmove(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);
- pWork->outputPos -= 0x1000;
- }
- }
-
- // Flush any remaining decompressed bytes
- copyBytes = pWork->outputPos - 0x1000;
- pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param);
- return result;
-}
-
-
-//-----------------------------------------------------------------------------
-// Main exploding function.
-
-unsigned int PKWAREAPI explode(
- unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param),
- void (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param),
- char *work_buf,
- void *param)
-{
- TDcmpStruct * pWork = (TDcmpStruct *)work_buf;
-
- // Initialize work struct and load compressed data
- // Note: The caller must zero the "work_buff" before passing it to explode
- pWork->read_buf = read_buf;
- pWork->write_buf = write_buf;
- pWork->param = param;
- pWork->in_pos = sizeof(pWork->in_buff);
- pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param);
- if(pWork->in_bytes <= 4)
- return CMP_BAD_DATA;
-
- pWork->ctype = pWork->in_buff[0]; // Get the compression type (CMP_BINARY or CMP_ASCII)
- pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size
- pWork->bit_buff = pWork->in_buff[2]; // Initialize 16-bit bit buffer
- pWork->extra_bits = 0; // Extra (over 8) bits
- pWork->in_pos = 3; // Position in input buffer
-
- // Test for the valid dictionary size
- if(4 > pWork->dsize_bits || pWork->dsize_bits > 6)
- return CMP_INVALID_DICTSIZE;
-
- pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction
-
- if(pWork->ctype != CMP_BINARY)
- {
- if(pWork->ctype != CMP_ASCII)
- return CMP_INVALID_MODE;
-
- memcpy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc));
- GenAscTabs(pWork);
- }
-
- memcpy(pWork->LenBits, LenBits, sizeof(pWork->LenBits));
- GenDecodeTabs(pWork->LengthCodes, LenCode, pWork->LenBits, sizeof(pWork->LenBits));
- memcpy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits));
- memcpy(pWork->LenBase, LenBase, sizeof(pWork->LenBase));
- memcpy(pWork->DistBits, DistBits, sizeof(pWork->DistBits));
- GenDecodeTabs(pWork->DistPosCodes, DistCode, pWork->DistBits, sizeof(pWork->DistBits));
- if(Expand(pWork) != 0x306)
- return CMP_NO_ERROR;
-
- return CMP_ABORT;
-}
diff --git a/3rdParty/PKWare/implode.cpp b/3rdParty/PKWare/implode.cpp
deleted file mode 100644
index 2ea8949d6..000000000
--- a/3rdParty/PKWare/implode.cpp
+++ /dev/null
@@ -1,775 +0,0 @@
-/*****************************************************************************/
-/* implode.cpp Copyright (c) Ladislav Zezula 2003 */
-/*---------------------------------------------------------------------------*/
-/* Implode function of PKWARE Data Compression library */
-/*---------------------------------------------------------------------------*/
-/* Date Ver Who Comment */
-/* -------- ---- --- ------- */
-/* 11.04.03 1.00 Lad First version of implode.cpp */
-/* 02.05.03 1.00 Lad Stress test done */
-/* 22.04.10 1.01 Lad Documented */
-/*****************************************************************************/
-
-#include
-#include
-
-#include "pkware.h"
-
-#if ((1200 < _MSC_VER) && (_MSC_VER < 1400))
-#pragma optimize("", off)
-#endif
-
-//-----------------------------------------------------------------------------
-// Defines
-
-#define MAX_REP_LENGTH 0x204 // The longest allowed repetition
-
-static char CopyrightPkware[] = "PKWARE Data Compression Library for Win32\r\n"
- "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
- "Patent No. 5,051,745\r\n"
- "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
- "Version 1.11\r\n";
-
-//-----------------------------------------------------------------------------
-// Tables
-
-static unsigned char DistBits[] =
-{
- 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
- 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
- 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
-};
-
-static unsigned char DistCode[] =
-{
- 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
- 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
- 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
- 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
-};
-
-static unsigned char ExLenBits[] =
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
-};
-
-static unsigned char LenBits[] =
-{
- 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
-};
-
-static unsigned char LenCode[] =
-{
- 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
-};
-
-static unsigned char ChBitsAsc[] =
-{
- 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
- 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
- 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
- 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
- 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
- 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
- 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
- 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
-};
-
-static unsigned short ChCodeAsc[] =
-{
- 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
- 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
- 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
- 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
- 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
- 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
- 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
- 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
- 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
- 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
- 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
- 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
- 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
- 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
- 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
- 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
- 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
- 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
- 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
- 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
- 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
- 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
- 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
- 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
- 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
- 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
- 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
- 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
- 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
- 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
- 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
- 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
-};
-
-//-----------------------------------------------------------------------------
-// Macros
-
-// Macro for calculating hash of the current byte pair.
-// Note that most exact byte pair hash would be buffer[0] + buffer[1] << 0x08,
-// but even this way gives nice indication of equal byte pairs, with significantly
-// smaller size of the array that holds numbers of those hashes
-#define BYTE_PAIR_HASH(buffer) ((buffer[0] * 4) + (buffer[1] * 5))
-
-//-----------------------------------------------------------------------------
-// Local functions
-
-// Builds the "hash_to_index" table and "pair_hash_offsets" table.
-// Every element of "hash_to_index" will contain lowest index to the
-// "pair_hash_offsets" table, effectively giving offset of the first
-// occurence of the given PAIR_HASH in the input data.
-static void PKWAREAPI SortBuffer(TCmpStruct * pWork, unsigned char * buffer_begin, unsigned char * buffer_end)
-{
- unsigned short * phash_to_index;
- unsigned char * buffer_ptr;
- unsigned short total_sum = 0;
- unsigned long byte_pair_hash; // Hash value of the byte pair
- unsigned short byte_pair_offs; // Offset of the byte pair, relative to "work_buff"
-
- // Zero the entire "phash_to_index" table
- memset(pWork->phash_to_index, 0, sizeof(pWork->phash_to_index));
-
- // Step 1: Count amount of each PAIR_HASH in the input buffer
- // The table will look like this:
- // offs 0x000: Number of occurences of PAIR_HASH 0
- // offs 0x001: Number of occurences of PAIR_HASH 1
- // ...
- // offs 0x8F7: Number of occurences of PAIR_HASH 0x8F7 (the highest hash value)
- for(buffer_ptr = buffer_begin; buffer_ptr < buffer_end; buffer_ptr++)
- pWork->phash_to_index[BYTE_PAIR_HASH(buffer_ptr)]++;
-
- // Step 2: Convert the table to the array of PAIR_HASH amounts.
- // Each element contains count of PAIR_HASHes that is less or equal
- // to element index
- // The table will look like this:
- // offs 0x000: Number of occurences of PAIR_HASH 0 or lower
- // offs 0x001: Number of occurences of PAIR_HASH 1 or lower
- // ...
- // offs 0x8F7: Number of occurences of PAIR_HASH 0x8F7 or lower
- for(phash_to_index = pWork->phash_to_index; phash_to_index < &pWork->phash_to_index_end; phash_to_index++)
- {
- total_sum = total_sum + phash_to_index[0];
- phash_to_index[0] = total_sum;
- }
-
- // Step 3: Convert the table to the array of indexes.
- // Now, each element contains index to the first occurence of given PAIR_HASH
- for(buffer_end--; buffer_end >= buffer_begin; buffer_end--)
- {
- byte_pair_hash = BYTE_PAIR_HASH(buffer_end);
- byte_pair_offs = (unsigned short)(buffer_end - pWork->work_buff);
-
- pWork->phash_to_index[byte_pair_hash]--;
- pWork->phash_offs[pWork->phash_to_index[byte_pair_hash]] = byte_pair_offs;
- }
-}
-
-static void PKWAREAPI FlushBuf(TCmpStruct * pWork)
-{
- unsigned char save_ch1;
- unsigned char save_ch2;
- unsigned int size = 0x800;
-
- pWork->write_buf(pWork->out_buff, &size, pWork->param);
-
- save_ch1 = pWork->out_buff[0x800];
- save_ch2 = pWork->out_buff[pWork->out_bytes];
- pWork->out_bytes -= 0x800;
-
- memset(pWork->out_buff, 0, sizeof(pWork->out_buff));
-
- if(pWork->out_bytes != 0)
- pWork->out_buff[0] = save_ch1;
- if(pWork->out_bits != 0)
- pWork->out_buff[pWork->out_bytes] = save_ch2;
-}
-
-static void PKWAREAPI OutputBits(TCmpStruct * pWork, unsigned int nbits, unsigned long bit_buff)
-{
- unsigned int out_bits;
-
- // If more than 8 bits to output, do recursion
- if(nbits > 8)
- {
- OutputBits(pWork, 8, bit_buff);
- bit_buff >>= 8;
- nbits -= 8;
- }
-
- // Add bits to the last out byte in out_buff;
- out_bits = pWork->out_bits;
- pWork->out_buff[pWork->out_bytes] |= (unsigned char)(bit_buff << out_bits);
- pWork->out_bits += nbits;
-
- // If 8 or more bits, increment number of bytes
- if(pWork->out_bits > 8)
- {
- pWork->out_bytes++;
- bit_buff >>= (8 - out_bits);
-
- pWork->out_buff[pWork->out_bytes] = (unsigned char)bit_buff;
- pWork->out_bits &= 7;
- }
- else
- {
- pWork->out_bits &= 7;
- if(pWork->out_bits == 0)
- pWork->out_bytes++;
- }
-
- // If there is enough compressed bytes, flush them
- if(pWork->out_bytes >= 0x800)
- FlushBuf(pWork);
-}
-
-// This function searches for a repetition
-// (a previous occurence of the current byte sequence)
-// Returns length of the repetition, and stores the backward distance
-// to pWork structure.
-static unsigned int PKWAREAPI FindRep(TCmpStruct * pWork, unsigned char * input_data)
-{
- unsigned short * phash_to_index; // Pointer into pWork->phash_to_index table
- unsigned short * phash_offs; // Pointer to the table containing offsets of each PAIR_HASH
- unsigned char * repetition_limit; // An eventual repetition must be at position below this pointer
- unsigned char * prev_repetition; // Pointer to the previous occurence of the current PAIR_HASH
- unsigned char * prev_rep_end; // End of the previous repetition
- unsigned char * input_data_ptr;
- unsigned short phash_offs_index; // Index to the table with PAIR_HASH positions
- unsigned short min_phash_offs; // The lowest allowed hash offset
- unsigned short offs_in_rep; // Offset within found repetition
- unsigned int equal_byte_count; // Number of bytes that are equal to the previous occurence
- unsigned int rep_length = 1; // Length of the found repetition
- unsigned int rep_length2; // Secondary repetition
- unsigned char pre_last_byte; // Last but one byte from a repetion
- unsigned short di_val;
-
- // Calculate the previous position of the PAIR_HASH
- phash_to_index = pWork->phash_to_index + BYTE_PAIR_HASH(input_data);
- min_phash_offs = (unsigned short)((input_data - pWork->work_buff) - pWork->dsize_bytes + 1);
- phash_offs_index = phash_to_index[0];
-
- // If the PAIR_HASH offset is below the limit, find a next one
- phash_offs = pWork->phash_offs + phash_offs_index;
- if(*phash_offs < min_phash_offs)
- {
- while(*phash_offs < min_phash_offs)
- {
- phash_offs_index++;
- phash_offs++;
- }
- *phash_to_index = phash_offs_index;
- }
-
- // Get the first location of the PAIR_HASH,
- // and thus the first eventual location of byte repetition
- phash_offs = pWork->phash_offs + phash_offs_index;
- prev_repetition = pWork->work_buff + phash_offs[0];
- repetition_limit = input_data - 1;
-
- // If the current PAIR_HASH was not encountered before,
- // we haven't found a repetition.
- if(prev_repetition >= repetition_limit)
- return 0;
-
- // We have found a match of a PAIR_HASH. Now we have to make sure
- // that it is also a byte match, because PAIR_HASH is not unique.
- // We compare the bytes and count the length of the repetition
- input_data_ptr = input_data;
- for(;;)
- {
- // If the first byte of the repetition and the so-far-last byte
- // of the repetition are equal, we will compare the blocks.
- if(*input_data_ptr == *prev_repetition && input_data_ptr[rep_length-1] == prev_repetition[rep_length-1])
- {
- // Skip the current byte
- prev_repetition++;
- input_data_ptr++;
- equal_byte_count = 2;
-
- // Now count how many more bytes are equal
- while(equal_byte_count < MAX_REP_LENGTH)
- {
- prev_repetition++;
- input_data_ptr++;
-
- // Are the bytes different ?
- if(*prev_repetition != *input_data_ptr)
- break;
-
- equal_byte_count++;
- }
-
- // If we found a repetition of at least the same length, take it.
- // If there are multiple repetitions in the input buffer, this will
- // make sure that we find the most recent one, which in turn allows
- // us to store backward length in less amount of bits
- input_data_ptr = input_data;
- if(equal_byte_count >= rep_length)
- {
- // Calculate the backward distance of the repetition.
- // Note that the distance is stored as decremented by 1
- pWork->distance = (unsigned int)(input_data - prev_repetition + equal_byte_count - 1);
-
- // Repetitions longer than 10 bytes will be stored in more bits,
- // so they need a bit different handling
- if((rep_length = equal_byte_count) > 10)
- break;
- }
- }
-
- // Move forward in the table of PAIR_HASH repetitions.
- // There might be a more recent occurence of the same repetition.
- phash_offs_index++;
- phash_offs++;
- prev_repetition = pWork->work_buff + phash_offs[0];
-
- // If the next repetition is beyond the minimum allowed repetition, we are done.
- if(prev_repetition >= repetition_limit)
- {
- // A repetition must have at least 2 bytes, otherwise it's not worth it
- return (rep_length >= 2) ? rep_length : 0;
- }
- }
-
- // If the repetition has max length of 0x204 bytes, we can't go any fuhrter
- if(equal_byte_count == MAX_REP_LENGTH)
- {
- pWork->distance--;
- return equal_byte_count;
- }
-
- // Check for possibility of a repetition that occurs at more recent position
- phash_offs = pWork->phash_offs + phash_offs_index;
- if(pWork->work_buff + phash_offs[1] >= repetition_limit)
- return rep_length;
-
- //
- // The following part checks if there isn't a longer repetition at
- // a latter offset, that would lead to better compression.
- //
- // Example of data that can trigger this optimization:
- //
- // "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEQQQQQQQQQQQQ"
- // "XYZ"
- // "EEEEEEEEEEEEEEEEQQQQQQQQQQQQ";
- //
- // Description of data in this buffer
- // [0x00] Single byte "E"
- // [0x01] Single byte "E"
- // [0x02] Repeat 0x1E bytes from [0x00]
- // [0x20] Single byte "X"
- // [0x21] Single byte "Y"
- // [0x22] Single byte "Z"
- // [0x23] 17 possible previous repetitions of length at least 0x10 bytes:
- // - Repetition of 0x10 bytes from [0x00] "EEEEEEEEEEEEEEEE"
- // - Repetition of 0x10 bytes from [0x01] "EEEEEEEEEEEEEEEE"
- // - Repetition of 0x10 bytes from [0x02] "EEEEEEEEEEEEEEEE"
- // ...
- // - Repetition of 0x10 bytes from [0x0F] "EEEEEEEEEEEEEEEE"
- // - Repetition of 0x1C bytes from [0x10] "EEEEEEEEEEEEEEEEQQQQQQQQQQQQ"
- // The last repetition is the best one.
- //
-
- pWork->offs09BC[0] = 0xFFFF;
- pWork->offs09BC[1] = 0x0000;
- di_val = 0;
-
- // Note: I failed to figure out what does the table "offs09BC" mean.
- // If anyone has an idea, let me know to zezula_at_volny_dot_cz
- for(offs_in_rep = 1; offs_in_rep < rep_length; )
- {
- if(input_data[offs_in_rep] != input_data[di_val])
- {
- di_val = pWork->offs09BC[di_val];
- if(di_val != 0xFFFF)
- continue;
- }
- pWork->offs09BC[++offs_in_rep] = ++di_val;
- }
-
- //
- // Now go through all the repetitions from the first found one
- // to the current input data, and check if any of them migh be
- // a start of a greater sequence match.
- //
-
- prev_repetition = pWork->work_buff + phash_offs[0];
- prev_rep_end = prev_repetition + rep_length;
- rep_length2 = rep_length;
-
- for(;;)
- {
- rep_length2 = pWork->offs09BC[rep_length2];
- if(rep_length2 == 0xFFFF)
- rep_length2 = 0;
-
- // Get the pointer to the previous repetition
- phash_offs = pWork->phash_offs + phash_offs_index;
-
- // Skip those repetitions that don't reach the end
- // of the first found repetition
- do
- {
- phash_offs++;
- phash_offs_index++;
- prev_repetition = pWork->work_buff + *phash_offs;
- if(prev_repetition >= repetition_limit)
- return rep_length;
- }
- while(prev_repetition + rep_length2 < prev_rep_end);
-
- // Verify if the last but one byte from the repetition matches
- // the last but one byte from the input data.
- // If not, find a next repetition
- pre_last_byte = input_data[rep_length - 2];
- if(pre_last_byte == prev_repetition[rep_length - 2])
- {
- // If the new repetition reaches beyond the end
- // of previously found repetition, reset the repetition length to zero.
- if(prev_repetition + rep_length2 != prev_rep_end)
- {
- prev_rep_end = prev_repetition;
- rep_length2 = 0;
- }
- }
- else
- {
- phash_offs = pWork->phash_offs + phash_offs_index;
- do
- {
- phash_offs++;
- phash_offs_index++;
- prev_repetition = pWork->work_buff + *phash_offs;
- if(prev_repetition >= repetition_limit)
- return rep_length;
- }
- while(prev_repetition[rep_length - 2] != pre_last_byte || prev_repetition[0] != input_data[0]);
-
- // Reset the length of the repetition to 2 bytes only
- prev_rep_end = prev_repetition + 2;
- rep_length2 = 2;
- }
-
- // Find out how many more characters are equal to the first repetition.
- while(*prev_rep_end == input_data[rep_length2])
- {
- if(++rep_length2 >= 0x204)
- break;
- prev_rep_end++;
- }
-
- // Is the newly found repetion at least as long as the previous one ?
- if(rep_length2 >= rep_length)
- {
- // Calculate the distance of the new repetition
- pWork->distance = (unsigned int)(input_data - prev_repetition - 1);
- if((rep_length = rep_length2) == 0x204)
- return rep_length;
-
- // Update the additional elements in the "offs09BC" table
- // to reflect new rep length
- while(offs_in_rep < rep_length2)
- {
- if(input_data[offs_in_rep] != input_data[di_val])
- {
- di_val = pWork->offs09BC[di_val];
- if(di_val != 0xFFFF)
- continue;
- }
- pWork->offs09BC[++offs_in_rep] = ++di_val;
- }
- }
- }
-}
-
-static void PKWAREAPI WriteCmpData(TCmpStruct * pWork)
-{
- unsigned char * input_data_end; // Pointer to the end of the input data
- unsigned char * input_data = pWork->work_buff + pWork->dsize_bytes + 0x204;
- unsigned int input_data_ended = 0; // If 1, then all data from the input stream have been already loaded
- unsigned int save_rep_length; // Saved length of current repetition
- unsigned int save_distance = 0; // Saved distance of current repetition
- unsigned int rep_length; // Length of the found repetition
- unsigned int phase = 0; //
-
- // Store the compression type and dictionary size
- pWork->out_buff[0] = (char)pWork->ctype;
- pWork->out_buff[1] = (char)pWork->dsize_bits;
- pWork->out_bytes = 2;
-
- // Reset output buffer to zero
- memset(&pWork->out_buff[2], 0, sizeof(pWork->out_buff) - 2);
- pWork->out_bits = 0;
-
- while(input_data_ended == 0)
- {
- unsigned int bytes_to_load = 0x1000;
- int total_loaded = 0;
- int bytes_loaded;
-
- // Load the bytes from the input stream, up to 0x1000 bytes
- while(bytes_to_load != 0)
- {
- bytes_loaded = pWork->read_buf((char *)pWork->work_buff + pWork->dsize_bytes + 0x204 + total_loaded,
- &bytes_to_load,
- pWork->param);
- if(bytes_loaded == 0)
- {
- if(total_loaded == 0 && phase == 0)
- goto __Exit;
- input_data_ended = 1;
- break;
- }
- else
- {
- bytes_to_load -= bytes_loaded;
- total_loaded += bytes_loaded;
- }
- }
-
- input_data_end = pWork->work_buff + pWork->dsize_bytes + total_loaded;
- if(input_data_ended)
- input_data_end += 0x204;
-
- //
- // Warning: The end of the buffer passed to "SortBuffer" is actually 2 bytes beyond
- // valid data. It is questionable if this is actually a bug or not,
- // but it might cause the compressed data output to be dependent on random bytes
- // that are in the buffer.
- // To prevent that, the calling application must always zero the compression
- // buffer before passing it to "implode"
- //
-
- // Search the PAIR_HASHes of the loaded blocks. Also, include
- // previously compressed data, if any.
- switch(phase)
- {
- case 0:
- SortBuffer(pWork, input_data, input_data_end + 1);
- phase++;
- if(pWork->dsize_bytes != 0x1000)
- phase++;
- break;
-
- case 1:
- SortBuffer(pWork, input_data - pWork->dsize_bytes + 0x204, input_data_end + 1);
- phase++;
- break;
-
- default:
- SortBuffer(pWork, input_data - pWork->dsize_bytes, input_data_end + 1);
- break;
- }
-
- // Perform the compression of the current block
- while(input_data < input_data_end)
- {
- // Find if the current byte sequence wasn't there before.
- rep_length = FindRep(pWork, input_data);
- while(rep_length != 0)
- {
- // If we found repetition of 2 bytes, that is 0x100 or fuhrter back,
- // don't bother. Storing the distance of 0x100 bytes would actually
- // take more space than storing the 2 bytes as-is.
- if(rep_length == 2 && pWork->distance >= 0x100)
- break;
-
- // When we are at the end of the input data, we cannot allow
- // the repetition to go past the end of the input data.
- if(input_data_ended && input_data + rep_length > input_data_end)
- {
- // Shorten the repetition length so that it only covers valid data
- rep_length = (unsigned long)(input_data_end - input_data);
- if(rep_length < 2)
- break;
-
- // If we got repetition of 2 bytes, that is 0x100 or more backward, don't bother
- if(rep_length == 2 && pWork->distance >= 0x100)
- break;
- goto __FlushRepetition;
- }
-
- if(rep_length >= 8 || input_data + 1 >= input_data_end)
- goto __FlushRepetition;
-
- // Try to find better repetition 1 byte later.
- // Example: "ARROCKFORT" "AROCKFORT"
- // When "input_data" points to the second string, FindRep
- // returns the occurence of "AR". But there is longer repetition "ROCKFORT",
- // beginning 1 byte after.
- save_rep_length = rep_length;
- save_distance = pWork->distance;
- rep_length = FindRep(pWork, input_data + 1);
-
- // Only use the new repetition if it's length is greater than the previous one
- if(rep_length > save_rep_length)
- {
- // If the new repetition if only 1 byte better
- // and the previous distance is less than 0x80 bytes, use the previous repetition
- if(rep_length > save_rep_length + 1 || save_distance > 0x80)
- {
- // Flush one byte, so that input_data will point to the secondary repetition
- OutputBits(pWork, pWork->nChBits[*input_data], pWork->nChCodes[*input_data]);
- input_data++;
- continue;
- }
- }
-
- // Revert to the previous repetition
- rep_length = save_rep_length;
- pWork->distance = save_distance;
-
- __FlushRepetition:
-
- OutputBits(pWork, pWork->nChBits[rep_length + 0xFE], pWork->nChCodes[rep_length + 0xFE]);
- if(rep_length == 2)
- {
- OutputBits(pWork, pWork->dist_bits[pWork->distance >> 2],
- pWork->dist_codes[pWork->distance >> 2]);
- OutputBits(pWork, 2, pWork->distance & 3);
- }
- else
- {
- OutputBits(pWork, pWork->dist_bits[pWork->distance >> pWork->dsize_bits],
- pWork->dist_codes[pWork->distance >> pWork->dsize_bits]);
- OutputBits(pWork, pWork->dsize_bits, pWork->dsize_mask & pWork->distance);
- }
-
- // Move the begin of the input data by the length of the repetition
- input_data += rep_length;
- goto _00402252;
- }
-
- // If there was no previous repetition for the current position in the input data,
- // just output the 9-bit literal for the one character
- OutputBits(pWork, pWork->nChBits[*input_data], pWork->nChCodes[*input_data]);
- input_data++;
-_00402252:;
- }
-
- if(input_data_ended == 0)
- {
- input_data -= 0x1000;
- memmove(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + 0x204);
- }
- }
-
-__Exit:
-
- // Write the termination literal
- OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
- if(pWork->out_bits != 0)
- pWork->out_bytes++;
- pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
- return;
-}
-
-//-----------------------------------------------------------------------------
-// Main imploding function
-
-unsigned int PKWAREAPI implode(
- unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param),
- void (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param),
- char *work_buf,
- void *param,
- unsigned int *type,
- unsigned int *dsize)
-{
- TCmpStruct * pWork = (TCmpStruct *)work_buf;
- unsigned int nChCode;
- unsigned int nCount;
- unsigned int i;
- int nCount2;
-
- // Fill the work buffer information
- // Note: The caller must zero the "work_buff" before passing it to implode
- pWork->read_buf = read_buf;
- pWork->write_buf = write_buf;
- pWork->dsize_bytes = *dsize;
- pWork->ctype = *type;
- pWork->param = param;
- pWork->dsize_bits = 4;
- pWork->dsize_mask = 0x0F;
-
- // Test dictionary size
- switch(*dsize)
- {
- case CMP_IMPLODE_DICT_SIZE3: // 0x1000 bytes
- pWork->dsize_bits++;
- pWork->dsize_mask |= 0x20;
- // No break here !!!
-
- case CMP_IMPLODE_DICT_SIZE2: // 0x800 bytes
- pWork->dsize_bits++;
- pWork->dsize_mask |= 0x10;
- // No break here !!!
-
- case CMP_IMPLODE_DICT_SIZE1: // 0x400
- break;
-
- default:
- return CMP_INVALID_DICTSIZE;
- }
-
- // Test the compression type
- switch(*type)
- {
- case CMP_BINARY: // We will compress data with binary compression type
- for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++)
- {
- pWork->nChBits[nCount] = 9;
- pWork->nChCodes[nCount] = (unsigned short)nChCode;
- nChCode = (nChCode & 0x0000FFFF) + 2;
- }
- break;
-
-
- case CMP_ASCII: // We will compress data with ASCII compression type
- for(nCount = 0; nCount < 0x100; nCount++)
- {
- pWork->nChBits[nCount] = (unsigned char )(ChBitsAsc[nCount] + 1);
- pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2);
- }
- break;
-
- default:
- return CMP_INVALID_MODE;
- }
-
- for(i = 0; i < 0x10; i++)
- {
- if(1 << ExLenBits[i])
- {
- for(nCount2 = 0; nCount2 < (1 << ExLenBits[i]); nCount2++)
- {
- pWork->nChBits[nCount] = (unsigned char)(ExLenBits[i] + LenBits[i] + 1);
- pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1);
- nCount++;
- }
- }
- }
-
- // Copy the distance codes and distance bits and perform the compression
- memcpy(&pWork->dist_codes, DistCode, sizeof(DistCode));
- memcpy(&pWork->dist_bits, DistBits, sizeof(DistBits));
- WriteCmpData(pWork);
- return CMP_NO_ERROR;
-}
diff --git a/3rdParty/PKWare/pkware.h b/3rdParty/PKWare/pkware.h
deleted file mode 100644
index 37ec0b808..000000000
--- a/3rdParty/PKWare/pkware.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/*****************************************************************************/
-/* pkware.h Copyright (c) Ladislav Zezula 2003 */
-/*---------------------------------------------------------------------------*/
-/* Header file for PKWARE Data Compression Library */
-/*---------------------------------------------------------------------------*/
-/* Date Ver Who Comment */
-/* -------- ---- --- ------- */
-/* 31.03.03 1.00 Lad The first version of pkware.h */
-/*****************************************************************************/
-
-#ifndef __PKWARE_H__
-#define __PKWARE_H__
-
-//-----------------------------------------------------------------------------
-// Defines
-
-#define CMP_BINARY 0 // Binary compression
-#define CMP_ASCII 1 // Ascii compression
-
-#define CMP_NO_ERROR 0
-#define CMP_INVALID_DICTSIZE 1
-#define CMP_INVALID_MODE 2
-#define CMP_BAD_DATA 3
-#define CMP_ABORT 4
-
-#define CMP_IMPLODE_DICT_SIZE1 1024 // Dictionary size of 1024
-#define CMP_IMPLODE_DICT_SIZE2 2048 // Dictionary size of 2048
-#define CMP_IMPLODE_DICT_SIZE3 4096 // Dictionary size of 4096
-
-//-----------------------------------------------------------------------------
-// Define calling convention
-
-#ifndef PKWAREAPI
-#ifdef WIN32
-#define PKWAREAPI __cdecl // Use for normal __cdecl calling
-#else
-#define PKWAREAPI
-#endif
-#endif
-
-//-----------------------------------------------------------------------------
-// Internal structures
-
-// Compression structure
-typedef struct
-{
- unsigned int distance; // 0000: Backward distance of the currently found repetition, decreased by 1
- unsigned int out_bytes; // 0004: # bytes available in out_buff
- unsigned int out_bits; // 0008: # of bits available in the last out byte
- unsigned int dsize_bits; // 000C: Number of bits needed for dictionary size. 4 = 0x400, 5 = 0x800, 6 = 0x1000
- unsigned int dsize_mask; // 0010: Bit mask for dictionary. 0x0F = 0x400, 0x1F = 0x800, 0x3F = 0x1000
- unsigned int ctype; // 0014: Compression type (CMP_ASCII or CMP_BINARY)
- unsigned int dsize_bytes; // 0018: Dictionary size in bytes
- unsigned char dist_bits[0x40]; // 001C: Distance bits
- unsigned char dist_codes[0x40]; // 005C: Distance codes
- unsigned char nChBits[0x306]; // 009C: Table of literal bit lengths to be put to the output stream
- unsigned short nChCodes[0x306]; // 03A2: Table of literal codes to be put to the output stream
- unsigned short offs09AE; // 09AE:
-
- void * param; // 09B0: User parameter
- unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param); // 9B4
- void (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param); // 9B8
-
- unsigned short offs09BC[0x204]; // 09BC:
- unsigned long offs0DC4; // 0DC4:
- unsigned short phash_to_index[0x900]; // 0DC8: Array of indexes (one for each PAIR_HASH) to the "pair_hash_offsets" table
- unsigned short phash_to_index_end; // 1FC8: End marker for "phash_to_index" table
- char out_buff[0x802]; // 1FCA: Compressed data
- unsigned char work_buff[0x2204]; // 27CC: Work buffer
- // + DICT_OFFSET => Dictionary
- // + UNCMP_OFFSET => Uncompressed data
- unsigned short phash_offs[0x2204]; // 49D0: Table of offsets for each PAIR_HASH
-} TCmpStruct;
-
-#define CMP_BUFFER_SIZE sizeof(TCmpStruct) // Size of compression structure.
- // Defined as 36312 in pkware header file
-
-
-// Decompression structure
-typedef struct
-{
- unsigned long offs0000; // 0000
- unsigned long ctype; // 0004: Compression type (CMP_BINARY or CMP_ASCII)
- unsigned long outputPos; // 0008: Position in output buffer
- unsigned long dsize_bits; // 000C: Dict size (4, 5, 6 for 0x400, 0x800, 0x1000)
- unsigned long dsize_mask; // 0010: Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000)
- unsigned long bit_buff; // 0014: 16-bit buffer for processing input data
- unsigned long extra_bits; // 0018: Number of extra (above 8) bits in bit buffer
- unsigned int in_pos; // 001C: Position in in_buff
- unsigned long in_bytes; // 0020: Number of bytes in input buffer
- void * param; // 0024: Custom parameter
- unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param); // Pointer to function that reads data from the input stream
- void (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param);// Pointer to function that writes data to the output stream
-
- unsigned char out_buff[0x2204]; // 0030: Output circle buffer.
- // 0x0000 - 0x0FFF: Previous uncompressed data, kept for repetitions
- // 0x1000 - 0x1FFF: Currently decompressed data
- // 0x2000 - 0x2203: Reserve space for the longest possible repetition
- unsigned char in_buff[0x800]; // 2234: Buffer for data to be decompressed
- unsigned char DistPosCodes[0x100]; // 2A34: Table of distance position codes
- unsigned char LengthCodes[0x100]; // 2B34: Table of length codes
- unsigned char offs2C34[0x100]; // 2C34: Buffer for
- unsigned char offs2D34[0x100]; // 2D34: Buffer for
- unsigned char offs2E34[0x80]; // 2EB4: Buffer for
- unsigned char offs2EB4[0x100]; // 2EB4: Buffer for
- unsigned char ChBitsAsc[0x100]; // 2FB4: Buffer for
- unsigned char DistBits[0x40]; // 30B4: Numbers of bytes to skip copied block length
- unsigned char LenBits[0x10]; // 30F4: Numbers of bits for skip copied block length
- unsigned char ExLenBits[0x10]; // 3104: Number of valid bits for copied block
- unsigned short LenBase[0x10]; // 3114: Buffer for
-} TDcmpStruct;
-
-#define EXP_BUFFER_SIZE sizeof(TDcmpStruct) // Size of decompression structure
- // Defined as 12596 in pkware headers
-
-//-----------------------------------------------------------------------------
-// Public functions
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-unsigned int PKWAREAPI implode(
- unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param),
- void (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param),
- char *work_buf,
- void *param,
- unsigned int *type,
- unsigned int *dsize);
-
-
-unsigned int PKWAREAPI explode(
- unsigned int (PKWAREAPI *read_buf)(char *buf, unsigned int *size, void *param),
- void (PKWAREAPI *write_buf)(char *buf, unsigned int *size, void *param),
- char *work_buf,
- void *param);
-
-#ifdef __cplusplus
- } // End of 'extern "C"' declaration
-#endif
-
-#endif // __PKWARE_H__
diff --git a/3rdParty/libmpq/CMakeLists.txt b/3rdParty/libmpq/CMakeLists.txt
deleted file mode 100644
index ad6cd4ad2..000000000
--- a/3rdParty/libmpq/CMakeLists.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-if(NOT TARGET ZLIB::ZLIB)
- find_package(ZLIB REQUIRED)
-endif()
-
-if(NOT TARGET BZip2::BZip2)
- find_package(BZip2 REQUIRED)
-endif()
-
-include(functions/FetchContent_ExcludeFromAll_backport)
-
-include(FetchContent)
-FetchContent_Declare_ExcludeFromAll(libmpq
- URL https://github.com/diasurgical/libmpq/archive/7c2924d4553513eba1a70bbdb558198dd8c2726a.tar.gz
- URL_HASH MD5=315c88c02b45851cdfee8460322de044
-)
-FetchContent_MakeAvailable_ExcludeFromAll(libmpq)
-
-add_library(libmpq STATIC
- ${libmpq_SOURCE_DIR}/libmpq/common.c
- ${libmpq_SOURCE_DIR}/libmpq/explode.c
- ${libmpq_SOURCE_DIR}/libmpq/extract.c
- ${libmpq_SOURCE_DIR}/libmpq/huffman.c
- ${libmpq_SOURCE_DIR}/libmpq/mpq.c
- ${libmpq_SOURCE_DIR}/libmpq/wave.c
-)
-
-target_include_directories(libmpq PUBLIC ${libmpq_SOURCE_DIR})
-target_include_directories(libmpq PRIVATE ${CMAKE_CURRENT_LIST_DIR})
-
-target_link_libraries(libmpq PRIVATE ZLIB::ZLIB BZip2::BZip2)
-
-if(LIBMPQ_FILE_BUFFER_SIZE)
- target_compile_definitions(libmpq PRIVATE "LIBMPQ_FILE_BUFFER_SIZE=${LIBMPQ_FILE_BUFFER_SIZE}")
-endif()
-
-if(DEVILUTIONX_WINDOWS_NO_WCHAR)
- target_compile_definitions(libmpq PRIVATE LIBMPQ_WINDOWS_NO_WCHAR)
-endif()
diff --git a/3rdParty/libmpq/config.h b/3rdParty/libmpq/config.h
deleted file mode 100644
index 05abf176b..000000000
--- a/3rdParty/libmpq/config.h
+++ /dev/null
@@ -1 +0,0 @@
-#define VERSION "0.4.2"
diff --git a/3rdParty/mpqfs/CMakeLists.txt b/3rdParty/mpqfs/CMakeLists.txt
new file mode 100644
index 000000000..05a4a5054
--- /dev/null
+++ b/3rdParty/mpqfs/CMakeLists.txt
@@ -0,0 +1,9 @@
+include(functions/FetchContent_ExcludeFromAll_backport)
+
+include(FetchContent)
+
+FetchContent_Declare_ExcludeFromAll(mpqfs
+ URL https://github.com/diasurgical/mpqfs/archive/27144129a5d8f84ddbe058a7c5d7f2c8a724af67.tar.gz
+ URL_HASH MD5=c137f8eb7f5e097c63f9b46769ff2b5c
+)
+FetchContent_MakeAvailable_ExcludeFromAll(mpqfs)
diff --git a/CMake/Dependencies.cmake b/CMake/Dependencies.cmake
index a574210b2..40b50038e 100644
--- a/CMake/Dependencies.cmake
+++ b/CMake/Dependencies.cmake
@@ -13,7 +13,7 @@ else()
endif()
if(SUPPORTS_MPQ)
- # bzip2 is a libmpq dependency.
+ # bzip2 is an mpqfs dependency.
if(EMSCRIPTEN)
emscripten_system_library("bzip2" BZip2::BZip2 USE_BZIP2=1)
else()
@@ -248,7 +248,15 @@ if(WIN32 AND NOT UWP_LIB)
endif()
if(SUPPORTS_MPQ)
- add_subdirectory(3rdParty/libmpq)
+ set(MPQFS_BUILD_TESTS OFF CACHE BOOL "" FORCE)
+ if(USE_SDL1)
+ set(MPQFS_SDL_VERSION "1" CACHE STRING "" FORCE)
+ elseif(USE_SDL3)
+ set(MPQFS_SDL_VERSION "3" CACHE STRING "" FORCE)
+ else()
+ set(MPQFS_SDL_VERSION "2" CACHE STRING "" FORCE)
+ endif()
+ add_subdirectory(3rdParty/mpqfs)
endif()
add_subdirectory(3rdParty/tl)
@@ -301,10 +309,6 @@ else()
add_subdirectory(3rdParty/magic_enum)
endif()
-if(SUPPORTS_MPQ OR NOT NONET)
- add_subdirectory(3rdParty/PKWare)
-endif()
-
if(NOT NONET AND NOT DISABLE_TCP)
add_subdirectory(3rdParty/asio)
endif()
diff --git a/CMake/platforms/n3ds.cmake b/CMake/platforms/n3ds.cmake
index 21dfa48cb..cf39f02cf 100644
--- a/CMake/platforms/n3ds.cmake
+++ b/CMake/platforms/n3ds.cmake
@@ -8,7 +8,6 @@ set(DEVILUTIONX_SYSTEM_LIBFMT OFF)
set(DEVILUTIONX_STATIC_LIBSODIUM ON)
set(DEVILUTIONX_STATIC_LIBFMT ON)
set(DISABLE_ZERO_TIER ON)
-set(LIBMPQ_FILE_BUFFER_SIZE 32768)
set(NOEXIT ON)
# 3DS libraries and compile definitions
diff --git a/CMake/platforms/xbox_nxdk.cmake b/CMake/platforms/xbox_nxdk.cmake
index 9a0137566..43a3dd0c4 100644
--- a/CMake/platforms/xbox_nxdk.cmake
+++ b/CMake/platforms/xbox_nxdk.cmake
@@ -7,6 +7,12 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/xbox_nxdk/finders")
set(DEVILUTIONX_SYSTEM_BZIP2 OFF)
set(DEVILUTIONX_SYSTEM_LIBFMT OFF)
+# Diablo/Hellfire MPQs only use PKWARE DCL implode, not zlib/bzip2.
+# Disable these in mpqfs to avoid pulling in zlib (which fails to build
+# from source on nxdk due to missing ).
+set(MPQFS_USE_ZLIB OFF CACHE BOOL "" FORCE)
+set(MPQFS_USE_BZIP2 OFF CACHE BOOL "" FORCE)
+
set(BUILD_ASSETS_MPQ OFF)
set(DEVILUTIONX_ASSETS_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pkg/assets")
set(DEVILUTIONX_WINDOWS_NO_WCHAR ON)
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 4501d6cc9..aeef1df35 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -589,7 +589,7 @@ if(SUPPORTS_MPQ)
DevilutionX::SDL
fmt::fmt
tl
- libmpq
+ mpqfs::mpqfs
libdevilutionx_file_util
libdevilutionx_logged_fstream
libdevilutionx_pkware_encrypt
@@ -640,7 +640,7 @@ if(SUPPORTS_MPQ OR NOT NONET)
)
target_link_dependencies(libdevilutionx_pkware_encrypt PUBLIC
DevilutionX::SDL
- PKWare
+ mpqfs::mpqfs
)
else()
add_library(libdevilutionx_pkware_encrypt INTERFACE)
diff --git a/Source/encrypt.cpp b/Source/encrypt.cpp
index ca4b6fd41..9e820d080 100644
--- a/Source/encrypt.cpp
+++ b/Source/encrypt.cpp
@@ -3,114 +3,48 @@
*
* Implementation of functions for compression and decompressing MPQ data.
*/
-#include
-#include
#include
#include
#include
-#include
+#include
#include "encrypt.h"
namespace devilution {
-namespace {
-
-struct TDataInfo {
- std::byte *srcData;
- uint32_t srcOffset;
- uint32_t srcSize;
- std::byte *destData;
- uint32_t destOffset;
- size_t destSize;
- bool error;
-};
-
-unsigned int PkwareBufferRead(char *buf, unsigned int *size, void *param) // NOLINT(readability-non-const-parameter)
-{
- auto *pInfo = reinterpret_cast(param);
-
- uint32_t sSize;
- if (*size >= pInfo->srcSize - pInfo->srcOffset) {
- sSize = pInfo->srcSize - pInfo->srcOffset;
- } else {
- sSize = *size;
- }
-
- memcpy(buf, pInfo->srcData + pInfo->srcOffset, sSize);
- pInfo->srcOffset += sSize;
-
- return sSize;
-}
-
-void PkwareBufferWrite(char *buf, unsigned int *size, void *param) // NOLINT(readability-non-const-parameter)
-{
- auto *pInfo = reinterpret_cast(param);
-
- pInfo->error = pInfo->error || pInfo->destOffset + *size > pInfo->destSize;
- if (pInfo->error) {
- return;
- }
-
- memcpy(pInfo->destData + pInfo->destOffset, buf, *size);
- pInfo->destOffset += *size;
-}
-
-} // namespace
-
uint32_t PkwareCompress(std::byte *srcData, uint32_t size)
{
- const std::unique_ptr ptr = std::make_unique(CMP_BUFFER_SIZE);
+ size_t dstCap = size * 2 + 64;
+ auto dst = std::make_unique(dstCap);
+ size_t dstSize = dstCap;
- unsigned destSize = 2 * size;
- if (destSize < 2 * 4096)
- destSize = 2 * 4096;
+ int rc = mpqfs_pk_implode(
+ reinterpret_cast(srcData), size,
+ dst.get(), &dstSize, /*dict_bits=*/6);
- const std::unique_ptr destData { new std::byte[destSize] };
-
- TDataInfo param;
- param.srcData = srcData;
- param.srcOffset = 0;
- param.srcSize = size;
- param.destData = destData.get();
- param.destOffset = 0;
- param.destSize = destSize;
- param.error = false;
-
- unsigned type = 0;
- unsigned dsize = 4096;
- implode(PkwareBufferRead, PkwareBufferWrite, ptr.get(), ¶m, &type, &dsize);
-
- if (param.destOffset < size) {
- memcpy(srcData, destData.get(), param.destOffset);
- size = param.destOffset;
+ if (rc == 0 && dstSize < size) {
+ std::memcpy(srcData, dst.get(), dstSize);
+ return static_cast(dstSize);
}
+ // Compression didn't help — return original size.
return size;
}
uint32_t PkwareDecompress(std::byte *inBuff, uint32_t recvSize, size_t maxBytes)
{
- const std::unique_ptr ptr = std::make_unique(CMP_BUFFER_SIZE);
- const std::unique_ptr outBuff { new std::byte[maxBytes] };
+ auto out = std::make_unique(maxBytes);
+ size_t outSize = maxBytes;
- TDataInfo info;
- info.srcData = inBuff;
- info.srcOffset = 0;
- info.srcSize = recvSize;
- info.destData = outBuff.get();
- info.destOffset = 0;
- info.destSize = maxBytes;
- info.error = false;
-
- explode(PkwareBufferRead, PkwareBufferWrite, ptr.get(), &info);
- if (info.error) {
+ int rc = mpqfs_pk_explode(
+ reinterpret_cast(inBuff), recvSize,
+ out.get(), &outSize);
+ if (rc != 0)
return 0;
- }
- memcpy(inBuff, outBuff.get(), info.destOffset);
- return info.destOffset;
+ std::memcpy(inBuff, out.get(), outSize);
+ return static_cast(outSize);
}
} // namespace devilution
diff --git a/Source/engine/assets.cpp b/Source/engine/assets.cpp
index d51164e17..fa33b7cbb 100644
--- a/Source/engine/assets.cpp
+++ b/Source/engine/assets.cpp
@@ -65,13 +65,13 @@ SDL_IOStream *OpenOptionalRWops(const std::string &path)
return SDL_IOFromFile(path.c_str(), "rb");
};
-bool FindMpqFile(std::string_view filename, MpqArchive **archive, uint32_t *fileNumber)
+bool FindMpqFile(std::string_view filename, MpqArchive **archive, uint32_t *hashIndex)
{
- const MpqFileHash fileHash = CalculateMpqFileHash(filename);
-
for (auto &[_, mpqArchive] : MpqArchives) {
- if (mpqArchive.GetFileNumber(fileHash, *fileNumber)) {
+ uint32_t hash = mpqArchive.FindHash(filename);
+ if (hash != UINT32_MAX) {
*archive = &mpqArchive;
+ *hashIndex = hash;
return true;
}
}
@@ -155,7 +155,7 @@ AssetRef FindAsset(std::string_view filename)
}
// Look for the file in all the MPQ archives:
- if (FindMpqFile(filename, &result.archive, &result.fileNumber)) {
+ if (FindMpqFile(filename, &result.archive, &result.hashIndex)) {
result.filename = filename;
return result;
}
@@ -185,7 +185,7 @@ AssetHandle OpenAsset(AssetRef &&ref, bool threadsafe)
return AssetHandle { OpenFile(ref.path, "rb") };
#else
if (ref.archive != nullptr)
- return AssetHandle { SDL_RWops_FromMpqFile(*ref.archive, ref.fileNumber, ref.filename, threadsafe) };
+ return AssetHandle { SDL_RWops_FromMpqFile(*ref.archive, ref.hashIndex, ref.filename, threadsafe) };
if (ref.directHandle != nullptr) {
// Transfer handle ownership:
auto *handle = ref.directHandle;
@@ -316,7 +316,7 @@ bool LoadMPQ(std::span paths, std::string_view mpqName, int p
return true;
}
if (error != 0) {
- LogError("Error {}: {}", MpqArchive::ErrorMessage(error), mpqAbsPath);
+ LogError("Error {}: {}", MpqArchive::ErrorMessage(), mpqAbsPath);
}
}
if (error == 0) {
diff --git a/Source/engine/assets.hpp b/Source/engine/assets.hpp
index be8d4167c..346d4596b 100644
--- a/Source/engine/assets.hpp
+++ b/Source/engine/assets.hpp
@@ -118,7 +118,7 @@ struct AssetHandle {
struct AssetRef {
// An MPQ file reference:
MpqArchive *archive = nullptr;
- uint32_t fileNumber;
+ uint32_t hashIndex = UINT32_MAX;
std::string_view filename;
// Alternatively, a direct SDL_IOStream handle:
@@ -128,7 +128,7 @@ struct AssetRef {
AssetRef(AssetRef &&other) noexcept
: archive(other.archive)
- , fileNumber(other.fileNumber)
+ , hashIndex(other.hashIndex)
, filename(other.filename)
, directHandle(other.directHandle)
{
@@ -139,7 +139,7 @@ struct AssetRef {
{
closeDirectHandle();
archive = other.archive;
- fileNumber = other.fileNumber;
+ hashIndex = other.hashIndex;
filename = other.filename;
directHandle = other.directHandle;
other.directHandle = nullptr;
@@ -165,8 +165,9 @@ struct AssetRef {
[[nodiscard]] size_t size() const
{
if (archive != nullptr) {
- int32_t error;
- return archive->GetUnpackedFileSize(fileNumber, error);
+ if (hashIndex != UINT32_MAX)
+ return archive->GetFileSizeFromHash(hashIndex);
+ return archive->GetFileSize(filename);
}
return static_cast(SDL_GetIOSize(directHandle));
}
diff --git a/Source/init.cpp b/Source/init.cpp
index d2acda710..1d73960b9 100644
--- a/Source/init.cpp
+++ b/Source/init.cpp
@@ -37,7 +37,6 @@
#include "utils/utf8.hpp"
#ifndef UNPACKED_MPQS
-#include "mpq/mpq_common.hpp"
#include "mpq/mpq_reader.hpp"
#endif
@@ -99,13 +98,10 @@ bool AreExtraFontsOutOfDate(std::string_view path)
bool AreExtraFontsOutOfDate(MpqArchive &archive)
{
const char filename[] = "fonts\\VERSION";
- const MpqFileHash fileHash = CalculateMpqFileHash(filename);
- uint32_t fileNumber;
- if (!archive.GetFileNumber(fileHash, fileNumber))
+ if (!archive.HasFile(filename))
return true;
AssetRef ref;
ref.archive = &archive;
- ref.fileNumber = fileNumber;
ref.filename = filename;
return CheckExtraFontsVersion(std::move(ref));
}
diff --git a/Source/mpq/mpq_common.cpp b/Source/mpq/mpq_common.cpp
index 9a11a1179..0fc738f16 100644
--- a/Source/mpq/mpq_common.cpp
+++ b/Source/mpq/mpq_common.cpp
@@ -2,7 +2,7 @@
#include
-#include
+#include
namespace devilution {
@@ -10,9 +10,9 @@ namespace devilution {
MpqFileHash CalculateMpqFileHash(std::string_view filename)
{
MpqFileHash fileHash;
- libmpq__file_hash_s(filename.data(), filename.size(), &fileHash[0], &fileHash[1], &fileHash[2]);
+ mpqfs_file_hash_s(filename.data(), filename.size(), &fileHash[0], &fileHash[1], &fileHash[2]);
return fileHash;
}
#endif
-} // namespace devilution
+} // namespace devilution
\ No newline at end of file
diff --git a/Source/mpq/mpq_reader.cpp b/Source/mpq/mpq_reader.cpp
index b1603632d..3949b54a1 100644
--- a/Source/mpq/mpq_reader.cpp
+++ b/Source/mpq/mpq_reader.cpp
@@ -1,149 +1,145 @@
#include "mpq/mpq_reader.hpp"
-#include
-#include
-#include
-#include
+#include
+#include
-#include
+#include
+
+#include "utils/file_util.h"
namespace devilution {
-std::optional MpqArchive::Open(const char *path, int32_t &error)
+// Helper: NUL-terminate a string_view into a stack buffer.
+// Returns false if the name doesn't fit.
+static bool CopyToPathBuf(std::string_view sv, char *buf, size_t bufSize)
{
- 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 };
+ if (sv.size() >= bufSize) return false;
+ std::memcpy(buf, sv.data(), sv.size());
+ buf[sv.size()] = '\0';
+ return true;
}
-std::optional MpqArchive::Clone(int32_t &error)
+MpqArchive::MpqArchive(std::string path, mpqfs_archive_t *archive)
+ : path_(std::move(path))
+ , archive_(archive)
{
- mpq_archive_s *copy;
- error = libmpq__archive_dup(archive_, path_.c_str(), ©);
- if (error != 0)
- return std::nullopt;
- return MpqArchive { path_, copy };
}
-const char *MpqArchive::ErrorMessage(int32_t errorCode)
+MpqArchive::MpqArchive(MpqArchive &&other) noexcept
+ : path_(std::move(other.path_))
+ , archive_(other.archive_)
{
- return libmpq__strerror(errorCode);
+ other.archive_ = nullptr;
}
MpqArchive &MpqArchive::operator=(MpqArchive &&other) noexcept
{
- path_ = std::move(other.path_);
- if (archive_ != nullptr)
- libmpq__archive_close(archive_);
- archive_ = other.archive_;
- other.archive_ = nullptr;
- tmp_buf_ = std::move(other.tmp_buf_);
+ if (this != &other) {
+ mpqfs_close(archive_);
+ path_ = std::move(other.path_);
+ archive_ = other.archive_;
+ other.archive_ = nullptr;
+ }
return *this;
}
MpqArchive::~MpqArchive()
{
- if (archive_ != nullptr)
- libmpq__archive_close(archive_);
+ mpqfs_close(archive_);
}
-bool MpqArchive::GetFileNumber(MpqFileHash fileHash, uint32_t &fileNumber)
+std::optional MpqArchive::Open(const char *path, int32_t &error)
{
- return libmpq__file_number_from_hash(archive_, fileHash[0], fileHash[1], fileHash[2], &fileNumber) == 0;
+ if (!FileExists(path)) {
+ error = 0;
+ return std::nullopt;
+ }
+ mpqfs_archive_t *handle = mpqfs_open(path);
+ if (!handle) {
+ error = -1;
+ return std::nullopt;
+ }
+ error = 0;
+ return MpqArchive(path, handle);
}
-std::unique_ptr MpqArchive::ReadFile(std::string_view filename, std::size_t &fileSize, int32_t &error)
+std::optional MpqArchive::Clone(int32_t &error)
{
- std::unique_ptr 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(static_cast(unpackedSize));
-
- const std::size_t blockSize = GetBlockSize(fileNumber, 0, error);
- if (error != 0)
- return result;
-
- std::vector &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(result.get()), unpackedSize,
- tmp.data(), static_cast(blockSize), nullptr);
- if (error != 0) {
- result = nullptr;
- CloseBlockOffsetTable(fileNumber);
- return result;
+ mpqfs_archive_t *clone = mpqfs_clone(archive_);
+ if (!clone) {
+ error = -1;
+ return std::nullopt;
}
- CloseBlockOffsetTable(fileNumber);
-
- fileSize = static_cast(unpackedSize);
- return result;
+ error = 0;
+ return MpqArchive(path_, clone);
}
-int32_t MpqArchive::ReadBlock(uint32_t fileNumber, uint32_t blockNumber, uint8_t *out, size_t outSize)
+const char *MpqArchive::ErrorMessage()
{
- std::vector &tmpBuf = GetTemporaryBuffer(outSize);
- return libmpq__block_read_with_temporary_buffer(
- archive_, fileNumber, blockNumber, out, static_cast(outSize),
- tmpBuf.data(), outSize,
- /*transferred=*/nullptr);
+ const char *msg = mpqfs_last_error();
+ return msg ? msg : "Unknown error";
}
-std::size_t MpqArchive::GetUnpackedFileSize(uint32_t fileNumber, int32_t &error)
+bool MpqArchive::HasFile(std::string_view filename) const
{
- libmpq__off_t unpackedSize;
- error = libmpq__file_size_unpacked(archive_, fileNumber, &unpackedSize);
- return static_cast(unpackedSize);
+ char buf[256];
+ if (!CopyToPathBuf(filename, buf, sizeof(buf)))
+ return false;
+ return mpqfs_has_file(archive_, buf);
}
-uint32_t MpqArchive::GetNumBlocks(uint32_t fileNumber, int32_t &error)
+size_t MpqArchive::GetFileSize(std::string_view filename) const
{
- uint32_t numBlocks;
- error = libmpq__file_blocks(archive_, fileNumber, &numBlocks);
- return numBlocks;
+ char buf[256];
+ if (!CopyToPathBuf(filename, buf, sizeof(buf)))
+ return 0;
+ return mpqfs_file_size(archive_, buf);
}
-int32_t MpqArchive::OpenBlockOffsetTable(uint32_t fileNumber, std::string_view filename)
+uint32_t MpqArchive::FindHash(std::string_view filename) const
{
- return libmpq__block_open_offset_with_filename_s(archive_, fileNumber, filename.data(), filename.size());
+ char buf[256];
+ if (!CopyToPathBuf(filename, buf, sizeof(buf)))
+ return UINT32_MAX;
+ return mpqfs_find_hash(archive_, buf);
}
-int32_t MpqArchive::CloseBlockOffsetTable(uint32_t fileNumber)
+bool MpqArchive::HasFileHash(uint32_t hash) const
{
- return libmpq__block_close_offset(archive_, fileNumber);
+ return mpqfs_has_file_hash(archive_, hash);
}
-// Requires the block offset table to be open
-std::size_t MpqArchive::GetBlockSize(uint32_t fileNumber, uint32_t blockNumber, int32_t &error)
+size_t MpqArchive::GetFileSizeFromHash(uint32_t hash) const
{
- libmpq__off_t blockSize;
- error = libmpq__block_size_unpacked(archive_, fileNumber, blockNumber, &blockSize);
- return static_cast(blockSize);
+ return mpqfs_file_size_from_hash(archive_, hash);
}
-bool MpqArchive::HasFile(std::string_view filename) const
+std::unique_ptr MpqArchive::ReadFile(
+ std::string_view filename, std::size_t &fileSize, int32_t &error)
{
- std::uint32_t fileNumber;
- const int32_t error = libmpq__file_number_s(archive_, filename.data(), filename.size(), &fileNumber);
- return error == 0;
+ char buf[256];
+ if (!CopyToPathBuf(filename, buf, sizeof(buf))) {
+ error = -1;
+ return nullptr;
+ }
+
+ const size_t size = mpqfs_file_size(archive_, buf);
+ if (size == 0) {
+ error = -1;
+ return nullptr;
+ }
+
+ auto result = std::make_unique(size);
+ const size_t read = mpqfs_read_file_into(archive_, buf,
+ result.get(), size);
+ if (read == 0) {
+ error = -1;
+ return nullptr;
+ }
+
+ error = 0;
+ fileSize = read;
+ return result;
}
} // namespace devilution
diff --git a/Source/mpq/mpq_reader.hpp b/Source/mpq/mpq_reader.hpp
index d2fd78a43..c56dfaddb 100644
--- a/Source/mpq/mpq_reader.hpp
+++ b/Source/mpq/mpq_reader.hpp
@@ -6,76 +6,46 @@
#include
#include
#include
-#include
-#include
-#include "mpq/mpq_common.hpp"
-
-// Forward-declare so that we can avoid exposing libmpq.
-struct mpq_archive;
-using mpq_archive_s = struct mpq_archive;
+// Forward-declare so that we can avoid exposing mpqfs.h to all consumers.
+struct mpqfs_archive;
+typedef struct mpqfs_archive mpqfs_archive_t;
namespace devilution {
class MpqArchive {
public:
- // If the file does not exist, returns nullopt without an error.
static std::optional Open(const char *path, int32_t &error);
-
std::optional Clone(int32_t &error);
+ static const char *ErrorMessage();
- static const char *ErrorMessage(int32_t errorCode);
-
- MpqArchive(MpqArchive &&other) noexcept
- : path_(std::move(other.path_))
- , archive_(other.archive_)
- , tmp_buf_(std::move(other.tmp_buf_))
- {
- other.archive_ = nullptr;
- }
-
+ MpqArchive(MpqArchive &&other) noexcept;
MpqArchive &operator=(MpqArchive &&other) noexcept;
-
~MpqArchive();
- // Returns false if the file does not exit.
- bool GetFileNumber(MpqFileHash fileHash, uint32_t &fileNumber);
-
- std::unique_ptr ReadFile(std::string_view filename, std::size_t &fileSize, int32_t &error);
+ MpqArchive(const MpqArchive &) = delete;
+ MpqArchive &operator=(const MpqArchive &) = delete;
- // Returns error code.
- int32_t ReadBlock(uint32_t fileNumber, uint32_t blockNumber, uint8_t *out, size_t outSize);
-
- std::size_t GetUnpackedFileSize(uint32_t fileNumber, int32_t &error);
-
- uint32_t GetNumBlocks(uint32_t fileNumber, int32_t &error);
-
- int32_t OpenBlockOffsetTable(uint32_t fileNumber, std::string_view filename);
+ bool HasFile(std::string_view filename) const;
+ size_t GetFileSize(std::string_view filename) const;
- int32_t CloseBlockOffsetTable(uint32_t fileNumber);
+ // Hash-based lookup: resolve once, reuse the index.
+ uint32_t FindHash(std::string_view filename) const;
+ bool HasFileHash(uint32_t hash) const;
+ size_t GetFileSizeFromHash(uint32_t hash) const;
- // Requires the block offset table to be open
- std::size_t GetBlockSize(uint32_t fileNumber, uint32_t blockNumber, int32_t &error);
+ std::unique_ptr ReadFile(
+ std::string_view filename,
+ std::size_t &fileSize,
+ int32_t &error);
- bool HasFile(std::string_view filename) const;
+ mpqfs_archive_t *handle() const { return archive_; }
private:
- MpqArchive(std::string path, mpq_archive_s *archive)
- : path_(std::move(path))
- , archive_(archive)
- {
- }
-
- std::vector &GetTemporaryBuffer(std::size_t size)
- {
- if (tmp_buf_.size() < size)
- tmp_buf_.resize(size);
- return tmp_buf_;
- }
+ MpqArchive(std::string path, mpqfs_archive_t *archive);
std::string path_;
- mpq_archive_s *archive_;
- std::vector tmp_buf_;
+ mpqfs_archive_t *archive_ = nullptr;
};
} // namespace devilution
diff --git a/Source/mpq/mpq_sdl_rwops.cpp b/Source/mpq/mpq_sdl_rwops.cpp
index cc135d6e0..63fc71a12 100644
--- a/Source/mpq/mpq_sdl_rwops.cpp
+++ b/Source/mpq/mpq_sdl_rwops.cpp
@@ -1,295 +1,60 @@
#include "mpq/mpq_sdl_rwops.hpp"
-#include
#include
-#include
-#include
-#include
-#ifdef USE_SDL3
-#include
-#else
-#include
-
-#include "utils/sdl_compat.h"
-#endif
+#include
namespace devilution {
namespace {
+constexpr size_t MaxMpqPathSize = 256;
+} // namespace
-struct Data {
- // File information:
- std::optional ownedArchive;
- MpqArchive *mpqArchive;
- uint32_t fileNumber;
- size_t blockSize;
- size_t lastBlockSize;
- uint32_t numBlocks;
- size_t size;
-
- // State:
- size_t position;
- bool blockRead;
- std::unique_ptr blockData;
-};
-
-#ifdef USE_SDL3
-Data *GetData(void *userdata) { return reinterpret_cast(userdata); }
-#else
-Data *GetData(struct SDL_RWops *context)
-{
- return reinterpret_cast(context->hidden.unknown.data1);
-}
-
-void SetData(struct SDL_RWops *context, Data *data)
-{
- context->hidden.unknown.data1 = data;
-}
-#endif
-
-#ifndef USE_SDL1
-using OffsetType = Sint64;
-using SizeType = size_t;
-#else
-using OffsetType = int;
-using SizeType = int;
-#endif
-
-extern "C" {
-
-#ifndef USE_SDL1
-static Sint64 MpqFileRwSize(
-#ifdef USE_SDL3
- void *
-#else
- struct SDL_RWops *
-#endif
- context)
-{
- return static_cast(GetData(context)->size);
-}
-#endif
-
-#ifdef USE_SDL3
-static Sint64 MpqFileRwSeek(void *context, Sint64 offset, SDL_IOWhence whence)
-#else
-static OffsetType MpqFileRwSeek(struct SDL_RWops *context, OffsetType offset, int whence)
-#endif
+SdlRwopsType *SDL_RWops_FromMpqFile(MpqArchive &archive,
+ uint32_t hashIndex,
+ std::string_view filename,
+ bool threadsafe)
{
- Data &data = *GetData(context);
- OffsetType newPosition;
- switch (whence) {
- case SDL_IO_SEEK_SET:
- newPosition = offset;
- break;
- case SDL_IO_SEEK_CUR:
- newPosition = static_cast(data.position + offset);
- break;
- case SDL_IO_SEEK_END:
- newPosition = static_cast(data.size + offset);
- break;
- default:
- return -1;
- }
-
- if (newPosition == static_cast(data.position))
- return newPosition;
-
- if (newPosition > static_cast(data.size)) {
- SDL_SetError("MpqFileRwSeek beyond EOF (%d > %u)", static_cast(newPosition), static_cast(data.size));
- return -1;
- }
-
- if (newPosition < 0) {
- SDL_SetError("MpqFileRwSeek beyond BOF (%d < 0)", static_cast(newPosition));
- return -1;
- }
-
- if (data.position / data.blockSize != static_cast(newPosition) / data.blockSize)
- data.blockRead = false;
-
- data.position = static_cast(newPosition);
-
- return newPosition;
-}
+ char pathBuf[MaxMpqPathSize];
+ if (filename.size() >= sizeof(pathBuf))
+ return nullptr;
+ std::memcpy(pathBuf, filename.data(), filename.size());
+ pathBuf[filename.size()] = '\0';
+ if (threadsafe) {
+ if (hashIndex != UINT32_MAX) {
#ifdef USE_SDL3
-static SizeType MpqFileRwRead(void *context, void *ptr, size_t size, SDL_IOStatus *status)
+ SdlRwopsType *result = mpqfs_open_io_threadsafe_from_hash(archive.handle(), hashIndex);
#else
-static SizeType MpqFileRwRead(struct SDL_RWops *context, void *ptr, SizeType size, SizeType maxnum)
+ SdlRwopsType *result = mpqfs_open_rwops_threadsafe_from_hash(archive.handle(), hashIndex);
#endif
-{
-#ifdef USE_SDL3
- const size_t maxnum = 1;
-#endif
- Data &data = *GetData(context);
- const size_t totalSize = size * maxnum;
- size_t remainingSize = totalSize;
-
- auto *out = static_cast(ptr);
-
- if (data.blockData == nullptr) {
- data.blockData = std::unique_ptr { new uint8_t[data.blockSize] };
- }
-
- auto blockNumber = static_cast(data.position / data.blockSize);
- while (remainingSize > 0) {
- if (data.position == data.size) {
-#ifdef USE_SDL3
- *status = SDL_IO_STATUS_EOF;
-#endif
- break;
+ if (result != nullptr)
+ return result;
}
-
- const size_t currentBlockSize = blockNumber + 1 == data.numBlocks ? data.lastBlockSize : data.blockSize;
-
- if (!data.blockRead) {
- const int32_t error = data.mpqArchive->ReadBlock(data.fileNumber, blockNumber, data.blockData.get(), currentBlockSize);
- if (error != 0) {
- SDL_SetError("MpqFileRwRead ReadBlock: %s", MpqArchive::ErrorMessage(error));
- return 0;
- }
- data.blockRead = true;
- }
-
- const size_t blockPosition = data.position - (blockNumber * data.blockSize);
- const size_t remainingBlockSize = currentBlockSize - blockPosition;
-
- if (remainingSize < remainingBlockSize) {
- std::memcpy(out, data.blockData.get() + blockPosition, remainingSize);
- data.position += remainingSize;
#ifdef USE_SDL3
- return size;
+ return mpqfs_open_io_threadsafe(archive.handle(), pathBuf);
#else
- return maxnum;
+ return mpqfs_open_rwops_threadsafe(archive.handle(), pathBuf);
#endif
- }
-
- std::memcpy(out, data.blockData.get() + blockPosition, remainingBlockSize);
- out += remainingBlockSize;
- data.position += remainingBlockSize;
- remainingSize -= remainingBlockSize;
- ++blockNumber;
- data.blockRead = false;
}
+ // Non-threadsafe path: use hash-based open if available to avoid re-hashing.
+ // This may fail for encrypted files (which need the filename for key derivation),
+ // so we fall back to filename-based open on failure.
+ if (hashIndex != UINT32_MAX) {
#ifdef USE_SDL3
- return static_cast(totalSize - remainingSize);
-#else
- return static_cast((totalSize - remainingSize) / size);
-#endif
-}
-
-#ifdef USE_SDL3
-static bool MpqFileRwClose(void *context)
-#else
-static int MpqFileRwClose(struct SDL_RWops *context)
-#endif
-{
- Data *data = GetData(context);
- data->mpqArchive->CloseBlockOffsetTable(data->fileNumber);
- delete data;
-#ifdef USE_SDL3
- return true;
-#else
- delete context;
- return 0;
-#endif
-}
-
-} // extern "C"
-
-} // namespace
-
-SDL_IOStream *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe)
-{
-#ifdef USE_SDL3
- SDL_IOStreamInterface interface;
- SDL_INIT_INTERFACE(&interface);
- SDL_IOStreamInterface *result = &interface;
+ SdlRwopsType *result = mpqfs_open_io_from_hash(archive.handle(), hashIndex);
#else
- auto result = std::make_unique();
- std::memset(result.get(), 0, sizeof(*result));
-#endif
-
-#ifndef USE_SDL1
- result->size = &MpqFileRwSize;
-#ifndef USE_SDL3
- result->type = SDL_RWOPS_UNKNOWN;
+ SdlRwopsType *result = mpqfs_open_rwops_from_hash(archive.handle(), hashIndex);
#endif
-#else
- result->type = 0;
-#endif
-
- result->seek = &MpqFileRwSeek;
- result->read = &MpqFileRwRead;
- result->write = nullptr;
- result->close = &MpqFileRwClose;
-#ifdef USE_SDL3
- result->flush = nullptr;
-#endif
-
- auto data = std::make_unique();
- int32_t error = 0;
-
- if (threadsafe) {
- data->ownedArchive = mpqArchive.Clone(error);
- if (error != 0) {
- SDL_SetError("MpqFileRwRead Clone: %s", MpqArchive::ErrorMessage(error));
- return nullptr;
- }
- data->mpqArchive = &*data->ownedArchive;
- } else {
- data->mpqArchive = &mpqArchive;
- }
- data->fileNumber = fileNumber;
- MpqArchive &archive = *data->mpqArchive;
-
- error = archive.OpenBlockOffsetTable(fileNumber, filename);
- if (error != 0) {
- SDL_SetError("MpqFileRwRead OpenBlockOffsetTable: %s", MpqArchive::ErrorMessage(error));
- return nullptr;
+ if (result != nullptr)
+ return result;
}
- data->size = archive.GetUnpackedFileSize(fileNumber, error);
- if (error != 0) {
- SDL_SetError("MpqFileRwRead GetUnpackedFileSize: %s", MpqArchive::ErrorMessage(error));
- return nullptr;
- }
-
- const std::uint32_t numBlocks = archive.GetNumBlocks(fileNumber, error);
- if (error != 0) {
- SDL_SetError("MpqFileRwRead GetNumBlocks: %s", MpqArchive::ErrorMessage(error));
- return nullptr;
- }
- data->numBlocks = numBlocks;
-
- const size_t blockSize = archive.GetBlockSize(fileNumber, 0, error);
- if (error != 0) {
- SDL_SetError("MpqFileRwRead GetBlockSize: %s", MpqArchive::ErrorMessage(error));
- return nullptr;
- }
- data->blockSize = blockSize;
-
- if (numBlocks > 1) {
- data->lastBlockSize = archive.GetBlockSize(fileNumber, numBlocks - 1, error);
- if (error != 0) {
- SDL_SetError("MpqFileRwRead GetBlockSize: %s", MpqArchive::ErrorMessage(error));
- return nullptr;
- }
- } else {
- data->lastBlockSize = blockSize;
- }
-
- data->position = 0;
- data->blockRead = false;
-
#ifdef USE_SDL3
- return SDL_OpenIO(&interface, data.release());
+ return mpqfs_open_io(archive.handle(), pathBuf);
#else
- SetData(result.get(), data.release());
- return result.release();
+ return mpqfs_open_rwops(archive.handle(), pathBuf);
#endif
}
diff --git a/Source/mpq/mpq_sdl_rwops.hpp b/Source/mpq/mpq_sdl_rwops.hpp
index 07ba794c0..2a1aee118 100644
--- a/Source/mpq/mpq_sdl_rwops.hpp
+++ b/Source/mpq/mpq_sdl_rwops.hpp
@@ -1,20 +1,23 @@
#pragma once
-#include
#include
+#include "mpq/mpq_reader.hpp"
+
+// Forward-declare the SDL type for the active SDL version.
#ifdef USE_SDL3
-#include
+struct SDL_IOStream;
+using SdlRwopsType = SDL_IOStream;
#else
-#include
-
-#include "utils/sdl_compat.h"
+struct SDL_RWops;
+using SdlRwopsType = SDL_RWops;
#endif
-#include "mpq/mpq_reader.hpp"
-
namespace devilution {
-SDL_IOStream *SDL_RWops_FromMpqFile(MpqArchive &mpqArchive, uint32_t fileNumber, std::string_view filename, bool threadsafe);
+SdlRwopsType *SDL_RWops_FromMpqFile(MpqArchive &archive,
+ uint32_t hashIndex,
+ std::string_view filename,
+ bool threadsafe);
} // namespace devilution
diff --git a/Source/mpq/mpq_writer.cpp b/Source/mpq/mpq_writer.cpp
index 1ba4c5cb2..69a61fb5a 100644
--- a/Source/mpq/mpq_writer.cpp
+++ b/Source/mpq/mpq_writer.cpp
@@ -6,7 +6,7 @@
#include
#include
-#include
+#include
#include "appfat.h"
#include "encrypt.h"
@@ -140,7 +140,7 @@ MpqWriter::MpqWriter(const char *path)
error = "Failed to read block table";
goto on_error;
}
- libmpq__decrypt_block(reinterpret_cast(blockTable_.get()), fhdr.blockEntriesCount * sizeof(MpqBlockEntry), LIBMPQ_BLOCK_TABLE_HASH_KEY);
+ mpqfs_decrypt_block(reinterpret_cast(blockTable_.get()), fhdr.blockEntriesCount * sizeof(MpqBlockEntry) / sizeof(uint32_t), MPQFS_BLOCK_TABLE_KEY);
}
hashTable_ = std::make_unique(HashEntriesCount);
@@ -152,7 +152,7 @@ MpqWriter::MpqWriter(const char *path)
error = "Failed to read hash entries";
goto on_error;
}
- libmpq__decrypt_block(reinterpret_cast(hashTable_.get()), fhdr.hashEntriesCount * sizeof(MpqHashEntry), LIBMPQ_HASH_TABLE_HASH_KEY);
+ mpqfs_decrypt_block(reinterpret_cast(hashTable_.get()), fhdr.hashEntriesCount * sizeof(MpqHashEntry) / sizeof(uint32_t), MPQFS_HASH_TABLE_KEY);
}
#ifndef CAN_SEEKP_BEYOND_EOF
@@ -469,17 +469,17 @@ bool MpqWriter::WriteHeader()
bool MpqWriter::WriteBlockTable()
{
- libmpq__encrypt_block(reinterpret_cast(blockTable_.get()), BlockEntrySize, LIBMPQ_BLOCK_TABLE_HASH_KEY);
+ mpqfs_encrypt_block(reinterpret_cast(blockTable_.get()), BlockEntrySize / sizeof(uint32_t), MPQFS_BLOCK_TABLE_KEY);
const bool success = stream_.Write(reinterpret_cast(blockTable_.get()), BlockEntrySize);
- libmpq__decrypt_block(reinterpret_cast(blockTable_.get()), BlockEntrySize, LIBMPQ_BLOCK_TABLE_HASH_KEY);
+ mpqfs_decrypt_block(reinterpret_cast(blockTable_.get()), BlockEntrySize / sizeof(uint32_t), MPQFS_BLOCK_TABLE_KEY);
return success;
}
bool MpqWriter::WriteHashTable()
{
- libmpq__encrypt_block(reinterpret_cast(hashTable_.get()), HashEntrySize, LIBMPQ_HASH_TABLE_HASH_KEY);
+ mpqfs_encrypt_block(reinterpret_cast(hashTable_.get()), HashEntrySize / sizeof(uint32_t), MPQFS_HASH_TABLE_KEY);
const bool success = stream_.Write(reinterpret_cast(hashTable_.get()), HashEntrySize);
- libmpq__decrypt_block(reinterpret_cast(hashTable_.get()), HashEntrySize, LIBMPQ_HASH_TABLE_HASH_KEY);
+ mpqfs_decrypt_block(reinterpret_cast(hashTable_.get()), HashEntrySize / sizeof(uint32_t), MPQFS_HASH_TABLE_KEY);
return success;
}
diff --git a/test/writehero_test.cpp b/test/writehero_test.cpp
index 892f7e18d..e748c14e7 100644
--- a/test/writehero_test.cpp
+++ b/test/writehero_test.cpp
@@ -413,7 +413,7 @@ TEST(Writehero, pfile_write_hero)
std::vector s(picosha2::k_digest_size);
picosha2::hash256(data.get(), data.get() + size, s.begin(), s.end());
EXPECT_EQ(picosha2::bytes_to_hex_string(s.begin(), s.end()),
- "a79367caae6192d54703168d82e0316aa289b2a33251255fad8abe34889c1d3a");
+ "4dffacf96d5aab89c07c38de54c5b90006c6379fdaf90785885872d8edccec40");
}
} // namespace
diff --git a/uwp-project/devilutionx.vcxproj b/uwp-project/devilutionx.vcxproj
index a75ace99d..40a48f4c9 100644
--- a/uwp-project/devilutionx.vcxproj
+++ b/uwp-project/devilutionx.vcxproj
@@ -73,8 +73,8 @@
- sdl_image.lib;libpng16_staticd.lib;pkware.lib;fmtd.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libmpq.lib;libdevilutionx.lib;lua_static.lib;sdl2.lib;sdl_audiolib.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)
- ..\build\SDL\VisualC-WinRT\x64\Debug\SDL-UWP;..\build\3rdParty\SDL_image\Debug;..\build\_deps\zlib-build\Debug;..\build\3rdParty\PKWare\Debug;..\build\3rdParty\bzip2\Debug;..\build\3rdParty\libsmackerdec\Debug;..\build\3rdParty\libmpq\Debug;..\build\_deps\lua-build\lua-5.4.7\Debug;..\build\_deps\sdl_audiolib-build\Debug;..\build\3rdParty\asio\Debug;..\build\_deps\libsodium-build\Debug;..\build\_deps\libzt-build\lib\Debug;..\build\_deps\libfmt-build\Debug;..\build\_deps\libpng-build\Debug;..\build\Source\libdevilutionx.dir\Debug;%(AdditionalLibraryDirectories)
+ sdl_image.lib;libpng16_staticd.lib;mpqfs.lib;fmtd.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libdevilutionx.lib;lua_static.lib;sdl2.lib;sdl_audiolib.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)
+ ..\build\SDL\VisualC-WinRT\x64\Debug\SDL-UWP;..\build\3rdParty\SDL_image\Debug;..\build\_deps\zlib-build\Debug;..\build\3rdParty\bzip2\Debug;..\build\3rdParty\libsmackerdec\Debug;..\build\_deps\mpqfs-build\Debug;..\build\_deps\lua-build\lua-5.4.7\Debug;..\build\_deps\sdl_audiolib-build\Debug;..\build\3rdParty\asio\Debug;..\build\_deps\libsodium-build\Debug;..\build\_deps\libzt-build\lib\Debug;..\build\_deps\libfmt-build\Debug;..\build\_deps\libpng-build\Debug;..\build\Source\libdevilutionx.dir\Debug;%(AdditionalLibraryDirectories)
pch.h
@@ -92,8 +92,8 @@
- sdl_image.lib;libpng16_static.lib;pkware.lib;fmt.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libmpq.lib;libdevilutionx.lib;lua_static.lib;sdl2.lib;sdl_audiolib.lib;sheenbidi.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)
- ..\build\SDL\VisualC-WinRT\x64\Release\SDL-UWP;..\build\3rdParty\SDL_image\Release;..\build\_deps\zlib-build\Release;..\build\3rdParty\PKWare\Release;..\build\3rdParty\bzip2\Release;..\build\3rdParty\libsmackerdec\Release;..\build\3rdParty\libmpq\Release;..\build\_deps\lua-build\lua-5.4.7\Release;..\build\_deps\sdl_audiolib-build\Release;..\build\3rdParty\asio\Release;..\build\_deps\libsodium-build\Release;..\build\_deps\libzt-build\lib\Release;..\build\_deps\libfmt-build\Release;..\build\_deps\libpng-build\Release;..\build\_deps\sheenbidi-build\Release;..\build\Source\libdevilutionx.dir\Release;%(AdditionalLibraryDirectories)
+ sdl_image.lib;libpng16_static.lib;mpqfs.lib;fmt.lib;zlibstatic.lib;bzip2.lib;libsmackerdec.lib;libdevilutionx.lib;lua_static.lib;sdl2.lib;sdl_audiolib.lib;sheenbidi.lib;asio.lib;sodium.lib;zt.lib;lwip_pic.lib;miniupnpc_pic.lib;natpmp_pic.lib;zt_pic.lib;zto_pic.lib;shlwapi.lib;shell32.lib;%(AdditionalDependencies)
+ ..\build\SDL\VisualC-WinRT\x64\Release\SDL-UWP;..\build\3rdParty\SDL_image\Release;..\build\_deps\zlib-build\Release;..\build\3rdParty\bzip2\Release;..\build\3rdParty\libsmackerdec\Release;..\build\_deps\mpqfs-build\Release;..\build\_deps\lua-build\lua-5.4.7\Release;..\build\_deps\sdl_audiolib-build\Release;..\build\3rdParty\asio\Release;..\build\_deps\libsodium-build\Release;..\build\_deps\libzt-build\lib\Release;..\build\_deps\libfmt-build\Release;..\build\_deps\libpng-build\Release;..\build\_deps\sheenbidi-build\Release;..\build\Source\libdevilutionx.dir\Release;%(AdditionalLibraryDirectories)
pch.h