From b88a2a0f3b85e22e783668e5778b6e29720f9a31 Mon Sep 17 00:00:00 2001 From: NukeULater Date: Mon, 4 May 2020 09:19:53 +0300 Subject: [PATCH 1/6] Fixed broadcast packet --- xlive/XLive/xnet/IpManagement/XnIp.h | 7 ------- xlive/XLive/xnet/Sockets/XSocket.cpp | 10 ++++++---- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/xlive/XLive/xnet/IpManagement/XnIp.h b/xlive/XLive/xnet/IpManagement/XnIp.h index 18e976264..337dbd3ed 100644 --- a/xlive/XLive/xnet/IpManagement/XnIp.h +++ b/xlive/XLive/xnet/IpManagement/XnIp.h @@ -38,12 +38,6 @@ struct XNetPacketHeader struct XBroadcastPacket { - XBroadcastPacket() - { - pckHeader.intHdr = 'BrOd'; - strncpy(pckHeader.HdrStr, broadcastStrHdr, MAX_HDR_STR); - } - XNetPacketHeader pckHeader; struct XBroadcast { @@ -62,7 +56,6 @@ struct XNetRequestPacket } XNetPacketHeader pckHeader; - struct XNetReq { XNKID xnkid; diff --git a/xlive/XLive/xnet/Sockets/XSocket.cpp b/xlive/XLive/xnet/Sockets/XSocket.cpp index 1071505ab..aeabecadd 100644 --- a/xlive/XLive/xnet/Sockets/XSocket.cpp +++ b/xlive/XLive/xnet/Sockets/XSocket.cpp @@ -291,11 +291,13 @@ int WINAPI XSocketWSASendTo(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, L //inTo->sin_addr.s_addr = H2Config_master_ip; //inTo->sin_port = ntohs(H2Config_master_port_relay); - XBroadcastPacket* packet = (XBroadcastPacket*)new char[sizeof(XBroadcastPacket) + lpBuffers->len]; + XBroadcastPacket* packet = (XBroadcastPacket*)malloc(sizeof(XBroadcastPacket) + lpBuffers->len); + packet->pckHeader.intHdr = 'BrOd'; + strncpy(packet->pckHeader.HdrStr, broadcastStrHdr, MAX_HDR_STR); ZeroMemory(&packet->data, sizeof(XBroadcastPacket::XBroadcast)); packet->data.name.sin_addr.s_addr = INADDR_BROADCAST; - memcpy((char*)&packet->data + sizeof(XBroadcastPacket), lpBuffers->buf, lpBuffers->len); + memcpy((char*)packet + sizeof(XBroadcastPacket), lpBuffers->buf, lpBuffers->len); int portOffset = H2Config_base_port % 1000; @@ -304,11 +306,11 @@ int WINAPI XSocketWSASendTo(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, L inTo->sin_port = ntohs(i + portOffset + 1); int result = sendto(xsocket->winSockHandle, (const char*)packet, sizeof(XBroadcastPacket) + lpBuffers->len, dwFlags, (sockaddr*)inTo, iTolen); if (result == SOCKET_ERROR) { - delete[] packet; + free(packet); return SOCKET_ERROR; } } - delete[] packet; + free(packet); return ERROR_SUCCESS; } From 412bad6a1df9d670034d7aad26e1a0f3816cee80 Mon Sep 17 00:00:00 2001 From: NukeULater Date: Thu, 7 May 2020 13:08:10 +0300 Subject: [PATCH 2/6] Fixed error login menus not popping up when login fails --- xlive/H2MOD/Modules/Accounts/AccountLogin.cpp | 23 +++++++++---------- xlive/H2MOD/Modules/Accounts/AccountLogin.h | 2 +- xlive/H2MOD/Modules/CustomMenu/CustomMenu.cpp | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/xlive/H2MOD/Modules/Accounts/AccountLogin.cpp b/xlive/H2MOD/Modules/Accounts/AccountLogin.cpp index 1ffdfc1cc..442f92976 100644 --- a/xlive/H2MOD/Modules/Accounts/AccountLogin.cpp +++ b/xlive/H2MOD/Modules/Accounts/AccountLogin.cpp @@ -375,7 +375,7 @@ static int InterpretMasterLogin(char* response_content, char* prev_login_token) return result; } -bool HandleGuiLogin(char* ltoken, char* identifier, char* password, DWORD* out_master_login_interpret_result) { +bool HandleGuiLogin(char* ltoken, char* identifier, char* password, int* out_master_login_interpret_result) { bool result = false; char* rtn_result = 0; @@ -427,14 +427,14 @@ bool HandleGuiLogin(char* ltoken, char* identifier, char* password, DWORD* out_m free(escaped_user_password); int master_login_interpret_result = -1; - int rtn_code = MasterHttpResponse("https://cartographer.online/login2", http_request_body_build, rtn_result); + int master_http_response_result = MasterHttpResponse("https://cartographer.online/login2", http_request_body_build, rtn_result); for (int i = strlen(http_request_body_build) - 1; i >= 0; i--) { http_request_body_build[i] = 0; } free(http_request_body_build); - if (rtn_code == 0) { + if (master_http_response_result == 0) { master_login_interpret_result = InterpretMasterLogin(rtn_result, ltoken); if (master_login_interpret_result > 0) { result = true; @@ -447,7 +447,6 @@ bool HandleGuiLogin(char* ltoken, char* identifier, char* password, DWORD* out_m addDebugText(NotificationPlayerText); if (master_login_interpret_result == ERROR_CODE_INVALID_LOGIN_TOKEN) { - char* username = 0; for (int i = 0; i < H2AccountCount; i++) { if (H2AccountBufferLoginToken[i] && strcmp(H2AccountBufferLoginToken[i], ltoken) == 0) { @@ -461,14 +460,14 @@ bool HandleGuiLogin(char* ltoken, char* identifier, char* password, DWORD* out_m snprintf(login_identifier, strlen(username) + 1, username); } } - else { - if (!H2IsDediServer) { - char* login_identifier = H2CustomLanguageGetLabel(CMLabelMenuId_AccountEdit, 1); - SecureZeroMemory(login_identifier, strlen(login_identifier)); - } - if (master_login_interpret_result == SUCCESS_CODE_MACHINE_SERIAL_INSUFFICIENT) { - result = false; - } + } + else { + if (!H2IsDediServer) { + char* login_identifier = H2CustomLanguageGetLabel(CMLabelMenuId_AccountEdit, 1); + SecureZeroMemory(login_identifier, strlen(login_identifier)); + } + if (master_login_interpret_result == SUCCESS_CODE_MACHINE_SERIAL_INSUFFICIENT) { + result = false; } } diff --git a/xlive/H2MOD/Modules/Accounts/AccountLogin.h b/xlive/H2MOD/Modules/Accounts/AccountLogin.h index 85d7df583..0bca3d515 100644 --- a/xlive/H2MOD/Modules/Accounts/AccountLogin.h +++ b/xlive/H2MOD/Modules/Accounts/AccountLogin.h @@ -14,7 +14,7 @@ const int ERROR_CODE_MACHINE_SERIAL_INSUFFICIENT = -13; const int SUCCESS_CODE_MACHINE_SERIAL_INSUFFICIENT = 7; void UpdateConnectionStatus(); -bool HandleGuiLogin(char* token, char* identifier, char* password, DWORD* master_login_interpret_result); +bool HandleGuiLogin(char* token, char* identifier, char* password, int* master_login_interpret_result); char ConfigureUserDetails(char* username, char* login_token, unsigned long long xuid, unsigned long saddr, unsigned long xnaddr, char* abEnet, char* abOnline, bool onlineSignIn); extern bool AccountEdit_remember; diff --git a/xlive/H2MOD/Modules/CustomMenu/CustomMenu.cpp b/xlive/H2MOD/Modules/CustomMenu/CustomMenu.cpp index b4aea7beb..d6f3536ea 100644 --- a/xlive/H2MOD/Modules/CustomMenu/CustomMenu.cpp +++ b/xlive/H2MOD/Modules/CustomMenu/CustomMenu.cpp @@ -3890,7 +3890,7 @@ __declspec(naked) void sub_2111ab_CMLTD_nak_AccountEdit() {//__thiscall } } -static DWORD master_login_code; +static int master_login_code; static HANDLE hThreadLogin = INVALID_HANDLE_VALUE; void xbox_live_task_progress_callback(DWORD a1) From 78a74de5895734330551e0bd0d624bd9f60dcbe9 Mon Sep 17 00:00:00 2001 From: NukeULater Date: Mon, 11 May 2020 19:35:51 +0300 Subject: [PATCH 3/6] Fixed game time counter from breaking the LIVE netcode Also prevent some unneeded code from running on dedicated servers --- xlive/H2MOD.cpp | 19 +++++++++++++++++-- xlive/H2MOD/Modules/MainMenu/Ranks.cpp | 10 ++-------- xlive/H2MOD/Modules/Tweaks/Tweaks.cpp | 2 ++ .../H2MOD/Modules/UI/XboxLiveTaskProgress.cpp | 2 +- xlive/H2MOD/Variants/XboxTick/XboxTick.cpp | 10 +--------- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/xlive/H2MOD.cpp b/xlive/H2MOD.cpp index 4f6746c5e..3b6fb2ad2 100644 --- a/xlive/H2MOD.cpp +++ b/xlive/H2MOD.cpp @@ -813,7 +813,6 @@ bool __cdecl OnMapLoad(game_engine_settings* engine_settings) H2Tweaks::setCrosshairPos(H2Config_crosshair_offset); H2Tweaks::setVehicleFOV(H2Config_vehicle_field_of_view); - if (h2mod->GetMapType() == scnr_type::MainMenu) { addDebugText("Map Type: Main-Menu"); @@ -839,11 +838,15 @@ bool __cdecl OnMapLoad(game_engine_settings* engine_settings) b_GunGame = false; } + if (b_XboxTick) { + engine_settings->tickrate = XboxTick::setTickRate(false); + b_XboxTick = false; + } + UIRankPatch(); H2Tweaks::setHz(); H2Tweaks::toggleAiMp(false); H2Tweaks::toggleUncappedCampaignCinematics(false); - engine_settings->tickrate = XboxTick::setTickRate(false); return result; } @@ -1250,6 +1253,16 @@ void __cdecl game_mode_engine_draw_team_indicators() p_game_mode_engine_draw_team_indicators(); } +bool __cdecl game_is_minimized_hook() +{ + // if xbox tickrate is set, use the built in frame limiter + if (b_XboxTick) + return true; + + // otherwise never use this frame limiter + return false; +} + void H2MOD::ApplyUnitHooks() { // increase the size of the unit entity creation definition packet @@ -1320,6 +1333,8 @@ void H2MOD::ApplyHooks() { LOG_TRACE_GAME("Applying client hooks..."); /* These hooks are only built for the client, don't enable them on the server! */ + PatchCall(h2mod->GetAddress(0x288B5), game_is_minimized_hook); + p_verify_game_version_on_join = (verify_game_version_on_join)DetourFunc(h2mod->GetAddress(0x1B4C14), (BYTE*)VerifyGameVersionOnJoin, 5); p_verify_executable_version = (verify_executable_version)DetourFunc(h2mod->GetAddress(0x1B4C32), (BYTE*)VerifyExecutableVersion, 8); diff --git a/xlive/H2MOD/Modules/MainMenu/Ranks.cpp b/xlive/H2MOD/Modules/MainMenu/Ranks.cpp index 5b1494269..070da365a 100644 --- a/xlive/H2MOD/Modules/MainMenu/Ranks.cpp +++ b/xlive/H2MOD/Modules/MainMenu/Ranks.cpp @@ -8,10 +8,7 @@ void UIRankPatch() { - if (H2IsDediServer) - return; - - if (!tags::get_cache_header()->is_main_menu()) //If not on mainmenu, returns + if (h2mod->GetMapType() != MainMenu || h2mod->Server) return; BYTE PlayerLevel = -1; //eventually this will pull level from webserver @@ -27,7 +24,6 @@ void UIRankPatch() { //Tag : ui\player_skins\pcr_2.skin const DWORD TagOffsetPostGameCarnage2 = 0x00485F50; //Property : Bitmap Buttons - const BYTE pSkinChunkSize = 0x38; //Property size per chunk const int pSkinChunkIndex = 2; //Property chunk index number (2 represents rank field) const BYTE xDefOffset = 0x0C; //Definition : Horizontal position on mainmenu @@ -46,7 +42,6 @@ void UIRankPatch() { const DWORD RankIconSM = 0xE4EC02CA; //Bitmap Datum Index const DWORD RankIconSMOff = 0x00476D3C; //Property : Bitmap - const BYTE RankChunkSize = 0x74; //Property size per chunk int RankChunkIndex; //Property chunk index number (0-49) const BYTE WidthDefOff = 0x04; //Definition : Width @@ -54,8 +49,7 @@ void UIRankPatch() { const BYTE HeightDefOff = 0x06; //Definition : Height const WORD HeightValue = 0x0020; //Value : 32 (decimal) - - //Sets Pregame Lobby + //Sets Pregame Lobby WriteValue((DWORD)&tags::get_tag_data()[TagOffsetPreGameLobby + (pSkinChunkIndex * pSkinChunkSize) + yDefOffset], yValuePGL); WriteValue((DWORD)&tags::get_tag_data()[TagOffsetPreGameLobby + (pSkinChunkIndex * pSkinChunkSize) + bitmOffset], RankIconSM); WriteValue((DWORD)&tags::get_tag_data()[TagOffsetPreGameLobby + (pSkinChunkIndex * pSkinChunkSize) + xDefOffset], xValuePGL); diff --git a/xlive/H2MOD/Modules/Tweaks/Tweaks.cpp b/xlive/H2MOD/Modules/Tweaks/Tweaks.cpp index 277832625..c2e649be8 100644 --- a/xlive/H2MOD/Modules/Tweaks/Tweaks.cpp +++ b/xlive/H2MOD/Modules/Tweaks/Tweaks.cpp @@ -861,6 +861,8 @@ void fix_shader_template_nvidia(const std::string &template_name, const std::str void fix_shaders_nvidia() { + if (h2mod->Server) return; + fix_shader_template_nvidia( "shaders\\shader_templates\\opaque\\tex_bump_alpha_test_single_pass", "shaders\\default_bitmaps\\bitmaps\\alpha_white", diff --git a/xlive/H2MOD/Modules/UI/XboxLiveTaskProgress.cpp b/xlive/H2MOD/Modules/UI/XboxLiveTaskProgress.cpp index cb349eb74..afe9feb1a 100644 --- a/xlive/H2MOD/Modules/UI/XboxLiveTaskProgress.cpp +++ b/xlive/H2MOD/Modules/UI/XboxLiveTaskProgress.cpp @@ -17,7 +17,7 @@ void c_xbox_live_task_progress_menu::Open(void* callback) void c_xbox_live_task_progress_menu::ApplyPatches() { - if (h2mod->GetMapType() != MainMenu) return; + if (h2mod->GetMapType() != MainMenu || h2mod->Server) return; std::string task_progress_dialog_tag_path("ui\\screens\\game_shell\\xbox_live\\task_progress_dialog\\task_progress_dialog"); diff --git a/xlive/H2MOD/Variants/XboxTick/XboxTick.cpp b/xlive/H2MOD/Variants/XboxTick/XboxTick.cpp index c60e00d4d..de77e2617 100644 --- a/xlive/H2MOD/Variants/XboxTick/XboxTick.cpp +++ b/xlive/H2MOD/Variants/XboxTick/XboxTick.cpp @@ -5,7 +5,7 @@ int XboxTick::setTickRate(bool enable) { int tickrate = 60; - if (enable) // enable + if (enable) { tickrate = 30; @@ -13,10 +13,6 @@ int XboxTick::setTickRate(bool enable) if (!h2mod->Server) WriteBytes(h2mod->GetAddress(0x3A938, 0x8DCE5), mov_al_1_retn, sizeof(mov_al_1_retn)); - BYTE jne[] = { 0x85 }; - if (!h2mod->Server) - WriteBytes(h2mod->GetAddress(0x288BD, 0x249CB), jne, sizeof(jne)); - LOG_TRACE_GAME("[h2mod] Set the game tickrate to 30"); } else @@ -26,10 +22,6 @@ int XboxTick::setTickRate(bool enable) if (!h2mod->Server) WriteBytes(h2mod->GetAddress(0x3A938, 0x8DCE5), push_ebp_xor_bl_bl, sizeof(push_ebp_xor_bl_bl)); - BYTE je[] = { 0x84 }; - if (!h2mod->Server) - WriteBytes(h2mod->GetAddress(0x288BD, 0x249CB), je, sizeof(je)); - LOG_TRACE_GAME("[h2mod] Set the game tickrate to 60"); } From 052c2c64b7c1d3720e8954e7d33a17d43f6d4c74 Mon Sep 17 00:00:00 2001 From: NukeULater Date: Mon, 11 May 2020 20:40:59 +0300 Subject: [PATCH 4/6] Added more safety checks for received packets, to prevent passing the game a bad packet Also don't use mt19937 rand engine to create a new connection identifier --- xlive/XLive/xnet/IpManagement/XnIp.cpp | 118 +++++++++++++------------ 1 file changed, 63 insertions(+), 55 deletions(-) diff --git a/xlive/XLive/xnet/IpManagement/XnIp.cpp b/xlive/XLive/xnet/IpManagement/XnIp.cpp index 251875c11..142ad5d45 100644 --- a/xlive/XLive/xnet/IpManagement/XnIp.cpp +++ b/xlive/XLive/xnet/IpManagement/XnIp.cpp @@ -50,73 +50,82 @@ void CXnIp::setTimeConnectionInteractionHappened(IN_ADDR ina, int time) int CXnIp::handleRecvdPacket(XSocket* xsocket, sockaddr_in* lpFrom, WSABUF* lpBuffers, LPDWORD bytesRecvdCount) { - XNetPacketHeader* XNetPck = reinterpret_cast(lpBuffers->buf); - switch (XNetPck->intHdr) + // check first if the packet received has the size bigger or equal to the XNet packet header first + if (*bytesRecvdCount >= sizeof(XNetPacketHeader)) { - case 'BrOd': - { - XBroadcastPacket* broadcastPck = reinterpret_cast(lpBuffers->buf); - if (*bytesRecvdCount >= sizeof(XBroadcastPacket) - && strncmp(broadcastPck->pckHeader.HdrStr, broadcastStrHdr, MAX_HDR_STR) == 0 - && broadcastPck->data.name.sin_addr.s_addr == INADDR_BROADCAST) + XNetPacketHeader* XNetPck = reinterpret_cast(lpBuffers->buf); + switch (XNetPck->intHdr) + { + case 'BrOd': { - if (*bytesRecvdCount > sizeof(XBroadcastPacket)) + XBroadcastPacket* broadcastPck = reinterpret_cast(lpBuffers->buf); + if (*bytesRecvdCount >= sizeof(XBroadcastPacket) + && strncmp(broadcastPck->pckHeader.HdrStr, broadcastStrHdr, MAX_HDR_STR) == 0 + && broadcastPck->data.name.sin_addr.s_addr == INADDR_BROADCAST) { - *bytesRecvdCount = *bytesRecvdCount - sizeof(XBroadcastPacket); - char* buffer = new char[*bytesRecvdCount]; - memcpy(buffer, lpBuffers->buf + sizeof(XBroadcastPacket), *bytesRecvdCount); - memcpy(lpBuffers->buf, buffer, *bytesRecvdCount); - delete[] buffer; - return ERROR_SUCCESS; + if (*bytesRecvdCount > sizeof(XBroadcastPacket)) + { + *bytesRecvdCount = *bytesRecvdCount - sizeof(XBroadcastPacket); + char* buffer = new char[*bytesRecvdCount]; + memcpy(buffer, lpBuffers->buf + sizeof(XBroadcastPacket), *bytesRecvdCount); + memcpy(lpBuffers->buf, buffer, *bytesRecvdCount); + delete[] buffer; + return ERROR_SUCCESS; + } + // set the bytes received count to 0 + *bytesRecvdCount = 0; + WSASetLastError(WSAEWOULDBLOCK); + return SOCKET_ERROR; } - WSASetLastError(WSAEWOULDBLOCK); - return SOCKET_ERROR; } - } - case 'XNeT': - { - XNetRequestPacket* XNetPck = reinterpret_cast(lpBuffers->buf); - if (*bytesRecvdCount == sizeof(XNetRequestPacket) - && strncmp(XNetPck->pckHeader.HdrStr, requestStrHdr, MAX_HDR_STR) == 0) + case 'XNeT': { - switch (XNetPck->data.reqType) + XNetRequestPacket* XNetPck = reinterpret_cast(lpBuffers->buf); + if (*bytesRecvdCount == sizeof(XNetRequestPacket) + && strncmp(XNetPck->pckHeader.HdrStr, requestStrHdr, MAX_HDR_STR) == 0) { - case XnIp_ConnectionEstablishSecure: - LOG_TRACE_NETWORK("handleRecvdPacket() - Received secure packet with ip address {:x}, port: {}", htonl(lpFrom->sin_addr.s_addr), htons(lpFrom->sin_port)); - HandleConnectionPacket(xsocket, XNetPck, lpFrom); // save NAT info and send back a connection packet - break; + switch (XNetPck->data.reqType) + { + case XnIp_ConnectionEstablishSecure: + LOG_TRACE_NETWORK("handleRecvdPacket() - Received secure packet from ip address {:x}, port: {}", htonl(lpFrom->sin_addr.s_addr), htons(lpFrom->sin_port)); + HandleConnectionPacket(xsocket, XNetPck, lpFrom); // save NAT info and send back a connection packet + break; + + case XnIp_ConnectionClose: + case XnIp_ConnectionPong: + case XnIp_ConnectionPing: + default: + break; + } - case XnIp_ConnectionClose: - case XnIp_ConnectionPong: - case XnIp_ConnectionPing: - default: - break; + // set the bytes received count to 0 + *bytesRecvdCount = 0; + WSASetLastError(WSAEWOULDBLOCK); + return SOCKET_ERROR; } - - WSASetLastError(WSAEWOULDBLOCK); - return SOCKET_ERROR; } + + default: + break; + } // switch (XNetPck->intHdr) } - default: - { - IN_ADDR ipIdentifier = GetConnectionIdentifierByRecvAddr(xsocket, lpFrom); - lpFrom->sin_addr = ipIdentifier; + IN_ADDR ipIdentifier = GetConnectionIdentifierByRecvAddr(xsocket, lpFrom); + lpFrom->sin_addr = ipIdentifier; - /* Let the game know the packet received came from an unkown source */ - if (lpFrom->sin_addr.s_addr == 0) - { - WSASetLastError(WSAEWOULDBLOCK); - return SOCKET_ERROR; - } + // Let the game know the packet received came from an unkown source + if (lpFrom->sin_addr.s_addr == 0) + { + // set the bytes received count to 0 + *bytesRecvdCount = 0; + WSASetLastError(WSAEWOULDBLOCK); + return SOCKET_ERROR; + } - setTimeConnectionInteractionHappened(ipIdentifier, timeGetTime()); + setTimeConnectionInteractionHappened(ipIdentifier, timeGetTime()); - return ERROR_SUCCESS; - } - - } // switch (XNetPck->intHdr) + return ERROR_SUCCESS; } void CXnIp::checkForLostConnections() @@ -311,6 +320,7 @@ int CXnIp::CreateXnIpIdentifier(const XNADDR* pxna, const XNKID* xnkid, IN_ADDR* return WSAEINVAL; } + // clear any lost connections before creating another one checkForLostConnections(); // check if the user is already in the system @@ -339,16 +349,14 @@ int CXnIp::CreateXnIpIdentifier(const XNADDR* pxna, const XNKID* xnkid, IN_ADDR* { if (firstUnusedConnectionIndexFound) { - std::mt19937 mt_rand(rd()); - std::uniform_int_distribution dist(1, 255); - XnIp* newXnIp = &XnIPs[firstUnusedConnectionIndex]; SecureZeroMemory(newXnIp, sizeof(XnIp)); newXnIp->xnkid = *xnkid; newXnIp->xnaddr = *pxna; - int randIdentifier = dist(mt_rand); + // if this is zero we are fucked + int randIdentifier = (rand() % 0xFF) + 1; // 0 to 254 + 1 randIdentifier <<= 8; LOG_INFO_NETWORK("CreateXnIpIdentifier() - new connection index {}, identifier {:x}", firstUnusedConnectionIndex, htonl(firstUnusedConnectionIndex | randIdentifier)); From e4c7ed209a9d68bc58bbfd697f5b4166edd5ffe3 Mon Sep 17 00:00:00 2001 From: NukeULater Date: Sat, 30 May 2020 18:25:14 +0300 Subject: [PATCH 5/6] Added network_channel structure and custom packets code cleanup --- .../CustomPackets/CustomPackets.cpp | 50 +++++-------- .../Networking/CustomPackets/CustomPackets.h | 8 ++- .../Modules/Networking/Memory/bitstream.cpp | 50 ++++++------- .../Modules/Networking/Memory/bitstream.h | 18 +++-- .../NetworkChannel/NetworkChannel.cpp | 18 +++++ .../NetworkChannel/NetworkChannel.h | 70 +++++++++++++++++++ .../NetworkConfiguration.cpp | 4 +- .../NetworkConfiguration.h | 6 ++ .../NetworkObserver/NetworkObserver.cpp | 5 +- .../NetworkObserver/NetworkObserver.h | 28 +++++--- .../NetworkSession/NetworkSession.cpp | 4 +- .../NetworkSession/NetworkSession.h | 11 +-- xlive/Project_Cartographer.vcxproj | 2 + xlive/Project_Cartographer.vcxproj.filters | 6 ++ 14 files changed, 189 insertions(+), 91 deletions(-) create mode 100644 xlive/H2MOD/Modules/Networking/NetworkChannel/NetworkChannel.cpp create mode 100644 xlive/H2MOD/Modules/Networking/NetworkChannel/NetworkChannel.h diff --git a/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.cpp b/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.cpp index 272a3cc3a..b185daf38 100644 --- a/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.cpp +++ b/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.cpp @@ -10,16 +10,11 @@ char g_network_message_types[e_network_message_types::end * 32]; -void register_packet_impl(void *packetObject, int type, char* name, int a4, int size1, int size2, void* write_packet_method, void* read_packet_method, void* a9) +void register_packet_impl(void *packetObject, int type, char* name, int a4, int size1, int size2, void* write_packet_method, void* read_packet_method, void* unk_callback) { - typedef void(__thiscall* register_packet_type)(void *packetObject, int type, char* name, int a4, int size1, int size2, void* write_packet_method, void* read_packet_method, void* a9); + typedef void(__thiscall* register_packet_type)(void *, int, char*, int, int, int, void*, void*, void*); auto register_packet = reinterpret_cast(h2mod->GetAddress(0x1E81D6, 0x1CA199)); - return register_packet(packetObject, type, name, a4, size1, size2, write_packet_method, read_packet_method, a9); -} - -char* getNetworkChannelData(int channel_index) -{ - return *h2mod->GetAddress(0x4FADBC, 0x525274) + 248 * channel_index; + return register_packet(packetObject, type, name, a4, size1, size2, write_packet_method, read_packet_method, unk_callback); } const char* getNetworkMessageName(int enumVal) @@ -27,30 +22,23 @@ const char* getNetworkMessageName(int enumVal) return network_message_name[enumVal]; } -bool getNetworkAddressFromNetworkChannel(char* network_channel, network_address* out_addr) -{ - typedef bool(__thiscall* get_network_address_from_network_channel)(char*, network_address*); - auto p_get_network_address_from_network_channel = reinterpret_cast(h2mod->GetAddress(0x1BA543, 0x1C9364)); - return p_get_network_address_from_network_channel(network_channel, out_addr); -} - void __cdecl encode_map_file_name_packet(bitstream* stream, int a2, s_custom_map_filename* data) { - stream->data_encode_string("map-file-name", (int)&data->file_name, 32); + stream->data_encode_string("map-file-name", &data->file_name, ARRAYSIZE(data->file_name)); } bool __cdecl decode_map_file_name_packet(bitstream* stream, int a2, s_custom_map_filename* data) { - stream->data_decode_string("map-file-name", (int)&data->file_name, 32); + stream->data_decode_string("map-file-name", &data->file_name, ARRAYSIZE(data->file_name)); return stream->packet_is_valid() == false; } void __cdecl encode_request_map_filename_packet(bitstream* stream, int a2, s_request_map_filename* data) { - stream->data_encode_bits("user-identifier", &data->user_identifier, 64); + stream->data_encode_bits("user-identifier", &data->user_identifier, player_identifier_size_bits); } bool __cdecl decode_request_map_filename_packet(bitstream* stream, int a2, s_request_map_filename* data) { - stream->data_decode_bits("user-identifier", (int)&data->user_identifier, 64); + stream->data_decode_bits("user-identifier", &data->user_identifier, player_identifier_size_bits); return stream->packet_is_valid() == false; } @@ -115,11 +103,11 @@ void __stdcall handle_out_of_band_message_hook(void *thisx, network_address* add if (map_filename.size() > 0) { data.is_custom_map = true; - wcsncpy_s(data.file_name, map_filename.c_str(), 32); + wcsncpy_s(data.file_name, map_filename.c_str(), ARRAYSIZE(data.file_name)); } LOG_TRACE_NETWORK(L"[H2MOD-CustomPackets] sending map file name packet to XUID: {}, peer index: {}, map name: {}", received_data->user_identifier, peer_index, map_filename.c_str()); - observer_channel_send_message(session->network_observer_ptr, session->unk_index, session->peer_observer_channels[peer_index].observer_index, true, + observer_channel_send_message(session->network_observer_ptr, session->unk_index, session->peer_observer_channels[peer_index].observer_index, network_observer::network_message_send_protocol::out_of_band, map_file_name, sizeof(s_custom_map_filename), &data); } @@ -174,10 +162,9 @@ void __stdcall handle_channel_message_hook(void *thisx, int network_channel_inde This handles received in-band data */ - char* network_channel = getNetworkChannelData(network_channel_index); network_address addr; - SecureZeroMemory(&addr, sizeof(network_address)); - getNetworkAddressFromNetworkChannel(network_channel, &addr); + network_channel* peer_network_channel = network_channel::getNetworkChannel(network_channel_index); + peer_network_channel->getNetworkAddressFromNetworkChannel(&addr); switch (message_type) { @@ -185,7 +172,8 @@ void __stdcall handle_channel_message_hook(void *thisx, int network_channel_inde { s_request_map_filename* received_data = (s_request_map_filename*)packet; LOG_TRACE_NETWORK("[H2MOD-CustomPackets] received on handle_channel_message_hook request-map-filename from XUID: {}", received_data->user_identifier); - if (*(int*)(network_channel + 0x54) == 5 && getNetworkAddressFromNetworkChannel(network_channel, &addr)) + if (peer_network_channel->channel_state == network_channel::e_channel_state::unk_state_5 + && peer_network_channel->getNetworkAddressFromNetworkChannel(&addr)) { LOG_TRACE_NETWORK(" - network address: {:x}", ntohl(addr.address.ipv4)); @@ -200,14 +188,14 @@ void __stdcall handle_channel_message_hook(void *thisx, int network_channel_inde mapManager->getMapFilename(map_filename); if (map_filename.size() > 0) { - wcsncpy_s(data.file_name, map_filename.c_str(), 32); + wcsncpy_s(data.file_name, map_filename.c_str(), ARRAYSIZE(data.file_name)); LOG_TRACE_NETWORK(L"[H2MOD-CustomPackets] sending map file name packet to XUID: {}, peer index: {}, map name: {}", received_data->user_identifier, peer_index, map_filename.c_str()); network_observer* observer = session->network_observer_ptr; peer_observer_channel* observer_channel = NetworkSession::getPeerObserverChannel(peer_index); - observer->sendNetworkMessage(session->unk_index, observer_channel->observer_index, false, custom_map_filename, sizeof(s_custom_map_filename), &data); + observer->sendNetworkMessage(session->unk_index, observer_channel->observer_index, network_observer::e_network_message_send_protocol::in_band, custom_map_filename, sizeof(s_custom_map_filename), &data); } else { @@ -221,7 +209,7 @@ void __stdcall handle_channel_message_hook(void *thisx, int network_channel_inde case custom_map_filename: { - if (*(int*)(network_channel + 0x54) == 5) + if (peer_network_channel->channel_state == network_channel::e_channel_state::unk_state_5) { s_custom_map_filename* received_data = (s_custom_map_filename*)packet; mapManager->setMapFileNameToDownload(received_data->file_name); @@ -233,7 +221,7 @@ void __stdcall handle_channel_message_hook(void *thisx, int network_channel_inde case team_change: { - if (*(int*)(network_channel + 0x54) == 5) + if (peer_network_channel->channel_state == network_channel::e_channel_state::unk_state_5) { s_team_change* received_data = (s_team_change*)packet; h2mod->set_local_team_index(0, received_data->team_index); @@ -262,7 +250,7 @@ void CustomPackets::sendRequestMapFilename() peer_observer_channel* observer_channel = NetworkSession::getPeerObserverChannel(session->session_host_peer_index); if (observer_channel->field_1) { - observer->sendNetworkMessage(session->unk_index, observer_channel->observer_index, false, request_map_filename, sizeof(s_request_map_filename), &data); + observer->sendNetworkMessage(session->unk_index, observer_channel->observer_index, network_observer::e_network_message_send_protocol::in_band, request_map_filename, sizeof(s_request_map_filename), &data); LOG_TRACE_NETWORK("[H2MOD-CustomPackets] Sending map name request info: session host peer index: {}, observer index {}, observer bool unk: {}, unk index: {}", session->session_host_peer_index, @@ -287,7 +275,7 @@ void CustomPackets::sendTeamChange(int peerIndex, int teamIndex) if (peerIndex != -1 && peerIndex != session->local_peer_index) { if (observer_channel->field_1) { - observer->sendNetworkMessage(session->unk_index, observer_channel->observer_index, false, team_change, sizeof(s_team_change), &data); + observer->sendNetworkMessage(session->unk_index, observer_channel->observer_index, network_observer::e_network_message_send_protocol::in_band, team_change, sizeof(s_team_change), &data); } } } diff --git a/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.h b/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.h index 593c9e327..3cb7846c5 100644 --- a/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.h +++ b/xlive/H2MOD/Modules/Networking/CustomPackets/CustomPackets.h @@ -1,6 +1,8 @@ #pragma once -#include "..\NetworkSession/NetworkSession.h" +#include "..\NetworkSession\NetworkSession.h" + +#define player_identifier_size_bits CHAR_BIT * sizeof(XUID) enum e_network_message_types { @@ -53,6 +55,7 @@ enum e_network_message_types game_results, text_chat, test, + //custom packets bellow request_map_filename, custom_map_filename, @@ -111,6 +114,7 @@ static const char* network_message_name[] = { "game_results", "text_chat", "test" + //custom packets bellow "request_map_filename" "map_file_name" @@ -148,8 +152,8 @@ struct s_text_chat #pragma pack(pop) const char* getNetworkMessageName(int enumVal); - void register_packet_impl(void *, int, char*, int, int, int, void*, void*, void*); + namespace CustomPackets { void ApplyGamePatches(); diff --git a/xlive/H2MOD/Modules/Networking/Memory/bitstream.cpp b/xlive/H2MOD/Modules/Networking/Memory/bitstream.cpp index 1d9fadfc9..c99c50166 100644 --- a/xlive/H2MOD/Modules/Networking/Memory/bitstream.cpp +++ b/xlive/H2MOD/Modules/Networking/Memory/bitstream.cpp @@ -2,67 +2,67 @@ #include "bitstream.h" #include "H2MOD.h" -void bitstream::data_encode_string(char* name, int a3, int a4) +void bitstream::data_encode_string(char* name, void* string, int size_in_words) { - typedef void(__thiscall* data_encode_string_def)(bitstream* thisx, char* name, int a3, int a4); + typedef void(__thiscall* data_encode_string_def)(bitstream*, char*, void*, int); auto p_data_encode_string = h2mod->GetAddress(0xD18DF, 0xCDE99); - p_data_encode_string(this, name, a3, a4); + p_data_encode_string(this, name, string, size_in_words); } -void bitstream::data_decode_string(char* name, int a3, int a4) +void bitstream::data_decode_string(char* name, void* string_buffer, int size_in_words) { - typedef void(__thiscall* data_decode_string_def)(bitstream* thisx, char* name, int a3, int a4); + typedef void(__thiscall* data_decode_string_def)(bitstream*, char*, void*, int); auto p_data_decode_string = h2mod->GetAddress(0xD1FA7, 0xCE561); - p_data_decode_string(this, name, a3, a4); + p_data_decode_string(this, name, string_buffer, size_in_words); } -void bitstream::data_encode_integer(char* name, unsigned int value, signed int a3) +void bitstream::data_encode_integer(char* name, unsigned int value, unsigned int size_in_bits) { - typedef void(__thiscall* data_encode_integer_def)(bitstream* thisx, char* name, unsigned int value, signed int a3); + typedef void(__thiscall* data_encode_integer_def)(bitstream*, char*, unsigned int, signed int); auto p_data_encode_integer = h2mod->GetAddress(0xD17C6, 0xCDD80); - p_data_encode_integer(this, name, value, a3); + p_data_encode_integer(this, name, value, size_in_bits); } -int bitstream::data_decode_integer(char* name, int a3) +int bitstream::data_decode_integer(char* name, unsigned int size_in_bits) { - typedef int(__thiscall* data_decode_integer_def)(bitstream* thisx, char* name, int a3); + typedef int(__thiscall* data_decode_integer_def)(bitstream*, char*, int); auto p_data_decode_integer = h2mod->GetAddress(0xD1EE5, 0xCE49F); - return p_data_decode_integer(this, name, a3); + return p_data_decode_integer(this, name, size_in_bits); } -void bitstream::data_encode_bits(char* name, void* a3, int a4) +void bitstream::data_encode_bits(char* name, void* data, unsigned int size_in_bits) { - typedef void(__thiscall* data_encode_bits_def)(bitstream* thisx, char* name, void* a3, int a4); + typedef void(__thiscall* data_encode_bits_def)(bitstream*, char*, void*, int); auto p_data_encode_bits = h2mod->GetAddress(0xD18CD, 0xCDE87); - p_data_encode_bits(this, name, a3, a4); + p_data_encode_bits(this, name, data, size_in_bits); } -void bitstream::data_decode_bits(char* name, int a3, int a4) +void bitstream::data_decode_bits(char* name, void* data, int size_in_bits) { - typedef void(__thiscall* data_decode_bits_def)(bitstream* thisx, char* name, int a3, int a4); + typedef void(__thiscall* data_decode_bits_def)(bitstream*, char*, void*, int); auto p_data_decode_bits = h2mod->GetAddress(0xD1F95, 0xCE54F); - p_data_decode_bits(this, name, a3, a4); + p_data_decode_bits(this, name, data, size_in_bits); } -void bitstream::data_encode_bool(char* name, bool a3) +void bitstream::data_encode_bool(char* name, bool value) { - typedef void(__thiscall* data_encode_bool_def)(bitstream* thisx, char* name, bool a3); + typedef void(__thiscall* data_encode_bool_def)(bitstream*, char*, bool); auto p_data_encode_bool = h2mod->GetAddress(0xD1886, 0xCDE40); - p_data_encode_bool(this, name, a3); + p_data_encode_bool(this, name, value); } bool bitstream::data_decode_bool(char* name) { - typedef bool(__thiscall* data_decode_bool_def)(bitstream* thisx, char* name); + typedef bool(__thiscall* data_decode_bool_def)(bitstream*, char*); auto p_data_decode_bool = h2mod->GetAddress(0xD1F47, 0xCE501); return p_data_decode_bool(this, name); } -void bitstream::data_decode_address(char* name, int a3) +void bitstream::data_decode_address(char* name, void* address) { - typedef void(__thiscall* data_decode_address_def)(bitstream* thisx, char* name, int a3); + typedef void(__thiscall* data_decode_address_def)(bitstream*, char*, void*); auto p_data_decode_address = h2mod->GetAddress(0xD1FFD, 0xCE5B7); - return p_data_decode_address(this, name, a3); + return p_data_decode_address(this, name, address); } bool bitstream::packet_is_valid() diff --git a/xlive/H2MOD/Modules/Networking/Memory/bitstream.h b/xlive/H2MOD/Modules/Networking/Memory/bitstream.h index c6173f2e7..9cadd9d81 100644 --- a/xlive/H2MOD/Modules/Networking/Memory/bitstream.h +++ b/xlive/H2MOD/Modules/Networking/Memory/bitstream.h @@ -7,18 +7,16 @@ struct bitstream DWORD field_4; BYTE gap_8[8]; DWORD field_10; - - void data_encode_string(char* name, int a3, int a4); - void data_encode_integer(char* name, unsigned int value, signed int a3); - void data_encode_bits(char* name, void* a3, int a4); - void data_encode_bool(char* name, bool a3); - void data_decode_string(char* name, int a3, int a4); - void data_decode_address(char* name, int a3); - int data_decode_integer(char* name, int a3); - void data_decode_bits(char* name, int a3, int a4); + void data_encode_string(char* name, void* string, int size_in_words); + void data_decode_string(char* name, void* string_buffer, int size_in_words); + void data_encode_integer(char* name, unsigned int value, unsigned int size_in_bits); + int data_decode_integer(char* name, unsigned int size_in_bits); + void data_encode_bits(char* name, void* data, unsigned int size_in_bits); + void data_decode_bits(char* name, void* data, int size_in_bits); + void data_encode_bool(char* name, bool value); bool data_decode_bool(char* name); - + void data_decode_address(char* name, void* address); bool packet_is_valid(); }; #pragma pack(pop) diff --git a/xlive/H2MOD/Modules/Networking/NetworkChannel/NetworkChannel.cpp b/xlive/H2MOD/Modules/Networking/NetworkChannel/NetworkChannel.cpp new file mode 100644 index 000000000..3c25e2edd --- /dev/null +++ b/xlive/H2MOD/Modules/Networking/NetworkChannel/NetworkChannel.cpp @@ -0,0 +1,18 @@ + +#include "NetworkChannel.h" + +#include "H2MOD.h" + +network_channel* network_channel::getNetworkChannel(int channelIndex) +{ + return h2mod->GetAddress(0x4FADBC, 0x525274)[channelIndex]; +} + +bool network_channel::getNetworkAddressFromNetworkChannel(network_address* out_addr) +{ + typedef bool(__thiscall* get_network_address_from_network_channel)(network_channel*, network_address*); + auto p_get_network_address_from_network_channel = reinterpret_cast(h2mod->GetAddress(0x1BA543, 0x1C9364)); + + SecureZeroMemory(out_addr, sizeof(network_address)); + return p_get_network_address_from_network_channel(this, out_addr); +} diff --git a/xlive/H2MOD/Modules/Networking/NetworkChannel/NetworkChannel.h b/xlive/H2MOD/Modules/Networking/NetworkChannel/NetworkChannel.h new file mode 100644 index 000000000..8c3f1ce16 --- /dev/null +++ b/xlive/H2MOD/Modules/Networking/NetworkChannel/NetworkChannel.h @@ -0,0 +1,70 @@ +#pragma once + +#include "..\NetworkObserver\NetworkObserver.h" + +struct __declspec(align(8)) network_channel +{ + enum e_channel_closure_reason + { + link_destroyed = 1, + channel_deleted = 3, + connect_reinitiate = 6, + channel_establishment_timeout = 7, + destination_unreachable = 9, + remote_closure = 10, + connection_overflows = 11, + observer_discard = 14, + observer_reset = 17, + }; + + enum e_channel_state + { + unk_state_5 = 5, + }; + + void* network_link; + void* network_message_gateway; + void* network_message_handler; + void* network_channel_config; + int network_connection_index; + int network_shared_globals_index; + char gap_18[4]; + bool field_1C; + BYTE field_1D; + BYTE gap_1E[2]; + DWORD field_20; + int field_24; + BYTE gap_28[8]; + DWORD field_30; + BYTE gap_34[4]; + BYTE gap_38[4]; + int field_3C; + network_observer *network_observer; + int channel_index; + DWORD channel_flags; + DWORD remote_identifier; + DWORD identifier; + e_channel_state channel_state; + e_channel_closure_reason field_58; + network_address old_address; + network_address address; + char field_84; + BYTE gap_85[3]; + DWORD field_88; + DWORD field_8C; + DWORD field_90; + DWORD unk_time; + DWORD field_98; + BYTE gap_9C[4]; + LARGE_INTEGER field_A0; + BYTE gap_A8[48]; + DWORD field_D8; + BYTE gap_DC[4]; + LARGE_INTEGER field_E0; + char gap[10]; + + static network_channel* getNetworkChannel(int channelIndex); + bool getNetworkAddressFromNetworkChannel(network_address* out_addr); +}; +static_assert(sizeof(network_channel) == 248, "network_channel size != 248"); + diff --git a/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.cpp b/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.cpp index cc6ff73ac..bb2f0381e 100644 --- a/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.cpp +++ b/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.cpp @@ -7,8 +7,6 @@ // LIVE netcode research -#define USE_LIVE_NETCODE 1 - network_configuration* g_network_configuration; void __cdecl InitializeConfiguration() { @@ -167,7 +165,7 @@ void NetworkConfiguration::ApplyPatches() NopFill(h2mod->GetAddress(0x1BDF1D, 0x1B7DF7), 18); // increase the network heap size - WriteValue(h2mod->GetAddress(0x1ACCC8, 0x1ACE96) + 6, 10485760); // original H2v: 1048576, MCC: 1048576 + WriteValue(h2mod->GetAddress(0x1ACCC8, 0x1ACE96) + 6, INCREASED_NETWORK_HEAP_SIZE); // original H2v: 1048576, MCC: 1048576 #else // disables LIVE netcode WriteValue(h2mod->GetAddress(0x1B555B, 0x1A92B9) + 1, 0); diff --git a/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.h b/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.h index c730b74c6..198631398 100644 --- a/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.h +++ b/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.h @@ -1,5 +1,11 @@ #pragma once +// enables/disables LIVE netcode, so we can use the LIVE serverlist +#define USE_LIVE_NETCODE 1 + +#define DEFAULT_NETWORK_HEAP_SIZE 1048576 +#define INCREASED_NETWORK_HEAP_SIZE 10485760 + struct network_configuration { DWORD field_0; diff --git a/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.cpp b/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.cpp index 5f8fdd397..ff921e108 100644 --- a/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.cpp +++ b/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.cpp @@ -3,9 +3,10 @@ #include "H2MOD.h" -void network_observer::sendNetworkMessage(int unk_index, int observer_index, bool send_out_of_band, int type, int size, void* data) +void network_observer::sendNetworkMessage(int unk_index, int observer_index, e_network_message_send_protocol send_out_of_band, int type, int size, void* data) { - typedef void(__thiscall* observer_channel_send_message)(void *observer, int unk_index, int observer_index, bool send_out_of_band, int type, int size, void* data); + typedef void(__thiscall* observer_channel_send_message)(void*, int, int, e_network_message_send_protocol, int, int, void*); auto p_observer_channel_send_message = reinterpret_cast(h2mod->GetAddress(0x1BED40, 0x1B8C1A)); + p_observer_channel_send_message(this, unk_index, observer_index, send_out_of_band, type, size, data); } diff --git a/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h b/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h index bff0041d2..35b0bf832 100644 --- a/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h +++ b/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h @@ -13,7 +13,7 @@ struct network_address short address_type; }; -struct qosinfo +struct qos_info { DWORD cProbesXmit; DWORD cProbesRecv; @@ -25,7 +25,7 @@ struct qosinfo DWORD pbData; }; -struct __declspec(align(8)) observer +struct __declspec(align(8)) observer_channel { DWORD unk_state; DWORD field_4; @@ -46,7 +46,7 @@ struct __declspec(align(8)) observer DWORD field_58; network_address address; DWORD qos_probe_datum; - qosinfo field_74; + qos_info field_74; DWORD field_94; DWORD field_98; DWORD field_9C; @@ -131,14 +131,14 @@ struct __declspec(align(8)) observer DWORD field_734; long long field_738; }; -static_assert(sizeof(observer) == 0x740, "Invalid observer size"); +static_assert(sizeof(observer_channel) == 0x740, "Invalid observer size"); struct __declspec(align(8)) network_observer { - DWORD field_0; - DWORD network_link; - BYTE* network_message_gateway; - DWORD message_types; + void* network_observer_vtbl; // vtable at the start + void* network_link; + void* network_message_gateway; + void* message_types; network_configuration* network_configuration; int *field_14; BYTE gap_18[8]; @@ -152,7 +152,7 @@ struct __declspec(align(8)) network_observer BYTE gap_68[12]; DWORD field_74; BYTE gap_78[8]; - observer observers[16]; + observer_channel observers[16]; BYTE network_obeserver_enabled; char field_7481; int field_7484; @@ -188,7 +188,13 @@ struct __declspec(align(8)) network_observer DWORD field_75C0; DWORD field_75C4; + enum e_network_message_send_protocol + { + in_band, + out_of_band + }; + int getObserverState(int observerIndex) { return observers[observerIndex].unk_state; }; - void sendNetworkMessage(int unk_index, int observer_index, bool send_out_of_band, int type, int size, void* data); + void sendNetworkMessage(int unk_index, int observer_index, e_network_message_send_protocol send_out_of_band, int type, int size, void* data); }; -static_assert(sizeof(network_observer) == 0x75C8, "Invalid network_observer size"); +static_assert(sizeof(network_observer) == 0x75C8, "network_observer size != 30152"); diff --git a/xlive/H2MOD/Modules/Networking/NetworkSession/NetworkSession.cpp b/xlive/H2MOD/Modules/Networking/NetworkSession/NetworkSession.cpp index f652601d0..70caea6b9 100644 --- a/xlive/H2MOD/Modules/Networking/NetworkSession/NetworkSession.cpp +++ b/xlive/H2MOD/Modules/Networking/NetworkSession/NetworkSession.cpp @@ -19,14 +19,14 @@ bool NetworkSession::getCurrentNetworkSession(network_session** outSession) return h2mod->GetAddress(0x1AD736, 0x1A66B3)(outSession); } -eNetwork_session_state NetworkSession::getLocalSessionState() +e_network_session_state NetworkSession::getLocalSessionState() { return getCurrentNetworkSession()->local_session_state; } bool NetworkSession::localPeerIsSessionHost() { - eNetwork_session_state state = getCurrentNetworkSession()->local_session_state; + e_network_session_state state = getCurrentNetworkSession()->local_session_state; return state == network_session_state_session_host || state == network_session_state_host_disband diff --git a/xlive/H2MOD/Modules/Networking/NetworkSession/NetworkSession.h b/xlive/H2MOD/Modules/Networking/NetworkSession/NetworkSession.h index f0c412341..d22a515c1 100644 --- a/xlive/H2MOD/Modules/Networking/NetworkSession/NetworkSession.h +++ b/xlive/H2MOD/Modules/Networking/NetworkSession/NetworkSession.h @@ -1,9 +1,10 @@ #pragma once #include "Blam\Engine\Players\Players.h" +#include "..\NetworkChannel\NetworkChannel.h" #include "..\NetworkObserver\NetworkObserver.h" -enum eNetwork_session_state : signed int +enum e_network_session_state : signed int { network_session_state_none, network_session_state_peer_joining, @@ -18,7 +19,7 @@ enum eNetwork_session_state : signed int network_session_state_unk_2 }; -enum eMap_status : int +enum e_map_status : int { unk_map_stats, map_unavailable, @@ -35,7 +36,7 @@ struct peer_information BYTE gap_24[4]; wchar_t name[16]; wchar_t peer_session_name[32]; - eMap_status map_status; + e_map_status map_status; unsigned int map_progress_percentage; char field_70; BYTE gap_71[3]; @@ -182,7 +183,7 @@ struct network_session session_parameters parameters_2; DWORD local_peer_index; peer_observer_channel peer_observer_channels[17]; - eNetwork_session_state local_session_state; + e_network_session_state local_session_state; DWORD time_unk_2; DWORD time_unk_3; DWORD time_unk; @@ -248,7 +249,7 @@ namespace NetworkSession network_session* getNetworkSessions(); network_session* getCurrentNetworkSession(); bool getCurrentNetworkSession(network_session** a1); - eNetwork_session_state getLocalSessionState(); + e_network_session_state getLocalSessionState(); bool localPeerIsSessionHost(); signed int getPeerIndexFromNetworkAddress(network_address* addr); char getMapFileLocation(wchar_t* buffer, size_t size); diff --git a/xlive/Project_Cartographer.vcxproj b/xlive/Project_Cartographer.vcxproj index 8c0f990fa..fa7bb5d51 100644 --- a/xlive/Project_Cartographer.vcxproj +++ b/xlive/Project_Cartographer.vcxproj @@ -272,6 +272,7 @@ + @@ -483,6 +484,7 @@ + diff --git a/xlive/Project_Cartographer.vcxproj.filters b/xlive/Project_Cartographer.vcxproj.filters index a9ba6b939..0bc0ccc8c 100644 --- a/xlive/Project_Cartographer.vcxproj.filters +++ b/xlive/Project_Cartographer.vcxproj.filters @@ -540,6 +540,9 @@ Source Files\H2MOD\Modules\UI + + Source Files\H2MOD\Modules\Networking\NetworkChannel + @@ -1223,6 +1226,9 @@ Source Files\H2MOD\Modules\UI + + Source Files\H2MOD\Modules\Networking\NetworkChannel + From 6ce5804bbef4331877e984c395f5b43738b5e7f6 Mon Sep 17 00:00:00 2001 From: NukeULater Date: Tue, 2 Jun 2020 20:02:12 +0300 Subject: [PATCH 6/6] Moved network observer configuration to the appropriate file And some cleanup --- .../NetworkConfiguration.cpp | 176 ------------------ .../NetworkConfiguration.h | 119 ------------ .../NetworkObserver/NetworkObserver.cpp | 170 +++++++++++++++++ .../NetworkObserver/NetworkObserver.h | 116 +++++++++++- xlive/H2MOD/Modules/Networking/Networking.cpp | 40 +--- xlive/H2MOD/Modules/Tweaks/Tweaks.cpp | 1 - xlive/Project_Cartographer.vcxproj | 2 - xlive/Project_Cartographer.vcxproj.filters | 6 - 8 files changed, 293 insertions(+), 337 deletions(-) delete mode 100644 xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.cpp delete mode 100644 xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.h diff --git a/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.cpp b/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.cpp deleted file mode 100644 index bb2f0381e..000000000 --- a/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "stdafx.h" - -#include "NetworkConfiguration.h" - -#include "H2MOD.h" -#include "Util/Hooks/Hook.h" - -// LIVE netcode research - -network_configuration* g_network_configuration; -void __cdecl InitializeConfiguration() -{ - /* - Configuration constants used by the game to define how LIVE netcode will behave - */ - - 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, MCC = 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, MCC - 100 - g_network_configuration->field_138 = 50 * 4; // h2v - 50, MCC - 200 - g_network_configuration->field_13C = 32; // h2v - 15, MCC - 32 - g_network_configuration->field_140 = 32; // h2v - 8, MCC - 32 - g_network_configuration->field_144 = 1; - g_network_configuration->field_148 = 2000; - g_network_configuration->field_14C = 4096 * 4; // h2v - 4096, MCC = 4096 * 4 - g_network_configuration->field_150 = 71680 * 4; // H2v - 71680, MCC = H2v * 4 - g_network_configuration->field_154 = 1000; - g_network_configuration->max_bits_per_second_single_player = 30720 * 4; // H2v = 30720, MCC = H2v * 4 - g_network_configuration->max_bits_per_second_full_lobby = 262144; // H2v - 122880, MCC = 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, MCC = 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, MCC = H2V * 4 - g_network_configuration->field_194 = 5120 * 4; // H2v - 5120, MCC = 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, MCC = H2v * 4 - g_network_configuration->field_1BC = 20000; - g_network_configuration->field_1A8 = 30720 * 4; // H2v - 30720, MCC = 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, MCC = H2v * 4 = 32768 - g_network_configuration->field_1FC = 0.33333334f; - g_network_configuration->field_200 = 4096 * 4; // H2v - 4096, MCC = H2v * 4 = 16384 -} - -void NetworkConfiguration::ApplyPatches() -{ -#if USE_LIVE_NETCODE - // increase the network tickrate of hosts to 60 - static float netcode_tickrate = 60.0f; - - WritePointer(h2mod->GetAddress(0x1BDE27, 0x1B7D01) + 4, &netcode_tickrate); - WritePointer(h2mod->GetAddress(0x1BE2FA, 0x1B81D4) + 4, &netcode_tickrate); - WritePointer(h2mod->GetAddress(0x1BFB3C, 0x1B9A1C) + 4, &netcode_tickrate); - WritePointer(h2mod->GetAddress(0x1C11FA, 0x1BB0DA) + 4, &netcode_tickrate); - WritePointer(h2mod->GetAddress(0x1C12BF, 0x1BB19F) + 4, &netcode_tickrate); - - g_network_configuration = h2mod->GetAddress(0x4F960C, 0x523B5C); - PatchCall(h2mod->GetAddress(0x1ABE23, 0x1AC328), InitializeConfiguration); - - // other config patches - WriteValue(h2mod->GetAddress(0x1AB4A1, 0x1AB9A6) + 6, 20480 * 4); // MCC = H2v * 4 - WriteValue(h2mod->GetAddress(0x1AB4AB, 0x1AB9B0) + 6, 51200 * 4); // MCC = H2v * 4 - WriteValue(h2mod->GetAddress(0x1AB4C9, 0x1AB9CE) + 6, 65536 * 4); // MCC = H2v * 4 - WriteValue(h2mod->GetAddress(0x1AB4D3, 0x1AB9D8) + 6, 32678 * 4); // MCC = H2v * 4 - - WriteValue(h2mod->GetAddress(0x3A03CC, 0x360E54), 8192.f * 2.f); // MCC = H2v * 2, H2v = 8192 - WriteValue(h2mod->GetAddress(0x3C60F0, 0x381BDC), 40960.f * 4.f); // MCC = H2v * 4, H2v = 40960 - WriteValue(h2mod->GetAddress(0x3C60F4, 0x381BE0), 30720.f * 4.f); // MCC = H2v * 4, H2v = 30720 - WriteValue(h2mod->GetAddress(0x3C60F8, 0x381BE4), 53248.f); // MCC = 53248, H2v = 9216 - - WriteValue(h2mod->GetAddress(0x1AB4FF, 0x1ABA04) + 1, 8192 * 4); // h2v = 8192, MCC = h2v * 4 - WriteValue(h2mod->GetAddress(0x1AB504, 0x1ABA09) + 1, 40960 * 4); // h2v = 40960, MCC = h2v * 4 - - WriteValue(h2mod->GetAddress(0x1AB558, 0x1ABA5D) + 1, 15360 * 4); // h2v = 15360, MCC = h2v * 4 - WriteValue(h2mod->GetAddress(0x1AB55D, 0x1ABA62) + 2, 61440 * 4); // h2v = 61440, MCC = h2v * 4 - - WriteValue(h2mod->GetAddress(0x1AB582, 0x1ABA87) + 1, 131072 * 4); // 524288 - WriteValue(h2mod->GetAddress(0x1AB587, 0x1ABA8C) + 1, 262144 * 4); // 1048576 - - WriteValue(h2mod->GetAddress(0x1AB5B6, 0x1ABABB) + 6, 10240 * 4); // 40960 - WriteValue(h2mod->GetAddress(0x1AB5C0, 0x1ABAC5) + 6, 131072); - - // prevent the game from setting the client's tickrate to half of host's tickrate - // this code has been removed from H2MCC as well - NopFill(h2mod->GetAddress(0x1BFBE7, 0x1B9AC7), 19); - NopFill(h2mod->GetAddress(0x1BE33A, 0x1B8214), 15); - NopFill(h2mod->GetAddress(0x1BDF1D, 0x1B7DF7), 18); - - // increase the network heap size - WriteValue(h2mod->GetAddress(0x1ACCC8, 0x1ACE96) + 6, INCREASED_NETWORK_HEAP_SIZE); // original H2v: 1048576, MCC: 1048576 -#else - // disables LIVE netcode - WriteValue(h2mod->GetAddress(0x1B555B, 0x1A92B9) + 1, 0); - // disable ping bars - NopFill(h2mod->GetAddress(0x1D4E33, 0x1C1B7D), 2); - WriteValue(h2mod->GetAddress(0x1D4E35, 0x1C1B7F), 0xEB); // jmp -#endif -} \ No newline at end of file diff --git a/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.h b/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.h deleted file mode 100644 index 198631398..000000000 --- a/xlive/H2MOD/Modules/Networking/NetworkConfiguration/NetworkConfiguration.h +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once - -// enables/disables LIVE netcode, so we can use the LIVE serverlist -#define USE_LIVE_NETCODE 1 - -#define DEFAULT_NETWORK_HEAP_SIZE 1048576 -#define INCREASED_NETWORK_HEAP_SIZE 10485760 - -struct network_configuration -{ - DWORD field_0; - DWORD field_4; - BYTE gap_8[28]; - DWORD field_24; - DWORD field_28; - DWORD field_2C; - DWORD field_30; - BYTE gap_34[20]; - DWORD field_48; - DWORD field_4C; - DWORD field_50; - DWORD field_54; - DWORD field_58; - BYTE gap_5C[16]; - DWORD field_6C; - DWORD field_70; - DWORD field_74; - DWORD field_78; - DWORD field_7C; - DWORD field_80; - DWORD field_84; - DWORD field_88; - DWORD field_8C; - float field_90; - float field_94; - float field_98; - DWORD unk_total_flt_array_elements; - float unk_floats_A0[7]; - BYTE gap_BC[36]; - DWORD field_E0; - float field_E4; - float field_E8; - float field_EC; - float field_F0; - DWORD field_F4; - DWORD field_F8; - DWORD field_FC; - DWORD field_100; - float field_104; - DWORD field_108; - DWORD field_10C; - float field_110; - int field_114; - int field_118; - float field_11C; - int field_120; - DWORD field_124; - DWORD field_128; - DWORD field_12C; - DWORD field_130; - DWORD field_134; - DWORD field_138; - DWORD field_13C; - DWORD field_140; - BYTE field_144; - DWORD field_148; - DWORD field_14C; - DWORD field_150; - DWORD field_154; - DWORD max_bits_per_second_single_player; - DWORD max_bits_per_second_full_lobby; - DWORD max_bits_per_second_splitscreen_players; - DWORD field_164; - DWORD field_168; - DWORD field_16C; - DWORD field_170; - DWORD field_174; - float field_178; - DWORD field_17C; - float field_180; - DWORD field_184; - DWORD field_188; - DWORD field_18C; - float field_190; - DWORD field_194; - float field_198; - DWORD field_19C; - DWORD field_1A0; - DWORD field_1A4; - DWORD field_1A8; - float field_1AC; - DWORD field_1B0; - DWORD field_1B4; - DWORD field_1B8; - DWORD field_1BC; - DWORD field_1C0; - float field_1C4; - float field_1C8; - DWORD field_1CC; - float field_1D0; - DWORD field_1D4; - DWORD field_1D8; - DWORD field_1DC; - DWORD field_1E0; - DWORD field_1E4; - DWORD field_1E8; - DWORD field_1EC; - DWORD field_1F0; - DWORD field_1F4; - DWORD field_1F8; - float field_1FC; - DWORD field_200; -}; -static_assert(sizeof(network_configuration) == 0x204, "Invalid network_configuration size"); - -namespace NetworkConfiguration -{ - void ApplyPatches(); -} diff --git a/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.cpp b/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.cpp index ff921e108..6a9b73b56 100644 --- a/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.cpp +++ b/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.cpp @@ -2,6 +2,122 @@ #include "NetworkObserver.h" #include "H2MOD.h" +#include "Util/Hooks/Hook.h" + +network_observer_configuration* g_network_configuration; + +// LIVE netcode research +void __cdecl initialize_network_observer_configuration() +{ + /* + Configuration constants used by the game to define how LIVE netcode will behave + */ + + 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 +} void network_observer::sendNetworkMessage(int unk_index, int observer_index, e_network_message_send_protocol send_out_of_band, int type, int size, void* data) { @@ -10,3 +126,57 @@ void network_observer::sendNetworkMessage(int unk_index, int observer_index, e_n p_observer_channel_send_message(this, unk_index, observer_index, send_out_of_band, type, size, data); } + +void network_observer::ApplyPatches() +{ +#if USE_LIVE_NETCODE + // increase the network tickrate of hosts to 60 + static float netcode_tickrate = 60.0f; + + WritePointer(h2mod->GetAddress(0x1BDE27, 0x1B7D01) + 4, &netcode_tickrate); + WritePointer(h2mod->GetAddress(0x1BE2FA, 0x1B81D4) + 4, &netcode_tickrate); + WritePointer(h2mod->GetAddress(0x1BFB3C, 0x1B9A1C) + 4, &netcode_tickrate); + WritePointer(h2mod->GetAddress(0x1C11FA, 0x1BB0DA) + 4, &netcode_tickrate); + WritePointer(h2mod->GetAddress(0x1C12BF, 0x1BB19F) + 4, &netcode_tickrate); + + g_network_configuration = h2mod->GetAddress(0x4F960C, 0x523B5C); + PatchCall(h2mod->GetAddress(0x1ABE23, 0x1AC328), initialize_network_observer_configuration); + + // other config patches + WriteValue(h2mod->GetAddress(0x1AB4A1, 0x1AB9A6) + 6, 20480 * 4); // 60 tick = H2v * 4 + WriteValue(h2mod->GetAddress(0x1AB4AB, 0x1AB9B0) + 6, 51200 * 4); // 60 tick = H2v * 4 + WriteValue(h2mod->GetAddress(0x1AB4C9, 0x1AB9CE) + 6, 65536 * 4); // 60 tick = H2v * 4 + WriteValue(h2mod->GetAddress(0x1AB4D3, 0x1AB9D8) + 6, 32678 * 4); // 60 tick = H2v * 4 + + WriteValue(h2mod->GetAddress(0x3A03CC, 0x360E54), 8192.f * 2.f); // 60 tick = H2v * 2, H2v = 8192 + WriteValue(h2mod->GetAddress(0x3C60F0, 0x381BDC), 40960.f * 4.f); // 60 tick = H2v * 4, H2v = 40960 + WriteValue(h2mod->GetAddress(0x3C60F4, 0x381BE0), 30720.f * 4.f); // 60 tick = H2v * 4, H2v = 30720 + WriteValue(h2mod->GetAddress(0x3C60F8, 0x381BE4), 53248.f); // 60 tick = 53248, H2v = 9216 + + WriteValue(h2mod->GetAddress(0x1AB4FF, 0x1ABA04) + 1, 8192 * 4); // h2v = 8192, 60 tick = h2v * 4 + WriteValue(h2mod->GetAddress(0x1AB504, 0x1ABA09) + 1, 40960 * 4); // h2v = 40960, 60 tick = h2v * 4 + + WriteValue(h2mod->GetAddress(0x1AB558, 0x1ABA5D) + 1, 15360 * 4); // h2v = 15360, 60 tick = h2v * 4 + WriteValue(h2mod->GetAddress(0x1AB55D, 0x1ABA62) + 2, 61440 * 4); // h2v = 61440, 60 tick = h2v * 4 + + WriteValue(h2mod->GetAddress(0x1AB582, 0x1ABA87) + 1, 131072 * 4); // 60 tick - 524288 + WriteValue(h2mod->GetAddress(0x1AB587, 0x1ABA8C) + 1, 262144 * 4); // 60 tick - 1048576 + + WriteValue(h2mod->GetAddress(0x1AB5B6, 0x1ABABB) + 6, 10240 * 4); // 60 tick - 40960 + WriteValue(h2mod->GetAddress(0x1AB5C0, 0x1ABAC5) + 6, 131072); + + // prevent the game from setting the client's tickrate to half of host network tickrate + NopFill(h2mod->GetAddress(0x1BFBE7, 0x1B9AC7), 19); + NopFill(h2mod->GetAddress(0x1BE33A, 0x1B8214), 15); + NopFill(h2mod->GetAddress(0x1BDF1D, 0x1B7DF7), 18); + + // increase the network heap size + WriteValue(h2mod->GetAddress(0x1ACCC8, 0x1ACE96) + 6, INCREASED_NETWORK_HEAP_SIZE); // original H2v: 1048576, 60 tick: 1048576 +#else + // disables LIVE netcode + WriteValue(h2mod->GetAddress(0x1B555B, 0x1A92B9) + 1, 0); + // disable ping bars + NopFill(h2mod->GetAddress(0x1D4E33, 0x1C1B7D), 2); + WriteValue(h2mod->GetAddress(0x1D4E35, 0x1C1B7F), 0xEB); // jmp +#endif +} diff --git a/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h b/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h index 35b0bf832..116040513 100644 --- a/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h +++ b/xlive/H2MOD/Modules/Networking/NetworkObserver/NetworkObserver.h @@ -1,6 +1,117 @@ #pragma once -#include "..\NetworkConfiguration\NetworkConfiguration.h" +// enables/disables LIVE netcode, so we can use the LIVE serverlist +#define USE_LIVE_NETCODE 1 + +#define DEFAULT_NETWORK_HEAP_SIZE 1048576 +#define INCREASED_NETWORK_HEAP_SIZE 10485760 + +struct network_observer_configuration +{ + DWORD field_0; + DWORD field_4; + BYTE gap_8[28]; + DWORD field_24; + DWORD field_28; + DWORD field_2C; + DWORD field_30; + BYTE gap_34[20]; + DWORD field_48; + DWORD field_4C; + DWORD field_50; + DWORD field_54; + DWORD field_58; + BYTE gap_5C[16]; + DWORD field_6C; + DWORD field_70; + DWORD field_74; + DWORD field_78; + DWORD field_7C; + DWORD field_80; + DWORD field_84; + DWORD field_88; + DWORD field_8C; + float field_90; + float field_94; + float field_98; + DWORD unk_total_flt_array_elements; + float unk_floats_A0[7]; + BYTE gap_BC[36]; + DWORD field_E0; + float field_E4; + float field_E8; + float field_EC; + float field_F0; + DWORD field_F4; + DWORD field_F8; + DWORD field_FC; + DWORD field_100; + float field_104; + DWORD field_108; + DWORD field_10C; + float field_110; + int field_114; + int field_118; + float field_11C; + int field_120; + DWORD field_124; + DWORD field_128; + DWORD field_12C; + DWORD field_130; + DWORD field_134; + DWORD field_138; + DWORD field_13C; + DWORD field_140; + BYTE field_144; + DWORD field_148; + DWORD field_14C; + DWORD field_150; + DWORD field_154; + DWORD max_bits_per_second_single_player; + DWORD max_bits_per_second_full_lobby; + DWORD max_bits_per_second_splitscreen_players; + DWORD field_164; + DWORD field_168; + DWORD field_16C; + DWORD field_170; + DWORD field_174; + float field_178; + DWORD field_17C; + float field_180; + DWORD field_184; + DWORD field_188; + DWORD field_18C; + float field_190; + DWORD field_194; + float field_198; + DWORD field_19C; + DWORD field_1A0; + DWORD field_1A4; + DWORD field_1A8; + float field_1AC; + DWORD field_1B0; + DWORD field_1B4; + DWORD field_1B8; + DWORD field_1BC; + DWORD field_1C0; + float field_1C4; + float field_1C8; + DWORD field_1CC; + float field_1D0; + DWORD field_1D4; + DWORD field_1D8; + DWORD field_1DC; + DWORD field_1E0; + DWORD field_1E4; + DWORD field_1E8; + DWORD field_1EC; + DWORD field_1F0; + DWORD field_1F4; + DWORD field_1F8; + float field_1FC; + DWORD field_200; +}; +static_assert(sizeof(network_observer_configuration) == 0x204, "Invalid network_observer_configuration size"); struct network_address { @@ -139,7 +250,7 @@ struct __declspec(align(8)) network_observer void* network_link; void* network_message_gateway; void* message_types; - network_configuration* network_configuration; + network_observer_configuration* configuration; int *field_14; BYTE gap_18[8]; XNKID sessionId; @@ -194,6 +305,7 @@ struct __declspec(align(8)) network_observer out_of_band }; + static void ApplyPatches(); int getObserverState(int observerIndex) { return observers[observerIndex].unk_state; }; void sendNetworkMessage(int unk_index, int observer_index, e_network_message_send_protocol send_out_of_band, int type, int size, void* data); }; diff --git a/xlive/H2MOD/Modules/Networking/Networking.cpp b/xlive/H2MOD/Modules/Networking/Networking.cpp index f8dcc0f68..c6dd0de7d 100644 --- a/xlive/H2MOD/Modules/Networking/Networking.cpp +++ b/xlive/H2MOD/Modules/Networking/Networking.cpp @@ -9,10 +9,6 @@ #include "Networking.h" #include "Memory\bitstream.h" #include "CustomPackets\CustomPackets.h" -#include "NetworkConfiguration\NetworkConfiguration.h" - -extern XSocket* game_network_data_gateway_socket_1000; -extern XSocket* game_network_message_gateway_socket_1001; CustomNetwork *network = new CustomNetwork; @@ -204,17 +200,6 @@ void __cdecl serializeParametersUpdatePacket(void* a1, int a2, int a3) { serialize_parameters_update_packet_method(a1, a2, a3); } -typedef bool(__stdcall *tjoin_game)(void* thisptr, int a2, int a3, XNKID* xnkid, XNKEY* xnkey, XNADDR* host_xn, int a7, int a8, int a9, int a10, int a11, char a12, int a13, int a14); -tjoin_game pjoin_game; - -bool __stdcall join_game(void* thisptr, int a2, int a3, XNKID* xnkid, XNKEY* xnkey, XNADDR* host_xn, int a7, int a8, int a9, int a10, int a11, char a12, int a13, int a14) -{ - memcpy(&ipManager.gameHostXn, host_xn, sizeof(XNADDR)); - LOG_TRACE_NETWORK("[H2MOD-Network] copied host information, XNADDR: {:#x}", ipManager.gameHostXn.ina.s_addr); - - return pjoin_game(thisptr, a2, a3, xnkid, xnkey, host_xn, a7, a8, a9, a10, a11, a12, a13, a14); -} - typedef bool(__cdecl* decode_text_chat_packet_)(bitstream* container, int a2, s_text_chat* data); decode_text_chat_packet_ p_decode_text_chat_packet; @@ -225,9 +210,6 @@ bool __cdecl decode_text_chat_packet(bitstream* container, int a2, s_text_chat* return ret; } -/* WIP */ -/* All this does is patch some checks that cause using actual ip addresses not to work. */ -/* When a call to XNetXnaddrtoInaddr happens we provide the actual ip address rather than a secure key */ typedef char(__stdcall *cmp_xnkid)(int thisx, int a2); cmp_xnkid p_cmp_xnkid; @@ -235,19 +217,19 @@ char __stdcall xnkid_cmp(int thisx, int a2) { return 1; } +/* All this does is patch some checks that cause using actual ip addresses not to work. */ +/* When a call to XNetXnaddrtoInaddr happens we provide the actual ip address rather than a secure key */ void removeXNetSecurity() { /* XNKEY bs */ p_cmp_xnkid = (cmp_xnkid)DetourClassFunc(h2mod->GetAddress(0x1C284A, 0x199F02), (BYTE*)xnkid_cmp, 9); - BYTE jmp = 0xEB; // apparently the secure address has 1 free byte // after HTONL call, game is checking the al register (the lower 8 bits of eax register) if it is zero, if not everything network related will fail - WriteBytes(h2mod->GetAddress(0x1B5DBE, 0x1961F8), &jmp, 1); + WriteValue(h2mod->GetAddress(0x1B5DBE, 0x1961F8), 0xEB); // place a jump (jmp opcode = 0xEB) NopFill(h2mod->GetAddress(0x1B624A, 0x196684), 2); NopFill(h2mod->GetAddress(0x1B6201, 0x19663B), 2); NopFill(h2mod->GetAddress(0x1B62BC, 0x1966F4), 2); - } // stub qos lookup function in-game between peers in a network session @@ -273,6 +255,8 @@ int __cdecl QoSLookUpImpl(int a1, signed int a2, int a3, int a4) return -1; } +// with GFWL this abOnline/abNet data was present on startup, but with our impl we don't have the abOnline/abNet data on startup +// so we just patch it to always update it instead of getting it only on startup void patchAbNetUpdate() { PatchCall(h2mod->GetAddress(0x1B583F, 0x195C79), h2mod->GetAddress(0x1B5DF3, 0x19622D)); @@ -286,21 +270,12 @@ void patchAbNetUpdate() void applyConnectionPatches() { - //removeXNetSecurity(); // live netcode research - NetworkConfiguration::ApplyPatches(); + network_observer::ApplyPatches(); // stub QoS lookup function for in-game data PatchCall(h2mod->GetAddress(0x1BDCB0, 0x1B7B8A), QoSLookUpImpl); - - //NopFill<9>(h2mod->GetBase() + (h2mod->Server ? 0x1B3CC3 : 0x1F1F94)); // check if secure/ipaddress != 127.0.0.1 - //NopFill(h2mod->GetAddress() + (h2mod->Server ? 0x1B3CC3 : 0x1F1F94), 9); // check if secure/ipaddress != 127.0.0.1 - - if (!h2mod->Server) - { - pjoin_game = (tjoin_game)DetourClassFunc(h2mod->GetAddress(0x1CDADE), (BYTE*)join_game, 13); - } } void CustomNetwork::applyNetworkHooks() { @@ -312,6 +287,9 @@ void CustomNetwork::applyNetworkHooks() { patchAbNetUpdate(); + // removing Xbox Secure Network (IPSec) from the game research + //removeXNetSecurity(); + register_connection_packets_method = (register_connection_packets)DetourFunc(h2mod->GetAddress(0x1F1B36, 0x1D24EF), (BYTE*)registerConnectionPackets, 5); //use for debugging diff --git a/xlive/H2MOD/Modules/Tweaks/Tweaks.cpp b/xlive/H2MOD/Modules/Tweaks/Tweaks.cpp index c2e649be8..40c807a77 100644 --- a/xlive/H2MOD/Modules/Tweaks/Tweaks.cpp +++ b/xlive/H2MOD/Modules/Tweaks/Tweaks.cpp @@ -876,7 +876,6 @@ void fix_shaders_nvidia() ); } -// probably MCC does this because it's 64 bit, but w/e, should work just fine int system_get_time() { LARGE_INTEGER PerformanceCount; diff --git a/xlive/Project_Cartographer.vcxproj b/xlive/Project_Cartographer.vcxproj index fa7bb5d51..c274e15e3 100644 --- a/xlive/Project_Cartographer.vcxproj +++ b/xlive/Project_Cartographer.vcxproj @@ -273,7 +273,6 @@ - @@ -485,7 +484,6 @@ - diff --git a/xlive/Project_Cartographer.vcxproj.filters b/xlive/Project_Cartographer.vcxproj.filters index 0bc0ccc8c..30e849905 100644 --- a/xlive/Project_Cartographer.vcxproj.filters +++ b/xlive/Project_Cartographer.vcxproj.filters @@ -489,9 +489,6 @@ Source Files\H2MOD\Modules\ServerConsole - - Source Files\H2MOD\Modules\Networking\NetworkConfiguration - Source Files\3rdparty\tinyxml @@ -1064,9 +1061,6 @@ Header Files - - Source Files\H2MOD\Modules\Networking\NetworkConfiguration - Header Files