From af56b6d2c69e81ff19acd74e7558796544edafdf Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Tue, 27 Jun 2023 00:26:47 -0700 Subject: [PATCH] describe how extension data works --- src/Player.cc | 10 +++++++--- src/Player.hh | 31 +++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/Player.cc b/src/Player.cc index 6349e0d7..bf3139e5 100644 --- a/src/Player.cc +++ b/src/Player.cc @@ -79,7 +79,7 @@ PlayerDispDataBB PlayerDispDataDCPCV3::to_bb() const { bb.visual.name = " 0"; bb.name = add_language_marker(this->visual.name, 'J'); bb.config = this->config; - bb.technique_levels = this->technique_levels; + bb.technique_levels = this->v1_technique_levels; return bb; } @@ -93,7 +93,7 @@ PlayerDispDataDCPCV3 PlayerDispDataBB::to_dcpcv3() const { ret.visual = this->visual; ret.visual.name = remove_language_marker(this->name); ret.config = this->config; - ret.technique_levels = this->technique_levels; + ret.v1_technique_levels = this->technique_levels; return ret; } @@ -496,11 +496,15 @@ PlayerInventoryItem::PlayerInventoryItem() { PlayerInventoryItem::PlayerInventoryItem(const PlayerBankItem& src) : present(1), + extension_data1(0), + extension_data2(0), flags(0), data(src.data) {} void PlayerInventoryItem::clear() { - this->present = 0x00000000; + this->present = 0x0000; + this->extension_data1 = 0x00; + this->extension_data2 = 0x00; this->flags = 0x00000000; this->data.clear(); } diff --git a/src/Player.hh b/src/Player.hh index 0b18816c..12ea1c2e 100644 --- a/src/Player.hh +++ b/src/Player.hh @@ -17,8 +17,35 @@ struct PlayerBankItem; +// PSO V2 stored some extra data in the character structs in a format that I'm +// sure Sega thought was very clever for backward compatibility, but for us is +// just plain annoying. Specifically, they used the third and fourth bytes of +// the InventoryItem struct to store some things not present in V1. The game +// stores arrays of bytes striped across these structures. In newserv, we call +// those fields extension_data. They contain: +// items[0].extension_data1 through items[19].extension_data1: +// Extended technique levels. The values in the v1_technique_levels array +// only go up to 14 (tech level 15); if the player has a technique above +// level 15, the corresponding extension_data1 field holds the remaining +// levels (so a level 20 tech would have 14 in v1_technique_levels and 5 +// in the corresponding item's extension_data1 field). +// items[0].extension_data2 through items[3].extension_data2: +// The value known as unknown_a1 in the PSOGCCharacterFile::Character +// struct. See SaveFileFormats.hh. +// items[4].extension_data2 through items[7].extension_data2: +// The timestamp when the character was last saved, in seconds since +// January 1, 2000. Stored little-endian, so items[4] contains the LSB. +// items[8].extension_data2 through items[12].extension_data2: +// Number of power materials, mind materials, evade materials, def +// materials, and luck materials (respectively) used by the player. +// items[13].extension_data2 through items[15].extension_data2: +// Unknown. These are not an array, but do appear to be related. + struct PlayerInventoryItem { // 0x1C bytes - le_uint32_t present; + le_uint16_t present; + // See note above about these fields + uint8_t extension_data1; + uint8_t extension_data2; le_uint32_t flags; // 8 = equipped ItemData data; @@ -125,7 +152,7 @@ struct PlayerDispDataDCPCV3 { /* 00 */ PlayerStats stats; /* 24 */ PlayerVisualConfig visual; /* 74 */ parray config; - /* BC */ parray technique_levels; + /* BC */ parray v1_technique_levels; /* D0 */ // Note: This struct has a default constructor because it's used in a command