mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-27 14:57:44 +00:00
Merge pull request #222 from takhlaq/pcb_reader
updated pcb_reader with mordred's eobj/enpc entries
This commit is contained in:
commit
4c3ed1fa7d
3 changed files with 163 additions and 23 deletions
|
@ -118,7 +118,7 @@ public:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LGB_GIMMICK_HEADER
|
struct LGB_ENTRY_HEADER
|
||||||
{
|
{
|
||||||
LgbEntryType type;
|
LgbEntryType type;
|
||||||
uint32_t unknown;
|
uint32_t unknown;
|
||||||
|
@ -126,6 +126,10 @@ struct LGB_GIMMICK_HEADER
|
||||||
vec3 translation;
|
vec3 translation;
|
||||||
vec3 rotation;
|
vec3 rotation;
|
||||||
vec3 scale;
|
vec3 scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LGB_GIMMICK_HEADER : public LGB_ENTRY_HEADER
|
||||||
|
{
|
||||||
uint32_t gimmickFileOffset;
|
uint32_t gimmickFileOffset;
|
||||||
char unknownBytes[100];
|
char unknownBytes[100];
|
||||||
};
|
};
|
||||||
|
@ -136,7 +140,7 @@ public:
|
||||||
LGB_GIMMICK_HEADER header;
|
LGB_GIMMICK_HEADER header;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string gimmickFileName;
|
std::string gimmickFileName;
|
||||||
|
|
||||||
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 );
|
||||||
|
@ -145,6 +149,45 @@ public:
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LGB_ENPC_HEADER : public LGB_ENTRY_HEADER
|
||||||
|
{
|
||||||
|
uint32_t enpcId;
|
||||||
|
uint8_t unknown1[0x24];
|
||||||
|
};
|
||||||
|
|
||||||
|
class LGB_ENPC_ENTRY : public LGB_MODEL_ENTRY
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LGB_ENPC_HEADER header;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
LGB_ENPC_ENTRY( char* buf, uint32_t offset )
|
||||||
|
{
|
||||||
|
header = *reinterpret_cast< LGB_ENPC_HEADER* >( buf + offset );
|
||||||
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LGB_EOBJ_HEADER : public LGB_ENTRY_HEADER
|
||||||
|
{
|
||||||
|
uint32_t eobjId;
|
||||||
|
uint8_t unknown1[0x10];
|
||||||
|
};
|
||||||
|
|
||||||
|
class LGB_EOBJ_ENTRY : public LGB_MODEL_ENTRY
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LGB_EOBJ_HEADER header;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
LGB_EOBJ_ENTRY( char* buf, uint32_t offset )
|
||||||
|
{
|
||||||
|
header = *reinterpret_cast< LGB_EOBJ_HEADER* >( buf + offset );
|
||||||
|
std::cout << header.eobjId << std::endl;
|
||||||
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct LGB_GROUP_HEADER
|
struct LGB_GROUP_HEADER
|
||||||
{
|
{
|
||||||
uint32_t unknown;
|
uint32_t unknown;
|
||||||
|
@ -167,30 +210,38 @@ struct LGB_GROUP
|
||||||
LGB_FILE* parent;
|
LGB_FILE* parent;
|
||||||
LGB_GROUP_HEADER header;
|
LGB_GROUP_HEADER header;
|
||||||
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;
|
||||||
const auto entriesOffset = offset + header.entriesOffset;
|
const auto entriesOffset = offset + header.entriesOffset;
|
||||||
for( auto i = 0; i < header.entryCount; ++i )
|
for( auto i = 0; i < header.entryCount; ++i )
|
||||||
{
|
{
|
||||||
const auto entryOffset = entriesOffset + *reinterpret_cast<int32_t*>( buf + ( entriesOffset + i * 4 ) );
|
const auto entryOffset = entriesOffset + *reinterpret_cast< int32_t* >( buf + ( entriesOffset + i * 4 ) );
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto type = *reinterpret_cast<LgbEntryType*>( buf + entryOffset );
|
const auto type = *reinterpret_cast<LgbEntryType*>( buf + entryOffset );
|
||||||
if( type == LgbEntryType::BgParts )
|
if( type == LgbEntryType::BgParts )
|
||||||
{
|
{
|
||||||
entries.push_back( std::make_shared<LGB_BGPARTS_ENTRY>( buf, entryOffset ) );
|
entries.push_back( std::make_shared< LGB_BGPARTS_ENTRY >( buf, entryOffset ) );
|
||||||
}
|
}
|
||||||
else if( type == LgbEntryType::Gimmick )
|
else if( type == LgbEntryType::Gimmick )
|
||||||
{
|
{
|
||||||
entries.push_back( std::make_shared<LGB_GIMMICK_ENTRY>( buf, entryOffset ) );
|
entries.push_back( std::make_shared< LGB_GIMMICK_ENTRY >( buf, entryOffset ) );
|
||||||
|
}
|
||||||
|
else if( type == LgbEntryType::EventNpc )
|
||||||
|
{
|
||||||
|
entries.push_back( std::make_shared< LGB_ENPC_ENTRY >( buf, entryOffset ) );
|
||||||
|
}
|
||||||
|
else if( type == LgbEntryType::EventObject )
|
||||||
|
{
|
||||||
|
entries.push_back( std::make_shared< LGB_EOBJ_ENTRY >( buf, entryOffset ) );
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
else
|
else
|
||||||
|
@ -223,11 +274,11 @@ struct LGB_FILE_HEADER
|
||||||
struct LGB_FILE
|
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::runtime_error( "Invalid LGB file!" );
|
throw std::runtime_error( "Invalid LGB file!" );
|
||||||
|
|
||||||
|
@ -236,7 +287,7 @@ struct LGB_FILE
|
||||||
constexpr auto baseOffset = sizeof( header );
|
constexpr auto baseOffset = sizeof( header );
|
||||||
for( auto i = 0; i < header.groupCount; ++i )
|
for( auto i = 0; i < header.groupCount; ++i )
|
||||||
{
|
{
|
||||||
const auto groupOffset = baseOffset + *reinterpret_cast<int32_t*>( buf + ( baseOffset + i * 4 ) );
|
const auto groupOffset = baseOffset + *reinterpret_cast< int32_t* >( buf + ( baseOffset + i * 4 ) );
|
||||||
const auto group = LGB_GROUP( buf, this, groupOffset );
|
const auto group = LGB_GROUP( buf, this, groupOffset );
|
||||||
groups.push_back( group );
|
groups.push_back( group );
|
||||||
}
|
}
|
||||||
|
@ -277,4 +328,4 @@ std::map<std::string, LGB_FILE> getLgbFiles( const std::string& dir )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
#endif
|
#endif
|
|
@ -5,6 +5,7 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "pcb.h"
|
#include "pcb.h"
|
||||||
#include "lgb.h"
|
#include "lgb.h"
|
||||||
|
@ -20,14 +21,15 @@
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
std::string gamePath("C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv");
|
||||||
|
std::unordered_map< uint32_t, std::string > eobjNameMap;
|
||||||
|
|
||||||
enum class TerritoryTypeExdIndexes : size_t
|
enum class TerritoryTypeExdIndexes : size_t
|
||||||
{
|
{
|
||||||
TerritoryType = 0,
|
TerritoryType = 0,
|
||||||
Path = 1
|
Path = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string gamePath( "C:\\Program Files (x86)\\SquareEnix\\FINAL FANTASY XIV - A Realm Reborn\\game\\sqpack\\ffxiv" );
|
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
struct face
|
struct face
|
||||||
|
@ -91,9 +93,51 @@ int parseBlockEntry( char* data, std::vector<PCB_BLOCK_ENTRY>& entries, int gOff
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dumpLevelExdEntries( uint32_t zoneId, const std::string& name = std::string() )
|
||||||
|
{
|
||||||
|
xiv::dat::GameData dat( gamePath );
|
||||||
|
xiv::exd::ExdData eData( dat );
|
||||||
|
auto& cat = eData.get_category( "Level" );
|
||||||
|
auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::none ) );
|
||||||
|
|
||||||
|
std::string fileName( name + "_" + std::to_string( zoneId ) + "_Level" + ".csv" );
|
||||||
|
std::ofstream outfile( fileName, std::ios::trunc );
|
||||||
|
|
||||||
|
if( outfile.good() )
|
||||||
|
{
|
||||||
|
outfile.close();
|
||||||
|
outfile.open( fileName, std::ios::app );
|
||||||
|
|
||||||
|
for( auto& row : exd.get_rows() )
|
||||||
|
{
|
||||||
|
auto id = row.first;
|
||||||
|
auto& fields = row.second;
|
||||||
|
auto x = *boost::get< float >( &fields.at( 0 ) );
|
||||||
|
auto y = *boost::get< float >( &fields.at( 1 ) );
|
||||||
|
auto z = *boost::get< float >( &fields.at( 2 ) );
|
||||||
|
auto yaw = *boost::get< float >( &fields.at( 3 ) );
|
||||||
|
auto radius = *boost::get< float >( &fields.at( 4 ) );
|
||||||
|
auto type = *boost::get< uint8_t >( &fields.at( 5 ) );
|
||||||
|
auto objectid = *boost::get< uint32_t >( &fields.at( 6 ) );
|
||||||
|
auto zone = *boost::get< uint16_t >( &fields.at( 9 ) );
|
||||||
|
|
||||||
|
if( zone == zoneId )
|
||||||
|
{
|
||||||
|
std::string outStr(
|
||||||
|
std::to_string( id ) + ", " + std::to_string( objectid ) + ", " +
|
||||||
|
std::to_string( x ) + ", " + std::to_string( y ) + ", " + std::to_string( z ) + ", " +
|
||||||
|
std::to_string( yaw ) + ", " + std::to_string( radius ) + ", " + std::to_string( type ) + "\n"
|
||||||
|
);
|
||||||
|
outfile.write( outStr.c_str(), outStr.size() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string zoneNameToPath( const std::string& name )
|
std::string zoneNameToPath( const std::string& name )
|
||||||
{
|
{
|
||||||
std::string path;
|
std::string path;
|
||||||
|
uint32_t id;
|
||||||
#ifdef STANDALONE
|
#ifdef STANDALONE
|
||||||
auto inFile = std::ifstream( "territorytype.exh.csv" );
|
auto inFile = std::ifstream( "territorytype.exh.csv" );
|
||||||
if( inFile.good() )
|
if( inFile.good() )
|
||||||
|
@ -107,6 +151,7 @@ std::string zoneNameToPath( const std::string& name )
|
||||||
{
|
{
|
||||||
if( name == match[2].str() )
|
if( name == match[2].str() )
|
||||||
{
|
{
|
||||||
|
id = match[1].str();
|
||||||
path = match[3].str();
|
path = match[3].str();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -126,6 +171,7 @@ std::string zoneNameToPath( const std::string& name )
|
||||||
if( teriName.empty() )
|
if( teriName.empty() )
|
||||||
continue;
|
continue;
|
||||||
auto teriPath = *boost::get< std::string >( &fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Path ) ) );
|
auto teriPath = *boost::get< std::string >( &fields.at( static_cast< size_t >( TerritoryTypeExdIndexes::Path ) ) );
|
||||||
|
id = row.first;
|
||||||
if( boost::iequals( name, teriName ) )
|
if( boost::iequals( name, teriName ) )
|
||||||
{
|
{
|
||||||
path = teriPath;
|
path = teriPath;
|
||||||
|
@ -146,9 +192,34 @@ std::string zoneNameToPath( const std::string& name )
|
||||||
throw std::runtime_error( "Unable to find path for " + name +
|
throw std::runtime_error( "Unable to find path for " + name +
|
||||||
".\n\tPlease double check spelling or open 0a0000.win32.index with FFXIV Explorer and extract territorytype.exh as CSV\n\tand copy territorytype.exh.csv into pcb_reader.exe directory if using standalone" );
|
".\n\tPlease double check spelling or open 0a0000.win32.index with FFXIV Explorer and extract territorytype.exh as CSV\n\tand copy territorytype.exh.csv into pcb_reader.exe directory if using standalone" );
|
||||||
}
|
}
|
||||||
|
dumpLevelExdEntries( id, name );
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void loadEobjNames()
|
||||||
|
{
|
||||||
|
xiv::dat::GameData dat( gamePath );
|
||||||
|
xiv::exd::ExdData eData( dat );
|
||||||
|
auto& cat = eData.get_category( "EObjName" );
|
||||||
|
auto exd = static_cast< xiv::exd::Exd >( cat.get_data_ln( xiv::exd::Language::en ) );
|
||||||
|
for( auto& row : exd.get_rows() )
|
||||||
|
{
|
||||||
|
auto id = row.first;
|
||||||
|
auto& fields = row.second;
|
||||||
|
auto name = *boost::get< std::string >( &fields.at( 0 ) );
|
||||||
|
eobjNameMap[id] = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeEobjEntry( std::ofstream& out, LGB_EOBJ_ENTRY* pEobj, const std::string& name )
|
||||||
|
{
|
||||||
|
std::string outStr(
|
||||||
|
std::to_string( pEobj->header.eobjId ) + ", \"" + name + "\", " +
|
||||||
|
std::to_string( pEobj->header.translation.x ) + ", " + std::to_string( pEobj->header.translation.y ) + ", " + std::to_string( pEobj->header.translation.z ) + "\n"
|
||||||
|
);
|
||||||
|
out.write( outStr.c_str(), outStr.size() );
|
||||||
|
}
|
||||||
|
|
||||||
void readFileToBuffer( const std::string& path, std::vector< char >& buf )
|
void readFileToBuffer( const std::string& path, std::vector< char >& buf )
|
||||||
{
|
{
|
||||||
auto inFile = std::ifstream( path, std::ios::binary );
|
auto inFile = std::ifstream( path, std::ios::binary );
|
||||||
|
@ -187,7 +258,7 @@ int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
const auto& zonePath = zoneNameToPath( zoneName );
|
const auto& zonePath = zoneNameToPath( zoneName );
|
||||||
std::string listPcbPath( zonePath + "/collision/list.pcb" );
|
std::string listPcbPath( zonePath + "/collision/list.pcb" );
|
||||||
std::string bgLgbPath( zonePath + "/level/bg.lgb" );
|
std::string bgLgbPath( zonePath + "/level/planmap.lgb" );
|
||||||
std::string collisionFilePath( zonePath + "/collision/" );
|
std::string collisionFilePath( zonePath + "/collision/" );
|
||||||
std::vector< char > section;
|
std::vector< char > section;
|
||||||
std::vector< char > section1;
|
std::vector< char > section1;
|
||||||
|
@ -215,6 +286,16 @@ int main( int argc, char* argv[] )
|
||||||
std::vector< std::string > stringList;
|
std::vector< std::string > stringList;
|
||||||
|
|
||||||
uint32_t offset1 = 0x20;
|
uint32_t offset1 = 0x20;
|
||||||
|
|
||||||
|
loadEobjNames();
|
||||||
|
std::string eobjFileName( zoneName + "eobj.csv" );
|
||||||
|
std::ofstream eobjOut( eobjFileName, std::ios::trunc );
|
||||||
|
if( !eobjOut.good() )
|
||||||
|
throw std::string( "Unable to create " + zoneName + "_eobj.csv for eobj entries. Run as admin or check there isnt already a handle on the file." ).c_str();
|
||||||
|
|
||||||
|
eobjOut.close();
|
||||||
|
eobjOut.open( eobjFileName, std::ios::app );
|
||||||
|
|
||||||
for( ; ; )
|
for( ; ; )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -435,6 +516,7 @@ int main( int argc, char* argv[] )
|
||||||
{
|
{
|
||||||
auto pGimmick = dynamic_cast< LGB_GIMMICK_ENTRY* >( pEntry.get() );
|
auto pGimmick = dynamic_cast< LGB_GIMMICK_ENTRY* >( pEntry.get() );
|
||||||
auto pBgParts = dynamic_cast< LGB_BGPARTS_ENTRY* >( pEntry.get() );
|
auto pBgParts = dynamic_cast< LGB_BGPARTS_ENTRY* >( pEntry.get() );
|
||||||
|
auto pEventObj = dynamic_cast< LGB_EOBJ_ENTRY* >( pEntry.get() );
|
||||||
|
|
||||||
std::string fileName( "" );
|
std::string fileName( "" );
|
||||||
fileName.resize( 256 );
|
fileName.resize( 256 );
|
||||||
|
@ -494,6 +576,13 @@ int main( int argc, char* argv[] )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( pEventObj )
|
||||||
|
{
|
||||||
|
fileName = pEventObj->name.empty() ? eobjNameMap[pEventObj->header.eobjId] : pEventObj->name;
|
||||||
|
writeEobjEntry( eobjOut, pEventObj, fileName );
|
||||||
|
writeOutput( fileName, &pEventObj->header.scale, &pEventObj->header.rotation, &pEventObj->header.translation );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout << "\n[Info] " << "Loaded " << pcbFiles.size() << " PCB Files \n";
|
std::cout << "\n[Info] " << "Loaded " << pcbFiles.size() << " PCB Files \n";
|
||||||
|
|
|
@ -100,7 +100,7 @@ struct SGB_MODEL_ENTRY : public SGB_GROUP_ENTRY
|
||||||
|
|
||||||
SGB_MODEL_ENTRY( char* buf, uint32_t offset )
|
SGB_MODEL_ENTRY( char* buf, uint32_t offset )
|
||||||
{
|
{
|
||||||
header = *reinterpret_cast<SGB_MODEL_HEADER*>( buf + offset );
|
header = *reinterpret_cast< SGB_MODEL_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 );
|
||||||
|
@ -112,25 +112,25 @@ struct SGB_GROUP
|
||||||
SGB_GROUP_HEADER header;
|
SGB_GROUP_HEADER header;
|
||||||
std::string name;
|
std::string name;
|
||||||
SGB_FILE* parent;
|
SGB_FILE* parent;
|
||||||
std::vector<std::shared_ptr<SGB_GROUP_ENTRY>> entries;
|
std::vector< std::shared_ptr< SGB_GROUP_ENTRY > > entries;
|
||||||
|
|
||||||
SGB_GROUP( char* buf, SGB_FILE* file, uint32_t fileSize, uint32_t offset )
|
SGB_GROUP( char* buf, SGB_FILE* file, uint32_t fileSize, uint32_t offset )
|
||||||
{
|
{
|
||||||
parent = file;
|
parent = file;
|
||||||
header = *reinterpret_cast<SGB_GROUP_HEADER*>( buf + offset );
|
header = *reinterpret_cast< SGB_GROUP_HEADER* >( buf + offset );
|
||||||
name = std::string( buf + offset + header.nameOffset );
|
name = std::string( buf + offset + header.nameOffset );
|
||||||
|
|
||||||
auto entriesOffset = offset + sizeof( header );
|
auto entriesOffset = offset + sizeof( header );
|
||||||
|
|
||||||
for( auto i = 0; i < header.entryCount; ++i )
|
for( auto i = 0; i < header.entryCount; ++i )
|
||||||
{
|
{
|
||||||
auto entryOffset = entriesOffset + *reinterpret_cast<uint32_t*>( buf + ( entriesOffset + (i * 4) ) );
|
auto entryOffset = entriesOffset + *reinterpret_cast< uint32_t* >( buf + ( entriesOffset + ( i * 4 ) ) );
|
||||||
if( entryOffset > fileSize )
|
if( entryOffset > fileSize )
|
||||||
throw std::runtime_error( "SGB_GROUP entry offset was larger than SGB file size!" );
|
throw std::runtime_error( "SGB_GROUP entry offset was larger than SGB file size!" );
|
||||||
auto type = *reinterpret_cast<uint32_t*>( buf + entryOffset );
|
auto type = *reinterpret_cast< uint32_t* >( buf + entryOffset );
|
||||||
if( type == SgbGroupEntryType::Model )
|
if( type == SgbGroupEntryType::Model )
|
||||||
{
|
{
|
||||||
entries.push_back( std::make_shared<SGB_MODEL_ENTRY>( buf, entryOffset ) );
|
entries.push_back( std::make_shared< SGB_MODEL_ENTRY >( buf, entryOffset ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +179,7 @@ struct SGB_FILE
|
||||||
SGB_FILE( char* buf )
|
SGB_FILE( char* buf )
|
||||||
{
|
{
|
||||||
constexpr int baseOffset = 0x14;
|
constexpr int baseOffset = 0x14;
|
||||||
header = *reinterpret_cast<SGB_HEADER*>( buf );
|
header = *reinterpret_cast< SGB_HEADER* >( buf );
|
||||||
|
|
||||||
if( strncmp( &header.magic[0], "SGB1", 4 ) != 0 || strncmp( &header.magic2[0], "SCN1", 4 ) != 0 )
|
if( strncmp( &header.magic[0], "SGB1", 4 ) != 0 || strncmp( &header.magic2[0], "SCN1", 4 ) != 0 )
|
||||||
throw std::runtime_error( "Unable to load SGB File!" );
|
throw std::runtime_error( "Unable to load SGB File!" );
|
||||||
|
|
Loading…
Add table
Reference in a new issue