diff options
Diffstat (limited to 'src/tools')
34 files changed, 1281 insertions, 1328 deletions
diff --git a/src/tools/map_extractor/CMakeLists.txt b/src/tools/map_extractor/CMakeLists.txt index f05424d6bbe..664b80c292d 100644 --- a/src/tools/map_extractor/CMakeLists.txt +++ b/src/tools/map_extractor/CMakeLists.txt @@ -11,20 +11,13 @@  file(GLOB_RECURSE sources *.cpp *.h) -set(include_Dirs -    ${CMAKE_SOURCE_DIR}/src/server/shared -    ${CMAKE_SOURCE_DIR}/dep/libmpq -    ${CMAKE_CURRENT_SOURCE_DIR} -    ${CMAKE_CURRENT_SOURCE_DIR}/loadlib +include_directories ( +  ${CMAKE_SOURCE_DIR}/src/server/shared +  ${CMAKE_SOURCE_DIR}/dep/StormLib/src +  ${CMAKE_CURRENT_SOURCE_DIR} +  ${CMAKE_CURRENT_SOURCE_DIR}/loadlib  ) -if( WIN32 ) -  set(include_Dirs -    ${include_Dirs} -    ${CMAKE_SOURCE_DIR}/dep/libmpq/win -  ) -endif() -  include_directories(${include_Dirs})  add_executable(mapextractor @@ -32,11 +25,13 @@ add_executable(mapextractor  )  target_link_libraries(mapextractor -  mpq    ${BZIP2_LIBRARIES}    ${ZLIB_LIBRARIES} +  storm  ) +add_dependencies(mapextractor storm) +  if( UNIX )    install(TARGETS mapextractor DESTINATION bin)  elseif( WIN32 ) diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index ca04e5a2081..a4de6f92a8d 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -20,18 +20,20 @@  #include <stdio.h>  #include <deque> -#include <set> +#include <list>  #include <cstdlib> +#include <cstring>  #ifdef _WIN32  #include "direct.h"  #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" @@ -48,11 +50,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  { @@ -78,6 +82,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; @@ -89,46 +94,63 @@ 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", +}; + +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 +#define NEW_BASE_SET_BUILD  15211 + +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"),  }; -static const char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; -#define LANG_COUNT 12 +#define LOCALES_COUNT 12 -void CreateDir( const std::string& Path ) +void CreateDir(std::string const& path)  { -    if(chdir(Path.c_str()) == 0) +    if (chdir(path.c_str()) == 0)      {              chdir("../");              return;      } -    int ret; -    #ifdef _WIN32 -    ret = _mkdir( Path.c_str()); -    #else -    ret = mkdir( Path.c_str(), 0777 ); -    #endif -    if (ret != 0) -    { -        printf("Fatal Error: Could not create directory %s check your permissions", Path.c_str()); -        exit(1); -    } +#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); @@ -138,7 +160,7 @@ bool FileExists( const char* FileName )      return false;  } -void Usage(char* prg) +void Usage(char const* prg)  {      printf(          "Usage:\n"\ @@ -147,52 +169,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)\n"\ +        "Example: %s -f 0 -i \"c:\\games\\game\"", prg, CONF_TargetBuild, prg);      exit(1);  } -void HandleArgs(int argc, char * arg[]) +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;          }      }  } @@ -200,22 +232,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 = std::string(m.getPointer(), m.getSize()); -    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()); @@ -237,9 +278,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); @@ -252,15 +300,23 @@ uint32 ReadMapDBC()          map_ids[x].id = dbc.getRecord(x).getUInt(0);          strcpy(map_ids[x].name, dbc.getRecord(x).getString(1));      } -    printf("Done! (%u maps loaded)\n", (uint32)map_count); + +    SFileCloseFile(dbcFile); +    printf("Done! (%u maps loaded)\n", uint32(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"); @@ -268,22 +324,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! (%u areas loaded)\n", (uint32)area_count); +    SFileCloseFile(dbcFile); +    printf("Done! (%u areas loaded)\n", uint32(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"); @@ -298,6 +359,7 @@ void ReadLiquidTypeTableDBC()      for(uint32 x = 0; x < liqTypeCount; ++x)          LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); +    SFileCloseFile(dbcFile);      printf("Done! (%u LiqTypes loaded)\n", (uint32)liqTypeCount);  } @@ -401,16 +463,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)); @@ -422,24 +477,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      //============================================ @@ -481,7 +539,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: @@ -652,7 +710,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; @@ -752,7 +810,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;                  } @@ -760,34 +818,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; @@ -874,7 +935,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;              holes[i][j] = cell->holes; @@ -926,15 +987,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);          }      } @@ -965,186 +1027,330 @@ 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/"; + +        CreateDir(outputPath); +        if (!basicLocale) +        { +            outputPath += Locales[l]; +            outputPath += "/"; +            CreateDir(outputPath); +        } + +        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('\\') + 1); + +            if (FileExists(filename.c_str())) +                continue; + +            if (ExtractFile(dbcFile, filename.c_str())) +                ++count; + +            SFileCloseFile(dbcFile); +        } while (SFileFindNextFile(listFile, &foundFile)); + +        SFileFindClose(listFile);      } -    std::string path = output_path; -    path += "/dbc/"; -    CreateDir(path); -    if(!basicLocale) +    printf("Extracted %u DBC files\n\n", count); +} + +void ExtractDB2Files(int l, bool basicLocale) +{ +    printf("Extracting db2 files...\n"); + +    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)      { -        path += langs[locale]; -        path += "/"; -        CreateDir(path); +        std::string outputPath = output_path; +        outputPath += "/dbc/"; +        if (!basicLocale) +        { +            outputPath += Locales[l]; +            outputPath += "/"; +        } + +        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('\\') + 1); +            if (ExtractFile(dbcFile, filename.c_str())) +                ++count; + +            SFileCloseFile(dbcFile); +        } while (SFileFindNextFile(listFile, &foundFile)); + +        SFileFindClose(listFile);      } -    // extract Build info file -    { -        string mpq_name = std::string("component.wow-") + langs[locale] + ".txt"; -        string filename = path + mpq_name; +    printf("Extracted %u DB2 files\n\n", count); +} -        ExtractFile(mpq_name.c_str(), filename); +bool LoadLocaleMPQFile(int locale) +{ +    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)) +    { +        if (GetLastError() != ERROR_PATH_NOT_FOUND) +        { +            _tprintf(_T("\nLoading %s locale MPQs\n"), LocalesT[locale]); +            _tprintf(_T("Cannot open archive %s\n"), buff); +        } +        return false;      } -    // extract DBCs -    uint32 count = 0; -    for (set<string>::iterator iter = dbcfiles.begin(); iter != dbcfiles.end(); ++iter) +    _tprintf(_T("\nLoading %s locale MPQs\n"), LocalesT[locale]); +    char const* prefix = NULL; +    for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)      { -        string filename = path; -        filename += (iter->c_str() + strlen("DBFilesClient\\")); -         -        if(FileExists(filename.c_str())) +        // Do not attempt to read older MPQ patch archives past this build, they were merged with base +        // and trying to read them together with new base will not end well +        if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD)              continue; -        if (ExtractFile(iter->c_str(), filename)) -            ++count; +        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; +        } +        else +            _tprintf(_T("Loaded %s\n"), buff);      } -    printf("Extracted %u DBC files\n\n", count); + +    printf("\n"); +    return true;  } -void LoadLocaleMPQFiles(int const locale) +void LoadCommonMPQFiles(uint32 build)  { -    char filename[512]; - -    sprintf(filename,"%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]); -    new MPQArchive(filename); +    TCHAR filename[512]; +    _stprintf(filename, _T("%s/Data/world.MPQ"), input_path); +    _tprintf(_T("Loading common MPQ files\n")); +    if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq)) +    { +        if (GetLastError() != ERROR_PATH_NOT_FOUND) +            _tprintf(_T("Cannot open archive %s\n"), filename); +        return; +    } -    for(int i = 1; i < 5; ++i) +    int count = sizeof(CONF_mpq_list) / sizeof(char*); +    for (int i = 1; i < count; ++i)      { -        char ext[3] = ""; -        if(i > 1) -            sprintf(ext, "-%i", i); +        if (build < NEW_BASE_SET_BUILD && !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); -        sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ", input_path, langs[locale], langs[locale], ext); -        if(FileExists(filename)) -            new MPQArchive(filename);      } -} -void LoadCommonMPQFiles() -{ -    char filename[512]; -    int count = sizeof(CONF_mpq_list)/sizeof(char*); -    for(int i = 0; i < count; ++i) +    char const* prefix = NULL; +    for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)      { -        sprintf(filename, "%s/Data/%s", input_path, CONF_mpq_list[i]); -        if(FileExists(filename)) -            new MPQArchive(filename); +        // Do not attempt to read older MPQ patch archives past this build, they were merged with base +        // and trying to read them together with new base will not end well +        if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD) +            continue; + +        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);      } -} -inline void CloseMPQFiles() -{ -    for(ArchiveSet::iterator j = gOpenArchives.begin(); j != gOpenArchives.end();++j) (*j)->close(); -        gOpenArchives.clear(); +    printf("\n");  }  int main(int argc, char * arg[])  {      printf("Map & DBC Extractor\n"); -    printf("===================\n\n"); +    printf("===================\n");      HandleArgs(argc, 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); +            printf("\n"); +            break; +        } + +        //Extract DBC files +        uint32 tempBuild = ReadBuild(i); +        printf("Detected client build %u for locale %s\n", tempBuild, Locales[i]); +        if (tempBuild > CONF_TargetBuild) +        { +            SFileCloseArchive(LocaleMpq); +            printf("Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n", Locales[i], tempBuild, CONF_TargetBuild); +            continue; +        } + +        printf("\n"); +        ExtractDBCFiles(i, FirstLocale < 0); +        ExtractDB2Files(i, FirstLocale < 0); -            //Close MPQs -            CloseMPQFiles(); +        if (FirstLocale < 0) +        { +            FirstLocale = i; +            build = tempBuild;          } + +        //Close MPQs +        SFileCloseArchive(LocaleMpq);      } -    if(FirstLocale < 0) +    if (FirstLocale < 0)      {          printf("No locales detected\n");          return 0; @@ -1152,17 +1358,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 095f598501a..9260828fd41 100644 --- a/src/tools/map_extractor/adt.cpp +++ b/src/tools/map_extractor/adt.cpp @@ -19,6 +19,7 @@  #define _CRT_SECURE_NO_DEPRECATE  #include "adt.h" +#include <cstring>  // Helper  int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; @@ -69,10 +70,31 @@ bool ADT_file::prepareLoadedData()          return false;      // Check and prepare MHDR -    a_grid = (adt_MHDR *)(GetData()+8+version->size); +    a_grid = (adt_MHDR*)(GetData()+8+version->size);      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 == MCNKMagic.fcc) +        { +            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 10894c7a697..9f8ada77317 100644 --- a/src/tools/map_extractor/adt.h +++ b/src/tools/map_extractor/adt.h @@ -265,15 +265,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 @@ -291,9 +294,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{ @@ -303,7 +305,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];  };  #pragma pack(pop) diff --git a/src/tools/map_extractor/dbcfile.cpp b/src/tools/map_extractor/dbcfile.cpp index 653b48ff949..fc7d8d25d05 100644 --- a/src/tools/map_extractor/dbcfile.cpp +++ b/src/tools/map_extractor/dbcfile.cpp @@ -19,83 +19,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 9e2e6670f89..2bf27f5c7f6 100644 --- a/src/tools/map_extractor/dbcfile.h +++ b/src/tools/map_extractor/dbcfile.h @@ -20,122 +20,129 @@  #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 -        { -            assert(field < file.fieldCount); -            return *reinterpret_cast<unsigned int*>(offset+field*4); -        } -        int getInt(size_t field) const +        // Database exceptions +        class Exception          { -            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) {} -        DBCFile &file; -        unsigned char *offset; - -        friend class DBCFile; -        friend class DBCFile::Iterator; - -        Record& operator=(Record const& right); -    }; -    /** 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); +                } + +                char const* 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) {} +                DBCFile& file; +                unsigned char* offset; + +                friend class DBCFile; +                friend class DBCFile::Iterator; + +				Record& operator=(Record const& right); +        }; +        /** 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; } +                Record const* operator->() const { return &record; } + +                /// Comparison +                bool operator==(Iterator const& b) const +                { +                    return record.offset == b.record.offset; +                } + +                bool operator!=(Iterator const& b) const +                { +                    return record.offset != b.record.offset; +                } + +            private: +                Record record; + +				Iterator& operator=(Iterator const& right); +        }; + +        // 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; - -        Iterator& operator=(Iterator const& right); -    }; - -    // 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 ebe1bd61b65..5d1742c224e 100644 --- a/src/tools/map_extractor/loadlib.cpp +++ b/src/tools/map_extractor/loadlib.cpp @@ -19,11 +19,8 @@  #define _CRT_SECURE_NO_DEPRECATE  #include "loadlib.h" -#include "mpq_libmpq04.h"  #include <cstdio> -class MPQFile; -  u_map_fcc MverMagic = { {'R','E','V','M'} };  FileLoader::FileLoader() @@ -38,28 +35,30 @@ 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]; -    mf.read(data, data_size); -    mf.close(); +    data_size = SFileGetFileSize(file, NULL); +    data = new uint8[data_size]; +    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 39f800d9b4c..2bea59e2c97 100644 --- a/src/tools/map_extractor/loadlib/loadlib.h +++ b/src/tools/map_extractor/loadlib/loadlib.h @@ -19,6 +19,8 @@  #ifndef LOAD_LIB_H  #define LOAD_LIB_H +#include "StormLib.h" +  #ifdef _WIN32  typedef __int64            int64;  typedef __int32            int32; @@ -68,6 +70,7 @@ struct file_MVER      uint32 ver;  }; +  class FileLoader{      uint8  *data;      uint32  data_size; @@ -79,7 +82,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();  }; diff --git a/src/tools/map_extractor/mpq_libmpq.cpp b/src/tools/map_extractor/mpq_libmpq.cpp deleted file mode 100644 index df9eb78fc65..00000000000 --- a/src/tools/map_extractor/mpq_libmpq.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * 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, see <http://www.gnu.org/licenses/>. - */ - -#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_t(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 76778c663a6..00000000000 --- a/src/tools/map_extractor/mpq_libmpq04.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * 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, see <http://www.gnu.org/licenses/>. - */ - -#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); -    ~MPQArchive() { close(); } -    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+1]; -        buffer[size] = '\0'; - -        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 fbb0b78567b..59444b46b88 100644 --- a/src/tools/map_extractor/wdt.cpp +++ b/src/tools/map_extractor/wdt.cpp @@ -79,6 +79,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;  } diff --git a/src/tools/map_extractor/wdt.h b/src/tools/map_extractor/wdt.h index 9b7fc53cb34..d897cbfd854 100644 --- a/src/tools/map_extractor/wdt.h +++ b/src/tools/map_extractor/wdt.h @@ -65,7 +65,7 @@ public:      uint32 size;      struct adtData{ -        uint32 exist; +        uint32 flag;          uint32 data1;      } adt_list[64][64]; diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h index 7f0d23b0418..075265f2627 100644 --- a/src/tools/mesh_extractor/ContinentBuilder.h +++ b/src/tools/mesh_extractor/ContinentBuilder.h @@ -44,4 +44,5 @@ private:      int tileXMax;      int tileYMax;  }; +  #endif diff --git a/src/tools/mesh_extractor/DBC.cpp b/src/tools/mesh_extractor/DBC.cpp index d1b95076ecd..e38b9560533 100644 --- a/src/tools/mesh_extractor/DBC.cpp +++ b/src/tools/mesh_extractor/DBC.cpp @@ -52,6 +52,7 @@ DBC::DBC( FILE* stream ) : StringBlock(NULL), StringBlockSize(0), IsFaulty(true)              size += 4;          }      } +      StringBlock = new uint8[StringBlockSize];      count = fread(StringBlock, sizeof(uint8), StringBlockSize, stream);      if (count != StringBlockSize) diff --git a/src/tools/vmap4_assembler/CMakeLists.txt b/src/tools/vmap4_assembler/CMakeLists.txt index 33e8188aee1..041d44e014c 100644 --- a/src/tools/vmap4_assembler/CMakeLists.txt +++ b/src/tools/vmap4_assembler/CMakeLists.txt @@ -21,10 +21,7 @@ include_directories(  )  add_executable(vmap4assembler VMapAssembler.cpp) - -if(CMAKE_SYSTEM_NAME MATCHES "Darwin") -  set_target_properties(vmap4assembler PROPERTIES LINK_FLAGS "-framework Carbon") -endif() +add_dependencies(vmap4assembler storm)  target_link_libraries(vmap4assembler    collision diff --git a/src/tools/vmap4_extractor/CMakeLists.txt b/src/tools/vmap4_extractor/CMakeLists.txt index 90d2c68977f..a98cc55666c 100644 --- a/src/tools/vmap4_extractor/CMakeLists.txt +++ b/src/tools/vmap4_extractor/CMakeLists.txt @@ -11,27 +11,30 @@  file(GLOB_RECURSE sources *.cpp *.h) -set(include_Dirs -    ${CMAKE_SOURCE_DIR}/dep/libmpq -) +# uncomment next line to disable debug mode +add_definitions("-DIOMAP_DEBUG") -if( WIN32 ) -  set(include_Dirs -    ${include_Dirs} -    ${CMAKE_SOURCE_DIR}/dep/libmpq/win -  ) +# build setup currently only supports libmpq 0.4.x +if( NOT MSVC ) +  add_definitions("-Wall") +  add_definitions("-ggdb") +  add_definitions("-O3")  endif() -include_directories(${include_Dirs}) +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 storm) +  if( UNIX )    install(TARGETS vmap4extractor DESTINATION bin)  elseif( WIN32 ) diff --git a/src/tools/vmap4_extractor/adtfile.cpp b/src/tools/vmap4_extractor/adtfile.cpp index c792524eec1..15723e7d941 100644 --- a/src/tools/vmap4_extractor/adtfile.cpp +++ b/src/tools/vmap4_extractor/adtfile.cpp @@ -44,26 +44,29 @@ char* GetPlainName(char* FileName)      return FileName;  } -void fixnamen(char* name, size_t len) +void FixNameCase(char* name, size_t len)  { -    for (size_t i = 0; i < len-3; i++) +    char* ptr = name + len - 1; + +    //extension in lowercase +    for (; *ptr != '.'; --ptr) +        *ptr |= 0x20; + +    for (; ptr >= name; --ptr)      { -        if (i > 0 && name[i] >= 'A' && name[i] <= 'Z' && isalpha(name[i-1])) -            name[i] |= 0x20; -        else if ((i == 0 || !isalpha(name[i-1])) && name[i]>='a' && name[i]<='z') -            name[i] &= ~0x20; +        if (ptr > name && *ptr >= 'A' && *ptr <= 'Z' && isalpha(*(ptr - 1))) +            *ptr |= 0x20; +        else if ((ptr == name || !isalpha(*(ptr - 1))) && *ptr >= 'a' && *ptr <= 'z') +            *ptr &= ~0x20;      } -    //extension in lowercase -    for (size_t i = len - 3; i < len; i++) -        name[i] |= 0x20;  } -void fixname2(char* name, size_t len) +void FixNameSpaces(char* name, size_t len)  {      for (size_t i=0; i<len-3; i++)      {          if(name[i] == ' ') -        name[i] = '_'; +            name[i] = '_';      }  } @@ -74,7 +77,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, false)  {      Adtfilename.append(filename);  } @@ -130,23 +135,24 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)          {              if (size)              { -                char *buf = new char[size]; +                char* buf = new char[size];                  ADT.read(buf, size); -                char *p=buf; -                int t=0; -                ModelInstansName = new string[size]; -                while (p<buf+size) +                char* p = buf; +                int t = 0; +                ModelInstanceNames = new std::string[size]; +                while (p < buf + size)                  { -                    fixnamen(p,strlen(p)); +                    std::string path(p); +                      char* s = GetPlainName(p); -                    fixname2(s,strlen(s)); +                    FixNameCase(s, strlen(s)); +                    FixNameSpaces(s, strlen(s)); -                    ModelInstansName[t++] = s; +                    ModelInstanceNames[t++] = s; -                    string path(p);                      ExtractSingleModel(path); -                    p = p+strlen(p)+1; +                    p += strlen(p) + 1;                  }                  delete[] buf;              } @@ -157,16 +163,18 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)              {                  char* buf = new char[size];                  ADT.read(buf, size); -                char* p=buf; +                char* p = buf;                  int q = 0; -                WmoInstansName = new std::string[size]; -                while (p<buf+size) +                WmoInstanceNames = new std::string[size]; +                while (p < buf + size)                  {                      char* s = GetPlainName(p); -                    fixnamen(s, strlen(s)); -                    fixname2(s, strlen(s)); +                    FixNameCase(s, strlen(s)); +                    FixNameSpaces(s, strlen(s)); + +                    WmoInstanceNames[q++] = s; +                      p += strlen(p) + 1; -                    WmoInstansName[q++] = s;                  }                  delete[] buf;              } @@ -181,9 +189,10 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)                  {                      uint32 id;                      ADT.read(&id, 4); -                    ModelInstance inst(ADT,ModelInstansName[id].c_str(), map_num, tileX, tileY, dirfile); +                    ModelInstance inst(ADT, ModelInstanceNames[id].c_str(), map_num, tileX, tileY, dirfile);                  } -                delete[] ModelInstansName; +                delete[] ModelInstanceNames; +                ModelInstanceNames = NULL;              }          }          else if (!strcmp(fourcc,"MODF")) @@ -195,14 +204,18 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)                  {                      uint32 id;                      ADT.read(&id, 4); -                    WMOInstance inst(ADT,WmoInstansName[id].c_str(), map_num, tileX, tileY, dirfile); +                    WMOInstance inst(ADT, WmoInstanceNames[id].c_str(), map_num, tileX, tileY, dirfile);                  } -                delete[] WmoInstansName; + +                delete[] WmoInstanceNames; +                WmoInstanceNames = NULL;              }          } +          //======================          ADT.seek(nextpos);      } +      ADT.close();      fclose(dirfile);      return true; diff --git a/src/tools/vmap4_extractor/adtfile.h b/src/tools/vmap4_extractor/adtfile.h index ac04074375f..1970686f30e 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" @@ -119,8 +119,8 @@ public:      ~ADTFile();      int nWMO;      int nMDX; -    std::string* WmoInstansName; -    std::string* ModelInstansName; +    std::string* WmoInstanceNames; +    std::string* ModelInstanceNames;      bool init(uint32 map_num, uint32 tileX, uint32 tileY);      //void LoadMapChunks(); @@ -133,11 +133,11 @@ public:  */  }; -const char * GetPlainName(const char * FileName); -char * GetPlainName(char * FileName); -char * GetExtension(char * FileName); -void fixnamen(char *name, size_t len); -void fixname2(char *name, size_t len); +char const* GetPlainName(char const* FileName); +char* GetPlainName(char* FileName); +char* GetExtension(char* FileName); +void FixNameCase(char* name, size_t len); +void FixNameSpaces(char* name, size_t len);  //void fixMapNamen(char *name, size_t len);  #endif diff --git a/src/tools/vmap4_extractor/dbcfile.cpp b/src/tools/vmap4_extractor/dbcfile.cpp index 66c5669b88b..a825fcacddd 100644 --- a/src/tools/vmap4_extractor/dbcfile.cpp +++ b/src/tools/vmap4_extractor/dbcfile.cpp @@ -16,81 +16,104 @@   * with this program. If not, see <http://www.gnu.org/licenses/>.   */ -#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 7551de8594c..8e2edf951e1 100644 --- a/src/tools/vmap4_extractor/dbcfile.h +++ b/src/tools/vmap4_extractor/dbcfile.h @@ -18,138 +18,144 @@  #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); +                } + +                char const* 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) {} +                DBCFile& file; +                unsigned char* offset; + +                friend class DBCFile; +                friend class DBCFile::Iterator; + +                Record& operator=(Record const&); +                Record(Record const& right) : file(right.file), offset(right.offset) +                { +                } +        }; +        /** Iterator that iterates over records +        */ +        class Iterator          { -            return record.offset != b.record.offset; -        } +            public: +                Iterator(DBCFile &file, unsigned char* offset) : record(file, offset) { } + +                Iterator(Iterator const& right) : record(right.record) +                { +                } + +                /// Advance (prefix only) +                Iterator& operator++() +                { +                    record.offset += record.file._recordSize; +                    return *this; +                } + +                /// Return address of current instance +                Record const& operator*() const { return record; } +                Record const* operator->() const { return &record; } + +                /// Comparison +                bool operator==(Iterator const& b) const +                { +                    return record.offset == b.record.offset; +                } + +                bool operator!=(Iterator const& b) const +                { +                    return record.offset != b.record.offset; +                } + +                Iterator& operator=(Iterator const& right) +                { +                    record.offset = right.record.offset; +                    return *this; +                } +            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 59871012ea5..3bb0ac86901 100644 --- a/src/tools/vmap4_extractor/gameobject_extract.cpp +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -26,18 +26,17 @@  bool ExtractSingleModel(std::string& fname)  { -    char * name = GetPlainName((char*)fname.c_str()); -    char * ext = GetExtension(name); - -    // < 3.1.0 ADT MMDX section store filename.mdx filenames for corresponded .m2 file -    if (!strcmp(ext, ".mdx")) +    if (fname.substr(fname.length() - 4, 4) == ".mdx")      { -        // replace .mdx -> .m2 -        fname.erase(fname.length()-2,2); +        fname.erase(fname.length() - 2, 2);          fname.append("2");      } -    // >= 3.1.0 ADT MMDX section store filename.m2 filenames for corresponded .m2 file -    // nothing do + +    std::string originalName = fname; + +    char* name = GetPlainName((char*)fname.c_str()); +    FixNameCase(name, strlen(name)); +    FixNameSpaces(name, strlen(name));      std::string output(szWorkDirWmo);      output += "/"; @@ -46,17 +45,19 @@ bool ExtractSingleModel(std::string& fname)      if (FileExists(output.c_str()))          return true; -    Model mdl(fname); +    Model mdl(originalName);      if (!mdl.open())          return false;      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"); @@ -82,9 +83,9 @@ void ExtractGameobjectModels()          if (path.length() < 4)              continue; -        fixnamen((char*)path.c_str(), path.size()); +        FixNameCase((char*)path.c_str(), path.size());          char * name = GetPlainName((char*)path.c_str()); -        fixname2(name, strlen(name)); +        FixNameSpaces(name, strlen(name));          char * ch_ext = GetExtension(name);          if (!ch_ext) @@ -94,18 +95,11 @@ void ExtractGameobjectModels()          bool result = false;          if (!strcmp(ch_ext, ".wmo")) -        {              result = ExtractSingleWmo(path); -        } -        else if (!strcmp(ch_ext, ".mdl")) -        { -            // TODO: extract .mdl files, if needed +        else if (!strcmp(ch_ext, ".mdl"))   // TODO: extract .mdl files, if needed              continue; -        }          else //if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2")) -        {              result = ExtractSingleModel(path); -        }          if (result)          { diff --git a/src/tools/vmap4_extractor/loadlib/loadlib.h b/src/tools/vmap4_extractor/loadlib/loadlib.h deleted file mode 100644 index b26d39fbbf8..00000000000 --- a/src/tools/vmap4_extractor/loadlib/loadlib.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * 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, see <http://www.gnu.org/licenses/>. - */ - -#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 - -#pragma pack(push, 1) - -// -// 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(); -}; - -#pragma pack(pop) - -#endif diff --git a/src/tools/vmap4_extractor/model.cpp b/src/tools/vmap4_extractor/model.cpp index 825a2697c16..0f1bde7712d 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())      { @@ -44,7 +46,7 @@ bool Model::open()      _unload();      memcpy(&header, f.getBuffer(), sizeof(ModelHeader)); -    if(header.nBoundingTriangles > 0) +    if (header.nBoundingTriangles > 0)      {          f.seek(0);          f.seekRelative(header.ofsBoundingVertices); diff --git a/src/tools/vmap4_extractor/model.h b/src/tools/vmap4_extractor/model.h index a1766ed0bb2..74df92efb3b 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 b0d729dd238..ce951d75f78 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 265ae99528f..00000000000 --- a/src/tools/vmap4_extractor/mpq_libmpq.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * 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, see <http://www.gnu.org/licenses/>. - */ - -#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_t(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 46cb50fb003..00000000000 --- a/src/tools/vmap4_extractor/mpq_libmpq04.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> - * 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, see <http://www.gnu.org/licenses/>. - */ - -#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); -    ~MPQArchive() { 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 + 1]; -        buffer[size] = '\0'; - -        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; -    } - -private: -    void close(); -}; -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..4e690aabee3 --- /dev/null +++ b/src/tools/vmap4_extractor/mpqfile.cpp @@ -0,0 +1,87 @@ +#include "mpqfile.h" +#include <deque> +#include <cstdio> +#include "StormLib.h" + +MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/) : +    eof(false), +    buffer(0), +    pointer(0), +    size(0) +{ +    HANDLE file; +    if (!SFileOpenFileEx(mpq, filename, SFILE_OPEN_PATCHED_FILE, &file)) +    { +        if (warnNoExist || GetLastError() != ERROR_FILE_NOT_FOUND) +            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, uint32(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, uint32(size), uint32(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..e7379c4f7a0 --- /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, bool warnNoExist = true);    // 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 d75af79f379..fbb7cb87ebe 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,47 @@  //----------------------------------------------------------------------------- -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 +#define NEW_BASE_SET_BUILD  15211 + +#define LOCALES_COUNT 12 + +char const* Locales[LOCALES_COUNT] = +{ +    "enGB", "enUS", +    "deDE", "esES", +    "frFR", "koKR", +    "zhCN", "zhTW", +    "enCN", "enTW", +    "esMX", "ruRU" +}; + +TCHAR const* LocalesT[LOCALES_COUNT] = +{ +    _T("enGB"), _T("enUS"), +    _T("deDE"), _T("esES"), +    _T("frFR"), _T("koKR"), +    _T("zhCN"), _T("zhTW"), +    _T("enCN"), _T("enTW"), +    _T("esMX"), _T("ruRU"), +};  typedef struct  { @@ -69,7 +110,6 @@ uint16 *LiqType = 0;  uint32 map_count;  char output_path[128]=".";  char input_path[1024]="."; -bool hasInputPathParam = false;  bool preciseVectorData = false;  // Constants @@ -78,6 +118,120 @@ 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("Loading %s locale MPQs\n"), LocalesT[locale]); +            _tprintf(_T("Cannot open archive %s\n"), buff); +        } +        return false; +    } + +    _tprintf(_T("Loading %s locale MPQs\n"), LocalesT[locale]); +    char const* prefix = NULL; +    for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i) +    { +        // Do not attempt to read older MPQ patch archives past this build, they were merged with base +        // and trying to read them together with new base will not end well +        if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD) +            continue; + +        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; +        } +    } + +    printf("\n"); +    return true; +} + +void LoadCommonMPQFiles(uint32 build) +{ +    TCHAR filename[512]; +    _stprintf(filename, _T("%sworld.MPQ"), input_path); +    _tprintf(_T("Loading common MPQ files\n")); +    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); +    } + +    char const* prefix = NULL; +    for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i) +    { +        // Do not attempt to read older MPQ patch archives past this build, they were merged with base +        // and trying to read them together with new base will not end well +        if (CONF_TargetBuild >= NEW_BASE_SET_BUILD && Builds[i] < NEW_BASE_SET_BUILD) +            continue; + +        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); +    } + +    printf("\n"); +} + +  // Local testing functions  bool FileExists(const char* file) @@ -103,7 +257,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 +278,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"); @@ -152,7 +309,7 @@ bool ExtractSingleWmo(std::string& fname)      char szLocalFile[1024];      const char * plain_name = GetPlainName(fname.c_str());      sprintf(szLocalFile, "%s/%s", szWorkDirWmo, plain_name); -    fixnamen(szLocalFile,strlen(szLocalFile)); +    FixNameCase(szLocalFile,strlen(szLocalFile));      if (FileExists(szLocalFile))          return true; @@ -203,7 +360,7 @@ bool ExtractSingleWmo(std::string& fname)              sprintf(groupFileName, "%s_%03u.wmo", temp, i);              //printf("Trying to open groupfile %s\n",groupFileName); -            string s = groupFileName; +            std::string s = groupFileName;              WMOGroup fgroup(s);              if(!fgroup.open())              { @@ -267,121 +424,10 @@ void getGamePath()  #endif  } -bool scan_patches(char* scanmatch, std::vector<std::string>& pArchiveNames) -{ -    int i; -    char path[512]; - -    for (i = 1; i <= 99; i++) -    { -        if (i != 1) -        { -            sprintf(path, "%s-%d.MPQ", scanmatch, i); -        } -        else -        { -            sprintf(path, "%s.MPQ", scanmatch); -        } -#ifdef __linux__ -        if(FILE* h = fopen64(path, "rb")) -#else -        if(FILE* h = fopen(path, "rb")) -#endif -        { -            fclose(h); -            //matches.push_back(path); -            pArchiveNames.push_back(path); -        } -    } - -    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 +459,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 +478,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)\n", CONF_TargetBuild);          printf("   -? : This message.\n");      } + +    if(!hasInputPathParam) +        getGamePath(); +      return result;  } @@ -465,7 +522,7 @@ int main(int argc, char ** argv)          }      } -    printf("Extract %s. Beginning work ....\n",versionString); +    printf("Extract %s. Beginning work ....\n\n",versionString);      //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx      // Create the working directory      if (mkdir(szWorkDirWmo @@ -475,21 +532,22 @@ 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); -    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: %s\n", Locales[i]); +        break;      } +      ReadLiquidTypeTableDBC();      // extract data @@ -500,7 +558,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; @@ -521,10 +579,13 @@ int main(int argc, char ** argv)          ParsMapFiles();          delete [] map_ids;          //nError = ERROR_SUCCESS; -        // Extract models, listed in DameObjectDisplayInfo.dbc +        // Extract models, listed in GameObjectDisplayInfo.dbc          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 20bee313e70..6e17c80e187 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));  } @@ -81,7 +83,7 @@ bool WDTFile::init(char* /*map_id*/, unsigned int mapID)                  while (p < buf + size)                  {                      char* s=wdtGetPlainName(p); -                    fixnamen(s,strlen(s)); +                    FixNameCase(s,strlen(s));                      p=p+strlen(p)+1;                      gWmoInstansName[q++] = s;                  } @@ -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 8545fd67560..637a2e0c24f 100644 --- a/src/tools/vmap4_extractor/wdtfile.h +++ b/src/tools/vmap4_extractor/wdtfile.h @@ -19,7 +19,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 8efdb899cab..fe79422c87e 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"); @@ -149,7 +151,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 a5bb7d518e8..c027c356ef5 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  | 
