add notes and support for final PCv2 version
This commit is contained in:
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+14
-10
@@ -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.
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user