#include "MapLib.h" #include "FFXIEncryption.h" #include FFxiMapLib::MapLib::MapLib() { m_pDatData = NULL; m_datSize = 0; m_ObjectMapCount = 0; m_ObjectMap = NULL; m_CallBack = NULL; } FFxiMapLib::MapLib::~MapLib() { FreeMap(); } void FFxiMapLib::MapLib::FreeMap() { m_datSize = 0; if( m_pDatData ) { delete []m_pDatData; m_pDatData = NULL; } m_pDatData=NULL; if( m_ObjectMap ) delete[] m_ObjectMap; m_ObjectMapCount = 0; m_ObjectMap = NULL; } void FFxiMapLib::MapLib::AddCallback(ICallbackClass* T) { m_CallBack = T; } FFxiMapLib::OBJINFO* FFxiMapLib::MapLib::GetObjectMap(UINT Index) { if( m_ObjectMap && Index <= m_ObjectMapCount ) return &m_ObjectMap[Index]; return NULL; } UINT FFxiMapLib::MapLib::GetObjectMapCount() { if( m_ObjectMap ) return m_ObjectMapCount; return 0; } bool FFxiMapLib::MapLib::SetGamePath(const char* Path) { lstrcpyA(m_ffxiDir, Path); //to do valadate path return true; } UINT FFxiMapLib::MapLib::GetFtableID(UINT Table, UINT ID) { HANDLE hFile; char fname[1024]; DWORD dwRead; BYTE v; WORD f; if( ID >= 51439 ) return 0; lstrcpyA(fname, m_ffxiDir); switch (Table) { case 1: lstrcatA(fname,"VTABLE.DAT"); break; case 2: lstrcatA(fname,"ROM2\\VTABLE2.DAT"); break; case 3: lstrcatA(fname,"ROM3\\VTABLE3.DAT"); break; case 4: lstrcatA(fname,"ROM4\\VTABLE4.DAT"); break; case 5: lstrcatA(fname,"ROM5\\VTABLE5.DAT"); break; case 6: lstrcatA(fname,"ROM6\\VTABLE6.DAT"); break; case 7: lstrcatA(fname,"ROM7\\VTABLE7.DAT"); break; case 8: lstrcatA(fname,"ROM8\\VTABLE8.DAT"); break; case 9: lstrcatA(fname,"ROM9\\VTABLE9.DAT"); break; default: return 0; } hFile = CreateFileA(fname,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL); if (hFile == INVALID_HANDLE_VALUE) return 0; SetFilePointer(hFile, ID, NULL, FILE_BEGIN); ReadFile(hFile, &v, 1, &dwRead, NULL); CloseHandle(hFile); if (dwRead != 1 || v == 0) return 0; lstrcpyA(fname, m_ffxiDir); switch (Table) { case 1: lstrcatA(fname,"FTABLE.DAT"); break; case 2: lstrcatA(fname,"ROM2\\FTABLE2.DAT"); break; case 3: lstrcatA(fname,"ROM3\\FTABLE3.DAT"); break; case 4: lstrcatA(fname,"ROM4\\FTABLE4.DAT"); break; case 5: lstrcatA(fname,"ROM5\\FTABLE5.DAT"); break; case 6: lstrcatA(fname,"ROM6\\FTABLE6.DAT"); break; case 7: lstrcatA(fname,"ROM7\\FTABLE7.DAT"); break; case 8: lstrcatA(fname,"ROM8\\FTABLE8.DAT"); break; case 9: lstrcatA(fname,"ROM9\\FTABLE9.DAT"); break; default: return 0; } hFile = CreateFileA(fname,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL); if (hFile == INVALID_HANDLE_VALUE) return 0; SetFilePointer(hFile, ID*2, NULL, FILE_BEGIN); ReadFile(hFile, &f, 2, &dwRead, NULL); CloseHandle(hFile); if(dwRead != 2) return 0; return (DWORD)MAKELONG(f,v); } bool FFxiMapLib::MapLib::LoadMap(UINT ZoneID) { m_MapID = ZoneID; UINT DatID = m_MapID + 100; FreeMap(); char DatPath[1024] = {0}; DWORD id; DWORD no; for (int i = 9; i > -1; i--) { id = GetFtableID(i,DatID); if( id ) break; } if (id == 0) return false; no = id & 0xffff; switch (HIWORD(id)) { case 1: wsprintfA(DatPath, "%sROM\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; case 2: wsprintfA(DatPath, "%sROM2\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; case 3: wsprintfA(DatPath, "%sROM3\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; case 4: wsprintfA(DatPath, "%sROM4\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; case 5: wsprintfA(DatPath, "%sROM5\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; case 6: wsprintfA(DatPath, "%sROM6\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; case 7: wsprintfA(DatPath, "%sROM7\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; case 8: wsprintfA(DatPath, "%sROM8\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; case 9: wsprintfA(DatPath, "%sROM9\\%d\\%d.dat", m_ffxiDir, no/0x80, no%0x80); break; default: return false; } return LoadMap(DatPath); } bool FFxiMapLib::MapLib::LoadMap(const char* DatPath) { HANDLE hFile = CreateFileA(DatPath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL); if( hFile!=INVALID_HANDLE_VALUE ) { DWORD dmy; m_datSize = GetFileSize(hFile,NULL); m_pDatData = new char[m_datSize]; ReadFile(hFile,m_pDatData,m_datSize,&dmy,NULL); CloseHandle(hFile); return ParseDat(); } return false; } bool FFxiMapLib::MapLib::ParseDat() { OBJINFO* pobjects = NULL; int type = 0; for(unsigned int i=0; i<= this->m_datSize; ) { unsigned int j=i; LPSTR iname = &this->m_pDatData[i]; unsigned int next = (int)(((*(DWORD*)&this->m_pDatData[i+4])>>3)&0x007ffff0); if( next<16 ) break; if( next+i > this->m_datSize ) break; type = (int)(((*(DWORD*)&this->m_pDatData[i+4]))&0x7f); switch(type) { case 0x1c: //Object map FFXIEncryption::FFXIEncryption::decode_ObjectMap((BYTE*)&this->m_pDatData[i+16]); pobjects = (OBJINFO *)(this->m_pDatData+i+32+16); this->m_ObjectMapCount = (*(int*)(this->m_pDatData+i+4+16) )&0xffffff; //copy the map to our buffer this->m_ObjectMap = new OBJINFO[this->m_ObjectMapCount]; memcpy(this->m_ObjectMap, pobjects, sizeof(OBJINFO)*this->m_ObjectMapCount); break; case 0x2e: //Map object FFXIEncryption::FFXIEncryption::decode_mmb((BYTE*)&this->m_pDatData[i+16]); //this->m_mMBlist[this->m_numMMB++] = this->m_pDatData+i+16; if(! ParseObject(this->m_pDatData+i+16) ) return false; break; case 0x20: //Texture break; case 0x2F: break; default: break; } i+=next; if( j>=i ) break; } return true; } bool FFxiMapLib::MapLib::ParseObject(char* pObject) { //pointer to the objects start char* ObjectStart = pObject; //pointer to our current read position char* Position = ObjectStart; //skip object name Position += 0x20; int Flag = *(int*)Position; if( Flag == 1 ) Position += 0x20; if( Flag >= 2 && Flag <= 16) Position += 0x40; if( Flag > 16 ) Position += Flag * 4; int StripCount; while(Flag) { StripCount = *(int*)Position; Position += 0x20; for (int StripOffset = 0; StripOffset < StripCount; StripOffset++) { int IndexCount = 0; int NewVertexCount = 0; int VertexCount = (int)*(short*)(Position + 16); if( VertexCount >= 0xFFFF || VertexCount <= 0 ) break; IndexCount = (*(int*)(Position + 16 + 4 + VertexCount * 36)); if( IndexCount >= 0xFFFF || IndexCount <= 0 ) break; int next = 16 + 4 + VertexCount * 36 + 4 + IndexCount * 2; next = 4 * (( next + 3) / 4); if( (this->m_pDatData + this->m_datSize) < (Position + next) ) break; char* VertexBuffer = (Position + 16 + 4); WORD* IndexBuffer = (WORD*)(Position + 16 + 4 + VertexCount * 36 + 4); //add this object. copies the vectors //unsigned int MapObjectIndex = ThisObject->AddVertexBuffer(IndexCount, VertexCount, IndexBuffer, VertexBuffer, pTexture); m_CallBack->HandleNewObject(ObjectStart+16, IndexCount, VertexCount, IndexBuffer, VertexBuffer); Position += next; }//@for (int StripOffset = 0; StripOffset < StripCount; StripOffset++) Flag--; }//@while(Flag) return true; }