Source code to the MapLib project by RZN.
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

#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;
}