2018-02-26 23:50:50 +01:00
|
|
|
#ifndef _LGB_H
|
|
|
|
#define _LGB_H
|
|
|
|
|
|
|
|
#include <cstring>
|
|
|
|
#include <memory>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <iostream>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "matrix4.h"
|
|
|
|
#include "vec3.h"
|
|
|
|
#include "sgb.h"
|
2019-10-21 23:24:26 +02:00
|
|
|
#include "LgbTypes.h"
|
2018-02-26 23:50:50 +01:00
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
// based on https://github.com/ufx/SaintCoinach/blob/master/SaintCoinach/Graphics/Lgb/
|
2018-02-26 23:50:50 +01:00
|
|
|
struct LGB_FILE;
|
|
|
|
struct LGB_FILE_HEADER;
|
|
|
|
struct LGB_GROUP;
|
|
|
|
struct LGB_GROUP_HEADER;
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
class LgbEntry
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
|
|
|
public:
|
2018-08-29 21:40:59 +02:00
|
|
|
char* m_buf;
|
|
|
|
uint32_t m_offset;
|
2019-10-21 23:24:26 +02:00
|
|
|
InstanceObject header;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
LgbEntry()
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
m_buf = nullptr;
|
|
|
|
m_offset = 0;
|
|
|
|
memset( &header, 0, sizeof( header ) );
|
|
|
|
};
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LgbEntry( char* buf, size_t offset )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
m_buf = buf;
|
2021-11-27 00:53:57 +01:00
|
|
|
m_offset = static_cast< uint32_t >( offset );
|
2019-10-21 23:24:26 +02:00
|
|
|
header = *reinterpret_cast< InstanceObject* >( buf + offset );
|
2018-08-29 21:40:59 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
const LgbEntryType getType() const
|
|
|
|
{
|
|
|
|
return header.type;
|
|
|
|
};
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
virtual ~LgbEntry()
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
class LGB_BGPARTS_ENTRY : public LgbEntry
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
|
|
|
public:
|
2019-10-22 22:34:34 +02:00
|
|
|
BgPartsData data;
|
2018-08-29 21:40:59 +02:00
|
|
|
std::string name;
|
|
|
|
std::string modelFileName;
|
|
|
|
std::string collisionFileName;
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_BGPARTS_ENTRY() = default;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_BGPARTS_ENTRY( char* buf, size_t offset ) : LgbEntry( buf, offset )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2019-10-22 22:34:34 +02:00
|
|
|
data = *reinterpret_cast< BgPartsData* >( buf + offset );
|
2018-08-29 21:40:59 +02:00
|
|
|
name = std::string( buf + offset + header.nameOffset );
|
2019-10-22 22:34:34 +02:00
|
|
|
modelFileName = std::string( buf + offset + data.modelFileOffset );
|
|
|
|
collisionFileName = std::string( buf + offset + data.collisionFileOffset );
|
2018-08-29 21:40:59 +02:00
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
class LGB_GIMMICK_ENTRY : public LgbEntry
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
|
|
|
public:
|
2019-10-22 22:34:34 +02:00
|
|
|
GimmickData data;
|
2018-08-29 21:40:59 +02:00
|
|
|
std::string name;
|
|
|
|
std::string gimmickFileName;
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_GIMMICK_ENTRY( char* buf, size_t offset ) : LgbEntry( buf, offset )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2019-10-22 22:34:34 +02:00
|
|
|
data = *reinterpret_cast< GimmickData* >( buf + offset );
|
2018-08-29 21:40:59 +02:00
|
|
|
name = std::string( buf + offset + header.nameOffset );
|
2019-10-22 22:34:34 +02:00
|
|
|
gimmickFileName = std::string( buf + offset + data.gimmickFileOffset );
|
2018-08-29 21:40:59 +02:00
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
2022-01-23 23:00:50 +01:00
|
|
|
struct LGB_ENPC_ENTRY : public LgbEntry
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
|
|
|
public:
|
2019-10-22 22:34:34 +02:00
|
|
|
ENpcData data;
|
2018-08-29 21:40:59 +02:00
|
|
|
std::string name;
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_ENPC_ENTRY( char* buf, size_t offset ) :
|
2019-10-21 23:24:26 +02:00
|
|
|
LgbEntry( buf, offset )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2019-10-22 22:34:34 +02:00
|
|
|
data = *reinterpret_cast< ENpcData* >( buf + offset );
|
2018-08-29 21:40:59 +02:00
|
|
|
name = std::string( buf + offset + header.nameOffset );
|
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
2022-01-23 23:00:50 +01:00
|
|
|
struct LGB_EOBJ_ENTRY : public LgbEntry
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
2019-10-21 23:24:26 +02:00
|
|
|
public:
|
2019-10-22 22:34:34 +02:00
|
|
|
EObjData data;
|
2019-10-21 23:24:26 +02:00
|
|
|
std::string name;
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_EOBJ_ENTRY( char* buf, size_t offset ) : LgbEntry( buf, offset )
|
2019-10-21 23:24:26 +02:00
|
|
|
{
|
2019-10-22 22:34:34 +02:00
|
|
|
data = *reinterpret_cast< EObjData* >( buf + offset );
|
2019-10-21 23:24:26 +02:00
|
|
|
name = std::string( buf + offset + header.nameOffset );
|
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
struct LGB_MAP_RANGE_ENTRY : public LgbEntry
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
|
|
|
public:
|
2019-10-22 22:34:34 +02:00
|
|
|
MapRangeData data;
|
2018-08-29 21:40:59 +02:00
|
|
|
std::string name;
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_MAP_RANGE_ENTRY( char* buf, size_t offset ) : LgbEntry( buf, offset )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2019-10-22 22:34:34 +02:00
|
|
|
data = *reinterpret_cast< MapRangeData* >( buf + offset );
|
2018-08-29 21:40:59 +02:00
|
|
|
name = std::string( buf + offset + header.nameOffset );
|
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
struct LGB_EXIT_RANGE_ENTRY : public LgbEntry
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
2019-10-21 23:24:26 +02:00
|
|
|
public:
|
2019-10-22 22:34:34 +02:00
|
|
|
ExitRangeData data;
|
2019-10-21 23:24:26 +02:00
|
|
|
std::string name;
|
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_EXIT_RANGE_ENTRY( char* buf, size_t offset ) : LgbEntry( buf, offset )
|
2019-10-21 23:24:26 +02:00
|
|
|
{
|
2019-10-22 22:34:34 +02:00
|
|
|
data = *reinterpret_cast< ExitRangeData* >( buf + offset );
|
2019-10-21 23:24:26 +02:00
|
|
|
name = std::string( buf + offset + header.nameOffset );
|
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
struct LGB_POP_RANGE_ENTRY : public LgbEntry
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
|
|
|
public:
|
2019-10-22 22:34:34 +02:00
|
|
|
PopRangeData data;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_POP_RANGE_ENTRY( char* buf, size_t offset ) : LgbEntry( buf, offset )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
2019-10-22 22:34:34 +02:00
|
|
|
data = *reinterpret_cast< PopRangeData* >( buf + offset );
|
2018-08-29 21:40:59 +02:00
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct LGB_GROUP_HEADER
|
|
|
|
{
|
2019-04-11 22:18:18 +10:00
|
|
|
uint32_t id;
|
2018-08-29 21:40:59 +02:00
|
|
|
int32_t groupNameOffset;
|
|
|
|
int32_t entriesOffset;
|
|
|
|
int32_t entryCount;
|
|
|
|
uint32_t unknown2;
|
|
|
|
uint32_t unknown3;
|
|
|
|
uint32_t unknown4;
|
|
|
|
uint32_t unknown5;
|
|
|
|
uint32_t unknown6;
|
|
|
|
uint32_t unknown7;
|
|
|
|
uint32_t unknown8;
|
|
|
|
uint32_t unknown9;
|
|
|
|
uint32_t unknown10;
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct LGB_GROUP
|
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
LGB_FILE* parent;
|
|
|
|
LGB_GROUP_HEADER header;
|
|
|
|
std::string name;
|
2019-10-21 23:24:26 +02:00
|
|
|
std::vector< std::shared_ptr< LgbEntry > > entries;
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2021-11-27 00:53:57 +01:00
|
|
|
LGB_GROUP( char* buf, LGB_FILE* parentStruct, size_t offset )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
parent = parentStruct;
|
|
|
|
header = *reinterpret_cast< LGB_GROUP_HEADER* >( buf + offset );
|
|
|
|
name = std::string( buf + offset + header.groupNameOffset );
|
|
|
|
const auto entriesOffset = offset + header.entriesOffset;
|
|
|
|
for( auto i = 0; i < header.entryCount; ++i )
|
|
|
|
{
|
|
|
|
const auto entryOffset = entriesOffset + *reinterpret_cast< int32_t* >( buf + ( entriesOffset + i * 4 ) );
|
|
|
|
|
|
|
|
try
|
2018-02-26 23:50:50 +01:00
|
|
|
{
|
2019-10-21 23:24:26 +02:00
|
|
|
const auto type = *reinterpret_cast< LgbEntryType* >( buf + entryOffset );
|
2019-04-11 19:06:27 +10:00
|
|
|
if( type == LgbEntryType::BgParts )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
entries.push_back( std::make_shared< LGB_BGPARTS_ENTRY >( buf, entryOffset ) );
|
|
|
|
}
|
|
|
|
else if( type == LgbEntryType::Gimmick )
|
|
|
|
{
|
|
|
|
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 ) );
|
|
|
|
}
|
2019-10-21 23:24:26 +02:00
|
|
|
else if( type == LgbEntryType::ExitRange )
|
|
|
|
{
|
|
|
|
entries.push_back( std::make_shared< LGB_EXIT_RANGE_ENTRY >( buf, entryOffset ) );
|
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
else if( type == LgbEntryType::MapRange )
|
|
|
|
{
|
2019-10-21 23:24:26 +02:00
|
|
|
entries.push_back( std::make_shared< LGB_MAP_RANGE_ENTRY >( buf, entryOffset ) );
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-10-21 23:24:26 +02:00
|
|
|
entries.push_back( std::make_shared< LgbEntry >( buf, entryOffset ) );
|
2018-08-29 21:40:59 +02:00
|
|
|
}
|
2018-02-26 23:50:50 +01:00
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
catch( std::exception& e )
|
|
|
|
{
|
|
|
|
std::cout << name << " " << e.what() << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct LGB_FILE_HEADER
|
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
char magic[4]; // LGB 1
|
|
|
|
uint32_t fileSize;
|
|
|
|
uint32_t unknown;
|
|
|
|
char magic2[4]; // LGP1
|
|
|
|
uint32_t unknown2;
|
|
|
|
uint32_t unknown3;
|
|
|
|
uint32_t unknown4;
|
|
|
|
uint32_t unknown5;
|
|
|
|
int32_t groupCount;
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct LGB_FILE
|
|
|
|
{
|
2018-08-29 21:40:59 +02:00
|
|
|
LGB_FILE_HEADER header;
|
|
|
|
std::vector< LGB_GROUP > groups;
|
2019-04-11 19:06:27 +10:00
|
|
|
std::string m_name;
|
|
|
|
|
2019-10-21 23:24:26 +02:00
|
|
|
LGB_FILE( char* buf, const std::string& name ) : LGB_FILE( buf )
|
2019-04-11 19:06:27 +10:00
|
|
|
{
|
|
|
|
m_name = name;
|
|
|
|
}
|
2018-08-29 21:40:59 +02:00
|
|
|
|
2019-04-11 19:06:27 +10:00
|
|
|
LGB_FILE( char* buf )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
header = *reinterpret_cast< LGB_FILE_HEADER* >( buf );
|
|
|
|
if( strncmp( &header.magic[ 0 ], "LGB1", 4 ) != 0 || strncmp( &header.magic2[ 0 ], "LGP1", 4 ) != 0 )
|
|
|
|
throw std::runtime_error( "Invalid LGB file!" );
|
|
|
|
|
|
|
|
constexpr auto baseOffset = sizeof( header );
|
2021-11-27 00:53:57 +01:00
|
|
|
for( size_t i = 0; i < header.groupCount; ++i )
|
2018-08-29 21:40:59 +02:00
|
|
|
{
|
|
|
|
const auto groupOffset = baseOffset + *reinterpret_cast< int32_t* >( buf + ( baseOffset + i * 4 ) );
|
|
|
|
const auto group = LGB_GROUP( buf, this, groupOffset );
|
|
|
|
groups.push_back( group );
|
|
|
|
}
|
|
|
|
};
|
2018-02-26 23:50:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
#if __cplusplus >= 201703L
|
|
|
|
#include <experimental/filesystem>
|
|
|
|
std::map<std::string, LGB_FILE> getLgbFiles( const std::string& dir )
|
|
|
|
{
|
|
|
|
namespace fs = std::experimental::filesystem;
|
|
|
|
std::map<std::string, LGB_FILE> fileMap;
|
|
|
|
for( const auto& path : fs::recursive_directory_iterator( dir ) )
|
|
|
|
{
|
|
|
|
if( path.path().extension() == ".lgb" )
|
|
|
|
{
|
|
|
|
const auto& strPath = path.path().string();
|
|
|
|
auto f = fopen( strPath.c_str(), "rb" );
|
|
|
|
fseek( f, 0, SEEK_END );
|
|
|
|
const auto size = ftell( f );
|
|
|
|
std::vector<char> bytes( size );
|
|
|
|
rewind( f );
|
|
|
|
fread( bytes.data(), 1, size, f );
|
|
|
|
fclose( f );
|
|
|
|
try
|
|
|
|
{
|
|
|
|
LGB_FILE lgbFile( bytes.data() );
|
|
|
|
fileMap.insert( std::make_pair( strPath, lgbFile ) );
|
|
|
|
}
|
|
|
|
catch( std::exception& e )
|
|
|
|
{
|
|
|
|
std::cout << "Unable to load " << strPath << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fileMap;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
*/
|
|
|
|
#endif
|