diff --git a/src/ReceiveCommands.cc b/src/ReceiveCommands.cc index e7651835..586eb22e 100644 --- a/src/ReceiveCommands.cc +++ b/src/ReceiveCommands.cc @@ -1001,37 +1001,6 @@ static void on_9E_XB(shared_ptr c, uint16_t, uint32_t, string& data) { } } -static void scramble_bb_security_data(parray& data, uint8_t which, bool reverse) { - static const uint8_t forward_orders[8][5] = { - {2, 0, 1, 4, 3}, - {3, 4, 0, 1, 2}, - {2, 3, 4, 0, 1}, - {2, 3, 0, 1, 4}, - {0, 2, 3, 4, 1}, - {1, 4, 2, 3, 0}, - {2, 0, 1, 4, 3}, - {1, 0, 3, 4, 2}, - }; - static const uint8_t reverse_orders[8][5] = { - {1, 2, 0, 4, 3}, - {2, 3, 4, 0, 1}, - {3, 4, 0, 1, 2}, - {2, 3, 0, 1, 4}, - {0, 4, 1, 2, 3}, - {4, 0, 2, 3, 1}, - {1, 2, 0, 4, 3}, - {1, 0, 4, 2, 3}, - }; - const auto& order = reverse ? reverse_orders[which & 7] : forward_orders[which & 7]; - parray scrambled_data; - for (size_t z = 0; z < 5; z++) { - for (size_t x = 0; x < 8; x++) { - scrambled_data[(z * 8) + x] = data[(order[z] * 8) + x]; - } - } - data = scrambled_data; -} - static void on_93_BB(shared_ptr c, uint16_t, uint32_t, string& data) { const auto& base_cmd = check_size_t(data, 0xFFFF); auto s = c->require_server_state(); @@ -1040,12 +1009,6 @@ static void on_93_BB(shared_ptr c, uint16_t, uint32_t, string& data) { ? check_size_t(data).client_config : check_size_t(data).client_config; - // If security_token is zero, the game scrambles the client config data based - // on the first character in the username. We undo the scramble here. - if (base_cmd.security_token == 0) { - scramble_bb_security_data(config_data, base_cmd.username.at(0), true); - } - c->config.set_flags_for_version(c->version(), base_cmd.sub_version); c->channel.language = base_cmd.language; string username = base_cmd.username.decode(); @@ -1075,7 +1038,7 @@ static void on_93_BB(shared_ptr c, uint16_t, uint32_t, string& data) { // normal version encoding logic. Otherwise, assume it's a community mod, // almost all of which are based on TethVer12513, so assume that version // otherwise. - if (true || starts_with(version_string, "Ver.")) { + if (starts_with(version_string, "Ver.")) { // Basic algorithm: take all numeric characters from the version string // and ignore everything else. Treat that as a decimal integer, then // base36-encode it into the low 3 bytes of specific_version. diff --git a/src/SendCommands.cc b/src/SendCommands.cc index 1bf4f650..b65f1c61 100644 --- a/src/SendCommands.cc +++ b/src/SendCommands.cc @@ -564,6 +564,37 @@ void send_pc_console_split_reconnect(shared_ptr c, uint32_t address, send_command_t(c, 0x19, 0x00, cmd); } +static void scramble_bb_security_data(parray& data, uint8_t which, bool reverse) { + static const uint8_t forward_orders[8][5] = { + {2, 0, 1, 4, 3}, + {3, 4, 0, 1, 2}, + {2, 3, 4, 0, 1}, + {2, 3, 0, 1, 4}, + {0, 2, 3, 4, 1}, + {1, 4, 2, 3, 0}, + {2, 0, 1, 4, 3}, + {1, 0, 3, 4, 2}, + }; + static const uint8_t reverse_orders[8][5] = { + {1, 2, 0, 4, 3}, + {2, 3, 4, 0, 1}, + {3, 4, 0, 1, 2}, + {2, 3, 0, 1, 4}, + {0, 4, 1, 2, 3}, + {4, 0, 2, 3, 1}, + {1, 2, 0, 4, 3}, + {1, 0, 4, 2, 3}, + }; + const auto& order = reverse ? reverse_orders[which & 7] : forward_orders[which & 7]; + parray scrambled_data; + for (size_t z = 0; z < 5; z++) { + for (size_t x = 0; x < 8; x++) { + scrambled_data[(z * 8) + x] = data[(order[z] * 8) + x]; + } + } + data = scrambled_data; +} + void send_client_init_bb(shared_ptr c, uint32_t error_code) { auto team = c->team(); S_ClientInit_BB_00E6 cmd; @@ -574,6 +605,15 @@ void send_client_init_bb(shared_ptr c, uint32_t error_code) { c->config.serialize_into(cmd.client_config); cmd.can_create_team = 1; cmd.episode_4_unlocked = 1; + + // If security_token is zero, the game scrambles the client config data based + // on the first character in the username. We undo the scramble here, so when + // the client scrambles the data upon receipt, it will be correct when it next + // is sent back to the server. + if (cmd.security_token == 0 && c->login && c->login->bb_license) { + scramble_bb_security_data(cmd.client_config, c->login->bb_license->username.at(0), true); + } + send_command_t(c, 0x00E6, 0x00000000, cmd); }