You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
7.6 KiB
282 lines
7.6 KiB
#include "MapLib.h" |
|
#include "FFXIEncryption.h" |
|
#include <Windows.h> |
|
|
|
|
|
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; |
|
} |