From de2614fa80da36791324d476654e665a6f6e1257 Mon Sep 17 00:00:00 2001 From: "False.Genesis" Date: Wed, 23 May 2007 17:25:16 +0000 Subject: [PATCH] * 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 --- src/shared/ADTFile.cpp | 51 ++++++++- src/shared/ADTFile.h | 6 ++ src/shared/ADTFileStructs.h | 8 +- src/tools/stuffextract/StuffExtract.cpp | 138 ++++++++++++++++++++++-- src/tools/stuffextract/StuffExtract.h | 3 + 5 files changed, 194 insertions(+), 12 deletions(-) diff --git a/src/shared/ADTFile.cpp b/src/shared/ADTFile.cpp index b71276e..31cb106 100644 --- a/src/shared/ADTFile.cpp +++ b/src/shared/ADTFile.cpp @@ -257,7 +257,7 @@ bool ADTFile::LoadMem(ByteBuffer& buf) else { 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); return false; // dont care about those few mem leaks @@ -271,9 +271,9 @@ bool ADTFile::LoadMem(ByteBuffer& buf) mcnkid++; } else - { + { 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"); return false; // dont care about those few mem leaks @@ -288,3 +288,48 @@ bool ADTFile::LoadMem(ByteBuffer& buf) m_loaded = true; return true; } + + + + + + +void ADT_ExportStringSetByOffset(const uint8* data, uint32 off, std::set& 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& st) +{ + ADT_ExportStringSetByOffset(data,OFFSET_TEXTURES,st,"XDMM"); +} + +void ADT_FillWMOData(const uint8* data,std::set& st) +{ + ADT_ExportStringSetByOffset(data,OFFSET_WMOS,st,"DIWM"); +} + +void ADT_FillModelData(const uint8* data,std::set& st) +{ + ADT_ExportStringSetByOffset(data,OFFSET_MODELS,st,"DIMM"); +} diff --git a/src/shared/ADTFile.h b/src/shared/ADTFile.h index 743eccb..711252b 100644 --- a/src/shared/ADTFile.h +++ b/src/shared/ADTFile.h @@ -1,6 +1,8 @@ #ifndef ADTFILE_H #define ADTFILE_H +#include + #define CHUNKS_PER_TILE 256 #include "ADTFileStructs.h" @@ -26,5 +28,9 @@ public: bool m_loaded; }; +void ADT_ExportStringSetByOffset(const uint8*, uint32, std::set&, char*); +void ADT_FillTextureData(const uint8*,std::set&); +void ADT_FillWMOData(const uint8*,std::set&); +void ADT_FillModelData(const uint8*,std::set&); #endif diff --git a/src/shared/ADTFileStructs.h b/src/shared/ADTFileStructs.h index e26564f..4c78f5c 100644 --- a/src/shared/ADTFileStructs.h +++ b/src/shared/ADTFileStructs.h @@ -3,6 +3,10 @@ #ifndef ADTFILESTRUCTS_H #define ADTFILESTRUCTS_H +#define OFFSET_TEXTURES 7 +#define OFFSET_MODELS 8 +#define OFFSET_WMOS 10 + struct MHDR_chunk { uint32 pad; @@ -10,8 +14,8 @@ struct MHDR_chunk uint32 offsTex; uint32 offsModels; uint32 offsModelsIds; - uint32 offsMapObejcts; - uint32 offsMapObejctsIds; + uint32 offsMapObjects; + uint32 offsMapObjectsIds; uint32 offsDoodsDef; uint32 offsObjectsDef; uint32 pad1; diff --git a/src/tools/stuffextract/StuffExtract.cpp b/src/tools/stuffextract/StuffExtract.cpp index 4f656be..e064cbf 100644 --- a/src/tools/stuffextract/StuffExtract.cpp +++ b/src/tools/stuffextract/StuffExtract.cpp @@ -1,4 +1,5 @@ #include +#include #define _COMMON_NO_THREADS #include "common.h" #include "MPQHelper.h" @@ -9,6 +10,9 @@ #include "Locale.h" std::vector mapNames; +std::set texNames; +std::set modelNames; +std::set wmoNames; int main(int argc, char *argv[]) @@ -27,6 +31,7 @@ int main(int argc, char *argv[]) CreateDir("stuffextract/data"); ConvertDBC(); ExtractMaps(); + ExtractMapDependencies(); //... printf("\n -- finished, press enter to exit --\n"); } @@ -252,6 +257,8 @@ void ExtractMaps(void) { 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(outbuf,MAPSDIR"/%s_%u_%u.adt",mapNames[it].c_str(),x,y); if(mpq.FileExists(namebuf)) @@ -269,23 +276,140 @@ void ExtractMaps(void) } fh.write((char*)bb.contents(),bb.size()); fh.close(); - ADTFile *adt = new ADTFile(); - adt->LoadMem(bb); - delete adt; + olddeps = texNames.size() + modelNames.size() + wmoNames.size(); + ADT_FillTextureData(bb.contents(),texNames); + ADT_FillModelData(bb.contents(),modelNames); + ADT_FillWMOData(bb.contents(),wmoNames); + depdiff = texNames.size() + modelNames.size() + wmoNames.size() - olddeps; 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; 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::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::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::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; +} + + + + diff --git a/src/tools/stuffextract/StuffExtract.h b/src/tools/stuffextract/StuffExtract.h index 5092b09..7460550 100644 --- a/src/tools/stuffextract/StuffExtract.h +++ b/src/tools/stuffextract/StuffExtract.h @@ -16,6 +16,9 @@ int main(int argc, char *argv[]); void OutSCP(char*, SCPStorageMap&); bool ConvertDBC(void); void ExtractMaps(void); +void ExtractMapDependencies(void); +void _FixFileName(std::string&); +std::string _PathToFileName(std::string); #endif \ No newline at end of file