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]=".";
59 bool preciseVectorData
= true;
60 //char gamepath[1024];
63 //bool ConvertADT(char*,char*);
67 //static const char * szWorkDirMaps = ".\\Maps";
68 static const char * szWorkDirWmo
= ".\\buildings";
70 //static LPBYTE pbBuffer1 = NULL;
71 //static LPBYTE pbBuffer2 = NULL;
73 // Local testing functions
80 static const char * GetPlainName(const char * szFileName
)
84 if((szTemp
= strrchr(szFileName
, '\\')) != NULL
)
85 szFileName
= szTemp
+ 1;
88 //------------------------------------------------------------------------------
89 static void ShowProcessedFile(const char * szFileName
)
92 size_t nLength
= strlen(szFileName
);
94 memset(szLine
, 0x20, sizeof(szLine
));
95 szLine
[sizeof(szLine
)-1] = 0;
97 if(nLength
> sizeof(szLine
)-1)
98 nLength
= sizeof(szLine
)-1;
99 memcpy(szLine
, szFileName
, nLength
);
100 printf("\r%s\n", szLine
);
104 //----------------------------------------------------------------------------------------------------------------------------------------------------------------------
105 int ExtractWmo(const std::vector
<std::string
>& pArchiveNames
)
108 char* szListFile
= "";
109 char szLocalFile
[MAX_PATH
] = "";
111 BOOL bResult
= FALSE
;
113 //const char* ParsArchiveNames[] = {"patch-2.MPQ", "patch.MPQ", "common.MPQ", "expansion.MPQ"};
115 int nError
= ERROR_SUCCESS
;
116 if(szListFile
== NULL
|| *szListFile
== 0)
119 //for (size_t i=0; i<4; i++)
120 for (size_t i
=0; i
<pArchiveNames
.size(); i
++)
123 //sprintf(tmp,"%s\\%s", input_path, ParsArchiveNames[i]);
124 //if(!SFileOpenArchive(tmp, 0, 0, &hMpq))
125 if(!SFileOpenArchive(pArchiveNames
[i
].c_str(), 0, 0, &hMpq
))
126 printf("NOT open!!! %s\n",pArchiveNames
[i
].c_str());
128 // Copy files from archive
129 if(nError
== ERROR_SUCCESS
)
132 HANDLE hFind
= SFileFindFirstFile(hMpq
,"*.wmo*", &wf
, szListFile
);
135 while(hFind
!= NULL
&& bResult
== TRUE
)
137 ShowProcessedFile(wf
.cFileName
);
138 SFileSetLocale(wf
.lcLocale
);
139 sprintf(szLocalFile
, "%s\\%s", szWorkDirWmo
, GetPlainName(wf
.cFileName
));
140 fixnamen(szLocalFile
,strlen(szLocalFile
));
142 if ((n
= fopen(szLocalFile
, "rb"))== NULL
)
145 //Select root wmo files
146 const char * rchr
= strrchr(GetPlainName(wf
.cFileName
),0x5f);
150 strncpy((char*)cpy
,rchr
,4);
151 for (int i
=0;i
<4;i
++)
160 //printf("RootWmo!\n");
161 string s
= wf
.cFileName
;
162 WMORoot
* froot
= new WMORoot(s
);
165 printf("Not open RootWmo!!!\n");
166 bResult
= SFileFindNextFile(hFind
, &wf
);
169 FILE *output
=fopen(szLocalFile
,"wb");
170 froot
->ConvertToVMAPRootWmo(output
);
171 int Wmo_nVertices
= 0;
172 if(froot
->nGroups
!=0)
174 for (int i
=0; i
<froot
->nGroups
; i
++)
177 strcpy(temp
, wf
.cFileName
);
178 temp
[strlen(wf
.cFileName
)-4] = 0;
179 char groupFileName
[512];
180 sprintf(groupFileName
,"%s_%03d.wmo",temp
, i
);
181 printf("%s\n",groupFileName
);
182 //printf("GroupWmo!\n");
183 string s
= groupFileName
;
184 WMOGroup
* fgroup
= new WMOGroup(s
);
187 printf("Not all open Group file for: %s\n",GetPlainName(wf
.cFileName
));
188 bResult
= SFileFindNextFile(hFind
, &wf
);
191 Wmo_nVertices
+= fgroup
->ConvertToVMAPGroupWmo(output
, preciseVectorData
);
194 fseek(output
, 8, SEEK_SET
); // store the correct no of vertices
195 fwrite(&Wmo_nVertices
,sizeof(int),1,output
);
201 wf
.dwFileFlags
&= ~MPQ_FILE_HAS_EXTRA
;
202 wf
.dwFileFlags
&= ~MPQ_FILE_EXISTS
;
203 // Find the next file
204 bResult
= SFileFindNextFile(hFind
, &wf
);
206 // Delete the extracted file in the case of an error
207 if(nError
!= ERROR_SUCCESS
)
208 DeleteFile(szLocalFile
);
209 // Close the search handle
211 SFileFindClose(hFind
);
215 // Close both archives
217 //SFileCloseArchive(hMpq);
218 if(nError
== ERROR_SUCCESS
)
219 printf("\nExtract wmo complete (No errors)\n");
225 void ExtractMapsFromMpq()
229 //-----------------------------------------------------------------------------
233 char id_filename
[64];
235 for (unsigned int i
=0; i
<map_count
; i
++)
237 sprintf(id
,"%03u",map_ids
[i
].id
);
238 sprintf(fn
,"World\\Maps\\%s\\%s.wdt", map_ids
[i
].name
, map_ids
[i
].name
);
239 WDTFile
WDT(fn
,map_ids
[i
].name
);
242 for (int x
=0; x
<64; x
++)
244 for (int y
=0; y
<64; y
++)
246 if (ADTFile
*ADT
= WDT
.GetMap(x
,y
))
248 sprintf(id_filename
,"%02u %02u %03u",x
,y
,map_ids
[i
].id
);//!!!!!!!!!
249 ADT
->init(id_filename
);
263 for (unsigned int i
=0; i
<map_count
; i
++)
265 sprintf(fn
,"World\\Maps\\%s\\%s.wdt", map_ids
[i
].name
, map_ids
[i
].name
);
266 WDTFile
WDT(fn
,map_ids
[i
].name
);
269 for (int x
=0; x
<64; x
++)
271 for (int y
=0; y
<64; y
++)
273 if (ADTFile
*ADT
= WDT
.GetMap(x
,y
))
285 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
293 s
= sizeof(input_path
);
294 memset(input_path
,0,s
);
295 l
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,"SOFTWARE\\Blizzard Entertainment\\World of Warcraft",0,KEY_QUERY_VALUE
,&key
);
296 //l = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SOFTWARE\\Blizzard Entertainment\\Burning Crusade Closed Beta",0,KEY_QUERY_VALUE,&key);
297 l
= RegQueryValueEx(key
,"InstallPath",0,&t
,(LPBYTE
)input_path
,&s
);
299 if (strlen(input_path
) > 0)
301 if (input_path
[strlen(input_path
) - 1] != '\\') strcat(input_path
, "\\");
303 strcat(input_path
,"Data\\");
305 strcpy(input_path
,"data/");
309 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
311 bool scan_patches(char* scanmatch
, std::vector
<std::string
>& pArchiveNames
)
315 std::list
<std::string
> matches
;
317 WIN32_FIND_DATA ffData
;
320 for (i
= 1; i
<= 99; i
++)
324 sprintf(path
, "%s-%d.mpq", scanmatch
, i
);
328 sprintf(path
, "%s.mpq", scanmatch
);
331 hFind
= INVALID_HANDLE_VALUE
;
332 hFind
= FindFirstFile(path
, &ffData
);
333 if (hFind
== INVALID_HANDLE_VALUE
) break;
336 matches
.push_back(path
);
340 for (std::list
<std::string
>::iterator i
= matches
.begin(); i
!= matches
.end(); i
++)
342 pArchiveNames
.push_back(i
->c_str());
350 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
352 bool fillArchiveNameVector(std::vector
<std::string
>& pArchiveNames
) {
353 //srand((unsigned int)time(0));
357 printf("\nGame path: %s\n", input_path
);
360 std::vector
<std::string
> locales
;
362 // scan game directories
363 WIN32_FIND_DATA ffData
;
367 // first, scan for locales (4-letter directories)
368 printf("Scanning for locales.\n");
369 sprintf(path
, "%s*.*", input_path
);
370 hFind
= INVALID_HANDLE_VALUE
;
371 hFind
= FindFirstFile(path
, &ffData
);
372 if (hFind
== INVALID_HANDLE_VALUE
)
374 printf("\nCould not open data directory for reading. Aborting.\n");
379 if (ffData
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
381 if (ffData
.cFileName
[0] != '.')
383 if (strlen(ffData
.cFileName
) == 4)
385 printf("Found locale: %s\n", ffData
.cFileName
);
386 locales
.push_back(ffData
.cFileName
);
390 } while (FindNextFile(hFind
, &ffData
) != 0);
391 dwError
= GetLastError();
393 if (dwError
!= ERROR_NO_MORE_FILES
)
395 printf("\nError reading data directory while scanning locales. Aborting.\n");
400 if (locales
.size() == 0)
402 printf("Sorry, no locales found. Aborting.\n");
406 // now, scan for the patch levels in the core dir
407 printf("Loading patch levels from data directory.\n");
408 sprintf(path
, "%spatch", input_path
);
409 if (!scan_patches(path
, pArchiveNames
)) return(false);
411 // now, scan for the patch levels in locale dirs
412 printf("Loading patch levels from locale directories.\n");
413 for (std::vector
<std::string
>::iterator i
= locales
.begin(); i
!= locales
.end(); i
++)
415 printf("Locale: %s\n", i
->c_str());
416 sprintf(path
, "%s%s\\patch-%s", input_path
, i
->c_str(), i
->c_str());
417 if (!scan_patches(path
, pArchiveNames
)) return(false);
420 // open expansion and common files
421 printf("Opening data files from data directory.\n");
422 sprintf(path
, "%sexpansion.mpq", input_path
);
423 pArchiveNames
.push_back(path
);
424 sprintf(path
, "%scommon.mpq", input_path
);
425 pArchiveNames
.push_back(path
);
428 // open locale expansion and common files
429 printf("Opening data files from locale directories.\n");
430 for (std::vector
<std::string
>::iterator i
= locales
.begin(); i
!= locales
.end(); i
++)
432 printf("Locale: %s\n", i
->c_str());
433 sprintf(path
, "%s%s\\expansion-locale-%s.mpq", input_path
, i
->c_str(), i
->c_str());
434 pArchiveNames
.push_back(path
);
435 sprintf(path
, "%s%s\\locale-%s.mpq", input_path
, i
->c_str(), i
->c_str());
436 pArchiveNames
.push_back(path
);
444 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
447 // The program must be run with two command line arguments
449 // Arg1 - The source MPQ name (for testing reading and file find)
450 // Arg2 - Listfile name
453 int main(int argc
, char ** argv
)
462 char szMpqName
[MAX_PATH
] = "";
463 char szListFile
[MAX_PATH
] = "";
464 int nError
= ERROR_SUCCESS
;
465 char *versionString
= "V2.3 2007_07_08";
467 // Use command line arguments, when some
469 if(strcmp("-s",argv
[1]) == 0) {
470 preciseVectorData
= false;
471 } else if(strcmp("-?",argv
[1]) == 0) {
472 printf("Extract %s.\n",versionString
);
473 printf("%s [-s]\n -s : small size (data size optimization, less precise), Will create about 500MB less vmap data.\n", argv
[0]);
477 printf("Extract %s. Beginning work ....\n",versionString
);
478 printf("Flags:\n -s : small size (data size optimization, less precise), Will create about 500MB less vmap data.\n");
479 // Set the lowest priority to allow running in the background
480 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL
);
481 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
482 // Create the working directory
483 if(nError
== ERROR_SUCCESS
)
485 //if(!CreateDirectory(szWorkDirMaps, NULL))
486 // nError = GetLastError();
487 if(!CreateDirectory(szWorkDirWmo
, NULL
))
488 nError
= GetLastError();
489 if(nError
== ERROR_ALREADY_EXISTS
)
490 nError
= ERROR_SUCCESS
;
492 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
493 // patch goes first -> fake priority handling
494 std::vector
<MPQArchive
*> archives
;
496 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
497 std::vector
<std::string
> archiveNames
;
499 fillArchiveNameVector(archiveNames
);
500 for (size_t i
=0; i
<archiveNames
.size(); i
++) {
501 archives
.push_back(new MPQArchive(archiveNames
[i
].c_str()));
503 ExtractWmo(archiveNames
);
505 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
507 if(nError
== ERROR_SUCCESS
)
509 DBCFile
* dbc
= new DBCFile("DBFilesClient\\Map.dbc");
511 map_count
=dbc
->getRecordCount ();
512 map_ids
=new map_id
[map_count
];
513 for(unsigned int x
=0;x
<map_count
;x
++)
515 map_ids
[x
].id
=dbc
->getRecord (x
).getUInt(0);
516 strcpy(map_ids
[x
].name
,dbc
->getRecord(x
).getString(1));
517 printf("Map - %s\n",map_ids
[x
].name
);
523 nError
= ERROR_SUCCESS
;
527 if(nError
!= ERROR_SUCCESS
) {
528 printf("ERROR: Extract %s. Work NOT complete.\n Precise vector data=%d.\nPress any key.\n",versionString
, preciseVectorData
);
531 printf("Extract %s. Work complete.\n Precise vector data=%d.\nNo errors.",versionString
, preciseVectorData
);