add notes and support for final PCv2 version

This commit is contained in:
Martin Michelsen
2025-06-14 00:35:56 -07:00
parent 3844c9881c
commit 9621e89cd7
10 changed files with 999 additions and 974 deletions
+38 -37
View File
@@ -457,43 +457,44 @@ The VERS token in client function filenames refers to the specific version of th
The specific versions are: The specific versions are:
| Game | VERS | Architecture | | Game | VERS | CPU architecture |
|------------------------------|------|---------------| |------------------------------|------|--------------------------------|
| PSO DC Network Trial Edition | 1OJ1 | Not supported | | PSO DC Network Trial Edition | 1OJ1 | Client functions not supported |
| PSO DC 11/2000 prototype | 1OJ2 | Not supported | | PSO DC 11/2000 prototype | 1OJ2 | Client functions not supported |
| PSO DC 12/2000 prototype | 1OJ3 | Not supported | | PSO DC 12/2000 prototype | 1OJ3 | Client functions not supported |
| PSO DC 01/2001 prototype | 1OJ4 | Not supported | | PSO DC 01/2001 prototype | 1OJ4 | Client functions not supported |
| PSO DC v1 JP | 1OJF | Not supported | | PSO DC v1 JP | 1OJF | Client functions not supported |
| PSO DC v1 US | 1OEF | Not supported | | PSO DC v1 US | 1OEF | Client functions not supported |
| PSO DC v1 EU | 1OPF | Not supported | | PSO DC v1 EU | 1OPF | Client functions not supported |
| PSO DC 08/2001 prototype | 2OJ5 | SH-4 | | PSO DC 08/2001 prototype | 2OJ5 | SH-4 |
| PSO DC v2 JP | 2OJF | SH-4 | | PSO DC v2 JP | 2OJF | SH-4 |
| PSO DC v2 US | 2OEF | SH-4 | | PSO DC v2 US | 2OEF | SH-4 |
| PSO DC v2 EU | 2OPF | SH-4 | | PSO DC v2 EU | 2OPF | SH-4 |
| PSO PC (v2) | 2OJW | Not supported | | PSO PC (v2) 04/2002 | 2OJW | Client functions not supported |
| PSO GC Trial Edition | 3OJT | PowerPC | | PSO PC (v2) 02/2003 | 2OJZ | Client functions not supported |
| PSO GC v1.2 JP | 3OJ2 | PowerPC | | PSO GC Trial Edition | 3OJT | PowerPC |
| PSO GC v1.3 JP | 3OJ3 | PowerPC | | PSO GC v1.2 JP | 3OJ2 | PowerPC |
| PSO GC v1.4 (Plus) JP | 3OJ4 | PowerPC | | PSO GC v1.3 JP | 3OJ3 | PowerPC |
| PSO GC v1.5 (Plus) JP | 3OJ5 | PowerPC (1) | | PSO GC v1.4 (Plus) JP | 3OJ4 | PowerPC |
| PSO GC v1.0 US | 3OE0 | PowerPC | | PSO GC v1.5 (Plus) JP | 3OJ5 | PowerPC (1) |
| PSO GC v1.1 US | 3OE1 | PowerPC | | PSO GC v1.0 US | 3OE0 | PowerPC |
| PSO GC v1.2 (Plus) US | 3OE2 | PowerPC (1) | | PSO GC v1.1 US | 3OE1 | PowerPC |
| PSO GC v1.0 EU | 3OP0 | PowerPC | | PSO GC v1.2 (Plus) US | 3OE2 | PowerPC (1) |
| PSO GC Ep3 Trial Edition | 3SJT | PowerPC | | PSO GC v1.0 EU | 3OP0 | PowerPC |
| PSO GC Ep3 JP | 3SJ0 | PowerPC | | PSO GC Ep3 Trial Edition | 3SJT | PowerPC |
| PSO GC Ep3 US | 3SE0 | PowerPC (1) | | PSO GC Ep3 JP | 3SJ0 | PowerPC |
| PSO GC Ep3 EU | 3SP0 | PowerPC (1) | | PSO GC Ep3 US | 3SE0 | PowerPC (1) |
| PSO Xbox Beta | 4OJB | x86 | | PSO GC Ep3 EU | 3SP0 | PowerPC (1) |
| PSO Xbox JP Disc | 4OJD | x86 | | PSO Xbox Beta | 4OJB | x86 |
| PSO Xbox JP TU | 4OJU | x86 | | PSO Xbox JP Disc | 4OJD | x86 |
| PSO Xbox US Disc | 4OED | x86 | | PSO Xbox JP TU | 4OJU | x86 |
| PSO Xbox US TU | 4OEU | x86 | | PSO Xbox US Disc | 4OED | x86 |
| PSO Xbox EU Disc | 4OPD | x86 | | PSO Xbox US TU | 4OEU | x86 |
| PSO Xbox EU TU | 4OPU | x86 | | PSO Xbox EU Disc | 4OPD | x86 |
| PSO BB JP 1.25.11 | 59NJ | x86 | | PSO Xbox EU TU | 4OPU | x86 |
| PSO BB JP 1.25.13 | 59NL | x86 | | PSO BB JP 1.25.11 | 59NJ | x86 |
| PSO BB Tethealla | 59NL | x86 | | PSO BB JP 1.25.13 | 59NL | x86 |
| PSO BB Tethealla | 59NL | x86 |
*Notes:* *Notes:*
1. *Client functions are only supported on these versions if EnableSendFunctionCallQuestNumbers is set in config.json. See the comments there for more information.* 1. *Client functions are only supported on these versions if EnableSendFunctionCallQuestNumbers is set in config.json. See the comments there for more information.*
+2 -1
View File
@@ -17,7 +17,8 @@ Version codes (from README.md):
2OJF: PSO DC v2 JP 2OJF: PSO DC v2 JP
2OEF: PSO DC v2 US 2OEF: PSO DC v2 US
2OPF: PSO DC v2 EU 2OPF: PSO DC v2 EU
2OJW: PSO PC (v2) 2OJW: PSO PC (v2) 04/2002
2OJZ: PSO PC (v2) 02/2003
3OJT: PSO GC Trial Edition 3OJT: PSO GC Trial Edition
3OJ2: PSO GC v1.2 JP 3OJ2: PSO GC v1.2 JP
3OJ3: PSO GC v1.3 JP 3OJ3: PSO GC v1.3 JP
+913 -910
View File
File diff suppressed because it is too large Load Diff
+14 -10
View File
@@ -2000,8 +2000,9 @@ struct C_LoginExtended_PC_9D : C_Login_DC_PC_GC_9D {
SC_MeetUserExtension_PC_BB extension; SC_MeetUserExtension_PC_BB extension;
} __packed_ws__(C_LoginExtended_PC_9D, 0x14C); } __packed_ws__(C_LoginExtended_PC_9D, 0x14C);
// 9E (C->S): Log in with client config (V3/BB) // 9E (C->S): Log in with client config (PC/V3/BB)
// Not used on GC Episodes 1&2 Trial Edition. // Not used on GC Episodes 1&2 Trial Edition, nor on v1 or most v2 versions.
// Of all pre-v3 versions, only the latest version of PCv2 appears to use this.
// The extended version of this command is used in the same circumstances as // The extended version of this command is used in the same circumstances as
// when PSO PC uses the extended version of the 9D command. // when PSO PC uses the extended version of the 9D command.
// PSO XB does not send the client config (security data) in the 9E command, // PSO XB does not send the client config (security data) in the 9E command,
@@ -2009,11 +2010,13 @@ struct C_LoginExtended_PC_9D : C_Login_DC_PC_GC_9D {
// retrieve the client config. // retrieve the client config.
// header.flag is 1 if the client has UDP disabled. // header.flag is 1 if the client has UDP disabled.
struct C_Login_GC_9E : C_Login_DC_PC_GC_9D { struct C_Login_PC_GC_9E : C_Login_DC_PC_GC_9D {
parray<uint8_t, 0x20> client_config; parray<uint8_t, 0x20> client_config;
} __packed_ws__(C_Login_GC_9E, 0xE8); } __packed_ws__(C_Login_PC_GC_9E, 0xE8);
struct C_LoginExtended_PC_9E : C_Login_PC_GC_9E {
struct C_LoginExtended_GC_9E : C_Login_GC_9E { SC_MeetUserExtension_PC_BB extension;
} __packed_ws__(C_LoginExtended_PC_9E, 0x16C);
struct C_LoginExtended_GC_9E : C_Login_PC_GC_9E {
SC_MeetUserExtension_DC_V3 extension; SC_MeetUserExtension_DC_V3 extension;
} __packed_ws__(C_LoginExtended_GC_9E, 0x14C); } __packed_ws__(C_LoginExtended_GC_9E, 0x14C);
@@ -2051,12 +2054,13 @@ struct C_LoginExtended_BB_9E {
/* 0170 */ /* 0170 */
} __packed_ws__(C_LoginExtended_BB_9E, 0x170); } __packed_ws__(C_LoginExtended_BB_9E, 0x170);
// 9F (S->C): Request client config / security data (V3/BB) // 9F (S->C): Request client config / security data (PC/V3/BB)
// This command is not valid on PSO GC Episodes 1&2 Trial Edition, nor any // This command is not valid on PSO GC Episodes 1&2 Trial Edition nor on any
// pre-V3 PSO versions. Client will respond with a 9F command. // other pre-v3 versions, except the latest PC v2 version, which does have it.
// Client will respond with a 9F command.
// No arguments // No arguments
// 9F (C->S): Client config / security data response (V3/BB) // 9F (C->S): Client config / security data response (PC/V3/BB)
// The data is opaque to the client, as described at the top of this file. // The data is opaque to the client, as described at the top of this file.
// On BB, this command does not work during the data server phase. // On BB, this command does not work during the data server phase.
+1 -1
View File
@@ -184,7 +184,7 @@ void DownloadSession::send_93_9D_9E(bool extended) {
ret.access_key2 = ret.access_key; ret.access_key2 = ret.access_key;
ret.login_character_name.encode(this->character->disp.name.decode()); ret.login_character_name.encode(this->character->disp.name.decode());
ret.client_config = this->client_config; ret.client_config = this->client_config;
this->channel->send(0x9E, 0x01, &ret, extended ? sizeof(ret) : sizeof(C_Login_GC_9E)); this->channel->send(0x9E, 0x01, &ret, extended ? sizeof(ret) : sizeof(C_Login_PC_GC_9E));
} else if (this->version == Version::XB_V3) { } else if (this->version == Version::XB_V3) {
C_LoginExtended_XB_9E ret; C_LoginExtended_XB_9E ret;
+1 -1
View File
@@ -236,7 +236,7 @@ static asio::awaitable<HandlerResult> S_G_9A(shared_ptr<Client> c, Channel::Mess
// right after the client config data // right after the client config data
c->proxy_session->server_channel->send( c->proxy_session->server_channel->send(
0x9E, 0x01, &cmd, 0x9E, 0x01, &cmd,
cmd.is_extended ? sizeof(C_LoginExtended_GC_9E) : sizeof(C_Login_GC_9E)); cmd.is_extended ? sizeof(C_LoginExtended_GC_9E) : sizeof(C_Login_PC_GC_9E));
co_return HandlerResult::SUPPRESS; co_return HandlerResult::SUPPRESS;
} }
+9
View File
@@ -2095,6 +2095,15 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
// is the last opcode implemented before v3. // is the last opcode implemented before v3.
{0xF8BB, "write_flag_buf_to_event_flags2", "unknownF8BB", {REG}, F_V2_V4}, {0xF8BB, "write_flag_buf_to_event_flags2", "unknownF8BB", {REG}, F_V2_V4},
// TODO(DX): Figure out what these do. They only exist on the latest
// version of PCv2; they do not exist in the more common version of PCv2 on
// the Internet, nor do they exist in any later PSO version (although F8BC
// was replaced with set_episode in GC_V3).
{0xF8BC, "unknown_F8BC", nullptr, {REG, REG}, F_PC_V2}, // regA = client ID, regB = result (TODO)
{0xF8BD, "unknown_F8BD", nullptr, {REG, {REG_SET_FIXED, 15}}, F_PC_V2}, // TODO: Document args
{0xF8BE, "unknown_F8BE", nullptr, {}, F_PC_V2},
{0xF8BF, "unknown_F8BF", nullptr, {}, F_PC_V2},
// Sets the current episode. Must be used in the start label. valueA should // Sets the current episode. Must be used in the start label. valueA should
// be 0 for Episode 1 (which is the default), 1 for Episode 2, or 2 for // be 0 for Episode 1 (which is the default), 1 for Episode 2, or 2 for
// Episode 4 (BB only). // Episode 4 (BB only).
+16 -10
View File
@@ -1211,17 +1211,21 @@ static asio::awaitable<void> on_9D_9E(shared_ptr<Client> c, Channel::Message& ms
} }
} else if (msg.command == 0x9E) { } else if (msg.command == 0x9E) {
const auto& cmd = check_size_t<C_Login_GC_9E>(msg.data, sizeof(C_LoginExtended_GC_9E)); auto handle_cmd = [&]<typename BaseCmdT, typename ExtendedCmdT>() {
base_cmd = &cmd; const auto& cmd = check_size_t<BaseCmdT>(msg.data, sizeof(ExtendedCmdT));
if (cmd.is_extended) { base_cmd = &cmd;
const auto& cmd = check_size_t<C_LoginExtended_GC_9E>(msg.data); if (cmd.is_extended) {
if (cmd.extension.lobby_refs[0].menu_id == MenuID::LOBBY) { const auto& cmd = check_size_t<ExtendedCmdT>(msg.data);
c->preferred_lobby_id = cmd.extension.lobby_refs[0].item_id; if (cmd.extension.lobby_refs[0].menu_id == MenuID::LOBBY) {
c->preferred_lobby_id = cmd.extension.lobby_refs[0].item_id;
}
} }
} };
if (is_v3(c->version())) { if (is_v3(c->version())) {
handle_cmd.template operator()<C_Login_PC_GC_9E, C_LoginExtended_GC_9E>();
c->set_flag(Client::Flag::AT_WELCOME_MESSAGE); c->set_flag(Client::Flag::AT_WELCOME_MESSAGE);
} else {
handle_cmd.template operator()<C_Login_PC_GC_9E, C_LoginExtended_PC_9E>();
} }
} else { } else {
@@ -1321,8 +1325,10 @@ static asio::awaitable<void> on_9D_9E(shared_ptr<Client> c, Channel::Message& ms
} }
if (resp.checksum == 0x3677024C) { if (resp.checksum == 0x3677024C) {
c->specific_version = SPECIFIC_VERSION_PC_V2_DEFAULT; c->specific_version = SPECIFIC_VERSION_PC_V2_DEFAULT;
c->log.info_f("Version detected as {:08X} from PE header checksum {:08X}", c->log.info_f("Version detected as {:08X} from PE header checksum {:08X}", c->specific_version, resp.checksum);
c->specific_version, resp.checksum); } else if (resp.checksum == 0x058BF2FF) {
c->specific_version = SPECIFIC_VERSION_PC_V2_FINAL;
c->log.info_f("Version detected as {:08X} from PE header checksum {:08X}", c->specific_version, resp.checksum);
} else { } else {
c->specific_version = SPECIFIC_VERSION_PC_V2_INDETERMINATE; c->specific_version = SPECIFIC_VERSION_PC_V2_INDETERMINATE;
c->log.info_f("Version cannot be determined from PE header checksum {:08X}", resp.checksum); c->log.info_f("Version cannot be determined from PE header checksum {:08X}", resp.checksum);
+3 -3
View File
@@ -215,16 +215,16 @@ bool specific_version_is_indeterminate(uint32_t specific_version) {
} }
bool specific_version_is_dc(uint32_t specific_version) { bool specific_version_is_dc(uint32_t specific_version) {
// All v1 and v2 specific_versions are DC except 324F4A57 (2OJW), which is PC // All v1 and v2 specific_versions are DC except 2OJW and 2OJZ, which are PC
uint8_t major_version = specific_version >> 24; uint8_t major_version = specific_version >> 24;
if (major_version < 0x31 || major_version > 0x32) { if (major_version < 0x31 || major_version > 0x32) {
return false; return false;
} }
return (specific_version != SPECIFIC_VERSION_PC_V2_DEFAULT); return !specific_version_is_pc_v2(specific_version);
} }
bool specific_version_is_pc_v2(uint32_t specific_version) { bool specific_version_is_pc_v2(uint32_t specific_version) {
return (specific_version == SPECIFIC_VERSION_PC_V2_DEFAULT); return ((specific_version == SPECIFIC_VERSION_PC_V2_DEFAULT) || (specific_version == SPECIFIC_VERSION_PC_V2_FINAL));
} }
bool specific_version_is_gc(uint32_t specific_version) { bool specific_version_is_gc(uint32_t specific_version) {
+2 -1
View File
@@ -191,8 +191,9 @@ constexpr uint32_t SPECIFIC_VERSION_DC_V1_US = 0x314F4546; // 1OEF
constexpr uint32_t SPECIFIC_VERSION_DC_V1_EU_INDETERMINATE = 0x314F5000; // 1OP_ constexpr uint32_t SPECIFIC_VERSION_DC_V1_EU_INDETERMINATE = 0x314F5000; // 1OP_
constexpr uint32_t SPECIFIC_VERSION_DC_V1_INDETERMINATE = 0x31000000; // 1___ constexpr uint32_t SPECIFIC_VERSION_DC_V1_INDETERMINATE = 0x31000000; // 1___
constexpr uint32_t SPECIFIC_VERSION_DC_V2_INDETERMINATE = 0x32000000; // 2___ constexpr uint32_t SPECIFIC_VERSION_DC_V2_INDETERMINATE = 0x32000000; // 2___
constexpr uint32_t SPECIFIC_VERSION_PC_V2_INDETERMINATE = 0x324F4A00; // 2OJW constexpr uint32_t SPECIFIC_VERSION_PC_V2_INDETERMINATE = 0x324F4A00; // 2OJ_
constexpr uint32_t SPECIFIC_VERSION_PC_V2_DEFAULT = 0x324F4A57; // 2OJW constexpr uint32_t SPECIFIC_VERSION_PC_V2_DEFAULT = 0x324F4A57; // 2OJW
constexpr uint32_t SPECIFIC_VERSION_PC_V2_FINAL = 0x324F4A5A; // 2OJZ
constexpr uint32_t SPECIFIC_VERSION_GC_NTE = 0x334F4A54; // 3OJT constexpr uint32_t SPECIFIC_VERSION_GC_NTE = 0x334F4A54; // 3OJT
constexpr uint32_t SPECIFIC_VERSION_GC_V3_EU = 0x334F5030; // 3OP0 constexpr uint32_t SPECIFIC_VERSION_GC_V3_EU = 0x334F5030; // 3OP0
constexpr uint32_t SPECIFIC_VERSION_GC_V3_US_12 = 0x334F4532; // 3OE2 constexpr uint32_t SPECIFIC_VERSION_GC_V3_US_12 = 0x334F4532; // 3OE2