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
24 #define __STORMLIB_SELF__ // Don't use StormLib.lib
27 #pragma warning(disable : 4505)
28 #pragma comment(lib, "Winmm.lib")
37 //------------------------------------------------------------------------------
40 #define MPQ_BLOCK_SIZE 0x1000
42 //-----------------------------------------------------------------------------
44 typedef unsigned char uint8
;
45 typedef unsigned short uint16
;
46 typedef unsigned int uint32
;
57 char output_path
[128]=".";
58 char input_path
[1024]=".";
59 bool hasInputPathParam
= false;
61 bool preciseVectorData
= false;
62 //char gamepath[1024];
65 //bool ConvertADT(char*,char*);
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
82 static const char * GetPlainName(const char * szFileName
)
86 if((szTemp
= strrchr(szFileName
, '\\')) != NULL
)
87 szFileName
= szTemp
+ 1;
91 static void ShowProcessedFile(const char * szFileName
)
93 /* not truncate file names in output
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
);
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)
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
)
126 HANDLE hFind
= SFileFindFirstFile(ar_itr
->hMPQ
,"*.wmo*", &wf
, szListFile
);
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
));
136 if ((n
= fopen(szLocalFile
, "rb"))== NULL
)
139 //Select root wmo files
140 const char * rchr
= strrchr(GetPlainName(wf
.cFileName
),0x5f);
144 strncpy((char*)cpy
,rchr
,4);
145 for (int i
=0;i
<4; ++i
)
154 //printf("RootWmo!\n");
155 string s
= wf
.cFileName
;
156 WMORoot
* froot
= new WMORoot(s
);
159 printf("Not open RootWmo!!!\n");
160 bResult
= SFileFindNextFile(hFind
, &wf
);
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
)
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
);
181 printf("Not all open Group file for: %s\n",GetPlainName(wf
.cFileName
));
182 bResult
= SFileFindNextFile(hFind
, &wf
);
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
);
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
207 SFileFindClose(hFind
);
211 if(nError
== ERROR_SUCCESS
)
212 printf("\nExtract wmo complete (No errors)\n");
217 void ExtractMapsFromMpq()
224 char id_filename
[64];
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
);
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
);
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
);
258 for (int x
=0; x
<64; ++x
)
260 for (int y
=0; y
<64; ++y
)
262 if (ADTFile
*ADT
= WDT
.GetMap(x
,y
))
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
);
286 if (strlen(input_path
) > 0)
288 if (input_path
[strlen(input_path
) - 1] != '\\') strcat(input_path
, "\\");
290 strcat(input_path
,"Data\\");
292 strcpy(input_path
,"data/");
296 bool scan_patches(char* scanmatch
, std::vector
<std::string
>& pArchiveNames
)
300 std::list
<std::string
> matches
;
302 WIN32_FIND_DATA ffData
;
305 for (i
= 1; i
<= 99; i
++)
309 sprintf(path
, "%s-%d.mpq", scanmatch
, i
);
313 sprintf(path
, "%s.mpq", scanmatch
);
316 hFind
= INVALID_HANDLE_VALUE
;
317 hFind
= FindFirstFile(path
, &ffData
);
318 if (hFind
== INVALID_HANDLE_VALUE
) break;
321 matches
.push_back(path
);
325 for (std::list
<std::string
>::iterator i
= matches
.begin(); i
!= matches
.end(); ++i
)
327 pArchiveNames
.push_back(i
->c_str());
335 bool fillArchiveNameVector(std::vector
<std::string
>& pArchiveNames
)
337 if(!hasInputPathParam
)
340 printf("\nGame path: %s\n", input_path
);
343 std::vector
<std::string
> locales
;
345 // scan game directories
346 WIN32_FIND_DATA ffData
;
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");
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();
376 if (dwError
!= ERROR_NO_MORE_FILES
)
378 printf("\nError reading data directory while scanning locales. Aborting.\n");
383 if (locales
.size() == 0)
385 printf("Sorry, no locales found. Aborting.\n");
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
))
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
);
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
);
432 bool processArgv(int argc
, char ** argv
, char*versionString
)
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)
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
, "\\");
459 else if(strcmp("-?",argv
[1]) == 0)
463 else if(strcmp("-l",argv
[i
]) == 0)
465 preciseVectorData
= true;
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");
485 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
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
)
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
))
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
);
539 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
541 if(nError
== ERROR_SUCCESS
)
543 DBCFile
* dbc
= new DBCFile("DBFilesClient\\Map.dbc");
547 printf("FATAL ERROR: Map.dbc not found in data file.\n");
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
);
562 nError
= ERROR_SUCCESS
;
566 if(nError
!= ERROR_SUCCESS
)
568 printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n",versionString
, preciseVectorData
);
572 printf("Extract %s. Work complete. No errors.",versionString
);