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
5 years ago
|
#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;
|
||
|
}
|