[8423] Fixed typo in mangos.sql.
[getmangos.git] / contrib / vmap_extractor_v2 / vmapextract / vmapexport.cpp
bloba96a404f62d30c7fdd3ec9568993ceb00bfb9d71
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
49 char name[64];
50 unsigned int id;
51 }map_id;
53 map_id * map_ids;
54 uint16 * areas;
55 uint16 *areamax;
56 uint32 map_count;
57 char output_path[128]=".";
58 char input_path[1024]=".";
59 bool hasInputPathParam = false;
60 char tmp[512];
61 bool preciseVectorData = false;
62 //char gamepath[1024];
64 //Convert function
65 //bool ConvertADT(char*,char*);
67 // Constants
69 //static const char * szWorkDirMaps = ".\\Maps";
70 static const char * szWorkDirWmo = ".\\buildings";
72 //static LPBYTE pbBuffer1 = NULL;
73 //static LPBYTE pbBuffer2 = NULL;
75 // Local testing functions
77 static void clreol()
79 printf("\r \r");
82 static const char * GetPlainName(const char * szFileName)
84 const char * szTemp;
86 if((szTemp = strrchr(szFileName, '\\')) != NULL)
87 szFileName = szTemp + 1;
88 return szFileName;
91 static void ShowProcessedFile(const char * szFileName)
93 /* not truncate file names in output
94 char szLine[80];
95 size_t nLength = strlen(szFileName);
97 memset(szLine, 0x20, sizeof(szLine));
98 szLine[sizeof(szLine)-1] = 0;
100 if(nLength > sizeof(szLine)-1)
101 nLength = sizeof(szLine)-1;
102 memcpy(szLine, szFileName, nLength);
103 printf("\r%s\n", szLine);
105 printf("\r%s\n", szFileName);
108 int ExtractWmo()
110 char* szListFile = "";
111 char szLocalFile[MAX_PATH] = "";
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;
120 for (ArchiveSet::const_iterator ar_itr = gOpenArchives.archives.begin(); ar_itr != gOpenArchives.archives.end(); ++ar_itr)
122 // Copy files from archive
123 if(nError == ERROR_SUCCESS)
125 SFILE_FIND_DATA wf;
126 HANDLE hFind = SFileFindFirstFile(ar_itr->hMPQ,"*.wmo*", &wf, szListFile);
127 bResult = TRUE;
129 while(hFind != NULL && bResult == TRUE)
131 ShowProcessedFile(wf.cFileName);
132 SFileSetLocale(wf.lcLocale);
133 sprintf(szLocalFile, "%s\\%s", szWorkDirWmo, GetPlainName(wf.cFileName));
134 fixnamen(szLocalFile,strlen(szLocalFile));
135 FILE * n;
136 if ((n = fopen(szLocalFile, "rb"))== NULL)
138 int p = 0;
139 //Select root wmo files
140 const char * rchr = strrchr(GetPlainName(wf.cFileName),0x5f);
141 if(rchr != NULL)
143 char cpy[4];
144 strncpy((char*)cpy,rchr,4);
145 for (int i=0;i<4; ++i)
147 int m = cpy[i];
148 if(isdigit(m))
149 p++;
152 if(p != 3)
154 //printf("RootWmo!\n");
155 string s = wf.cFileName;
156 WMORoot * froot = new WMORoot(s);
157 if(!froot->open())
159 printf("Not open RootWmo!!!\n");
160 bResult = SFileFindNextFile(hFind, &wf);
161 continue;
163 FILE *output=fopen(szLocalFile,"wb");
164 froot->ConvertToVMAPRootWmo(output);
165 int Wmo_nVertices = 0;
166 if(froot->nGroups !=0)
168 for (int i=0; i<froot->nGroups; ++i)
170 char temp[MAX_PATH];
171 strcpy(temp, wf.cFileName);
172 temp[strlen(wf.cFileName)-4] = 0;
173 char groupFileName[MAX_PATH];
174 sprintf(groupFileName,"%s_%03d.wmo",temp, i);
175 printf("%s\n",groupFileName);
176 //printf("GroupWmo!\n");
177 string s = groupFileName;
178 WMOGroup * fgroup = new WMOGroup(s);
179 if(!fgroup->open())
181 printf("Not all open Group file for: %s\n",GetPlainName(wf.cFileName));
182 bResult = SFileFindNextFile(hFind, &wf);
183 break;
185 Wmo_nVertices += fgroup->ConvertToVMAPGroupWmo(output, preciseVectorData);
188 fseek(output, 8, SEEK_SET); // store the correct no of vertices
189 fwrite(&Wmo_nVertices,sizeof(int),1,output);
190 fclose(output);
193 else
195 fclose(n);
197 wf.dwFileFlags &= ~MPQ_FILE_HAS_EXTRA;
198 wf.dwFileFlags &= ~MPQ_FILE_EXISTS;
199 // Find the next file
200 bResult = SFileFindNextFile(hFind, &wf);
202 // Delete the extracted file in the case of an error
203 if(nError != ERROR_SUCCESS)
204 DeleteFile(szLocalFile);
205 // Close the search handle
206 if(hFind != NULL)
207 SFileFindClose(hFind);
211 if(nError == ERROR_SUCCESS)
212 printf("\nExtract wmo complete (No errors)\n");
214 return nError;
217 void ExtractMapsFromMpq()
221 void ParsMapFiles()
223 char fn[512];
224 char id_filename[64];
225 char id[10];
226 for (unsigned int i=0; i<map_count; ++i)
228 sprintf(id,"%03u",map_ids[i].id);
229 sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
230 WDTFile WDT(fn,map_ids[i].name);
231 if(WDT.init(id))
233 for (int x=0; x<64; ++x)
235 for (int y=0; y<64; ++y)
237 if (ADTFile*ADT = WDT.GetMap(x,y))
239 sprintf(id_filename,"%02u %02u %03u",x,y,map_ids[i].id);//!!!!!!!!!
240 ADT->init(id_filename);
241 delete ADT;
248 #if 0
249 void ParsMapFiles()
251 char fn[512];
252 for (unsigned int i=0; i<map_count; ++i)
254 sprintf(fn,"World\\Maps\\%s\\%s.wdt", map_ids[i].name, map_ids[i].name);
255 WDTFile WDT(fn,map_ids[i].name);
256 if(WDT.init())
258 for (int x=0; x<64; ++x)
260 for (int y=0; y<64; ++y)
262 if (ADTFile*ADT = WDT.GetMap(x,y))
264 ADT->init();
265 delete ADT;
272 #endif
274 void getGamePath()
276 #ifdef _WIN32
277 HKEY key;
278 DWORD t,s;
279 LONG l;
280 s = sizeof(input_path);
281 memset(input_path,0,s);
282 l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\World of Warcraft",0,KEY_QUERY_VALUE,&key);
283 //l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\Burning Crusade Closed Beta",0,KEY_QUERY_VALUE,&key);
284 l = RegQueryValueEx(key,"InstallPath",0,&t,(LPBYTE)input_path,&s);
285 RegCloseKey(key);
286 if (strlen(input_path) > 0)
288 if (input_path[strlen(input_path) - 1] != '\\') strcat(input_path, "\\");
290 strcat(input_path,"Data\\");
291 #else
292 strcpy(input_path,"data/");
293 #endif
296 bool scan_patches(char* scanmatch, std::vector<std::string>& pArchiveNames)
298 int i;
299 char path[512];
300 std::list<std::string> matches;
302 WIN32_FIND_DATA ffData;
303 HANDLE hFind;
305 for (i = 1; i <= 99; i++)
307 if (i != 1)
309 sprintf(path, "%s-%d.mpq", scanmatch, i);
311 else
313 sprintf(path, "%s.mpq", scanmatch);
316 hFind = INVALID_HANDLE_VALUE;
317 hFind = FindFirstFile(path, &ffData);
318 if (hFind == INVALID_HANDLE_VALUE) break;
319 FindClose(hFind);
321 matches.push_back(path);
324 matches.reverse();
325 for (std::list<std::string>::iterator i = matches.begin(); i != matches.end(); ++i)
327 pArchiveNames.push_back(i->c_str());
330 printf("\n");
332 return(true);
335 bool fillArchiveNameVector(std::vector<std::string>& pArchiveNames)
337 if(!hasInputPathParam)
338 getGamePath();
340 printf("\nGame path: %s\n", input_path);
342 char path[512];
343 std::vector<std::string> locales;
345 // scan game directories
346 WIN32_FIND_DATA ffData;
347 HANDLE hFind;
348 DWORD dwError;
350 // first, scan for locales (4-letter directories)
351 printf("Scanning for locales.\n");
352 sprintf(path, "%s*.*", input_path);
353 hFind = INVALID_HANDLE_VALUE;
354 hFind = FindFirstFile(path, &ffData);
355 if (hFind == INVALID_HANDLE_VALUE)
357 printf("\nCould not open data directory for reading. Aborting.\n");
358 return(false);
362 if (ffData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
364 if (ffData.cFileName[0] != '.')
366 if (strlen(ffData.cFileName) == 4)
368 printf("Found locale: %s\n", ffData.cFileName);
369 locales.push_back(ffData.cFileName);
373 } while (FindNextFile(hFind, &ffData) != 0);
374 dwError = GetLastError();
375 FindClose(hFind);
376 if (dwError != ERROR_NO_MORE_FILES)
378 printf("\nError reading data directory while scanning locales. Aborting.\n");
379 return(false);
381 printf("\n");
383 if (locales.size() == 0)
385 printf("Sorry, no locales found. Aborting.\n");
386 return(false);
389 // now, scan for the patch levels in the core dir
390 printf("Loading patch levels from data directory.\n");
391 sprintf(path, "%spatch", input_path);
392 if (!scan_patches(path, pArchiveNames))
393 return(false);
395 // now, scan for the patch levels in locale dirs
396 printf("Loading patch levels from locale directories.\n");
397 for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i)
399 printf("Locale: %s\n", i->c_str());
400 sprintf(path, "%s%s\\patch-%s", input_path, i->c_str(), i->c_str());
401 if (!scan_patches(path, pArchiveNames)) return(false);
404 // open expansion and common files
405 printf("Opening data files from data directory.\n");
406 sprintf(path, "%slichking.mpq", input_path);
407 pArchiveNames.push_back(path);
408 sprintf(path, "%scommon-2.mpq", input_path);
409 pArchiveNames.push_back(path);
410 sprintf(path, "%sexpansion.mpq", input_path);
411 pArchiveNames.push_back(path);
412 sprintf(path, "%scommon.mpq", input_path);
413 pArchiveNames.push_back(path);
414 printf("\n");
416 // open locale expansion and common files
417 printf("Opening data files from locale directories.\n");
418 for (std::vector<std::string>::iterator i = locales.begin(); i != locales.end(); ++i)
420 printf("Locale: %s\n", i->c_str());
421 sprintf(path, "%s%s\\lichking-locale-%s.mpq", input_path, i->c_str(), i->c_str());
422 pArchiveNames.push_back(path);
423 sprintf(path, "%s%s\\expansion-locale-%s.mpq", input_path, i->c_str(), i->c_str());
424 pArchiveNames.push_back(path);
425 sprintf(path, "%s%s\\locale-%s.mpq", input_path, i->c_str(), i->c_str());
426 pArchiveNames.push_back(path);
427 printf("\n");
429 return true;
432 bool processArgv(int argc, char ** argv, char*versionString)
434 bool result = true;
435 hasInputPathParam = false;
436 bool preciseVectorData = false;
438 for(int i=1; i< argc; ++i)
440 if(strcmp("-s",argv[i]) == 0)
442 preciseVectorData = false;
444 else if(strcmp("-d",argv[i]) == 0)
446 if((i+1)<argc)
448 hasInputPathParam = true;
449 strcpy(input_path, argv[i+1]);
450 if (input_path[strlen(input_path) - 1] != '\\' || input_path[strlen(input_path) - 1] != '/')
451 strcat(input_path, "\\");
452 ++i;
454 else
456 result = false;
459 else if(strcmp("-?",argv[1]) == 0)
461 result = false;
463 else if(strcmp("-l",argv[i]) == 0)
465 preciseVectorData = true;
467 else
469 result = false;
470 break;
473 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;
527 // prepare archive name list
528 std::vector<std::string> archiveNames;
529 fillArchiveNameVector(archiveNames);
530 if(!gOpenArchives.Open(archiveNames))
532 printf("FATAL ERROR: None MPQ archive found by path '%s'. Use -d option with proper path.\n",input_path);
533 return 1;
536 // extract data
537 ExtractWmo();
539 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
540 //map.dbc
541 if(nError == ERROR_SUCCESS)
543 DBCFile * dbc = new DBCFile("DBFilesClient\\Map.dbc");
544 if(!dbc->open())
546 delete dbc;
547 printf("FATAL ERROR: Map.dbc not found in data file.\n");
548 return 1;
550 map_count=dbc->getRecordCount ();
551 map_ids=new map_id[map_count];
552 for(unsigned int x=0;x<map_count;++x)
554 map_ids[x].id=dbc->getRecord (x).getUInt(0);
555 strcpy(map_ids[x].name,dbc->getRecord(x).getString(1));
556 printf("Map - %s\n",map_ids[x].name);
559 delete dbc;
560 ParsMapFiles();
561 delete [] map_ids;
562 nError = ERROR_SUCCESS;
565 clreol();
566 if(nError != ERROR_SUCCESS)
568 printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n",versionString, preciseVectorData);
569 _getch();
572 printf("Extract %s. Work complete. No errors.",versionString);