6#define _CRT_SECURE_NO_DEPRECATE
23#define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND
33#if defined( __GNUC__ )
44 #define OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE)
46 #define OPEN_FLAGS (O_RDONLY | O_BINARY)
103uint32 const Builds[] = {16016, 16048, 16057, 16309, 16357, 16516, 16650, 16844, 16965, 17116, 17266, 17325, 17345, 17538, 17645, 17688, 17898, 18273};
105#define NEW_BASE_SET_BUILD 15211
106#define LOCALES_COUNT 15
122 _T(
"enGB"), _T(
"enUS"),
123 _T(
"deDE"), _T(
"esES"),
124 _T(
"frFR"), _T(
"koKR"),
125 _T(
"zhCN"), _T(
"zhTW"),
126 _T(
"enCN"), _T(
"enTW"),
127 _T(
"esMX"), _T(
"ruRU"),
128 _T(
"ptBR"), _T(
"ptPT"),
134 if (chdir(path.c_str()) == 0)
141 _mkdir(path.c_str());
143 mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
149 int fp = _open(fileName, O_RDONLY | O_BINARY);
163 "%s -[var] [value]\n"\
164 "-i set input path\n"\
165 "-o set output path\n"\
166 "-e extract only MAP(1)/DBC(2)/Camera(4) - standard: all(7)\n"\
167 "-f height stored as int (less map size but lost some accuracy) 1 by default\n"\
168 "-b target build (default %u)\n"\
175 for (
int c = 1; c < argc; ++c)
183 if (arg[c][0] !=
'-')
231 std::string filename = std::string(
"component.wow-") +
Locales[locale] +
".txt";
235 if (!SFileOpenFileEx(
LocaleMpq, filename.c_str(), SFILE_OPEN_FROM_MPQ, &dbcFile))
237 printf(
"Fatal error: Not found %s file!\n", filename.c_str());
241 char buff[512] = { 0 };
243 SFileReadFile(dbcFile, buff, 512, &readBytes, NULL);
246 printf(
"Fatal error: Not found %s file!\n", filename.c_str());
250 std::string text = buff;
251 SFileCloseFile(dbcFile);
252 std::string version =
"version=\"";
254 size_t pos = text.find(version);
255 size_t pos1 = pos + version.length();
256 size_t pos2 = text.find(
"\"", pos1);
257 if (pos == text.npos || pos2 == text.npos || pos1 >= pos2)
259 printf(
"Fatal error: Invalid %s file format!\n", filename.c_str());
263 std::string build_str = text.substr(pos1,pos2-pos1);
265 int build = atoi(build_str.c_str());
268 printf(
"Fatal error: Invalid %s file format!\n", filename.c_str());
277 printf(
"Read Map.dbc file... ");
280 if (!SFileOpenFileEx(
LocaleMpq,
"DBFilesClient\\Map.dbc", SFILE_OPEN_FROM_MPQ, &dbcFile))
282 printf(
"Fatal error: Cannot find Map.dbc in archive!\n");
289 printf(
"Fatal error: Invalid Map.dbc file format!\n");
301 SFileCloseFile(dbcFile);
308 printf(
"Read AreaTable.dbc file...");
310 if (!SFileOpenFileEx(
LocaleMpq,
"DBFilesClient\\AreaTable.dbc", SFILE_OPEN_FROM_MPQ, &dbcFile))
312 printf(
"Fatal error: Cannot find AreaTable.dbc in archive!\n");
319 printf(
"Fatal error: Invalid AreaTable.dbc file format!\n");
327 for (
uint32 x = 0; x < area_count; ++x)
330 SFileCloseFile(dbcFile);
331 printf(
"Done! (%u areas loaded)\n",
uint32(area_count));
336 printf(
"Read LiquidType.dbc file...");
338 if (!SFileOpenFileEx(
LocaleMpq,
"DBFilesClient\\LiquidType.dbc", SFILE_OPEN_FROM_MPQ, &dbcFile))
340 printf(
"Fatal error: Cannot find LiquidType.dbc in archive!\n");
347 printf(
"Fatal error: Invalid LiquidType.dbc file format!\n");
352 size_t liqTypeMaxId = dbc.
getMaxId();
356 for (
uint32 x = 0; x < liqTypeCount; ++x)
359 SFileCloseFile(dbcFile);
360 printf(
"Done! (%u LiqTypes loaded)\n", (
uint32)liqTypeCount);
389#define MAP_AREA_NO_AREA 0x0001
398#define MAP_HEIGHT_NO_HEIGHT 0x0001
399#define MAP_HEIGHT_AS_INT16 0x0002
400#define MAP_HEIGHT_AS_INT8 0x0004
410#define MAP_LIQUID_TYPE_NO_WATER 0x00
411#define MAP_LIQUID_TYPE_WATER 0x01
412#define MAP_LIQUID_TYPE_OCEAN 0x02
413#define MAP_LIQUID_TYPE_MAGMA 0x04
414#define MAP_LIQUID_TYPE_SLIME 0x08
416#define MAP_LIQUID_TYPE_DARK_WATER 0x10
417#define MAP_LIQUID_TYPE_WMO_WATER 0x20
419#define MAP_LIQUID_NO_TYPE 0x0001
420#define MAP_LIQUID_NO_HEIGHT 0x0002
436 return 255 / maxDiff;
441 return 65535 / maxDiff;
473 memset(
V9, 0,
sizeof(
V9));
474 memset(
V8, 0,
sizeof(
V8));
482 bool hasHoles =
false;
484 for (std::multimap<std::string, FileChunk*>::const_iterator itr = adt.
chunks.lower_bound(
"MCNK"); itr != adt.
chunks.upper_bound(
"MCNK"); ++itr)
569 if (liquid->
flags[y][x] != 0x0F)
572 if (liquid->
flags[y][x] & (1 << 7))
580 if (c_flag & (1 << 2))
585 if (c_flag & (1 << 3))
590 if (c_flag & (1 << 4))
597 fprintf(stderr,
"Wrong liquid detect in MCLQ chunk");
612 if (!(mcnk->
flags & 0x10000))
636 for (
int y = 0; y < h->
height; y++)
639 for (
int x = 0; x < h->
width; x++)
659 printf(
"\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->
liquidType, filename, i, j);
671 printf(
"Wrong liquid detect in MH2O chunk");
675 for (
int y = 0; y <= h->
height; y++)
678 for (
int x = 0; x <= h->
width; x++)
697 bool fullAreaData =
false;
716 areaHeader.
flags = 0;
731 float maxHeight = -20000;
732 float minHeight = 20000;
738 if (maxHeight < h) maxHeight = h;
739 if (minHeight > h) minHeight = h;
747 if (maxHeight < h) maxHeight = h;
748 if (minHeight > h) minHeight = h;
774 heightHeader.
flags = 0;
778 if (maxHeight == minHeight)
792 float diff = maxHeight - minHeight;
834 bool fullType =
false;
851 if (type == 0 && !fullType)
859 int minX = 255, minY = 255;
860 int maxX = 0, maxY = 0;
869 if (minX > x) minX = x;
870 if (maxX < x) maxX = x;
871 if (minY > y) minY = y;
872 if (maxY < y) maxY = y;
874 if (maxHeight < h) maxHeight = h;
875 if (minHeight > h) minHeight = h;
884 liquidHeader.
flags = 0;
888 liquidHeader.
width = maxX - minX + 1 + 1;
889 liquidHeader.
height = maxY - minY + 1 + 1;
892 if (maxHeight == minHeight)
922 FILE* output = fopen(filename2,
"wb");
925 printf(
"Can't create the output file '%s'\n", filename2);
928 fwrite(&map,
sizeof(map), 1, output);
930 fwrite(&areaHeader,
sizeof(areaHeader), 1, output);
935 fwrite(&heightHeader,
sizeof(heightHeader), 1, output);
950 fwrite(
V9,
sizeof(
V9), 1, output);
951 fwrite(
V8,
sizeof(
V8), 1, output);
958 fwrite(&liquidHeader,
sizeof(liquidHeader), 1, output);
967 for (
int y = 0; y < liquidHeader.
height; y++)
983 char mpq_filename[1024];
984 char output_filename[1024];
985 char mpq_map_name[1024];
987 printf(
"Extracting maps...\n");
998 printf(
"Convert map files\n");
1003 snprintf(mpq_map_name,
sizeof(mpq_map_name),
"World\\Maps\\%s\\%s.wdt",
map_ids[z].name,
map_ids[z].name);
1016 snprintf(mpq_filename,
sizeof(mpq_filename),
"World\\Maps\\%s\\%s_%u_%u.adt",
map_ids[z].name,
map_ids[z].name, x, y);
1017 snprintf(output_filename,
sizeof(output_filename),
"%s/maps/%04u_%02u_%02u.map",
output_path,
map_ids[z].
id, y, x);
1018 ConvertADT(mpq_filename, output_filename, y, x, build);
1022 printf(
"Processing........................%d%%\r", (100 * (y+1)) /
WDT_MAP_SIZE);
1033 FILE* output = fopen(filename,
"wb");
1036 printf(
"Can't create the output file '%s'\n", filename);
1040 char buffer[0x10000];
1041 DWORD readBytes = 1;
1043 while (readBytes > 0)
1045 SFileReadFile(fileInArchive, buffer,
sizeof(buffer), &readBytes, NULL);
1047 fwrite(buffer, 1, readBytes, output);
1056 printf(
"Extracting dbc files...\n");
1058 SFILE_FIND_DATA foundFile;
1059 memset(&foundFile, 0,
sizeof(foundFile));
1060 HANDLE listFile = SFileFindFirstFile(
LocaleMpq,
"DBFilesClient\\*dbc", &foundFile, NULL);
1061 HANDLE dbcFile = NULL;
1066 outputPath +=
"/dbc/";
1076 std::string filename;
1080 if (!SFileOpenFileEx(
LocaleMpq, foundFile.cFileName, SFILE_OPEN_FROM_MPQ, &dbcFile))
1082 printf(
"Unable to open file %s in the archive\n", foundFile.cFileName);
1086 filename = foundFile.cFileName;
1087 filename = outputPath + filename.substr(filename.rfind(
'\\') + 1);
1095 SFileCloseFile(dbcFile);
1096 }
while (SFileFindNextFile(listFile, &foundFile));
1098 SFileFindClose(listFile);
1101 printf(
"Extracted %u DBC files\n\n", count);
1106 printf(
"Extracting camera files...\n");
1108 if (!SFileOpenFileEx(
LocaleMpq,
"DBFilesClient\\CinematicCamera.dbc", SFILE_OPEN_FROM_MPQ, &dbcFile))
1110 printf(
"Fatal error: Cannot find CinematicCamera.dbc in archive!\n");
1118 printf(
"Unable to open CinematicCamera.dbc. Camera extract aborted.\n");
1123 std::vector<std::string> camerafiles;
1126 for (
size_t i = 0; i < cam_count; ++i)
1129 size_t loc = camFile.find(
".mdx");
1130 if (loc != std::string::npos)
1131 camFile.replace(loc, 4,
".m2");
1132 camerafiles.push_back(std::string(camFile));
1134 SFileCloseFile(dbcFile);
1137 path +=
"/cameras/";
1148 for (std::string thisFile : camerafiles)
1150 std::string filename = path;
1151 std::string camerasFolder =
"Cameras\\";
1152 HANDLE dbcFile = NULL;
1153 filename += (thisFile.c_str() + camerasFolder.length());
1158 if (!SFileOpenFileEx(
WorldMpq, thisFile.c_str(), SFILE_OPEN_FROM_MPQ, &dbcFile))
1160 printf(
"Unable to open file %s in the archive\n", thisFile.c_str());
1167 SFileCloseFile(dbcFile);
1169 printf(
"Extracted %u camera files\n", count);
1174 printf(
"Extracting db2 files...\n");
1176 SFILE_FIND_DATA foundFile;
1177 memset(&foundFile, 0,
sizeof(foundFile));
1178 HANDLE listFile = SFileFindFirstFile(
LocaleMpq,
"DBFilesClient\\*db2", &foundFile, NULL);
1179 HANDLE dbcFile = NULL;
1184 outputPath +=
"/db2/";
1194 std::string filename;
1198 if (!SFileOpenFileEx(
LocaleMpq, foundFile.cFileName, SFILE_OPEN_FROM_MPQ, &dbcFile))
1200 printf(
"Unable to open file %s in the archive\n", foundFile.cFileName);
1204 filename = foundFile.cFileName;
1205 filename = outputPath + filename.substr(filename.rfind(
'\\') + 1);
1209 SFileCloseFile(dbcFile);
1210 }
while (SFileFindNextFile(listFile, &foundFile));
1212 SFileFindClose(listFile);
1215 printf(
"Extracted %u DB2 files\n\n", count);
1221 char const* prefix =
"";
1223 memset(buff, 0,
sizeof(buff));
1224 _stprintf(buff, _T(
"%s/Data/misc.MPQ"),
input_path);
1225 if (!SFileOpenArchive(buff, 0, MPQ_OPEN_READ_ONLY, &
LocaleMpq))
1229 _tprintf(_T(
"\nLoading %s locale MPQs\n"),
LocalesT[locale]);
1230 _tprintf(_T(
"Cannot open archive %s\n"), buff);
1235 memset(buff, 0,
sizeof(buff));
1237 if (!SFileOpenPatchArchive(
LocaleMpq, buff, prefix, 0))
1239 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1240 _tprintf(_T(
"Cannot open patch archive %s\n"), buff);
1243 _tprintf(_T(
"\nLoading %s locale MPQs\n"),
LocalesT[locale]);
1244 _tprintf(_T(
"Cannot open archive %s\n"), buff);
1249 _tprintf(_T(
"\nLoading %s locale MPQs\n"),
LocalesT[locale]);
1253 memset(buff, 0,
sizeof(buff));
1255 _stprintf(buff, _T(
"%s/Data/wow-update-base-%u.MPQ"),
input_path,
Builds[i]);
1257 if (!SFileOpenPatchArchive(
LocaleMpq, buff, prefix, 0))
1260 _tprintf(_T(
"Cannot open patch archive %s\n"), buff);
1262 _tprintf(_T(
"Not found %s\n"), buff);
1266 _tprintf(_T(
"Loaded %s\n"), buff);
1271 memset(buff, 0,
sizeof(buff));
1275 if (!SFileOpenPatchArchive(
LocaleMpq, buff, prefix, 0))
1277 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1278 _tprintf(_T(
"Cannot open patch archive %s\n"), buff);
1282 _tprintf(_T(
"Loaded %s\n"), buff);
1287 memset(buff, 0,
sizeof(buff));
1289 _stprintf(buff, _T(
"%s/Data/Cache/patch-base-%u.MPQ"),
input_path,
Builds[i]);
1291 if (!SFileOpenPatchArchive(
LocaleMpq, buff, prefix, 0))
1293 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1294 _tprintf(_T(
"Cannot open patch archive %s\n"), buff);
1298 _tprintf(_T(
"Loaded %s\n"), buff);
1304 memset(buff, 0,
sizeof(buff));
1308 if (!SFileOpenPatchArchive(
LocaleMpq, buff, prefix, 0))
1310 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1311 _tprintf(_T(
"Cannot open patch archive %s\n"), buff);
1315 _tprintf(_T(
"Loaded %s\n"), buff);
1324 TCHAR filename[512];
1325 _stprintf(filename, _T(
"%s/Data/world.MPQ"),
input_path);
1326 _tprintf(_T(
"Loading common MPQ files\n"));
1327 if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &
WorldMpq))
1330 _tprintf(_T(
"Cannot open archive %s\n"), filename);
1334 _tprintf(_T(
"Loaded %s\n"), filename);
1337 for (
int i = 1; i < count; ++i)
1343 if (!SFileOpenPatchArchive(
WorldMpq, filename,
"", 0))
1346 _tprintf(_T(
"Cannot open archive %s\n"), filename);
1348 _tprintf(_T(
"Not found %s\n"), filename);
1351 _tprintf(_T(
"Loaded %s\n"), filename);
1354 char const* prefix = NULL;
1357 memset(filename, 0,
sizeof(filename));
1359 _stprintf(filename, _T(
"%s/Data/wow-update-base-%u.MPQ"),
input_path,
Builds[i]);
1361 if (!SFileOpenPatchArchive(
WorldMpq, filename, prefix, 0))
1364 _tprintf(_T(
"Cannot open patch archive %s\n"), filename);
1366 _tprintf(_T(
"Not found %s\n"), filename);
1370 _tprintf(_T(
"Loaded %s\n"), filename);
1375 memset(filename, 0,
sizeof(filename));
1377 _stprintf(filename, _T(
"%s/Data/Cache/patch-base-%u.MPQ"),
input_path,
Builds[i]);
1379 if (!SFileOpenPatchArchive(
WorldMpq, filename, prefix, 0))
1382 _tprintf(_T(
"Cannot open patch archive %s\n"), filename);
1384 _tprintf(_T(
"Not found %s\n"), filename);
1388 _tprintf(_T(
"Loaded %s\n"), filename);
1396 printf(
"Map & DBC Extractor\n");
1397 printf(
"===================\n");
1401 int FirstLocale = -1;
1410 printf(
"Unable to load %s locale archives!\n",
Locales[i]);
1414 printf(
"Detected locale: %s\n",
Locales[i]);
1421 printf(
"Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n",
Locales[i], build,
CONF_TargetBuild);
1425 printf(
"Detected client build: %u\n", build);
1432 printf(
"Detected client build %u for locale %s\n", tempBuild,
Locales[i]);
1436 printf(
"Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n",
Locales[i], tempBuild,
CONF_TargetBuild);
1444 if (FirstLocale < 0)
1454 if (FirstLocale < 0)
1456 printf(
"No locales detected\n");
1462 printf(
"Using locale: %s\n",
Locales[FirstLocale]);
1478 printf(
"Using locale: %s\n",
Locales[FirstLocale]);
#define MAP_LIQUID_TYPE_MAGMA
#define MAP_HEIGHT_AS_INT8
#define MAP_LIQUID_NO_TYPE
#define MAP_LIQUID_NO_HEIGHT
#define MAP_LIQUID_TYPE_WATER
#define MAP_LIQUID_TYPE_DARK_WATER
#define MAP_LIQUID_TYPE_OCEAN
#define MAP_LIQUID_TYPE_SLIME
#define MAP_HEIGHT_NO_HEIGHT
#define MAP_HEIGHT_AS_INT16
void ExtractDBCFiles(int l, bool basicLocale)
float selectUInt8StepStore(float maxDiff)
float CONF_float_to_int8_limit
uint16 uint16_V8[ADT_GRID_SIZE][ADT_GRID_SIZE]
uint16 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
bool CONF_allow_height_limit
void HandleArgs(int argc, char *arg[])
bool CONF_allow_float_to_int
bool ExtractFile(HANDLE fileInArchive, char const *filename)
static char const * MAP_AREA_MAGIC
#define ERROR_PATH_NOT_FOUND
void CreateDir(std::string const &path)
void LoadCommonMPQFiles(uint32 build)
bool LoadLocaleMPQFile(int locale)
uint16 uint16_V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
static char const * MAP_MAGIC
float CONF_flat_liquid_delta_limit
uint16 area_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
#define NEW_BASE_SET_BUILD
uint16 liquid_entry[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
float selectUInt16StepStore(float maxDiff)
static char const * MAP_LIQUID_MAGIC
float liquid_height[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
static char const * MAP_VERSION_MAGIC
void ExtractMapsFromMpq(uint32 build)
void ExtractDB2Files(int l, bool basicLocale)
uint8 liquid_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
float V8[ADT_GRID_SIZE][ADT_GRID_SIZE]
uint8 uint8_V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
int main(int argc, char *arg[])
uint32 ReadBuild(int locale)
void ReadLiquidTypeTableDBC()
void Usage(char const *prg)
TCHAR const * LocalesT[LOCALES_COUNT]
float V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
static char const * MAP_HEIGHT_MAGIC
float CONF_float_to_int16_limit
char const * CONF_mpq_list[]
bool FileExists(TCHAR const *fileName)
uint8 uint8_V8[ADT_GRID_SIZE][ADT_GRID_SIZE]
bool liquid_show[ADT_GRID_SIZE][ADT_GRID_SIZE]
bool ConvertADT(char *filename, char *filename2, int, int, uint32 build)
char const * Locales[LOCALES_COUNT]
void ExtractCameraFiles(int locale, bool basicLocale)
float CONF_flat_height_delta_limit
#define ADT_CELLS_PER_GRID
bool loadFile(HANDLE mpq, char *filename, bool log=true)
FileChunk * GetChunk(std::string const &name)
std::multimap< std::string, FileChunk * > chunks
char const * getString(size_t field) const
unsigned int getUInt(size_t field) const
Record getRecord(size_t id)
size_t getRecordCount() const
Trivial.
struct adt_MCLQ::liquid_data liquid[ADT_CELL_SIZE+1][ADT_CELL_SIZE+1]
uint8 flags[ADT_CELL_SIZE][ADT_CELL_SIZE]
float height_map[(ADT_CELL_SIZE+1) *(ADT_CELL_SIZE+1)+ADT_CELL_SIZE *ADT_CELL_SIZE]
uint64 getLiquidShowMap(adt_liquid_header *h)
adt_liquid_header * getLiquidData(int x, int y)
uint8 * getLiquidLightMap(adt_liquid_header *h)
float * getLiquidHeightMap(adt_liquid_header *h)
struct wdt_MAIN::adtData adt_list[64][64]