struct BmgHeader
{
u64 magic; // "MESGbmg1"
u32 size; // total file size
u32 sectionCnt; // number of sections
u32 pad1; // 0x10 bytes of padding
u32 pad2;
u32 pad3;
u32 pad4;
}__attribute__((packed));
// 0x10 bytes
struct Inf1Header
{
u32 magic; // INF1 - 0x494e4631
u32 size; // section size
u16 numMessages; // number of messages
u16 four; // i guess this is the size of each entry in the INF1 section?
u32 pad;
}__attribute__((packed));
// 0x8 bytes
struct Dat1Header
{
u32 magic; // DAT1 - 0x44415431
u32 size; // section size
}__attribute__((packed));
bool Bmg::SetResource( const u8* stuff, u32 len )
{
Reset();
if( !stuff || len < 0x40 )
{
gprintf( "data is too small\n" );
return false;
}
// i didnt see the system menu checking the header, but it cant be a bad idea to take a peek at it
bmgHeader = (BmgHeader*)stuff;
if( bmgHeader->magic != 0x4d455347626d6731ull || bmgHeader->size < len || bmgHeader->sectionCnt != 2 )
{
gprintf( "bad file\n" );
Reset();
return false;
}
u32 r8 = 0x20;
for( u32 i = 0; i < bmgHeader->sectionCnt; i++ )
{
u32 magic = *(u32*)( stuff + r8 );
u32 sectionSize = *(u32*)( stuff + r8 + 4 );
if( sectionSize + r8 > len )
{
gprintf( "bad file 2 %08x %08x %08x\n", sectionSize, r8, len );
hexdump( stuff, 0x40 );
Reset();
return false;
}
if( magic == 0x494E4631 )// INF1
{
inf1Header = (Inf1Header*)( stuff + r8 );
}
else if( magic == 0x44415431 )// DAT1
{
dat1Header = (Dat1Header*)( stuff + r8 );
}
r8 += sectionSize;
}
if( !inf1Header || !dat1Header )
{
gprintf( "failed to find the sections\n" );
Reset();
return false;
}
if( inf1Header->size < inf1Header->numMessages * 4 )
{
gprintf( "bad INF1 header\n" );
Reset();
return false;
}
return true;
}
const char16* Bmg::GetMessage( u16 index ) const
{
if( !bmgHeader || index >= inf1Header->numMessages )
{
return NULL;
}
u32 offset = *(u32*)(((u8*)inf1Header) + sizeof( Inf1Header ) + ( index * 4 ));
if( offset >= dat1Header->size )
{
gprintf( "index out of range\n" );
return NULL;
}
return (char16*)( ((u8*)dat1Header) + sizeof( Dat1Header ) + offset );
}