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
;
56 char output_path
[128]=".";
57 char input_path
[1024]=".";
58 bool hasInputPathParam
= false;
60 bool preciseVectorData
= false;
61 //char gamepath[1024];
64 //bool ConvertADT(char*,char*);
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
81 static const char * GetPlainName(const char * szFileName
)
85 if((szTemp
= strrchr(szFileName
, '\\')) != NULL
)
86 szFileName
= szTemp
+ 1;
89 //------------------------------------------------------------------------------
90 static void ShowProcessedFile(const char * szFileName
)
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
] = "";
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 (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
)
133 HANDLE hFind
= SFileFindFirstFile(hMpq
,"*.wmo*", &wf
, szListFile
);
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
));
143 if ((n
= fopen(szLocalFile
, "rb"))== NULL
)
146 //Select root wmo files
147 const char * rchr
= strrchr(GetPlainName(wf
.cFileName
),0x5f);
151 strncpy((char*)cpy
,rchr
,4);
152 for (int i
=0;i
<4;i
++)
161 //printf("RootWmo!\n");
162 string s
= wf
.cFileName
;
163 WMORoot
* froot
= new WMORoot(s
);
166 printf("Not open RootWmo!!!\n");
167 bResult
= SFileFindNextFile(hFind
, &wf
);
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
++)
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
);
188 printf("Not all open Group file for: %s\n",GetPlainName(wf
.cFileName
));
189 bResult
= SFileFindNextFile(hFind
, &wf
);
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
);
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
212 SFileFindClose(hFind
);
216 // Close both archives
218 //SFileCloseArchive(hMpq);
219 if(nError
== ERROR_SUCCESS
)
220 printf("\nExtract wmo complete (No errors)\n");
226 void ExtractMapsFromMpq()
230 //-----------------------------------------------------------------------------
234 char id_filename
[64];
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
);
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
);
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
);
270 for (int x
=0; x
<64; x
++)
272 for (int y
=0; y
<64; y
++)
274 if (ADTFile
*ADT
= WDT
.GetMap(x
,y
))
286 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
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
);
300 if (strlen(input_path
) > 0)
302 if (input_path
[strlen(input_path
) - 1] != '\\') strcat(input_path
, "\\");
304 strcat(input_path
,"Data\\");
306 strcpy(input_path
,"data/");
310 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
312 bool scan_patches(char* scanmatch
, std::vector
<std::string
>& pArchiveNames
)
316 std::list
<std::string
> matches
;
318 WIN32_FIND_DATA ffData
;
321 for (i
= 1; i
<= 99; i
++)
325 sprintf(path
, "%s-%d.mpq", scanmatch
, i
);
329 sprintf(path
, "%s.mpq", scanmatch
);
332 hFind
= INVALID_HANDLE_VALUE
;
333 hFind
= FindFirstFile(path
, &ffData
);
334 if (hFind
== INVALID_HANDLE_VALUE
) break;
337 matches
.push_back(path
);
341 for (std::list
<std::string
>::iterator i
= matches
.begin(); i
!= matches
.end(); i
++)
343 pArchiveNames
.push_back(i
->c_str());
351 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
353 bool fillArchiveNameVector(std::vector
<std::string
>& pArchiveNames
) {
354 //srand((unsigned int)time(0));
356 if(!hasInputPathParam
)
359 printf("\nGame path: %s\n", input_path
);
362 std::vector
<std::string
> locales
;
364 // scan game directories
365 WIN32_FIND_DATA ffData
;
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");
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();
395 if (dwError
!= ERROR_NO_MORE_FILES
)
397 printf("\nError reading data directory while scanning locales. Aborting.\n");
402 if (locales
.size() == 0)
404 printf("Sorry, no locales found. Aborting.\n");
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
);
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
);
443 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
444 // return false it normal processing can not proceed
446 bool processArgv(int argc
, char ** argv
, char*versionString
)
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) {
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
, "\\");
465 } else if(strcmp("-?",argv
[1]) == 0) {
467 } else if(strcmp("-l",argv
[i
]) == 0) {
468 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
;
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
541 if(nError
== ERROR_SUCCESS
)
543 DBCFile
* dbc
= new DBCFile("DBFilesClient\\Map.dbc");
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
);
557 nError
= ERROR_SUCCESS
;
561 if(nError
!= ERROR_SUCCESS
) {
562 printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n",versionString
, preciseVectorData
);
565 printf("Extract %s. Work complete. No errors.",versionString
);