#pragma once #include "Message/BMGEnums.hpp" #include "System/SysNew.hpp" #include "global.h" #include "types.h" #define BMG_MAGIC "MESGbmg1" #define BMG_GET_INF1(pGroups, flags) ((pGroups)->entries[(flags) >> 0x10].func_02037258((flags) & 0xFFFF)) #define BMG_GET_MSG_OFFSET(pGroups, flags) (BMG_GET_INF1((pGroups), (flags))->offset) #define BMG_GET_MSG_ADDR(pGroups, flags) \ ((u32) (pGroups)->entries[(flags) >> 0x10].pDAT1 + (BMG_GET_MSG_OFFSET((pGroups), (flags)) & ~1)) #define BMG_ID(group, infIndex) (((group) << 16) | (infIndex)) enum BMGGroup_ { BMGGroup_regular = 0x00, BMGGroup_select = 0x02, BMGGroup_maingame = 0x03, BMGGroup_battle_parent = 0x04, BMGGroup_battle_common = 0x05, BMGGroup_field = 0x07, BMGGroup_dungeon = 0x08, BMGGroup_train = 0x09, BMGGroup_demo = 0x0A, BMGGroup_castle = 0x0B, BMGGroup_castle_town = 0x0C, BMGGroup_tower = 0x0D, BMGGroup_tower_lobby = 0x0E, BMGGroup_forest = 0x0F, BMGGroup_snow = 0x10, BMGGroup_water = 0x11, BMGGroup_flame = 0x12, BMGGroup_intrain = 0x13, BMGGroup_village = 0x14, BMGGroup_collect = 0x15, BMGGroup_demo01_05 = 0x16, BMGGroup_demo06_10 = 0x17, BMGGroup_demo11_15 = 0x18, BMGGroup_demo16_20 = 0x19, BMGGroup_demo21_25 = 0x1A, BMGGroup_shop = 0x1B, BMGGroup_flame_fld = 0x1C, BMGGroup_post = 0x1D, BMGGroup_desert = 0x1E, BMGGroup_staff = 0x1F, BMGGroup_train_extra = 0x20, }; enum BMGTag { /* "INF1" */ BMG_TAG_INF1 = '1FNI', /* "FLW1" */ BMG_TAG_FLW1 = '1WLF', /* "FLI1" */ BMG_TAG_FLI1 = '1ILF', /* "DAT1" */ BMG_TAG_DAT1 = '1TAD', /* "MID1" */ BMG_TAG_MID1 = '1DIM', /* "STR1" */ BMG_TAG_STR1 = '1RTS', }; enum BMGEncoding { /* 1 */ BMG_ENCODING_CP1252 = 1, /* 2 */ BMG_ENCODING_UTF16_BE, /* 3 */ BMG_ENCODING_SHIFT_JIS, /* 4 */ BMG_ENCODING_UTF8, /* 5 */ BMG_ENCODING_MAX }; //! TODO: find if this is still a thing typedef enum BMGFileIndex { /* 0 */ BMG_FILE_INDEX_0, /* 34 */ BMG_FILE_INDEX_MAX } BMGFileIndex; struct SectionBase { /* 00 */ u32 tag; // "INF1", "DAT1", ... /* 04 */ u32 size; // the size of the section /* 08 */ }; struct BMGHeader { /* 00 */ char magic[8]; // always "MESGbmg1" /* 08 */ u32 fileSize; // the size of the BMG file /* 0C */ u32 numSections; // the number of sections (INF1, DAT1, ...) /* 10 */ u8 encoding; // see `BMGEncoding` /* 11 */ u8 unk_11[0x0F]; // alignment padding? /* 20 */ }; struct EntryINF1 { /* 00 */ u32 offset; // relative to the end of the DAT1 header /* 04 */ u8 mUnk_04; // flags/attributes? (+0x04 to +0x06) /* 05 */ u8 mUnk_05; /* 06 */ u8 mUnk_06; /* 07 */ u8 mUnk_07; /* 08 */ }; struct SectionINF1 { /* 00 */ SectionBase base; /* 08 */ u16 numEntries; /* 0A */ u16 entrySize; /* 0C */ u16 groupId; /* 0E */ u8 colorId; /* 0F */ u8 mUnk_0F[0x1]; // alignment padding? /* 10 */ EntryINF1 *entries; /* 14 */ }; enum InstrType { /* 1 */ FLW1_TYPE_SHOW_MSG = 1, /* 2 */ FLW1_TYPE_BRANCH = 2, /* 3 */ FLW1_TYPE_EVENT = 3, /* 4 */ }; struct InstrShowMsg { /* 01 */ u8 bmgFileIndex; // index into sBMGFiles /* 02 */ u16 msgIndex; // index of INF1 entry /* 04 */ s16 nextIndex; // index of FLW1 entry, 0xFFFF stops the conversation /* 06 */ s16 nextBMGFileIndex; // index into sBMGFiles /* 08 */ }; struct InstrBranch { /* 01 */ u8 mUnk_01; /* 02 */ u16 funcIndex; // index of the query function to run /* 04 */ u16 funcArg; // the argument to use in the function /* 06 */ u16 flwEntry; // the index of the second section table to be used next in the conversation. /* 08 */ }; struct InstrEvent { /* 01 */ u8 funcIndex; // index of the query function to run /* 02 */ u16 flwEntry; // the index of the second section table to be used next in the conversation. /* 04 */ u32 funcArg; // the argument to use in the function /* 08 */ }; struct FLW1Instr { /* 00 */ u8 type; // see InstrType /* 01 */ union { InstrShowMsg showMsg; InstrBranch branch; InstrEvent event; }; /* 09 */ }; struct SectionFLW1 { /* 00 */ SectionBase base; /* 04 */ u16 numInstructions; /* 08 */ u16 numLabels; /* 0C */ u32 mUnk_0C; // always zero? /* 10 */ FLW1Instr *instructions; /* 14 */ s16 *flwEntries; /* 18 */ s8 *bmgFileIndices; /* 1C */ }; struct EntryFLI1 { /* 00 */ u32 msgFlowID; /* 04 */ u32 msgFlowNodeIndex; /* 08 */ }; struct SectionFLI1 { /* 00 */ SectionBase base; /* 04 */ u16 numEntries; /* 08 */ u16 entrySize; /* 0C */ u32 mUnk_0C; // always zero? /* 10 */ EntryFLI1 *entries; /* 14 */ }; struct EntryDAT1 { /* 00 */ char *text; /* 04 */ }; struct SectionDAT1 { /* 00 */ SectionBase base; /* 08 */ EntryDAT1 *entries; /* 0C */ }; struct BMGFileInfo { /* 00 */ BMGHeader *pHeader; // pointer to the file's header /* 04 */ SectionINF1 *pINF1; // pointer to the data informations (INF -> informations) /* 08 */ SectionFLW1 *pFLW1; // pointer to the message flow data (FLW -> flow) /* 0C */ SectionFLI1 *pFLI1; // pointer to the message flow index table (FLI -> flow index table) /* 10 */ SectionDAT1 *pDAT1; // pointer to the data (DAT -> data) /* 14 */ BMGHeader *mUnk_14; // same as pHeader (?) /* 18 */ s16 mUnk_18; // stores `func_020372F0`->param_3 value (currently undetermined purpose) /* 1A */ s16 groupId; // stores the group id /* 1C */ }; class BMGGroups : public SysObject { public: /* 00 */ BMGFileInfo *entries; // accessed with `groupId` /* 04 */ s32 numEntries; /* 08 */ BMGGroups(); ~BMGGroups(); };