* implemented partial(=faster) ADT texture, model & wmo loading.

* stuffextract does now extract all files referenced in ADTs.
* some adt loading fixes to be able to load expansion maps at least partially.
* fixed typos
This commit is contained in:
False.Genesis 2007-05-23 17:25:16 +00:00
parent d50ea1c7a2
commit de2614fa80
5 changed files with 194 additions and 12 deletions

View File

@ -257,7 +257,7 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
else else
{ {
DEBUG(printf("ADT: MCNK: '%s' block unhandled, skipping %u bytes\n",mfcc,msize)); DEBUG(printf("ADT: MCNK: '%s' block unhandled, skipping %u bytes\n",mfcc,msize));
if(strcmp((char*)mfcc,"MCRF")) if(!(isalnum(mfcc[0]) && isalnum(mfcc[1]) && isalnum(mfcc[2]) && isalnum(mfcc[3])))
{ {
printf("Error loading ADT file (chunk %u error).\n",mcnkid); printf("Error loading ADT file (chunk %u error).\n",mcnkid);
return false; // dont care about those few mem leaks return false; // dont care about those few mem leaks
@ -271,9 +271,9 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
mcnkid++; mcnkid++;
} }
else else
{ {
DEBUG(printf("ADT: '%s' block unhandled, skipping %u bytes\n",fourcc,size)); DEBUG(printf("ADT: '%s' block unhandled, skipping %u bytes\n",fourcc,size));
if(strcmp((char*)fourcc,"MWID") && strcmp((char*)fourcc,"MMID")) if(!(isalnum(fourcc[0]) && isalnum(fourcc[1]) && isalnum(fourcc[2]) && isalnum(fourcc[3])))
{ {
printf("Error loading ADT file.\n"); printf("Error loading ADT file.\n");
return false; // dont care about those few mem leaks return false; // dont care about those few mem leaks
@ -288,3 +288,48 @@ bool ADTFile::LoadMem(ByteBuffer& buf)
m_loaded = true; m_loaded = true;
return true; return true;
} }
void ADT_ExportStringSetByOffset(const uint8* data, uint32 off, std::set<std::string>& st, char* stop)
{
data += ((uint32*)data)[off]; // seek to correct absolute offset
data += 28; // move ptr to real start of data
uint32 offset=0;
std::string s;
char c;
while(memcmp(data+offset,stop,4))
{
c = data[offset];
if(!c)
{
if(s.length())
{
DEBUG(printf("DEP: %s\n",s.c_str()));
st.insert(s);
s.clear();
}
}
else
s += c;
offset++;
}
}
void ADT_FillTextureData(const uint8* data,std::set<std::string>& st)
{
ADT_ExportStringSetByOffset(data,OFFSET_TEXTURES,st,"XDMM");
}
void ADT_FillWMOData(const uint8* data,std::set<std::string>& st)
{
ADT_ExportStringSetByOffset(data,OFFSET_WMOS,st,"DIWM");
}
void ADT_FillModelData(const uint8* data,std::set<std::string>& st)
{
ADT_ExportStringSetByOffset(data,OFFSET_MODELS,st,"DIMM");
}

View File

@ -1,6 +1,8 @@
#ifndef ADTFILE_H #ifndef ADTFILE_H
#define ADTFILE_H #define ADTFILE_H
#include <set>
#define CHUNKS_PER_TILE 256 #define CHUNKS_PER_TILE 256
#include "ADTFileStructs.h" #include "ADTFileStructs.h"
@ -26,5 +28,9 @@ public:
bool m_loaded; bool m_loaded;
}; };
void ADT_ExportStringSetByOffset(const uint8*, uint32, std::set<std::string>&, char*);
void ADT_FillTextureData(const uint8*,std::set<std::string>&);
void ADT_FillWMOData(const uint8*,std::set<std::string>&);
void ADT_FillModelData(const uint8*,std::set<std::string>&);
#endif #endif

View File

@ -3,6 +3,10 @@
#ifndef ADTFILESTRUCTS_H #ifndef ADTFILESTRUCTS_H
#define ADTFILESTRUCTS_H #define ADTFILESTRUCTS_H
#define OFFSET_TEXTURES 7
#define OFFSET_MODELS 8
#define OFFSET_WMOS 10
struct MHDR_chunk struct MHDR_chunk
{ {
uint32 pad; uint32 pad;
@ -10,8 +14,8 @@ struct MHDR_chunk
uint32 offsTex; uint32 offsTex;
uint32 offsModels; uint32 offsModels;
uint32 offsModelsIds; uint32 offsModelsIds;
uint32 offsMapObejcts; uint32 offsMapObjects;
uint32 offsMapObejctsIds; uint32 offsMapObjectsIds;
uint32 offsDoodsDef; uint32 offsDoodsDef;
uint32 offsObjectsDef; uint32 offsObjectsDef;
uint32 pad1; uint32 pad1;

View File

@ -1,4 +1,5 @@
#include <fstream> #include <fstream>
#include <set>
#define _COMMON_NO_THREADS #define _COMMON_NO_THREADS
#include "common.h" #include "common.h"
#include "MPQHelper.h" #include "MPQHelper.h"
@ -9,6 +10,9 @@
#include "Locale.h" #include "Locale.h"
std::vector<std::string> mapNames; std::vector<std::string> mapNames;
std::set<std::string> texNames;
std::set<std::string> modelNames;
std::set<std::string> wmoNames;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -27,6 +31,7 @@ int main(int argc, char *argv[])
CreateDir("stuffextract/data"); CreateDir("stuffextract/data");
ConvertDBC(); ConvertDBC();
ExtractMaps(); ExtractMaps();
ExtractMapDependencies();
//... //...
printf("\n -- finished, press enter to exit --\n"); printf("\n -- finished, press enter to exit --\n");
} }
@ -252,6 +257,8 @@ void ExtractMaps(void)
{ {
for(uint32 y=0;y<64; y++) for(uint32 y=0;y<64; y++)
{ {
uint32 olddeps;
uint32 depdiff;
sprintf(namebuf,"World\\Maps\\%s\\%s_%u_%u.adt",mapNames[it].c_str(),mapNames[it].c_str(),x,y); sprintf(namebuf,"World\\Maps\\%s\\%s_%u_%u.adt",mapNames[it].c_str(),mapNames[it].c_str(),x,y);
sprintf(outbuf,MAPSDIR"/%s_%u_%u.adt",mapNames[it].c_str(),x,y); sprintf(outbuf,MAPSDIR"/%s_%u_%u.adt",mapNames[it].c_str(),x,y);
if(mpq.FileExists(namebuf)) if(mpq.FileExists(namebuf))
@ -269,23 +276,140 @@ void ExtractMaps(void)
} }
fh.write((char*)bb.contents(),bb.size()); fh.write((char*)bb.contents(),bb.size());
fh.close(); fh.close();
ADTFile *adt = new ADTFile(); olddeps = texNames.size() + modelNames.size() + wmoNames.size();
adt->LoadMem(bb); ADT_FillTextureData(bb.contents(),texNames);
delete adt; ADT_FillModelData(bb.contents(),modelNames);
ADT_FillWMOData(bb.contents(),wmoNames);
depdiff = texNames.size() + modelNames.size() + wmoNames.size() - olddeps;
extr++; extr++;
printf("[%u/%u]: %s; %u new deps.\n",it+1,mapNames.size(),namebuf,depdiff);
} }
} }
printf("Map [%u/%u]: %s: %u\r",it+1,mapNames.size(),mapNames[it].c_str(),extr);
} }
} }
extrtotal+=extr; extrtotal+=extr;
printf("\n"); printf("\n");
} }
printf("\nDONE - %u maps extracted.\n",extrtotal); printf("\nDONE - %u maps extracted, %u total dependencies.\n",extrtotal, texNames.size() + modelNames.size() + wmoNames.size());
} }
void DoNothingDummy(void) void ExtractMapDependencies(void)
{ {
delete [] new uint8[50]; printf("\nExtracting map dependencies...\n\n");
printf("- Preparing to read MPQ arcives...\n");
MPQHelper mpqmodel("model");
MPQHelper mpqtex("texture");
MPQHelper mpqwmo("wmo");
std::string path = "stuffextract/data";
std::string pathtex = path + "/texture";
std::string pathmodel = path + "/model";
std::string pathwmo = path + "/wmo";
std::string mpqfn,realfn;
CreateDir(pathtex.c_str());
CreateDir(pathmodel.c_str());
CreateDir(pathwmo.c_str());
uint32 wmosdone=0,texdone=0,mdone=0;
for(std::set<std::string>::iterator i = texNames.begin(); i != texNames.end(); i++)
{
mpqfn = *i;
if(!mpqtex.FileExists((char*)mpqfn.c_str()))
continue;
realfn = pathtex + "/" + _PathToFileName(mpqfn);
std::fstream fh;
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
if(fh.is_open())
{
ByteBuffer& bb = mpqtex.ExtractFile((char*)mpqfn.c_str());
fh.write((const char*)bb.contents(),bb.size());
texdone++;
printf("- textures... %u\r",texdone);
}
else
printf("Could not write texture %s\n",realfn.c_str());
fh.close();
}
printf("\n");
for(std::set<std::string>::iterator i = modelNames.begin(); i != modelNames.end(); i++)
{
mpqfn = *i;
// no idea what bliz intended by this. the ADT files refer to .mdx models,
// however there are only .m2 files in the MPQ archives.
// so we just need to check if there is a .m2 file instead of the .mdx file, and load that one.
if(!mpqmodel.FileExists((char*)mpqfn.c_str()))
{
std::string alt = i->substr(0,i->length()-3) + "m2";
DEBUG(printf("MDX model not found, trying M2 file."));
if(!mpqmodel.FileExists((char*)alt.c_str()))
{
DEBUG(printf(" fail.\n"));
continue;
}
else
{
mpqfn = alt;
DEBUG(printf(" success.\n"));
}
}
realfn = pathmodel + "/" + _PathToFileName(mpqfn);
std::fstream fh;
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
if(fh.is_open())
{
ByteBuffer& bb = mpqmodel.ExtractFile((char*)mpqfn.c_str());
fh.write((const char*)bb.contents(),bb.size());
mdone++;
printf("- models... %u\r",mdone);
}
else
printf("Could not write model %s\n",realfn.c_str());
fh.close();
}
printf("\n");
for(std::set<std::string>::iterator i = wmoNames.begin(); i != wmoNames.end(); i++)
{
mpqfn = *i;
if(!mpqwmo.FileExists((char*)mpqfn.c_str()))
continue;
realfn = pathwmo + "/" + _PathToFileName(mpqfn);
std::fstream fh;
fh.open(realfn.c_str(),std::ios_base::out | std::ios_base::binary);
if(fh.is_open())
{
ByteBuffer& bb = mpqwmo.ExtractFile((char*)mpqfn.c_str());
fh.write((const char*)bb.contents(),bb.size());
wmosdone++;
printf("- WMOs... %u\r",wmosdone);
}
else
printf("Could not write WMO %s\n",realfn.c_str());
fh.close();
}
printf("\n");
} }
// fix filenames for linux ( '/' instead of windows '\')
void _FixFileName(std::string& str)
{
for(uint32 i = 0; i < str.length(); i++)
if(str[i]=='\\')
str[i]='/';
}
std::string _PathToFileName(std::string str)
{
uint32 pathend = str.find_last_of("/\\");
if(pathend != std::string::npos)
{
return str.substr(pathend+1);
}
return str;
}

View File

@ -16,6 +16,9 @@ int main(int argc, char *argv[]);
void OutSCP(char*, SCPStorageMap&); void OutSCP(char*, SCPStorageMap&);
bool ConvertDBC(void); bool ConvertDBC(void);
void ExtractMaps(void); void ExtractMaps(void);
void ExtractMapDependencies(void);
void _FixFileName(std::string&);
std::string _PathToFileName(std::string);
#endif #endif