implement full character backups on GC

This commit is contained in:
Martin Michelsen
2024-04-06 19:52:22 -07:00
parent 91131f8b36
commit af4d3a3325
64 changed files with 3155 additions and 2208 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ public:
le_uint32_t level;
void print(FILE* stream) const;
} __attribute__((packed));
} __packed_ws__(PlayerEntry, 0x440);
struct Event {
enum class Type : uint8_t {
+2 -1
View File
@@ -6,6 +6,7 @@
#include "../Text.hh"
#include "DataIndexes.hh"
#include "Server.hh"
namespace Episode3 {
@@ -94,7 +95,7 @@ public:
void print(FILE* stream) const;
uint32_t at(size_t index) const;
} __attribute__((packed));
} __packed_ws__(AttackEnvStats, 0x9C);
CardSpecial(std::shared_ptr<Server> server);
std::shared_ptr<Server> server();
+22 -22
View File
@@ -447,7 +447,7 @@ struct Location {
void clear();
void clear_FF();
} __attribute__((packed));
} __packed_ws__(Location, 4);
struct CardDefinition {
struct Stat {
@@ -470,7 +470,7 @@ struct CardDefinition {
void decode_code();
std::string str() const;
JSON json() const;
} __attribute__((packed));
} __packed_ws__(Stat, 4);
struct Effect {
// effect_num is the 1-based index of this effect within the card definition
@@ -507,7 +507,7 @@ struct CardDefinition {
static std::string str_for_arg(const std::string& arg);
std::string str(const char* separator = ", ", const TextSet* text_archive = nullptr) const;
JSON json() const;
} __attribute__((packed));
} __packed_ws__(Effect, 0x20);
/* 0000 */ be_uint32_t card_id;
/* 0004 */ pstring<TextEncoding::SJIS, 0x40> jp_name;
@@ -774,7 +774,7 @@ struct CardDefinition {
void decode_range();
std::string str(bool single_line = true, const TextSet* text_archive = nullptr) const;
JSON json() const;
} __attribute__((packed)); // 0x128 bytes in total
} __packed_ws__(CardDefinition, 0x128);
struct CardDefinitionsFooter {
// Technically the card definitions file is a REL file, so the last 0x20 bytes
@@ -790,7 +790,7 @@ struct CardDefinitionsFooter {
/* 48 */ be_uint32_t footer_offset;
/* 4C */ parray<be_uint32_t, 3> unused2;
/* 58 */
} __attribute__((packed));
} __packed_ws__(CardDefinitionsFooter, 0x58);
struct DeckDefinition {
/* 00 */ pstring<TextEncoding::MARKED, 0x10> name;
@@ -810,7 +810,7 @@ struct DeckDefinition {
/* 82 */ uint8_t second;
/* 83 */ uint8_t unknown_a2;
/* 84 */
} __attribute__((packed));
} __packed_ws__(DeckDefinition, 0x84);
struct PlayerConfig {
// The game splits this internally into two structures. The first column of
@@ -828,7 +828,7 @@ struct PlayerConfig {
// earlier version, this was the offline records structure, but they later
// decided to just count online and offline records together in the main
// records structure and didn't remove the codepath that reads from this.
/* 0138:---- */ PlayerRecords_Battle<true> unused_offline_records;
/* 0138:---- */ PlayerRecordsBattleBE unused_offline_records;
/* 0150:---- */ parray<uint8_t, 4> unknown_a4;
// The PlayerDataSegment structure begins here. In newserv, we combine this
// structure into PlayerConfig since the two are always used together.
@@ -879,7 +879,7 @@ struct PlayerConfig {
struct PlayerReference {
/* 00 */ be_uint32_t guild_card_number;
/* 04 */ pstring<TextEncoding::MARKED, 0x18> name;
} __attribute__((packed));
} __packed_ws__(PlayerReference, 0x1C);
// This array is updated when a battle is started (via a 6xB4x05 command). The
// client adds the opposing players' info to ths first two entries here if the
// opponents are human. (The existing entries are always moved back by two
@@ -902,7 +902,7 @@ struct PlayerConfig {
void decrypt();
void encrypt(uint8_t basis);
} __attribute__((packed));
} __packed_ws__(PlayerConfig, 0x2350);
enum class HPType : uint8_t {
DEFEAT_PLAYER = 0,
@@ -972,7 +972,7 @@ struct Rules {
std::pair<uint8_t, uint8_t> def_dice_range(bool is_1p_2v1) const;
std::string str() const;
} __attribute__((packed));
} __packed_ws__(Rules, 0x14);
struct RulesTrial {
// Most fields here have the same meanings as in the final version.
@@ -996,7 +996,7 @@ struct RulesTrial {
RulesTrial() = default;
RulesTrial(const Rules&);
operator Rules() const;
} __attribute__((packed));
} __packed_ws__(RulesTrial, 0x0C);
struct StateFlags {
/* 00 */ le_uint16_t turn_num;
@@ -1018,7 +1018,7 @@ struct StateFlags {
bool operator!=(const StateFlags& other) const;
void clear();
void clear_FF();
} __attribute__((packed));
} __packed_ws__(StateFlags, 0x18);
struct MapList {
be_uint32_t num_maps;
@@ -1046,18 +1046,18 @@ struct MapList {
/* 021C */ uint8_t map_category;
/* 021D */ parray<uint8_t, 3> unused;
/* 0220 */
} __attribute__((packed));
} __packed_ws__(Entry, 0x220);
// Variable-length fields:
// Entry entries[num_maps];
// char strings[...EOF]; // Null-terminated strings, pointed to by offsets in Entry structs
} __attribute__((packed));
} __packed_ws__(MapList, 0x10);
struct CompressedMapHeader { // .mnm file format
le_uint32_t map_number;
le_uint32_t compressed_data_size;
// Compressed data immediately follows (which decompresses to a MapDefinition)
} __attribute__((packed));
} __packed_ws__(CompressedMapHeader, 8);
struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
// If tag is not 0x00000100, the game considers the map to be corrupt in
@@ -1155,7 +1155,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
std::string str() const;
JSON json() const;
} __attribute__((packed));
} __packed_ws__(CameraSpec, 0x48);
// This array specifies the camera zone maps. A camera zone map is a subset of
// the main map (specified in map_tiles). Tiles that are part of each camera
@@ -1213,7 +1213,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
/* 18 */ parray<be_uint16_t, 0x20> card_ids; // Last one appears to always be FFFF
/* 58 */
JSON json(uint8_t language) const;
} __attribute__((packed));
} __packed_ws__(NPCDeck, 0x58);
/* 1FE8 */ parray<NPCDeck, 3> npc_decks; // Unused if name[0] == 0
// These are almost (but not quite) the same format as the entries in
@@ -1229,7 +1229,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
/* 0018 */ parray<be_uint16_t, 0x7E> params;
/* 0114 */
JSON json(uint8_t language) const;
} __attribute__((packed));
} __packed_ws__(AIParams, 0x114);
/* 20F0 */ parray<AIParams, 3> npc_ai_params; // Unused if name[0] == 0
/* 242C */ parray<uint8_t, 8> unknown_a7;
@@ -1282,7 +1282,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
/* 0004 */ parray<pstring<TextEncoding::MARKED, 0x40>, 4> strings;
/* 0104 */
JSON json(uint8_t language) const;
} __attribute__((packed));
} __packed_ws__(DialogueSet, 0x104);
// There are up to 0x10 of these per valid NPC, but only the first 13 of them
// are used, since each one must have a unique value for .when and the values
@@ -1365,7 +1365,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
bool operator==(const EntryState& other) const = default;
bool operator!=(const EntryState& other) const = default;
JSON json() const;
} __attribute__((packed));
} __packed_ws__(EntryState, 2);
/* 5A10 */ parray<EntryState, 4> entry_states;
/* 5A18 */
@@ -1381,7 +1381,7 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
std::string str(const CardIndex* card_index, uint8_t language) const;
JSON json(uint8_t language) const;
} __attribute__((packed));
} __packed_ws__(MapDefinition, 0x5A18);
struct MapDefinitionTrial {
// This is the format of Episode 3 Trial Edition maps. See the comments in
@@ -1430,7 +1430,7 @@ struct MapDefinitionTrial {
MapDefinitionTrial(const MapDefinition& map);
operator MapDefinition() const;
} __attribute__((packed));
} __packed_ws__(MapDefinitionTrial, 0x41A0);
struct COMDeckDefinition {
size_t index;
+2 -2
View File
@@ -20,7 +20,7 @@ struct NameEntry {
NameEntry();
void clear();
} __attribute__((packed));
} __packed_ws__(NameEntry, 0x14);
struct DeckEntry {
/* 00 */ pstring<TextEncoding::MARKED, 0x10> name;
@@ -37,7 +37,7 @@ struct DeckEntry {
DeckEntry();
void clear();
} __attribute__((packed));
} __packed_ws__(DeckEntry, 0x58);
uint8_t index_for_card_ref(uint16_t card_ref);
uint8_t client_id_for_card_ref(uint16_t card_ref);
+4 -4
View File
@@ -20,7 +20,7 @@ struct MapState {
void clear();
void print(FILE* stream) const;
} __attribute__((packed));
} __packed_ws__(MapState, 0x110);
struct MapAndRulesState {
/* 0000 */ MapState map;
@@ -45,7 +45,7 @@ struct MapAndRulesState {
void set_occupied_bit_for_tile(uint8_t x, uint8_t y);
void clear_occupied_bit_for_tile(uint8_t x, uint8_t y);
} __attribute__((packed));
} __packed_ws__(MapAndRulesState, 0x138);
struct MapAndRulesStateTrial {
/* 0000 */ MapState map;
@@ -65,7 +65,7 @@ struct MapAndRulesStateTrial {
MapAndRulesStateTrial() = default;
MapAndRulesStateTrial(const MapAndRulesState& state);
operator MapAndRulesState() const;
} __attribute__((packed));
} __packed_ws__(MapAndRulesStateTrial, 0x130);
struct OverlayState {
parray<parray<uint8_t, 0x10>, 0x10> tiles;
@@ -75,6 +75,6 @@ struct OverlayState {
OverlayState();
void clear();
} __attribute__((packed));
} __packed_ws__(OverlayState, 0x174);
} // namespace Episode3
+11 -11
View File
@@ -36,7 +36,7 @@ struct Condition {
void clear_FF();
std::string str(std::shared_ptr<const Server> s) const;
} __attribute__((packed));
} __packed_ws__(Condition, 0x10);
struct EffectResult {
/* 00 */ le_uint16_t attacker_card_ref;
@@ -58,7 +58,7 @@ struct EffectResult {
void clear();
std::string str(std::shared_ptr<const Server> s) const;
} __attribute__((packed));
} __packed_ws__(EffectResult, 0x0C);
struct CardShortStatus {
/* 00 */ le_uint16_t card_ref;
@@ -78,7 +78,7 @@ struct CardShortStatus {
void clear_FF();
std::string str(std::shared_ptr<const Server> s) const;
} __attribute__((packed));
} __packed_ws__(CardShortStatus, 0x10);
struct ActionState {
/* 00 */ le_uint16_t client_id;
@@ -99,7 +99,7 @@ struct ActionState {
void clear();
std::string str(std::shared_ptr<const Server> s) const;
} __attribute__((packed));
} __packed_ws__(ActionState, 0x64);
struct ActionChain {
// Note: Episode 3 Trial Edition has a different format for this structure.
@@ -135,7 +135,7 @@ struct ActionChain {
void clear_FF();
std::string str(std::shared_ptr<const Server> s) const;
} __attribute__((packed));
} __packed_ws__(ActionChain, 0x70);
struct ActionChainWithConds {
/* 0000 */ ActionChain chain;
@@ -173,7 +173,7 @@ struct ActionChainWithConds {
uint8_t get_adjusted_move_ability_nte(uint8_t ability) const;
std::string str(std::shared_ptr<const Server> s) const;
} __attribute__((packed));
} __packed_ws__(ActionChainWithConds, 0x100);
struct ActionChainWithCondsTrial {
/* 0000 */ int8_t effective_ap;
@@ -205,7 +205,7 @@ struct ActionChainWithCondsTrial {
ActionChainWithCondsTrial() = default;
ActionChainWithCondsTrial(const ActionChainWithConds& src);
operator ActionChainWithConds() const;
} __attribute__((packed));
} __packed_ws__(ActionChainWithCondsTrial, 0x100);
struct ActionMetadata {
/* 00 */ le_uint16_t card_ref;
@@ -241,7 +241,7 @@ struct ActionMetadata {
uint16_t original_attacker_card_ref);
std::string str(std::shared_ptr<const Server> s) const;
} __attribute__((packed));
} __packed_ws__(ActionMetadata, 0x74);
struct HandAndEquipState {
/* 00 */ parray<uint8_t, 2> dice_results;
@@ -276,7 +276,7 @@ struct HandAndEquipState {
void clear_FF();
std::string str(std::shared_ptr<const Server> s) const;
} __attribute__((packed));
} __packed_ws__(HandAndEquipState, 0x54);
struct PlayerBattleStats {
/* 00 */ le_uint16_t damage_given;
@@ -310,7 +310,7 @@ struct PlayerBattleStats {
static uint8_t rank_for_score(float score);
static const char* name_for_rank(uint8_t rank);
} __attribute__((packed));
} __packed_ws__(PlayerBattleStats, 0x28);
struct PlayerBattleStatsTrial {
/* 00 */ le_uint32_t damage_given = 0;
@@ -323,7 +323,7 @@ struct PlayerBattleStatsTrial {
PlayerBattleStatsTrial() = default;
PlayerBattleStatsTrial(const PlayerBattleStats& data);
operator PlayerBattleStats() const;
} __attribute__((packed));
} __packed_ws__(PlayerBattleStatsTrial, 0x14);
std::vector<uint16_t> get_card_refs_within_range(
const parray<uint8_t, 9 * 9>& range,
+2 -1
View File
@@ -290,7 +290,8 @@ public:
uint8_t is_cpu_player;
PresenceEntry();
void clear();
} __attribute__((packed));
} __packed_ws__(PresenceEntry, 3);
std::shared_ptr<MapAndRulesState> map_and_rules;
bcarray<std::shared_ptr<DeckEntry>, 4> deck_entries;
parray<PresenceEntry, 4> presence_entries;