diff options
Diffstat (limited to 'src/tools')
32 files changed, 1165 insertions, 1148 deletions
diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt index 55a136f6329..b84e56e5734 100644 --- a/src/tools/map_extractor/CMakeLists.txt +++ b/src/tools/map_extractor/CMakeLists.txt @@ -11,34 +11,24 @@ file(GLOB_RECURSE sources *.cpp *.h) -if( UNIX ) - include_directories ( - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/dep/libmpq - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/loadlib - ) -elseif( WIN32 ) - include_directories ( - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/dep/libmpq - ${CMAKE_SOURCE_DIR}/dep/libmpq/win - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/loadlib - ) -endif() +include_directories ( + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/dep/StormLib/src + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/loadlib +) add_executable(mapextractor ${sources} ) target_link_libraries(mapextractor - mpq ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES} + storm ) -add_dependencies(mapextractor mpq) +add_dependencies(mapextractor storm) if( UNIX ) install(TARGETS mapextractor DESTINATION bin) diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index d0342717324..63132d269b2 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -2,7 +2,7 @@ #include <stdio.h> #include <deque> -#include <set> +#include <list> #include <cstdlib> #ifdef _WIN32 @@ -10,10 +10,11 @@ #else #include <sys/stat.h> #include <unistd.h> +#define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND #endif +#include "StormLib.h" #include "dbcfile.h" -#include "mpq_libmpq04.h" #include "adt.h" #include "wdt.h" @@ -30,11 +31,13 @@ #endif #ifdef O_LARGEFILE - #define OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE) + #define OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE) #else #define OPEN_FLAGS (O_RDONLY | O_BINARY) #endif -extern ArchiveSet gOpenArchives; + +HANDLE WorldMpq = NULL; +HANDLE LocaleMpq = NULL; typedef struct { @@ -60,6 +63,7 @@ enum Extract // Select data for extract int CONF_extract = EXTRACT_MAP | EXTRACT_DBC; + // This option allow limit minimum height to some value (Allow save some memory) bool CONF_allow_height_limit = true; float CONF_use_minHeight = -500.0f; @@ -71,34 +75,47 @@ 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 -const 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", +uint32 CONF_TargetBuild = 15595; // 4.3.4.15595 + +// List MPQ for extract maps from +char const* CONF_mpq_list[]= +{ + "world.MPQ", + "art.MPQ", + "world2.MPQ", + "expansion1.MPQ", + "expansion2.MPQ", + "expansion3.MPQ", }; -static const char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; -#define LANG_COUNT 12 +uint32 const Builds[] = {13164, 13205, 13287, 13329, 13596, 13623, 13914, 14007, 14333, 14480, 14545, 15005, 15050, 15211, 15354, 15595, 0}; +#define LAST_DBC_IN_DATA_BUILD 13623 // after this build mpqs with dbc are back to locale folder -void CreateDir( const std::string& Path ) +char* const Locales[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU"}; +TCHAR* const LocalesT[] = { - #ifdef _WIN32 - _mkdir( Path.c_str()); - #else - mkdir( Path.c_str(), 0777 ); - #endif + _T("enGB"), _T("enUS"), + _T("deDE"), _T("esES"), + _T("frFR"), _T("koKR"), + _T("zhCN"), _T("zhTW"), + _T("enCN"), _T("enTW"), + _T("esMX"), _T("ruRU"), +}; + +#define LOCALES_COUNT 12 + +void CreateDir(std::string const& path) +{ +#ifdef _WIN32 + _mkdir(path.c_str()); +#else + mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); // 0777 +#endif } -bool FileExists( const char* FileName ) +bool FileExists(TCHAR const* fileName) { - int fp = _open(FileName, OPEN_FLAGS); + int fp = _open(fileName, OPEN_FLAGS); if(fp != -1) { _close(fp); @@ -117,52 +134,62 @@ void Usage(char* prg) "-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); + "-b target build (default %u)"\ + "Example: %s -f 0 -i \"c:\\games\\game\"", prg, CONF_TargetBuild, prg); exit(1); } void HandleArgs(int argc, char * arg[]) { - for(int c = 1; c < argc; ++c) + for (int c = 1; c < argc; ++c) { // i - input path // o - output path // e - extract only MAP(1)/DBC(2) - standard both(3) // f - use float to int conversion // h - limit minimum height - if(arg[c][0] != '-') + // b - target client build + if (arg[c][0] != '-') Usage(arg[0]); - switch(arg[c][1]) + switch (arg[c][1]) { case 'i': - if(c + 1 < argc) // all ok - strcpy(input_path, arg[(c++) + 1]); + if (c + 1 < argc) // all ok + strcpy(input_path, arg[c++ + 1]); else Usage(arg[0]); break; case 'o': - if(c + 1 < argc) // all ok - strcpy(output_path, arg[(c++) + 1]); + if (c + 1 < argc) // all ok + strcpy(output_path, arg[c++ + 1]); else Usage(arg[0]); break; case 'f': - if(c + 1 < argc) // all ok - CONF_allow_float_to_int=atoi(arg[(c++) + 1])!=0; + if (c + 1 < argc) // all ok + CONF_allow_float_to_int = atoi(arg[c++ + 1])!=0; else Usage(arg[0]); break; case 'e': - if(c + 1 < argc) // all ok + if (c + 1 < argc) // all ok { - CONF_extract=atoi(arg[(c++) + 1]); - if(!(CONF_extract > 0 && CONF_extract < 4)) + CONF_extract = atoi(arg[c++ + 1]); + if (!(CONF_extract > 0 && CONF_extract < 4)) Usage(arg[0]); } else Usage(arg[0]); break; + case 'b': + if (c + 1 < argc) // all ok + CONF_TargetBuild = atoi(arg[c++ + 1]); + else + Usage(arg[0]); + break; + default: + break; } } } @@ -170,22 +197,31 @@ void HandleArgs(int argc, char * arg[]) uint32 ReadBuild(int locale) { // include build info file also - std::string filename = std::string("component.wow-")+langs[locale]+".txt"; + std::string filename = std::string("component.wow-") + Locales[locale] + ".txt"; //printf("Read %s file... ", filename.c_str()); - MPQFile m(filename.c_str()); - if(m.isEof()) + HANDLE dbcFile; + if (!SFileOpenFileEx(LocaleMpq, filename.c_str(), SFILE_OPEN_PATCHED_FILE, &dbcFile)) { printf("Fatal error: Not found %s file!\n", filename.c_str()); exit(1); } - std::string text = m.getPointer(); - m.close(); + char buff[512]; + DWORD readBytes = 0; + SFileReadFile(dbcFile, buff, 512, &readBytes, NULL); + if (!readBytes) + { + printf("Fatal error: Not found %s file!\n", filename.c_str()); + exit(1); + } + + std::string text = buff; + SFileCloseFile(dbcFile); size_t pos = text.find("version=\""); size_t pos1 = pos + strlen("version=\""); - size_t pos2 = text.find("\"",pos1); + size_t pos2 = text.find("\"", pos1); if (pos == text.npos || pos2 == text.npos || pos1 >= pos2) { printf("Fatal error: Invalid %s file format!\n", filename.c_str()); @@ -207,9 +243,16 @@ uint32 ReadBuild(int locale) uint32 ReadMapDBC() { printf("Read Map.dbc file... "); - DBCFile dbc("DBFilesClient\\Map.dbc"); - if(!dbc.open()) + HANDLE dbcFile; + if (!SFileOpenFileEx(LocaleMpq, "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"); exit(1); @@ -222,15 +265,23 @@ uint32 ReadMapDBC() map_ids[x].id = dbc.getRecord(x).getUInt(0); strcpy(map_ids[x].name, dbc.getRecord(x).getString(1)); } - printf("Done! (%zu maps loaded)\n", map_count); + + SFileCloseFile(dbcFile); + printf("Done! (%u maps loaded)\n", map_count); return map_count; } void ReadAreaTableDBC() { printf("Read AreaTable.dbc file..."); - DBCFile dbc("DBFilesClient\\AreaTable.dbc"); + HANDLE dbcFile; + if (!SFileOpenFileEx(LocaleMpq, "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()) { printf("Fatal error: Invalid AreaTable.dbc file format!\n"); @@ -238,22 +289,27 @@ void ReadAreaTableDBC() } size_t area_count = dbc.getRecordCount(); - size_t maxid = dbc.getMaxId(); - areas = new uint16[maxid + 1]; - memset(areas, 0xff, (maxid + 1) * sizeof(uint16)); + maxAreaId = dbc.getMaxId(); + areas = new uint16[maxAreaId + 1]; - for(uint32 x = 0; x < area_count; ++x) + for (uint32 x = 0; x < area_count; ++x) areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); - maxAreaId = dbc.getMaxId(); - - printf("Done! (%zu areas loaded)\n", area_count); + SFileCloseFile(dbcFile); + printf("Done! (%u areas loaded)\n", area_count); } void ReadLiquidTypeTableDBC() { printf("Read LiquidType.dbc file..."); - DBCFile dbc("DBFilesClient\\LiquidType.dbc"); + HANDLE dbcFile; + if (!SFileOpenFileEx(LocaleMpq, "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"); @@ -268,7 +324,8 @@ void ReadLiquidTypeTableDBC() for(uint32 x = 0; x < liqTypeCount; ++x) LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); - printf("Done! (%zu LiqTypes loaded)\n", liqTypeCount); + SFileCloseFile(dbcFile); + printf("Done! (%u LiqTypes loaded)\n", liqTypeCount); } // @@ -369,16 +426,9 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, { ADT_file adt; - if (!adt.loadFile(filename)) + if (!adt.loadFile(WorldMpq, filename)) 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_flags, 0, sizeof(liquid_flags)); memset(liquid_entry, 0, sizeof(liquid_entry)); @@ -390,24 +440,27 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, map.buildMagic = build; // Get area flags data - for (int i=0;i<ADT_CELLS_PER_GRID;i++) + for (int i = 0; i < ADT_CELLS_PER_GRID; ++i) { - for(int j=0;j<ADT_CELLS_PER_GRID;j++) + 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) + if (areaid && areaid <= maxAreaId) { - if(areas[areaid] != 0xffff) + if (areas[areaid] != 0xFFFF) { area_flags[i][j] = areas[areaid]; continue; } + printf("File: %s\nCan't find area flag for areaid %u [%d, %d].\n", filename, areaid, cell->ix, cell->iy); } + area_flags[i][j] = 0xffff; } } + //============================================ // Try pack area data //============================================ @@ -449,7 +502,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, { 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: @@ -620,7 +673,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, { 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; @@ -720,7 +773,7 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, // Dark water detect if (LiqType[h->liquidType] == LIQUID_TYPE_OCEAN) { - uint8 *lm = h2o->getLiquidLightMap(h); + uint8* lm = h2o->getLiquidLightMap(h); if (!lm) liquid_flags[i][j] |= MAP_LIQUID_TYPE_DARK_WATER; } @@ -728,34 +781,37 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, if (!count && liquid_flags[i][j]) printf("Wrong liquid detect in MH2O chunk"); - float *height = h2o->getLiquidHeightMap(h); + float* height = h2o->getLiquidHeightMap(h); int pos = 0; - for (int y=0; y<=h->height;y++) + for (int y = 0; y <= h->height; y++) { - int cy = i*ADT_CELL_SIZE + y + h->yOffset; - for (int x=0; x<= h->width; x++) + int cy = i * ADT_CELL_SIZE + y + h->yOffset; + for (int x = 0; x <= h->width; x++) { - int cx = j*ADT_CELL_SIZE + x + h->xOffset; + int cx = j * ADT_CELL_SIZE + x + h->xOffset; + if (height) liquid_height[cy][cx] = height[pos]; else liquid_height[cy][cx] = h->heightLevel1; + pos++; } } } } } + //============================================ // Pack liquid data //============================================ uint8 type = liquid_flags[0][0]; bool fullType = false; - for (int y=0;y<ADT_CELLS_PER_GRID;y++) + for (int y = 0; y < ADT_CELLS_PER_GRID; y++) { - for(int x=0;x<ADT_CELLS_PER_GRID;x++) + for (int x = 0; x < ADT_CELLS_PER_GRID; x++) { - if (liquid_flags[y][x]!=type) + if (liquid_flags[y][x] != type) { fullType = true; y = ADT_CELLS_PER_GRID; @@ -865,15 +921,16 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, if (map.liquidMapOffset) { fwrite(&liquidHeader, sizeof(liquidHeader), 1, output); - if (!(liquidHeader.flags&MAP_LIQUID_NO_TYPE)) + if (!(liquidHeader.flags & MAP_LIQUID_NO_TYPE)) { fwrite(liquid_entry, sizeof(liquid_entry), 1, output); fwrite(liquid_flags, sizeof(liquid_flags), 1, output); } - if (!(liquidHeader.flags&MAP_LIQUID_NO_HEIGHT)) + + if (!(liquidHeader.flags & MAP_LIQUID_NO_HEIGHT)) { - for (int y=0; y<liquidHeader.height;y++) - fwrite(&liquid_height[y+liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output); + for (int y = 0; y < liquidHeader.height; y++) + fwrite(&liquid_height[y + liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output); } } fclose(output); @@ -899,135 +956,244 @@ void ExtractMapsFromMpq(uint32 build) CreateDir(path); printf("Convert map files\n"); - for(uint32 z = 0; z < map_count; ++z) + for (uint32 z = 0; z < map_count; ++z) { printf("Extract %s (%d/%u) \n", map_ids[z].name, z+1, map_count); // Loadup map grid data 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); + if (!wdt.loadFile(WorldMpq, mpq_map_name, false)) continue; - } - for(uint32 y = 0; y < WDT_MAP_SIZE; ++y) + for (uint32 y = 0; y < WDT_MAP_SIZE; ++y) { - for(uint32 x = 0; x < WDT_MAP_SIZE; ++x) + for (uint32 x = 0; x < WDT_MAP_SIZE; ++x) { - if (!wdt.main->adt_list[y][x].exist) + if (!(wdt.main->adt_list[y][x].flag & 0x1)) 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); } + // draw progress bar printf("Processing........................%d%%\r", (100 * (y+1)) / WDT_MAP_SIZE); } } + printf("\n"); delete [] areas; delete [] map_ids; } -bool ExtractFile( char const* mpq_name, std::string const& filename ) +bool ExtractFile(HANDLE fileInArchive, char const* filename) { - FILE *output = fopen(filename.c_str(), "wb"); + FILE* output = fopen(filename, "wb"); if(!output) { - printf("Can't create the output file '%s'\n", filename.c_str()); + printf("Can't create the output file '%s'\n", filename); return false; } - MPQFile m(mpq_name); - if(!m.isEof()) - fwrite(m.getPointer(), 1, m.getSize(), output); + + char buffer[0x10000]; + DWORD readBytes = 1; + + while (readBytes > 0) + { + SFileReadFile(fileInArchive, buffer, sizeof(buffer), &readBytes, NULL); + if (readBytes > 0) + fwrite(buffer, 1, readBytes, output); + } fclose(output); return true; } -void ExtractDBCFiles(int locale, bool basicLocale) +void ExtractDBCFiles(int l, bool basicLocale) { printf("Extracting dbc files...\n"); - std::set<std::string> dbcfiles; - - // get DBC file list - for(ArchiveSet::iterator i = gOpenArchives.begin(); i != gOpenArchives.end();++i) + SFILE_FIND_DATA foundFile; + memset(&foundFile, 0, sizeof(foundFile)); + HANDLE listFile = SFileFindFirstFile(LocaleMpq, "DBFilesClient\\*dbc", &foundFile, NULL); + HANDLE dbcFile = NULL; + uint32 count = 0; + if (listFile) { - 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); - } + std::string outputPath = output_path; + outputPath += "/dbc/"; - std::string path = output_path; - path += "/dbc/"; - CreateDir(path); - if(!basicLocale) - { - path += langs[locale]; - path += "/"; - CreateDir(path); - } + CreateDir(outputPath); + if (!basicLocale) + { + outputPath += Locales[l]; + outputPath += "/"; + CreateDir(outputPath); + } - // extract Build info file - { - string mpq_name = std::string("component.wow-") + langs[locale] + ".txt"; - string filename = path + mpq_name; + std::string filename; - ExtractFile(mpq_name.c_str(), filename); - } + do + { + if (!SFileOpenFileEx(LocaleMpq, foundFile.cFileName, SFILE_OPEN_PATCHED_FILE, &dbcFile)) + { + printf("Unable to open file %s in the archive\n", foundFile.cFileName); + continue; + } - // extract DBCs - uint32 count = 0; - for (set<string>::iterator iter = dbcfiles.begin(); iter != dbcfiles.end(); ++iter) - { - string filename = path; - filename += (iter->c_str() + strlen("DBFilesClient\\")); + filename = foundFile.cFileName; + filename = outputPath + filename.substr(filename.rfind('\\')); + if (ExtractFile(dbcFile, filename.c_str())) + ++count; + + SFileCloseFile(dbcFile); + } while (SFileFindNextFile(listFile, &foundFile)); - if (ExtractFile(iter->c_str(), filename)) - ++count; + SFileFindClose(listFile); } + printf("Extracted %u DBC files\n\n", count); } -void LoadLocaleMPQFiles(int const locale) +void ExtractDB2Files(int l, bool basicLocale) { - char filename[512]; - - sprintf(filename,"%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]); - new MPQArchive(filename); + printf("Extracting db2 files...\n"); - for(int i = 1; i < 5; ++i) + SFILE_FIND_DATA foundFile; + memset(&foundFile, 0, sizeof(foundFile)); + HANDLE listFile = SFileFindFirstFile(LocaleMpq, "DBFilesClient\\*db2", &foundFile, NULL); + HANDLE dbcFile = NULL; + uint32 count = 0; + if (listFile) { - char ext[3] = ""; - if(i > 1) - sprintf(ext, "-%i", i); + std::string outputPath = output_path; + outputPath += "/dbc/"; + if (!basicLocale) + { + outputPath += Locales[l]; + outputPath += "/"; + } - sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ", input_path, langs[locale], langs[locale], ext); - if(FileExists(filename)) - new MPQArchive(filename); + std::string filename; + + do + { + if (!SFileOpenFileEx(LocaleMpq, foundFile.cFileName, SFILE_OPEN_PATCHED_FILE, &dbcFile)) + { + printf("Unable to open file %s in the archive\n", foundFile.cFileName); + continue; + } + + filename = foundFile.cFileName; + filename = outputPath + filename.substr(filename.rfind('\\')); + if (ExtractFile(dbcFile, filename.c_str())) + ++count; + + SFileCloseFile(dbcFile); + } while (SFileFindNextFile(listFile, &foundFile)); + + SFileFindClose(listFile); } + + printf("Extracted %u DB2 files\n\n", count); } -void LoadCommonMPQFiles() +bool LoadLocaleMPQFile(int locale) { - char filename[512]; - int count = sizeof(CONF_mpq_list)/sizeof(char*); - for(int i = 0; i < count; ++i) + TCHAR buff[512]; + memset(buff, 0, sizeof(buff)); + _stprintf(buff, _T("%s/Data/%s/locale-%s.MPQ"), input_path, LocalesT[locale], LocalesT[locale]); + if (!SFileOpenArchive(buff, 0, MPQ_OPEN_READ_ONLY, &LocaleMpq)) { - sprintf(filename, "%s/Data/%s", input_path, CONF_mpq_list[i]); - if(FileExists(filename)) - new MPQArchive(filename); + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), buff); + return false; } + + char const* prefix = NULL; + for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i) + { + memset(buff, 0, sizeof(buff)); + if (Builds[i] > LAST_DBC_IN_DATA_BUILD) + { + prefix = ""; + _stprintf(buff, _T("%s/Data/%s/wow-update-%s-%u.MPQ"), input_path, LocalesT[locale], LocalesT[locale], Builds[i]); + } + else + { + prefix = Locales[locale]; + _stprintf(buff, _T("%s/Data/wow-update-%u.MPQ"), input_path, Builds[i]); + } + + if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0)) + { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + _tprintf(_T("Cannot open patch archive %s\n"), buff); + continue; + } + } + + return true; } -inline void CloseMPQFiles() +void LoadCommonMPQFiles(uint32 build) { - for(ArchiveSet::iterator j = gOpenArchives.begin(); j != gOpenArchives.end();++j) (*j)->close(); - gOpenArchives.clear(); + TCHAR filename[512]; + _stprintf(filename, _T("%s/Data/world.MPQ"), input_path); + if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), filename); + return; + } + + int count = sizeof(CONF_mpq_list) / sizeof(char*); + for (int i = 1; i < count; ++i) + { + if (build < 15211 && !strcmp("world2.MPQ", CONF_mpq_list[i])) // 4.3.2 and higher MPQ + continue; + + _stprintf(filename, _T("%s/Data/%s"), input_path, CONF_mpq_list[i]); + if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), filename); + else + _tprintf(_T("Not found %s\n"), filename); + } + else + _tprintf(_T("Loaded %s\n"), filename); + + } + + char const* prefix = NULL; + for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i) + { + memset(filename, 0, sizeof(filename)); + if (Builds[i] > LAST_DBC_IN_DATA_BUILD) + { + prefix = ""; + _stprintf(filename, _T("%s/Data/wow-update-base-%u.MPQ"), input_path, Builds[i]); + } + else + { + prefix = "base"; + _stprintf(filename, _T("%s/Data/wow-update-%u.MPQ"), input_path, Builds[i]); + } + + if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open patch archive %s\n"), filename); + else + _tprintf(_T("Not found %s\n"), filename); + continue; + } + else + _tprintf(_T("Loaded %s\n"), filename); + } + } int main(int argc, char * arg[]) @@ -1040,42 +1206,54 @@ int main(int argc, char * arg[]) int FirstLocale = -1; uint32 build = 0; - for (int i = 0; i < LANG_COUNT; i++) + for (int i = 0; i < LOCALES_COUNT; ++i) { - char tmp1[512]; - sprintf(tmp1, "%s/Data/%s/locale-%s.MPQ", input_path, langs[i], langs[i]); - if (FileExists(tmp1)) + //Open MPQs + if (!LoadLocaleMPQFile(i)) { - printf("Detected locale: %s\n", langs[i]); - - //Open MPQs - LoadLocaleMPQFiles(i); + if (GetLastError() != ERROR_PATH_NOT_FOUND) + printf("Unable to load %s locale archives!\n", Locales[i]); + continue; + } - if((CONF_extract & EXTRACT_DBC) == 0) + printf("Detected locale: %s\n", Locales[i]); + if ((CONF_extract & EXTRACT_DBC) == 0) + { + FirstLocale = i; + build = ReadBuild(i); + if (build > CONF_TargetBuild) { - FirstLocale = i; - build = ReadBuild(FirstLocale); - printf("Detected client build: %u\n", build); - break; + printf("Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n", Locales[i], build, CONF_TargetBuild); + return 0; } - //Extract DBC files - if(FirstLocale < 0) - { - FirstLocale = i; - build = ReadBuild(FirstLocale); - printf("Detected client build: %u\n", build); - ExtractDBCFiles(i, true); - } - else - ExtractDBCFiles(i, false); + printf("Detected client build: %u\n", build); + break; + } - //Close MPQs - CloseMPQFiles(); + //Extract DBC files + uint32 tempBuild = ReadBuild(i); + printf("Detected client build %u for locale %s\n", tempBuild, Locales[i]); + if (tempBuild > CONF_TargetBuild) + { + printf("Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n", Locales[i], tempBuild, CONF_TargetBuild); + continue; } + + ExtractDBCFiles(i, FirstLocale < 0); + ExtractDB2Files(i, FirstLocale < 0); + + if (FirstLocale < 0) + { + FirstLocale = i; + build = tempBuild; + } + + //Close MPQs + SFileCloseArchive(LocaleMpq); } - if(FirstLocale < 0) + if (FirstLocale < 0) { printf("No locales detected\n"); return 0; @@ -1083,17 +1261,18 @@ int main(int argc, char * arg[]) if (CONF_extract & EXTRACT_MAP) { - printf("Using locale: %s\n", langs[FirstLocale]); + printf("Using locale: %s\n", Locales[FirstLocale]); // Open MPQs - LoadLocaleMPQFiles(FirstLocale); - LoadCommonMPQFiles(); + LoadLocaleMPQFile(FirstLocale); + LoadCommonMPQFiles(build); // Extract maps ExtractMapsFromMpq(build); // Close MPQs - CloseMPQFiles(); + SFileCloseArchive(WorldMpq); + SFileCloseArchive(LocaleMpq); } return 0; diff --git a/src/tools/map_extractor/adt.cpp b/src/tools/map_extractor/adt.cpp index fde70681113..bb1e3bfcc45 100644 --- a/src/tools/map_extractor/adt.cpp +++ b/src/tools/map_extractor/adt.cpp @@ -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; } diff --git a/src/tools/map_extractor/adt.h b/src/tools/map_extractor/adt.h index 5daf5820c3f..20b5ac93540 100644 --- a/src/tools/map_extractor/adt.h +++ b/src/tools/map_extractor/adt.h @@ -245,15 +245,18 @@ public: // // Adt file header chunk // +class ADT_file; class adt_MHDR { + friend class ADT_file; + union{ uint32 fcc; char fcc_txt[4]; }; uint32 size; - uint32 pad; + uint32 flags; uint32 offsMCIN; // MCIN uint32 offsTex; // MTEX uint32 offsModels; // MMDX @@ -271,9 +274,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) : NULL; } + adt_MH2O* getMH2O() { return offsMH2O ? (adt_MH2O *)((uint8 *)&flags+offsMH2O) : NULL; } }; class ADT_file : public FileLoader{ @@ -283,7 +285,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]; }; #endif diff --git a/src/tools/map_extractor/dbcfile.cpp b/src/tools/map_extractor/dbcfile.cpp index c1cab7ddb2f..021dc6f6e33 100644 --- a/src/tools/map_extractor/dbcfile.cpp +++ b/src/tools/map_extractor/dbcfile.cpp @@ -1,83 +1,91 @@ #define _CRT_SECURE_NO_DEPRECATE #include "dbcfile.h" -#include "mpq_libmpq04.h" -DBCFile::DBCFile(const std::string& filename): - filename(filename), recordSize(0), recordCount(0), fieldCount(0), stringSize(0), data(NULL), stringTable(NULL) +DBCFile::DBCFile(HANDLE file) : + _file(file), _data(NULL), _stringTable(NULL) { - } bool DBCFile::open() { - MPQFile f(filename.c_str()); char header[4]; - unsigned int na,nb,es,ss; + unsigned int na, nb, es, ss; - if(f.read(header,4)!=4) // Number of records + DWORD readBytes = 0; + SFileReadFile(_file, header, 4, &readBytes, NULL); + if (readBytes != 4) // Number of records 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') return false; - if(f.read(&na,4)!=4) // Number of records + SFileReadFile(_file, &na, 4, &readBytes, NULL); + if (readBytes != 4) // Number of records return false; - if(f.read(&nb,4)!=4) // Number of fields + + SFileReadFile(_file, &nb, 4, &readBytes, NULL); + if (readBytes != 4) // Number of fields return false; - if(f.read(&es,4)!=4) // Size of a record + + SFileReadFile(_file, &es, 4, &readBytes, NULL); + if (readBytes != 4) // Size of a record return false; - if(f.read(&ss,4)!=4) // String size + + SFileReadFile(_file, &ss, 4, &readBytes, NULL); + if (readBytes != 4) // String size return false; - recordSize = es; - recordCount = na; - fieldCount = nb; - stringSize = ss; - if(fieldCount*4 != recordSize) + _recordSize = es; + _recordCount = na; + _fieldCount = nb; + _stringSize = ss; + if (_fieldCount * 4 != _recordSize) return false; - data = new unsigned char[recordSize*recordCount+stringSize]; - stringTable = data + recordSize*recordCount; + _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) + size_t data_size = _recordSize * _recordCount + _stringSize; + SFileReadFile(_file, _data, data_size, &readBytes, NULL); + if (readBytes != data_size) return false; - f.close(); + return true; } + DBCFile::~DBCFile() { - delete [] data; + delete [] _data; } DBCFile::Record DBCFile::getRecord(size_t id) { - assert(data); - return Record(*this, data + id*recordSize); + assert(_data); + return Record(*this, _data + id*_recordSize); } size_t DBCFile::getMaxId() { - assert(data); + assert(_data); size_t maxId = 0; for(size_t i = 0; i < getRecordCount(); ++i) - { - if(maxId < getRecord(i).getUInt(0)) + if (maxId < getRecord(i).getUInt(0)) maxId = getRecord(i).getUInt(0); - } + return maxId; } DBCFile::Iterator DBCFile::begin() { - assert(data); - return Iterator(*this, data); + assert(_data); + return Iterator(*this, _data); } + DBCFile::Iterator DBCFile::end() { - assert(data); - return Iterator(*this, stringTable); + assert(_data); + return Iterator(*this, _stringTable); } diff --git a/src/tools/map_extractor/dbcfile.h b/src/tools/map_extractor/dbcfile.h index aef61df7aaa..adb4a34f473 100644 --- a/src/tools/map_extractor/dbcfile.h +++ b/src/tools/map_extractor/dbcfile.h @@ -2,118 +2,124 @@ #define DBCFILE_H #include <cassert> #include <string> +#include "StormLib.h" class DBCFile { -public: - DBCFile(const std::string &filename); - ~DBCFile(); + public: + DBCFile(HANDLE file); + ~DBCFile(); - // Open database. It must be openened before it can be used. - bool open(); + // Open database. It must be openened before it can be used. + bool open(); - // Database exceptions - class Exception - { - public: - Exception(const std::string &message): message(message) - { } - virtual ~Exception() - { } - const std::string &getMessage() {return message;} - private: - std::string message; - }; - class NotFound: public Exception - { - public: - NotFound(): Exception("Key was not found") - { } - }; - // Iteration over database - class Iterator; - class Record - { - public: - float getFloat(size_t field) const - { - assert(field < file.fieldCount); - return *reinterpret_cast<float*>(offset+field*4); - } - unsigned int getUInt(size_t field) const + // Database exceptions + class Exception { - assert(field < file.fieldCount); - return *reinterpret_cast<unsigned int*>(offset+field*4); - } - int getInt(size_t field) const - { - assert(field < file.fieldCount); - return *reinterpret_cast<int*>(offset+field*4); - } - const char *getString(size_t field) const + public: + Exception(const std::string &message) : message(message) { } + virtual ~Exception() { } + const std::string &getMessage() { return message; } + private: + std::string message; + }; + + class NotFound: public Exception { - assert(field < file.fieldCount); - size_t stringOffset = getUInt(field); - assert(stringOffset < file.stringSize); - return reinterpret_cast<char*>(file.stringTable + stringOffset); - } - private: - Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {} - unsigned char *offset; - DBCFile &file; - - friend class DBCFile; - friend class DBCFile::Iterator; - }; - /** Iterator that iterates over records - */ - class Iterator - { - public: - Iterator(DBCFile &file, unsigned char *offset): - record(file, offset) {} - /// Advance (prefix only) - Iterator & operator++() { - record.offset += record.file.recordSize; - return *this; - } - /// Return address of current instance - Record const & operator*() const { return record; } - const Record* operator->() const { - return &record; - } - /// Comparison - bool operator==(const Iterator &b) const + public: + NotFound(): Exception("Key was not found") { } + }; + + // Iteration over database + class Iterator; + class Record { - return record.offset == b.record.offset; - } - bool operator!=(const Iterator &b) const + public: + float getFloat(size_t field) const + { + assert(field < file._fieldCount); + return *reinterpret_cast<float*>(offset+field*4); + } + + unsigned int getUInt(size_t field) const + { + assert(field < file._fieldCount); + return *reinterpret_cast<unsigned int*>(offset+field*4); + } + + int getInt(size_t field) const + { + assert(field < file._fieldCount); + return *reinterpret_cast<int*>(offset+field*4); + } + + const char *getString(size_t field) const + { + assert(field < file._fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file._stringSize); + return reinterpret_cast<char*>(file._stringTable + stringOffset); + } + + private: + Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {} + unsigned char *offset; + DBCFile &file; + + friend class DBCFile; + friend class DBCFile::Iterator; + }; + /** Iterator that iterates over records + */ + class Iterator { - return record.offset != b.record.offset; - } + public: + Iterator(DBCFile &file, unsigned char *offset) : record(file, offset) { } + + /// Advance (prefix only) + Iterator & operator++() + { + record.offset += record.file._recordSize; + return *this; + } + + /// Return address of current instance + Record const & operator*() const { return record; } + const Record* operator->() const { return &record; } + + /// Comparison + bool operator==(const Iterator &b) const + { + return record.offset == b.record.offset; + } + + bool operator!=(const Iterator &b) const + { + return record.offset != b.record.offset; + } + private: + Record record; + }; + + // Get record by id + Record getRecord(size_t id); + /// Get begin iterator over records + Iterator begin(); + /// Get begin iterator over records + Iterator end(); + /// Trivial + size_t getRecordCount() const { return _recordCount; } + size_t getFieldCount() const { return _fieldCount; } + size_t getMaxId(); + private: - Record record; - }; - - // Get record by id - Record getRecord(size_t id); - /// Get begin iterator over records - Iterator begin(); - /// Get begin iterator over records - Iterator end(); - /// Trivial - size_t getRecordCount() const { return recordCount;} - size_t getFieldCount() const { return fieldCount; } - size_t getMaxId(); -private: - std::string filename; - size_t recordSize; - size_t recordCount; - size_t fieldCount; - size_t stringSize; - unsigned char *data; - unsigned char *stringTable; + HANDLE _file; + size_t _recordSize; + size_t _recordCount; + size_t _fieldCount; + size_t _stringSize; + unsigned char *_data; + unsigned char* _stringTable; }; #endif - diff --git a/src/tools/map_extractor/loadlib.cpp b/src/tools/map_extractor/loadlib.cpp index 465eb04083f..0e2112b2f26 100644 --- a/src/tools/map_extractor/loadlib.cpp +++ b/src/tools/map_extractor/loadlib.cpp @@ -1,11 +1,8 @@ #define _CRT_SECURE_NO_DEPRECATE #include "loadlib.h" -#include "mpq_libmpq04.h" #include <cstdio> -class MPQFile; - FileLoader::FileLoader() { data = 0; @@ -18,29 +15,31 @@ FileLoader::~FileLoader() free(); } -bool FileLoader::loadFile(char *filename, bool log) +bool FileLoader::loadFile(HANDLE mpq, char* filename, bool log) { free(); - MPQFile mf(filename); - if(mf.isEof()) + HANDLE file; + if (!SFileOpenFileEx(mpq, filename, SFILE_OPEN_PATCHED_FILE, &file)) { if (log) printf("No such file %s\n", filename); return false; } - data_size = mf.getSize(); - - data = new uint8 [data_size]; + data_size = SFileGetFileSize(file, NULL); + data = new uint8[data_size]; if (data) { - mf.read(data, data_size); - mf.close(); + SFileReadFile(file, data, data_size, NULL/*bytesRead*/, NULL); if (prepareLoadedData()) + { + SFileCloseFile(file); return true; + } } - printf("Error loading %s", filename); - mf.close(); + + printf("Error loading %s\n", filename); + SFileCloseFile(file); free(); return false; } diff --git a/src/tools/map_extractor/loadlib/loadlib.h b/src/tools/map_extractor/loadlib/loadlib.h index bf6c0706d46..7a158ddfcf1 100644 --- a/src/tools/map_extractor/loadlib/loadlib.h +++ b/src/tools/map_extractor/loadlib/loadlib.h @@ -1,6 +1,8 @@ #ifndef LOAD_LIB_H #define LOAD_LIB_H +#include "StormLib.h" + #ifdef _WIN32 typedef __int64 int64; typedef __int32 int32; @@ -42,6 +44,7 @@ struct file_MVER uint32 ver; }; + class FileLoader{ uint8 *data; uint32 data_size; @@ -53,7 +56,7 @@ public: file_MVER *version; FileLoader(); ~FileLoader(); - bool loadFile(char *filename, bool log = true); + bool loadFile(HANDLE mpq, char *filename, bool log = true); virtual void free(); }; #endif diff --git a/src/tools/map_extractor/mpq_libmpq.cpp b/src/tools/map_extractor/mpq_libmpq.cpp deleted file mode 100644 index 81aa8cc2894..00000000000 --- a/src/tools/map_extractor/mpq_libmpq.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "mpq_libmpq04.h" -#include <deque> -#include <cstdio> - -ArchiveSet gOpenArchives; - -MPQArchive::MPQArchive(const char* filename) -{ - int result = libmpq__archive_open(&mpq_a, filename, -1); - printf("Opening %s\n", filename); - if(result) { - switch(result) { - case LIBMPQ_ERROR_OPEN : - printf("Error opening archive '%s': Does file really exist?\n", filename); - break; - case LIBMPQ_ERROR_FORMAT : /* bad file format */ - printf("Error opening archive '%s': Bad file format\n", filename); - break; - case LIBMPQ_ERROR_SEEK : /* seeking in file failed */ - printf("Error opening archive '%s': Seeking in file failed\n", filename); - break; - case LIBMPQ_ERROR_READ : /* Read error in archive */ - printf("Error opening archive '%s': Read error in archive\n", filename); - break; - case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */ - printf("Error opening archive '%s': Maybe not enough memory\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; - - uint32_t filenum; - if(libmpq__file_number(mpq_a, filename, &filenum)) continue; - libmpq__off_t transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); - - // HACK: in patch.mpq some files don't want to open and give 1 for filesize - if (size<=1) { -// printf("warning: file %s has size %d; cannot read.\n", filename, size); - eof = true; - buffer = 0; - return; - } - buffer = new char[size]; - - //libmpq_file_getdata - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - /*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; -} diff --git a/src/tools/map_extractor/mpq_libmpq04.h b/src/tools/map_extractor/mpq_libmpq04.h deleted file mode 100644 index 89f715e9e87..00000000000 --- a/src/tools/map_extractor/mpq_libmpq04.h +++ /dev/null @@ -1,91 +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_s *mpq_a; - - MPQArchive(const char* filename); - void close(); - - void GetFileListTo(vector<string>& filelist) { - uint32_t filenum; - if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; - libmpq__off_t size, transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); - - char *buffer = new char[size]; - - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - - 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; - libmpq__off_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 diff --git a/src/tools/map_extractor/wdt.cpp b/src/tools/map_extractor/wdt.cpp index dedefbb64e5..6c2fa337d4f 100644 --- a/src/tools/map_extractor/wdt.cpp +++ b/src/tools/map_extractor/wdt.cpp @@ -57,6 +57,6 @@ bool WDT_file::prepareLoadedData() return false; wmo = (wdt_MWMO *)((uint8*)main+ main->size+8); if (!wmo->prepareLoadedData()) - return false; + wmo = NULL; // optional as of cataclysm return true; }
\ No newline at end of file diff --git a/src/tools/map_extractor/wdt.h b/src/tools/map_extractor/wdt.h index fcee8ac64f2..be6df3f173d 100644 --- a/src/tools/map_extractor/wdt.h +++ b/src/tools/map_extractor/wdt.h @@ -45,7 +45,7 @@ public: uint32 size; struct adtData{ - uint32 exist; + uint32 flag; uint32 data1; } adt_list[64][64]; diff --git a/src/tools/vmap4_assembler/CMakeLists.txt b/src/tools/vmap4_assembler/CMakeLists.txt index e4f57646c49..f0f2e88c471 100644 --- a/src/tools/vmap4_assembler/CMakeLists.txt +++ b/src/tools/vmap4_assembler/CMakeLists.txt @@ -22,7 +22,7 @@ include_directories( add_definitions(-DNO_CORE_FUNCS) add_executable(vmap4assembler VMapAssembler.cpp) -add_dependencies(vmap4assembler mpq) +add_dependencies(vmap4assembler storm) if(CMAKE_SYSTEM_NAME MATCHES "Darwin") set_target_properties(vmap4assembler PROPERTIES LINK_FLAGS "-framework Carbon") diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt index 5c98d84eb17..5a40e89f1ac 100644 --- a/src/tools/vmap4_extractor/CMakeLists.txt +++ b/src/tools/vmap4_extractor/CMakeLists.txt @@ -15,31 +15,25 @@ file(GLOB_RECURSE sources *.cpp *.h) add_definitions("-DIOMAP_DEBUG") # build setup currently only supports libmpq 0.4.x -add_definitions("-DUSE_LIBMPQ04") -add_definitions("-Wall") -add_definitions("-ggdb") -add_definitions("-O3") - -if( UNIX ) - include_directories( - ${CMAKE_SOURCE_DIR}/dep/libmpq - ) -elseif( WIN32 ) - include_directories( - ${CMAKE_SOURCE_DIR}/dep/libmpq - ${CMAKE_SOURCE_DIR}/dep/libmpq/win - ) +if( NOT WIN32 ) + add_definitions("-Wall") + add_definitions("-ggdb") + add_definitions("-O3") endif() +include_directories( + ${CMAKE_SOURCE_DIR}/dep/StormLib/src +) + add_executable(vmap4extractor ${sources}) target_link_libraries(vmap4extractor - mpq ${BZIP2_LIBRARIES} ${ZLIB_LIBRARIES} + storm ) -add_dependencies(vmap4extractor mpq) +add_dependencies(vmap4extractor storm) if( UNIX ) install(TARGETS vmap4extractor DESTINATION bin) diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index a605118eead..d2ad71b8179 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -75,7 +75,9 @@ char* GetExtension(char* FileName) return NULL; } -ADTFile::ADTFile(char* filename): ADT(filename), nWMO(0), nMDX(0), WmoInstansName(NULL), ModelInstansName(NULL) +extern HANDLE WorldMpq; + +ADTFile::ADTFile(char* filename): ADT(WorldMpq, filename) { Adtfilename.append(filename); } diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index 08814996f68..795eebc892f 100644 --- a/src/tools/vmap4_extractor/adtfile.h +++ b/src/tools/vmap4_extractor/adtfile.h @@ -19,7 +19,7 @@ #ifndef ADT_H #define ADT_H -#include "mpq_libmpq04.h" +#include "mpqfile.h" #include "wmo.h" #include "model.h" diff --git a/src/tools/vmap4_extractor/dbcfile.cpp b/src/tools/vmap4_extractor/dbcfile.cpp index a651456d916..efc8aeabe8c 100644 --- a/src/tools/vmap4_extractor/dbcfile.cpp +++ b/src/tools/vmap4_extractor/dbcfile.cpp @@ -16,81 +16,104 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "dbcfile.h" -#include "mpq_libmpq04.h" -#undef min -#undef max +#define _CRT_SECURE_NO_DEPRECATE -#include <cstdio> +#include "dbcfile.h" -DBCFile::DBCFile(const std::string& filename): - filename(filename), recordSize(0), recordCount(0), fieldCount(0), stringSize(0), data(NULL), stringTable(NULL) +DBCFile::DBCFile(HANDLE mpq, const char* filename) : + _mpq(mpq), _filename(filename), _file(NULL), _data(NULL), _stringTable(NULL) { - } bool DBCFile::open() { - MPQFile f(filename.c_str()); + if (!SFileOpenFileEx(_mpq, _filename, SFILE_OPEN_PATCHED_FILE, &_file)) + return false; + + char header[4]; + unsigned int na, nb, es, ss; + + DWORD readBytes = 0; + SFileReadFile(_file, header, 4, &readBytes, NULL); + if (readBytes != 4) // Number of records + return false; + + if (header[0] != 'W' || header[1] != 'D' || header[2] != 'B' || header[3] != 'C') + return false; - // Need some error checking, otherwise an unhandled exception error occurs - // if people screw with the data path. - if (f.isEof() == true) + readBytes = 0; + SFileReadFile(_file, &na, 4, &readBytes, NULL); + if (readBytes != 4) // Number of records return false; - unsigned char header[4]; - unsigned int na,nb,es,ss; + readBytes = 0; + SFileReadFile(_file, &nb, 4, &readBytes, NULL); + if (readBytes != 4) // Number of fields + return false; - f.read(header,4); // File Header + readBytes = 0; + SFileReadFile(_file, &es, 4, &readBytes, NULL); + if (readBytes != 4) // Size of a record + return false; - if (header[0]!='W' || header[1]!='D' || header[2]!='B' || header[3] != 'C') - { - f.close(); - data = NULL; - printf("Critical Error: An error occured while trying to read the DBCFile %s.", filename.c_str()); + readBytes = 0; + SFileReadFile(_file, &ss, 4, &readBytes, NULL); + if (readBytes != 4) // String size return false; - } - - //assert(header[0]=='W' && header[1]=='D' && header[2]=='B' && header[3] == 'C'); - - f.read(&na,4); // Number of records - f.read(&nb,4); // Number of fields - f.read(&es,4); // Size of a record - f.read(&ss,4); // String size - - recordSize = es; - recordCount = na; - fieldCount = nb; - stringSize = ss; - //assert(fieldCount*4 == recordSize); - assert(fieldCount*4 >= recordSize); - - data = new unsigned char[recordSize*recordCount+stringSize]; - stringTable = data + recordSize*recordCount; - f.read(data,recordSize*recordCount+stringSize); - f.close(); + + _recordSize = es; + _recordCount = na; + _fieldCount = nb; + _stringSize = ss; + if (_fieldCount * 4 != _recordSize) + return false; + + _data = new unsigned char[_recordSize * _recordCount + _stringSize]; + _stringTable = _data + _recordSize*_recordCount; + + size_t data_size = _recordSize * _recordCount + _stringSize; + readBytes = 0; + SFileReadFile(_file, _data, data_size, &readBytes, NULL); + if (readBytes != data_size) + return false; + return true; } DBCFile::~DBCFile() { - delete [] data; + delete [] _data; + if (_file != NULL) + SFileCloseFile(_file); } DBCFile::Record DBCFile::getRecord(size_t id) { - assert(data); - return Record(*this, data + id*recordSize); + assert(_data); + return Record(*this, _data + id*_recordSize); +} + +size_t DBCFile::getMaxId() +{ + assert(_data); + + size_t maxId = 0; + for(size_t i = 0; i < getRecordCount(); ++i) + if (maxId < getRecord(i).getUInt(0)) + maxId = getRecord(i).getUInt(0); + + return maxId; } DBCFile::Iterator DBCFile::begin() { - assert(data); - return Iterator(*this, data); + assert(_data); + return Iterator(*this, _data); } DBCFile::Iterator DBCFile::end() { - assert(data); - return Iterator(*this, stringTable); + assert(_data); + return Iterator(*this, _stringTable); } + diff --git a/src/tools/vmap4_extractor/dbcfile.h b/src/tools/vmap4_extractor/dbcfile.h index 56cce9a521c..007ccb6cdcb 100644 --- a/src/tools/vmap4_extractor/dbcfile.h +++ b/src/tools/vmap4_extractor/dbcfile.h @@ -18,138 +18,128 @@ #ifndef DBCFILE_H #define DBCFILE_H - #include <cassert> #include <string> +#include "StormLib.h" class DBCFile { -public: - DBCFile(const std::string &filename); - ~DBCFile(); - - // Open database. It must be openened before it can be used. - bool open(); - - // TODO: Add a close function? - - // Database exceptions - class Exception - { public: - Exception(const std::string &message): message(message) - { } - virtual ~Exception() - { } - const std::string &getMessage() {return message;} - private: - std::string message; - }; + DBCFile(HANDLE mpq, const char* filename); + ~DBCFile(); - // - class NotFound: public Exception - { - public: - NotFound(): Exception("Key was not found") - { } - }; - - // Iteration over database - class Iterator; - class Record - { - public: - Record& operator= (const Record& r) - { - file = r.file; - offset = r.offset; - return *this; - } - float getFloat(size_t field) const - { - assert(field < file.fieldCount); - return *reinterpret_cast<float*>(offset+field*4); - } - unsigned int getUInt(size_t field) const - { - assert(field < file.fieldCount); - return *reinterpret_cast<unsigned int*>(offset+(field*4)); - } - int getInt(size_t field) const + // Open database. It must be openened before it can be used. + bool open(); + + // Database exceptions + class Exception { - assert(field < file.fieldCount); - return *reinterpret_cast<int*>(offset+field*4); - } - unsigned char getByte(size_t ofs) const + public: + Exception(const std::string &message) : message(message) { } + virtual ~Exception() { } + const std::string &getMessage() { return message; } + private: + std::string message; + }; + + class NotFound: public Exception { - assert(ofs < file.recordSize); - return *reinterpret_cast<unsigned char*>(offset+ofs); - } - const char *getString(size_t field) const + public: + NotFound(): Exception("Key was not found") { } + }; + + // Iteration over database + class Iterator; + class Record { - assert(field < file.fieldCount); - size_t stringOffset = getUInt(field); - assert(stringOffset < file.stringSize); - //char * tmp = (char*)file.stringTable + stringOffset; - //unsigned char * tmp2 = file.stringTable + stringOffset; - return reinterpret_cast<char*>(file.stringTable + stringOffset); - } - private: - Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {} - DBCFile &file; - unsigned char *offset; + public: + float getFloat(size_t field) const + { + assert(field < file._fieldCount); + return *reinterpret_cast<float*>(offset+field*4); + } - friend class DBCFile; - friend class Iterator; - }; + unsigned int getUInt(size_t field) const + { + assert(field < file._fieldCount); + return *reinterpret_cast<unsigned int*>(offset+field*4); + } - /* Iterator that iterates over records */ - class Iterator - { - public: - Iterator(DBCFile &file, unsigned char *offset): - record(file, offset) {} - /// Advance (prefix only) - Iterator & operator++() { - record.offset += record.file.recordSize; - return *this; - } - /// Return address of current instance - Record const & operator*() const { return record; } - const Record* operator->() const { - return &record; - } - /// Comparison - bool operator==(const Iterator &b) const - { - return record.offset == b.record.offset; - } - bool operator!=(const Iterator &b) const + int getInt(size_t field) const + { + assert(field < file._fieldCount); + return *reinterpret_cast<int*>(offset+field*4); + } + + const char *getString(size_t field) const + { + assert(field < file._fieldCount); + size_t stringOffset = getUInt(field); + assert(stringOffset < file._stringSize); + return reinterpret_cast<char*>(file._stringTable + stringOffset); + } + + private: + Record(DBCFile &file, unsigned char *offset): file(file), offset(offset) {} + unsigned char *offset; + DBCFile &file; + + friend class DBCFile; + friend class DBCFile::Iterator; + }; + /** Iterator that iterates over records + */ + class Iterator { - return record.offset != b.record.offset; - } + public: + Iterator(DBCFile &file, unsigned char *offset) : record(file, offset) { } + + /// Advance (prefix only) + Iterator & operator++() + { + record.offset += record.file._recordSize; + return *this; + } + + /// Return address of current instance + Record const & operator*() const { return record; } + const Record* operator->() const { return &record; } + + /// Comparison + bool operator==(const Iterator &b) const + { + return record.offset == b.record.offset; + } + + bool operator!=(const Iterator &b) const + { + return record.offset != b.record.offset; + } + private: + Record record; + }; + + // Get record by id + Record getRecord(size_t id); + /// Get begin iterator over records + Iterator begin(); + /// Get begin iterator over records + Iterator end(); + /// Trivial + size_t getRecordCount() const { return _recordCount; } + size_t getFieldCount() const { return _fieldCount; } + size_t getMaxId(); + private: - Record record; - }; - - // Get record by id - Record getRecord(size_t id); - /// Get begin iterator over records - Iterator begin(); - /// Get begin iterator over records - Iterator end(); - /// Trivial - size_t getRecordCount() const { return recordCount;} - size_t getFieldCount() const { return fieldCount; } - -private: - std::string filename; - size_t recordSize; - size_t recordCount; - size_t fieldCount; - size_t stringSize; - unsigned char *data; - unsigned char *stringTable; + HANDLE _mpq; + const char* _filename; + HANDLE _file; + size_t _recordSize; + size_t _recordCount; + size_t _fieldCount; + size_t _stringSize; + unsigned char *_data; + unsigned char* _stringTable; }; #endif diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp index 8a1f67cd2c2..4c8e423bfc4 100644 --- a/src/tools/vmap4_extractor/gameobject_extract.cpp +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -35,10 +35,12 @@ bool ExtractSingleModel(std::string& fname) return mdl.ConvertToVMAPModel(output.c_str()); } +extern HANDLE LocaleMpq; + void ExtractGameobjectModels() { printf("Extracting GameObject models..."); - DBCFile dbc("DBFilesClient\\GameObjectDisplayInfo.dbc"); + DBCFile dbc(LocaleMpq, "DBFilesClient\\GameObjectDisplayInfo.dbc"); if(!dbc.open()) { printf("Fatal error: Invalid GameObjectDisplayInfo.dbc file format!\n"); diff --git a/src/tools/vmap4_extractor/loadlib/loadlib.h b/src/tools/vmap4_extractor/loadlib/loadlib.h deleted file mode 100644 index 61865c4b436..00000000000 --- a/src/tools/vmap4_extractor/loadlib/loadlib.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2005-2011 MaNGOS <http://getmangos.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 LOAD_LIB_H -#define LOAD_LIB_H - -#ifdef WIN32 -typedef __int64 int64; -typedef __int32 int32; -typedef __int16 int16; -typedef __int8 int8; -typedef unsigned __int64 uint64; -typedef unsigned __int32 uint32; -typedef unsigned __int16 uint16; -typedef unsigned __int8 uint8; -#else -#include <stdint.h> -#ifndef uint64_t -#ifdef __linux__ -#include <linux/types.h> -#endif -#endif -typedef int64_t int64; -typedef int32_t int32; -typedef int16_t int16; -typedef int8_t int8; -typedef uint64_t uint64; -typedef uint32_t uint32; -typedef uint16_t uint16; -typedef uint8_t uint8; -#endif - -#define FILE_FORMAT_VERSION 18 - -// -// File version chunk -// -struct file_MVER -{ - union{ - uint32 fcc; - char fcc_txt[4]; - }; - uint32 size; - uint32 ver; -}; - -class FileLoader{ - uint8 *data; - uint32 data_size; -public: - virtual bool prepareLoadedData(); - uint8 *GetData() {return data;} - uint32 GetDataSize() {return data_size;} - - file_MVER *version; - FileLoader(); - ~FileLoader(); - bool loadFile(char *filename, bool log = true); - virtual void free(); -}; -#endif diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index 57f9b421dbe..7a03cea23c0 100644 --- a/src/tools/vmap4_extractor/model.cpp +++ b/src/tools/vmap4_extractor/model.cpp @@ -19,11 +19,13 @@ #include "vmapexport.h" #include "model.h" #include "wmo.h" -#include "mpq_libmpq04.h" +#include "mpqfile.h" #include <cassert> #include <algorithm> #include <cstdio> +extern HANDLE WorldMpq; + Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0) { memset(&header, 0, sizeof(header)); @@ -31,7 +33,7 @@ Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0 bool Model::open() { - MPQFile f(filename.c_str()); + MPQFile f(WorldMpq, filename.c_str()); if (f.isEof()) { diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h index 7dd69212b54..acd31d58ec9 100644 --- a/src/tools/vmap4_extractor/model.h +++ b/src/tools/vmap4_extractor/model.h @@ -19,7 +19,6 @@ #ifndef MODEL_H #define MODEL_H -#include "loadlib/loadlib.h" #include "vec3d.h" #include "modelheaders.h" #include <vector> diff --git a/src/tools/vmap4_extractor/modelheaders.h b/src/tools/vmap4_extractor/modelheaders.h index d859fd3511e..7fd908d7442 100644 --- a/src/tools/vmap4_extractor/modelheaders.h +++ b/src/tools/vmap4_extractor/modelheaders.h @@ -19,12 +19,7 @@ #ifndef MODELHEADERS_H #define MODELHEADERS_H -/* typedef unsigned char uint8; -typedef char int8; -typedef unsigned short uint16; -typedef short int16; -typedef unsigned int uint32; -typedef int int32; */ +#include "mpqfile.h" // integer typedefs #pragma pack(push,1) diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp deleted file mode 100644 index 528b9679a58..00000000000 --- a/src/tools/vmap4_extractor/mpq_libmpq.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "mpq_libmpq04.h" -#include <deque> -#include <cstdio> - -ArchiveSet gOpenArchives; - -MPQArchive::MPQArchive(const char* filename) -{ - int result = libmpq__archive_open(&mpq_a, filename, -1); - printf("Opening %s\n", filename); - if(result) { - switch(result) { - case LIBMPQ_ERROR_OPEN : - printf("Error opening archive '%s': Does file really exist?\n", filename); - break; - case LIBMPQ_ERROR_FORMAT : /* bad file format */ - printf("Error opening archive '%s': Bad file format\n", filename); - break; - case LIBMPQ_ERROR_SEEK : /* seeking in file failed */ - printf("Error opening archive '%s': Seeking in file failed\n", filename); - break; - case LIBMPQ_ERROR_READ : /* Read error in archive */ - printf("Error opening archive '%s': Read error in archive\n", filename); - break; - case LIBMPQ_ERROR_MALLOC : /* maybe not enough memory? :) */ - printf("Error opening archive '%s': Maybe not enough memory\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; - - uint32 filenum; - if(libmpq__file_number(mpq_a, filename, &filenum)) continue; - libmpq__off_t transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); - - // HACK: in patch.mpq some files don't want to open and give 1 for filesize - if (size<=1) { - // printf("info: file %s has size %d; considered dummy file.\n", filename, size); - eof = true; - buffer = 0; - return; - } - buffer = new char[size]; - - //libmpq_file_getdata - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - /*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; -} diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h deleted file mode 100644 index 89f715e9e87..00000000000 --- a/src/tools/vmap4_extractor/mpq_libmpq04.h +++ /dev/null @@ -1,91 +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_s *mpq_a; - - MPQArchive(const char* filename); - void close(); - - void GetFileListTo(vector<string>& filelist) { - uint32_t filenum; - if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; - libmpq__off_t size, transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); - - char *buffer = new char[size]; - - libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred); - - 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; - libmpq__off_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 diff --git a/src/tools/vmap4_extractor/mpqfile.cpp b/src/tools/vmap4_extractor/mpqfile.cpp new file mode 100644 index 00000000000..9f019f99f38 --- /dev/null +++ b/src/tools/vmap4_extractor/mpqfile.cpp @@ -0,0 +1,86 @@ +#include "mpqfile.h" +#include <deque> +#include <cstdio> +#include "StormLib.h" + +MPQFile::MPQFile(HANDLE mpq, const char* filename): + eof(false), + buffer(0), + pointer(0), + size(0) +{ + HANDLE file; + if (!SFileOpenFileEx(mpq, filename, SFILE_OPEN_PATCHED_FILE, &file)) + { + fprintf(stderr, "Can't open %s, err=%u!\n", filename, GetLastError()); + eof = true; + return; + } + + DWORD hi = 0; + size = SFileGetFileSize(file, &hi); + + if (hi) + { + fprintf(stderr, "Can't open %s, size[hi] = %u!\n", filename, (uint32)hi); + SFileCloseFile(file); + eof = true; + return; + } + + if (size <= 1) + { + fprintf(stderr, "Can't open %s, size = %u!\n", filename, size); + SFileCloseFile(file); + eof = true; + return; + } + + DWORD read = 0; + buffer = new char[size]; + if (!SFileReadFile(file, buffer, size, &read) || size != read) + { + fprintf(stderr, "Can't read %s, size=%u read=%u!\n", filename, size, read); + SFileCloseFile(file); + eof = true; + return; + } + + SFileCloseFile(file); +} + +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; +} diff --git a/src/tools/vmap4_extractor/mpqfile.h b/src/tools/vmap4_extractor/mpqfile.h new file mode 100644 index 00000000000..dfd1b713c97 --- /dev/null +++ b/src/tools/vmap4_extractor/mpqfile.h @@ -0,0 +1,81 @@ +#define _CRT_SECURE_NO_DEPRECATE +#ifndef _CRT_SECURE_NO_WARNINGS // fuck the police^Wwarnings +#define _CRT_SECURE_NO_WARNINGS +#endif + +#ifndef MPQ_H +#define MPQ_H + +#include <string.h> +#include <ctype.h> +#include <vector> +#include <iostream> +#include <deque> +#include "StormLib.h" + +#ifdef _WIN32 +#include <Windows.h> // mainly only HANDLE definition is required +typedef __int64 int64; +typedef __int32 int32; +typedef __int16 int16; +typedef __int8 int8; +typedef unsigned __int64 uint64; +typedef unsigned __int32 uint32; +typedef unsigned __int16 uint16; +typedef unsigned __int8 uint8; +#else +#include <stdint.h> +#ifndef uint64_t +#ifdef __linux__ +#include <linux/types.h> +#endif +#endif +typedef int64_t int64; +typedef int32_t int32; +typedef int16_t int16; +typedef int8_t int8; +typedef uint64_t uint64; +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; +#endif + +using namespace std; + +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(HANDLE mpq, 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 diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index 40a22a2a6e0..eebc763f2f2 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -30,6 +30,7 @@ #define mkdir _mkdir #else #include <sys/stat.h> + #define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND #endif #undef min @@ -45,7 +46,7 @@ #include "wdtfile.h" #include "dbcfile.h" #include "wmo.h" -#include "mpq_libmpq04.h" +#include "mpqfile.h" #include "vmapexport.h" @@ -56,7 +57,37 @@ //----------------------------------------------------------------------------- -extern ArchiveSet gOpenArchives; +HANDLE WorldMpq = NULL; +HANDLE LocaleMpq = NULL; + +uint32 CONF_TargetBuild = 15595; // 4.3.4.15595 + +// List MPQ for extract maps from +char const* CONF_mpq_list[]= +{ + "world.MPQ", + "art.MPQ", + "expansion1.MPQ", + "expansion2.MPQ", + "expansion3.MPQ", + "world2.MPQ", +}; + +uint32 const Builds[] = {13164, 13205, 13287, 13329, 13596, 13623, 13914, 14007, 14333, 14480, 14545, 15005, 15050, 15211, 15354, 15595, 0}; +#define LAST_DBC_IN_DATA_BUILD 13623 // after this build mpqs with dbc are back to locale folder + +char* const Locales[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU"}; +TCHAR* const LocalesT[] = +{ + _T("enGB"), _T("enUS"), + _T("deDE"), _T("esES"), + _T("frFR"), _T("koKR"), + _T("zhCN"), _T("zhTW"), + _T("enCN"), _T("enTW"), + _T("esMX"), _T("ruRU"), +}; + +#define LOCALES_COUNT 12 typedef struct { @@ -69,7 +100,6 @@ uint16 *LiqType = 0; uint32 map_count; char output_path[128]="."; char input_path[1024]="."; -bool hasInputPathParam = false; bool preciseVectorData = false; // Constants @@ -78,6 +108,148 @@ bool preciseVectorData = false; const char* szWorkDirWmo = "./Buildings"; const char* szRawVMAPMagic = "VMAP041"; +bool LoadLocaleMPQFile(int locale) +{ + TCHAR buff[512]; + memset(buff, 0, sizeof(buff)); + _stprintf(buff, _T("%s%s/locale-%s.MPQ"), input_path, LocalesT[locale], LocalesT[locale]); + if (!SFileOpenArchive(buff, 0, MPQ_OPEN_READ_ONLY, &LocaleMpq)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), buff); + return false; + } + + char const* prefix = NULL; + for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i) + { + memset(buff, 0, sizeof(buff)); + if (Builds[i] > LAST_DBC_IN_DATA_BUILD) + { + prefix = ""; + _stprintf(buff, _T("%s%s/wow-update-%s-%u.MPQ"), input_path, LocalesT[locale], LocalesT[locale], Builds[i]); + } + else + { + prefix = Locales[locale]; + _stprintf(buff, _T("%swow-update-%u.MPQ"), input_path, Builds[i]); + } + + if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0)) + { + if (GetLastError() != ERROR_FILE_NOT_FOUND) + _tprintf(_T("Cannot open patch archive %s\n"), buff); + continue; + } + } + + return true; +} + +void LoadCommonMPQFiles(uint32 build) +{ + TCHAR filename[512]; + _stprintf(filename, _T("%sworld.MPQ"), input_path); + if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), filename); + return; + } + + int count = sizeof(CONF_mpq_list) / sizeof(char*); + for (int i = 1; i < count; ++i) + { + if (build < 15211 && !strcmp("world2.MPQ", CONF_mpq_list[i])) // 4.3.2 and higher MPQ + continue; + + _stprintf(filename, _T("%s%s"), input_path, CONF_mpq_list[i]); + if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open archive %s\n"), filename); + else + _tprintf(_T("Not found %s\n"), filename); + } + else + { + _tprintf(_T("Loaded %s\n"), filename); + + bool found = false; + int count = 0; + SFILE_FIND_DATA data; + HANDLE find = SFileFindFirstFile(WorldMpq, "*.*", &data, NULL); + if (find != NULL) + { + do + { + ++count; + if (data.dwFileFlags & MPQ_FILE_PATCH_FILE) + { + found = true; + break; + } + } + while (SFileFindNextFile(find, &data)); + } + SFileFindClose(find); + printf("Scanned %d files, found patch = %d\n", count, found); + } + } + + char const* prefix = NULL; + for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i) + { + memset(filename, 0, sizeof(filename)); + if (Builds[i] > LAST_DBC_IN_DATA_BUILD) + { + prefix = ""; + _stprintf(filename, _T("%swow-update-base-%u.MPQ"), input_path, Builds[i]); + } + else + { + prefix = "base"; + _stprintf(filename, _T("%swow-update-%u.MPQ"), input_path, Builds[i]); + } + + if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + _tprintf(_T("Cannot open patch archive %s\n"), filename); + else + _tprintf(_T("Not found %s\n"), filename); + continue; + } + else + { + _tprintf(_T("Loaded %s\n"), filename); + + + bool found = false; + int count = 0; + SFILE_FIND_DATA data; + HANDLE find = SFileFindFirstFile(WorldMpq, "*.*", &data, NULL); + if (find != NULL) + { + do + { + ++count; + if (data.dwFileFlags & MPQ_FILE_PATCH_FILE) + { + found = true; + break; + } + } + while (SFileFindNextFile(find, &data)); + } + SFileFindClose(find); + printf("Scanned %d files, found patch = %d\n", count, found); + } + } + +} + + // Local testing functions bool FileExists(const char* file) @@ -103,7 +275,8 @@ void strToLower(char* str) void ReadLiquidTypeTableDBC() { printf("Read LiquidType.dbc file..."); - DBCFile dbc("DBFilesClient\\LiquidType.dbc"); + + DBCFile dbc(LocaleMpq, "DBFilesClient\\LiquidType.dbc"); if(!dbc.open()) { printf("Fatal error: Invalid LiquidType.dbc file format!\n"); @@ -123,21 +296,23 @@ void ReadLiquidTypeTableDBC() bool ExtractWmo() { - bool success = true; + bool success = false; //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"}; - for (ArchiveSet::const_iterator ar_itr = gOpenArchives.begin(); ar_itr != gOpenArchives.end() && success; ++ar_itr) + SFILE_FIND_DATA data; + HANDLE find = SFileFindFirstFile(WorldMpq, "*.wmo", &data, NULL); + if (find != NULL) { - vector<string> filelist; - - (*ar_itr)->GetFileListTo(filelist); - for (vector<string>::iterator fname = filelist.begin(); fname != filelist.end() && success; ++fname) + do { - if (fname->find(".wmo") != string::npos) - success = ExtractSingleWmo(*fname); + std::string str = data.cFileName; + //printf("Extracting wmo %s\n", str.c_str()); + success |= ExtractSingleWmo(str); } + while (SFileFindNextFile(find, &data)); } + SFileFindClose(find); if (success) printf("\nExtract wmo complete (No (fatal) errors)\n"); @@ -297,91 +472,10 @@ bool scan_patches(char* scanmatch, std::vector<std::string>& pArchiveNames) return(true); } -bool fillArchiveNameVector(std::vector<std::string>& pArchiveNames) -{ - if(!hasInputPathParam) - getGamePath(); - - printf("\nGame path: %s\n", input_path); - - char path[512]; - string in_path(input_path); - std::vector<std::string> locales, searchLocales; - - searchLocales.push_back("enGB"); - searchLocales.push_back("enUS"); - searchLocales.push_back("deDE"); - searchLocales.push_back("esES"); - searchLocales.push_back("frFR"); - searchLocales.push_back("koKR"); - searchLocales.push_back("zhCN"); - searchLocales.push_back("zhTW"); - searchLocales.push_back("enCN"); - searchLocales.push_back("enTW"); - searchLocales.push_back("esMX"); - searchLocales.push_back("ruRU"); - - for (std::vector<std::string>::iterator i = searchLocales.begin(); i != searchLocales.end(); ++i) - { - std::string localePath = in_path + *i; - // check if locale exists: - struct stat status; - if (stat(localePath.c_str(), &status)) - continue; - if ((status.st_mode & S_IFDIR) == 0) - continue; - printf("Found locale '%s'\n", i->c_str()); - locales.push_back(*i); - } - printf("\n"); - - // open locale expansion and common files - printf("Adding data files from locale directories.\n"); - for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i) - { - pArchiveNames.push_back(in_path + *i + "/locale-" + *i + ".MPQ"); - pArchiveNames.push_back(in_path + *i + "/expansion-locale-" + *i + ".MPQ"); - pArchiveNames.push_back(in_path + *i + "/lichking-locale-" + *i + ".MPQ"); - } - - // open expansion and common files - pArchiveNames.push_back(input_path + string("common.MPQ")); - pArchiveNames.push_back(input_path + string("common-2.MPQ")); - pArchiveNames.push_back(input_path + string("expansion.MPQ")); - pArchiveNames.push_back(input_path + string("lichking.MPQ")); - - // now, scan for the patch levels in the core dir - printf("Scanning patch levels from data directory.\n"); - sprintf(path, "%spatch", input_path); - if (!scan_patches(path, pArchiveNames)) - return(false); - - // now, scan for the patch levels in locale dirs - printf("Scanning patch levels from locale directories.\n"); - bool foundOne = false; - for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i) - { - printf("Locale: %s\n", i->c_str()); - sprintf(path, "%s%s/patch-%s", input_path, i->c_str(), i->c_str()); - if(scan_patches(path, pArchiveNames)) - foundOne = true; - } - - printf("\n"); - - if(!foundOne) - { - printf("no locale found\n"); - return false; - } - - return true; -} - bool processArgv(int argc, char ** argv, const char *versionString) { bool result = true; - hasInputPathParam = false; + bool hasInputPathParam = false; preciseVectorData = false; for(int i = 1; i < argc; ++i) @@ -413,12 +507,18 @@ bool processArgv(int argc, char ** argv, const char *versionString) { preciseVectorData = true; } + else if(strcmp("-b",argv[i]) == 0) + { + if (i + 1 < argc) // all ok + CONF_TargetBuild = atoi(argv[i++ + 1]); + } else { result = false; break; } } + if(!result) { printf("Extract %s.\n",versionString); @@ -426,8 +526,13 @@ bool processArgv(int argc, char ** argv, const char *versionString) printf(" -s : (default) small size (data size optimization), ~500MB less vmap data.\n"); printf(" -l : large size, ~500MB more vmap data. (might contain more details)\n"); printf(" -d <path>: Path to the vector data source folder.\n"); + printf(" -b : target build (default %u)", CONF_TargetBuild); printf(" -? : This message.\n"); } + + if(!hasInputPathParam) + getGamePath(); + return result; } @@ -476,21 +581,24 @@ int main(int argc, char ** argv) )) success = (errno == EEXIST); - // prepare archive name list - std::vector<std::string> archiveNames; - fillArchiveNameVector(archiveNames); - for (size_t i=0; i < archiveNames.size(); ++i) - { - MPQArchive *archive = new MPQArchive(archiveNames[i].c_str()); - if (gOpenArchives.empty() || gOpenArchives.front() != archive) - delete archive; - } + LoadCommonMPQFiles(CONF_TargetBuild); + + int FirstLocale = -1; - if (gOpenArchives.empty()) + for (int i = 0; i < LOCALES_COUNT; ++i) { - printf("FATAL ERROR: None MPQ archive found by path '%s'. Use -d option with proper path.\n",input_path); - return 1; + //Open MPQs + if (!LoadLocaleMPQFile(i)) + { + if (GetLastError() != ERROR_PATH_NOT_FOUND) + printf("Unable to load %s locale archives!\n", Locales[i]); + continue; + } + + printf("Detected and using locale locale: %s\n", Locales[i]); + break; } + ReadLiquidTypeTableDBC(); // extract data @@ -501,7 +609,7 @@ int main(int argc, char ** argv) //map.dbc if (success) { - DBCFile * dbc = new DBCFile("DBFilesClient\\Map.dbc"); + DBCFile * dbc = new DBCFile(LocaleMpq, "DBFilesClient\\Map.dbc"); if (!dbc->open()) { delete dbc; @@ -526,6 +634,9 @@ int main(int argc, char ** argv) ExtractGameobjectModels(); } + SFileCloseArchive(LocaleMpq); + SFileCloseArchive(WorldMpq); + printf("\n"); if (!success) { diff --git a/src/tools/vmap4_extractor/wdtfile.cpp b/src/tools/vmap4_extractor/wdtfile.cpp index a799a928710..9e208dac8dc 100644 --- a/src/tools/vmap4_extractor/wdtfile.cpp +++ b/src/tools/vmap4_extractor/wdtfile.cpp @@ -30,7 +30,9 @@ char * wdtGetPlainName(char * FileName) return FileName; } -WDTFile::WDTFile(char* file_name, char* file_name1) : WDT(file_name), gWmoInstansName(NULL), gnWMO(0) +extern HANDLE WorldMpq; + +WDTFile::WDTFile(char* file_name, char* file_name1):WDT(WorldMpq, file_name) { filename.append(file_name1,strlen(file_name1)); } @@ -125,6 +127,6 @@ ADTFile* WDTFile::GetMap(int x, int z) char name[512]; - sprintf(name,"World\\Maps\\%s\\%s_%d_%d.adt", filename.c_str(), filename.c_str(), x, z); + sprintf(name,"World\\Maps\\%s\\%s_%d_%d_obj0.adt", filename.c_str(), filename.c_str(), x, z); return new ADTFile(name); } diff --git a/src/tools/vmap4_extractor/wdtfile.h b/src/tools/vmap4_extractor/wdtfile.h index 2c66dbceb92..b085965343a 100644 --- a/src/tools/vmap4_extractor/wdtfile.h +++ b/src/tools/vmap4_extractor/wdtfile.h @@ -1,7 +1,7 @@ #ifndef WDTFILE_H #define WDTFILE_H -#include "mpq_libmpq04.h" +#include "mpqfile.h" #include "wmo.h" #include <string> #include "stdlib.h" diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 0bc749b9bd5..85cae02e41c 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -26,7 +26,7 @@ #include <fstream> #undef min #undef max -#include "mpq_libmpq04.h" +#include "mpqfile.h" using namespace std; extern uint16 *LiqType; @@ -39,9 +39,11 @@ WMORoot::WMORoot(std::string &filename) memset(bbcorn2, 0, sizeof(bbcorn2)); } +extern HANDLE WorldMpq; + bool WMORoot::open() { - MPQFile f(filename.c_str()); + MPQFile f(WorldMpq, filename.c_str()); if(f.isEof ()) { printf("No such file.\n"); @@ -151,7 +153,7 @@ WMOGroup::WMOGroup(const std::string &filename) : bool WMOGroup::open() { - MPQFile f(filename.c_str()); + MPQFile f(WorldMpq, filename.c_str()); if(f.isEof ()) { printf("No such file.\n"); diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index 74e666d3f82..02e4be4aa79 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -24,7 +24,7 @@ #include <string> #include <set> #include "vec3d.h" -#include "loadlib/loadlib.h" +#include "mpqfile.h" // MOPY flags #define WMO_MATERIAL_NOCAMCOLLIDE 0x01 |