Tools/Extractors: Updated vmap_extractor for 6.0.2

This commit is contained in:
Shauren
2014-10-19 14:02:08 +02:00
parent ced4fc6347
commit 457c93bc4b
23 changed files with 225 additions and 324 deletions

View File

@@ -18,7 +18,7 @@ install:
- mysql -uroot -e 'create database test_mysql;'
- mkdir bin
- cd bin
- cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=0 -DSCRIPTS=1 -DSERVERS=1 -DNOJEM=1 -DCMAKE_BUILD_TYPE=Release
- cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS=1 -DSERVERS=1 -DNOJEM=1 -DCMAKE_BUILD_TYPE=Release
script:
- cd ..

View File

@@ -25,8 +25,8 @@
namespace VMAP
{
const char VMAP_MAGIC[] = "VMAP_4.1";
const char RAW_VMAP_MAGIC[] = "VMAP041"; // used in extracted vmap files with raw data
const char VMAP_MAGIC[] = "VMAP_4.2";
const char RAW_VMAP_MAGIC[] = "VMAP042"; // used in extracted vmap files with raw data
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
// defined in TileAssembler.cpp currently...

View File

@@ -38,7 +38,7 @@
#include "VMapFactory.h"
u_map_magic MapMagic = { {'M','A','P','S'} };
u_map_magic MapVersionMagic = { {'v','1','.','3'} };
u_map_magic MapVersionMagic = { {'v','1','.','4'} };
u_map_magic MapAreaMagic = { {'A','R','E','A'} };
u_map_magic MapHeightMagic = { {'M','H','G','T'} };
u_map_magic MapLiquidMagic = { {'M','L','I','Q'} };

View File

@@ -4630,7 +4630,7 @@ enum PartyResult
};
const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP'
#define MMAP_VERSION 5
#define MMAP_VERSION 6
struct MmapTileHeader
{

View File

@@ -18,9 +18,10 @@
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <cstdio>
#include <deque>
#include <list>
#include <set>
#include <cstdlib>
#include <cstring>
@@ -262,7 +263,7 @@ uint32 ReadMapDBC()
printf("Read Map.dbc file... ");
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, "DBFilesClient\\Map.dbc", CASC_LOCALE_ALL, 0, &dbcFile))
if (!CascOpenFile(CascStorage, "DBFilesClient\\Map.dbc", CASC_LOCALE_NONE, 0, &dbcFile))
{
printf("Fatal error: Cannot find Map.dbc in archive!\n");
exit(1);
@@ -292,7 +293,7 @@ void ReadAreaTableDBC()
{
printf("Read AreaTable.dbc file...");
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, "DBFilesClient\\AreaTable.dbc", CASC_LOCALE_ALL, 0, &dbcFile))
if (!CascOpenFile(CascStorage, "DBFilesClient\\AreaTable.dbc", CASC_LOCALE_NONE, 0, &dbcFile))
{
printf("Fatal error: Cannot find AreaTable.dbc in archive!\n");
exit(1);
@@ -320,7 +321,7 @@ void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
HANDLE dbcFile;
if (!CascOpenFile(CascStorage, "DBFilesClient\\LiquidType.dbc", CASC_LOCALE_ALL, 0, &dbcFile))
if (!CascOpenFile(CascStorage, "DBFilesClient\\LiquidType.dbc", CASC_LOCALE_NONE, 0, &dbcFile))
{
printf("Fatal error: Cannot find LiquidType.dbc in archive!\n");
exit(1);
@@ -351,7 +352,7 @@ void ReadLiquidTypeTableDBC()
// Map file format data
static char const* MAP_MAGIC = "MAPS";
static char const* MAP_VERSION_MAGIC = "v1.3";
static char const* MAP_VERSION_MAGIC = "v1.4";
static char const* MAP_AREA_MAGIC = "AREA";
static char const* MAP_HEIGHT_MAGIC = "MHGT";
static char const* MAP_LIQUID_MAGIC = "MLIQ";
@@ -440,7 +441,22 @@ uint16 liquid_entry[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
uint8 liquid_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
bool liquid_show[ADT_GRID_SIZE][ADT_GRID_SIZE];
float liquid_height[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1];
uint16 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID];
uint8 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID][8];
bool TransformToHighRes(uint16 holes, uint8 hiResHoles[8])
{
for (uint8 i = 0; i < 8; i++)
{
for (uint8 j = 0; j < 8; j++)
{
int32 holeIdxL = (i / 2) * 4 + (j / 2);
if (((holes >> holeIdxL) & 1) == 1)
hiResHoles[i] |= (1 << j);
}
}
return *((uint64*)hiResHoles) != 0;
}
bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, uint32 build)
{
@@ -599,10 +615,14 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
if (!(mcnk->flags & 0x10000))
{
if (uint16 hole = mcnk->holes)
{
holes[mcnk->iy][mcnk->ix] = mcnk->holes;
if (TransformToHighRes(hole, holes[mcnk->iy][mcnk->ix]))
hasHoles = true;
}
else
{
memcpy(holes[mcnk->iy][mcnk->ix], mcnk->union_5_3_0.HighResHoles, sizeof(uint64));
if (*((uint64*)holes[mcnk->iy][mcnk->ix]) != 0)
hasHoles = true;
}
}
}
@@ -965,6 +985,23 @@ bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/,
return true;
}
void ExtractWmos(ChunkedFile& file, std::set<std::string>& wmoList)
{
if (FileChunk* chunk = file.GetChunk("MWMO"))
{
file_MWMO* wmo = chunk->As<file_MWMO>();
if (wmo->size)
{
char* fileName = wmo->FileList;
while (fileName < wmo->FileList + wmo->size)
{
wmoList.insert(fileName);
fileName += strlen(fileName) + 1;
}
}
}
}
void ExtractMaps(uint32 build)
{
char storagePath[1024];
@@ -981,6 +1018,8 @@ void ExtractMaps(uint32 build)
path += "/maps/";
CreateDir(path);
std::set<std::string> wmoList;
printf("Convert map files\n");
for (uint32 z = 0; z < map_count; ++z)
{
@@ -991,6 +1030,8 @@ void ExtractMaps(uint32 build)
if (!wdt.loadFile(CascStorage, storagePath, false))
continue;
ExtractWmos(wdt, wmoList);
FileChunk* chunk = wdt.GetChunk("MAIN");
for (uint32 y = 0; y < WDT_MAP_SIZE; ++y)
{
@@ -1002,6 +1043,11 @@ void ExtractMaps(uint32 build)
sprintf(storagePath, "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(storagePath, output_filename, y, x, build);
sprintf(storagePath, "World\\Maps\\%s\\%s_%u_%u_obj0.adt", map_ids[z].name, map_ids[z].name, x, y);
ChunkedFile adtObj;
if (adtObj.loadFile(CascStorage, storagePath, false))
ExtractWmos(adtObj, wmoList);
}
// draw progress bar
@@ -1009,6 +1055,17 @@ void ExtractMaps(uint32 build)
}
}
if (!wmoList.empty())
{
if (FILE* wmoListFile = fopen("wmo_list.txt", "w"))
{
for (std::string const& wmo : wmoList)
fprintf(wmoListFile, "%s\n", wmo.c_str());
fclose(wmoListFile);
}
}
printf("\n");
delete[] areas;
delete[] map_ids;

View File

@@ -107,7 +107,7 @@ public:
uint32 offsMCVT; // height map
uint32 offsMCNR; // Normal vectors for each vertex
} offsets;
uint64 HighResHoles; // TODO: maybe use this?
uint8 HighResHoles[8];
} union_5_3_0;
uint32 offsMCLY; // Texture layer definitions
uint32 offsMCRF; // A list of indices into the parent file's MDDF chunk

View File

@@ -95,6 +95,7 @@ u_map_fcc InterestingChunks[] = {
{ 'O', '2', 'H', 'M' },
{ 'K', 'N', 'C', 'M' },
{ 'T', 'V', 'C', 'M' },
{ 'O', 'M', 'W', 'M' },
{ 'Q', 'L', 'C', 'M' }
};
@@ -113,10 +114,9 @@ void ChunkedFile::parseChunks()
while (ptr < GetData() + GetDataSize())
{
u_map_fcc header = *(u_map_fcc*)ptr;
uint32 size = 0;
if (IsInterestingChunk(header))
{
size = *(uint32*)(ptr + 4);
uint32 size = *(uint32*)(ptr + 4);
if (size <= data_size)
{
std::swap(header.fcc_txt[0], header.fcc_txt[3]);
@@ -126,10 +126,12 @@ void ChunkedFile::parseChunks()
chunk->parseSubChunks();
chunks.insert({ std::string(header.fcc_txt, 4), chunk });
}
}
// move to next chunk
ptr += size + 8;
// move to next chunk
ptr += size + 8;
}
else
++ptr;
}
}
@@ -156,10 +158,9 @@ void FileChunk::parseSubChunks()
while (ptr < data + size)
{
u_map_fcc header = *(u_map_fcc*)ptr;
uint32 subsize = 0;
if (IsInterestingChunk(header))
{
subsize = *(uint32*)(ptr + 4);
uint32 subsize = *(uint32*)(ptr + 4);
if (subsize < size)
{
std::swap(header.fcc_txt[0], header.fcc_txt[3]);
@@ -169,10 +170,12 @@ void FileChunk::parseSubChunks()
chunk->parseSubChunks();
subchunks.insert({ std::string(header.fcc_txt, 4), chunk });
}
}
// move to next chunk
ptr += subsize + 8;
// move to next chunk
ptr += subsize + 8;
}
else
++ptr;
}
}

View File

@@ -72,6 +72,12 @@ struct file_MVER
uint32 ver;
};
struct file_MWMO
{
u_map_fcc fcc;
uint32 size;
char FileList[1];
};
class FileChunk
{

View File

@@ -28,7 +28,7 @@
#include "DetourCommon.h"
#define MMAP_MAGIC 0x4d4d4150 // 'MMAP'
#define MMAP_VERSION 5
#define MMAP_VERSION 6
struct MmapTileHeader
{

View File

@@ -80,7 +80,7 @@ struct map_liquidHeader
namespace MMAP
{
char const* MAP_VERSION_MAGIC = "v1.3";
char const* MAP_VERSION_MAGIC = "v1.4";
TerrainBuilder::TerrainBuilder(bool skipLiquid) : m_skipLiquid (skipLiquid){ }
TerrainBuilder::~TerrainBuilder() { }
@@ -168,7 +168,7 @@ namespace MMAP
}
// data used later
uint16 holes[16][16];
uint8 holes[16][16][8];
memset(holes, 0, sizeof(holes));
uint8 liquid_type[16][16];
memset(liquid_type, 0, sizeof(liquid_type));
@@ -599,22 +599,17 @@ namespace MMAP
coord[2] = v[index2];
}
static uint16 holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
static uint16 holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
/**************************************************************************/
bool TerrainBuilder::isHole(int square, const uint16 holes[16][16])
bool TerrainBuilder::isHole(int square, uint8 const holes[16][16][8])
{
int row = square / 128;
int col = square % 128;
int cellRow = row / 8; // 8 squares per cell
int cellCol = col / 8;
int holeRow = row % 8 / 2;
int holeCol = (square - (row * 128 + cellCol * 8)) / 2;
int holeRow = row % 8;
int holeCol = (square - (row * 128 + cellCol * 8));
uint16 hole = holes[cellRow][cellCol];
return (hole & holetab_h[holeCol] & holetab_v[holeRow]) != 0;
return holes[cellRow][cellCol][holeRow] & (1 << holeCol);
}
/**************************************************************************/

View File

@@ -114,7 +114,7 @@ namespace MMAP
void getHeightTriangle(int square, Spot triangle, int* indices, bool liquid = false);
/// Determines if the specific position's triangles should be rendered
bool isHole(int square, const uint16 holes[16][16]);
bool isHole(int square, uint8 const holes[16][16][8]);
/// Get the liquid vector coordinate for a specific position
void getLiquidCoord(int index, int index2, float xOffset, float yOffset, float* coord, float* v);

View File

@@ -77,35 +77,19 @@ char* GetExtension(char* FileName)
return NULL;
}
extern HANDLE WorldMpq;
extern HANDLE CascStorage;
ADTFile::ADTFile(char* filename) : ADT(WorldMpq, filename, false)
ADTFile::ADTFile(char* filename) : ADT(CascStorage, filename, false)
{
Adtfilename.append(filename);
}
bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
{
if(ADT.isEof ())
if (ADT.isEof())
return false;
uint32 size;
string xMap;
string yMap;
Adtfilename.erase(Adtfilename.find(".adt"),4);
string TempMapNumber;
TempMapNumber = Adtfilename.substr(Adtfilename.length()-6,6);
xMap = TempMapNumber.substr(TempMapNumber.find("_")+1,(TempMapNumber.find_last_of("_")-1) - (TempMapNumber.find("_")));
yMap = TempMapNumber.substr(TempMapNumber.find_last_of("_")+1,(TempMapNumber.length()) - (TempMapNumber.find_last_of("_")));
Adtfilename.erase((Adtfilename.length()-xMap.length()-yMap.length()-2), (xMap.length()+yMap.length()+2));
//string AdtMapNumber = xMap + ' ' + yMap + ' ' + GetPlainName((char*)Adtfilename.c_str());
//printf("Processing map %s...\n", AdtMapNumber.c_str());
//printf("MapNumber = %s\n", TempMapNumber.c_str());
//printf("xMap = %s\n", xMap.c_str());
//printf("yMap = %s\n", yMap.c_str());
std::string dirname = std::string(szWorkDirWmo) + "/dir_bin";
FILE *dirfile;
dirfile = fopen(dirname.c_str(), "ab");
@@ -138,8 +122,6 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
char* buf = new char[size];
ADT.read(buf, size);
char* p = buf;
int t = 0;
ModelInstanceNames = new std::string[size];
while (p < buf + size)
{
std::string path(p);
@@ -148,7 +130,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
FixNameCase(s, strlen(s));
FixNameSpaces(s, strlen(s));
ModelInstanceNames[t++] = s;
ModelInstanceNames.push_back(s);
ExtractSingleModel(path);
@@ -164,15 +146,13 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
char* buf = new char[size];
ADT.read(buf, size);
char* p = buf;
int q = 0;
WmoInstanceNames = new std::string[size];
while (p < buf + size)
{
char* s = GetPlainName(p);
FixNameCase(s, strlen(s));
FixNameSpaces(s, strlen(s));
WmoInstanceNames[q++] = s;
WmoInstanceNames.push_back(s);
p += strlen(p) + 1;
}
@@ -191,8 +171,8 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
ADT.read(&id, 4);
ModelInstance inst(ADT, ModelInstanceNames[id].c_str(), map_num, tileX, tileY, dirfile);
}
delete[] ModelInstanceNames;
ModelInstanceNames = NULL;
ModelInstanceNames.clear();
}
}
else if (!strcmp(fourcc,"MODF"))
@@ -207,8 +187,7 @@ bool ADTFile::init(uint32 map_num, uint32 tileX, uint32 tileY)
WMOInstance inst(ADT, WmoInstanceNames[id].c_str(), map_num, tileX, tileY, dirfile);
}
delete[] WmoInstanceNames;
WmoInstanceNames = NULL;
WmoInstanceNames.clear();
}
}

View File

@@ -119,8 +119,8 @@ public:
~ADTFile();
int nWMO;
int nMDX;
std::string* WmoInstanceNames;
std::string* ModelInstanceNames;
std::vector<std::string> WmoInstanceNames;
std::vector<std::string> ModelInstanceNames;
bool init(uint32 map_num, uint32 tileX, uint32 tileY);
//void LoadMapChunks();

View File

@@ -27,14 +27,14 @@ DBCFile::DBCFile(HANDLE mpq, const char* filename) :
bool DBCFile::open()
{
if (!SFileOpenFileEx(_mpq, _filename, SFILE_OPEN_PATCHED_FILE, &_file))
if (!CascOpenFile(_mpq, _filename, CASC_LOCALE_NONE, 0, &_file))
return false;
char header[4];
unsigned int na, nb, es, ss;
DWORD readBytes = 0;
SFileReadFile(_file, header, 4, &readBytes, NULL);
CascReadFile(_file, header, 4, &readBytes);
if (readBytes != 4) // Number of records
return false;
@@ -42,22 +42,22 @@ bool DBCFile::open()
return false;
readBytes = 0;
SFileReadFile(_file, &na, 4, &readBytes, NULL);
CascReadFile(_file, &na, 4, &readBytes);
if (readBytes != 4) // Number of records
return false;
readBytes = 0;
SFileReadFile(_file, &nb, 4, &readBytes, NULL);
CascReadFile(_file, &nb, 4, &readBytes);
if (readBytes != 4) // Number of fields
return false;
readBytes = 0;
SFileReadFile(_file, &es, 4, &readBytes, NULL);
CascReadFile(_file, &es, 4, &readBytes);
if (readBytes != 4) // Size of a record
return false;
readBytes = 0;
SFileReadFile(_file, &ss, 4, &readBytes, NULL);
CascReadFile(_file, &ss, 4, &readBytes);
if (readBytes != 4) // String size
return false;
@@ -73,7 +73,7 @@ bool DBCFile::open()
size_t data_size = _recordSize * _recordCount + _stringSize;
readBytes = 0;
SFileReadFile(_file, _data, data_size, &readBytes, NULL);
CascReadFile(_file, _data, data_size, &readBytes);
if (readBytes != data_size)
return false;
@@ -84,7 +84,7 @@ DBCFile::~DBCFile()
{
delete [] _data;
if (_file != NULL)
SFileCloseFile(_file);
CascCloseFile(_file);
}
DBCFile::Record DBCFile::getRecord(size_t id)

View File

@@ -20,7 +20,7 @@
#define DBCFILE_H
#include <cassert>
#include <string>
#include "StormLib.h"
#include "CascLib.h"
class DBCFile
{

View File

@@ -52,18 +52,25 @@ bool ExtractSingleModel(std::string& fname)
return mdl.ConvertToVMAPModel(output.c_str());
}
extern HANDLE LocaleMpq;
extern HANDLE CascStorage;
void ExtractGameobjectModels()
{
printf("Extracting GameObject models...");
DBCFile dbc(LocaleMpq, "DBFilesClient\\GameObjectDisplayInfo.dbc");
DBCFile dbc(CascStorage, "DBFilesClient\\GameObjectDisplayInfo.dbc");
if(!dbc.open())
{
printf("Fatal error: Invalid GameObjectDisplayInfo.dbc file format!\n");
exit(1);
}
DBCFile fileData(CascStorage, "DBFilesClient\\FileData.dbc");
if (!fileData.open())
{
printf("Fatal error: Invalid FileData.dbc file format!\n");
exit(1);
}
std::string basepath = szWorkDirWmo;
basepath += "/";
std::string path;
@@ -76,9 +83,27 @@ void ExtractGameobjectModels()
return;
}
size_t maxFileId = fileData.getMaxId() + 1;
uint32* fileDataIndex = new uint32[maxFileId];
memset(fileDataIndex, 0, maxFileId * sizeof(uint32));
size_t files = fileData.getRecordCount();
for (uint32 i = 0; i < files; ++i)
fileDataIndex[fileData.getRecord(i).getUInt(0)] = i;
for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it)
{
path = it->getString(1);
uint32 fileId = it->getUInt(1);
if (!fileId)
continue;
uint32 fileIndex = fileDataIndex[fileId];
if (!fileIndex)
continue;
std::string filename = fileData.getRecord(fileIndex).getString(1);
std::string filepath = fileData.getRecord(fileIndex).getString(2);
path = filepath + filename;
if (path.length() < 4)
continue;
@@ -98,7 +123,7 @@ void ExtractGameobjectModels()
result = ExtractSingleWmo(path);
else if (!strcmp(ch_ext, ".mdl")) // TODO: extract .mdl files, if needed
continue;
else //if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2"))
else if (!strcmp(ch_ext, ".mdx") || !strcmp(ch_ext, ".m2"))
result = ExtractSingleModel(path);
if (result)
@@ -113,5 +138,7 @@ void ExtractGameobjectModels()
fclose(model_list);
delete[] fileDataIndex;
printf("Done!\n");
}

View File

@@ -24,7 +24,7 @@
#include <algorithm>
#include <cstdio>
extern HANDLE WorldMpq;
extern HANDLE CascStorage;
Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0)
{
@@ -33,7 +33,7 @@ Model::Model(std::string &filename) : filename(filename), vertices(0), indices(0
bool Model::open()
{
MPQFile f(WorldMpq, filename.c_str());
MPQFile f(CascStorage, filename.c_str());
if (f.isEof())
{

View File

@@ -1,7 +1,6 @@
#include "mpqfile.h"
#include <deque>
#include <cstdio>
#include "StormLib.h"
MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/) :
eof(false),
@@ -10,7 +9,7 @@ MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/)
size(0)
{
HANDLE file;
if (!SFileOpenFileEx(mpq, filename, SFILE_OPEN_PATCHED_FILE, &file))
if (!CascOpenFile(mpq, filename, CASC_LOCALE_ALL, 0, &file))
{
if (warnNoExist || GetLastError() != ERROR_FILE_NOT_FOUND)
fprintf(stderr, "Can't open %s, err=%u!\n", filename, GetLastError());
@@ -19,12 +18,12 @@ MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/)
}
DWORD hi = 0;
size = SFileGetFileSize(file, &hi);
size = CascGetFileSize(file, &hi);
if (hi)
{
fprintf(stderr, "Can't open %s, size[hi] = %u!\n", filename, uint32(hi));
SFileCloseFile(file);
CascCloseFile(file);
eof = true;
return;
}
@@ -32,22 +31,22 @@ MPQFile::MPQFile(HANDLE mpq, const char* filename, bool warnNoExist /*= true*/)
if (size <= 1)
{
fprintf(stderr, "Can't open %s, size = %u!\n", filename, uint32(size));
SFileCloseFile(file);
CascCloseFile(file);
eof = true;
return;
}
DWORD read = 0;
buffer = new char[size];
if (!SFileReadFile(file, buffer, size, &read) || size != read)
if (!CascReadFile(file, buffer, size, &read) || size != read)
{
fprintf(stderr, "Can't read %s, size=%u read=%u!\n", filename, uint32(size), uint32(read));
SFileCloseFile(file);
CascCloseFile(file);
eof = true;
return;
}
SFileCloseFile(file);
CascCloseFile(file);
}
size_t MPQFile::read(void* dest, size_t bytes)

View File

@@ -11,7 +11,7 @@
#include <vector>
#include <iostream>
#include <deque>
#include "StormLib.h"
#include "CascLib.h"
#ifdef _WIN32
#include <Windows.h> // mainly only HANDLE definition is required

View File

@@ -24,6 +24,7 @@
#include <errno.h>
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <sys/stat.h>
#include <direct.h>
@@ -33,13 +34,8 @@
#define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND
#endif
#undef min
#undef max
//#pragma warning(disable : 4505)
//#pragma comment(lib, "Winmm.lib")
#include <map>
#include <fstream>
//From Extractor
#include "adtfile.h"
@@ -57,51 +53,7 @@
//-----------------------------------------------------------------------------
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 15
char const* Locales[LOCALES_COUNT] =
{
"enGB", "enUS",
"deDE", "esES",
"frFR", "koKR",
"zhCN", "zhTW",
"enCN", "enTW",
"esMX", "ruRU",
"ptBR", "ptPT",
"itIT"
};
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"),
_T("ptBR"), _T("ptPT"),
_T("itIT"),
};
HANDLE CascStorage = NULL;
typedef struct
{
@@ -112,130 +64,28 @@ typedef struct
map_id * map_ids;
uint16 *LiqType = 0;
uint32 map_count;
char output_path[128]=".";
char input_path[1024]=".";
char output_path[128] = ".";
char input_path[1024] = ".";
bool preciseVectorData = false;
// Constants
//static const char * szWorkDirMaps = ".\\Maps";
const char* szWorkDirWmo = "./Buildings";
const char* szRawVMAPMagic = "VMAP041";
const char* szRawVMAPMagic = "VMAP042";
bool LoadLocaleMPQFile(int locale)
bool OpenCascStorage()
{
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 (!CascOpenStorage(".\\Data", 0, &CascStorage))
{
if (GetLastError() != ERROR_PATH_NOT_FOUND)
{
_tprintf(_T("Loading %s locale MPQs\n"), LocalesT[locale]);
_tprintf(_T("Cannot open archive %s\n"), buff);
}
printf("Error %d\n", GetLastError());
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)
@@ -262,7 +112,7 @@ void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
DBCFile dbc(LocaleMpq, "DBFilesClient\\LiquidType.dbc");
DBCFile dbc(CascStorage, "DBFilesClient\\LiquidType.dbc");
if(!dbc.open())
{
printf("Fatal error: Invalid LiquidType.dbc file format!\n");
@@ -282,23 +132,28 @@ void ReadLiquidTypeTableDBC()
bool ExtractWmo()
{
bool success = false;
bool success = true;
//const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"};
SFILE_FIND_DATA data;
HANDLE find = SFileFindFirstFile(WorldMpq, "*.wmo", &data, NULL);
if (find != NULL)
std::ifstream wmoList("wmo_list.txt");
if (!wmoList)
{
do
{
std::string str = data.cFileName;
//printf("Extracting wmo %s\n", str.c_str());
success |= ExtractSingleWmo(str);
}
while (SFileFindNextFile(find, &data));
printf("\nUnable to open wmo_list.txt! Nothing extracted.\n");
return false;
}
SFileFindClose(find);
std::set<std::string> wmos;
for (;;)
{
std::string str;
std::getline(wmoList, str);
if (str.empty())
break;
wmos.insert(std::move(str));
}
for (std::string str : wmos)
success &= ExtractSingleWmo(str);
if (success)
printf("\nExtract wmo complete (No (fatal) errors)\n");
@@ -463,11 +318,6 @@ 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;
@@ -475,14 +325,13 @@ bool processArgv(int argc, char ** argv, const char *versionString)
}
}
if(!result)
if (!result)
{
printf("Extract %s.\n",versionString);
printf("%s [-?][-s][-l][-d <path>]\n", argv[0]);
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");
}
@@ -492,7 +341,6 @@ bool processArgv(int argc, char ** argv, const char *versionString)
return result;
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Main
//
@@ -504,7 +352,7 @@ bool processArgv(int argc, char ** argv, const char *versionString)
int main(int argc, char ** argv)
{
bool success=true;
bool success = true;
const char *versionString = "V4.00 2012_02";
// Use command line arguments, when some
@@ -526,7 +374,7 @@ int main(int argc, char ** argv)
}
}
printf("Extract %s. Beginning work ....\n\n",versionString);
printf("Extract %s. Beginning work ....\n\n", versionString);
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// Create the working directory
if (mkdir(szWorkDirWmo
@@ -536,22 +384,16 @@ int main(int argc, char ** argv)
))
success = (errno == EEXIST);
LoadCommonMPQFiles(CONF_TargetBuild);
for (int i = 0; i < LOCALES_COUNT; ++i)
if (!OpenCascStorage())
{
//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;
if (GetLastError() != ERROR_PATH_NOT_FOUND)
printf("Unable to open storage!\n");
return 1;
}
// Extract models, listed in GameObjectDisplayInfo.dbc
ExtractGameobjectModels();
ReadLiquidTypeTableDBC();
// extract data
@@ -562,42 +404,38 @@ int main(int argc, char ** argv)
//map.dbc
if (success)
{
DBCFile * dbc = new DBCFile(LocaleMpq, "DBFilesClient\\Map.dbc");
DBCFile * dbc = new DBCFile(CascStorage, "DBFilesClient\\Map.dbc");
if (!dbc->open())
{
delete dbc;
printf("FATAL ERROR: Map.dbc not found in data file.\n");
return 1;
}
map_count=dbc->getRecordCount ();
map_ids=new map_id[map_count];
for (unsigned int x=0;x<map_count;++x)
{
map_ids[x].id=dbc->getRecord (x).getUInt(0);
strcpy(map_ids[x].name,dbc->getRecord(x).getString(1));
printf("Map - %s\n",map_ids[x].name);
}
map_count = dbc->getRecordCount();
map_ids = new map_id[map_count];
for (unsigned int x = 0; x < map_count; ++x)
{
map_ids[x].id = dbc->getRecord(x).getUInt(0);
strcpy(map_ids[x].name, dbc->getRecord(x).getString(1));
printf("Map - %s\n", map_ids[x].name);
}
delete dbc;
ParsMapFiles();
delete [] map_ids;
//nError = ERROR_SUCCESS;
// Extract models, listed in GameObjectDisplayInfo.dbc
ExtractGameobjectModels();
}
SFileCloseArchive(LocaleMpq);
SFileCloseArchive(WorldMpq);
CascCloseStorage(CascStorage);
printf("\n");
if (!success)
{
printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n",versionString, preciseVectorData);
printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n", versionString, preciseVectorData);
getchar();
}
printf("Extract %s. Work complete. No errors.\n",versionString);
printf("Extract %s. Work complete. No errors.\n", versionString);
delete [] LiqType;
return 0;
}

View File

@@ -30,9 +30,9 @@ char * wdtGetPlainName(char * FileName)
return FileName;
}
extern HANDLE WorldMpq;
extern HANDLE CascStorage;
WDTFile::WDTFile(char* file_name, char* file_name1):WDT(WorldMpq, file_name)
WDTFile::WDTFile(char* file_name, char* file_name1):WDT(CascStorage, file_name)
{
filename.append(file_name1,strlen(file_name1));
}
@@ -77,15 +77,13 @@ bool WDTFile::init(char* /*map_id*/, unsigned int mapID)
{
char *buf = new char[size];
WDT.read(buf, size);
char *p=buf;
int q = 0;
gWmoInstansName = new string[size];
char *p = buf;
while (p < buf + size)
{
char* s=wdtGetPlainName(p);
FixNameCase(s,strlen(s));
p=p+strlen(p)+1;
gWmoInstansName[q++] = s;
char* s = wdtGetPlainName(p);
FixNameCase(s, strlen(s));
p = p + strlen(p) + 1;
gWmoInstansName.push_back(s);
}
delete[] buf;
}
@@ -101,10 +99,8 @@ bool WDTFile::init(char* /*map_id*/, unsigned int mapID)
{
int id;
WDT.read(&id, 4);
WMOInstance inst(WDT,gWmoInstansName[id].c_str(), mapID, 65, 65, dirfile);
WMOInstance inst(WDT, gWmoInstansName[id].c_str(), mapID, 65, 65, dirfile);
}
delete[] gWmoInstansName;
}
}
WDT.seek((int)nextpos);

View File

@@ -22,7 +22,8 @@
#include "mpqfile.h"
#include "wmo.h"
#include <string>
#include "stdlib.h"
#include <vector>
#include <cstdlib>
class ADTFile;
@@ -30,13 +31,13 @@ class WDTFile
{
private:
MPQFile WDT;
string filename;
std::string filename;
public:
WDTFile(char* file_name, char* file_name1);
~WDTFile(void);
bool init(char* map_id, unsigned int mapID);
string* gWmoInstansName;
std::vector<std::string> gWmoInstansName;
int gnWMO;
ADTFile* GetMap(int x, int z);

View File

@@ -39,11 +39,11 @@ WMORoot::WMORoot(std::string &filename)
memset(bbcorn2, 0, sizeof(bbcorn2));
}
extern HANDLE WorldMpq;
extern HANDLE CascStorage;
bool WMORoot::open()
{
MPQFile f(WorldMpq, filename.c_str());
MPQFile f(CascStorage, filename.c_str());
if(f.isEof ())
{
printf("No such file.\n");
@@ -151,7 +151,7 @@ WMOGroup::WMOGroup(const std::string &filename) :
bool WMOGroup::open()
{
MPQFile f(WorldMpq, filename.c_str());
MPQFile f(CascStorage, filename.c_str());
if(f.isEof ())
{
printf("No such file.\n");