diff --git a/src/PseuWoW.vcproj b/src/PseuWoW.vcproj
index 268f084..fd5b311 100644
--- a/src/PseuWoW.vcproj
+++ b/src/PseuWoW.vcproj
@@ -379,6 +379,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#include "common.h"
+#include "ADTFile.h"
+
+
+inline void flipcc(uint8 *fcc)
+{
+ char t;
+ t=fcc[0];
+ fcc[0]=fcc[3];
+ fcc[3]=t;
+ t=fcc[1];
+ fcc[1]=fcc[2];
+ fcc[2]=t;
+}
+
+bool ADTFile::Load(std::string fn)
+{
+ uint32 fs = GetFileSize(fn.c_str());
+ if(!fs)
+ return false;
+ std::fstream fh;
+ fh.open(fn.c_str());
+ if(!fh.is_open())
+ return false;
+
+ ByteBuffer buf(fs);
+ buf.resize(fs);
+ fh.read((char*)buf.contents(),fs);
+ fh.close();
+
+ LoadMem(buf);
+ return m_loaded;
+}
+
+bool ADTFile::LoadMem(ByteBuffer& buf)
+{
+ uint32 texturecnt=0,modelcnt=0,wmocnt=0;
+ uint32 size; // used for every chunk
+ uint32 mcnkid=0;
+ uint8 *fourcc = new uint8[5]; fourcc[4]=0;
+
+ while(buf.rpos()> _version;
+ }
+ else if(!strcmp((char*)fourcc,"MHDR"))
+ {
+ mhdr = buf.read();
+ }
+ else if(!strcmp((char*)fourcc,"MCIN"))
+ {
+ for(uint32 i = 0; i < CHUNKS_PER_TILE; i++)
+ {
+ mcin[i] = buf.read();
+ DEBUG(printf("ADT chunk %u at offset %u, size %u flags %X async %u\n",i,mcin[i].offset,mcin[i].size,mcin[i].flags,mcin[i].async));
+ }
+ }
+ else if(!strcmp((char*)fourcc,"MTEX"))
+ {
+ for(uint32 i=0;;i++)
+ {
+ std::string tex;
+ memcpy(fourcc,buf.contents()+buf.rpos(),4);
+ flipcc(fourcc);
+ if(!memcmp(fourcc,"MMDX",4))
+ break;
+ buf >> tex;
+ DEBUG(printf("MTEX offset %u \"%s\"\n",buf.rpos(),tex.c_str()));
+ _textures.push_back(tex);
+ texturecnt++;
+ }
+ }
+ else if(!strcmp((char*)fourcc,"MMDX"))
+ {
+ for(uint32 i=0;;i++)
+ {
+ std::string model;
+ memcpy(fourcc,buf.contents()+buf.rpos(),4);
+ flipcc(fourcc);
+ if(!memcmp(fourcc,"MMID",4))
+ break;
+ buf >> model;
+ DEBUG(printf("MMDX offset %u \"%s\"\n",buf.rpos(),model.c_str()));
+ _models.push_back(model);
+ modelcnt++;
+ }
+ }
+ /*else if(!strcmp((char*)fourcc,"MMID"))
+ {
+ for(uint32 i = 0; i <= modelcnt; i++)
+ {
+ uint32 offs;
+ buf >> offs; // we dont really need those offsets
+ }
+ }*/
+ else if(!strcmp((char*)fourcc,"MWMO"))
+ {
+ for(uint32 i=0;;i++)
+ {
+ std::string wmo;
+ memcpy(fourcc,buf.contents()+buf.rpos(),4);
+ flipcc(fourcc);
+ if(!memcmp(fourcc,"MWID",4))
+ break;
+ buf >> wmo;
+ DEBUG(printf("MWMO offset %u \"%s\"\n",buf.rpos(),wmo.c_str()));
+ _wmos.push_back(wmo);
+ wmocnt++;
+ }
+ }
+ /*else if(!strcmp((char*)fourcc,"MWID"))
+ {
+ for(uint32 i = 0; i <= wmocnt; i++)
+ {
+ uint32 offs;
+ buf >> offs; // we dont really need those offsets
+ }
+ }*/
+ else if(!strcmp((char*)fourcc,"MDDF"))
+ {
+ uint32 ndoodads = size / 36;
+ DEBUG(printf("ADT: Loading %u doodads.\n",ndoodads));
+ for(uint32 i = 0; i());
+ }
+ }
+ else if(!strcmp((char*)fourcc,"MODF"))
+ {
+ uint32 nwmos = size / 64;
+ DEBUG(printf("ADT: Loading %u wmos.\n",nwmos));
+ for(uint32 i = 0; i());
+ }
+ }
+ else if(!strcmp((char*)fourcc,"MCNK"))
+ {
+ _chunks[mcnkid].hdr = buf.read();
+ uint8 *mfcc = new uint8[5]; mfcc[4]=0;
+ uint32 msize;
+ while(buf.rpos()>_chunks[mcnkid].vertices[i];
+ }
+ }
+ else if(!strcmp((char*)mfcc,"MCNR"))
+ {
+ for(uint32 i = 0; i < 145; i++)
+ {
+ _chunks[mcnkid].normalvecs[i] = buf.read();
+ }
+ // HACK: skip unk junk bytes
+ if(msize==0x1B3)
+ buf.rpos(buf.rpos()+0xD);
+ }
+ else if(!strcmp((char*)mfcc,"MCLY"))
+ {
+ _chunks[mcnkid].nTextures = msize / 16;
+ ASSERT(msize/16 == _chunks[mcnkid].hdr.nLayers);
+ for(uint32 i = 0; i < _chunks[mcnkid].nTextures; i++)
+ {
+ _chunks[mcnkid].layer[i] = buf.read();
+ }
+ }
+ else if(!strcmp((char*)mfcc,"MCSH"))
+ {
+ buf.read((uint8*)&(_chunks[mcnkid].shadowmap),512);
+ }
+ else if(!strcmp((char*)mfcc,"MCAL"))
+ {
+ for(uint32 i = 0; i < (_chunks[mcnkid].hdr.sizeAlpha - 8) / 2048; i++)
+ {
+ buf.read((uint8*)(_chunks[mcnkid].alphamap[i]),2048);
+ }
+ }
+ else if(!strcmp((char*)mfcc,"MCLQ"))
+ {
+ uint8 *fcc1 = new uint8[5];
+ buf.read(fcc1,4);
+ flipcc(fcc1);
+ fcc1[4]=0;
+ if (!strcmp((char*)fcc1,"MCSE"))
+ {
+ _chunks[mcnkid].haswater = false;
+ DEBUG(printf("ADT: MCNK: MCLQ not present\n"));
+ buf.rpos(buf.rpos()-4);
+ delete [] fcc1;
+ continue; // next block read will be the MCSE block
+ }
+ else
+ {
+ _chunks[mcnkid].haswater = true;
+ float tmp;
+ buf.rpos(buf.rpos()-4);
+ uint32 bufpos=buf.rpos();
+ uint32 rbytes,diffbytes;
+ buf >> _chunks[mcnkid].waterlevel;
+ buf >> tmp;
+ DEBUG(printf("ADT: MCNK: MCLQ base floats: %f %f\n",_chunks[mcnkid].waterlevel,tmp));
+ //buf.rpos(buf.rpos()+4); // base height??
+ if(msize > 8) // just to be sure
+ {
+ for(uint32 i = 0; i < 81; i++)
+ {
+ _chunks[mcnkid].lqvertex[i] = buf.read();
+ }
+ for(uint32 i = 0; i < 64; i++)
+ {
+ buf >> _chunks[mcnkid].lqflags[i];
+ }
+ rbytes = buf.rpos() - bufpos;
+ DEBUG(printf("ADT: MCNK: MCLQ block loaded. %u / %u bytes.\n",rbytes,msize));
+ }
+ else
+ {
+ DEBUG(printf("ADT: MCNK: MCLQ block has only %u bytes\n",msize));
+ }
+ // HACK: skip some unk junk bytes
+ diffbytes = (msize-8) - rbytes; // dont forget to skip the 8 initial bytes
+ buf.rpos(buf.rpos()+diffbytes);
+ DEBUG(printf("ADT: MCNK: MCLQ - %u junk bytes skipped\n",diffbytes));
+ delete [] fcc1;
+ }
+ }
+ else if(!strcmp((char*)mfcc,"MCSE"))
+ {
+ uint32 emm = _chunks[mcnkid].hdr.nSndEmitters;
+ for(uint32 i = 0; i < emm; i++)
+ {
+ _soundemm.push_back(buf.read());
+ }
+ break;
+ }
+ else
+ {
+ DEBUG(printf("ADT: MCNK: '%s' block unhandled, skipping %u bytes\n",mfcc,msize));
+ if(strcmp((char*)mfcc,"MCRF"))
+ {
+ printf("Error loading ADT file (chunk %u error).\n",mcnkid);
+ return false; // dont care about those few mem leaks
+ }
+
+ buf.rpos(buf.rpos()+msize);
+ }
+
+ }
+ delete [] mfcc;
+ mcnkid++;
+ }
+ else
+ {
+ DEBUG(printf("ADT: '%s' block unhandled, skipping %u bytes\n",fourcc,size));
+ if(strcmp((char*)fourcc,"MWID") && strcmp((char*)fourcc,"MMID"))
+ {
+ printf("Error loading ADT file.\n");
+ return false; // dont care about those few mem leaks
+ }
+ buf.rpos(buf.rpos()+size);
+ }
+
+ }
+ delete [] fourcc;
+
+
+ m_loaded = true;
+ return true;
+}
diff --git a/src/shared/ADTFile.h b/src/shared/ADTFile.h
new file mode 100644
index 0000000..743eccb
--- /dev/null
+++ b/src/shared/ADTFile.h
@@ -0,0 +1,30 @@
+#ifndef ADTFILE_H
+#define ADTFILE_H
+
+#define CHUNKS_PER_TILE 256
+
+#include "ADTFileStructs.h"
+
+class ADTFile
+{
+public:
+ bool Load(std::string);
+ bool LoadMem(ByteBuffer&);
+ bool Loaded(void) { return m_loaded; }
+
+ MapChunk _chunks[CHUNKS_PER_TILE]; // 16x16
+ std::vector _textures;
+ std::vector _wmos;
+ std::vector _models;
+ std::vector _doodadsp;
+ std::vector _wmosp;
+ std::vector _soundemm;
+ MHDR_chunk mhdr;
+ MCIN_chunk mcin[CHUNKS_PER_TILE];
+ uint32 _version;
+
+ bool m_loaded;
+};
+
+
+#endif
diff --git a/src/shared/ADTFileStructs.h b/src/shared/ADTFileStructs.h
new file mode 100644
index 0000000..e26564f
--- /dev/null
+++ b/src/shared/ADTFileStructs.h
@@ -0,0 +1,208 @@
+// all credit for this file goes to the guys who write the wiki article about ADT files @ wowdev.org
+
+#ifndef ADTFILESTRUCTS_H
+#define ADTFILESTRUCTS_H
+
+struct MHDR_chunk
+{
+ uint32 pad;
+ uint32 offsInfo;
+ uint32 offsTex;
+ uint32 offsModels;
+ uint32 offsModelsIds;
+ uint32 offsMapObejcts;
+ uint32 offsMapObejctsIds;
+ uint32 offsDoodsDef;
+ uint32 offsObjectsDef;
+ uint32 pad1;
+ uint32 pad2;
+ uint32 pad3;
+ uint32 pad4;
+ uint32 pad5;
+ uint32 pad6;
+ uint32 pad7;
+};
+
+struct MCIN_chunk
+{
+ uint32 offset;
+ uint32 size;
+ uint32 flags;
+ uint32 async;
+};
+
+// MTEX: texture filename list. strings only!
+
+// MMDX: M2 models filename list. strings only!
+
+// MMID: string start offset list of the MMDX block
+
+// MWMO: filename list for WMOs
+
+// MWID: string start offset list of the MWMO block
+
+struct MDDF_chunk
+{
+ uint32 id; // position in the MMDX list
+ uint32 uniqueid; // unique instance id (?)
+ float x;
+ float y;
+ float z;
+ float oy;
+ float oz;
+ float ox;
+ uint16 flags;
+ uint16 scale;
+};
+
+struct MODF_chunk
+{
+ uint32 id;
+ uint32 uniqueid;
+ float x;
+ float y;
+ float z;
+ float oy;
+ float oz;
+ float ox;
+ // unk floats (orientation?)
+ float ou11;
+ float ou12;
+ float ou13;
+ float ou21;
+ float ou22;
+ float ou23;
+ uint32 flags;
+ uint16 doodadSet;
+ uint16 nameSet;
+};
+
+enum MapChunkHeaderFlags
+{
+ FLAG_SHADOW,
+ FLAG_IMPASS,
+ FLAG_LQ_RIVER,
+ FLAG_LQ_OCEAN,
+ FLAG_LQ_MAGMA,
+};
+
+struct MapChunkHeader
+{
+ uint32 flags;
+ uint32 IndexX;
+ uint32 IndexY;
+ uint32 nLayers;
+ uint32 nDoodadRefs;
+ uint32 offsHeight;
+ uint32 offsNormal;
+ uint32 offsLayer;
+ uint32 offsRefs;
+ uint32 offsAlpha;
+ uint32 sizeAlpha;
+ uint32 offsShadow;
+ uint32 sizeShadow;
+ uint32 areaid;
+ uint32 nMapObjRefs;
+ uint32 holes;
+ uint16 unk1;
+ uint16 unk2;
+ uint32 unk3;
+ uint32 unk4;
+ uint32 unk5;
+ uint32 predTex;
+ uint32 noEffectDoodad;
+ uint32 offsSndEmitters;
+ uint32 nSndEmitters;
+ uint32 offsLiquid;
+ uint32 sizeLiquid; // includes the 8 initinal bytes ("MCLQ" and size)
+ float xbase;
+ float ybase;
+ float zbase;
+ uint32 textureId;
+ uint32 props;
+ uint32 effectId;
+};
+
+// MCNK sub-chunk
+// 9x9+8x8 vertices. 145 floats, format: 9 outer, 8 inner, 9 outer, 8 inner, ... , 9 outer.
+
+// MCNR chunk: Normal vectors for each vertex, encoded as 3 signed bytes per normal, in the same order as specified above.
+
+struct MCLY_chunk
+{
+ uint32 textureId; // offset in MTEX list
+ uint32 flags; // 0x100 means using alpha map
+ uint32 offAlpha;
+ uint32 effectId; //detail texture id (?)
+};
+
+// MCRF chunk:
+// A list of indices into the parent file's MDDF chunk,
+// saying which MCNK subchunk those particular MDDF doodads are drawn within.
+// This MCRF list contains duplicates for map doodads that overlap areas.
+// But I guess that's what the MDDF's UniqueID field is for.
+
+// MCSH chunk: 8x8 bytes (64x64 bits) shadow map
+
+
+
+
+
+struct MCSE_chunk
+{
+ uint32 soundPointID;
+ uint32 soundNameID;
+ float x;
+ float y;
+ float z;
+ float minDistance;
+ float maxDistance;
+ float cutoffDistance;
+ uint16 startTime;
+ uint16 endTime;
+ uint16 groupSilenceMin;
+ uint16 groupSilenceMax;
+ uint16 playInstancesMin;
+ uint16 playInstancesMax;
+ uint16 loopCountMin;
+ uint16 loopCountMax;
+ uint16 interSoundGapMin;
+ uint16 interSoundGapMax;
+};
+
+struct LiquidVertex
+{
+ uint16 unk1;
+ uint16 unk2;
+ float h;
+};
+
+struct NormalVector
+{
+ uint8 x;
+ uint8 y;
+ uint8 z;
+};
+
+// also known as MCNK block
+// 256 per adt file
+struct MapChunk
+{
+ MapChunkHeader hdr;
+ float vertices[145];
+ NormalVector normalvecs[145];
+ MCLY_chunk layer[4]; // can be less
+ uint32 nTextures;
+ uint8 shadowmap[512]; // 1 bit 64x64
+ uint8 alphamap[4][2048]; // 4 bits, 64x64. max 4, 1 per layer
+ bool haswater;
+ float waterlevel;
+ LiquidVertex lqvertex[81];
+ uint8 lqflags[64];
+
+
+
+
+};
+
+#endif
\ No newline at end of file
diff --git a/src/shared/tools.cpp b/src/shared/tools.cpp
index c271eee..018e674 100644
--- a/src/shared/tools.cpp
+++ b/src/shared/tools.cpp
@@ -185,4 +185,15 @@ uint32 getMSTime(void)
return time_in_ms;
}
+uint32 GetFileSize(const char* sFileName)
+{
+ std::ifstream f;
+ f.open(sFileName, std::ios_base::binary | std::ios_base::in);
+ if (!f.good() || f.eof() || !f.is_open()) { return 0; }
+ f.seekg(0, std::ios_base::beg);
+ std::ifstream::pos_type begin_pos = f.tellg();
+ f.seekg(0, std::ios_base::end);
+ return f.tellg() - begin_pos;
+}
+
diff --git a/src/shared/tools.h b/src/shared/tools.h
index 839046a..364ecb4 100644
--- a/src/shared/tools.h
+++ b/src/shared/tools.h
@@ -19,5 +19,6 @@ std::deque GetFileList(std::string);
bool FileExists(std::string);
bool CreateDir(const char*);
uint32 getMSTime(void);
+uint32 GetFileSize(const char*);
#endif
\ No newline at end of file
diff --git a/src/tools/stuffextract/StuffExtract.cpp b/src/tools/stuffextract/StuffExtract.cpp
index 755b2d1..4f656be 100644
--- a/src/tools/stuffextract/StuffExtract.cpp
+++ b/src/tools/stuffextract/StuffExtract.cpp
@@ -3,6 +3,7 @@
#include "common.h"
#include "MPQHelper.h"
#include "dbcfile.h"
+#include "ADTFile.h"
#include "StuffExtract.h"
#include "DBCFieldData.h"
#include "Locale.h"
@@ -268,6 +269,9 @@ void ExtractMaps(void)
}
fh.write((char*)bb.contents(),bb.size());
fh.close();
+ ADTFile *adt = new ADTFile();
+ adt->LoadMem(bb);
+ delete adt;
extr++;
}
}
@@ -280,3 +284,8 @@ void ExtractMaps(void)
printf("\nDONE - %u maps extracted.\n",extrtotal);
}
+
+void DoNothingDummy(void)
+{
+ delete [] new uint8[50];
+}