Some missing from merge.

Signed-off-by: Salja <salja2012@hotmail.de>
This commit is contained in:
Salja 2012-08-05 14:54:07 +02:00 committed by Antz
parent ec939a5bce
commit f4be15a7af
1895 changed files with 160408 additions and 53601 deletions

View file

@ -11,6 +11,10 @@
cmake_minimum_required (VERSION 2.6)
project (MANGOS_MAP_EXTRACTOR)
message(FATAL_ERROR
"This project CMakeLists.txt outdated after switch use dep/libmpq and need update use existed Visual Studio projects for build."
)
add_subdirectory (libmpq)
add_subdirectory (loadlib)

View file

@ -2,17 +2,19 @@
#include <stdio.h>
#include <deque>
#include <map>
#include <set>
#include <cstdlib>
#ifdef WIN32
#include "direct.h"
#include <windows.h>
#else
#include <dirent.h>
#include <sys/stat.h>
#endif
#include "dbcfile.h"
#include "mpq_libmpq.h"
#include "loadlib/adt.h"
#include "loadlib/wdt.h"
@ -33,7 +35,6 @@
#else
#define OPEN_FLAGS (O_RDONLY | O_BINARY)
#endif
extern ArchiveSet gOpenArchives;
typedef struct
{
@ -47,6 +48,7 @@ uint16 *LiqType;
char output_path[128] = ".";
char input_path[128] = ".";
uint32 maxAreaId = 0;
uint32 CONF_max_build = 0;
//**************************************************
// Extractor options
@ -71,22 +73,13 @@ float CONF_float_to_int16_limit = 2048.0f; // Max accuracy = val/65536
float CONF_flat_height_delta_limit = 0.005f; // If max - min less this value - surface is flat
float CONF_flat_liquid_delta_limit = 0.001f; // If max - min less this value - liquid surface is flat
// List MPQ for extract from
char *CONF_mpq_list[]={
"common.MPQ",
"common-2.MPQ",
"lichking.MPQ",
"expansion.MPQ",
"patch.MPQ",
"patch-2.MPQ",
"patch-3.MPQ",
"patch-4.MPQ",
"patch-5.MPQ",
};
static char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" };
#define LANG_COUNT 12
#define MIN_SUPPORTED_BUILD 15050 // code expect mpq files and mpq content files structure for this build or later
#define EXPANSION_COUNT 3
#define WORLD_COUNT 2
void CreateDir( const std::string& Path )
{
#ifdef WIN32
@ -111,13 +104,15 @@ bool FileExists( const char* FileName )
void Usage(char* prg)
{
printf(
"Usage:\n"\
"%s -[var] [value]\n"\
"-i set input path\n"\
"-o set output path\n"\
"-e extract only MAP(1)/DBC(2) - standard: both(3)\n"\
"-f height stored as int (less map size but lost some accuracy) 1 by default\n"\
"Example: %s -f 0 -i \"c:\\games\\game\"", prg, prg);
"Usage:\n"
"%s -[var] [value]\n"
"-i set input path\n"
"-o set output path\n"
"-e extract only MAP(1)/DBC(2) - standard: both(3)\n"
"-e extract only MAP(1)/DBC(2) - temporary only: DBC(2)\n"
"-f height stored as int (less map size but lost some accuracy) 1 by default\n"
"-b extract data for specific build (at least not greater it from available). Min supported build %u.\n"
"Example: %s -f 0 -i \"c:\\games\\game\"", prg, MIN_SUPPORTED_BUILD, prg);
exit(1);
}
@ -163,25 +158,81 @@ void HandleArgs(int argc, char * arg[])
else
Usage(arg[0]);
break;
case 'b':
if(c + 1 < argc) // all ok
{
CONF_max_build = atoi(arg[(c++) + 1]);
if (CONF_max_build < MIN_SUPPORTED_BUILD)
Usage(arg[0]);
}
else
Usage(arg[0]);
break;
default:
Usage(arg[0]);
break;
}
}
}
void AppendDBCFileListTo(HANDLE mpqHandle, std::set<std::string>& filelist)
{
SFILE_FIND_DATA findFileData;
HANDLE searchHandle = SFileFindFirstFile(mpqHandle, "*.dbc", &findFileData, NULL);
if (!searchHandle)
return;
filelist.insert(findFileData.cFileName);
while (SFileFindNextFile(searchHandle, &findFileData))
filelist.insert(findFileData.cFileName);
SFileFindClose(searchHandle);
}
void AppendDB2FileListTo(HANDLE mpqHandle, std::set<std::string>& filelist)
{
SFILE_FIND_DATA findFileData;
HANDLE searchHandle = SFileFindFirstFile(mpqHandle, "*.db2", &findFileData, NULL);
if (!searchHandle)
return;
filelist.insert(findFileData.cFileName);
while (SFileFindNextFile(searchHandle, &findFileData))
filelist.insert(findFileData.cFileName);
SFileFindClose(searchHandle);
}
uint32 ReadBuild(int locale)
{
// include build info file also
std::string filename = std::string("component.wow-")+langs[locale]+".txt";
//printf("Read %s file... ", filename.c_str());
MPQFile m(filename.c_str());
if(m.isEof())
HANDLE fileHandle;
if (!OpenNewestFile(filename.c_str(), &fileHandle))
{
printf("Fatal error: Not found %s file!\n", filename.c_str());
exit(1);
}
std::string text = m.getPointer();
m.close();
unsigned int data_size = SFileGetFileSize(fileHandle, NULL);
std::string text;
text.resize(data_size);
if (!SFileReadFile(fileHandle, &text[0], data_size, NULL, NULL))
{
printf("Fatal error: Can't read %s file!\n", filename.c_str());
exit(1);
}
SFileCloseFile(fileHandle);
size_t pos = text.find("version=\"");
size_t pos1 = pos + strlen("version=\"");
@ -201,14 +252,33 @@ uint32 ReadBuild(int locale)
exit(1);
}
if (build < MIN_SUPPORTED_BUILD)
{
printf("Fatal error: tool can correctly extract data only for build %u or later (detected: %u)!\n", MIN_SUPPORTED_BUILD, build);
exit(1);
}
return build;
}
uint32 ReadMapDBC()
uint32 ReadMapDBC(int const locale)
{
printf("Read Map.dbc file... ");
DBCFile dbc("DBFilesClient\\Map.dbc");
HANDLE localeFile;
char localMPQ[512];
sprintf(localMPQ, "%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]);
if (!SFileOpenArchive(localMPQ, 0, MPQ_OPEN_READ_ONLY, &localeFile))
exit(1);
printf("Read Map.dbc file... ");
HANDLE dbcFile;
if (!SFileOpenFileEx(localeFile, "DBFilesClient\\Map.dbc", SFILE_OPEN_PATCHED_FILE, &dbcFile))
{
printf("Fatal error: Cannot find Map.dbc in archive!\n");
exit(1);
}
DBCFile dbc(dbcFile);
if(!dbc.open())
{
printf("Fatal error: Invalid Map.dbc file format!\n");
@ -226,10 +296,24 @@ uint32 ReadMapDBC()
return map_count;
}
void ReadAreaTableDBC()
void ReadAreaTableDBC(int const locale)
{
HANDLE localeFile;
char localMPQ[512];
sprintf(localMPQ, "%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]);
if (!SFileOpenArchive(localMPQ, 0, MPQ_OPEN_READ_ONLY, &localeFile))
exit(1);
printf("Read AreaTable.dbc file...");
DBCFile dbc("DBFilesClient\\AreaTable.dbc");
HANDLE dbcFile;
if (!SFileOpenFileEx(localeFile, "DBFilesClient\\AreaTable.dbc", SFILE_OPEN_PATCHED_FILE, &dbcFile))
{
printf("Fatal error: Cannot find AreaTable.dbc in archive!\n");
exit(1);
}
DBCFile dbc(dbcFile);
if(!dbc.open())
{
@ -250,10 +334,24 @@ void ReadAreaTableDBC()
printf("Done! (%u areas loaded)\n", area_count);
}
void ReadLiquidTypeTableDBC()
void ReadLiquidTypeTableDBC(int const locale)
{
HANDLE localeFile;
char localMPQ[512];
sprintf(localMPQ, "%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]);
if (!SFileOpenArchive(localMPQ, 0, MPQ_OPEN_READ_ONLY, &localeFile))
exit(1);
printf("Read LiquidType.dbc file...");
DBCFile dbc("DBFilesClient\\LiquidType.dbc");
HANDLE dbcFile;
if (!SFileOpenFileEx(localeFile, "DBFilesClient\\LiquidType.dbc", SFILE_OPEN_PATCHED_FILE, &dbcFile))
{
printf("Fatal error: Cannot find LiquidType.dbc in archive!\n");
exit(1);
}
DBCFile dbc(dbcFile);
if(!dbc.open())
{
printf("Fatal error: Invalid LiquidType.dbc file format!\n");
@ -370,16 +468,9 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32
{
ADT_file adt;
if (!adt.loadFile(filename))
if (!adt.loadFile(filename, false))
return false;
adt_MCIN *cells = adt.a_grid->getMCIN();
if (!cells)
{
printf("Can't find cells in '%s'\n", filename);
return false;
}
memset(liquid_show, 0, sizeof(liquid_show));
memset(liquid_type, 0, sizeof(liquid_type));
@ -394,7 +485,7 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
adt_MCNK * cell = cells->getMCNK(i,j);
adt_MCNK * cell = adt.cells[i][j];
uint32 areaid = cell->areaid;
if(areaid && areaid <= maxAreaId)
{
@ -449,7 +540,7 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
adt_MCNK * cell = cells->getMCNK(i,j);
adt_MCNK * cell = adt.cells[i][j];
if (!cell)
continue;
// Height values for triangles stored in order:
@ -691,7 +782,7 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32
{
for(int j=0;j<ADT_CELLS_PER_GRID;j++)
{
adt_MCNK *cell = cells->getMCNK(i, j);
adt_MCNK *cell = adt.cells[i][j];
if (!cell)
continue;
@ -836,7 +927,7 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32
{
for(int j = 0; j < ADT_CELLS_PER_GRID; ++j)
{
adt_MCNK * cell = cells->getMCNK(i,j);
adt_MCNK * cell = adt.cells[i][j];
if(!cell)
continue;
holes[i][j] = cell->holes;
@ -898,18 +989,18 @@ bool ConvertADT(char *filename, char *filename2, int cell_y, int cell_x, uint32
return true;
}
void ExtractMapsFromMpq(uint32 build)
void ExtractMapsFromMpq(uint32 build, const int locale)
{
char mpq_filename[1024];
char output_filename[1024];
char mpq_map_name[1024];
printf("Extracting maps...\n");
printf("\nExtracting maps...\n");
uint32 map_count = ReadMapDBC();
uint32 map_count = ReadMapDBC(locale);
ReadAreaTableDBC();
ReadLiquidTypeTableDBC();
ReadAreaTableDBC(locale);
ReadLiquidTypeTableDBC(locale);
std::string path = output_path;
path += "/maps/";
@ -923,10 +1014,7 @@ void ExtractMapsFromMpq(uint32 build)
sprintf(mpq_map_name, "World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name);
WDT_file wdt;
if (!wdt.loadFile(mpq_map_name, false))
{
// printf("Error loading %s map wdt data\n", map_ids[z].name);
continue;
}
for(uint32 y = 0; y < WDT_MAP_SIZE; ++y)
{
@ -934,6 +1022,7 @@ void ExtractMapsFromMpq(uint32 build)
{
if (!wdt.main->adt_list[y][x].exist)
continue;
sprintf(mpq_filename, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y);
sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x);
ConvertADT(mpq_filename, output_filename, y, x, build);
@ -946,22 +1035,6 @@ void ExtractMapsFromMpq(uint32 build)
delete [] map_ids;
}
bool ExtractFile( char const* mpq_name, std::string const& filename )
{
FILE *output = fopen(filename.c_str(), "wb");
if(!output)
{
printf("Can't create the output file '%s'\n", filename.c_str());
return false;
}
MPQFile m(mpq_name);
if(!m.isEof())
fwrite(m.getPointer(), 1, m.getSize(), output);
fclose(output);
return true;
}
void ExtractDBCFiles(int locale, bool basicLocale)
{
printf("Extracting dbc files...\n");
@ -969,19 +1042,17 @@ void ExtractDBCFiles(int locale, bool basicLocale)
std::set<std::string> dbcfiles;
// get DBC file list
for(ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i)
ArchiveSetBounds archives = GetArchivesBounds();
for(ArchiveSet::const_iterator i = archives.first; i != archives.second;++i)
{
vector<string> files;
(*i)->GetFileListTo(files);
for (vector<string>::iterator iter = files.begin(); iter != files.end(); ++iter)
if (iter->rfind(".dbc") == iter->length() - strlen(".dbc"))
dbcfiles.insert(*iter);
AppendDBCFileListTo(*i, dbcfiles);
AppendDB2FileListTo(*i, dbcfiles);
}
std::string path = output_path;
path += "/dbc/";
CreateDir(path);
if(!basicLocale)
if (!basicLocale)
{
path += langs[locale];
path += "/";
@ -990,60 +1061,169 @@ void ExtractDBCFiles(int locale, bool basicLocale)
// extract Build info file
{
string mpq_name = std::string("component.wow-") + langs[locale] + ".txt";
string filename = path + mpq_name;
std::string mpq_name = std::string("component.wow-") + langs[locale] + ".txt";
std::string filename = path + mpq_name;
ExtractFile(mpq_name.c_str(), filename);
}
// extract DBCs
int count = 0;
for (set<string>::iterator iter = dbcfiles.begin(); iter != dbcfiles.end(); ++iter)
for (std::set<std::string>::iterator iter = dbcfiles.begin(); iter != dbcfiles.end(); ++iter)
{
string filename = path;
std::string filename = path;
filename += (iter->c_str() + strlen("DBFilesClient\\"));
if(ExtractFile(iter->c_str(), filename))
if (ExtractFile(iter->c_str(), filename))
++count;
}
printf("Extracted %u DBC files\n\n", count);
printf("Extracted %u DBC/DB2 files\n\n", count);
}
typedef std::pair<std::string /*full_filename*/, char const* /*locale_prefix*/> UpdatesPair;
typedef std::map<int /*build*/, UpdatesPair> Updates;
void AppendPatchMPQFilesToList(char const* subdir, char const* suffix, char const* section, Updates& updates)
{
char dirname[512];
if (subdir)
sprintf(dirname,"%s/Data/%s", input_path, subdir);
else
sprintf(dirname,"%s/Data", input_path);
char scanname[512];
if (suffix)
sprintf(scanname,"wow-update-%s-%%u.MPQ", suffix);
else
sprintf(scanname,"wow-update-%%u.MPQ");
#ifdef WIN32
char maskname[512];
if (suffix)
sprintf(maskname,"%s/wow-update-%s-*.MPQ", dirname, suffix);
else
sprintf(maskname,"%s/wow-update-*.MPQ", dirname);
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile(maskname, &ffd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
uint32 ubuild = 0;
if (sscanf(ffd.cFileName, scanname, &ubuild) == 1 && (!CONF_max_build || ubuild <= CONF_max_build))
updates[ubuild] = UpdatesPair(ffd.cFileName, section);
}
while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
}
#else
if (DIR *dp = opendir(dirname))
{
int ubuild = 0;
dirent *dirp;
while ((dirp = readdir(dp)) != NULL)
if (sscanf(dirp->d_name, scanname, &ubuild) == 1 && (!CONF_max_build || ubuild <= CONF_max_build))
updates[ubuild] = UpdatesPair(dirp->d_name, section);
closedir(dp);
}
#endif
}
void LoadLocaleMPQFiles(int const locale)
{
char filename[512];
// first base old version of dbc files
sprintf(filename,"%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]);
new MPQArchive(filename);
for(int i = 1; i < 5; ++i)
HANDLE localeMpqHandle;
if (!OpenArchive(filename, &localeMpqHandle))
{
char ext[3] = "";
if(i > 1)
sprintf(ext, "-%i", i);
printf("Error open archive: %s\n\n", filename);
return;
}
sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ", input_path, langs[locale], langs[locale], ext);
if(FileExists(filename))
new MPQArchive(filename);
// prepare sorted list patches in locale dir and Data root
Updates updates;
// now update to newer view, locale
AppendPatchMPQFilesToList(langs[locale], langs[locale], NULL, updates);
// now update to newer view, root
AppendPatchMPQFilesToList(NULL, NULL, langs[locale], updates);
for (Updates::const_iterator itr = updates.begin(); itr != updates.end(); ++itr)
{
if (!itr->second.second)
sprintf(filename,"%s/Data/%s/%s", input_path, langs[locale], itr->second.first.c_str());
else
sprintf(filename,"%s/Data/%s", input_path, itr->second.first.c_str());
//if (!OpenArchive(filename))
if (!SFileOpenPatchArchive(localeMpqHandle, filename, itr->second.second ? itr->second.second : "", 0))
printf("Error open patch archive: %s\n\n", filename);
}
}
void LoadCommonMPQFiles()
void LoadBaseMPQFiles()
{
char filename[512];
int count = sizeof(CONF_mpq_list)/sizeof(char*);
for(int i = 0; i < count; ++i)
{
sprintf(filename, "%s/Data/%s", input_path, CONF_mpq_list[i]);
if(FileExists(filename))
new MPQArchive(filename);
}
}
HANDLE worldMpqHandle;
inline void CloseMPQFiles()
{
for(ArchiveSet::iterator j = gOpenArchives.begin(); j != gOpenArchives.end();++j) (*j)->close();
gOpenArchives.clear();
printf("Loaded MPQ files for map extraction:\n");
for (int i = 1; i <= WORLD_COUNT; i++)
{
sprintf(filename, "%s/Data/World%s.MPQ", input_path, (i == 2 ? "2" : ""));
printf("%s\n", filename);
if (!OpenArchive(filename, &worldMpqHandle))
{
printf("Error open archive: %s\n\n", filename);
return;
}
}
for (int i = 1; i <= EXPANSION_COUNT; i++)
{
sprintf(filename, "%s/Data/Expansion%i.MPQ", input_path, i);
printf("%s\n", filename);
if (!OpenArchive(filename, &worldMpqHandle))
{
printf("Error open archive: %s\n\n", filename);
return;
}
}
// prepare sorted list patches in Data root
Updates updates;
// now update to newer view, root -base
AppendPatchMPQFilesToList(NULL, NULL, "base", updates);
// now update to newer view, root -base
AppendPatchMPQFilesToList(NULL, "base", NULL, updates);
for (Updates::const_iterator itr = updates.begin(); itr != updates.end(); ++itr)
{
sprintf(filename,"%s/Data/%s", input_path, itr->second.first.c_str());
printf("%s\n", filename);
if (!OpenArchive(filename, &worldMpqHandle))
{
printf("Error open patch archive: %s\n\n", filename);
return;
}
}
}
int main(int argc, char * arg[])
@ -1087,7 +1267,7 @@ int main(int argc, char * arg[])
ExtractDBCFiles(i, false);
//Close MPQs
CloseMPQFiles();
CloseArchives();
}
}
@ -1102,14 +1282,14 @@ int main(int argc, char * arg[])
printf("Using locale: %s\n", langs[FirstLocale]);
// Open MPQs
LoadBaseMPQFiles();
LoadLocaleMPQFiles(FirstLocale);
LoadCommonMPQFiles();
// Extract maps
ExtractMapsFromMpq(build);
ExtractMapsFromMpq(build, FirstLocale);
// Close MPQs
CloseMPQFiles();
CloseArchives();
}
return 0;

View file

@ -1,6 +1,11 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ad", "VC100_ad.vcxproj", "{D7552D4F-408F-4F8E-859B-366659150CF4}"
ProjectSection(ProjectDependencies) = postProject
{78424708-1F6E-4D4B-920C-FB6D26847055} = {78424708-1F6E-4D4B-920C-FB6D26847055}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib", "..\..\dep\StormLib\StormLib.vcxproj", "{78424708-1F6E-4D4B-920C-FB6D26847055}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -12,6 +17,10 @@ Global
{D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.Build.0 = Debug|Win32
{D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.ActiveCfg = Release|Win32
{D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.Build.0 = Release|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|Win32.ActiveCfg = DebugAS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|Win32.Build.0 = DebugAS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|Win32.ActiveCfg = ReleaseAS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|Win32.Build.0 = ReleaseAS|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -52,6 +52,7 @@
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">ad_debug</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>
@ -65,7 +66,7 @@
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>libmpq;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\dep\StormLib\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@ -87,11 +88,10 @@
<Culture>0x0419</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>StormLibDAS.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\dep\StormLib\bin\StormLib\$(Platform)\$(Configuration)AS;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>ad_debug.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>./debug/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>LIBCD.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>./ad_debug.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
@ -114,7 +114,7 @@
<ClCompile>
<Optimization>Full</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>libmpq;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\dep\StormLib\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
@ -132,11 +132,10 @@
<Culture>0x0419</Culture>
</ResourceCompile>
<Link>
<AdditionalDependencies>zlib.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>StormLibRAS.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\..\dep\StormLib\bin\StormLib\$(Platform)\$(Configuration)AS;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OutputFile>./ad.exe</OutputFile>
<SuppressStartupBanner>true</SuppressStartupBanner>
<AdditionalLibraryDirectories>./release/;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>LIBC.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<ProgramDatabaseFile>./ad.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
@ -147,36 +146,15 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="loadlib\adt.cpp" />
<ClCompile Include="libmpq\common.cpp" />
<ClCompile Include="dbcfile.cpp" />
<ClCompile Include="libmpq\explode.cpp" />
<ClCompile Include="libmpq\extract.cpp" />
<ClCompile Include="libmpq\huffman.cpp" />
<ClCompile Include="loadlib\loadlib.cpp" />
<ClCompile Include="libmpq\mpq.cpp" />
<ClCompile Include="mpq_libmpq.cpp" />
<ClCompile Include="libmpq\parser.cpp" />
<ClCompile Include="system.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">EnableFastChecks</BasicRuntimeChecks>
<BrowseInformation Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</BrowseInformation>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Full</Optimization>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="libmpq\wave.cpp" />
<ClCompile Include="system.cpp" />
<ClCompile Include="loadlib\wdt.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="loadlib\adt.h" />
<ClInclude Include="libmpq\common.h" />
<ClInclude Include="dbcfile.h" />
<ClInclude Include="libmpq\explode.h" />
<ClInclude Include="libmpq\huffman.h" />
<ClInclude Include="loadlib\loadlib.h" />
<ClInclude Include="libmpq\mpq.h" />
<ClInclude Include="mpq_libmpq.h" />
<ClInclude Include="libmpq\wave.h" />
<ClInclude Include="loadlib\wdt.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View file

@ -14,39 +14,15 @@
<ClCompile Include="loadlib\adt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libmpq\common.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dbcfile.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libmpq\explode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libmpq\extract.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libmpq\huffman.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="loadlib\loadlib.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libmpq\mpq.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mpq_libmpq.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libmpq\parser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="system.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="libmpq\wave.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="loadlib\wdt.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -55,30 +31,12 @@
<ClInclude Include="loadlib\adt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libmpq\common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="dbcfile.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libmpq\explode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libmpq\huffman.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="loadlib\loadlib.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libmpq\mpq.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mpq_libmpq.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="libmpq\wave.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="loadlib\wdt.h">
<Filter>Header Files</Filter>
</ClInclude>

View file

@ -1,6 +1,11 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ad", "VC90_ad.vcproj", "{D7552D4F-408F-4F8E-859B-366659150CF4}"
ProjectSection(ProjectDependencies) = postProject
{78424708-1F6E-4D4B-920C-FB6D26847055} = {78424708-1F6E-4D4B-920C-FB6D26847055}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StormLib", "..\..\dep\StormLib\StormLib.vcproj", "{78424708-1F6E-4D4B-920C-FB6D26847055}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -12,6 +17,10 @@ Global
{D7552D4F-408F-4F8E-859B-366659150CF4}.Debug|Win32.Build.0 = Debug|Win32
{D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.ActiveCfg = Release|Win32
{D7552D4F-408F-4F8E-859B-366659150CF4}.Release|Win32.Build.0 = Release|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|Win32.ActiveCfg = DebugAS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Debug|Win32.Build.0 = DebugAS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|Win32.ActiveCfg = ReleaseAS|Win32
{78424708-1F6E-4D4B-920C-FB6D26847055}.Release|Win32.Build.0 = ReleaseAS|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -49,7 +49,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="libmpq"
AdditionalIncludeDirectories="..\..\dep\StormLib\src"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
@ -78,12 +78,11 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="zlib.lib"
AdditionalDependencies="StormLibDAS.lib"
OutputFile="ad_debug.exe"
LinkIncremental="0"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="./debug/"
IgnoreDefaultLibraryNames="LIBCD.lib"
AdditionalLibraryDirectories="..\..\dep\StormLib\bin\StormLib\$(PlatformName)\$(ConfigurationName)AS"
GenerateDebugInformation="true"
ProgramDatabaseFile="./ad_debug.pdb"
SubSystem="1"
@ -148,7 +147,7 @@
Name="VCCLCompilerTool"
Optimization="3"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="libmpq"
AdditionalIncludeDirectories="..\..\dep\StormLib\src"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
@ -173,12 +172,11 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="zlib.lib"
AdditionalDependencies="StormLibRAS.lib"
OutputFile="./ad.exe"
LinkIncremental="0"
SuppressStartupBanner="true"
AdditionalLibraryDirectories="./release/"
IgnoreDefaultLibraryNames="LIBC.lib"
AdditionalLibraryDirectories="..\..\dep\StormLib\bin\StormLib\$(PlatformName)\$(ConfigurationName)AS"
ProgramDatabaseFile="./ad.pdb"
SubSystem="1"
RandomizedBaseAddress="1"
@ -219,69 +217,17 @@
RelativePath=".\loadlib\adt.cpp"
>
</File>
<File
RelativePath=".\libmpq\common.cpp"
>
</File>
<File
RelativePath=".\dbcfile.cpp"
>
</File>
<File
RelativePath=".\libmpq\explode.cpp"
>
</File>
<File
RelativePath=".\libmpq\extract.cpp"
>
</File>
<File
RelativePath=".\libmpq\huffman.cpp"
>
</File>
<File
RelativePath=".\loadlib\loadlib.cpp"
>
</File>
<File
RelativePath=".\libmpq\mpq.cpp"
>
</File>
<File
RelativePath=".\mpq_libmpq.cpp"
>
</File>
<File
RelativePath=".\libmpq\parser.cpp"
>
</File>
<File
RelativePath="system.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions=""
BasicRuntimeChecks="3"
BrowseInformation="1"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
Optimization="3"
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<File
RelativePath=".\libmpq\wave.cpp"
>
</File>
<File
RelativePath=".\loadlib\wdt.cpp"
@ -296,38 +242,14 @@
RelativePath=".\loadlib\adt.h"
>
</File>
<File
RelativePath=".\libmpq\common.h"
>
</File>
<File
RelativePath=".\dbcfile.h"
>
</File>
<File
RelativePath=".\libmpq\explode.h"
>
</File>
<File
RelativePath=".\libmpq\huffman.h"
>
</File>
<File
RelativePath=".\loadlib\loadlib.h"
>
</File>
<File
RelativePath=".\libmpq\mpq.h"
>
</File>
<File
RelativePath=".\mpq_libmpq.h"
>
</File>
<File
RelativePath=".\libmpq\wave.h"
>
</File>
<File
RelativePath=".\loadlib\wdt.h"
>

Binary file not shown.

Binary file not shown.

View file

@ -1,7 +1,7 @@
#define _CRT_SECURE_NO_DEPRECATE
#include "dbcfile.h"
#include "mpq_libmpq.h"
#include "loadlib/loadlib.h"
DBCFile::DBCFile(const std::string &filename):
filename(filename),
@ -9,43 +9,81 @@ DBCFile::DBCFile(const std::string &filename):
{
}
DBCFile::DBCFile(HANDLE file) : fileHandle(file), data(0)
{
}
bool DBCFile::open()
{
MPQFile f(filename.c_str());
//if (!OpenNewestFile(filename.c_str(), &fileHandle))
// return false;
char header[4];
unsigned int na,nb,es,ss;
if(f.read(header,4)!=4) // Number of records
if (!SFileReadFile(fileHandle, header, 4, NULL, NULL)) // Magic header
{
SFileCloseFile(fileHandle);
return false;
}
if(header[0]!='W' || header[1]!='D' || header[2]!='B' || header[3]!='C')
if (header[0]!='W' || header[1]!='D' || header[2]!='B' || header[3]!='C')
{
SFileCloseFile(fileHandle);
return false;
}
if(f.read(&na,4)!=4) // Number of records
if (!SFileReadFile(fileHandle, &na, 4, NULL, NULL)) // Number of records
{
SFileCloseFile(fileHandle);
return false;
if(f.read(&nb,4)!=4) // Number of fields
}
if (!SFileReadFile(fileHandle, &nb, 4, NULL, NULL)) // Number of fields
{
SFileCloseFile(fileHandle);
return false;
if(f.read(&es,4)!=4) // Size of a record
}
if (!SFileReadFile(fileHandle, &es, 4, NULL, NULL)) // Size of a record
{
SFileCloseFile(fileHandle);
return false;
if(f.read(&ss,4)!=4) // String size
}
if (!SFileReadFile(fileHandle, &ss, 4, NULL, NULL)) // String size
{
SFileCloseFile(fileHandle);
return false;
}
recordSize = es;
recordCount = na;
fieldCount = nb;
stringSize = ss;
if(fieldCount*4 != recordSize)
if (fieldCount * 4 != recordSize)
{
SFileCloseFile(fileHandle);
return false;
}
data = new unsigned char[recordSize*recordCount+stringSize];
stringTable = data + recordSize*recordCount;
size_t data_size = recordSize*recordCount+stringSize;
if(f.read(data,data_size)!=data_size)
if (!SFileReadFile(fileHandle, data, data_size, NULL, NULL))
{
SFileCloseFile(fileHandle);
return false;
f.close();
}
SFileCloseFile(fileHandle);
return true;
}
DBCFile::~DBCFile()
{
delete [] data;

View file

@ -3,10 +3,17 @@
#include <cassert>
#include <string>
#ifdef _DLL
#undef _DLL
#endif
#include "StormLib.h"
class DBCFile
{
public:
DBCFile(const std::string &filename);
DBCFile(HANDLE file);
~DBCFile();
// Open database. It must be openened before it can be used.
@ -107,6 +114,7 @@ public:
size_t getMaxId();
private:
std::string filename;
HANDLE fileHandle;
size_t recordSize;
size_t recordCount;
size_t fieldCount;

Binary file not shown.

View file

@ -1,13 +0,0 @@
# Copyright (C) 2005-2012 MaNGOS project <http://getmangos.com/>
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
add_library (libmpq common.cpp explode.cpp extract.cpp huffman.cpp mpq.cpp parser.cpp wave.cpp )
# link libmpq with zlib
target_link_libraries (libmpq z)

View file

@ -1,792 +0,0 @@
/*
* common.c -- shared functions used by mpq-tools.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: common.c,v 1.12 2004/02/12 00:42:54 mbroemme Exp $
*/
#define _CRT_SECURE_NO_DEPRECATE
//#include <dirent.h>
#include <sys/stat.h>
#ifndef WIN32
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "mpq.h"
#include "common.h"
#include <ctype.h>
unsigned int libmpq_lseek(mpq_archive* mpq_a, unsigned int pos)
{
#ifdef WIN32
return (unsigned int)_lseeki64(mpq_a->fd, pos, SEEK_SET);
#elif defined(__APPLE__)
return (unsigned int)lseek(mpq_a->fd, pos, SEEK_SET);
#else
return (unsigned int)lseek64(mpq_a->fd, pos, SEEK_SET);
#endif
}
/*
* This function decrypts a MPQ block.
*/
int libmpq_decrypt_block(mpq_archive *mpq_a, unsigned int *block, unsigned int length, unsigned int seed1) {
unsigned int seed2 = 0xEEEEEEEE;
unsigned int ch;
/* Round to unsigned int's */
length >>= 2;
while (length-- > 0) {
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = *block ^ (seed1 + seed2);
seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
*block++ = ch;
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function decrypts the hashtable for the
* file informations.
*/
int libmpq_decrypt_hashtable(mpq_archive *mpq_a, unsigned char *pbKey) {
unsigned int seed1 = 0x7FED7FED;
unsigned int seed2 = 0xEEEEEEEE;
unsigned int ch; /* One key character */
unsigned int *pdwTable = (unsigned int *)(mpq_a->hashtable);
unsigned int length = mpq_a->header->hashtablesize * 4;
/* Prepare seeds */
while (*pbKey != 0) {
ch = toupper(*pbKey++);
seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
/* Decrypt it */
seed2 = 0xEEEEEEEE;
while (length-- > 0) {
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = *pdwTable ^ (seed1 + seed2);
seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
*pdwTable++ = ch;
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function decrypts the blocktable.
*/
int libmpq_decrypt_blocktable(mpq_archive *mpq_a, unsigned char *pbKey) {
unsigned int seed1 = 0x7FED7FED;
unsigned int seed2 = 0xEEEEEEEE;
unsigned int ch; /* One key character */
unsigned int *pdwTable = (unsigned int *)(mpq_a->blocktable);
unsigned int length = mpq_a->header->blocktablesize * 4;
/* Prepare seeds */
while(*pbKey != 0) {
ch = toupper(*pbKey++);
seed1 = mpq_a->buf[0x300 + ch] ^ (seed1 + seed2);
seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
}
/* Decrypt it */
seed2 = 0xEEEEEEEE;
while(length-- > 0) {
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = *pdwTable ^ (seed1 + seed2);
seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
*pdwTable++ = ch;
}
return LIBMPQ_TOOLS_SUCCESS;
}
int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp) {
int mpq_size;
int mpq_ht_size;
int mpq_bt_size;
int mpq_blocksize;
int mpq_files;
int mpq_csize;
int mpq_fsize;
int entries;
char listdb_version[10];
char libmpq_version[10];
int listdb_temp_version = 0;
int libmpq_temp_version = 0;
/* first check header and version */
if (libmpq_conf_get_value(fp, "LIBMPQ_VERSION", mpq_a->mpq_l->mpq_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_version))) {
return LIBMPQ_CONF_EFILE_CORRUPT;
} else {
/* copy to temp buffer for removing . characters */
sprintf(listdb_version, (char *)mpq_a->mpq_l->mpq_version);
/* remove . characters from listfile version */
libmpq_conf_delete_char(listdb_version, ".");
/* get libmpq version */
sprintf(libmpq_version, "%i%i%i",LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
/* convert to number */
listdb_temp_version = atoi(listdb_version);
libmpq_temp_version = atoi(libmpq_version);
/* check if installed libmpq version is valid for listfile version */
if ((libmpq_temp_version < listdb_temp_version) || (libmpq_temp_version == 0) || (listdb_temp_version == 0)) {
return LIBMPQ_CONF_EFILE_VERSION;
}
}
/* check listfile header, the following entries must be set */
if (libmpq_conf_get_value(fp, "MPQ_SIZE", &mpq_size, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_HASHTABLE_SIZE", &mpq_ht_size, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_BLOCKTABLE_SIZE", &mpq_bt_size, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_BLOCKSIZE", &mpq_blocksize, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_FILES", &mpq_files, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_COMPRESSED_SIZE", &mpq_csize, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_UNCOMPRESSED_SIZE", &mpq_fsize, LIBMPQ_CONF_TYPE_INT, 0)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_NAME", mpq_a->mpq_l->mpq_name, LIBMPQ_CONF_TYPE_CHAR, PATH_MAX)) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
if (libmpq_conf_get_value(fp, "MPQ_TYPE", mpq_a->mpq_l->mpq_type, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_type))) {
return LIBMPQ_CONF_EFILE_CORRUPT;
}
/* these are optional parameters, if they are empty we set the struct members empty */
libmpq_conf_get_value(fp, "MPQ_GAME", mpq_a->mpq_l->mpq_game, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game));
libmpq_conf_get_value(fp, "MPQ_GAME_VERSION", mpq_a->mpq_l->mpq_game_version, LIBMPQ_CONF_TYPE_CHAR, sizeof(mpq_a->mpq_l->mpq_game_version));
/* check if we found a valid listfile for the given archive */
if (mpq_a->header->hashtablesize == mpq_ht_size && mpq_a->header->blocktablesize == mpq_bt_size && mpq_a->blocksize == mpq_blocksize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_ARCHIVE_SIZE) == mpq_size && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) == mpq_files && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_COMPRESSED_SIZE) == mpq_csize && libmpq_archive_info(mpq_a, LIBMPQ_MPQ_UNCOMPRESSED_SIZE) == mpq_fsize) {
/* check if the filelist is correct */
if (!libmpq_conf_get_array(fp, "FILE_NAMES", (char ***)&mpq_a->mpq_l->mpq_files, &entries)) {
/* we have a corrupt filelist, so return */
return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
} else {
/* now check if filelist entries matches number of files in the archive. */
if (entries != libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES)) {
libmpq_free_listfile((char **)mpq_a->mpq_l->mpq_files);
mpq_a->mpq_l->mpq_files = NULL;
return LIBMPQ_CONF_EFILE_LIST_CORRUPT;
}
}
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function frees up the space reserved by libmpq_get_listfile()
*/
int libmpq_free_listfile(char **filelist) {
int i = 0;
while (filelist[i]) {
free(filelist[i++]);
}
free(filelist);
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function reads the directory and the subdirectories
* of the listfile database and adds a entry to the lisfile
* array.
*/
/*int libmpq_detect_listfile_rec(char path[PATH_MAX], char ***filelist, int *fl_count, int *fl_size) {
char nextpath[PATH_MAX];
DIR *dp = opendir(path);
FILE *fp;
struct dirent *entry;
struct stat statbuf;
char buf[LIBMPQ_CONF_BUFSIZE];
if (dp == NULL) {
return LIBMPQ_CONF_EOPEN_DIR;
} else {
while ((entry = readdir(dp)) != NULL) {
if (strncmp(entry->d_name, ".", 1) == 0 || strncmp(entry->d_name, "..", 2) == 0) {
continue;
}
if (strnlen(path, PATH_MAX) + strnlen(entry->d_name, PATH_MAX) + 2 > sizeof nextpath) {
continue;
}
snprintf(nextpath, PATH_MAX, "%s/%s", path, entry->d_name);
// check if file extension matches listdb file extension
if (strncmp(&entry->d_name[strlen(entry->d_name) - strlen(LIBMPQ_CONF_EXT)], LIBMPQ_CONF_EXT, strlen(LIBMPQ_CONF_EXT)) == 0) {
// check if it is really a listdb file
if ((fp = fopen(nextpath, "r")) != NULL ) {
while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
char *line;
buf[strlen(buf) - 1] = '\0';
// skip whitespace
for (line = buf; isspace(*line); line++) {
continue;
}
// skip empty line
if (line[0] == '\0') {
continue;
}
// skip comments
if (line[0] == '#') {
continue;
}
//search for listdb header; dirty but works :)
if (!strncasecmp(line, LIBMPQ_CONF_HEADER, strlen(LIBMPQ_CONF_HEADER))) {
// set the next filelist entry to a copy of the file path
(*filelist)[(*fl_count)++] = strdup(nextpath);
// increase the array size
if ((*fl_count) == (*fl_size)) {
(*filelist) = realloc((*filelist), ((*fl_size) + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
(*fl_size) += LIBMPQ_CONF_FL_INCREMENT;
}
// header found so we could stop reading the file.
break;
}
}
fclose(fp);
}
}
if (stat(nextpath, &statbuf) < 0) {
continue;
}
// if entry ia a subdirectory, read it
if (S_ISDIR(statbuf.st_mode)) {
libmpq_detect_listfile_rec(nextpath, filelist, fl_count, fl_size);
}
}
closedir(dp);
}
return LIBMPQ_TOOLS_SUCCESS;
}
*/
/*
* This functions tries to get file decryption key. The trick comes from block
* positions which are stored at the begin of each compressed file. We know the
* file size, that means we know number of blocks that means we know the first
* int value in block position. And if we know encrypted and decrypted value,
* we can find the decryption key.
*/
int libmpq_detect_fileseed(mpq_archive *mpq_a, unsigned int *block, unsigned int decrypted) {
unsigned int saveseed1;
unsigned int temp = *block ^ decrypted; /* temp = seed1 + seed2 */
int i = 0;
temp -= 0xEEEEEEEE; /* temp = seed1 + mpq_a->buf[0x400 + (seed1 & 0xFF)] */
for (i = 0; i < 0x100; i++) { /* Try all 255 possibilities */
unsigned int seed1;
unsigned int seed2 = 0xEEEEEEEE;
unsigned int ch;
/* Try the first unsigned int's (We exactly know the value) */
seed1 = temp - mpq_a->buf[0x400 + i];
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = block[0] ^ (seed1 + seed2);
if (ch != decrypted) {
continue;
}
/* Add 1 because we are decrypting block positions */
saveseed1 = seed1 + 1;
/*
* If OK, continue and test the second value. We don't know exactly the value,
* but we know that the second one has lower 16 bits set to zero
* (no compressed block is larger than 0xFFFF bytes)
*/
seed1 = ((~seed1 << 0x15) + 0x11111111) | (seed1 >> 0x0B);
seed2 = ch + seed2 + (seed2 << 5) + 3;
seed2 += mpq_a->buf[0x400 + (seed1 & 0xFF)];
ch = block[1] ^ (seed1 + seed2);
if ((ch & 0xFFFF0000) == 0) {
return saveseed1;
}
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function initialize the decryption buffer
*/
int libmpq_init_buffer(mpq_archive *mpq_a) {
unsigned int seed = 0x00100001;
unsigned int index1 = 0;
unsigned int index2 = 0;
int i;
memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
/* Initialize the decryption buffer. */
for (index1 = 0; index1 < 0x100; index1++) {
for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100) {
unsigned int temp1, temp2;
seed = (seed * 125 + 3) % 0x2AAAAB;
temp1 = (seed & 0xFFFF) << 0x10;
seed = (seed * 125 + 3) % 0x2AAAAB;
temp2 = (seed & 0xFFFF);
mpq_a->buf[index2] = (temp1 | temp2);
}
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This functions fills the mpq_hash structure with the
* hashtable found in the MPQ file. The hashtable will
* be decrypted for later use.
*/
int libmpq_read_hashtable(mpq_archive *mpq_a) {
unsigned int bytes = 0;
int rb = 0;
/*
* Allocate memory. Note that the block table should be as large as the
* hash table. (for later file additions)
*/
mpq_a->hashtable = (mpq_hash *)malloc(sizeof(mpq_hash) * mpq_a->header->hashtablesize);
if (!mpq_a->hashtable) {
return LIBMPQ_EALLOCMEM;
}
/* Read the hash table into the buffer */
bytes = mpq_a->header->hashtablesize * sizeof(mpq_hash);
libmpq_lseek(mpq_a, mpq_a->header->hashtablepos);
rb = _read(mpq_a->fd, mpq_a->hashtable, bytes);
if (rb != bytes) {
return LIBMPQ_EFILE_CORRUPT;
}
/* Decrypt hash table and check if it is correctly decrypted */
mpq_hash *mpq_h_end = mpq_a->hashtable + mpq_a->header->hashtablesize;
mpq_hash *mpq_h = NULL;
libmpq_decrypt_hashtable(mpq_a, (unsigned char *)"(hash table)");
/* Check hash table if is correctly decrypted */
for (mpq_h = mpq_a->hashtable; mpq_h < mpq_h_end; mpq_h++) {
if (mpq_h->locale != 0xFFFFFFFF && (mpq_h->locale & 0xFFFF0000) != 0) {
return LIBMPQ_EFILE_FORMAT;
}
/* Remember the highest block table entry */
if (mpq_h->blockindex < LIBMPQ_HASH_ENTRY_DELETED && mpq_h->blockindex > 0) {
mpq_a->maxblockindex = mpq_h->blockindex;
}
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This functions fills the mpq_block structure with the
* blocktable found in the MPQ file. The blocktable will
* be decrypted for later use.
*
* NOTICE: Some MPQs have decrypted block table, e.g.
* cracked Diablo versions.
*/
int libmpq_read_blocktable(mpq_archive *mpq_a) {
unsigned int bytes = 0;
int rb = 0;
/*
* Allocate memory. Note that the block table should be as large as the
* hash table. (for later file additions)
*/
mpq_a->blocktable = (mpq_block *)malloc(sizeof(mpq_block) * mpq_a->header->hashtablesize);
mpq_a->blockbuf = (unsigned char *)malloc(mpq_a->blocksize);
if (!mpq_a->blocktable || !mpq_a->blockbuf) {
return LIBMPQ_EALLOCMEM;
}
/* Read the block table into the buffer */
bytes = mpq_a->header->blocktablesize * sizeof(mpq_block);
memset(mpq_a->blocktable, 0, mpq_a->header->blocktablesize * sizeof(mpq_block));
libmpq_lseek(mpq_a, mpq_a->header->blocktablepos);
rb = _read(mpq_a->fd, mpq_a->blocktable, bytes);
if (rb != bytes) {
return LIBMPQ_EFILE_CORRUPT;
}
/*
* Decrypt block table. Some MPQs don't have encrypted block table,
* e.g. cracked Diablo version. We have to check if block table is
* already decrypted
*/
mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->maxblockindex + 1;
mpq_block *mpq_b = NULL;
unsigned int archivesize = mpq_a->header->archivesize + mpq_a->mpqpos;
if (mpq_a->header->offset != mpq_a->blocktable->filepos) {
libmpq_decrypt_blocktable(mpq_a, (unsigned char *)"(block table)");
}
for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
if (mpq_b->filepos > archivesize || mpq_b->csize > archivesize) {
if ((mpq_a->flags & LIBMPQ_FLAG_PROTECTED) == 0) {
return LIBMPQ_EFILE_FORMAT;
}
}
mpq_b->filepos += mpq_a->mpqpos;
}
return LIBMPQ_TOOLS_SUCCESS;
}
int libmpq_file_read_block(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int blockpos, char *buffer, unsigned int blockbytes) {
unsigned char *tempbuf = NULL; /* Buffer for reading compressed data from the file */
unsigned int readpos; /* Reading position from the file */
unsigned int toread = 0; /* Number of bytes to read */
unsigned int blocknum; /* Block number (needed for decrypt) */
unsigned int bytesread = 0; /* Total number of bytes read */
unsigned int nblocks; /* Number of blocks to load */
unsigned int i;
/* Test parameters. Block position and block size must be block-aligned, block size nonzero */
if ((blockpos & (mpq_a->blocksize - 1)) || blockbytes == 0) {
return 0;
}
/* Check the end of file */
if ((blockpos + blockbytes) > mpq_f->mpq_b->fsize) {
blockbytes = mpq_f->mpq_b->fsize - blockpos;
}
blocknum = blockpos / mpq_a->blocksize;
nblocks = blockbytes / mpq_a->blocksize;
if (blockbytes % mpq_a->blocksize) {
nblocks++;
}
/* If file has variable block positions, we have to load them */
if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) && mpq_f->blockposloaded == FALSE) {
unsigned int nread;
if (mpq_f->mpq_b->filepos != mpq_a->filepos) {
libmpq_lseek(mpq_a, mpq_f->mpq_b->filepos);
}
/* Read block positions from begin of file. */
nread = (mpq_f->nblocks + 1) * sizeof(int);
nread = _read(mpq_a->fd, mpq_f->blockpos, nread);
/*
* If the archive is protected some way, perform additional check
* Sometimes, the file appears not to be encrypted, but it is.
*/
/*if (mpq_f->blockpos[0] != nread) {
mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
}*/
if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_HAS_METADATA) == 0) {
if (mpq_f->blockpos[0] != nread) {
mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
}
}
/* Decrypt loaded block positions if necessary */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
/* If we don't know the file seed, try to find it. */
if (mpq_f->seed == 0) {
mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
}
/* If we don't know the file seed, sorry but we cannot extract the file. */
if (mpq_f->seed == 0) {
return 0;
}
/* Decrypt block positions */
libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
/*
* Check if the block positions are correctly decrypted
* I don't know why, but sometimes it will result invalid
* block positions on some files.
*/
if (mpq_f->blockpos[0] != nread) {
/* Try once again to detect file seed and decrypt the blocks */
libmpq_lseek(mpq_a, mpq_f->mpq_b->filepos);
nread = _read(mpq_a->fd, mpq_f->blockpos, (mpq_f->nblocks + 1) * sizeof(int));
mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);
/* Check if the block positions are correctly decrypted. */
if (mpq_f->blockpos[0] != nread) {
return 0;
}
}
}
/* Update mpq_f's variables */
mpq_f->blockposloaded = TRUE;
mpq_a->filepos = mpq_f->mpq_b->filepos + nread;
}
/* Get file position and number of bytes to read */
readpos = blockpos;
toread = blockbytes;
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
readpos = mpq_f->blockpos[blocknum];
toread = mpq_f->blockpos[blocknum + nblocks] - readpos;
}
readpos += mpq_f->mpq_b->filepos;
/* Get work buffer for store read data */
if ((tempbuf = (unsigned char *)malloc(toread)) == NULL) {
/* Hmmm... We should add a better error handling here :) */
return 0;
}
/* Set file pointer, if necessary. */
if (mpq_a->filepos != readpos) {
mpq_a->filepos = libmpq_lseek(mpq_a, readpos);
}
/* 15018F87 - Read all requested blocks. */
bytesread = _read(mpq_a->fd, tempbuf, toread);
mpq_a->filepos = readpos + bytesread;
/* Block processing part. */
unsigned int blockstart = 0; /* Index of block start in work buffer. */
unsigned int blocksize = min(blockbytes, mpq_a->blocksize);
unsigned int index = blocknum; /* Current block index. */
bytesread = 0; /* Clear read byte counter */
/* Walk through all blocks. */
for (i = 0; i < nblocks; i++, index++) {
int outlength = mpq_a->blocksize;
/* Get current block length */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
blocksize = mpq_f->blockpos[index + 1] - mpq_f->blockpos[index];
}
/* If block is encrypted, we have to decrypt it. */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
if (mpq_f->seed == 0) {
return 0;
}
libmpq_decrypt_block(mpq_a, (unsigned int *)&tempbuf[blockstart], blocksize, mpq_f->seed + index);
}
/*
* If the block is really compressed, recompress it.
* WARNING: Some block may not be compressed, it can
* only be determined by comparing uncompressed and
* compressed size!
*/
if (blocksize < blockbytes) {
/* Is the file compressed with PKWARE Data Compression Library? */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
libmpq_pkzip_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
}
/*
* Is it a file compressed by Blizzard's multiple compression ?
* Note that Storm.dll v 1.0.9 distributed with Warcraft III
* passes the full path name of the opened archive as the new
* last parameter.
*/
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
libmpq_multi_decompress(buffer, &outlength, (char *)&tempbuf[blockstart], blocksize);
}
bytesread += outlength;
buffer += outlength;
} else {
memcpy(buffer, tempbuf, blocksize);
bytesread += blocksize;
buffer += blocksize;
}
blockstart += blocksize;
}
/* Delete input buffer, if necessary. */
free(tempbuf);
return bytesread;
}
int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread) {
unsigned int bytesread = 0; /* Number of bytes read from the file */
unsigned int blockpos; /* Position in the file aligned to the whole blocks */
unsigned int loaded = 0;
/* File position is greater or equal to file size? */
if (filepos >= mpq_f->mpq_b->fsize) {
return 0;
}
/* If to few bytes in the file remaining, cut them */
if ((mpq_f->mpq_b->fsize - filepos) < toread) {
toread = (mpq_f->mpq_b->fsize - filepos);
}
/* Block position in the file */
blockpos = filepos & ~(mpq_a->blocksize - 1);
/*
* Load the first block, if noncomplete. It may be loaded in the cache buffer.
* We have to check if this block is loaded. If not, load it.
*/
if ((filepos % mpq_a->blocksize) != 0) {
/* Number of bytes remaining in the buffer */
unsigned int tocopy;
unsigned int loaded = mpq_a->blocksize;
/* Check if data are loaded in the cache */
if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
/* Load one MPQ block into archive buffer */
loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
if (loaded == 0) {
return 0;
}
/* Save lastly accessed file and block position for later use */
mpq_f->accessed = TRUE;
mpq_a->blockpos = blockpos;
mpq_a->bufpos = filepos % mpq_a->blocksize;
}
tocopy = loaded - mpq_a->bufpos;
if (tocopy > toread) {
tocopy = toread;
}
/* Copy data from block buffer into target buffer */
memcpy(buffer, mpq_a->blockbuf + mpq_a->bufpos, tocopy);
/* Update pointers */
toread -= tocopy;
bytesread += tocopy;
buffer += tocopy;
blockpos += mpq_a->blocksize;
mpq_a->bufpos += tocopy;
/* If all, return. */
if (toread == 0) {
return bytesread;
}
}
/* Load the whole ("middle") blocks only if there are more or equal one block */
if (toread > mpq_a->blocksize) {
unsigned int blockbytes = toread & ~(mpq_a->blocksize - 1);
loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, buffer, blockbytes);
if (loaded == 0) {
return 0;
}
/* Update pointers */
toread -= loaded;
bytesread += loaded;
buffer += loaded;
blockpos += loaded;
/* If all, return. */
if (toread == 0) {
return bytesread;
}
}
/* Load the terminating block */
if (toread > 0) {
unsigned int tocopy = mpq_a->blocksize;
/* Check if data are loaded in the cache */
if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {
/* Load one MPQ block into archive buffer */
tocopy = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char *)mpq_a->blockbuf, mpq_a->blocksize);
if (tocopy == 0) {
return 0;
}
/* Save lastly accessed file and block position for later use */
mpq_f->accessed = TRUE;
mpq_a->blockpos = blockpos;
}
mpq_a->bufpos = 0;
/* Check number of bytes read */
if (tocopy > toread) {
tocopy = toread;
}
memcpy(buffer, mpq_a->blockbuf, tocopy);
bytesread += tocopy;
mpq_a->bufpos = tocopy;
}
/* Return what we've read */
return bytesread;
}

View file

@ -1,74 +0,0 @@
/*
* common.h -- defines and structs used by the config files.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: common.h,v 1.4 2004/02/12 00:41:55 mbroemme Exp $
*/
#define LIBMPQ_CONF_FL_INCREMENT 512 /* i hope we did not need more :) */
#define LIBMPQ_CONF_EXT ".conf" /* listdb file seems to be valid with this extension */
#define LIBMPQ_CONF_HEADER "LIBMPQ_VERSION" /* listdb file must include this entry to be valid */
#define LIBMPQ_CONF_BUFSIZE 4096 /* maximum number of bytes a line in the file could contain */
#define LIBMPQ_CONF_TYPE_CHAR 1 /* value in config file is from type char */
#define LIBMPQ_CONF_TYPE_INT 2 /* value in config file is from type int */
#define LIBMPQ_CONF_EOPEN_DIR -1 /* error on open directory */
#define LIBMPQ_CONF_EVALUE_NOT_FOUND -2 /* value for the option was not found */
#if defined( __GNUC__ )
#include <sys/types.h>
#include <unistd.h>
#define _lseek lseek
#define _read read
#define _open open
#define _write write
#define _close close
#define _strdup strdup
#ifndef O_BINARY
#define O_BINARY 0
#endif
#else
#include <io.h>
#endif
#ifdef O_LARGEFILE
#define MPQ_FILE_OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE)
#else
#define MPQ_FILE_OPEN_FLAGS (O_RDONLY | O_BINARY)
#endif
#ifndef min
#define min(a, b) ((a < b) ? a : b)
#endif
int libmpq_init_buffer(mpq_archive *mpq_a);
int libmpq_read_hashtable(mpq_archive *mpq_a);
int libmpq_read_blocktable(mpq_archive *mpq_a);
int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread);
int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp);
int libmpq_conf_get_value(FILE *fp, char *search_value, void *return_value, int type, int size);
char *libmpq_conf_delete_char(char *buf, char *chars);
int libmpq_conf_get_array(FILE *fp, char *search_value, char ***filelist, int *entries);
int libmpq_free_listfile(char **filelist);
int libmpq_read_listfile(mpq_archive *mpq_a, FILE *fp);
unsigned int libmpq_lseek(mpq_archive* mpq_a, unsigned int pos);

View file

@ -1,428 +0,0 @@
/*
* explode.c -- explode function of PKWARE data compression library.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of pkware.cpp included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <assert.h>
#include <string.h>
#include "mpq.h"
#include "explode.h"
/* Tables */
static unsigned char pkzip_dist_bits[] = {
0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
};
static unsigned char pkzip_dist_code[] = {
0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
};
static unsigned char pkzip_clen_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
static unsigned short pkzip_len_base[] = {
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
};
static unsigned char pkzip_slen_bits[] = {
0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
};
static unsigned char pkzip_len_code[] = {
0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
};
static unsigned char pkzip_bits_asc[] = {
0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
};
static unsigned short pkzip_code_asc[] = {
0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
};
/* Local variables */
static char copyright[] = "PKWARE Data Compression Library for Win32\r\n"
"Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
"Patent No. 5,051,745\r\n"
"PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
"Version 1.11\r\n";
/* Local functions */
static void libmpq_pkzip_gen_decode_tabs(long count, unsigned char *bits, unsigned char *code, unsigned char *buf2) {
long i;
for (i = count-1; i >= 0; i--) { /* EBX - count */
unsigned long idx1 = code[i];
unsigned long idx2 = 1 << bits[i];
do {
buf2[idx1] = (unsigned char)i;
idx1 += idx2;
} while (idx1 < 0x100);
}
}
static void libmpq_pkzip_gen_asc_tabs(pkzip_data_cmp *mpq_pkzip) {
unsigned short *code_asc = &pkzip_code_asc[0xFF];
unsigned long acc, add;
unsigned short count;
for (count = 0x00FF; code_asc >= pkzip_code_asc; code_asc--, count--) {
unsigned char *bits_asc = mpq_pkzip->bits_asc + count;
unsigned char bits_tmp = *bits_asc;
if (bits_tmp <= 8) {
add = (1 << bits_tmp);
acc = *code_asc;
do {
mpq_pkzip->offs_2c34[acc] = (unsigned char)count;
acc += add;
} while (acc < 0x100);
} else {
if ((acc = (*code_asc & 0xFF)) != 0) {
mpq_pkzip->offs_2c34[acc] = 0xFF;
if (*code_asc & 0x3F) {
bits_tmp -= 4;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 4;
do {
mpq_pkzip->offs_2d34[acc] = (unsigned char)count;
acc += add;
} while (acc < 0x100);
} else {
bits_tmp -= 6;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 6;
do {
mpq_pkzip->offs_2e34[acc] = (unsigned char)count;
acc += add;
} while (acc < 0x80);
}
} else {
bits_tmp -= 8;
*bits_asc = bits_tmp;
add = (1 << bits_tmp);
acc = *code_asc >> 8;
do {
mpq_pkzip->offs_2eb4[acc] = (unsigned char)count;
acc += add;
} while (acc < 0x100);
}
}
}
}
/*
* Skips given number of bits in bit buffer. Result is stored in mpq_pkzip->bit_buf
* If no data in input buffer, returns true
*/
static int libmpq_pkzip_skip_bits(pkzip_data_cmp *mpq_pkzip, unsigned long bits) {
/* If number of bits required is less than number of (bits in the buffer) ? */
if (bits <= mpq_pkzip->extra_bits) {
mpq_pkzip->extra_bits -= bits;
mpq_pkzip->bit_buf >>= bits;
return 0;
}
/* Load input buffer if necessary */
mpq_pkzip->bit_buf >>= mpq_pkzip->extra_bits;
if (mpq_pkzip->in_pos == mpq_pkzip->in_bytes) {
mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf);
if ((mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param)) == 0) {
return 1;
}
mpq_pkzip->in_pos = 0;
}
/* Update bit buffer */
mpq_pkzip->bit_buf |= (mpq_pkzip->in_buf[mpq_pkzip->in_pos++] << 8);
mpq_pkzip->bit_buf >>= (bits - mpq_pkzip->extra_bits);
mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8;
return 0;
}
/*
* Decompress the imploded data using coded literals.
* Returns: 0x000 - 0x0FF : One byte from compressed file.
* 0x100 - 0x305 : Copy previous block (0x100 = 1 byte)
* 0x306 : Out of buffer (?)
*/
static unsigned long libmpq_pkzip_explode_lit(pkzip_data_cmp *mpq_pkzip) {
unsigned long bits; /* Number of bits to skip */
unsigned long value; /* Position in buffers */
/* Test the current bit in byte buffer. If is not set, simply return the next byte. */
if (mpq_pkzip->bit_buf & 1) {
/* Skip current bit in the buffer. */
if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) {
return 0x306;
}
/* The next bits are position in buffers. */
value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)];
/* Get number of bits to skip */
if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->slen_bits[value])) {
return 0x306;
}
if ((bits = mpq_pkzip->clen_bits[value]) != 0) {
unsigned long val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1);
if (libmpq_pkzip_skip_bits(mpq_pkzip, bits)) {
if ((value + val2) != 0x10E) {
return 0x306;
}
}
value = mpq_pkzip->len_base[value] + val2;
}
return value + 0x100; /* Return number of bytes to repeat */
}
/* Skip one bit */
if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) {
return 0x306;
}
/* If the binary compression type, read 8 bits and return them as one byte. */
if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) {
value = mpq_pkzip->bit_buf & 0xFF;
if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) {
return 0x306;
}
return value;
}
/* When ASCII compression ... */
if (mpq_pkzip->bit_buf & 0xFF) {
value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF];
if (value == 0xFF) {
if (mpq_pkzip->bit_buf & 0x3F) {
if (libmpq_pkzip_skip_bits(mpq_pkzip, 4)) {
return 0x306;
}
value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF];
} else {
if (libmpq_pkzip_skip_bits(mpq_pkzip, 6)) {
return 0x306;
}
value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F];
}
}
} else {
if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) {
return 0x306;
}
value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF];
}
return libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value;
}
/*
* Retrieves the number of bytes to move back.
*/
static unsigned long libmpq_pkzip_explode_dist(pkzip_data_cmp *mpq_pkzip, unsigned long length) {
unsigned long pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)];
unsigned long skip = mpq_pkzip->dist_bits[pos]; /* Number of bits to skip */
/* Skip the appropriate number of bits */
if (libmpq_pkzip_skip_bits(mpq_pkzip, skip) == 1) {
return 0;
}
if (length == 2) {
pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03);
if (libmpq_pkzip_skip_bits(mpq_pkzip, 2) == 1) {
return 0;
}
} else {
pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask);
/* Skip the bits */
if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) {
return 0;
}
}
return pos + 1;
}
static unsigned long libmpq_pkzip_expand(pkzip_data_cmp *mpq_pkzip) {
unsigned int copy_bytes; /* Number of bytes to copy */
unsigned long one_byte; /* One byte from compressed file */
unsigned long result;
mpq_pkzip->out_pos = 0x1000; /* Initialize output buffer position */
/* If end of data or error, terminate decompress */
while ((result = one_byte = libmpq_pkzip_explode_lit(mpq_pkzip)) < 0x305) {
/* If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" */
if (one_byte >= 0x100) {
unsigned char *source; /* ECX */
unsigned char *target; /* EDX */
unsigned long copy_length = one_byte - 0xFE;
unsigned long move_back;
/* Get length of data to copy */
if ((move_back = libmpq_pkzip_explode_dist(mpq_pkzip, copy_length)) == 0) {
result = 0x306;
break;
}
/* Target and source pointer */
target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos];
source = target - move_back;
mpq_pkzip->out_pos += copy_length;
while (copy_length-- > 0) {
*target++ = *source++;
}
} else {
mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (unsigned char)one_byte;
}
/*
* If number of extracted bytes has reached 1/2 of output buffer,
* flush output buffer.
*/
if (mpq_pkzip->out_pos >= 0x2000) {
/* Copy decompressed data into user buffer. */
copy_bytes = 0x1000;
mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
/* If there are some data left, keep them alive */
memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000);
mpq_pkzip->out_pos -= 0x1000;
}
}
copy_bytes = mpq_pkzip->out_pos - 0x1000;
mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
return result;
}
/*
* Main exploding function.
*/
unsigned int libmpq_pkzip_explode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param) {
pkzip_data_cmp *mpq_pkzip = (pkzip_data_cmp *)work_buf;
/* Set the whole work buffer to zeros */
memset(mpq_pkzip, 0, sizeof(pkzip_data_cmp));
/* Initialize work struct and load compressed data */
mpq_pkzip->read_buf = read_buf;
mpq_pkzip->write_buf = write_buf;
mpq_pkzip->param = param;
mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf);
mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param);
if (mpq_pkzip->in_bytes <= 4) {
return LIBMPQ_PKZIP_CMP_BAD_DATA;
}
mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0]; /* Get the compression type */
mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1]; /* Get the dictionary size */
mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2]; /* Initialize 16-bit bit buffer */
mpq_pkzip->extra_bits = 0; /* Extra (over 8) bits */
mpq_pkzip->in_pos = 3; /* Position in input buffer */
/* Test for the valid dictionary size */
if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) {
return LIBMPQ_PKZIP_CMP_INV_DICTSIZE;
}
mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits); /* Shifted by 'sar' instruction */
if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) {
if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) {
return LIBMPQ_PKZIP_CMP_INV_MODE;
}
memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc));
libmpq_pkzip_gen_asc_tabs(mpq_pkzip);
}
memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits));
libmpq_pkzip_gen_decode_tabs(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2);
memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits));
memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base));
memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits));
libmpq_pkzip_gen_decode_tabs(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1);
if (libmpq_pkzip_expand(mpq_pkzip) != 0x306) {
return LIBMPQ_PKZIP_CMP_NO_ERROR;
}
return LIBMPQ_PKZIP_CMP_ABORT;
}

View file

@ -1,86 +0,0 @@
/*
* explode.h -- header file for PKWARE data decompression library
* used by mpq-tools.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of pklib.h included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _EXPLODE_H
#define _EXPLODE_H
#define LIBMPQ_PKZIP_EXP_BUFFER_SIZE 12596 /* Size of decompress buffer */
#define LIBMPQ_PKZIP_CMP_BINARY 0 /* Binary compression */
#define LIBMPQ_PKZIP_CMP_ASCII 1 /* Ascii compression */
#define LIBMPQ_PKZIP_CMP_NO_ERROR 0
#define LIBMPQ_PKZIP_CMP_INV_DICTSIZE 1
#define LIBMPQ_PKZIP_CMP_INV_MODE 2
#define LIBMPQ_PKZIP_CMP_BAD_DATA 3
#define LIBMPQ_PKZIP_CMP_ABORT 4
/* Compression structure (size: 12596 bytes on x86-32) */
typedef struct {
unsigned long offs0000; /* 0000 */
unsigned long cmp_type; /* 0004 - Compression type (LIBMPQ_PZIP_CMP_BINARY or LIBMPQ_PKZIP_CMP_ASCII) */
unsigned long out_pos; /* 0008 - Position in output buffer */
unsigned long dsize_bits; /* 000C - Dict size (4, 5, 6 for 0x400, 0x800, 0x1000) */
unsigned long dsize_mask; /* 0010 - Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000) */
unsigned long bit_buf; /* 0014 - 16-bit buffer for processing input data */
unsigned long extra_bits; /* 0018 - Number of extra (above 8) bits in bit buffer */
unsigned int in_pos; /* 001C - Position in in_buf */
unsigned long in_bytes; /* 0020 - Number of bytes in input buffer */
void *param; /* 0024 - Custom parameter */
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); /* 0028 */
void (*write_buf)(char *buf, unsigned int *size, void *param); /* 002C */
unsigned char out_buf[0x2000]; /* 0030 - Output circle buffer. Starting position is 0x1000 */
unsigned char offs_2030[0x204]; /* 2030 - ??? */
unsigned char in_buf[0x800]; /* 2234 - Buffer for data to be decompressed */
unsigned char pos1[0x100]; /* 2A34 - Positions in buffers */
unsigned char pos2[0x100]; /* 2B34 - Positions in buffers */
unsigned char offs_2c34[0x100]; /* 2C34 - Buffer for */
unsigned char offs_2d34[0x100]; /* 2D34 - Buffer for */
unsigned char offs_2e34[0x80]; /* 2EB4 - Buffer for */
unsigned char offs_2eb4[0x100]; /* 2EB4 - Buffer for */
unsigned char bits_asc[0x100]; /* 2FB4 - Buffer for */
unsigned char dist_bits[0x40]; /* 30B4 - Numbers of bytes to skip copied block length */
unsigned char slen_bits[0x10]; /* 30F4 - Numbers of bits for skip copied block length */
unsigned char clen_bits[0x10]; /* 3104 - Number of valid bits for copied block */
unsigned short len_base[0x10]; /* 3114 - Buffer for */
} pkzip_data_cmp;
// __attribute__ ((packed)) pkzip_data_cmp;
typedef struct {
char *in_buf; /* Pointer to input data buffer */
unsigned int in_pos; /* Current offset in input data buffer */
int in_bytes; /* Number of bytes in the input buffer */
char *out_buf; /* Pointer to output data buffer */
unsigned int out_pos; /* Position in the output buffer */
int max_out; /* Maximum number of bytes in the output buffer */
} pkzip_data;
extern unsigned int libmpq_pkzip_explode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param
);
#endif /* _EXPLODE_H */

View file

@ -1,262 +0,0 @@
/*
* extract.c -- global extracting function for all known file compressions
* in a MPQ archive.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define HAVE_LIBZ
#ifdef HAVE_LIBZ
#include <zlib.h>
#endif
#include "mpq.h"
#include "explode.h"
#include "huffman.h"
#include "wave.h"
/*
* Support functions for PKWARE data compression library.
*
* Function loads data from the input buffer. Used by mpq_pkzip
* "implode" and "explode" function as user-defined callback.
* Returns number of bytes loaded.
*
* char * buf - Pointer to a buffer where to store loaded data
* unsigned int * size - Max. number of bytes to read
* void * param - Custom pointer, parameter of implode/explode
*/
static unsigned int libmpq_pkzip_read_input_data(char *buf, unsigned int *size, void *param) {
pkzip_data *info = (pkzip_data *)param;
unsigned int max_avail = (info->in_bytes - info->in_pos);
unsigned int to_read = *size;
/* Check the case when not enough data available */
if (to_read > max_avail) {
to_read = max_avail;
}
/* Load data and increment offsets */
memcpy(buf, info->in_buf + info->in_pos, to_read);
info->in_pos += to_read;
return to_read;
}
/*
* Support functions for PKWARE data compression library.
*
* Function for store output data. Used by mpq_pkzip "implode" and
* "explode" as user-defined callback.
*
* char * buf - Pointer to data to be written
* unsigned int * size - Number of bytes to write
* void * param - Custom pointer, parameter of implode/explode
*/
static void libmpq_pkzip_write_output_data(char *buf, unsigned int *size, void *param) {
pkzip_data *info = (pkzip_data *)param;
unsigned int max_write = (info->max_out - info->out_pos);
unsigned int to_write = *size;
/* Check the case when not enough space in the output buffer */
if (to_write > max_write) {
to_write = max_write;
}
/* Write output data and increments offsets */
memcpy(info->out_buf + info->out_pos, buf, to_write);
info->out_pos += to_write;
}
int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
pkzip_data info; /* Data information */
char *work_buf = (char *)malloc(LIBMPQ_PKZIP_EXP_BUFFER_SIZE); /* mpq_pkzip work buffer */
/* Fill data information structure */
info.in_buf = in_buf;
info.in_pos = 0;
info.in_bytes = in_length;
info.out_buf = out_buf;
info.out_pos = 0;
info.max_out = *out_length;
/* Do the decompression */
libmpq_pkzip_explode(libmpq_pkzip_read_input_data, libmpq_pkzip_write_output_data, work_buf, &info);
*out_length = info.out_pos;
free(work_buf);
return 0;
}
int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length) {
*out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 1);
return 1;
}
int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length) {
*out_length = libmpq_wave_decompress((unsigned char *)out_buf, *out_length, (unsigned char *)in_buf, in_length, 2);
return 1;
}
int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
#ifdef HAVE_LIBZ
z_stream z; /* Stream information for zlib */
int result;
/* Fill the stream structure for zlib */
z.next_in = (Bytef *)in_buf;
z.avail_in = (uInt)in_length;
z.total_in = in_length;
z.next_out = (Bytef *)out_buf;
z.avail_out = *out_length;
z.total_out = 0;
z.zalloc = NULL;
z.zfree = NULL;
/* Initialize the decompression structure. Storm.dll uses zlib version 1.1.3 */
if ((result = inflateInit(&z)) == 0) {
/* Call zlib to decompress the data */
result = inflate(&z, Z_FINISH);
*out_length = z.total_out;
inflateEnd(&z);
}
return result;
#else
memset(out_buf, '0', *out_length);
return 0;
#endif
}
/*
* Huffmann decompression routine. The in_length parameter is not used, but needs
* to be specified due to compatibility reasons.
*
* 1500F5F0
*/
int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length) {
struct huffman_tree *ht = (huffman_tree *)malloc(sizeof(struct huffman_tree));
struct huffman_input_stream *is = (huffman_input_stream *)malloc(sizeof(struct huffman_input_stream));
struct huffman_tree_item *hi = (huffman_tree_item *)malloc(sizeof(struct huffman_tree_item));
memset(ht, 0, sizeof(struct huffman_tree));
memset(is, 0, sizeof(struct huffman_input_stream));
memset(hi, 0, sizeof(struct huffman_tree_item));
/* Initialize input stream */
is->bit_buf = *(unsigned long *)in_buf;
in_buf += sizeof(unsigned long);
is->in_buf = (unsigned char *)in_buf;
is->bits = 32;
/* Initialize the Huffmann tree for decompression */
libmpq_huff_init_tree(ht, hi, LIBMPQ_HUFF_DECOMPRESS);
*out_length = libmpq_huff_do_decompress(ht, is, (unsigned char *)out_buf, *out_length);
free(hi);
free(is);
free(ht);
return 0;
}
int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length) {
char *temp_buf = NULL; /* Temporary storage for decompressed data */
char *work_buf = NULL; /* Where to store decompressed data */
int out_length = *pout_length; /* For storage number of output bytes */
unsigned fDecompressions1; /* Decompressions applied to the block */
unsigned fDecompressions2; /* Just another copy of decompressions applied to the block */
int count = 0; /* Counter for every use */
int entries = (sizeof(dcmp_table) / sizeof(decompress_table));
int i;
/* If the input length is the same as output, do nothing. */
if (in_length == out_length) {
if (in_buf == out_buf) {
return 1;
}
memcpy(out_buf, in_buf, in_length);
return 1;
}
/* Get applied compression types and decrement data length */
fDecompressions1 = fDecompressions2 = (unsigned char)*in_buf++;
in_length--;
/* Search decompression table type and get all types of compression */
for (i = 0; i < entries; i++) {
/* We have to apply this decompression? */
if (fDecompressions1 & dcmp_table[i].mask) {
count++;
}
/* Clear this flag from temporary variable. */
fDecompressions2 &= ~dcmp_table[i].mask;
}
/*
* Check if there is some method unhandled
* (E.g. compressed by future versions)
*/
if (fDecompressions2 != 0) {
printf("Unknown Compression\n");
return 0;
}
/* If there is more than only one compression, we have to allocate extra buffer */
if (count >= 2) {
temp_buf = (char *)malloc(out_length);
}
/* Apply all decompressions */
for (i = 0, count = 0; i < entries; i++) {
/* If not used this kind of compression, skip the loop */
if (fDecompressions1 & dcmp_table[i].mask) {
/* If odd case, use target buffer for output, otherwise use allocated tempbuf */
work_buf = (count++ & 1) ? temp_buf : out_buf;
out_length = *pout_length;
/* Decompress buffer using corresponding function */
dcmp_table[i].decompress(work_buf, &out_length, in_buf, in_length);
/* Move output length to src length for next compression */
in_length = out_length;
in_buf = work_buf;
}
}
/* If output buffer is not the same like target buffer, we have to copy data */
if (work_buf != out_buf) {
memcpy(out_buf, in_buf, out_length);
}
*pout_length = out_length;
/* Delete temporary buffer, if necessary */
if (temp_buf != NULL) {
free(temp_buf);
}
return 1;
}

View file

@ -1,833 +0,0 @@
/*
* huffman.c -- functions do decompress files in MPQ files which
* uses a modified huffman version.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* Differences between C++ and C version:
*
* - Removed the object oriented stuff.
* - Replaced the goto things with some better C code.
*
* This source was adepted from the C++ version of huffman.cpp included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* ShadowFlare <BlakFlare@hotmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdlib.h>
#include <string.h>
#include "mpq.h"
#include "huffman.h"
unsigned char table1502A630[] = {
/* Data for compression type 0x00 */
0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00,
/* Data for compression type 0x01 */
0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05,
0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02,
0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02,
0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04,
0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02,
0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02,
0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03,
0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02,
0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03,
0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B,
0x00, 0x00,
/* Data for compression type 0x02 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04,
0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01,
0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02,
0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01,
0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A,
0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x03 */
0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03,
0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01,
0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03,
0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03,
0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01,
0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11,
0x00, 0x00,
/* Data for compression type 0x04 */
0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x05 */
0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82,
0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37,
0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D,
0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x06 */
0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x07 */
0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Data for compression type 0x08 */
0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10,
0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11,
0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00
};
/* Gets previous Huffman tree item (?) */
struct huffman_tree_item *libmpq_huff_get_prev_item(struct huffman_tree_item *hi, long value) {
if (PTR_INT(hi->prev) < 0) {
return PTR_NOT(hi->prev);
}
if (value < 0) {
value = hi - hi->next->prev;
}
return hi->prev + value;
}
/* 1500BC90 */
static void libmpq_huff_remove_item(struct huffman_tree_item *hi) {
struct huffman_tree_item *temp; /* EDX */
if (hi->next != NULL) {
temp = hi->prev;
if (PTR_INT(temp) <= 0) {
temp = PTR_NOT(temp);
} else {
temp += (hi - hi->next->prev);
}
temp->next = hi->next;
hi->next->prev = hi->prev;
hi->next = hi->prev = NULL;
}
}
static void libmpq_huff_insert_item(struct huffman_tree_item **p_item, struct huffman_tree_item *item, unsigned long where, struct huffman_tree_item *item2) {
struct huffman_tree_item *next = item->next; /* EDI - next to the first item */
struct huffman_tree_item *prev = item->prev; /* ESI - prev to the first item */
struct huffman_tree_item *prev2; /* Pointer to previous item */
long next2; /* Pointer to the next item */
/* The same code like in mpq_huff_remove_item(); */
if (next != 0) { /* If the first item already has next one */
if (PTR_INT(prev) < 0) {
prev = PTR_NOT(prev);
} else {
prev += (item - next->prev);
}
/*
* 150083C1
* Remove the item from the tree
*/
prev->next = next;
next->prev = prev;
/* Invalidate 'prev' and 'next' pointer */
item->next = 0;
item->prev = 0;
}
if (item2 == NULL) { /* EDX - If the second item is not entered, */
item2 = PTR_PTR(&p_item[1]); /* take the first tree item */
}
switch (where) {
case SWITCH_ITEMS: /* Switch the two items */
item->next = item2->next; /* item2->next (Pointer to pointer to first) */
item->prev = item2->next->prev;
item2->next->prev = item;
item2->next = item; /* Set the first item */
return;
case INSERT_ITEM: /* Insert as the last item */
item->next = item2; /* Set next item (or pointer to pointer to first item) */
item->prev = item2->prev; /* Set prev item (or last item in the tree) */
next2 = PTR_INT(p_item[0]); /* Usually NULL */
prev2 = item2->prev; /* Prev item to the second (or last tree item) */
if (PTR_INT(prev2) < 0) {
prev2 = PTR_NOT(prev);
prev2->next = item;
item2->prev = item; /* Next after last item */
return;
}
if (next2 < 0) {
next2 = item2 - item2->next->prev;
}
prev2 += next2;
prev2->next = item;
item2->prev = item; /* Set the next/last item */
return;
default:
return;
}
}
/* Builds Huffman tree. Called with the first 8 bits loaded from input stream. */
static void libmpq_huff_build_tree(struct huffman_tree *ht, unsigned int cmp_type) {
unsigned long max_byte; /* [ESP+10] - The greatest character found in table */
unsigned char *byte_array; /* [ESP+1C] - Pointer to unsigned char in table1502A630 */
unsigned long i; /* egcs in linux doesn't like multiple for loops without an explicit i */
unsigned int found; /* Thats needed to replace the goto stuff from original source :) */
struct huffman_tree_item **p_item; /* [ESP+14] - Pointer to Huffman tree item pointer array */
struct huffman_tree_item *child1;
/* Loop while pointer has a negative value. */
while (PTR_INT(ht->last) > 0) { /* ESI - Last entry */
struct huffman_tree_item *temp; /* EAX */
if (ht->last->next != NULL) { /* ESI->next */
libmpq_huff_remove_item(ht->last);
}
ht->item3058 = PTR_PTR(&ht->item3054);/* [EDI+4] */
ht->last->prev = ht->item3058; /* EAX */
temp = libmpq_huff_get_prev_item(PTR_PTR(&ht->item3054), PTR_INT(&ht->item3050));
temp->next = ht->last;
ht->item3054 = ht->last;
}
/* Clear all pointers in huffman tree item array. */
memset(ht->items306C, 0, sizeof(ht->items306C));
max_byte = 0; /* Greatest character found init to zero. */
p_item = (struct huffman_tree_item **)&ht->items306C; /* Pointer to current entry in huffman tree item pointer array */
/* Ensure we have low 8 bits only */
cmp_type &= 0xFF;
byte_array = table1502A630 + cmp_type * 258; /* EDI also */
for (i = 0; i < 0x100; i++, p_item++) {
struct huffman_tree_item *item = ht->item3058; /* Item to be created */
struct huffman_tree_item *p_item3 = ht->item3058;
unsigned char one_byte = byte_array[i];
/* Skip all the bytes which are zero. */
if (byte_array[i] == 0) {
continue;
}
/* If not valid pointer, take the first available item in the array. */
if (PTR_INT(item) <= 0) {
item = &ht->items0008[ht->items++];
}
/* Insert this item as the top of the tree. */
libmpq_huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL);
item->parent = NULL; /* Invalidate child and parent */
item->child = NULL;
*p_item = item; /* Store pointer into pointer array */
item->dcmp_byte = i; /* Store counter */
item->byte_value = one_byte; /* Store byte value */
if (one_byte >= max_byte) {
max_byte = one_byte;
continue;
}
/* Find the first item which has byte value greater than current one byte */
found = 0;
if (PTR_INT((p_item3 = ht->last)) > 0) {/* EDI - Pointer to the last item */
/* 15006AF7 */
if (p_item3 != NULL) {
do { /* 15006AFB */
if (p_item3->byte_value >= one_byte) {
found = 1;
break;
}
p_item3 = p_item3->prev;
} while (PTR_INT(p_item3) > 0);
}
}
if (found == 0) {
p_item3 = NULL;
}
/* 15006B09 */
if (item->next != NULL) {
libmpq_huff_remove_item(item);
}
/* 15006B15 */
if (p_item3 == NULL) {
p_item3 = PTR_PTR(&ht->first);
}
/* 15006B1F */
item->next = p_item3->next;
item->prev = p_item3->next->prev;
p_item3->next->prev = item;
p_item3->next = item;
}
/* 15006B4A */
for (; i < 0x102; i++) {
struct huffman_tree_item **p_item2 = &ht->items306C[i]; /* EDI */
/* 15006B59 */
struct huffman_tree_item *item2 = ht->item3058; /* ESI */
if (PTR_INT(item2) <= 0) {
item2 = &ht->items0008[ht->items++];
}
libmpq_huff_insert_item(&ht->item305C, item2, INSERT_ITEM, NULL);
/* 15006B89 */
item2->dcmp_byte = i;
item2->byte_value = 1;
item2->parent = NULL;
item2->child = NULL;
*p_item2++ = item2;
}
/* 15006BAA */
if (PTR_INT((child1 = ht->last)) > 0) { /* EDI - last item (first child to item */
struct huffman_tree_item *child2; /* EBP */
struct huffman_tree_item *item; /* ESI */
/* 15006BB8 */
while (PTR_INT((child2 = child1->prev)) > 0) {
if (PTR_INT((item = ht->item3058)) <= 0) {
item = &ht->items0008[ht->items++];
}
/* 15006BE3 */
libmpq_huff_insert_item(&ht->item305C, item, SWITCH_ITEMS, NULL);
/* 15006BF3 */
item->parent = NULL;
item->child = NULL;
/*
* EDX = child2->byte_value + child1->byte_value;
* EAX = child1->byte_value;
* ECX = max_byte; The greatest character (0xFF usually)
*/
item->byte_value = child1->byte_value + child2->byte_value; /* 0x02 */
item->child = child1; /* Prev item in the */
child1->parent = item;
child2->parent = item;
/* EAX = item->byte_value; */
if (item->byte_value >= max_byte) {
max_byte = item->byte_value;
} else {
struct huffman_tree_item *p_item2 = child2->prev; /* EDI */
found = 0;
if (PTR_INT(p_item2) > 0) {
/* 15006C2D */
do {
if (p_item2->byte_value >= item->byte_value) {
found = 1;
break;
}
p_item2 = p_item2->prev;
} while (PTR_INT(p_item2) > 0);
}
if (found == 0) {
p_item2 = NULL;
}
if (item->next != 0) {
struct huffman_tree_item *temp4 = libmpq_huff_get_prev_item(item, -1);
temp4->next = item->next; /* The first item changed */
item->next->prev = item->prev; /* First->prev changed to negative value */
item->next = NULL;
item->prev = NULL;
}
/* 15006C62 */
if (p_item2 == NULL) {
p_item2 = PTR_PTR(&ht->first);
}
item->next = p_item2->next; /* Set item with 0x100 byte value */
item->prev = p_item2->next->prev; /* Set item with 0x17 byte value */
p_item2->next->prev = item; /* Changed prev of item with */
p_item2->next = item;
}
/* 15006C7B */
if (PTR_INT((child1 = child2->prev)) <= 0) {
break;
}
}
}
/* 15006C88 */
ht->offs0004 = 1;
}
/* Gets the whole byte from the input stream. */
static unsigned long libmpq_huff_get_8bits(struct huffman_input_stream *is) {
unsigned long one_byte;
if (is->bits <= 8) {
is->bit_buf |= *(unsigned short *)is->in_buf << is->bits;
is->in_buf += sizeof(unsigned short);
is->bits += 16;
}
one_byte = (is->bit_buf & 0xFF);
is->bit_buf >>= 8;
is->bits -= 8;
return one_byte;
}
/* Gets 7 bits from the stream. */
static unsigned long libmpq_huff_get_7bits(struct huffman_input_stream *is) {
if (is->bits <= 7) {
is->bit_buf |= *(unsigned short *)is->in_buf << is->bits;
is->in_buf += sizeof(unsigned short);
is->bits += 16;
}
/* Get 7 bits from input stream. */
return (is->bit_buf & 0x7F);
}
/* Gets one bit from input stream. */
unsigned long libmpq_huff_get_bit(struct huffman_input_stream *is) {
unsigned long bit = (is->bit_buf & 1);
is->bit_buf >>= 1;
if (--is->bits == 0) {
is->bit_buf = *(unsigned long *)is->in_buf;
is->in_buf += sizeof(unsigned long);
is->bits = 32;
}
return bit;
}
static struct huffman_tree_item *libmpq_huff_call1500E740(struct huffman_tree *ht, unsigned int value) {
struct huffman_tree_item *p_item1 = ht->item3058; /* EDX */
struct huffman_tree_item *p_item2; /* EAX */
struct huffman_tree_item *p_next;
struct huffman_tree_item *p_prev;
struct huffman_tree_item **pp_item;
if (PTR_INT(p_item1) <= 0 || (p_item2 = p_item1) == NULL) {
if((p_item2 = &ht->items0008[ht->items++]) != NULL) {
p_item1 = p_item2;
} else {
p_item1 = ht->first;
}
} else {
p_item1 = p_item2;
}
p_next = p_item1->next;
if (p_next != NULL) {
p_prev = p_item1->prev;
if (PTR_INT(p_prev) <= 0) {
p_prev = PTR_NOT(p_prev);
} else {
p_prev += (p_item1 - p_item1->next->prev);
}
p_prev->next = p_next;
p_next->prev = p_prev;
p_item1->next = NULL;
p_item1->prev = NULL;
}
pp_item = &ht->first; /* ESI */
if (value > 1) {
/* ECX = ht->first->next; */
p_item1->next = *pp_item;
p_item1->prev = (*pp_item)->prev;
(*pp_item)->prev = p_item2;
*pp_item = p_item1;
p_item2->parent = NULL;
p_item2->child = NULL;
} else {
p_item1->next = (struct huffman_tree_item *)pp_item;
p_item1->prev = pp_item[1];
/* EDI = ht->item305C; */
p_prev = pp_item[1]; /* ECX */
if (p_prev <= 0) {
p_prev = PTR_NOT(p_prev);
p_prev->next = p_item1;
p_prev->prev = p_item2;
p_item2->parent = NULL;
p_item2->child = NULL;
} else {
if (PTR_INT(ht->item305C) < 0) {
p_prev += (struct huffman_tree_item *)pp_item - (*pp_item)->prev;
} else {
p_prev += PTR_INT(ht->item305C);
}
p_prev->next = p_item1;
pp_item[1] = p_item2;
p_item2->parent = NULL;
p_item2->child = NULL;
}
}
return p_item2;
}
static void libmpq_huff_call1500E820(struct huffman_tree *ht, struct huffman_tree_item *p_item) {
struct huffman_tree_item *p_item1; /* EDI */
struct huffman_tree_item *p_item2 = NULL; /* EAX */
struct huffman_tree_item *p_item3; /* EDX */
struct huffman_tree_item *p_prev; /* EBX */
for (; p_item != NULL; p_item = p_item->parent) {
p_item->byte_value++;
for (p_item1 = p_item; ; p_item1 = p_prev) {
p_prev = p_item1->prev;
if (PTR_INT(p_prev) <= 0) {
p_prev = NULL;
break;
}
if (p_prev->byte_value >= p_item->byte_value) {
break;
}
}
if (p_item1 == p_item) {
continue;
}
if (p_item1->next != NULL) {
p_item2 = libmpq_huff_get_prev_item(p_item1, -1);
p_item2->next = p_item1->next;
p_item1->next->prev = p_item1->prev;
p_item1->next = NULL;
p_item1->prev = NULL;
}
p_item2 = p_item->next;
p_item1->next = p_item2;
p_item1->prev = p_item2->prev;
p_item2->prev = p_item1;
p_item->next = p_item1;
if ((p_item2 = p_item1) != NULL) {
p_item2 = libmpq_huff_get_prev_item(p_item, -1);
p_item2->next = p_item->next;
p_item->next->prev = p_item->prev;
p_item->next = NULL;
p_item->prev = NULL;
}
if (p_prev == NULL) {
p_prev = PTR_PTR(&ht->first);
}
p_item2 = p_prev->next;
p_item->next = p_item2;
p_item->prev = p_item2->prev;
p_item2->prev = p_item;
p_prev->next = p_item;
p_item3 = p_item1->parent->child;
p_item2 = p_item->parent;
if (p_item2->child == p_item) {
p_item2->child = p_item1;
}
if (p_item3 == p_item1) {
p_item1->parent->child = p_item;
}
p_item2 = p_item->parent;
p_item->parent = p_item1->parent;
p_item1->parent = p_item2;
ht->offs0004++;
}
}
int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length) {
unsigned int n8bits; /* 8 bits loaded from input stream */
unsigned int n7bits; /* 7 bits loaded from input stream */
unsigned int found; /* Thats needed to replace the goto stuff from original source :) */
unsigned int dcmp_byte = 0;
unsigned long bit_count;
struct huffman_decompress *qd;
unsigned int has_qd; /* Can we use quick decompression? */
struct huffman_tree_item *p_item1;
struct huffman_tree_item *p_item2;
unsigned char *out_pos = out_buf;
/* Test the output length. Must not be non zero. */
if (out_length == 0) {
return 0;
}
/* Get the compression type from the input stream. */
n8bits = libmpq_huff_get_8bits(is);
/* Build the Huffman tree */
libmpq_huff_build_tree(ht, n8bits);
ht->cmp0 = (n8bits == 0) ? TRUE : FALSE;
for(;;) {
n7bits = libmpq_huff_get_7bits(is); /* Get 7 bits from input stream */
/*
* Try to use quick decompression. Check huffman_decompress array for corresponding item.
* If found, use the result byte instead.
*/
qd = &ht->qd3474[n7bits];
/* If there is a quick-pass possible (ebx) */
has_qd = (qd->offs00 >= ht->offs0004) ? TRUE : FALSE;
/* If we can use quick decompress, use it. */
if (has_qd) {
found = 0;
if (qd->bits > 7) {
is->bit_buf >>= 7;
is->bits -= 7;
p_item1 = qd->p_item;
found = 1;
}
if (found == 0) {
is->bit_buf >>= qd->bits;
is->bits -= qd->bits;
dcmp_byte = qd->dcmp_byte;
}
} else {
found = 1;
p_item1 = ht->first->next->prev;
if (PTR_INT(p_item1) <= 0) {
p_item1 = NULL;
}
}
if (found == 1) {
bit_count = 0;
p_item2 = NULL;
do {
p_item1 = p_item1->child; /* Move down by one level */
if (libmpq_huff_get_bit(is)) { /* If current bit is set, move to previous */
p_item1 = p_item1->prev;
}
if (++bit_count == 7) { /* If we are at 7th bit, save current huffman tree item. */
p_item2 = p_item1;
}
} while (p_item1->child != NULL); /* Walk until tree has no deeper level */
if (has_qd == FALSE) {
if (bit_count > 7) {
qd->offs00 = ht->offs0004;
qd->bits = bit_count;
qd->p_item = p_item2;
} else {
unsigned long index = n7bits & (0xFFFFFFFF >> (32 - bit_count));
unsigned long add = (1 << bit_count);
for (qd = &ht->qd3474[index]; index <= 0x7F; index += add, qd += add) {
qd->offs00 = ht->offs0004;
qd->bits = bit_count;
qd->dcmp_byte = p_item1->dcmp_byte;
}
}
}
dcmp_byte = p_item1->dcmp_byte;
}
if (dcmp_byte == 0x101) { /* Huffman tree needs to be modified */
n8bits = libmpq_huff_get_8bits(is);
p_item1 = (ht->last <= 0) ? NULL : ht->last;
p_item2 = libmpq_huff_call1500E740(ht, 1);
p_item2->parent = p_item1;
p_item2->dcmp_byte = p_item1->dcmp_byte;
p_item2->byte_value = p_item1->byte_value;
ht->items306C[p_item2->dcmp_byte] = p_item2;
p_item2 = libmpq_huff_call1500E740(ht, 1);
p_item2->parent = p_item1;
p_item2->dcmp_byte = n8bits;
p_item2->byte_value = 0;
ht->items306C[p_item2->dcmp_byte] = p_item2;
p_item1->child = p_item2;
libmpq_huff_call1500E820(ht, p_item2);
if (ht->cmp0 == 0) {
libmpq_huff_call1500E820(ht, ht->items306C[n8bits]);
}
dcmp_byte = n8bits;
}
if (dcmp_byte == 0x100) {
break;
}
*out_pos++ = (unsigned char)dcmp_byte;
if (--out_length == 0) {
break;
}
if (ht->cmp0) {
libmpq_huff_call1500E820(ht, ht->items306C[dcmp_byte]);
}
}
return (out_pos - out_buf);
}
int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp) {
int count;
/* Clear links for all the items in the tree */
for (hi = ht->items0008, count = 0x203; count != 0; hi++, count--) {
hi->next = hi->prev = NULL;
}
ht->item3050 = NULL;
ht->item3054 = PTR_PTR(&ht->item3054);
ht->item3058 = PTR_NOT(ht->item3054);
ht->item305C = NULL;
ht->first = PTR_PTR(&ht->first);
ht->last = PTR_NOT(ht->first);
ht->offs0004 = 1;
ht->items = 0;
/* Clear all huffman_decompress items. Do this only if preparing for decompression */
if (cmp == LIBMPQ_HUFF_DECOMPRESS) {
for (count = 0; count < sizeof(ht->qd3474) / sizeof(struct huffman_decompress); count++) {
ht->qd3474[count].offs00 = 0;
}
}
return 0;
}

View file

@ -1,105 +0,0 @@
/*
* huffman.h -- structures used for huffman compression.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of huffman.h included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* ShadowFlare <BlakFlare@hotmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _HUFFMAN_H
#define _HUFFMAN_H
#define PTR_NOT(ptr) (struct huffman_tree_item *)(~(unsigned long)(ptr))
#define PTR_PTR(ptr) ((struct huffman_tree_item *)(ptr))
#define PTR_INT(ptr) (long)(ptr)
#define INSERT_ITEM 1
#define SWITCH_ITEMS 2 /* Switch the item1 and item2 */
/*
* Input stream for Huffmann decompression
*/
struct huffman_input_stream {
unsigned char *in_buf; /* 00 - Input data */
unsigned long bit_buf; /* 04 - Input bit buffer */
unsigned int bits; /* 08 - Number of bits remaining in 'byte' */
};
/*
* Huffmann tree item.
*/
struct huffman_tree_item {
struct huffman_tree_item *next; /* 00 - Pointer to next huffman_tree_item */
struct huffman_tree_item *prev; /* 04 - Pointer to prev huffman_tree_item (< 0 if none) */
unsigned long dcmp_byte; /* 08 - Index of this item in item pointer array, decompressed byte value */
unsigned long byte_value; /* 0C - Some byte value */
struct huffman_tree_item *parent; /* 10 - Pointer to parent huffman_tree_item (NULL if none) */
struct huffman_tree_item *child; /* 14 - Pointer to child huffman_tree_item */
};
/*
* Structure used for quick decompress. The 'bits' contains
* number of bits and dcmp_byte contains result decompressed byte
* value. After each walk through Huffman tree are filled all entries
* which are multiplies of number of bits loaded from input stream.
* These entries contain number of bits and result value. At the next
* 7 bits is tested this structure first. If corresponding entry found,
* decompression routine will not walk through Huffman tree and
* directly stores output byte to output stream.
*/
struct huffman_decompress {
unsigned long offs00; /* 00 - 1 if resolved */
unsigned long bits; /* 04 - Bit count */
union {
unsigned long dcmp_byte; /* 08 - Byte value for decompress (if bitCount <= 7) */
struct huffman_tree_item *p_item; /* 08 - THTreeItem (if number of bits is greater than 7 */
};
};
/*
* Structure for Huffman tree.
*/
struct huffman_tree {
unsigned long cmp0; /* 0000 - 1 if compression type 0 */
unsigned long offs0004; /* 0004 - Some flag */
struct huffman_tree_item items0008[0x203]; /* 0008 - huffman tree items */
/* Sometimes used as huffman tree item */
struct huffman_tree_item *item3050; /* 3050 - Always NULL (?) */
struct huffman_tree_item *item3054; /* 3054 - Pointer to huffman_tree_item */
struct huffman_tree_item *item3058; /* 3058 - Pointer to huffman_tree_item (< 0 if invalid) */
/* Sometimes used as huffman tree item */
struct huffman_tree_item *item305C; /* 305C - Usually NULL */
struct huffman_tree_item *first; /* 3060 - Pointer to top (first) Huffman tree item */
struct huffman_tree_item *last; /* 3064 - Pointer to bottom (last) Huffman tree item (< 0 if invalid) */
unsigned long items; /* 3068 - Number of used huffman tree items */
struct huffman_tree_item *items306C[0x102]; /* 306C - huffman_tree_item pointer array */
struct huffman_decompress qd3474[0x80]; /* 3474 - Array for quick decompression */
//unsigned char table1502A630[]; /* Some table to make struct size flexible */
};
int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp);
int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length);
#endif /* _HUFFMAN_H */

View file

@ -1,610 +0,0 @@
/*
* mpq.c -- functions for developers using libmpq.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: mpq.c,v 1.6 2004/02/12 00:49:00 mbroemme Exp $
*/
#define _CRT_SECURE_NO_DEPRECATE
#include <stdlib.h>
#include <sys/stat.h>
//#include <unistd.h>
//#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include "mpq.h"
#include "common.h"
/*
* This function returns version information.
* format: MAJOR.MINOR.PATCH
*/
char *libmpq_version() {
static char version[10];
sprintf(version, "%i.%i.%i", LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
return version;
}
/*
* This function reads a file and verify if it is a legit MPQ archive
* or not. Then it fills the mpq_header structure and reads the hash
* table.
*/
int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) {
int fd = 0;
int rb = 0;
int ncnt = FALSE;
struct stat fileinfo;
/* allocate memory */
mpq_a->mpq_l = (mpq_list *)malloc(sizeof(mpq_list));
memset(mpq_a->mpq_l, 0, sizeof(mpq_list));
mpq_a->header = (mpq_header *)malloc(sizeof(mpq_header));
memset(mpq_a->header, 0, sizeof(mpq_header));
/* Check if file exists and is readable */
fd = _open((char *)mpq_filename, MPQ_FILE_OPEN_FLAGS);
if (fd == LIBMPQ_EFILE) {
return LIBMPQ_EFILE;
}
/* fill the structures with informations */
strcpy((char *)mpq_a->filename, (char *)mpq_filename);
libmpq_init_buffer(mpq_a);
mpq_a->fd = fd;
mpq_a->header->id = 0;
mpq_a->maxblockindex = 0;
mpq_a->mpq_l->mpq_files = NULL;
mpq_a->mpqpos = 0; //k
while (!ncnt) {
mpq_a->header->id = 0;
libmpq_lseek(mpq_a, mpq_a->mpqpos);
rb = _read(mpq_a->fd, mpq_a->header, sizeof(mpq_header));
/* if different number of bytes read, break the loop */
if (rb != sizeof(mpq_header)) {
return LIBMPQ_EFILE_FORMAT;
}
/* special offset for protected MPQs */
if (mpq_a->header->offset == LIBMPQ_HEADER_W3M) {
mpq_a->flags |= LIBMPQ_FLAG_PROTECTED;
mpq_a->header->offset = sizeof(mpq_header);
}
/* if valid signature has been found, break the loop */
if (mpq_a->header->id == LIBMPQ_ID_MPQ) {
ncnt = true;
}
/*if (mpq_a->header->id == LIBMPQ_ID_MPQ &&
mpq_a->header->offset == sizeof(mpq_header) &&
mpq_a->header->hashtablepos < mpq_a->header->archivesize &&
mpq_a->header->blocktablepos < mpq_a->header->archivesize) {
ncnt = TRUE;
}*/
/* move to the next possible offset */
if (!ncnt) {
mpq_a->mpqpos += 0x200;
}
}
/* get the right positions of the hash table and the block table. */
mpq_a->blocksize = (0x200 << mpq_a->header->blocksize);
fstat(mpq_a->fd, &fileinfo);
/* Normal MPQs must have position of */
/*if (mpq_a->header->hashtablepos + mpq_a->mpqpos < fileinfo.st_size &&
mpq_a->header->blocktablepos + mpq_a->mpqpos < fileinfo.st_size) {
mpq_a->header->hashtablepos += mpq_a->mpqpos;
mpq_a->header->blocktablepos += mpq_a->mpqpos;
} else {
return LIBMPQ_EFILE_FORMAT;
}*/
/* Try to read and decrypt the hashtable */
if (libmpq_read_hashtable(mpq_a) != 0) {
return LIBMPQ_EHASHTABLE;
}
/* Try to read and decrypt the blocktable */
if (libmpq_read_blocktable(mpq_a) != 0) {
return LIBMPQ_EBLOCKTABLE;
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function closes the file descriptor opened by
* mpq_open_archive(); and frees the decryption buffer.
*/
int libmpq_archive_close(mpq_archive *mpq_a) {
memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
/* free the allocated memory. */
free(mpq_a->header);
free(mpq_a->mpq_l);
/* Check if file descriptor is valid. */
if ((_close(mpq_a->fd)) == LIBMPQ_EFILE) {
return LIBMPQ_EFILE;
}
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function returns the value for the given infotype.
* If an error occurs something < 0 is returned.
*/
int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype) {
unsigned int filecount = 0;
unsigned int fsize = 0;
unsigned int csize = 0;
mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->header->blocktablesize;
mpq_block *mpq_b = NULL;
switch (infotype) {
case LIBMPQ_MPQ_ARCHIVE_SIZE:
return mpq_a->header->archivesize;
case LIBMPQ_MPQ_HASHTABLE_SIZE:
return mpq_a->header->hashtablesize;
case LIBMPQ_MPQ_BLOCKTABLE_SIZE:
return mpq_a->header->blocktablesize;
case LIBMPQ_MPQ_BLOCKSIZE:
return mpq_a->blocksize;
case LIBMPQ_MPQ_NUMFILES:
for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
filecount++;
}
return filecount;
case LIBMPQ_MPQ_COMPRESSED_SIZE:
for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
csize += mpq_b->csize;
}
return csize;
case LIBMPQ_MPQ_UNCOMPRESSED_SIZE:
for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
fsize += mpq_b->fsize;
}
return fsize;
default:
return LIBMPQ_TOOLS_SUCCESS;
}
}
/*
* This function returns some useful file information.
*/
int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const unsigned int number) {
int blockindex = number;
int i = 0;
mpq_block *mpq_b = NULL;
mpq_hash *mpq_h = NULL;
/* check if given number is not out of range */
if (number < 0 || number >= mpq_a->header->blocktablesize) {
return LIBMPQ_EINV_RANGE;
}
/* check if sizes are correct */
mpq_b = mpq_a->blocktable + blockindex;
if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
return LIBMPQ_EFILE_CORRUPT;
}
/* check if file exists */
if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
return LIBMPQ_EFILE_NOT_FOUND;
}
switch (infotype) {
case LIBMPQ_FILE_COMPRESSED_SIZE:
return mpq_b->csize;
case LIBMPQ_FILE_UNCOMPRESSED_SIZE:
return mpq_b->fsize;
case LIBMPQ_FILE_COMPRESSION_TYPE:
if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
return LIBMPQ_FILE_COMPRESS_PKWARE;
}
if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
return LIBMPQ_FILE_COMPRESS_MULTI;
}
default:
return LIBMPQ_TOOLS_SUCCESS;
}
}
/*
* This function searches the listfile for the filename.
* On success it returns the filename, otherwiese a name
* like file000001.xxx and if number is out of range it
* returns NULL.
*/
char *libmpq_file_name(mpq_archive *mpq_a, const int number) {
static char tempfile[PATH_MAX];
/* check if we are in the range of available files. */
if (number > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || number < 1) {
return NULL;
}
/* this is safe because we built a fallback filelist, if something was wrong. */
sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[number - 1], number);
return tempfile;
}
/*
* This function returns the number to the given
* filename.
*/
int libmpq_file_number(mpq_archive *mpq_a, const char *name) {
int i;
char tempfile[PATH_MAX];
for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) {
sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i + 1);
if (strncmp(tempfile, name, strlen(name)) == 0) {
/* if file found return the number */
return i + 1;
}
}
/* if no matching entry found return LIBMPQ_EFILE_NOT_FOUND */
return LIBMPQ_EFILE_NOT_FOUND;
}
/*
* This function verifies if a given file (by number
* or name) is in the opened mpq archive. On success
* it returns 0, otherwise LIBMPQ_EFILE_NOT_FOUND.
*/
int libmpq_file_check(mpq_archive *mpq_a, void *file, int type) {
int found = 0;
int i;
char tempfile[PATH_MAX];
switch (type) {
case LIBMPQ_FILE_TYPE_INT:
/* check if we are in the range of available files. */
if (*(int *)file > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || *(int *)file < 1) {
return LIBMPQ_EFILE_NOT_FOUND;
} else {
return LIBMPQ_TOOLS_SUCCESS;
}
case LIBMPQ_FILE_TYPE_CHAR:
for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) {
sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i);
if (strncmp(tempfile, (char *)file, strlen((char *)file)) == 0) {
/* if file found break */
found = 1;
break;
}
}
/* if a file was found return 0 */
if (found == 1) {
return LIBMPQ_TOOLS_SUCCESS;
} else {
return LIBMPQ_EFILE_NOT_FOUND;
}
default:
return LIBMPQ_TOOLS_SUCCESS;
}
}
/*
* This function extracts a file from a MPQ archive
* by the given number.
*/
int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename) {
int blockindex = number; //-1;
int fd = 0;
int i = 0;
char buffer[0x1000];
//char tempfile[PATH_MAX];
unsigned int transferred = 1;
mpq_file *mpq_f = NULL;
mpq_block *mpq_b = NULL;
mpq_hash *mpq_h = NULL;
/* if (number < 1 || number > mpq_a->header->blocktablesize) {
return LIBMPQ_EINV_RANGE;
}*/
/*
sprintf(tempfile, libmpq_file_name(mpq_a, number));
*/
/* check if mpq_f->filename could be written here. */
fd = _open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644);
if (fd == LIBMPQ_EFILE) {
return LIBMPQ_EFILE;
}
/* search for correct hashtable */
/*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
blockindex = (mpq_a->hashtable[i]).blockindex;
mpq_h = &(mpq_a->hashtable[i]);
break;
}
}*/
/* check if file was found */
if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
return LIBMPQ_EFILE_NOT_FOUND;
}
/* check if sizes are correct */
mpq_b = mpq_a->blocktable + blockindex;
if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
return LIBMPQ_EFILE_CORRUPT;
}
/* check if file exists */
if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
return LIBMPQ_EFILE_NOT_FOUND;
}
/* allocate memory for file structure */
mpq_f = (mpq_file *)malloc(sizeof(mpq_file));
if (!mpq_f) {
return LIBMPQ_EALLOCMEM;
}
/* initialize file structure */
memset(mpq_f, 0, sizeof(mpq_file));
mpq_f->fd = fd;
mpq_f->mpq_b = mpq_b;
mpq_f->nblocks = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize;
mpq_f->mpq_h = mpq_h;
mpq_f->accessed = FALSE;
mpq_f->blockposloaded = FALSE;
sprintf((char *)mpq_f->filename, filename);
/* allocate buffers for decompression. */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
/*
* Allocate buffer for block positions. At the begin of file are stored
* unsigned ints holding positions of each block relative from begin of
* file in the archive.
*/
if ((mpq_f->blockpos = (unsigned int *)malloc(sizeof(int) * mpq_f->nblocks + 1)) == NULL) {
return LIBMPQ_EALLOCMEM;
}
}
while (transferred > 0) {
transferred = libmpq_file_read_file(mpq_a, mpq_f, mpq_f->filepos, buffer, sizeof(buffer));
if (transferred == 0) {
break;
} else {
mpq_f->accessed = TRUE;
mpq_f->filepos += transferred;
}
transferred = _write(mpq_f->fd, buffer, transferred);
if (transferred == 0) {
break;
}
}
_close(fd);
/* freeing the file structure */
free(mpq_f);
return LIBMPQ_TOOLS_SUCCESS;
}
/*
* This function tries to get the filenames for the hashes. It uses
* an internal listfile database and gets the correct listfile from
* some specific archive informations.
*/
int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]) {
FILE *fp;
//char **filelist;
int i = 0;
//int fl_count;
//int fl_size;
int fl_count_fb;
int fl_size_fb;
int result = LIBMPQ_TOOLS_SUCCESS;
struct stat statbuf;
/* get file status */
if (stat(file, &statbuf) < 0) {
result = LIBMPQ_CONF_EFILE_NOT_FOUND;
}
/* check if file is a filename or directory */
/*if (S_ISDIR(statbuf.st_mode)) {
// allocate memory for the file list
filelist = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
fl_count = 0;
fl_size = LIBMPQ_CONF_FL_INCREMENT;
// check if it is a valid listfile
if (libmpq_detect_listfile_rec(file, &filelist, &fl_count, &fl_size)) {
filelist == NULL;
}
filelist[fl_count] = NULL;
// return if no listfile was found
if (filelist == NULL) {
result = LIBMPQ_CONF_EFILE_NOT_FOUND;
}
for (i = 0; filelist[i]; i++) {
if ((fp = fopen(filelist[i], "r")) != NULL ) {
result = libmpq_read_listfile(mpq_a, fp);
fclose(fp);
}
}
// freeing the listfile struct
libmpq_free_listfile(filelist);
}*/
/* if file is a regular file use it */
//if (S_ISREG(statbuf.st_mode)) {
/* if specific listfile was forced. */
if ((fp = fopen(file, "r")) != NULL ) {
result = libmpq_read_listfile(mpq_a, fp);
fclose(fp);
} else {
result = LIBMPQ_CONF_EFILE_OPEN;
}
//}
/* if error occured we need to create a fallback filelist. */
if (mpq_a->mpq_l->mpq_files == NULL) {
/* allocate memory for the file list */
mpq_a->mpq_l->mpq_files = (unsigned char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
fl_count_fb = 0;
fl_size_fb = LIBMPQ_CONF_FL_INCREMENT;
for (i = 0; i < libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES); i++) {
/* set the next filelist entry to a copy of the file */
mpq_a->mpq_l->mpq_files[fl_count_fb++] = (unsigned char *)_strdup("file%06lu.xxx");
/* increase the array size */
if (fl_count_fb == fl_size_fb) {
mpq_a->mpq_l->mpq_files = (unsigned char **)realloc(mpq_a->mpq_l->mpq_files, (fl_size_fb + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
fl_size_fb += LIBMPQ_CONF_FL_INCREMENT;
}
}
mpq_a->mpq_l->mpq_files[fl_count_fb] = NULL;
/* if no error occurs and no listfile was assigned, we think there was no matching listfile. */
if (result == 0) {
result = LIBMPQ_CONF_EFILE_NOT_FOUND;
}
}
return result;
}
/*
* This function frees the allocated memory for the listfile.
*/
int libmpq_listfile_close(mpq_archive *mpq_a) {
int i = 0;
/* safety check if we really have a filelist. */
if (mpq_a->mpq_l->mpq_files != NULL) {
/* freeing the filelist */
while (mpq_a->mpq_l->mpq_files[i]) {
free(mpq_a->mpq_l->mpq_files[i++]);
}
free(mpq_a->mpq_l->mpq_files);
}
return 0;
}
int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest) {
int blockindex = number; //-1;
int i = 0;
mpq_file *mpq_f = NULL;
mpq_block *mpq_b = NULL;
int success = 0;
/*if (number < 1 || number > mpq_a->header->blocktablesize) {
return LIBMPQ_EINV_RANGE;
}*/
/* search for correct hashtable */
/*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
blockindex = (mpq_a->hashtable[i]).blockindex;
mpq_h = &(mpq_a->hashtable[i]);
break;
}
}*/
/* check if file was found */
if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
return LIBMPQ_EFILE_NOT_FOUND;
}
/* check if sizes are correct */
mpq_b = mpq_a->blocktable + blockindex;
if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
return LIBMPQ_EFILE_CORRUPT;
}
/* check if file exists */
if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
return LIBMPQ_EFILE_NOT_FOUND;
}
/* allocate memory for file structure */
mpq_f = (mpq_file*)malloc(sizeof(mpq_file));
if (!mpq_f) {
return LIBMPQ_EALLOCMEM;
}
/* initialize file structure */
memset(mpq_f, 0, sizeof(mpq_file));
mpq_f->mpq_b = mpq_b;
mpq_f->nblocks = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize;
mpq_f->mpq_h = &mpq_h;
mpq_f->accessed = FALSE;
mpq_f->blockposloaded = FALSE;
/* allocate buffers for decompression. */
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
/*
* Allocate buffer for block positions. At the begin of file are stored
* unsigned ints holding positions of each block relative from begin of
* file in the archive.
*/
if ((mpq_f->blockpos = (unsigned int*)malloc(sizeof(int) * (mpq_f->nblocks + 1))) == NULL) {
return LIBMPQ_EALLOCMEM;
}
}
if(libmpq_file_read_file(mpq_a, mpq_f, 0, (char*)dest, mpq_b->fsize) == mpq_b->fsize)
success = 1;
if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
// Free buffer for block positions
free(mpq_f->blockpos);
}
/* freeing the file structure */
free(mpq_f);
return success?LIBMPQ_TOOLS_SUCCESS:LIBMPQ_EFILE_CORRUPT;
}

View file

@ -1,225 +0,0 @@
/*
* mpq.h -- some default types and defines.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of StormLib.h and
* StormPort.h included in stormlib. The C++ version belongs to
* the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* Marko Friedemann <marko.friedemann@bmx-chemnitz.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: mpq.h,v 1.8 2004/02/12 00:45:50 mbroemme Exp $
*/
#ifndef _MPQ_H
#define _MPQ_H
#include <limits.h>
#ifndef PATH_MAX
#define PATH_MAX 260
#endif
#define LIBMPQ_MAJOR_VERSION 0 /* Major version number... maybe sometimes we reach version 1 :) */
#define LIBMPQ_MINOR_VERSION 3 /* Minor version number - increased only for small changes */
#define LIBMPQ_PATCH_VERSION 0 /* Patchlevel - changed on bugfixes etc... */
#define LIBMPQ_TOOLS_SUCCESS 0 /* return value for all functions which success */
#define LIBMPQ_TOOLS_BUFSIZE 0x500 /* buffer size for the decryption engine */
#define LIBMPQ_EFILE -1 /* error on file operation */
#define LIBMPQ_EFILE_FORMAT -2 /* bad file format */
#define LIBMPQ_EFILE_CORRUPT -3 /* file corrupt */
#define LIBMPQ_EFILE_NOT_FOUND -4 /* file in archive not found */
#define LIBMPQ_EFILE_READ -5 /* Read error in archive */
#define LIBMPQ_EALLOCMEM -6 /* maybe not enough memory? :) */
#define LIBMPQ_EFREEMEM -7 /* can not free memory */
#define LIBMPQ_EINV_RANGE -8 /* Given filenumber is out of range */
#define LIBMPQ_EHASHTABLE -9 /* error in reading hashtable */
#define LIBMPQ_EBLOCKTABLE -10 /* error in reading blocktable */
#define LIBMPQ_ID_MPQ 0x1A51504D /* MPQ archive header ID ('MPQ\x1A') */
#define LIBMPQ_HEADER_W3M 0x6D9E4B86 /* special value used by W3M Map Protector */
#define LIBMPQ_FLAG_PROTECTED 0x00000002 /* Set on protected MPQs (like W3M maps) */
#define LIBMPQ_HASH_ENTRY_DELETED 0xFFFFFFFE /* Block index for deleted hash entry */
#define LIBMPQ_FILE_COMPRESS_PKWARE 0x00000100 /* Compression made by PKWARE Data Compression Library */
#define LIBMPQ_FILE_COMPRESS_MULTI 0x00000200 /* Multiple compressions */
#define LIBMPQ_FILE_COMPRESSED 0x0000FF00 /* File is compressed */
#define LIBMPQ_FILE_EXISTS 0x80000000 /* Set if file exists, reset when the file was deleted */
#define LIBMPQ_FILE_ENCRYPTED 0x00010000 /* Indicates whether file is encrypted */
#define LIBMPQ_FILE_HAS_METADATA 0x04000000
#define LIBMPQ_FILE_COMPRESSED_SIZE 1 /* MPQ compressed filesize of given file */
#define LIBMPQ_FILE_UNCOMPRESSED_SIZE 2 /* MPQ uncompressed filesize of given file */
#define LIBMPQ_FILE_COMPRESSION_TYPE 3 /* MPQ compression type of given file */
#define LIBMPQ_FILE_TYPE_INT 4 /* file is given by number */
#define LIBMPQ_FILE_TYPE_CHAR 5 /* file is given by name */
#define LIBMPQ_MPQ_ARCHIVE_SIZE 1 /* MPQ archive size */
#define LIBMPQ_MPQ_HASHTABLE_SIZE 2 /* MPQ archive hashtable size */
#define LIBMPQ_MPQ_BLOCKTABLE_SIZE 3 /* MPQ archive blocktable size */
#define LIBMPQ_MPQ_BLOCKSIZE 4 /* MPQ archive blocksize */
#define LIBMPQ_MPQ_NUMFILES 5 /* Number of files in the MPQ archive */
#define LIBMPQ_MPQ_COMPRESSED_SIZE 6 /* Compressed archive size */
#define LIBMPQ_MPQ_UNCOMPRESSED_SIZE 7 /* Uncompressed archive size */
#define LIBMPQ_HUFF_DECOMPRESS 0 /* Defines that we want to decompress using huffman trees. */
#define LIBMPQ_CONF_EFILE_OPEN -1 /* error if a specific listfile was forced and could not be opened. */
#define LIBMPQ_CONF_EFILE_CORRUPT -2 /* listfile seems to be corrupt */
#define LIBMPQ_CONF_EFILE_LIST_CORRUPT -3 /* listfile seems correct, but filelist is broken */
#define LIBMPQ_CONF_EFILE_NOT_FOUND -4 /* error if no matching listfile found */
#define LIBMPQ_CONF_EFILE_VERSION -5 /* libmpq version does not match required listfile version */
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
#ifndef min
#define min(a, b) ((a < b) ? a : b)
#endif
*/
typedef unsigned int mpq_buffer[LIBMPQ_TOOLS_BUFSIZE];
typedef int (*DECOMPRESS)(char *, int *, char *, int);
typedef struct {
unsigned long mask; /* Decompression bit */
DECOMPRESS decompress; /* Decompression function */
} decompress_table;
/* MPQ file header */
typedef struct {
unsigned int id; /* The 0x1A51504D ('MPQ\x1A') signature */
unsigned int offset; /* Offset of the first file (Relative to MPQ start) */
unsigned int archivesize; /* Size of MPQ archive */
unsigned short offsetsc; /* 0000 for SC and BW */
unsigned short blocksize; /* Size of file block is (0x200 << blockSize) */
unsigned int hashtablepos; /* File position of hashTable */
unsigned int blocktablepos; /* File position of blockTable. Each entry has 16 bytes */
unsigned int hashtablesize; /* Number of entries in hash table */
unsigned int blocktablesize; /* Number of entries in the block table */
} mpq_header;
//} __attribute__ ((packed)) mpq_header;
/* Hash entry. All files in the archive are searched by their hashes. */
typedef struct {
unsigned int name1; /* The first two unsigned ints */
unsigned int name2; /* are the encrypted file name */
unsigned int locale; /* Locale information. */
unsigned int blockindex; /* Index to file description block */
} mpq_hash;
/* File description block contains informations about the file */
typedef struct {
unsigned int filepos; /* Block file starting position in the archive */
unsigned int csize; /* Compressed file size */
unsigned int fsize; /* Uncompressed file size */
unsigned int flags; /* Flags */
} mpq_block;
/* File handle structure used since Diablo 1.00 (0x38 bytes) */
typedef struct {
unsigned char filename[PATH_MAX]; /* filename of the actual file in the archive */
int fd; /* File handle */
unsigned int seed; /* Seed used for file decrypt */
unsigned int filepos; /* Current file position */
unsigned int offset;
unsigned int nblocks; /* Number of blocks in the file (incl. the last noncomplete one) */
unsigned int *blockpos; /* Position of each file block (only for compressed files) */
int blockposloaded; /* TRUE if block positions loaded */
unsigned int offset2; /* (Number of bytes somewhere ?) */
mpq_hash *mpq_h; /* Hash table entry */
mpq_block *mpq_b; /* File block pointer */
/* Non-Storm.dll members */
unsigned int accessed; /* Was something from the file already read? */
} mpq_file;
/* List handle structure */
typedef struct {
unsigned char mpq_version[10]; /* libmpq version required by the listfile */
unsigned char mpq_name[PATH_MAX]; /* mpq archive name without full path */
unsigned char mpq_type[20]; /* mpq archive type */
unsigned char mpq_game[40]; /* blizzard title the file matches */
unsigned char mpq_game_version[10]; /* game version */
unsigned char **mpq_files; /* filelist */
} mpq_list;
/* Archive handle structure used since Diablo 1.00 */
typedef struct {
unsigned char filename[PATH_MAX]; /* Opened archive file name */
int fd; /* File handle */
unsigned int blockpos; /* Position of loaded block in the file */
unsigned int blocksize; /* Size of file block */
unsigned char *blockbuf; /* Buffer (cache) for file block */
unsigned int bufpos; /* Position in block buffer */
unsigned int mpqpos; /* MPQ archive position in the file */
unsigned int filepos; /* Current file pointer */
unsigned int openfiles; /* Number of open files + 1 */
mpq_buffer buf; /* MPQ buffer */
mpq_header *header; /* MPQ file header */
mpq_hash *hashtable; /* Hash table */
mpq_block *blocktable; /* Block table */
/* Non-Storm.dll members */
mpq_list *mpq_l; /* Handle to file list from database */
unsigned int flags; /* See LIBMPQ_TOOLS_FLAG_XXXXX */
unsigned int maxblockindex; /* The highest block table entry */
} mpq_archive;
extern char *libmpq_version();
extern int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename);
extern int libmpq_archive_close(mpq_archive *mpq_a);
extern int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype);
//extern int libmpq_file_extract(mpq_archive *mpq_a, const int number);
extern int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const unsigned int number);
extern char *libmpq_file_name(mpq_archive *mpq_a, const int number);
extern int libmpq_file_number(mpq_archive *mpq_a, const char *name);
extern int libmpq_file_check(mpq_archive *mpq_a, void *file, int type);
extern int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]);
extern int libmpq_listfile_close(mpq_archive *mpq_a);
extern int libmpq_pkzip_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_zlib_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_huff_decompress(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_wave_decompress_stereo(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_wave_decompress_mono(char *out_buf, int *out_length, char *in_buf, int in_length);
extern int libmpq_multi_decompress(char *out_buf, int *pout_length, char *in_buf, int in_length);
static decompress_table dcmp_table[] = {
{0x08, libmpq_pkzip_decompress}, /* Decompression with Pkware Data Compression Library */
{0x02, libmpq_zlib_decompress}, /* Decompression with the "zlib" library */
{0x01, libmpq_huff_decompress}, /* Huffmann decompression */
{0x80, libmpq_wave_decompress_stereo}, /* WAVE decompression for stereo waves */
{0x40, libmpq_wave_decompress_mono} /* WAVE decompression for mono waves */
};
int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename);
int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest);
#endif /* _MPQ_H */

View file

@ -1,294 +0,0 @@
/*
* parser.c -- functions used to parse list or config file.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: parser.c,v 1.5 2004/02/12 00:47:53 mbroemme Exp $
*/
#define _CRT_SECURE_NO_DEPRECATE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "mpq.h"
#include "common.h"
#include <ctype.h>
/*
* This function deletes the specified characters, but leaves
* escape sequences unaffected. This means that " would be
* deleted but \" would not.
*/
char *libmpq_conf_delete_char(char *buf, char *chars) {
static char *temp;
char ch;
temp = buf;
/* strip out special chars like " */
while (temp = strpbrk(temp, chars)) {
ch = temp[0];
memmove(&temp[0], &temp[1], strlen(temp));
if (ch == '\\') {
temp++;
}
}
return buf;
}
/*
* This function parses a line for the value to the given option. It
* return 1 on success and the byte array or 0 and null.
*/
int libmpq_conf_parse_line(char *line, char *search_value, char *return_value, int size) {
int level = 0;
int found = 0;
int i = 0;
int pos = 0;
/* search value */
while (*(++line)) {
/* check for spaces */
if (!isspace(*line) && level == 1) {
/* we found our value so break */
found = 1;
break;
}
/* check for '=' so the value follows as next parameter */
if (*line == '=' && level == 0) {
level = 1;
}
}
/* now search for comment in this line */
for (i = 0; i < int(strlen(line)); i++) {
if (line[i] == '#') {
pos = i - 1;
break;
}
}
/* now set end of byte array behind value, but only if comment was found */
if (pos != 0) {
for (i = pos; i >= 0; i--) {
if (line[i] != ' ' && line[i] != '\t') {
line[i + 1] = '\0';
break;
}
}
}
/* now check if line has trailing spaces */
for (i = strlen(line); i >= 0; i--) {
if (line[i] != ' ' && line[i] != '\t') {
line[i + 1] = '\0';
break;
}
}
/* now check if value is quoted with "" and if there is a char behind. */
for (i = strlen(line); i >= 0; i--) {
if (line[i] == '"') {
line[i + 1] = '\0';
break;
}
}
/* return the values */
strncpy(return_value, line, size);
return found;
}
/*
* This function returns the value for a given option in the
* listdb or config file. On success it returns 1, otherwise 0.
*/
int libmpq_conf_get_value(FILE *fp, char *search_value, void *return_value, int type, int size) {
char buf[LIBMPQ_CONF_BUFSIZE];
int found = 0;
int result = LIBMPQ_TOOLS_SUCCESS;
while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
char *line;
buf[strlen(buf) - 1] = '\0';
/* skip whitespace */
for (line = buf; isspace(*line); line++) {
continue;
}
/* skip empty line */
if (line[0] == '\0') {
continue;
}
/* skip comments */
if (line[0] == '#') {
continue;
}
/* process the line */
//if (!strncasecmp(line, search_value, strlen(search_value))) {
if (!strcmp(line, search_value)) {
found = libmpq_conf_parse_line(line, search_value, line, LIBMPQ_CONF_BUFSIZE);
if (found == 1) {
libmpq_conf_delete_char(line, "\"\\");
switch (type) {
case LIBMPQ_CONF_TYPE_INT:
/* if it is no valid number it is safe to return 0 */
*(int *)return_value = atoi(line);
break;
default:
strncpy((char *)return_value, line, size);
break;
}
/* value found, so rewind stream */
break;
}
}
}
/* if value was not found */
if (found == 0) {
switch (type) {
case LIBMPQ_CONF_TYPE_INT:
*(int *)return_value = 0;
result = LIBMPQ_CONF_EVALUE_NOT_FOUND;
break;
default:
strncpy((char *)return_value, "", size);
result = LIBMPQ_CONF_EVALUE_NOT_FOUND;
break;
}
}
fseek(fp, 0L, SEEK_SET);
return result;
}
/*
* This function returns a pointer to a byte array, with all values
* found in the config file. As second value it returns th number of
* entries in the byte array. On success it returns 1, otherwise 0.
*/
int libmpq_conf_get_array(FILE *fp, char *search_value, char ***filelist, int *entries) {
char buf[LIBMPQ_CONF_BUFSIZE];
char temp[LIBMPQ_CONF_BUFSIZE];
int level = 0;
int array_start = 0;
int array_end = 0;
int fl_count;
int fl_size;
int found = 0;
int i = 0;
*entries = 0;
/* allocate memory for the file list */
(*filelist) = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
fl_count = 0;
fl_size = LIBMPQ_CONF_FL_INCREMENT;
while (fgets(buf, LIBMPQ_CONF_BUFSIZE, fp) != NULL) {
char *line;
buf[strlen(buf) - 1] = '\0';
/* skip whitespace */
for (line = buf; isspace(*line); line++) {
continue;
}
/* skip empty line */
if (line[0] == '\0') {
continue;
}
/* skip comments */
if (line[0] == '#') {
continue;
}
/* check for array end ) */
if (*line == ')') {
array_end = 1;
break;
}
/* process entries between () */
if (array_start == 1 && array_end == 0) {
/* add dummy option to use with libmpq_conf_parse_line() */
strncpy(temp, "MPQ_BUFFER = ", LIBMPQ_CONF_BUFSIZE);
strncat(temp, line, LIBMPQ_CONF_BUFSIZE);
found = libmpq_conf_parse_line(temp, "MPQ_BUFFER", temp, LIBMPQ_CONF_BUFSIZE);
if (found == 1) {
libmpq_conf_delete_char(temp, "\"\\");
/* set the next filelist entry to a copy of the file */
(*filelist)[fl_count++] = _strdup(temp);
/* increase the array size */
if (fl_count == fl_size) {
(*filelist) = (char **)realloc((*filelist), (fl_size + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
fl_size += LIBMPQ_CONF_FL_INCREMENT;
}
/* increase number of entries */
(*entries)++;
}
}
/* process the line and search array start */
//if (!strncasecmp(line, search_value, strlen(search_value))) {
if (!strcmp(line, search_value)) {
/* search value */
while (*(++line)) {
/* check for array start ( */
if (*line == '(' && level == 1) {
/* we found our value so break */
array_start = 1;
break;
}
/* check for '=' so the value follows as next parameter */
if (*line == '=' && level == 0) {
level = 1;
}
}
}
}
/* we got all files, so rewind stream */
fseek(fp, 0L, SEEK_SET);
(*filelist)[fl_count] = NULL;
return found;
}

View file

@ -1,185 +0,0 @@
/*
* wave.c -- this file contains decompression methods used by Storm.dll
* to decompress wave files.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of wave.cpp included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* Tom Amigo <tomamigo@apexmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "wave.h"
/* Tables necessary dor decompression */
static unsigned long wave_table_1503f120[] = {
0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000006,
0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0x00000005, 0xFFFFFFFF, 0x00000003, 0xFFFFFFFF, 0x00000007,
0xFFFFFFFF, 0x00000002, 0xFFFFFFFF, 0x00000004, 0xFFFFFFFF, 0x00000006, 0xFFFFFFFF, 0x00000008
};
static unsigned long wave_table_1503f1a0[] = {
0x00000007, 0x00000008, 0x00000009, 0x0000000A, 0x0000000B, 0x0000000C, 0x0000000D, 0x0000000E,
0x00000010, 0x00000011, 0x00000013, 0x00000015, 0x00000017, 0x00000019, 0x0000001C, 0x0000001F,
0x00000022, 0x00000025, 0x00000029, 0x0000002D, 0x00000032, 0x00000037, 0x0000003C, 0x00000042,
0x00000049, 0x00000050, 0x00000058, 0x00000061, 0x0000006B, 0x00000076, 0x00000082, 0x0000008F,
0x0000009D, 0x000000AD, 0x000000BE, 0x000000D1, 0x000000E6, 0x000000FD, 0x00000117, 0x00000133,
0x00000151, 0x00000173, 0x00000198, 0x000001C1, 0x000001EE, 0x00000220, 0x00000256, 0x00000292,
0x000002D4, 0x0000031C, 0x0000036C, 0x000003C3, 0x00000424, 0x0000048E, 0x00000502, 0x00000583,
0x00000610, 0x000006AB, 0x00000756, 0x00000812, 0x000008E0, 0x000009C3, 0x00000ABD, 0x00000BD0,
0x00000CFF, 0x00000E4C, 0x00000FBA, 0x0000114C, 0x00001307, 0x000014EE, 0x00001706, 0x00001954,
0x00001BDC, 0x00001EA5, 0x000021B6, 0x00002515, 0x000028CA, 0x00002CDF, 0x0000315B, 0x0000364B,
0x00003BB9, 0x000041B2, 0x00004844, 0x00004F7E, 0x00005771, 0x0000602F, 0x000069CE, 0x00007462,
0x00007FFF
};
/*
* Decompress a wave file, mono or stereo
*
* Offset: 1500F230
*/
int libmpq_wave_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels) {
byte_and_short out;
byte_and_short in;
unsigned char *in_end = in_buf + in_length; /* End on input buffer */
unsigned long index;
long nr_array1[2];
long nr_array2[2];
int count = 0;
out.pb = out_buf;
in.pb = in_buf;
nr_array1[0] = 0x2C;
nr_array1[1] = 0x2C;
in.pw++;
/* 15007AD7 */
for (count = 0; count < channels; count++) {
long temp;
temp = *(short *)in.pw++;
nr_array2[count] = temp;
if (out_length < 2) {
return out.pb - out_buf;
}
*out.pw++ = (unsigned short)temp;
out_length -= 2;
}
index = channels - 1;
while (in.pb < in_end) {
unsigned char one_byte = *in.pb++;
if (channels == 2) {
index = (index == 0) ? 1 : 0;
}
/*
* Get one byte from input buffer
* 15007B25
*/
if (one_byte & 0x80) {
/* 15007B32 */
switch(one_byte & 0x7F) {
case 0: /* 15007B8E */
if (nr_array1[index] != 0) {
nr_array1[index]--;
}
if (out_length < 2) {
break;
}
*out.pw++ = (unsigned short)nr_array2[index];
out_length -= 2;
continue;
case 1: /* 15007B72 */
nr_array1[index] += 8; /* EBX also */
if (nr_array1[index] > 0x58) {
nr_array1[index] = 0x58;
}
if (channels == 2) {
index = (index == 0) ? 1 : 0;
}
continue;
case 2:
continue;
default:
nr_array1[index] -= 8;
if (nr_array1[index] < 0) {
nr_array1[index] = 0;
}
if (channels != 2) {
continue;
}
index = (index == 0) ? 1 : 0;
continue;
}
} else {
unsigned long temp1 = wave_table_1503f1a0[nr_array1[index]]; /* EDI */
unsigned long temp2 = temp1 >> in_buf[1]; /* ESI */
long temp3 = nr_array2[index]; /* ECX */
if (one_byte & 0x01) { /* EBX = one_byte */
temp2 += (temp1 >> 0);
}
if (one_byte & 0x02) {
temp2 += (temp1 >> 1);
}
if (one_byte & 0x04) {
temp2 += (temp1 >> 2);
}
if (one_byte & 0x08) {
temp2 += (temp1 >> 3);
}
if (one_byte & 0x10) {
temp2 += (temp1 >> 4);
}
if (one_byte & 0x20) {
temp2 += (temp1 >> 5);
}
if(one_byte & 0x40) {
temp3 -= temp2;
if (temp3 <= (long)0xFFFF8000) {
temp3 = (long)0xFFFF8000;
}
} else {
temp3 += temp2;
if (temp3 >= 0x7FFF) {
temp3 = 0x7FFF;
}
}
nr_array2[index] = temp3;
if (out_length < 2) {
break;
}
temp2 = nr_array1[index];
one_byte &= 0x1F;
*out.pw++ = (unsigned short)temp3;
out_length -= 2;
temp2 += wave_table_1503f120[one_byte];
nr_array1[index] = temp2;
if (nr_array1[index] < 0) {
nr_array1[index] = 0;
} else {
if (nr_array1[index] > 0x58) {
nr_array1[index] = 0x58;
}
}
}
}
return (out.pb - out_buf);
}

View file

@ -1,37 +0,0 @@
/*
* wave.h -- header file for WAVe unplode functions used by mpq-tools.
*
* Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
*
* This source was adepted from the C++ version of wave.h included
* in stormlib. The C++ version belongs to the following authors,
*
* Ladislav Zezula <ladik.zezula.net>
* Tom Amigo <tomamigo@apexmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _WAVE_H
#define _WAVE_H
typedef union {
unsigned short *pw;
unsigned char *pb;
} byte_and_short;
int libmpq_wave_decompress(unsigned char *out_buf, int out_length, unsigned char *in_buf, int in_length, int channels);
#endif /* _WAVE_H */

View file

@ -1,323 +0,0 @@
/* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2003 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id$ */
#ifndef ZCONF_H
#define ZCONF_H
/*
* If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
*/
#ifdef Z_PREFIX
# define deflateInit_ z_deflateInit_
# define deflate z_deflate
# define deflateEnd z_deflateEnd
# define inflateInit_ z_inflateInit_
# define inflate z_inflate
# define inflateEnd z_inflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateSetDictionary z_deflateSetDictionary
# define deflateCopy z_deflateCopy
# define deflateReset z_deflateReset
# define deflatePrime z_deflatePrime
# define deflateParams z_deflateParams
# define deflateBound z_deflateBound
# define inflateInit2_ z_inflateInit2_
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateCopy z_inflateCopy
# define inflateReset z_inflateReset
# define compress z_compress
# define compress2 z_compress2
# define compressBound z_compressBound
# define uncompress z_uncompress
# define adler32 z_adler32
# define crc32 z_crc32
# define get_crc_table z_get_crc_table
# define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
# define Bytef z_Bytef
# define charf z_charf
# define intf z_intf
# define uIntf z_uIntf
# define uLongf z_uLongf
# define voidpf z_voidpf
# define voidp z_voidp
#endif
#if defined(__MSDOS__) && !defined(MSDOS)
# define MSDOS
#endif
#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
# define OS2
#endif
#if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
#endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32)
# define WIN32
#endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
# ifndef SYS16BIT
# define SYS16BIT
# endif
# endif
#endif
/*
* Compile with -DMAXSEG_64K if the alloc function cannot allocate more
* than 64k bytes at a time (needed on systems with 16-bit int).
*/
#ifdef SYS16BIT
# define MAXSEG_64K
#endif
#ifdef MSDOS
# define UNALIGNED_OK
#endif
#ifdef __STDC_VERSION__
# ifndef STDC
# define STDC
# endif
# if __STDC_VERSION__ >= 199901L
# ifndef STDC99
# define STDC99
# endif
# endif
#endif
#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
# define STDC
#endif
#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
# define STDC
#endif
#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
# define STDC
#endif
#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
# define STDC
#endif
#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */
# define STDC
#endif
#ifndef STDC
# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
# define const /* note: need a more gentle solution here */
# endif
#endif
/* Some Mac compilers merge all .h files incorrectly: */
#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
# define NO_DUMMY_DECL
#endif
/* Maximum value for memLevel in deflateInit2 */
#ifndef MAX_MEM_LEVEL
# ifdef MAXSEG_64K
# define MAX_MEM_LEVEL 8
# else
# define MAX_MEM_LEVEL 9
# endif
#endif
/* Maximum value for windowBits in deflateInit2 and inflateInit2.
* WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
* created by gzip. (Files created by minigzip can still be extracted by
* gzip.)
*/
#ifndef MAX_WBITS
# define MAX_WBITS 15 /* 32K LZ77 window */
#endif
/* The memory requirements for deflate are (in bytes):
(1 << (windowBits+2)) + (1 << (memLevel+9))
that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
plus a few kilobytes for small objects. For example, if you want to reduce
the default memory requirements from 256K to 128K, compile with
make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
Of course this will generally degrade compression (there's no free lunch).
The memory requirements for inflate are (in bytes) 1 << windowBits
that is, 32K for windowBits=15 (default value) plus a few kilobytes
for small objects.
*/
/* Type declarations */
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
/* The following definitions for FAR are needed only for MSDOS mixed
* model programming (small or medium model with some far allocations).
* This was tested only with MSC; for other MSDOS compilers you may have
* to define NO_MEMCPY in zutil.h. If you don't need the mixed model,
* just define FAR to be empty.
*/
#ifdef SYS16BIT
# if defined(M_I86SM) || defined(M_I86MM)
/* MSC small or medium model */
# define SMALL_MEDIUM
# ifdef _MSC_VER
# define FAR _far
# else
# define FAR far
# endif
# endif
# if (defined(__SMALL__) || defined(__MEDIUM__))
/* Turbo C small or medium model */
# define SMALL_MEDIUM
# ifdef __BORLANDC__
# define FAR _far
# else
# define FAR far
# endif
# endif
#endif
#if defined(WINDOWS) || defined(WIN32)
/* If building or using zlib as a DLL, define ZLIB_DLL.
* This is not mandatory, but it offers a little performance increase.
*/
# ifdef ZLIB_DLL
# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
# ifdef ZLIB_INTERNAL
# define ZEXTERN extern __declspec(dllexport)
# else
# define ZEXTERN extern __declspec(dllimport)
# endif
# endif
# endif /* ZLIB_DLL */
/* If building or using zlib with the WINAPI/WINAPIV calling convention,
* define ZLIB_WINAPI.
* Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
*/
# ifdef ZLIB_WINAPI
# ifdef FAR
# undef FAR
# endif
# include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */
# define ZEXPORT WINAPI
# ifdef WIN32
# define ZEXPORTVA WINAPIV
# else
# define ZEXPORTVA FAR CDECL
# endif
# endif
#endif
#if defined (__BEOS__)
# ifdef ZLIB_DLL
# ifdef ZLIB_INTERNAL
# define ZEXPORT __declspec(dllexport)
# define ZEXPORTVA __declspec(dllexport)
# else
# define ZEXPORT __declspec(dllimport)
# define ZEXPORTVA __declspec(dllimport)
# endif
# endif
#endif
#ifndef ZEXTERN
# define ZEXTERN extern
#endif
#ifndef ZEXPORT
# define ZEXPORT
#endif
#ifndef ZEXPORTVA
# define ZEXPORTVA
#endif
#ifndef FAR
# define FAR
#endif
#if !defined(__MACTYPES__)
typedef unsigned char Byte; /* 8 bits */
#endif
typedef unsigned int uInt; /* 16 bits or more */
typedef unsigned long uLong; /* 32 bits or more */
#ifdef SMALL_MEDIUM
/* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
# define Bytef Byte FAR
#else
typedef Byte FAR Bytef;
#endif
typedef char FAR charf;
typedef int FAR intf;
typedef uInt FAR uIntf;
typedef uLong FAR uLongf;
#ifdef STDC
typedef void const *voidpc;
typedef void FAR *voidpf;
typedef void *voidp;
#else
typedef Byte const *voidpc;
typedef Byte FAR *voidpf;
typedef Byte *voidp;
#endif
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */
# include <sys/types.h> /* for off_t */
# include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS
# include <unixio.h> /* for off_t */
# endif
# define z_off_t off_t
#endif
#ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif
#ifndef z_off_t
# define z_off_t long
#endif
#if defined(__OS400__)
#define NO_vsnprintf
#endif
#if defined(__MVS__)
# define NO_vsnprintf
# ifdef FAR
# undef FAR
# endif
#endif
/* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__)
# pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND")
# pragma map(deflateBound,"DEBND")
# pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI")
# pragma map(compressBound,"CMBND")
# pragma map(inflate_table,"INTABL")
# pragma map(inflate_fast,"INFA")
# pragma map(inflate_copyright,"INCOPY")
#endif
#endif /* ZCONF_H */

File diff suppressed because it is too large Load diff

View file

@ -48,6 +48,27 @@ bool ADT_file::prepareLoadedData()
if (!a_grid->prepareLoadedData())
return false;
// funny offsets calculations because there is no mapping for them and they have variable lengths
uint8* ptr = (uint8*)a_grid + a_grid->size + 8;
uint32 mcnk_count = 0;
memset(cells, 0, ADT_CELLS_PER_GRID * ADT_CELLS_PER_GRID * sizeof(adt_MCNK*));
while (ptr < GetData() + GetDataSize())
{
uint32 header = *(uint32*)ptr;
uint32 size = *(uint32*)(ptr + 4);
if (header == 'MCNK')
{
cells[mcnk_count / ADT_CELLS_PER_GRID][mcnk_count % ADT_CELLS_PER_GRID] = (adt_MCNK*)ptr;
++mcnk_count;
}
// move to next chunk
ptr += size + 8;
}
if (mcnk_count != ADT_CELLS_PER_GRID * ADT_CELLS_PER_GRID)
return false;
return true;
}

View file

@ -25,6 +25,7 @@ enum LiquidType
//
// Adt file height map chunk
//
class ADT_file;
class adt_MCVT
{
union{
@ -252,9 +253,11 @@ class adt_MHDR
uint32 fcc;
char fcc_txt[4];
};
public:
uint32 size;
uint32 pad;
uint32 flags;
uint32 offsMCIN; // MCIN
uint32 offsTex; // MTEX
uint32 offsModels; // MMDX
@ -272,8 +275,8 @@ class adt_MHDR
uint32 data5;
public:
bool prepareLoadedData();
adt_MCIN *getMCIN(){ return (adt_MCIN *)((uint8 *)&pad+offsMCIN);}
adt_MH2O *getMH2O(){ return offsMH2O ? (adt_MH2O *)((uint8 *)&pad+offsMH2O) : 0;}
adt_MCIN* getMCIN() { return offsMCIN ? (adt_MCIN *)((uint8 *)&flags+offsMCIN) : 0; }
adt_MH2O* getMH2O() { return offsMH2O ? (adt_MH2O *)((uint8 *)&flags+offsMH2O) : 0; }
};
@ -284,7 +287,8 @@ public:
~ADT_file();
void free();
adt_MHDR *a_grid;
adt_MHDR* a_grid;
adt_MCNK* cells[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
};
bool isHole(int holes, int i, int j);

View file

@ -1,11 +1,78 @@
#define _CRT_SECURE_NO_DEPRECATE
#include "loadlib.h"
#include "../mpq_libmpq.h"
#include <stdio.h>
// list of mpq files for lookup most recent file version
ArchiveSet gOpenArchives;
class MPQFile;
ArchiveSetBounds GetArchivesBounds()
{
return ArchiveSetBounds(gOpenArchives.begin(), gOpenArchives.end());
}
bool OpenArchive(char const* mpqFileName, HANDLE* mpqHandlePtr /*= NULL*/)
{
HANDLE mpqHandle;
if (!SFileOpenArchive(mpqFileName, 0, MPQ_OPEN_READ_ONLY, &mpqHandle))
return false;
gOpenArchives.push_back(mpqHandle);
if (mpqHandlePtr)
*mpqHandlePtr = mpqHandle;
return true;
}
bool OpenNewestFile(char const* filename, HANDLE* fileHandlerPtr)
{
for(ArchiveSet::const_reverse_iterator i=gOpenArchives.rbegin(); i!=gOpenArchives.rend();++i)
{
// always prefer get updated file version
if (SFileOpenFileEx(*i, filename, SFILE_OPEN_PATCHED_FILE, fileHandlerPtr))
return true;
}
return false;
}
bool ExtractFile( char const* mpq_name, std::string const& filename )
{
for(ArchiveSet::const_reverse_iterator i=gOpenArchives.rbegin(); i!=gOpenArchives.rend();++i)
{
HANDLE fileHandle;
if (!SFileOpenFileEx(*i, mpq_name, SFILE_OPEN_PATCHED_FILE, &fileHandle))
continue;
if (SFileGetFileSize(fileHandle, NULL) == 0) // some files removed in next updates and its reported size 0
{
SFileCloseFile(fileHandle);
return true;
}
SFileCloseFile(fileHandle);
if (!SFileExtractFile(*i, mpq_name, filename.c_str(), SFILE_OPEN_PATCHED_FILE))
{
printf("Can't extract file: %s\n", mpq_name);
return false;
}
return true;
}
printf("Extracting file not found: %s\n", filename.c_str());
return false;
}
void CloseArchives()
{
for(ArchiveSet::const_iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i)
SFileCloseArchive(*i);
gOpenArchives.clear();
}
FileLoader::FileLoader()
{
@ -22,36 +89,54 @@ FileLoader::~FileLoader()
bool FileLoader::loadFile(char *filename, bool log)
{
free();
MPQFile mf(filename);
if(mf.isEof())
HANDLE fileHandle = 0;
if (!OpenNewestFile(filename, &fileHandle))
{
if (log)
printf("No such file %s\n", filename);
return false;
}
data_size = mf.getSize();
data_size = SFileGetFileSize(fileHandle, NULL);
data = new uint8 [data_size];
if (data)
if (!data)
{
mf.read(data, data_size);
mf.close();
if (prepareLoadedData())
return true;
SFileCloseFile(fileHandle);
return false;
}
printf("Error loading %s", filename);
mf.close();
free();
return false;
if (!SFileReadFile(fileHandle, data, data_size, NULL, NULL))
{
if (log)
printf("Can't read file %s\n", filename);
SFileCloseFile(fileHandle);
return false;
}
SFileCloseFile(fileHandle);
// ToDo: Fix WDT errors...
if (!prepareLoadedData())
{
//printf("Error loading %s\n\n", filename);
//free();
return true;
}
return true;
}
bool FileLoader::prepareLoadedData()
{
// Check version
version = (file_MVER *) data;
if (version->fcc != 'MVER')
return false;
if (version->ver != FILE_FORMAT_VERSION)
return false;
return true;

View file

@ -1,6 +1,13 @@
#ifndef LOAD_LIB_H
#define LOAD_LIB_H
#ifdef _DLL
#undef _DLL
#endif
#include "StormLib.h"
#include <deque>
#ifdef WIN32
typedef __int64 int64;
typedef __int32 int32;
@ -27,6 +34,15 @@ typedef uint16_t uint16;
typedef uint8_t uint8;
#endif
typedef std::deque<HANDLE> ArchiveSet;
typedef std::pair<ArchiveSet::const_iterator,ArchiveSet::const_iterator> ArchiveSetBounds;
bool OpenArchive(char const* mpqFileName, HANDLE* mpqHandlePtr = NULL);
bool OpenNewestFile(char const* filename, HANDLE* fileHandlerPtr);
ArchiveSetBounds GetArchivesBounds();
bool ExtractFile( char const* mpq_name, std::string const& filename );
void CloseArchives();
#define FILE_FORMAT_VERSION 18
//

View file

@ -1,133 +0,0 @@
#include "mpq_libmpq.h"
#include <deque>
#include <stdio.h>
ArchiveSet gOpenArchives;
MPQArchive::MPQArchive(const char* filename)
{
int result = libmpq_archive_open(&mpq_a, (unsigned char*)filename);
printf("Opening %s\n", filename);
if(result) {
switch(result) {
case LIBMPQ_EFILE : /* error on file operation */
printf("Error opening archive '%s': File operation Error\n", filename);
break;
case LIBMPQ_EFILE_FORMAT : /* bad file format */
printf("Error opening archive '%s': Bad file format\n", filename);
break;
case LIBMPQ_EFILE_CORRUPT : /* file corrupt */
printf("Error opening archive '%s': File corrupt\n", filename);
break;
case LIBMPQ_EFILE_NOT_FOUND : /* file in archive not found */
printf("Error opening archive '%s': File in archive not found\n", filename);
break;
case LIBMPQ_EFILE_READ : /* Read error in archive */
printf("Error opening archive '%s': Read error in archive\n", filename);
break;
case LIBMPQ_EALLOCMEM : /* maybe not enough memory? :) */
printf("Error opening archive '%s': Maybe not enough memory\n", filename);
break;
case LIBMPQ_EFREEMEM : /* can not free memory */
printf("Error opening archive '%s': Cannot free memory\n", filename);
break;
case LIBMPQ_EINV_RANGE : /* Given filenumber is out of range */
printf("Error opening archive '%s': Given filenumber is out of range\n", filename);
break;
case LIBMPQ_EHASHTABLE : /* error in reading hashtable */
printf("Error opening archive '%s': Error in reading hashtable\n", filename);
break;
case LIBMPQ_EBLOCKTABLE : /* error in reading blocktable */
printf("Error opening archive '%s': Error in reading blocktable\n", filename);
break;
default:
printf("Error opening archive '%s': Unknown error\n", filename);
break;
}
return;
}
gOpenArchives.push_front(this);
}
void MPQArchive::close()
{
//gOpenArchives.erase(erase(&mpq_a);
libmpq_archive_close(&mpq_a);
}
MPQFile::MPQFile(const char* filename):
eof(false),
buffer(0),
pointer(0),
size(0)
{
for(ArchiveSet::iterator i=gOpenArchives.begin(); i!=gOpenArchives.end();++i)
{
mpq_archive &mpq_a = (*i)->mpq_a;
mpq_hash hash = (*i)->GetHashEntry(filename);
uint32 blockindex = hash.blockindex;
if (blockindex == 0xFFFFFFFF)
continue; //file not found
uint32 fileno = blockindex;
//int fileno = libmpq_file_number(&mpq_a, filename);
//if(fileno == LIBMPQ_EFILE_NOT_FOUND)
// continue;
// Found!
size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, fileno);
// HACK: in patch.mpq some files don't want to open and give 1 for filesize
if (size<=1) {
eof = true;
buffer = 0;
return;
}
buffer = new char[size];
//libmpq_file_getdata
libmpq_file_getdata(&mpq_a, hash, fileno, (unsigned char*)buffer);
return;
}
eof = true;
buffer = 0;
}
size_t MPQFile::read(void* dest, size_t bytes)
{
if (eof) return 0;
size_t rpos = pointer + bytes;
if (rpos > size) {
bytes = size - pointer;
eof = true;
}
memcpy(dest, &(buffer[pointer]), bytes);
pointer = rpos;
return bytes;
}
void MPQFile::seek(int offset)
{
pointer = offset;
eof = (pointer >= size);
}
void MPQFile::seekRelative(int offset)
{
pointer += offset;
eof = (pointer >= size);
}
void MPQFile::close()
{
if (buffer) delete[] buffer;
buffer = 0;
eof = true;
}

View file

@ -1,121 +0,0 @@
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#ifndef MPQ_H
#define MPQ_H
#include "loadlib/loadlib.h"
#include "libmpq/mpq.h"
#include <string.h>
#include <ctype.h>
#include <vector>
#include <iostream>
#include <deque>
using namespace std;
class MPQArchive
{
public:
mpq_archive mpq_a;
MPQArchive(const char* filename);
void close();
uint32 HashString(const char* Input, uint32 Offset) {
uint32 seed1 = 0x7fed7fed;
uint32 seed2 = 0xeeeeeeee;
for (uint32 i = 0; i < strlen(Input); i++) {
uint32 val = toupper(Input[i]);
seed1 = mpq_a.buf[Offset + val] ^ (seed1 + seed2);
seed2 = val + seed1 + seed2 + (seed2 << 5) + 3;
}
return seed1;
}
mpq_hash GetHashEntry(const char* Filename) {
uint32 index = HashString(Filename, 0);
index &= mpq_a.header->hashtablesize - 1;
uint32 name1 = HashString(Filename, 0x100);
uint32 name2 = HashString(Filename, 0x200);
for(uint32 i = index; i < mpq_a.header->hashtablesize; ++i) {
mpq_hash hash = mpq_a.hashtable[i];
if (hash.name1 == name1 && hash.name2 == name2) return hash;
}
mpq_hash nullhash;
nullhash.blockindex = 0xFFFFFFFF;
return nullhash;
}
void GetFileListTo(vector<string>& filelist) {
mpq_hash hash = GetHashEntry("(listfile)");
uint32 blockindex = hash.blockindex;
if ((blockindex == 0xFFFFFFFF) || (blockindex == 0))
return;
uint32 size = libmpq_file_info(&mpq_a, LIBMPQ_FILE_UNCOMPRESSED_SIZE, blockindex);
char *buffer = new char[size];
libmpq_file_getdata(&mpq_a, hash, blockindex, (unsigned char*)buffer);
char seps[] = "\n";
char *token;
token = strtok( buffer, seps );
uint32 counter = 0;
while ((token != NULL) && (counter < size)) {
//cout << token << endl;
token[strlen(token) - 1] = 0;
string s = token;
filelist.push_back(s);
counter += strlen(token) + 2;
token = strtok(NULL, seps);
}
delete[] buffer;
}
};
typedef std::deque<MPQArchive*> ArchiveSet;
class MPQFile
{
//MPQHANDLE handle;
bool eof;
char *buffer;
size_t pointer,size;
// disable copying
MPQFile(const MPQFile &f) {}
void operator=(const MPQFile &f) {}
public:
MPQFile(const char* filename); // filenames are not case sensitive
~MPQFile() { close(); }
size_t read(void* dest, size_t bytes);
size_t getSize() { return size; }
size_t getPos() { return pointer; }
char* getBuffer() { return buffer; }
char* getPointer() { return buffer + pointer; }
bool isEof() { return eof; }
void seek(int offset);
void seekRelative(int offset);
void close();
};
inline void flipcc(char *fcc)
{
char t;
t=fcc[0];
fcc[0]=fcc[3];
fcc[3]=t;
t=fcc[1];
fcc[1]=fcc[2];
fcc[2]=t;
}
#endif

Binary file not shown.