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
+14 -10
View File
@@ -2000,8 +2000,9 @@ struct C_LoginExtended_PC_9D : C_Login_DC_PC_GC_9D {
SC_MeetUserExtension_PC_BB extension;
} __packed_ws__(C_LoginExtended_PC_9D, 0x14C);
// 9E (C->S): Log in with client config (V3/BB)
// Not used on GC Episodes 1&2 Trial Edition.
// 9E (C->S): Log in with client config (PC/V3/BB)
// 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
// 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,
@@ -2009,11 +2010,13 @@ struct C_LoginExtended_PC_9D : C_Login_DC_PC_GC_9D {
// retrieve the client config.
// 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;
} __packed_ws__(C_Login_GC_9E, 0xE8);
struct C_LoginExtended_GC_9E : C_Login_GC_9E {
} __packed_ws__(C_Login_PC_GC_9E, 0xE8);
struct C_LoginExtended_PC_9E : C_Login_PC_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;
} __packed_ws__(C_LoginExtended_GC_9E, 0x14C);
@@ -2051,12 +2054,13 @@ struct C_LoginExtended_BB_9E {
/* 0170 */
} __packed_ws__(C_LoginExtended_BB_9E, 0x170);
// 9F (S->C): Request client config / security data (V3/BB)
// This command is not valid on PSO GC Episodes 1&2 Trial Edition, nor any
// pre-V3 PSO versions. Client will respond with a 9F command.
// 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 on any
// other pre-v3 versions, except the latest PC v2 version, which does have it.
// Client will respond with a 9F command.
// 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.
// 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.login_character_name.encode(this->character->disp.name.decode());
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) {
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
c->proxy_session->server_channel->send(
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;
}
+9
View File
@@ -2095,6 +2095,15 @@ static const QuestScriptOpcodeDefinition opcode_defs[] = {
// is the last opcode implemented before v3.
{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
// be 0 for Episode 1 (which is the default), 1 for Episode 2, or 2 for
// 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) {
const auto& cmd = check_size_t<C_Login_GC_9E>(msg.data, sizeof(C_LoginExtended_GC_9E));
base_cmd = &cmd;
if (cmd.is_extended) {
const auto& cmd = check_size_t<C_LoginExtended_GC_9E>(msg.data);
if (cmd.extension.lobby_refs[0].menu_id == MenuID::LOBBY) {
c->preferred_lobby_id = cmd.extension.lobby_refs[0].item_id;
auto handle_cmd = [&]<typename BaseCmdT, typename ExtendedCmdT>() {
const auto& cmd = check_size_t<BaseCmdT>(msg.data, sizeof(ExtendedCmdT));
base_cmd = &cmd;
if (cmd.is_extended) {
const auto& cmd = check_size_t<ExtendedCmdT>(msg.data);
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())) {
handle_cmd.template operator()<C_Login_PC_GC_9E, C_LoginExtended_GC_9E>();
c->set_flag(Client::Flag::AT_WELCOME_MESSAGE);
} else {
handle_cmd.template operator()<C_Login_PC_GC_9E, C_LoginExtended_PC_9E>();
}
} else {
@@ -1321,8 +1325,10 @@ static asio::awaitable<void> on_9D_9E(shared_ptr<Client> c, Channel::Message& ms
}
if (resp.checksum == 0x3677024C) {
c->specific_version = SPECIFIC_VERSION_PC_V2_DEFAULT;
c->log.info_f("Version detected as {:08X} from PE header checksum {:08X}",
c->specific_version, resp.checksum);
c->log.info_f("Version detected as {:08X} from PE header checksum {:08X}", 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 {
c->specific_version = SPECIFIC_VERSION_PC_V2_INDETERMINATE;
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) {
// 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;
if (major_version < 0x31 || major_version > 0x32) {
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) {
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) {
+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_INDETERMINATE = 0x31000000; // 1___
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_FINAL = 0x324F4A5A; // 2OJZ
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_US_12 = 0x334F4532; // 3OE2