diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj
index 2c8f91afa..67bde0724 100644
--- a/desmume/src/windows/DeSmuME_2005.vcproj
+++ b/desmume/src/windows/DeSmuME_2005.vcproj
@@ -55,7 +55,7 @@
FavorSizeOrSpeed="0"
EnableFiberSafeOptimizations="false"
WholeProgramOptimization="false"
- AdditionalIncludeDirectories=".;..;lua\include;"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx"
+ AdditionalIncludeDirectories=".;..;lua\include;"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;stdint"
PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;DEBUG;_CRT_SECURE_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;HAVE_LIBZ;NOMINMAX;_WIN32_WINNT=0x0501;_CRTDBG_MAPALLOC "
ExceptionHandling="1"
BasicRuntimeChecks="0"
@@ -247,7 +247,7 @@
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
WholeProgramOptimization="true"
- AdditionalIncludeDirectories=".;..;lua\include;"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx"
+ AdditionalIncludeDirectories=".;..;lua\include;"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;stdint"
PreprocessorDefinitions="_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;HAVE_LIBZ;NOMINMAX;NDEBUG;RELEASE;_WIN32_WINNT=0x0501"
StringPooling="true"
ExceptionHandling="1"
@@ -446,7 +446,7 @@
OmitFramePointers="true"
EnableFiberSafeOptimizations="true"
WholeProgramOptimization="false"
- AdditionalIncludeDirectories=".;..;lua\include;"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx"
+ AdditionalIncludeDirectories=".;..;lua\include;"glib-2.20.1\build";"glib-2.20.1\build\glib";.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;stdint"
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;HAVE_LIBZ;NOMINMAX;NDEBUG;RELEASE;_WIN32_WINNT=0x0501;FASTBUILD"
StringPooling="true"
ExceptionHandling="1"
@@ -689,6 +689,10 @@
RelativePath=".\FEX_Interface.cpp"
>
+
+
@@ -961,80 +965,52 @@
Name="File_Extractor"
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -1043,30 +1019,66 @@
RelativePath=".\File_Extractor\7z_C\7zDec.c"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1075,30 +1087,70 @@
RelativePath=".\File_Extractor\7z_C\BraIA64.c"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1111,22 +1163,50 @@
RelativePath=".\File_Extractor\7z_C\LzmaDec.c"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1136,9 +1216,29 @@
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1171,10 +1287,30 @@
RelativePath=".\File_Extractor\unrar\getbits.cpp"
>
+
+
+
+
+
+
+
+
+
+
@@ -1187,10 +1323,30 @@
RelativePath=".\File_Extractor\unrar\rawread.cpp"
>
+
+
+
+
+
+
+
+
+
+
@@ -1207,6 +1363,22 @@
RelativePath=".\File_Extractor\unrar\unpack20.cpp"
>
+
+
+
+
+
+
+
+
@@ -1220,6 +1392,118 @@
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Neither
false
false
- .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;%(AdditionalIncludeDirectories)
+ .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;%(AdditionalIncludeDirectories)
DEBUG;_CRT_SECURE_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;BETA_VERSION;NOMINMAX;HAVE_LIBZ;%(PreprocessorDefinitions)
Sync
EnableFastChecks
@@ -164,7 +164,7 @@
true
true
true
- .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;%(AdditionalIncludeDirectories)
+ .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;%(AdditionalIncludeDirectories)
_CRT_SECURE_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;HAVE_LIBZ;NOMINMAX;RELEASE;NDEBUG;%(PreprocessorDefinitions)
true
Sync
@@ -204,7 +204,7 @@
true
true
false
- .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;%(AdditionalIncludeDirectories)
+ .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;%(AdditionalIncludeDirectories)
_CRT_SECURE_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;HAVE_LIBZ;NOMINMAX;RELEASE;NDEBUG;FASTBUILD;DEVELOPER;%(PreprocessorDefinitions)
true
Sync
@@ -536,40 +536,10 @@
-
- true
- true
- true
- true
- true
- true
-
-
- true
- true
- true
- true
- true
- true
-
+
+
-
- true
- true
- true
- true
- true
- true
-
-
- true
- true
- true
- true
- true
- true
-
@@ -591,7 +561,7 @@
-
+
@@ -606,20 +576,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -671,7 +654,6 @@
-
@@ -817,9 +799,7 @@
-
-
@@ -843,6 +823,7 @@
+
@@ -860,22 +841,24 @@
+
+
+
+
+
-
-
-
@@ -984,6 +967,7 @@
+
diff --git a/desmume/src/windows/DeSmuME_2010.vcxproj.filters b/desmume/src/windows/DeSmuME_2010.vcxproj.filters
index 1f023f033..7f6cc9267 100644
--- a/desmume/src/windows/DeSmuME_2010.vcxproj.filters
+++ b/desmume/src/windows/DeSmuME_2010.vcxproj.filters
@@ -52,21 +52,24 @@
{faa7804e-deb3-482f-b348-921cb7dacca7}
-
- {d2287daf-de85-4c64-8eef-2198f501904a}
-
-
- {fddf8c65-a8f4-41ed-ab58-cd268c3a12da}
-
-
- {24398c49-4650-412e-b46f-4725ad4f5b11}
-
{82c38db3-d06d-44b5-a9a4-be3c002d0db0}
{0d620905-0dcf-47a4-bac2-91f307aa9994}
+
+ {d2287daf-de85-4c64-8eef-2198f501904a}
+
+
+ {a6326bbe-afb7-4dd5-ae76-a7436bc8f7db}
+
+
+ {5f6c8f8e-0d1d-41a6-bd1f-0c7e51175b0f}
+
+
+ {6e0c9a80-56da-436a-a32d-d64cf6323ac7}
+
@@ -480,204 +483,9 @@
Core
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex
-
Windows
-
- Windows\fex\unrar
-
Core\utils\AsmJit\core
@@ -810,6 +618,234 @@
Core\filter
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
@@ -1211,195 +1247,6 @@
Core
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex
-
Windows
@@ -1553,6 +1400,207 @@
Core\filter
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
@@ -1570,36 +1618,39 @@
Core\filter
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\7z
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
-
- Windows\fex\unrar
-
Core\utils\AsmJit
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
diff --git a/desmume/src/windows/DeSmuME_2012.vcxproj b/desmume/src/windows/DeSmuME_2012.vcxproj
index 11f11dacd..696e87b66 100644
--- a/desmume/src/windows/DeSmuME_2012.vcxproj
+++ b/desmume/src/windows/DeSmuME_2012.vcxproj
@@ -553,40 +553,10 @@
-
- true
- true
- true
- true
- true
- true
-
-
- true
- true
- true
- true
- true
- true
-
+
+
-
- true
- true
- true
- true
- true
- true
-
-
- true
- true
- true
- true
- true
- true
-
@@ -608,7 +578,7 @@
-
+
@@ -623,20 +593,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -688,7 +671,6 @@
-
@@ -773,7 +755,6 @@
-
@@ -834,9 +815,7 @@
-
-
@@ -860,6 +839,7 @@
+
@@ -877,22 +857,24 @@
+
+
+
+
+
-
-
-
@@ -930,9 +912,6 @@
-
-
-
call un7z_and_touch.bat directx\directx.7z .libs\directx*
@@ -997,19 +976,22 @@
.libs\lua.tag;
7z.exe;un7z_and_touch.bat
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/desmume/src/windows/DeSmuME_2012.vcxproj.filters b/desmume/src/windows/DeSmuME_2012.vcxproj.filters
index be801258e..377a3efd3 100644
--- a/desmume/src/windows/DeSmuME_2012.vcxproj.filters
+++ b/desmume/src/windows/DeSmuME_2012.vcxproj.filters
@@ -49,12 +49,6 @@
{ec682647-9bb7-4315-99a4-4f9398db61ad}
-
- {321e6567-acbd-4dc4-a5c6-6cd8fe445d53}
-
-
- {4c97f223-843f-4975-b774-4d0c887cfd37}
-
{4d7483df-e22e-4e77-9ae8-8446c04d335d}
@@ -67,6 +61,18 @@
{191da306-49b9-43b4-a4d9-d91dd3a18db8}
+
+ {dca5253d-1a55-4e81-8605-bf389a113e5e}
+
+
+ {10a34cfb-f98c-4878-a918-de5ff0b23abf}
+
+
+ {217b886d-4d87-4690-b66d-88d57b966c3f}
+
+
+ {f6fdb39c-754f-4b71-986e-5ecbbee3e476}
+
@@ -531,189 +537,6 @@
Windows
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
Windows\tools
@@ -759,10 +582,6 @@
Windows
-
-
-
-
Core
@@ -802,6 +621,234 @@
Core\filter
+
+ Windows\File_Extractor\7z_C\win32
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
@@ -1326,75 +1373,6 @@
Windows
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Core
@@ -1419,6 +1397,210 @@
Core\filter
+
+ Windows\File_Extractor\7z_C\win32
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows
+
@@ -1430,18 +1612,6 @@
Core\filter
-
-
-
-
-
-
-
-
-
-
-
-
@@ -1459,4 +1629,36 @@
Windows\libs
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
\ No newline at end of file
diff --git a/desmume/src/windows/DeSmuME_2015.vcxproj b/desmume/src/windows/DeSmuME_2015.vcxproj
index e09b151e3..22510558e 100644
--- a/desmume/src/windows/DeSmuME_2015.vcxproj
+++ b/desmume/src/windows/DeSmuME_2015.vcxproj
@@ -133,7 +133,7 @@
Neither
false
false
- .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;%(AdditionalIncludeDirectories)
+ .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;%(AdditionalIncludeDirectories)
_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion) ;DEBUG;_CRT_SECURE_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;BETA_VERSION;NOMINMAX;HAVE_LIBZ;%(PreprocessorDefinitions)
Sync
EnableFastChecks
@@ -174,7 +174,7 @@
true
true
true
- .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;%(AdditionalIncludeDirectories)
+ .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;%(AdditionalIncludeDirectories)
_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion) ;_CRT_SECURE_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;HAVE_LIBZ;NOMINMAX;RELEASE;NDEBUG;%(PreprocessorDefinitions)
true
Sync
@@ -216,7 +216,7 @@
true
true
false
- .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;%(AdditionalIncludeDirectories)
+ .;..;lua\include;glib-2.20.1\build;glib-2.20.1\build\glib;.\zlib123;.\zziplib;.\winpcap;userconfig;defaultconfig;.\agg\include;.\agg\examples;directx;File_Extractor;%(AdditionalIncludeDirectories)
_MSC_PLATFORM_TOOLSET=$(PlatformToolsetVersion) ;_CRT_SECURE_NO_DEPRECATE;GLIB_STATIC_COMPILATION;WIN32;HAVE_LIBZ;NOMINMAX;RELEASE;NDEBUG;FASTBUILD;DEVELOPER;%(PreprocessorDefinitions)
true
Sync
@@ -553,40 +553,10 @@
-
- true
- true
- true
- true
- true
- true
-
-
- true
- true
- true
- true
- true
- true
-
+
+
-
- true
- true
- true
- true
- true
- true
-
-
- true
- true
- true
- true
- true
- true
-
@@ -608,7 +578,7 @@
-
+
@@ -623,20 +593,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -688,7 +671,6 @@
-
@@ -773,7 +755,6 @@
-
@@ -834,9 +815,7 @@
-
-
@@ -860,6 +839,7 @@
+
@@ -877,22 +857,24 @@
+
+
+
+
+
-
-
-
@@ -930,9 +912,6 @@
-
-
-
call un7z_and_touch.bat directx\directx.7z .libs\directx*
@@ -1001,6 +980,7 @@
+
diff --git a/desmume/src/windows/DeSmuME_2015.vcxproj.filters b/desmume/src/windows/DeSmuME_2015.vcxproj.filters
index be801258e..1f87c87c6 100644
--- a/desmume/src/windows/DeSmuME_2015.vcxproj.filters
+++ b/desmume/src/windows/DeSmuME_2015.vcxproj.filters
@@ -49,12 +49,6 @@
{ec682647-9bb7-4315-99a4-4f9398db61ad}
-
- {321e6567-acbd-4dc4-a5c6-6cd8fe445d53}
-
-
- {4c97f223-843f-4975-b774-4d0c887cfd37}
-
{4d7483df-e22e-4e77-9ae8-8446c04d335d}
@@ -67,6 +61,18 @@
{191da306-49b9-43b4-a4d9-d91dd3a18db8}
+
+ {cd842cb5-7e8f-4265-b893-f44eb7f52c00}
+
+
+ {4604012a-be54-4537-827b-65c44969f012}
+
+
+ {553c2a14-1f94-4468-9667-56bdc454cb04}
+
+
+ {bb7018b5-f7ad-45e8-8179-8cc0ce8a6a20}
+
@@ -531,189 +537,6 @@
Windows
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\7-Zip
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
-
- Windows\File_Extractor\unrar
-
Windows\tools
@@ -759,10 +582,6 @@
Windows
-
-
-
-
Core
@@ -802,6 +621,234 @@
Core\filter
+
+ Windows\File_Extractor\7z_C\win32
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
@@ -1326,75 +1373,6 @@
Windows
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Core
@@ -1419,6 +1397,210 @@
Core\filter
+
+ Windows\File_Extractor\7z_C\win32
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\fex
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows
+
@@ -1430,18 +1612,36 @@
Core\filter
-
-
-
-
-
-
-
-
-
-
-
-
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\unrar
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
+
+ Windows\File_Extractor\7z_C
+
diff --git a/desmume/src/windows/FEX_Interface.cpp b/desmume/src/windows/FEX_Interface.cpp
index ea618d405..a78c223c0 100644
--- a/desmume/src/windows/FEX_Interface.cpp
+++ b/desmume/src/windows/FEX_Interface.cpp
@@ -31,7 +31,6 @@ struct ArchiveFormatInfo
{
std::string name;
std::vector extensions;
- std::vector signatures;
fex_type_t type;
};
@@ -101,13 +100,6 @@ void InitDecoder()
info.type = type_list[i];
- const char ** signatures = fex_type_signatures(type_list[i]);
-
- for (unsigned int j = 0; signatures[j]; j++)
- {
- info.signatures.push_back(signatures[j]);
- }
-
s_formatInfos.push_back(info);
}
}
@@ -122,7 +114,7 @@ ArchiveFile::ArchiveFile(const char* filename)
{
assert(!s_formatInfos.empty());
- m_typeIndex = -1;
+ archiveType = NULL;
m_numItems = 0;
m_items = NULL;
m_filename = NULL;
@@ -144,52 +136,18 @@ ArchiveFile::ArchiveFile(const char* filename)
m_filename = new char[strlen(filename_utf8)+1];
strcpy(m_filename, filename_utf8);
- // detect archive type using format signature in file
- for(size_t i = 0; i < s_formatInfos.size() && m_typeIndex < 0; i++)
+ fex_err_t err = fex_identify_file(&archiveType, filename);
+
+ //handle uncompressed files specially
+ if(!err)
{
- for (size_t j = 0; j < s_formatInfos[i].signatures.size(); j++)
- {
- fseek(file, 0, SEEK_SET);
-
- std::string& formatSig = s_formatInfos[i].signatures[j];
- int len = formatSig.size();
-
- if(len == 0)
- continue; // because some formats have no signature
-
- char* fileSig = (char*)_alloca(len);
- fread(fileSig, 1, len, file);
-
- if(!memcmp(formatSig.c_str(), fileSig, len))
- m_typeIndex = i;
- }
+ if(!strcmp(fex_type_name(archiveType),"file"))
+ archiveType = NULL;
}
- // if no signature match has been found, detect archive type using filename.
- // this is only for signature-less formats
- const char* fileExt = strrchr(filename, '.');
- if(fileExt++)
+ if (err || archiveType == NULL)
{
- for(size_t i = 0; i < s_formatInfos.size() && m_typeIndex < 0; i++)
- {
- if(s_formatInfos[i].signatures.empty())
- {
- std::vector& formatExts = s_formatInfos[i].extensions;
- for(size_t j = 0; j < formatExts.size(); j++)
- {
- if(!_stricmp(formatExts[j].c_str(), fileExt))
- {
- m_typeIndex = i;
- break;
- }
- }
- }
- }
- }
-
- if(m_typeIndex < 0)
- {
- // uncompressed
+ // uncompressed, we guess
m_numItems = 1;
m_items = new ArchiveItem[m_numItems];
@@ -205,7 +163,7 @@ ArchiveFile::ArchiveFile(const char* filename)
else
{
fex_t * object;
- fex_err_t err = fex_open_type( &object, m_filename, s_formatInfos[m_typeIndex].type );
+ fex_err_t err = fex_open_type( &object, m_filename, archiveType );
if ( !err )
{
int numItems = 0;
@@ -279,10 +237,10 @@ const char* ArchiveFile::GetArchiveTypeName()
{
assert(!s_formatInfos.empty());
- if((size_t)m_typeIndex >= s_formatInfos.size())
+ if(archiveType == NULL)
return "";
- return s_formatInfos[m_typeIndex].name.c_str();
+ return fex_type_name(archiveType);
}
int ArchiveFile::GetNumItems()
@@ -314,7 +272,7 @@ const wchar_t* ArchiveFile::GetItemNameW(int item)
bool ArchiveFile::IsCompressed()
{
- return (m_typeIndex >= 0);
+ return archiveType != NULL;
}
int ArchiveFile::ExtractItem(int index, unsigned char* outBuffer, int bufSize) const
@@ -328,7 +286,7 @@ int ArchiveFile::ExtractItem(int index, unsigned char* outBuffer, int bufSize) c
if(bufSize < item.size)
return 0;
- if(m_typeIndex < 0)
+ if(archiveType == NULL)
{
// uncompressed
FILE* file = fopen(m_filename, "rb");
@@ -338,7 +296,7 @@ int ArchiveFile::ExtractItem(int index, unsigned char* outBuffer, int bufSize) c
else
{
fex_t * object;
- fex_err_t err = fex_open_type( &object, m_filename, s_formatInfos[m_typeIndex].type );
+ fex_err_t err = fex_open_type( &object, m_filename, archiveType );
if ( !err )
{
if ( index != 0 ) err = fex_seek_arc( object, item.offset );
@@ -375,7 +333,7 @@ int ArchiveFile::ExtractItem(int index, const char* outFilename) const
if(outAttributes & FILE_ATTRIBUTE_READONLY)
SetFileAttributes(outFilename, outAttributes & ~FILE_ATTRIBUTE_READONLY); // temporarily remove read-only attribute so we can decompress to there
- if(m_typeIndex < 0)
+ if(archiveType == NULL)
{
// uncompressed
if(!CopyFile(m_filename, outFilename, false))
@@ -384,7 +342,7 @@ int ArchiveFile::ExtractItem(int index, const char* outFilename) const
else
{
fex_t * object;
- fex_err_t err = fex_open_type( &object, m_filename, s_formatInfos[m_typeIndex].type );
+ fex_err_t err = fex_open_type( &object, m_filename, archiveType );
if ( !err )
{
if ( index != 0 ) err = fex_seek_arc( object, item.offset );
diff --git a/desmume/src/windows/FEX_Interface.h b/desmume/src/windows/FEX_Interface.h
index 4e0a3df91..bf7b6cafc 100644
--- a/desmume/src/windows/FEX_Interface.h
+++ b/desmume/src/windows/FEX_Interface.h
@@ -24,6 +24,8 @@
// NOTE: if you want to add support for opening files within archives to some part of DeSmuME,
// consider using the higher-level interface provided by OpenArchive.h instead
+typedef const struct fex_type_t_* fex_type_t;
+
void InitDecoder();
void CleanupDecoder();
const char* GetSupportedFormatsFilter();
@@ -56,7 +58,7 @@ protected:
};
ArchiveItem* m_items;
int m_numItems;
- int m_typeIndex;
+ fex_type_t archiveType;
char* m_filename;
};
diff --git a/desmume/src/windows/File_Extractor/7z_C/7z.h b/desmume/src/windows/File_Extractor/7z_C/7z.h
index b7edd3ba5..e282b7a70 100644
--- a/desmume/src/windows/File_Extractor/7z_C/7z.h
+++ b/desmume/src/windows/File_Extractor/7z_C/7z.h
@@ -175,7 +175,7 @@ size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
SRes SzArEx_Extract(
const CSzArEx *db,
ILookInStream *inStream,
- UInt32 fileIndex, /* index of file */
+ UInt64 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
diff --git a/desmume/src/windows/File_Extractor/7z_C/7zIn.c b/desmume/src/windows/File_Extractor/7z_C/7zIn.c
index f1a44928e..7b047effe 100644
--- a/desmume/src/windows/File_Extractor/7z_C/7zIn.c
+++ b/desmume/src/windows/File_Extractor/7z_C/7zIn.c
@@ -1322,7 +1322,7 @@ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAl
SRes SzArEx_Extract(
const CSzArEx *p,
ILookInStream *inStream,
- UInt32 fileIndex,
+ UInt64 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
diff --git a/desmume/src/windows/File_Extractor/7z_C/LzFindMt.c b/desmume/src/windows/File_Extractor/7z_C/LzFindMt.c
index db95590c3..8b44ef706 100644
--- a/desmume/src/windows/File_Extractor/7z_C/LzFindMt.c
+++ b/desmume/src/windows/File_Extractor/7z_C/LzFindMt.c
@@ -97,7 +97,7 @@ void MtSync_Destruct(CMtSync *p)
#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; }
-static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
+static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_RET_TYPE (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
{
if (p->wasCreated)
return SZ_OK;
@@ -119,7 +119,7 @@ static SRes MtSync_Create2(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void
return SZ_OK;
}
-static SRes MtSync_Create(CMtSync *p, unsigned (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
+static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_RET_TYPE (MY_STD_CALL *startAddress)(void *), void *obj, UInt32 numBlocks)
{
SRes res = MtSync_Create2(p, startAddress, obj, numBlocks);
if (res != SZ_OK)
@@ -451,8 +451,8 @@ void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAlloc *alloc)
#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks)
#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks)
-static unsigned MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
-static unsigned MY_STD_CALL BtThreadFunc2(void *p)
+static THREAD_FUNC_RET_TYPE MY_STD_CALL HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; }
+static THREAD_FUNC_RET_TYPE MY_STD_CALL BtThreadFunc2(void *p)
{
Byte allocaDummy[0x180];
int i = 0;
diff --git a/desmume/src/windows/File_Extractor/7z_C/MtCoder.c b/desmume/src/windows/File_Extractor/7z_C/MtCoder.c
index 9f0d268cf..7d0205048 100644
--- a/desmume/src/windows/File_Extractor/7z_C/MtCoder.c
+++ b/desmume/src/windows/File_Extractor/7z_C/MtCoder.c
@@ -25,12 +25,12 @@ static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
for (;;)
{
if (Event_Wait(&p->startEvent) != 0)
- return SZ_ERROR_THREAD;
+ return (THREAD_FUNC_RET_TYPE) SZ_ERROR_THREAD;
if (p->stop)
return 0;
p->res = p->func(p->param);
if (Event_Set(&p->finishedEvent) != 0)
- return SZ_ERROR_THREAD;
+ return (THREAD_FUNC_RET_TYPE) SZ_ERROR_THREAD;
}
}
@@ -239,7 +239,7 @@ static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
next->stopWriting = True;
Event_Set(&next->canRead);
Event_Set(&next->canWrite);
- return res;
+ return (THREAD_FUNC_RET_TYPE) (long) res;
}
if (stop)
return 0;
diff --git a/desmume/src/windows/File_Extractor/7z_C/Threads.h b/desmume/src/windows/File_Extractor/7z_C/Threads.h
index 6a7afa829..42934a1e0 100644
--- a/desmume/src/windows/File_Extractor/7z_C/Threads.h
+++ b/desmume/src/windows/File_Extractor/7z_C/Threads.h
@@ -1,59 +1,5 @@
-/* Threads.h -- multithreading library
-2009-03-27 : Igor Pavlov : Public domain */
-
-#ifndef __7Z_THREADS_H
-#define __7Z_THREADS_H
-
-#include "Types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-WRes HandlePtr_Close(HANDLE *h);
-WRes Handle_WaitObject(HANDLE h);
-
-typedef HANDLE CThread;
-#define Thread_Construct(p) *(p) = NULL
-#define Thread_WasCreated(p) (*(p) != NULL)
-#define Thread_Close(p) HandlePtr_Close(p)
-#define Thread_Wait(p) Handle_WaitObject(*(p))
-typedef unsigned THREAD_FUNC_RET_TYPE;
-#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
-#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
-typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
-WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
-
-typedef HANDLE CEvent;
-typedef CEvent CAutoResetEvent;
-typedef CEvent CManualResetEvent;
-#define Event_Construct(p) *(p) = NULL
-#define Event_IsCreated(p) (*(p) != NULL)
-#define Event_Close(p) HandlePtr_Close(p)
-#define Event_Wait(p) Handle_WaitObject(*(p))
-WRes Event_Set(CEvent *p);
-WRes Event_Reset(CEvent *p);
-WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
-WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
-WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
-WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
-
-typedef HANDLE CSemaphore;
-#define Semaphore_Construct(p) (*p) = NULL
-#define Semaphore_Close(p) HandlePtr_Close(p)
-#define Semaphore_Wait(p) Handle_WaitObject(*(p))
-WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
-WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
-WRes Semaphore_Release1(CSemaphore *p);
-
-typedef CRITICAL_SECTION CCriticalSection;
-WRes CriticalSection_Init(CCriticalSection *p);
-#define CriticalSection_Delete(p) DeleteCriticalSection(p)
-#define CriticalSection_Enter(p) EnterCriticalSection(p)
-#define CriticalSection_Leave(p) LeaveCriticalSection(p)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+#ifdef _WIN32
+#include "win32/Threads.h"
+#else
+#include "posix/Threads.h"
+#endif
diff --git a/desmume/src/windows/File_Extractor/7z_C/Types.h b/desmume/src/windows/File_Extractor/7z_C/Types.h
index f193ce2f5..eef262838 100644
--- a/desmume/src/windows/File_Extractor/7z_C/Types.h
+++ b/desmume/src/windows/File_Extractor/7z_C/Types.h
@@ -8,6 +8,16 @@
#ifdef _WIN32
#include
+#else
+
+typedef unsigned char BOOL;
+#define FALSE 0
+#define TRUE 1
+
+typedef long LONG;
+
+typedef void *LPVOID;
+
#endif
#ifndef EXTERN_C_BEGIN
diff --git a/desmume/src/windows/File_Extractor/7z_C/win32/Threads.c b/desmume/src/windows/File_Extractor/7z_C/win32/Threads.c
new file mode 100644
index 000000000..4be44fb0f
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/7z_C/win32/Threads.c
@@ -0,0 +1,84 @@
+/* Threads.c -- multithreading library
+2009-09-20 : Igor Pavlov : Public domain */
+
+#ifndef _WIN32_WCE
+#include
+#endif
+
+#include "Threads.h"
+
+static WRes GetError()
+{
+ DWORD res = GetLastError();
+ return (res) ? (WRes)(res) : 1;
+}
+
+WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
+WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
+
+WRes HandlePtr_Close(HANDLE *p)
+{
+ if (*p != NULL)
+ if (!CloseHandle(*p))
+ return GetError();
+ *p = NULL;
+ return 0;
+}
+
+WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
+
+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
+{
+ unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
+ *p =
+ #ifdef UNDER_CE
+ CreateThread(0, 0, func, param, 0, &threadId);
+ #else
+ (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
+ #endif
+ /* maybe we must use errno here, but probably GetLastError() is also OK. */
+ return HandleToWRes(*p);
+}
+
+WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
+{
+ *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
+ return HandleToWRes(*p);
+}
+
+WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }
+WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }
+
+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }
+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }
+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }
+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
+
+
+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
+{
+ *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
+ return HandleToWRes(*p);
+}
+
+static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
+ { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
+ { return Semaphore_Release(p, (LONG)num, NULL); }
+WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
+
+WRes CriticalSection_Init(CCriticalSection *p)
+{
+ /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */
+ #ifdef _MSC_VER
+ __try
+ #endif
+ {
+ InitializeCriticalSection(p);
+ /* InitializeCriticalSectionAndSpinCount(p, 0); */
+ }
+ #ifdef _MSC_VER
+ __except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
+ #endif
+ return 0;
+}
diff --git a/desmume/src/windows/File_Extractor/7z_C/win32/Threads.h b/desmume/src/windows/File_Extractor/7z_C/win32/Threads.h
new file mode 100644
index 000000000..159099459
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/7z_C/win32/Threads.h
@@ -0,0 +1,59 @@
+/* Threads.h -- multithreading library
+2009-03-27 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_THREADS_H
+#define __7Z_THREADS_H
+
+#include "../Types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+WRes HandlePtr_Close(HANDLE *h);
+WRes Handle_WaitObject(HANDLE h);
+
+typedef HANDLE CThread;
+#define Thread_Construct(p) *(p) = NULL
+#define Thread_WasCreated(p) (*(p) != NULL)
+#define Thread_Close(p) HandlePtr_Close(p)
+#define Thread_Wait(p) Handle_WaitObject(*(p))
+typedef unsigned THREAD_FUNC_RET_TYPE;
+#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
+#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
+typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
+WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
+
+typedef HANDLE CEvent;
+typedef CEvent CAutoResetEvent;
+typedef CEvent CManualResetEvent;
+#define Event_Construct(p) *(p) = NULL
+#define Event_IsCreated(p) (*(p) != NULL)
+#define Event_Close(p) HandlePtr_Close(p)
+#define Event_Wait(p) Handle_WaitObject(*(p))
+WRes Event_Set(CEvent *p);
+WRes Event_Reset(CEvent *p);
+WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
+WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
+WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
+WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
+
+typedef HANDLE CSemaphore;
+#define Semaphore_Construct(p) (*p) = NULL
+#define Semaphore_Close(p) HandlePtr_Close(p)
+#define Semaphore_Wait(p) Handle_WaitObject(*(p))
+WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
+WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
+WRes Semaphore_Release1(CSemaphore *p);
+
+typedef CRITICAL_SECTION CCriticalSection;
+WRes CriticalSection_Init(CCriticalSection *p);
+#define CriticalSection_Delete(p) DeleteCriticalSection(p)
+#define CriticalSection_Enter(p) EnterCriticalSection(p)
+#define CriticalSection_Leave(p) LeaveCriticalSection(p)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/fex/Binary_Extractor.cpp b/desmume/src/windows/File_Extractor/fex/Binary_Extractor.cpp
index 625d6926d..92998eb65 100644
--- a/desmume/src/windows/File_Extractor/fex/Binary_Extractor.cpp
+++ b/desmume/src/windows/File_Extractor/fex/Binary_Extractor.cpp
@@ -24,7 +24,6 @@ static File_Extractor* new_binary()
fex_type_t_ const fex_bin_type [1] = {{
"",
- { NULL },
&new_binary,
"file",
NULL
@@ -72,7 +71,7 @@ blargg_err_t Binary_Extractor::stat_v()
return open_v();
}
-blargg_err_t Binary_Extractor::extract_v( void* p, int n )
+blargg_err_t Binary_Extractor::extract_v( void* p, long n )
{
return arc().read( p, n );
}
diff --git a/desmume/src/windows/File_Extractor/fex/Binary_Extractor.h b/desmume/src/windows/File_Extractor/fex/Binary_Extractor.h
index d8cca642f..f01508a89 100644
--- a/desmume/src/windows/File_Extractor/fex/Binary_Extractor.h
+++ b/desmume/src/windows/File_Extractor/fex/Binary_Extractor.h
@@ -20,7 +20,7 @@ protected:
virtual blargg_err_t rewind_v();
virtual blargg_err_t stat_v();
- virtual blargg_err_t extract_v( void*, int );
+ virtual blargg_err_t extract_v( void*, long );
};
#endif
diff --git a/desmume/src/windows/File_Extractor/fex/Data_Reader.cpp b/desmume/src/windows/File_Extractor/fex/Data_Reader.cpp
index 16c49a454..0ad8bf648 100644
--- a/desmume/src/windows/File_Extractor/fex/Data_Reader.cpp
+++ b/desmume/src/windows/File_Extractor/fex/Data_Reader.cpp
@@ -6,10 +6,6 @@
#include
#include
-#if BLARGG_UTF8_PATHS
- #include
-#endif
-
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
@@ -25,7 +21,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
// Data_Reader
-blargg_err_t Data_Reader::read( void* p, int n )
+blargg_err_t Data_Reader::read( void* p, long n )
{
assert( n >= 0 );
@@ -49,7 +45,7 @@ blargg_err_t Data_Reader::read_avail( void* p, int* n_ )
{
assert( *n_ >= 0 );
- int n = min( (BOOST::uint64_t)(*n_), remain() );
+ long n = (long) min( (BOOST::uint64_t)(*n_), remain() );
*n_ = 0;
if ( n < 0 )
@@ -62,7 +58,7 @@ blargg_err_t Data_Reader::read_avail( void* p, int* n_ )
if ( !err )
{
remain_ -= n;
- *n_ = n;
+ *n_ = (int) n;
}
return err;
@@ -76,19 +72,19 @@ blargg_err_t Data_Reader::read_avail( void* p, long* n )
return err;
}
-blargg_err_t Data_Reader::skip_v( int count )
+blargg_err_t Data_Reader::skip_v( BOOST::uint64_t count )
{
char buf [512];
while ( count )
{
- int n = min( count, (int) sizeof buf );
+ BOOST::uint64_t n = min( count, (BOOST::uint64_t) sizeof buf );
count -= n;
- RETURN_ERR( read_v( buf, n ) );
+ RETURN_ERR( read_v( buf, (long)n ) );
}
return blargg_ok;
}
-blargg_err_t Data_Reader::skip( int n )
+blargg_err_t Data_Reader::skip( long n )
{
assert( n >= 0 );
@@ -115,9 +111,6 @@ blargg_err_t File_Reader::seek( BOOST::uint64_t n )
{
assert( n >= 0 );
- if ( n < 0 )
- return blargg_err_caller;
-
if ( n == tell() )
return blargg_ok;
@@ -145,7 +138,7 @@ Subset_Reader::Subset_Reader( Data_Reader* dr, BOOST::uint64_t size ) :
set_remain( min( size, dr->remain() ) );
}
-blargg_err_t Subset_Reader::read_v( void* p, int s )
+blargg_err_t Subset_Reader::read_v( void* p, long s )
{
return in->read( p, s );
}
@@ -162,9 +155,9 @@ Remaining_Reader::Remaining_Reader( void const* h, int size, Data_Reader* r ) :
set_remain( size + r->remain() );
}
-blargg_err_t Remaining_Reader::read_v( void* out, int count )
+blargg_err_t Remaining_Reader::read_v( void* out, long count )
{
- int first = min( count, header_remain );
+ long first = min( count, header_remain );
if ( first )
{
memcpy( out, header, first );
@@ -184,13 +177,13 @@ Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
set_size( s );
}
-blargg_err_t Mem_File_Reader::read_v( void* p, int s )
+blargg_err_t Mem_File_Reader::read_v( void* p, long s )
{
memcpy( p, begin + tell(), s );
return blargg_ok;
}
-blargg_err_t Mem_File_Reader::seek_v( int )
+blargg_err_t Mem_File_Reader::seek_v( BOOST::uint64_t )
{
return blargg_ok;
}
@@ -205,7 +198,7 @@ Callback_Reader::Callback_Reader( callback_t c, BOOST::uint64_t s, void* d ) :
set_remain( s );
}
-blargg_err_t Callback_Reader::read_v( void* out, int count )
+blargg_err_t Callback_Reader::read_v( void* out, long count )
{
return callback( user_data, out, count );
}
@@ -220,12 +213,12 @@ Callback_File_Reader::Callback_File_Reader( callback_t c, BOOST::uint64_t s, voi
set_size( s );
}
-blargg_err_t Callback_File_Reader::read_v( void* out, int count )
+blargg_err_t Callback_File_Reader::read_v( void* out, long count )
{
return callback( user_data, out, count, tell() );
}
-blargg_err_t Callback_File_Reader::seek_v( int )
+blargg_err_t Callback_File_Reader::seek_v( BOOST::uint64_t )
{
return blargg_ok;
}
@@ -236,8 +229,6 @@ static const BOOST::uint8_t val_tab[6]={0,0xC0,0xE0,0xF0,0xF8,0xFC};
size_t utf8_char_len_from_header( char p_c )
{
- BOOST::uint8_t c = (BOOST::uint8_t)p_c;
-
size_t cnt = 0;
for(;;)
{
@@ -349,21 +340,21 @@ size_t utf8_encode_char( unsigned wide, char * target )
return count;
}
-size_t utf16_encode_char( unsigned cur_wchar, wchar_t * out )
+size_t utf16_encode_char( unsigned cur_wchar, blargg_wchar_t * out )
{
if ( cur_wchar < 0x10000 )
{
- if ( out ) *out = (wchar_t) cur_wchar; return 1;
+ if ( out ) *out = (blargg_wchar_t) cur_wchar; return 1;
}
else if ( cur_wchar < ( 1 << 20 ) )
{
unsigned c = cur_wchar - 0x10000;
//MSDN:
- //The first (high) surrogate is a 16-bit code value in the range U+D800 to U+DBFF. The second (low) surrogate is a 16-bit code value in the range U+DC00 to U+DFFF. Using surrogates, Unicode can support over one million characters. For more details about surrogates, refer to The Unicode Standard, version 2.0.
+ //The first (high) surrogate is a 16-bit code value in the range U+D800 to U+DBFF. The second (low) surrogate is a 16-bit code value in the range U+DC00 to U+DFFF. Using surrogates, Unicode can support over one million characters. For more details about surrogates, refer to The Unicode Standard, version 2.0.
if ( out )
{
- out[0] = ( wchar_t )( 0xD800 | ( 0x3FF & ( c >> 10 ) ) );
- out[1] = ( wchar_t )( 0xDC00 | ( 0x3FF & c ) ) ;
+ out[0] = ( blargg_wchar_t )( 0xD800 | ( 0x3FF & ( c >> 10 ) ) );
+ out[1] = ( blargg_wchar_t )( 0xDC00 | ( 0x3FF & c ) ) ;
}
return 2;
}
@@ -373,7 +364,7 @@ size_t utf16_encode_char( unsigned cur_wchar, wchar_t * out )
}
}
-size_t utf16_decode_char( const wchar_t * p_source, unsigned * p_out, size_t p_source_length )
+size_t utf16_decode_char( const blargg_wchar_t * p_source, unsigned * p_out, size_t p_source_length )
{
if ( p_source_length == 0 ) return 0;
else if ( p_source_length == 1 )
@@ -404,13 +395,13 @@ size_t utf16_decode_char( const wchar_t * p_source, unsigned * p_out, size_t p_s
}
// Converts wide-character path to UTF-8. Free result with free(). Only supported on Windows.
-char* blargg_to_utf8( const wchar_t* wpath )
+char* blargg_to_utf8( const blargg_wchar_t* wpath )
{
if ( wpath == NULL )
return NULL;
size_t needed = 0;
- size_t mmax = wcslen( wpath );
+ size_t mmax = blargg_wcslen( wpath );
if ( mmax <= 0 )
return NULL;
@@ -452,7 +443,7 @@ char* blargg_to_utf8( const wchar_t* wpath )
}
// Converts UTF-8 path to wide-character. Free result with free() Only supported on Windows.
-wchar_t* blargg_to_wide( const char* path )
+blargg_wchar_t* blargg_to_wide( const char* path )
{
if ( path == NULL )
return NULL;
@@ -474,7 +465,7 @@ wchar_t* blargg_to_wide( const char* path )
if ( needed <= 0 )
return NULL;
- wchar_t* wpath = (wchar_t*) calloc( needed + 1, sizeof *wpath );
+ blargg_wchar_t* wpath = (blargg_wchar_t*) calloc( needed + 1, sizeof *wpath );
if ( wpath == NULL )
return NULL;
@@ -503,15 +494,19 @@ wchar_t* blargg_to_wide( const char* path )
static FILE* blargg_fopen( const char path [], const char mode [] )
{
FILE* file = NULL;
- wchar_t* wmode = NULL;
- wchar_t* wpath = NULL;
+ blargg_wchar_t* wmode = NULL;
+ blargg_wchar_t* wpath = NULL;
wpath = blargg_to_wide( path );
if ( wpath )
{
wmode = blargg_to_wide( mode );
- if ( wmode )
+ if (wmode)
+#if _MSC_VER >= 1300
+ errno = _wfopen_s(&file, wpath, wmode);
+#else
file = _wfopen( wpath, wmode );
+#endif
}
// Save and restore errno in case free() clears it
@@ -603,11 +598,21 @@ blargg_err_t Std_File_Reader::open( const char path [] )
void Std_File_Reader::make_unbuffered()
{
+#ifdef _WIN32
+ BOOST::uint64_t offset = _ftelli64( STATIC_CAST(FILE*, file_) );
+#else
+ BOOST::uint64_t offset = ftello( STATIC_CAST(FILE*, file_) );
+#endif
if ( setvbuf( STATIC_CAST(FILE*, file_), NULL, _IONBF, 0 ) )
check( false ); // shouldn't fail, but OK if it does
+#ifdef _WIN32
+ _fseeki64( STATIC_CAST(FILE*, file_), offset, SEEK_SET );
+#else
+ fseeko( STATIC_CAST(FILE*, file_), offset, SEEK_SET );
+#endif
}
-blargg_err_t Std_File_Reader::read_v( void* p, int s )
+blargg_err_t Std_File_Reader::read_v( void* p, long s )
{
if ( (size_t) s != fread( p, 1, s, STATIC_CAST(FILE*, file_) ) )
{
@@ -622,7 +627,11 @@ blargg_err_t Std_File_Reader::read_v( void* p, int s )
blargg_err_t Std_File_Reader::seek_v( BOOST::uint64_t n )
{
+#ifdef _WIN32
if ( _fseeki64( STATIC_CAST(FILE*, file_), n, SEEK_SET ) )
+#else
+ if ( fseeko( STATIC_CAST(FILE*, file_), n, SEEK_SET ) )
+#endif
{
// Data_Reader's wrapper should prevent EOF
check( !feof( STATIC_CAST(FILE*, file_) ) );
@@ -729,24 +738,30 @@ static blargg_err_t convert_gz_error( gzFile file )
return blargg_err_internal;
}
-blargg_err_t Gzip_File_Reader::read_v( void* p, int s )
+blargg_err_t Gzip_File_Reader::read_v( void* p, long s )
{
- int result = gzread( file_, p, s );
- if ( result != s )
- {
- if ( result < 0 )
- return convert_gz_error( file_ );
+ while ( s > 0 )
+ {
+ int s_i = (int)( s > INT_MAX ? INT_MAX : s );
+ int result = gzread( (gzFile) file_, p, s_i );
+ if ( result != s_i )
+ {
+ if ( result < 0 )
+ return convert_gz_error( (gzFile) file_ );
- return blargg_err_file_corrupt;
- }
+ return blargg_err_file_corrupt;
+ }
+ p = (char*)p + result;
+ s -= result;
+ }
return blargg_ok;
}
-blargg_err_t Gzip_File_Reader::seek_v( int n )
+blargg_err_t Gzip_File_Reader::seek_v( BOOST::uint64_t n )
{
- if ( gzseek( file_, n, SEEK_SET ) < 0 )
- return convert_gz_error( file_ );
+ if ( gzseek( (gzFile) file_, (long)n, SEEK_SET ) < 0 )
+ return convert_gz_error( (gzFile) file_ );
return blargg_ok;
}
@@ -755,7 +770,7 @@ void Gzip_File_Reader::close()
{
if ( file_ )
{
- if ( gzclose( file_ ) )
+ if ( gzclose( (gzFile) file_ ) )
check( false );
file_ = NULL;
}
diff --git a/desmume/src/windows/File_Extractor/fex/Data_Reader.h b/desmume/src/windows/File_Extractor/fex/Data_Reader.h
index 12847cb99..4216e9e5a 100644
--- a/desmume/src/windows/File_Extractor/fex/Data_Reader.h
+++ b/desmume/src/windows/File_Extractor/fex/Data_Reader.h
@@ -26,13 +26,13 @@ public:
// Reads exactly n bytes, or returns error if they couldn't ALL be read.
// Reading past end of file results in blargg_err_file_eof.
- blargg_err_t read( void* p, int n );
+ blargg_err_t read( void* p, long n );
// Number of bytes remaining until end of file
BOOST::uint64_t remain() const { return remain_; }
// Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof.
- blargg_err_t skip( int n );
+ blargg_err_t skip( long n );
virtual ~Data_Reader() { }
@@ -50,12 +50,12 @@ protected:
// Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated
// AFTER this call succeeds, not before. set_remain() should NOT be called from this.
- virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
+ virtual blargg_err_t read_v( void*, long n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
// Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data
// and discards it. Value of remain() is updated AFTER this call succeeds, not
// before. set_remain() should NOT be called from this.
- virtual blargg_err_t skip_v( int n );
+ virtual blargg_err_t skip_v( BOOST::uint64_t n );
// Implementation
public:
@@ -126,7 +126,7 @@ public:
virtual ~Std_File_Reader();
protected:
- virtual blargg_err_t read_v( void*, int );
+ virtual blargg_err_t read_v( void*, long );
virtual blargg_err_t seek_v( BOOST::uint64_t );
private:
@@ -142,8 +142,8 @@ public:
// Implementation
protected:
- virtual blargg_err_t read_v( void*, int );
- virtual blargg_err_t seek_v( int );
+ virtual blargg_err_t read_v( void*, long );
+ virtual blargg_err_t seek_v( BOOST::uint64_t );
private:
const char* const begin;
@@ -158,7 +158,7 @@ public:
// Implementation
protected:
- virtual blargg_err_t read_v( void*, int );
+ virtual blargg_err_t read_v( void*, long );
private:
Data_Reader* const in;
@@ -175,12 +175,12 @@ public:
// Implementation
protected:
- virtual blargg_err_t read_v( void*, int );
+ virtual blargg_err_t read_v( void*, long );
private:
Data_Reader* const in;
void const* header;
- int header_remain;
+ long header_remain;
};
@@ -189,7 +189,7 @@ extern "C" { // necessary to be usable from C
typedef const char* (*callback_reader_func_t)(
void* user_data, // Same value passed to constructor
void* out, // Buffer to place data into
- int count // Number of bytes to read
+ long count // Number of bytes to read
);
}
class Callback_Reader : public Data_Reader {
@@ -199,7 +199,7 @@ public:
// Implementation
protected:
- virtual blargg_err_t read_v( void*, int );
+ virtual blargg_err_t read_v( void*, long );
private:
callback_t const callback;
@@ -212,7 +212,7 @@ extern "C" { // necessary to be usable from C
typedef const char* (*callback_file_reader_func_t)(
void* user_data, // Same value passed to constructor
void* out, // Buffer to place data into
- int count, // Number of bytes to read
+ long count, // Number of bytes to read
BOOST::uint64_t pos // Position in file to read from
);
}
@@ -223,8 +223,8 @@ public:
// Implementation
protected:
- virtual blargg_err_t read_v( void*, int );
- virtual blargg_err_t seek_v( int );
+ virtual blargg_err_t read_v( void*, long );
+ virtual blargg_err_t seek_v( BOOST::uint64_t );
private:
callback_t const callback;
@@ -250,8 +250,8 @@ public:
~Gzip_File_Reader();
protected:
- virtual blargg_err_t read_v( void*, int );
- virtual blargg_err_t seek_v( int );
+ virtual blargg_err_t read_v( void*, long );
+ virtual blargg_err_t seek_v( BOOST::uint64_t );
private:
// void* so "zlib.h" doesn't have to be included here
@@ -259,7 +259,16 @@ private:
};
#endif
-char* blargg_to_utf8( const wchar_t* );
-wchar_t* blargg_to_wide( const char* );
+#ifdef _WIN32
+typedef wchar_t blargg_wchar_t;
+#elif defined(HAVE_STDINT_H)
+#include
+typedef uint16_t blargg_wchar_t;
+#else
+typedef unsigned short blargg_wchar_t;
+#endif
+
+char* blargg_to_utf8( const blargg_wchar_t* );
+blargg_wchar_t* blargg_to_wide( const char* );
#endif
diff --git a/desmume/src/windows/File_Extractor/fex/File_Extractor.cpp b/desmume/src/windows/File_Extractor/fex/File_Extractor.cpp
index 2aaefd038..5170af279 100644
--- a/desmume/src/windows/File_Extractor/fex/File_Extractor.cpp
+++ b/desmume/src/windows/File_Extractor/fex/File_Extractor.cpp
@@ -152,7 +152,7 @@ void File_Extractor::clear_file()
clear_file_v();
}
-void File_Extractor::set_name( const char new_name [], const wchar_t* new_wname )
+void File_Extractor::set_name( const char new_name [], const blargg_wchar_t* new_wname )
{
name_ = new_name;
wname_ = new_wname;
@@ -313,7 +313,7 @@ blargg_err_t File_Extractor::data( const void** data_out )
blargg_err_t File_Extractor::data_v( void const** out )
{
- RETURN_ERR( own_data_.resize( size() ) );
+ RETURN_ERR( own_data_.resize( (size_t) size() ) );
*out = own_data_.begin();
blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() );
@@ -323,7 +323,7 @@ blargg_err_t File_Extractor::data_v( void const** out )
return err;
}
-blargg_err_t File_Extractor::extract_v( void* out, int count )
+blargg_err_t File_Extractor::extract_v( void* out, long count )
{
void const* p;
RETURN_ERR( data( &p ) );
@@ -332,7 +332,7 @@ blargg_err_t File_Extractor::extract_v( void* out, int count )
return blargg_ok;
}
-blargg_err_t File_Extractor::read_v( void* out, int count )
+blargg_err_t File_Extractor::read_v( void* out, long count )
{
if ( data_ptr_ )
return File_Extractor::extract_v( out, count );
diff --git a/desmume/src/windows/File_Extractor/fex/File_Extractor.h b/desmume/src/windows/File_Extractor/fex/File_Extractor.h
index fff0c4da9..7ee4507b4 100644
--- a/desmume/src/windows/File_Extractor/fex/File_Extractor.h
+++ b/desmume/src/windows/File_Extractor/fex/File_Extractor.h
@@ -39,7 +39,7 @@ public:
// See fex.h
const char* name() const { return name_; }
- const wchar_t* wname() const { return wname_; }
+ const blargg_wchar_t* wname() const { return wname_; }
blargg_err_t stat();
BOOST::uint64_t size() const { assert( stat_called ); return size_; }
unsigned int dos_date() const { return date_; }
@@ -73,7 +73,7 @@ protected:
File_Reader& arc() const { return *reader_; }
// Sets current file name
- void set_name( const char name [], const wchar_t* wname = NULL );
+ void set_name( const char name [], const blargg_wchar_t* wname = NULL );
// Sets current file information
void set_info( BOOST::uint64_t size, unsigned date = 0, unsigned crc = 0 );
@@ -118,7 +118,7 @@ protected:
virtual blargg_err_t data_v( const void** out );
// Extract next n bytes
- virtual blargg_err_t extract_v( void* out, int n );
+ virtual blargg_err_t extract_v( void* out, long n );
// Implementation
public:
@@ -139,7 +139,7 @@ private:
// Info for current file in archive
const char* name_;
- const wchar_t* wname_;
+ const blargg_wchar_t* wname_;
unsigned date_;
unsigned crc32_;
BOOST::uint64_t size_;
@@ -158,13 +158,12 @@ private:
// Data_Reader overrides
// TODO: override skip_v?
- virtual blargg_err_t read_v( void* out, int n );
+ virtual blargg_err_t read_v( void* out, long n );
};
struct fex_type_t_
{
const char* extension;
- const char** signatures;
File_Extractor* (*new_fex)();
const char* name;
blargg_err_t (*init)(); // Called by fex_init(). Can be NULL.
diff --git a/desmume/src/windows/File_Extractor/fex/Gzip_Extractor.cpp b/desmume/src/windows/File_Extractor/fex/Gzip_Extractor.cpp
index a25b78533..a5f74b079 100644
--- a/desmume/src/windows/File_Extractor/fex/Gzip_Extractor.cpp
+++ b/desmume/src/windows/File_Extractor/fex/Gzip_Extractor.cpp
@@ -28,11 +28,8 @@ static File_Extractor* new_gzip()
return BLARGG_NEW Gzip_Extractor;
}
-static const char * gz_signatures[] = { "\x1F\x8B", NULL };
-
fex_type_t_ const fex_gz_type [1] = {{
".gz",
- gz_signatures,
&new_gzip,
"gzipped file",
&init_gzip_file
@@ -95,7 +92,7 @@ blargg_err_t Gzip_Extractor::rewind_v()
return blargg_ok;
}
-blargg_err_t Gzip_Extractor::extract_v( void* p, int n )
+blargg_err_t Gzip_Extractor::extract_v( void* p, long n )
{
return gr.read( p, n );
}
diff --git a/desmume/src/windows/File_Extractor/fex/Gzip_Extractor.h b/desmume/src/windows/File_Extractor/fex/Gzip_Extractor.h
index 02044d0c7..28e02f26a 100644
--- a/desmume/src/windows/File_Extractor/fex/Gzip_Extractor.h
+++ b/desmume/src/windows/File_Extractor/fex/Gzip_Extractor.h
@@ -22,7 +22,7 @@ protected:
virtual blargg_err_t rewind_v();
virtual blargg_err_t stat_v();
- virtual blargg_err_t extract_v( void*, int );
+ virtual blargg_err_t extract_v( void*, long );
private:
Gzip_Reader gr;
diff --git a/desmume/src/windows/File_Extractor/fex/Gzip_Reader.cpp b/desmume/src/windows/File_Extractor/fex/Gzip_Reader.cpp
index 464beee7e..90512d3c9 100644
--- a/desmume/src/windows/File_Extractor/fex/Gzip_Reader.cpp
+++ b/desmume/src/windows/File_Extractor/fex/Gzip_Reader.cpp
@@ -25,7 +25,7 @@ Gzip_Reader::Gzip_Reader()
Gzip_Reader::~Gzip_Reader()
{ }
-static blargg_err_t gzip_reader_read( void* file, void* out, int* count )
+static blargg_err_t gzip_reader_read( void* file, void* out, long* count )
{
return STATIC_CAST(File_Reader*,file)->read_avail( out, count );
}
@@ -37,7 +37,7 @@ blargg_err_t Gzip_Reader::calc_size()
if ( inflater.deflated() )
{
byte trailer [8];
- int old_pos = in->tell();
+ BOOST::uint64_t old_pos = in->tell();
RETURN_ERR( in->seek( size_ - sizeof trailer ) );
RETURN_ERR( in->read( trailer, sizeof trailer ) );
RETURN_ERR( in->seek( old_pos ) );
@@ -72,10 +72,10 @@ void Gzip_Reader::close()
inflater.end();
}
-blargg_err_t Gzip_Reader::read_v( void* out, int count )
+blargg_err_t Gzip_Reader::read_v( void* out, long count )
{
assert( in );
- int actual = count;
+ long actual = count;
RETURN_ERR( inflater.read( out, &actual ) );
if ( actual != count )
diff --git a/desmume/src/windows/File_Extractor/fex/Gzip_Reader.h b/desmume/src/windows/File_Extractor/fex/Gzip_Reader.h
index b514772fa..b4e51135b 100644
--- a/desmume/src/windows/File_Extractor/fex/Gzip_Reader.h
+++ b/desmume/src/windows/File_Extractor/fex/Gzip_Reader.h
@@ -32,12 +32,12 @@ public:
virtual ~Gzip_Reader();
protected:
- virtual blargg_err_t read_v( void*, int );
+ virtual blargg_err_t read_v( void*, long );
private:
File_Reader* in;
unsigned crc32_;
- int size_;
+ BOOST::uint64_t size_;
Zlib_Inflater inflater;
blargg_err_t calc_size();
diff --git a/desmume/src/windows/File_Extractor/fex/Rar_Extractor.cpp b/desmume/src/windows/File_Extractor/fex/Rar_Extractor.cpp
index 8d18afccb..dbac70e7b 100644
--- a/desmume/src/windows/File_Extractor/fex/Rar_Extractor.cpp
+++ b/desmume/src/windows/File_Extractor/fex/Rar_Extractor.cpp
@@ -30,11 +30,8 @@ static File_Extractor* new_rar()
return BLARGG_NEW Rar_Extractor;
}
-static const char * rar_signatures[] = { "\x52\x45\x7E\x5E", "\x52\x61\x72\x21", NULL };
-
fex_type_t_ const fex_rar_type [1] = {{
".rar",
- rar_signatures,
&new_rar,
"RAR archive",
&init_rar
@@ -86,8 +83,6 @@ extern "C"
{
static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos )
{
- // TODO: 64-bit file support
-
Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data);
if ( h->pos != pos )
{
@@ -148,7 +143,7 @@ blargg_err_t Rar_Extractor::skip_unextractables()
unrar_info_t const* info = unrar_info( unrar );
set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL );
- set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) );
+ set_info( info->size, (unsigned int)info->dos_date, (unsigned int)(info->is_crc32 ? info->crc : 0) );
}
return blargg_ok;
@@ -187,7 +182,7 @@ blargg_err_t Rar_Extractor::data_v( void const** out )
return convert_err( unrar_extract_mem( unrar, out ) );
}
-blargg_err_t Rar_Extractor::extract_v( void* out, int count )
+blargg_err_t Rar_Extractor::extract_v( void* out, long count )
{
// We can read entire file directly into user buffer
if ( count == size() )
diff --git a/desmume/src/windows/File_Extractor/fex/Rar_Extractor.h b/desmume/src/windows/File_Extractor/fex/Rar_Extractor.h
index f457e8843..edf841b60 100644
--- a/desmume/src/windows/File_Extractor/fex/Rar_Extractor.h
+++ b/desmume/src/windows/File_Extractor/fex/Rar_Extractor.h
@@ -5,7 +5,7 @@
#define RAR_EXTRACTOR_H
#include "File_Extractor.h"
-#include "../unrar/unrar.h"
+#include "unrar/unrar.h"
class Rar_Extractor : public File_Extractor {
public:
@@ -29,7 +29,7 @@ protected:
virtual blargg_err_t seek_arc_v( fex_pos_t );
virtual blargg_err_t data_v( void const** );
- virtual blargg_err_t extract_v( void*, int );
+ virtual blargg_err_t extract_v( void*, long );
private:
unrar_t* unrar;
diff --git a/desmume/src/windows/File_Extractor/fex/Zip7_Extractor.cpp b/desmume/src/windows/File_Extractor/fex/Zip7_Extractor.cpp
index 0dca6cece..862aab8c2 100644
--- a/desmume/src/windows/File_Extractor/fex/Zip7_Extractor.cpp
+++ b/desmume/src/windows/File_Extractor/fex/Zip7_Extractor.cpp
@@ -3,9 +3,9 @@
#include "Zip7_Extractor.h"
extern "C" {
-#include "../7z_C/7z.h"
-#include "../7z_C/7zAlloc.h"
-#include "../7z_C/7zCrc.h"
+#include "7z_C/7z.h"
+#include "7z_C/7zAlloc.h"
+#include "7z_C/7zCrc.h"
}
#include
@@ -143,11 +143,8 @@ static File_Extractor* new_7z()
return BLARGG_NEW Zip7_Extractor;
}
-static const char * zip7_signatures[] = { "\x37\x7A\xBC\xAF", NULL };
-
fex_type_t_ const fex_7z_type [1] = {{
".7z",
- zip7_signatures,
&new_7z,
"7-zip archive",
&init_7z
@@ -228,9 +225,13 @@ blargg_err_t Zip7_Extractor::next_v()
time_t _time = time;
- localtime_s( &tm, &_time );
+#ifdef _WIN32
+ localtime_s( &tm, &_time );
+#else
+ localtime_r( &_time, &tm );
+#endif
- date = ( tm.tm_sec >> 1 ) & 0x1F |
+ date = (( tm.tm_sec >> 1 ) & 0x1F) |
(( tm.tm_min & 0x3F ) << 5 ) |
(( tm.tm_hour & 0x1F ) << 11 ) |
(( tm.tm_mday & 0x1F ) << 16 ) |
@@ -238,15 +239,16 @@ blargg_err_t Zip7_Extractor::next_v()
(( ( tm.tm_year - 80 ) & 0x7F ) << 25 );
}
- size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 );
+ size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, (size_t) index, 0 );
name16.resize( name_length );
- SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() );
+ SzArEx_GetFileNameUtf16( &impl->db, (size_t) index, ( UInt16 * ) name16.begin() );
char * temp = blargg_to_utf8( name16.begin() );
- if ( !temp ) temp = "";
- size_t utf8_length = strlen( temp );
+ const char * name_8 = temp;
+ if ( !temp ) name_8 = "";
+ size_t utf8_length = strlen( name_8 );
name8.resize( utf8_length + 1 );
- memcpy( name8.begin(), temp, utf8_length + 1 );
- free( temp );
+ memcpy( name8.begin(), name_8, utf8_length + 1 );
+ if ( temp ) free( temp );
set_name( name8.begin(), name16.begin() );
set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) );
break;
diff --git a/desmume/src/windows/File_Extractor/fex/Zip7_Extractor.h b/desmume/src/windows/File_Extractor/fex/Zip7_Extractor.h
index 8a48c9606..714402913 100644
--- a/desmume/src/windows/File_Extractor/fex/Zip7_Extractor.h
+++ b/desmume/src/windows/File_Extractor/fex/Zip7_Extractor.h
@@ -26,9 +26,9 @@ protected:
private:
Zip7_Extractor_Impl* impl;
- int index;
+ fex_pos_t index;
blargg_vector name8;
- blargg_vector name16;
+ blargg_vector name16;
blargg_err_t zip7_err( int err );
};
diff --git a/desmume/src/windows/File_Extractor/fex/Zip_Extractor.cpp b/desmume/src/windows/File_Extractor/fex/Zip_Extractor.cpp
index 1c3826727..2293d3fc6 100644
--- a/desmume/src/windows/File_Extractor/fex/Zip_Extractor.cpp
+++ b/desmume/src/windows/File_Extractor/fex/Zip_Extractor.cpp
@@ -34,8 +34,6 @@ int const disk_block_size = 4 * 1024;
// Read buffer used for extracting file data
int const read_buf_size = 16 * 1024;
-#include
-
struct header_t
{
char type [4];
@@ -102,11 +100,8 @@ static File_Extractor* new_zip()
return BLARGG_NEW Zip_Extractor;
}
-static const char * zip_signatures[] = { "\x50\x4B\x03\x04", "\x50\x4B\x05\x06", NULL };
-
fex_type_t_ const fex_zip_type [1] = {{
".zip",
- zip_signatures,
&new_zip,
"ZIP archive",
&init_zip
@@ -135,7 +130,7 @@ blargg_err_t Zip_Extractor::open_path_v()
}
inline
-void Zip_Extractor::reorder_entry_header( int offset )
+void Zip_Extractor::reorder_entry_header( long offset )
{
catalog [offset + 0] = 0;
catalog [offset + 4] = 'P';
@@ -147,19 +142,19 @@ blargg_err_t Zip_Extractor::open_v()
return blargg_err_file_type;
// Read final end_read_size bytes of file
- BOOST::uint64_t file_pos = max( (BOOST::uint64_t) 0, arc().size() - end_read_size );
+ BOOST::int64_t file_pos = max( (BOOST::int64_t) 0, (BOOST::int64_t) arc().size() - end_read_size );
file_pos -= file_pos % disk_block_size;
- RETURN_ERR( catalog.resize( arc().size() - file_pos ) );
+ RETURN_ERR( catalog.resize( (size_t)(arc().size() - file_pos) ) );
RETURN_ERR( arc().seek( file_pos ) );
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
// Find end-of-catalog entry
- BOOST::uint64_t end_pos = catalog.size() - end_entry_size;
- while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) )
+ BOOST::int64_t end_pos = catalog.size() - end_entry_size;
+ while ( end_pos >= 0 && memcmp( &catalog [(size_t)end_pos], "PK\5\6", 4 ) )
end_pos--;
if ( end_pos < 0 )
return blargg_err_file_type;
- end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos];
+ end_entry_t const& end_entry = (end_entry_t&) catalog [(size_t)end_pos];
end_pos += file_pos;
// some idiotic zip compressors add data to end of zip without setting comment len
@@ -167,17 +162,17 @@ blargg_err_t Zip_Extractor::open_v()
// Find file offset of beginning of catalog
catalog_begin = get_le32( end_entry.dir_offset );
- int catalog_size = end_pos - catalog_begin;
+ BOOST::int64_t catalog_size = end_pos - catalog_begin;
if ( catalog_size < 0 )
return blargg_err_file_corrupt;
catalog_size += end_entry_size;
// See if catalog is entirely contained in bytes already read
- BOOST::uint64_t begin_offset = catalog_begin - file_pos;
+ BOOST::int64_t begin_offset = catalog_begin - file_pos;
if ( begin_offset >= 0 )
- memmove( catalog.begin(), &catalog [begin_offset], catalog_size );
+ memmove( catalog.begin(), &catalog [(size_t)begin_offset], (size_t)catalog_size );
- RETURN_ERR( catalog.resize( catalog_size ) );
+ RETURN_ERR( catalog.resize( (size_t)catalog_size ) );
if ( begin_offset < 0 )
{
// Catalog begins before bytes read, so it needs to be read
@@ -233,7 +228,7 @@ blargg_err_t Zip_Extractor::update_info( bool advance_first )
{
while ( 1 )
{
- entry_t& e = (entry_t&) catalog [catalog_pos];
+ entry_t& e = (entry_t&) catalog [(size_t)catalog_pos];
if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) )
{
@@ -242,74 +237,22 @@ blargg_err_t Zip_Extractor::update_info( bool advance_first )
}
unsigned len = get_le16( e.filename_len );
- int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) +
+ BOOST::int64_t next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) +
get_le16( e.comment_len );
if ( (unsigned) next_offset > catalog.size() - end_entry_size )
return blargg_err_file_corrupt;
- if ( catalog [next_offset] == 'P' )
- reorder_entry_header( next_offset );
+ if ( catalog [(size_t)next_offset] == 'P' )
+ reorder_entry_header( (long)next_offset );
if ( !advance_first )
{
- char unterminate = e.filename[len];
e.filename [len] = 0; // terminate name
- std::string fname = e.filename;
if ( is_normal_file( e, len ) )
{
- e.filename[len] = unterminate;
- name.resize(fname.size()+1);
- if(len != 0)
- {
- memcpy(name.begin(),fname.c_str(),len);
- name[name.size()-1] = 0;
- }
- set_name( name.begin() );
+ set_name( e.filename );
set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) );
-
- unsigned extra_len = get_le32(e.extra_len);
-
- //walk over extra fields
- unsigned i = len;
- while(i < extra_len + len)
- {
- unsigned id = get_le16(e.filename + i);
- i += 2;
- unsigned exlen = get_le16(e.filename + i);
- i += 2;
- int exfield = i;
- i += exlen;
- if(id == 0x7075) //INFO-ZIP unicode path extra field (contains version, checksum, and utf-8 filename)
- {
- unsigned version = (unsigned char)*(e.filename + exfield);
- if(version == 1)
- {
- exfield += 1; //skip version
- exfield += 4; //skip crc
- //the remainder is a utf-8 filename
- int fnamelen = exlen-5;
- char* tempbuf = (char*)malloc(fnamelen + 1);
- memcpy(tempbuf,e.filename + exfield, fnamelen);
- tempbuf[fnamelen] = 0;
- wchar_t* wfname_buf = blargg_to_wide(tempbuf);
- std::wstring wfname = wfname_buf;
- free(tempbuf);
- free(wfname_buf);
-
- size_t wfname_len = wfname.size();
-
- this->wname.resize(wfname_len+1);
- if(wfname_len != 0)
- {
- memcpy(this->wname.begin(),wfname.c_str(),wfname_len*sizeof(wchar_t));
- wname[wname.size()-1] = 0;
- }
- set_name( name.begin(), wname.begin() );
-
- }
- }
- }
break;
}
}
@@ -351,28 +294,28 @@ void Zip_Extractor::clear_file_v()
buf.end();
}
-blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count )
+blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, long* count )
{
Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data);
if ( *count > self.raw_remain )
- *count = self.raw_remain;
+ *count = (long)self.raw_remain;
self.raw_remain -= *count;
return self.arc().read( out, *count );
}
-blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read )
+blargg_err_t Zip_Extractor::fill_buf( long offset, long buf_size, long initial_read )
{
raw_remain = arc().size() - offset;
RETURN_ERR( arc().seek( offset ) );
return buf.begin( inflater_read, this, buf_size, initial_read );
}
-blargg_err_t Zip_Extractor::first_read( int count )
+blargg_err_t Zip_Extractor::first_read( long count )
{
- entry_t const& e = (entry_t&) catalog [catalog_pos];
+ entry_t const& e = (entry_t&) catalog [(size_t)catalog_pos];
// Determine compression
{
@@ -429,17 +372,25 @@ blargg_err_t Zip_Extractor::first_read( int count )
return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset );
}
-blargg_err_t Zip_Extractor::extract_v( void* out, int count )
+blargg_err_t Zip_Extractor::extract_v( void* out, long count )
{
if ( tell() == 0 )
RETURN_ERR( first_read( count ) );
- int actual = count;
+ long actual = count;
RETURN_ERR( buf.read( out, &actual ) );
if ( actual < count )
return blargg_err_file_corrupt;
-
- crc = ::crc32( crc, (byte const*) out, count );
+
+ long count_crc = count;
+ const byte * out_crc = (const byte *) out;
+ while ( count_crc > 0 )
+ {
+ unsigned int count_i = (unsigned int)( count_crc > UINT_MAX ? UINT_MAX : count_crc );
+ crc = ::crc32( crc, out_crc, count_i );
+ out_crc += count_i;
+ count_crc -= count_i;
+ }
if ( count == reader().remain() && crc != correct_crc )
return blargg_err_file_corrupt;
diff --git a/desmume/src/windows/File_Extractor/fex/Zip_Extractor.h b/desmume/src/windows/File_Extractor/fex/Zip_Extractor.h
index 71e67aa9f..9f0d8adcb 100644
--- a/desmume/src/windows/File_Extractor/fex/Zip_Extractor.h
+++ b/desmume/src/windows/File_Extractor/fex/Zip_Extractor.h
@@ -23,26 +23,23 @@ protected:
virtual fex_pos_t tell_arc_v() const;
virtual blargg_err_t seek_arc_v( fex_pos_t );
- virtual blargg_err_t extract_v( void*, int );
+ virtual blargg_err_t extract_v( void*, long );
private:
blargg_vector catalog;
- int catalog_begin; // offset of first catalog entry in file (to detect corruption)
- int catalog_pos; // position of current entry in catalog
+ BOOST::int64_t catalog_begin; // offset of first catalog entry in file (to detect corruption)
+ BOOST::int64_t catalog_pos; // position of current entry in catalog
BOOST::uint64_t raw_remain; // bytes remaining to be read from zip file for current file
- unsigned crc; // ongoing CRC of extracted bytes
- unsigned correct_crc;
+ unsigned long crc; // ongoing CRC of extracted bytes
+ unsigned long correct_crc;
bool file_deflated;
Zlib_Inflater buf;
- blargg_err_t fill_buf( int offset, int buf_size, int initial_read );
+ blargg_err_t fill_buf( long offset, long buf_size, long initial_read );
blargg_err_t update_info( bool advance_first );
- blargg_err_t first_read( int count );
- void reorder_entry_header( int offset );
- static blargg_err_t inflater_read( void* data, void* out, int* count );
-
- blargg_vector name;
- blargg_vector wname;
+ blargg_err_t first_read( long count );
+ void reorder_entry_header( long offset );
+ static blargg_err_t inflater_read( void* data, void* out, long* count );
};
#endif
diff --git a/desmume/src/windows/File_Extractor/fex/Zlib_Inflater.cpp b/desmume/src/windows/File_Extractor/fex/Zlib_Inflater.cpp
index ac77ca515..d6add6b6f 100644
--- a/desmume/src/windows/File_Extractor/fex/Zlib_Inflater.cpp
+++ b/desmume/src/windows/File_Extractor/fex/Zlib_Inflater.cpp
@@ -59,17 +59,17 @@ Zlib_Inflater::~Zlib_Inflater()
end();
}
-blargg_err_t Zlib_Inflater::fill_buf( int count )
+blargg_err_t Zlib_Inflater::fill_buf( long count )
{
byte* out = buf.end() - count;
RETURN_ERR( callback( user_data, out, &count ) );
- zbuf.avail_in = count;
+ zbuf.avail_in = (uInt) count;
zbuf.next_in = out;
return blargg_ok;
}
blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data,
- int new_buf_size, int initial_read )
+ long new_buf_size, long initial_read )
{
callback = new_callback;
user_data = new_user_data;
@@ -163,15 +163,15 @@ blargg_err_t Zlib_Inflater::read_all( void* out, int count )
}
*/
-blargg_err_t Zlib_Inflater::read( void* out, int* count_io )
+blargg_err_t Zlib_Inflater::read( void* out, long* count_io )
{
- int remain = *count_io;
+ long remain = *count_io;
if ( remain && zbuf.next_in )
{
if ( deflated_ )
{
zbuf.next_out = (Bytef*) out;
- zbuf.avail_out = remain;
+ zbuf.avail_out = (uInt)( remain > UINT_MAX ? UINT_MAX : remain );
while ( 1 )
{
@@ -232,7 +232,7 @@ blargg_err_t Zlib_Inflater::read( void* out, int* count_io )
// read large request directly
if ( remain + zbuf.total_out % block_size >= buf.size() )
{
- int count = remain;
+ long count = remain;
RETURN_ERR( callback( user_data, out, &count ) );
zbuf.total_out += count;
out = (char*) out + count;
diff --git a/desmume/src/windows/File_Extractor/fex/Zlib_Inflater.h b/desmume/src/windows/File_Extractor/fex/Zlib_Inflater.h
index 8dedfe8e2..a0a3309ff 100644
--- a/desmume/src/windows/File_Extractor/fex/Zlib_Inflater.h
+++ b/desmume/src/windows/File_Extractor/fex/Zlib_Inflater.h
@@ -13,13 +13,13 @@ public:
// Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count
// to that number, or returns error if that many can't be read.
- typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count );
+ typedef blargg_err_t (*callback_t)( void* user_data, void* out, long* count );
// Begins by setting callback and filling buffer. Default buffer is 16K and
// filled to 4K, or specify buf_size and initial_read for custom buffer size
// and how much to read initially.
blargg_err_t begin( callback_t, void* user_data,
- int buf_size = 0, int initial_read = 0 );
+ long buf_size = 0, long initial_read = 0 );
// Data read into buffer by begin()
const unsigned char* data() const { return zbuf.next_in; }
@@ -39,10 +39,10 @@ public:
// number of bytes read (less than requested if end of data was reached).
// Buffers source data internally, even in copy mode, so input file can be
// unbuffered without sacrificing performance.
- blargg_err_t read( void* out, int* count_io );
+ blargg_err_t read( void* out, long* count_io );
// Total number of bytes read since begin()
- int tell() const { return zbuf.total_out; }
+ long tell() const { return zbuf.total_out; }
// Ends inflation and frees memory
void end();
@@ -64,7 +64,7 @@ private:
callback_t callback;
void* user_data;
- blargg_err_t fill_buf( int count );
+ blargg_err_t fill_buf( long count );
};
#endif
diff --git a/desmume/src/windows/File_Extractor/fex/blargg_common.h b/desmume/src/windows/File_Extractor/fex/blargg_common.h
index 7844b48e9..ac29f929c 100644
--- a/desmume/src/windows/File_Extractor/fex/blargg_common.h
+++ b/desmume/src/windows/File_Extractor/fex/blargg_common.h
@@ -6,13 +6,27 @@
#define BLARGG_COMMON_H
#include
+#include
#include
#include
typedef const char* blargg_err_t; // 0 on success, otherwise error string
+#ifdef _WIN32
+typedef wchar_t blargg_wchar_t;
+#else
+typedef uint16_t blargg_wchar_t;
+#endif
+
+inline size_t blargg_wcslen( const blargg_wchar_t* str )
+{
+ size_t length = 0;
+ while ( *str++ ) length++;
+ return length;
+}
+
// Success; no error
-int const blargg_ok = 0;
+blargg_err_t const blargg_ok = 0;
// BLARGG_RESTRICT: equivalent to C99's restrict, where supported
#if __GNUC__ >= 3 || _MSC_VER >= 1100
diff --git a/desmume/src/windows/File_Extractor/fex/blargg_config.h b/desmume/src/windows/File_Extractor/fex/blargg_config.h
index 79e621b2c..8ec5b87c8 100644
--- a/desmume/src/windows/File_Extractor/fex/blargg_config.h
+++ b/desmume/src/windows/File_Extractor/fex/blargg_config.h
@@ -27,8 +27,7 @@
fex_zip_type,
*/
-//old (any?) msvc doesnt have stdint.h so this better not be here.
-//#define HAVE_STDINT_H
+#define HAVE_STDINT_H
// Use standard config.h if present
#ifdef HAVE_CONFIG_H
diff --git a/desmume/src/windows/File_Extractor/fex/blargg_source.h b/desmume/src/windows/File_Extractor/fex/blargg_source.h
index 96b750a23..6c253acd0 100644
--- a/desmume/src/windows/File_Extractor/fex/blargg_source.h
+++ b/desmume/src/windows/File_Extractor/fex/blargg_source.h
@@ -69,21 +69,8 @@ otherwise continues normally. */
return blargg_err_memory;\
} while ( 0 )
-/* The usual min/max functions for built-in types.
-
-template T min( T x, T y ) { return x < y ? x : y; }
-template T max( T x, T y ) { return x > y ? x : y; } */
-#define BLARGG_DEF_MIN_MAX( type ) \
- static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\
- static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; }
-
-BLARGG_DEF_MIN_MAX( int )
-BLARGG_DEF_MIN_MAX( unsigned )
-BLARGG_DEF_MIN_MAX( long )
-BLARGG_DEF_MIN_MAX( unsigned long )
-BLARGG_DEF_MIN_MAX( float )
-BLARGG_DEF_MIN_MAX( double )
-BLARGG_DEF_MIN_MAX( BOOST::uint64_t )
+template T blargg_min( T x, T y ) { return x < y ? x : y; }
+template T blargg_max( T x, T y ) { return x > y ? x : y; }
#undef min
#define min blargg_min
diff --git a/desmume/src/windows/File_Extractor/fex/fex.cpp b/desmume/src/windows/File_Extractor/fex/fex.cpp
index 78e547668..3941c7d5c 100644
--- a/desmume/src/windows/File_Extractor/fex/fex.cpp
+++ b/desmume/src/windows/File_Extractor/fex/fex.cpp
@@ -235,9 +235,9 @@ BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] )
//// Wide paths
-char* fex_wide_to_path( const wchar_t* wide )
+char* fex_wide_to_path( const blargg_wchar_t* wide )
{
- return blargg_to_utf8( wide );
+ return blargg_to_utf8( wide );
}
void fex_free_path( char* path )
@@ -295,28 +295,33 @@ BLARGG_EXPORT const char* fex_err_details( fex_err_t err )
//// Wrappers
-BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, int count )
+BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, long count )
{
RETURN_ERR( fe->stat() );
return fe->reader().read( out, count );
}
+BLARGG_EXPORT fex_err_t fex_skip( fex_t* fe, long count )
+{
+ RETURN_ERR( fe->stat() );
+ return fe->reader().skip( count );
+}
+
BLARGG_EXPORT void fex_close ( fex_t* fe ) { delete fe; }
BLARGG_EXPORT fex_type_t fex_type ( const fex_t* fe ) { return fe->type(); }
BLARGG_EXPORT int fex_done ( const fex_t* fe ) { return fe->done(); }
BLARGG_EXPORT const char* fex_name ( const fex_t* fe ) { return fe->name(); }
-BLARGG_EXPORT const wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); }
-BLARGG_EXPORT __int64 fex_size ( const fex_t* fe ) { return fe->size(); }
+BLARGG_EXPORT const blargg_wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); }
+BLARGG_EXPORT uint64_t fex_size ( const fex_t* fe ) { return fe->size(); }
BLARGG_EXPORT unsigned fex_dos_date ( const fex_t* fe ) { return fe->dos_date(); }
BLARGG_EXPORT unsigned fex_crc32 ( const fex_t* fe ) { return fe->crc32(); }
BLARGG_EXPORT fex_err_t fex_stat ( fex_t* fe ) { return fe->stat(); }
BLARGG_EXPORT fex_err_t fex_next ( fex_t* fe ) { return fe->next(); }
BLARGG_EXPORT fex_err_t fex_rewind ( fex_t* fe ) { return fe->rewind(); }
-BLARGG_EXPORT __int64 fex_tell ( const fex_t* fe ) { return fe->tell(); }
+BLARGG_EXPORT uint64_t fex_tell ( const fex_t* fe ) { return fe->tell(); }
BLARGG_EXPORT fex_pos_t fex_tell_arc ( const fex_t* fe ) { return fe->tell_arc(); }
BLARGG_EXPORT fex_err_t fex_seek_arc ( fex_t* fe, fex_pos_t pos ) { return fe->seek_arc( pos ); }
BLARGG_EXPORT const char* fex_type_extension ( fex_type_t t ) { return t->extension; }
-BLARGG_EXPORT const char**fex_type_signatures ( fex_type_t t ) { return t->signatures; }
BLARGG_EXPORT const char* fex_type_name ( fex_type_t t ) { return t->name; }
BLARGG_EXPORT fex_err_t fex_data ( fex_t* fe, const void** data_out ) { return fe->data( data_out ); }
BLARGG_EXPORT const char* fex_err_str ( fex_err_t err ) { return blargg_err_str( err ); }
diff --git a/desmume/src/windows/File_Extractor/fex/fex.h b/desmume/src/windows/File_Extractor/fex/fex.h
index 70c0d70a7..cb901a366 100644
--- a/desmume/src/windows/File_Extractor/fex/fex.h
+++ b/desmume/src/windows/File_Extractor/fex/fex.h
@@ -5,12 +5,18 @@
#define FEX_H
#include
+#include
+
+#ifdef _WIN32
+typedef wchar_t blargg_wchar_t;
+#else
+typedef uint16_t blargg_wchar_t;
+#endif
#ifdef __cplusplus
extern "C" {
#endif
-
/** First parameter of most functions is fex_t*, or const fex_t* if nothing is
changed. Once one of these functions returns an error, the archive should not
be used any further, other than to close it. One exception is
@@ -39,16 +45,11 @@ const char* fex_type_name( fex_type_t );
returns "", since it can open any file. */
const char* fex_type_extension( fex_type_t );
-/** List of possible start bytes combinations for the file, ending with a NULL.
-For binary file type, returns an empty list, since binary files have no applicable
-signature. */
-const char** fex_type_signatures( fex_type_t );
-
/**** Wide-character file paths ****/
/** Converts wide-character path to form suitable for use with fex functions. */
-char* fex_wide_to_path( const wchar_t* wide );
+char* fex_wide_to_path( const blargg_wchar_t* wide );
/** Frees converted path. OK to pass NULL. */
void fex_free_path( char* );
@@ -112,7 +113,7 @@ fex_open() */
fex_err_t fex_rewind( fex_t* );
/** Saved position in archive. Can also store zero. */
-typedef __int64 fex_pos_t;
+typedef uint64_t fex_pos_t;
/** Position of current file in archive. Never returns zero. */
fex_pos_t fex_tell_arc( const fex_t* );
@@ -127,13 +128,13 @@ fex_err_t fex_seek_arc( fex_t*, fex_pos_t );
const char* fex_name( const fex_t* );
/** Wide-character name of current file, or NULL if unavailable */
-const wchar_t* fex_wname( const fex_t* );
+const blargg_wchar_t* fex_wname( const fex_t* );
/** Makes further information available for file */
fex_err_t fex_stat( fex_t* );
/** Size of current file. fex_stat() or fex_data() must have been called. */
-__int64 fex_size( const fex_t* );
+uint64_t fex_size( const fex_t* );
/** Modification date of current file (MS-DOS format), or 0 if unavailable.
fex_stat() must have been called. */
@@ -149,10 +150,13 @@ unsigned int fex_crc32( const fex_t* );
/** Reads n bytes from current file. Reading past end of file results in
fex_err_file_eof. */
-fex_err_t fex_read( fex_t*, void* out, int n );
+fex_err_t fex_read( fex_t*, void* out, long n );
/** Number of bytes read from current file */
-__int64 fex_tell( const fex_t* );
+uint64_t fex_tell( const fex_t* );
+
+/** Skips the specified number of bytes in the current file */
+fex_err_t fex_skip( fex_t*, long n );
/** Points *out at current file's data in memory. Pointer is valid until
fex_next(), fex_rewind(), fex_seek_arc(), or fex_close() is called. Pointer
diff --git a/desmume/src/windows/File_Extractor/unrar/acknow.txt b/desmume/src/windows/File_Extractor/unrar/acknow.txt
new file mode 100644
index 000000000..a68b67277
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/acknow.txt
@@ -0,0 +1,92 @@
+ ACKNOWLEDGMENTS
+
+* We used "Screaming Fast Galois Field Arithmetic Using Intel
+ SIMD Instructions" paper by James S. Plank, Kevin M. Greenan
+ and Ethan L. Miller to improve Reed-Solomon coding performance.
+ Also we are grateful to Artem Drobanov and Bulat Ziganshin
+ for samples and ideas allowed to make Reed-Solomon coding
+ more efficient.
+
+* RAR text compression algorithm is based on Dmitry Shkarin PPMII
+ and Dmitry Subbotin carryless rangecoder public domain source code.
+ You may find it in ftp.elf.stuba.sk/pub/pc/pack.
+
+* RAR encryption includes parts of code from Szymon Stefanek
+ and Brian Gladman AES implementations also as Steve Reid SHA-1 source.
+
+ ---------------------------------------------------------------------------
+ Copyright (c) 2002, Dr Brian Gladman < >, Worcester, UK.
+ All rights reserved.
+
+ LICENSE TERMS
+
+ The free distribution and use of this software in both source and binary
+ form is allowed (with or without changes) provided that:
+
+ 1. distributions of this source code include the above copyright
+ notice, this list of conditions and the following disclaimer;
+
+ 2. distributions in binary form include the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other associated materials;
+
+ 3. the copyright holder's name is not used to endorse products
+ built using this software without specific written permission.
+
+ ALTERNATIVELY, provided that this notice is retained in full, this product
+ may be distributed under the terms of the GNU General Public License (GPL),
+ in which case the provisions of the GPL apply INSTEAD OF those given above.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+
+ Source code of this package also as other cryptographic technology
+ and computing project related links are available on Brian Gladman's
+ web site: http://www.gladman.me.uk
+
+* RAR uses CRC32 function based on Intel Slicing-by-8 algorithm.
+ Original Intel Slicing-by-8 code is available here:
+
+ http://sourceforge.net/projects/slicing-by-8/
+
+ Original Intel Slicing-by-8 code is licensed under BSD License
+ available at http://www.opensource.org/licenses/bsd-license.html
+
+ Copyright (c) 2004-2006 Intel Corporation.
+ All Rights Reserved
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer
+ in the documentation and/or other materials provided with
+ the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+* RAR archives may optionally include BLAKE2sp hash ( https://blake2.net ),
+ designed by Jean-Philippe Aumasson, Samuel Neves, Zooko Wilcox-O'Hearn
+ and Christian Winnerlein.
+
+* Useful hints provided by Alexander Khoroshev and Bulat Ziganshin allowed
+ to significantly improve RAR compression and speed.
diff --git a/desmume/src/windows/File_Extractor/unrar/archive.cpp b/desmume/src/windows/File_Extractor/unrar/archive.cpp
index 6cf05f5ce..528da7506 100644
--- a/desmume/src/windows/File_Extractor/unrar/archive.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/archive.cpp
@@ -5,90 +5,89 @@
Archive::Archive() : Raw( this )
{
- OldFormat=false;
+ Format=RARFMT15;
Solid=false;
CurBlockPos=0;
NextBlockPos=0;
- memset(&NewMhd,0,sizeof(NewMhd));
- NewMhd.HeadType=MAIN_HEAD;
- NewMhd.HeadSize=SIZEOF_NEWMHD;
- HeaderCRC=0;
+ memset(&MainHead,0,sizeof(MainHead));
+ memset(&EndArcHead,0,sizeof(EndArcHead));
+
+ HeaderCRC=0;
}
-bool Archive::IsSignature(byte *D)
+RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
{
- bool Valid=false;
- if (D[0]==0x52)
+ RARFORMAT Type=RARFMT_NONE;
+ if (Size>=1 && D[0]==0x52)
#ifndef SFX_MODULE
- if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
- {
- OldFormat=true;
- Valid=true;
- }
+ if (Size>=4 && D[1]==0x45 && D[2]==0x7e && D[3]==0x5e)
+ Type=RARFMT14;
else
#endif
- if (D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07 && D[6]==0x00)
+ if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
{
- OldFormat=false;
- Valid=true;
+ // We check for non-zero last signature byte, so we can return
+ // a sensible warning in case we'll want to change the archive
+ // format sometimes in the future.
+ if (D[6]==0)
+ Type=RARFMT15;
+ else if (D[6]==1)
+ Type=RARFMT50;
+ else if (D[6]==2)
+ Type=RARFMT_FUTURE;
}
- return(Valid);
+ return Type;
}
unrar_err_t Archive::IsArchive()
{
- if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD)
+ if (Read(MarkHead.Mark,SIZEOF_MARKHEAD3)!=SIZEOF_MARKHEAD3)
return unrar_err_not_arc;
- if (IsSignature(MarkHead.Mark))
+ RARFORMAT Type;
+ if ((Type=IsSignature(MarkHead.Mark,SIZEOF_MARKHEAD3))!=RARFMT_NONE)
{
- if (OldFormat)
- Seek(0,SEEK_SET);
+ Format=Type;
+ if (Format==RARFMT14)
+ Seek(Tell()-SIZEOF_MARKHEAD3,SEEK_SET);
}
else
{
if (SFXSize==0)
return unrar_err_not_arc;
}
+ if (Format==RARFMT_FUTURE)
+ return unrar_err_new_algo;
+ if (Format==RARFMT50) // RAR 5.0 signature is one byte longer.
+ {
+ Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1);
+ if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
+ return unrar_err_not_arc;
+ MarkHead.HeadSize=SIZEOF_MARKHEAD5;
+ }
+ else
+ MarkHead.HeadSize=SIZEOF_MARKHEAD3;
- unrar_err_t error =
- ReadHeader();
- // (no need to seek to next)
+ unrar_err_t error;
+ size_t HeaderSize;
+ while ((error=ReadHeader(&HeaderSize))==unrar_ok && HeaderSize!=0)
+ {
+ HEADER_TYPE Type=GetHeaderType();
+ // In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
+ // avoid the password prompt.
+ if (Type==HEAD_MAIN)
+ break;
+ SeekToNext();
+ }
if ( error != unrar_ok )
return error;
-#ifndef SFX_MODULE
- if (OldFormat)
- {
- NewMhd.Flags=OldMhd.Flags & 0x3f;
- NewMhd.HeadSize=OldMhd.HeadSize;
- }
- else
-#endif
- {
- if (HeaderCRC!=NewMhd.HeadCRC)
- {
- return unrar_err_corrupt;
- }
- }
- bool
- Volume=(NewMhd.Flags & MHD_VOLUME);
- Solid=(NewMhd.Flags & MHD_SOLID)!=0;
- bool
- Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0;
-
- // (removed decryption and volume handling)
-
- if ( Encrypted )
- return unrar_err_encrypted;
-
- if ( Volume )
- return unrar_err_segmented;
-
- return unrar_ok;
+ SeekToNext();
+
+ return unrar_ok;
}
void Archive::SeekToNext()
diff --git a/desmume/src/windows/File_Extractor/unrar/archive.hpp b/desmume/src/windows/File_Extractor/unrar/archive.hpp
index 4d117c839..dbd32a651 100644
--- a/desmume/src/windows/File_Extractor/unrar/archive.hpp
+++ b/desmume/src/windows/File_Extractor/unrar/archive.hpp
@@ -4,39 +4,49 @@
typedef ComprDataIO File;
#include "rawread.hpp"
+enum RARFORMAT {RARFMT_NONE,RARFMT14,RARFMT15,RARFMT50,RARFMT_FUTURE};
+
class Archive:public File
{
private:
- bool IsSignature(byte *D);
- void ConvertUnknownHeader();
- int ReadOldHeader();
+ void ConvertFileHeader(FileHeader *hd);
+ void WriteBlock50(HEADER_TYPE HeaderType,BaseBlock *wb,bool OnlySetSize,bool NonFinalWrite);
+ unrar_err_t ReadHeader14(size_t *ReadSize);
+ unrar_err_t ReadHeader15(size_t *ReadSize);
+ unrar_err_t ReadHeader50(size_t *ReadSize);
+ unrar_err_t ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb);
RawRead Raw;
- MarkHeader MarkHead;
- OldMainHeader OldMhd;
-
- int CurHeaderType;
-
+ HEADER_TYPE CurHeaderType;
+
public:
Archive();
+ RARFORMAT IsSignature(const byte *D,size_t Size);
unrar_err_t IsArchive();
- unrar_err_t ReadHeader();
+ size_t SearchBlock(HEADER_TYPE HeaderType);
+ size_t SearchSubBlock(const wchar *Type);
+ size_t SearchRR();
+ unrar_err_t ReadHeader(size_t *ReadSize);
void SeekToNext();
bool IsArcDir();
bool IsArcLabel();
- int GetHeaderType() {return(CurHeaderType);};
+ int64 GetStartPos();
+ HEADER_TYPE GetHeaderType() {return(CurHeaderType);};
BaseBlock ShortBlock;
- MainHeader NewMhd;
- FileHeader NewLhd;
+ MarkHeader MarkHead;
+ MainHeader MainHead;
+ FileHeader FileHead;
+ EndArcHeader EndArcHead;
SubBlockHeader SubBlockHead;
FileHeader SubHead;
ProtectHeader ProtectHead;
- Int64 CurBlockPos;
- Int64 NextBlockPos;
+ int64 CurBlockPos;
+ int64 NextBlockPos;
+ RARFORMAT Format;
bool Solid;
enum { SFXSize = 0 }; // self-extracting not supported
ushort HeaderCRC;
diff --git a/desmume/src/windows/File_Extractor/unrar/arcread.cpp b/desmume/src/windows/File_Extractor/unrar/arcread.cpp
index f10d31798..b29f38dad 100644
--- a/desmume/src/windows/File_Extractor/unrar/arcread.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/arcread.cpp
@@ -5,310 +5,731 @@
#include "encname.hpp"
// arcread.cpp
-unrar_err_t Archive::ReadHeader()
+unrar_err_t Archive::ReadHeader(size_t * ReadSize_)
{
CurBlockPos=Tell();
-
+
+ unrar_err_t Error;
+ size_t ReadSize;
+ switch(Format)
+ {
#ifndef SFX_MODULE
- if (OldFormat)
- {
- ReadOldHeader();
-
- if ( Raw.Size() == 0 )
- return unrar_err_arc_eof; // right at end of file
-
- if ( Raw.PaddedSize() > 0 ) // added check
- return unrar_err_corrupt; // missing data
-
- return unrar_ok;
- }
+ case RARFMT14:
+ Error=ReadHeader14(&ReadSize);
+ break;
#endif
+ case RARFMT15:
+ Error=ReadHeader15(&ReadSize);
+ break;
+ case RARFMT50:
+ Error=ReadHeader50(&ReadSize);
+ break;
+
+ default: // unreachable
+ Error=unrar_err_corrupt;
+ break;
+ }
+
+ if (Error!=unrar_ok)
+ return Error;
+
+ if (ReadSize>0 && NextBlockPos<=CurBlockPos)
+ return unrar_err_corrupt;
- Raw.Reset();
-
- // (removed decryption)
-
- Raw.Read(SIZEOF_SHORTBLOCKHEAD);
- if (Raw.Size()==0)
- {
- return unrar_err_arc_eof; // right at end of file
- }
-
- Raw.Get(ShortBlock.HeadCRC);
- byte HeadType;
- Raw.Get(HeadType);
- ShortBlock.HeadType=(HEADER_TYPE)HeadType;
- Raw.Get(ShortBlock.Flags);
- Raw.Get(ShortBlock.HeadSize);
- if (ShortBlock.HeadSize 0 ) // fewer than requested bytes read above?
- return unrar_err_corrupt; // missing data
-
- NextBlockPos=CurBlockPos+ShortBlock.HeadSize;
-
- switch(ShortBlock.HeadType)
- {
- case MAIN_HEAD:
- *(BaseBlock *)&NewMhd=ShortBlock;
- Raw.Get(NewMhd.HighPosAV);
- Raw.Get(NewMhd.PosAV);
- check( Raw.ReadPos == Raw.DataSize ); // we should have read all fields
- break;
- case FILE_HEAD:
- case NEWSUB_HEAD:
- {
- FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead;
- *(BaseBlock *)hd=ShortBlock;
- Raw.Get(hd->PackSize);
- Raw.Get(hd->UnpSize);
- Raw.Get(hd->HostOS);
- Raw.Get(hd->FileCRC);
- Raw.Get(hd->FileTime);
- Raw.Get(hd->UnpVer);
- Raw.Get(hd->Method);
- Raw.Get(hd->NameSize);
- Raw.Get(hd->FileAttr);
- if (hd->Flags & LHD_LARGE)
- {
- Raw.Get(hd->HighPackSize);
- Raw.Get(hd->HighUnpSize);
- }
- else
- {
- hd->HighPackSize=hd->HighUnpSize=0;
- if (hd->UnpSize==0xffffffff)
- {
- // TODO: what the heck is this for anyway?
- hd->UnpSize=0;
- hd->HighUnpSize=0x7fffffff;
- }
- }
- hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize);
- hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize);
-
- if ( int32to64( 1, 0 ) == 0 && (hd->HighPackSize || hd->HighUnpSize) )
- return unrar_err_huge;
-
- char (&FileName) [sizeof hd->FileName] = hd->FileName; // eliminated local buffer
- int NameSize=Min(hd->NameSize,sizeof(FileName)-1);
- Raw.Get((byte *)FileName,NameSize);
- FileName[NameSize]=0;
-
- if (hd->HeadType==NEWSUB_HEAD)
- {
- // have to adjust this, even through we're ignoring this block
- NextBlockPos+=hd->FullPackSize;
- break;
- }
- else
- if (hd->HeadType==FILE_HEAD)
- {
- if (hd->Flags & LHD_UNICODE)
- {
- EncodeFileName NameCoder;
- int Length=strlen(FileName);
- if (Length==hd->NameSize)
- {
- UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1);
- WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1);
- ExtToInt(hd->FileName,hd->FileName);
- }
- else
- {
- Length++;
- NameCoder.Decode(FileName,(byte *)FileName+Length,
- hd->NameSize-Length,hd->FileNameW,
- sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0]));
- }
- if (*hd->FileNameW==0)
- hd->Flags &= ~LHD_UNICODE;
- }
- else
- *hd->FileNameW=0;
-
- ConvertUnknownHeader();
- }
- if (hd->Flags & LHD_SALT)
- Raw.Get(hd->Salt,SALT_SIZE);
- hd->mtime.SetDos(hd->FileTime);
- if (hd->Flags & LHD_EXTTIME)
- {
- ushort Flags;
- Raw.Get(Flags);
- // Ignore additional time information
- for (int I=0;I<4;I++)
- {
- uint rmode=Flags>>(3-I)*4;
- if ((rmode & 8)==0)
- continue;
- if (I!=0)
- {
- uint DosTime;
- Raw.Get(DosTime);
- }
-
- // skip time info
- int count=rmode&3;
- for (int J=0;JFullPackSize;
- bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0;
- HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff;
- if (hd->HeadCRC!=HeaderCRC)
- return unrar_err_corrupt;
- check( CRCProcessedOnly == false ); // I need to test on archives where this doesn't hold
- check( Raw.ReadPos == Raw.DataSize ); // we should have read all fields
- }
- break;
-#ifndef SFX_MODULE
- // Handle these block types just so we can adjust NextBlockPos properly
- case PROTECT_HEAD:
- Raw.Get(ProtectHead.DataSize);
- NextBlockPos+=ProtectHead.DataSize;
- break;
- case SUB_HEAD:
- Raw.Get(SubBlockHead.DataSize);
- NextBlockPos+=SubBlockHead.DataSize;
- break;
-#endif
- default:
- if (ShortBlock.Flags & LONG_BLOCK)
- {
- uint DataSize;
- Raw.Get(DataSize);
- NextBlockPos+=DataSize;
- }
- break;
- }
- HeaderCRC=~Raw.GetCRC(false)&0xffff;
- CurHeaderType=ShortBlock.HeadType;
- // (removed decryption)
-
- if (NextBlockPosReset();
+
+ *(BaseBlock *)hd=ShortBlock;
+
+ hd->SplitBefore=(hd->Flags & LHD_SPLIT_BEFORE)!=0;
+ hd->SplitAfter=(hd->Flags & LHD_SPLIT_AFTER)!=0;
+ hd->Encrypted=(hd->Flags & LHD_PASSWORD)!=0;
+ hd->Solid=FileBlock && (hd->Flags & LHD_SOLID)!=0;
+ hd->SubBlock=!FileBlock && (hd->Flags & LHD_SOLID)!=0;
+ hd->Dir=(hd->Flags & LHD_WINDOWMASK)==LHD_DIRECTORY;
+ hd->WinSize=hd->Dir ? 0:0x10000<<((hd->Flags & LHD_WINDOWMASK)>>5);
+ hd->CommentInHeader=(hd->Flags & LHD_COMMENT)!=0;
+ hd->Version=(hd->Flags & LHD_VERSION)!=0;
+
+ hd->DataSize=Raw.Get4();
+ uint LowUnpSize=Raw.Get4();
+ hd->HostOS=Raw.Get1();
+
+ hd->FileHash.Type=HASH_CRC32;
+ hd->FileHash.CRC32=Raw.Get4();
+
+ uint FileTime=Raw.Get4();
+ hd->UnpVer=Raw.Get1();
+ hd->Method=Raw.Get1()-0x30;
+ size_t NameSize=Raw.Get2();
+ hd->FileAttr=Raw.Get4();
+
+ if (hd->Encrypted)
+ return unrar_err_encrypted;
+
+ hd->HSType=HSYS_UNKNOWN;
+ if (hd->HostOS==HOST_UNIX || hd->HostOS==HOST_BEOS)
+ hd->HSType=HSYS_UNIX;
+ else
+ if (hd->HostOSHSType=HSYS_WINDOWS;
+
+ hd->RedirType=FSREDIR_NONE;
+
+ // RAR 4.x Unix symlink.
+ if (hd->HostOS==HOST_UNIX && (hd->FileAttr & 0xF000)==0xA000)
+ {
+ hd->RedirType=FSREDIR_UNIXSYMLINK;
+ *hd->RedirName=0;
+ }
+
+ hd->Inherited=!FileBlock && (hd->SubFlags & SUBHEAD_FLAGS_INHERITED)!=0;
+
+ hd->LargeFile=(hd->Flags & LHD_LARGE)!=0;
+
+ uint HighPackSize,HighUnpSize;
+ if (hd->LargeFile)
+ {
+ HighPackSize=Raw.Get4();
+ HighUnpSize=Raw.Get4();
+ hd->UnknownUnpSize=(LowUnpSize==0xffffffff && HighUnpSize==0xffffffff);
+ }
+ else
+ {
+ HighPackSize=HighUnpSize=0;
+ // UnpSize equal to 0xffffffff without LHD_LARGE flag indicates
+ // that we do not know the unpacked file size and must unpack it
+ // until we find the end of file marker in compressed data.
+ hd->UnknownUnpSize=(LowUnpSize==0xffffffff);
+ }
+ hd->PackSize=int32to64(HighPackSize,hd->DataSize);
+ hd->UnpSize=int32to64(HighUnpSize,LowUnpSize);
+ if (hd->UnknownUnpSize)
+ hd->UnpSize=INT64NDF;
+
+ char FileName[NM*4];
+ size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
+ Raw.GetB((byte *)FileName,ReadNameSize);
+ FileName[ReadNameSize]=0;
+
+ if (FileBlock)
+ {
+ if ((hd->Flags & LHD_UNICODE)!=0)
+ {
+ EncodeFileName NameCoder;
+ size_t Length=strlen(FileName);
+ Length++;
+ NameCoder.Decode(FileName,(byte *)FileName+Length,
+ NameSize-Length,hd->FileName,
+ ASIZE(hd->FileName));
+ }
+ else
+ *hd->FileName=0;
+
+ char AnsiName[NM];
+ IntToExt(FileName,AnsiName,ASIZE(AnsiName));
+ GetWideName(AnsiName,hd->FileName,hd->FileName,ASIZE(hd->FileName));
+
+ ConvertFileHeader(hd);
+ }
+ else
+ {
+ CharToWide(FileName,hd->FileName,ASIZE(hd->FileName));
+
+ // Calculate the size of optional data.
+ int DataSize=int(hd->HeadSize-NameSize-SIZEOF_FILEHEAD3);
+ if ((hd->Flags & LHD_SALT)!=0)
+ return unrar_err_encrypted;
+
+ if (DataSize>0)
+ {
+ // Here we read optional additional fields for subheaders.
+ // They are stored after the file name and before salt.
+ hd->SubData.Alloc(DataSize);
+ Raw.GetB(&hd->SubData[0],DataSize);
+ }
+ }
+ if ((hd->Flags & LHD_SALT)!=0)
+ return unrar_err_encrypted;
+ hd->mtime.SetDos(FileTime);
+ if ((hd->Flags & LHD_EXTTIME)!=0)
+ {
+ ushort Flags=Raw.Get2();
+ RarTime *tbl[4];
+ tbl[0]=&FileHead.mtime;
+ tbl[1]=&FileHead.ctime;
+ tbl[2]=&FileHead.atime;
+ tbl[3]=NULL; // Archive time is not used now.
+ for (int I=0;I<4;I++)
+ {
+ RarTime *CurTime=tbl[I];
+ uint rmode=Flags>>(3-I)*4;
+ if ((rmode & 8)==0 || CurTime==NULL)
+ continue;
+ if (I!=0)
+ {
+ uint DosTime=Raw.Get4();
+ CurTime->SetDos(DosTime);
+ }
+ RarLocalTime rlt;
+ CurTime->GetLocal(&rlt);
+ if (rmode & 4)
+ rlt.Second++;
+ rlt.Reminder=0;
+ int count=rmode&3;
+ for (int J=0;JSetLocal(&rlt);
+ }
+ }
+ NextBlockPos+=hd->PackSize;
+ bool CRCProcessedOnly=hd->CommentInHeader;
+ ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly);
+ if (hd->HeadCRC!=HeaderCRC)
+ return unrar_err_corrupt;
+ }
+ break;
+ case HEAD_ENDARC:
+ *(BaseBlock *)&EndArcHead=ShortBlock;
+ EndArcHead.NextVolume=(EndArcHead.Flags & EARC_NEXT_VOLUME)!=0;
+ EndArcHead.DataCRC=(EndArcHead.Flags & EARC_DATACRC)!=0;
+ EndArcHead.RevSpace=(EndArcHead.Flags & EARC_REVSPACE)!=0;
+ EndArcHead.StoreVolNumber=(EndArcHead.Flags & EARC_VOLNUMBER)!=0;
+ if (EndArcHead.DataCRC)
+ EndArcHead.ArcDataCRC=Raw.Get4();
+ if (EndArcHead.StoreVolNumber)
+ return unrar_err_segmented;
+ break;
+ default:
+ if (ShortBlock.Flags & LONG_BLOCK)
+ NextBlockPos+=Raw.Get4();
+ break;
+ }
+
+ ushort HeaderCRC=Raw.GetCRC15(false);
+
+ // Old AV header does not have header CRC properly set.
+ if (ShortBlock.HeadCRC!=HeaderCRC && ShortBlock.HeaderType!=HEAD3_SIGN &&
+ ShortBlock.HeaderType!=HEAD3_AV)
+ return unrar_err_corrupt;
+
+ if (NextBlockPos<=CurBlockPos)
+ return unrar_err_corrupt;
+
+ *ReadSize=Raw.Size();
+ return unrar_ok;
+}
- NewLhd.Flags=OldLhd.Flags|LONG_BLOCK;
- NewLhd.UnpVer=(OldLhd.UnpVer==2) ? 13 : 10;
- NewLhd.Method=OldLhd.Method+0x30;
- NewLhd.NameSize=OldLhd.NameSize;
- NewLhd.FileAttr=OldLhd.FileAttr;
- NewLhd.FileCRC=OldLhd.FileCRC;
- NewLhd.FullPackSize=NewLhd.PackSize;
- NewLhd.FullUnpSize=NewLhd.UnpSize;
- NewLhd.mtime.SetDos(NewLhd.FileTime);
- // (removed other times)
+unrar_err_t Archive::ReadHeader50(size_t *ReadSize)
+{
+ Raw.Reset();
+
+ // Header size must not occupy more than 3 variable length integer bytes
+ // resulting in 2 MB maximum header size, so here we read 4 byte CRC32
+ // followed by 3 bytes or less of header size.
+ const size_t FirstReadSize=7; // Smallest possible block size.
+ if (Raw.Read(FirstReadSize)=ShortBlock.HeadSize)
+ return unrar_err_corrupt;
+ }
+
+ uint64 DataSize=0;
+ if ((ShortBlock.Flags & HFL_DATA)!=0)
+ DataSize=Raw.GetV();
+
+ NextBlockPos=CurBlockPos+ShortBlock.HeadSize+DataSize;
+
+ switch(ShortBlock.HeaderType)
+ {
+ case HEAD_CRYPT:
+ return unrar_err_encrypted;
+ case HEAD_MAIN:
+ {
+ MainHead.Reset();
+ *(BaseBlock *)&MainHead=ShortBlock;
+ uint ArcFlags=(uint)Raw.GetV();
+
+ Solid=(ArcFlags & MHFL_SOLID)!=0;
+
+ if (ExtraSize!=0)
+ {
+ unrar_err_t Error;
+ if ((Error=ProcessExtra50(&Raw,(size_t)ExtraSize,&MainHead))!=unrar_ok)
+ return Error;
+ }
+ }
+ break;
+ case HEAD_FILE:
+ case HEAD_SERVICE:
+ {
+ FileHeader *hd=ShortBlock.HeaderType==HEAD_FILE ? &FileHead:&SubHead;
+ hd->Reset();
+ *(BaseBlock *)hd=ShortBlock;
+
+ bool FileBlock=ShortBlock.HeaderType==HEAD_FILE;
+
+ hd->LargeFile=true;
+
+ hd->PackSize=DataSize;
+ hd->FileFlags=(uint)Raw.GetV();
+ hd->UnpSize=Raw.GetV();
+
+ hd->UnknownUnpSize=(hd->FileFlags & FHFL_UNPUNKNOWN)!=0;
+ if (hd->UnknownUnpSize)
+ hd->UnpSize=INT64NDF;
+
+ hd->MaxSize=Max(hd->PackSize,hd->UnpSize);
+ hd->FileAttr=(uint)Raw.GetV();
+ if ((hd->FileFlags & FHFL_UTIME)!=0)
+ hd->mtime=(time_t)Raw.Get4();
+
+ hd->FileHash.Type=HASH_NONE;
+ if ((hd->FileFlags & FHFL_CRC32)!=0)
+ {
+ hd->FileHash.Type=HASH_CRC32;
+ hd->FileHash.CRC32=Raw.Get4();
+ }
+
+ hd->RedirType=FSREDIR_NONE;
+
+ uint CompInfo=(uint)Raw.GetV();
+ hd->Method=(CompInfo>>7) & 7;
+ hd->UnpVer=CompInfo & 0x3f;
+
+ hd->HostOS=(byte)Raw.GetV();
+ size_t NameSize=(size_t)Raw.GetV();
+ hd->Inherited=(ShortBlock.Flags & HFL_INHERITED)!=0;
+
+ hd->HSType=HSYS_UNKNOWN;
+ if (hd->HostOS==HOST5_UNIX)
+ hd->HSType=HSYS_UNIX;
+ else
+ if (hd->HostOS==HOST5_WINDOWS)
+ hd->HSType=HSYS_WINDOWS;
+
+ hd->SplitBefore=(hd->Flags & HFL_SPLITBEFORE)!=0;
+ hd->SplitAfter=(hd->Flags & HFL_SPLITAFTER)!=0;
+ hd->SubBlock=(hd->Flags & HFL_CHILD)!=0;
+ hd->Solid=FileBlock && (CompInfo & FCI_SOLID)!=0;
+ hd->Dir=(hd->FileFlags & FHFL_DIRECTORY)!=0;
+ hd->WinSize=hd->Dir ? 0:size_t(0x20000)<<((CompInfo>>10)&0xf);
+
+ if (hd->Encrypted)
+ return unrar_err_encrypted;
+
+ char FileName[NM*4];
+ size_t ReadNameSize=Min(NameSize,ASIZE(FileName)-1);
+ Raw.GetB((byte *)FileName,ReadNameSize);
+ FileName[ReadNameSize]=0;
+
+ UtfToWide(FileName,hd->FileName,ASIZE(hd->FileName)-1);
+
+ // Should do it before converting names, because extra fields can
+ // affect name processing, like in case of NTFS streams.
+ if (ExtraSize!=0)
+ ProcessExtra50(&Raw,(size_t)ExtraSize,hd);
+
+ if (FileBlock)
+ ConvertFileHeader(hd);
+
+ if (BadCRC) // Add the file name to broken header message displayed above.
+ return unrar_err_corrupt;
+ }
+ break;
+ case HEAD_ENDARC:
+ {
+ *(BaseBlock *)&EndArcHead=ShortBlock;
+ uint ArcFlags=(uint)Raw.GetV();
+ EndArcHead.NextVolume=(ArcFlags & EHFL_NEXTVOLUME)!=0;
+ EndArcHead.StoreVolNumber=false;
+ EndArcHead.DataCRC=false;
+ EndArcHead.RevSpace=false;
+ }
+ break;
+ }
+
+ if (NextBlockPos<=CurBlockPos)
+ return unrar_err_corrupt;
+
+ *ReadSize=Raw.Size();
+
+ return unrar_ok;
+}
- Raw.Read(OldLhd.NameSize);
- Raw.Get((byte *)NewLhd.FileName,OldLhd.NameSize);
- NewLhd.FileName[OldLhd.NameSize]=0;
- // (removed name case conversion)
- *NewLhd.FileNameW=0;
- if (Raw.Size()!=0)
- NextBlockPos=CurBlockPos+NewLhd.HeadSize+NewLhd.PackSize;
- CurHeaderType=FILE_HEAD;
- }
- return(NextBlockPos>CurBlockPos ? Raw.Size():0);
+unrar_err_t Archive::ProcessExtra50(RawRead *Raw,size_t ExtraSize,BaseBlock *bb)
+{
+ // Read extra data from the end of block skipping any fields before it.
+ size_t ExtraStart=Raw->Size()-ExtraSize;
+ if (ExtraStartGetPos())
+ return unrar_err_corrupt;
+ Raw->SetPos(ExtraStart);
+ while (Raw->DataLeft()>=2)
+ {
+ int64 FieldSize=Raw->GetV();
+ if (FieldSize==0 || Raw->DataLeft()==0 || FieldSize>(int64)Raw->DataLeft())
+ break;
+ size_t NextPos=size_t(Raw->GetPos()+FieldSize);
+ uint64 FieldType=Raw->GetV();
+
+ FieldSize=Raw->DataLeft(); // Field size without size and type fields.
+
+ if (bb->HeaderType==HEAD_MAIN)
+ {
+ MainHeader *hd=(MainHeader *)bb;
+ if (FieldType==MHEXTRA_LOCATOR)
+ {
+ hd->Locator=true;
+ uint Flags=(uint)Raw->GetV();
+ if ((Flags & MHEXTRA_LOCATOR_QLIST)!=0)
+ {
+ uint64 Offset=Raw->GetV();
+ if (Offset!=0) // 0 means that reserved space was not enough to write the offset.
+ hd->QOpenOffset=Offset+CurBlockPos;
+ }
+ if ((Flags & MHEXTRA_LOCATOR_RR)!=0)
+ {
+ uint64 Offset=Raw->GetV();
+ if (Offset!=0) // 0 means that reserved space was not enough to write the offset.
+ hd->RROffset=Offset+CurBlockPos;
+ }
+ }
+ }
+
+ if (bb->HeaderType==HEAD_FILE || bb->HeaderType==HEAD_SERVICE)
+ {
+ FileHeader *hd=(FileHeader *)bb;
+ switch(FieldType)
+ {
+ case FHEXTRA_CRYPT:
+ return unrar_err_encrypted;
+ case FHEXTRA_HASH:
+ {
+ FileHeader *hd=(FileHeader *)bb;
+ uint Type=(uint)Raw->GetV();
+ if (Type==FHEXTRA_HASH_BLAKE2)
+ {
+ hd->FileHash.Type=HASH_BLAKE2;
+ Raw->GetB(hd->FileHash.Digest,BLAKE2_DIGEST_SIZE);
+ }
+ }
+ break;
+ case FHEXTRA_HTIME:
+ if (FieldSize>=9)
+ {
+ byte Flags=(byte)Raw->GetV();
+ bool UnixTime=(Flags & FHEXTRA_HTIME_UNIXTIME)!=0;
+ if ((Flags & FHEXTRA_HTIME_MTIME)!=0)
+ {
+ if (UnixTime)
+ hd->mtime=(time_t)Raw->Get4();
+ else
+ hd->mtime.SetRaw(Raw->Get8());
+ }
+ if ((Flags & FHEXTRA_HTIME_CTIME)!=0)
+ {
+ if (UnixTime)
+ hd->ctime=(time_t)Raw->Get4();
+ else
+ hd->ctime.SetRaw(Raw->Get8());
+ }
+ if ((Flags & FHEXTRA_HTIME_ATIME)!=0)
+ {
+ if (UnixTime)
+ hd->atime=(time_t)Raw->Get4();
+ else
+ hd->atime.SetRaw(Raw->Get8());
+ }
+ }
+ break;
+ case FHEXTRA_REDIR:
+ {
+ hd->RedirType=(FILE_SYSTEM_REDIRECT)Raw->GetV();
+ uint Flags=(uint)Raw->GetV();
+ hd->DirTarget=(Flags & FHEXTRA_REDIR_DIR)!=0;
+ size_t NameSize=(size_t)Raw->GetV();
+
+ char UtfName[NM*4];
+ *UtfName=0;
+ if (NameSizeGetB(UtfName,NameSize);
+ UtfName[NameSize]=0;
+ }
+#ifdef _WIN_ALL
+ UnixSlashToDos(UtfName,UtfName,ASIZE(UtfName));
+#endif
+ UtfToWide(UtfName,hd->RedirName,ASIZE(hd->RedirName));
+ }
+ break;
+ case FHEXTRA_UOWNER:
+ {
+ uint Flags=(uint)Raw->GetV();
+ hd->UnixOwnerNumeric=(Flags & FHEXTRA_UOWNER_NUMUID)!=0;
+ hd->UnixGroupNumeric=(Flags & FHEXTRA_UOWNER_NUMGID)!=0;
+ *hd->UnixOwnerName=*hd->UnixGroupName=0;
+ if ((Flags & FHEXTRA_UOWNER_UNAME)!=0)
+ {
+ size_t Length=(size_t)Raw->GetV();
+ Length=Min(Length,ASIZE(hd->UnixOwnerName)-1);
+ Raw->GetB(hd->UnixOwnerName,Length);
+ hd->UnixOwnerName[Length]=0;
+ }
+ if ((Flags & FHEXTRA_UOWNER_GNAME)!=0)
+ {
+ size_t Length=(size_t)Raw->GetV();
+ Length=Min(Length,ASIZE(hd->UnixGroupName)-1);
+ Raw->GetB(hd->UnixGroupName,Length);
+ hd->UnixGroupName[Length]=0;
+ }
+#ifdef _UNIX
+ if (hd->UnixOwnerNumeric)
+ hd->UnixOwnerID=(uid_t)Raw->GetV();
+ if (hd->UnixGroupNumeric)
+ hd->UnixGroupID=(uid_t)Raw->GetV();
+#else
+ // Need these fields in Windows too for 'list' command,
+ // but uid_t and gid_t are not defined.
+ if (hd->UnixOwnerNumeric)
+ hd->UnixOwnerID=(uint)Raw->GetV();
+ if (hd->UnixGroupNumeric)
+ hd->UnixGroupID=(uint)Raw->GetV();
+#endif
+ hd->UnixOwnerSet=true;
+ }
+ break;
+ case FHEXTRA_SUBDATA:
+ {
+ hd->SubData.Alloc((size_t)FieldSize);
+ Raw->GetB(hd->SubData.Addr(0),(size_t)FieldSize);
+ }
+ break;
+ }
+ }
+
+ Raw->SetPos(NextPos);
+ }
+
+ return unrar_ok;
+}
+
+
+#ifndef SFX_MODULE
+unrar_err_t Archive::ReadHeader14(size_t *ReadSize)
+{
+ Raw.Reset();
+
+ if (CurBlockPos<=(int64)SFXSize)
+ {
+ Raw.Read(SIZEOF_MAINHEAD14);
+ MainHead.Reset();
+ byte Mark[4];
+ Raw.GetB(Mark,4);
+ uint HeadSize=Raw.Get2();
+ byte Flags=Raw.Get1();
+ NextBlockPos=CurBlockPos+HeadSize;
+ CurHeaderType=HEAD_MAIN;
+
+ Solid=(Flags & MHD_SOLID)!=0;
+ MainHead.CommentInHeader=(Flags & MHD_COMMENT)!=0;
+ MainHead.PackComment=(Flags & MHD_PACK_COMMENT)!=0;
+ }
+ else
+ {
+ Raw.Read(SIZEOF_FILEHEAD14);
+ FileHead.Reset();
+
+ FileHead.HeaderType=HEAD_FILE;
+ FileHead.DataSize=Raw.Get4();
+ FileHead.UnpSize=Raw.Get4();
+ FileHead.FileHash.Type=HASH_RAR14;
+ FileHead.FileHash.CRC32=Raw.Get2();
+ FileHead.HeadSize=Raw.Get2();
+ uint FileTime=Raw.Get4();
+ FileHead.FileAttr=Raw.Get1();
+ FileHead.Flags=Raw.Get1()|LONG_BLOCK;
+ FileHead.UnpVer=(Raw.Get1()==2) ? 13 : 10;
+ size_t NameSize=Raw.Get1();
+ FileHead.Method=Raw.Get1();
+
+ FileHead.SplitBefore=(FileHead.Flags & LHD_SPLIT_BEFORE)!=0;
+ FileHead.SplitAfter=(FileHead.Flags & LHD_SPLIT_AFTER)!=0;
+ FileHead.Encrypted=(FileHead.Flags & LHD_PASSWORD)!=0;
+ if (FileHead.Encrypted)
+ return unrar_err_encrypted;
+
+ FileHead.PackSize=FileHead.DataSize;
+ FileHead.WinSize=0x10000;
+
+ FileHead.mtime.SetDos(FileTime);
+
+ Raw.Read(NameSize);
+
+ char FileName[NM];
+ Raw.GetB((byte *)FileName,Min(NameSize,ASIZE(FileName)));
+ FileName[NameSize]=0;
+ IntToExt(FileName,FileName,ASIZE(FileName));
+ CharToWide(FileName,FileHead.FileName,ASIZE(FileHead.FileName));
+
+ if (Raw.Size()!=0)
+ NextBlockPos=CurBlockPos+FileHead.HeadSize+FileHead.PackSize;
+ CurHeaderType=HEAD_FILE;
+ }
+ *ReadSize=(NextBlockPos>CurBlockPos ? Raw.Size():0);
+ return unrar_ok;
}
#endif
+
// (removed name case and attribute conversion)
bool Archive::IsArcDir()
{
- return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY);
+ return FileHead.Dir;
}
bool Archive::IsArcLabel()
{
- return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8));
+ return(FileHead.HostOS<=HOST_WIN32 && (FileHead.FileAttr & 8));
}
-// TODO: use '\\' on Windows?
-char const CPATHDIVIDER = '/';
-#define charnext(s) ((s)+1)
-void Archive::ConvertUnknownHeader()
+void Archive::ConvertFileHeader(FileHeader *hd)
{
- if (NewLhd.UnpVer<20 && (NewLhd.FileAttr & 0x10))
- NewLhd.Flags|=LHD_DIRECTORY;
- if (NewLhd.HostOS>=HOST_MAX)
- {
- if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY)
- NewLhd.FileAttr=0x10;
- else
- NewLhd.FileAttr=0x20;
- }
- {
- for (char *s=NewLhd.FileName;*s!=0;s=charnext(s))
- {
- if (*s=='/' || *s=='\\')
- *s=CPATHDIVIDER;
- }
- }
- // (removed Apple Unicode handling)
- for (wchar *s=NewLhd.FileNameW;*s!=0;s++)
- {
- if (*s=='/' || *s=='\\')
- *s=CPATHDIVIDER;
- }
+ if (Format==RARFMT15 && hd->UnpVer<20 && (hd->FileAttr & 0x10))
+ hd->Dir=true;
+ if (hd->HSType==HSYS_UNKNOWN)
+ if (hd->Dir)
+ hd->FileAttr=0x10;
+ else
+ hd->FileAttr=0x20;
+}
+
+
+int64 Archive::GetStartPos()
+{
+ int64 StartPos=SFXSize+MarkHead.HeadSize;
+ StartPos+=MainHead.HeadSize;
+ return StartPos;
}
diff --git a/desmume/src/windows/File_Extractor/unrar/array.hpp b/desmume/src/windows/File_Extractor/unrar/array.hpp
index 6b6ae98c6..46bf4126c 100644
--- a/desmume/src/windows/File_Extractor/unrar/array.hpp
+++ b/desmume/src/windows/File_Extractor/unrar/array.hpp
@@ -1,26 +1,33 @@
#ifndef _RAR_ARRAY_
#define _RAR_ARRAY_
+#include
+
template class Array
{
private:
T *Buffer;
- int BufSize;
- int AllocSize;
+ size_t BufSize;
+ size_t AllocSize;
+ size_t MaxSize;
public:
- Rar_Error_Handler& ErrHandler;
- Array(Rar_Error_Handler*);
- Array(int Size,Rar_Error_Handler*);
+ Array();
+ Array(size_t Size);
+ Array(const Array &Src); // Copy constructor.
~Array();
inline void CleanData();
- inline T& operator [](int Item);
- inline int Size();
- void Add(int Items);
- void Alloc(int Items);
+ inline T& operator [](size_t Item) const;
+ inline T* operator + (size_t Pos);
+ inline size_t Size();
+ void Add(size_t Items);
+ void Alloc(size_t Items);
void Reset();
+ void SoftReset();
void operator = (Array &Src);
void Push(T Item);
- T* Addr() {return(Buffer);}
+ void Append(T *Item,size_t Count);
+ T* Addr(size_t Item) {return Buffer+Item;}
+ void SetMaxSize(size_t Size) {MaxSize=Size;}
};
template void Array::CleanData()
@@ -28,67 +35,80 @@ template void Array::CleanData()
Buffer=NULL;
BufSize=0;
AllocSize=0;
+ MaxSize=0;
}
-template Array::Array(Rar_Error_Handler* eh) : ErrHandler( *eh )
+template Array::Array()
{
CleanData();
}
-template Array::Array(int Size, Rar_Error_Handler* eh) : ErrHandler( *eh )
+template Array::Array(size_t Size)
{
- Buffer=(T *)rarmalloc(sizeof(T)*Size);
- if (Buffer==NULL && Size!=0)
- ErrHandler.MemoryError();
+ CleanData();
+ Add(Size);
+}
- AllocSize=BufSize=Size;
+
+// Copy constructor in case we need to pass an object as value.
+template Array::Array(const Array &Src)
+{
+ CleanData();
+ Alloc(Src.BufSize);
+ if (Src.BufSize!=0)
+ memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T));
}
template Array::~Array()
{
- if (Buffer!=NULL)
- rarfree(Buffer);
+ if (Buffer!=NULL)
+ rarfree(Buffer);
}
-template inline T& Array::operator [](int Item)
+template inline T& Array::operator [](size_t Item) const
{
- return(Buffer[Item]);
+ return Buffer[Item];
}
-template inline int Array::Size()
+template inline T* Array::operator +(size_t Pos)
{
- return(BufSize);
+ return Buffer+Pos;
}
-template void Array::Add(int Items)
+template inline size_t Array::Size()
{
- int BufSize = this->BufSize; // don't change actual vars until alloc succeeds
- T* Buffer = this->Buffer;
-
- BufSize+=Items;
- if (BufSize>AllocSize)
+ return BufSize;
+}
+
+
+template void Array::Add(size_t Items)
+{
+ size_t NewBufSize=BufSize+Items;
+ if (NewBufSize>AllocSize)
{
- int Suggested=AllocSize+AllocSize/4+32;
- int NewSize=Max(BufSize,Suggested);
+ if (MaxSize!=0 && NewBufSize>MaxSize)
+ throw std::bad_alloc();
- Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T));
- if (Buffer==NULL)
- ErrHandler.MemoryError();
+ size_t Suggested=AllocSize+AllocSize/4+32;
+ size_t NewSize=Max(NewBufSize,Suggested);
+
+ T *NewBuffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T));
+ if (NewBuffer==NULL)
+ throw std::bad_alloc();
+ Buffer=NewBuffer;
AllocSize=NewSize;
}
-
- this->Buffer = Buffer;
- this->BufSize = BufSize;
+ BufSize=NewBufSize;
}
-template void Array::Alloc(int Items)
+template void Array::Alloc(size_t Items)
{
if (Items>AllocSize)
Add(Items-BufSize);
@@ -117,6 +137,14 @@ template void Array::Reset()
}
+// Reset buffer size, but preserve already allocated memory if any,
+// so we can reuse it without wasting time to allocation.
+template void Array::SoftReset()
+{
+ BufSize=0;
+}
+
+
template void Array::operator =(Array &Src)
{
Reset();
@@ -132,4 +160,12 @@ template void Array::Push(T Item)
(*this)[Size()-1]=Item;
}
+
+template void Array::Append(T *Items,size_t Count)
+{
+ size_t CurSize=Size();
+ Add(Count);
+ memcpy(Buffer+CurSize,Items,Count*sizeof(T));
+}
+
#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/blake2s.cpp b/desmume/src/windows/File_Extractor/unrar/blake2s.cpp
new file mode 100644
index 000000000..e51748907
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/blake2s.cpp
@@ -0,0 +1,189 @@
+// Based on public domain code written in 2012 by Samuel Neves
+
+#include "rar.hpp"
+
+#ifdef USE_SSE
+#include "blake2s_sse.cpp"
+#endif
+
+static void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth);
+static void blake2s_update( blake2s_state *S, const byte *in, size_t inlen );
+static void blake2s_final( blake2s_state *S, byte *digest );
+
+#include "blake2sp.cpp"
+
+static const uint32 blake2s_IV[8] =
+{
+ 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
+ 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
+};
+
+static const byte blake2s_sigma[10][16] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
+};
+
+static inline void blake2s_set_lastnode( blake2s_state *S )
+{
+ S->f[1] = ~0U;
+}
+
+
+/* Some helper functions, not necessarily useful */
+static inline void blake2s_set_lastblock( blake2s_state *S )
+{
+ if( S->last_node ) blake2s_set_lastnode( S );
+
+ S->f[0] = ~0U;
+}
+
+
+static inline void blake2s_increment_counter( blake2s_state *S, const uint32 inc )
+{
+ S->t[0] += inc;
+ S->t[1] += ( S->t[0] < inc );
+}
+
+
+/* init2 xors IV with input parameter block */
+void blake2s_init_param( blake2s_state *S, uint32 node_offset, uint32 node_depth)
+{
+#ifdef USE_SSE
+ if (_SSE_Version>=SSE_SSE2)
+ blake2s_init_sse();
+#endif
+
+ S->init(); // Clean data.
+ for( int i = 0; i < 8; ++i )
+ S->h[i] = blake2s_IV[i];
+
+ S->h[0] ^= 0x02080020; // We use BLAKE2sp parameters block.
+ S->h[2] ^= node_offset;
+ S->h[3] ^= (node_depth<<16)|0x20000000;
+}
+
+
+static inline uint32 rotr32( const uint32 w, const unsigned c )
+{
+ return ( w >> c ) | ( w << ( 32 - c ) );
+}
+
+
+#define G(r,i,m,a,b,c,d) \
+ a = a + b + m[blake2s_sigma[r][2*i+0]]; \
+ d = rotr32(d ^ a, 16); \
+ c = c + d; \
+ b = rotr32(b ^ c, 12); \
+ a = a + b + m[blake2s_sigma[r][2*i+1]]; \
+ d = rotr32(d ^ a, 8); \
+ c = c + d; \
+ b = rotr32(b ^ c, 7);
+
+
+static void blake2s_compress( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
+{
+ uint32 m[16];
+ uint32 v[16];
+
+ for( size_t i = 0; i < 16; ++i )
+ m[i] = RawGet4( block + i * 4 );
+
+ for( size_t i = 0; i < 8; ++i )
+ v[i] = S->h[i];
+
+ v[ 8] = blake2s_IV[0];
+ v[ 9] = blake2s_IV[1];
+ v[10] = blake2s_IV[2];
+ v[11] = blake2s_IV[3];
+ v[12] = S->t[0] ^ blake2s_IV[4];
+ v[13] = S->t[1] ^ blake2s_IV[5];
+ v[14] = S->f[0] ^ blake2s_IV[6];
+ v[15] = S->f[1] ^ blake2s_IV[7];
+
+ for ( uint r = 0; r <= 9; ++r ) // No gain on i7 if unrolled, but exe size grows.
+ {
+ G(r,0,m,v[ 0],v[ 4],v[ 8],v[12]);
+ G(r,1,m,v[ 1],v[ 5],v[ 9],v[13]);
+ G(r,2,m,v[ 2],v[ 6],v[10],v[14]);
+ G(r,3,m,v[ 3],v[ 7],v[11],v[15]);
+ G(r,4,m,v[ 0],v[ 5],v[10],v[15]);
+ G(r,5,m,v[ 1],v[ 6],v[11],v[12]);
+ G(r,6,m,v[ 2],v[ 7],v[ 8],v[13]);
+ G(r,7,m,v[ 3],v[ 4],v[ 9],v[14]);
+ }
+
+ for( size_t i = 0; i < 8; ++i )
+ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+}
+
+
+void blake2s_update( blake2s_state *S, const byte *in, size_t inlen )
+{
+ while( inlen > 0 )
+ {
+ size_t left = S->buflen;
+ size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
+
+ if( inlen > fill )
+ {
+ memcpy( S->buf + left, in, fill ); // Fill buffer
+ S->buflen += fill;
+ blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
+
+#ifdef USE_SSE
+#ifdef _WIN_32 // We use SSSE3 _mm_shuffle_epi8 only in x64 mode.
+ if (_SSE_Version>=SSE_SSE2)
+#else
+ if (_SSE_Version>=SSE_SSSE3)
+#endif
+ blake2s_compress_sse( S, S->buf );
+ else
+ blake2s_compress( S, S->buf ); // Compress
+#else
+ blake2s_compress( S, S->buf ); // Compress
+#endif
+
+ memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
+ S->buflen -= BLAKE2S_BLOCKBYTES;
+ in += fill;
+ inlen -= fill;
+ }
+ else // inlen <= fill
+ {
+ memcpy( S->buf + left, in, (size_t)inlen );
+ S->buflen += (size_t)inlen; // Be lazy, do not compress
+ in += inlen;
+ inlen -= inlen;
+ }
+ }
+}
+
+
+void blake2s_final( blake2s_state *S, byte *digest )
+{
+ if( S->buflen > BLAKE2S_BLOCKBYTES )
+ {
+ blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
+ blake2s_compress( S, S->buf );
+ S->buflen -= BLAKE2S_BLOCKBYTES;
+ memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
+ }
+
+ blake2s_increment_counter( S, ( uint32 )S->buflen );
+ blake2s_set_lastblock( S );
+ memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
+ blake2s_compress( S, S->buf );
+
+ for( int i = 0; i < 8; ++i ) /* Output full hash */
+ RawPut4( S->h[i], digest + 4 * i );
+}
+
diff --git a/desmume/src/windows/File_Extractor/unrar/blake2s.hpp b/desmume/src/windows/File_Extractor/unrar/blake2s.hpp
new file mode 100644
index 000000000..7dd715713
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/blake2s.hpp
@@ -0,0 +1,101 @@
+// Based on public domain code written in 2012 by Samuel Neves
+#ifndef _RAR_BLAKE2_
+#define _RAR_BLAKE2_
+
+#define BLAKE2_DIGEST_SIZE 32
+
+enum blake2s_constant
+{
+ BLAKE2S_BLOCKBYTES = 64,
+ BLAKE2S_OUTBYTES = 32
+};
+
+
+// Alignment to 64 improves performance of both SSE and non-SSE versions.
+// Alignment to n*16 is required for SSE version, so we selected 64.
+// We use the custom alignment scheme instead of __declspec(align(x)),
+// because it is less compiler dependent. Also the compiler directive
+// does not help if structure is a member of class allocated through
+// 'new' operator.
+struct blake2s_state
+{
+ enum { BLAKE_ALIGNMENT = 64 };
+
+ // buffer and uint32 h[8], t[2], f[2];
+ enum { BLAKE_DATA_SIZE = 48 + 2 * BLAKE2S_BLOCKBYTES };
+
+ byte ubuf[BLAKE_DATA_SIZE + BLAKE_ALIGNMENT];
+
+ byte *buf; // byte buf[2 * BLAKE2S_BLOCKBYTES].
+ uint32 *h, *t, *f; // uint32 h[8], t[2], f[2].
+
+ size_t buflen;
+ byte last_node;
+
+ blake2s_state()
+ {
+ set_pointers();
+ }
+
+ // Required when we declare and assign in the same command.
+ blake2s_state(blake2s_state &st)
+ {
+ set_pointers();
+ *this=st;
+ }
+
+ void set_pointers()
+ {
+ // Set aligned pointers. Must be done in constructor, not in Init(),
+ // so assignments like 'blake2sp_state res=blake2ctx' work correctly
+ // even if blake2sp_init is not called for 'res'.
+ buf = (byte *) ALIGN_VALUE(ubuf, BLAKE_ALIGNMENT);
+ h = (uint32 *) (buf + 2 * BLAKE2S_BLOCKBYTES);
+ t = h + 8;
+ f = t + 2;
+ }
+
+ void init()
+ {
+ memset( ubuf, 0, sizeof( ubuf ) );
+ buflen = 0;
+ last_node = 0;
+ }
+
+ // Since we use pointers, the default = would work incorrectly.
+ blake2s_state& operator = (blake2s_state &st)
+ {
+ if (this != &st)
+ {
+ memcpy(buf, st.buf, BLAKE_DATA_SIZE);
+ buflen = st.buflen;
+ last_node = st.last_node;
+ }
+ return *this;
+ }
+};
+
+
+#ifdef RAR_SMP
+class ThreadPool;
+#endif
+
+struct blake2sp_state
+{
+ blake2s_state S[8];
+ blake2s_state R;
+ byte buf[8 * BLAKE2S_BLOCKBYTES];
+ size_t buflen;
+
+#ifdef RAR_SMP
+ ThreadPool *ThPool;
+ uint MaxThreads;
+#endif
+};
+
+void blake2sp_init( blake2sp_state *S );
+void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen );
+void blake2sp_final( blake2sp_state *S, byte *digest );
+
+#endif
+
diff --git a/desmume/src/windows/File_Extractor/unrar/blake2s_sse.cpp b/desmume/src/windows/File_Extractor/unrar/blake2s_sse.cpp
new file mode 100644
index 000000000..3a94fbc13
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/blake2s_sse.cpp
@@ -0,0 +1,131 @@
+// Based on public domain code written in 2012 by Samuel Neves
+
+#ifdef RAR_COMMON_HPP
+
+extern const byte blake2s_sigma[10][16];
+
+// Initialization vector.
+static __m128i blake2s_IV_0_3, blake2s_IV_4_7;
+
+#ifdef _WIN_64
+// Constants for cyclic rotation. Used in 64-bit mode in mm_rotr_epi32 macro.
+static __m128i crotr8, crotr16;
+#endif
+
+static void blake2s_init_sse()
+{
+ // We cannot initialize these 128 bit variables in place when declaring
+ // them globally, because global scope initialization is performed before
+ // our SSE check and it would make code incompatible with older non-SSE2
+ // CPUs. Also we cannot initialize them as static inside of function
+ // using these variables, because SSE static initialization is not thread
+ // safe: first thread starts initialization and sets "init done" flag even
+ // if it is not done yet, second thread can attempt to access half-init
+ // SSE data. So we moved init code here.
+
+ blake2s_IV_0_3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A );
+ blake2s_IV_4_7 = _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 );
+
+#ifdef _WIN_64
+ crotr8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 );
+ crotr16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 );
+#endif
+}
+
+
+#define LOAD(p) _mm_load_si128( (__m128i *)(p) )
+#define STORE(p,r) _mm_store_si128((__m128i *)(p), r)
+
+#ifdef _WIN_32
+// 32-bit mode has less SSE2 registers and in MSVC2008 it is more efficient
+// to not use _mm_shuffle_epi8 here.
+#define mm_rotr_epi32(r, c) ( \
+ _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
+#else
+#define mm_rotr_epi32(r, c) ( \
+ c==8 ? _mm_shuffle_epi8(r,crotr8) \
+ : c==16 ? _mm_shuffle_epi8(r,crotr16) \
+ : _mm_xor_si128(_mm_srli_epi32( (r), c ),_mm_slli_epi32( (r), 32-c )) )
+#endif
+
+
+#define G1(row1,row2,row3,row4,buf) \
+ row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
+ row4 = _mm_xor_si128( row4, row1 ); \
+ row4 = mm_rotr_epi32(row4, 16); \
+ row3 = _mm_add_epi32( row3, row4 ); \
+ row2 = _mm_xor_si128( row2, row3 ); \
+ row2 = mm_rotr_epi32(row2, 12);
+
+#define G2(row1,row2,row3,row4,buf) \
+ row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \
+ row4 = _mm_xor_si128( row4, row1 ); \
+ row4 = mm_rotr_epi32(row4, 8); \
+ row3 = _mm_add_epi32( row3, row4 ); \
+ row2 = _mm_xor_si128( row2, row3 ); \
+ row2 = mm_rotr_epi32(row2, 7);
+
+#define DIAGONALIZE(row1,row2,row3,row4) \
+ row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(2,1,0,3) ); \
+ row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
+ row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(0,3,2,1) );
+
+#define UNDIAGONALIZE(row1,row2,row3,row4) \
+ row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(0,3,2,1) ); \
+ row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \
+ row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) );
+
+#ifdef _WIN_64
+ // MSVC 2008 in x64 mode expands _mm_set_epi32 to store to stack and load
+ // from stack operations, which are slower than this code.
+ #define _mm_set_epi32(i3,i2,i1,i0) \
+ _mm_unpacklo_epi32(_mm_unpacklo_epi32(_mm_cvtsi32_si128(i0),_mm_cvtsi32_si128(i2)), \
+ _mm_unpacklo_epi32(_mm_cvtsi32_si128(i1),_mm_cvtsi32_si128(i3)))
+#endif
+
+// Original BLAKE2 SSE4.1 message loading code was a little slower in x86 mode
+// and about the same in x64 mode in our test. Perhaps depends on compiler.
+#define SSE_ROUND(m,row,r) \
+{ \
+ __m128i buf; \
+ buf=_mm_set_epi32(m[blake2s_sigma[r][6]],m[blake2s_sigma[r][4]],m[blake2s_sigma[r][2]],m[blake2s_sigma[r][0]]); \
+ G1(row[0],row[1],row[2],row[3],buf); \
+ buf=_mm_set_epi32(m[blake2s_sigma[r][7]],m[blake2s_sigma[r][5]],m[blake2s_sigma[r][3]],m[blake2s_sigma[r][1]]); \
+ G2(row[0],row[1],row[2],row[3],buf); \
+ DIAGONALIZE(row[0],row[1],row[2],row[3]); \
+ buf=_mm_set_epi32(m[blake2s_sigma[r][14]],m[blake2s_sigma[r][12]],m[blake2s_sigma[r][10]],m[blake2s_sigma[r][8]]); \
+ G1(row[0],row[1],row[2],row[3],buf); \
+ buf=_mm_set_epi32(m[blake2s_sigma[r][15]],m[blake2s_sigma[r][13]],m[blake2s_sigma[r][11]],m[blake2s_sigma[r][9]]); \
+ G2(row[0],row[1],row[2],row[3],buf); \
+ UNDIAGONALIZE(row[0],row[1],row[2],row[3]); \
+}
+
+
+static int blake2s_compress_sse( blake2s_state *S, const byte block[BLAKE2S_BLOCKBYTES] )
+{
+ __m128i row[4];
+ __m128i ff0, ff1;
+
+ const uint32 *m = ( uint32 * )block;
+
+ row[0] = ff0 = LOAD( &S->h[0] );
+ row[1] = ff1 = LOAD( &S->h[4] );
+
+ row[2] = blake2s_IV_0_3;
+ row[3] = _mm_xor_si128( blake2s_IV_4_7, LOAD( &S->t[0] ) );
+ SSE_ROUND( m, row, 0 );
+ SSE_ROUND( m, row, 1 );
+ SSE_ROUND( m, row, 2 );
+ SSE_ROUND( m, row, 3 );
+ SSE_ROUND( m, row, 4 );
+ SSE_ROUND( m, row, 5 );
+ SSE_ROUND( m, row, 6 );
+ SSE_ROUND( m, row, 7 );
+ SSE_ROUND( m, row, 8 );
+ SSE_ROUND( m, row, 9 );
+ STORE( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row[0], row[2] ) ) );
+ STORE( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row[1], row[3] ) ) );
+ return 0;
+}
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/blake2sp.cpp b/desmume/src/windows/File_Extractor/unrar/blake2sp.cpp
new file mode 100644
index 000000000..d9f42e6a9
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/blake2sp.cpp
@@ -0,0 +1,157 @@
+/*
+ BLAKE2 reference source code package - reference C implementations
+
+ Written in 2012 by Samuel Neves
+
+ To the extent possible under law, the author(s) have dedicated all copyright
+ and related and neighboring rights to this software to the public domain
+ worldwide. This software is distributed without any warranty.
+
+ You should have received a copy of the CC0 Public Domain Dedication along with
+ this software. If not, see .
+*/
+
+#ifdef RAR_COMMON_HPP
+
+#define PARALLELISM_DEGREE 8
+
+void blake2sp_init( blake2sp_state *S )
+{
+ memset( S->buf, 0, sizeof( S->buf ) );
+ S->buflen = 0;
+
+ blake2s_init_param( &S->R, 0, 1 ); // Init root.
+
+ for( uint i = 0; i < PARALLELISM_DEGREE; ++i )
+ blake2s_init_param( &S->S[i], i, 0 ); // Init leaf.
+
+ S->R.last_node = 1;
+ S->S[PARALLELISM_DEGREE - 1].last_node = 1;
+}
+
+
+struct Blake2ThreadData
+{
+ void Update();
+ blake2s_state *S;
+ const byte *in;
+ size_t inlen;
+};
+
+
+void Blake2ThreadData::Update()
+{
+ size_t inlen__ = inlen;
+ const byte *in__ = ( const byte * )in;
+
+ while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
+ {
+#ifdef USE_SSE
+ // We gain 5% in i7 SSE mode by prefetching next data block.
+ if (_SSE_Version>=SSE_SSE && inlen__ >= 2 * PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES)
+ _mm_prefetch((char*)(in__ + PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES), _MM_HINT_T0);
+#endif
+ blake2s_update( S, in__, BLAKE2S_BLOCKBYTES );
+ in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
+ inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
+ }
+}
+
+#ifdef RAR_SMP
+THREAD_PROC(Blake2Thread)
+{
+ Blake2ThreadData *td=(Blake2ThreadData *)Data;
+ td->Update();
+}
+#endif
+
+
+void blake2sp_update( blake2sp_state *S, const byte *in, size_t inlen )
+{
+ size_t left = S->buflen;
+ size_t fill = sizeof( S->buf ) - left;
+
+ if( left && inlen >= fill )
+ {
+ memcpy( S->buf + left, in, fill );
+
+ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
+ blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
+
+ in += fill;
+ inlen -= fill;
+ left = 0;
+ }
+
+ Blake2ThreadData btd_array[PARALLELISM_DEGREE];
+
+#ifdef RAR_SMP
+ uint ThreadNumber = inlen < 0x1000 ? 1 : S->MaxThreads;
+
+ if (ThreadNumber==6 || ThreadNumber==7) // 6 and 7 threads work slower than 4 here.
+ ThreadNumber=4;
+#else
+ uint ThreadNumber=1;
+#endif
+
+ for (size_t id__=0;id__inlen = inlen;
+ btd->in = in + id__ * BLAKE2S_BLOCKBYTES;
+ btd->S = &S->S[id__];
+
+#ifdef RAR_SMP
+ if (ThreadNumber>1)
+ S->ThPool->AddTask(Blake2Thread,(void*)btd);
+ else
+ btd->Update();
+#else
+ btd->Update();
+#endif
+ id__++;
+ }
+#ifdef RAR_SMP
+ if (S->ThPool!=NULL) // Can be NULL in -mt1 mode.
+ S->ThPool->WaitDone();
+#endif // RAR_SMP
+ }
+
+ in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
+ inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
+
+ if( inlen > 0 )
+ memcpy( S->buf + left, in, (size_t)inlen );
+
+ S->buflen = left + (size_t)inlen;
+}
+
+
+void blake2sp_final( blake2sp_state *S, byte *digest )
+{
+ byte hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
+
+ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
+ {
+ if( S->buflen > i * BLAKE2S_BLOCKBYTES )
+ {
+ size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
+
+ if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
+
+ blake2s_update( &S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
+ }
+
+ blake2s_final( &S->S[i], hash[i] );
+ }
+
+ for( size_t i = 0; i < PARALLELISM_DEGREE; ++i )
+ blake2s_update( &S->R, hash[i], BLAKE2S_OUTBYTES );
+
+ blake2s_final( &S->R, digest );
+}
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/coder.cpp b/desmume/src/windows/File_Extractor/unrar/coder.cpp
index 1f090574f..ad09fc52a 100644
--- a/desmume/src/windows/File_Extractor/unrar/coder.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/coder.cpp
@@ -18,9 +18,10 @@ void RangeCoder::InitDecoder(Unpack *UnpackRead)
}
+// (int) cast before "low" added only to suppress compiler warnings.
#define ARI_DEC_NORMALIZE(code,low,range,read) \
{ \
- while ((low^(low+range))GetChar(); \
range <<= 8; \
diff --git a/desmume/src/windows/File_Extractor/unrar/coder.hpp b/desmume/src/windows/File_Extractor/unrar/coder.hpp
index 81eaabf48..7fd45327a 100644
--- a/desmume/src/windows/File_Extractor/unrar/coder.hpp
+++ b/desmume/src/windows/File_Extractor/unrar/coder.hpp
@@ -2,7 +2,6 @@
* Contents: 'Carryless rangecoder' by Dmitry Subbotin *
****************************************************************************/
-const uint TOP=1 << 24, BOT=1 << 15;
class RangeCoder
{
diff --git a/desmume/src/windows/File_Extractor/unrar/compress.hpp b/desmume/src/windows/File_Extractor/unrar/compress.hpp
index dfb86e50d..4b6d47800 100644
--- a/desmume/src/windows/File_Extractor/unrar/compress.hpp
+++ b/desmume/src/windows/File_Extractor/unrar/compress.hpp
@@ -1,36 +1,50 @@
#ifndef _RAR_COMPRESS_
#define _RAR_COMPRESS_
-class ComprDataIO;
-class PackingFileTable;
+// Combine pack and unpack constants to class to avoid polluting global
+// namespace with numerous short names.
+class PackDef
+{
+ public:
+ static const uint MAX_LZ_MATCH = 0x1001;
+ static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3.
+ static const uint LOW_DIST_REP_COUNT = 16;
-#define CODEBUFSIZE 0x4000
-#define MAXWINSIZE 0x400000
-#define MAXWINMASK (MAXWINSIZE-1)
+ static const uint NC = 306; /* alphabet = {0, 1, 2, ..., NC - 1} */
+ static const uint DC = 64;
+ static const uint LDC = 16;
+ static const uint RC = 44;
+ static const uint HUFF_TABLE_SIZE = NC + DC + RC + LDC;
+ static const uint BC = 20;
-#define LOW_DIST_REP_COUNT 16
+ static const uint NC30 = 299; /* alphabet = {0, 1, 2, ..., NC - 1} */
+ static const uint DC30 = 60;
+ static const uint LDC30 = 17;
+ static const uint RC30 = 28;
+ static const uint BC30 = 20;
+ static const uint HUFF_TABLE_SIZE30 = NC30 + DC30 + RC30 + LDC30;
-#define NC 299 /* alphabet = {0, 1, 2, ..., NC - 1} */
-#define DC 60
-#define LDC 17
-#define RC 28
-#define HUFF_TABLE_SIZE (NC+DC+RC+LDC)
-#define BC 20
+ static const uint NC20 = 298; /* alphabet = {0, 1, 2, ..., NC - 1} */
+ static const uint DC20 = 48;
+ static const uint RC20 = 28;
+ static const uint BC20 = 19;
+ static const uint MC20 = 257;
-#define NC20 298 /* alphabet = {0, 1, 2, ..., NC - 1} */
-#define DC20 48
-#define RC20 28
-#define BC20 19
-#define MC20 257
+ // Largest alphabet size among all values listed above.
+ static const uint LARGEST_TABLE_SIZE = 306;
-enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ,
- CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA};
+ enum {
+ CODE_HUFFMAN, CODE_LZ, CODE_REPEATLZ, CODE_CACHELZ, CODE_STARTFILE,
+ CODE_ENDFILE, CODE_FILTER, CODE_FILTERDATA
+ };
+};
enum FilterType {
- FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9,
- FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA,
- FILTER_ITANIUM, FILTER_E8E9V2
+ // These values must not be changed, because we use them directly
+ // in RAR5 compression and decompression code.
+ FILTER_DELTA=0, FILTER_E8, FILTER_E8E9, FILTER_ARM,
+ FILTER_AUDIO, FILTER_RGB, FILTER_ITANIUM, FILTER_PPM, FILTER_NONE
};
#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/crc.cpp b/desmume/src/windows/File_Extractor/unrar/crc.cpp
index 76b1c7dbc..909504902 100644
--- a/desmume/src/windows/File_Extractor/unrar/crc.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/crc.cpp
@@ -1,69 +1,97 @@
+// This CRC function is based on Intel Slicing-by-8 algorithm.
+//
+// Original Intel Slicing-by-8 code is available here:
+//
+// http://sourceforge.net/projects/slicing-by-8/
+//
+// Original Intel Slicing-by-8 code is licensed as:
+//
+// Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved
+//
+// This software program is licensed subject to the BSD License,
+// available at http://www.opensource.org/licenses/bsd-license.html
+
+
#include "rar.hpp"
-uint CRCTab[256];
+uint crc_tables[8][256]; // Tables for Slicing-by-8.
-void InitCRC()
+
+// Build the classic CRC32 lookup table.
+// We also provide this function to legacy RAR and ZIP decryption code.
+void InitCRC32(uint *CRCTab)
{
- for (int I=0;I<256;I++)
+ if (CRCTab[1]!=0)
+ return;
+ for (uint I=0;I<256;I++)
{
uint C=I;
- for (int J=0;J<8;J++)
- C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1);
+ for (uint J=0;J<8;J++)
+ C=(C & 1) ? (C>>1)^0xEDB88320 : (C>>1);
CRCTab[I]=C;
}
}
-uint CRC(uint StartCRC,const void *Addr,size_t Size)
+void InitCRCTables()
{
- // Always initialized ahead of time, and this func call makes it a non-leaf func.
- if (false)
- if (CRCTab[1]==0)
- InitCRC();
- byte *Data=(byte *)Addr;
-#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT)
-
-#ifdef _MSC_VER
- // avoid a warning about 'Data' pointer truncation in 64 bit mode
- #pragma warning( disable : 4311 )
-#endif
-
- while (Size>0 && ((long)Data & 7))
- {
- StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8);
- Size--;
- Data++;
- }
- while (Size>=8)
- {
- StartCRC^=*(uint32 *)Data;
- StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
- StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
- StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
- StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
- StartCRC^=*(uint32 *)(Data+4);
- StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
- StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
- StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
- StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8);
- Data+=8;
- Size-=8;
- }
-#endif
- for (size_t I=0;I>8);
- return(StartCRC);
+ InitCRC32(crc_tables[0]);
+
+ for (uint I=0;I<256;I++) // Build additional lookup tables.
+ {
+ uint C=crc_tables[0][I];
+ for (uint J=1;J<8;J++)
+ {
+ C=crc_tables[0][(byte)C]^(C>>8);
+ crc_tables[J][I]=C;
+ }
+ }
}
+uint CRC32(uint StartCRC,const void *Addr,size_t Size)
+{
+ byte *Data=(byte *)Addr;
+
+ // Align Data to 8 for better performance.
+ for (;Size>0 && ((size_t)Data & 7);Size--,Data++)
+ StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
+
+ for (;Size>=8;Size-=8,Data+=8)
+ {
+#ifdef BIG_ENDIAN
+ StartCRC ^= Data[0]|(Data[1] << 8)|(Data[2] << 16)|(Data[3] << 24);
+ uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24);
+#else
+ StartCRC ^= *(uint32 *) Data;
+ uint NextData = *(uint32 *) (Data +4);
+#endif
+ StartCRC = crc_tables[7][(byte) StartCRC ] ^
+ crc_tables[6][(byte)(StartCRC >> 8) ] ^
+ crc_tables[5][(byte)(StartCRC >> 16)] ^
+ crc_tables[4][(byte)(StartCRC >> 24)] ^
+ crc_tables[3][(byte) NextData ] ^
+ crc_tables[2][(byte)(NextData >>8 ) ] ^
+ crc_tables[1][(byte)(NextData >> 16)] ^
+ crc_tables[0][(byte)(NextData >> 24)];
+ }
+
+ for (;Size>0;Size--,Data++) // Process left data.
+ StartCRC=crc_tables[0][(byte)(StartCRC^Data[0])]^(StartCRC>>8);
+
+ return StartCRC;
+}
+
+
#ifndef SFX_MODULE
-ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size)
+// For RAR 1.4 archives in case somebody still has them.
+ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size)
{
- byte *Data=(byte *)Addr;
- for (size_t I=0;I>15))&0xffff;
- }
- return(StartCRC);
+ byte *Data=(byte *)Addr;
+ for (size_t I=0;I>15))&0xffff;
+ }
+ return StartCRC;
}
#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/encname.cpp b/desmume/src/windows/File_Extractor/unrar/encname.cpp
index dab8c7bfa..555894a85 100644
--- a/desmume/src/windows/File_Extractor/unrar/encname.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/encname.cpp
@@ -11,10 +11,10 @@ EncodeFileName::EncodeFileName()
-void EncodeFileName::Decode(char *Name,byte *EncName,int EncSize,wchar *NameW,
- int MaxDecSize)
+void EncodeFileName::Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,
+ size_t MaxDecSize)
{
- int EncPos=0,DecPos=0;
+ size_t EncPos=0,DecPos=0;
byte HighByte=EncName[EncPos++];
while (EncPosUNP_VER)
+ if (Arc.FileHead.UnpVer!=VER_UNPACK5 &&
+ (Arc.FileHead.UnpVer<13 || Arc.FileHead.UnpVer>VER_UNPACK))
#endif
{
- if (Arc.NewLhd.UnpVer>UNP_VER)
+ if (Arc.FileHead.UnpVer>VER_UNPACK)
return unrar_err_new_algo;
return unrar_err_old_algo;
}
@@ -44,12 +45,15 @@ unrar_err_t CmdExtract::ExtractCurrentFile( bool SkipSolid, bool check_compatibi
FileCount++;
DataIO.UnpFileCRC=Arc.OldFormat ? 0 : 0xffffffff;
// (removed decryption)
- DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize);
+ DataIO.UnpHash.Init(Arc.FileHead.FileHash.Type,1);
+ DataIO.PackedDataHash.Init(Arc.FileHead.FileHash.Type,1);
+ DataIO.SetPackedSizeToRead(Arc.FileHead.PackSize);
+ DataIO.SetSkipUnpCRC(SkipSolid);
// (removed command-line handling)
DataIO.SetSkipUnpCRC(SkipSolid);
- if (Arc.NewLhd.Method==0x30)
- UnstoreFile(Arc.NewLhd.FullUnpSize);
+ if (Arc.FileHead.Method==0)
+ UnstoreFile(Arc.FileHead.UnpSize);
else
{
// Defer creation of Unpack until first extraction
@@ -58,26 +62,26 @@ unrar_err_t CmdExtract::ExtractCurrentFile( bool SkipSolid, bool check_compatibi
Unp = new Unpack( &Arc );
if ( !Unp )
return unrar_err_memory;
-
- Unp->Init( NULL );
}
- Unp->SetDestSize(Arc.NewLhd.FullUnpSize);
+ Unp->Init(Arc.FileHead.WinSize,Arc.FileHead.Solid);
+ Unp->SetDestSize(Arc.FileHead.UnpSize);
#ifndef SFX_MODULE
- if (Arc.NewLhd.UnpVer<=15)
+ if (Arc.Format!=RARFMT50 && Arc.FileHead.UnpVer<=15)
Unp->DoUnpack(15,FileCount>1 && Arc.Solid);
else
#endif
- Unp->DoUnpack(Arc.NewLhd.UnpVer,Arc.NewLhd.Flags & LHD_SOLID);
+ Unp->DoUnpack(Arc.FileHead.UnpVer,Arc.FileHead.Solid);
}
// (no need to seek to next file)
if (!SkipSolid)
{
- if (Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC) ||
- !Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC^0xffffffff))
- {
+ HashValue UnpHash;
+ DataIO.UnpHash.Result(&UnpHash);
+ if (UnpHash==Arc.FileHead.FileHash)
+ {
// CRC is correct
}
else
@@ -93,12 +97,12 @@ unrar_err_t CmdExtract::ExtractCurrentFile( bool SkipSolid, bool check_compatibi
}
-void CmdExtract::UnstoreFile(Int64 DestUnpSize)
+void CmdExtract::UnstoreFile(int64 DestUnpSize)
{
- Buffer.Alloc(Min(DestUnpSize,0x10000));
+ Buffer.Alloc((int)Min(DestUnpSize,0x10000));
while (1)
{
- unsigned int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size());
+ unsigned int Code=DataIO.UnpRead(&Buffer[0],(uint)Buffer.Size());
if (Code==0 || (int)Code==-1)
break;
Code=Code>3;
InBit=Bits&7;
}
- unsigned int getbits()
+
+ // Return 16 bits from current position in the buffer.
+ // Bit at (InAddr,InBit) has the highest position in returning data.
+ uint getbits()
{
- unsigned int BitField=(uint)InBuf[InAddr] << 16;
+ uint BitField=(uint)InBuf[InAddr] << 16;
BitField|=(uint)InBuf[InAddr+1] << 8;
BitField|=(uint)InBuf[InAddr+2];
BitField >>= (8-InBit);
return(BitField & 0xffff);
}
- void faddbits(int Bits);
- unsigned int fgetbits();
- bool Overflow(int IncPtr) {return(InAddr+IncPtr>=MAX_SIZE);}
+
+ // Return 32 bits from current position in the buffer.
+ // Bit at (InAddr,InBit) has the highest position in returning data.
+ uint getbits32()
+ {
+ uint BitField=(uint)InBuf[InAddr] << 24;
+ BitField|=(uint)InBuf[InAddr+1] << 16;
+ BitField|=(uint)InBuf[InAddr+2] << 8;
+ BitField|=(uint)InBuf[InAddr+3];
+ BitField <<= InBit;
+ BitField|=(uint)InBuf[InAddr+4] >> (8-InBit);
+ return(BitField & 0xffffffff);
+ }
+
+ void faddbits(uint Bits);
+ uint fgetbits();
+
+ // Check if buffer has enough space for IncPtr bytes. Returns 'true'
+ // if buffer will be overflown.
+ bool Overflow(uint IncPtr)
+ {
+ return(InAddr+IncPtr>=MAX_SIZE);
+ }
+
+ void SetExternalBuffer(byte *Buf);
};
#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/hash.cpp b/desmume/src/windows/File_Extractor/unrar/hash.cpp
new file mode 100644
index 000000000..4e4f43c34
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/hash.cpp
@@ -0,0 +1,118 @@
+#include "rar.hpp"
+
+void HashValue::Init(HASH_TYPE Type)
+{
+ HashValue::Type=Type;
+
+ // Zero length data CRC32 is 0. It is important to set it when creating
+ // headers with no following data like directories or symlinks.
+ if (Type==HASH_RAR14 || Type==HASH_CRC32)
+ CRC32=0;
+ if (Type==HASH_BLAKE2)
+ {
+ // dd0e891776933f43c7d032b08a917e25741f8aa9a12c12e1cac8801500f2ca4f
+ // is BLAKE2sp hash of empty data. We init the structure to this value,
+ // so if we create a file or service header with no following data like
+ // "file copy" or "symlink", we set the checksum to proper value avoiding
+ // additional header type or size checks when extracting.
+ static byte EmptyHash[32]={
+ 0xdd, 0x0e, 0x89, 0x17, 0x76, 0x93, 0x3f, 0x43,
+ 0xc7, 0xd0, 0x32, 0xb0, 0x8a, 0x91, 0x7e, 0x25,
+ 0x74, 0x1f, 0x8a, 0xa9, 0xa1, 0x2c, 0x12, 0xe1,
+ 0xca, 0xc8, 0x80, 0x15, 0x00, 0xf2, 0xca, 0x4f
+ };
+ memcpy(Digest,EmptyHash,sizeof(Digest));
+ }
+}
+
+
+bool HashValue::operator == (const HashValue &cmp)
+{
+ if (Type==HASH_NONE || cmp.Type==HASH_NONE)
+ return true;
+ if ((Type==HASH_RAR14 && cmp.Type==HASH_RAR14) ||
+ (Type==HASH_CRC32 && cmp.Type==HASH_CRC32))
+ return CRC32==cmp.CRC32;
+ if (Type==HASH_BLAKE2 && cmp.Type==HASH_BLAKE2)
+ return memcmp(Digest,cmp.Digest,sizeof(Digest))==0;
+ return false;
+}
+
+
+DataHash::DataHash()
+{
+ HashType=HASH_NONE;
+#ifdef RAR_SMP
+ ThPool=NULL;
+ MaxThreads=0;
+#endif
+}
+
+
+DataHash::~DataHash()
+{
+#ifdef RAR_SMP
+ DestroyThreadPool(ThPool);
+#endif
+ cleandata(&blake2ctx, sizeof(blake2ctx));
+ cleandata(&CurCRC32, sizeof(CurCRC32));
+}
+
+
+void DataHash::Init(HASH_TYPE Type,uint MaxThreads)
+{
+ HashType=Type;
+ if (Type==HASH_RAR14)
+ CurCRC32=0;
+ if (Type==HASH_CRC32)
+ CurCRC32=0xffffffff; // Initial CRC32 value.
+ if (Type==HASH_BLAKE2)
+ blake2sp_init( &blake2ctx );
+#ifdef RAR_SMP
+ DataHash::MaxThreads=Min(MaxThreads,MaxHashThreads);
+#endif
+}
+
+
+void DataHash::Update(const void *Data,size_t DataSize)
+{
+#ifndef SFX_MODULE
+ if (HashType==HASH_RAR14)
+ CurCRC32=Checksum14((ushort)CurCRC32,Data,DataSize);
+#endif
+ if (HashType==HASH_CRC32)
+ CurCRC32=CRC32(CurCRC32,Data,DataSize);
+
+ if (HashType==HASH_BLAKE2)
+ {
+#ifdef RAR_SMP
+ if (MaxThreads>1 && ThPool==NULL)
+ ThPool=CreateThreadPool();
+ blake2ctx.ThPool=ThPool;
+ blake2ctx.MaxThreads=MaxThreads;
+#endif
+ blake2sp_update( &blake2ctx, (byte *)Data, DataSize);
+ }
+}
+
+
+void DataHash::Result(HashValue *Result)
+{
+ Result->Type=HashType;
+ if (HashType==HASH_RAR14)
+ Result->CRC32=CurCRC32;
+ if (HashType==HASH_CRC32)
+ Result->CRC32=CurCRC32^0xffffffff;
+ if (HashType==HASH_BLAKE2)
+ {
+ // Preserve the original context, so we can continue hashing if necessary.
+ blake2sp_state res=blake2ctx;
+ blake2sp_final( &res, Result->Digest );
+ }
+}
+
+
+uint DataHash::GetCRC32()
+{
+ return HashType==HASH_CRC32 ? CurCRC32^0xffffffff : 0;
+}
diff --git a/desmume/src/windows/File_Extractor/unrar/hash.hpp b/desmume/src/windows/File_Extractor/unrar/hash.hpp
new file mode 100644
index 000000000..dae31d1b2
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/hash.hpp
@@ -0,0 +1,52 @@
+#ifndef _RAR_DATAHASH_
+#define _RAR_DATAHASH_
+
+enum HASH_TYPE {HASH_NONE,HASH_RAR14,HASH_CRC32,HASH_BLAKE2};
+
+struct HashValue
+{
+ void Init(HASH_TYPE Type);
+ bool operator == (const HashValue &cmp);
+ bool operator != (const HashValue &cmp) {return !(*this==cmp);}
+
+ HASH_TYPE Type;
+ union
+ {
+ uint CRC32;
+ byte Digest[SHA256_DIGEST_SIZE];
+ };
+};
+
+
+#ifdef RAR_SMP
+class ThreadPool;
+class DataHash;
+#endif
+
+
+class DataHash
+{
+ private:
+ HASH_TYPE HashType;
+ uint CurCRC32;
+ blake2sp_state blake2ctx;
+
+#ifdef RAR_SMP
+ ThreadPool *ThPool;
+
+ uint MaxThreads;
+ // Upper limit for maximum threads to prevent wasting threads in pool.
+ static const uint MaxHashThreads=8;
+#endif
+ public:
+ DataHash();
+ ~DataHash();
+ void Init(HASH_TYPE Type,uint MaxThreads);
+ void Update(const void *Data,size_t DataSize);
+ void Result(HashValue *Result);
+ uint GetCRC32();
+ bool Cmp(HashValue *CmpValue,byte *Key);
+ HASH_TYPE Type() {return HashType;}
+};
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/headers.cpp b/desmume/src/windows/File_Extractor/unrar/headers.cpp
new file mode 100644
index 000000000..70c550437
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/headers.cpp
@@ -0,0 +1,60 @@
+#include "rar.hpp"
+
+void FileHeader::Reset(size_t SubDataSize)
+{
+ SubData.Alloc(SubDataSize);
+ BaseBlock::Reset();
+#ifndef SHELL_EXT
+ FileHash.Init(HASH_NONE);
+#endif
+ mtime.Reset();
+ atime.Reset();
+ ctime.Reset();
+ SplitBefore=false;
+ SplitAfter=false;
+
+ UnknownUnpSize=0;
+
+ SubFlags=0; // Important for RAR 3.0 subhead.
+
+ Encrypted=false;
+ UsePswCheck=false;
+ UseHashKey=false;
+ Lg2Count=0;
+
+ Solid=false;
+ Dir=false;
+ WinSize=0;
+ Inherited=false;
+ SubBlock=false;
+ CommentInHeader=false;
+ Version=false;
+ LargeFile=false;
+
+ RedirType=FSREDIR_NONE;
+ UnixOwnerSet=false;
+}
+
+
+FileHeader& FileHeader::operator = (FileHeader &hd)
+{
+ SubData.Reset();
+ memcpy(this,&hd,sizeof(*this));
+ SubData.CleanData();
+ SubData=hd.SubData;
+ return *this;
+}
+
+
+void MainHeader::Reset()
+{
+ HighPosAV=0;
+ PosAV=0;
+ CommentInHeader=false;
+ PackComment=false;
+ Locator=false;
+ QOpenOffset=0;
+ QOpenMaxSize=0;
+ RROffset=0;
+ RRMaxSize=0;
+}
diff --git a/desmume/src/windows/File_Extractor/unrar/headers.hpp b/desmume/src/windows/File_Extractor/unrar/headers.hpp
index 38a0bdb28..9b336655a 100644
--- a/desmume/src/windows/File_Extractor/unrar/headers.hpp
+++ b/desmume/src/windows/File_Extractor/unrar/headers.hpp
@@ -1,145 +1,362 @@
-#ifndef _RAR_HEADERS_
-#define _RAR_HEADERS_
-
-#define SIZEOF_MARKHEAD 7
-#define SIZEOF_OLDMHD 7
-#define SIZEOF_NEWMHD 13
-#define SIZEOF_OLDLHD 21
-#define SIZEOF_NEWLHD 32
-#define SIZEOF_SHORTBLOCKHEAD 7
-#define SIZEOF_SUBBLOCKHEAD 14
-#define SIZEOF_COMMHEAD 13
-
-#define UNP_VER 36
-
-#define MHD_VOLUME 0x0001
-#define MHD_COMMENT 0x0002
-#define MHD_SOLID 0x0008
-#define MHD_PASSWORD 0x0080
-
-#define LHD_SPLIT_BEFORE 0x0001
-#define LHD_SPLIT_AFTER 0x0002
-#define LHD_PASSWORD 0x0004
-#define LHD_COMMENT 0x0008
-#define LHD_SOLID 0x0010
-
-#define LHD_WINDOWMASK 0x00e0
-#define LHD_DIRECTORY 0x00e0
-
-#define LHD_LARGE 0x0100
-#define LHD_UNICODE 0x0200
-#define LHD_SALT 0x0400
-#define LHD_EXTTIME 0x1000
-
-#define LONG_BLOCK 0x8000
-
-enum HEADER_TYPE {
- MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76,
- SUB_HEAD=0x77,PROTECT_HEAD=0x78,SIGN_HEAD=0x79,NEWSUB_HEAD=0x7a,
- ENDARC_HEAD=0x7b
-};
-
-enum HOST_SYSTEM {
- HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
- HOST_BEOS=5,HOST_MAX
-};
-
-struct OldMainHeader
-{
- byte Mark[4];
- ushort HeadSize;
- byte Flags;
-};
-
-
-struct OldFileHeader
-{
- uint PackSize;
- uint UnpSize;
- ushort FileCRC;
- ushort HeadSize;
- uint FileTime;
- byte FileAttr;
- byte Flags;
- byte UnpVer;
- byte NameSize;
- byte Method;
-};
-
-
-struct MarkHeader
-{
- byte Mark[7];
-};
-
-
-struct BaseBlock
-{
- ushort HeadCRC;
- HEADER_TYPE HeadType;//byte
- ushort Flags;
- ushort HeadSize;
-};
-
-struct BlockHeader:BaseBlock
-{
- union {
- uint DataSize;
- uint PackSize;
- };
-};
-
-
-struct MainHeader:BaseBlock
-{
- ushort HighPosAV;
- uint PosAV;
-};
-
-#define SALT_SIZE 8
-
-struct FileHeader:BlockHeader
-{
- uint UnpSize;
- byte HostOS;
- uint FileCRC;
- uint FileTime;
- byte UnpVer;
- byte Method;
- ushort NameSize;
- union {
- uint FileAttr;
- uint SubFlags;
- };
-/* optional */
- uint HighPackSize;
- uint HighUnpSize;
-/* names */
- char FileName[NM*4]; // *4 to avoid using lots of stack in arcread
- wchar FileNameW[NM];
-/* optional */
- byte Salt[SALT_SIZE];
-
- RarTime mtime;
-/* dummy */
- Int64 FullPackSize;
- Int64 FullUnpSize;
-};
-
-// SubBlockHeader and its successors were used in RAR 2.x format.
-// RAR 3.x uses FileHeader with NEWSUB_HEAD HeadType for subblocks.
-struct SubBlockHeader:BlockHeader
-{
- ushort SubType;
- byte Level;
-};
-
-struct ProtectHeader:BlockHeader
-{
- byte Version;
- ushort RecSectors;
- uint TotalBlocks;
- byte Mark[8];
-};
-
-#endif
+#ifndef _RAR_HEADERS_
+#define _RAR_HEADERS_
+
+#define SIZEOF_MARKHEAD3 7 // Size of RAR 4.x archive mark header.
+#define SIZEOF_MAINHEAD14 7 // Size of RAR 1.4 main archive header.
+#define SIZEOF_MAINHEAD3 13 // Size of RAR 4.x main archive header.
+#define SIZEOF_FILEHEAD14 21 // Size of RAR 1.4 file header.
+#define SIZEOF_FILEHEAD3 32 // Size of RAR 3.0 file header.
+#define SIZEOF_SHORTBLOCKHEAD 7
+#define SIZEOF_LONGBLOCKHEAD 11
+#define SIZEOF_SUBBLOCKHEAD 14
+#define SIZEOF_COMMHEAD 13
+#define SIZEOF_PROTECTHEAD 26
+#define SIZEOF_AVHEAD 14
+#define SIZEOF_SIGNHEAD 15
+#define SIZEOF_UOHEAD 18
+#define SIZEOF_MACHEAD 22
+#define SIZEOF_EAHEAD 24
+#define SIZEOF_BEEAHEAD 24
+#define SIZEOF_STREAMHEAD 26
+
+#define VER_PACK 29
+#define VER_PACK5 0
+#define VER_UNPACK 29
+#define VER_UNPACK5 0
+
+#define MHD_VOLUME 0x0001U
+
+// Old style main archive comment embed into main archive header. Must not
+// be used in new archives anymore.
+#define MHD_COMMENT 0x0002U
+
+#define MHD_LOCK 0x0004U
+#define MHD_SOLID 0x0008U
+#define MHD_PACK_COMMENT 0x0010U
+#define MHD_NEWNUMBERING 0x0010U
+#define MHD_AV 0x0020U
+#define MHD_PROTECT 0x0040U
+#define MHD_PASSWORD 0x0080U
+#define MHD_FIRSTVOLUME 0x0100U
+
+#define LHD_SPLIT_BEFORE 0x0001U
+#define LHD_SPLIT_AFTER 0x0002U
+#define LHD_PASSWORD 0x0004U
+
+// Old style file comment embed into file header. Must not be used
+// in new archives anymore.
+#define LHD_COMMENT 0x0008U
+
+// For non-file subheaders it denotes 'subblock having a parent file' flag.
+#define LHD_SOLID 0x0010U
+
+
+#define LHD_WINDOWMASK 0x00e0U
+#define LHD_WINDOW64 0x0000U
+#define LHD_WINDOW128 0x0020U
+#define LHD_WINDOW256 0x0040U
+#define LHD_WINDOW512 0x0060U
+#define LHD_WINDOW1024 0x0080U
+#define LHD_WINDOW2048 0x00a0U
+#define LHD_WINDOW4096 0x00c0U
+#define LHD_DIRECTORY 0x00e0U
+
+#define LHD_LARGE 0x0100U
+#define LHD_UNICODE 0x0200U
+#define LHD_SALT 0x0400U
+#define LHD_VERSION 0x0800U
+#define LHD_EXTTIME 0x1000U
+
+#define SKIP_IF_UNKNOWN 0x4000U
+#define LONG_BLOCK 0x8000U
+
+#define EARC_NEXT_VOLUME 0x0001U // Not last volume.
+#define EARC_DATACRC 0x0002U // Store CRC32 of RAR archive (now is used only in volumes).
+#define EARC_REVSPACE 0x0004U // Reserve space for end of REV file 7 byte record.
+#define EARC_VOLNUMBER 0x0008U // Store a number of current volume.
+
+enum HEADER_TYPE {
+ // RAR 5.0 header types.
+ HEAD_MARK=0x00, HEAD_MAIN=0x01, HEAD_FILE=0x02, HEAD_SERVICE=0x03,
+ HEAD_CRYPT=0x04, HEAD_ENDARC=0x05, HEAD_UNKNOWN=0xff,
+
+ // RAR 1.5 - 4.x header types.
+ HEAD3_MARK=0x72,HEAD3_MAIN=0x73,HEAD3_FILE=0x74,HEAD3_CMT=0x75,
+ HEAD3_AV=0x76,HEAD3_OLDSERVICE=0x77,HEAD3_PROTECT=0x78,HEAD3_SIGN=0x79,
+ HEAD3_SERVICE=0x7a,HEAD3_ENDARC=0x7b
+};
+
+enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103,
+ NTACL_HEAD=0x104,STREAM_HEAD=0x105 };
+
+
+// Internal implementation, depends on archive format version.
+enum HOST_SYSTEM {
+ // RAR 5.0 host OS
+ HOST5_WINDOWS=0,HOST5_UNIX=1,
+
+ // RAR 3.0 host OS.
+ HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4,
+ HOST_BEOS=5,HOST_MAX
+};
+
+// Unified archive format independent implementation.
+enum HOST_SYSTEM_TYPE {
+ HSYS_WINDOWS, HSYS_UNIX, HSYS_UNKNOWN
+};
+
+
+// We also use these values in extra field, so do not modify them.
+enum FILE_SYSTEM_REDIRECT {
+ FSREDIR_NONE=0, FSREDIR_UNIXSYMLINK, FSREDIR_WINSYMLINK, FSREDIR_JUNCTION,
+ FSREDIR_HARDLINK, FSREDIR_FILECOPY
+};
+
+
+static const wchar SUBHEAD_TYPE_CMT[] = {'C', 'M', 'T', 0};
+static const wchar SUBHEAD_TYPE_QOPEN[] = {'Q', 'O', 0};
+static const wchar SUBHEAD_TYPE_ACL[] = {'A', 'C', 'L', 0};
+static const wchar SUBHEAD_TYPE_STREAM[] = {'S', 'T', 'M', 0};
+static const wchar SUBHEAD_TYPE_UOWNER[] = {'U', 'O', 'W', 0};
+static const wchar SUBHEAD_TYPE_AV[] = {'A', 'V', 0};
+static const wchar SUBHEAD_TYPE_RR[] = {'R', 'R', 0};
+static const wchar SUBHEAD_TYPE_OS2EA[] = {'E', 'A', '2', 0};
+
+/* new file inherits a subblock when updating a host file */
+#define SUBHEAD_FLAGS_INHERITED 0x80000000
+
+#define SUBHEAD_FLAGS_CMT_UNICODE 0x00000001
+
+
+struct MarkHeader
+{
+ byte Mark[8];
+
+ // Following fields are virtual and not present in real blocks.
+ uint HeadSize;
+};
+
+
+struct BaseBlock
+{
+ uint HeadCRC; // 'ushort' for RAR 1.5.
+ HEADER_TYPE HeaderType; // 1 byte for RAR 1.5.
+ uint Flags; // 'ushort' for RAR 1.5.
+ uint HeadSize; // 'ushort' for RAR 1.5, up to 2 MB for RAR 5.0.
+
+ bool SkipIfUnknown;
+
+ void Reset()
+ {
+ SkipIfUnknown=false;
+ }
+};
+
+
+struct BlockHeader:BaseBlock
+{
+ uint DataSize;
+};
+
+
+struct MainHeader:BaseBlock
+{
+ ushort HighPosAV;
+ uint PosAV;
+ bool CommentInHeader;
+ bool PackComment; // For RAR 1.4 archive format only.
+ bool Locator;
+ uint64 QOpenOffset; // Offset of quick list record.
+ uint64 QOpenMaxSize; // Maximum size of QOpen offset in locator extra field.
+ uint64 RROffset; // Offset of recovery record.
+ uint64 RRMaxSize; // Maximum size of RR offset in locator extra field.
+ void Reset();
+};
+
+
+struct FileHeader:BlockHeader
+{
+ byte HostOS;
+ byte UnpVer;
+ byte Method;
+ union {
+ uint FileAttr;
+ uint SubFlags;
+ };
+ wchar FileName[NM];
+
+ Array SubData;
+
+ RarTime mtime;
+ RarTime ctime;
+ RarTime atime;
+
+ int64 PackSize;
+ int64 UnpSize;
+ int64 MaxSize; // Reserve size bytes for vint of this size.
+
+ HashValue FileHash;
+
+ uint FileFlags;
+
+ bool SplitBefore;
+ bool SplitAfter;
+
+ bool UnknownUnpSize;
+
+ bool Encrypted;
+ bool UsePswCheck;
+
+ // Use HMAC calculated from HashKey and checksum instead of plain checksum.
+ bool UseHashKey;
+
+ uint Lg2Count; // Log2 of PBKDF2 repetition count.
+
+ bool Solid;
+ bool Dir;
+ bool CommentInHeader; // RAR 2.0 file comment.
+ bool Version; // name.ext;ver file name containing the version number.
+ size_t WinSize;
+ bool Inherited; // New file inherits a subblock when updating a host file (for subblocks only).
+
+ // 'true' if file sizes use 8 bytes instead of 4. Not used in RAR 5.0.
+ bool LargeFile;
+
+ // 'true' for HEAD_SERVICE block, which is a child of preceding file block.
+ // RAR 4.x uses 'solid' flag to indicate child subheader blocks in archives.
+ bool SubBlock;
+
+ HOST_SYSTEM_TYPE HSType;
+
+ FILE_SYSTEM_REDIRECT RedirType;
+ wchar RedirName[NM];
+ bool DirTarget;
+
+ bool UnixOwnerSet,UnixOwnerNumeric,UnixGroupNumeric;
+ char UnixOwnerName[256],UnixGroupName[256];
+#ifdef _UNIX
+ uid_t UnixOwnerID;
+ uid_t UnixGroupID;
+#else // Need these Unix fields in Windows too for 'list' command.
+ uint UnixOwnerID;
+ uint UnixGroupID;
+#endif
+
+ void Reset(size_t SubDataSize=0);
+
+ bool CmpName(const wchar *Name)
+ {
+ return(my_wcscmp(FileName,Name)==0);
+ }
+
+ FileHeader& operator = (FileHeader &hd);
+};
+
+
+struct EndArcHeader:BaseBlock
+{
+ // Optional CRC32 of entire archive up to start of EndArcHeader block.
+ // Present in RAR 4.x archives if EARC_DATACRC flag is set.
+ uint ArcDataCRC;
+
+ uint VolNumber; // Optional number of current volume.
+
+ // 7 additional zero bytes can be stored here if EARC_REVSPACE is set.
+
+ bool NextVolume; // Not last volume.
+ bool DataCRC;
+ bool RevSpace;
+ bool StoreVolNumber;
+ void Reset()
+ {
+ BaseBlock::Reset();
+ NextVolume=false;
+ DataCRC=false;
+ RevSpace=false;
+ StoreVolNumber=false;
+ }
+};
+
+
+// SubBlockHeader and its successors were used in RAR 2.x format.
+// RAR 4.x uses FileHeader with HEAD_SERVICE HeaderType for subblocks.
+struct SubBlockHeader:BlockHeader
+{
+ ushort SubType;
+ byte Level;
+};
+
+
+struct CommentHeader:BaseBlock
+{
+ ushort UnpSize;
+ byte UnpVer;
+ byte Method;
+ ushort CommCRC;
+};
+
+
+struct ProtectHeader:BlockHeader
+{
+ byte Version;
+ ushort RecSectors;
+ uint TotalBlocks;
+ byte Mark[8];
+};
+
+
+struct AVHeader:BaseBlock
+{
+ byte UnpVer;
+ byte Method;
+ byte AVVer;
+ uint AVInfoCRC;
+};
+
+
+struct SignHeader:BaseBlock
+{
+ uint CreationTime;
+ ushort ArcNameSize;
+ ushort UserNameSize;
+};
+
+
+struct UnixOwnersHeader:SubBlockHeader
+{
+ ushort OwnerNameSize;
+ ushort GroupNameSize;
+/* dummy */
+ char OwnerName[256];
+ char GroupName[256];
+};
+
+
+struct EAHeader:SubBlockHeader
+{
+ uint UnpSize;
+ byte UnpVer;
+ byte Method;
+ uint EACRC;
+};
+
+
+struct StreamHeader:SubBlockHeader
+{
+ uint UnpSize;
+ byte UnpVer;
+ byte Method;
+ uint StreamCRC;
+ ushort StreamNameSize;
+ char StreamName[260];
+};
+
+
+struct MacFInfoHeader:SubBlockHeader
+{
+ uint fileType;
+ uint fileCreator;
+};
+
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/headers5.hpp b/desmume/src/windows/File_Extractor/unrar/headers5.hpp
new file mode 100644
index 000000000..4f403c216
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/headers5.hpp
@@ -0,0 +1,99 @@
+#ifndef _RAR_HEADERS5_
+#define _RAR_HEADERS5_
+
+#define SIZEOF_MARKHEAD5 8 // RAR 5.0 signature length.
+#define SIZEOF_SHORTBLOCKHEAD5 7 // Smallest RAR 5.0 block size.
+
+// RAR 5.0 block flags common for all blocks.
+
+// Additional extra area is present in the end of block header.
+#define HFL_EXTRA 0x0001
+// Additional data area is present in the end of block header.
+#define HFL_DATA 0x0002
+// Unknown blocks with this flag must be skipped when updating an archive.
+#define HFL_SKIPIFUNKNOWN 0x0004
+// Data area of this block is continuing from previous volume.
+#define HFL_SPLITBEFORE 0x0008
+// Data area of this block is continuing in next volume.
+#define HFL_SPLITAFTER 0x0010
+// Block depends on preceding file block.
+#define HFL_CHILD 0x0020
+// Preserve a child block if host is modified.
+#define HFL_INHERITED 0x0040
+
+// RAR 5.0 main archive header specific flags.
+#define MHFL_VOLUME 0x0001 // Volume.
+#define MHFL_VOLNUMBER 0x0002 // Volume number field is present. True for all volumes except first.
+#define MHFL_SOLID 0x0004 // Solid archive.
+#define MHFL_PROTECT 0x0008 // Recovery record is present.
+#define MHFL_LOCK 0x0010 // Locked archive.
+
+// RAR 5.0 file header specific flags.
+#define FHFL_DIRECTORY 0x0001 // Directory.
+#define FHFL_UTIME 0x0002 // Time field in Unix format is present.
+#define FHFL_CRC32 0x0004 // CRC32 field is present.
+#define FHFL_UNPUNKNOWN 0x0008 // Unknown unpacked size.
+
+// RAR 5.0 end of archive header specific flags.
+#define EHFL_NEXTVOLUME 0x0001 // Not last volume.
+
+// RAR 5.0 archive encryption header specific flags.
+#define CHFL_CRYPT_PSWCHECK 0x0001 // Password check data is present.
+
+
+// RAR 5.0 file compression flags.
+#define FCI_ALGO_BIT0 0x0001 // Version of compression algorithm.
+#define FCI_ALGO_BIT1 0x0002 // 0 .. 63.
+#define FCI_ALGO_BIT2 0x0004
+#define FCI_ALGO_BIT3 0x0008
+#define FCI_ALGO_BIT4 0x0010
+#define FCI_ALGO_BIT5 0x0020
+#define FCI_SOLID 0x0040 // Solid flag.
+#define FCI_METHOD_BIT0 0x0080 // Compression method.
+#define FCI_METHOD_BIT1 0x0100 // 0 .. 5 (6 and 7 are not used).
+#define FCI_METHOD_BIT2 0x0200
+#define FCI_DICT_BIT0 0x0400 // Dictionary size.
+#define FCI_DICT_BIT1 0x0800 // 128 KB .. 4 GB.
+#define FCI_DICT_BIT2 0x1000
+#define FCI_DICT_BIT3 0x2000
+
+// Main header extra field values.
+#define MHEXTRA_LOCATOR 0x01 // Position of quick list and other blocks.
+
+// Flags for MHEXTRA_LOCATOR.
+#define MHEXTRA_LOCATOR_QLIST 0x01 // Quick open offset is present.
+#define MHEXTRA_LOCATOR_RR 0x02 // Recovery record offset is present.
+
+// File and service header extra field values.
+#define FHEXTRA_CRYPT 0x01 // Encryption parameters.
+#define FHEXTRA_HASH 0x02 // File hash.
+#define FHEXTRA_HTIME 0x03 // High precision file time.
+#define FHEXTRA_VERSION 0x04 // File version information.
+#define FHEXTRA_REDIR 0x05 // File system redirection (links, etc.).
+#define FHEXTRA_UOWNER 0x06 // Unix owner and group information.
+#define FHEXTRA_SUBDATA 0x07 // Service header subdata array.
+
+
+// Hash type values for FHEXTRA_HASH.
+#define FHEXTRA_HASH_BLAKE2 0x00
+
+// Flags for FHEXTRA_HTIME.
+#define FHEXTRA_HTIME_UNIXTIME 0x01 // Use Unix time_t format.
+#define FHEXTRA_HTIME_MTIME 0x02 // mtime is present.
+#define FHEXTRA_HTIME_CTIME 0x04 // ctime is present.
+#define FHEXTRA_HTIME_ATIME 0x08 // atime is present.
+
+// Flags for FHEXTRA_CRYPT.
+#define FHEXTRA_CRYPT_PSWCHECK 0x01 // Store password check data.
+#define FHEXTRA_CRYPT_HASHMAC 0x02 // Use MAC for unpacked data checksums.
+
+// Flags for FHEXTRA_REDIR.
+#define FHEXTRA_REDIR_DIR 0x01 // Link target is directory.
+
+// Flags for FHEXTRA_UOWNER.
+#define FHEXTRA_UOWNER_UNAME 0x01 // User name string is present.
+#define FHEXTRA_UOWNER_GNAME 0x02 // Group name string is present.
+#define FHEXTRA_UOWNER_NUMUID 0x04 // Numeric user ID is present.
+#define FHEXTRA_UOWNER_NUMGID 0x08 // Numeric group ID is present.
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/license.txt b/desmume/src/windows/File_Extractor/unrar/license.txt
index 2aa475c71..0811276a1 100644
--- a/desmume/src/windows/File_Extractor/unrar/license.txt
+++ b/desmume/src/windows/File_Extractor/unrar/license.txt
@@ -1,40 +1,42 @@
- ****** ***** ****** UnRAR - free utility for RAR archives
- ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ****** ******* ****** License for use and distribution of
- ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ** ** ** ** ** ** FREE portable version
- ~~~~~~~~~~~~~~~~~~~~~
-
- The source code of UnRAR utility is freeware. This means:
-
- 1. All copyrights to RAR and the utility UnRAR are exclusively
- owned by the author - Alexander Roshal.
-
- 2. The UnRAR sources may be used in any software to handle RAR
- archives without limitations free of charge, but cannot be used
- to re-create the RAR compression algorithm, which is proprietary.
- Distribution of modified UnRAR sources in separate form or as a
- part of other software is permitted, provided that it is clearly
- stated in the documentation and source comments that the code may
- not be used to develop a RAR (WinRAR) compatible archiver.
-
- 3. The UnRAR utility may be freely distributed. It is allowed
- to distribute UnRAR inside of other software packages.
-
- 4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
- NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
- YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
- DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
- OR MISUSING THIS SOFTWARE.
-
- 5. Installing and using the UnRAR utility signifies acceptance of
- these terms and conditions of the license.
-
- 6. If you don't agree with terms of the license you must remove
- UnRAR files from your storage devices and cease to use the
- utility.
-
- Thank you for your interest in RAR and UnRAR.
-
-
- Alexander L. Roshal
\ No newline at end of file
+ ****** ***** ****** UnRAR - free utility for RAR archives
+ ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ****** ******* ****** License for use and distribution of
+ ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ** ** ** ** ** ** FREE portable version
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ The source code of UnRAR utility is freeware. This means:
+
+ 1. All copyrights to RAR and the utility UnRAR are exclusively
+ owned by the author - Alexander Roshal.
+
+ 2. UnRAR source code may be used in any software to handle
+ RAR archives without limitations free of charge, but cannot be
+ used to develop RAR (WinRAR) compatible archiver and to
+ re-create RAR compression algorithm, which is proprietary.
+ Distribution of modified UnRAR source code in separate form
+ or as a part of other software is permitted, provided that
+ full text of this paragraph, starting from "UnRAR source code"
+ words, is included in license, or in documentation if license
+ is not available, and in source code comments of resulting package.
+
+ 3. The UnRAR utility may be freely distributed. It is allowed
+ to distribute UnRAR inside of other software packages.
+
+ 4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS".
+ NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT
+ YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS,
+ DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING
+ OR MISUSING THIS SOFTWARE.
+
+ 5. Installing and using the UnRAR utility signifies acceptance of
+ these terms and conditions of the license.
+
+ 6. If you don't agree with terms of the license you must remove
+ UnRAR files from your storage devices and cease to use the
+ utility.
+
+ Thank you for your interest in RAR and UnRAR.
+
+
+ Alexander L. Roshal
diff --git a/desmume/src/windows/File_Extractor/unrar/model.cpp b/desmume/src/windows/File_Extractor/unrar/model.cpp
index c65ae6807..4aca883b6 100644
--- a/desmume/src/windows/File_Extractor/unrar/model.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/model.cpp
@@ -1,612 +1,621 @@
-// #included by unpack.cpp
-#ifdef RAR_COMMON_HPP
-/****************************************************************************
- * This file is part of PPMd project *
- * Written and distributed to public domain by Dmitry Shkarin 1997, *
- * 1999-2000 *
- * Contents: model description and encoding/decoding routines *
- ****************************************************************************/
-
-inline PPM_CONTEXT* PPM_CONTEXT::createChild(ModelPPM *Model,STATE* pStats,
- STATE& FirstState)
-{
- PPM_CONTEXT* pc = (PPM_CONTEXT*) Model->SubAlloc.AllocContext();
- if ( pc )
- {
- pc->NumStats=1;
- pc->OneState=FirstState;
- pc->Suffix=this;
- pStats->Successor=pc;
- }
- return pc;
-}
-
-
-ModelPPM::ModelPPM()
-{
- MinContext=NULL;
- MaxContext=NULL;
- MedContext=NULL;
-}
-
-
-void ModelPPM::RestartModelRare()
-{
- int i, k, m;
- memset(CharMask,0,sizeof(CharMask));
- SubAlloc.InitSubAllocator();
- InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
- MinContext = MaxContext = (PPM_CONTEXT*) SubAlloc.AllocContext();
- MinContext->Suffix=NULL;
- OrderFall=MaxOrder;
- MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
- FoundState=MinContext->U.Stats=(STATE*)SubAlloc.AllocUnits(256/2);
- for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
- {
- MinContext->U.Stats[i].Symbol=i;
- MinContext->U.Stats[i].Freq=1;
- MinContext->U.Stats[i].Successor=NULL;
- }
-
- static const ushort InitBinEsc[]={
- 0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051
- };
-
- for (i=0;i < 128;i++)
- for (k=0;k < 8;k++)
- for (m=0;m < 64;m += 8)
- BinSumm[i][k+m]=BIN_SCALE-InitBinEsc[k]/(i+2);
- for (i=0;i < 25;i++)
- for (k=0;k < 16;k++)
- SEE2Cont[i][k].init(5*i+10);
-}
-
-
-void ModelPPM::StartModelRare(int MaxOrder)
-{
- int i, k, m ,Step;
- EscCount=1;
-/*
- if (MaxOrder < 2)
- {
- memset(CharMask,0,sizeof(CharMask));
- OrderFall=ModelPPM::MaxOrder;
- MinContext=MaxContext;
- while (MinContext->Suffix != NULL)
- {
- MinContext=MinContext->Suffix;
- OrderFall--;
- }
- FoundState=MinContext->U.Stats;
- MinContext=MaxContext;
- }
- else
-*/
- {
- ModelPPM::MaxOrder=MaxOrder;
- RestartModelRare();
- NS2BSIndx[0]=2*0;
- NS2BSIndx[1]=2*1;
- memset(NS2BSIndx+2,2*2,9);
- memset(NS2BSIndx+11,2*3,256-11);
- for (i=0;i < 3;i++)
- NS2Indx[i]=i;
- for (m=i, k=Step=1;i < 256;i++)
- {
- NS2Indx[i]=m;
- if ( !--k )
- {
- k = ++Step;
- m++;
- }
- }
- memset(HB2Flag,0,0x40);
- memset(HB2Flag+0x40,0x08,0x100-0x40);
- DummySEE2Cont.Shift=PERIOD_BITS;
- }
-}
-
-
-void PPM_CONTEXT::rescale(ModelPPM *Model)
-{
- int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
- STATE* p1, * p;
- for (p=Model->FoundState;p != U.Stats;p--)
- _PPMD_SWAP(p[0],p[-1]);
- U.Stats->Freq += 4;
- U.SummFreq += 4;
- EscFreq=U.SummFreq-p->Freq;
- Adder=(Model->OrderFall != 0);
- U.SummFreq = (p->Freq=(p->Freq+Adder) >> 1);
- do
- {
- EscFreq -= (++p)->Freq;
- U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
- if (p[0].Freq > p[-1].Freq)
- {
- STATE tmp=*(p1=p);
- do
- {
- p1[0]=p1[-1];
- } while (--p1 != U.Stats && tmp.Freq > p1[-1].Freq);
- *p1=tmp;
- }
- } while ( --i );
- if (p->Freq == 0)
- {
- do
- {
- i++;
- } while ((--p)->Freq == 0);
- EscFreq += i;
- if ((NumStats -= i) == 1)
- {
- STATE tmp=*U.Stats;
- do
- {
- tmp.Freq-=(tmp.Freq >> 1);
- EscFreq>>=1;
- } while (EscFreq > 1);
- Model->SubAlloc.FreeUnits(U.Stats,(OldNS+1) >> 1);
- *(Model->FoundState=&OneState)=tmp; return;
- }
- }
- U.SummFreq += (EscFreq -= (EscFreq >> 1));
- int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1;
- if (n0 != n1)
- U.Stats = (STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
- Model->FoundState=U.Stats;
-}
-
-
-inline PPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,STATE* p1)
-{
- // (removed conditional static)
- STATE UpState;
- PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
- STATE * p, * ps[MAX_O], ** pps=ps;
- if ( !Skip )
- {
- *pps++ = FoundState;
- if ( !pc->Suffix )
- goto NO_LOOP;
- }
- if ( p1 )
- {
- p=p1;
- pc=pc->Suffix;
- goto LOOP_ENTRY;
- }
- do
- {
- pc=pc->Suffix;
- if (pc->NumStats != 1)
- {
- if ((p=pc->U.Stats)->Symbol != FoundState->Symbol)
- do
- {
- p++;
- } while (p->Symbol != FoundState->Symbol);
- }
- else
- p=&(pc->OneState);
-LOOP_ENTRY:
- if (p->Successor != UpBranch)
- {
- pc=p->Successor;
- break;
- }
- *pps++ = p;
- } while ( pc->Suffix );
-NO_LOOP:
- if (pps == ps)
- return pc;
- UpState.Symbol=*(byte*) UpBranch;
- UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1);
- if (pc->NumStats != 1)
- {
- if ((byte*) pc <= SubAlloc.pText)
- return(NULL);
- if ((p=pc->U.Stats)->Symbol != UpState.Symbol)
- do
- {
- p++;
- } while (p->Symbol != UpState.Symbol);
- uint cf=p->Freq-1;
- uint s0=pc->U.SummFreq-pc->NumStats-cf;
- UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
- }
- else
- UpState.Freq=pc->OneState.Freq;
- do
- {
- pc = pc->createChild(this,*--pps,UpState);
- if ( !pc )
- return NULL;
- } while (pps != ps);
- return pc;
-}
-
-
-inline void ModelPPM::UpdateModel()
-{
- STATE fs = *FoundState, *p = NULL;
- PPM_CONTEXT *pc, *Successor;
- uint ns1, ns, cf, sf, s0;
- if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
- {
- if (pc->NumStats != 1)
- {
- if ((p=pc->U.Stats)->Symbol != fs.Symbol)
- {
- do
- {
- p++;
- } while (p->Symbol != fs.Symbol);
- if (p[0].Freq >= p[-1].Freq)
- {
- _PPMD_SWAP(p[0],p[-1]);
- p--;
- }
- }
- if (p->Freq < MAX_FREQ-9)
- {
- p->Freq += 2;
- pc->U.SummFreq += 2;
- }
- }
- else
- {
- p=&(pc->OneState);
- p->Freq += (p->Freq < 32);
- }
- }
- if ( !OrderFall )
- {
- MinContext=MaxContext=FoundState->Successor=CreateSuccessors(true,p);
- if ( !MinContext )
- goto RESTART_MODEL;
- return;
- }
- *SubAlloc.pText++ = fs.Symbol;
- Successor = (PPM_CONTEXT*) SubAlloc.pText;
- if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
- goto RESTART_MODEL;
- if ( fs.Successor )
- {
- if ((byte*) fs.Successor <= SubAlloc.pText &&
- (fs.Successor=CreateSuccessors(false,p)) == NULL)
- goto RESTART_MODEL;
- if ( !--OrderFall )
- {
- Successor=fs.Successor;
- SubAlloc.pText -= (MaxContext != MinContext);
- }
- }
- else
- {
- FoundState->Successor=Successor;
- fs.Successor=MinContext;
- }
- s0=MinContext->U.SummFreq-(ns=MinContext->NumStats)-(fs.Freq-1);
- for (pc=MaxContext;pc != MinContext;pc=pc->Suffix)
- {
- if ((ns1=pc->NumStats) != 1)
- {
- if ((ns1 & 1) == 0)
- {
- pc->U.Stats=(STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
- if ( !pc->U.Stats )
- goto RESTART_MODEL;
- }
- pc->U.SummFreq += (2*ns1 < ns)+2*((4*ns1 <= ns) & (pc->U.SummFreq <= 8*ns1));
- }
- else
- {
- p=(STATE*) SubAlloc.AllocUnits(1);
- if ( !p )
- goto RESTART_MODEL;
- *p=pc->OneState;
- pc->U.Stats=p;
- if (p->Freq < MAX_FREQ/4-1)
- p->Freq += p->Freq;
- else
- p->Freq = MAX_FREQ-4;
- pc->U.SummFreq=p->Freq+InitEsc+(ns > 3);
- }
- cf=2*fs.Freq*(pc->U.SummFreq+6);
- sf=s0+pc->U.SummFreq;
- if (cf < 6*sf)
- {
- cf=1+(cf > sf)+(cf >= 4*sf);
- pc->U.SummFreq += 3;
- }
- else
- {
- cf=4+(cf >= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf);
- pc->U.SummFreq += cf;
- }
- p=pc->U.Stats+ns1;
- p->Successor=Successor;
- p->Symbol = fs.Symbol;
- p->Freq = cf;
- pc->NumStats=++ns1;
- }
- MaxContext=MinContext=fs.Successor;
- return;
-RESTART_MODEL:
- RestartModelRare();
- EscCount=0;
-}
-
-
-// Tabulated escapes for exponential symbol distribution
-static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
-#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
-
-
-
-inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
-{
- STATE& rs=OneState;
- Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
- ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
- Model->NS2BSIndx[Suffix->NumStats-1]+
- Model->HiBitsFlag+2*Model->HB2Flag[rs.Symbol]+
- ((Model->RunLength >> 26) & 0x20)];
- if (Model->Coder.GetCurrentShiftCount(TOT_BITS) < bs)
- {
- Model->FoundState=&rs;
- rs.Freq += (rs.Freq < 128);
- Model->Coder.SubRange.LowCount=0;
- Model->Coder.SubRange.HighCount=bs;
- bs = SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
- Model->PrevSuccess=1;
- Model->RunLength++;
- }
- else
- {
- Model->Coder.SubRange.LowCount=bs;
- bs = SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
- Model->Coder.SubRange.HighCount=BIN_SCALE;
- Model->InitEsc=ExpEscape[bs >> 10];
- Model->NumMasked=1;
- Model->CharMask[rs.Symbol]=Model->EscCount;
- Model->PrevSuccess=0;
- Model->FoundState=NULL;
- }
-}
-
-
-inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p)
-{
- (Model->FoundState=p)->Freq += 4;
- U.SummFreq += 4;
- if (p[0].Freq > p[-1].Freq)
- {
- _PPMD_SWAP(p[0],p[-1]);
- Model->FoundState=--p;
- if (p->Freq > MAX_FREQ)
- rescale(Model);
- }
-}
-
-
-
-
-inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
-{
- Model->Coder.SubRange.scale=U.SummFreq;
- STATE* p=U.Stats;
- int i, HiCnt;
- int count=Model->Coder.GetCurrentCount();
- if (count>=Model->Coder.SubRange.scale)
- return(false);
- if (count < (HiCnt=p->Freq))
- {
- Model->PrevSuccess=(2*(Model->Coder.SubRange.HighCount=HiCnt) > Model->Coder.SubRange.scale);
- Model->RunLength += Model->PrevSuccess;
- (Model->FoundState=p)->Freq=(HiCnt += 4);
- U.SummFreq += 4;
- if (HiCnt > MAX_FREQ)
- rescale(Model);
- Model->Coder.SubRange.LowCount=0;
- return(true);
- }
- else
- if (Model->FoundState==NULL)
- return(false);
- Model->PrevSuccess=0;
- i=NumStats-1;
- while ((HiCnt += (++p)->Freq) <= count)
- if (--i == 0)
- {
- Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
- Model->Coder.SubRange.LowCount=HiCnt;
- Model->CharMask[p->Symbol]=Model->EscCount;
- i=(Model->NumMasked=NumStats)-1;
- Model->FoundState=NULL;
- do
- {
- Model->CharMask[(--p)->Symbol]=Model->EscCount;
- } while ( --i );
- Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
- return(true);
- }
- Model->Coder.SubRange.LowCount=(Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
- update1(Model,p);
- return(true);
-}
-
-
-inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p)
-{
- (Model->FoundState=p)->Freq += 4;
- U.SummFreq += 4;
- if (p->Freq > MAX_FREQ)
- rescale(Model);
- Model->EscCount++;
- Model->RunLength=Model->InitRL;
-}
-
-
-inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
-{
- SEE2_CONTEXT* psee2c;
- if (NumStats != 256)
- {
- psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
- (Diff < Suffix->NumStats-NumStats)+
- 2*(U.SummFreq < 11*NumStats)+4*(Model->NumMasked > Diff)+
- Model->HiBitsFlag;
- Model->Coder.SubRange.scale=psee2c->getMean();
- }
- else
- {
- psee2c=&Model->DummySEE2Cont;
- Model->Coder.SubRange.scale=1;
- }
- return psee2c;
-}
-
-
-
-
-inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
-{
- int count, HiCnt, i=NumStats-Model->NumMasked;
- SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
- STATE* ps[256], ** pps=ps, * p=U.Stats-1;
- HiCnt=0;
- do
- {
- do
- {
- p++;
- } while (Model->CharMask[p->Symbol] == Model->EscCount);
- HiCnt += p->Freq;
- *pps++ = p;
- } while ( --i );
- Model->Coder.SubRange.scale += HiCnt;
- count=Model->Coder.GetCurrentCount();
- if (count>=Model->Coder.SubRange.scale)
- return(false);
- p=*(pps=ps);
- if (count < HiCnt)
- {
- HiCnt=0;
- while ((HiCnt += p->Freq) <= count)
- p=*++pps;
- Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
- psee2c->update();
- update2(Model,p);
- }
- else
- {
- Model->Coder.SubRange.LowCount=HiCnt;
- Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
- i=NumStats-Model->NumMasked;
- pps--;
- do
- {
- Model->CharMask[(*++pps)->Symbol]=Model->EscCount;
- } while ( --i );
- psee2c->Summ += Model->Coder.SubRange.scale;
- Model->NumMasked = NumStats;
- }
- return(true);
-}
-
-
-inline void ModelPPM::ClearMask()
-{
- EscCount=1;
- memset(CharMask,0,sizeof(CharMask));
-}
-
-
-
-
-// reset PPM variables after data error allowing safe resuming
-// of further data processing
-void ModelPPM::CleanUp()
-{
- SubAlloc.StopSubAllocator();
- SubAlloc.StartSubAllocator(1);
- StartModelRare(2);
-}
-
-
-bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
-{
- int MaxOrder=UnpackRead->GetChar();
- bool Reset=MaxOrder & 0x20;
-
- int MaxMB;
- MaxMB = 0; // avoids warning of being uninitialized
- if (Reset)
- MaxMB=UnpackRead->GetChar();
- else
- if (SubAlloc.GetAllocatedMemory()==0)
- return(false);
- if (MaxOrder & 0x40)
- EscChar=UnpackRead->GetChar();
- Coder.InitDecoder(UnpackRead);
- if (Reset)
- {
- MaxOrder=(MaxOrder & 0x1f)+1;
- if (MaxOrder>16)
- MaxOrder=16+(MaxOrder-16)*3;
- if (MaxOrder==1)
- {
- SubAlloc.StopSubAllocator();
- return(false);
- }
- SubAlloc.StartSubAllocator(MaxMB+1);
- StartModelRare(MaxOrder);
- }
- return(MinContext!=NULL);
-}
-
-
-int ModelPPM::DecodeChar()
-{
- if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
- return(-1);
- if (MinContext->NumStats != 1)
- {
- if ((byte*)MinContext->U.Stats <= SubAlloc.pText || (byte*)MinContext->U.Stats>SubAlloc.HeapEnd)
- return(-1);
- if (!MinContext->decodeSymbol1(this))
- return(-1);
- }
- else
- MinContext->decodeBinSymbol(this);
- Coder.Decode();
- while ( !FoundState )
- {
- ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
- do
- {
- OrderFall++;
- MinContext=MinContext->Suffix;
- if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
- return(-1);
- } while (MinContext->NumStats == NumMasked);
- if (!MinContext->decodeSymbol2(this))
- return(-1);
- Coder.Decode();
- }
- int Symbol=FoundState->Symbol;
- if (!OrderFall && (byte*) FoundState->Successor > SubAlloc.pText)
- MinContext=MaxContext=FoundState->Successor;
- else
- {
- UpdateModel();
- if (EscCount == 0)
- ClearMask();
- }
- ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
- return(Symbol);
-}
-#endif
+/****************************************************************************
+ * This file is part of PPMd project *
+ * Written and distributed to public domain by Dmitry Shkarin 1997, *
+ * 1999-2000 *
+ * Contents: model description and encoding/decoding routines *
+ ****************************************************************************/
+
+#ifdef RAR_COMMON_HPP
+
+static const int MAX_O=64; /* maximum allowed model order */
+const uint TOP=1 << 24, BOT=1 << 15;
+
+template
+inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
+
+
+inline RARPPM_CONTEXT* RARPPM_CONTEXT::createChild(ModelPPM *Model,RARPPM_STATE* pStats,
+ RARPPM_STATE& FirstState)
+{
+ RARPPM_CONTEXT* pc = (RARPPM_CONTEXT*) Model->SubAlloc.AllocContext();
+ if ( pc )
+ {
+ pc->NumStats=1;
+ pc->OneState=FirstState;
+ pc->Suffix=this;
+ pStats->Successor=pc;
+ }
+ return pc;
+}
+
+
+ModelPPM::ModelPPM()
+{
+ MinContext=NULL;
+ MaxContext=NULL;
+ MedContext=NULL;
+}
+
+
+void ModelPPM::RestartModelRare()
+{
+ int i, k, m;
+ memset(CharMask,0,sizeof(CharMask));
+ SubAlloc.InitSubAllocator();
+ InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1;
+ MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext();
+ MinContext->Suffix=NULL;
+ OrderFall=MaxOrder;
+ MinContext->U.SummFreq=(MinContext->NumStats=256)+1;
+ FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2);
+ for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++)
+ {
+ MinContext->U.Stats[i].Symbol=i;
+ MinContext->U.Stats[i].Freq=1;
+ MinContext->U.Stats[i].Successor=NULL;
+ }
+
+ static const ushort InitBinEsc[]={
+ 0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051
+ };
+
+ for (i=0;i < 128;i++)
+ for (k=0;k < 8;k++)
+ for (m=0;m < 64;m += 8)
+ BinSumm[i][k+m]=BIN_SCALE-InitBinEsc[k]/(i+2);
+ for (i=0;i < 25;i++)
+ for (k=0;k < 16;k++)
+ SEE2Cont[i][k].init(5*i+10);
+}
+
+
+void ModelPPM::StartModelRare(int MaxOrder)
+{
+ int i, k, m ,Step;
+ EscCount=1;
+/*
+ if (MaxOrder < 2)
+ {
+ memset(CharMask,0,sizeof(CharMask));
+ OrderFall=ModelPPM::MaxOrder;
+ MinContext=MaxContext;
+ while (MinContext->Suffix != NULL)
+ {
+ MinContext=MinContext->Suffix;
+ OrderFall--;
+ }
+ FoundState=MinContext->U.Stats;
+ MinContext=MaxContext;
+ }
+ else
+*/
+ {
+ ModelPPM::MaxOrder=MaxOrder;
+ RestartModelRare();
+ NS2BSIndx[0]=2*0;
+ NS2BSIndx[1]=2*1;
+ memset(NS2BSIndx+2,2*2,9);
+ memset(NS2BSIndx+11,2*3,256-11);
+ for (i=0;i < 3;i++)
+ NS2Indx[i]=i;
+ for (m=i, k=Step=1;i < 256;i++)
+ {
+ NS2Indx[i]=m;
+ if ( !--k )
+ {
+ k = ++Step;
+ m++;
+ }
+ }
+ memset(HB2Flag,0,0x40);
+ memset(HB2Flag+0x40,0x08,0x100-0x40);
+ DummySEE2Cont.Shift=PERIOD_BITS;
+ }
+}
+
+
+void RARPPM_CONTEXT::rescale(ModelPPM *Model)
+{
+ int OldNS=NumStats, i=NumStats-1, Adder, EscFreq;
+ RARPPM_STATE* p1, * p;
+ for (p=Model->FoundState;p != U.Stats;p--)
+ _PPMD_SWAP(p[0],p[-1]);
+ U.Stats->Freq += 4;
+ U.SummFreq += 4;
+ EscFreq=U.SummFreq-p->Freq;
+ Adder=(Model->OrderFall != 0);
+ U.SummFreq = (p->Freq=(p->Freq+Adder) >> 1);
+ do
+ {
+ EscFreq -= (++p)->Freq;
+ U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1);
+ if (p[0].Freq > p[-1].Freq)
+ {
+ RARPPM_STATE tmp=*(p1=p);
+ do
+ {
+ p1[0]=p1[-1];
+ } while (--p1 != U.Stats && tmp.Freq > p1[-1].Freq);
+ *p1=tmp;
+ }
+ } while ( --i );
+ if (p->Freq == 0)
+ {
+ do
+ {
+ i++;
+ } while ((--p)->Freq == 0);
+ EscFreq += i;
+ if ((NumStats -= i) == 1)
+ {
+ RARPPM_STATE tmp=*U.Stats;
+ do
+ {
+ tmp.Freq-=(tmp.Freq >> 1);
+ EscFreq>>=1;
+ } while (EscFreq > 1);
+ Model->SubAlloc.FreeUnits(U.Stats,(OldNS+1) >> 1);
+ *(Model->FoundState=&OneState)=tmp; return;
+ }
+ }
+ U.SummFreq += (EscFreq -= (EscFreq >> 1));
+ int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1;
+ if (n0 != n1)
+ U.Stats = (RARPPM_STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1);
+ Model->FoundState=U.Stats;
+}
+
+
+inline RARPPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,RARPPM_STATE* p1)
+{
+#ifdef __ICL
+ static
+#endif
+ RARPPM_STATE UpState;
+ RARPPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor;
+ RARPPM_STATE * p, * ps[MAX_O], ** pps=ps;
+ if ( !Skip )
+ {
+ *pps++ = FoundState;
+ if ( !pc->Suffix )
+ goto NO_LOOP;
+ }
+ if ( p1 )
+ {
+ p=p1;
+ pc=pc->Suffix;
+ goto LOOP_ENTRY;
+ }
+ do
+ {
+ pc=pc->Suffix;
+ if (pc->NumStats != 1)
+ {
+ if ((p=pc->U.Stats)->Symbol != FoundState->Symbol)
+ do
+ {
+ p++;
+ } while (p->Symbol != FoundState->Symbol);
+ }
+ else
+ p=&(pc->OneState);
+LOOP_ENTRY:
+ if (p->Successor != UpBranch)
+ {
+ pc=p->Successor;
+ break;
+ }
+ *pps++ = p;
+ } while ( pc->Suffix );
+NO_LOOP:
+ if (pps == ps)
+ return pc;
+ UpState.Symbol=*(byte*) UpBranch;
+ UpState.Successor=(RARPPM_CONTEXT*) (((byte*) UpBranch)+1);
+ if (pc->NumStats != 1)
+ {
+ if ((byte*) pc <= SubAlloc.pText)
+ return(NULL);
+ if ((p=pc->U.Stats)->Symbol != UpState.Symbol)
+ do
+ {
+ p++;
+ } while (p->Symbol != UpState.Symbol);
+ uint cf=p->Freq-1;
+ uint s0=pc->U.SummFreq-pc->NumStats-cf;
+ UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0)));
+ }
+ else
+ UpState.Freq=pc->OneState.Freq;
+ do
+ {
+ pc = pc->createChild(this,*--pps,UpState);
+ if ( !pc )
+ return NULL;
+ } while (pps != ps);
+ return pc;
+}
+
+
+inline void ModelPPM::UpdateModel()
+{
+ RARPPM_STATE fs = *FoundState, *p = NULL;
+ RARPPM_CONTEXT *pc, *Successor;
+ uint ns1, ns, cf, sf, s0;
+ if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL)
+ {
+ if (pc->NumStats != 1)
+ {
+ if ((p=pc->U.Stats)->Symbol != fs.Symbol)
+ {
+ do
+ {
+ p++;
+ } while (p->Symbol != fs.Symbol);
+ if (p[0].Freq >= p[-1].Freq)
+ {
+ _PPMD_SWAP(p[0],p[-1]);
+ p--;
+ }
+ }
+ if (p->Freq < MAX_FREQ-9)
+ {
+ p->Freq += 2;
+ pc->U.SummFreq += 2;
+ }
+ }
+ else
+ {
+ p=&(pc->OneState);
+ p->Freq += (p->Freq < 32);
+ }
+ }
+ if ( !OrderFall )
+ {
+ MinContext=MaxContext=FoundState->Successor=CreateSuccessors(TRUE,p);
+ if ( !MinContext )
+ goto RESTART_MODEL;
+ return;
+ }
+ *SubAlloc.pText++ = fs.Symbol;
+ Successor = (RARPPM_CONTEXT*) SubAlloc.pText;
+ if (SubAlloc.pText >= SubAlloc.FakeUnitsStart)
+ goto RESTART_MODEL;
+ if ( fs.Successor )
+ {
+ if ((byte*) fs.Successor <= SubAlloc.pText &&
+ (fs.Successor=CreateSuccessors(FALSE,p)) == NULL)
+ goto RESTART_MODEL;
+ if ( !--OrderFall )
+ {
+ Successor=fs.Successor;
+ SubAlloc.pText -= (MaxContext != MinContext);
+ }
+ }
+ else
+ {
+ FoundState->Successor=Successor;
+ fs.Successor=MinContext;
+ }
+ s0=MinContext->U.SummFreq-(ns=MinContext->NumStats)-(fs.Freq-1);
+ for (pc=MaxContext;pc != MinContext;pc=pc->Suffix)
+ {
+ if ((ns1=pc->NumStats) != 1)
+ {
+ if ((ns1 & 1) == 0)
+ {
+ pc->U.Stats=(RARPPM_STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1);
+ if ( !pc->U.Stats )
+ goto RESTART_MODEL;
+ }
+ pc->U.SummFreq += (2*ns1 < ns)+2*((4*ns1 <= ns) & (pc->U.SummFreq <= 8*ns1));
+ }
+ else
+ {
+ p=(RARPPM_STATE*) SubAlloc.AllocUnits(1);
+ if ( !p )
+ goto RESTART_MODEL;
+ *p=pc->OneState;
+ pc->U.Stats=p;
+ if (p->Freq < MAX_FREQ/4-1)
+ p->Freq += p->Freq;
+ else
+ p->Freq = MAX_FREQ-4;
+ pc->U.SummFreq=p->Freq+InitEsc+(ns > 3);
+ }
+ cf=2*fs.Freq*(pc->U.SummFreq+6);
+ sf=s0+pc->U.SummFreq;
+ if (cf < 6*sf)
+ {
+ cf=1+(cf > sf)+(cf >= 4*sf);
+ pc->U.SummFreq += 3;
+ }
+ else
+ {
+ cf=4+(cf >= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf);
+ pc->U.SummFreq += cf;
+ }
+ p=pc->U.Stats+ns1;
+ p->Successor=Successor;
+ p->Symbol = fs.Symbol;
+ p->Freq = cf;
+ pc->NumStats=++ns1;
+ }
+ MaxContext=MinContext=fs.Successor;
+ return;
+RESTART_MODEL:
+ RestartModelRare();
+ EscCount=0;
+}
+
+
+// Tabulated escapes for exponential symbol distribution
+static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 };
+#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT))
+
+
+
+inline void RARPPM_CONTEXT::decodeBinSymbol(ModelPPM *Model)
+{
+ RARPPM_STATE& rs=OneState;
+ Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
+ ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+
+ Model->NS2BSIndx[Suffix->NumStats-1]+
+ Model->HiBitsFlag+2*Model->HB2Flag[rs.Symbol]+
+ ((Model->RunLength >> 26) & 0x20)];
+ if (Model->Coder.GetCurrentShiftCount(TOT_BITS) < bs)
+ {
+ Model->FoundState=&rs;
+ rs.Freq += (rs.Freq < 128);
+ Model->Coder.SubRange.LowCount=0;
+ Model->Coder.SubRange.HighCount=bs;
+ bs = GET_SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2));
+ Model->PrevSuccess=1;
+ Model->RunLength++;
+ }
+ else
+ {
+ Model->Coder.SubRange.LowCount=bs;
+ bs = GET_SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2));
+ Model->Coder.SubRange.HighCount=BIN_SCALE;
+ Model->InitEsc=ExpEscape[bs >> 10];
+ Model->NumMasked=1;
+ Model->CharMask[rs.Symbol]=Model->EscCount;
+ Model->PrevSuccess=0;
+ Model->FoundState=NULL;
+ }
+}
+
+
+inline void RARPPM_CONTEXT::update1(ModelPPM *Model,RARPPM_STATE* p)
+{
+ (Model->FoundState=p)->Freq += 4;
+ U.SummFreq += 4;
+ if (p[0].Freq > p[-1].Freq)
+ {
+ _PPMD_SWAP(p[0],p[-1]);
+ Model->FoundState=--p;
+ if (p->Freq > MAX_FREQ)
+ rescale(Model);
+ }
+}
+
+
+
+
+inline bool RARPPM_CONTEXT::decodeSymbol1(ModelPPM *Model)
+{
+ Model->Coder.SubRange.scale=U.SummFreq;
+ RARPPM_STATE* p=U.Stats;
+ int i, HiCnt;
+ int count=Model->Coder.GetCurrentCount();
+ if (count>=(int)Model->Coder.SubRange.scale)
+ return(false);
+ if (count < (HiCnt=p->Freq))
+ {
+ Model->PrevSuccess=(2*(Model->Coder.SubRange.HighCount=HiCnt) > Model->Coder.SubRange.scale);
+ Model->RunLength += Model->PrevSuccess;
+ (Model->FoundState=p)->Freq=(HiCnt += 4);
+ U.SummFreq += 4;
+ if (HiCnt > MAX_FREQ)
+ rescale(Model);
+ Model->Coder.SubRange.LowCount=0;
+ return(true);
+ }
+ else
+ if (Model->FoundState==NULL)
+ return(false);
+ Model->PrevSuccess=0;
+ i=NumStats-1;
+ while ((HiCnt += (++p)->Freq) <= count)
+ if (--i == 0)
+ {
+ Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol];
+ Model->Coder.SubRange.LowCount=HiCnt;
+ Model->CharMask[p->Symbol]=Model->EscCount;
+ i=(Model->NumMasked=NumStats)-1;
+ Model->FoundState=NULL;
+ do
+ {
+ Model->CharMask[(--p)->Symbol]=Model->EscCount;
+ } while ( --i );
+ Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
+ return(true);
+ }
+ Model->Coder.SubRange.LowCount=(Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
+ update1(Model,p);
+ return(true);
+}
+
+
+inline void RARPPM_CONTEXT::update2(ModelPPM *Model,RARPPM_STATE* p)
+{
+ (Model->FoundState=p)->Freq += 4;
+ U.SummFreq += 4;
+ if (p->Freq > MAX_FREQ)
+ rescale(Model);
+ Model->EscCount++;
+ Model->RunLength=Model->InitRL;
+}
+
+
+inline RARPPM_SEE2_CONTEXT* RARPPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff)
+{
+ RARPPM_SEE2_CONTEXT* psee2c;
+ if (NumStats != 256)
+ {
+ psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+
+ (Diff < Suffix->NumStats-NumStats)+
+ 2*(U.SummFreq < 11*NumStats)+4*(Model->NumMasked > Diff)+
+ Model->HiBitsFlag;
+ Model->Coder.SubRange.scale=psee2c->getMean();
+ }
+ else
+ {
+ psee2c=&Model->DummySEE2Cont;
+ Model->Coder.SubRange.scale=1;
+ }
+ return psee2c;
+}
+
+
+
+
+inline bool RARPPM_CONTEXT::decodeSymbol2(ModelPPM *Model)
+{
+ int count, HiCnt, i=NumStats-Model->NumMasked;
+ RARPPM_SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i);
+ RARPPM_STATE* ps[256], ** pps=ps, * p=U.Stats-1;
+ HiCnt=0;
+ do
+ {
+ do
+ {
+ p++;
+ } while (Model->CharMask[p->Symbol] == Model->EscCount);
+ HiCnt += p->Freq;
+ *pps++ = p;
+ } while ( --i );
+ Model->Coder.SubRange.scale += HiCnt;
+ count=Model->Coder.GetCurrentCount();
+ if (count>=(int)Model->Coder.SubRange.scale)
+ return(false);
+ p=*(pps=ps);
+ if (count < HiCnt)
+ {
+ HiCnt=0;
+ while ((HiCnt += p->Freq) <= count)
+ p=*++pps;
+ Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq;
+ psee2c->update();
+ update2(Model,p);
+ }
+ else
+ {
+ Model->Coder.SubRange.LowCount=HiCnt;
+ Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale;
+ i=NumStats-Model->NumMasked;
+ pps--;
+ do
+ {
+ Model->CharMask[(*++pps)->Symbol]=Model->EscCount;
+ } while ( --i );
+ psee2c->Summ += Model->Coder.SubRange.scale;
+ Model->NumMasked = NumStats;
+ }
+ return(true);
+}
+
+
+inline void ModelPPM::ClearMask()
+{
+ EscCount=1;
+ memset(CharMask,0,sizeof(CharMask));
+}
+
+
+
+
+// reset PPM variables after data error allowing safe resuming
+// of further data processing
+void ModelPPM::CleanUp()
+{
+ SubAlloc.StopSubAllocator();
+ SubAlloc.StartSubAllocator(1);
+ StartModelRare(2);
+}
+
+
+bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar)
+{
+ int MaxOrder=UnpackRead->GetChar();
+ bool Reset=(MaxOrder & 0x20)!=0;
+
+ int MaxMB;
+ if (Reset)
+ MaxMB=UnpackRead->GetChar();
+ else
+ if (SubAlloc.GetAllocatedMemory()==0)
+ return(false);
+ if (MaxOrder & 0x40)
+ EscChar=UnpackRead->GetChar();
+ Coder.InitDecoder(UnpackRead);
+ if (Reset)
+ {
+ MaxOrder=(MaxOrder & 0x1f)+1;
+ if (MaxOrder>16)
+ MaxOrder=16+(MaxOrder-16)*3;
+ if (MaxOrder==1)
+ {
+ SubAlloc.StopSubAllocator();
+ return(false);
+ }
+ SubAlloc.StartSubAllocator(MaxMB+1);
+ StartModelRare(MaxOrder);
+ }
+ return(MinContext!=NULL);
+}
+
+
+int ModelPPM::DecodeChar()
+{
+ if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
+ return(-1);
+ if (MinContext->NumStats != 1)
+ {
+ if ((byte*)MinContext->U.Stats <= SubAlloc.pText || (byte*)MinContext->U.Stats>SubAlloc.HeapEnd)
+ return(-1);
+ if (!MinContext->decodeSymbol1(this))
+ return(-1);
+ }
+ else
+ MinContext->decodeBinSymbol(this);
+ Coder.Decode();
+ while ( !FoundState )
+ {
+ ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
+ do
+ {
+ OrderFall++;
+ MinContext=MinContext->Suffix;
+ if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd)
+ return(-1);
+ } while (MinContext->NumStats == NumMasked);
+ if (!MinContext->decodeSymbol2(this))
+ return(-1);
+ Coder.Decode();
+ }
+ int Symbol=FoundState->Symbol;
+ if (!OrderFall && (byte*) FoundState->Successor > SubAlloc.pText)
+ MinContext=MaxContext=FoundState->Successor;
+ else
+ {
+ UpdateModel();
+ if (EscCount == 0)
+ ClearMask();
+ }
+ ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead);
+ return(Symbol);
+}
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/model.hpp b/desmume/src/windows/File_Extractor/unrar/model.hpp
index b4716d12a..52abc89b3 100644
--- a/desmume/src/windows/File_Extractor/unrar/model.hpp
+++ b/desmume/src/windows/File_Extractor/unrar/model.hpp
@@ -1,133 +1,122 @@
-#ifndef _RAR_PPMMODEL_
-#define _RAR_PPMMODEL_
-
-#include "coder.hpp"
-#include "suballoc.hpp"
-
-const int MAX_O=64; /* maximum allowed model order */
-
-const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
- INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
-
-#ifndef STRICT_ALIGNMENT_REQUIRED
-#pragma pack(1)
-#endif
-
-struct SEE2_CONTEXT
-{ // SEE-contexts for PPM-contexts with masked symbols
- ushort Summ;
- byte Shift, Count;
- void init(int InitVal)
- {
- Summ=InitVal << (Shift=PERIOD_BITS-4);
- Count=4;
- }
- uint getMean()
- {
- uint RetVal=SHORT16(Summ) >> Shift;
- Summ -= RetVal;
- return RetVal+(RetVal == 0);
- }
- void update()
- {
- if (Shift < PERIOD_BITS && --Count == 0)
- {
- Summ += Summ;
- Count=3 << Shift++;
- }
- }
-};
-
-
-class ModelPPM;
-struct PPM_CONTEXT;
-
-struct STATE
-{
- byte Symbol;
- byte Freq;
- PPM_CONTEXT* Successor;
-};
-
-struct FreqData
-{
- ushort SummFreq;
- STATE _PACK_ATTR * Stats;
-};
-
-struct PPM_CONTEXT
-{
- ushort NumStats;
- union
- {
- FreqData U;
- STATE OneState;
- };
-
- PPM_CONTEXT* Suffix;
- inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder:
- inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context
- inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix
- inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor
- inline bool decodeSymbol1(ModelPPM *Model); // other orders:
- inline bool decodeSymbol2(ModelPPM *Model); // BCD context
- inline void update1(ModelPPM *Model,STATE* p); // CD suffix
- inline void update2(ModelPPM *Model,STATE* p); // BCDE successor
- void rescale(ModelPPM *Model);
- inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState);
- inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
-};
-
-#ifndef STRICT_ALIGNMENT_REQUIRED
-#ifdef _AIX
-#pragma pack(pop)
-#else
-#pragma pack()
-#endif
-#endif
-
-const uint UNIT_SIZE=Max(sizeof(PPM_CONTEXT),sizeof(RAR_MEM_BLK));
-const uint FIXED_UNIT_SIZE=12;
-
-/*
-inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext):
- NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; }
-inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {}
-*/
-
-template
-inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; }
-
-
-class ModelPPM
-{
- private:
- friend struct PPM_CONTEXT;
-
- /*_PACK_ATTR*/ SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
-
- struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext;
- STATE* FoundState; // found next state transition
- int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
- byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
- byte EscCount, PrevSuccess, HiBitsFlag;
- ushort BinSumm[128][64]; // binary SEE-contexts
-
- RangeCoder Coder;
- SubAllocator SubAlloc;
-
- void RestartModelRare();
- void StartModelRare(int MaxOrder);
- inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1);
-
- inline void UpdateModel();
- inline void ClearMask();
- friend class Unpack;
- public:
- ModelPPM();
- void CleanUp(); // reset PPM variables after data error
- bool DecodeInit(Unpack *UnpackRead,int &EscChar);
- int DecodeChar();
-};
-
-#endif
+#ifndef _RAR_PPMMODEL_
+#define _RAR_PPMMODEL_
+
+#include "coder.hpp"
+#include "suballoc.hpp"
+
+#ifdef ALLOW_MISALIGNED
+#pragma pack(1)
+#endif
+
+struct RARPPM_DEF
+{
+ static const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS,
+ INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124;
+};
+
+struct RARPPM_SEE2_CONTEXT : RARPPM_DEF
+{ // SEE-contexts for PPM-contexts with masked symbols
+ ushort Summ;
+ byte Shift, Count;
+ void init(int InitVal)
+ {
+ Summ=InitVal << (Shift=PERIOD_BITS-4);
+ Count=4;
+ }
+ uint getMean()
+ {
+ uint RetVal=GET_SHORT16(Summ) >> Shift;
+ Summ -= RetVal;
+ return RetVal+(RetVal == 0);
+ }
+ void update()
+ {
+ if (Shift < PERIOD_BITS && --Count == 0)
+ {
+ Summ += Summ;
+ Count=3 << Shift++;
+ }
+ }
+};
+
+
+class ModelPPM;
+struct RARPPM_CONTEXT;
+
+struct RARPPM_STATE
+{
+ byte Symbol;
+ byte Freq;
+ RARPPM_CONTEXT* Successor;
+};
+
+
+struct RARPPM_CONTEXT : RARPPM_DEF
+{
+ ushort NumStats;
+
+ struct FreqData
+ {
+ ushort SummFreq;
+ RARPPM_STATE RARPPM_PACK_ATTR * Stats;
+ };
+
+ union
+ {
+ FreqData U;
+ RARPPM_STATE OneState;
+ };
+
+ RARPPM_CONTEXT* Suffix;
+ inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder:
+ inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context
+ inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix
+ inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor
+ inline bool decodeSymbol1(ModelPPM *Model); // other orders:
+ inline bool decodeSymbol2(ModelPPM *Model); // BCD context
+ inline void update1(ModelPPM *Model,RARPPM_STATE* p); // CD suffix
+ inline void update2(ModelPPM *Model,RARPPM_STATE* p); // BCDE successor
+ void rescale(ModelPPM *Model);
+ inline RARPPM_CONTEXT* createChild(ModelPPM *Model,RARPPM_STATE* pStats,RARPPM_STATE& FirstState);
+ inline RARPPM_SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff);
+};
+
+#ifdef ALLOW_MISALIGNED
+#ifdef _AIX
+#pragma pack(pop)
+#else
+#pragma pack()
+#endif
+#endif
+
+class ModelPPM : RARPPM_DEF
+{
+ private:
+ friend struct RARPPM_CONTEXT;
+
+ RARPPM_SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont;
+
+ struct RARPPM_CONTEXT *MinContext, *MedContext, *MaxContext;
+ RARPPM_STATE* FoundState; // found next state transition
+ int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL;
+ byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256];
+ byte EscCount, PrevSuccess, HiBitsFlag;
+ ushort BinSumm[128][64]; // binary SEE-contexts
+
+ RangeCoder Coder;
+ SubAllocator SubAlloc;
+
+ void RestartModelRare();
+ void StartModelRare(int MaxOrder);
+ inline RARPPM_CONTEXT* CreateSuccessors(bool Skip,RARPPM_STATE* p1);
+
+ inline void UpdateModel();
+ inline void ClearMask();
+ public:
+ ModelPPM();
+ void CleanUp(); // reset PPM variables after data error
+ bool DecodeInit(Unpack *UnpackRead,int &EscChar);
+ int DecodeChar();
+};
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/pathfn.cpp b/desmume/src/windows/File_Extractor/unrar/pathfn.cpp
new file mode 100644
index 000000000..7c254a560
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/pathfn.cpp
@@ -0,0 +1,56 @@
+#include "rar.hpp"
+
+wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize)
+{
+ if (NameW!=NULL && *NameW!=0)
+ {
+ if (DestW!=NameW)
+ my_wcsncpy(DestW,NameW,DestSize);
+ }
+ else
+ if (Name!=NULL)
+ CharToWide(Name,DestW,DestSize);
+ else
+ *DestW=0;
+
+ // Ensure that we return a zero terminate string for security reasons.
+ if (DestSize>0)
+ DestW[DestSize-1]=0;
+
+ return(DestW);
+}
+
+void UnixSlashToDos(const char *SrcName, char *DestName, size_t MaxLength)
+{
+ size_t Copied = 0;
+ for (; Copied
#include
#include
#include
@@ -21,7 +22,7 @@
// These names are too generic and might clash (or have already, hmpf)
#define Array Rar_Array
#define uint32 rar_uint32
-#define sint32 rar_sint32
+#define int32 rar_int32
#define Unpack Rar_Unpack
#define Archive Rar_Archive
#define RawRead Rar_RawRead
@@ -73,6 +74,8 @@ struct Rar_Allocator
};
//// os.hpp
+#define FALSE 0
+#define TRUE 1
#undef STRICT_ALIGNMENT_REQUIRED
#undef LITTLE_ENDIAN
#define NM 1024
@@ -92,7 +95,7 @@ struct Rar_Allocator
//// rartypes.hpp
#if INT_MAX == 0x7FFFFFFF && UINT_MAX == 0xFFFFFFFF
typedef unsigned int uint32; //32 bits exactly
- typedef int sint32; //signed 32 bits exactly
+ typedef int int32; //signed 32 bits exactly
#define PRESENT_INT32
#endif
@@ -100,36 +103,37 @@ typedef unsigned char byte; //8 bits
typedef unsigned short ushort; //preferably 16 bits, but can be more
typedef unsigned int uint; //32 bits or more
-typedef wchar_t wchar;
+typedef blargg_wchar_t wchar;
-#define SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
-#define UINT32(x) (sizeof(uint )==4 ? (uint )(x):((x)&0xffffffff))
+#define GET_SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff))
+#define GET_UINT32(x) (sizeof(uint )==4 ? (uint )(x):((x)&0xffffffff))
//// rardefs.hpp
#define Min(x,y) (((x)<(y)) ? (x):(y))
#define Max(x,y) (((x)>(y)) ? (x):(y))
+#define ALIGN_VALUE(v,a) (size_t(v) + ( (~size_t(v) + 1) & (a - 1) ) )
+#define ASIZE(x) (sizeof(x)/sizeof(x[0]))
//// int64.hpp
-typedef unrar_long_long Int64;
+typedef unrar_long_long int64;
+typedef unrar_ulong_long uint64;
#define int64to32(x) ((uint)(x))
-#define int32to64(high,low) ((((Int64)(high))<<31<<1)+(low))
+#define int32to64(high,low) ((((int64)(high))<<31<<1)+(low))
#define is64plus(x) (x>=0)
#define INT64MAX int32to64(0x7fffffff,0)
+#define INT64NDF int32to64(0x7fffffff,0x7fffffff)
//// crc.hpp
-extern uint CRCTab[256];
-void InitCRC();
-uint CRC(uint StartCRC,const void *Addr,size_t Size);
-ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size);
+extern uint crc_tables[8][256];
+void InitCRCTables();
+uint CRC32(uint StartCRC,const void *Addr,size_t Size);
+ushort Checksum14(ushort StartCRC,const void *Addr,size_t Size);
-//// rartime.hpp
-struct RarTime
-{
- unsigned time;
- void SetDos(uint DosTime) { time = DosTime; }
-};
+#define SHA256_DIGEST_SIZE 32
+#include "blake2s.hpp"
+#include "hash.hpp"
//// rdwrfn.hpp
class ComprDataIO
@@ -141,30 +145,47 @@ public:
void* user_read_data;
void* user_write_data;
unrar_err_t write_error; // once write error occurs, no more writes are made
- Int64 Tell_;
+ int64 Tell_;
bool OldFormat;
private:
- Int64 UnpPackedSize;
+ int64 UnpPackedSize;
bool SkipUnpCRC;
public:
int UnpRead(byte *Addr,uint Count);
void UnpWrite(byte *Addr,uint Count);
void SetSkipUnpCRC( bool b ) { SkipUnpCRC = b; }
- void SetPackedSizeToRead( Int64 n ) { UnpPackedSize = n; }
+ void SetPackedSizeToRead( int64 n ) { UnpPackedSize = n; }
uint UnpFileCRC;
- void Seek(Int64 Offset, int Method = 0 ) { (void)Method; Tell_ = Offset; }
- Int64 Tell() { return Tell_; }
+ void Seek(int64 Offset, int Method = 0 ) { (void)Method; Tell_ = Offset; }
+ int64 Tell() { return Tell_; }
int Read( void* p, int n );
+
+ DataHash PackedDataHash; // Packed write and unpack read hash.
+ DataHash PackHash; // Pack read hash.
+ DataHash UnpHash; // Unpack write hash.
};
+//// secpassword.hpp
+void cleandata(void *data,size_t size);
+
+//// pathfn.hpp
+wchar* GetWideName(const char *Name,const wchar *NameW,wchar *DestW,size_t DestSize);
+void UnixSlashToDos(const char *SrcName, char *DestName, size_t MaxLength);
+void DosSlashToUnix(const char *SrcName, char *DestName, size_t MaxLength);
+void UnixSlashToDos(const wchar *SrcName, wchar *DestName, size_t MaxLength);
+void DosSlashToUnix(const wchar *SrcName, wchar *DestName, size_t MaxLength);
+
//// rar.hpp
class Unpack;
#include "array.hpp"
+#include "unicode.hpp"
+#include "timefn.hpp"
#include "headers.hpp"
+#include "headers5.hpp"
#include "getbits.hpp"
#include "archive.hpp"
#include "rawread.hpp"
@@ -172,8 +193,27 @@ class Unpack;
#include "compress.hpp"
#include "rarvm.hpp"
#include "model.hpp"
+#include "strfn.hpp"
#include "unpack.hpp"
+//// savepos.hpp
+class SaveFilePos
+{
+private:
+ File *SaveFile;
+ int64 SavePos;
+public:
+ SaveFilePos(File &Src)
+ {
+ SaveFile=&Src;
+ SavePos=Src.Tell();
+ }
+ ~SaveFilePos()
+ {
+ SaveFile->Seek(SavePos,SEEK_SET);
+ }
+};
+
//// extract.hpp
/** RAR archive */
struct unrar_t
@@ -195,7 +235,7 @@ struct unrar_t
unrar_t();
~unrar_t();
- void UnstoreFile( Int64 );
+ void UnstoreFile( int64 );
unrar_err_t ExtractCurrentFile( bool SkipSolid = false, bool check_compatibility_only = false );
void update_first_file_pos()
{
diff --git a/desmume/src/windows/File_Extractor/unrar/rarvm.cpp b/desmume/src/windows/File_Extractor/unrar/rarvm.cpp
index aec43e4e6..5afd8b635 100644
--- a/desmume/src/windows/File_Extractor/unrar/rarvm.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/rarvm.cpp
@@ -8,6 +8,7 @@
#define VM_FS ((unsigned) VM_FS)
RarVM::RarVM()
+:BitInput(true)
{
Mem=NULL;
}
@@ -55,24 +56,24 @@ inline uint RarVM::GetValue(bool ByteMode,uint *Addr)
}
else
{
-#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT)
+#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED)
if (IS_VM_MEM(Addr))
{
byte *B=(byte *)Addr;
- return UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
+ return GET_UINT32((uint)B[0]|((uint)B[1]<<8)|((uint)B[2]<<16)|((uint)B[3]<<24));
}
else
- return UINT32(*Addr);
+ return GET_UINT32(*Addr);
#else
- return UINT32(*Addr);
+ return GET_UINT32(*Addr);
#endif
}
}
-#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT)
-#define GET_VALUE(ByteMode,Addr) GetValue(ByteMode,(uint *)Addr)
+#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED)
+ #define GET_VALUE(ByteMode,Addr) GetValue(ByteMode,(uint *)Addr)
#else
- #define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):UINT32(*(uint *)(Addr)))
+ #define GET_VALUE(ByteMode,Addr) ((ByteMode) ? (*(byte *)(Addr)):GET_UINT32(*(uint *)(Addr)))
#endif
@@ -91,7 +92,7 @@ inline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value)
}
else
{
-#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
+#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
if (IS_VM_MEM(Addr))
{
((byte *)Addr)[0]=(byte)Value;
@@ -107,16 +108,16 @@ inline void RarVM::SetValue(bool ByteMode,uint *Addr,uint Value)
}
}
-#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
-#define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint *)Addr,Value)
+#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
+ #define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint *)Addr,Value)
#else
- #define SET_VALUE(ByteMode,Addr,Value) ((ByteMode) ? (*(byte *)(Addr)=(Value)):(*(uint32 *)(Addr)=((uint32)(Value))))
+ #define SET_VALUE(ByteMode,Addr,Value) ((ByteMode) ? (*(byte *)(Addr)=((byte)(Value))):(*(uint32 *)(Addr)=((uint32)(Value))))
#endif
void RarVM::SetLowEndianValue(uint *Addr,uint Value)
{
-#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32)
+#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
((byte *)Addr)[0]=(byte)Value;
((byte *)Addr)[1]=(byte)(Value>>8);
((byte *)Addr)[2]=(byte)(Value>>16);
@@ -139,10 +140,10 @@ inline uint* RarVM::GetOperand(VM_PreparedOperand *CmdOp)
void RarVM::Execute(VM_PreparedProgram *Prg)
{
memcpy(R,Prg->InitR,sizeof(Prg->InitR));
- unsigned int GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE);
+ size_t GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE);
if (GlobalSize)
memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize);
- unsigned int StaticSize=Min(Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize);
+ size_t StaticSize=Min(Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize);
if (StaticSize)
memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize);
@@ -150,8 +151,11 @@ void RarVM::Execute(VM_PreparedProgram *Prg)
Flags=0;
VM_PreparedCommand *PreparedCode=Prg->AltCmd ? Prg->AltCmd:&Prg->Cmd[0];
- if (!ExecuteCode(PreparedCode,Prg->CmdCount))
- PreparedCode[0].OpCode=VM_RET;
+ if (Prg->CmdCount>0 && !ExecuteCode(PreparedCode,Prg->CmdCount))
+ {
+ // Invalid VM program. Let's replace it with 'return' command.
+ PreparedCode[0].OpCode=VM_RET;
+ }
uint NewBlockPos=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20])&VM_MEMMASK;
uint NewBlockSize=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c])&VM_MEMMASK;
if (NewBlockPos+NewBlockSize>=VM_MEMSIZE)
@@ -185,7 +189,7 @@ Note:
return(false); \
Cmd=PreparedCode+(IP);
-bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
+bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize)
{
int MaxOpCount=25000000;
VM_PreparedCommand *Cmd=PreparedCode;
@@ -213,7 +217,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
case VM_CMP:
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
- uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
+ uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
}
break;
@@ -221,14 +225,14 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
case VM_CMPB:
{
uint Value1=GET_VALUE(true,Op1);
- uint Result=UINT32(Value1-GET_VALUE(true,Op2));
+ uint Result=GET_UINT32(Value1-GET_VALUE(true,Op2));
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
}
break;
case VM_CMPD:
{
uint Value1=GET_VALUE(false,Op1);
- uint Result=UINT32(Value1-GET_VALUE(false,Op2));
+ uint Result=GET_UINT32(Value1-GET_VALUE(false,Op2));
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
}
break;
@@ -236,7 +240,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
case VM_ADD:
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
- uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2));
+ uint Result=GET_UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2));
if (Cmd->ByteMode)
{
Result&=0xff;
@@ -258,7 +262,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
case VM_SUB:
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
- uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
+ uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2));
Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS);
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
@@ -287,7 +291,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
break;
case VM_INC:
{
- uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1);
+ uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1);
if (Cmd->ByteMode)
Result&=0xff;
SET_VALUE(Cmd->ByteMode,Op1,Result);
@@ -304,7 +308,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
#endif
case VM_DEC:
{
- uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1);
+ uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1);
SET_VALUE(Cmd->ByteMode,Op1,Result);
Flags=Result==0 ? VM_FZ:Result&VM_FS;
}
@@ -322,28 +326,28 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
continue;
case VM_XOR:
{
- uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2));
+ uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2));
Flags=Result==0 ? VM_FZ:Result&VM_FS;
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
case VM_AND:
{
- uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
+ uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
Flags=Result==0 ? VM_FZ:Result&VM_FS;
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
case VM_OR:
{
- uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2));
+ uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2));
Flags=Result==0 ? VM_FZ:Result&VM_FS;
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
case VM_TEST:
{
- uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
+ uint Result=GET_UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2));
Flags=Result==0 ? VM_FZ:Result&VM_FS;
}
break;
@@ -399,7 +403,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
break;
case VM_CALL:
R[7]-=4;
- SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Cmd-PreparedCode+1);
+ SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],(uint)(Cmd-PreparedCode+1));
SET_IP(GET_VALUE(false,Op1));
continue;
case VM_NOT:
@@ -409,7 +413,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
- uint Result=UINT32(Value1<ByteMode,Op1,Result);
}
@@ -418,7 +422,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
- uint Result=UINT32(Value1>>Value2);
+ uint Result=GET_UINT32(Value1>>Value2);
Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC);
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
@@ -427,24 +431,26 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
uint Value2=GET_VALUE(Cmd->ByteMode,Op2);
- uint Result=UINT32(((int)Value1)>>Value2);
+ uint Result=GET_UINT32(((int)Value1)>>Value2);
Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC);
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
case VM_NEG:
{
- uint Result=UINT32(-GET_VALUE(Cmd->ByteMode,Op1));
+ // We use "0-value" expression to suppress "unary minus to unsigned"
+ // compiler warning.
+ uint Result=GET_UINT32(0-GET_VALUE(Cmd->ByteMode,Op1));
Flags=Result==0 ? VM_FZ:VM_FC|(Result&VM_FS);
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
#ifdef VM_OPTIMIZE
case VM_NEGB:
- SET_VALUE(true,Op1,-GET_VALUE(true,Op1));
+ SET_VALUE(true,Op1,0-GET_VALUE(true,Op1));
break;
case VM_NEGD:
- SET_VALUE(false,Op1,-GET_VALUE(false,Op1));
+ SET_VALUE(false,Op1,0-GET_VALUE(false,Op1));
break;
#endif
case VM_PUSHA:
@@ -503,10 +509,10 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
uint FC=(Flags&VM_FC);
- uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC);
+ uint Result=GET_UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC);
if (Cmd->ByteMode)
Result&=0xff;
- Flags=(ResultByteMode,Op1,Result);
}
break;
@@ -514,10 +520,10 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
{
uint Value1=GET_VALUE(Cmd->ByteMode,Op1);
uint FC=(Flags&VM_FC);
- uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC);
+ uint Result=GET_UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC);
if (Cmd->ByteMode)
Result&=0xff;
- Flags=(Result>Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS));
+ Flags=(Result>Value1 || (Result==Value1 && FC))|(Result==0 ? VM_FZ:(Result&VM_FS));
SET_VALUE(Cmd->ByteMode,Op1,Result);
}
break;
@@ -531,7 +537,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
#ifdef VM_STANDARDFILTERS
case VM_STANDARD:
ExecuteStandardFilter((VM_StandardFilters)Cmd->Op1.Data);
- break;
+ return true;
#endif
case VM_PRINT:
break;
@@ -544,7 +550,7 @@ bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize)
-void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
+void RarVM::Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg)
{
InitBitInput();
memcpy(InBuf,Code,Min(CodeSize,BitInput::MAX_SIZE));
@@ -552,7 +558,7 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
// Calculate the single byte XOR checksum to check validity of VM code.
byte XorSum=0;
{
- for (int I=1;IOp2.Addr=&CurCmd->Op2.Data;
CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE;
CodeSize=0;
+ return;
}
#endif
uint DataFlag=fgetbits();
@@ -583,8 +590,8 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
if (DataFlag&0x8000)
{
- int DataSize=ReadData(*this)+1;
- for (int I=0;InAddrStaticData.Add(1);
Prg->StaticData[I]=fgetbits()>>8;
@@ -592,7 +599,7 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
}
}
- while (InAddrCmd.Add(1);
VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount];
@@ -609,7 +616,7 @@ void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg)
}
if (VM_CmdFlags[CurCmd->OpCode] & VMCF_BYTEMODE)
{
- CurCmd->ByteMode=fgetbits()>>15;
+ CurCmd->ByteMode=(fgetbits()>>15)!=0;
faddbits(1);
}
else
@@ -773,7 +780,7 @@ uint RarVM::ReadData(BitInput &Inp)
}
-void RarVM::SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize)
+void RarVM::SetMemory(size_t Pos,byte *Data,size_t DataSize)
{
if (PosCmd[0];
- int CodeSize=Prg->CmdCount;
+ uint CodeSize=Prg->CmdCount;
- for (int I=0;IOpCode=Cmd->ByteMode ? VM_CMPB:VM_CMPD;
continue;
+
+ default: break;
}
if ((VM_CmdFlags[Cmd->OpCode] & VMCF_CHFLAGS)==0)
continue;
@@ -809,7 +818,7 @@ void RarVM::Optimize(VM_PreparedProgram *Prg)
// the current command with faster version which does not need to
// modify flags.
bool FlagsRequired=false;
- for (int J=I+1;JOpCode=Cmd->ByteMode ? VM_NEGB:VM_NEGD;
continue;
+
+ default: break;
}
}
}
@@ -850,7 +861,7 @@ void RarVM::Optimize(VM_PreparedProgram *Prg)
#ifdef VM_STANDARDFILTERS
-VM_StandardFilters RarVM::IsStandardFilter(byte *Code,int CodeSize)
+VM_StandardFilters RarVM::IsStandardFilter(byte *Code,uint CodeSize)
{
static const
struct StandardFilterSignature
@@ -871,12 +882,10 @@ VM_StandardFilters RarVM::IsStandardFilter(byte *Code,int CodeSize)
149, 0x1c2c5dc8, VMSF_RGB,
},{
216, 0xbc85e701, VMSF_AUDIO,
- },{
- 40, 0x46b9c560, VMSF_UPCASE
}
};
- uint CodeCRC=CRC(0xffffffff,Code,CodeSize)^0xffffffff;
- for (int I=0;I=VM_GLOBALMEMADDR || DataSize<4)
+ if ((uint)DataSize>=VM_GLOBALMEMADDR || DataSize<4)
break;
const int FileSize=0x1000000;
@@ -906,8 +915,8 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
if (CurByte==0xe8 || CurByte==CmpByte2)
{
#ifdef PRESENT_INT32
- sint32 Offset=CurPos+FileOffset;
- sint32 Addr=GET_VALUE(false,Data);
+ int32 Offset=CurPos+FileOffset;
+ int32 Addr=GET_VALUE(false,Data);
if (Addr<0)
{
if (Addr+Offset>=0)
@@ -940,7 +949,7 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
int DataSize=R[4];
uint FileOffset=R[6];
- if (DataSize>=VM_GLOBALMEMADDR || DataSize<21)
+ if ((uint)DataSize>=VM_GLOBALMEMADDR || DataSize<21)
break;
int CurPos=0;
@@ -978,7 +987,7 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
{
int DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
- if (DataSize>=VM_GLOBALMEMADDR/2)
+ if ((uint)DataSize>=VM_GLOBALMEMADDR/2)
break;
// Bytes from same channels are grouped to continual data blocks,
@@ -997,21 +1006,21 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
byte *SrcData=Mem,*DestData=SrcData+DataSize;
const int Channels=3;
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
- if (DataSize>=VM_GLOBALMEMADDR/2 || PosR<0)
+ if ((uint)DataSize>=VM_GLOBALMEMADDR/2 || Width<0 || PosR<0)
break;
for (int CurChannel=0;CurChannel=3)
{
byte *UpperData=DestData+UpperPos;
- unsigned int UpperByte=*UpperData;
- unsigned int UpperLeftByte=*(UpperData-3);
+ uint UpperByte=*UpperData;
+ uint UpperLeftByte=*(UpperData-3);
Predicted=PrevByte+UpperByte-UpperLeftByte;
int pa=abs((int)(Predicted-PrevByte));
int pb=abs((int)(Predicted-UpperByte));
@@ -1042,11 +1051,11 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
int DataSize=R[4],Channels=R[0];
byte *SrcData=Mem,*DestData=SrcData+DataSize;
SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
- if (DataSize>=VM_GLOBALMEMADDR/2)
+ if ((uint)DataSize>=VM_GLOBALMEMADDR/2)
break;
for (int CurChannel=0;CurChannel>3) & 0xff;
- unsigned int CurByte=*(SrcData++);
+ uint CurByte=*(SrcData++);
Predicted-=CurByte;
DestData[I]=Predicted;
@@ -1079,7 +1088,7 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
if ((ByteCount & 0x1f)==0)
{
- unsigned int MinDif=Dif[0],NumMinDif=0;
+ uint MinDif=Dif[0],NumMinDif=0;
Dif[0]=0;
for (int J=1;J=VM_GLOBALMEMADDR/2)
- break;
- while (SrcPos>(32-BitCount);
+ uint AndMask=0xffffffff>>(32-BitCount);
AndMask=~(AndMask< Cmd;
VM_PreparedCommand *AltCmd;
@@ -71,7 +75,7 @@ struct VM_PreparedProgram
uint InitR[7];
byte *FilteredData;
- unsigned int FilteredDataSize;
+ uint FilteredDataSize;
};
class RarVM:private BitInput
@@ -84,13 +88,12 @@ class RarVM:private BitInput
#ifdef VM_OPTIMIZE
void Optimize(VM_PreparedProgram *Prg);
#endif
- bool ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize);
+ bool ExecuteCode(VM_PreparedCommand *PreparedCode,uint CodeSize);
#ifdef VM_STANDARDFILTERS
- VM_StandardFilters IsStandardFilter(byte *Code,int CodeSize);
+ VM_StandardFilters IsStandardFilter(byte *Code,uint CodeSize);
void ExecuteStandardFilter(VM_StandardFilters FilterType);
unsigned int FilterItanium_GetBits(byte *Data,int BitPos,int BitCount);
- void FilterItanium_SetBits(byte *Data,unsigned int BitField,int BitPos,
- int BitCount);
+ void FilterItanium_SetBits(byte *Data,uint BitField,int BitPos,int BitCount);
#endif
byte *Mem;
@@ -102,10 +105,10 @@ class RarVM:private BitInput
void Init();
void handle_mem_error( Rar_Error_Handler& );
friend class Unpack;
- void Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg);
+ void Prepare(byte *Code,uint CodeSize,VM_PreparedProgram *Prg);
void Execute(VM_PreparedProgram *Prg);
void SetLowEndianValue(uint *Addr,uint Value);
- void SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize);
+ void SetMemory(size_t Pos,byte *Data,size_t DataSize);
static uint ReadData(BitInput &Inp);
};
diff --git a/desmume/src/windows/File_Extractor/unrar/rawread.cpp b/desmume/src/windows/File_Extractor/unrar/rawread.cpp
index bd49b8846..2e8df202e 100644
--- a/desmume/src/windows/File_Extractor/unrar/rawread.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/rawread.cpp
@@ -1,10 +1,9 @@
#include "rar.hpp"
-RawRead::RawRead(ComprDataIO *SrcFile) : Data( SrcFile )
+RawRead::RawRead(ComprDataIO *SrcFile)
{
RawRead::SrcFile=SrcFile;
- ReadPos=0;
- DataSize=0;
+ Reset();
}
void RawRead::Reset()
@@ -14,73 +13,147 @@ void RawRead::Reset()
Data.Reset();
}
-void RawRead::Read(int Size)
+size_t RawRead::Read(size_t Size)
{
+ size_t ReadSize=0;
// (removed decryption)
- if (Size!=0)
- {
- Data.Add(Size);
- DataSize+=SrcFile->Read(&Data[DataSize],Size);
- }
+ if (Size!=0)
+ {
+ Data.Add(Size);
+ ReadSize=SrcFile->Read(&Data[DataSize],Size);
+ DataSize+=ReadSize;
+ }
+ return ReadSize;
}
-
-
-void RawRead::Get(byte &Field)
+void RawRead::Read(byte *SrcData,size_t Size)
{
- if (ReadPos2 ? CRC(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2):0xffffffff);
+ uint Low=Get4(),High=Get4();
+ return int32to64(High,Low);
+}
+
+
+uint64 RawRead::GetV()
+{
+ uint64 Result=0;
+ for (uint Shift=0;ReadPos0)
+ memcpy(F,&Data[ReadPos],CopySize);
+ if (Size>CopySize)
+ memset(F+CopySize,0,Size-CopySize);
+ ReadPos+=CopySize;
+ return CopySize;
+}
+
+
+void RawRead::GetW(wchar *Field,size_t Size)
+{
+ if (ReadPos+2*Size-1 Data;
File *SrcFile;
- int DataSize;
- int ReadPos;
- friend class Archive;
+ size_t DataSize;
+ size_t ReadPos;
public:
RawRead(File *SrcFile);
void Reset();
- void Read(int Size);
- void Get(byte &Field);
- void Get(ushort &Field);
- void Get(uint &Field);
- void Get(byte *Field,int Size);
- uint GetCRC(bool ProcessedOnly);
- int Size() {return DataSize;}
- int PaddedSize() {return Data.Size()-DataSize;}
+ size_t Read(size_t Size);
+ void Read(byte *SrcData,size_t Size);
+ byte Get1();
+ ushort Get2();
+ uint Get4();
+ uint64 Get8();
+ uint64 GetV();
+ uint GetVSize(size_t Pos);
+ size_t GetB(void *Field,size_t Size);
+ void GetW(wchar *Field,size_t Size);
+ uint GetCRC15(bool ProcessedOnly);
+ uint GetCRC50();
+ byte* GetDataPtr() {return &Data[0];}
+ size_t Size() {return DataSize;}
+ size_t PaddedSize() {return Data.Size()-DataSize;}
+ size_t DataLeft() {return DataSize-ReadPos;}
+ size_t GetPos() {return ReadPos;}
+ void SetPos(size_t Pos) {ReadPos=Pos;}
+ void Skip(size_t Size) {ReadPos+=Size;}
+ void Rewind() {SetPos(0);}
};
+uint64 RawGetV(const byte *Data,uint &ReadPos,uint DataSize,bool &Overflow);
+
+inline uint RawGet2(const void *Data)
+{
+ byte *D=(byte *)Data;
+ return D[0]+(D[1]<<8);
+}
+
+inline uint RawGet4(const void *Data)
+{
+ byte *D=(byte *)Data;
+#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
+ return D[0]+(D[1]<<8)+(D[2]<<16)+(D[3]<<24);
+#else
+ return GET_UINT32(*(uint32 *)D);
+#endif
+}
+
+inline uint64 RawGet8(const void *Data)
+{
+ byte *D=(byte *)Data;
+ return int32to64(RawGet4(D+4),RawGet4(D));
+}
+
+
+// We need these "put" functions also in UnRAR code. This is why they are
+// in rawread.hpp file even though they are "write" functions.
+inline void RawPut2(uint Field,void *Data)
+{
+ byte *D=(byte *)Data;
+ D[0]=(byte)(Field);
+ D[1]=(byte)(Field>>8);
+}
+
+
+inline void RawPut4(uint Field,void *Data)
+{
+ byte *D=(byte *)Data;
+#if defined(BIG_ENDIAN) || !defined(ALLOW_MISALIGNED) || !defined(PRESENT_INT32)
+ D[0]=(byte)(Field);
+ D[1]=(byte)(Field>>8);
+ D[2]=(byte)(Field>>16);
+ D[3]=(byte)(Field>>24);
+#else
+ *(uint32 *)D=Field;
+#endif
+}
+
+
+inline void RawPut8(uint64 Field,void *Data)
+{
+ byte *D=(byte *)Data;
+ D[0]=(byte)(Field);
+ D[1]=(byte)(Field>>8);
+ D[2]=(byte)(Field>>16);
+ D[3]=(byte)(Field>>24);
+ D[4]=(byte)(Field>>32);
+ D[5]=(byte)(Field>>40);
+ D[6]=(byte)(Field>>48);
+ D[7]=(byte)(Field>>56);
+}
+
#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/readme.txt b/desmume/src/windows/File_Extractor/unrar/readme.txt
index 20e70c772..a1f820af1 100644
--- a/desmume/src/windows/File_Extractor/unrar/readme.txt
+++ b/desmume/src/windows/File_Extractor/unrar/readme.txt
@@ -1,63 +1,50 @@
-
- Portable UnRAR version
-
-
- 1. General
-
- This package includes freeware Unrar C++ source and a few makefiles
- (makefile.bcc, makefile.msc+msc.dep, makefile.unix). Unrar source
- is subset of RAR and generated from RAR source automatically,
- by a small program removing blocks like '#ifndef UNRAR ... #endif'.
- Such method is not perfect and you may find some RAR related
- stuff unnecessary in Unrar, especially in header files.
-
- If you wish to port Unrar to a new platform, you may need to edit
- '#define LITTLE_ENDIAN' in os.hpp and data type definitions
- in rartypes.hpp.
-
- if computer architecture does not allow not aligned data access,
- you need to undefine ALLOW_NOT_ALIGNED_INT and define
- STRICT_ALIGNMENT_REQUIRED in os.h. Note that it will increase memory
- requirements.
-
- If you use Borland C++ makefile (makefile.bcc), you need to define
- BASEPATHCC environment (or makefile) variable containing
- the path to Borland C++ installation.
-
- Makefile.unix contains numerous compiler option sets.
- GCC Linux is selected by default. If you need to compile Unrar
- for other platforms, uncomment corresponding lines.
-
-
- 2. Unrar binaries
-
- If you compiled Unrar for OS, which is not present in "Downloads"
- and "RAR extras" on www.rarlab.com, we will appreciate if you send
- us the compiled executable to place it to our site.
-
-
- 3. Acknowledgements
-
- This source includes parts of code written by the following authors:
-
- Dmitry Shkarin PPMII v.H text compression
- Dmitry Subbotin Carryless rangecoder
- Szymon Stefanek AES encryption
- Brian Gladman AES encryption
- Steve Reid SHA-1 hash function
- Marcus Herbert makefile.unix file
- Tomasz Klim fixes for libunrar.so
- Robert Riebisch makefile.dj and patches for DJGPP
-
-
- 4. Legal stuff
-
- Unrar source may be used in any software to handle RAR archives
- without limitations free of charge, but cannot be used to re-create
- the RAR compression algorithm, which is proprietary. Distribution
- of modified Unrar source in separate form or as a part of other
- software is permitted, provided that it is clearly stated in
- the documentation and source comments that the code may not be used
- to develop a RAR (WinRAR) compatible archiver.
-
- More detailed license text is available in license.txt.
+
+ Portable UnRAR version
+
+
+ 1. General
+
+ This package includes freeware Unrar C++ source and makefile for
+ several Unix compilers.
+
+ Unrar source is subset of RAR and generated from RAR source automatically,
+ by a small program removing blocks like '#ifndef UNRAR ... #endif'.
+ Such method is not perfect and you may find some RAR related stuff
+ unnecessary in Unrar, especially in header files.
+
+ If you wish to port Unrar to a new platform, you may need to edit
+ '#define LITTLE_ENDIAN' in os.hpp and data type definitions
+ in rartypes.hpp.
+
+ if computer architecture does not allow not aligned data access,
+ you need to undefine ALLOW_NOT_ALIGNED_INT and define
+ STRICT_ALIGNMENT_REQUIRED in os.h.
+
+ UnRAR.vcproj and UnRARDll.vcproj are projects for Microsoft Visual C++.
+ UnRARDll.vcproj lets to build unrar.dll library.
+
+
+ 2. Unrar binaries
+
+ If you compiled Unrar for OS, which is not present in "Downloads"
+ and "RAR extras" on www.rarlab.com, we will appreciate if you send
+ us the compiled executable to place it to our site.
+
+
+ 3. Acknowledgements
+
+ This source includes parts of code written by other authors.
+ Please see acknow.txt file for details.
+
+
+ 4. Legal stuff
+
+ Unrar source may be used in any software to handle RAR archives
+ without limitations free of charge, but cannot be used to re-create
+ the RAR compression algorithm, which is proprietary. Distribution
+ of modified Unrar source in separate form or as a part of other
+ software is permitted, provided that it is clearly stated in
+ the documentation and source comments that the code may not be used
+ to develop a RAR (WinRAR) compatible archiver.
+
+ More detailed license text is available in license.txt.
diff --git a/desmume/src/windows/File_Extractor/unrar/secpassword.cpp b/desmume/src/windows/File_Extractor/unrar/secpassword.cpp
new file mode 100644
index 000000000..913d71fae
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/secpassword.cpp
@@ -0,0 +1,18 @@
+#include "rar.hpp"
+
+// When we call memset in end of function to clean local variables
+// for security reason, compiler optimizer can remove such call.
+// So we use our own function for this purpose.
+void cleandata(void *data,size_t size)
+{
+#if defined(_WIN_ALL) && defined(_MSC_VER)
+ SecureZeroMemory(data,size);
+#else
+ // 'volatile' is required. Otherwise optimizers can remove this function
+ // if cleaning local variables, which are not used after that.
+ volatile byte *d = (volatile byte *)data;
+ for (size_t i=0;i
+
+const char *NullToEmpty(const char *Str)
+{
+ return Str==NULL ? "":Str;
+}
+
+static const wchar Empty[] = {0};
+
+const wchar *NullToEmpty(const wchar *Str)
+{
+ return Str==NULL ? Empty:Str;
+}
+
+
+void IntToExt(const char *Src,char *Dest,size_t DestSize)
+{
+#ifdef _WIN_ALL
+ OemToCharBuffA(Src,Dest,(DWORD)DestSize);
+ Dest[DestSize-1]=0;
+#elif defined(_ANDROID)
+ wchar DestW[NM];
+ UnkToWide(Src,DestW,ASIZE(DestW));
+ WideToChar(DestW,Dest,DestSize);
+#else
+ if (Dest!=Src)
+ strncpyz(Dest,Src,DestSize);
+#endif
+}
+
+
+int stricomp(const char *s1,const char *s2)
+{
+#ifdef _WIN_ALL
+ return CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,-1,s2,-1)-2;
+#else
+ while (toupper(*s1)==toupper(*s2))
+ {
+ if (*s1==0)
+ return 0;
+ s1++;
+ s2++;
+ }
+ return s1 < s2 ? -1 : 1;
+#endif
+}
+
+
+int strnicomp(const char *s1,const char *s2,size_t n)
+{
+#ifdef _WIN_ALL
+ // If we specify 'n' exceeding the actual string length, CompareString goes
+ // beyond the trailing zero and compares garbage. So we need to limit 'n'
+ // to real string length.
+ // It is important to use strnlen (or memchr(...,0)) instead of strlen,
+ // because data can be not zero terminated.
+ size_t l1=Min(strnlen(s1,n),n);
+ size_t l2=Min(strnlen(s2,n),n);
+ return CompareStringA(LOCALE_USER_DEFAULT,NORM_IGNORECASE|SORT_STRINGSORT,s1,(int)l1,s2,(int)l2)-2;
+#else
+ if (n==0)
+ return 0;
+ while (toupper(*s1)==toupper(*s2))
+ {
+ if (*s1==0 || --n==0)
+ return 0;
+ s1++;
+ s2++;
+ }
+ return s1 < s2 ? -1 : 1;
+#endif
+}
+
+
+wchar* RemoveEOL(wchar *Str)
+{
+ for (int I=(int)my_wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n' || Str[I]==' ' || Str[I]=='\t');I--)
+ Str[I]=0;
+ return Str;
+}
+
+
+wchar* RemoveLF(wchar *Str)
+{
+ for (int I=(int)my_wcslen(Str)-1;I>=0 && (Str[I]=='\r' || Str[I]=='\n');I--)
+ Str[I]=0;
+ return(Str);
+}
+
+
+unsigned char loctolower(unsigned char ch)
+{
+#ifdef _WIN_ALL
+ // Convert to LPARAM first to avoid a warning in 64 bit mode.
+ return((int)(LPARAM)CharLowerA((LPSTR)ch));
+#else
+ return(tolower(ch));
+#endif
+}
+
+
+unsigned char loctoupper(unsigned char ch)
+{
+#ifdef _WIN_ALL
+ // Convert to LPARAM first to avoid a warning in 64 bit mode.
+ return((int)(LPARAM)CharUpperA((LPSTR)ch));
+#else
+ return(toupper(ch));
+#endif
+}
+
+
+// toupper with English only results if English input is provided.
+// It avoids Turkish (small i) -> (big I with dot) conversion problem.
+// We do not define 'ch' as 'int' to avoid necessity to cast all
+// signed chars passed to this function to unsigned char.
+unsigned char etoupper(unsigned char ch)
+{
+ if (ch=='i')
+ return('I');
+ return(toupper(ch));
+}
+
+
+// Unicode version of etoupper.
+wchar etoupperw(wchar ch)
+{
+ if (ch=='i')
+ return('I');
+#if defined(__APPLE__) || defined(_MSC_VER)
+ return(toupper(ch));
+#else
+ return(toupperw(ch));
+#endif
+}
+
+
+// We do not want to cast every signed char to unsigned when passing to
+// isdigit, so we implement the replacement. Shall work for Unicode too.
+// If chars are signed, conversion from char to int could generate negative
+// values, resulting in undefined behavior in standard isdigit.
+bool IsDigit(int ch)
+{
+ return(ch>='0' && ch<='9');
+}
+
+
+// We do not want to cast every signed char to unsigned when passing to
+// isspace, so we implement the replacement. Shall work for Unicode too.
+// If chars are signed, conversion from char to int could generate negative
+// values, resulting in undefined behavior in standard isspace.
+bool IsSpace(int ch)
+{
+ return(ch==' ' || ch=='\t');
+}
+
+
+// We do not want to cast every signed char to unsigned when passing to
+// isalpha, so we implement the replacement. Shall work for Unicode too.
+// If chars are signed, conversion from char to int could generate negative
+// values, resulting in undefined behavior in standard function.
+bool IsAlpha(int ch)
+{
+ return((ch>='A' && ch<='Z') || (ch>='a' && ch<='z'));
+}
+
+
+
+
+void BinToHex(const byte *Bin,size_t BinSize,char *HexA,wchar *HexW,size_t HexSize)
+{
+ uint A=0,W=0; // ASCII and Unicode hex output positions.
+ for (uint I=0;I> 4;
+ uint Low=Bin[I] & 0xf;
+ uint HighHex=High>9 ? 'a'+High-10:'0'+High;
+ uint LowHex=Low>9 ? 'a'+Low-10:'0'+Low;
+ if (HexA!=NULL && A0)
+ HexA[A]=0;
+ if (HexW!=NULL && HexSize>0)
+ HexW[W]=0;
+}
+
+
+#ifndef SFX_MODULE
+uint GetDigits(uint Number)
+{
+ uint Digits=1;
+ while (Number>=10)
+ {
+ Number/=10;
+ Digits++;
+ }
+ return Digits;
+}
+#endif
+
+
+bool LowAscii(const char *Str)
+{
+ for (int I=0;Str[I]!=0;I++)
+ if ((byte)Str[I]<32 || (byte)Str[I]>127)
+ return false;
+ return true;
+}
+
+
+bool LowAscii(const wchar *Str)
+{
+ for (int I=0;Str[I]!=0;I++)
+ {
+ // We convert wchar_t to uint just in case if some compiler
+ // uses signed wchar_t.
+ if ((uint)Str[I]<32 || (uint)Str[I]>127)
+ return false;
+ }
+ return true;
+}
+
+
+int wcsicompc(const wchar *Str1,const wchar *Str2)
+{
+#if defined(_UNIX) || defined(_MSC_VER)
+ return my_wcscmp(Str1,Str2);
+#else
+ return wcsicomp(Str1,Str2);
+#endif
+}
+
+
+// safe strncpy: copies maxlen-1 max and always returns zero terminated dest
+char* strncpyz(char *dest, const char *src, size_t maxlen)
+{
+ if (maxlen>0)
+ {
+#if _MSC_VER >= 1300
+ strcpy_s(dest,maxlen-1,src);
+#else
+ strncpy(dest,src,maxlen-1);
+#endif
+ dest[maxlen-1]=0;
+ }
+ return dest;
+}
+
+
+// Safe wcsncpy: copies maxlen-1 max and always returns zero terminated dest.
+wchar* wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
+{
+ if (maxlen>0)
+ {
+ my_wcsncpy(dest,src,maxlen-1);
+ dest[maxlen-1]=0;
+}
+ return dest;
+}
+
+
+// Safe strncat: resulting dest length cannot exceed maxlen and dest
+// is always zero terminated. Note that 'maxlen' parameter defines the entire
+// dest buffer size and is not compatible with standard strncat.
+char* strncatz(char* dest, const char* src, size_t maxlen)
+{
+ size_t Length = strlen(dest);
+ if (Length + 1 < maxlen)
+#if _MSC_VER >= 1300
+ strcat_s(dest, maxlen - Length - 1, src);
+#else
+ strncat(dest, src, maxlen - Length - 1);
+#endif
+ return dest;
+}
+
+
+// Safe wcsncat: resulting dest length cannot exceed maxlen and dest
+// is always zero terminated. Note that 'maxlen' parameter defines the entire
+// dest buffer size and is not compatible with standard wcsncat.
+wchar* wcsncatz(wchar* dest, const wchar* src, size_t maxlen)
+{
+ size_t Length = my_wcslen(dest);
+ if (Length + 1 < maxlen)
+ my_wcsncat(dest, src, maxlen - Length - 1);
+ return dest;
+}
+
+
+void itoa(int64 n,char *Str)
+{
+ char NumStr[50];
+ size_t Pos=0;
+
+ do
+ {
+ NumStr[Pos++]=char(n%10)+'0';
+ n=n/10;
+ } while (n!=0);
+
+ for (size_t I=0;I= ASIZE(StrTable))
+ StrNum=0;
+ wchar *Str=StrTable[StrNum];
+ CharToWide(Src,Str,MaxLength);
+ Str[MaxLength-1]=0;
+ return Str;
+}
+
+
+// Parse string containing parameters separated with spaces.
+// Support quote marks. Param can be NULL to return the pointer to next
+// parameter, which can be used to estimate the buffer size for Param.
+const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize)
+{
+ while (IsSpace(*CmdLine))
+ CmdLine++;
+ if (*CmdLine==0)
+ return NULL;
+
+ size_t ParamSize=0;
+ bool Quote=false;
+ while (*CmdLine!=0 && (Quote || !IsSpace(*CmdLine)))
+ {
+ if (*CmdLine=='\"')
+ {
+ if (CmdLine[1]=='\"')
+ {
+ // Insert the quote character instead of two adjoining quote characters.
+ if (Param!=NULL && ParamSizeinsertAt(&s0);
p->Stamp=0xFFFF;
p->NU=Indx2Units[i];
diff --git a/desmume/src/windows/File_Extractor/unrar/suballoc.hpp b/desmume/src/windows/File_Extractor/unrar/suballoc.hpp
index 77440dfae..46852bd69 100644
--- a/desmume/src/windows/File_Extractor/unrar/suballoc.hpp
+++ b/desmume/src/windows/File_Extractor/unrar/suballoc.hpp
@@ -10,21 +10,21 @@
const int N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4;
const int N_INDEXES=N1+N2+N3+N4;
-#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT_REQUIRED)
-#define _PACK_ATTR __attribute__ ((packed))
+#if defined(__GNUC__) && defined(ALLOW_MISALIGNED)
+#define RARPPM_PACK_ATTR __attribute__ ((packed))
#else
-#define _PACK_ATTR
+#define RARPPM_PACK_ATTR
#endif /* defined(__GNUC__) */
-#ifndef STRICT_ALIGNMENT_REQUIRED
+#ifdef ALLOW_MISALIGNED
#pragma pack(1)
#endif
-struct RAR_MEM_BLK
+struct RARPPM_MEM_BLK
{
ushort Stamp, NU;
- RAR_MEM_BLK* next, * prev;
- void insertAt(RAR_MEM_BLK* p)
+ RARPPM_MEM_BLK* next, * prev;
+ void insertAt(RARPPM_MEM_BLK* p)
{
next=(prev=p)->next;
p->next=next->prev=this;
@@ -34,9 +34,9 @@ struct RAR_MEM_BLK
prev->next=next;
next->prev=prev;
}
-} _PACK_ATTR;
+} RARPPM_PACK_ATTR;
-#ifndef STRICT_ALIGNMENT_REQUIRED
+#ifndef ALLOW_MISALIGNED
#ifdef _AIX
#pragma pack(pop)
#else
@@ -60,7 +60,7 @@ class SubAllocator
uint GetUsedMemory();
inline void GlueFreeBlocks();
void* AllocUnitsRare(int indx);
- inline RAR_MEM_BLK* MBPtr(RAR_MEM_BLK *BasePtr,int Items);
+ inline RARPPM_MEM_BLK* MBPtr(RARPPM_MEM_BLK *BasePtr,int Items);
long SubAllocatorSize;
byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount;
diff --git a/desmume/src/windows/File_Extractor/unrar/timefn.cpp b/desmume/src/windows/File_Extractor/unrar/timefn.cpp
new file mode 100644
index 000000000..faeba74ce
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/timefn.cpp
@@ -0,0 +1,257 @@
+#include "rar.hpp"
+
+#ifdef _WIN_ALL
+#include
+RarTime& RarTime::operator =(FILETIME &ft)
+{
+ _ULARGE_INTEGER ul = {ft.dwLowDateTime, ft.dwHighDateTime};
+ itime=ul.QuadPart;
+ return *this;
+}
+
+
+void RarTime::GetWin32(FILETIME *ft)
+{
+ _ULARGE_INTEGER ul;
+ ul.QuadPart=itime;
+ ft->dwLowDateTime=ul.LowPart;
+ ft->dwHighDateTime=ul.HighPart;
+}
+#endif
+
+
+RarTime& RarTime::operator =(time_t ut)
+{
+ uint64 ushift=int32to64(0x19DB1DE,0xD53E8000); // 116444736000000000.
+ itime=uint64(ut)*10000000+ushift;
+ return *this;
+}
+
+
+time_t RarTime::GetUnix()
+{
+ uint64 ushift=int32to64(0x19DB1DE,0xD53E8000); // 116444736000000000.
+ time_t ut=(itime-ushift)/10000000;
+ return ut;
+}
+
+
+void RarTime::GetLocal(RarLocalTime *lt)
+{
+#ifdef _WIN_ALL
+ FILETIME ft;
+ GetWin32(&ft);
+ FILETIME lft;
+
+ // SystemTimeToTzSpecificLocalTime based code produces 1 hour error on XP.
+ FileTimeToLocalFileTime(&ft,&lft);
+
+ SYSTEMTIME st;
+ FileTimeToSystemTime(&lft,&st);
+ lt->Year=st.wYear;
+ lt->Month=st.wMonth;
+ lt->Day=st.wDay;
+ lt->Hour=st.wHour;
+ lt->Minute=st.wMinute;
+ lt->Second=st.wSecond;
+ lt->wDay=st.wDayOfWeek;
+ lt->yDay=lt->Day-1;
+
+ static int mdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
+ for (uint I=1;IMonth && I<=ASIZE(mdays);I++)
+ lt->yDay+=mdays[I-1];
+
+ if (lt->Month>2 && IsLeapYear(lt->Year))
+ lt->yDay++;
+
+ st.wMilliseconds=0;
+ FILETIME zft;
+ SystemTimeToFileTime(&st,&zft);
+
+ // Calculate the time reminder, which is the part of time smaller
+ // than 1 second, represented in 100-nanosecond intervals.
+ lt->Reminder=int32to64(lft.dwHighDateTime,lft.dwLowDateTime)-
+ int32to64(zft.dwHighDateTime,zft.dwLowDateTime);
+#else
+ time_t ut=GetUnix();
+ struct tm *t;
+ t=localtime(&ut);
+
+ lt->Year=t->tm_year+1900;
+ lt->Month=t->tm_mon+1;
+ lt->Day=t->tm_mday;
+ lt->Hour=t->tm_hour;
+ lt->Minute=t->tm_min;
+ lt->Second=t->tm_sec;
+ lt->Reminder=itime % 10000000;
+ lt->wDay=t->tm_wday;
+ lt->yDay=t->tm_yday;
+#endif
+}
+
+
+void RarTime::SetLocal(RarLocalTime *lt)
+{
+#ifdef _WIN_ALL
+ SYSTEMTIME st;
+ st.wYear=lt->Year;
+ st.wMonth=lt->Month;
+ st.wDay=lt->Day;
+ st.wHour=lt->Hour;
+ st.wMinute=lt->Minute;
+ st.wSecond=lt->Second;
+ st.wMilliseconds=0;
+ FILETIME lft;
+ if (SystemTimeToFileTime(&st,&lft))
+ {
+ lft.dwLowDateTime+=lt->Reminder;
+ if (lft.dwLowDateTimeReminder)
+ lft.dwHighDateTime++;
+
+ FILETIME ft;
+
+ // TzSpecificLocalTimeToSystemTime based code produces 1 hour error on XP.
+ LocalFileTimeToFileTime(&lft,&ft);
+
+ *this=ft;
+ }
+ else
+ Reset();
+#else
+ struct tm t;
+
+ t.tm_sec=lt->Second;
+ t.tm_min=lt->Minute;
+ t.tm_hour=lt->Hour;
+ t.tm_mday=lt->Day;
+ t.tm_mon=lt->Month-1;
+ t.tm_year=lt->Year-1900;
+ t.tm_isdst=-1;
+ *this=mktime(&t);
+ itime+=lt->Reminder;
+#endif
+}
+
+
+// Return the stored time as 64-bit number of 100-nanosecond intervals since
+// 01.01.1601. Actually we do not care since which date this time starts from
+// as long as this date is the same for GetRaw and SetRaw. We use the value
+// returned by GetRaw() for time comparisons, for relative operations
+// like SetRaw(GetRaw()-C) and for compact time storage when necessary.
+uint64 RarTime::GetRaw()
+{
+ return itime;
+}
+
+
+void RarTime::SetRaw(uint64 RawTime)
+{
+ itime=RawTime;
+}
+
+
+uint RarTime::GetDos()
+{
+ RarLocalTime lt;
+ GetLocal(<);
+ uint DosTime=(lt.Second/2)|(lt.Minute<<5)|(lt.Hour<<11)|
+ (lt.Day<<16)|(lt.Month<<21)|((lt.Year-1980)<<25);
+ return DosTime;
+}
+
+
+void RarTime::SetDos(uint DosTime)
+{
+ RarLocalTime lt;
+ lt.Second=(DosTime & 0x1f)*2;
+ lt.Minute=(DosTime>>5) & 0x3f;
+ lt.Hour=(DosTime>>11) & 0x1f;
+ lt.Day=(DosTime>>16) & 0x1f;
+ lt.Month=(DosTime>>21) & 0x0f;
+ lt.Year=(DosTime>>25)+1980;
+ lt.Reminder=0;
+ SetLocal(<);
+}
+
+
+#ifndef SFX_MODULE
+void RarTime::SetIsoText(const wchar *TimeText)
+{
+ int Field[6];
+ memset(Field,0,sizeof(Field));
+ for (uint DigitCount=0;*TimeText!=0;TimeText++)
+ if (IsDigit(*TimeText))
+ {
+ int FieldPos=DigitCount<4 ? 0:(DigitCount-4)/2+1;
+ if (FieldPos
+#ifdef _WIN_ALL
+#include
+#endif
+
+struct RarLocalTime
+{
+ uint Year;
+ uint Month;
+ uint Day;
+ uint Hour;
+ uint Minute;
+ uint Second;
+ uint Reminder; // Part of time smaller than 1 second, represented in 100-nanosecond intervals.
+ uint wDay;
+ uint yDay;
+};
+
+
+class RarTime
+{
+ private:
+ // Internal FILETIME like time representation in 100 nanoseconds
+ // since 01.01.1601.
+ uint64 itime;
+ public:
+ RarTime() {Reset();}
+#ifdef _WIN_ALL
+ RarTime(FILETIME &ft) {*this=ft;}
+ RarTime& operator =(FILETIME &ft);
+ void GetWin32(FILETIME *ft);
+#endif
+ RarTime(time_t ut) {*this=ut;}
+ RarTime& operator =(time_t ut);
+ time_t GetUnix();
+ bool operator == (RarTime &rt) {return itime==rt.itime;}
+ bool operator < (RarTime &rt) {return itime (RarTime &rt) {return itime>rt.itime;}
+ bool operator >= (RarTime &rt) {return itime>rt.itime || itime==rt.itime;}
+ void GetLocal(RarLocalTime *lt);
+ void SetLocal(RarLocalTime *lt);
+ uint64 GetRaw();
+ void SetRaw(uint64 RawTime);
+ uint GetDos();
+ void SetDos(uint DosTime);
+ void SetIsoText(const wchar *TimeText);
+ void SetAgeText(const wchar *TimeText);
+ void SetCurrentTime();
+ void Reset() {itime=0;}
+ bool IsSet() {return itime!=0;}
+};
+
+bool IsLeapYear(int Year);
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/unicode.cpp b/desmume/src/windows/File_Extractor/unrar/unicode.cpp
index 5b04d6665..1c718481b 100644
--- a/desmume/src/windows/File_Extractor/unrar/unicode.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/unicode.cpp
@@ -2,6 +2,48 @@
#include "unicode.hpp"
+bool CharToWide(const char *Src,wchar *Dest,int DestSize)
+{
+ bool RetCode=true;
+#ifdef _WIN_32
+ if (MultiByteToWideChar(CP_ACP,0,Src,-1,Dest,DestSize,NULL,NULL)==0)
+ RetCode=false;
+#else
+#ifdef _APPLE
+ UtfToWide(Src,Dest,DestSize);
+#else
+#ifdef MBFUNCTIONS
+
+ size_t ResultingSize=mbstowcs(Dest,Src,DestSize);
+ if (ResultingSize==(size_t)-1)
+ RetCode=false;
+ if (ResultingSize==0 && *Src!=0)
+ RetCode=false;
+
+ if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlen(Src)NextWindow flag
+ // in UnpWriteBuf(). Minimum window size 0x20000 would be enough, but let's
+ // use 0x40000 for extra safety and possible filter area size expansion.
+ const size_t MinAllocSize=0x40000;
+ if (WinSize>16)>0x10000) // Window size must not exceed 4 GB.
+ return;
+
+ // Archiving code guarantees that window size does not grow in the same
+ // solid stream. So if we are here, we are either creating a new window
+ // or increasing the size of non-solid window. So we could safely reject
+ // current window data without copying them to a new window, though being
+ // extra cautious, we still handle the solid window grow case below.
+ bool Grow=Solid && (Window!=NULL || Fragmented);
+
+ // We do not handle growth for existing fragmented window.
+ if (Grow && Fragmented)
+ throw std::bad_alloc();
+
+ byte *NewWindow=Fragmented ? NULL : (byte *)malloc(WinSize);
+
+ if (NewWindow==NULL)
+ if (Grow || WinSize<0x1000000)
+ {
+ // We do not support growth for new fragmented window.
+ // Also exclude RAR4 and small dictionaries.
+ throw std::bad_alloc();
+ }
+ else
+ {
+ if (Window!=NULL) // If allocated by preceding files.
+ {
+ free(Window);
+ Window=NULL;
+ }
+ FragWindow.Init(WinSize);
+ Fragmented=true;
+ }
+
+ if (!Fragmented)
{
- Unpack::Window = (byte*) rarmalloc( MAXWINSIZE );
- if (Unpack::Window==NULL)
- ErrHandler.MemoryError();
+ // Clean the window to generate the same output when unpacking corrupt
+ // RAR files, which may access to unused areas of sliding dictionary.
+ memset(NewWindow,0,WinSize);
+
+ // If Window is not NULL, it means that window size has grown.
+ // In solid streams we need to copy data to a new window in such case.
+ // RAR archiving code does not allow it in solid streams now,
+ // but let's implement it anyway just in case we'll change it sometimes.
+ if (Grow)
+ for (size_t I=1;IUnpPtr; // cache in register
- byte* const Window = this->Window; // cache in register
-
- unsigned int DestPtr=UnpPtr-Distance;
- if (UnpPtrUnpPtr += Length;
- if ( Distance < Length ) // can't use memcpy when source and dest overlap
- {
- // Length always >= 1
- do
- {
- Window[UnpPtr++]=Window[DestPtr++];
- }
- while (--Length>0)
- ;
- }
- else
- {
- memcpy( &Window[UnpPtr], &Window[DestPtr], Length );
- }
- }
- else
- {
- while (Length--)
- {
- Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK];
- UnpPtr=(UnpPtr+1) & MAXWINMASK;
- }
-
- this->UnpPtr = UnpPtr;
- }
-}
-
-
-int Unpack::DecodeNumber(struct Decode *Dec)
-{
- unsigned int Bits;
- unsigned int BitField=getbits() & 0xfffe;
- if (BitFieldDecodeLen[8])
- if (BitFieldDecodeLen[4])
- if (BitFieldDecodeLen[2])
- if (BitFieldDecodeLen[1])
- Bits=1;
- else
- Bits=2;
- else
- if (BitFieldDecodeLen[3])
- Bits=3;
- else
- Bits=4;
- else
- if (BitFieldDecodeLen[6])
- if (BitFieldDecodeLen[5])
- Bits=5;
- else
- Bits=6;
- else
- if (BitFieldDecodeLen[7])
- Bits=7;
- else
- Bits=8;
- else
- if (BitFieldDecodeLen[12])
- if (BitFieldDecodeLen[10])
- if (BitFieldDecodeLen[9])
- Bits=9;
- else
- Bits=10;
- else
- if (BitFieldDecodeLen[11])
- Bits=11;
- else
- Bits=12;
- else
- if (BitFieldDecodeLen[14])
- if (BitFieldDecodeLen[13])
- Bits=13;
- else
- Bits=14;
- else
- Bits=15;
-
- unsigned int N=Dec->DecodePos[Bits]+((BitField-Dec->DecodeLen[Bits-1])>>(16-Bits));
- if (N>=Dec->MaxNum)
- N=0;
- // do after reading values, to allow better instruction scheduling
- addbits(Bits);
- return(Dec->DecodeNum[N]);
-}
-
-const
-static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
-const
-static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
-static int DDecode[DC];
-static byte DBits[DC];
-const
-static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
-const
-static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
-const
-static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
-
-void Unpack::init_tables()
-{
- if (DDecode[1]==0)
- {
- int Dist=0,BitLength=0,Slot=0;
- for (int I=0;IReadBorder)
- {
- if (!UnpReadBuf())
- break;
- }
- if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr)
- {
- UnpWriteBuf();
- if (WrittenFileSize>DestUnpSize)
- return;
- if (Suspended)
- {
- FileExtracted=false;
- return;
- }
- }
- if (UnpBlockType==BLOCK_PPM)
- {
- int Ch=PPM.DecodeChar();
- if (Ch==-1)
- {
- PPM.CleanUp();
-
- // turn off PPM compression mode in case of error, so UnRAR will
- // call PPM.DecodeInit in case it needs to turn it on back later.
- UnpBlockType=BLOCK_LZ;
- break;
- }
- if (Ch==PPMEscChar)
- {
- int NextCh=PPM.DecodeChar();
- if (NextCh==0)
- {
- if (!ReadTables())
- break;
- continue;
- }
- if (NextCh==2 || NextCh==-1)
- break;
- if (NextCh==3)
- {
- if (!ReadVMCodePPM())
- break;
- continue;
- }
- if (NextCh==4)
- {
- unsigned int Distance=0,Length;
- Length = 0; // avoids warning
- bool Failed=false;
- for (int I=0;I<4 && !Failed;I++)
- {
- int Ch=PPM.DecodeChar();
- if (Ch==-1)
- Failed=true;
- else
- if (I==3)
- Length=(byte)Ch;
- else
- Distance=(Distance<<8)+(byte)Ch;
- }
- if (Failed)
- break;
-
-#ifdef _MSC_VER
- // avoid a warning about uninitialized 'Length' variable
- #pragma warning( disable : 4701 )
-#endif
- CopyString(Length+32,Distance+2);
- continue;
- }
- if (NextCh==5)
- {
- int Length=PPM.DecodeChar();
- if (Length==-1)
- break;
- CopyString(Length+4,1);
- continue;
- }
- }
- Window[UnpPtr++]=Ch;
- continue;
- }
-
- int Number=DecodeNumber((struct Decode *)&LD);
- if (Number<256)
- {
- Window[UnpPtr++]=(byte)Number;
- continue;
- }
- if (Number>=271)
- {
- int Length=LDecode[Number-=271]+3;
- if ((Bits=LBits[Number])>0)
- {
- Length+=getbits()>>(16-Bits);
- addbits(Bits);
- }
-
- int DistNumber=DecodeNumber((struct Decode *)&DD);
- unsigned int Distance=DDecode[DistNumber]+1;
- if ((Bits=DBits[DistNumber])>0)
- {
- if (DistNumber>9)
- {
- if (Bits>4)
- {
- Distance+=((getbits()>>(20-Bits))<<4);
- addbits(Bits-4);
- }
- if (LowDistRepCount>0)
- {
- LowDistRepCount--;
- Distance+=PrevLowDist;
- }
- else
- {
- int LowDist=DecodeNumber((struct Decode *)&LDD);
- if (LowDist==16)
- {
- LowDistRepCount=LOW_DIST_REP_COUNT-1;
- Distance+=PrevLowDist;
- }
- else
- {
- Distance+=LowDist;
- PrevLowDist=LowDist;
- }
- }
- }
- else
- {
- Distance+=getbits()>>(16-Bits);
- addbits(Bits);
- }
- }
-
- if (Distance>=0x2000)
- {
- Length++;
- if (Distance>=0x40000L)
- Length++;
- }
-
- InsertOldDist(Distance);
- InsertLastMatch(Length,Distance);
- CopyString(Length,Distance);
- continue;
- }
- if (Number==256)
- {
- if (!ReadEndOfBlock())
- break;
- continue;
- }
- if (Number==257)
- {
- if (!ReadVMCode())
- break;
- continue;
- }
- if (Number==258)
- {
- if (LastLength!=0)
- CopyString(LastLength,LastDist);
- continue;
- }
- if (Number<263)
- {
- int DistNum=Number-259;
- unsigned int Distance=OldDist[DistNum];
- for (int I=DistNum;I>0;I--)
- OldDist[I]=OldDist[I-1];
- OldDist[0]=Distance;
-
- int LengthNumber=DecodeNumber((struct Decode *)&RD);
- int Length=LDecode[LengthNumber]+2;
- if ((Bits=LBits[LengthNumber])>0)
- {
- Length+=getbits()>>(16-Bits);
- addbits(Bits);
- }
- InsertLastMatch(Length,Distance);
- CopyString(Length,Distance);
- continue;
- }
- if (Number<272)
- {
- unsigned int Distance=SDDecode[Number-=263]+1;
- if ((Bits=SDBits[Number])>0)
- {
- Distance+=getbits()>>(16-Bits);
- addbits(Bits);
- }
- InsertOldDist(Distance);
- InsertLastMatch(2,Distance);
- CopyString(2,Distance);
- continue;
- }
- }
- UnpWriteBuf();
-}
-
-
-bool Unpack::ReadEndOfBlock()
-{
- unsigned int BitField=getbits();
- bool NewTable,NewFile=false;
- if (BitField & 0x8000)
- {
- NewTable=true;
- addbits(1);
- }
- else
- {
- NewFile=true;
- NewTable=(BitField & 0x4000);
- addbits(2);
- }
- TablesRead=!NewTable;
- return !(NewFile || NewTable && !ReadTables());
-}
-
-
-bool Unpack::ReadVMCode()
-{
- unsigned int FirstByte=getbits()>>8;
- addbits(8);
- int Length=(FirstByte & 7)+1;
- if (Length==7)
- {
- Length=(getbits()>>8)+7;
- addbits(8);
- }
- else
- if (Length==8)
- {
- Length=getbits();
- addbits(16);
- }
- VMCode.Alloc( Length );
- for (int I=0;I=ReadTop-1 && !UnpReadBuf() && I>8;
- addbits(8);
- }
- return(AddVMCode(FirstByte,&VMCode[0],Length));
-}
-
-
-bool Unpack::ReadVMCodePPM()
-{
- unsigned int FirstByte=PPM.DecodeChar();
- if ((int)FirstByte==-1)
- return(false);
- int Length=(FirstByte & 7)+1;
- if (Length==7)
- {
- int B1=PPM.DecodeChar();
- if (B1==-1)
- return(false);
- Length=B1+7;
- }
- else
- if (Length==8)
- {
- int B1=PPM.DecodeChar();
- if (B1==-1)
- return(false);
- int B2=PPM.DecodeChar();
- if (B2==-1)
- return(false);
- Length=B1*256+B2;
- }
- VMCode.Alloc( Length );
- for (int I=0;IFilters.Size() || FiltPos>OldFilterLengths.Size())
- return(false);
- LastFilter=FiltPos;
- bool NewFilter=(FiltPos==Filters.Size());
-
- delete LastStackFilter;
- LastStackFilter = NULL;
- UnpackFilter *StackFilter=new UnpackFilter(&ErrHandler);
- LastStackFilter = StackFilter;
- if ( !StackFilter )
- ErrHandler.MemoryError();
-
- UnpackFilter *Filter;
- if (NewFilter) // new filter code, never used before since VM reset
- {
- // too many different filters, corrupt archive
- if (FiltPos>1024)
- return(false);
-
- Filters.Add(1);
- Filters[Filters.Size()-1]=Filter=new UnpackFilter(&ErrHandler);
- if ( !Filter )
- ErrHandler.MemoryError();
- StackFilter->ParentFilter=Filters.Size()-1;
- OldFilterLengths.Add(1);
- Filter->ExecCount=0;
- }
- else // filter was used in the past
- {
- Filter=Filters[FiltPos];
- StackFilter->ParentFilter=FiltPos;
- Filter->ExecCount++;
- }
-
- int EmptyCount=0;
- {
- for (int I=0;I0)
- PrgStack[I]=NULL;
- }
- }
- if (EmptyCount==0)
- {
- PrgStack.Add(1);
- EmptyCount=1;
- }
- int StackPos=PrgStack.Size()-EmptyCount;
- PrgStack[StackPos]=StackFilter;
- LastStackFilter = NULL;
- StackFilter->ExecCount=Filter->ExecCount;
-
- uint BlockStart=RarVM::ReadData(Inp);
- if (FirstByte & 0x40)
- BlockStart+=258;
- StackFilter->BlockStart=(BlockStart+UnpPtr)&MAXWINMASK;
- if (FirstByte & 0x20)
- StackFilter->BlockLength=RarVM::ReadData(Inp);
- else
- StackFilter->BlockLength=FiltPosNextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MAXWINMASK)<=BlockStart;
-
-// DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
-
- OldFilterLengths[FiltPos]=StackFilter->BlockLength;
-
- memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
- StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
- StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
- StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
-
- if (FirstByte & 0x10) // set registers to optional parameters if any
- {
- unsigned int InitMask=Inp.fgetbits()>>9;
- Inp.faddbits(7);
- for (int I=0;I<7;I++)
- if (InitMask & (1<Prg.InitR[I]=RarVM::ReadData(Inp);
- }
-
- if (NewFilter)
- {
- uint VMCodeSize=RarVM::ReadData(Inp);
- if (VMCodeSize>=0x10000 || VMCodeSize==0)
- return(false);
- VMCode.Alloc( VMCodeSize );
- for (int I=0;I>8;
- Inp.faddbits(8);
- }
- VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
- VMCode.Reset();
- }
- StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
- StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
-
- int StaticDataSize=Filter->Prg.StaticData.Size();
- if (StaticDataSize>0 && StaticDataSizePrg.StaticData.Add(StaticDataSize);
- memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
- }
-
- if (StackFilter->Prg.GlobalData.Size()Prg.GlobalData.Reset();
- StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
- }
- byte *GlobalData=&StackFilter->Prg.GlobalData[0];
- for (int I=0;I<7;I++)
- VM.SetLowEndianValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]);
- VM.SetLowEndianValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength);
- VM.SetLowEndianValue((uint *)&GlobalData[0x20],0);
- VM.SetLowEndianValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount);
- memset(&GlobalData[0x30],0,16);
-
- if (FirstByte & 8) // put data block passed as parameter if any
- {
- if (Inp.Overflow(3))
- return(false);
- uint DataSize=RarVM::ReadData(Inp);
- if (DataSize>VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE)
- return(false);
- unsigned int CurSize=StackFilter->Prg.GlobalData.Size();
- if (CurSizePrg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
- byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE];
- for (int I=0;I>8;
- Inp.faddbits(8);
- }
- }
- Inp.InitBitInput();
- return(true);
-}
-
-
-bool Unpack::UnpReadBuf()
-{
- int DataSize=ReadTop-InAddr;
- if (DataSize<0)
- return(false);
- if (InAddr>BitInput::MAX_SIZE/2)
- {
- if (DataSize>0)
- memmove(InBuf,InBuf+InAddr,DataSize);
- InAddr=0;
- ReadTop=DataSize;
- }
- else
- DataSize=ReadTop;
- int ReadCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf);
- if (ReadCode>0)
- ReadTop+=ReadCode;
- ReadBorder=ReadTop-30;
- return(ReadCode!=-1);
-}
-
-
-void Unpack::UnpWriteBuf()
-{
- unsigned int WrittenBorder=WrPtr;
- unsigned int WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
- for (int I=0;INextWindow)
- {
- flt->NextWindow=false;
- continue;
- }
- unsigned int BlockStart=flt->BlockStart;
- unsigned int BlockLength=flt->BlockLength;
- if (((BlockStart-WrittenBorder)&MAXWINMASK)ParentFilter]->Prg;
- VM_PreparedProgram *Prg=&flt->Prg;
-
- if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
- {
- // copy global data from previous script execution if any
- Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
- memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
- }
-
- ExecuteCode(Prg);
-
- if (Prg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
- {
- // save global data for next script execution
- if (ParentPrg->GlobalData.Size()GlobalData.Size())
- ParentPrg->GlobalData.Alloc(Prg->GlobalData.Size());
- memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
- }
- else
- ParentPrg->GlobalData.Reset();
-
- byte *FilteredData=Prg->FilteredData;
- unsigned int FilteredDataSize=Prg->FilteredDataSize;
-
- delete PrgStack[I];
- PrgStack[I]=NULL;
- while (I+1BlockStart!=BlockStart ||
- NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow)
- break;
-
- // apply several filters to same data block
-
- VM.SetMemory(0,FilteredData,FilteredDataSize);
-
- VM_PreparedProgram *ParentPrg=&Filters[NextFilter->ParentFilter]->Prg;
- VM_PreparedProgram *NextPrg=&NextFilter->Prg;
-
- if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
- {
- // copy global data from previous script execution if any
- NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
- memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
- }
-
- ExecuteCode(NextPrg);
-
- if (NextPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
- {
- // save global data for next script execution
- if (ParentPrg->GlobalData.Size()GlobalData.Size())
- ParentPrg->GlobalData.Alloc(NextPrg->GlobalData.Size());
- memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
- }
- else
- ParentPrg->GlobalData.Reset();
-
- FilteredData=NextPrg->FilteredData;
- FilteredDataSize=NextPrg->FilteredDataSize;
- I++;
- delete PrgStack[I];
- PrgStack[I]=NULL;
- }
- UnpIO->UnpWrite(FilteredData,FilteredDataSize);
- UnpSomeRead=true;
- WrittenFileSize+=FilteredDataSize;
- WrittenBorder=BlockEnd;
- WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK;
- }
- else
- {
- for (int J=I;JNextWindow)
- flt->NextWindow=false;
- }
- WrPtr=WrittenBorder;
- return;
- }
- }
- }
-
- UnpWriteArea(WrittenBorder,UnpPtr);
- WrPtr=UnpPtr;
-}
-
-
-void Unpack::ExecuteCode(VM_PreparedProgram *Prg)
-{
- if (Prg->GlobalData.Size()>0)
- {
- Prg->InitR[6]=int64to32(WrittenFileSize);
- VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize));
- VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>31>>1));
- VM.Execute(Prg);
- }
-}
-
-
-void Unpack::UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr)
-{
- if (EndPtr!=StartPtr)
- UnpSomeRead=true;
- if (EndPtr=DestUnpSize)
- return;
- int WriteSize=Size;
- Int64 LeftToWrite=DestUnpSize-WrittenFileSize;
- if (WriteSize>LeftToWrite)
- WriteSize=int64to32(LeftToWrite);
- UnpIO->UnpWrite(Data,WriteSize);
- WrittenFileSize+=Size;
-}
-
-
-bool Unpack::ReadTables()
-{
- byte BitLength[BC];
- unsigned char Table[HUFF_TABLE_SIZE];
- if (InAddr>ReadTop-25)
- if (!UnpReadBuf())
- return(false);
- faddbits((8-InBit)&7);
- unsigned int BitField=fgetbits();
- if (BitField & 0x8000)
- {
- UnpBlockType=BLOCK_PPM;
- return(PPM.DecodeInit(this,PPMEscChar));
- }
- UnpBlockType=BLOCK_LZ;
-
- PrevLowDist=0;
- LowDistRepCount=0;
-
- if (!(BitField & 0x4000))
- memset(UnpOldTable,0,sizeof(UnpOldTable));
- faddbits(2);
- {
- for (int I=0;I> 12);
- faddbits(4);
- if (Length==15)
- {
- int ZeroCount=(byte)(fgetbits() >> 12);
- faddbits(4);
- if (ZeroCount==0)
- BitLength[I]=15;
- else
- {
- ZeroCount+=2;
- while (ZeroCount-- > 0 && IReadTop-5)
- if (!UnpReadBuf())
- return(false);
- int Number=DecodeNumber((struct Decode *)&BD);
- if (Number<16)
- {
- Table[I]=(Number+UnpOldTable[I]) & 0xf;
- I++;
- }
- else
- if (Number<18)
- {
- int N;
- if (Number==16)
- {
- N=(fgetbits() >> 13)+3;
- faddbits(3);
- }
- else
- {
- N=(fgetbits() >> 9)+11;
- faddbits(7);
- }
- while (N-- > 0 && I> 13)+3;
- faddbits(3);
- }
- else
- {
- N=(fgetbits() >> 9)+11;
- faddbits(7);
- }
- while (N-- > 0 && IReadTop)
- return(false);
- MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC);
- MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC);
- MakeDecodeTables(&Table[NC+DC],(struct Decode *)&LDD,LDC);
- MakeDecodeTables(&Table[NC+DC+LDC],(struct Decode *)&RD,RC);
- memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
- return(true);
-}
-
-
-void Unpack::UnpInitData(int Solid)
-{
- if (!Solid)
- {
- TablesRead=false;
- memset(OldDist,0,sizeof(OldDist));
- OldDistPtr=0;
- LastDist=LastLength=0;
-// memset(Window,0,MAXWINSIZE);
- memset(UnpOldTable,0,sizeof(UnpOldTable));
- memset(&LD,0,sizeof(LD));
- memset(&DD,0,sizeof(DD));
- memset(&LDD,0,sizeof(LDD));
- memset(&RD,0,sizeof(RD));
- memset(&BD,0,sizeof(BD));
- UnpPtr=WrPtr=0;
- PPMEscChar=2;
- UnpBlockType=BLOCK_LZ;
-
- InitFilters();
- }
- InitBitInput();
- WrittenFileSize=0;
- ReadTop=0;
- ReadBorder=0;
+ if (!Solid)
+ {
+ memset(OldDist,0,sizeof(OldDist));
+ OldDistPtr=0;
+ LastDist=LastLength=0;
+ // memset(Window,0,MaxWinSize);
+ memset(&BlockTables,0,sizeof(BlockTables));
+ UnpPtr=WrPtr=0;
+ WriteBorder=Min(MaxWinSize,UNPACK_MAX_WRITE)&MaxWinMask;
+
+ InitFilters();
+ }
+ Inp.InitBitInput();
+ WrittenFileSize=0;
+ ReadTop=0;
+ ReadBorder=0;
+
+ memset(&BlockHeader,0,sizeof(BlockHeader));
+ BlockHeader.BlockSize=-1; // '-1' means not defined yet.
#ifndef SFX_MODULE
- UnpInitData20(Solid);
+ UnpInitData20(Solid);
#endif
+ UnpInitData30(Solid);
}
-void Unpack::InitFilters()
+// LengthTable contains the length in bits for every element of alphabet.
+// Dec is the structure to decode Huffman code/
+// Size is size of length table and DecodeNum field in Dec structure,
+void Unpack::MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size)
{
- delete LastStackFilter;
- LastStackFilter = NULL;
-
- OldFilterLengths.Reset();
- LastFilter=0;
- {
- for (int I=0;IDecodeNum,0,Size*sizeof(*Dec->DecodeNum));
- for (I=0;IDecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++)
- {
- N=2*(N+LenCount[I]);
- M=N<<(15-I);
- if (M>0xFFFF)
- M=0xFFFF;
- Dec->DecodeLen[I]=(unsigned int)M;
- TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1];
- }
-
- for (I=0;IDecodeNum[TmpPos[LenTab[I] & 0xF]++]=I;
- Dec->MaxNum=Size;
+ // Size of alphabet and DecodePos array.
+ Dec->MaxNum=Size;
+
+ // Calculate how many entries for every bit length in LengthTable we have.
+ uint LengthCount[16];
+ memset(LengthCount,0,sizeof(LengthCount));
+ for (size_t I=0;IDecodeNum,0,Size*sizeof(*Dec->DecodeNum));
+
+ // Initialize not really used entry for zero length code.
+ Dec->DecodePos[0]=0;
+
+ // Start code for bit length 1 is 0.
+ Dec->DecodeLen[0]=0;
+
+ // Right aligned upper limit code for current bit length.
+ uint UpperLimit=0;
+
+ for (size_t I=1;I<16;I++)
+ {
+ // Adjust the upper limit code.
+ UpperLimit+=LengthCount[I];
+
+ // Left aligned upper limit code.
+ uint LeftAligned=UpperLimit<<(16-I);
+
+ // Prepare the upper limit code for next bit length.
+ UpperLimit*=2;
+
+ // Store the left aligned upper limit code.
+ Dec->DecodeLen[I]=(uint)LeftAligned;
+
+ // Every item of this array contains the sum of all preceding items.
+ // So it contains the start position in code list for every bit length.
+ Dec->DecodePos[I]=Dec->DecodePos[I-1]+LengthCount[I-1];
+ }
+
+ // Prepare the copy of DecodePos. We'll modify this copy below,
+ // so we cannot use the original DecodePos.
+ uint CopyDecodePos[16];
+ memcpy(CopyDecodePos,Dec->DecodePos,sizeof(CopyDecodePos));
+
+ // For every bit length in the bit length table and so for every item
+ // of alphabet.
+ for (uint I=0;IDecodeNum[LastPos]=(ushort)I;
+
+ // We'll use next position number for this bit length next time.
+ // So we pass through the entire range of positions available
+ // for every bit length.
+ CopyDecodePos[CurBitLength]++;
+ }
+ }
+
+ // Define the number of bits to process in quick mode. We use more bits
+ // for larger alphabets. More bits means that more codes will be processed
+ // in quick mode, but also that more time will be spent to preparation
+ // of tables for quick decode.
+ switch (Size)
+ {
+ case NC:
+ case NC20:
+ case NC30:
+ Dec->QuickBits=MAX_QUICK_DECODE_BITS;
+ break;
+ default:
+ Dec->QuickBits=MAX_QUICK_DECODE_BITS-3;
+ break;
+ }
+
+ // Size of tables for quick mode.
+ uint QuickDataSize=1<QuickBits;
+
+ // Bit length for current code, start from 1 bit codes. It is important
+ // to use 1 bit instead of 0 for minimum code length, so we are moving
+ // forward even when processing a corrupt archive.
+ uint CurBitLength=1;
+
+ // For every right aligned bit string which supports the quick decoding.
+ for (uint Code=0;CodeQuickBits);
+
+ // Prepare the table for quick decoding of bit lengths.
+
+ // Find the upper limit for current bit field and adjust the bit length
+ // accordingly if necessary.
+ while (BitField>=Dec->DecodeLen[CurBitLength] && CurBitLengthDecodeLen))
+ CurBitLength++;
+
+ // Translation of right aligned bit string to bit length.
+ Dec->QuickLen[Code]=CurBitLength;
+
+ // Prepare the table for quick translation of position in code list
+ // to position in alphabet.
+
+ // Calculate the distance from the start code for current bit length.
+ uint Dist=BitField-Dec->DecodeLen[CurBitLength-1];
+
+ // Right align the distance.
+ Dist>>=(16-CurBitLength);
+
+ // Now we can calculate the position in the code list. It is the sum
+ // of first position for current bit length and right aligned distance
+ // between our bit field and start code for current bit length.
+ uint Pos=Dec->DecodePos[CurBitLength]+Dist;
+
+ if (PosQuickNum[Code]=Dec->DecodeNum[Pos];
+ }
+ else
+ Dec->QuickNum[Code]=0;
+ }
}
diff --git a/desmume/src/windows/File_Extractor/unrar/unpack.hpp b/desmume/src/windows/File_Extractor/unrar/unpack.hpp
index 732ebe863..541189a5d 100644
--- a/desmume/src/windows/File_Extractor/unrar/unpack.hpp
+++ b/desmume/src/windows/File_Extractor/unrar/unpack.hpp
@@ -1,227 +1,369 @@
-#ifndef _RAR_UNPACK_
-#define _RAR_UNPACK_
-
-enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM};
-
-struct Decode
-{
- unsigned int MaxNum;
- unsigned int DecodeLen[16];
- unsigned int DecodePos[16];
- unsigned int DecodeNum[2];
-};
-
-struct LitDecode
-{
- unsigned int MaxNum;
- unsigned int DecodeLen[16];
- unsigned int DecodePos[16];
- unsigned int DecodeNum[NC];
-};
-
-struct DistDecode
-{
- unsigned int MaxNum;
- unsigned int DecodeLen[16];
- unsigned int DecodePos[16];
- unsigned int DecodeNum[DC];
-};
-
-struct LowDistDecode
-{
- unsigned int MaxNum;
- unsigned int DecodeLen[16];
- unsigned int DecodePos[16];
- unsigned int DecodeNum[LDC];
-};
-
-struct RepDecode
-{
- unsigned int MaxNum;
- unsigned int DecodeLen[16];
- unsigned int DecodePos[16];
- unsigned int DecodeNum[RC];
-};
-
-struct BitDecode
-{
- unsigned int MaxNum;
- unsigned int DecodeLen[16];
- unsigned int DecodePos[16];
- unsigned int DecodeNum[BC];
-};
-
-struct UnpackFilter
- : Rar_Allocator
-{
- unsigned int BlockStart;
- unsigned int BlockLength;
- unsigned int ExecCount;
- bool NextWindow;
-
- // position of parent filter in Filters array used as prototype for filter
- // in PrgStack array. Not defined for filters in Filters array.
- unsigned int ParentFilter;
-
- VM_PreparedProgram Prg;
- UnpackFilter( Rar_Error_Handler* eh ) : Prg( eh ) { }
-};
-
-/***************************** Unpack v 2.0 *********************************/
-struct MultDecode
-{
- unsigned int MaxNum;
- unsigned int DecodeLen[16];
- unsigned int DecodePos[16];
- unsigned int DecodeNum[MC20];
-};
-
-struct AudioVariables
-{
- int K1,K2,K3,K4,K5;
- int D1,D2,D3,D4;
- int LastDelta;
- unsigned int Dif[11];
- unsigned int ByteCount;
- int LastChar;
-};
-/***************************** Unpack v 2.0 *********************************/
-
-
-// public so operator new/delete will be accessible, argh
-class Unpack:public BitInput
-{
-private:
- friend class Pack;
-
- void Unpack29(bool Solid);
- bool UnpReadBuf();
- void UnpWriteBuf();
- void ExecuteCode(VM_PreparedProgram *Prg);
- void UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr);
- void UnpWriteData(byte *Data,int Size);
- bool ReadTables();
- void MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size);
- int DecodeNumber(struct Decode *Dec);
- void CopyString();
- inline void InsertOldDist(unsigned int Distance);
- inline void InsertLastMatch(unsigned int Length,unsigned int Distance);
- void UnpInitData(int Solid);
- void CopyString(unsigned int Length,unsigned int Distance);
- bool ReadEndOfBlock();
- bool ReadVMCode();
- bool ReadVMCodePPM();
- bool AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize);
- void InitFilters();
-
- ComprDataIO *UnpIO;
- ModelPPM PPM;
- int PPMEscChar;
-
- Array VMCode; // here to avoid leaks
- BitInput Inp; // here to avoid leaks
-
- RarVM VM;
-
- UnpackFilter* LastStackFilter; // avoids leak for stack-based filter
-
- /* Filters code, one entry per filter */
- Array Filters;
-
- /* Filters stack, several entrances of same filter are possible */
- Array PrgStack;
-
- /* lengths of preceding blocks, one length per filter. Used to reduce
- size required to write block length if lengths are repeating */
- Array OldFilterLengths;
-
- int LastFilter;
-
- bool TablesRead;
- struct LitDecode LD;
- struct DistDecode DD;
- struct LowDistDecode LDD;
- struct RepDecode RD;
- struct BitDecode BD;
-
- unsigned int OldDist[4],OldDistPtr;
- unsigned int LastDist,LastLength;
-
- unsigned int UnpPtr,WrPtr;
-
- int ReadTop;
- int ReadBorder;
-
- unsigned char UnpOldTable[HUFF_TABLE_SIZE];
-
- int UnpBlockType;
-
- byte *Window;
- bool ExternalWindow;
-
-
- Int64 DestUnpSize;
-
- enum { Suspended = false }; // original source could never set to true
- bool UnpAllBuf;
- bool UnpSomeRead;
- Int64 WrittenFileSize;
- bool FileExtracted;
-
- int PrevLowDist,LowDistRepCount;
-
- /***************************** Unpack v 1.5 *********************************/
- void Unpack15(bool Solid);
- void ShortLZ();
- void LongLZ();
- void HuffDecode();
- void GetFlagsBuf();
- void OldUnpInitData(int Solid);
- void InitHuff();
- void CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace);
- void OldCopyString(unsigned int Distance,unsigned int Length);
- unsigned int DecodeNum(int Num,unsigned int StartPos,
- const unsigned int *DecTab,const unsigned int *PosTab);
- void OldUnpWriteBuf();
-
- unsigned int ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
- unsigned int Place[256],PlaceA[256],PlaceB[256],PlaceC[256];
- unsigned int NToPl[256],NToPlB[256],NToPlC[256];
- unsigned int FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
- int Buf60,NumHuf,StMode,LCount,FlagsCnt;
- unsigned int Nhfb,Nlzb,MaxDist3;
- /***************************** Unpack v 1.5 *********************************/
-
- /***************************** Unpack v 2.0 *********************************/
- void Unpack20(bool Solid);
- struct MultDecode MD[4];
- unsigned char UnpOldTable20[MC20*4];
- int UnpAudioBlock,UnpChannels,UnpCurChannel,UnpChannelDelta;
- void CopyString20(unsigned int Length,unsigned int Distance);
- bool ReadTables20();
- void UnpInitData20(int Solid);
- void ReadLastTables();
- byte DecodeAudio(int Delta);
- struct AudioVariables AudV[4];
- /***************************** Unpack v 2.0 *********************************/
-
-public:
- Rar_Error_Handler& ErrHandler;
- byte const* window_wrptr() const { return &Window [WrPtr & MAXWINMASK]; }
-
- static void init_tables();
- Unpack(ComprDataIO *DataIO);
- ~Unpack();
- void Init(byte *Window=NULL);
- void DoUnpack(int Method,bool Solid);
- void SetDestSize(Int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;}
-
- unsigned int GetChar()
- {
- if (InAddr>BitInput::MAX_SIZE-30)
- UnpReadBuf();
- return(InBuf[InAddr++]);
- }
-};
-
-#endif
+#ifndef _RAR_UNPACK_
+#define _RAR_UNPACK_
+
+// Maximum allowed number of compressed bits processed in quick mode.
+#define MAX_QUICK_DECODE_BITS 10
+
+// Maximum number of filters per entire data block.
+#define MAX_UNPACK_FILTERS 8192
+
+// Maximum number of filters per entire data block for RAR3 unpack.
+#define MAX3_FILTERS 1024
+
+// Write data in 4 MB or smaller blocks.
+#define UNPACK_MAX_WRITE 0x400000
+
+// Decode compressed bit fields to alphabet numbers.
+struct DecodeTable:PackDef
+{
+ // Real size of DecodeNum table.
+ uint MaxNum;
+
+ // Left aligned start and upper limit codes defining code space
+ // ranges for bit lengths. DecodeLen[BitLength-1] defines the start of
+ // range for bit length and DecodeLen[BitLength] defines next code
+ // after the end of range or in other words the upper limit code
+ // for specified bit length.
+ uint DecodeLen[16];
+
+ // Every item of this array contains the sum of all preceding items.
+ // So it contains the start position in code list for every bit length.
+ uint DecodePos[16];
+
+ // Number of compressed bits processed in quick mode.
+ // Must not exceed MAX_QUICK_DECODE_BITS.
+ uint QuickBits;
+
+ // Translates compressed bits (up to QuickBits length)
+ // to bit length in quick mode.
+ byte QuickLen[1< FilterSrcMemory;
+ Array FilterDstMemory;
+
+ // Filters code, one entry per filter.
+ Array Filters;
+
+ uint OldDist[4],OldDistPtr;
+ uint LastLength;
+
+ // LastDist is necessary only for RAR2 and older with circular OldDist
+ // array. In RAR3 last distance is always stored in OldDist[0].
+ uint LastDist;
+
+ size_t UnpPtr,WrPtr;
+
+ // Top border of read packed data.
+ int ReadTop;
+
+ // Border to call UnpReadBuf. We use it instead of (ReadTop-C)
+ // for optimization reasons. Ensures that we have C bytes in buffer
+ // unless we are at the end of file.
+ int ReadBorder;
+
+ UnpackBlockHeader BlockHeader;
+ UnpackBlockTables BlockTables;
+
+ size_t WriteBorder;
+
+ byte *Window;
+
+ FragmentedWindow FragWindow;
+ bool Fragmented;
+
+
+ int64 DestUnpSize;
+
+ bool Suspended;
+ bool UnpAllBuf;
+ bool UnpSomeRead;
+ int64 WrittenFileSize;
+ bool FileExtracted;
+
+
+/***************************** Unpack v 1.5 *********************************/
+ void Unpack15(bool Solid);
+ void ShortLZ();
+ void LongLZ();
+ void HuffDecode();
+ void GetFlagsBuf();
+ void UnpInitData15(int Solid);
+ void InitHuff();
+ void CorrHuff(ushort *CharSet,byte *NumToPlace);
+ void CopyString15(uint Distance,uint Length);
+ uint DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab);
+
+ ushort ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256];
+ byte NToPl[256],NToPlB[256],NToPlC[256];
+ uint FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3;
+ int Buf60,NumHuf,StMode,LCount,FlagsCnt;
+ uint Nhfb,Nlzb,MaxDist3;
+/***************************** Unpack v 1.5 *********************************/
+
+/***************************** Unpack v 2.0 *********************************/
+ void Unpack20(bool Solid);
+
+ DecodeTable MD[4]; // Decode multimedia data, up to 4 channels.
+
+ unsigned char UnpOldTable20[MC20*4];
+ uint UnpAudioBlock,UnpChannels,UnpCurChannel;
+ int UnpChannelDelta;
+ void CopyString20(uint Length,uint Distance);
+ bool ReadTables20();
+ void UnpWriteBuf20();
+ void UnpInitData20(int Solid);
+ void ReadLastTables();
+ byte DecodeAudio(int Delta);
+ struct AudioVariables AudV[4];
+/***************************** Unpack v 2.0 *********************************/
+
+/***************************** Unpack v 3.0 *********************************/
+ enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM};
+
+ void UnpInitData30(bool Solid);
+ void Unpack29(bool Solid);
+ void InitFilters30();
+ bool ReadEndOfBlock();
+ bool ReadVMCode();
+ bool ReadVMCodePPM();
+ bool AddVMCode(uint FirstByte,byte *Code,int CodeSize);
+ int SafePPMDecodeChar();
+ bool ReadTables30();
+ bool UnpReadBuf30();
+ void UnpWriteBuf30();
+ void ExecuteCode(VM_PreparedProgram *Prg);
+
+ int PrevLowDist,LowDistRepCount;
+
+ ModelPPM PPM;
+ int PPMEscChar;
+
+ byte UnpOldTable[HUFF_TABLE_SIZE30];
+ int UnpBlockType;
+
+ bool TablesRead;
+
+ // Virtual machine to execute filters code.
+ RarVM VM;
+
+ // Buffer to read VM filters code. We moved it here from AddVMCode
+ // function to reduce time spent in BitInput constructor.
+ BitInput VMCodeInp;
+
+ // Filters code, one entry per filter.
+ Array Filters30;
+
+ // Filters stack, several entrances of same filter are possible.
+ Array PrgStack;
+
+ // Lengths of preceding data blocks, one length of one last block
+ // for every filter. Used to reduce the size required to write
+ // the data block length if lengths are repeating.
+ Array OldFilterLengths;
+
+ int LastFilter;
+/***************************** Unpack v 3.0 *********************************/
+
+ public:
+ Unpack(ComprDataIO *DataIO);
+ ~Unpack();
+ void Init(size_t WinSize,bool Solid);
+ void DoUnpack(int Method,bool Solid);
+ bool IsFileExtracted() {return(FileExtracted);}
+ void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;}
+ void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;}
+
+ byte const* window_wrptr() const { return &Window [WrPtr & MaxWinMask]; }
+
+ size_t MaxWinSize;
+ size_t MaxWinMask;
+
+ uint GetChar()
+ {
+ if (Inp.InAddr>BitInput::MAX_SIZE-30)
+ UnpReadBuf();
+ return(Inp.InBuf[Inp.InAddr++]);
+ }
+};
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/unpack15.cpp b/desmume/src/windows/File_Extractor/unrar/unpack15.cpp
index 89e75e6c7..1328de946 100644
--- a/desmume/src/windows/File_Extractor/unrar/unpack15.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/unpack15.cpp
@@ -1,532 +1,485 @@
-// #included by unpack.cpp
-#ifdef RAR_COMMON_HPP
-#define STARTL1 2
-const
-static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
- 0xee00,0xf000,0xf200,0xf200,0xffff};
-const
-static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
-
-#define STARTL2 3
-const
-static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
- 0xf000,0xf200,0xf240,0xffff};
-const
-static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
-
-#define STARTHF0 4
-const
-static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
- 0xf200,0xf200,0xffff};
-const
-static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
-
-
-#define STARTHF1 5
-const
-static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
- 0xf7e0,0xffff};
-const
-static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
-
-
-#define STARTHF2 5
-const
-static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
- 0xffff,0xffff};
-const
-static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
-
-
-#define STARTHF3 6
-const
-static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
- 0xffff};
-const
-static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
-
-
-#define STARTHF4 8
-const
-static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
-const
-static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};
-
-
-void Unpack::Unpack15(bool Solid)
-{
- if (Suspended)
- UnpPtr=WrPtr;
- else
- {
- UnpInitData(Solid);
- OldUnpInitData(Solid);
- UnpReadBuf();
- if (!Solid)
- {
- InitHuff();
- UnpPtr=0;
- }
- else
- UnpPtr=WrPtr;
- --DestUnpSize;
- }
- if (DestUnpSize>=0)
- {
- GetFlagsBuf();
- FlagsCnt=8;
- }
-
- while (DestUnpSize>=0)
- {
- UnpPtr&=MAXWINMASK;
-
- if (InAddr>ReadTop-30 && !UnpReadBuf())
- break;
- if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
- {
- OldUnpWriteBuf();
- if (Suspended)
- return;
- }
- if (StMode)
- {
- HuffDecode();
- continue;
- }
-
- if (--FlagsCnt < 0)
- {
- GetFlagsBuf();
- FlagsCnt=7;
- }
-
- if (FlagBuf & 0x80)
- {
- FlagBuf<<=1;
- if (Nlzb > Nhfb)
- LongLZ();
- else
- HuffDecode();
- }
- else
- {
- FlagBuf<<=1;
- if (--FlagsCnt < 0)
- {
- GetFlagsBuf();
- FlagsCnt=7;
- }
- if (FlagBuf & 0x80)
- {
- FlagBuf<<=1;
- if (Nlzb > Nhfb)
- HuffDecode();
- else
- LongLZ();
- }
- else
- {
- FlagBuf<<=1;
- ShortLZ();
- }
- }
- }
- OldUnpWriteBuf();
-}
-
-
-void Unpack::OldUnpWriteBuf()
-{
- if (UnpPtr!=WrPtr)
- UnpSomeRead=true;
- if (UnpPtrUnpWrite(&Window[WrPtr],-WrPtr & MAXWINMASK);
- UnpIO->UnpWrite(Window,UnpPtr);
- UnpAllBuf=true;
- }
- else
- UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
- WrPtr=UnpPtr;
-}
-
-
-#define GetShortLen1(pos) ((pos)==1 ? Buf60+3:ShortLen1[pos])
-#define GetShortLen2(pos) ((pos)==3 ? Buf60+3:ShortLen2[pos])
-
-void Unpack::ShortLZ()
-{
- const
- static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
- const
- static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
- 0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
- const
- static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
- const
- static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
- 0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
-
-
- unsigned int Length,SaveLength;
- unsigned int LastDistance;
- unsigned int Distance;
- int DistancePlace;
- NumHuf=0;
-
- unsigned int BitField=fgetbits();
- if (LCount==2)
- {
- faddbits(1);
- if (BitField >= 0x8000)
- {
- OldCopyString((unsigned int)LastDist,LastLength);
- return;
- }
- BitField <<= 1;
- LCount=0;
- }
-
- BitField>>=8;
-
-// not thread safe, replaced by GetShortLen1 and GetShortLen2 macro
-// ShortLen1[1]=ShortLen2[3]=Buf60+3;
-
- if (AvrLn1<37)
- {
- for (Length=0;;Length++)
- if (((BitField^ShortXor1[Length]) & (~(0xff>>GetShortLen1(Length))))==0)
- break;
- faddbits(GetShortLen1(Length));
- }
- else
- {
- for (Length=0;;Length++)
- if (((BitField^ShortXor2[Length]) & (~(0xff>>GetShortLen2(Length))))==0)
- break;
- faddbits(GetShortLen2(Length));
- }
-
- if (Length >= 9)
- {
- if (Length == 9)
- {
- LCount++;
- OldCopyString((unsigned int)LastDist,LastLength);
- return;
- }
- if (Length == 14)
- {
- LCount=0;
- Length=DecodeNum(fgetbits(),STARTL2,DecL2,PosL2)+5;
- Distance=(fgetbits()>>1) | 0x8000;
- faddbits(15);
- LastLength=Length;
- LastDist=Distance;
- OldCopyString(Distance,Length);
- return;
- }
-
- LCount=0;
- SaveLength=Length;
- Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
- Length=DecodeNum(fgetbits(),STARTL1,DecL1,PosL1)+2;
- if (Length==0x101 && SaveLength==10)
- {
- Buf60 ^= 1;
- return;
- }
- if (Distance > 256)
- Length++;
- if (Distance >= MaxDist3)
- Length++;
-
- OldDist[OldDistPtr++]=Distance;
- OldDistPtr = OldDistPtr & 3;
- LastLength=Length;
- LastDist=Distance;
- OldCopyString(Distance,Length);
- return;
- }
-
- LCount=0;
- AvrLn1 += Length;
- AvrLn1 -= AvrLn1 >> 4;
-
- DistancePlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff;
- Distance=ChSetA[DistancePlace];
- if (--DistancePlace != -1)
- {
- PlaceA[Distance]--;
- LastDistance=ChSetA[DistancePlace];
- PlaceA[LastDistance]++;
- ChSetA[DistancePlace+1]=LastDistance;
- ChSetA[DistancePlace]=Distance;
- }
- Length+=2;
- OldDist[OldDistPtr++] = ++Distance;
- OldDistPtr = OldDistPtr & 3;
- LastLength=Length;
- LastDist=Distance;
- OldCopyString(Distance,Length);
-}
-
-
-void Unpack::LongLZ()
-{
- unsigned int Length;
- unsigned int Distance;
- unsigned int DistancePlace,NewDistancePlace;
- unsigned int OldAvr2,OldAvr3;
-
- NumHuf=0;
- Nlzb+=16;
- if (Nlzb > 0xff)
- {
- Nlzb=0x90;
- Nhfb >>= 1;
- }
- OldAvr2=AvrLn2;
-
- unsigned int BitField=fgetbits();
- if (AvrLn2 >= 122)
- Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
- else
- if (AvrLn2 >= 64)
- Length=DecodeNum(BitField,STARTL1,DecL1,PosL1);
- else
- if (BitField < 0x100)
- {
- Length=BitField;
- faddbits(16);
- }
- else
- {
- for (Length=0;((BitField<> 5;
-
- BitField=fgetbits();
- if (AvrPlcB > 0x28ff)
- DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
- else
- if (AvrPlcB > 0x6ff)
- DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
- else
- DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
-
- AvrPlcB += DistancePlace;
- AvrPlcB -= AvrPlcB >> 8;
- while (1)
- {
- Distance = ChSetB[DistancePlace & 0xff];
- NewDistancePlace = NToPlB[Distance++ & 0xff]++;
- if (!(Distance & 0xff))
- CorrHuff(ChSetB,NToPlB);
- else
- break;
- }
-
- ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
- ChSetB[NewDistancePlace]=Distance;
-
- Distance=((Distance & 0xff00) | (fgetbits() >> 8)) >> 1;
- faddbits(7);
-
- OldAvr3=AvrLn3;
- if (Length!=1 && Length!=4)
- if (Length==0 && Distance <= MaxDist3)
- {
- AvrLn3++;
- AvrLn3 -= AvrLn3 >> 8;
- }
- else
- if (AvrLn3 > 0)
- AvrLn3--;
- Length+=3;
- if (Distance >= MaxDist3)
- Length++;
- if (Distance <= 256)
- Length+=8;
- if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40)
- MaxDist3=0x7f00;
- else
- MaxDist3=0x2001;
- OldDist[OldDistPtr++]=Distance;
- OldDistPtr = OldDistPtr & 3;
- LastLength=Length;
- LastDist=Distance;
- OldCopyString(Distance,Length);
-}
-
-
-void Unpack::HuffDecode()
-{
- unsigned int CurByte,NewBytePlace;
- unsigned int Length;
- unsigned int Distance;
- int BytePlace;
-
- unsigned int BitField=fgetbits();
-
- if (AvrPlc > 0x75ff)
- BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
- else
- if (AvrPlc > 0x5dff)
- BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3);
- else
- if (AvrPlc > 0x35ff)
- BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
- else
- if (AvrPlc > 0x0dff)
- BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
- else
- BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
- BytePlace&=0xff;
- if (StMode)
- {
- if (BytePlace==0 && BitField > 0xfff)
- BytePlace=0x100;
- if (--BytePlace==-1)
- {
- BitField=fgetbits();
- faddbits(1);
- if (BitField & 0x8000)
- {
- NumHuf=StMode=0;
- return;
- }
- else
- {
- Length = (BitField & 0x4000) ? 4 : 3;
- faddbits(1);
- Distance=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
- Distance = (Distance << 5) | (fgetbits() >> 11);
- faddbits(5);
- OldCopyString(Distance,Length);
- return;
- }
- }
- }
- else
- if (NumHuf++ >= 16 && FlagsCnt==0)
- StMode=1;
- AvrPlc += BytePlace;
- AvrPlc -= AvrPlc >> 8;
- Nhfb+=16;
- if (Nhfb > 0xff)
- {
- Nhfb=0x90;
- Nlzb >>= 1;
- }
-
- Window[UnpPtr++]=(byte)(ChSet[BytePlace]>>8);
- --DestUnpSize;
-
- while (1)
- {
- CurByte=ChSet[BytePlace];
- NewBytePlace=NToPl[CurByte++ & 0xff]++;
- if ((CurByte & 0xff) > 0xa1)
- CorrHuff(ChSet,NToPl);
- else
- break;
- }
-
- ChSet[BytePlace]=ChSet[NewBytePlace];
- ChSet[NewBytePlace]=CurByte;
-}
-
-
-void Unpack::GetFlagsBuf()
-{
- unsigned int Flags,NewFlagsPlace;
- unsigned int FlagsPlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2);
-
- while (1)
- {
- Flags=ChSetC[FlagsPlace];
- FlagBuf=Flags>>8;
- NewFlagsPlace=NToPlC[Flags++ & 0xff]++;
- if ((Flags & 0xff) != 0)
- break;
- CorrHuff(ChSetC,NToPlC);
- }
-
- ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace];
- ChSetC[NewFlagsPlace]=Flags;
-}
-
-
-void Unpack::OldUnpInitData(int Solid)
-{
- if (!Solid)
- {
- AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0;
- AvrPlc=0x3500;
- MaxDist3=0x2001;
- Nhfb=Nlzb=0x80;
- }
- FlagsCnt=0;
- FlagBuf=0;
- StMode=0;
- LCount=0;
- ReadTop=0;
-}
-
-
-void Unpack::InitHuff()
-{
- for (unsigned int I=0;I<256;I++)
- {
- Place[I]=PlaceA[I]=PlaceB[I]=I;
- PlaceC[I]=(~I+1) & 0xff;
- ChSet[I]=ChSetB[I]=I<<8;
- ChSetA[I]=I;
- ChSetC[I]=((~I+1) & 0xff)<<8;
- }
- memset(NToPl,0,sizeof(NToPl));
- memset(NToPlB,0,sizeof(NToPlB));
- memset(NToPlC,0,sizeof(NToPlC));
- CorrHuff(ChSetB,NToPlB);
-}
-
-
-void Unpack::CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace)
-{
- int I,J;
- for (I=7;I>=0;I--)
- for (J=0;J<32;J++,CharSet++)
- *CharSet=(*CharSet & ~0xff) | I;
- memset(NumToPlace,0,sizeof(NToPl));
- for (I=6;I>=0;I--)
- NumToPlace[I]=(7-I)*32;
-}
-
-
-void Unpack::OldCopyString(unsigned int Distance,unsigned int Length)
-{
- DestUnpSize-=Length;
- while (Length--)
- {
- Window[UnpPtr]=Window[(UnpPtr-Distance) & MAXWINMASK];
- UnpPtr=(UnpPtr+1) & MAXWINMASK;
- }
-}
-
-
-unsigned int Unpack::DecodeNum(int Num,unsigned int StartPos,
- const unsigned int *DecTab,const unsigned int *PosTab)
-{
- int I;
- for (Num&=0xfff0,I=0;DecTab[I]<=Num;I++)
- StartPos++;
- faddbits(StartPos);
- return(((Num-(I ? DecTab[I-1]:0))>>(16-StartPos))+PosTab[StartPos]);
-}
-#endif
+#ifdef RAR_COMMON_HPP
+
+#define STARTL1 2
+static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00,
+ 0xee00,0xf000,0xf200,0xf200,0xffff};
+static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32};
+
+#define STARTL2 3
+static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00,
+ 0xf000,0xf200,0xf240,0xffff};
+static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36};
+
+#define STARTHF0 4
+static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200,
+ 0xf200,0xf200,0xffff};
+static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33};
+
+
+#define STARTHF1 5
+static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200,
+ 0xf7e0,0xffff};
+static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127};
+
+
+#define STARTHF2 5
+static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff,
+ 0xffff,0xffff};
+static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0};
+
+
+#define STARTHF3 6
+static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff,
+ 0xffff};
+static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0};
+
+
+#define STARTHF4 8
+static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff};
+static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0};
+
+
+void Unpack::Unpack15(bool Solid)
+{
+ UnpInitData(Solid);
+ UnpInitData15(Solid);
+ UnpReadBuf();
+ if (!Solid)
+ {
+ InitHuff();
+ UnpPtr=0;
+ }
+ else
+ UnpPtr=WrPtr;
+ --DestUnpSize;
+ if (DestUnpSize>=0)
+ {
+ GetFlagsBuf();
+ FlagsCnt=8;
+ }
+
+ while (DestUnpSize>=0)
+ {
+ UnpPtr&=MaxWinMask;
+
+ if (Inp.InAddr>ReadTop-30 && !UnpReadBuf())
+ break;
+ if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr)
+ UnpWriteBuf20();
+ if (StMode)
+ {
+ HuffDecode();
+ continue;
+ }
+
+ if (--FlagsCnt < 0)
+ {
+ GetFlagsBuf();
+ FlagsCnt=7;
+ }
+
+ if (FlagBuf & 0x80)
+ {
+ FlagBuf<<=1;
+ if (Nlzb > Nhfb)
+ LongLZ();
+ else
+ HuffDecode();
+ }
+ else
+ {
+ FlagBuf<<=1;
+ if (--FlagsCnt < 0)
+ {
+ GetFlagsBuf();
+ FlagsCnt=7;
+ }
+ if (FlagBuf & 0x80)
+ {
+ FlagBuf<<=1;
+ if (Nlzb > Nhfb)
+ HuffDecode();
+ else
+ LongLZ();
+ }
+ else
+ {
+ FlagBuf<<=1;
+ ShortLZ();
+ }
+ }
+ }
+ UnpWriteBuf20();
+}
+
+
+#define GetShortLen1(pos) ((pos)==1 ? Buf60+3:ShortLen1[pos])
+#define GetShortLen2(pos) ((pos)==3 ? Buf60+3:ShortLen2[pos])
+
+void Unpack::ShortLZ()
+{
+ static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0};
+ static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe,
+ 0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0};
+ static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0};
+ static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8,
+ 0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0};
+
+
+ unsigned int Length,SaveLength;
+ unsigned int LastDistance;
+ unsigned int Distance;
+ int DistancePlace;
+ NumHuf=0;
+
+ unsigned int BitField=Inp.fgetbits();
+ if (LCount==2)
+ {
+ Inp.faddbits(1);
+ if (BitField >= 0x8000)
+ {
+ CopyString15((unsigned int)LastDist,LastLength);
+ return;
+ }
+ BitField <<= 1;
+ LCount=0;
+ }
+
+ BitField>>=8;
+
+// not thread safe, replaced by GetShortLen1 and GetShortLen2 macro
+// ShortLen1[1]=ShortLen2[3]=Buf60+3;
+
+ if (AvrLn1<37)
+ {
+ for (Length=0;;Length++)
+ if (((BitField^ShortXor1[Length]) & (~(0xff>>GetShortLen1(Length))))==0)
+ break;
+ Inp.faddbits(GetShortLen1(Length));
+ }
+ else
+ {
+ for (Length=0;;Length++)
+ if (((BitField^ShortXor2[Length]) & (~(0xff>>GetShortLen2(Length))))==0)
+ break;
+ Inp.faddbits(GetShortLen2(Length));
+ }
+
+ if (Length >= 9)
+ {
+ if (Length == 9)
+ {
+ LCount++;
+ CopyString15((unsigned int)LastDist,LastLength);
+ return;
+ }
+ if (Length == 14)
+ {
+ LCount=0;
+ Length=DecodeNum(Inp.fgetbits(),STARTL2,DecL2,PosL2)+5;
+ Distance=(Inp.fgetbits()>>1) | 0x8000;
+ Inp.faddbits(15);
+ LastLength=Length;
+ LastDist=Distance;
+ CopyString15(Distance,Length);
+ return;
+ }
+
+ LCount=0;
+ SaveLength=Length;
+ Distance=OldDist[(OldDistPtr-(Length-9)) & 3];
+ Length=DecodeNum(Inp.fgetbits(),STARTL1,DecL1,PosL1)+2;
+ if (Length==0x101 && SaveLength==10)
+ {
+ Buf60 ^= 1;
+ return;
+ }
+ if (Distance > 256)
+ Length++;
+ if (Distance >= MaxDist3)
+ Length++;
+
+ OldDist[OldDistPtr++]=Distance;
+ OldDistPtr = OldDistPtr & 3;
+ LastLength=Length;
+ LastDist=Distance;
+ CopyString15(Distance,Length);
+ return;
+ }
+
+ LCount=0;
+ AvrLn1 += Length;
+ AvrLn1 -= AvrLn1 >> 4;
+
+ DistancePlace=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff;
+ Distance=ChSetA[DistancePlace];
+ if (--DistancePlace != -1)
+ {
+ LastDistance=ChSetA[DistancePlace];
+ ChSetA[DistancePlace+1]=LastDistance;
+ ChSetA[DistancePlace]=Distance;
+ }
+ Length+=2;
+ OldDist[OldDistPtr++] = ++Distance;
+ OldDistPtr = OldDistPtr & 3;
+ LastLength=Length;
+ LastDist=Distance;
+ CopyString15(Distance,Length);
+}
+
+
+void Unpack::LongLZ()
+{
+ unsigned int Length;
+ unsigned int Distance;
+ unsigned int DistancePlace,NewDistancePlace;
+ unsigned int OldAvr2,OldAvr3;
+
+ NumHuf=0;
+ Nlzb+=16;
+ if (Nlzb > 0xff)
+ {
+ Nlzb=0x90;
+ Nhfb >>= 1;
+ }
+ OldAvr2=AvrLn2;
+
+ unsigned int BitField=Inp.fgetbits();
+ if (AvrLn2 >= 122)
+ Length=DecodeNum(BitField,STARTL2,DecL2,PosL2);
+ else
+ if (AvrLn2 >= 64)
+ Length=DecodeNum(BitField,STARTL1,DecL1,PosL1);
+ else
+ if (BitField < 0x100)
+ {
+ Length=BitField;
+ Inp.faddbits(16);
+ }
+ else
+ {
+ for (Length=0;((BitField<> 5;
+
+ BitField=Inp.fgetbits();
+ if (AvrPlcB > 0x28ff)
+ DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
+ else
+ if (AvrPlcB > 0x6ff)
+ DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
+ else
+ DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
+
+ AvrPlcB += DistancePlace;
+ AvrPlcB -= AvrPlcB >> 8;
+ while (1)
+ {
+ Distance = ChSetB[DistancePlace & 0xff];
+ NewDistancePlace = NToPlB[Distance++ & 0xff]++;
+ if (!(Distance & 0xff))
+ CorrHuff(ChSetB,NToPlB);
+ else
+ break;
+ }
+
+ ChSetB[DistancePlace]=ChSetB[NewDistancePlace];
+ ChSetB[NewDistancePlace]=Distance;
+
+ Distance=((Distance & 0xff00) | (Inp.fgetbits() >> 8)) >> 1;
+ Inp.faddbits(7);
+
+ OldAvr3=AvrLn3;
+ if (Length!=1 && Length!=4)
+ if (Length==0 && Distance <= MaxDist3)
+ {
+ AvrLn3++;
+ AvrLn3 -= AvrLn3 >> 8;
+ }
+ else
+ if (AvrLn3 > 0)
+ AvrLn3--;
+ Length+=3;
+ if (Distance >= MaxDist3)
+ Length++;
+ if (Distance <= 256)
+ Length+=8;
+ if (OldAvr3 > 0xb0 || (AvrPlc >= 0x2a00 && OldAvr2 < 0x40))
+ MaxDist3=0x7f00;
+ else
+ MaxDist3=0x2001;
+ OldDist[OldDistPtr++]=Distance;
+ OldDistPtr = OldDistPtr & 3;
+ LastLength=Length;
+ LastDist=Distance;
+ CopyString15(Distance,Length);
+}
+
+
+void Unpack::HuffDecode()
+{
+ unsigned int CurByte,NewBytePlace;
+ unsigned int Length;
+ unsigned int Distance;
+ int BytePlace;
+
+ unsigned int BitField=Inp.fgetbits();
+
+ if (AvrPlc > 0x75ff)
+ BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4);
+ else
+ if (AvrPlc > 0x5dff)
+ BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3);
+ else
+ if (AvrPlc > 0x35ff)
+ BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2);
+ else
+ if (AvrPlc > 0x0dff)
+ BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1);
+ else
+ BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0);
+ BytePlace&=0xff;
+ if (StMode)
+ {
+ if (BytePlace==0 && BitField > 0xfff)
+ BytePlace=0x100;
+ if (--BytePlace==-1)
+ {
+ BitField=Inp.fgetbits();
+ Inp.faddbits(1);
+ if (BitField & 0x8000)
+ {
+ NumHuf=StMode=0;
+ return;
+ }
+ else
+ {
+ Length = (BitField & 0x4000) ? 4 : 3;
+ Inp.faddbits(1);
+ Distance=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2);
+ Distance = (Distance << 5) | (Inp.fgetbits() >> 11);
+ Inp.faddbits(5);
+ CopyString15(Distance,Length);
+ return;
+ }
+ }
+ }
+ else
+ if (NumHuf++ >= 16 && FlagsCnt==0)
+ StMode=1;
+ AvrPlc += BytePlace;
+ AvrPlc -= AvrPlc >> 8;
+ Nhfb+=16;
+ if (Nhfb > 0xff)
+ {
+ Nhfb=0x90;
+ Nlzb >>= 1;
+ }
+
+ Window[UnpPtr++]=(byte)(ChSet[BytePlace]>>8);
+ --DestUnpSize;
+
+ while (1)
+ {
+ CurByte=ChSet[BytePlace];
+ NewBytePlace=NToPl[CurByte++ & 0xff]++;
+ if ((CurByte & 0xff) > 0xa1)
+ CorrHuff(ChSet,NToPl);
+ else
+ break;
+ }
+
+ ChSet[BytePlace]=ChSet[NewBytePlace];
+ ChSet[NewBytePlace]=CurByte;
+}
+
+
+void Unpack::GetFlagsBuf()
+{
+ unsigned int Flags,NewFlagsPlace;
+ unsigned int FlagsPlace=DecodeNum(Inp.fgetbits(),STARTHF2,DecHf2,PosHf2);
+
+ while (1)
+ {
+ Flags=ChSetC[FlagsPlace];
+ FlagBuf=Flags>>8;
+ NewFlagsPlace=NToPlC[Flags++ & 0xff]++;
+ if ((Flags & 0xff) != 0)
+ break;
+ CorrHuff(ChSetC,NToPlC);
+ }
+
+ ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace];
+ ChSetC[NewFlagsPlace]=Flags;
+}
+
+
+void Unpack::UnpInitData15(int Solid)
+{
+ if (!Solid)
+ {
+ AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0;
+ AvrPlc=0x3500;
+ MaxDist3=0x2001;
+ Nhfb=Nlzb=0x80;
+ }
+ FlagsCnt=0;
+ FlagBuf=0;
+ StMode=0;
+ LCount=0;
+ ReadTop=0;
+}
+
+
+void Unpack::InitHuff()
+{
+ for (unsigned int I=0;I<256;I++)
+ {
+ ChSet[I]=ChSetB[I]=I<<8;
+ ChSetA[I]=I;
+ ChSetC[I]=((~I+1) & 0xff)<<8;
+ }
+ memset(NToPl,0,sizeof(NToPl));
+ memset(NToPlB,0,sizeof(NToPlB));
+ memset(NToPlC,0,sizeof(NToPlC));
+ CorrHuff(ChSetB,NToPlB);
+}
+
+
+void Unpack::CorrHuff(ushort *CharSet,byte *NumToPlace)
+{
+ int I,J;
+ for (I=7;I>=0;I--)
+ for (J=0;J<32;J++,CharSet++)
+ *CharSet=(*CharSet & ~0xff) | I;
+ memset(NumToPlace,0,sizeof(NToPl));
+ for (I=6;I>=0;I--)
+ NumToPlace[I]=(7-I)*32;
+}
+
+
+void Unpack::CopyString15(uint Distance,uint Length)
+{
+ DestUnpSize-=Length;
+ while (Length--)
+ {
+ Window[UnpPtr]=Window[(UnpPtr-Distance) & MaxWinMask];
+ UnpPtr=(UnpPtr+1) & MaxWinMask;
+ }
+}
+
+
+uint Unpack::DecodeNum(uint Num,uint StartPos,uint *DecTab,uint *PosTab)
+{
+ int I;
+ for (Num&=0xfff0,I=0;DecTab[I]<=Num;I++)
+ StartPos++;
+ Inp.faddbits(StartPos);
+ return(((Num-(I ? DecTab[I-1]:0))>>(16-StartPos))+PosTab[StartPos]);
+}
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/unpack20.cpp b/desmume/src/windows/File_Extractor/unrar/unpack20.cpp
index 5bba0ef49..f0b8e41e7 100644
--- a/desmume/src/windows/File_Extractor/unrar/unpack20.cpp
+++ b/desmume/src/windows/File_Extractor/unrar/unpack20.cpp
@@ -1,394 +1,372 @@
-// #included by unpack.cpp
-#ifdef RAR_COMMON_HPP
-#include "rar.hpp"
-
-// Presumably these optimizations give similar speedup as those for CopyString in unpack.cpp
-void Unpack::CopyString20(unsigned int Length,unsigned int Distance)
-{
- LastDist=OldDist[OldDistPtr++ & 3]=Distance;
- LastLength=Length;
- DestUnpSize-=Length;
-
- unsigned UnpPtr = this->UnpPtr; // cache in register
- byte* const Window = this->Window; // cache in register
-
- unsigned int DestPtr=UnpPtr-Distance;
- if (UnpPtrUnpPtr += Length;
- if ( Distance < Length ) // can't use memcpy when source and dest overlap
- {
- Window[UnpPtr++]=Window[DestPtr++];
- Window[UnpPtr++]=Window[DestPtr++];
- while (Length>2)
- {
- Length--;
- Window[UnpPtr++]=Window[DestPtr++];
- }
- }
- else
- {
- memcpy( &Window[UnpPtr], &Window[DestPtr], Length );
- }
- }
- else
- {
- while (Length--)
- {
- Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK];
- UnpPtr=(UnpPtr+1) & MAXWINMASK;
- }
- this->UnpPtr = UnpPtr;
- }
-}
-
-
-void Unpack::Unpack20(bool Solid)
-{
- const
- static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
- const
- static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
- const
- static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
- const
- static unsigned char DBits[]= {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
- const
- static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
- const
- static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
- unsigned int Bits;
-
- if (Suspended)
- UnpPtr=WrPtr;
- else
- {
- UnpInitData(Solid);
- if (!UnpReadBuf())
- return;
- if (!Solid)
- if (!ReadTables20())
- return;
- --DestUnpSize;
- }
-
- while (is64plus(DestUnpSize))
- {
- UnpPtr&=MAXWINMASK;
-
- if (InAddr>ReadTop-30)
- if (!UnpReadBuf())
- break;
- if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr)
- {
- OldUnpWriteBuf();
- if (Suspended)
- return;
- }
- if (UnpAudioBlock)
- {
- int AudioNumber=DecodeNumber((struct Decode *)&MD[UnpCurChannel]);
-
- if (AudioNumber==256)
- {
- if (!ReadTables20())
- break;
- continue;
- }
- Window[UnpPtr++]=DecodeAudio(AudioNumber);
- if (++UnpCurChannel==UnpChannels)
- UnpCurChannel=0;
- --DestUnpSize;
- continue;
- }
-
- int Number=DecodeNumber((struct Decode *)&LD);
- if (Number<256)
- {
- Window[UnpPtr++]=(byte)Number;
- --DestUnpSize;
- continue;
- }
- if (Number>269)
- {
- int Length=LDecode[Number-=270]+3;
- if ((Bits=LBits[Number])>0)
- {
- Length+=getbits()>>(16-Bits);
- addbits(Bits);
- }
-
- int DistNumber=DecodeNumber((struct Decode *)&DD);
- unsigned int Distance=DDecode[DistNumber]+1;
- if ((Bits=DBits[DistNumber])>0)
- {
- Distance+=getbits()>>(16-Bits);
- addbits(Bits);
- }
-
- if (Distance>=0x2000)
- {
- Length++;
- if (Distance>=0x40000L)
- Length++;
- }
-
- CopyString20(Length,Distance);
- continue;
- }
- if (Number==269)
- {
- if (!ReadTables20())
- break;
- continue;
- }
- if (Number==256)
- {
- CopyString20(LastLength,LastDist);
- continue;
- }
- if (Number<261)
- {
- unsigned int Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
- int LengthNumber=DecodeNumber((struct Decode *)&RD);
- int Length=LDecode[LengthNumber]+2;
- if ((Bits=LBits[LengthNumber])>0)
- {
- Length+=getbits()>>(16-Bits);
- addbits(Bits);
- }
- if (Distance>=0x101)
- {
- Length++;
- if (Distance>=0x2000)
- {
- Length++;
- if (Distance>=0x40000)
- Length++;
- }
- }
- CopyString20(Length,Distance);
- continue;
- }
- if (Number<270)
- {
- unsigned int Distance=SDDecode[Number-=261]+1;
- if ((Bits=SDBits[Number])>0)
- {
- Distance+=getbits()>>(16-Bits);
- addbits(Bits);
- }
- CopyString20(2,Distance);
- continue;
- }
- }
- ReadLastTables();
- OldUnpWriteBuf();
-}
-
-
-bool Unpack::ReadTables20()
-{
- byte BitLength[BC20];
- unsigned char Table[MC20*4];
- int TableSize,N,I;
- if (InAddr>ReadTop-25)
- if (!UnpReadBuf())
- return(false);
- unsigned int BitField=getbits();
- UnpAudioBlock=(BitField & 0x8000);
-
- if (!(BitField & 0x4000))
- memset(UnpOldTable20,0,sizeof(UnpOldTable20));
- addbits(2);
-
- if (UnpAudioBlock)
- {
- UnpChannels=((BitField>>12) & 3)+1;
- if (UnpCurChannel>=UnpChannels)
- UnpCurChannel=0;
- addbits(2);
- TableSize=MC20*UnpChannels;
- }
- else
- TableSize=NC20+DC20+RC20;
-
- for (I=0;I> 12);
- addbits(4);
- }
- MakeDecodeTables(BitLength,(struct Decode *)&BD,BC20);
- I=0;
- while (IReadTop-5)
- if (!UnpReadBuf())
- return(false);
- int Number=DecodeNumber((struct Decode *)&BD);
- if (Number<16)
- {
- Table[I]=(Number+UnpOldTable20[I]) & 0xf;
- I++;
- }
- else
- if (Number==16)
- {
- N=(getbits() >> 14)+3;
- addbits(2);
- while (N-- > 0 && I> 13)+3;
- addbits(3);
- }
- else
- {
- N=(getbits() >> 9)+11;
- addbits(7);
- }
- while (N-- > 0 && IReadTop)
- return(true);
- if (UnpAudioBlock)
- for (I=0;I=InAddr+5)
- if (UnpAudioBlock)
- {
- if (DecodeNumber((struct Decode *)&MD[UnpCurChannel])==256)
- ReadTables20();
- }
- else
- if (DecodeNumber((struct Decode *)&LD)==269)
- ReadTables20();
-}
-
-
-void Unpack::UnpInitData20(int Solid)
-{
- if (!Solid)
- {
- UnpAudioBlock=UnpChannelDelta=UnpCurChannel=0;
- UnpChannels=1;
-
- memset(AudV,0,sizeof(AudV));
- memset(UnpOldTable20,0,sizeof(UnpOldTable20));
- memset(MD,0,sizeof(MD));
- }
-}
-
-
-byte Unpack::DecodeAudio(int Delta)
-{
- struct AudioVariables *V=&AudV[UnpCurChannel];
- V->ByteCount++;
- V->D4=V->D3;
- V->D3=V->D2;
- V->D2=V->LastDelta-V->D1;
- V->D1=V->LastDelta;
- int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta;
- PCh=(PCh>>3) & 0xFF;
-
- unsigned int Ch=PCh-Delta;
-
- int D=((signed char)Delta)<<3;
-
- V->Dif[0]+=abs(D);
- V->Dif[1]+=abs(D-V->D1);
- V->Dif[2]+=abs(D+V->D1);
- V->Dif[3]+=abs(D-V->D2);
- V->Dif[4]+=abs(D+V->D2);
- V->Dif[5]+=abs(D-V->D3);
- V->Dif[6]+=abs(D+V->D3);
- V->Dif[7]+=abs(D-V->D4);
- V->Dif[8]+=abs(D+V->D4);
- V->Dif[9]+=abs(D-UnpChannelDelta);
- V->Dif[10]+=abs(D+UnpChannelDelta);
-
- UnpChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
- V->LastChar=Ch;
-
- if ((V->ByteCount & 0x1F)==0)
- {
- unsigned int MinDif=V->Dif[0],NumMinDif=0;
- V->Dif[0]=0;
- for (int I=1;IDif)/sizeof(V->Dif[0]);I++)
- {
- if (V->Dif[I]Dif[I];
- NumMinDif=I;
- }
- V->Dif[I]=0;
- }
- switch(NumMinDif)
- {
- case 1:
- if (V->K1>=-16)
- V->K1--;
- break;
- case 2:
- if (V->K1<16)
- V->K1++;
- break;
- case 3:
- if (V->K2>=-16)
- V->K2--;
- break;
- case 4:
- if (V->K2<16)
- V->K2++;
- break;
- case 5:
- if (V->K3>=-16)
- V->K3--;
- break;
- case 6:
- if (V->K3<16)
- V->K3++;
- break;
- case 7:
- if (V->K4>=-16)
- V->K4--;
- break;
- case 8:
- if (V->K4<16)
- V->K4++;
- break;
- case 9:
- if (V->K5>=-16)
- V->K5--;
- break;
- case 10:
- if (V->K5<16)
- V->K5++;
- break;
- }
- }
- return((byte)Ch);
-}
-#endif
+#ifdef RAR_COMMON_HPP
+
+void Unpack::CopyString20(uint Length,uint Distance)
+{
+ LastDist=OldDist[OldDistPtr++ & 3]=Distance;
+ LastLength=Length;
+ DestUnpSize-=Length;
+ CopyString(Length,Distance);
+}
+
+
+void Unpack::Unpack20(bool Solid)
+{
+ static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
+ static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
+ static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040};
+ static unsigned char DBits[]= {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16};
+ static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
+ static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
+ unsigned int Bits;
+
+ if (Suspended)
+ UnpPtr=WrPtr;
+ else
+ {
+ UnpInitData(Solid);
+ if (!UnpReadBuf())
+ return;
+ if (!Solid)
+ if (!ReadTables20())
+ return;
+ --DestUnpSize;
+ }
+
+ while (DestUnpSize>=0)
+ {
+ UnpPtr&=MaxWinMask;
+
+ if (Inp.InAddr>ReadTop-30)
+ if (!UnpReadBuf())
+ break;
+ if (((WrPtr-UnpPtr) & MaxWinMask)<270 && WrPtr!=UnpPtr)
+ {
+ UnpWriteBuf20();
+ if (Suspended)
+ return;
+ }
+ if (UnpAudioBlock)
+ {
+ int AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]);
+
+ if (AudioNumber==256)
+ {
+ if (!ReadTables20())
+ break;
+ continue;
+ }
+ Window[UnpPtr++]=DecodeAudio(AudioNumber);
+ if (++UnpCurChannel==UnpChannels)
+ UnpCurChannel=0;
+ --DestUnpSize;
+ continue;
+ }
+
+ int Number=DecodeNumber(Inp,&BlockTables.LD);
+ if (Number<256)
+ {
+ Window[UnpPtr++]=(byte)Number;
+ --DestUnpSize;
+ continue;
+ }
+ if (Number>269)
+ {
+ int Length=LDecode[Number-=270]+3;
+ if ((Bits=LBits[Number])>0)
+ {
+ Length+=Inp.getbits()>>(16-Bits);
+ Inp.addbits(Bits);
+ }
+
+ int DistNumber=DecodeNumber(Inp,&BlockTables.DD);
+ unsigned int Distance=DDecode[DistNumber]+1;
+ if ((Bits=DBits[DistNumber])>0)
+ {
+ Distance+=Inp.getbits()>>(16-Bits);
+ Inp.addbits(Bits);
+ }
+
+ if (Distance>=0x2000)
+ {
+ Length++;
+ if (Distance>=0x40000L)
+ Length++;
+ }
+
+ CopyString20(Length,Distance);
+ continue;
+ }
+ if (Number==269)
+ {
+ if (!ReadTables20())
+ break;
+ continue;
+ }
+ if (Number==256)
+ {
+ CopyString20(LastLength,LastDist);
+ continue;
+ }
+ if (Number<261)
+ {
+ unsigned int Distance=OldDist[(OldDistPtr-(Number-256)) & 3];
+ int LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
+ int Length=LDecode[LengthNumber]+2;
+ if ((Bits=LBits[LengthNumber])>0)
+ {
+ Length+=Inp.getbits()>>(16-Bits);
+ Inp.addbits(Bits);
+ }
+ if (Distance>=0x101)
+ {
+ Length++;
+ if (Distance>=0x2000)
+ {
+ Length++;
+ if (Distance>=0x40000)
+ Length++;
+ }
+ }
+ CopyString20(Length,Distance);
+ continue;
+ }
+ if (Number<270)
+ {
+ unsigned int Distance=SDDecode[Number-=261]+1;
+ if ((Bits=SDBits[Number])>0)
+ {
+ Distance+=Inp.getbits()>>(16-Bits);
+ Inp.addbits(Bits);
+ }
+ CopyString20(2,Distance);
+ continue;
+ }
+ }
+ ReadLastTables();
+ UnpWriteBuf20();
+}
+
+
+void Unpack::UnpWriteBuf20()
+{
+ if (UnpPtr!=WrPtr)
+ UnpSomeRead=true;
+ if (UnpPtrUnpWrite(&Window[WrPtr],-(int)WrPtr & MaxWinMask);
+ UnpIO->UnpWrite(Window,UnpPtr);
+ UnpAllBuf=true;
+ }
+ else
+ UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr);
+ WrPtr=UnpPtr;
+}
+
+
+bool Unpack::ReadTables20()
+{
+ byte BitLength[BC20];
+ byte Table[MC20*4];
+ int TableSize,N,I;
+ if (Inp.InAddr>ReadTop-25)
+ if (!UnpReadBuf())
+ return(false);
+ uint BitField=Inp.getbits();
+ UnpAudioBlock=(BitField & 0x8000);
+
+ if (!(BitField & 0x4000))
+ memset(UnpOldTable20,0,sizeof(UnpOldTable20));
+ Inp.addbits(2);
+
+ if (UnpAudioBlock)
+ {
+ UnpChannels=((BitField>>12) & 3)+1;
+ if (UnpCurChannel>=UnpChannels)
+ UnpCurChannel=0;
+ Inp.addbits(2);
+ TableSize=MC20*UnpChannels;
+ }
+ else
+ TableSize=NC20+DC20+RC20;
+
+ for (I=0;I> 12);
+ Inp.addbits(4);
+ }
+ MakeDecodeTables(BitLength,&BlockTables.BD,BC20);
+ I=0;
+ while (IReadTop-5)
+ if (!UnpReadBuf())
+ return false;
+ int Number=DecodeNumber(Inp,&BlockTables.BD);
+ if (Number<16)
+ {
+ Table[I]=(Number+UnpOldTable20[I]) & 0xf;
+ I++;
+ }
+ else
+ if (Number==16)
+ {
+ N=(Inp.getbits() >> 14)+3;
+ Inp.addbits(2);
+ if (I>0)
+ while (N-- > 0 && I> 13)+3;
+ Inp.addbits(3);
+ }
+ else
+ {
+ N=(Inp.getbits() >> 9)+11;
+ Inp.addbits(7);
+ }
+ while (N-- > 0 && IReadTop)
+ return(true);
+ if (UnpAudioBlock)
+ for (I=0;I=Inp.InAddr+5)
+ if (UnpAudioBlock)
+ {
+ if (DecodeNumber(Inp,&MD[UnpCurChannel])==256)
+ ReadTables20();
+ }
+ else
+ if (DecodeNumber(Inp,&BlockTables.LD)==269)
+ ReadTables20();
+}
+
+
+void Unpack::UnpInitData20(int Solid)
+{
+ if (!Solid)
+ {
+ UnpAudioBlock=UnpChannelDelta=UnpCurChannel=0;
+ UnpChannels=1;
+
+ memset(AudV,0,sizeof(AudV));
+ memset(UnpOldTable20,0,sizeof(UnpOldTable20));
+ memset(MD,0,sizeof(MD));
+ }
+}
+
+
+byte Unpack::DecodeAudio(int Delta)
+{
+ struct AudioVariables *V=&AudV[UnpCurChannel];
+ V->ByteCount++;
+ V->D4=V->D3;
+ V->D3=V->D2;
+ V->D2=V->LastDelta-V->D1;
+ V->D1=V->LastDelta;
+ int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta;
+ PCh=(PCh>>3) & 0xFF;
+
+ unsigned int Ch=PCh-Delta;
+
+ int D=((signed char)Delta)<<3;
+
+ V->Dif[0]+=abs(D);
+ V->Dif[1]+=abs(D-V->D1);
+ V->Dif[2]+=abs(D+V->D1);
+ V->Dif[3]+=abs(D-V->D2);
+ V->Dif[4]+=abs(D+V->D2);
+ V->Dif[5]+=abs(D-V->D3);
+ V->Dif[6]+=abs(D+V->D3);
+ V->Dif[7]+=abs(D-V->D4);
+ V->Dif[8]+=abs(D+V->D4);
+ V->Dif[9]+=abs(D-UnpChannelDelta);
+ V->Dif[10]+=abs(D+UnpChannelDelta);
+
+ UnpChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar);
+ V->LastChar=Ch;
+
+ if ((V->ByteCount & 0x1F)==0)
+ {
+ unsigned int MinDif=V->Dif[0],NumMinDif=0;
+ V->Dif[0]=0;
+ for (int I=1;IDif)/sizeof(V->Dif[0]);I++)
+ {
+ if (V->Dif[I]Dif[I];
+ NumMinDif=I;
+ }
+ V->Dif[I]=0;
+ }
+ switch(NumMinDif)
+ {
+ case 1:
+ if (V->K1>=-16)
+ V->K1--;
+ break;
+ case 2:
+ if (V->K1<16)
+ V->K1++;
+ break;
+ case 3:
+ if (V->K2>=-16)
+ V->K2--;
+ break;
+ case 4:
+ if (V->K2<16)
+ V->K2++;
+ break;
+ case 5:
+ if (V->K3>=-16)
+ V->K3--;
+ break;
+ case 6:
+ if (V->K3<16)
+ V->K3++;
+ break;
+ case 7:
+ if (V->K4>=-16)
+ V->K4--;
+ break;
+ case 8:
+ if (V->K4<16)
+ V->K4++;
+ break;
+ case 9:
+ if (V->K5>=-16)
+ V->K5--;
+ break;
+ case 10:
+ if (V->K5<16)
+ V->K5++;
+ break;
+ }
+ }
+ return((byte)Ch);
+}
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/unpack30.cpp b/desmume/src/windows/File_Extractor/unrar/unpack30.cpp
new file mode 100644
index 000000000..9f41acdda
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/unpack30.cpp
@@ -0,0 +1,840 @@
+#ifdef RAR_COMMON_HPP
+
+// We use it instead of direct PPM.DecodeChar call to be sure that
+// we reset PPM structures in case of corrupt data. It is important,
+// because these structures can be invalid after PPM.DecodeChar returned -1.
+inline int Unpack::SafePPMDecodeChar()
+{
+ int Ch=PPM.DecodeChar();
+ if (Ch==-1) // Corrupt PPM data found.
+ {
+ PPM.CleanUp(); // Reset possibly corrupt PPM data structures.
+ UnpBlockType=BLOCK_LZ; // Set faster and more fail proof LZ mode.
+ }
+ return(Ch);
+}
+
+
+void Unpack::Unpack29(bool Solid)
+{
+ static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224};
+ static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5};
+ static int DDecode[DC];
+ static byte DBits[DC];
+ static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12};
+ static unsigned char SDDecode[]={0,4,8,16,32,64,128,192};
+ static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6};
+ unsigned int Bits;
+
+ if (DDecode[1]==0)
+ {
+ int Dist=0,BitLength=0,Slot=0;
+ for (int I=0;IReadBorder)
+ {
+ if (!UnpReadBuf30())
+ break;
+ }
+ if (((WrPtr-UnpPtr) & MaxWinMask)<260 && WrPtr!=UnpPtr)
+ {
+ UnpWriteBuf30();
+ if (WrittenFileSize>DestUnpSize)
+ return;
+ if (Suspended)
+ {
+ FileExtracted=false;
+ return;
+ }
+ }
+ if (UnpBlockType==BLOCK_PPM)
+ {
+ // Here speed is critical, so we do not use SafePPMDecodeChar,
+ // because sometimes even the inline function can introduce
+ // some additional penalty.
+ int Ch=PPM.DecodeChar();
+ if (Ch==-1) // Corrupt PPM data found.
+ {
+ PPM.CleanUp(); // Reset possibly corrupt PPM data structures.
+ UnpBlockType=BLOCK_LZ; // Set faster and more fail proof LZ mode.
+ break;
+ }
+ if (Ch==PPMEscChar)
+ {
+ int NextCh=SafePPMDecodeChar();
+ if (NextCh==0) // End of PPM encoding.
+ {
+ if (!ReadTables30())
+ break;
+ continue;
+ }
+ if (NextCh==-1) // Corrupt PPM data found.
+ break;
+ if (NextCh==2) // End of file in PPM mode.
+ break;
+ if (NextCh==3) // Read VM code.
+ {
+ if (!ReadVMCodePPM())
+ break;
+ continue;
+ }
+ if (NextCh==4) // LZ inside of PPM.
+ {
+ unsigned int Distance=0,Length;
+ bool Failed=false;
+ for (int I=0;I<4 && !Failed;I++)
+ {
+ int Ch=SafePPMDecodeChar();
+ if (Ch==-1)
+ Failed=true;
+ else
+ if (I==3)
+ Length=(byte)Ch;
+ else
+ Distance=(Distance<<8)+(byte)Ch;
+ }
+ if (Failed)
+ break;
+
+ CopyString(Length+32,Distance+2);
+ continue;
+ }
+ if (NextCh==5) // One byte distance match (RLE) inside of PPM.
+ {
+ int Length=SafePPMDecodeChar();
+ if (Length==-1)
+ break;
+ CopyString(Length+4,1);
+ continue;
+ }
+ // If we are here, NextCh must be 1, what means that current byte
+ // is equal to our 'escape' byte, so we just store it to Window.
+ }
+ Window[UnpPtr++]=Ch;
+ continue;
+ }
+
+ int Number=DecodeNumber(Inp,&BlockTables.LD);
+ if (Number<256)
+ {
+ Window[UnpPtr++]=(byte)Number;
+ continue;
+ }
+ if (Number>=271)
+ {
+ int Length=LDecode[Number-=271]+3;
+ if ((Bits=LBits[Number])>0)
+ {
+ Length+=Inp.getbits()>>(16-Bits);
+ Inp.addbits(Bits);
+ }
+
+ int DistNumber=DecodeNumber(Inp,&BlockTables.DD);
+ unsigned int Distance=DDecode[DistNumber]+1;
+ if ((Bits=DBits[DistNumber])>0)
+ {
+ if (DistNumber>9)
+ {
+ if (Bits>4)
+ {
+ Distance+=((Inp.getbits()>>(20-Bits))<<4);
+ Inp.addbits(Bits-4);
+ }
+ if (LowDistRepCount>0)
+ {
+ LowDistRepCount--;
+ Distance+=PrevLowDist;
+ }
+ else
+ {
+ int LowDist=DecodeNumber(Inp,&BlockTables.LDD);
+ if (LowDist==16)
+ {
+ LowDistRepCount=LOW_DIST_REP_COUNT-1;
+ Distance+=PrevLowDist;
+ }
+ else
+ {
+ Distance+=LowDist;
+ PrevLowDist=LowDist;
+ }
+ }
+ }
+ else
+ {
+ Distance+=Inp.getbits()>>(16-Bits);
+ Inp.addbits(Bits);
+ }
+ }
+
+ if (Distance>=0x2000)
+ {
+ Length++;
+ if (Distance>=0x40000L)
+ Length++;
+ }
+
+ InsertOldDist(Distance);
+ LastLength=Length;
+ CopyString(Length,Distance);
+ continue;
+ }
+ if (Number==256)
+ {
+ if (!ReadEndOfBlock())
+ break;
+ continue;
+ }
+ if (Number==257)
+ {
+ if (!ReadVMCode())
+ break;
+ continue;
+ }
+ if (Number==258)
+ {
+ if (LastLength!=0)
+ CopyString(LastLength,OldDist[0]);
+ continue;
+ }
+ if (Number<263)
+ {
+ int DistNum=Number-259;
+ unsigned int Distance=OldDist[DistNum];
+ for (int I=DistNum;I>0;I--)
+ OldDist[I]=OldDist[I-1];
+ OldDist[0]=Distance;
+
+ int LengthNumber=DecodeNumber(Inp,&BlockTables.RD);
+ int Length=LDecode[LengthNumber]+2;
+ if ((Bits=LBits[LengthNumber])>0)
+ {
+ Length+=Inp.getbits()>>(16-Bits);
+ Inp.addbits(Bits);
+ }
+ LastLength=Length;
+ CopyString(Length,Distance);
+ continue;
+ }
+ if (Number<272)
+ {
+ unsigned int Distance=SDDecode[Number-=263]+1;
+ if ((Bits=SDBits[Number])>0)
+ {
+ Distance+=Inp.getbits()>>(16-Bits);
+ Inp.addbits(Bits);
+ }
+ InsertOldDist(Distance);
+ LastLength=2;
+ CopyString(2,Distance);
+ continue;
+ }
+ }
+ UnpWriteBuf30();
+}
+
+
+// Return 'false' to quit unpacking the current file or 'true' to continue.
+bool Unpack::ReadEndOfBlock()
+{
+ uint BitField=Inp.getbits();
+ bool NewTable,NewFile=false;
+
+ // "1" - no new file, new table just here.
+ // "00" - new file, no new table.
+ // "01" - new file, new table (in beginning of next file).
+
+ if ((BitField & 0x8000)!=0)
+ {
+ NewTable=true;
+ Inp.addbits(1);
+ }
+ else
+ {
+ NewFile=true;
+ NewTable=(BitField & 0x4000)!=0;
+ Inp.addbits(2);
+ }
+ TablesRead=!NewTable;
+
+ // Quit immediately if "new file" flag is set. If "new table" flag
+ // is present, we'll read the table in beginning of next file
+ // based on 'TablesRead' 'false' value.
+ if (NewFile)
+ return false;
+ return ReadTables30(); // Quit only if we failed to read tables.
+}
+
+
+bool Unpack::ReadVMCode()
+{
+ // Entire VM code is guaranteed to fully present in block defined
+ // by current Huffman table. Compressor checks that VM code does not cross
+ // Huffman block boundaries.
+ unsigned int FirstByte=Inp.getbits()>>8;
+ Inp.addbits(8);
+ int Length=(FirstByte & 7)+1;
+ if (Length==7)
+ {
+ Length=(Inp.getbits()>>8)+7;
+ Inp.addbits(8);
+ }
+ else
+ if (Length==8)
+ {
+ Length=Inp.getbits();
+ Inp.addbits(16);
+ }
+ Array VMCode(Length);
+ for (int I=0;I=ReadTop-1 && !UnpReadBuf30() && I>8;
+ Inp.addbits(8);
+ }
+ return(AddVMCode(FirstByte,&VMCode[0],Length));
+}
+
+
+bool Unpack::ReadVMCodePPM()
+{
+ unsigned int FirstByte=SafePPMDecodeChar();
+ if ((int)FirstByte==-1)
+ return(false);
+ int Length=(FirstByte & 7)+1;
+ if (Length==7)
+ {
+ int B1=SafePPMDecodeChar();
+ if (B1==-1)
+ return(false);
+ Length=B1+7;
+ }
+ else
+ if (Length==8)
+ {
+ int B1=SafePPMDecodeChar();
+ if (B1==-1)
+ return(false);
+ int B2=SafePPMDecodeChar();
+ if (B2==-1)
+ return(false);
+ Length=B1*256+B2;
+ }
+ Array VMCode(Length);
+ for (int I=0;IFilters30.Size() || FiltPos>OldFilterLengths.Size())
+ return(false);
+ LastFilter=FiltPos;
+ bool NewFilter=(FiltPos==Filters30.Size());
+
+ UnpackFilter30 *StackFilter=new UnpackFilter30; // New filter for PrgStack.
+
+ UnpackFilter30 *Filter;
+ if (NewFilter) // New filter code, never used before since VM reset.
+ {
+ if (FiltPos>MAX3_FILTERS)
+ {
+ // Too many different filters, corrupt archive.
+ delete StackFilter;
+ return false;
+ }
+
+ Filters30.Add(1);
+ Filters30[Filters30.Size()-1]=Filter=new UnpackFilter30;
+ StackFilter->ParentFilter=(uint)(Filters30.Size()-1);
+
+ // Reserve one item, where we store the data block length of our new
+ // filter entry. We'll set it to real block length below, after reading
+ // it. But we need to initialize it now, because when processing corrupt
+ // data, we can access this item even before we set it to real value.
+ OldFilterLengths.Push(0);
+ Filter->ExecCount=0;
+ }
+ else // Filter was used in the past.
+ {
+ Filter=Filters30[FiltPos];
+ StackFilter->ParentFilter=FiltPos;
+ Filter->ExecCount++;
+ }
+
+ int EmptyCount=0;
+ for (uint I=0;I0)
+ PrgStack[I]=NULL;
+ }
+ if (EmptyCount==0)
+ {
+ PrgStack.Add(1);
+ EmptyCount=1;
+ }
+ int StackPos=(int)(PrgStack.Size()-EmptyCount);
+ PrgStack[StackPos]=StackFilter;
+ StackFilter->ExecCount=Filter->ExecCount;
+
+ uint BlockStart=RarVM::ReadData(VMCodeInp);
+ if (FirstByte & 0x40)
+ BlockStart+=258;
+ StackFilter->BlockStart=(uint)((BlockStart+UnpPtr)&MaxWinMask);
+ if (FirstByte & 0x20)
+ {
+ StackFilter->BlockLength=RarVM::ReadData(VMCodeInp);
+
+ // Store the last data block length for current filter.
+ OldFilterLengths[FiltPos]=StackFilter->BlockLength;
+ }
+ else
+ {
+ // Set the data block size to same value as the previous block size
+ // for same filter. It is possible on corrupt data to access here a new
+ // and not filled yet item of OldFilterLengths array. This is why above
+ // we set new OldFilterLengths items to zero.
+ StackFilter->BlockLength=FiltPosNextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=BlockStart;
+
+// DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart);
+
+ memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR));
+ StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR;
+ StackFilter->Prg.InitR[4]=StackFilter->BlockLength;
+ StackFilter->Prg.InitR[5]=StackFilter->ExecCount;
+
+ if (FirstByte & 0x10) // set registers to optional parameters if any
+ {
+ unsigned int InitMask=VMCodeInp.fgetbits()>>9;
+ VMCodeInp.faddbits(7);
+ for (int I=0;I<7;I++)
+ if (InitMask & (1<Prg.InitR[I]=RarVM::ReadData(VMCodeInp);
+ }
+
+ if (NewFilter)
+ {
+ uint VMCodeSize=RarVM::ReadData(VMCodeInp);
+ if (VMCodeSize>=0x10000 || VMCodeSize==0)
+ return(false);
+ Array VMCode(VMCodeSize);
+ for (uint I=0;I>8;
+ VMCodeInp.faddbits(8);
+ }
+ VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg);
+ }
+ StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0];
+ StackFilter->Prg.CmdCount=Filter->Prg.CmdCount;
+
+ size_t StaticDataSize=Filter->Prg.StaticData.Size();
+ if (StaticDataSize>0 && StaticDataSizePrg.StaticData.Add(StaticDataSize);
+ memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize);
+ }
+
+ if (StackFilter->Prg.GlobalData.Size()Prg.GlobalData.Reset();
+ StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE);
+ }
+ byte *GlobalData=&StackFilter->Prg.GlobalData[0];
+ for (int I=0;I<7;I++)
+ VM.SetLowEndianValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]);
+ VM.SetLowEndianValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength);
+ VM.SetLowEndianValue((uint *)&GlobalData[0x20],0);
+ VM.SetLowEndianValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount);
+ memset(&GlobalData[0x30],0,16);
+
+ if (FirstByte & 8) // Put the data block passed as parameter if any.
+ {
+ if (VMCodeInp.Overflow(3))
+ return(false);
+ uint DataSize=RarVM::ReadData(VMCodeInp);
+ if (DataSize>VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE)
+ return(false);
+ size_t CurSize=StackFilter->Prg.GlobalData.Size();
+ if (CurSizePrg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize);
+ byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE];
+ for (uint I=0;I>8;
+ VMCodeInp.faddbits(8);
+ }
+ }
+ return(true);
+}
+
+
+bool Unpack::UnpReadBuf30()
+{
+ int DataSize=ReadTop-Inp.InAddr; // Data left to process.
+ if (DataSize<0)
+ return(false);
+ if (Inp.InAddr>BitInput::MAX_SIZE/2)
+ {
+ // If we already processed more than half of buffer, let's move
+ // remaining data into beginning to free more space for new data
+ // and ensure that calling function does not cross the buffer border
+ // even if we did not read anything here. Also it ensures that read size
+ // is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
+ // to make it zero.
+ if (DataSize>0)
+ memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
+ Inp.InAddr=0;
+ ReadTop=DataSize;
+ }
+ else
+ DataSize=ReadTop;
+ int ReadCode=UnpIO->UnpRead(Inp.InBuf+DataSize,BitInput::MAX_SIZE-DataSize);
+ if (ReadCode>0)
+ ReadTop+=ReadCode;
+ ReadBorder=ReadTop-30;
+ return(ReadCode!=-1);
+}
+
+
+void Unpack::UnpWriteBuf30()
+{
+ uint WrittenBorder=(uint)WrPtr;
+ uint WriteSize=(uint)((UnpPtr-WrittenBorder)&MaxWinMask);
+ for (size_t I=0;INextWindow)
+ {
+ flt->NextWindow=false;
+ continue;
+ }
+ unsigned int BlockStart=flt->BlockStart;
+ unsigned int BlockLength=flt->BlockLength;
+ if (((BlockStart-WrittenBorder)&MaxWinMask)ParentFilter]->Prg;
+ VM_PreparedProgram *Prg=&flt->Prg;
+
+ if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
+ {
+ // Copy global data from previous script execution if any.
+ Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
+ memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
+ }
+
+ ExecuteCode(Prg);
+
+ if (Prg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
+ {
+ // Save global data for next script execution.
+ if (ParentPrg->GlobalData.Size()GlobalData.Size())
+ ParentPrg->GlobalData.Alloc(Prg->GlobalData.Size());
+ memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
+ }
+ else
+ ParentPrg->GlobalData.Reset();
+
+ byte *FilteredData=Prg->FilteredData;
+ unsigned int FilteredDataSize=Prg->FilteredDataSize;
+
+ delete PrgStack[I];
+ PrgStack[I]=NULL;
+ while (I+1BlockStart!=BlockStart ||
+ NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow)
+ break;
+
+ // Apply several filters to same data block.
+
+ VM.SetMemory(0,FilteredData,FilteredDataSize);
+
+ VM_PreparedProgram *ParentPrg=&Filters30[NextFilter->ParentFilter]->Prg;
+ VM_PreparedProgram *NextPrg=&NextFilter->Prg;
+
+ if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
+ {
+ // Copy global data from previous script execution if any.
+ NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size());
+ memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
+ }
+
+ ExecuteCode(NextPrg);
+
+ if (NextPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE)
+ {
+ // Save global data for next script execution.
+ if (ParentPrg->GlobalData.Size()GlobalData.Size())
+ ParentPrg->GlobalData.Alloc(NextPrg->GlobalData.Size());
+ memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE);
+ }
+ else
+ ParentPrg->GlobalData.Reset();
+
+ FilteredData=NextPrg->FilteredData;
+ FilteredDataSize=NextPrg->FilteredDataSize;
+ I++;
+ delete PrgStack[I];
+ PrgStack[I]=NULL;
+ }
+ UnpIO->UnpWrite(FilteredData,FilteredDataSize);
+ UnpSomeRead=true;
+ WrittenFileSize+=FilteredDataSize;
+ WrittenBorder=BlockEnd;
+ WriteSize=uint((UnpPtr-WrittenBorder)&MaxWinMask);
+ }
+ else
+ {
+ // Current filter intersects the window write border, so we adjust
+ // the window border to process this filter next time, not now.
+ for (size_t J=I;JNextWindow)
+ flt->NextWindow=false;
+ }
+ WrPtr=WrittenBorder;
+ return;
+ }
+ }
+ }
+
+ UnpWriteArea(WrittenBorder,UnpPtr);
+ WrPtr=UnpPtr;
+}
+
+
+void Unpack::ExecuteCode(VM_PreparedProgram *Prg)
+{
+ if (Prg->GlobalData.Size()>0)
+ {
+ Prg->InitR[6]=(uint)WrittenFileSize;
+ VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x24],(uint)WrittenFileSize);
+ VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x28],(uint)(WrittenFileSize>>32));
+ VM.Execute(Prg);
+ }
+}
+
+
+bool Unpack::ReadTables30()
+{
+ byte BitLength[BC];
+ byte Table[HUFF_TABLE_SIZE30];
+ if (Inp.InAddr>ReadTop-25)
+ if (!UnpReadBuf30())
+ return(false);
+ Inp.faddbits((8-Inp.InBit)&7);
+ uint BitField=Inp.fgetbits();
+ if (BitField & 0x8000)
+ {
+ UnpBlockType=BLOCK_PPM;
+ return(PPM.DecodeInit(this,PPMEscChar));
+ }
+ UnpBlockType=BLOCK_LZ;
+
+ PrevLowDist=0;
+ LowDistRepCount=0;
+
+ if (!(BitField & 0x4000))
+ memset(UnpOldTable,0,sizeof(UnpOldTable));
+ Inp.faddbits(2);
+
+ for (int I=0;I> 12);
+ Inp.faddbits(4);
+ if (Length==15)
+ {
+ int ZeroCount=(byte)(Inp.fgetbits() >> 12);
+ Inp.faddbits(4);
+ if (ZeroCount==0)
+ BitLength[I]=15;
+ else
+ {
+ ZeroCount+=2;
+ while (ZeroCount-- > 0 && IReadTop-5)
+ if (!UnpReadBuf30())
+ return(false);
+ int Number=DecodeNumber(Inp,&BlockTables.BD);
+ if (Number<16)
+ {
+ Table[I]=(Number+UnpOldTable[I]) & 0xf;
+ I++;
+ }
+ else
+ if (Number<18)
+ {
+ int N;
+ if (Number==16)
+ {
+ N=(Inp.fgetbits() >> 13)+3;
+ Inp.faddbits(3);
+ }
+ else
+ {
+ N=(Inp.fgetbits() >> 9)+11;
+ Inp.faddbits(7);
+ }
+ if (I>0)
+ while (N-- > 0 && I> 13)+3;
+ Inp.faddbits(3);
+ }
+ else
+ {
+ N=(Inp.fgetbits() >> 9)+11;
+ Inp.faddbits(7);
+ }
+ while (N-- > 0 && IReadTop)
+ return false;
+ MakeDecodeTables(&Table[0],&BlockTables.LD,NC30);
+ MakeDecodeTables(&Table[NC30],&BlockTables.DD,DC30);
+ MakeDecodeTables(&Table[NC30+DC30],&BlockTables.LDD,LDC30);
+ MakeDecodeTables(&Table[NC30+DC30+LDC30],&BlockTables.RD,RC30);
+ memcpy(UnpOldTable,Table,sizeof(UnpOldTable));
+ return true;
+}
+
+
+void Unpack::UnpInitData30(bool Solid)
+{
+ if (!Solid)
+ {
+ TablesRead=false;
+ memset(UnpOldTable,0,sizeof(UnpOldTable));
+ PPMEscChar=2;
+ UnpBlockType=BLOCK_LZ;
+
+ InitFilters30();
+ }
+}
+
+
+void Unpack::InitFilters30()
+{
+ OldFilterLengths.Reset();
+ LastFilter=0;
+
+ for (size_t I=0;I=ReadBorder)
+ {
+ bool FileDone=false;
+
+ // We use 'while', because for empty block containing only Huffman table,
+ // we'll be on the block border once again just after reading the table.
+ while (Inp.InAddr>BlockHeader.BlockStart+BlockHeader.BlockSize-1 ||
+ Inp.InAddr==BlockHeader.BlockStart+BlockHeader.BlockSize-1 &&
+ Inp.InBit>=BlockHeader.BlockBitSize)
+ {
+ if (BlockHeader.LastBlockInFile)
+ {
+ FileDone=true;
+ break;
+ }
+ if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables))
+ return;
+ }
+ if (FileDone || !UnpReadBuf())
+ break;
+ }
+
+ if (((WriteBorder-UnpPtr) & MaxWinMask)DestUnpSize)
+ return;
+ if (Suspended)
+ {
+ FileExtracted=false;
+ return;
+ }
+ }
+
+ uint MainSlot=DecodeNumber(Inp,&BlockTables.LD);
+ if (MainSlot<256)
+ {
+ if (Fragmented)
+ FragWindow[UnpPtr++]=(byte)MainSlot;
+ else
+ Window[UnpPtr++]=(byte)MainSlot;
+ continue;
+ }
+ if (MainSlot>=262)
+ {
+ uint Length=SlotToLength(Inp,MainSlot-262);
+
+ uint DBits,Distance=1,DistSlot=DecodeNumber(Inp,&BlockTables.DD);
+ if (DistSlot<4)
+ {
+ DBits=0;
+ Distance+=DistSlot;
+ }
+ else
+ {
+ DBits=DistSlot/2 - 1;
+ Distance+=(2 | (DistSlot & 1)) << DBits;
+ }
+
+ if (DBits>0)
+ {
+ if (DBits>=4)
+ {
+ if (DBits>4)
+ {
+ Distance+=((Inp.getbits32()>>(36-DBits))<<4);
+ Inp.addbits(DBits-4);
+ }
+ uint LowDist=DecodeNumber(Inp,&BlockTables.LDD);
+ Distance+=LowDist;
+ }
+ else
+ {
+ Distance+=Inp.getbits32()>>(32-DBits);
+ Inp.addbits(DBits);
+ }
+ }
+
+ if (Distance>0x100)
+ {
+ Length++;
+ if (Distance>0x2000)
+ {
+ Length++;
+ if (Distance>0x40000)
+ Length++;
+ }
+ }
+
+ InsertOldDist(Distance);
+ LastLength=Length;
+ if (Fragmented)
+ FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
+ else
+ CopyString(Length,Distance);
+ continue;
+ }
+ if (MainSlot==256)
+ {
+ UnpackFilter Filter;
+ if (!ReadFilter(Inp,Filter) || !AddFilter(Filter))
+ break;
+ continue;
+ }
+ if (MainSlot==257)
+ {
+ if (LastLength!=0)
+ if (Fragmented)
+ FragWindow.CopyString(LastLength,OldDist[0],UnpPtr,MaxWinMask);
+ else
+ CopyString(LastLength,OldDist[0]);
+ continue;
+ }
+ if (MainSlot<262)
+ {
+ uint DistNum=MainSlot-258;
+ uint Distance=OldDist[DistNum];
+ for (uint I=DistNum;I>0;I--)
+ OldDist[I]=OldDist[I-1];
+ OldDist[0]=Distance;
+
+ uint LengthSlot=DecodeNumber(Inp,&BlockTables.RD);
+ uint Length=SlotToLength(Inp,LengthSlot);
+ LastLength=Length;
+ if (Fragmented)
+ FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
+ else
+ CopyString(Length,Distance);
+ continue;
+ }
+ }
+ UnpWriteBuf();
+}
+
+
+uint Unpack::ReadFilterData(BitInput &Inp)
+{
+ uint ByteCount=(Inp.fgetbits()>>14)+1;
+ Inp.addbits(2);
+
+ uint Data=0;
+ for (uint I=0;I>8)<<(I*8);
+ Inp.addbits(8);
+ }
+ return Data;
+}
+
+
+bool Unpack::ReadFilter(BitInput &Inp,UnpackFilter &Filter)
+{
+ if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-16)
+ if (!UnpReadBuf())
+ return false;
+
+ Filter.BlockStart=ReadFilterData(Inp);
+ Filter.BlockLength=ReadFilterData(Inp);
+
+ Filter.Type=Inp.fgetbits()>>13;
+ Inp.faddbits(3);
+
+ if (Filter.Type==FILTER_DELTA)
+ {
+ Filter.Channels=(Inp.fgetbits()>>11)+1;
+ Inp.faddbits(5);
+ }
+
+ return true;
+}
+
+
+bool Unpack::AddFilter(UnpackFilter &Filter)
+{
+ if (Filters.Size()>=MAX_UNPACK_FILTERS-1)
+ UnpWriteBuf(); // Write data, apply and flush filters.
+
+ // If distance to filter start is that large that due to circular dictionary
+ // mode it points to old not written yet data, then we set 'NextWindow'
+ // flag and process this filter only after processing that older data.
+ Filter.NextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<=Filter.BlockStart;
+
+ Filter.BlockStart=uint((Filter.BlockStart+UnpPtr)&MaxWinMask);
+ Filters.Push(Filter);
+ return true;
+}
+
+
+bool Unpack::UnpReadBuf()
+{
+ int DataSize=ReadTop-Inp.InAddr; // Data left to process.
+ if (DataSize<0)
+ return false;
+ BlockHeader.BlockSize-=Inp.InAddr-BlockHeader.BlockStart;
+ if (Inp.InAddr>BitInput::MAX_SIZE/2)
+ {
+ // If we already processed more than half of buffer, let's move
+ // remaining data into beginning to free more space for new data
+ // and ensure that calling function does not cross the buffer border
+ // even if we did not read anything here. Also it ensures that read size
+ // is not less than CRYPT_BLOCK_SIZE, so we can align it without risk
+ // to make it zero.
+ if (DataSize>0)
+ memmove(Inp.InBuf,Inp.InBuf+Inp.InAddr,DataSize);
+ Inp.InAddr=0;
+ ReadTop=DataSize;
+ }
+ else
+ DataSize=ReadTop;
+ int ReadCode=0;
+ if (BitInput::MAX_SIZE!=DataSize)
+ ReadCode=UnpIO->UnpRead(Inp.InBuf+DataSize,BitInput::MAX_SIZE-DataSize);
+ if (ReadCode>0) // Can be also -1.
+ ReadTop+=ReadCode;
+ ReadBorder=ReadTop-30;
+ BlockHeader.BlockStart=Inp.InAddr;
+ if (BlockHeader.BlockSize!=-1) // '-1' means not defined yet.
+ {
+ // We may need to quit from main extraction loop and read new block header
+ // and trees earlier than data in input buffer ends.
+ ReadBorder=Min(ReadBorder,BlockHeader.BlockStart+BlockHeader.BlockSize-1);
+ }
+ return ReadCode!=-1;
+}
+
+
+void Unpack::UnpWriteBuf()
+{
+ size_t WrittenBorder=WrPtr;
+ size_t FullWriteSize=(UnpPtr-WrittenBorder)&MaxWinMask;
+ size_t WriteSizeLeft=FullWriteSize;
+ bool NotAllFiltersProcessed=false;
+ for (size_t I=0;IType==FILTER_NONE)
+ continue;
+ if (flt->NextWindow)
+ {
+ // Here we skip filters which have block start in current data range
+ // due to address warp around in circular dictionary, but actually
+ // belong to next dictionary block. If such filter start position
+ // is included to current write range, then we reset 'NextWindow' flag.
+ // In fact we can reset it even without such check, because current
+ // implementation seems to guarantee 'NextWindow' flag reset after
+ // buffer writing for all existing filters. But let's keep this check
+ // just in case. Compressor guarantees that distance between
+ // filter block start and filter storing position cannot exceed
+ // the dictionary size. So if we covered the filter block start with
+ // our write here, we can safely assume that filter is applicable
+ // to next block on no further wrap arounds is possible.
+ if (((flt->BlockStart-WrPtr)&MaxWinMask)<=FullWriteSize)
+ flt->NextWindow=false;
+ continue;
+ }
+ uint BlockStart=flt->BlockStart;
+ uint BlockLength=flt->BlockLength;
+ if (((BlockStart-WrittenBorder)&MaxWinMask)0)
+ {
+ uint BlockEnd=(BlockStart+BlockLength)&MaxWinMask;
+
+ FilterSrcMemory.Alloc(BlockLength);
+ byte *Mem=&FilterSrcMemory[0];
+ if (BlockStartUnpWrite(OutMem,BlockLength);
+
+ UnpSomeRead=true;
+ WrittenFileSize+=BlockLength;
+ WrittenBorder=BlockEnd;
+ WriteSizeLeft=(UnpPtr-WrittenBorder)&MaxWinMask;
+ }
+ }
+ else
+ {
+ // Current filter intersects the window write border, so we adjust
+ // the window border to process this filter next time, not now.
+ WrPtr=WrittenBorder;
+
+ // Since Filter start position can only increase, we quit processing
+ // all following filters for this data block and reset 'NextWindow'
+ // flag for them.
+ for (size_t J=I;JType!=FILTER_NONE)
+ flt->NextWindow=false;
+ }
+
+ // Do not write data left after current filter now.
+ NotAllFiltersProcessed=true;
+ break;
+ }
+ }
+ }
+
+ // Remove processed filters from queue.
+ size_t EmptyCount=0;
+ for (size_t I=0;I0)
+ Filters[I-EmptyCount]=Filters[I];
+ if (Filters[I].Type==FILTER_NONE)
+ EmptyCount++;
+ }
+ if (EmptyCount>0)
+ Filters.Alloc(Filters.Size()-EmptyCount);
+
+ if (!NotAllFiltersProcessed) // Only if all filters are processed.
+ {
+ // Write data left after last filter.
+ UnpWriteArea(WrittenBorder,UnpPtr);
+ WrPtr=UnpPtr;
+ }
+
+ // We prefer to write data in blocks not exceeding UNPACK_MAX_WRITE
+ // instead of potentially huge MaxWinSize blocks.
+ WriteBorder=(UnpPtr+Min(MaxWinSize,UNPACK_MAX_WRITE))&MaxWinMask;
+
+ // Choose the nearest among WriteBorder and WrPtr actual written border.
+ // If border is equal to UnpPtr, it means that we have MaxWinSize data ahead.
+ if (WriteBorder==UnpPtr ||
+ WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MaxWinMask)<((WriteBorder-UnpPtr)&MaxWinMask))
+ WriteBorder=WrPtr;
+}
+
+
+byte* Unpack::ApplyFilter(byte *Data,uint DataSize,UnpackFilter *Flt)
+{
+ byte *SrcData=Data;
+ switch(Flt->Type)
+ {
+ case FILTER_E8:
+ case FILTER_E8E9:
+ {
+ uint FileOffset=(uint)WrittenFileSize;
+
+ const int FileSize=0x1000000;
+ byte CmpByte2=Flt->Type==FILTER_E8E9 ? 0xe9:0xe8;
+ for (uint CurPos=0;(int)CurPos<(int)DataSize-4;)
+ {
+ byte CurByte=*(Data++);
+ CurPos++;
+ if (CurByte==0xe8 || CurByte==CmpByte2)
+ {
+ uint Offset=(CurPos+FileOffset)%FileSize;
+ uint Addr=RawGet4(Data);
+
+ // We check 0x80000000 bit instead of '< 0' comparison
+ // not assuming int32 presence or uint size and endianness.
+ if ((Addr & 0x80000000)!=0) // Addr<0
+ {
+ if (((Addr+Offset) & 0x80000000)==0) // Addr+Offset>=0
+ RawPut4(Addr+FileSize,Data);
+ }
+ else
+ if (((Addr-FileSize) & 0x80000000)!=0) // Addr>8);
+ D[2]=(byte)(Offset>>16);
+ }
+ }
+ }
+ return SrcData;
+ case FILTER_DELTA:
+ {
+ uint Channels=Flt->Channels,SrcPos=0;
+
+ FilterDstMemory.Alloc(DataSize);
+ byte *DstData=&FilterDstMemory[0];
+
+ // Bytes from same channels are grouped to continual data blocks,
+ // so we need to place them back to their interleaving positions.
+ for (uint CurChannel=0;CurChannel0)
+ {
+ size_t BlockSize=FragWindow.GetBlockSize(StartPtr,SizeToWrite);
+ UnpWriteData(&FragWindow[StartPtr],BlockSize);
+ SizeToWrite-=BlockSize;
+ StartPtr=(StartPtr+BlockSize) & MaxWinMask;
+ }
+ }
+ else
+ if (EndPtr=DestUnpSize)
+ return;
+ size_t WriteSize=Size;
+ int64 LeftToWrite=DestUnpSize-WrittenFileSize;
+ if ((int64)WriteSize>LeftToWrite)
+ WriteSize=(size_t)LeftToWrite;
+ UnpIO->UnpWrite(Data,WriteSize);
+ WrittenFileSize+=Size;
+}
+
+
+bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header)
+{
+ Header.HeaderSize=0;
+
+ if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-7)
+ if (!UnpReadBuf())
+ return false;
+ Inp.faddbits((8-Inp.InBit)&7);
+
+ byte BlockFlags=Inp.fgetbits()>>8;
+ Inp.faddbits(8);
+ uint ByteCount=((BlockFlags>>3)&3)+1; // Block size byte count.
+
+ if (ByteCount==4)
+ return false;
+
+ Header.HeaderSize=2+ByteCount;
+
+ Header.BlockBitSize=(BlockFlags&7)+1;
+
+ byte SavedCheckSum=Inp.fgetbits()>>8;
+ Inp.faddbits(8);
+
+ int BlockSize=0;
+ for (uint I=0;I>8)<<(I*8);
+ Inp.addbits(8);
+ }
+
+ Header.BlockSize=BlockSize;
+ byte CheckSum=byte(0x5a^BlockFlags^BlockSize^(BlockSize>>8)^(BlockSize>>16));
+ if (CheckSum!=SavedCheckSum)
+ return false;
+
+ Header.BlockStart=Inp.InAddr;
+ ReadBorder=Min(ReadBorder,Header.BlockStart+Header.BlockSize-1);
+
+ Header.LastBlockInFile=(BlockFlags & 0x40)!=0;
+ Header.TablePresent=(BlockFlags & 0x80)!=0;
+ return true;
+}
+
+
+bool Unpack::ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables)
+{
+ if (!Header.TablePresent)
+ return true;
+
+ if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-25)
+ if (!UnpReadBuf())
+ return false;
+
+ byte BitLength[BC];
+ for (int I=0;I> 12);
+ Inp.faddbits(4);
+ if (Length==15)
+ {
+ int ZeroCount=(byte)(Inp.fgetbits() >> 12);
+ Inp.faddbits(4);
+ if (ZeroCount==0)
+ BitLength[I]=15;
+ else
+ {
+ ZeroCount+=2;
+ while (ZeroCount-- > 0 && IReadTop-5)
+ if (!UnpReadBuf())
+ return(false);
+ int Number=DecodeNumber(Inp,&Tables.BD);
+ if (Number<16)
+ {
+ Table[I]=Number;
+ I++;
+ }
+ else
+ if (Number<18)
+ {
+ int N;
+ if (Number==16)
+ {
+ N=(Inp.fgetbits() >> 13)+3;
+ Inp.faddbits(3);
+ }
+ else
+ {
+ N=(Inp.fgetbits() >> 9)+11;
+ Inp.faddbits(7);
+ }
+ if (I>0)
+ while (N-- > 0 && I> 13)+3;
+ Inp.faddbits(3);
+ }
+ else
+ {
+ N=(Inp.fgetbits() >> 9)+11;
+ Inp.faddbits(7);
+ }
+ while (N-- > 0 && IReadTop)
+ return(false);
+ MakeDecodeTables(&Table[0],&Tables.LD,NC);
+ MakeDecodeTables(&Table[NC],&Tables.DD,DC);
+ MakeDecodeTables(&Table[NC+DC],&Tables.LDD,LDC);
+ MakeDecodeTables(&Table[NC+DC+LDC],&Tables.RD,RC);
+ return(true);
+}
+
+
+void Unpack::InitFilters()
+{
+ Filters.Reset();
+}
+
+#endif
diff --git a/desmume/src/windows/File_Extractor/unrar/unpack50frag.cpp b/desmume/src/windows/File_Extractor/unrar/unpack50frag.cpp
new file mode 100644
index 000000000..89718c9d0
--- /dev/null
+++ b/desmume/src/windows/File_Extractor/unrar/unpack50frag.cpp
@@ -0,0 +1,107 @@
+#ifdef RAR_COMMON_HPP
+
+FragmentedWindow::FragmentedWindow()
+{
+ memset(Mem,0,sizeof(Mem));
+ memset(MemSize,0,sizeof(MemSize));
+}
+
+
+FragmentedWindow::~FragmentedWindow()
+{
+ Reset();
+}
+
+
+void FragmentedWindow::Reset()
+{
+ for (uint I=0;I=MinSize)
+ {
+ NewMem=(byte *)malloc(Size);
+ if (NewMem!=NULL)
+ break;
+ Size-=Size/32;
+ }
+ if (NewMem==NULL)
+ throw std::bad_alloc();
+
+ // Clean the window to generate the same output when unpacking corrupt
+ // RAR files, which may access to unused areas of sliding dictionary.
+ memset(NewMem,0,Size);
+
+ Mem[BlockNum]=NewMem;
+ TotalSize+=Size;
+ MemSize[BlockNum]=TotalSize;
+ BlockNum++;
+ }
+ if (TotalSize 0)
+ {
+ (*this)[UnpPtr]=(*this)[SrcPtr++ & MaxWinMask];
+ // We need to have masked UnpPtr after quit from loop, so it must not
+ // be replaced with '(*this)[UnpPtr++ & MaxWinMask]'
+ UnpPtr=(UnpPtr+1) & MaxWinMask;
+ }
+}
+
+
+void FragmentedWindow::CopyData(byte *Dest,size_t WinPos,size_t Size)
+{
+ for (size_t I=0;I=8)
+ {
+ Dest[0]=Src[0];
+ Dest[1]=Src[1];
+ Dest[2]=Src[2];
+ Dest[3]=Src[3];
+ Dest[4]=Src[4];
+ Dest[5]=Src[5];
+ Dest[6]=Src[6];
+ Dest[7]=Src[7];
+
+ Src+=8;
+ Dest+=8;
+ Length-=8;
+ }
+#ifdef FAST_MEMCPY
+ else
+ while (Length>=8)
+ {
+ // This memcpy expanded inline by MSVC. We could also use uint64
+ // assignment, which seems to provide about the same speed.
+ memcpy(Dest,Src,8);
+
+ Src+=8;
+ Dest+=8;
+ Length-=8;
+ }
+#endif
+
+ // Unroll the loop for 0 - 7 bytes left. Note that we use nested "if"s.
+ if (Length>0) { Dest[0]=Src[0];
+ if (Length>1) { Dest[1]=Src[1];
+ if (Length>2) { Dest[2]=Src[2];
+ if (Length>3) { Dest[3]=Src[3];
+ if (Length>4) { Dest[4]=Src[4];
+ if (Length>5) { Dest[5]=Src[5];
+ if (Length>6) { Dest[6]=Src[6]; } } } } } } } // Close all nested "if"s.
+ }
+ else
+ while (Length-- > 0) // Slow copying with all possible precautions.
+ {
+ Window[UnpPtr]=Window[SrcPtr++ & MaxWinMask];
+ // We need to have masked UnpPtr after quit from loop, so it must not
+ // be replaced with 'Window[UnpPtr++ & MaxWinMask]'
+ UnpPtr=(UnpPtr+1) & MaxWinMask;
+ }
+}
+
+
+inline uint Unpack::DecodeNumber(BitInput &Inp,DecodeTable *Dec)
+{
+ // Left aligned 15 bit length raw bit field.
+ uint BitField=Inp.getbits() & 0xfffe;
+
+ if (BitField