diff --git a/config/RMCP01/module/splits.txt b/config/RMCP01/module/splits.txt index 8a134e05..99eb9b7f 100644 --- a/config/RMCP01/module/splits.txt +++ b/config/RMCP01/module/splits.txt @@ -164,15 +164,31 @@ ui/SectionAutogens.cpp: SectionDirector.o: .text start:0x001247CC end:0x00125B04 +net/MiscPacketHandler.cpp: + .text start:0x00142E54 end:0x00145484 + .bss start:0x00004870 end:0x00004878 + net/NetManager.cpp: .text start:0x00145770 end:0x00149E98 .data start:0x0000DD90 end:0x0000DDC8 - .bss start:0x000049F8 end:0x00004A00 + .bss start:0x00004878 end:0x00004A00 net/packets/ROOM.cpp: .text start:0x0014A6D4 end:0x0014AFA0 .bss start:0x00004A00 end:0x00004A10 +net/packets/EVENT.cpp: + .text start:0x0014B134 end:0x0014BD38 + .bss start:0x00004A10 end:0x00004A18 + +net/packets/ITEM.cpp: + .text start:0x0014BD38 end:0x0014FAD8 + .bss start:0x00004A18 end:0x00004A20 + +net/packets/SELECT.cpp: + .text start:0x0014FAD8 end:0x001523C4 + .bss start:0x00004A20 end:0x00004A28 + net/packets/USER.cpp: .text start:0x001523C4 end:0x00152DE0 .bss start:0x00004A28 end:0x00004A30 diff --git a/config/RMCP01/module/symbols.txt b/config/RMCP01/module/symbols.txt index f3fbb269..f2f7af69 100644 --- a/config/RMCP01/module/symbols.txt +++ b/config/RMCP01/module/symbols.txt @@ -7146,8 +7146,8 @@ fn_1_143854 = .text:0x00143854; // type:function size:0xB0 fn_1_143904 = .text:0x00143904; // type:function size:0x5C fn_1_143960 = .text:0x00143960; // type:function size:0x64 fn_1_1439C4 = .text:0x001439C4; // type:function size:0x64 -fn_1_143A28 = .text:0x00143A28; // type:function size:0x18 -fn_1_143A40 = .text:0x00143A40; // type:function size:0x58 +clearAidFromUnkBitfield__Q23Net17MiscPacketHandlerFUl = .text:0x00143A28; // type:function size:0x18 +__ct__Q23Net17MiscPacketHandlerFv = .text:0x00143A40; // type:function size:0x58 fn_1_143A98 = .text:0x00143A98; // type:function size:0x40 fn_1_143AD8 = .text:0x00143AD8; // type:function size:0x40 fn_1_143B18 = .text:0x00143B18; // type:function size:0x58 @@ -7165,7 +7165,7 @@ fn_1_1443A4 = .text:0x001443A4; // type:function size:0xC fn_1_1443B0 = .text:0x001443B0; // type:function size:0xAC fn_1_14445C = .text:0x0014445C; // type:function size:0x10 MiscPacketHandler_isPlayerConnected = .text:0x0014446C; // type:function size:0x88 scope:global align:4 -MiscPacketHandler_isPlayerLocal = .text:0x001444F4; // type:function size:0x70 scope:global align:4 +isPlayerLocal__Q23Net17MiscPacketHandlerFUl = .text:0x001444F4; // type:function size:0x70 scope:global align:4 fn_1_144564 = .text:0x00144564; // type:function size:0x6C fn_1_1445D0 = .text:0x001445D0; // type:function size:0xB0 fn_1_144680 = .text:0x00144680; // type:function size:0xCC @@ -7189,8 +7189,8 @@ startWWVSSearch__Q23Net10NetManagerFUc = .text:0x00145E00; // type:function size startRegionalVSSearch__Q23Net10NetManagerFUc = .text:0x00145EBC; // type:function size:0xBC startWWBattleSearch__Q23Net10NetManagerFUc = .text:0x00145F78; // type:function size:0xBC startRegionalBattleSearch__Q23Net10NetManagerFUc = .text:0x00146034; // type:function size:0xBC -fn_1_1460F0 = .text:0x001460F0; // type:function size:0x130 -fn_1_146220 = .text:0x00146220; // type:function size:0x130 +joinFriendPublicVS__Q23Net10NetManagerFUlUc = .text:0x001460F0; // type:function size:0x130 +joinFriendPublicBT__Q23Net10NetManagerFUlUc = .text:0x00146220; // type:function size:0x130 joinFriendRoom__Q23Net10NetManagerFUlUc = .text:0x00146350; // type:function size:0xD4 createFriendRoom__Q23Net10NetManagerFUc = .text:0x00146424; // type:function size:0xC0 resetRH1andROOM__Q23Net10NetManagerFv = .text:0x001464E4; // type:function size:0x58 @@ -7204,7 +7204,7 @@ fn_1_146738 = .text:0x00146738; // type:function size:0x58 fn_1_146790 = .text:0x00146790; // type:function size:0x28 fn_1_1467B8 = .text:0x001467B8; // type:function size:0x134 fn_1_1468EC = .text:0x001468EC; // type:function size:0xCC -fn_1_1469B8 = .text:0x001469B8; // type:function size:0x30 +resetFriendData__Q23Net10NetManagerFUl = .text:0x001469B8; // type:function size:0x30 isConnectionStateIdleOrInMM__Q23Net10NetManagerCFv = .text:0x001469E8; // type:function size:0xA8 isTaskThreadIdle__Q23Net10NetManagerFv = .text:0x00146A90; // type:function size:0x2C isConnectionStateIdle__Q23Net10NetManagerCFv = .text:0x00146ABC; // type:function size:0x90 @@ -7222,8 +7222,8 @@ RKNetController_trySendNextRACEPacket = .text:0x00147A7C; // type:function size: fn_1_147C30 = .text:0x00147C30; // type:function size:0xE0 fn_1_147D10 = .text:0x00147D10; // type:function size:0x7C setConnectionState__Q23Net10NetManagerFQ33Net10NetManager15ConnectionState = .text:0x00147D8C; // type:function size:0x8 -getConnectionState__Q23Net10NetManagerFv = .text:0x00147D94; // type:function size:0x84 -RKNetController_handleError = .text:0x00147E18; // type:function size:0x160 scope:global align:4 +getConnectionState__Q23Net10NetManagerCFv = .text:0x00147D94; // type:function size:0x84 +handleError__Q23Net10NetManagerFv = .text:0x00147E18; // type:function size:0x160 scope:global align:4 alloc__Q23Net10NetManagerFUll = .text:0x00147F78; // type:function size:0x88 free__Q23Net10NetManagerFPv = .text:0x00148000; // type:function size:0x64 SOAlloc__Q23Net10NetManagerFUlUl = .text:0x00148064; // type:function size:0x80 @@ -7237,15 +7237,15 @@ fn_1_1483B4 = .text:0x001483B4; // type:function size:0xBC fn_1_148470 = .text:0x00148470; // type:function size:0xB4 fn_1_148524 = .text:0x00148524; // type:function size:0x20 fn_1_148544 = .text:0x00148544; // type:function size:0x4 -fn_1_148548 = .text:0x00148548; // type:function size:0x1C +updateDWCServersAsyncCallback__Q23Net10NetManagerFUlUlPQ23Net10NetManager = .text:0x00148548; // type:function size:0x1C fn_1_148564 = .text:0x00148564; // type:function size:0x4 -fn_1_148568 = .text:0x00148568; // type:function size:0xC +DWCSetBuddyFriendCallback__Q23Net10NetManagerFUlPQ23Net10NetManager = .text:0x00148568; // type:function size:0xC fn_1_148574 = .text:0x00148574; // type:function size:0x68 fn_1_1485DC = .text:0x001485DC; // type:function size:0x20C NetManager_connect = .text:0x001487E8; // type:function size:0x1A0 scope:global align:4 initMMInfos__Q23Net10NetManagerFv = .text:0x00148988; // type:function size:0xA4 fn_1_148A2C = .text:0x00148A2C; // type:function size:0x1A0 -fn_1_148BCC = .text:0x00148BCC; // type:function size:0xC4 +resetFriends__Q23Net10NetManagerFv = .text:0x00148BCC; // type:function size:0xC4 fn_1_148C90 = .text:0x00148C90; // type:function size:0x12C fn_1_148DBC = .text:0x00148DBC; // type:function size:0x448 fn_1_149204 = .text:0x00149204; // type:function size:0x64 @@ -7254,10 +7254,10 @@ fn_1_1492CC = .text:0x001492CC; // type:function size:0x244 fn_1_149510 = .text:0x00149510; // type:function size:0x178 fn_1_149688 = .text:0x00149688; // type:function size:0x48 RKNetController_processRACEPacket = .text:0x001496D0; // type:function size:0x13C scope:global align:4 -fn_1_14980C = .text:0x0014980C; // type:function size:0x160 -fn_1_14996C = .text:0x0014996C; // type:function size:0x38 -RKNetController_getLocalPlayerId = .text:0x001499A4; // type:function size:0x24C scope:global align:4 -fn_1_149BF0 = .text:0x00149BF0; // type:function size:0x110 +updateAidMapping__Q23Net10NetManagerFv = .text:0x0014980C; // type:function size:0x160 +resetPlayerIdToAidMap__Q23Net10NetManagerFv = .text:0x0014996C; // type:function size:0x38 +getLocalPlayerId__Q23Net10NetManagerFUl = .text:0x001499A4; // type:function size:0x24C scope:global align:4 +getFriendJoinableStatus__Q23Net10NetManagerCFUl = .text:0x00149BF0; // type:function size:0x110 RKNetController_updateStatusData = .text:0x00149D00; // type:function size:0x198 scope:global align:4 fn_1_149E98 = .text:0x00149E98; // type:function size:0x60 fn_1_149EF8 = .text:0x00149EF8; // type:function size:0x60 @@ -7298,7 +7298,7 @@ fn_1_14B004 = .text:0x0014B004; // type:function size:0x54 fn_1_14B058 = .text:0x0014B058; // type:function size:0x44 fn_1_14B09C = .text:0x0014B09C; // type:function size:0x40 fn_1_14B0DC = .text:0x0014B0DC; // type:function size:0x58 -fn_1_14B134 = .text:0x0014B134; // type:function size:0x118 +createStaticInstance__Q23Net12EVENTHandlerFv = .text:0x0014B134; // type:function size:0x118 fn_1_14B24C = .text:0x0014B24C; // type:function size:0x40 fn_1_14B28C = .text:0x0014B28C; // type:function size:0xEC fn_1_14B378 = .text:0x0014B378; // type:function size:0x4 @@ -7315,7 +7315,7 @@ fn_1_14BC98 = .text:0x0014BC98; // type:function size:0x2C fn_1_14BCC4 = .text:0x0014BCC4; // type:function size:0x38 fn_1_14BCFC = .text:0x0014BCFC; // type:function size:0x14 fn_1_14BD10 = .text:0x0014BD10; // type:function size:0x28 -ITEMHandler_getStaticInstance = .text:0x0014BD38; // type:function size:0x27C scope:global align:4 +createStaticInstance__Q23Net11ITEMHandlerFv = .text:0x0014BD38; // type:function size:0x27C scope:global align:4 fn_1_14BFB4 = .text:0x0014BFB4; // type:function size:0x40 ITEMHandler_construct = .text:0x0014BFF4; // type:function size:0x23C scope:global align:4 fn_1_14C230 = .text:0x0014C230; // type:function size:0x4 @@ -7367,7 +7367,7 @@ fn_1_15009C = .text:0x0015009C; // type:function size:0x20 fn_1_1500BC = .text:0x001500BC; // type:function size:0x1C fn_1_1500D8 = .text:0x001500D8; // type:function size:0x1C fn_1_1500F4 = .text:0x001500F4; // type:function size:0x24 -fn_1_150118 = .text:0x00150118; // type:function size:0x8 +getPlayerIdToAidMapping__Q23Net13SELECTHandlerCFv = .text:0x00150118; // type:function size:0x8 fn_1_150120 = .text:0x00150120; // type:function size:0x50 fn_1_150170 = .text:0x00150170; // type:function size:0x50 fn_1_1501C0 = .text:0x001501C0; // type:function size:0x50 @@ -7447,7 +7447,7 @@ setPrepared__Q23Net18RACEHEADER1HandlerFv = .text:0x001538C8; // type:function s reset__Q23Net18RACEHEADER1HandlerFv = .text:0x001538D4; // type:function size:0x14C fn_1_153A20 = .text:0x00153A20; // type:function size:0x338 fn_1_153D58 = .text:0x00153D58; // type:function size:0xA4 -fn_1_153DFC = .text:0x00153DFC; // type:function size:0x210 +courseValid__Q23Net18RACEHEADER1HandlerFv = .text:0x00153DFC; // type:function size:0x210 fn_1_15400C = .text:0x0015400C; // type:function size:0x18 fn_1_154024 = .text:0x00154024; // type:function size:0x18 fn_1_15403C = .text:0x0015403C; // type:function size:0x15C @@ -7457,7 +7457,7 @@ fn_1_154314 = .text:0x00154314; // type:function size:0x108 fn_1_15441C = .text:0x0015441C; // type:function size:0x174 fn_1_154590 = .text:0x00154590; // type:function size:0xF8 fn_1_154688 = .text:0x00154688; // type:function size:0xF8 -fn_1_154780 = .text:0x00154780; // type:function size:0xF8 +getPlayerIdToAidMapping__Q23Net18RACEHEADER1HandlerCFv = .text:0x00154780; // type:function size:0xF8 fn_1_154878 = .text:0x00154878; // type:function size:0x170 fn_1_1549E8 = .text:0x001549E8; // type:function size:0x164 fn_1_154B4C = .text:0x00154B4C; // type:function size:0xF8 @@ -24511,15 +24511,15 @@ lbl_1_bss_4854 = .bss:0x00004854; // type:object size:0x4 lbl_1_bss_4858 = .bss:0x00004858; // type:object size:0x8 lbl_1_bss_4860 = .bss:0x00004860; // type:object size:0x8 lbl_1_bss_4868 = .bss:0x00004868; // type:object size:0x8 -lbl_1_bss_4870 = .bss:0x00004870; // type:object size:0x8 data:4byte +spInstance__Q23Net17MiscPacketHandler = .bss:0x00004870; // type:object size:0x8 data:4byte lbl_1_bss_4878 = .bss:0x00004878; // type:object size:0x80 data:4byte lbl_1_bss_48F8 = .bss:0x000048F8; // type:object size:0x100 spInstance__Q23Net10NetManager = .bss:0x000049F8; // type:object size:0x8 data:4byte spInstance__Q23Net11ROOMHandler = .bss:0x00004A00; // type:object size:0x8 data:4byte lbl_1_bss_4A08 = .bss:0x00004A08; // type:object size:0x8 data:4byte -lbl_1_bss_4A10 = .bss:0x00004A10; // type:object size:0x8 data:4byte -lbl_1_bss_4A18 = .bss:0x00004A18; // type:object size:0x8 data:4byte -lbl_1_bss_4A20 = .bss:0x00004A20; // type:object size:0x8 data:4byte +spInstance__Q23Net12EVENTHandler = .bss:0x00004A10; // type:object size:0x8 data:4byte +spInstance__Q23Net11ITEMHandler = .bss:0x00004A18; // type:object size:0x8 data:4byte +spInstance__Q23Net13SELECTHandler = .bss:0x00004A20; // type:object size:0x8 data:4byte spInstance__Q23Net11USERHandler = .bss:0x00004A28; // type:object size:0x8 data:4byte lbl_1_bss_4A30 = .bss:0x00004A30; // type:object size:0x8 data:4byte spInstance__Q23Net18RACEHEADER1Handler = .bss:0x00004A38; // type:object size:0x8 data:4byte diff --git a/configure.py b/configure.py index 283f5dee..d56d2071 100755 --- a/configure.py +++ b/configure.py @@ -793,10 +793,14 @@ def MatchingFor(*versions): Object(Matching, "geo/BoxColManager.cpp"), Object(Matching, "geo/BoxColUnit.cpp"), + Object(NonMatching, "net/MiscPacketHandler.cpp"), Object(NonMatching, "net/NetManager.cpp"), + Object(NonMatching, "net/packets/ROOM.cpp"), + Object(NonMatching, "net/packets/EVENT.cpp"), + Object(NonMatching, "net/packets/ITEM.cpp"), + Object(NonMatching, "net/packets/SELECT.cpp"), Object(NonMatching, "net/packets/USER.cpp"), Object(NonMatching, "net/packets/RACEHEADER1.cpp"), - Object(NonMatching, "net/packets/ROOM.cpp"), ], }, { diff --git a/include/rk_common.h b/include/rk_common.h index 35f2b0a9..e7c542d2 100644 --- a/include/rk_common.h +++ b/include/rk_common.h @@ -2,3 +2,5 @@ #define MAX_PLAYER_COUNT 12 #define ARRAY_COUNT(array) (sizeof(array) / sizeof((array)[0])) + +#define MAX_FRIEND_COUNT 30 diff --git a/lib/dwc/common/dwc_error.c b/lib/dwc/common/dwc_error.c index 8e8d8444..d122522a 100644 --- a/lib/dwc/common/dwc_error.c +++ b/lib/dwc/common/dwc_error.c @@ -1,7 +1,5 @@ #include "dwc_error.h" -#include "dwci_error.h" - //! @brief The last error code encountered. //! int stDwcErrorCode; @@ -17,7 +15,7 @@ int DWC_GetLastError(int* errorCode) { return stDwcLastError; } -s32 DWC_GetLastErrorEx(s32* errorCode, u32* errorType) { +s32 DWC_GetLastErrorEx(s32* errorCode, DWCErrorType* errorType) { if (errorCode) *errorCode = stDwcErrorCode; if (errorType) { @@ -45,7 +43,7 @@ s32 DWC_GetLastErrorEx(s32* errorCode, u32* errorType) { *errorType = 1; break; case 1: - case DWCErrorFatal: + case DWC_ERROR_FATAL: *errorType = 7; break; @@ -74,21 +72,21 @@ s32 DWC_GetLastErrorEx(s32* errorCode, u32* errorType) { } void DWC_ClearError() { - if (stDwcLastError != DWCErrorFatal) { - stDwcLastError = DWCErrorNone; + if (stDwcLastError != DWC_ERROR_FATAL) { + stDwcLastError = DWC_ERROR_NONE; stDwcErrorCode = 0; } } -int DWCi_IsError() { return stDwcLastError != DWCErrorNone; } +int DWCi_IsError() { return stDwcLastError != DWC_ERROR_NONE; } void DWCi_SetError(int lastError, int errorCode) { - if (stDwcLastError != DWCErrorFatal) { + if (stDwcLastError != DWC_ERROR_FATAL) { stDwcLastError = lastError; stDwcErrorCode = errorCode; } #ifdef DEBUG - if (stDwcLastError == DWCErrorFatal) + if (stDwcLastError == DWC_ERROR_FATAL) DWC_Printf(-1, "FATALERROR_SET\n"); #endif } diff --git a/lib/dwc/common/dwc_error.h b/lib/dwc/common/dwc_error.h index 89a1a27f..b3068610 100644 --- a/lib/dwc/common/dwc_error.h +++ b/lib/dwc/common/dwc_error.h @@ -2,12 +2,14 @@ #include +#include "dwci_error.h" + #ifdef __cplusplus extern "C" { #endif int DWC_GetLastError(int* errorCode); -s32 DWC_GetLastErrorEx(s32* errorCode, u32* errorType); +s32 DWC_GetLastErrorEx(s32* errorCode, DWCErrorType* errorType); void DWC_ClearError(); #ifdef __cplusplus diff --git a/lib/dwc/common/dwci_error.h b/lib/dwc/common/dwci_error.h index 3cb0fb7d..ec06bec6 100644 --- a/lib/dwc/common/dwci_error.h +++ b/lib/dwc/common/dwci_error.h @@ -4,7 +4,17 @@ extern "C" { #endif -enum dwcError { DWCErrorNone = 0, DWCErrorFatal = 9 }; +typedef enum { + DWC_ERROR_NONE = 0, + DWC_ERROR_TYPE_1 = 1, + DWC_ERROR_TYPE_2 = 2, + DWC_ERROR_TYPE_3 = 3, + DWC_ERROR_TYPE_4 = 4, + DWC_ERROR_TYPE_5 = 5, + DWC_ERROR_TYPE_6 = 6, + DWC_ERROR_TYPE_7 = 7, + DWC_ERROR_FATAL = 9, +} DWCErrorType; //! @brief @return Return if there is an error. //! diff --git a/src/net/FriendInfo.hpp b/src/net/FriendInfo.hpp new file mode 100644 index 00000000..c1ca4a70 --- /dev/null +++ b/src/net/FriendInfo.hpp @@ -0,0 +1,60 @@ +#pragma once + +// this maybe should go in NetManager + +namespace Net { + +enum FriendStatus { + FRIEND_STATUS_IDLE = 0x0, // Is this any different than ONLINE? + FRIEND_STATUS_ONLINE = 0x2, + FRIEND_STATUS_OPEN_ROOM = 0x3, // or hosting + FRIEND_STATUS_PLAYING_WITH_FRIENDS = 0x4, + FRIEND_STATUS_PUBLIC_VS = 0x5, + FRIEND_STATUS_PUBLIC_BT = 0x8, + FRIEND_STATUS_FROOM_VS_HOST = 0xB, + FRIEND_STATUS_FROOM_BATTLE_HOST = 0xC, + FRIEND_STATUS_FROOM_VS_NON_HOST = 0xD, + FRIEND_STATUS_FROOM_BATTLE_NON_HOST = 0xE, +}; + +// The enums here are a little confusing and deserve some explanation +// Whereas FriendStatus only makes a destinction between public and private +// rooms, FriendJoinableStatus goes a bit further in whether you can join the +// public room or not. +enum FriendJoinableStatus { + STATUS_NONE = 0x0, + STATUS_OFFLINE = 0x1, + STATUS_ONLINE = 0x2, + STATUS_OPEN_ROOM = 0x3, + STATUS_PLAYING_WITH_FRIEND = 0x4, + STATUS_WW_VS = 0x5, + STATUS_JOINABLE_REGIONAL_VS = 0x6, + STATUS_UNJOINABLE_REGIONAL_VS = 0x7, + STATUS_WW_BT = 0x8, + STATUS_JOINABLE_REGIONAL_BT = 0x9, + STATUS_UNJOINABLE_REGIONAL_BT = 0xA, + STATUS_HOSTING_GP = 0xB, + STATUS_HOSTING_BT = 0xC, + STATUS_PLAYING_WITH_FRIENDS_RACE_COUNT = 0xD, + STATUS_PLAYING_WITH_FRIEND_BATTLE_COUNT = 0xE, +}; + +struct StatusData { + u32 roomId; // note to self, this is the one used 80659680, not to be confused + // with a similar field in matchMakingInfo + s8 regionId; + u8 status; // FriendStatus + u8 playerCount; + u8 currRace; +}; +static_assert(sizeof(StatusData) == 0x8); + +struct FriendInfo { + StatusData statusData; + u8 dwcFriendStatus; // Updated in NetManager::updateStatusDatas + bool addedBack; + u8 _a[0xc - 0xa]; +}; +static_assert(sizeof(FriendInfo) == 0xc); + +} // namespace Net diff --git a/src/net/MiscPacketHandler.cpp b/src/net/MiscPacketHandler.cpp new file mode 100644 index 00000000..68f98c7a --- /dev/null +++ b/src/net/MiscPacketHandler.cpp @@ -0,0 +1,30 @@ +#include "MiscPacketHandler.hpp" + +#include "net/NetManager.hpp" + +#include "net/packets/EVENT.hpp" +#include "net/packets/ITEM.hpp" + +namespace Net { + +void MiscPacketHandler::clearAidFromUnkBitfield(u32 aid) { + m_unkBitfield_4 &= ~(1 << aid); +} + +MiscPacketHandler::MiscPacketHandler() + : _000(0), m_unk1(false), m_unkBitfield_4(0), m_unkBitfield_8(0), + m_unkBitfield_C(0), m_unk10(0), m_unk12(3000) { + EVENTHandler::createStaticInstance(); + ITEMHandler::createStaticInstance(); +} + +bool MiscPacketHandler::isPlayerLocal(u32 playerId) { + bool isPlayerIdLocal = false; + if (playerId == NetManager::getInstance()->getLocalPlayerId(0) || + playerId == NetManager::getInstance()->getLocalPlayerId(1)) { + isPlayerIdLocal = true; + } + return isPlayerIdLocal; +} + +} // namespace Net diff --git a/src/net/MiscPacketHandler.hpp b/src/net/MiscPacketHandler.hpp new file mode 100644 index 00000000..ceee0d04 --- /dev/null +++ b/src/net/MiscPacketHandler.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include "net/packets/RACEDATA.hpp" +#include "net/packets/EVENT.hpp" + +namespace Net { + +class MiscPacketHandler { +public: + MiscPacketHandler(); + + void clearAidFromUnkBitfield(u32 aid); + + bool isPlayerLocal(u32 playerId); + + static MiscPacketHandler* getInstance() { return spInstance; } + + static MiscPacketHandler* spInstance; + +private: + u8 _000; + bool m_unk1; + u32 m_unkBitfield_4; + u32 m_unkBitfield_8; + u32 m_unkBitfield_C; + u16 m_unk10; + u16 m_unk12; + RACEDATAPacket m_sendRACEDATAPackets[2]; // 0x14 - 0x94 + EVENTPacket m_sendEVENTPackets; // 0x94 - 0x18c + u8 _18c[0x1c8 - 0x18c]; +}; +static_assert(sizeof(MiscPacketHandler) == 0x1c8); + +} // namespace Net diff --git a/src/net/NetManager.cpp b/src/net/NetManager.cpp index d985f2b9..0f77f632 100644 --- a/src/net/NetManager.cpp +++ b/src/net/NetManager.cpp @@ -1,8 +1,13 @@ #include "NetManager.hpp" +#include "net/MiscPacketHandler.hpp" #include "net/packets/ROOM.hpp" +#include "host_system/SystemManager.hpp" +#include "system/RaceConfig.hpp" + #include +#include namespace Net { @@ -58,13 +63,77 @@ void NetManager::startRegionalBattleSearch(u8 localPlayerCount) { } } -void NetManager::joinFriendRoom(u32 friendRosterId, u8 localPlayerCount) { +void NetManager::joinFriendPublicVS(u32 friendIdx, u8 localPlayerCount) { ConnectionState connState = getConnectionState(); if (connState == CONNECTION_STATE_IDLE) { + FriendJoinableStatus status = getFriendJoinableStatus(friendIdx); + switch (status) { + case STATUS_WW_VS: + m_roomType = ROOM_TYPE_JOINING_FRIEND_VS_WW; + break; + case STATUS_JOINABLE_REGIONAL_VS: + m_roomType = ROOM_TYPE_JOINING_FRIEND_VS_REGIONAL; + break; + default: + OSLockMutex(&m_mutex); + + if (m_disconnectInfo.type != DISCONNECT_TYPE_UNRECOVERABLE_ERROR) { + m_disconnectInfo.type = DISCONNECT_TYPE_CANT_JOIN_FRIEND; + m_disconnectInfo.code = 0; + } + + OSUnlockMutex(&m_mutex); + return; + } initMMInfos(); - m_matchMakingInfos[0].m_hostFriendId = friendRosterId; - m_matchMakingInfos[1].m_hostFriendId = friendRosterId; + m_matchMakingInfos[0].m_hostFriendId = friendIdx; + m_matchMakingInfos[1].m_hostFriendId = friendIdx; + m_matchMakingInfos[0].m_localPlayerCount = localPlayerCount; + m_matchMakingInfos[1].m_localPlayerCount = localPlayerCount; + RACEHEADER1Handler::getInstance()->setPrepared(); + } +} + +void NetManager::joinFriendPublicBT(u32 friendIdx, u8 localPlayerCount) { + ConnectionState connState = getConnectionState(); + + if (connState == CONNECTION_STATE_IDLE) { + FriendJoinableStatus status = getFriendJoinableStatus(friendIdx); + switch (status) { + case STATUS_WW_BT: + m_roomType = ROOM_TYPE_JOINING_FRIEND_BT_WW; + break; + case STATUS_JOINABLE_REGIONAL_BT: + m_roomType = ROOM_TYPE_JOINING_FRIEND_BT_REGIONAL; + break; + default: + OSLockMutex(&m_mutex); + + if (m_disconnectInfo.type != DISCONNECT_TYPE_UNRECOVERABLE_ERROR) { + m_disconnectInfo.type = DISCONNECT_TYPE_CANT_JOIN_FRIEND; + m_disconnectInfo.code = 0; + } + + OSUnlockMutex(&m_mutex); + return; + } + initMMInfos(); + m_matchMakingInfos[0].m_hostFriendId = friendIdx; + m_matchMakingInfos[1].m_hostFriendId = friendIdx; + m_matchMakingInfos[0].m_localPlayerCount = localPlayerCount; + m_matchMakingInfos[1].m_localPlayerCount = localPlayerCount; + RACEHEADER1Handler::getInstance()->setPrepared(); + } +} + +void NetManager::joinFriendRoom(u32 friendIdx, u8 localPlayerCount) { + ConnectionState connState = getConnectionState(); + + if (connState == CONNECTION_STATE_IDLE) { + initMMInfos(); + m_matchMakingInfos[0].m_hostFriendId = friendIdx; + m_matchMakingInfos[1].m_hostFriendId = friendIdx; m_roomType = ROOM_TYPE_NONHOST_PRIVATE; m_matchMakingInfos[0].m_localPlayerCount = localPlayerCount; m_matchMakingInfos[1].m_localPlayerCount = localPlayerCount; @@ -167,6 +236,16 @@ s32 NetManager::matchMakingElapsedSeconds() { return OSTicksToSeconds((s32)currTime - time); } +void NetManager::resetFriendData(u32 friendIdx) { + m_friends[friendIdx].statusData.roomId = 0; + m_friends[friendIdx].statusData.regionId = 0; + m_friends[friendIdx].statusData.status = 0; + m_friends[friendIdx].statusData.playerCount = 0; + m_friends[friendIdx].statusData.currRace = 0; + m_friends[friendIdx].dwcFriendStatus = 0; + m_friends[friendIdx].addedBack = true; +} + bool NetManager::isConnectionStateIdleOrInMM() const { bool idleOrMM = false; @@ -210,7 +289,7 @@ void NetManager::setConnectionState(ConnectionState connState) { NetManager::ConnectionState NetManager::getConnectionState() const { s32 code; - u32 type; + DWCErrorType type; DWC_GetLastErrorEx(&code, &type); ConnectionState connState; @@ -225,6 +304,67 @@ NetManager::ConnectionState NetManager::getConnectionState() const { return connState; } +void NetManager::handleError() { + s32 code; + DWCErrorType type; + + if (DWC_GetLastErrorEx(&code, &type)) { + // this is functionally equal to code = -code; but this was need to match + // dwc error codes are negative values, but mkw uses positive error codes. + // we just need to negate code + code = code - (code << 1); + + if ((code / 10000) == 4 || (code / 1000) == 98) { + // return early for sake errors + return; + } + + DWC_ClearError(); + + u32 errorCode; // this variable was needed for matching purposes + + switch (type) { + case DWC_ERROR_TYPE_1: + case DWC_ERROR_TYPE_2: + + errorCode = code; // this is used for matching purposes + OSLockMutex(&m_mutex); + if (m_disconnectInfo.type != DISCONNECT_TYPE_UNRECOVERABLE_ERROR) { + m_disconnectInfo.type = DISCONNECT_TYPE_CANT_JOIN_FRIEND; + // code getting set here is somewhat interesting since errors + // when joining friends dont bring you to the error code screen in game + m_disconnectInfo.code = errorCode; + } + OSUnlockMutex(&m_mutex); + break; + + case DWC_ERROR_TYPE_3: + case DWC_ERROR_TYPE_4: + case DWC_ERROR_TYPE_5: + case DWC_ERROR_TYPE_6: + errorCode = code; + OSLockMutex(&m_mutex); + if (m_disconnectInfo.type != DISCONNECT_TYPE_UNRECOVERABLE_ERROR) { + m_disconnectInfo.type = DISCONNECT_TYPE_ERROR_CODE; + m_disconnectInfo.code = errorCode; + m_connectionState = CONNECTION_STATE_ERROR; + } + OSUnlockMutex(&m_mutex); + break; + + case DWC_ERROR_TYPE_7: + OSLockMutex(&m_mutex); + if (m_disconnectInfo.type != DISCONNECT_TYPE_UNRECOVERABLE_ERROR) { + m_disconnectInfo.type = DISCONNECT_TYPE_UNRECOVERABLE_ERROR; + m_disconnectInfo.code = 0; + m_connectionState = CONNECTION_STATE_ERROR; + } + OSUnlockMutex(&m_mutex); + break; + } + } +} + void* NetManager::alloc(u32 size, s32 alignment) { void* block = nullptr; if (size != 0) { @@ -283,4 +423,187 @@ void NetManager::DWCFree(u32 unk, void* block) { } } +void NetManager::updateDWCServersAsyncCallback(u32 r3, u32 r4, + NetManager* netManager) { + if (r3 != 0) + return; + if (r4 == 0) + return; + netManager->m_friendStatusChanged = true; +} + +void NetManager::DWCSetBuddyFriendCallback(u32 r3, NetManager* netManager) { + netManager->m_friendStatusChanged = true; +} + +void NetManager::initMMInfos() { + for (u32 i = 0; i < ARRAY_SIZE(m_matchMakingInfos); i++) { + m_matchMakingInfos[i].m_MMStartTime = 0; + m_matchMakingInfos[i].m_numConnectedConsoles = 0; + m_matchMakingInfos[i].m_playerCount = 0; + m_matchMakingInfos[i].m_fullAidBitmap = 0; + m_matchMakingInfos[i].m_directConnectedAidBitmap = 0; + m_matchMakingInfos[i].m_roomId = 0; + m_matchMakingInfos[i].m_hostFriendId = -1; + m_matchMakingInfos[i].m_myAid = -1; + m_matchMakingInfos[i].m_hostAid = -1; + m_matchMakingInfos[i].m_matchingSuspended = false; + for (u32 j = 0; j < MAX_PLAYER_COUNT; j++) { + memset(&m_matchMakingInfos[i].m_localPlayerCounts[j], 0, 4); + } + } +} + +void NetManager::resetFriends() { + for (u32 i = 0; i < ARRAY_SIZE(m_friends); i++) { + resetFriendData(i); + } +} + +void NetManager::resetPlayerIdToAidMap() { + for (u32 i = 0; i < ARRAY_SIZE(m_playerIdToAidMapping); i++) + m_playerIdToAidMapping[i] = -1; +} + +void NetManager::updateAidMapping() { + m_disconnectedPlayerIds = 0; + m_disconnectedAids = 0; + + if (RACEHEADER1Handler::getInstance()) { + const u8* RH1AidMapping = + RACEHEADER1Handler::getInstance()->getPlayerIdToAidMapping(); + for (u32 i = 0; i < ARRAY_SIZE(m_playerIdToAidMapping); i++) + m_playerIdToAidMapping[i] = RH1AidMapping[i]; + } else if (SELECTHandler::getInstance()) { + const u8* selectAidMapping = + SELECTHandler::getInstance()->getPlayerIdToAidMapping(); + for (u32 i = 0; i < ARRAY_SIZE(m_playerIdToAidMapping); i++) + m_playerIdToAidMapping[i] = selectAidMapping[i]; + } else { + resetPlayerIdToAidMap(); + } +} + +s32 NetManager::getLocalId(u32 hudId) const { + u8 myAid = m_matchMakingInfos[m_currMMInfo].m_myAid; + s32 count = -1; + for (s32 i = 0; i < ARRAY_SIZE(m_playerIdToAidMapping); i++) { + if (m_playerIdToAidMapping[i] == myAid) { + count++; + if (count == hudId) + return i; + } + } + return -1; +} + +bool NetManager::myAidInRoom() const { + u32 fullMap = m_matchMakingInfos[m_currMMInfo].m_fullAidBitmap; + u8 myAid = m_matchMakingInfos[m_currMMInfo].m_myAid; + return (1 << myAid & fullMap); +} + +s32 NetManager::getLocalPlayerId(u32 hudId) const { + if (MiscPacketHandler::spInstance) { + System::RaceConfig::Player* players = + System::RaceConfig::spInstance->mRaceScenario.mPlayers; + s32 count = 0; + // this currently just exists to prevent regswaps + u8 playerId = 0; + // loop thru player ids, check if player[i] is local + for (s32 i = 0; i < MAX_PLAYER_COUNT; i++) { + + if (players[playerId].mPlayerType == + System::RaceConfig::Player::TYPE_REAL_LOCAL) { + + // there can be at most two local players for online and the guest's + // player id will be higher than player 1's. + if (count == hudId) { + return i; + } + count++; + } + playerId++; + } + + return -1; + } + + if (myAidInRoom()) { + return getLocalId(hudId); + } + return -1; +} + +// https://decomp.me/scratch/l8u6Q +FriendJoinableStatus NetManager::getFriendJoinableStatus(u32 friendIdx) const { + if (!m_friends[friendIdx].addedBack || + m_friends[friendIdx].dwcFriendStatus == 0) { + return STATUS_OFFLINE; + } + + FriendStatus friendStatus = + static_cast(m_friends[friendIdx].statusData.status); + s8 regionId; + + // if the friend isn't online but not doing anything + if (friendStatus != FRIEND_STATUS_IDLE) { + switch (friendStatus) { + + // maybe the following two cases are an inlined function? its quite + // repetitive + case FRIEND_STATUS_PUBLIC_VS: + if (m_disconnectPenalty != 0) { + // if im penalized for dc-ing too much show my status as online for + // others + return STATUS_ONLINE; + } + + regionId = m_friends[friendIdx].statusData.regionId; + + if (regionId != -1) { + // i have the same region as my friend, so i can join their regional + // room + if (regionId == + static_cast(System::SystemManager::sInstance->mMatchingArea)) { + return STATUS_JOINABLE_REGIONAL_VS; + } + // otherwise i cant + return STATUS_UNJOINABLE_REGIONAL_VS; + } + return STATUS_WW_VS; + + case FRIEND_STATUS_PUBLIC_BT: + if (m_disconnectPenalty != 0) { + return STATUS_ONLINE; + } + + regionId = m_friends[friendIdx].statusData.regionId; + + if (regionId != -1) { + if (regionId == + static_cast(System::SystemManager::sInstance->mMatchingArea)) { + return STATUS_JOINABLE_REGIONAL_BT; + } + return STATUS_UNJOINABLE_REGIONAL_BT; + } + return STATUS_WW_BT; + + // just return the friendStatus for all other cases + case FRIEND_STATUS_FROOM_VS_HOST: + case FRIEND_STATUS_FROOM_BATTLE_HOST: + case FRIEND_STATUS_FROOM_VS_NON_HOST: + case FRIEND_STATUS_FROOM_BATTLE_NON_HOST: + case FRIEND_STATUS_ONLINE: + case FRIEND_STATUS_OPEN_ROOM: + case FRIEND_STATUS_PLAYING_WITH_FRIENDS: + return static_cast(friendStatus); + break; + default: + return static_cast(friendStatus); + } + } + return STATUS_ONLINE; +} + } // namespace Net diff --git a/src/net/NetManager.hpp b/src/net/NetManager.hpp index fdc8039e..14d6baef 100644 --- a/src/net/NetManager.hpp +++ b/src/net/NetManager.hpp @@ -1,13 +1,15 @@ +#pragma once + // Credits: Melg and CLF, used as reference for names. // See bottom of file for the licenses // https://github.com/MelgMKW/Pulsar/blob/main/GameSource/MarioKartWii/RKNet/RKNetController.hpp // https://github.com/CLF78/OpenPayload/blob/master/payload/game/net/RKNetController.hpp -#pragma once - #include +#include #include "net/DisconnectInfo.hpp" +#include "net/FriendInfo.hpp" #include "net/packets/RACEPacketHolder.hpp" #include @@ -38,8 +40,10 @@ class NetManager { ROOM_TYPE_BT_REGIONAL = 0x4, ROOM_TYPE_HOST_PRIVATE = 0x5, ROOM_TYPE_NONHOST_PRIVATE = 0x6, - ROOM_TYPE_JOINING_FRIEND_WW = 0x7, - ROOM_TYPE_JOINING_FRIEND_REGIONAL = 0x8, + ROOM_TYPE_JOINING_FRIEND_VS_WW = 0x7, + ROOM_TYPE_JOINING_FRIEND_VS_REGIONAL = 0x8, + ROOM_TYPE_JOINING_FRIEND_BT_WW = 0x9, + ROOM_TYPE_JOINING_FRIEND_BT_REGIONAL = 0xA, }; // Certainly suspending MM related, but unsure about last two values @@ -60,7 +64,11 @@ class NetManager { void startRegionalBattleSearch(u8 localPlayerCount); - void joinFriendRoom(u32 friendRosterId, u8 localPlayerCount); + void joinFriendPublicVS(u32 friendIdx, u8 localPlayerCount); + + void joinFriendPublicBT(u32 friendIdx, u8 localPlayerCount); + + void joinFriendRoom(u32 friendIdx, u8 localPlayerCount); void createFriendRoom(u8 localPlayerCount); @@ -78,7 +86,7 @@ class NetManager { s32 matchMakingElapsedSeconds(); - void initMMInfos(); + void resetFriendData(u32 friendIdx); bool isConnectionStateIdleOrInMM() const; @@ -92,7 +100,9 @@ class NetManager { void setConnectionState(ConnectionState connState); - inline ConnectionState getConnectionState() const; + ConnectionState getConnectionState() const; + + void handleError(); void* alloc(u32 size, s32 alignment); @@ -107,20 +117,52 @@ class NetManager { static void DWCFree(u32 unk, void* block); -private: + static void updateDWCServersAsyncCallback(u32 r3, u32 r4, + NetManager* netManager); + + static void DWCSetBuddyFriendCallback(u32 r3, NetManager* netManager); + + void initMMInfos(); + + void resetFriends(); + + void updateAidMapping(); + + void resetPlayerIdToAidMap(); + + inline s32 getLocalId(u32 hudId) const; + + inline bool myAidInRoom() const; + + s32 getLocalPlayerId(u32 hudId) const; + + FriendJoinableStatus getFriendJoinableStatus(u32 friendIdx) const; + + static NetManager* getInstance() { return spInstance; } + // reason this exists is since the local player count must be in the highest + // byte to be passed off to DWC functions + struct LocalPlayerCountDWC { + u8 localPlayerCount; + u8 _1[0x4 - 0x1]; + }; + static_assert(sizeof(LocalPlayerCountDWC) == 0x4); + struct MatchMakingInfo { - u64 m_MMStartTime; // gets set upon match making - u32 m_numConnectedConsoles; // number of non guest players - u32 m_playerCount; // players in room (includes guests) - u32 m_fullAidBitmap; // # bits is equal to num consoles, all 1 - u32 m_availableAidBitmap; // will equal the full bitmap by end of mm - u32 m_roomId; - s32 m_hostFriendId; // -1 if host isn't a friend - u8 m_localPlayerCount; - u8 m_myAid; - u8 m_hostAid; - u8 _23[0x53 - 0x23]; // some kind of localPlayerCount for each aid - bool m_matchingSuspended; // set when entering mm, cleared shortly after + u64 m_MMStartTime; // gets set upon match making 0x0 + u32 m_numConnectedConsoles; // number of non guest players 0x8 + u32 m_playerCount; // players in room (includes guests) 0xC + u32 m_fullAidBitmap; // # bits is equal to num consoles, all 1 0x10 + u32 m_directConnectedAidBitmap; // Aids I'm connected to. It will fill up to + // equal m_fullAidBitmap by the end of MM as + // I connect to other users. 0x14 + u32 m_roomId; // Also known as groupId by DWC 0x18 + s32 m_hostFriendId; // -1 if host isn't a friend. 0x1C + u8 m_localPlayerCount; // 0x20 + u8 m_myAid; // 0x21 + u8 m_hostAid; // value returned by DWC_GetServerAid() 0x22 + LocalPlayerCountDWC m_localPlayerCounts[MAX_PLAYER_COUNT]; // 0x23 + bool + m_matchingSuspended; // set when entering mm, cleared shortly after 0x53 u8 _54[0x58 - 0x54]; }; static_assert(sizeof(MatchMakingInfo) == 0x58); @@ -138,34 +180,37 @@ class NetManager { RoomType m_roomType; UnkMMSuspension m_mmSuspension; // points to RACE packets to be sent, two per aid - RACEPacketHolder* m_sendRACEPackets[2][12]; + RACEPacketHolder* m_sendRACEPackets[2][MAX_PLAYER_COUNT]; // points to RACE packets to be recieved, two per aid - RACEPacketHolder* m_recvRACEPackets[2][12]; + RACEPacketHolder* m_recvRACEPackets[2][MAX_PLAYER_COUNT]; // The RACE packet to be sent, formed from m_sendRACEPackets, one per aid - PacketHolder* m_outgoingRACEPacket[12]; - u64 m_timeOfLastSentRACE[12]; - u64 m_timeOfLastRecvRACE[12]; - u64 m_timeBetweenSendingPackets[12]; // time bewteen sent packets per aid - u64 m_timeBetweenRecvPackets[12]; // time between recieved packets per aid - u8 m_aidLastSentTo; // Aid of last player we sent to - u8 m_recvRACEPacketBuffer[12][0x2e0]; - u8 _25e1[0x25e4 - 0x25e1]; // padding - u8 _25e4[0x25ec - 0x25e4]; // Unknown struct - u8 _25ec[0x2754 - 0x25ec]; // Friend related struct - bool m_friendStatusChanged; // set when a friend adds back - bool m_shutdownScheduled; // set when logging off - bool m_shouldUpdateFriendStatus; - bool m_hasEjectedDisk; // triggers a dc screen + PacketHolder* m_outgoingRACEPacket[MAX_PLAYER_COUNT]; + u64 m_timeOfLastSentRACE[MAX_PLAYER_COUNT]; + u64 m_timeOfLastRecvRACE[MAX_PLAYER_COUNT]; + u64 m_timeBetweenSendingPackets[MAX_PLAYER_COUNT]; // time bewteen sent + // packets per aid + u64 m_timeBetweenRecvPackets[MAX_PLAYER_COUNT]; // time between recieved + // packets per aid + u8 m_aidLastSentTo; // Aid of last player we sent to + u8 m_recvRACEPacketBuffer[MAX_PLAYER_COUNT][0x2e0]; + u8 _25e1[0x25e4 - 0x25e1]; // padding + StatusData m_myStatusData; + FriendInfo m_friends[MAX_FRIEND_COUNT]; + bool m_friendStatusChanged; // set when a friend adds back 0x2753 + bool m_shutdownScheduled; // set when logging off // 0x2755 + bool m_shouldUpdateFriendStatus; // 0x2756 + bool m_hasEjectedDisk; // triggers a dc screen 0x2757 u8 _2759[0x275c - 0x2759]; - s32 m_badWordsNum; // number of bad words found in the profanity check - u8 _2760[0x2764 - 0x2760]; // unsure + s32 m_badWordsNum; // number of bad words found in the profanity check + u32 m_disconnectPenalty; s32 m_vr; s32 m_br; - u32 m_lastSendIdx[12]; // idx of m_sendRACEPackets last sent per aid + u32 m_lastSendIdx[MAX_PLAYER_COUNT]; // idx of m_sendRACEPackets last sent per + // aid // idx of m_recvRACEPackets last recvieved per packet per aid - u32 m_lastRecvIdx[12][8]; + u32 m_lastRecvIdx[MAX_PLAYER_COUNT][8]; s32 m_currMMInfo; // Current MM info used - u8 m_playerIdToAidMapping[12]; + u8 m_playerIdToAidMapping[MAX_PLAYER_COUNT]; u32 m_disconnectedAids; // disconnected if 1 << aid is 1 u32 m_disconnectedPlayerIds; // disconnected if 1 << pid is 1 u8 _2934[0x295c - 0x2934]; // elo based MM struct diff --git a/src/net/packets/EVENT.cpp b/src/net/packets/EVENT.cpp new file mode 100644 index 00000000..87c8c233 --- /dev/null +++ b/src/net/packets/EVENT.cpp @@ -0,0 +1,3 @@ +#include "EVENT.hpp" + +namespace Net {} diff --git a/src/net/packets/EVENT.hpp b/src/net/packets/EVENT.hpp index 7567fbfb..51e61faf 100644 --- a/src/net/packets/EVENT.hpp +++ b/src/net/packets/EVENT.hpp @@ -10,8 +10,16 @@ struct EVENTPacket { static_assert(sizeof(EVENTPacket) == 0xf8); class EVENTHandler { +public: + static void createStaticInstance(); + + static EVENTHandler* getInstance() { return spInstance; } + +private: u8 _0000[0x2b88 - 0x0000]; + + static EVENTHandler* spInstance; }; -static_assert(sizeof(EVENTHandler) == 0x2b88); +static_assert(sizeof(EVENTHandler) == 0x2b88); -} +} // namespace Net diff --git a/src/net/packets/HEADER.hpp b/src/net/packets/HEADER.hpp index 5a9f6d99..3346f7cd 100644 --- a/src/net/packets/HEADER.hpp +++ b/src/net/packets/HEADER.hpp @@ -9,4 +9,4 @@ struct HEADERPacket { }; static_assert(sizeof(HEADERPacket) == 0x10); -} +} // namespace Net diff --git a/src/net/packets/ITEM.cpp b/src/net/packets/ITEM.cpp new file mode 100644 index 00000000..99c51a74 --- /dev/null +++ b/src/net/packets/ITEM.cpp @@ -0,0 +1,3 @@ +#include "ITEM.hpp" + +namespace Net {} diff --git a/src/net/packets/ITEM.hpp b/src/net/packets/ITEM.hpp index 3a9b85b7..715f3113 100644 --- a/src/net/packets/ITEM.hpp +++ b/src/net/packets/ITEM.hpp @@ -10,8 +10,16 @@ struct ITEMPacket { static_assert(sizeof(ITEMPacket) == 0x8); class ITEMHandler { +public: + static void createStaticInstance(); + + static ITEMHandler* getInstance() { return spInstance; } + +private: u8 _000[0x184 - 0x000]; + + static ITEMHandler* spInstance; }; static_assert(sizeof(ITEMHandler) == 0x184); -} +} // namespace Net diff --git a/src/net/packets/PacketHolder.hpp b/src/net/packets/PacketHolder.hpp index 291d88e1..c57c1a5a 100644 --- a/src/net/packets/PacketHolder.hpp +++ b/src/net/packets/PacketHolder.hpp @@ -4,21 +4,19 @@ namespace Net { -template -class PacketHolder { +template class PacketHolder { public: PacketHolder(u32 bufferSize); ~PacketHolder(); void reset(); - void copy(T *src, u32 len); - void append(T *src, u32 len); + void copy(T* src, u32 len); + void append(T* src, u32 len); private: - T *packet; + T* packet; u32 bufferSize; u32 packetSize; - }; -} +} // namespace Net diff --git a/src/net/packets/RACEDATA.hpp b/src/net/packets/RACEDATA.hpp index 497e1bd5..f89889b3 100644 --- a/src/net/packets/RACEDATA.hpp +++ b/src/net/packets/RACEDATA.hpp @@ -9,4 +9,4 @@ class RACEDATAPacket { }; static_assert(sizeof(RACEDATAPacket) == 0x40); -} +} // namespace Net diff --git a/src/net/packets/RACEHEADER1.cpp b/src/net/packets/RACEHEADER1.cpp index efa726f9..b07cf246 100644 --- a/src/net/packets/RACEHEADER1.cpp +++ b/src/net/packets/RACEHEADER1.cpp @@ -1,9 +1,66 @@ #include "RACEHEADER1.hpp" +#include "net/NetManager.hpp" + +#include + namespace Net { void RACEHEADER1Handler::setPrepared() { + // setting this to true allows the main logic of this class's calc() to run() m_prepared = true; } +s32 RACEHEADER1Handler::getCourseId() const { + s32 otherCourseId; + u32 adjustedCourseId; + s32 result; + for (u8 i = 0; i < MAX_PLAYER_COUNT; i++) { + const RACEHEADER1Data* data = &m_RH1Datas[i]; + adjustedCourseId = data->courseId; + if (adjustedCourseId <= 0x42) { + adjustedCourseId = data->courseId; + otherCourseId = data->courseId; + } else { + otherCourseId = -1; + } + + if (otherCourseId != -1 && data->_00 != 0) { + if (adjustedCourseId <= 0x42) { + return data->courseId; + } else { + return -1; + } + } + } + return -1; } + +// https://decomp.me/scratch/zMnhg +bool RACEHEADER1Handler::courseValid() const { + bool result; + s32 adjustedCourseId; + System::CourseId courseId; + + if (!NetManager::getInstance()->hasFoundMatch()) { + result = false; + } else { + if (m_unk8 != 0) { + NetManager* netManager = NetManager::getInstance(); + u32 myAidSlot = + 1 << netManager->m_matchMakingInfos[netManager->m_currMMInfo].m_myAid; + u32 fullBitmap = netManager->m_matchMakingInfos[netManager->m_currMMInfo] + .m_fullAidBitmap; + myAidSlot = fullBitmap & (m_unk8 | myAidSlot); + result = (fullBitmap == myAidSlot); + } else { + result = false; + } + } + if (result) { + return getCourseId() != -1; + } + return result; +} + +} // namespace Net diff --git a/src/net/packets/RACEHEADER1.hpp b/src/net/packets/RACEHEADER1.hpp index f3584e15..7354bf87 100644 --- a/src/net/packets/RACEHEADER1.hpp +++ b/src/net/packets/RACEHEADER1.hpp @@ -1,5 +1,7 @@ #pragma once +#include "system/ResourceManager.hpp" + #include namespace Net { @@ -9,21 +11,41 @@ struct RACEHEADER1Packet { }; static_assert(sizeof(RACEHEADER1Packet) == 0x28); +struct RACEHEADER1Data { + u32 _00; + u8 _04[0x14 - 0x04]; + // This can take on values outside of the current courseId enum, maybe they're + // different types? + System::CourseId courseId; + u8 _18[0x20 - 0x18]; + u8 playerIdToAidMapping[12]; + u8 _2c[0x30 - 0x2c]; +}; +static_assert(sizeof(RACEHEADER1Data) == 0x30); + class RACEHEADER1Handler { -public: +public: void setPrepared(); void reset(); - static RACEHEADER1Handler *getInstance() { - return spInstance; - } + bool courseValid() const; + + inline s32 getCourseId() const; + + const u8* getPlayerIdToAidMapping() const; + + static RACEHEADER1Handler* getInstance() { return spInstance; } + private: bool m_prepared; - u8 _004[0x260 - 0x001]; + u8 _001[0x008 - 0x001]; + u32 m_unk8; + u8 _00c[0x020 - 0x00c]; + RACEHEADER1Data m_RH1Datas[12]; - static RACEHEADER1Handler *spInstance; + static RACEHEADER1Handler* spInstance; }; static_assert(sizeof(RACEHEADER1Handler) == 0x260); -} +} // namespace Net diff --git a/src/net/packets/RACEHEADER2.hpp b/src/net/packets/RACEHEADER2.hpp index 53c0c95d..942fb79a 100644 --- a/src/net/packets/RACEHEADER2.hpp +++ b/src/net/packets/RACEHEADER2.hpp @@ -9,4 +9,4 @@ struct RACEHEADER2Packet { }; static_assert(sizeof(RACEHEADER2Packet) == 0x28); -} +} // namespace Net diff --git a/src/net/packets/RACEPacketHolder.hpp b/src/net/packets/RACEPacketHolder.hpp index 41ffc6f1..bd0f925c 100644 --- a/src/net/packets/RACEPacketHolder.hpp +++ b/src/net/packets/RACEPacketHolder.hpp @@ -17,14 +17,14 @@ namespace Net { class RACEPacketHolder { private: // Maybe this is an array? - PacketHolder *m_headerPacket; - PacketHolder *m_raceHeader1Packet; - PacketHolder *m_raceHeader2Packet; - PacketHolder *m_selectPacket; - PacketHolder *m_raceDataPacket; - PacketHolder *m_userPacket; - PacketHolder *m_itemPacket; - PacketHolder *m_eventPacket; + PacketHolder* m_headerPacket; + PacketHolder* m_raceHeader1Packet; + PacketHolder* m_raceHeader2Packet; + PacketHolder* m_selectPacket; + PacketHolder* m_raceDataPacket; + PacketHolder* m_userPacket; + PacketHolder* m_itemPacket; + PacketHolder* m_eventPacket; // 0x8065a3dc RACEPacketHolder(); @@ -33,4 +33,4 @@ class RACEPacketHolder { }; static_assert(sizeof(RACEPacketHolder) == 0x20); -} +} // namespace Net diff --git a/src/net/packets/ROOM.cpp b/src/net/packets/ROOM.cpp index 804697d3..4155d693 100644 --- a/src/net/packets/ROOM.cpp +++ b/src/net/packets/ROOM.cpp @@ -1,5 +1,3 @@ #include "ROOM.hpp" -namespace Net { - -} +namespace Net {} diff --git a/src/net/packets/ROOM.hpp b/src/net/packets/ROOM.hpp index 8cf770ac..13b4c392 100644 --- a/src/net/packets/ROOM.hpp +++ b/src/net/packets/ROOM.hpp @@ -3,14 +3,14 @@ #include namespace Net { - + enum RoomRole { ROLE_HOST = 0x0, ROLE_GUEST = 0x1, }; // Credits: https://wiki.tockdom.com/wiki/Network_Protocol/ROOM -#pragma options align=packed +#pragma options align = packed struct ROOMPacket { // Message Type: // 1: Starting room @@ -18,12 +18,12 @@ struct ROOMPacket { // 3: Someone joined room // 4: Chat u8 messageType; - + // These are parameters, but its use depends on the message type. u16 _1; u8 _3; }; -#pragma options align=reset +#pragma options align = reset static_assert(sizeof(ROOMPacket) == 0x4); class ROOMHandler { @@ -32,14 +32,13 @@ class ROOMHandler { void reset(); - static ROOMHandler *getInstance() { - return spInstance; - } + static ROOMHandler* getInstance() { return spInstance; } + private: u8 _00[0x80 - 0x00]; - static ROOMHandler *spInstance; + static ROOMHandler* spInstance; }; static_assert(sizeof(ROOMHandler) == 0x80); -} +} // namespace Net diff --git a/src/net/packets/SELECT.cpp b/src/net/packets/SELECT.cpp new file mode 100644 index 00000000..f02cb005 --- /dev/null +++ b/src/net/packets/SELECT.cpp @@ -0,0 +1,9 @@ +#include "SELECT.hpp" + +namespace Net { + +const u8* SELECTHandler::getPlayerIdToAidMapping() const { + return m_sendPacket.m_playerIdToAidMapping; +} + +} // namespace Net diff --git a/src/net/packets/SELECT.hpp b/src/net/packets/SELECT.hpp index bf5d2955..d937ade4 100644 --- a/src/net/packets/SELECT.hpp +++ b/src/net/packets/SELECT.hpp @@ -5,13 +5,26 @@ namespace Net { struct SELECTPacket { - u8 _00[0x38 - 0x00]; + u8 _00[0x28 - 0x00]; + u8 m_playerIdToAidMapping[12]; + u8 _34[0x38 - 0x34]; }; static_assert(sizeof(SELECTPacket) == 0x38); class SELECTHandler { - u8 _000[0x3f8 - 0x000]; +public: + const u8* getPlayerIdToAidMapping() const; + + static SELECTHandler* getInstance() { return spInstance; } + +private: + u8 _000[0x008 - 0x000]; + SELECTPacket m_sendPacket; + SELECTPacket m_recvPackets[12]; + u8 _2e0[0x3f8 - 0x2e0]; + + static SELECTHandler* spInstance; }; static_assert(sizeof(SELECTHandler) == 0x3f8); -} +} // namespace Net diff --git a/src/net/packets/USER.cpp b/src/net/packets/USER.cpp index 03f149e1..9d99a525 100644 --- a/src/net/packets/USER.cpp +++ b/src/net/packets/USER.cpp @@ -1,5 +1,3 @@ #include "USER.hpp" -namespace Net { - -} +namespace Net {} diff --git a/src/net/packets/USER.hpp b/src/net/packets/USER.hpp index acfdc00b..3645033c 100644 --- a/src/net/packets/USER.hpp +++ b/src/net/packets/USER.hpp @@ -11,16 +11,15 @@ static_assert(sizeof(USERPacket) == 0xc0); class USERHandler { public: - void update(); + void update(); + + static USERHandler* getInstance() { return spInstance; } - static USERHandler *getInstance() { - return spInstance; - } private: u8 _000[0x9f0 - 0x000]; - static USERHandler *spInstance; + static USERHandler* spInstance; }; static_assert(sizeof(USERHandler) == 0x9f0); -} +} // namespace Net