1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-03 01:07:47 +00:00

slightly cleaned up PCB reader, added some exception logging

This commit is contained in:
Tahir Akhlaq 2017-10-17 21:49:01 +01:00
parent ae1b8a393e
commit 2e13df1934
2 changed files with 277 additions and 256 deletions

View file

@ -57,6 +57,26 @@ enum class LgbEntryType : uint32_t
SphereCastRange = 75, SphereCastRange = 75,
}; };
class LGB_MODEL_ENTRY
{
public:
char* m_buf;
uint32_t m_offset;
LGB_MODEL_ENTRY()
{
m_buf = nullptr;
m_offset = 0;
};
LGB_MODEL_ENTRY( char* buf, uint32_t offset )
{
m_buf = buf;
m_offset = offset;
};
virtual ~LGB_MODEL_ENTRY() {};
};
struct LGB_BGPARTS_HEADER struct LGB_BGPARTS_HEADER
{ {
LgbEntryType type; LgbEntryType type;
@ -75,25 +95,6 @@ struct LGB_BGPARTS_HEADER
uint32_t unknown9; uint32_t unknown9;
}; };
class LGB_MODEL_ENTRY
{
public:
char* m_buf;
uint32_t m_offset;
LGB_MODEL_ENTRY()
{
m_buf = nullptr;
m_offset = 0;
};
LGB_MODEL_ENTRY(char* buf, uint32_t offset)
{
m_buf = buf;
m_offset = offset;
};
virtual ~LGB_MODEL_ENTRY(){};
};
class LGB_BGPARTS_ENTRY : public LGB_MODEL_ENTRY class LGB_BGPARTS_ENTRY : public LGB_MODEL_ENTRY
{ {
public: public:
@ -101,13 +102,13 @@ public:
std::string name; std::string name;
std::string modelFileName; std::string modelFileName;
std::string collisionFileName; std::string collisionFileName;
LGB_BGPARTS_ENTRY(){}; LGB_BGPARTS_ENTRY() {};
LGB_BGPARTS_ENTRY(char* buf, uint32_t offset) LGB_BGPARTS_ENTRY( char* buf, uint32_t offset )
{ {
header = *reinterpret_cast<LGB_BGPARTS_HEADER*>(buf + offset); header = *reinterpret_cast<LGB_BGPARTS_HEADER*>(buf + offset);
name = std::string(buf + offset + header.nameOffset); name = std::string( buf + offset + header.nameOffset );
modelFileName = std::string(buf + offset + header.modelFileOffset); modelFileName = std::string( buf + offset + header.modelFileOffset );
collisionFileName = std::string(buf + offset + header.collisionFileOffset); collisionFileName = std::string( buf + offset + header.collisionFileOffset );
//std::cout << "BGPARTS_ENTRY " << name << "\n"; //std::cout << "BGPARTS_ENTRY " << name << "\n";
//std::cout << " " << modelFileName << "\n"; //std::cout << " " << modelFileName << "\n";
//std::cout << " " << collisionFileName << "\n"; //std::cout << " " << collisionFileName << "\n";
@ -132,10 +133,10 @@ public:
LGB_GIMMICK_HEADER header; LGB_GIMMICK_HEADER header;
std::string name; std::string name;
LGB_GIMMICK_ENTRY(char* buf, uint32_t offset) LGB_GIMMICK_ENTRY( char* buf, uint32_t offset )
{ {
header = *reinterpret_cast<LGB_GIMMICK_HEADER*>(buf + offset); header = *reinterpret_cast<LGB_GIMMICK_HEADER*>(buf + offset);
name = std::string(buf + offset + header.nameOffset); name = std::string( buf + offset + header.nameOffset );
}; };
}; };
@ -163,12 +164,12 @@ struct LGB_GROUP
std::string name; std::string name;
std::vector<std::shared_ptr<LGB_MODEL_ENTRY>> entries; std::vector<std::shared_ptr<LGB_MODEL_ENTRY>> entries;
LGB_GROUP(char* buf, LGB_FILE* parentStruct, uint32_t offset) LGB_GROUP( char* buf, LGB_FILE* parentStruct, uint32_t offset )
{ {
parent = parentStruct; parent = parentStruct;
header = *reinterpret_cast<LGB_GROUP_HEADER*>(buf + offset); header = *reinterpret_cast<LGB_GROUP_HEADER*>(buf + offset);
name = std::string(buf + offset + header.groupNameOffset); name = std::string( buf + offset + header.groupNameOffset );
entries.resize(header.entryCount); entries.resize( header.entryCount );
//std::cout << name << std::endl; //std::cout << name << std::endl;
auto entriesOffset = offset + header.entriesOffset; auto entriesOffset = offset + header.entriesOffset;
for( auto i = 0; i < header.entryCount; ++i ) for( auto i = 0; i < header.entryCount; ++i )
@ -179,20 +180,20 @@ struct LGB_GROUP
{ {
auto type = *reinterpret_cast<LgbEntryType*>(buf + entryOffset); auto type = *reinterpret_cast<LgbEntryType*>(buf + entryOffset);
LGB_MODEL_ENTRY* entry; LGB_MODEL_ENTRY* entry;
if (type == LgbEntryType::BgParts) if( type == LgbEntryType::BgParts )
{ {
entries[i] = std::make_shared<LGB_BGPARTS_ENTRY>(buf, entryOffset); entries[i] = std::make_shared<LGB_BGPARTS_ENTRY>( buf, entryOffset );
} }
else if (type == LgbEntryType::Gimmick) else if( type == LgbEntryType::Gimmick )
{ {
entries[i] = std::make_shared<LGB_GIMMICK_ENTRY>(buf, entryOffset); entries[i] = std::make_shared<LGB_GIMMICK_ENTRY>( buf, entryOffset );
} }
else else
{ {
entries[i] = nullptr; entries[i] = nullptr;
} }
} }
catch (std::exception& e) catch( std::exception& e )
{ {
std::cout << name << " " << e.what() << std::endl; std::cout << name << " " << e.what() << std::endl;
} }
@ -218,46 +219,46 @@ struct LGB_FILE
LGB_FILE_HEADER header; LGB_FILE_HEADER header;
std::vector<LGB_GROUP> groups; std::vector<LGB_GROUP> groups;
LGB_FILE(char* buf) LGB_FILE( char* buf )
{ {
header = *reinterpret_cast<LGB_FILE_HEADER*>(buf); header = *reinterpret_cast<LGB_FILE_HEADER*>(buf);
if (strncmp(&header.magic[0], "LGB1", 4) != 0 || strncmp(&header.magic2[0], "LGP1", 4) != 0) if( strncmp( &header.magic[0], "LGB1", 4 ) != 0 || strncmp( &header.magic2[0], "LGP1", 4 ) != 0 )
throw std::exception("Invalid LGB file!"); throw std::exception( "Invalid LGB file!" );
//groups.resize(header.groupCount); //groups.resize(header.groupCount);
auto baseOffset = sizeof(header); auto baseOffset = sizeof( header );
for(auto i = 0; i < header.groupCount; ++i) for( auto i = 0; i < header.groupCount; ++i )
{ {
auto groupOffset = baseOffset + *reinterpret_cast<int32_t*>(buf + (baseOffset + i * 4)); auto groupOffset = baseOffset + *reinterpret_cast<int32_t*>(buf + (baseOffset + i * 4));
auto group = LGB_GROUP(buf, this, groupOffset); auto group = LGB_GROUP( buf, this, groupOffset );
groups.push_back(group); groups.push_back( group );
} }
}; };
}; };
std::map<std::string, LGB_FILE> getLgbFiles(const std::string& dir) std::map<std::string, LGB_FILE> getLgbFiles( const std::string& dir )
{ {
namespace fs = std::experimental::filesystem; namespace fs = std::experimental::filesystem;
std::map<std::string, LGB_FILE> fileMap; std::map<std::string, LGB_FILE> fileMap;
for (const auto& path : fs::recursive_directory_iterator(dir)) for( const auto& path : fs::recursive_directory_iterator( dir ) )
{ {
if (path.path().extension() == ".lgb") if( path.path().extension() == ".lgb" )
{ {
auto strPath = path.path().string(); auto strPath = path.path().string();
auto f = fopen(strPath.c_str(), "rb"); auto f = fopen( strPath.c_str(), "rb" );
fseek(f, 0, SEEK_END); fseek( f, 0, SEEK_END );
auto size = ftell(f); auto size = ftell( f );
std::vector<char> bytes(size); std::vector<char> bytes( size );
rewind(f); rewind( f );
fread(bytes.data(), 1, size, f); fread( bytes.data(), 1, size, f );
fclose(f); fclose( f );
try try
{ {
LGB_FILE lgbFile(bytes.data()); LGB_FILE lgbFile( bytes.data() );
fileMap.insert(std::make_pair(strPath, lgbFile)); fileMap.insert( std::make_pair( strPath, lgbFile ) );
} }
catch (std::exception& e) catch( std::exception& e )
{ {
std::cout << "Unable to load " << strPath << std::endl; std::cout << "Unable to load " << strPath << std::endl;
} }

View file

@ -14,6 +14,10 @@
#include <Exd.h> #include <Exd.h>
#include <iostream> #include <iostream>
#include <boost/algorithm/string.hpp>
#include <chrono>
using namespace std::chrono_literals;
namespace fs = std::experimental::filesystem; namespace fs = std::experimental::filesystem;
struct face struct face
{ {
@ -28,7 +32,7 @@ int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff
{ {
PCB_BLOCK_ENTRY block_entry; PCB_BLOCK_ENTRY block_entry;
memcpy( &block_entry.header, data + offset, sizeof( block_entry.header ) ); memcpy( &block_entry.header, data + offset, sizeof( block_entry.header ) );
isgroup = block_entry.header.type == 0x30 ? true : false; isgroup = block_entry.header.type == 0x30;
//printf( " BLOCKHEADER_%X: type: %i, group_size: %i\n", gOff + offset, block_entry.header.type, block_entry.header.group_size ); //printf( " BLOCKHEADER_%X: type: %i, group_size: %i\n", gOff + offset, block_entry.header.type, block_entry.header.group_size );
@ -115,6 +119,8 @@ std::string zoneNameToPath( const std::string& name )
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
{ {
auto startTime = std::chrono::system_clock::now();
std::string gamePath = "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv"; std::string gamePath = "C:\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv";
std::string zoneName = "r1f1"; std::string zoneName = "r1f1";
@ -128,6 +134,8 @@ int main( int argc, char* argv[] )
} }
const auto& zonePath = zoneNameToPath( zoneName ); const auto& zonePath = zoneNameToPath( zoneName );
try
{
xiv::dat::GameData data1( gamePath ); xiv::dat::GameData data1( gamePath );
xiv::exd::ExdData eData( data1 ); xiv::exd::ExdData eData( data1 );
@ -135,11 +143,10 @@ int main( int argc, char* argv[] )
auto &test_file = data1.get_file( "bg/ffxiv/" + zonePath + "/level/bg.lgb" ); auto &test_file = data1.get_file( "bg/ffxiv/" + zonePath + "/level/bg.lgb" );
auto &section = test_file->access_data_sections().at( 0 ); auto &section = test_file->access_data_sections().at( 0 );
int32_t list_offset = *( uint32_t* ) &section[0x18]; int32_t list_offset = *(uint32_t*)&section[0x18];
int32_t size = *( uint32_t* ) &section[4]; int32_t size = *(uint32_t*)&section[4];
std::vector<std::string> stringList; std::vector<std::string> stringList;
std::vector<std::string> stringList2;
auto &test_file1 = data1.get_file( "bg/ffxiv/" + zonePath + "/collision/list.pcb" ); auto &test_file1 = data1.get_file( "bg/ffxiv/" + zonePath + "/collision/list.pcb" );
auto &section1 = test_file1->access_data_sections().at( 0 ); auto &section1 = test_file1->access_data_sections().at( 0 );
@ -148,7 +155,7 @@ int main( int argc, char* argv[] )
for( ; ; ) for( ; ; )
{ {
uint16_t trId = *( uint16_t* ) &section1[offset1]; uint16_t trId = *(uint16_t*)&section1[offset1];
char someString[200]; char someString[200];
sprintf( someString, "%str%04d.pcb", path.c_str(), trId ); sprintf( someString, "%str%04d.pcb", path.c_str(), trId );
@ -162,7 +169,7 @@ int main( int argc, char* argv[] )
} }
} }
LGB_FILE bgLgb(&section[0]); LGB_FILE bgLgb( &section[0] );
int max_index = 0; int max_index = 0;
@ -181,7 +188,10 @@ int main( int argc, char* argv[] )
} }
else else
{ {
throw std::exception( "Cannot create new file. Run as admin." ); std::string errorMessage( "Cannot create " + zoneName + ".obj\n" +
" Check no programs have a handle to file and run as admin.\n" );
std::cout << errorMessage;
throw std::exception( errorMessage.c_str() );
return 0; return 0;
} }
@ -212,7 +222,7 @@ int main( int argc, char* argv[] )
{ {
PCB_BLOCK_ENTRY block_entry; PCB_BLOCK_ENTRY block_entry;
memcpy( &block_entry.header, &dataSection[0] + offset, sizeof( block_entry.header ) ); memcpy( &block_entry.header, &dataSection[0] + offset, sizeof( block_entry.header ) );
isgroup = block_entry.header.type == 0x30 ? true : false; isgroup = block_entry.header.type == 0x30;
//printf( "BLOCKHEADER_%X: type: %i, group_size: %i\n", offset, block_entry.header.type, block_entry.header.group_size ); //printf( "BLOCKHEADER_%X: type: %i, group_size: %i\n", offset, block_entry.header.type, block_entry.header.group_size );
// //
@ -264,12 +274,9 @@ int main( int argc, char* argv[] )
}; };
for( auto &vertex_list : entry.data.vertices ) for( auto &vertex : entry.data.vertices )
{ {
vec3 v; vec3 v( vertex.x, vertex.y, vertex.z );
v.x = vertex_list.x;
v.y = vertex_list.y;
v.z = vertex_list.z;
makeTranslation( v ); makeTranslation( v );
fprintf( fp_out, "v %f %f %f\n", v.x, v.y, v.z ); fprintf( fp_out, "v %f %f %f\n", v.x, v.y, v.z );
} }
@ -291,16 +298,13 @@ int main( int argc, char* argv[] )
{ {
//if( index.index[0] != 0 || index.index[1] != 0 || index.index[2] != 0 ) //if( index.index[0] != 0 || index.index[1] != 0 || index.index[2] != 0 )
{ {
face f; fprintf( fp_out, "f %i %i %i\n",
f.f1 = index.index[0] + max_index; index.index[0] + max_index + 1,
f.f2 = index.index[1] + max_index; index.index[1] + max_index + 1,
f.f3 = index.index[2] + max_index; index.index[2] + max_index + 1 );
fprintf( fp_out, "f %i %i %i\n", f.f1 + 1, f.f2 + 1, f.f3 + 1 );
} }
//std::cout << std::to_string( index.unknown[0] )<< " " << std::to_string( index.unknown[1] )<< " " << std::to_string( index.unknown[2]) << std::endl; //std::cout << std::to_string( index.unknown[0] )<< " " << std::to_string( index.unknown[1] )<< " " << std::to_string( index.unknown[2]) << std::endl;
} }
//max_index = vertices.size();
max_index += entry.data.vertices.size() + entry.data.vertices_i16.size(); max_index += entry.data.vertices.size() + entry.data.vertices_i16.size();
} }
}; };
@ -320,13 +324,22 @@ int main( int argc, char* argv[] )
continue; continue;
auto pBgParts = dynamic_cast<LGB_BGPARTS_ENTRY*>(pEntry.get()); auto pBgParts = dynamic_cast<LGB_BGPARTS_ENTRY*>(pEntry.get());
if( !pBgParts || pBgParts->collisionFileName.empty() if( pBgParts && pBgParts->collisionFileName.empty() )
|| std::find( stringList.begin(), stringList.end(), pBgParts->collisionFileName ) != stringList.end() ) {
pBgParts->collisionFileName = pBgParts->modelFileName;
boost::replace_all( pBgParts->collisionFileName, "bgparts", "collision" );
boost::replace_all( pBgParts->collisionFileName, ".mdl", ".pcb" );
//std::cout << pBgParts->collisionFileName << " renamed\n";
}
if( !pBgParts || pBgParts->collisionFileName.empty() )
//|| std::find( stringList.begin(), stringList.end(), pBgParts->collisionFileName ) != stringList.end() )
continue; continue;
auto it = pcbFiles.find( pBgParts->collisionFileName ); auto it = pcbFiles.find( pBgParts->collisionFileName );
if( it == pcbFiles.end() ) if( it == pcbFiles.end() )
{ {
loadPcbFile( pBgParts->collisionFileName ); loadPcbFile( pBgParts->collisionFileName );
//std::cout << "\t\tLoaded PCB File " << pBgParts->collisionFileName << "\n";
} }
if( it != pcbFiles.end() ) if( it != pcbFiles.end() )
{ {
@ -342,5 +355,12 @@ int main( int argc, char* argv[] )
} }
} }
} }
std::cout << "Finished exporting " << zoneName << " in " <<
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - startTime).count() << " seconds\n";
}
catch( std::exception& e )
{
std::cout << e.what() << std::endl;
}
return 0; return 0;
} }