MaNGOS 0.12 release.
[getmangos.git] / contrib / vmap_extractor_v2 / vmapextract / vmapexport.cpp
blobdfc7cddcfdd4a5b262b2712a185b38144dfc47b3
1 /*****************************************************************************/
2 /* StormLibTest.cpp Copyright (c) Ladislav Zezula 2003 */
3 /*---------------------------------------------------------------------------*/
4 /* This module uses very brutal test methods for StormLib. It extracts all */
5 /* files from the archive with Storm.dll and with stormlib and compares them,*/
6 /* then tries to build a copy of the entire archive, then removes a few files*/
7 /* from the archive and adds them back, then compares the two archives, ... */
8 /*---------------------------------------------------------------------------*/
9 /* Date Ver Who Comment */
10 /* -------- ---- --- ------- */
11 /* 25.03.03 1.00 Lad The first version of StormLibTest.cpp */
12 /*****************************************************************************/
14 #define _CRT_SECURE_NO_DEPRECATE
15 #include <io.h>
16 #include <conio.h>
17 #include <stdio.h>
18 #include <windows.h>
19 #include <mmsystem.h>
20 #include <vector>
21 #include <list>
24 #define __STORMLIB_SELF__ // Don't use StormLib.lib
25 #include "StormLib.h"
27 #pragma warning(disable : 4505)
28 #pragma comment(lib, "Winmm.lib")
30 //From Extractor
31 #include "adtfile.h"
32 #include "wdtfile.h"
33 #include "dbcfile.h"
34 #include "mpq.h"
35 #include "wmo.h"
37 //------------------------------------------------------------------------------
38 // Defines
40 #define MPQ_BLOCK_SIZE 0x1000
42 //-----------------------------------------------------------------------------
43 // from extractor
44 typedef unsigned char uint8;
45 typedef unsigned short uint16;
46 typedef unsigned int uint32;
47 typedef struct{
48 char name[64];
49 unsigned int id;
50 }map_id;
52 map_id * map_ids;
53 uint16 * areas;
54 uint16 *areamax;
55 uint32 map_count;
56 char output_path[128]=".";
57 char input_path[1024]=".";
58 bool hasInputPathParam = false;
59 char tmp[512];
60 bool preciseVectorData = false;
61 //char gamepath[1024];
63 //Convert function
64 //bool ConvertADT(char*,char*);
66 // Constants
68 //static const char * szWorkDirMaps = ".\\Maps";
69 static const char * szWorkDirWmo = ".\\buildings";
71 //static LPBYTE pbBuffer1 = NULL;
72 //static LPBYTE pbBuffer2 = NULL;
74 // Local testing functions
76 static void clreol()
78 printf("\r \r");
81 static const char * GetPlainName(const char * szFileName)
83 const char * szTemp;
85 if((szTemp = strrchr(szFileName, '\\')) != NULL)
86 szFileName = szTemp + 1;
87 return szFileName;
89 //------------------------------------------------------------------------------
90 static void ShowProcessedFile(const char * szFileName)
92 char szLine[80];
93 size_t nLength = strlen(szFileName);
95 memset(szLine, 0x20, sizeof(szLine));
96 szLine[sizeof(szLine)-1] = 0;
98 if(nLength > sizeof(szLine)-1)
99 nLength = sizeof(szLine)-1;
100 memcpy(szLine, szFileName, nLength);
101 printf("\r%s\n", szLine);
105 //----------------------------------------------------------------------------------------------------------------------------------------------------------------------
106 int ExtractWmo(const std::vector<std::string>& pArchiveNames)
109 char* szListFile = "";
110 char szLocalFile[MAX_PATH] = "";
111 HANDLE hMpq = "";
112 BOOL bResult = FALSE;
114 //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"};
116 int nError = ERROR_SUCCESS;
117 if(szListFile == NULL || *szListFile == 0)
118 szListFile = NULL;
119 //char tmp[1024];
120 //for (size_t i=0; i<4; i++)
121 for (size_t i=0; i<pArchiveNames.size(); i++)
124 //sprintf(tmp,"%s\\%s", input_path, ParsArchiveNames[i]);
125 //if(!SFileOpenArchive(tmp, 0, 0, &hMpq))
126 if(!SFileOpenArchive(pArchiveNames[i].c_str(), 0, 0, &hMpq))
127 printf("NOT open!!! %s\n",pArchiveNames[i].c_str());
129 // Copy files from archive
130 if(nError == ERROR_SUCCESS)
132 SFILE_FIND_DATA wf;
133 HANDLE hFind = SFileFindFirstFile(hMpq,"*.wmo*", &wf, szListFile);
134 bResult = TRUE;
136 while(hFind != NULL && bResult == TRUE)
138 ShowProcessedFile(wf.cFileName);
139 SFileSetLocale(wf.lcLocale);
140 sprintf(szLocalFile, "%s\\%s", szWorkDirWmo, GetPlainName(wf.cFileName));
141 fixnamen(szLocalFile,strlen(szLocalFile));
142 FILE * n;
143 if ((n = fopen(szLocalFile, "rb"))== NULL)
145 int p = 0;
146 //Select root wmo files
147 const char * rchr = strrchr(GetPlainName(wf.cFileName),0x5f);
148 if(rchr != NULL)
150 char cpy[4];
151 strncpy((char*)cpy,rchr,4);
152 for (int i=0;i<4;i++)
154 int m = cpy[i];
155 if(isdigit(m))
156 p++;
159 if(p != 3)
161 //printf("RootWmo!\n");
162 string s = wf.cFileName;
163 WMORoot * froot = new WMORoot(s);
164 if(!froot->open())
166 printf("Not open RootWmo!!!\n");
167 bResult = SFileFindNextFile(hFind, &wf);
168 continue;
170 FILE *output=fopen(szLocalFile,"wb");
171 froot->ConvertToVMAPRootWmo(output);
172 int Wmo_nVertices = 0;
173 if(froot->nGroups !=0)
175 for (int i=0; i<froot->nGroups; i++)
177 char temp[512];
178 strcpy(temp, wf.cFileName);
179 temp[strlen(wf.cFileName)-4] = 0;
180 char groupFileName[512];
181 sprintf(groupFileName,"%s_%03d.wmo",temp, i);
182 printf("%s\n",groupFileName);
183 //printf("GroupWmo!\n");
184 string s = groupFileName;
185 WMOGroup * fgroup = new WMOGroup(s);
186 if(!fgroup->open())
188 printf("Not all open Group file for: %s\n",GetPlainName(wf.cFileName));
189 bResult = SFileFindNextFile(hFind, &wf);
190 break;
192 Wmo_nVertices += fgroup->ConvertToVMAPGroupWmo(output, preciseVectorData);
195 fseek(output, 8, SEEK_SET); // store the correct no of vertices
196 fwrite(&Wmo_nVertices,sizeof(int),1,output);
197 fclose(output);
199 } else {
200 fclose(n);
202 wf.dwFileFlags &= ~MPQ_FILE_HAS_EXTRA;
203 wf.dwFileFlags &= ~MPQ_FILE_EXISTS;
204 // Find the next file
205 bResult = SFileFindNextFile(hFind, &wf);
207 // Delete the extracted file in the case of an error
208 if(nError != ERROR_SUCCESS)
209 DeleteFile(szLocalFile);
210 // Close the search handle
211 if(hFind != NULL)
212 SFileFindClose(hFind);
216 // Close both archives
217 if(hMpq != NULL)
218 //SFileCloseArchive(hMpq);
219 if(nError == ERROR_SUCCESS)
220 printf("\nExtract wmo complete (No errors)\n");
222 return nError;
226 void ExtractMapsFromMpq()
230 //-----------------------------------------------------------------------------
231 void ParsMapFiles()
233 char fn[512];
234 char id_filename[64];
235 char id[10];
236 for (unsigned int i=0; i<map_count; i++)
238 sprintf(id,"%03u",map_ids[i].id);
239 sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
240 WDTFile WDT(fn,map_ids[i].name);
241 if(WDT.init(id))
243 for (int x=0; x<64; x++)
245 for (int y=0; y<64; y++)
247 if (ADTFile*ADT = WDT.GetMap(x,y))
249 sprintf(id_filename,"%02u %02u %03u",x,y,map_ids[i].id);//!!!!!!!!!
250 ADT->init(id_filename);
251 delete ADT;
259 #if 0
260 void ParsMapFiles()
263 char fn[512];
264 for (unsigned int i=0; i<map_count; i++)
266 sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
267 WDTFile WDT(fn,map_ids[i].name);
268 if(WDT.init())
270 for (int x=0; x<64; x++)
272 for (int y=0; y<64; y++)
274 if (ADTFile*ADT = WDT.GetMap(x,y))
276 ADT->init();
277 delete ADT;
285 #endif
286 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
288 void getGamePath()
290 #ifdef _WIN32
291 HKEY key;
292 DWORD t,s;
293 LONG l;
294 s = sizeof(input_path);
295 memset(input_path,0,s);
296 l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\World of Warcraft",0,KEY_QUERY_VALUE,&key);
297 //l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\Burning Crusade Closed Beta",0,KEY_QUERY_VALUE,&key);
298 l = RegQueryValueEx(key,"InstallPath",0,&t,(LPBYTE)input_path,&s);
299 RegCloseKey(key);
300 if (strlen(input_path) > 0)
302 if (input_path[strlen(input_path) - 1] != '\\') strcat(input_path, "\\");
304 strcat(input_path,"Data\\");
305 #else
306 strcpy(input_path,"data/");
307 #endif
310 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
312 bool scan_patches(char* scanmatch, std::vector<std::string>& pArchiveNames)
314 int i;
315 char path[512];
316 std::list<std::string> matches;
318 WIN32_FIND_DATA ffData;
319 HANDLE hFind;
321 for (i = 1; i <= 99; i++)
323 if (i != 1)
325 sprintf(path, "%s-%d.mpq", scanmatch, i);
327 else
329 sprintf(path, "%s.mpq", scanmatch);
332 hFind = INVALID_HANDLE_VALUE;
333 hFind = FindFirstFile(path, &ffData);
334 if (hFind == INVALID_HANDLE_VALUE) break;
335 FindClose(hFind);
337 matches.push_back(path);
340 matches.reverse();
341 for (std::list<std::string>::iterator i = matches.begin(); i != matches.end(); i++)
343 pArchiveNames.push_back(i->c_str());
346 printf("\n");
348 return(true);
351 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
353 bool fillArchiveNameVector(std::vector<std::string>& pArchiveNames) {
354 //srand((unsigned int)time(0));
356 if(!hasInputPathParam)
357 getGamePath();
359 printf("\nGame path: %s\n", input_path);
361 char path[512];
362 std::vector<std::string> locales;
364 // scan game directories
365 WIN32_FIND_DATA ffData;
366 HANDLE hFind;
367 DWORD dwError;
369 // first, scan for locales (4-letter directories)
370 printf("Scanning for locales.\n");
371 sprintf(path, "%s*.*", input_path);
372 hFind = INVALID_HANDLE_VALUE;
373 hFind = FindFirstFile(path, &ffData);
374 if (hFind == INVALID_HANDLE_VALUE)
376 printf("\nCould not open data directory for reading. Aborting.\n");
377 return(false);
381 if (ffData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
383 if (ffData.cFileName[0] != '.')
385 if (strlen(ffData.cFileName) == 4)
387 printf("Found locale: %s\n", ffData.cFileName);
388 locales.push_back(ffData.cFileName);
392 } while (FindNextFile(hFind, &ffData) != 0);
393 dwError = GetLastError();
394 FindClose(hFind);
395 if (dwError != ERROR_NO_MORE_FILES)
397 printf("\nError reading data directory while scanning locales. Aborting.\n");
398 return(false);
400 printf("\n");
402 if (locales.size() == 0)
404 printf("Sorry, no locales found. Aborting.\n");
405 return(false);
408 // now, scan for the patch levels in the core dir
409 printf("Loading patch levels from data directory.\n");
410 sprintf(path, "%spatch", input_path);
411 if (!scan_patches(path, pArchiveNames)) return(false);
413 // now, scan for the patch levels in locale dirs
414 printf("Loading patch levels from locale directories.\n");
415 for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); i++)
417 printf("Locale: %s\n", i->c_str());
418 sprintf(path, "%s%s\\patch-%s", input_path, i->c_str(), i->c_str());
419 if (!scan_patches(path, pArchiveNames)) return(false);
422 // open expansion and common files
423 printf("Opening data files from data directory.\n");
424 sprintf(path, "%sexpansion.mpq", input_path);
425 pArchiveNames.push_back(path);
426 sprintf(path, "%scommon.mpq", input_path);
427 pArchiveNames.push_back(path);
428 printf("\n");
430 // open locale expansion and common files
431 printf("Opening data files from locale directories.\n");
432 for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); i++)
434 printf("Locale: %s\n", i->c_str());
435 sprintf(path, "%s%s\\expansion-locale-%s.mpq", input_path, i->c_str(), i->c_str());
436 pArchiveNames.push_back(path);
437 sprintf(path, "%s%s\\locale-%s.mpq", input_path, i->c_str(), i->c_str());
438 pArchiveNames.push_back(path);
439 printf("\n");
441 return true;
443 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
444 // return false it normal processing can not proceed
446 bool processArgv(int argc, char ** argv, char*versionString)
448 bool result = true;
449 hasInputPathParam = false;
450 bool preciseVectorData = false;
452 for(int i=1; i< argc; ++i) {
453 if(strcmp("-s",argv[i]) == 0) {
454 preciseVectorData = false;
455 } else if(strcmp("-d",argv[i]) == 0) {
456 if((i+1)<argc) {
457 hasInputPathParam = true;
458 strcpy(input_path, argv[i+1]);
459 if (input_path[strlen(input_path) - 1] != '\\' || input_path[strlen(input_path) - 1] != '/')
460 strcat(input_path, "\\");
461 ++i;
462 } else {
463 result = false;
465 } else if(strcmp("-?",argv[1]) == 0) {
466 result = false;
467 } else if(strcmp("-l",argv[i]) == 0) {
468 preciseVectorData = true;
469 } else {
470 result = false;
471 break;
474 if(!result) {
475 printf("Extract %s.\n",versionString);
476 printf("%s [-?][-s][-l][-d <path>]\n", argv[0]);
477 printf(" -s : (default) small size (data size optimization), ~500MB less vmap data.\n");
478 printf(" -l : large size, ~500MB more vmap data. (might contain more details)\n");
479 printf(" -d <path>: Path to the vector data source folder.\n");
480 printf(" -? : This message.\n");
482 return result;
485 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
486 // Main
488 // The program must be run with two command line arguments
490 // Arg1 - The source MPQ name (for testing reading and file find)
491 // Arg2 - Listfile name
494 int main(int argc, char ** argv)
496 //char tmp[512];
497 // FILE* pDatei;
498 // char tmp[512];
499 // char tmp1[512];
500 //char tmp2[512];
501 // char tmp3[512];
502 // char tmp4[512];
503 // char szMpqName[MAX_PATH] = "";
504 // char szListFile[MAX_PATH] = "";
505 int nError = ERROR_SUCCESS;
506 char *versionString = "V2.4 2007_07_12";
508 // Use command line arguments, when some
509 if(!processArgv(argc, argv, versionString))
510 return 1;
512 printf("Extract %s. Beginning work ....\n",versionString);
513 // Set the lowest priority to allow running in the background
514 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
515 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
516 // Create the working directory
517 if(nError == ERROR_SUCCESS)
519 //if(!CreateDirectory(szWorkDirMaps, NULL))
520 // nError = GetLastError();
521 if(!CreateDirectory(szWorkDirWmo, NULL))
522 nError = GetLastError();
523 if(nError == ERROR_ALREADY_EXISTS)
524 nError = ERROR_SUCCESS;
526 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
527 // patch goes first -> fake priority handling
528 std::vector<MPQArchive*> archives;
530 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
531 std::vector<std::string> archiveNames;
533 fillArchiveNameVector(archiveNames);
534 for (size_t i=0; i<archiveNames.size(); i++) {
535 archives.push_back(new MPQArchive(archiveNames[i].c_str()));
537 ExtractWmo(archiveNames);
539 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
540 //map.dbc
541 if(nError == ERROR_SUCCESS)
543 DBCFile * dbc = new DBCFile("DBFilesClient\\Map.dbc");
544 dbc->open();
545 map_count=dbc->getRecordCount ();
546 map_ids=new map_id[map_count];
547 for(unsigned int x=0;x<map_count;x++)
549 map_ids[x].id=dbc->getRecord (x).getUInt(0);
550 strcpy(map_ids[x].name,dbc->getRecord(x).getString(1));
551 printf("Map - %s\n",map_ids[x].name);
554 delete dbc;
555 ParsMapFiles();
556 delete [] map_ids;
557 nError = ERROR_SUCCESS;
560 clreol();
561 if(nError != ERROR_SUCCESS) {
562 printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n",versionString, preciseVectorData);
563 _getch();
565 printf("Extract %s. Work complete. No errors.",versionString);