#include "Version.hh" #include #include #include "Client.hh" using namespace std; const char* login_port_name_for_version(Version v) { switch (v) { case Version::PC_PATCH: return "pc-patch"; case Version::BB_PATCH: return "bb-patch"; case Version::DC_NTE: case Version::DC_V1_11_2000_PROTOTYPE: case Version::DC_V1: case Version::DC_V2: case Version::GC_NTE: case Version::GC_V3: case Version::GC_EP3_NTE: case Version::GC_EP3: return "console-login"; case Version::PC_NTE: case Version::PC_V2: return "pc-login"; case Version::XB_V3: return "xb-login"; case Version::BB_V4: return "bb-init"; default: throw runtime_error("unknown version"); } } const char* lobby_port_name_for_version(Version v) { switch (v) { case Version::PC_PATCH: return "pc-patch"; case Version::BB_PATCH: return "bb-patch"; case Version::DC_NTE: case Version::DC_V1_11_2000_PROTOTYPE: case Version::DC_V1: case Version::DC_V2: case Version::GC_NTE: case Version::GC_V3: case Version::GC_EP3_NTE: case Version::GC_EP3: return "console-lobby"; case Version::PC_NTE: case Version::PC_V2: return "pc-lobby"; case Version::XB_V3: return "xb-lobby"; case Version::BB_V4: return "bb-lobby"; default: throw runtime_error("unknown version"); } } const char* proxy_port_name_for_version(Version v) { switch (v) { case Version::PC_PATCH: return "pc-patch"; case Version::BB_PATCH: return "bb-patch"; case Version::DC_NTE: case Version::DC_V1_11_2000_PROTOTYPE: case Version::DC_V1: case Version::DC_V2: case Version::GC_NTE: return "dc-proxy"; case Version::GC_V3: case Version::GC_EP3_NTE: case Version::GC_EP3: return "gc-proxy"; case Version::PC_NTE: case Version::PC_V2: return "pc-proxy"; case Version::XB_V3: return "xb-proxy"; case Version::BB_V4: return "bb-proxy"; default: throw runtime_error("unknown version"); } } template <> const char* name_for_enum(Version v) { switch (v) { case Version::PC_PATCH: return "PC_PATCH"; case Version::BB_PATCH: return "BB_PATCH"; case Version::DC_NTE: return "DC_NTE"; case Version::DC_V1_11_2000_PROTOTYPE: return "DC_V1_11_2000_PROTOTYPE"; case Version::DC_V1: return "DC_V1"; case Version::DC_V2: return "DC_V2"; case Version::PC_NTE: return "PC_NTE"; case Version::PC_V2: return "PC_V2"; case Version::GC_NTE: return "GC_NTE"; case Version::GC_V3: return "GC_V3"; case Version::GC_EP3_NTE: return "GC_EP3_NTE"; case Version::GC_EP3: return "GC_EP3"; case Version::XB_V3: return "XB_V3"; case Version::BB_V4: return "BB_V4"; default: throw runtime_error("unknown version"); } } template <> Version enum_for_name(const char* name) { if (!strcmp(name, "PC_PATCH") || !strcasecmp(name, "patch")) { return Version::PC_PATCH; } else if (!strcmp(name, "BB_PATCH")) { return Version::BB_PATCH; } else if (!strcmp(name, "DC_NTE")) { return Version::DC_NTE; } else if (!strcmp(name, "DC_V1_11_2000_PROTOTYPE")) { return Version::DC_V1_11_2000_PROTOTYPE; } else if (!strcmp(name, "DC_V1")) { return Version::DC_V1; } else if (!strcmp(name, "DC_V2") || !strcasecmp(name, "dc")) { return Version::DC_V2; } else if (!strcmp(name, "PC_NTE")) { return Version::PC_NTE; } else if (!strcmp(name, "PC_V2") || !strcasecmp(name, "pc")) { return Version::PC_V2; } else if (!strcmp(name, "GC_NTE")) { return Version::GC_NTE; } else if (!strcmp(name, "GC_V3") || !strcasecmp(name, "gc")) { return Version::GC_V3; } else if (!strcmp(name, "GC_EP3_NTE")) { return Version::GC_EP3_NTE; } else if (!strcmp(name, "GC_EP3")) { return Version::GC_EP3; } else if (!strcmp(name, "XB_V3") || !strcasecmp(name, "xb")) { return Version::XB_V3; } else if (!strcmp(name, "BB_V4") || !strcasecmp(name, "bb")) { return Version::BB_V4; } else { throw invalid_argument("incorrect version name"); } } template <> const char* name_for_enum(ServerBehavior behavior) { switch (behavior) { case ServerBehavior::PC_CONSOLE_DETECT: return "pc_console_detect"; case ServerBehavior::LOGIN_SERVER: return "login_server"; case ServerBehavior::LOBBY_SERVER: return "lobby_server"; case ServerBehavior::PATCH_SERVER_PC: return "patch_server_pc"; case ServerBehavior::PATCH_SERVER_BB: return "patch_server_bb"; case ServerBehavior::PROXY_SERVER: return "proxy_server"; } throw logic_error("invalid server behavior"); } template <> ServerBehavior enum_for_name(const char* name) { if (!strcasecmp(name, "pc_console_detect")) { return ServerBehavior::PC_CONSOLE_DETECT; } else if (!strcasecmp(name, "login_server") || !strcasecmp(name, "login") || !strcasecmp(name, "data_server_bb")) { return ServerBehavior::LOGIN_SERVER; } else if (!strcasecmp(name, "lobby_server") || !strcasecmp(name, "lobby")) { return ServerBehavior::LOBBY_SERVER; } else if (!strcasecmp(name, "patch_server_pc") || !strcasecmp(name, "patch_pc")) { return ServerBehavior::PATCH_SERVER_PC; } else if (!strcasecmp(name, "patch_server_bb") || !strcasecmp(name, "patch_bb")) { return ServerBehavior::PATCH_SERVER_BB; } else if (!strcasecmp(name, "proxy_server") || !strcasecmp(name, "proxy")) { return ServerBehavior::PROXY_SERVER; } else { throw invalid_argument("incorrect server behavior name"); } } uint32_t default_specific_version_for_version(Version version, int64_t sub_version) { // For versions that don't support send_function_call by default, we need // to set the specific_version based on sub_version. Fortunately, all // versions that share sub_version values also support send_function_call, // so for those versions we get the specific_version later by sending the // VersionDetect call. switch (version) { case Version::GC_NTE: return 0x334F4A54; // 3OJT case Version::GC_V3: switch (sub_version) { case 0x32: // GC Ep1&2 EU 50Hz case 0x33: // GC Ep1&2 EU 60Hz return 0x334F5030; // 3OP0 case 0x36: // GC Ep1&2 US v1.02 (Plus) return 0x334F4532; // 3OE2 case 0x39: // GC Ep1&2 JP v1.05 (Plus) return 0x334F4A35; // 3OJ5 case 0x34: // GC Ep1&2 JP v1.03 return 0x334F4A33; // 3OJ3 case 0x35: // GC Ep1&2 JP v1.04 (Plus) return 0x334F4A34; // 3OJ4 case -1: // Initial check (before sub_version recognition) case 0x30: // GC Ep1&2 GameJam demo, GC Ep1&2 Trial Edition, GC Ep1&2 JP v1.02, at least one version of PSO XB case 0x31: // GC Ep1&2 US v1.00, GC US v1.01, XB US default: return 0x33000000; } throw logic_error("this should be impossible"); case Version::GC_EP3_NTE: return 0x33534A54; // 3SJT case Version::GC_EP3: switch (sub_version) { case 0x41: // GC Ep3 US return 0x33534530; // 3SE0 case 0x42: // GC Ep3 EU 50Hz case 0x43: // GC Ep3 EU 60Hz return 0x33535030; // 3SP0 case -1: // Initial check (before sub_version recognition) case 0x40: // GC Ep3 trial and GC Ep3 JP default: return 0x33000000; } default: return 0x00000000; } } const char* file_path_token_for_version(Version version) { switch (version) { case Version::PC_PATCH: return "pc-patch"; case Version::BB_PATCH: return "bb-patch"; case Version::DC_NTE: return "dc-nte"; case Version::DC_V1_11_2000_PROTOTYPE: return "dc-11-2000"; case Version::DC_V1: return "dc-v1"; case Version::DC_V2: return "dc-v2"; case Version::PC_NTE: return "pc-nte"; case Version::PC_V2: return "pc-v2"; case Version::GC_NTE: return "gc-nte"; case Version::GC_V3: return "gc-v3"; case Version::GC_EP3_NTE: return "gc-ep3-nte"; case Version::GC_EP3: return "gc-ep3"; case Version::XB_V3: return "xb-v3"; case Version::BB_V4: return "bb-v4"; default: throw runtime_error("invalid game version"); } }