diff --git a/src/Episode3.hh b/src/Episode3.hh new file mode 100644 index 00000000..1379e7fd --- /dev/null +++ b/src/Episode3.hh @@ -0,0 +1,164 @@ + +struct Ep3Deck { + // TODO: are the last 4 bytes actually part of this? They don't seem to be + // used for anything else, but the game limits the name to 14 chars + a + // language marker, which equals exactly 0x10 characters. + ptext name; + // List of card IDs. The card count is the number of nonzero entries here + // before a zero entry (or 50 if no entries are nonzero). The first card ID is + // the SC card, which the game implicitly subtracts from the limit - so a + // valid deck should actually have 31 cards in it. + parray card_ids; + be_uint32_t unknown_a1; + // Last modification time + le_uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t unknown_a2; +} __attribute__((packed)); // 0x84 bytes in total + +struct Ep3Config { + // Offsets in comments in this struct are relative to start of 61/98 command + /* 0728 */ parray unknown_a1; + /* 1B5C */ parray decks; + /* 2840 */ uint64_t unknown_a2; + /* 2848 */ be_uint32_t offline_clv_exp; // CLvOff = this / 100 + /* 284C */ be_uint32_t online_clv_exp; // CLvOn = this / 100 + /* 2850 */ parray unknown_a3; + /* 299C */ ptext name; + // Other records are probably somewhere in here - e.g. win/loss, play time, etc. + /* 29AC */ parray unknown_a4; +} __attribute__((packed)); + +struct Ep3BattleRules { + // When this structure is used in a map/quest definition, FF in any of these + // fields means the user is allowed to override it. Any non-FF fields are + // fixed for the map/quest and cannot be overridden. + uint8_t overall_time_limit; // In increments of 5 minutes; 0 = unlimited + uint8_t phase_time_limit; // In seconds; 0 = unlimited + uint8_t allowed_cards; // 0 = any, 1 = N-rank only, 2 = N and R, 3 = N, R, and S + uint8_t min_dice; // 0 = default (1) + // 4 + uint8_t max_dice; // 0 = default (6) + uint8_t disable_deck_shuffle; // 0 = shuffle on, 1 = off + uint8_t disable_deck_loop; // 0 = loop on, 1 = off + uint8_t char_hp; + // 8 + uint8_t hp_type; // 0 = defeat player, 1 = defeat team, 2 = common hp + uint8_t no_assist_cards; // 1 = assist cards disallowed + uint8_t disable_dialogue; // 0 = dialogue on, 1 = dialogue off + uint8_t dice_exchange_mode; // 0 = high attack, 1 = high defense, 2 = none + // C + uint8_t disable_dice_boost; // 0 = dice boost on, 1 = off + parray unused; +} __attribute__((packed)); + + + +struct Ep3MapList { + be_uint32_t num_maps; + be_uint32_t unknown_a1; // Always 0? + be_uint32_t strings_offset; // From after total_size field (add 0x10 to this value) + be_uint32_t total_size; // Including header, entries, and strings + + struct Entry { // Should be 0x220 bytes in total + // These 3 fields probably include the location ID (scenery to load) and the + // music ID + be_uint16_t scene_data0; + be_uint16_t scene_data1; + be_uint16_t scene_data2; + be_uint16_t map_number; + // Text offsets are from the beginning of the strings block after all map + // entries (that is, add strings_offset to them to get the string offset) + be_uint32_t name_offset; + be_uint32_t location_name_offset; + be_uint32_t quest_name_offset; + be_uint32_t description_offset; + be_uint16_t width; + be_uint16_t height; + parray map_tiles; + parray modification_tiles; + be_uint32_t unknown_a2; // Seems to always be 0xFF000000 + } __attribute__((packed)); + + // Variable-length fields: + // Entry entries[num_maps]; + // char strings[...EOF]; // Null-terminated strings, pointed to by offsets in Entry structs +} __attribute__((packed)); + +struct Ep3Map { // .mnm file format (after decompression) + /* 0000 */ be_uint32_t unknown_a1; + /* 0004 */ be_uint32_t map_number; + /* 0008 */ uint8_t width; + /* 0009 */ uint8_t height; + /* 000A */ uint8_t scene_data2; // TODO: What is this? + // All alt_maps fields (including the floats) past num_alt_maps are filled in + // with FF. For example, if num_alt_maps == 8, the last two fields in each + // alt_maps array are filled with FF. + /* 000B */ uint8_t num_alt_maps; // TODO: What are the alt maps for? + // In the map_tiles array, the values are: + // 00 = not a valid tile + // 01 = valid tile unless punched out (later) + // 02 = team A start (1v1) + // 03, 04 = team A start (2v2) + // 05 = ??? + // 06, 07 = team B start (2v2) + // 08 = team B start (1v1) + // Note that the game displays the map reversed vertically in the preview + // window. For example, player 1 is on team A, which usually starts at the top + // of the map as defined in this struct, or at the bottom as shown in the + // preview window. + /* 000C */ parray map_tiles; + /* 010C */ parray unknown_a2; + /* 0118 */ parray alt_maps1[0x0A]; + /* 0B18 */ parray alt_maps2[0x0A]; + /* 1518 */ parray alt_maps_unknown_a3[0x0A]; + /* 17E8 */ parray alt_maps_unknown_a4[0x0A]; + /* 1AB8 */ parray unknown_a5; + // In the modification_tiles array, the values are: + // 10 = blocked (as if the corresponding map_tiles value was 00) + // 20 = blocked (maybe one of 10 or 20 are passable by Aerial characters though) + // 30, 31 = teleporters (green, red) + // 40-44 = ???? (used in 244, 2E4, 2F9) + // 50 = appears as improperly-z-buffered teal cube in preview + // TODO: There may be more values that are valid here. + /* 1C68 */ parray modification_tiles; + // Note: The rules are near the end of this struct (starting 0x14 bytes before the end) + /* 1D68 */ parray unknown_a6; + /* 1DDC */ Ep3BattleRules default_rules; + /* 1DEC */ parray unknown_a7; + /* 1DF0 */ ptext map_name; + /* 1E04 */ ptext location_name; + /* 1E18 */ ptext quest_name; // Same a location_name for non-quest maps + /* 1E54 */ ptext description; + /* 1FE4 */ be_uint16_t scene_data0; + /* 1FE6 */ be_uint16_t scene_data1; + struct NPCDeck { + ptext name; + parray card_ids; // Last one appears to always be FFFF + } __attribute__((packed)); + /* 1FE8 */ NPCDeck npc_decks[3]; // Unused if name[0] == 0 + struct NPCCharacter { + parray unknown_a1; + parray unknown_a2; + ptext name; + parray unknown_a3; + } __attribute__((packed)); + /* 20F0 */ parray npc_chars; // Unused if name[0] == 0 + /* 242C */ parray unknown_a8; // Always FF? + /* 2440 */ ptext before_message; + /* 25D0 */ ptext after_message; + /* 2760 */ ptext dispatch_message; // Usually "You can only dispatch " or blank + struct DialogueSet { + be_uint16_t unknown_a1; + be_uint16_t unknown_a2; // Always 0x0064 if valid, 0xFFFF if unused? + ptext strings[4]; + } __attribute__((packed)); // Total size: 0x104 bytes + /* 28F0 */ parray dialogue_sets[3]; // Up to 0x10 per valid NPC + /* 59B0 */ be_uint16_t reward_card_id; // TODO: This could be an array. The only examples I've seen have only one here + /* 59B2 */ parray unknown_a9; + /* 5A18 */ +} __attribute__((packed)); diff --git a/src/Player.hh b/src/Player.hh index d4a80ecb..74e76e72 100644 --- a/src/Player.hh +++ b/src/Player.hh @@ -10,6 +10,7 @@ #include "LevelTable.hh" #include "Version.hh" #include "Text.hh" +#include "Episode3.hh" @@ -254,41 +255,6 @@ struct KeyAndTeamConfigBB { -struct Ep3Deck { - // TODO: are the last 4 bytes actually part of this? They don't seem to be - // used for anything else, but the game limits the name to 14 chars + a - // language marker, which equals exactly 0x10 characters. - ptext name; - // List of card IDs. The card count is the number of nonzero entries here - // before a zero entry (or 50 if no entries are nonzero). The first card ID is - // the SC card, which the game implicitly subtracts from the limit - so a - // valid deck should actually have 31 cards in it. - le_uint16_t card_ids[50]; - uint32_t unknown_a1; - // Last modification time - le_uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t unknown_a2; -} __attribute__((packed)); - -struct Ep3Config { - parray unknown_a1; // at 728 in 61/98 command - Ep3Deck decks[25]; // at 1B5C in 61/98 command - uint64_t unknown_a2; // at 2840 in 61/98 command - be_uint32_t offline_clv_exp; // CLvOff = this / 100 - be_uint32_t online_clv_exp; // CLvOn = this / 100 - parray unknown_a3; // at 2850 in 61/98 command - ptext name; // at 299C in 61/98 command - // Other records are probably somewhere in here - e.g. win/loss, play time, etc. - parray unknown_a4; // at 29AC in 61/98 command -} __attribute__((packed)); - - - struct PlayerLobbyDataPC { le_uint32_t player_tag; le_uint32_t guild_card;