From 1ab01d3e502fa142db456aa1b62d37c184324bb8 Mon Sep 17 00:00:00 2001 From: nukeulater <18323679+nukeulater@users.noreply.github.com> Date: Thu, 2 Jan 2025 22:59:22 +0200 Subject: [PATCH] reverse engineered some of the network observer configuration parameters and updates - network bitstream management still disabled, probably not worth the time looking further into this --- .../networking/transport/network_observer.cpp | 359 +++++++++--------- .../networking/transport/network_observer.h | 59 +-- .../render/render_cartographer_ingame_ui.cpp | 10 +- 3 files changed, 214 insertions(+), 214 deletions(-) diff --git a/xlive/Blam/Engine/networking/transport/network_observer.cpp b/xlive/Blam/Engine/networking/transport/network_observer.cpp index 21a6c9190..f8f858206 100644 --- a/xlive/Blam/Engine/networking/transport/network_observer.cpp +++ b/xlive/Blam/Engine/networking/transport/network_observer.cpp @@ -3,12 +3,12 @@ #include "network_observer.h" #include "network_channel.h" -s_network_observer_configuration* g_network_configuration; +s_network_observer_configuration* g_network_observer_configuration; #if defined(LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS) # if LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS == true -// variables, TODO configurable +// ### TODO configurable real32 _online_netcode_client_rate_real = k_online_netcode_client_rate_real; real32 _online_netcode_server_rate_real = k_online_netcode_server_rate_real; @@ -21,117 +21,141 @@ int32 _online_netcode_window_size = -1; # endif // LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS == true #endif // defined(LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS) -// LIVE netcode research void __cdecl initialize_network_observer_configuration() { /* - Configuration constants used by the game to define how LIVE netcode will behave + network stream configuration contains different network parameters, used to adjust the functionality and performance counters + + UPDATE: + I don't think this is worth fixing, the H2's code itself looks unfinished/unpolished, + things which are addressed/improved in H3 */ - g_network_configuration->field_0 = 1; - g_network_configuration->field_2C = 500; - g_network_configuration->field_30 = 500; - g_network_configuration->field_4C = 500; - g_network_configuration->field_50 = 500; - g_network_configuration->field_78 = 500; - g_network_configuration->field_94 = 1.0f; - g_network_configuration->field_98 = 30.0f; - g_network_configuration->field_80 = 4000; - g_network_configuration->field_84 = 4000; - g_network_configuration->field_100 = 4000; - g_network_configuration->unk_floats_A0[0] = 1.0f; - g_network_configuration->unk_floats_A0[1] = 0.66666669f; - g_network_configuration->unk_floats_A0[2] = 0.5f; - g_network_configuration->unk_floats_A0[3] = 0.33333334f; - g_network_configuration->unk_floats_A0[4] = 0.25f; - g_network_configuration->unk_floats_A0[5] = 0.2f; - g_network_configuration->unk_floats_A0[6] = 0.1f; - g_network_configuration->unk_total_flt_array_elements = 7; - g_network_configuration->field_4 = 0; - g_network_configuration->field_24 = 3; - g_network_configuration->field_28 = 0; - g_network_configuration->field_48 = 4; - g_network_configuration->field_54 = 1000; - g_network_configuration->field_58 = 2000; - g_network_configuration->field_6C = 15000; - g_network_configuration->field_70 = 1000; - g_network_configuration->field_74 = 2000; - g_network_configuration->field_7C = 2000; - g_network_configuration->field_88 = 1000; - g_network_configuration->field_8C = 5000; - g_network_configuration->field_90 = 0.5f; - g_network_configuration->field_E0 = 200; - g_network_configuration->field_E4 = 0.25f; - g_network_configuration->field_E8 = 0.5f; - g_network_configuration->field_EC = 0.75f; - g_network_configuration->field_F0 = 12.0f; - g_network_configuration->field_F4 = 2000; - g_network_configuration->field_F8 = 2000; - g_network_configuration->field_FC = 30; - g_network_configuration->field_104 = 0.5; - g_network_configuration->field_108 = 64; - g_network_configuration->field_10C = 96; - g_network_configuration->field_110 = 0.33333334f; - g_network_configuration->field_114 = 10240 * 4; // H2v - 10240, 60 tick = H2v * 4 - g_network_configuration->field_118 = 1000; - g_network_configuration->field_11C = 0.5f; - g_network_configuration->field_120 = 3; - g_network_configuration->field_124 = 40; - g_network_configuration->field_128 = 5000; - g_network_configuration->field_12C = 15; - g_network_configuration->field_130 = 100; - g_network_configuration->field_134 = 50 * 2; // h2v - 50, 60 tick - 100 - g_network_configuration->field_138 = 50 * 4; // h2v - 50, 60 tick - 200 - g_network_configuration->field_13C = 32; // h2v - 15, 60 tick - 32 - g_network_configuration->field_140 = 32; // h2v - 8, 60 tick - 32 - g_network_configuration->field_144 = 1; - g_network_configuration->field_148 = 2000; - g_network_configuration->field_14C = 4096 * 4; // h2v - 4096, 60 tick = 4096 * 4 - g_network_configuration->field_150 = 71680 * 4; // H2v - 71680, 60 tick = H2v * 4 - g_network_configuration->field_154 = 1000; - g_network_configuration->max_bits_per_second_single_player = 30720 * 4; // H2v = 30720, 60 tick = H2v * 4 - g_network_configuration->max_bits_per_second_full_lobby = 262144; // H2v - 122880, 60 tick = 262144 - g_network_configuration->max_bits_per_second_splitscreen_players = 512000; - g_network_configuration->field_1C4 = 0.5f; - g_network_configuration->field_1A0 = 1500; - g_network_configuration->field_1A4 = 1500; - g_network_configuration->field_178 = 0.1f; - g_network_configuration->field_190 = 0.2f; - g_network_configuration->field_1C8 = 20.0f; - g_network_configuration->field_168 = 40; - g_network_configuration->field_1D8 = 40; - g_network_configuration->field_164 = 65536; // H2v 8192, 60 tick = 65536 - g_network_configuration->field_16C = 320; - g_network_configuration->field_170 = 3; - g_network_configuration->field_174 = 32; - g_network_configuration->field_17C = 4; - g_network_configuration->field_180 = 0.80000001f; - g_network_configuration->field_184 = 10; - g_network_configuration->field_188 = 21; - g_network_configuration->field_18C = 3072 * 4; // H2v - 3072, 60 tick = H2V * 4 - g_network_configuration->field_194 = 5120 * 4; // H2v - 5120, 60 tick = H2V * 4 - g_network_configuration->field_198 = 0.30000001f; - g_network_configuration->field_19C = 5000; - g_network_configuration->field_1B4 = 3; - g_network_configuration->field_1B8 = 6144 * 4; // H2v - 6144, 60 tick = H2v * 4 - g_network_configuration->field_1BC = 20000; - g_network_configuration->field_1A8 = 30720 * 4; // H2v - 30720, 60 tick = H2v * 4; - g_network_configuration->field_1AC = 0.75f; - g_network_configuration->field_1B0 = 60000; - g_network_configuration->field_1C0 = 6; - g_network_configuration->field_1CC = 0; - g_network_configuration->field_1D0 = 0.00039062501f; - g_network_configuration->field_1D4 = 160; - g_network_configuration->field_1DC = 120; - g_network_configuration->field_1E0 = 3; - g_network_configuration->field_1E4 = 10; - g_network_configuration->field_1E8 = 10; - g_network_configuration->field_1EC = 3; - g_network_configuration->field_1F0 = 8000; - g_network_configuration->field_1F4 = 6; - g_network_configuration->field_1F8 = 8192 * 4; // H2v - 8192, 60 tick = H2v * 4 = 32768 - g_network_configuration->field_1FC = 0.33333334f; - g_network_configuration->field_200 = 4096 * 4; // H2v - 4096, 60 tick = H2v * 4 = 16384 + g_network_observer_configuration->field_2C = 500; + g_network_observer_configuration->field_30 = 500; + g_network_observer_configuration->field_4C = 500; + g_network_observer_configuration->field_50 = 500; + g_network_observer_configuration->field_78 = 500; + g_network_observer_configuration->field_94 = 1.0f; + g_network_observer_configuration->field_98 = 30.0f; + g_network_observer_configuration->field_80 = 4000; + g_network_observer_configuration->field_84 = 4000; + g_network_observer_configuration->field_100 = 4000; + g_network_observer_configuration->field_E4 = 0.25f; + g_network_observer_configuration->field_0 = 1; + g_network_observer_configuration->field_4 = 0; + g_network_observer_configuration->field_24 = 3; + g_network_observer_configuration->field_28 = 0; + g_network_observer_configuration->field_48 = 4; + g_network_observer_configuration->field_54 = 1000; + g_network_observer_configuration->field_58 = 2000; + g_network_observer_configuration->field_6C = 15000; + g_network_observer_configuration->field_70 = 1000; + g_network_observer_configuration->field_74 = 2000; + g_network_observer_configuration->field_7C = 2000; + g_network_observer_configuration->field_88 = 1000; + g_network_observer_configuration->field_8C = 5000; + g_network_observer_configuration->field_90 = 0.5f; + + g_network_observer_configuration->stream_packet_rate_throttle_scale_stage_count = 7; + g_network_observer_configuration->stream_packet_rate_throttle_scale_stages[0] = 1.0f; + g_network_observer_configuration->stream_packet_rate_throttle_scale_stages[1] = 0.66666669f; + g_network_observer_configuration->stream_packet_rate_throttle_scale_stages[2] = 0.5f; + g_network_observer_configuration->stream_packet_rate_throttle_scale_stages[3] = 0.33333334f; + g_network_observer_configuration->stream_packet_rate_throttle_scale_stages[4] = 0.25f; + g_network_observer_configuration->stream_packet_rate_throttle_scale_stages[5] = 0.2f; + g_network_observer_configuration->stream_packet_rate_throttle_scale_stages[6] = 0.1f; + + // doesn't really need to be increased, the value per stream is proportional with round time trip + // packets take longer to arrive when round time trip is higher + // which allows for more data on the wire at once + g_network_observer_configuration->stream_minimum_window_size_bytes = 200; + + g_network_observer_configuration->field_E8 = 0.5f; + g_network_observer_configuration->field_EC = 0.75f; + g_network_observer_configuration->field_F0 = 12.0f; + g_network_observer_configuration->field_F4 = 2000; + g_network_observer_configuration->field_F8 = 2000; + g_network_observer_configuration->field_FC = 30; + g_network_observer_configuration->field_104 = 0.5f; + g_network_observer_configuration->avg_payload_size_outside_simulation = 64; + g_network_observer_configuration->avg_payload_size_in_simulation = 96; + g_network_observer_configuration->minimum_packet_rate_scale = 0.33333334f; + + // this is pretty low, could be increased, but doesn't matter since bandwidth tracking is currently disabled + g_network_observer_configuration->minimum_estimated_upstream_bandwidth_bps = 10240; + + g_network_observer_configuration->field_118 = 1000; + g_network_observer_configuration->field_11C = 0.5f; + g_network_observer_configuration->field_120 = 3; + g_network_observer_configuration->field_124 = 40; + g_network_observer_configuration->field_128 = 5000; + g_network_observer_configuration->field_12C = 15; + g_network_observer_configuration->field_130 = 100; + g_network_observer_configuration->field_134 = 50; + g_network_observer_configuration->field_138 = 50; + g_network_observer_configuration->field_13C = 15; + g_network_observer_configuration->field_140 = 8; + g_network_observer_configuration->field_144 = 1; + g_network_observer_configuration->field_148 = 2000; + g_network_observer_configuration->stream_minimum_bps = 4096 * 4 /* 4096 */; + g_network_observer_configuration->stream_maximum_bps = 71680; + g_network_observer_configuration->field_154 = 1000; + g_network_observer_configuration->stream_desired_bps = 71680 /* 30720 */; + + g_network_observer_configuration->upstream_bandwidth0 = 1146880 /* 122880 */; + g_network_observer_configuration->upstream_bandwidth1 = 1146880 /* 512000 */; + + g_network_observer_configuration->field_1C4 = 0.5f; + g_network_observer_configuration->stream_minimum_period_before_adjust_attempt_msec = 1500; + g_network_observer_configuration->field_1A4 = 1500; + g_network_observer_configuration->field_178 = 0.1f; + + // stream re-growth factor + g_network_observer_configuration->field_190 = 0.2f /* 0.2f */; + + g_network_observer_configuration->field_1C8 = 20.0f; + g_network_observer_configuration->field_168 = 40; + g_network_observer_configuration->field_1D8 = 40; + + // sligtly below stream_desired_bps + // has to be a value which is high enough for the desired packet rate to actually send + // and to do so when the stream is actually created, for the full bandwidth at creation + // instead of gradually increasing the stream towards stream_maximum_bps (if possible) + // formula: packet_rate = stream_bits_per_second / (8 * (avg_payload_size_in_simulation + network_layer_overhead (48 for UDP)) + g_network_observer_configuration->stream_default_bps = 71680 /* 8192 */; + + g_network_observer_configuration->field_16C = 320; + g_network_observer_configuration->field_170 = 3; + g_network_observer_configuration->field_174 = 32; + g_network_observer_configuration->field_17C = 4; + g_network_observer_configuration->stream_packet_rate_scale_during_packet_loss = 0.80000001f; + g_network_observer_configuration->field_184 = 10; + g_network_observer_configuration->field_188 = 21; + g_network_observer_configuration->stream_maximum_bps_regrowth_per_cycle = 1024 * 15 /* 3072 */; + g_network_observer_configuration->stream_maximum_bps_throttle_per_cycle = 1024 * 20 /* 5120 */; + g_network_observer_configuration->field_198 = 0.30000001f; + g_network_observer_configuration->field_19C = 5000; + g_network_observer_configuration->field_1B4 = 3; + g_network_observer_configuration->field_1B8 = 6144; + g_network_observer_configuration->field_1BC = 20000; + g_network_observer_configuration->field_1A8 = 30720; + g_network_observer_configuration->field_1AC = 0.75f; + g_network_observer_configuration->field_1B0 = 60000; + g_network_observer_configuration->field_1C0 = 6; + g_network_observer_configuration->field_1CC = 0; + g_network_observer_configuration->field_1D0 = 0.00039062501f; + g_network_observer_configuration->field_1D4 = 160; + g_network_observer_configuration->field_1DC = 120; + g_network_observer_configuration->field_1E0 = 3; + g_network_observer_configuration->field_1E4 = 10; + g_network_observer_configuration->field_1E8 = 10; + g_network_observer_configuration->field_1EC = 3; + g_network_observer_configuration->field_1F0 = 8000; + g_network_observer_configuration->field_1F4 = 6; + g_network_observer_configuration->field_1F8 = 8192; + g_network_observer_configuration->field_1FC = 0.33333334f; + g_network_observer_configuration->field_200 = 4096; } void c_network_observer::send_message(int32 session_index, int32 observer_index, bool send_out_of_band, int32 type, int32 size, void* data) @@ -165,7 +189,7 @@ void __declspec(naked) jmp_get_bandwidth_results() { __asm jmp c_network_observe // raw WinSock has a 28 bytes packet overhead for the packet header, unlike Xbox LIVE, which has 44 bytes (28 bytes + whatever LIVE packet header adds) int32 __cdecl transport_get_packet_overhead_hook(int32 protocol_type) { - enum e_protocol_type : int32 + enum e_transport_protocol_type : int32 { _protocol_udp_loopback = 2, _protocol_udp, @@ -173,7 +197,7 @@ int32 __cdecl transport_get_packet_overhead_hook(int32 protocol_type) k_protocol_count }; - switch ((e_protocol_type)protocol_type) + switch ((e_transport_protocol_type)protocol_type) { // replace XNet UDP header overhead with WinSock overhead @@ -201,14 +225,14 @@ bool __thiscall c_network_observer::channel_should_send_packet_hook( bool a4, int32 a5, int32* out_send_sequenced_packet, - int32* out_force_fill_packet, + bool* out_force_fill_packet, int32* out_packet_size, int32* out_voice_size, int32 out_voice_chat_data_buffer_size, uint8* out_voice_chat_data_buffer) { - typedef bool(__thiscall* channel_should_send_packet_t)(c_network_observer*, int32, bool, bool, int32, int32*, int32*, int32*, int32*, int32, uint8*); - auto p_channel_should_send_packet = Memory::GetAddressRelative(0x5BEE8D, 0x5B8D67); + typedef bool(__thiscall* channel_should_send_packet_t)(c_network_observer*, int32, bool, bool, int32, int32*, bool*, int32*, int32*, int32, uint8*); + auto p_channel_should_send_packet = Memory::GetAddress(0x1BEE8D, 0x1B8D67); int32 observer_index = NONE; for (int32 i = 0; i < 16; i++) @@ -228,29 +252,35 @@ bool __thiscall c_network_observer::channel_should_send_packet_hook( s_observer_channel* observer_channel = &this->m_observer_channels[observer_index]; // we modify the network channel paramters to force the network tickrate - const real32 _temp_network_rate = observer_channel->net_rate_managed_stream; - const int32 _temp_network_bandwidth_per_stream = observer_channel->net_managed_stream_bandwidth; - const int32 _temp_network_window_size = observer_channel->net_managed_stream_window_size; + const real32 _temp_network_rate = observer_channel->stream_packet_rate; + const int32 _temp_network_bandwidth_per_stream = observer_channel->stream_bps; + const int32 _temp_network_window_size = observer_channel->stream_window_size; #if defined(LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS) # if LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS == true + // patches to force static network rate and bandwidth + // because the network configuration doesn't behave well in Halo 2 Vista + // since the configuration is the same + // but there are some benefits in using Online's netcode + // like limited network packet rate, otherwise people with uncapped FPS will overflow host's packet buffer + // first we check if we are dealing with a managed network stream if (observer_channel->managed_stream) { // check if we're host if (network_channel->is_simulation_authority()) { - observer_channel->net_rate_managed_stream = _online_netcode_server_rate_real; - observer_channel->net_managed_stream_bandwidth = _online_netcode_server_max_bandwidth_per_channel; + observer_channel->stream_packet_rate = _online_netcode_server_rate_real; + observer_channel->stream_bps = _online_netcode_server_max_bandwidth_per_channel; } else { - observer_channel->net_rate_managed_stream = _online_netcode_client_rate_real; - observer_channel->net_managed_stream_bandwidth = _online_netcode_client_max_bandwidth_per_channel; + observer_channel->stream_packet_rate = _online_netcode_client_rate_real; + observer_channel->stream_bps = _online_netcode_client_max_bandwidth_per_channel; } - observer_channel->net_managed_stream_window_size = _online_netcode_window_size; + observer_channel->stream_window_size = _online_netcode_window_size; } # endif // LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS == true @@ -259,24 +289,9 @@ bool __thiscall c_network_observer::channel_should_send_packet_hook( bool ret = p_channel_should_send_packet(this, network_channel_index, a3, a4, a5, out_send_sequenced_packet, out_force_fill_packet, out_packet_size, out_voice_size, out_voice_chat_data_buffer_size, out_voice_chat_data_buffer); // then we reset the values back to normal - observer_channel->net_rate_managed_stream = _temp_network_rate; - observer_channel->net_managed_stream_bandwidth = _temp_network_bandwidth_per_stream; - observer_channel->net_managed_stream_window_size = _temp_network_window_size; - - return ret; -} - -static void __declspec(naked) jmp_network_observer_channel_should_send_packet_hook() { __asm jmp c_network_observer::channel_should_send_packet_hook } - -void c_network_observer::force_constant_network_rate() -{ - // patches to force static network rate and bandwidth - // because the bandwidth management is totaly fucked/busted in Halo 2 Vista - // but there are some benefits in using Online's netcode - // like limited network packet rate, otherwise people with uncapped FPS will overflow host's packet buffer - - // replace vtable pointer of network_observer::channel_should_send_packet - WritePointer(Memory::GetAddressRelative(0x7C615C, 0x781C48), jmp_network_observer_channel_should_send_packet_hook); + observer_channel->stream_packet_rate = _temp_network_rate; + observer_channel->stream_bps = _temp_network_bandwidth_per_stream; + observer_channel->stream_window_size = _temp_network_window_size; // don't force packet filling when game simulation is attached // otherwise we send packets filled with nothing... @@ -285,52 +300,47 @@ void c_network_observer::force_constant_network_rate() // filled with nothing // unless original XNet transport layer had packet compression but even then it's rather dumb // or maybe the UDP protocol has something like that, no idea - NopFill(Memory::GetAddressRelative(0x5BF000, 0x5B8EDA), 14); + if (out_force_fill_packet) + *out_force_fill_packet = false; + + return ret; } +static void __declspec(naked) jmp_network_observer_channel_should_send_packet_hook() { __asm jmp c_network_observer::channel_should_send_packet_hook } + void c_network_observer::apply_patches() { -#if USE_LIVE_NETWORK_PROTOCOL -# if INCREASE_NETWORK_TICKRATE_OBSOLETE == true +#if defined(USE_LIVE_NETWORK_PROTOCOL) && USE_LIVE_NETWORK_PROTOCOL // increase the network tickrate of hosts to 60 - static real32 netcode_tickrate = k_online_netcode_tickrate_real; + static const real32 k_network_rate_override = k_online_netcode_server_rate_real; - WritePointer(Memory::GetAddress(0x1BDE27, 0x1B7D01) + 4, &netcode_tickrate); - WritePointer(Memory::GetAddress(0x1BE2FA, 0x1B81D4) + 4, &netcode_tickrate); - WritePointer(Memory::GetAddress(0x1BFB3C, 0x1B9A1C) + 4, &netcode_tickrate); - WritePointer(Memory::GetAddress(0x1C11FA, 0x1BB0DA) + 4, &netcode_tickrate); - WritePointer(Memory::GetAddress(0x1C12BF, 0x1BB19F) + 4, &netcode_tickrate); + WritePointer(Memory::GetAddress(0x1BDE27, 0x1B7D01) + 4, &k_network_rate_override); + WritePointer(Memory::GetAddress(0x1BE2FA, 0x1B81D4) + 4, &k_network_rate_override); + WritePointer(Memory::GetAddress(0x1BFB3C, 0x1B9A1C) + 4, &k_network_rate_override); + WritePointer(Memory::GetAddress(0x1C11FA, 0x1BB0DA) + 4, &k_network_rate_override); + WritePointer(Memory::GetAddress(0x1C12BF, 0x1BB19F) + 4, &k_network_rate_override); - g_network_configuration = Memory::GetAddress(0x4F960C, 0x523B5C); + g_network_observer_configuration = Memory::GetAddress(0x4F960C, 0x523B5C); PatchCall(Memory::GetAddress(0x1ABE23, 0x1AC328), initialize_network_observer_configuration); - // other config patches - WriteValue(Memory::GetAddress(0x1AB4A1, 0x1AB9A6) + 6, 20480 * 4); // 60 tick = H2v * 4 - WriteValue(Memory::GetAddress(0x1AB4AB, 0x1AB9B0) + 6, 51200 * 4); // 60 tick = H2v * 4 - WriteValue(Memory::GetAddress(0x1AB4C9, 0x1AB9CE) + 6, 65536 * 4); // 60 tick = H2v * 4 - WriteValue(Memory::GetAddress(0x1AB4D3, 0x1AB9D8) + 6, 32768 * 4); // 60 tick = H2v * 4 - - WriteValue(Memory::GetAddress(0x3A03CC, 0x360E54), 8192.f * 2.f); // 60 tick = H2v * 2, H2v = 8192 - WriteValue(Memory::GetAddress(0x3C60F0, 0x381BDC), 40960.f * 4.f); // 60 tick = H2v * 4, H2v = 40960 - WriteValue(Memory::GetAddress(0x3C60F4, 0x381BE0), 30720.f * 4.f); // 60 tick = H2v * 4, H2v = 30720 - WriteValue(Memory::GetAddress(0x3C60F8, 0x381BE4), 53248.f); // 60 tick = 53248, H2v = 9216 - - WriteValue(Memory::GetAddress(0x1AB4FF, 0x1ABA04) + 1, 8192 * 2); // h2v = 8192, 60 tick = h2v * 4 - WriteValue(Memory::GetAddress(0x1AB504, 0x1ABA09) + 1, 40960 * 4); // h2v = 40960, 60 tick = h2v * 4 + // increase the network heap size + WriteValue(Memory::GetAddress(0x1ACCC8, 0x1ACE96) + 6, k_network_heap_size); - WriteValue(Memory::GetAddress(0x1AB558, 0x1ABA5D) + 1, 15360 * 4); // h2v = 15360, 60 tick = h2v * 4 - WriteValue(Memory::GetAddress(0x1AB55D, 0x1ABA62) + 2, 61440 * 4); // h2v = 61440, 60 tick = h2v * 4 + PatchCall(Memory::GetAddress(0x1E0FEE, 0x1B5EDE), jmp_get_bandwidth_results); - WriteValue(Memory::GetAddress(0x1AB582, 0x1ABA87) + 1, 131072 * 4); // 60 tick - 524288 - WriteValue(Memory::GetAddress(0x1AB587, 0x1ABA8C) + 1, 262144 * 4); // 60 tick - 1048576 + WriteJmpTo(Memory::GetAddress(0x1AC1BD, 0x1A6B76), transport_get_packet_overhead_hook); - WriteValue(Memory::GetAddress(0x1AB5B6, 0x1ABABB) + 6, 10240 * 4); // 60 tick - 40960 + // replace vtable pointer of network_observer::channel_should_send_packet + WritePointer(Memory::GetAddress(0x3C615C, 0x381C48), jmp_network_observer_channel_should_send_packet_hook); // prevent the game from setting the client's tickrate to half of host network tickrate NopFill(Memory::GetAddress(0x1BFBE7, 0x1B9AC7), 19); NopFill(Memory::GetAddress(0x1BE33A, 0x1B8214), 15); NopFill(Memory::GetAddress(0x1BDF1D, 0x1B7DF7), 18); -# endif // if INCREASE_NETWORK_TICKRATE_OBSOLETE == true + + // disable upstream bandwidth estimate override + // note it doesn't even work on dedicated servers, keeping server hosts using the lowest upstream bandwidth available + NopFill(Memory::GetAddress(0x1C00F6, 0x1B9FD6), 2); #else // disables LIVE netcode WriteValue(Memory::GetAddress(0x1B555B, 0x1A92B9) + 1, 0); @@ -339,19 +349,6 @@ void c_network_observer::apply_patches() WriteValue(Memory::GetAddress(0x1D4E35, 0x1C1B7F), 0xEB); // jmp #endif - // increase the network heap size - WriteValue(Memory::GetAddress(0x1ACCC8, 0x1ACE96) + 6, k_network_heap_size); - - PatchCall(Memory::GetAddress(0x1E0FEE, 0x1B5EDE), jmp_get_bandwidth_results); - - WriteJmpTo(Memory::GetAddressRelative(0x5AC1BD, 0x5A6B76), transport_get_packet_overhead_hook); - -#if defined(LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS) -#if LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS == true - force_constant_network_rate(); -#endif // LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS == true -#endif // defined(LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS) - // disable forced host migration in P2P games // this is using the XNet QoS probes to select a preferred host with a possible better connection // which is not really available anymore with cartographer, since the QoS probes are not that accurate anymore diff --git a/xlive/Blam/Engine/networking/transport/network_observer.h b/xlive/Blam/Engine/networking/transport/network_observer.h index 24018fb88..4f7f72d64 100644 --- a/xlive/Blam/Engine/networking/transport/network_observer.h +++ b/xlive/Blam/Engine/networking/transport/network_observer.h @@ -18,7 +18,7 @@ #if defined(USE_LIVE_NETWORK_PROTOCOL) # if USE_LIVE_NETWORK_PROTOCOL == true # define INCREASE_NETWORK_TICKRATE_OBSOLETE 0 // old method of incresing the packet rate, now OBSOLETE -# define LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS 1 +# define LIVE_NETWORK_PROTOCOL_FORCE_CONSTANT_NETWORK_PARAMETERS true # endif #endif #endif @@ -35,6 +35,8 @@ #define k_online_netcode_client_rate_real 60.0f #define k_online_netcode_server_rate_real 60.0f +#define k_online_netcode_rate_real 60.0f + #define k_online_netcode_client_max_packet_size_bytes 1264 #define k_online_netcode_server_max_packet_size_bytes 1264 @@ -109,9 +111,9 @@ struct alignas(8) s_observer_channel bool simulation_authority; bool simulation_not_authority; uint8 gap_6A9[3]; - int32 net_managed_stream_bandwidth; - int32 net_managed_stream_window_size; - real32 net_rate_managed_stream; + int32 stream_bps; + int32 stream_window_size; + real32 stream_packet_rate; bool field_6B8; int8 field_6B9; int8 field_6BA; @@ -160,7 +162,7 @@ struct alignas(8) c_network_observer void* m_network_link; void* m_network_message_gateway; void* m_message_types; - s_network_observer_configuration* configuration; + s_network_observer_configuration* m_configuration; int32 *field_14; uint8 gap_18[8]; XNKID session_id; @@ -218,7 +220,7 @@ struct alignas(8) c_network_observer bool a5, int32 a6, int32* out_send_sequenced_packet, - int32* out_force_fill_packet, + bool* out_force_fill_packet, int32* out_packet_size, int32* out_voice_size, int32 out_voice_chat_data_buffer_size, @@ -233,22 +235,22 @@ struct alignas(8) c_network_observer }; ASSERT_STRUCT_SIZE(c_network_observer, 0x75C8); -struct s_network_observer_configuration +struct __declspec(align(4)) s_network_observer_configuration { int32 field_0; int32 field_4; - uint8 gap_8[28]; + int8 gap_8[28]; int32 field_24; int32 field_28; int32 field_2C; int32 field_30; - uint8 gap_34[20]; + int8 gap_34[20]; int32 field_48; int32 field_4C; int32 field_50; int32 field_54; int32 field_58; - uint8 gap_5C[16]; + int8 gap_5C[16]; int32 field_6C; int32 field_70; int32 field_74; @@ -261,10 +263,9 @@ struct s_network_observer_configuration real32 field_90; real32 field_94; real32 field_98; - int32 unk_total_flt_array_elements; - real32 unk_floats_A0[7]; - uint8 gap_BC[36]; - int32 field_E0; + int32 stream_packet_rate_throttle_scale_stage_count; + real32 stream_packet_rate_throttle_scale_stages[16]; + int32 stream_minimum_window_size_bytes; real32 field_E4; real32 field_E8; real32 field_EC; @@ -274,10 +275,10 @@ struct s_network_observer_configuration int32 field_FC; int32 field_100; real32 field_104; - int32 field_108; - int32 field_10C; - real32 field_110; - int32 field_114; + int32 avg_payload_size_outside_simulation; + int32 avg_payload_size_in_simulation; + real32 minimum_packet_rate_scale; + int32 minimum_estimated_upstream_bandwidth_bps; int32 field_118; real32 field_11C; int32 field_120; @@ -289,30 +290,30 @@ struct s_network_observer_configuration int32 field_138; int32 field_13C; int32 field_140; - uint8 field_144; + int32 field_144; int32 field_148; - int32 field_14C; - int32 field_150; + int32 stream_minimum_bps; + int32 stream_maximum_bps; int32 field_154; - int32 max_bits_per_second_single_player; - int32 max_bits_per_second_full_lobby; - int32 max_bits_per_second_splitscreen_players; - int32 field_164; + int32 stream_desired_bps; + int32 upstream_bandwidth0; + int32 upstream_bandwidth1; + int32 stream_default_bps; int32 field_168; int32 field_16C; int32 field_170; int32 field_174; real32 field_178; int32 field_17C; - real32 field_180; + real32 stream_packet_rate_scale_during_packet_loss; int32 field_184; int32 field_188; - int32 field_18C; + int32 stream_maximum_bps_regrowth_per_cycle; real32 field_190; - int32 field_194; + int32 stream_maximum_bps_throttle_per_cycle; real32 field_198; int32 field_19C; - int32 field_1A0; + int32 stream_minimum_period_before_adjust_attempt_msec; int32 field_1A4; int32 field_1A8; real32 field_1AC; diff --git a/xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp b/xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp index 3f32b659f..7973addda 100644 --- a/xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp +++ b/xlive/Blam/Engine/render/render_cartographer_ingame_ui.cpp @@ -271,17 +271,19 @@ void render_netdebug_text(void) { s_simulation_player_netdebug_data netdebug_data_default{}; s_simulation_player_netdebug_data* netdebug_data = &netdebug_data_default; + s_observer_channel* observer_channel = NULL; + int32 observer_channel_index; if (!session->is_host()) { s_membership_peer* membership_peer = session->get_peer_membership(session->get_local_peer_index()); - int32 observer_channel_index = session->m_session_peers[session->get_session_host_peer_index()].observer_channel_index; + observer_channel_index = session->m_session_peers[session->get_session_host_peer_index()].observer_channel_index; if (observer_channel_index != NONE) { - s_observer_channel* observer_channel = &session->m_network_observer->m_observer_channels[observer_channel_index]; + observer_channel = &session->m_network_observer->m_observer_channels[observer_channel_index]; netdebug_data->client_rtt_msec = observer_channel->net_rtt; - netdebug_data->client_packet_rate = observer_channel->net_rate_managed_stream * 10.f; + netdebug_data->client_packet_rate = observer_channel->stream_packet_rate * 10.f; netdebug_data->client_throughput = (observer_channel->throughput_bps * 10.f) / 1024.f; netdebug_data->client_packet_loss_percentage = observer_channel->field_440.average_values_in_window() * 100.f; @@ -312,7 +314,7 @@ void render_netdebug_text(void) text_color_console.alpha *= (65.f / 100.f); swprintf_s(netdebug_text, ARRAYSIZE(netdebug_text), - L"[up^ rtt: %d msec, pck rate: %.3f, throughput: %.3f bps, loss: %d %%]", + L"[up^ rtt: %3d msec, pck rate: %.1f, throughput: %.3f bps, loss: %3d %%]", netdebug_data->client_rtt_msec, (real32)netdebug_data->client_packet_rate / 10.f, ((real32)netdebug_data->client_throughput / 10.f) * 1024.f,