├── .vscode └── c_cpp_properties.json ├── LICENSE ├── README.md ├── assets ├── CommonWiimmfi_E.bmg.json5 ├── CommonWiimmfi_F.bmg.json5 ├── CommonWiimmfi_G.bmg.json5 ├── CommonWiimmfi_I.bmg.json5 ├── CommonWiimmfi_M.bmg.json5 ├── CommonWiimmfi_Q.bmg.json5 ├── CommonWiimmfi_S.bmg.json5 ├── MenuWiimmfi_E.bmg.json5 ├── MenuWiimmfi_F.bmg.json5 ├── MenuWiimmfi_G.bmg.json5 ├── MenuWiimmfi_I.bmg.json5 ├── MenuWiimmfi_J.bmg.json5 ├── MenuWiimmfi_K.bmg.json5 ├── MenuWiimmfi_M.bmg.json5 ├── MenuWiimmfi_Q.bmg.json5 ├── MenuWiimmfi_S.bmg.json5 ├── MenuWiimmfi_U.bmg.json5 └── RaceWiimmfi.bmg.json5 ├── externals-mkw.txt ├── payload ├── DolphinDevice.cpp ├── DolphinDevice.hpp ├── ModSupport.hpp ├── common │ ├── Common.h │ ├── Common.hpp │ └── Kamek.h ├── dwc │ ├── dwc_account.h │ ├── dwc_auth_interface.cpp │ ├── dwc_base64.h │ ├── dwc_common.h │ ├── dwc_error.h │ ├── dwc_friend.cpp │ ├── dwc_login.cpp │ ├── dwc_login.h │ ├── dwc_main.cpp │ ├── dwc_main.h │ ├── dwc_match.cpp │ ├── dwc_match.h │ ├── dwc_node.h │ ├── dwc_report.h │ └── dwc_transport.h ├── egg │ └── core │ │ ├── eggAllocator.hpp │ │ ├── eggDecomp.hpp │ │ ├── eggDisposer.hpp │ │ ├── eggExpHeap.hpp │ │ ├── eggHeap.hpp │ │ ├── eggSceneManager.hpp │ │ └── eggTaskThread.hpp ├── game │ ├── gfx │ │ └── AnmHolder.hpp │ ├── host_system │ │ └── ParameterFile.hpp │ ├── item │ │ └── ItemObj.cpp │ ├── kart │ │ ├── KartMove.cpp │ │ ├── KartNetReceiver.cpp │ │ ├── KartNetReceiver.hpp │ │ ├── KartObjectManager.hpp │ │ ├── KartObjectProxy.hpp │ │ ├── KartParam.cpp │ │ ├── KartPointers.hpp │ │ └── KartState.hpp │ ├── net │ │ ├── RKNetController.cpp │ │ ├── RKNetController.hpp │ │ ├── RKNetFriend.hpp │ │ ├── RKNetMutex.hpp │ │ ├── RKNetPacketCreator.cpp │ │ ├── RKNetPacketHolder.hpp │ │ ├── RKNetRoomHandler.hpp │ │ ├── RKNetSelectHandler.cpp │ │ ├── RKNetSelectHandler.hpp │ │ ├── RKNetStatusData.hpp │ │ ├── WifiDisconnectInfo.hpp │ │ └── packet │ │ │ ├── RKNetRacePacketHeader.hpp │ │ │ ├── RKNetRoomPacket.hpp │ │ │ └── RKNetSelectPacket.hpp │ ├── obj │ │ └── ObjDossun.cpp │ ├── race │ │ └── RaceGlobals.hpp │ ├── scene │ │ └── RaceScene.cpp │ ├── system │ │ ├── Competition.hpp │ │ ├── CourseMap.cpp │ │ ├── CourseMap.hpp │ │ ├── DvdArchive.cpp │ │ ├── DvdArchive.hpp │ │ ├── FriendList.cpp │ │ ├── GhostFile.hpp │ │ ├── Mii.hpp │ │ ├── MultiDvdArchive.hpp │ │ ├── RKSystem.hpp │ │ ├── RaceConfig.hpp │ │ ├── RaceManager.cpp │ │ ├── RaceManager.hpp │ │ ├── RaceMode.hpp │ │ ├── RaceModeOnlineVs.cpp │ │ ├── RaceModeOnlineVs.hpp │ │ ├── Rating.hpp │ │ ├── RawSave.hpp │ │ ├── ResourceManager.hpp │ │ ├── SaveGhostManager.hpp │ │ ├── SaveManager.hpp │ │ ├── Timer.hpp │ │ ├── TimerManager.cpp │ │ └── TimerManager.hpp │ ├── ui │ │ ├── ButtonInfo.hpp │ │ ├── ControlGroup.hpp │ │ ├── GlobalContext.hpp │ │ ├── InputHandler.hpp │ │ ├── Layout.hpp │ │ ├── LayoutUIControl.hpp │ │ ├── MenuInputManager.hpp │ │ ├── MessageGroup.hpp │ │ ├── MessageInfo.hpp │ │ ├── Page.hpp │ │ ├── PageInputManager.hpp │ │ ├── Section.hpp │ │ ├── SectionManager.hpp │ │ ├── TypeInfo.hpp │ │ ├── UIAnimator.hpp │ │ ├── UIControl.hpp │ │ ├── UIControlTimer.hpp │ │ ├── ctrl │ │ │ ├── BlackBackControl.hpp │ │ │ └── CountdownTimerControl.hpp │ │ └── page │ │ │ ├── FriendRoomJoinPage.hpp │ │ │ ├── FriendRoomMessageSelectPage.cpp │ │ │ ├── MessagePage.hpp │ │ │ ├── MessagePopupPage.hpp │ │ │ ├── OptionMessagePage.cpp │ │ │ ├── WifiDisconnectPage.cpp │ │ │ ├── WifiDisconnectPage.hpp │ │ │ └── WifiMenuPage.cpp │ └── util │ │ └── Random.hpp ├── gs │ ├── common │ │ ├── gsAvailable.h │ │ ├── gsPlatformUtil.h │ │ └── gsSocketRevolution.h │ ├── darray.h │ ├── gp │ │ ├── gp.h │ │ ├── gpi.cpp │ │ ├── gpi.h │ │ ├── gpiBuddy.h │ │ ├── gpiBuffer.h │ │ ├── gpiCallback.h │ │ ├── gpiConnect.cpp │ │ ├── gpiOperation.h │ │ ├── gpiPeer.h │ │ └── gpiProfile.h │ ├── gt2 │ │ ├── gt2.h │ │ ├── gt2Buffer.h │ │ ├── gt2Callback.h │ │ ├── gt2Main.h │ │ ├── gt2Socket.cpp │ │ └── gt2Utility.h │ ├── hashtable.h │ ├── natneg │ │ ├── natify.c │ │ ├── natify.h │ │ ├── natneg.cpp │ │ └── natneg.h │ └── qr2 │ │ ├── qr2.cpp │ │ └── qr2.h ├── nw4r │ ├── lyt │ │ ├── drawInfo.hpp │ │ ├── material.hpp │ │ ├── pane.hpp │ │ └── texmap.hpp │ ├── math │ │ └── types.hpp │ └── ut │ │ ├── Lock.hpp │ │ ├── rect.hpp │ │ └── utList.hpp ├── platform │ ├── new.hpp │ ├── stdio.h │ ├── stdlib.h │ └── string.h ├── revolution │ ├── base │ │ ├── PPCArch.h │ │ ├── PPCReg.h │ │ └── PPCWGPipe.h │ ├── dvd │ │ └── dvd.h │ ├── es │ │ ├── es.c │ │ └── es.h │ ├── ios.h │ ├── mem │ │ ├── allocator.h │ │ ├── heapCommon.h │ │ └── list.h │ ├── mtx.h │ ├── os │ │ ├── OS.h │ │ ├── OSCache.h │ │ ├── OSContext.h │ │ ├── OSExec.h │ │ ├── OSLoMem.h │ │ ├── OSLog.h │ │ ├── OSModule.h │ │ ├── OSMutex.h │ │ ├── OSThread.h │ │ └── OSTitle.h │ ├── sc.h │ └── vi.h ├── revolutionex │ ├── net │ │ └── NETDigest.h │ ├── nhttp │ │ ├── NHTTP.h │ │ └── NHTTPInternal.h │ └── so │ │ └── SOBasic.h └── wiimmfi │ ├── Auth.cpp │ ├── Auth.hpp │ ├── Challenge.cpp │ ├── Challenge.hpp │ ├── ConnectionMatrix.cpp │ ├── ConnectionMatrix.hpp │ ├── Delay.cpp │ ├── Delay.hpp │ ├── Domains.cpp │ ├── Kick.cpp │ ├── Kick.hpp │ ├── MatchCommand.cpp │ ├── MatchCommand.hpp │ ├── Natify.cpp │ ├── Natify.hpp │ ├── Natneg.cpp │ ├── Natneg.hpp │ ├── Port.cpp │ ├── Port.hpp │ ├── Reporting.cpp │ ├── Reporting.hpp │ ├── RoomStall.cpp │ ├── RoomStall.hpp │ ├── Security.cpp │ ├── Security.hpp │ ├── Status.cpp │ └── Status.hpp └── versions-mkw.txt /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "OpenPayload", 5 | "includePath": [ 6 | "${workspaceFolder}/payload/**" 7 | ], 8 | "defines": [ 9 | "__CWCC__", 10 | "DEBUG=1" 11 | ], 12 | "cStandard": "c99", 13 | "cppStandard": "c++11" 14 | } 15 | ], 16 | "version": 4 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 CLF78 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /assets/CommonWiimmfi_E.bmg.json5: -------------------------------------------------------------------------------- 1 | { 2 | "9903": { 3 | string: "Controllers cannot be changed during\na Wiimmfi match. Please restore\nthe original controller.", 4 | }, 5 | } -------------------------------------------------------------------------------- /assets/CommonWiimmfi_F.bmg.json5: -------------------------------------------------------------------------------- 1 | { 2 | "9903": { 3 | string: "Les manettes ne peuvent pas être changés\npendant un match en ligne.\nReconnectez la manette précédente.", 4 | }, 5 | } -------------------------------------------------------------------------------- /assets/CommonWiimmfi_G.bmg.json5: -------------------------------------------------------------------------------- 1 | { 2 | "9903": { 3 | string: "Während eines Matchs via Wiimmfi\nkann der Controller nicht gewechselt werden.\nBitte vorherigen Controller verwenden.", 4 | }, 5 | } -------------------------------------------------------------------------------- /assets/CommonWiimmfi_I.bmg.json5: -------------------------------------------------------------------------------- 1 | { 2 | "9903": { 3 | string: "Non puoi cambiare controller durante\nuna partita su Wiimmfi.\nTorna al controller originale.", 4 | }, 5 | } 6 | -------------------------------------------------------------------------------- /assets/CommonWiimmfi_M.bmg.json5: -------------------------------------------------------------------------------- 1 | { 2 | "9903": { 3 | string: "No puedes cambiar los mandos mientras\nestás jugando en línea.\nVuelve a colocar el anterior.", 4 | }, 5 | } -------------------------------------------------------------------------------- /assets/CommonWiimmfi_Q.bmg.json5: -------------------------------------------------------------------------------- 1 | { 2 | "9903": { 3 | string: "Les manettes ne peuvent pas être changés\npendant un match en ligne.\nReconnectez la manette précédente.", 4 | }, 5 | } -------------------------------------------------------------------------------- /assets/CommonWiimmfi_S.bmg.json5: -------------------------------------------------------------------------------- 1 | { 2 | "9903": { 3 | string: "No puedes cambiar los mandos mientras\nestás jugando en línea.\nVuelve a colocar el anterior.", 4 | }, 5 | } -------------------------------------------------------------------------------- /assets/RaceWiimmfi.bmg.json5: -------------------------------------------------------------------------------- 1 | { 2 | "1020": { 3 | string: "Wiimmfi", 4 | }, 5 | } -------------------------------------------------------------------------------- /payload/DolphinDevice.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace DolphinDevice { 5 | 6 | s32 sDevDolphin = -1; 7 | char sVersionBuffer[64]; 8 | char sProdCodeBuffer[6]; 9 | 10 | bool IsOpen() { 11 | return sDevDolphin >= 0; 12 | } 13 | 14 | bool Open() { 15 | if (!IsOpen()) 16 | sDevDolphin = IOS_Open("/dev/dolphin", IPC_OPEN_NONE); 17 | return IsOpen(); 18 | } 19 | 20 | u32 GetElapsedTime() { 21 | 22 | // Check if device is open 23 | if (!IsOpen()) 24 | return 0; 25 | 26 | // Do IOS call 27 | u32 milliseconds = 0; 28 | IOSIoVector vec = {&milliseconds, sizeof(milliseconds)}; 29 | s32 result = IOS_Ioctlv(sDevDolphin, GET_ELAPSED_TIME, 0, 1, &vec); 30 | 31 | // Bail on failure 32 | if (result != IPC_OK) 33 | return 0; 34 | 35 | // Return correct value 36 | return milliseconds; 37 | } 38 | 39 | const char* GetVersion() { 40 | 41 | // If the version was already obtained, return it directly 42 | static bool sVersionObtained = false; 43 | if (sVersionObtained) 44 | return sVersionBuffer; 45 | 46 | // Check if device is open 47 | if (!IsOpen()) 48 | return nullptr; 49 | 50 | // Do IOS call 51 | IOSIoVector vec = {sVersionBuffer, sizeof(sVersionBuffer)}; 52 | s32 result = IOS_Ioctlv(sDevDolphin, GET_VERSION, 0, 1, &vec); 53 | 54 | // Bail on failure 55 | if (result != IPC_OK) 56 | return nullptr; 57 | 58 | // Ensure the string is null-terminated 59 | sVersionBuffer[sizeof(sVersionBuffer)-1] = '\0'; 60 | 61 | // Return the buffer 62 | sVersionObtained = true; 63 | return sVersionBuffer; 64 | } 65 | 66 | const char* GetRealProductCode() { 67 | 68 | // If the code was already obtained, return it directly 69 | static bool sProdCodeObtained = false; 70 | if (sProdCodeObtained) 71 | return sProdCodeBuffer; 72 | 73 | // Check if device is open 74 | if (!IsOpen()) 75 | return nullptr; 76 | 77 | // Do IOS call 78 | IOSIoVector vec = {sProdCodeBuffer, sizeof(sProdCodeBuffer)}; 79 | s32 result = IOS_Ioctlv(sDevDolphin, GET_REAL_PRODUCT_CODE, 0, 1, &vec); 80 | 81 | // Bail on failure 82 | if (result != IPC_OK) 83 | return nullptr; 84 | 85 | // Ensure the string is null-terminated 86 | sProdCodeBuffer[sizeof(sProdCodeBuffer)-1] = '\0'; 87 | 88 | // Return the buffer 89 | sProdCodeObtained = true; 90 | return sProdCodeBuffer; 91 | } 92 | 93 | } // namespace DolphinDevice 94 | -------------------------------------------------------------------------------- /payload/DolphinDevice.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace DolphinDevice { 5 | 6 | enum Ioctlv { 7 | 8 | // 5.0-11186 and onwards 9 | GET_ELAPSED_TIME = 1, // In = None, Out = u32 10 | GET_VERSION = 2, // In = None, Out = char[] 11 | GET_SPEED_LIMIT = 3, // In = None, Out = u32 12 | SET_SPEED_LIMIT = 4, // In = u32, Out = None 13 | GET_CPU_SPEED = 5, // In = None, Out = u32 14 | 15 | // 5.0-12058 and onwards 16 | GET_REAL_PRODUCT_CODE = 6, // In = None, Out = char[] 17 | 18 | // 5.0-17155 and onwards 19 | DISCORD_SET_CLIENT = 7, // In = char[], Out = None 20 | DISCORD_SET_PRESENCE = 8, // In = (char[], char[], char[], char[], char[], s64, s64, u32, u32), Out = None 21 | DISCORD_RESET = 9, // In = None, Out = None 22 | 23 | // 5.0-17856 and onwards 24 | GET_SYSTEM_TIME = 10, // In = None, Out = u64 25 | }; 26 | 27 | bool Open(); 28 | u32 GetElapsedTime(); 29 | const char* GetVersion(); 30 | const char* GetRealProductCode(); 31 | 32 | } // namespace DolphinDevice 33 | -------------------------------------------------------------------------------- /payload/ModSupport.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Generic functions meant for mods to override 4 | namespace ModSupport { 5 | 6 | // Process custom match commands 7 | // Return true if the custom function recognized the custom command 8 | bool ProcessRecvMatchCommand(u8 cmd, int profileId, u32 publicIp, u16 publicPort, void* cmdData, int dataLen); 9 | 10 | // Return true if Ultra UnCut should be enabled 11 | // It's recommended to turn it on for Worldwide matches 12 | bool AreUltraShortcutsEnabled(); 13 | 14 | // Return the race time limit, in milliseconds 15 | u32 GetOnlineTimeLimit(); 16 | 17 | // Return a custom UPNP port if a specific one is requested, else 0 to let Wiimmfi derive it from 18 | // the console serial number 19 | u16 GetCustomUPNPPort(); 20 | 21 | // Allows relaxing the checks for valid data (e.g custom packets) 22 | // Return true if the packet section is valid (see RKNetRacePacketHeader.hpp for the section index) 23 | bool IsPacketSectionDataValid(int section, u8* sectionData, u32 sectionDataLen); 24 | 25 | // Gets the Online VS region 26 | u16 GetVSRegion(); 27 | 28 | // Gets the Online Battle region 29 | u16 GetBTRegion(); 30 | 31 | } // namespace ModSupport 32 | -------------------------------------------------------------------------------- /payload/common/Common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Kamek Standard Library 3 | * Wii game patching engine 4 | * (c) Treeki 2010-2018 5 | */ 6 | 7 | // Base asserts 8 | #ifndef __CWCC__ 9 | #error "Kamek requires the CodeWarrior compiler!" 10 | #endif 11 | 12 | // Defines 13 | #define NULL 0 14 | #define FALSE 0 15 | #define TRUE 1 16 | 17 | // Base types 18 | typedef unsigned char u8; 19 | typedef unsigned short u16; 20 | typedef unsigned int u32; 21 | typedef unsigned long long u64; 22 | typedef signed char s8; 23 | typedef signed short s16; 24 | typedef signed int s32; 25 | typedef signed long long s64; 26 | typedef float f32; 27 | typedef double f64; 28 | typedef unsigned long size_t; 29 | typedef unsigned long ulong; 30 | typedef volatile s8 vs8; 31 | typedef volatile s16 vs16; 32 | typedef volatile s32 vs32; 33 | typedef volatile s64 vs64; 34 | typedef volatile u8 vu8; 35 | typedef volatile u16 vu16; 36 | typedef volatile u32 vu32; 37 | typedef volatile u64 vu64; 38 | typedef volatile f32 vf32; 39 | typedef volatile f64 vf64; 40 | typedef void (*Func)(); 41 | 42 | // Macros 43 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 44 | #define ALIGN(a) __attribute__ ((aligned(a))) 45 | #define BIT_FLAG(bit) ((bit) < 0 ? 0 : 1 << (bit)) 46 | #define BOOL s32 47 | #define MIN(a, b) (((b) < (a)) ? (b) : (a)) 48 | #define MAX(a, b) (((a) < (b)) ? (b) : (a)) 49 | #define offsetof(a, b) ((int)(&(((a*)(0))->b))) 50 | #define STRINGIFY(x) #x 51 | 52 | #ifdef __INTELLISENSE__ 53 | #define AT_ADDR(addr) 54 | #else 55 | #define AT_ADDR(addr) : (addr); 56 | #endif 57 | 58 | // Include other base headers 59 | #include 60 | #include 61 | -------------------------------------------------------------------------------- /payload/common/Common.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Macros 4 | #ifndef __INTELLISENSE__ 5 | #define static_assert(cond) __static_assert((cond), #cond) 6 | #define size_assert(type, size) static_assert(sizeof(type) == (size)) 7 | #else 8 | #define size_assert(type, size) 9 | #endif 10 | -------------------------------------------------------------------------------- /payload/common/Kamek.h: -------------------------------------------------------------------------------- 1 | // Allow Kamek hooks to be defined from C++ source files 2 | #pragma section ".kamek" 3 | 4 | // Hook type IDs must match the Kamek source! 5 | enum KamekCommandType { 6 | kctNone, 7 | kctWrite, 8 | kctWriteArea, // replaces kctConditionalWrite 9 | kctInjectBranch, 10 | kctInjectCall, 11 | kctPatchExit, 12 | }; 13 | 14 | // Base macros 15 | #define kmHookFn \ 16 | extern "C" static 17 | #define kmIdentifierImpl(key, counter) \ 18 | _k##key##counter 19 | #define kmIdentifier(key, counter) \ 20 | kmIdentifierImpl(key, counter) 21 | 22 | // Remove non-existent Intellisense errors 23 | #ifndef __INTELLISENSE__ 24 | #define kmSection __declspec (section ".kamek") 25 | #else 26 | #define kmSection 27 | #endif 28 | 29 | // General hook definition macros 30 | #define kmHookInt(counter) \ 31 | kmSection static const u32 kmIdentifierImpl(Hook, counter) 32 | #define kmHook0(type) \ 33 | kmHookInt(__COUNTER__)[2] = { 0, (type) } 34 | #define kmHook1(type, arg0) \ 35 | kmHookInt(__COUNTER__)[3] = { 1, (type), (u32)(arg0) } 36 | #define kmHook2(type, arg0, arg1) \ 37 | kmHookInt(__COUNTER__)[4] = { 2, (type), (u32)(arg0), (u32)(arg1) } 38 | #define kmHook3(type, arg0, arg1, arg2) \ 39 | kmHookInt(__COUNTER__)[5] = { 3, (type), (u32)(arg0), (u32)(arg1), (u32)(arg2) } 40 | #define kmHook4(type, arg0, arg1, arg2, arg3) \ 41 | kmHookInt(__COUNTER__)[6] = { 4, (type), (u32)(arg0), (u32)(arg1), (u32)(arg2), (u32)(arg3) } 42 | 43 | // kmWrite 44 | // Write value to address 45 | #define kmWritePointer(addr, ptr) kmHook3(kctWrite, 1, (addr), (ptr)) 46 | #define kmWrite32(addr, value) kmHook3(kctWrite, 2, (addr), (value)) 47 | #define kmWrite16(addr, value) kmHook3(kctWrite, 3, (addr), (value)) 48 | #define kmWrite8(addr, value) kmHook3(kctWrite, 4, (addr), (value)) 49 | #define kmWriteArea(addr, value) kmHook4(kctWriteArea, 1, (addr), (value), sizeof((value))) 50 | 51 | // kmPatchExitPoint 52 | // Force the end of a Kamek function to always jump to a specific address 53 | // (if the address is 0, the end remains as-is (i.e. blr)) 54 | #define kmPatchExitPoint(funcStart, dest) kmHook2(kctPatchExit, (funcStart), (dest)) 55 | 56 | // kmBranch, kmCall 57 | // Set up a branch from a specific instruction to a specific address 58 | #define kmBranch(addr, ptr) kmHook2(kctInjectBranch, (addr), (ptr)) 59 | #define kmCall(addr, ptr) kmHook2(kctInjectCall, (addr), (ptr)) 60 | 61 | // kmBranchDefCpp, kmBranchDefAsm 62 | // Set up a branch (b) from a specific instruction to a function defined 63 | // directly underneath. If exitPoint is not NULL, the function will 64 | // branch to exitPoint when done; otherwise, it executes blr as normal 65 | #define kmBranchDefInt(counter, addr, exitPoint, returnType, ...) \ 66 | static returnType kmIdentifierImpl(UserFunc, counter) (__VA_ARGS__); \ 67 | kmBranch(addr, kmIdentifierImpl(UserFunc, counter)); \ 68 | kmPatchExitPoint(kmIdentifierImpl(UserFunc, counter), exitPoint); \ 69 | static returnType kmIdentifierImpl(UserFunc, counter) (__VA_ARGS__) 70 | 71 | #define kmBranchDefCpp(addr, exitPoint, returnType, ...) \ 72 | kmBranchDefInt(__COUNTER__, addr, exitPoint, returnType, __VA_ARGS__) 73 | #define kmBranchDefAsm(addr, exitPoint) \ 74 | kmBranchDefInt(__COUNTER__, addr, exitPoint, asm void, ) 75 | 76 | // kmCallDefCpp, kmCallDefAsm 77 | // Set up a branch with link (bl) from a specific instruction to a function 78 | // defined directly underneath. 79 | #define kmCallDefInt(counter, addr, returnType, ...) \ 80 | static returnType kmIdentifierImpl(UserFunc, counter) (__VA_ARGS__); \ 81 | kmCall(addr, kmIdentifierImpl(UserFunc, counter)); \ 82 | static returnType kmIdentifierImpl(UserFunc, counter) (__VA_ARGS__) 83 | 84 | #define kmCallDefCpp(addr, returnType, ...) \ 85 | kmCallDefInt(__COUNTER__, addr, returnType, __VA_ARGS__) 86 | #define kmCallDefAsm(addr) \ 87 | kmCallDefInt(__COUNTER__, addr, asm void, ) 88 | 89 | // kmPointerDefCpp, kmPointerDefAsm 90 | // Replace a pointer to a function with one to the function defined directly underneath. 91 | #define kmPointerDefInt(counter, addr, returnType, ...) \ 92 | static returnType kmIdentifierImpl(UserFunc, counter) (__VA_ARGS__); \ 93 | kmWritePointer(addr, kmIdentifierImpl(UserFunc, counter)); \ 94 | static returnType kmIdentifierImpl(UserFunc, counter) (__VA_ARGS__) 95 | 96 | #define kmPointerDefCpp(addr, returnType, ...) \ 97 | kmPointerDefInt(__COUNTER__, addr, returnType, __VA_ARGS__) 98 | #define kmPointerDefAsm(addr) \ 99 | kmPointerDefInt(__COUNTER__, addr, asm void, ) 100 | -------------------------------------------------------------------------------- /payload/dwc/dwc_account.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #define DWC_ACC_MASKBITS(bits) (((1 << bits) - 1)) 8 | 9 | #define DWC_ACC_FLAGS_SHIFT 11 10 | #define DWC_ACC_FLAGS_BITS 21 11 | #define DWC_ACC_FLAGS_MASK DWC_ACC_MASKBITS(DWC_ACC_FLAGS_BITS) 12 | 13 | typedef struct { 14 | u32 flags; 15 | u32 reserved[2]; 16 | } DWCAccFlag; 17 | 18 | typedef struct { 19 | u32 id_data; 20 | u32 userId; 21 | u32 playerId; 22 | } DWCLoginId; 23 | 24 | typedef struct { 25 | u32 id_data; 26 | u32 friendkey[2]; 27 | } DWCFriendKey; 28 | 29 | typedef struct { 30 | u32 id_data; 31 | int id; 32 | u32 reserved; 33 | } DWCGsProfileId; 34 | 35 | typedef union { 36 | DWCAccFlag flags; 37 | DWCLoginId login_id; 38 | DWCFriendKey friend_key; 39 | DWCGsProfileId gs_profile_id; 40 | } DWCFriendData; 41 | 42 | typedef enum { 43 | DWC_FRIENDDATA_NODATA, 44 | DWC_FRIENDDATA_LOGIN_ID, 45 | DWC_FRIENDDATA_FRIEND_KEY, 46 | DWC_FRIENDDATA_GS_PROFILE_ID, 47 | DWC_FRIENDDATA_MASK = 3, 48 | } DWCFriendDataType; 49 | 50 | typedef struct { 51 | int size; 52 | DWCLoginId pseudo; 53 | DWCLoginId authentic; 54 | int gs_profile_id; 55 | int flag; 56 | u32 gamecode; 57 | int reserved[5]; 58 | u32 crc32; 59 | } DWCUserData; 60 | 61 | typedef enum { 62 | DWC_USER_DATA_FLAG_DIRTY = BIT_FLAG(0), 63 | } DWCUserDataFlag; 64 | 65 | void DWCi_Acc_SetUserId(DWCLoginId* data, u64 userid); 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | -------------------------------------------------------------------------------- /payload/dwc/dwc_auth_interface.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | //////////////////////////// 11 | // Wiimmfi Authentication // 12 | //////////////////////////// 13 | 14 | // DWCi_Auth_SendRequest() patch 15 | // Insert custom authentication parameters 16 | // Credits: Wiimmfi 17 | kmCallDefCpp(0x800EDEE8, void, NHTTPReq* req, const char* key, const char* val) { 18 | 19 | // Original call 20 | NHTTPAddPostDataAscii(req, key, val); 21 | 22 | // Send the required extra data 23 | Wiimmfi::Auth::AppendAuthParameters(req); 24 | } 25 | 26 | // DWCi_Auth_SendRequest() patch 27 | // Report the product code from the imported NAND on Dolphin 28 | // Credits: Wiimmfi 29 | kmCallDefCpp(0x800EE098, const char*) { 30 | 31 | // Check if we're on Dolphin and use the dedicated IOCTL if so 32 | if (DolphinDevice::Open()) { 33 | const char* prodCode = DolphinDevice::GetRealProductCode(); 34 | return (prodCode != nullptr) ? prodCode : SCGetProductCode(); 35 | } 36 | 37 | // Else just call the original function 38 | return SCGetProductCode(); 39 | } 40 | 41 | // DWCi_Auth_HandleResponse() patch 42 | // Parse the custom response data 43 | // Credits: Wiimmfi 44 | kmCallDefCpp(0x800EEA08, void, DWCReportFlag level, const char* fmt, const char* arg) { 45 | 46 | // Original call 47 | DWC_Printf(level, fmt, arg); 48 | 49 | // Parse the extra response data 50 | Wiimmfi::Auth::ParseAuthResponse(arg); 51 | } 52 | 53 | ///////////////////////////// 54 | // Wiimmfi Challenge Check // 55 | ///////////////////////////// 56 | 57 | // DWCi_Auth_HandleResponse() patch 58 | // Save the login challenge 59 | // Credits: Wiimmfi 60 | kmCallDefCpp(0x800EE74C, void, char* dest, const char* src) { 61 | 62 | // Save the challenge both to the stack and the Wiimmfi buffers 63 | strcpy(dest, src); 64 | Wiimmfi::Challenge::Save(src); 65 | } 66 | -------------------------------------------------------------------------------- /payload/dwc/dwc_base64.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | int DWC_Base64Encode(const char* src, const ulong srclen, char* dst, const ulong dstlen); 8 | int DWC_Base64Decode(const char* src, const ulong srclen, char* dst, const ulong dstlen); 9 | 10 | #define DWC_Base64GetEncodedSize(x) (((x) / 3 + ((x) % 3 != 0)) * 4) 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /payload/dwc/dwc_common.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | u32 DWCi_GetMathRand32(u32 max); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | 13 | 14 | -------------------------------------------------------------------------------- /payload/dwc/dwc_error.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef enum { 9 | DWC_ERROR_NONE, 10 | DWC_ERROR_DS_MEMORY_ANY, 11 | DWC_ERROR_AUTH_ANY, 12 | DWC_ERROR_AUTH_OUT_OF_SERVICE, 13 | DWC_ERROR_AUTH_STOP_SERVICE, 14 | DWC_ERROR_AC_ANY, 15 | DWC_ERROR_NETWORK, 16 | DWC_ERROR_GHTTP_ANY, 17 | DWC_ERROR_DISCONNECTED, 18 | DWC_ERROR_FATAL, 19 | DWC_ERROR_FRIENDS_SHORTAGE, 20 | DWC_ERROR_NOT_FRIEND_SERVER, 21 | DWC_ERROR_SERVER_FULL, 22 | DWC_ERROR_ND_ANY, 23 | DWC_ERROR_ND_HTTP, 24 | DWC_ERROR_SVL_ANY, 25 | DWC_ERROR_SVL_HTTP, 26 | DWC_ERROR_PROF_PARSE_ERR, 27 | DWC_ERROR_PROF_HTTP, 28 | DWC_ERROR_DB_ANY, 29 | DWC_ERROR_SC_CONNECT_BLOCK, 30 | DWC_ERROR_NETWORK_LIGHT, 31 | DWC_ERROR_COUNT, 32 | } DWCError; 33 | 34 | int DWCi_HandleGPError(int error); 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | -------------------------------------------------------------------------------- /payload/dwc/dwc_friend.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /////////////////////////////////////// 6 | // Friend Status Buffer Overflow Fix // 7 | /////////////////////////////////////// 8 | 9 | // DWC_GetFriendStatusData() patch 10 | // Enforce the destination buffer size to prevent an overflow 11 | // Credits: Wiimmfi 12 | kmWrite32(0x800CE220, 0x38C00000 | sizeof(RKNetStatusData[2])); 13 | 14 | ///////////////////////// 15 | // NATify Improvements // 16 | ///////////////////////// 17 | 18 | // DWCi_FriendProcess() patch 19 | // Update custom NATify procedure 20 | // Credits: Wiimmfi 21 | kmBranchDefCpp(0x800CE7A4, NULL, void) { 22 | Wiimmfi::Natify::Update(); 23 | } 24 | -------------------------------------------------------------------------------- /payload/dwc/dwc_login.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Ported from NitroDWC decompilation 7 | inline u32 DWCi_Acc_GetMaskBits(u32 data, u32 shift, u32 mask) { 8 | return ((data >> shift) & mask); 9 | } 10 | 11 | // Ported from NitroDWC decompilation 12 | BOOL DWCi_Acc_SetMaskBits(u32* ptr, u32 data, u32 shift, u32 mask) { 13 | if ((data & ~mask) != 0) 14 | return FALSE; 15 | 16 | *ptr = (*ptr & ~(mask << shift)) | (data << shift); 17 | return TRUE; 18 | } 19 | 20 | // Ported from NitroDWC decompilation 21 | u32 DWCi_Acc_GetFlags(const DWCAccFlag* userdata) { 22 | return DWCi_Acc_GetMaskBits(userdata->flags, DWC_ACC_FLAGS_SHIFT, DWC_ACC_FLAGS_MASK); 23 | } 24 | 25 | // Ported from NitroDWC decompilation 26 | void DWCi_Acc_SetFlags(DWCAccFlag* userdata, u32 flags) { 27 | DWCi_Acc_SetMaskBits(&userdata->flags, flags, DWC_ACC_FLAGS_SHIFT, DWC_ACC_FLAGS_MASK); 28 | } 29 | 30 | // Ported from NitroDWC decompilation 31 | void DWCi_Acc_SetFlag_DataType(DWCAccFlag* userdata, int type) { 32 | u32 flags = DWCi_Acc_GetFlags(userdata); 33 | flags = (flags & ~DWC_FRIENDDATA_MASK) | type; 34 | DWCi_Acc_SetFlags(userdata, flags); 35 | } 36 | 37 | ///////////////////// 38 | // Error 60000 Fix // 39 | ///////////////////// 40 | 41 | // DWCi_GPConnectCallback() patch 42 | // Clear the Profile ID if error 60000 is encountered 43 | // Credits: Wiimmfi 44 | kmBranchDefCpp(0x800D05A8, 0x800D0610, void) { 45 | 46 | // Debug report 47 | DEBUG_REPORT("[WIIMMFI] Invalid profile ID detected, requesting new one\n") 48 | 49 | // Set state to GPGETINFO (AKA lastname acquisition during GP login) 50 | stpLoginCnt->state = DWC_LOGIN_STATE_GPGETINFO; 51 | 52 | // Set the user ID and the data type 53 | DWCi_Acc_SetUserId(&stpLoginCnt->tempLoginId, DWCi_Auth_GetConsoleUserId()); 54 | DWCi_Acc_SetFlag_DataType((DWCAccFlag*)&stpLoginCnt->tempLoginId, DWC_FRIENDDATA_LOGIN_ID); 55 | 56 | // Copy temp loginId from pseudo loginId and mark user data as dirty 57 | stpLoginCnt->tempLoginId.playerId = stpLoginCnt->userdata->pseudo.playerId; 58 | stpLoginCnt->userdata->flag = DWC_USER_DATA_FLAG_DIRTY; 59 | } 60 | 61 | ///////////////////////// 62 | // NATify Improvements // 63 | ///////////////////////// 64 | 65 | // DWCi_RemoteLoginProcess() patch 66 | // Start custom NATify procedure 67 | // Credits: Wiimmfi 68 | kmCallDefCpp(0x800D086C, void, DWCReportFlag level, const char* str) { 69 | 70 | // Original call 71 | DWC_Printf(level, str); 72 | 73 | // Start NATify 74 | Wiimmfi::Natify::Start(); 75 | } 76 | -------------------------------------------------------------------------------- /payload/dwc/dwc_login.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | typedef enum { 10 | DWC_LOGIN_STATE_INIT, 11 | DWC_LOGIN_STATE_REMOTE_AUTH, 12 | DWC_LOGIN_STATE_CONNECTING, 13 | DWC_LOGIN_STATE_GPGETINFO, 14 | DWC_LOGIN_STATE_GPSETINFO, 15 | DWC_LOGIN_STATE_CONNECTED, 16 | DWC_LOGIN_STATE_COUNT, 17 | } DWCLoginState; 18 | 19 | typedef void (*DWCLoginCallback)(DWCError error, int profileID, void* param); 20 | 21 | typedef struct { 22 | void* gpConnection; 23 | DWCLoginState state; 24 | int productID; 25 | u32 gamecode; 26 | u16* playerName; 27 | DWCLoginCallback callback; 28 | void* param; 29 | DWCUserData* userdata; 30 | void* bmwork; 31 | void* http; 32 | u64 startTick; 33 | u32 connectFlag; 34 | u64 connectTick; 35 | DWCLoginId tempLoginId; 36 | char authToken[256]; 37 | char partnerChallenge[256]; 38 | char username[21]; 39 | u8 unk2[7]; 40 | } DWCLoginControl; 41 | 42 | extern DWCLoginControl* stpLoginCnt; 43 | 44 | u64 DWCi_Auth_GetConsoleUserId(); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | -------------------------------------------------------------------------------- /payload/dwc/dwc_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | ///////////////// 10 | // Fast NATNEG // 11 | ///////////////// 12 | 13 | // DWC_InitFriendsMatch() patch 14 | // Replace ConnectedCallback to accept incoming connections in more cases 15 | // Credits: Wiimmfi 16 | kmBranchDefCpp(0x800D0FE8, NULL, void) { 17 | stpDwcCnt->callbacks.connectedCb = &Wiimmfi::Natneg::ConnectedCallback; 18 | } 19 | 20 | // DWCi_GT2Startup() patch 21 | // Replace ConnectAttemptCallback to accept incoming connections in more cases 22 | // Credits: Wiimmfi 23 | kmCallDefCpp(0x800D28CC, void, GT2Socket sock, GT2ConnectAttemptCallback callback) { 24 | gt2Listen(sock, Wiimmfi::Natneg::ConnectAttemptCallback); 25 | } 26 | 27 | // DWCi_MatchedCallback() patch 28 | // Update NATNEG timers 29 | // Credits: Wiimmfi 30 | kmCallDefCpp(0x800D3188, void, DWCError error, int cancel, int self, int isServer, int index, void* param) { 31 | 32 | // Original call 33 | stpDwcCnt->userMatchedCallback(error, cancel, self, isServer, index, param); 34 | 35 | // Update NATNEG with the self value 36 | Wiimmfi::Natneg::CalcTimers(self); 37 | } 38 | 39 | ///////////////////////////////////// 40 | // Fast NATNEG / Wiimmfi Telemetry // 41 | ///////////////////////////////////// 42 | 43 | // DWCi_GT2ClosedProcess() patch 44 | // Update the connection matrix when a connection is closed 45 | // Credits: Wiimmfi 46 | kmBranch(0x800D3F1C, Wiimmfi::ConnectionMatrix::Update); 47 | 48 | ////////////////////////// 49 | // Wiimmfi Port Binding // 50 | ////////////////////////// 51 | 52 | // DWCi_GT2Startup() patch 53 | // Use the server-provided port for GT2Sockets 54 | // Credits: Wiimmfi 55 | kmCallDefCpp(0x800D2884, char*, u32 ip, u16 port, char* string) { 56 | 57 | // Override port if set 58 | if (Wiimmfi::Port::sPort) 59 | port = Wiimmfi::Port::sPort; 60 | 61 | // Original call 62 | return gt2AddressToString(ip, port, string); 63 | } 64 | -------------------------------------------------------------------------------- /payload/dwc/dwc_main.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | typedef struct { 10 | GT2Socket socket; 11 | GT2Callbacks callbacks; 12 | u8 unk[0x88 - 0x14]; 13 | DWCMatchedCallback userMatchedCallback; 14 | void* userMatchedCallbackParam; 15 | u8 unk2[0x360 - 0x90]; 16 | DWCMatchControl matchControl; 17 | } DWCControl; // TODO finish header 18 | 19 | typedef struct { 20 | u8 index; 21 | u8 aid; 22 | u16 pad; 23 | u32 profileId; 24 | } DWCConnectionInfo; 25 | 26 | BOOL DWC_IsServerMyself(); 27 | int DWC_CloseAllConnectionsHard(); 28 | int DWC_CloseConnectionHard(u8 aid); 29 | 30 | int DWCi_GT2GetConnectionListIdx(); 31 | GT2Connection* DWCi_GetGT2ConnectionByIdx(int idx); 32 | GT2Connection DWCi_GetGT2Connection(u8 aid); 33 | DWCConnectionInfo* DWCi_GetConnectionInfoByIdx(int idx); 34 | 35 | u8 DWC_GetMyAID(); 36 | u8 DWC_GetServerAID(); 37 | u32 DWC_GetAIDBitmap(); 38 | 39 | extern DWCControl* stpDwcCnt; 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /payload/dwc/dwc_node.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct { 8 | u8 playersAtConsole; 9 | u8 _1[3]; // unused 10 | } DWCConnectionUserData; 11 | 12 | typedef struct { 13 | int profileId; 14 | u32 publicip; 15 | u32 localIp; 16 | u16 publicport; 17 | u16 localPort; 18 | u32 gt2Ip; 19 | u16 gt2Port; 20 | 21 | u8 aid; 22 | u8 hasPrivateAddress; 23 | int nnTryCount; 24 | // 4 bytes padding 25 | 26 | s64 nextMeshMakeTryTick; 27 | DWCConnectionUserData connectionUserData; 28 | u32 pad; 29 | } DWCNodeInfo; 30 | 31 | typedef struct { 32 | int nodeCount; 33 | u32 pad; 34 | DWCNodeInfo nodeInfos[32]; 35 | } DWCNodeInfoList; 36 | 37 | DWCNodeInfo* DWCi_NodeInfoList_GetServerNodeInfo(); 38 | DWCNodeInfo* DWCi_NodeInfoList_GetNodeInfoForProfileId(int pid); 39 | DWCNodeInfo* DWCi_NodeInfoList_GetNodeInfoForAid(u8 aid); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /payload/dwc/dwc_report.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef enum { 8 | DWC_REPORT_NONE = BIT_FLAG(-1), 9 | DWC_REPORT_INFO = BIT_FLAG(0), 10 | DWC_REPORT_ERROR = BIT_FLAG(1), 11 | DWC_REPORT_DEBUG = BIT_FLAG(2), 12 | DWC_REPORT_WARNING = BIT_FLAG(3), 13 | DWC_REPORT_ACHECK = BIT_FLAG(4), 14 | DWC_REPORT_LOGIN = BIT_FLAG(5), 15 | DWC_REPORT_MATCH_NN = BIT_FLAG(6), 16 | DWC_REPORT_MATCH_GT2 = BIT_FLAG(7), 17 | DWC_REPORT_TRANSPORT = BIT_FLAG(8), 18 | DWC_REPORT_QR2_REQ = BIT_FLAG(9), 19 | DWC_REPORT_SB_UPDATE = BIT_FLAG(10), 20 | DWC_REPORT_SEND_INFO = BIT_FLAG(15), 21 | DWC_REPORT_RECV_INFO = BIT_FLAG(16), 22 | DWC_REPORT_UPDATE_SV = BIT_FLAG(17), 23 | DWC_REPORT_CONNECTINET = BIT_FLAG(18), 24 | DWC_REPORT_TEST = BIT_FLAG(20), 25 | DWC_REPORT_AUTH = BIT_FLAG(24), 26 | DWC_REPORT_AC = BIT_FLAG(25), 27 | DWC_REPORT_BM = BIT_FLAG(26), 28 | DWC_REPORT_UTIL = BIT_FLAG(27), 29 | DWC_REPORT_OPTION_CF = BIT_FLAG(28), 30 | DWC_REPORT_OPTION_CONNTEST = BIT_FLAG(29), 31 | DWC_REPORT_GAMESPY = BIT_FLAG(31), 32 | DWC_REPORT_ALL = 0xFFFFFFFF, 33 | } DWCReportFlag; 34 | 35 | void DWC_Printf(DWCReportFlag level, const char* fmt, ...); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | -------------------------------------------------------------------------------- /payload/dwc/dwc_transport.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void DWCi_ResetLastSomeDataRecvTimeByAid(u8 aid); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | -------------------------------------------------------------------------------- /payload/egg/core/eggAllocator.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace EGG { 5 | 6 | class Heap; 7 | 8 | class Allocator : public MEMAllocator { 9 | public: 10 | virtual ~Allocator(); 11 | virtual void* alloc(u32 size); 12 | virtual void free(void* buffer); 13 | 14 | Heap* heap; 15 | s32 alignment; 16 | }; 17 | 18 | } // namespace EGG 19 | -------------------------------------------------------------------------------- /payload/egg/core/eggDecomp.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace EGG { 4 | namespace Decomp { 5 | 6 | s32 getExpandSize(const void* src); 7 | s32 decodeSZS(const void* src, void* dest); 8 | 9 | } // namespace Decomp 10 | } // namespace EGG 11 | -------------------------------------------------------------------------------- /payload/egg/core/eggDisposer.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace EGG { 5 | 6 | // Forward declaration 7 | class Heap; 8 | 9 | class Disposer { 10 | public: 11 | virtual ~Disposer(); 12 | Heap* mContainHeap; 13 | nw4r::ut::Link mLink; 14 | }; 15 | size_assert(Disposer, 0x10); 16 | 17 | } // namespace EGG 18 | -------------------------------------------------------------------------------- /payload/egg/core/eggExpHeap.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace EGG { 4 | 5 | class ExpHeap : public Heap { 6 | public: 7 | 8 | struct GroupSizeRecord { 9 | u32 entries[256]; 10 | }; 11 | 12 | virtual ~ExpHeap(); 13 | virtual int getHeapKind(); 14 | virtual void initAllocator(Allocator* allocator, s32 alignment); 15 | virtual void* alloc(size_t size, s32 alignment); 16 | virtual void free(void* buffer); 17 | virtual void destroy(); 18 | virtual u32 resizeForMBlock(void* buffer, u32 newSize); 19 | virtual u32 getAllocatableSize(s32 alignment); 20 | virtual u32 adjust(); 21 | }; 22 | size_assert(ExpHeap, sizeof(Heap)); 23 | 24 | } // namespace EGG 25 | -------------------------------------------------------------------------------- /payload/egg/core/eggHeap.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace EGG { 8 | 9 | class Heap : public Disposer { 10 | public: 11 | virtual ~Heap(); 12 | virtual int getKind() = 0; 13 | virtual void initAllocator(Allocator* allocator, s32 alignment) = 0; 14 | virtual void* alloc(size_t size, s32 alignment) = 0; 15 | virtual void free(void* buffer) = 0; 16 | virtual void destroy() = 0; 17 | virtual u32 resizeForMBlock(void* buffer, u32 newSize) = 0; 18 | virtual u32 getAllocatableSize(s32 alignment) = 0; 19 | 20 | MEMiHeapHead* mHeapHandle; 21 | void* mParentBlock; 22 | Heap* mParentHeap; 23 | u16 mFlag; 24 | // 2 bytes padding 25 | 26 | nw4r::ut::Link mLink; 27 | nw4r::ut::List mChildren; 28 | const char* mName; 29 | 30 | static void* alloc(size_t size, int align, Heap* heap); 31 | static void free(void* buffer, Heap* heap); 32 | }; 33 | size_assert(Heap, 0x38); 34 | 35 | } // namespace EGG 36 | -------------------------------------------------------------------------------- /payload/egg/core/eggSceneManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace EGG { 4 | 5 | class ColorFader; 6 | class Scene; 7 | 8 | class SceneManager { 9 | public: 10 | void* vtable; 11 | void* creator; 12 | u32 _8; 13 | 14 | Scene* currentScene; 15 | SceneManager* parent; 16 | int nextSceneId; 17 | int _18, _1C; 18 | 19 | int transitionStatus; 20 | ColorFader* currentFader; 21 | u32 useMem2; 22 | }; 23 | size_assert(SceneManager, 0x2C); 24 | 25 | } // namespace EGG 26 | -------------------------------------------------------------------------------- /payload/egg/core/eggTaskThread.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace EGG { 4 | 5 | class TaskThread { 6 | public: 7 | bool request(Func func, s32 arg0, s32 arg1); 8 | }; 9 | 10 | } // namespace EGG 11 | -------------------------------------------------------------------------------- /payload/game/gfx/AnmHolder.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class AnmHolder { 4 | public: 5 | virtual float GetFrameCount(); 6 | virtual float GetFrame() const; 7 | virtual void SetFrame(float frame); 8 | virtual void UpdateRateAndSetFrame(float frame); 9 | virtual float GetUpdateRate() const; 10 | virtual void SetUpdateRate(float rate); 11 | virtual bool IsLooped(); 12 | 13 | u8 unk[0x1C-0x4]; 14 | }; 15 | size_assert(AnmHolder, 0x1C); 16 | -------------------------------------------------------------------------------- /payload/game/host_system/ParameterFile.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class ParameterFile { 6 | public: 7 | virtual ~ParameterFile(); 8 | virtual void read(EGG::Heap* heap); 9 | 10 | s32 vf_10(); 11 | virtual void vf_14(); 12 | virtual void vf_18(); 13 | virtual void vf_1c(); 14 | 15 | nw4r::ut::List strings; 16 | u32 totalAllocated; 17 | const char* path; 18 | u32 _18; 19 | }; 20 | size_assert(ParameterFile, 0x1C); 21 | -------------------------------------------------------------------------------- /payload/game/item/ItemObj.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | ////////////////////////////// 4 | // Item Object Momentum Fix // 5 | ////////////////////////////// 6 | 7 | // Ensure stationary items hitting each other have zero momentum 8 | // Credits: MrBean35000vr 9 | kmCallDefAsm(0x807A1914) { 10 | nofralloc 11 | 12 | // Ensure the float vector in the stack is zero-initialized 13 | li r31, 0 14 | stw r31, 0x44(r1) 15 | stw r31, 0x48(r1) 16 | stw r31, 0x4C(r1) 17 | 18 | // Original instruction 19 | mr r31, r6 20 | blr 21 | } 22 | -------------------------------------------------------------------------------- /payload/game/kart/KartMove.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | ///////////////////////////// 5 | // Invalid KMP Point Fixes // 6 | ///////////////////////////// 7 | 8 | // Restore original item point behaviour to prevent lag in Battle Mode 9 | kmCallDefCpp(0x805845D8, const MapdataItemPoint*, CourseMap* self, u32 id) { 10 | 11 | // Get item point 12 | const MapdataItemPoint* point = self->getItemPoint(id); 13 | 14 | // If the function returned the dummy point, restore original behaviour and return null 15 | if (point == CourseMap::getDummyItemPoint()) 16 | return nullptr; 17 | 18 | return point; 19 | } 20 | -------------------------------------------------------------------------------- /payload/game/kart/KartNetReceiver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /////////////////////////////// 6 | // Online Halfpipe Trick Fix // 7 | /////////////////////////////// 8 | 9 | // KartNetReceiver::calc() patch 10 | // Introduce a timer to prevent other online players from getting stuck in the halfpipe state 11 | // Credits: MrBean35000vr 12 | kmCallDefCpp(0x80589ACC, u8, KartNetReceiver* self) { 13 | 14 | // If the halfpipe bit is set, update the timer 15 | KartState* state = self->pointers->kartState; 16 | if (state->bitfield1 & KartState::OVER_ZIPPER) { 17 | 18 | // If the timer is zero, initialize it 19 | if (self->halfpipeTimer == 0) 20 | self->halfpipeTimer = 210 + 1; 21 | 22 | // Update it 23 | self->halfpipeTimer--; 24 | 25 | // If it reaches zero, toggle the halfpipe bit 26 | if (self->halfpipeTimer == 0) 27 | state->bitfield1 &= ~KartState::OVER_ZIPPER; 28 | 29 | // If it's not set, reset the timer in case the halfpipe state lasted less than the timer 30 | } else 31 | self->halfpipeTimer = 0; 32 | 33 | // Original call 34 | return self->getPlayerIdx(); 35 | } 36 | -------------------------------------------------------------------------------- /payload/game/kart/KartNetReceiver.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class KartNetReceiver : public KartObjectProxy { 5 | public: 6 | virtual ~KartNetReceiver(); 7 | 8 | u8 unk[0x62 - 0x10]; 9 | u16 halfpipeTimer; // custom field, previously padding 10 | u8 unk2[0xB4 - 0x64]; 11 | }; 12 | size_assert(KartNetReceiver, 0xB4); 13 | -------------------------------------------------------------------------------- /payload/game/kart/KartObjectManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class KartObjectManager { 4 | public: 5 | static void endRace(u8 playerIdx); 6 | }; 7 | -------------------------------------------------------------------------------- /payload/game/kart/KartObjectProxy.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class KartObjectProxy { 7 | public: 8 | KartPointers* pointers; 9 | nw4r::ut::Link linkList; 10 | 11 | u8 getPlayerIdx(); 12 | VehiclePhysics* getVehiclePhysics(); 13 | VEC3* getPlayerPosition(); 14 | 15 | void setOobCamera(); 16 | 17 | void FUN_80591050(int, bool, bool); 18 | }; 19 | -------------------------------------------------------------------------------- /payload/game/kart/KartParam.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /////////////////////// 6 | // Wiimmfi Telemetry // 7 | /////////////////////// 8 | 9 | // KartParam::Init() patch 10 | // Report Common.szs subfile hashes for potential cheating 11 | // Credits: Wiimmfi 12 | kmBranchDefCpp(0x80591B70, NULL, void) { 13 | if (RaceGlobals::isOnlineRace) 14 | Wiimmfi::Reporting::ReportCommonSubfiles(); 15 | } 16 | -------------------------------------------------------------------------------- /payload/game/kart/KartPointers.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class KartSettings; 4 | class KartState; 5 | class KartBody; 6 | class KartSuspension; 7 | class KartTire; 8 | class PlayerModel; 9 | class KartSub; 10 | class PlayerSound; 11 | class KartMove; 12 | class KartAction; 13 | class KartCollide; 14 | class KartEnemy; 15 | class RacedataFactory; 16 | class KartNetReceiver; 17 | class BoxColUnit; 18 | class KartBlink; 19 | class KartKiller; 20 | class VehiclePhysics; 21 | 22 | class KartPointers { 23 | public: 24 | 25 | KartSettings* kartSettings; 26 | KartState* kartState; 27 | KartBody* kartBody; 28 | KartSuspension** kartSuspensions; 29 | KartTire** kartTires; 30 | PlayerModel* playerModel; 31 | KartSub* kartSub; 32 | PlayerSound* playerSound; 33 | void* kartShadowMaybe; 34 | void* kartCamera; 35 | KartMove* kartMove; 36 | KartAction* kartAction; 37 | KartCollide* kartCollide; 38 | void* _34; 39 | KartEnemy* kartEnemy; 40 | RacedataFactory* racedataFactory; 41 | KartNetReceiver* kartNetReceiver; 42 | void* _44; 43 | void* _48; 44 | BoxColUnit* entity; 45 | void* _50; 46 | void* _54; 47 | KartBlink* kartBlink; 48 | void* _5C; 49 | KartKiller* kartKiller; 50 | }; 51 | -------------------------------------------------------------------------------- /payload/game/kart/KartState.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class KartState { 6 | public: 7 | 8 | enum Bitfield0 { 9 | ACCELERATE = BIT_FLAG(0), 10 | BRAKE = BIT_FLAG(1), 11 | DRIFT_INPUT = BIT_FLAG(2), 12 | DRIFT_MANUAL = BIT_FLAG(3), 13 | BEFORE_RESPAWN = BIT_FLAG(4), 14 | WALL_3_COLLISION = BIT_FLAG(5), 15 | WALL_COLLISION = BIT_FLAG(6), 16 | HOP_START = BIT_FLAG(7), 17 | ACCELERATE_START = BIT_FLAG(8), 18 | GROUND_START = BIT_FLAG(9), 19 | VEHICLE_BODY_FLOOR_COLLISION = BIT_FLAG(10), 20 | ANY_WHEEL_COLLISION = BIT_FLAG(11), 21 | ALL_WHEELS_COLLISION = BIT_FLAG(12), 22 | STICK_LEFT = BIT_FLAG(13), 23 | AIRTIME_OVER_20 = BIT_FLAG(15), 24 | STICKY_ROAD = BIT_FLAG(16), 25 | GROUND = BIT_FLAG(18), 26 | HOP = BIT_FLAG(19), 27 | BOOST = BIT_FLAG(20), 28 | AIR_START = BIT_FLAG(23), 29 | STICK_RIGHT = BIT_FLAG(24), 30 | SOMETHING_EXPLOSION = BIT_FLAG(25), 31 | MUSHROOM_BOOST = BIT_FLAG(26), 32 | SLIPDRIFT_CHARGE = BIT_FLAG(27), 33 | DRIFT_AUTO = BIT_FLAG(28), 34 | WHEELIE = BIT_FLAG(29), 35 | JUMP_PAD = BIT_FLAG(30), 36 | RAMP_BOOST = BIT_FLAG(31), 37 | }; 38 | 39 | enum Bitfield1 { 40 | HIT_ITEM_OR_OBJ = BIT_FLAG(0), 41 | TRIGGER_RESPAWN = BIT_FLAG(1), 42 | CANNON_START = BIT_FLAG(3), 43 | IN_CANNON = BIT_FLAG(4), 44 | TRICK_START = BIT_FLAG(5), 45 | IN_A_TRICK = BIT_FLAG(6), 46 | BOOST_OFFROAD_INVINCIBILITY = BIT_FLAG(7), 47 | ZIPPER_COLLISION = BIT_FLAG(9), 48 | OVER_ZIPPER = BIT_FLAG(10), 49 | MUSHROOM_COLLISION = BIT_FLAG(11), 50 | ZIPPER_BOOST = BIT_FLAG(13), 51 | ZIPPER_TRICK = BIT_FLAG(15), 52 | MT_BOOST = BIT_FLAG(20), 53 | HAS_TRICK_ROT = BIT_FLAG(22), 54 | TRICKABLE = BIT_FLAG(30), 55 | IN_A_STAR = BIT_FLAG(31), 56 | }; 57 | 58 | enum Bitfield2 { 59 | CHARGING_A_SLIPSTREAM = BIT_FLAG(0), 60 | IN_A_SLIPSTREAM = BIT_FLAG(1), 61 | SOMETHING_WHEELIE_BUMP = BIT_FLAG(2), 62 | WHEELIE_ROT = BIT_FLAG(4), 63 | UNK_20 = BIT_FLAG(5), 64 | SHOCKED = BIT_FLAG(7), 65 | UNK_100 = BIT_FLAG(8), 66 | IN_RESPAWN = BIT_FLAG(13), 67 | AFTER_RESPAWN = BIT_FLAG(14), 68 | IN_A_MEGA = BIT_FLAG(15), 69 | CRUSHED = BIT_FLAG(16), 70 | HAS_STOPPED_B2 = BIT_FLAG(18), 71 | HAS_VANISHED = BIT_FLAG(19), 72 | HAS_JUMP_PAD_DIR = BIT_FLAG(22), 73 | IN_A_BULLET = BIT_FLAG(27), 74 | INK_APPLIED = BIT_FLAG(28), 75 | IN_A_TC = BIT_FLAG(29), 76 | }; 77 | 78 | enum Bitfield3 { 79 | SOMETHING_WALL_COLLISION = BIT_FLAG(3), 80 | HWG = BIT_FLAG(5), 81 | UNK_40 = BIT_FLAG(6), 82 | CHARGE_START_BOOST = BIT_FLAG(8), 83 | }; 84 | 85 | enum Bitfield4 { 86 | CPU = BIT_FLAG(0), 87 | LOCAL = BIT_FLAG(1), 88 | ONLINE_LOCAL = BIT_FLAG(2), 89 | ONLINE_REMOTE = BIT_FLAG(3), 90 | AUTOMATIC_DRIFT = BIT_FLAG(4), 91 | GHOST = BIT_FLAG(6), 92 | BATTLE_RESPAWN = BIT_FLAG(7), 93 | HAS_STOPPED_B4 = BIT_FLAG(12), 94 | BEFORE_BATTLE_RESPAWN = BIT_FLAG(17), 95 | }; 96 | 97 | virtual ~KartState(); 98 | 99 | void handleStartBoost(); 100 | 101 | u32 bitfield0; 102 | u32 bitfield1; 103 | u32 bitfield2; 104 | u32 bitfield3; 105 | u32 bitfield4; 106 | 107 | KartObjectProxy* mpProxy; 108 | 109 | u32 airtime; 110 | u32 _20; 111 | 112 | float _24; 113 | VEC3 _28; 114 | VEC3 _34; 115 | VEC3 _40; 116 | VEC3 _4C; 117 | 118 | float _58; 119 | float _5C; 120 | VEC3 _60; 121 | 122 | s32 hwgTimer; 123 | s32 _70; 124 | 125 | s32 boostRampType; 126 | u32 jumpPadType; 127 | float _7C; 128 | 129 | u32 cnptId; 130 | s16 _84; 131 | s16 _86; 132 | 133 | float stickX; 134 | float stickY; 135 | 136 | s32 oobWipeState; 137 | s16 oobWipeFrame; 138 | // 2 bytes padding 139 | 140 | float _98; 141 | float startBoostCharge; 142 | s32 startBoostIdx; 143 | s16 _A4; 144 | 145 | s16 trickableTimer; 146 | 147 | VEC3 _A8; 148 | VEC3 _B4; 149 | }; 150 | -------------------------------------------------------------------------------- /payload/game/net/RKNetController.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | ///////////////// 19 | // Fast NATNEG // 20 | ///////////////// 21 | 22 | // RKNetController::mainNetworkLoop() patch 23 | // Update NATNEG 24 | // Credits: Wiimmfi 25 | // Q: Can we move this to the main Wiimmfi network loop? 26 | kmCallDefCpp(0x80657990, void, RKNetController* self) { 27 | 28 | // Original call 29 | self->updateSubsAndVr(); 30 | 31 | // Update Wiimmfi NATNEG 32 | // Since we're in a matching state, force the value to 0 33 | Wiimmfi::Natneg::CalcTimers(false); 34 | } 35 | 36 | ///////////// 37 | // RCE Fix // 38 | ///////////// 39 | 40 | // RKNet_UserRecvCallback() patch 41 | // Validate incoming player data to prevent remote code execution exploits 42 | // Credits: WiiLink24, Wiimmfi 43 | kmBranchDefCpp(0x80658610, NULL, void, RKNetController* self, u32 aid, RKNetRACEPacketHeader* data, u32 dataLength) { 44 | 45 | // Bail if the packet doesn't even include a full header 46 | if (dataLength < sizeof(RKNetRACEPacketHeader)) 47 | return; 48 | 49 | // Verify the checksum 50 | // The game already does this later, but we shouldn't disconnect a player because a packet got corrupted 51 | u32 savedChecksum = data->checksum; 52 | data->checksum = 0; 53 | u32 realChecksum = NETCalcCRC32(data, dataLength); 54 | data->checksum = savedChecksum; 55 | if (realChecksum != savedChecksum) { 56 | DEBUG_REPORT("[RKNET] Detected corrupted packet from aid %d\n", aid) 57 | return; 58 | } 59 | 60 | // If the packet is valid, process it 61 | // Else kick the aid who sent it 62 | if (Wiimmfi::Security::ValidateRACEPacket(aid, data, dataLength)) 63 | self->processRacePacket(aid, data, dataLength); 64 | else { 65 | nw4r::ut::AutoInterruptLock lock; 66 | DEBUG_REPORT("[RKNET] Detected malicious packet from aid %d\n", aid) 67 | 68 | // Do not kick players if we're not host 69 | if (self->isPlayerHost()) 70 | Wiimmfi::Kick::ScheduleForAID(aid); 71 | 72 | // Warn the user if possible 73 | FriendRoomJoinPage* page = FriendRoomJoinPage::getPage(); 74 | if (page) page->forceConnectionError(); 75 | } 76 | } 77 | 78 | ///////////////////////////////// 79 | // Wiimmfi Telemetry / Various // 80 | ///////////////////////////////// 81 | 82 | // RKNetController::mainNetworkLoop() patch 83 | // Main Wiimmfi update function 84 | // Credits: Wiimmfi 85 | kmCallDefCpp(0x806579B0, void) { 86 | 87 | // Only run the tasks if we are online 88 | if (stpMatchCnt) { 89 | nw4r::ut::AutoInterruptLock lock; 90 | Wiimmfi::Kick::CalcKick(); 91 | Wiimmfi::Reporting::ReportMatchStateChange(); 92 | Wiimmfi::Natneg::StopNATNEGAfterTime(); 93 | Wiimmfi::Reporting::ReportSuspendUpdate(); 94 | Wiimmfi::Reporting::ReportAIDPIDMap(); 95 | Wiimmfi::Reporting::ReportHostSlotChange(); 96 | Wiimmfi::Reporting::ReportRegionChange(); 97 | 98 | // Only run race tasks if we are in an online race 99 | if (RaceGlobals::isOnlineRace && RaceManager::instance != nullptr) { 100 | Wiimmfi::Reporting::ReportFrameCount(RaceManager::instance->frameCounter); 101 | Wiimmfi::Delay::Calc(RaceManager::instance->frameCounter); 102 | } 103 | 104 | // Only run SELECT-tasks if the handler exists 105 | if (RKNetSELECTHandler::instance) 106 | Wiimmfi::Reporting::ReportSELECTInfo(); 107 | } 108 | 109 | // Original call 110 | VIWaitForRetrace(); 111 | } 112 | -------------------------------------------------------------------------------- /payload/game/net/RKNetController.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class RKNetController { 13 | public: 14 | 15 | struct Sub { 16 | s64 _0; // A timer 17 | u32 connectionCount; 18 | u32 playerCount; 19 | u32 availableAids; // Bitfield 20 | u32 directConnectedAids; // Bitfield 21 | u32 groupId; 22 | u32 friendToJoin; 23 | u8 localPlayerCount; 24 | u8 myAid; 25 | u8 hostAid; 26 | DWCConnectionUserData connectionUserDatas[12]; // 1 per aid 27 | bool matchingSuspended; 28 | // 4 bytes padding 29 | }; 30 | 31 | enum ConnectionState { 32 | STATE_SHUTDOWN, 33 | STATE_UNK_1, 34 | STATE_LOGIN_START, 35 | STATE_LOGIN_AUTHORISED, 36 | STATE_LOGIN_FRIENDS_SYNCED, 37 | STATE_UNK_5, 38 | STATE_MATCHING, 39 | STATE_FAILED, 40 | STATE_ERROR, 41 | }; 42 | 43 | enum SearchType { 44 | SEARCH_NONE, 45 | SEARCH_VS_WW, 46 | SEARCH_VS_REG, 47 | SEARCH_BT_WW, 48 | SEARCH_BT_REG, 49 | }; 50 | 51 | Sub* getCurrentSub() { 52 | return &subs[currentSub]; 53 | } 54 | 55 | bool isPlayerHost() { 56 | Sub* sub = getCurrentSub(); 57 | return sub->myAid == sub->hostAid; 58 | } 59 | 60 | virtual ~RKNetController(); 61 | 62 | void processRacePacket(u32 aid, void* data, u32 dataLength); 63 | void updateSubsAndVr(); 64 | WifiDisconnectInfo getWifiDisconnectInfo(); 65 | 66 | RKNetMutex mutex; 67 | EGG::ExpHeap* heap; 68 | EGG::TaskThread* taskThread; 69 | 70 | ConnectionState connState; 71 | WifiDisconnectInfo disconnectInfo; 72 | // 4 bytes padding 73 | 74 | Sub subs[2]; 75 | SearchType searchType; 76 | int _EC; // Something with suspend 77 | 78 | RKNetRACEPacketHolder* splitSendRACEPackets[2][12]; // Double buffered, 1 per aid 79 | RKNetRACEPacketHolder* splitRecvRACEPackets[2][12]; // Double buffered, 1 per aid 80 | RKNetPacketHolder* fullSendRACEPackets[12]; // 1 per aid 81 | 82 | s64 lastRACESendTimes[12]; // Time since a packet was last sent to each aid 83 | s64 lastRACERecvTimes[12]; // Time since a packet was last received from each aid 84 | s64 RACESendTimesTaken[12]; // Time between the last two packets sent to each aid 85 | s64 RACERecvTimesTaken[12]; // Time between the last two packets received from each aid 86 | u8 lastRACESendAid; // The last aid a packet was sent to 87 | u8 fullRecvRACEPackets[12][736]; // 1 per aid 88 | // 3 bytes padding 89 | 90 | RKNetStatusData ownStatus; 91 | RKNetFriend friendStatus[30]; 92 | bool friendsListChanged; 93 | bool shutdownScheduled; 94 | bool friendStatusUpdateScheduled; 95 | bool _2757; // Something with disc errors 96 | 97 | bool profanityCheckFailed; 98 | // 3 bytes padding 99 | int badWordsNum; 100 | 101 | // Used for matchmaking 102 | int _2760; // Pulled from savegame, looks like some sort of winrate? 103 | int vr; 104 | int br; 105 | 106 | int lastSendBufferUsed[12]; // 1 per aid 107 | int lastRecvBufferUsed[12][RKNetRACEPacketHeader::SECTION_COUNT]; // 1 per packet section per aid 108 | int currentSub; 109 | u8 aidPidMap[12]; // Index is player id, value is aid 110 | u32 disconnectedAids; // Bitfield 111 | u32 disconnectedPlayerIds; // Bitfield 112 | 113 | // Used for matchmaking 114 | u16 maxVrGaps[10]; 115 | u16 maxBrGaps[10]; 116 | // 4 bytes padding 117 | 118 | s64 _2960[12]; // More timers 119 | u32 _29C0; // Another timer 120 | // 4 bytes padding 121 | 122 | static RKNetController* instance; 123 | static u32 packetBufferSizes[RKNetRACEPacketHeader::SECTION_COUNT]; 124 | }; 125 | size_assert(RKNetController, 0x29C8); 126 | -------------------------------------------------------------------------------- /payload/game/net/RKNetFriend.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct RKNetFriend { 5 | RKNetStatusData statusData; 6 | u8 status; // see DWCFriendStatus 7 | u8 _9; // bit flags, 4 if room open, 1 if online 8 | u8 _A; 9 | u8 _B; 10 | }; 11 | size_assert(RKNetFriend, 0xC); 12 | -------------------------------------------------------------------------------- /payload/game/net/RKNetMutex.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class RKNetMutex { 5 | public: 6 | virtual ~RKNetMutex(); 7 | OSMutex mutex; 8 | }; 9 | size_assert(RKNetMutex, 0x1C); 10 | -------------------------------------------------------------------------------- /payload/game/net/RKNetPacketCreator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | ////////////////// 4 | // Game Lag Fix // 5 | ////////////////// 6 | 7 | // RKNetPacketCreator::updateAsRacer() patch 8 | // Disable processing of lag frames to fix matrix slowdown and delays caused by slower Dolphin players 9 | // Credits: Wiimmfi 10 | kmWrite32(0x80654400, 0x60000000); 11 | -------------------------------------------------------------------------------- /payload/game/net/RKNetPacketHolder.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class RKNetPacketHolder { 4 | public: 5 | void* buffer; 6 | u32 bufferSize; 7 | u32 currentPacketSize; 8 | }; 9 | size_assert(RKNetPacketHolder, 0xC); 10 | 11 | class RKNetRACEPacketHolder { 12 | public: 13 | RKNetPacketHolder* header; 14 | RKNetPacketHolder* raceHeader1; 15 | RKNetPacketHolder* raceHeader2; 16 | RKNetPacketHolder* select; 17 | RKNetPacketHolder* racedata; 18 | RKNetPacketHolder* user; 19 | RKNetPacketHolder* item; 20 | RKNetPacketHolder* event; 21 | }; 22 | size_assert(RKNetRACEPacketHolder, 0x20); 23 | -------------------------------------------------------------------------------- /payload/game/net/RKNetRoomHandler.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class RKNetROOMHandler { 5 | public: 6 | enum ROOMRole { 7 | ROOM_HOST, 8 | ROOM_GUEST, 9 | }; 10 | 11 | void SetAllSendPackets(u32 packet); 12 | 13 | bool statusDataSet; 14 | ROOMRole role; 15 | RKNetROOMPacket sendPackets[12]; 16 | RKNetROOMPacket recvPackets[12]; 17 | u8 lastSendAid; 18 | s64 lastSendTimestamp; 19 | s64 _78; // unused 20 | 21 | static RKNetROOMHandler* instance; 22 | }; 23 | size_assert(RKNetROOMHandler, 0x80); 24 | -------------------------------------------------------------------------------- /payload/game/net/RKNetSelectHandler.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | ////////////////////////////////// 5 | // Online Room Stall Prevention // 6 | ////////////////////////////////// 7 | 8 | // RKNetSELECTHandler::calc() patch 9 | // Update the timer every frame and kick if necessary 10 | // Credits: Wiimmfi 11 | kmCallDefCpp(0x80660330, bool) { 12 | Wiimmfi::RoomStall::Update(); 13 | return true; // Not calling the original function here because the result would always be true 14 | } 15 | 16 | // RKNetSELECTHandler::getStaticInstance() patch 17 | // Initialize the timer 18 | // Credits: Wiimmfi 19 | kmBranchDefCpp(0x8065FF5C, NULL, void) { 20 | Wiimmfi::RoomStall::Init(); 21 | } 22 | -------------------------------------------------------------------------------- /payload/game/net/RKNetSelectHandler.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class RKNetSELECTHandler { 5 | public: 6 | enum Mode { 7 | MODE_NONE, 8 | MODE_PUBLIC_VS, 9 | MODE_PUBLIC_BATTLE, 10 | MODE_PRIVATE_VS, 11 | MODE_PRIVATE_BATTLE, 12 | }; 13 | 14 | int mode; 15 | // 4 bytes padding 16 | 17 | RKNetSELECTPacket sendPacket; 18 | RKNetSELECTPacket recvPackets[12]; 19 | u8 lastSentToAid; 20 | // 7 bytes padding 21 | 22 | s64 lastSentTime; 23 | s64 lastRecvTimes[12]; 24 | s64 lastRecvDelays[12]; 25 | u32 timelyRecvPacketCounts[12]; 26 | 27 | // Bitfields follow 28 | u32 aidsWithNewSelect; 29 | u32 aidsWithNewRH1; 30 | u32 aidsWithNewRaceSettings; 31 | u32 aidsWithVoteData; 32 | u32 aidsThatHaveVoted; 33 | // 4 bytes padding 34 | 35 | static RKNetSELECTHandler* instance; 36 | }; 37 | size_assert(RKNetSELECTHandler, 0x3F8); 38 | -------------------------------------------------------------------------------- /payload/game/net/RKNetStatusData.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | enum RKNetStatus { 4 | STATUS_INACTIVE = 0, 5 | STATUS_WAITING = 2, 6 | STATUS_ROOM_HOST = 3, 7 | STATUS_ROOM_GUEST = 4, 8 | STATUS_PUBLIC_VS = 5, 9 | STATUS_PUBLIC_BT = 8, 10 | STATUS_PRIVATE_VS_HOST = 11, 11 | STATUS_PRIVATE_VS_GUEST = 12, 12 | STATUS_PRIVATE_BT_HOST = 13, 13 | STATUS_PRIVATE_BT_GUEST = 14, 14 | }; 15 | 16 | struct RKNetStatusData { 17 | u32 groupId; 18 | u8 searchRegion; // 0xFF for Worldwides 19 | u8 status; // see enum above 20 | u8 playerCount; 21 | u8 raceNumber; 22 | }; 23 | -------------------------------------------------------------------------------- /payload/game/net/WifiDisconnectInfo.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct WifiDisconnectInfo { 4 | 5 | enum ErrorCategory { 6 | ERROR_NONE, 7 | ERROR_WITH_CODE, 8 | ERROR_OFFENSIVE_MII, 9 | ERROR_FRIEND_JOIN, 10 | ERROR_GENERIC, 11 | ERROR_UNRECOVERABLE, 12 | }; 13 | 14 | void reset(); 15 | 16 | s32 errorCategory; 17 | s32 errorCode; 18 | }; 19 | -------------------------------------------------------------------------------- /payload/game/net/packet/RKNetRacePacketHeader.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct RKNetRACEPacketHeader { 4 | 5 | enum Section { 6 | HEADER, 7 | RACEHEADER_1, 8 | RACEHEADER_2, 9 | ROOM_SELECT, 10 | RACEDATA, 11 | USER, 12 | ITEM, 13 | EVENT, 14 | SECTION_COUNT, 15 | }; 16 | 17 | u32 empty; 18 | u32 checksum; 19 | u8 sizes[SECTION_COUNT]; 20 | }; 21 | size_assert(RKNetRACEPacketHeader, 0x10); 22 | -------------------------------------------------------------------------------- /payload/game/net/packet/RKNetRoomPacket.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma pack(push, 1) 3 | 4 | struct RKNetROOMPacket { 5 | enum MessageType { 6 | MSG_NONE, 7 | MSG_ROOM_START, // param1: event type, param2: none 8 | MSG_REGISTER_FRIEND, // param1: none, param2: none 9 | MSG_JOIN, // param1: none, param2: none 10 | MSG_CHAT, // param1: message id, param2: queue position 11 | }; 12 | 13 | enum EventType { 14 | EVENT_GP, 15 | EVENT_TEAM_GP, 16 | EVENT_BALLOON_BT, 17 | EVENT_COIN_BT, 18 | }; 19 | 20 | u8 msgType; 21 | u16 param1; 22 | u8 param2; 23 | }; 24 | size_assert(RKNetROOMPacket, 0x4); 25 | 26 | union RKNetROOMPacketRaw { 27 | RKNetROOMPacketRaw(u32 data) : raw(data) {} 28 | 29 | RKNetROOMPacket packet; 30 | u32 raw; 31 | }; 32 | 33 | #pragma pack(pop) 34 | -------------------------------------------------------------------------------- /payload/game/net/packet/RKNetSelectPacket.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct RKNetSELECTPlayer { 4 | u16 prevRaceRank; 5 | u16 sumPoints; 6 | u8 character; 7 | u8 vehicle; 8 | u8 courseVote; 9 | u8 starRank; 10 | }; 11 | size_assert(RKNetSELECTPlayer, 0x8); 12 | 13 | struct RKNetSELECTPacket { 14 | 15 | enum Phase { 16 | PREPARE, 17 | VOTING, 18 | LOTTERY, 19 | }; 20 | 21 | s64 timeSender; 22 | s64 timeReceived; 23 | RKNetSELECTPlayer playerData[2]; 24 | u32 selectId; 25 | 26 | union { 27 | struct { 28 | u8 battleType; 29 | u32 teams : 24; // 0 = ??, 1 = red team, 2 = ??, 3 = ?? 30 | }; 31 | 32 | u32 raw; 33 | } battleTeamData; 34 | 35 | union { 36 | u8 playerIds[12]; 37 | u32 raw[3]; 38 | } playerIdToAid; 39 | 40 | u8 winningCourse; 41 | u8 phase; // 0 = prepare, 1 = voting, 2 = lottery 42 | u8 winningVoterAid; 43 | u8 engineClass; 44 | }; 45 | size_assert(RKNetSELECTPacket, 0x38); 46 | -------------------------------------------------------------------------------- /payload/game/obj/ObjDossun.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //////////////////// 5 | // Game Bug Fixes // 6 | //////////////////// 7 | 8 | // Prevent Thwomps from crashing the game when they are hit before they land the first time 9 | // Credits: MrBean35000vr 10 | kmCallDefCpp(0x80760A88, float, AnmHolder* anm) { 11 | 12 | // Get animation frame count, otherwise a dummy value 13 | return (anm != nullptr) ? anm->GetFrameCount() : 0.0f; 14 | } 15 | 16 | // Glue code 17 | // kmBranchDefCpp cannot be used here due to compiler optimizations 18 | kmBranch(0x80760A8C, 0x80760A98); 19 | -------------------------------------------------------------------------------- /payload/game/race/RaceGlobals.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class RaceGlobals { 4 | public: 5 | static bool isOnlineRace; 6 | }; 7 | -------------------------------------------------------------------------------- /payload/game/scene/RaceScene.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /////////////////////// 9 | // Wiimmfi Telemetry // 10 | /////////////////////// 11 | 12 | // RaceScene::createSubsystems() patch 13 | // Hash and report various course subfiles 14 | // Credits: Wiimmfi 15 | kmCallDefCpp(0x805543A4, void, CourseMap* self) { 16 | 17 | // If we're online, send the data 18 | // We cannot use the isOnline variable since it hasn't been initialized yet 19 | if (RaceConfig::instance->raceScenario.settings.isOnline()) 20 | Wiimmfi::Reporting::ReportCourseSubfiles(); 21 | 22 | // Original call 23 | self->init(); 24 | } 25 | 26 | ///////////////////// 27 | // Wiimmfi Various // 28 | ///////////////////// 29 | 30 | // RaceScene::createSubsystems() patch 31 | // Reset various values before the race begins 32 | kmBranchDefCpp(0x80554728, NULL, void) { 33 | Wiimmfi::Reporting::sTargetFrameCount = 0; 34 | Wiimmfi::Kick::sMustEndRace = false; 35 | Wiimmfi::Delay::sMatchStartTime = 0; 36 | Wiimmfi::Delay::sCumulativeDelay = 0; 37 | Wiimmfi::Delay::sCurrentDelay = 0; 38 | } 39 | -------------------------------------------------------------------------------- /payload/game/system/Competition.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct CharacterVehicleChoice { 4 | s8 characterId; 5 | s8 vehicleId; 6 | }; 7 | size_assert(CharacterVehicleChoice, 0x2); 8 | 9 | struct CompetitionSettings { 10 | u16 missionFileId; 11 | u16 missionType; 12 | u8 courseId; 13 | u8 characterId; 14 | u8 vehicleId; 15 | u8 engineClass; 16 | u8 _8[0x24]; 17 | 18 | u16 timeLimit; 19 | u8 _2E; 20 | u8 controllerRestriction; 21 | u32 scores[6]; 22 | 23 | u16 cameraAngle; 24 | u16 minimapObject; 25 | u16 _4C; 26 | u16 _4E; 27 | u16 cannonFlag; 28 | u8 _52[6]; 29 | u16 cpuCount; 30 | CharacterVehicleChoice cpuCombos[11]; 31 | }; 32 | size_assert(CompetitionSettings, 0x70); 33 | -------------------------------------------------------------------------------- /payload/game/system/CourseMap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | ///////////////////////////// 5 | // Invalid KMP Point Fixes // 6 | ///////////////////////////// 7 | 8 | // Prevent invalid item points from crashing the game 9 | const MapdataItemPoint* CourseMap::getDummyItemPoint() { 10 | static const MapdataItemPoint::SData dummyPointData = {{0.0f, 0.0f, 0.0f}, 1.0f, {0, 0}}; 11 | static const MapdataItemPoint dummyPoint = {(MapdataItemPoint::SData*)&dummyPointData }; 12 | 13 | return &dummyPoint; 14 | } 15 | 16 | // CourseMap::getItemPoint() override 17 | // Prevent invalid item points from crashing the game 18 | kmBranchDefCpp(0x80514D3C, NULL, const MapdataItemPoint*, CourseMap* self, u32 id) { 19 | if (!self->mpItemPoint || id >= self->mpItemPoint->numEntries) 20 | return CourseMap::getDummyItemPoint(); 21 | 22 | return self->mpItemPoint->entries[id]; 23 | } 24 | 25 | // Prevent invalid cannon points from crashing the game 26 | const MapdataCannonPoint* CourseMap::getDummyCannonPoint() { 27 | static const MapdataCannonPoint::SData dummyPointData = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 0, 0}; 28 | static const MapdataCannonPoint dummyPoint = {(MapdataCannonPoint::SData*)&dummyPointData}; 29 | 30 | return &dummyPoint; 31 | } 32 | 33 | // CourseMap::getCannonPoint() override 34 | // Prevent invalid cannon points from crashing the game 35 | kmBranchDefCpp(0x80518AE0, NULL, const MapdataCannonPoint*, CourseMap* self, u32 id) { 36 | if (!self->mpCannonPoint || id >= self->mpCannonPoint->numEntries) 37 | return CourseMap::getDummyCannonPoint(); 38 | 39 | return self->mpCannonPoint->entries[id]; 40 | } 41 | -------------------------------------------------------------------------------- /payload/game/system/DvdArchive.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /////////////////////// 11 | // Wiimmfi Telemetry // 12 | /////////////////////// 13 | 14 | // DvdArchive::decompress() override 15 | // Hash track file, store the hash and report it to Wiimmfi if necessary 16 | // Credits: Wiimmfi 17 | kmBranchDefCpp(0x80519508, NULL, void, DvdArchive* self, const char* path, EGG::Heap* heap) { 18 | 19 | // Get decompressed size 20 | u32 decompressedSize = EGG::Decomp::getExpandSize(self->fileBuffer); 21 | 22 | // Allocate the buffer and decode the file in it 23 | void* buffer = heap->alloc(decompressedSize, 0x20); 24 | EGG::Decomp::decodeSZS(self->fileBuffer, buffer); 25 | 26 | // Store info and invalidate cache 27 | self->archiveSize = decompressedSize; 28 | self->archiveBuffer = buffer; 29 | self->archiveHeap = heap; 30 | DCStoreRange(buffer, decompressedSize); 31 | self->state = DvdArchive::DECOMPRESSED; 32 | 33 | // Check if it's a track file, if not bail 34 | // The path will be null if the course is being loaded from the cache, so check for that as well 35 | if (path && !strstartw(path, "Race/Course/")) 36 | return; 37 | 38 | // Check if we're online, if not bail 39 | // We cannot use the isOnline variable since it hasn't been initialized yet 40 | if (!RaceConfig::instance->raceScenario.settings.isOnline()) 41 | return; 42 | 43 | // We're online, send the track hash to the server 44 | u32 hash[5]; 45 | NETCalcSHA1(hash, buffer, decompressedSize); 46 | Wiimmfi::Reporting::ReportTrackHash(hash, RaceConfig::instance->raceScenario.settings.courseId); 47 | } 48 | -------------------------------------------------------------------------------- /payload/game/system/DvdArchive.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class DvdArchive { 5 | public: 6 | 7 | enum State { 8 | CLEARED, 9 | UNK_1, 10 | RIPPED, 11 | DECOMPRESSED, 12 | MOUNTED, 13 | UNK_5, 14 | }; 15 | 16 | virtual ~DvdArchive(); 17 | 18 | void* getFile(const char* path, u32* size); 19 | 20 | void* archive; // actually EGG::Archive 21 | void* archiveBuffer; 22 | u32 archiveSize; 23 | EGG::Heap* archiveHeap; 24 | void* fileBuffer; 25 | u32 fileSize; 26 | EGG::Heap* fileHeap; 27 | u32 state; 28 | }; 29 | size_assert(DvdArchive, 0x24); 30 | -------------------------------------------------------------------------------- /payload/game/system/FriendList.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /////////////////////////////////// 4 | // Invalid Profile ID Antifreeze // 5 | /////////////////////////////////// 6 | 7 | // Prevent invalid profile identifiers from crashing the game 8 | // Credits: MrBean35000vr 9 | kmBranch(0x805D2EF8, 0x805D2EBC); 10 | kmBranch(0x805D2F00, 0x805D2EBC); 11 | -------------------------------------------------------------------------------- /payload/game/system/GhostFile.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #pragma pack(push, 1) 5 | struct RawGhostFile { 6 | 7 | union { 8 | u8 buffer[0x2800]; 9 | 10 | struct { 11 | u32 magic; 12 | 13 | u32 raceMinutes : 7; 14 | u32 raceSeconds : 7; 15 | u32 raceMilliseconds : 10; 16 | u32 courseId : 6; 17 | u32 _pad0 : 2; 18 | 19 | u32 vehicleId : 6; 20 | u32 characterId : 6; 21 | u32 year : 7; 22 | u32 month : 4; 23 | u32 day : 5; 24 | u32 controllerId : 4; 25 | 26 | u16 _pad1 : 4; 27 | bool isCompressed : 1; 28 | u16 _pad2 : 2; 29 | u16 type : 7; 30 | u16 driftType : 1; 31 | u16 _pad3 : 1; 32 | 33 | u16 inputsSize; 34 | u8 lapCount; 35 | 36 | struct { 37 | u32 minutes : 7; 38 | u32 seconds : 7; 39 | u32 milliseconds : 10; 40 | } lapTimes[5]; 41 | 42 | wchar_t userData[10]; 43 | u8 countryCode; 44 | u8 stateCode; 45 | u16 locationCode; 46 | u32 _38; 47 | RawMii mii; 48 | }; 49 | }; 50 | }; 51 | size_assert(RawGhostFile, 0x2800); 52 | 53 | #pragma pack(pop) 54 | -------------------------------------------------------------------------------- /payload/game/system/Mii.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class RawMii { 4 | public: 5 | u8 buffer[0x4C]; 6 | }; 7 | size_assert(RawMii, 0x4C); 8 | 9 | struct unkStruct { 10 | u8 _0; 11 | u8 _1; 12 | u8 _2; 13 | u8 _3; 14 | }; 15 | size_assert(unkStruct, 0x4); 16 | 17 | class Mii { 18 | public: 19 | virtual ~Mii(); 20 | 21 | s32 _4; 22 | u8 _8; 23 | s8 _9; 24 | s32 _C; 25 | RawMii rawMii; 26 | s32 _5C; 27 | unkStruct _60; 28 | u32 _64; 29 | u32 _68[15]; 30 | u8 _A4; 31 | u8 _A5; 32 | u8 _A6; 33 | u32 _A8; 34 | u8 _AC; 35 | u8 _AD; 36 | u8 _AE; 37 | u32 _B0; 38 | u32 _B4; 39 | }; 40 | size_assert(Mii, 0xB8); 41 | -------------------------------------------------------------------------------- /payload/game/system/MultiDvdArchive.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class MultiDvdArchive { 5 | public: 6 | enum Type { 7 | COMMON, 8 | COURSE, 9 | MENU, 10 | FONT, 11 | EARTH, 12 | MIIBODY, 13 | DRIVER, 14 | DEMO, 15 | BACKMODEL, 16 | }; 17 | 18 | enum KindFlag { 19 | SUFFIX_ONLY = BIT_FLAG(-1), 20 | FULL_NAME = BIT_FLAG(0), 21 | CACHED = BIT_FLAG(2), 22 | }; 23 | 24 | virtual ~MultiDvdArchive(); 25 | virtual void init(); 26 | 27 | bool isLoaded(); 28 | bool exists(const char* path); 29 | 30 | DvdArchive* archives; 31 | u16 archiveCount; 32 | u32* fileSizes; 33 | char** suffixes; 34 | void** fileStarts; 35 | int* kinds; 36 | 37 | static MultiDvdArchive* create(int type); 38 | }; 39 | size_assert(MultiDvdArchive, 0x1C); 40 | -------------------------------------------------------------------------------- /payload/game/system/RKSystem.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class RKSystem { 6 | public: 7 | virtual void* getVideo(); 8 | virtual EGG::Heap* getSysHeap(); 9 | virtual void* getDisplay(); 10 | virtual void* getXFBManager(); 11 | virtual void* getProcessMeter(); 12 | virtual EGG::SceneManager* getSceneManager(); 13 | virtual void* getAudioManager(); 14 | virtual void onBeginFrame(); 15 | virtual void onEndFrame(); 16 | virtual void initRenderMode(); 17 | virtual void initMemory(); 18 | virtual void run(); 19 | virtual void initSystem(); 20 | 21 | void* MEM1ArenaLo; 22 | void* MEM1ArenaHi; 23 | void* MEM2ArenaLo; 24 | void* MEM2ArenaHi; 25 | u32 memorySize; 26 | EGG::ExpHeap* EGGRootMEM1; 27 | EGG::ExpHeap* EGGRootMEM2; 28 | EGG::ExpHeap* EGGRootDebug; 29 | EGG::ExpHeap* EGGSystem; 30 | void* heapSystemThread; 31 | u32 _2C; 32 | u32 _30; 33 | u32 sysHeapSize; 34 | u32 gxFifoBufSize; 35 | void* renderMode; 36 | void* audioManager; 37 | void* video; 38 | void* xfbManager; 39 | void* asyncDisplay; 40 | void* processMeter; 41 | EGG::SceneManager* sceneManager; 42 | EGG::ExpHeap* kpadWorkHeap; 43 | u32 _5C; 44 | EGG::ExpHeap* relLinkHeap; 45 | EGG::ExpHeap* heapSystem2; 46 | u8 frameClock; 47 | u8 _69; 48 | bool drawFrame; 49 | u8 _6B; 50 | u8 _6C; 51 | u32 _70; 52 | 53 | static RKSystem instance; 54 | }; 55 | size_assert(RKSystem, 0x74); 56 | 57 | #define KAMEK_HEAP RKSystem::instance.EGGSystem 58 | -------------------------------------------------------------------------------- /payload/game/system/RaceConfig.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class RaceConfigEx { 9 | public: 10 | virtual ~RaceConfigEx(); 11 | }; 12 | size_assert(RaceConfigEx, 0x4); 13 | 14 | class RaceConfig : public RaceConfigEx, public ParameterFile { 15 | public: 16 | 17 | class Player { 18 | public: 19 | enum Type { 20 | TYPE_LOCAL, 21 | TYPE_CPU, 22 | TYPE_UNUSED, 23 | TYPE_GHOST, 24 | TYPE_ONLINE, 25 | TYPE_NONE, 26 | }; 27 | 28 | enum Team { 29 | TEAM_RED, 30 | TEAM_BLUE, 31 | TEAM_NONE, 32 | }; 33 | 34 | virtual ~Player(); 35 | 36 | int computeGPRank(); 37 | 38 | u8 _4; 39 | s8 localPlayerNum; 40 | s8 playerInputIdx; 41 | u32 vehicleId; 42 | u32 characterId; 43 | u32 playerType; 44 | Mii mii; 45 | u32 team; 46 | s32 controllerId; 47 | u32 _D4; 48 | u16 previousScore; 49 | u16 gpScore; 50 | u16 _DC; 51 | s16 gpRankScore; 52 | u8 gpRank; 53 | u8 prevFinishPos; 54 | u8 finishPos; 55 | Rating rating; 56 | s8 _EC; 57 | }; 58 | size_assert(Player, 0xF0); 59 | 60 | struct Settings { 61 | 62 | enum EngineClass { 63 | CC_50, 64 | CC_100, 65 | CC_150, 66 | CC_COUNT, 67 | }; 68 | 69 | enum GameMode { 70 | GAMEMODE_GP, 71 | GAMEMODE_VS, 72 | GAMEMODE_TT, 73 | GAMEMODE_BT, 74 | GAMEMODE_MR, 75 | GAMEMODE_GHOST_RACE, 76 | GAMEMODE_UNK_6, 77 | GAMEMODE_PRIVATE_VS, 78 | GAMEMODE_PUBLIC_VS, 79 | GAMEMODE_PUBLIC_BT, 80 | GAMEMODE_PRIVATE_BT, 81 | GAMEMODE_AWARDS, 82 | GAMEMODE_CREDITS, 83 | }; 84 | 85 | enum CameraMode { 86 | CAMERA_MODE_GAMEPLAY_NO_INTRO, 87 | CAMERA_MODE_REPLAY, 88 | CAMERA_MODE_TITLE_1P, 89 | CAMERA_MODE_TITLE_2P, 90 | CAMERA_MODE_TITLE_4P, 91 | CAMERA_MODE_GAMEPLAY_INTRO, 92 | CAMERA_MODE_LIVE_VIEW, 93 | CAMERA_MODE_GP_WIN, 94 | CAMERA_MODE_SOLO_VS_WIN, 95 | CAMERA_MODE_TEAM_VS_WIN, 96 | CAMERA_MODE_BT_WIN, 97 | CAMERA_MODE_UNK_B, 98 | CAMERA_MODE_LOSS, 99 | }; 100 | 101 | enum BattleType { 102 | BATTLE_BALLOON, 103 | BATTLE_COIN, 104 | }; 105 | 106 | enum CPUMode { 107 | CPU_EASY, 108 | CPU_NORMAL, 109 | CPU_HARD, 110 | CPU_NONE, 111 | }; 112 | 113 | enum ModeFlags { 114 | FLAG_MIRROR = BIT_FLAG(0), 115 | FLAG_TEAMS = BIT_FLAG(1), 116 | FLAG_COMPETITION = BIT_FLAG(2), 117 | }; 118 | 119 | enum ItemMode { 120 | ITEMS_BALANCED, 121 | ITEMS_FRANTIC, 122 | ITEMS_STRATEGIC, 123 | ITEMS_NONE, 124 | }; 125 | 126 | bool isBattle() const { 127 | switch (gameMode) { 128 | case GAMEMODE_BT: 129 | case GAMEMODE_PUBLIC_BT: 130 | case GAMEMODE_PRIVATE_BT: 131 | return true; 132 | default: 133 | return false; 134 | } 135 | } 136 | 137 | bool isOnline() const { 138 | switch (gameMode) { 139 | case GAMEMODE_PRIVATE_VS: 140 | case GAMEMODE_PUBLIC_VS: 141 | case GAMEMODE_PUBLIC_BT: 142 | case GAMEMODE_PRIVATE_BT: 143 | return true; 144 | default: 145 | return false; 146 | } 147 | } 148 | 149 | u32 courseId; 150 | u32 engineClass; 151 | u32 gameMode; 152 | u32 cameraMode; 153 | u32 battleType; 154 | u32 cpuMode; 155 | u32 itemMode; 156 | s8 hudPlayerIds[4]; 157 | u32 cupId; 158 | u8 raceNumber; 159 | u8 lapCount; 160 | u32 modeFlags; 161 | u32 seed1; 162 | u32 seed2; 163 | }; 164 | size_assert(Settings, 0x34); 165 | 166 | class Scenario { 167 | public: 168 | virtual ~Scenario(); 169 | 170 | u8 playerCount; 171 | u8 hudCount; 172 | u8 localPlayerCount; 173 | u8 hudCount2; 174 | Player players[12]; 175 | Settings settings; 176 | CompetitionSettings competitionSettings; 177 | RawGhostFile* ghost; 178 | }; 179 | size_assert(Scenario, 0xBF0); 180 | 181 | virtual ~RaceConfig(); 182 | 183 | Scenario raceScenario; 184 | Scenario menuScenario; 185 | Scenario awardsScenario; 186 | RawGhostFile ghosts[2]; 187 | 188 | static RaceConfig* instance; 189 | }; 190 | size_assert(RaceConfig, 0x73F0); 191 | -------------------------------------------------------------------------------- /payload/game/system/RaceManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | //////////////////////// 11 | // Ultra Shortcut Fix // 12 | //////////////////////// 13 | 14 | // RaceManager::Player::updateCheckpoint() patch 15 | // Disable ultra shortcuts in online worldwide races 16 | // Credits: Chadderz, MrBean35000vr 17 | kmHookFn bool UltraUncut(float requiredCompletion, MapdataCheckPoint* currCkpt, MapdataCheckPoint* nextCkpt) { 18 | 19 | // Check if it's a start line check point 20 | if (currCkpt->mpData->lapCheck == 0) { 21 | 22 | // If the previous key checkpoint is not 1 and the feature is enabled, always decrement the lap 23 | if (nextCkpt->prevKcpId > 1 && ModSupport::AreUltraShortcutsEnabled()) 24 | return false; 25 | 26 | // Original check 27 | for (int i = 0; i < nextCkpt->nextCount; i++) { 28 | if (currCkpt->id == nextCkpt->nextCheckPoints[i].checkpoint->id) 29 | return false; 30 | } 31 | } 32 | 33 | // Ensure at least 5% of the lap is completed 34 | return (requiredCompletion >= -0.95f); 35 | } 36 | 37 | // Glue code 38 | kmCallDefAsm(0x805350DC) { 39 | nofralloc 40 | 41 | // Push stack 42 | stwu r1, -0x10(r1) 43 | mflr r0 44 | stw r0, 0x14(r1) 45 | 46 | // Call C++ code 47 | fmr f1, f30 48 | mr r3, r28 49 | mr r4, r29 50 | bl UltraUncut 51 | 52 | // Determine the exit address based on the bool return value 53 | // Return 0 to run regular check -> returns to 80535154 54 | // Return 1 to skip the next checks -> returns to 805351DC 55 | mulli r3, r3, 0x88 56 | addi r3, r3, 0x74 57 | lwz r4, 0x14(r1) 58 | add r3, r3, r4 59 | 60 | // Pop stack and return 61 | mtlr r3 62 | addi r1, r1, 0x10 63 | blr 64 | } 65 | 66 | /////////////////////// 67 | // Wiimmfi Telemetry // 68 | /////////////////////// 69 | 70 | // RaceManager::calc() patch 71 | // Report race finish 72 | // Credits: Wiimmfi 73 | kmBranchDefCpp(0x8053369C, NULL, void) { 74 | 75 | // Check if the race is online 76 | if (!RaceGlobals::isOnlineRace) 77 | return; 78 | 79 | // Check if the race is finished 80 | u32 raceStage = RaceManager::instance->raceStage; 81 | if (raceStage != RaceManager::STAGE_FINISH_ALL) 82 | return; 83 | 84 | // Report it 85 | Wiimmfi::Reporting::ReportRaceStage(raceStage); 86 | } 87 | 88 | // RaceManager::Player::endRace() patch 89 | // Report finish times 90 | // Credits: Wiimmfi 91 | kmCallDefCpp(0x8053490C, void, u8 playerIdx) { 92 | 93 | // Check if the race is online and if so send the data 94 | if (RaceGlobals::isOnlineRace) 95 | Wiimmfi::Reporting::ReportFinishTime(playerIdx); 96 | 97 | // Original call 98 | KartObjectManager::endRace(playerIdx); 99 | } 100 | -------------------------------------------------------------------------------- /payload/game/system/RaceManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class RaceMode; 7 | 8 | class RaceManager { 9 | public: 10 | 11 | enum RaceStage { 12 | STAGE_INTRO, 13 | STAGE_COUNTDOWN, 14 | STAGE_RACE, 15 | STAGE_FINISH, 16 | STAGE_FINISH_ALL, 17 | }; 18 | 19 | class Player { 20 | public: 21 | virtual ~Player(); 22 | 23 | u8 unk[0x0A - 0x04]; 24 | u16 checkpointId; 25 | 26 | u8 unk2[0x26 - 0x0C]; 27 | u8 maxLap; 28 | 29 | u8 unk3[0x40 - 0x27]; 30 | Timer* finishTime; 31 | 32 | u8 unk4[0x54 - 0x44]; 33 | }; 34 | size_assert(Player, 0x54); 35 | 36 | virtual ~RaceManager(); 37 | 38 | Random* dynamicRandom; 39 | Random* staticRandom; 40 | Player** players; 41 | RaceMode* gameModeData; 42 | TimerManager* timerManager; 43 | u8 unk[0x20 - 0x18]; 44 | 45 | u32 frameCounter; 46 | u8 unk2[0x28 - 0x24]; 47 | 48 | u32 raceStage; 49 | u8 unk3[0x4C - 0x2C]; 50 | 51 | static RaceManager* instance; 52 | }; 53 | size_assert(RaceManager, 0x4C); 54 | -------------------------------------------------------------------------------- /payload/game/system/RaceMode.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class RaceMode { 5 | public: 6 | virtual ~RaceMode(); 7 | virtual bool canEndRace(); 8 | virtual void endRace(); 9 | virtual void calc(); 10 | virtual void calcPosition(); 11 | virtual void getJugemPoint(); 12 | virtual void init(); 13 | virtual void vf_20(); 14 | virtual void tryEndRace(); 15 | virtual void vf_28(); 16 | 17 | RaceManager* manager; 18 | }; 19 | size_assert(RaceMode, 0x8); 20 | -------------------------------------------------------------------------------- /payload/game/system/RaceModeOnlineVs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /////////////////////////////////////////// 8 | // Time Limit Modifier / Wiimmfi Kicking // 9 | /////////////////////////////////////////// 10 | 11 | // RaceModeOnlineVs::calc() patch 12 | // Add extra conditions to end the race 13 | // Credits: Chadderz, Wiimmfi 14 | kmBranchDefCpp(0x8053F39C, 0x8053F444, void, RaceModeOnlineVs* self) { 15 | 16 | // Original function call 17 | // No need to trigger the race finish if the 30 second timer has run out 18 | if (self->tryEndRaceAfterLeaderFinish()) 19 | return; 20 | 21 | // If we are in live view mode, don't do anything 22 | if (RaceConfig::instance->raceScenario.settings.cameraMode == RaceConfig::Settings::CAMERA_MODE_LIVE_VIEW) 23 | return; 24 | 25 | // Run the modified check 26 | // TODO custom reason for Wiimmfi-mandated race end? 27 | if (self->manager->timerManager->timers[0].getTimeMs() > ModSupport::GetOnlineTimeLimit() || Wiimmfi::Kick::sMustEndRace) 28 | self->endLocalRaceWithReason(4); 29 | } 30 | -------------------------------------------------------------------------------- /payload/game/system/RaceModeOnlineVs.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class RaceModeOnlineVs : public RaceMode { 5 | public: 6 | bool tryEndRaceAfterLeaderFinish(); 7 | void endLocalRaceWithReason(int reason); 8 | 9 | u8 unk[0x174-0x8]; 10 | }; 11 | size_assert(RaceModeOnlineVs, 0x174); 12 | -------------------------------------------------------------------------------- /payload/game/system/Rating.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Rating { 4 | public: 5 | virtual ~Rating(); 6 | 7 | u16 points; 8 | }; 9 | size_assert(Rating, 0x8); 10 | -------------------------------------------------------------------------------- /payload/game/system/RawSave.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct RawSave { 4 | 5 | struct License { 6 | u8 data[0x8CC0]; 7 | }; 8 | size_assert(License, 0x8CC0); 9 | 10 | struct GlobalData { 11 | 12 | enum Settings { 13 | CONTROLLER_RUMBLE = BIT_FLAG(0), 14 | FLAG_REGION_DISPLAY = BIT_FLAG(1), 15 | UNK_4 = BIT_FLAG(2), 16 | MESSAGE_SERVICE = BIT_FLAG(3), 17 | DATA_SHARING = BIT_FLAG(4), 18 | MII_DISPLAY = BIT_FLAG(5), 19 | DEFAULT_VALUE = MII_DISPLAY | UNK_4 | FLAG_REGION_DISPLAY | CONTROLLER_RUMBLE, 20 | 21 | // Custom fields below 22 | WIIMMFI_DATA_SHARING = BIT_FLAG(7), 23 | }; 24 | 25 | u32 magic; 26 | u32 settings; 27 | u8 unk[0x37FA]; 28 | u16 regionId; 29 | }; 30 | size_assert(GlobalData, 0x3804); 31 | 32 | struct UnkBlock { 33 | u8 data[0x14F0]; 34 | }; 35 | size_assert(UnkBlock, 0x14F0); 36 | 37 | u32 magic; 38 | u32 version; 39 | License licenses[4]; 40 | GlobalData globalData; 41 | UnkBlock unkBlock; 42 | u32 crc32; 43 | }; 44 | size_assert(RawSave, 0x28000); 45 | -------------------------------------------------------------------------------- /payload/game/system/ResourceManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class ResourceManager { 6 | public: 7 | 8 | class MenuKartArchive { 9 | public: 10 | virtual ~MenuKartArchive(); 11 | 12 | EGG::Heap* archiveHeap; 13 | EGG::Heap* fileHeap; 14 | 15 | u32 state; 16 | u32 character; 17 | u32 modelType; 18 | }; 19 | size_assert(MenuKartArchive, 0x18); 20 | 21 | struct JobContext { 22 | 23 | enum JobType { 24 | GENERIC, 25 | UI, 26 | TRACK, 27 | MISSION, 28 | COMPETITION, 29 | KART, 30 | MII, 31 | }; 32 | 33 | MultiDvdArchive* multiArchive; 34 | DvdArchive* archive; 35 | u32 resourceID; 36 | char filename[0x40]; 37 | 38 | EGG::Heap *archiveHeap; 39 | EGG::Heap *fileHeap; 40 | }; 41 | size_assert(JobContext, 0x54); 42 | 43 | virtual ~ResourceManager(); 44 | 45 | void* getFile(int source, const char* path, size_t* size); 46 | void process(); 47 | static void doLoadTask(int jobContext); 48 | 49 | MultiDvdArchive* loadMission(u32 courseId, u32 missionNum, EGG::Heap* heap, bool isSplitScreen); 50 | 51 | MultiDvdArchive** multis; 52 | 53 | MultiDvdArchive kartArchives[12]; 54 | MultiDvdArchive kartArchives2[12]; 55 | DvdArchive variousArchives[4]; 56 | 57 | JobContext jobContexts[7]; 58 | EGG::TaskThread* taskThread; 59 | u8 unused[0x24]; // previously CourseCache 60 | 61 | MenuKartArchive allKartArchives[4]; 62 | bool isGlobeLoadingBusy; 63 | bool _60D; 64 | 65 | EGG::Heap* menuManagerHeap; 66 | EGG::Heap* globeHeap; 67 | 68 | bool requestPending; 69 | bool requestsEnabled; 70 | 71 | static const char* courseNames[67]; 72 | static ResourceManager* instance; 73 | }; 74 | size_assert(ResourceManager, 0x61C); 75 | -------------------------------------------------------------------------------- /payload/game/system/SaveGhostManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class SaveGhostManager { 4 | public: 5 | void markLicensesDirty(); 6 | }; 7 | -------------------------------------------------------------------------------- /payload/game/system/SaveManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class SaveManager { 8 | public: 9 | 10 | struct License { 11 | 12 | struct Cup { 13 | RawMii unusedMii; 14 | Timer unusedTimer; 15 | u32 _58; 16 | u32 _5C; 17 | 18 | u32 starRank; 19 | s32 trophy; 20 | u8 _68; 21 | u32 _6C; 22 | }; 23 | 24 | struct LeaderboardEntry { 25 | RawMii mii; 26 | Timer time; 27 | u32 character; 28 | u32 vehicle; 29 | u32 laps; 30 | }; 31 | 32 | struct CompetitionLeaderboardEntry { 33 | Timer time; 34 | u32 _C; 35 | u32 _10; 36 | u32 _14; 37 | u32 _18; 38 | }; 39 | 40 | class UnlockFlags { 41 | virtual ~UnlockFlags(); 42 | u32 flags[4]; 43 | }; 44 | 45 | class Rating { 46 | virtual ~Rating(); 47 | s16 rating; 48 | }; 49 | 50 | wchar_t miiName[11]; 51 | u8 miiAvatarId[4]; 52 | u8 miiClientId[4]; 53 | 54 | Cup cups[4][8]; // unused 55 | LeaderboardEntry ttLeaderboards[6][32]; // unused 56 | CompetitionLeaderboardEntry CompetitionLeaderboards[6]; // unused 57 | 58 | u8 friendData[0x35F0]; 59 | u8 dwcUserData[0x40]; 60 | 61 | UnlockFlags unlockFlags; // unused 62 | u32 staffGhostsBeaten[2]; // unused 63 | 64 | Rating vr; // unused 65 | Rating br; // unused 66 | 67 | u32 _9024[64]; 68 | u32 driftMode; 69 | 70 | u32 offlineEngineClass[4]; // unused 71 | u32 offlineCpuDifficulty[4]; // unused 72 | u32 offlineCpuVehicles[4]; // unused 73 | u32 offlineCourseOrder[4]; // unused 74 | u32 offlineItemSetting[4]; // unused 75 | u32 offlineRaceCount[4]; // unused 76 | u8 _9188[0x9260-0x9188]; 77 | 78 | u32 pbGhostFlags; // unused 79 | u32 downloadedGhostFlags; // unused 80 | bool isManualDrift; 81 | 82 | u32 offlineVsWins; 83 | u32 offlineVsLosses; 84 | u32 offlineBattleWins; 85 | u32 offlineBattleLosses; 86 | u32 onlineVsWins; 87 | u32 onlineVsLosses; 88 | u32 onlineBattleWins; 89 | u32 onlineBattleLosses; 90 | u32 ghostRaceWins; 91 | u32 ghostRaceLosses; 92 | u32 totalRacesPlayed; 93 | u32 totalBattlesPlayed; 94 | u32 nonWiiWheelMatches; 95 | u32 wiiWheelMatches; 96 | u32 challengesSent; 97 | u32 challengesReceived; 98 | u32 hitsDelivered; 99 | u32 hitsReceived; 100 | u32 tricksPerformed; 101 | u32 firstPlacesCount; 102 | float distanceTravelled; 103 | float distanceTravelledIn1st; 104 | float distanceTravelledInVS; 105 | u16 competitionsEntered; 106 | u16 racesCompletedWithCharacter[25]; // unused 107 | u16 racesCompletedWithVehicle[36]; // unused 108 | u16 racesCompletedOnCourse[32]; // unused 109 | u16 battlesCompletedOnStage[10]; // unused 110 | 111 | u8 _9398[0x93ED-0x9398]; 112 | bool validLicense; 113 | }; 114 | size_assert(License, 0x93F0); 115 | 116 | EGG::Disposer inherit; 117 | virtual ~SaveManager(); 118 | 119 | RawSave* rawSave; 120 | void* rawGhostFile; 121 | void* taskThread; 122 | 123 | u32 ghostOffset; 124 | bool _24; 125 | 126 | void* ghostGroup; 127 | s32 _2C; 128 | s32 _30; 129 | 130 | u8 bannerType; 131 | bool saveGhostResult; 132 | 133 | s16 currentLicenseId; 134 | License licenses[4]; 135 | 136 | bool initialized; 137 | RawSave* rawSaveCopy; 138 | 139 | bool busy; 140 | bool valid; 141 | bool canSave; 142 | 143 | s32 result; 144 | 145 | static SaveManager* instance; 146 | }; 147 | size_assert(SaveManager, 0x25008); 148 | -------------------------------------------------------------------------------- /payload/game/system/Timer.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Timer { 4 | public: 5 | virtual ~Timer(); 6 | 7 | u32 getTimeMs() { return milliseconds + seconds * 1000 + minutes * 60 * 1000; } 8 | 9 | u16 minutes; 10 | u8 seconds; 11 | u16 milliseconds; 12 | bool active; 13 | }; 14 | size_assert(Timer, 0xC); 15 | -------------------------------------------------------------------------------- /payload/game/system/TimerManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | ///////////////////////// 6 | // Wiimmfi Timekeeping // 7 | ///////////////////////// 8 | 9 | // TimerManager::calc() patch 10 | // Account for lag when updating the frame counter in online race 11 | // Credits: Wiimmfi 12 | kmCallDefCpp(0x80535C78, u32, u32 timer) { 13 | return (RaceGlobals::isOnlineRace) ? Wiimmfi::Delay::Apply(timer) : timer + 1; 14 | } 15 | 16 | // Glue code 17 | kmWrite8(0x80535C7D, 0x7D); 18 | -------------------------------------------------------------------------------- /payload/game/system/TimerManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class TimerManager { 6 | public: 7 | virtual ~TimerManager(); 8 | virtual void reset(); 9 | virtual void calc(); 10 | 11 | Timer timers[3]; 12 | Random random; 13 | 14 | bool raceTimeout; 15 | bool raceStarted; 16 | bool timerReversed; 17 | // 1 byte padding 18 | 19 | u32 raceDurationMillis; 20 | s32 raceFrameCounter; 21 | u32 _4C; // unused 22 | }; 23 | size_assert(TimerManager, 0x50); 24 | -------------------------------------------------------------------------------- /payload/game/ui/ButtonInfo.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class ButtonInfo { 5 | public: 6 | virtual ~ButtonInfo(); 7 | 8 | u32 pressTimes[MenuInputManager::INPUT_COUNT]; 9 | bool buttonHeld[MenuInputManager::INPUT_COUNT]; 10 | }; 11 | size_assert(ButtonInfo, 0x34); 12 | -------------------------------------------------------------------------------- /payload/game/ui/ControlGroup.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Page; 4 | class UIControl; 5 | 6 | class ControlGroup { 7 | public: 8 | UIControl** data; 9 | UIControl** dataSorted; // By draw order 10 | UIControl* parent; 11 | Page* page; 12 | s32 dataSize; 13 | }; 14 | size_assert(ControlGroup, 0x14); 15 | -------------------------------------------------------------------------------- /payload/game/ui/GlobalContext.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class GlobalContext { 5 | public: 6 | 7 | enum VehicleRestriction { 8 | VEHICLES_KARTS, 9 | VEHICLES_BIKES, 10 | VEHICLES_ALL, 11 | }; 12 | 13 | u8 unk[0x60]; 14 | 15 | u32 currentRace; 16 | u32 raceCount; 17 | u32 redTeamVictories; 18 | u32 blueTeamVictories; 19 | int lastVictoryTeam; 20 | u32 vehicleRestriction; 21 | 22 | // Modified 23 | u16* trackOrder; 24 | u32 nextTracks[31]; // free for use 25 | 26 | int vsRaceLimit; 27 | 28 | // Modified 29 | u16* arenaOrder; 30 | u32 nextArenas[9]; // free for use 31 | 32 | u32 humanPlayerCount; 33 | u32 _128; 34 | 35 | int playerCharacters[4]; 36 | int playerVehicles[4]; 37 | 38 | s32 lastCourse; 39 | s32 lastStage; 40 | u8 unk2[0x4D0 - 0x154]; 41 | 42 | int demoCameraMode; 43 | int demoType; 44 | int demoBattleType; 45 | u32 _4DC; 46 | int demoTrack; 47 | int demoArena; 48 | 49 | u8 unk3[0x500-0x4E8]; 50 | 51 | WifiDisconnectInfo disconnectInfo; 52 | u8 unk4[0x510-0x508]; 53 | }; 54 | size_assert(GlobalContext, 0x510); 55 | -------------------------------------------------------------------------------- /payload/game/ui/InputHandler.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | class InputHandler0 { 6 | public: 7 | InputHandler0(T* pOwner, R (T::*pInputFunc)()) : owner(pOwner), handle(pInputFunc) {} 8 | virtual R operator()() { return (owner->*handle)(); } 9 | 10 | T* owner; 11 | R (T::*handle)(); 12 | 13 | static InputHandler0* construct(T* pOwner, R (T::*pInputFunc)(), void* buffer) { 14 | return new(buffer) InputHandlerEx(pOwner, pInputFunc); 15 | } 16 | }; 17 | 18 | template 19 | class InputHandler1 { 20 | public: 21 | InputHandler1(T* pOwner, R (T::*pInputFunc)(A1)) : owner(pOwner), handle(pInputFunc) {} 22 | virtual R operator()(A1 arg1) { return (owner->*handle)(arg1); } 23 | 24 | T* owner; 25 | R (T::*handle)(A1); 26 | 27 | static InputHandler1* construct(T* pOwner, R (T::*pInputFunc)(A1), void* buffer) { 28 | return new(buffer) InputHandler1(pOwner, pInputFunc); 29 | } 30 | }; 31 | 32 | template 33 | class InputHandler2 { 34 | public: 35 | InputHandler2(T* pOwner, R (T::*pInputFunc)(A1, A2)) : owner(pOwner), handle(pInputFunc) {} 36 | virtual R operator()(A1 arg1, A2 arg2) { return (owner->*handle)(arg1, arg2); } 37 | 38 | T* owner; 39 | R (T::*handle)(A1, A2); 40 | 41 | static InputHandler2* construct(T* pOwner, R (T::*pInputFunc)(A1, A2), void* buffer) { 42 | return new(buffer) InputHandler2(pOwner, pInputFunc); 43 | } 44 | }; 45 | 46 | template 47 | class InputHandler3 { 48 | public: 49 | InputHandler3(T* pOwner, R (T::*pInputFunc)(A1, A2, A3)) : owner(pOwner), handle(pInputFunc) {} 50 | virtual R operator()(A1 arg1, A2 arg2, A3 arg3) { return (owner->*handle)(arg1, arg2, arg3); } 51 | 52 | T* owner; 53 | R (T::*handle)(A1, A2, A3); 54 | 55 | static InputHandler3* construct(T* pOwner, R (T::*pInputFunc)(A1, A2, A3), void* buffer) { 56 | return new(buffer) InputHandler3(pOwner, pInputFunc); 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /payload/game/ui/Layout.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class Layout { 5 | public: 6 | u8 _00[0x28]; 7 | 8 | nw4r::lyt::Pane* getPaneByName(const char* name); 9 | }; 10 | size_assert(Layout, 0x28); 11 | 12 | class MainLayout : public Layout { 13 | public: 14 | u8 _28[0x9c - 0x28]; 15 | }; 16 | size_assert(MainLayout, 0x9C); 17 | 18 | class PictureSourceLayout : public Layout { 19 | public: 20 | u8 _28[0xb0 - 0x28]; 21 | }; 22 | size_assert(PictureSourceLayout, 0xB0); 23 | -------------------------------------------------------------------------------- /payload/game/ui/LayoutUIControl.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class LayoutUIControl : public UIControl { 9 | public: 10 | LayoutUIControl(); 11 | virtual ~LayoutUIControl(); 12 | 13 | virtual void init(); 14 | virtual void calc(); 15 | virtual void draw(int drawPass); 16 | 17 | virtual const TypeInfo* getTypeInfo() const; 18 | virtual const char* getTypeName() const; 19 | virtual void vf_30(); 20 | 21 | virtual void loadResources(const char* arcName, const char* layoutName); 22 | 23 | void setMovieCrop(const char* pane, float top, float bottom, float left, float right); 24 | void setText(u32 bmgId, MessageInfo* info); 25 | void setMatIcon(const char* materialName, const char* iconPaneName); 26 | void setMatText(const char* materialName, u32 bmgId, MessageInfo* info); 27 | void setPaneVisible(const char* pane, bool visible); 28 | void resetText(); 29 | 30 | UIAnimator animator; 31 | MainLayout mainLayout; 32 | MessageGroup specificMessageGroup; 33 | MessageGroup commonMessageGroup; 34 | PictureSourceLayout* pictureSourceLayout; 35 | nw4r::lyt::Pane* mainPane; 36 | }; 37 | size_assert(LayoutUIControl, 0x174); 38 | -------------------------------------------------------------------------------- /payload/game/ui/MenuInputManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class MenuInputManager { 5 | public: 6 | enum InputType { 7 | FORWARD_PRESS, 8 | BACK_PRESS, 9 | START_PRESS, 10 | UP_PRESS, 11 | DOWN_PRESS, 12 | LEFT_PRESS, 13 | RIGHT_PRESS, 14 | UNK_7, 15 | UNK_8, // Home button maybe? 16 | INPUT_COUNT, 17 | }; 18 | 19 | virtual TypeInfo* getTypeInfo() const; 20 | virtual ~MenuInputManager(); 21 | virtual void init(u32 playerFlags, bool isMultiPlayer); 22 | virtual void vf_14(); 23 | virtual void vf_18(); 24 | virtual void vf_1c(); 25 | virtual void onActivate(bool isMultiPlayer); 26 | virtual void vf_24(); 27 | virtual void vf_28(); 28 | virtual void vf_2c(); 29 | virtual void vf_30(); 30 | virtual void vf_34(); 31 | 32 | u32 playerFlags; 33 | u32 playerEnabledFlags; // (1 << player) to enable inputs for player X 34 | bool inaccessible; 35 | bool isMultiPlayer; 36 | u8 _E; 37 | }; 38 | size_assert(MenuInputManager, 0x10); 39 | -------------------------------------------------------------------------------- /payload/game/ui/MessageGroup.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class MessageGroup { 4 | public: 5 | struct Header { 6 | u32 signature; 7 | u32 dataType; 8 | u32 dataSize; 9 | u32 numBlocks; 10 | u8 charset; 11 | u8 pad[0xf]; 12 | }; 13 | 14 | struct Block { 15 | u32 kind; 16 | u32 size; 17 | u8 data[]; 18 | }; 19 | 20 | enum BlockKind { 21 | BLOCK_KIND_INF = 'INF1', 22 | BLOCK_KIND_DAT = 'DAT1', 23 | BLOCK_KIND_STR = 'STR1', 24 | BLOCK_KIND_MID = 'MID1', 25 | }; 26 | 27 | struct Entry { 28 | u32 offset; 29 | u8 attributes; 30 | }; 31 | 32 | struct Inf { 33 | u16 numEntries; 34 | u16 entrySize; 35 | u16 groupID; 36 | u8 defaultColor; 37 | Entry entries[]; 38 | }; 39 | 40 | struct Mid { 41 | u16 numEntries; 42 | u8 format; 43 | u8 info; 44 | u32 pad; 45 | u32 messageIds[]; 46 | }; 47 | 48 | const Header* header; 49 | const Inf* inf; 50 | const wchar_t* dat; 51 | const void* str; 52 | const Mid* mid; 53 | }; 54 | size_assert(MessageGroup, 0x14); 55 | -------------------------------------------------------------------------------- /payload/game/ui/MessageInfo.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct MessageEscapeSequence { 5 | u16 magic; 6 | u8 length; 7 | u8 fontType; 8 | u16 sequenceType; 9 | u16 settings[3]; 10 | }; 11 | 12 | class MessageInfo { 13 | public: 14 | MessageInfo(); 15 | 16 | void setCondMessageValue(int idx, bool val, bool prependSpaceCharacter) { 17 | intVals[idx] = val + 1; 18 | prependSpace = prependSpaceCharacter; 19 | } 20 | 21 | int intVals[9]; 22 | int messageIds[9]; 23 | Mii* miis[9]; 24 | u8 licenseIds[9]; 25 | // 3 bytes padding 26 | 27 | int playerIds[9]; 28 | wchar_t* strings[9]; 29 | bool useColoredBorder; 30 | }; 31 | size_assert(MessageInfo, 0xC4); 32 | -------------------------------------------------------------------------------- /payload/game/ui/PageInputManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class PageInputManager : public MenuInputManager { 8 | public: 9 | InputHandler2* handlers[9]; 10 | bool isTriggered[INPUT_COUNT]; 11 | ButtonInfo buttoninfoArray[5]; 12 | }; 13 | size_assert(PageInputManager, 0x144); 14 | -------------------------------------------------------------------------------- /payload/game/ui/SectionManager.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class SectionManager { 8 | public: 9 | Section* curSection; 10 | u8 unk[0x8C]; 11 | 12 | SaveGhostManager* saveGhostManager; 13 | MessageGroup* systemMsgGroup; 14 | GlobalContext* globalContext; 15 | 16 | static SectionManager* instance; 17 | }; 18 | size_assert(SectionManager, 0x9C); 19 | -------------------------------------------------------------------------------- /payload/game/ui/TypeInfo.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct TypeInfo { 4 | TypeInfo* base; 5 | }; 6 | size_assert(TypeInfo, 0x4); 7 | -------------------------------------------------------------------------------- /payload/game/ui/UIAnimator.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class UIAnimationGroup { 4 | public: 5 | void setAnimation(u32 animationId, float frame); 6 | }; 7 | 8 | class UIAnimator { 9 | public: 10 | UIAnimationGroup* getGroup(u32 groupId); 11 | 12 | u8 _0[0x10]; 13 | }; 14 | size_assert(UIAnimator, 0x10); 15 | -------------------------------------------------------------------------------- /payload/game/ui/UIControl.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | enum ElementPosition { 7 | POS_PROGRAMMER_REL, // Set by the programmer 8 | POS_LAYOUT, // Set by the layout artist in a .brctr file 9 | POS_INHERITED, // Propagated down from the root 10 | POS_FINAL, // Final position displayed on screen 11 | POS_COUNT, 12 | }; 13 | 14 | struct Element { 15 | VEC3 trans; 16 | VEC2 scale; 17 | u8 opacity; 18 | }; 19 | 20 | class UIControl { 21 | public: 22 | enum PageEventTrigger { 23 | EVENT_PAGE_OPEN, 24 | EVENT_PAGE_CLOSE, 25 | }; 26 | 27 | virtual ~UIControl(); 28 | 29 | virtual void init(); 30 | virtual void calc(); 31 | virtual void draw(int drawPass); 32 | 33 | virtual void initSelf(); 34 | virtual void calcSelf(); 35 | 36 | virtual void solveAnim(Element* element, float frame); 37 | virtual void onPageEventSelf(PageEventTrigger event, u32 pageId); 38 | 39 | virtual const TypeInfo* getTypeInfo() const; 40 | virtual const char* getTypeName() const; 41 | 42 | virtual void vf_30(); 43 | virtual void vf_34(); 44 | 45 | void initChildren(u32 count); 46 | void insertChild(u32 index, UIControl* child); 47 | 48 | Element elementPositions[POS_COUNT]; 49 | 50 | ControlGroup* group; // the true "parent" is group->parent 51 | ControlGroup children; 52 | 53 | f32 zIndex; 54 | bool hidden; 55 | u32 drawPass; 56 | 57 | bool animated; 58 | f32 animStartFrame; 59 | 60 | s32 onShowSfxId; 61 | s32 onHideSfxId; 62 | }; 63 | size_assert(UIControl, 0x98); 64 | -------------------------------------------------------------------------------- /payload/game/ui/UIControlTimer.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class UIControlTimer { 4 | public: 5 | float value; 6 | bool active; 7 | int seconds; 8 | }; 9 | size_assert(UIControlTimer, 0xC); 10 | -------------------------------------------------------------------------------- /payload/game/ui/ctrl/BlackBackControl.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class BlackBackControl : public LayoutUIControl { 5 | public: 6 | virtual ~BlackBackControl(); 7 | 8 | virtual void solveAnim(Element* element, float frame); 9 | 10 | virtual const TypeInfo* getTypeInfo() const; 11 | virtual const char* getTypeName() const; 12 | }; 13 | size_assert(BlackBackControl, 0x174); 14 | -------------------------------------------------------------------------------- /payload/game/ui/ctrl/CountdownTimerControl.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | class CountdownTimerControl : public LayoutUIControl { 6 | public: 7 | virtual ~CountdownTimerControl(); 8 | 9 | virtual void initSelf(); 10 | virtual void calcSelf(); 11 | 12 | virtual const TypeInfo* getTypeInfo() const; 13 | virtual const char* getTypeName() const; 14 | 15 | UIControlTimer* timer; 16 | bool _178; 17 | }; 18 | size_assert(CountdownTimerControl, 0x17C); 19 | -------------------------------------------------------------------------------- /payload/game/ui/page/FriendRoomJoinPage.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | class FriendRoomJoinPage : public Page { 10 | public: 11 | 12 | enum PlayerState { 13 | NOT_IN_ROOM = -1, 14 | OPENED_ROOM, 15 | JOINED_ROOM, 16 | OPENING_ROOM, 17 | JOINING_ROOM, 18 | }; 19 | 20 | enum PlayerRoomState { 21 | ENTERING, 22 | JOINED_AS_GUEST, 23 | CONNECTION_ERROR, 24 | JOINED_AS_HOST, 25 | STARTING, 26 | UNK_5, 27 | UNABLE_TO_JOIN_FRIEND, 28 | DISCONNECTED_FROM_HOST, 29 | DISCONNECTED_FROM_OTHER_PLAYERS, 30 | DISCONNECTED_FROM_OTHER_PLAYERS_2, 31 | CLOSED, 32 | }; 33 | 34 | virtual ~FriendRoomJoinPage(); 35 | virtual int getReplacement(); 36 | virtual int vf_14(); 37 | 38 | virtual void onInit(); 39 | virtual void onActivate(); 40 | virtual void onDeactivate(); 41 | virtual void beforeInAnim(); 42 | 43 | virtual void afterCalc(); 44 | virtual void onRefocus(); 45 | 46 | virtual TypeInfo* getTypeInfo() const; 47 | 48 | void forceConnectionError() { 49 | if (playerRoomState == JOINED_AS_GUEST) 50 | playerRoomState = CONNECTION_ERROR; 51 | } 52 | 53 | static FriendRoomJoinPage* getPage() { 54 | return (FriendRoomJoinPage*)SectionManager::instance->curSection->pages[Page::FRIEND_ROOM_JOIN]; 55 | } 56 | 57 | MenuInputManager inputManager; 58 | LayoutUIControl matchingMessageWindow; 59 | CountdownTimerControl timerControl; 60 | UIControlTimer timer; 61 | 62 | int playerState; 63 | int friendToJoin; 64 | u8 localPlayerCount; 65 | 66 | int playerRoomState; 67 | int nextPage; 68 | }; 69 | size_assert(FriendRoomJoinPage, 0x364); 70 | -------------------------------------------------------------------------------- /payload/game/ui/page/FriendRoomMessageSelectPage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /////////////////////// 6 | // Wiimmfi Telemetry // 7 | /////////////////////// 8 | 9 | // FriendRoomMessageSelectPage::onModeBtnClick() patch 10 | // Report friend room starts 11 | kmCallDefCpp(0x805DCE34, void, RKNetROOMHandler* self, u32 data) { 12 | 13 | // Call telemetry function 14 | RKNetROOMPacketRaw packet(data); 15 | Wiimmfi::Reporting::ReportFriendRoomStart(&packet.packet); 16 | 17 | // Original call 18 | self->SetAllSendPackets(data); 19 | } 20 | -------------------------------------------------------------------------------- /payload/game/ui/page/MessagePage.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class MessagePage : public Page { 7 | public: 8 | virtual ~MessagePage(); 9 | 10 | virtual void onInit(); 11 | virtual void onActivate(); 12 | virtual void onDeactivate(); 13 | virtual void afterCalc(); 14 | 15 | virtual TypeInfo* getTypeInfo() const; 16 | 17 | virtual void reset(); 18 | virtual void setWindowMessage(u32 msgId, MessageInfo* msgInfo) = 0; 19 | virtual void process() = 0; 20 | 21 | PageInputManager inputManager; 22 | InputHandler0* onPopupFront; 23 | InputHandler0 onFront; 24 | u32 playerFlags; 25 | u32 _1A4; 26 | }; 27 | size_assert(MessagePage, 0x1A8); 28 | -------------------------------------------------------------------------------- /payload/game/ui/page/MessagePopupPage.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class MessagePopupPage : public MessagePage { 8 | public: 9 | virtual ~MessagePopupPage(); 10 | 11 | virtual void onInit(); 12 | virtual void beforeInAnim(); 13 | virtual void afterOutAnim(); 14 | 15 | virtual TypeInfo* getTypeInfo() const; 16 | virtual void reset(); 17 | virtual void setWindowMessage(u32 msgId, MessageInfo* msgInfo); 18 | virtual void process(); 19 | 20 | static MessagePopupPage* getPage() { 21 | return (MessagePopupPage*)SectionManager::instance->curSection->pages[Page::MESSAGE_POPUP]; 22 | } 23 | 24 | LayoutUIControl messageWindow; 25 | LayoutUIControl okButton; 26 | BlackBackControl blackBackControl; 27 | }; 28 | size_assert(MessagePopupPage, 0x604); 29 | -------------------------------------------------------------------------------- /payload/game/ui/page/OptionMessagePage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | ////////////////////////// 5 | // Wiimmfi Data Sharing // 6 | ////////////////////////// 7 | 8 | // When revoking consent to data sharing, toggle the Wiimmfi-specific data sharing bit so the DNS method 9 | // can ask the player to consent to data sharing again 10 | kmBranchDefCpp(0x80600D10, 0x80600D78, void) { 11 | SaveManager::instance->rawSaveCopy->globalData.settings &= ~RawSave::GlobalData::WIIMMFI_DATA_SHARING; 12 | } 13 | -------------------------------------------------------------------------------- /payload/game/ui/page/WifiDisconnectPage.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class WifiDisconnectPage : public Page { 8 | public: 9 | PageInputManager inputManager; 10 | WifiDisconnectInfo disconnectInfo; 11 | LayoutUIControl messageBox; 12 | LayoutUIControl okButton; 13 | InputHandler0 onBtnSelect; 14 | }; 15 | size_assert(WifiDisconnectPage, 0x48C); 16 | -------------------------------------------------------------------------------- /payload/game/ui/page/WifiMenuPage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | //////////////////////////////// 8 | // Wiimmfi Console Assignment // 9 | //////////////////////////////// 10 | 11 | // WifiMenuPage::beforeCalc() override 12 | // Display the Wiimmfi console assignment message if available 13 | // Credits: Wiimmfi 14 | kmPointerDefCpp(0x808BFF8C, void, Page* self) { 15 | 16 | // Check if a message is available, if not bail 17 | if (!Wiimmfi::Auth::sConsoleAssignMessage) 18 | return; 19 | 20 | // Get the message popup page, if not available bail 21 | MessagePopupPage* page = MessagePopupPage::getPage(); 22 | if (!page) return; 23 | 24 | // Inform the server we have seen the message 25 | Wiimmfi::Status::SendMessage("message", "type=server"); 26 | 27 | // Display the message 28 | MessageInfo msgInfo; 29 | msgInfo.strings[0] = Wiimmfi::Auth::sConsoleAssignMessage; 30 | page->setWindowMessage(6602, &msgInfo); 31 | 32 | // Display the page and delete the pointer so this doesn't run again next frame 33 | self->addPage(Page::MESSAGE_POPUP, Page::ANIM_NEXT); 34 | Wiimmfi::Auth::sConsoleAssignMessage = nullptr; 35 | } 36 | -------------------------------------------------------------------------------- /payload/game/util/Random.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Random { 4 | public: 5 | Random(); 6 | 7 | virtual ~Random(); 8 | 9 | u32 nextU32(u32 range); 10 | 11 | u64 x; 12 | u64 seed; 13 | }; 14 | size_assert(Random, 0x18); 15 | -------------------------------------------------------------------------------- /payload/gs/common/gsAvailable.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef enum { 8 | GSIAC_WAITING, 9 | GSIAC_AVAILABLE, 10 | GSIAC_UNAVAILABLE, 11 | GSIAC_TEMPORARILY_UNAVAILABLE, 12 | } GSIACResult; 13 | 14 | extern int __GSIACResult; 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /payload/gs/common/gsPlatformUtil.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | u32 current_time(); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | -------------------------------------------------------------------------------- /payload/gs/common/gsSocketRevolution.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | SOHostEnt* gethostbyname(const char* name); 9 | int socket(int protocolFamily, int type, int protocol); 10 | int bind(int sock, const SOSockAddrIn* addr, int len); 11 | int sendto(int sock, const char* buf, int len, int flags, const SOSockAddrIn* addr, int tolen); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /payload/gs/darray.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef void (*ArrayFreeFunc)(void* element); 8 | 9 | typedef struct { 10 | int count; 11 | int capacity; 12 | int elemSize; 13 | int growBy; 14 | ArrayFreeFunc elemFreeFunc; 15 | void* list; 16 | } DArrayImplementation; 17 | 18 | typedef DArrayImplementation* DArray; 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /payload/gs/gp/gp.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct GPIConnection GPIConnection, **GPConnection; 8 | 9 | typedef void (*GPCallback)(GPConnection connection, void* arg, void* param); 10 | 11 | typedef enum { 12 | GP_ERROR_NONE, 13 | GP_ERROR_MEMORY, 14 | GP_ERROR_PARAMETER, 15 | GP_ERROR_NETWORK, 16 | GP_ERROR_SERVER, 17 | } GPResult; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /payload/gs/gp/gpi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | ////////////////////////// 8 | // Wiimmfi Kick Support // 9 | ////////////////////////// 10 | 11 | // gpiProcessConnectionManager() patch 12 | // Parse Wiimmfi kick messages 13 | // Credits: Wiimmfi 14 | kmCallDefCpp(0x800FCEE8, int, GPConnection conn, char* data) { 15 | 16 | // Reproduce skipped code 17 | if (strstartw(data, "\\bsi\\")) 18 | return gpiProcessRecvBuddyStatusInfo(conn, data); 19 | 20 | // Call Wiimmfi code 21 | return Wiimmfi::Kick::ParseKickMessage(conn, data); 22 | } 23 | 24 | // Glue code 25 | kmBranch(0x800FCEC8, 0x800FCEE0); 26 | -------------------------------------------------------------------------------- /payload/gs/gp/gpi.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | struct GPIConnection { 15 | char errorString[256]; 16 | int infoCaching; 17 | int infoCachingBuddyOnly; 18 | int simulation; 19 | int firewall; 20 | 21 | char nick[31]; 22 | char uniqueNick[21]; 23 | char email[51]; 24 | char password[31]; 25 | // 2 bytes padding 26 | 27 | int sessKey; 28 | int userId; 29 | int profileId; 30 | int partnerId; 31 | GPICallback callbacks[9]; 32 | int cmSocket; 33 | int connectState; 34 | GPIBuffer socketBuffer; 35 | char* inputBuffer; 36 | int inputBufferSize; 37 | GPIBuffer outputBuffer; 38 | 39 | char mHeader[16]; 40 | u16 peerPort; 41 | // 2 bytes padding 42 | 43 | int nextOperationId; 44 | int numSearches; 45 | int lastStatusState; 46 | 47 | u32 hostIp; 48 | u32 hostPrivateIp; 49 | u16 queryPort; 50 | u16 hostPort; 51 | int sessionFlags; 52 | 53 | char richStatus[256]; 54 | char gameType[33]; 55 | char gameVariant[33]; 56 | char gameMapName[33]; 57 | // 1 byte padding 58 | 59 | DArray extendedInfoKeys; 60 | char lastStatusString[256]; 61 | char lastLocationString[256]; 62 | int errorCode; 63 | int fatalError; 64 | void* diskCache; // actually FILE 65 | GPIOperation* operationList; 66 | GPIProfileList profileList; 67 | GPIPeer* peerList; 68 | GPICallbackData* callbackList; 69 | GPICallbackData* lastCallback; 70 | GPIBuffer updateProBuffer; 71 | GPIBuffer updateUiBuffer; 72 | DArray transfers; 73 | u32 nextTransferId; 74 | int productId; 75 | int namespaceId; 76 | char loginTicket[25]; 77 | // 3 bytes padding 78 | 79 | int quietModeFlags; 80 | int kaTransfer; 81 | }; 82 | 83 | #ifdef __cplusplus 84 | } 85 | #endif 86 | -------------------------------------------------------------------------------- /payload/gs/gp/gpiBuddy.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | GPResult gpiProcessRecvBuddyStatusInfo(GPConnection conn, const char* data); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /payload/gs/gp/gpiBuffer.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct { 9 | char* buffer; 10 | int size; 11 | int len; 12 | int pos; 13 | } GPIBuffer; 14 | 15 | GPResult gpiAppendStringToBuffer(GPConnection connection, GPIBuffer* outputBuffer, const char* buffer); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /payload/gs/gp/gpiCallback.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct GPICallbackData GPICallbackData; 9 | 10 | typedef struct { 11 | GPCallback callback; 12 | void* param; 13 | } GPICallback; 14 | 15 | struct GPICallbackData { 16 | GPICallback callback; 17 | void* arg; 18 | int type; 19 | int operationID; 20 | GPICallbackData* next; 21 | }; 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /payload/gs/gp/gpiConnect.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /////////////////////// 5 | // Wiimmfi Telemetry // 6 | /////////////////////// 7 | 8 | // gpiSendLogin() patch 9 | // Report the signature and certificate to the server 10 | // Credits: Wiimmfi 11 | kmBranchDefCpp(0x801007D8, NULL, int, int ret) { 12 | Wiimmfi::Reporting::ReportSignatureAndCert(); 13 | return ret; 14 | } 15 | -------------------------------------------------------------------------------- /payload/gs/gp/gpiOperation.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct GPIOperation GPIOperation; 9 | 10 | struct GPIOperation { 11 | int type; 12 | void* data; 13 | int blocking; 14 | GPICallback callback; 15 | int state; 16 | int id; 17 | int result; 18 | GPIOperation* next; 19 | }; 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /payload/gs/gp/gpiPeer.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | typedef struct GPIPeer GPIPeer; 10 | 11 | struct GPIPeer { 12 | int state; 13 | int initiated; 14 | int socket; 15 | int profile; 16 | int timeout; 17 | int nackCount; 18 | GPIBuffer inputBuffer; 19 | GPIBuffer outputBuffer; 20 | DArray messages; 21 | GPIPeer* next; 22 | }; 23 | 24 | #ifdef __cplusplus 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /payload/gs/gp/gpiProfile.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct { 9 | HashTable profileHashTable; 10 | int num; 11 | int numBuddies; 12 | } GPIProfileList; 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | -------------------------------------------------------------------------------- /payload/gs/gt2/gt2.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef enum { 8 | GT2_CLOSE_LOCAL, 9 | GT2_CLOSE_REMOTE, 10 | GT2_CLOSE_COMM_ERR, 11 | GT2_CLOSE_SOCKET_ERR, 12 | GT2_CLOSE_OUT_OF_MEMORY, 13 | } GT2CloseReason; 14 | 15 | typedef enum { 16 | GT2_PROTOCOL_UDP = 0, 17 | GT2_PROTOCOL_VDP = 2, 18 | GT2_PROTOCOL_ADHOC = 3, 19 | } GT2Protocol; 20 | 21 | typedef enum { 22 | GT2_RESULT_SUCCESS, 23 | GT2_RESULT_OUT_OF_MEMORY, 24 | GT2_RESULT_REJECTED, 25 | GT2_RESULT_NETWORK_ERROR, 26 | GT2_RESULT_ADDRESS_ERROR, 27 | GT2_RESULT_DUPLICATE_ADDR, 28 | GT2_RESULT_TIMED_OUT, 29 | GT2_RESULT_NEGOTIATION_ERROR, 30 | GT2_RESULT_INVALID_CONN, 31 | GT2_RESULT_INVALID_MSG, 32 | GT2_RESULT_SEND_FAILED, 33 | } GT2Result; 34 | 35 | typedef enum { 36 | GT2_STATE_WAITING_SERVER_CHALLENGE, 37 | GT2_STATE_WAITING_ACCEPTANCE, 38 | GT2_STATE_WAITING_CLIENT_CHALLENGE, 39 | GT2_STATE_WAITING_CLIENT_RESPONSE, 40 | GT2_STATE_WAITING_ACCEPT_REJECT, 41 | GT2_STATE_CONNECTED, 42 | GT2_STATE_CLOSING, 43 | GT2_STATE_CLOSED, 44 | } GT2SocketState; 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | -------------------------------------------------------------------------------- /payload/gs/gt2/gt2Buffer.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct { 8 | u8* buffer; 9 | int size; 10 | int len; 11 | } GTI2Buffer; 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | -------------------------------------------------------------------------------- /payload/gs/gt2/gt2Callback.h: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | typedef struct GTI2Socket GTI2Socket, *GT2Socket; 10 | typedef struct GTI2Connection GTI2Connection, *GT2Connection; 11 | 12 | typedef void (*GT2SocketErrorCallback)(GT2Socket sock); 13 | typedef void (*GT2ConnectAttemptCallback)(GT2Socket sock, GT2Connection conn, u32 ip, u16 port, 14 | int latency, const char* msg, int msgLen); 15 | typedef void (*GT2ConnectedCallback)(GT2Connection conn, GT2Result, const char* msg, int msgLen); 16 | typedef void (*GT2ReceivedCallback)(GT2Connection conn, u8* msg, int msgLen, int isReliable); 17 | typedef void (*GT2ClosedCallback)(GT2Connection conn, GT2CloseReason reason); 18 | typedef void (*GT2PingCallback)(GT2Connection conn, int latency); 19 | typedef void (*GT2DumpCallback)(GT2Socket sock, GT2Connection conn, u32 ip, u16 port, 20 | int latency, u8* msg, int msgLen); 21 | typedef int (*GT2UnrecognizedMessageCallback)(GT2Socket sock, u32 ip, u16 port, u8* msg, int msgLen); 22 | 23 | typedef struct { 24 | GT2ConnectedCallback connectedCb; 25 | GT2ReceivedCallback receivedCb; 26 | GT2ClosedCallback closeCb; 27 | GT2PingCallback pingCb; 28 | } GT2Callbacks; 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | -------------------------------------------------------------------------------- /payload/gs/gt2/gt2Main.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | struct GTI2Socket { 12 | int socket; 13 | u32 ip; 14 | u16 port; 15 | // 2 bytes padding 16 | 17 | HashTable connections; 18 | DArray closedConnections; 19 | int close; 20 | int error; 21 | int callbackLevel; 22 | 23 | GT2ConnectAttemptCallback connectAttemptCallback; 24 | GT2SocketErrorCallback socketErrorCallback; 25 | GT2DumpCallback sendDumpCallback; 26 | GT2DumpCallback receiveDumpCallback; 27 | GT2UnrecognizedMessageCallback unrecognizedMsgCallback; 28 | 29 | void* data; 30 | u32 sendBufferSize; 31 | u32 recvBufferSize; 32 | 33 | GT2Protocol protocolType; 34 | int protocolOffset; 35 | int broadcastEnabled; 36 | }; 37 | 38 | struct GTI2Connection { 39 | u32 ip; 40 | u16 port; 41 | u8 aid; // custom field 42 | // 1 byte padding 43 | 44 | GTI2Socket* socket; 45 | GT2SocketState state; 46 | int initiated; 47 | int freeAtAcceptReject; 48 | GT2Result result; 49 | u32 startTime; 50 | u32 timeout; 51 | int callbackLevel; 52 | GT2Callbacks callbacks; 53 | char * initialMessage; 54 | int initialMessageLen; 55 | void* data; 56 | GTI2Buffer incomingBuffer; 57 | GTI2Buffer outgoingBuffer; 58 | DArray incomingBufferMessages; 59 | DArray outgoingBufferMessages; 60 | u16 serialNumber; 61 | u16 expectedSerialNumber; 62 | char response[32]; 63 | u32 lastSend; 64 | u32 challengeTime; 65 | int pendingAck; 66 | u32 pendingAckTime; 67 | DArray sendFilters; 68 | DArray receiveFilters; 69 | }; 70 | 71 | GT2Result gt2Connect(GT2Socket socket, GT2Connection* connection, const char* remoteAddress, 72 | const char* msg, int msgLen, int timeout, GT2Callbacks* callbacks, int blocking); 73 | 74 | BOOL gt2Accept(GT2Connection connection, GT2Callbacks* callbacks); 75 | void gt2Listen(GT2Socket socket, GT2ConnectAttemptCallback callback); 76 | void gt2Reject(GT2Connection connection, const char* msg, int msgLen); 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | -------------------------------------------------------------------------------- /payload/gs/gt2/gt2Socket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | ////////////////////////// 6 | // Wiimmfi Port Binding // 7 | ////////////////////////// 8 | 9 | // gti2CreateSocket() patch 10 | // Try to bind on the custom port, retry on a different port on failure 11 | // Credits: Wiimmfi 12 | kmCallDefCpp(0x8010E090, int, int sock, SOSockAddrIn* addr, int len) { 13 | 14 | // Original call 15 | int ret = bind(sock, addr, sizeof(*addr)); 16 | if (ret >= 0) 17 | return ret; 18 | 19 | DEBUG_REPORT("[WIIMMFI_PORT] Bind failed on port %d\n", addr->port) 20 | 21 | // If binding fails, try on a different random port up to 10 times 22 | for (int i = 0; i < 10; i++) { 23 | addr->port = (DWCi_GetMathRand32(0x4000) + 0xC000) & 0xFFFF; 24 | ret = bind(sock, addr, sizeof(*addr)); 25 | if (ret >= 0) { 26 | DEBUG_REPORT("[WIIMMFI_PORT] Bind successful on alternate port %d\n", addr->port) 27 | return ret; 28 | } 29 | } 30 | 31 | // Everything failed, give up 32 | return -1; 33 | } 34 | -------------------------------------------------------------------------------- /payload/gs/gt2/gt2Utility.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | char* gt2AddressToString(u32 ip, u16 port, char* string); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | -------------------------------------------------------------------------------- /payload/gs/hashtable.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef void (*TableFreeFunc)(void* elem); 9 | typedef int (*TableHashFunc)(void* elem, int); 10 | typedef int (*TableCompareFunc)(void* elem1, void* elem2); 11 | 12 | typedef struct { 13 | DArray* buckets; 14 | int numBuckets; 15 | TableFreeFunc freeFunc; 16 | TableHashFunc hashFunc; 17 | TableCompareFunc compareFunc; 18 | } HashImplementation; 19 | 20 | typedef HashImplementation* HashTable; 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | -------------------------------------------------------------------------------- /payload/gs/natneg/natify.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // Ported from GameSpy SDK 8 | int DiscoverReachability(int sock, u32 ip, u16 port, int portType) { 9 | 10 | // Set up address 11 | SOSockAddrIn addr; 12 | addr.family = SO_PF_IPV4; 13 | addr.addr = ip; 14 | addr.port = port; 15 | 16 | // Set up packet 17 | NATNEGPacket p; 18 | memset(&p, 0, sizeof(p)); 19 | memcpy(&p.magic, NNMagicData, sizeof(p.magic)); 20 | p.version = NATNEG_PROTOCOL_VERSION; 21 | p.packetType = NN_NATIFY_REQUEST; 22 | p.cookie = NATIFY_COOKIE; 23 | p.data.init.porttype = portType; 24 | 25 | // Send it 26 | return sendto(sock, (const char*)&p, sizeof(p), 0, &addr, sizeof(addr)); 27 | } 28 | 29 | // Ported from GameSpy SDK 30 | int DiscoverMapping(int sock, u32 ip, u16 port, int portType, int id) { 31 | 32 | // Set up address 33 | SOSockAddrIn addr; 34 | addr.family = SO_PF_IPV4; 35 | addr.addr = ip; 36 | addr.port = port; 37 | 38 | // Set up packet 39 | NATNEGPacket p; 40 | memset(&p, 0, sizeof(p)); 41 | memcpy(&p.magic, NNMagicData, sizeof(p.magic)); 42 | p.version = NATNEG_PROTOCOL_VERSION; 43 | p.packetType = NN_ADDRESS_CHECK; 44 | p.cookie = id; 45 | p.data.init.porttype = portType; 46 | 47 | // Send it 48 | return sendto(sock, (const char*)&p, sizeof(p), 0, &addr, sizeof(addr)); 49 | } 50 | -------------------------------------------------------------------------------- /payload/gs/natneg/natify.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #define NATIFY_COOKIE 777 8 | 9 | typedef enum { 10 | NATIFY_MAP_1A, 11 | NATIFY_MAP_2, 12 | NATIFY_MAP_3, 13 | NATIFY_MAP_1B, 14 | NATIFY_MAP_NUM, 15 | } NatifyPacket; 16 | 17 | typedef enum { 18 | NAT_PROMISCUITY_ALL, 19 | NAT_PROMISCUITY_NONE, 20 | NAT_PROMISCUITY_PORT, 21 | NAT_PROMISCUITY_IP, 22 | NAT_PROMISCUITY_UNKNOWN, 23 | NAT_PROMISCUITY_NUM, 24 | } NATPromiscuity; 25 | 26 | typedef enum { 27 | NAT_MAP_UNRECOGNIZED, 28 | NAT_MAP_PRIVATE_AS_PUBLIC, 29 | NAT_MAP_CONSISTENT_PORT, 30 | NAT_MAP_INCREMENTAL, 31 | NAT_MAP_MIXED, 32 | NAT_MAP_NUM, 33 | } NATMapping; 34 | 35 | typedef enum { 36 | NAT_TYPE_NONE, 37 | NAT_TYPE_FIREWALL_ONLY, 38 | NAT_TYPE_FULL_CONE, 39 | NAT_TYPE_RESTRICTED_CONE, 40 | NAT_TYPE_PORT_RESTRICTED_CONE, 41 | NAT_TYPE_SYMMETRIC, 42 | NAT_TYPE_UNKNOWN, 43 | NAT_TYPE_NUM, 44 | } NATType; 45 | 46 | typedef struct { 47 | u32 privateIp; 48 | u16 privatePort; 49 | u32 publicIp; 50 | u16 publicPort; 51 | } AddressMapping; 52 | 53 | typedef struct { 54 | char brand[32]; 55 | char model[32]; 56 | char firmware[64]; 57 | BOOL ipRestricted; 58 | BOOL portRestricted; 59 | int promiscuity; 60 | int type; 61 | int mappingScheme; 62 | AddressMapping mappings[4]; 63 | BOOL qr2Compatible; 64 | } NAT; 65 | 66 | BOOL DetermineNatType(NAT* nat); 67 | int DiscoverReachability(int sock, unsigned int ip, unsigned short port, int portType); // reimplemented 68 | int DiscoverMapping(int sock, unsigned int ip, unsigned short port, int portType, int id); // reimplemented 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | -------------------------------------------------------------------------------- /payload/gs/natneg/natneg.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Ported from GameSpy SDK 10 | u32 NameToIp(const char* name) { 11 | 12 | SOHostEnt* hent = gethostbyname(name); 13 | if (!hent) return 0; 14 | return hent->addrList[0][0]; 15 | } 16 | 17 | // Ported from GameSpy SDK 18 | BOOL ResolveServers() { 19 | 20 | if (matchup1ip == 0) 21 | matchup1ip = NameToIp(Matchup1Hostname); 22 | 23 | if (matchup2ip == 0) 24 | matchup2ip = NameToIp(Matchup2Hostname); 25 | 26 | if (matchup3ip == 0) 27 | matchup3ip = NameToIp(Matchup3Hostname); 28 | 29 | if (matchup1ip == 0 || matchup2ip == 0 || matchup3ip == 0) 30 | return FALSE; 31 | 32 | return TRUE; 33 | } 34 | 35 | // Ported from GameSpy SDK 36 | int NNStartNatDetection(NatDetectionResultsFunc resultscallback) { 37 | 38 | // Check if the backend is available 39 | if(__GSIACResult != GSIAC_AVAILABLE) 40 | return NN_SOCKET_ERROR; 41 | 42 | if (!ResolveServers()) 43 | return NN_DNS_ERROR; 44 | 45 | activeNatify = TRUE; 46 | natifyCallback = resultscallback; 47 | natifyStartTime = current_time(); 48 | 49 | // Assume these for now 50 | nat.ipRestricted = TRUE; 51 | nat.portRestricted = TRUE; 52 | 53 | // Create socket for external reach tests 54 | ertSock = socket(SO_PF_IPV4, SO_SOCK_UDP, SO_IPPROTO_UDP); 55 | 56 | // Create socket for determining how traffic is mapped 57 | mappingSock = socket(SO_PF_IPV4, SO_SOCK_UDP, SO_IPPROTO_UDP); 58 | 59 | // Send reachability packets 60 | DiscoverReachability(ertSock, matchup1ip, NATNEG_PORT, NN_PT_NN1); 61 | DiscoverReachability(ertSock, matchup1ip, NATNEG_PORT, NN_PT_NN2); 62 | DiscoverReachability(ertSock, matchup2ip, NATNEG_PORT, NN_PT_NN3); 63 | 64 | // Send mapping packets 65 | DiscoverMapping(mappingSock, matchup1ip, NATNEG_PORT, NN_PT_NN1, NATIFY_MAP_1A); 66 | DiscoverMapping(mappingSock, matchup1ip, NATNEG_PORT, NN_PT_NN1, NATIFY_MAP_1B); 67 | DiscoverMapping(mappingSock, matchup2ip, NATNEG_PORT, NN_PT_NN2, NATIFY_MAP_2); 68 | DiscoverMapping(mappingSock, matchup3ip, NATNEG_PORT, NN_PT_NN3, NATIFY_MAP_3); 69 | 70 | return NN_NO_ERROR; 71 | } 72 | 73 | ///////////////// 74 | // Fast NATNEG // 75 | ///////////////// 76 | 77 | // NegotiateThink() patch 78 | // Reduce PING retry time from 700 to 80 79 | // Credits: Wiimmfi 80 | kmWrite16(0x8011B47A, 80); 81 | 82 | // NegotiateThink() patch 83 | // Do not wait the retry time in case of successful NATNEG 84 | // Credits: Wiimmfi 85 | kmWrite32(0x8011B4B0, 0x60000000); 86 | 87 | // ProcessPingPacket() patch 88 | // Do not wait the idle time after a successful NATNEG 89 | // Credits: WiiLink24 90 | kmWrite16(0x8011BC3A, 0); 91 | 92 | ///////////////////////// 93 | // NATify Improvements // 94 | ///////////////////////// 95 | 96 | // SendInitPackets() patch 97 | // Modify INIT packets to send the NATify data 98 | // Credits: Wiimmfi 99 | kmCallDefCpp(0x8011AB28, int, u8* buffer) { 100 | return Wiimmfi::Natify::CopyData(buffer); 101 | } 102 | 103 | // SendInitPackets() patch 104 | // Replace INIT message type 105 | // Credits: Wiimmfi 106 | kmWrite32(0x8011AB2C, 0x3BC00000 | WIIMMFI_NATIFY); 107 | kmWrite32(0x8011AB30, 0x9BC1004F); 108 | -------------------------------------------------------------------------------- /payload/gs/natneg/natneg.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | #pragma pack(push, 1) 8 | 9 | #define NATNEG_MAGIC_LEN 6 10 | #define NATNEG_PORT 27901 11 | #define NATNEG_PROTOCOL_VERSION 3 12 | 13 | typedef enum { 14 | NN_NO_ERROR, 15 | NN_ALLOC_ERROR, 16 | NN_SOCKET_ERROR, 17 | NN_DNS_ERROR, 18 | } NATNEGError; 19 | 20 | typedef enum { 21 | NN_STATE_INIT_SENT, 22 | NN_STATE_INIT_ACK, 23 | NN_STATE_INIT_CONNECT_PING, 24 | NN_STATE_FINISHED, 25 | NN_STATE_CANCELED, 26 | NN_STATE_REPORT_SENT, 27 | NN_STATE_REPORT_ACK, 28 | } NATNEGState; 29 | 30 | typedef enum { 31 | NN_RESULT_SUCCESS, 32 | NN_RESULT_DEADBEAT_PARTNER, 33 | NN_RESULT_INIT_TIMEOUT, 34 | NN_RESULT_PING_TIMEOUT, 35 | NN_RESULT_UNK_ERROR, 36 | NN_RESULT_NONE, 37 | } NATNEGResult; 38 | 39 | typedef enum { 40 | NN_PT_GP, 41 | NN_PT_NN1, 42 | NN_PT_NN2, 43 | NN_PT_NN3, 44 | } NATNEGPortType; 45 | 46 | typedef enum { 47 | NN_INIT, 48 | NN_INITACK, 49 | NN_ERTTEST, 50 | NN_ERTACK, 51 | NN_STATEUPDATE, 52 | NN_CONNECT, 53 | NN_CONNECT_ACK, 54 | NN_CONNECT_PING, 55 | NN_BACKUP_TEST, 56 | NN_BACKUP_ACK, 57 | NN_ADDRESS_CHECK, 58 | NN_ADDRESS_REPLY, 59 | NN_NATIFY_REQUEST, 60 | NN_REPORT, 61 | NN_REPORT_ACK, 62 | 63 | // Custom commands from here onwards 64 | WIIMMFI_NATIFY = 0x80, 65 | } NATNEGCommand; 66 | 67 | typedef struct { 68 | u8 porttype; 69 | u8 clientindex; 70 | u8 usegameport; 71 | u32 localip; 72 | u16 localport; 73 | } InitPacket; 74 | 75 | typedef struct { 76 | u8 portType; 77 | u8 clientindex; 78 | u8 negResult; 79 | int natType; 80 | int natMappingScheme; 81 | char gamename[50]; 82 | } ReportPacket; 83 | 84 | typedef struct { 85 | u32 remoteIP; 86 | u16 remotePort; 87 | u8 gotData; 88 | u8 finished; 89 | } ConnectPacket; 90 | 91 | typedef struct { 92 | u8 magic[NATNEG_MAGIC_LEN]; 93 | u8 version; 94 | u8 packetType; 95 | int cookie; 96 | 97 | union { 98 | InitPacket init; 99 | ConnectPacket connect; 100 | ReportPacket report; 101 | } data; 102 | 103 | } NATNEGPacket; 104 | 105 | typedef void (*NegotiateProgressFunc)(int state, void* userData); 106 | typedef void (*NegotiateCompletedFunc)(int result, int gamesocket, SOSockAddrIn* remoteAddr, void* userData); 107 | typedef void (*NatDetectionResultsFunc)(BOOL success, NAT* nat); 108 | 109 | typedef struct { 110 | int negotiateSock; 111 | int gameSock; 112 | int cookie; 113 | int clientindex; 114 | int state; 115 | int initAckRecv[4]; 116 | int retryCount; 117 | int maxRetryCount; 118 | u32 retryTime; 119 | u32 guessedIP; 120 | u16 guessedPort; 121 | u8 gotRemoteData; 122 | u8 sendGotRemoteData; 123 | NegotiateProgressFunc progressCallback; 124 | NegotiateCompletedFunc completedCallback; 125 | void *userdata; 126 | int result; 127 | int connectedSocket; 128 | SOSockAddrIn remoteAddr; 129 | } NATNegotiator; 130 | 131 | void NegotiateThink(NATNegotiator* neg); 132 | int NNStartNatDetection(NatDetectionResultsFunc resultscallback); // reimplemented 133 | 134 | extern char Matchup1Hostname[], Matchup2Hostname[], Matchup3Hostname[]; 135 | extern u32 matchup1ip, matchup2ip, matchup3ip; 136 | extern int mappingSock, ertSock; 137 | extern BOOL activeNatify; 138 | extern u32 natifyStartTime; 139 | extern NatDetectionResultsFunc natifyCallback; 140 | extern NAT nat; 141 | extern u8 NNMagicData[NATNEG_MAGIC_LEN]; 142 | 143 | #pragma pack(pop) 144 | #ifdef __cplusplus 145 | } 146 | #endif 147 | -------------------------------------------------------------------------------- /payload/gs/qr2/qr2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | ///////////////////////////// 8 | // Wiimmfi Challenge Check // 9 | ///////////////////////////// 10 | 11 | // send_heartbeat() patch 12 | // Send the login challenge 13 | // Credits: Wiimmfi 14 | kmCallDefCpp(0x80111534, void, int socket, qr2_buffer* buffer, int bufferLength, int flags, 15 | const SOSockAddrIn* addr, u8 toLen) { 16 | 17 | // Store the challenge into the buffer and send it 18 | Wiimmfi::Challenge::Send(buffer); 19 | sendto(socket, buffer->data, buffer->dataSize, flags, addr, toLen); 20 | } 21 | -------------------------------------------------------------------------------- /payload/gs/qr2/qr2.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct { 8 | char data[1400]; 9 | int dataSize; 10 | } qr2_buffer; 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /payload/nw4r/lyt/drawInfo.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace nw4r { 6 | namespace lyt { 7 | 8 | class DrawInfo { 9 | public: 10 | virtual ~DrawInfo(); 11 | 12 | math::MTX34 mViewMtx; 13 | ut::Rect mViewRect; 14 | math::VEC2 mLocationAdjustScale; 15 | f32 mGlobalAlpha; 16 | u8 mFlag; 17 | }; 18 | 19 | } // namespace lyt 20 | } // namespace nw4r 21 | -------------------------------------------------------------------------------- /payload/nw4r/lyt/material.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace nw4r { 5 | namespace lyt { 6 | 7 | class Material { 8 | public: 9 | u8 unk[0x3C]; 10 | u32 flags; 11 | 12 | TexMap* GetTexMapAry(); 13 | }; 14 | 15 | } // namespace lyt 16 | } // namespace nw4r 17 | -------------------------------------------------------------------------------- /payload/nw4r/lyt/pane.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace nw4r { 5 | namespace lyt { 6 | 7 | class Pane { 8 | public: 9 | Material* GetMaterial(); 10 | }; 11 | 12 | } // namespace lyt 13 | } // namespace nw4r 14 | -------------------------------------------------------------------------------- /payload/nw4r/lyt/texmap.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace nw4r { 4 | namespace lyt { 5 | 6 | class TexMap { 7 | public: 8 | u8 unk[0x1C]; 9 | 10 | void ReplaceImage(void* image, u32 id); // Actually TPLDescriptor* but i cannot be arsed 11 | }; 12 | 13 | } // namespace lyt 14 | } // namespace nw4r 15 | -------------------------------------------------------------------------------- /payload/nw4r/math/types.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace nw4r { 5 | namespace math { 6 | 7 | typedef VEC2 VEC2; 8 | typedef MTX34 MTX34; 9 | 10 | } // namespace math 11 | } // namespace nw4r 12 | -------------------------------------------------------------------------------- /payload/nw4r/ut/Lock.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace nw4r { 5 | namespace ut { 6 | 7 | class AutoInterruptLock { 8 | public: 9 | 10 | AutoInterruptLock() : mOldState(OSDisableInterrupts()) {} 11 | ~AutoInterruptLock() { OSRestoreInterrupts(mOldState); } 12 | 13 | BOOL mOldState; 14 | }; 15 | 16 | } // namespace ut 17 | } // namespace nw4r 18 | -------------------------------------------------------------------------------- /payload/nw4r/ut/rect.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace nw4r { 4 | namespace ut { 5 | 6 | struct Rect { 7 | f32 left; 8 | f32 top; 9 | f32 right; 10 | f32 bottom; 11 | }; 12 | 13 | } // namespace ut 14 | } // namespace nw4r 15 | -------------------------------------------------------------------------------- /payload/nw4r/ut/utList.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace nw4r { 4 | namespace ut { 5 | 6 | typedef struct { 7 | void* prev; 8 | void* next; 9 | } Link; 10 | 11 | typedef struct { 12 | void* head; 13 | void* tail; 14 | u16 count; 15 | u16 offset; 16 | } List; 17 | 18 | typedef struct { 19 | u32 count; 20 | Link node; 21 | } LinkListImpl; 22 | 23 | } // namespace ut 24 | } // namespace nw4r 25 | -------------------------------------------------------------------------------- /payload/platform/new.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void* operator new(size_t size, void* buffer); 5 | void* operator new(size_t size, int align); 6 | void* operator new(size_t size, EGG::Heap* heap, int align); 7 | 8 | void* operator new[](size_t size, void* buffer); 9 | void* operator new[](size_t size, int align); 10 | void* operator new[](size_t size, EGG::Heap* heap, int align); 11 | -------------------------------------------------------------------------------- /payload/platform/stdio.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | int sprintf(char* s, const char* format, ...); 8 | int snprintf(char* s, size_t n, const char* format, ...); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /payload/platform/stdlib.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | int atoi(const char* str); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | -------------------------------------------------------------------------------- /payload/platform/string.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void* memcpy(void* destination, const void* source, size_t size); 8 | void* memset(void* ptr, int value, size_t num); 9 | 10 | int strcmp(const char* str1, const char* str2); 11 | int strncmp(const char* str1, const char* str2, size_t num); 12 | char* strcpy(char* destination, const char* source); 13 | char* strncpy(char* destination, const char* source, size_t num); 14 | char* strstr(char* str1, const char* str2); 15 | size_t strlen(const char* str); 16 | u32 strtoul(const char* str, char** endptr, int base); 17 | 18 | #define strlenconst(str) (sizeof((str)) - 1) 19 | #define strshift(str, str2) (str) += strlenconst(str2) 20 | #define strstartw(str, str2) (strncmp((str), (str2), strlenconst(str2)) == 0) 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | -------------------------------------------------------------------------------- /payload/revolution/base/PPCArch.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | /////////////// 8 | // Registers // 9 | /////////////// 10 | #define ECID_U 924 11 | #define ECID_M 925 12 | #define ECID_L 926 13 | 14 | ////////// 15 | // ECID // 16 | ////////// 17 | #define DEFAULT_ECID_U 0x0D96E200 18 | #define DEFAULT_ECID_M 0x1840C00D 19 | #define DEFAULT_ECID_L 0x82BB08E8 20 | 21 | /////////// 22 | // FPSCR // 23 | /////////// 24 | typedef enum { 25 | FPSCR_FX = BIT_FLAG(31), // Exception summary 26 | FPSCR_FEX = BIT_FLAG(30), // Enabled exception summary 27 | FPSCR_VX = BIT_FLAG(29), // Invalid operation 28 | FPSCR_OX = BIT_FLAG(28), // Overflow exception 29 | FPSCR_UX = BIT_FLAG(27), // Underflow exception 30 | FPSCR_ZX = BIT_FLAG(26), // Zero divide exception 31 | FPSCR_XX = BIT_FLAG(25), // Inexact exception 32 | FPSCR_VXSNAN = BIT_FLAG(24), // SNaN 33 | FPSCR_VXISI = BIT_FLAG(23), // Infinity - Infinity 34 | FPSCR_VXIDI = BIT_FLAG(22), // Infinity / Infinity 35 | FPSCR_VXZDZ = BIT_FLAG(21), // 0 / 0 36 | FPSCR_VXIMZ = BIT_FLAG(20), // Infinity * 0 37 | FPSCR_VXVC = BIT_FLAG(19), // Invalid compare 38 | FPSCR_FR = BIT_FLAG(18), // Fraction rounded 39 | FPSCR_FI = BIT_FLAG(17), // Fraction inexact 40 | FPSCR_VXSOFT = BIT_FLAG(10), // Software request 41 | FPSCR_VXSQRT = BIT_FLAG(9), // Invalid square root 42 | FPSCR_VXCVI = BIT_FLAG(8), // Invalid integer convert 43 | FPSCR_VE = BIT_FLAG(7), // Invalid operation exception enable 44 | FPSCR_OE = BIT_FLAG(6), // Overflow exception enable 45 | FPSCR_UE = BIT_FLAG(5), // Underflow exception enable 46 | FPSCR_ZE = BIT_FLAG(4), // Zero divide exception enable 47 | FPSCR_XE = BIT_FLAG(3), // Inexact exception enable 48 | FPSCR_NI = BIT_FLAG(2), // Non-IEEE mode 49 | } FPSCR; 50 | 51 | /////////////// 52 | // Functions // 53 | /////////////// 54 | 55 | inline u32 PPCGetECID_U() { 56 | register u32 val; 57 | __asm__ (mfspr val, ECID_U); 58 | return val; 59 | } 60 | 61 | inline u32 PPCGetECID_M() { 62 | register u32 val; 63 | __asm__ (mfspr val, ECID_M); 64 | return val; 65 | } 66 | 67 | inline u32 PPCGetECID_L() { 68 | register u32 val; 69 | __asm__ (mfspr val, ECID_L); 70 | return val; 71 | } 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | -------------------------------------------------------------------------------- /payload/revolution/base/PPCReg.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | vu16 __CPRegs[0x33] AT_ADDR(0xCC000000); 9 | vu16 __PERegs[0x100] AT_ADDR(0xCC001000); 10 | vu16 __VIRegs[0x3A] AT_ADDR(0xCC002000); 11 | vu32 __PIRegs[0xD] AT_ADDR(0xCC003000); 12 | vu16 __MEMRegs[0x40] AT_ADDR(0xCC004000); 13 | vu16 __DSPRegs[0x20] AT_ADDR(0xCC005000); 14 | vu32 __DIRegs[0x10] AT_ADDR(0xCC006000); 15 | vu32 __SIRegs[0x40] AT_ADDR(0xCC006400); 16 | vu32 __EXIRegs[0x10] AT_ADDR(0xCC006800); 17 | vu32 __AIRegs[0x8] AT_ADDR(0xCC006C00); 18 | vu32 __ACRRegs[0x89] AT_ADDR(0xCD000000); 19 | volatile PPCWGPipe __GXFIFO AT_ADDR(0xCC008000); 20 | vu16 __LT_CHIPREVID AT_ADDR(0xCD8005A0); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | -------------------------------------------------------------------------------- /payload/revolution/base/PPCWGPipe.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef union { 8 | u8 u8; 9 | u16 u16; 10 | u32 u32; 11 | u64 u64; 12 | s8 s8; 13 | s16 s16; 14 | s32 s32; 15 | s64 s64; 16 | f32 f32; 17 | f64 f64; 18 | } PPCWGPipe; 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /payload/revolution/dvd/dvd.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct DVDCommandBlock DVDCommandBlock; 8 | typedef struct DVDFileInfo DVDFileInfo; 9 | typedef struct DVDDiskID DVDDiskID; 10 | 11 | typedef void (*DVDCBCallback)(s32 result, DVDCommandBlock* block); 12 | typedef void (*DVDCallback)(s32 result, DVDFileInfo* fileInfo); 13 | 14 | struct DVDDiskID { 15 | char gameName[4]; 16 | char company[2]; 17 | u8 diskNumber; 18 | u8 gameVersion; 19 | u8 streaming; 20 | u8 streamingBufSize; 21 | u8 padding[14]; 22 | u32 rvlMagic; 23 | u32 gcMagic; 24 | }; 25 | 26 | struct DVDCommandBlock { 27 | DVDCommandBlock* next; 28 | DVDCommandBlock* prev; 29 | u32 command; 30 | s32 state; 31 | u32 offset; 32 | u32 length; 33 | void* addr; 34 | u32 currTransferSize; 35 | u32 transferredSize; 36 | DVDDiskID* id; 37 | DVDCBCallback callback; 38 | void* userData; 39 | }; 40 | 41 | struct DVDFileInfo { 42 | DVDCommandBlock cb; 43 | u32 startAddr; 44 | u32 length; 45 | DVDCallback callback; 46 | }; 47 | 48 | typedef struct { 49 | u32 entryNum; 50 | u32 location; 51 | u32 next; 52 | } DVDDir; 53 | 54 | typedef struct { 55 | u32 entryNum; 56 | u32 isDir; 57 | char* name; 58 | } DVDDirEntry; 59 | 60 | s32 DVDConvertPathToEntrynum(const char* path); 61 | 62 | BOOL DVDFastOpen(s32 entrynum, DVDFileInfo* fileInfo); 63 | BOOL DVDOpen(const char* fileName, DVDFileInfo* fileInfo); 64 | 65 | s32 DVDReadPrio(DVDFileInfo* fileInfo, void* addr, s32 length, s32 offset, s32 prio); 66 | 67 | BOOL DVDClose(DVDFileInfo* fileInfo); 68 | 69 | #ifdef __cplusplus 70 | } 71 | #endif 72 | -------------------------------------------------------------------------------- /payload/revolution/es/es.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | s32 ES_GetDeviceCert(u8* outBuf) { 6 | if (__esFd < 0) 7 | return ES_ERR_INVALID; 8 | 9 | if (!outBuf) 10 | return ES_ERR_INVALID; 11 | 12 | if ((u32)outBuf & 0x1F) 13 | return ES_ERR_INVALID; 14 | 15 | ALIGN(32) IOSIoVector vec = {outBuf, IOSECCCertSize}; 16 | IOS_Ioctlv(__esFd, ES_CMD_GET_DEVICE_CERT, 0, 1, &vec); 17 | return ES_ERR_OK; 18 | } 19 | 20 | s32 ES_Sign(u8* source, u32 size, u8* sig, u8* cert) { 21 | if (__esFd < 0) 22 | return ES_ERR_INVALID; 23 | 24 | if (!source || !size || !sig || !cert) 25 | return ES_ERR_INVALID; 26 | 27 | if ((u32)source & 0x1F || (u32)sig & 0x1F || (u32)cert & 0x1F) 28 | return ES_ERR_INVALID; 29 | 30 | ALIGN(32) IOSIoVector vec[3] = { 31 | {source, size}, {sig, IOSECCSigSize}, {cert, IOSECCCertSize} 32 | }; 33 | 34 | IOS_Ioctlv(__esFd, ES_CMD_SIGN, 1, 2, vec); 35 | return ES_ERR_OK; 36 | } 37 | -------------------------------------------------------------------------------- /payload/revolution/es/es.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef enum { 8 | ES_ERR_OK = 0, 9 | ES_ERR_INCORRECT_CERT_TYPE = -1001, 10 | ES_ERR_GENKEY_FAILED = -1002, 11 | ES_ERR_VERIFY_SIG_FAILED = -1003, 12 | ES_ERR_CANNOT_OPEN_FILE = -1004, 13 | ES_ERR_INCORRECT_PUBKEY_TYPE = -1005, 14 | ES_ERR_CERT_ISSUER_MISMATCH = -1006, 15 | ES_ERR_ENCRYPTION_FAILED = -1007, 16 | ES_ERR_FILE_OPEN_FAILED = -1008, 17 | ES_ERR_FILE_READ_FAILED = -1009, 18 | ES_ERR_FILE_WRITE_FAILED = -1010, 19 | ES_ERR_TMD_NUM_CONTENTS = -1011, 20 | ES_ERR_INCORRECT_SIG_TYPE = -1012, 21 | ES_ERR_INCORRECT_SIG_LENGTH = -1013, 22 | ES_ERR_INCORRECT_CERT_LENGTH = -1014, 23 | ES_ERR_DEV = -1015, 24 | ES_ERR_MAXFD = -1016, 25 | ES_ERR_INVALID = -1017, 26 | ES_ERR_FS_CONNECTION_FAILED = -1018, 27 | ES_ERR_UNSUPPORTED_TRANSFER_SOURCE = -1019, 28 | ES_ERR_DEVICE_ID_MISMATCH = -1020, 29 | ES_ERR_INCORRECT_CONTENT_SIZE = -1021, 30 | ES_ERR_HASH_MISMATCH = -1022, 31 | ES_ERR_INCORRECT_CONTENT_COUNT = -1023, 32 | ES_ERR_OUT_OF_MEMORY = -1024, 33 | ES_ERR_NO_TMD_FILE = -1025, 34 | ES_ERR_NO_RIGHT = -1026, 35 | ES_ERR_ISSUER_NOT_FOUND = -1027, 36 | ES_ERR_NO_TICKET = -1028, 37 | ES_ERR_INCORRECT_TICKET = -1029, 38 | ES_ERR_NOT_ENOUGH_SPACE = -1030, 39 | ES_ERR_INCORRECT_BOOT_VERSION = -1031, 40 | ES_ERR_UNKNOWN = -1032, 41 | ES_ERR_EXPIRED = -1033, 42 | ES_ERR_UNUSED = -1034, 43 | ES_ERR_INCORRECT_TITLE_VERSION = -1035, 44 | ES_ERR_OS_TICKET_NOEXISTS = -1036, 45 | ES_ERR_OS_CONTENT_NOEXISTS = -1037, 46 | ES_ERR_NOT_EMPTY = -1038, 47 | ES_ERR_DISC_NAND_NO_TMD = -1039, 48 | ES_ERR_NOEXISTS = -106, 49 | } ESError; 50 | 51 | typedef enum { 52 | ES_CMD_INVALID, 53 | ES_CMD_IMP_SERVER_TICKET, 54 | ES_CMD_IMP_SERVER_TITLE_INIT, 55 | ES_CMD_IMP_CONTENT_BEGIN, 56 | ES_CMD_IMP_CONTENT_DATA, 57 | ES_CMD_IMP_CONTENT_END, 58 | ES_CMD_IMP_TITLE_DONE, 59 | ES_CMD_GET_DEVICE_ID, 60 | ES_CMD_LAUNCH_TITLE, 61 | ES_CMD_OPEN_CONTENT_FILE, 62 | ES_CMD_READ_CONTENT_FILE, 63 | ES_CMD_CLOSE_CONTENT_FILE, 64 | ES_CMD_LIST_OWNED_TITLES_CNT, 65 | ES_CMD_LIST_OWNED_TITLES, 66 | ES_CMD_LIST_TITLES_ON_CARD_CNT, 67 | ES_CMD_LIST_TITLES_ON_CARD, 68 | ES_CMD_LIST_TITLE_CONTENTS_CNT, 69 | ES_CMD_LIST_TITLE_CONTENTS, 70 | ES_CMD_GET_TICKET_VIEW_CNT, 71 | ES_CMD_GET_TICKET_VIEWS, 72 | ES_CMD_GET_TMD_VIEW_SIZE, 73 | ES_CMD_GET_TMD_VIEW, 74 | ES_CMD_GET_CONSUMPTION, 75 | ES_CMD_DELETE_TITLE, 76 | ES_CMD_DELETE_TICKET, 77 | ES_CMD_DI_GET_TMD_VIEW_SIZE, 78 | ES_CMD_DI_GET_TMD_VIEW, 79 | ES_CMD_DI_GET_TICKET_VIEW, 80 | ES_CMD_DI_VERIFY, 81 | ES_CMD_GET_DATA_DIR, 82 | ES_CMD_GET_DEVICE_CERT, 83 | ES_CMD_IMP_BOOT, 84 | ES_CMD_GET_TITLE_ID, 85 | ES_CMD_SET_UID, 86 | ES_CMD_DELETE_TITLE_CONTENT, 87 | ES_CMD_SEEK_CONTENT_FILE, 88 | ES_CMD_OPEN_TITLE_CONTENT_FILE, 89 | ES_CMD_SWITCH_MODE, 90 | ES_CMD_EXP_BACKUP_TITLE_INIT, 91 | ES_CMD_EXP_CONTENT_BEGIN, 92 | ES_CMD_EXP_CONTENT_DATA, 93 | ES_CMD_EXP_CONTENT_END, 94 | ES_CMD_EXP_TITLE_DONE, 95 | ES_CMD_IMP_BACKUP_TITLE_INIT, 96 | ES_CMD_ENCRYPT, 97 | ES_CMD_DECRYPT, 98 | ES_CMD_GET_BOOT2_VERSION, 99 | ES_CMD_IMP_TITLE_CANCEL, 100 | ES_CMD_SIGN, 101 | ES_CMD_VERIFY_SIGN, 102 | ES_CMD_LIST_TMD_CONTENTS_CNT, 103 | ES_CMD_LIST_TMD_CONTENTS, 104 | ES_CMD_GET_TMD_SIZE, 105 | ES_CMD_GET_TMD, 106 | ES_CMD_LIST_SHARED_CONTENTS_CNT, 107 | ES_CMD_LIST_SHARED_CONTENTS, 108 | ES_CMD_DELETE_SHARED_CONTENT, 109 | ES_CMD_DI_GET_TMD_SIZE, 110 | ES_CMD_DI_GET_TMD, 111 | ES_CMD_DI_VERIFY_WITH_TICKET_VIEW, 112 | ES_CMD_SETUP_STREAM_KEY, 113 | ES_CMD_DELETE_STREAM_KEY, 114 | ES_CMD_DELETE_CONTENT, 115 | } ESCommand; 116 | 117 | s32 ES_GetDeviceCert(u8* outBuf); 118 | s32 ES_Sign(u8* source, u32 size, u8* sig, u8* cert); 119 | 120 | extern int __esFd; 121 | 122 | #ifdef __cplusplus 123 | } 124 | #endif 125 | -------------------------------------------------------------------------------- /payload/revolution/ios.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #define IOSECCCertSize 384 8 | #define IOSECCSigSize 60 9 | 10 | typedef enum { 11 | IPC_OK = 0, 12 | IPC_EACCES = -1, 13 | IPC_EEXIST = -2, 14 | IPC_EINVAL = -4, 15 | IPC_ENOENT = -6, 16 | IPC_EQUEUEFULL = -8, 17 | IPC_ENOMEM = -22, 18 | } IPCResult; 19 | 20 | typedef enum { 21 | IPC_OPEN_NONE = BIT_FLAG(-1), 22 | IPC_OPEN_READ = BIT_FLAG(0), 23 | IPC_OPEN_WRITE = BIT_FLAG(1), 24 | IPC_OPEN_RW = IPC_OPEN_READ | IPC_OPEN_WRITE, 25 | } IPCOpenFlags; 26 | 27 | typedef struct { 28 | void* data; 29 | u32 size; 30 | } IOSIoVector; 31 | 32 | s32 IOS_Open(const char* path, u32 flags); 33 | s32 IOS_Ioctlv(s32 fd, s32 cmd, u32 inputCount, u32 outputCount, IOSIoVector* vector); 34 | s32 IOS_Close(s32 fd); 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | -------------------------------------------------------------------------------- /payload/revolution/mem/allocator.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct MEMAllocator MEMAllocator; 8 | typedef void* (*MEMFuncAllocatorAlloc) (MEMAllocator* allocator, u32 size); 9 | typedef void (*MEMFuncAllocatorFree) (MEMAllocator* allocator, void* memBlock); 10 | 11 | struct MEMAllocatorFunc { 12 | MEMFuncAllocatorAlloc alloc; 13 | MEMFuncAllocatorFree free; 14 | }; 15 | 16 | struct MEMAllocator { 17 | MEMAllocatorFunc* func; 18 | void* heap; 19 | u32 heapParam1; 20 | u32 heapParam2; 21 | }; 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /payload/revolution/mem/heapCommon.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | typedef struct { 10 | u32 signature; 11 | MEMLink link; 12 | MEMList childList; 13 | void* heapStart; 14 | void* heapEnd; 15 | OSMutex mutex; 16 | u8 reserved[3]; 17 | u8 optFlag; 18 | } MEMiHeapHead; 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /payload/revolution/mem/list.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct { 8 | void* prev; 9 | void* next; 10 | } MEMLink; 11 | 12 | typedef struct { 13 | void* head; 14 | void* tail; 15 | u16 count; 16 | u16 offset; 17 | } MEMList; 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /payload/revolution/mtx.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct { 8 | float x, y; 9 | } VEC2; 10 | 11 | typedef struct { 12 | float x, y, z; 13 | } VEC3; 14 | 15 | typedef struct { 16 | float x, y, z, w; 17 | } QUAT; 18 | 19 | typedef struct { 20 | s16 x, y, z; 21 | } S16VEC; 22 | 23 | typedef float MTX33[3][3]; 24 | typedef float MTX34[3][4]; 25 | typedef float MTX44[4][4]; 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | -------------------------------------------------------------------------------- /payload/revolution/os/OS.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // Round API 9 | #define OSRoundUp32B(x) (((u32)(x) + 32 - 1) & ~(32 - 1)) 10 | #define OSRoundDown32B(x) (((u32)(x)) & ~(32 - 1)) 11 | 12 | // Interrupt API 13 | BOOL OSDisableInterrupts(); 14 | BOOL OSEnableInterrupts(); 15 | BOOL OSRestoreInterrupts(BOOL interrupts); 16 | 17 | // Clock API 18 | #define OS_BUS_CLOCK __OSBusClockSpeed 19 | #define OS_TIMER_CLOCK (OS_BUS_CLOCK / 4) 20 | 21 | #define OSTicksToSeconds(ticks) ((ticks) / OS_TIMER_CLOCK) 22 | #define OSTicksToMilliseconds(ticks) ((ticks) / (OS_TIMER_CLOCK / 1000)) 23 | #define OSTicksToMicroseconds(ticks) (((ticks) * 8) / (OS_TIMER_CLOCK / 125000)) 24 | #define OSTicksToNanoseconds(ticks) (((ticks) * 8000) / (OS_TIMER_CLOCK / 125000)) 25 | 26 | #define OSSecondsToTicks(sec) ((sec) * OS_TIMER_CLOCK) 27 | #define OSMillisecondsToTicks(msec) ((msec) * (OS_TIMER_CLOCK / 1000)) 28 | #define OSMicrosecondsToTicks(usec) (((usec) * (OS_TIMER_CLOCK / 125000)) / 8) 29 | #define OSNanosecondsToTicks(nsec) (((nsec) * (OS_TIMER_CLOCK / 125000)) / 8000) 30 | 31 | u32 OSGetTick(); 32 | s64 OSGetTime(); 33 | 34 | inline void OSWait(u32 ticks) { 35 | u32 tick0 = OSGetTick(); 36 | u32 tick1; 37 | do { 38 | tick1 = OSGetTick(); 39 | } while (tick1 - tick0 < ticks); 40 | } 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /payload/revolution/os/OSCache.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void __flush_cache(void* buffer, u32 size); 8 | 9 | void DCStoreRange(void* addr, u32 nBytes); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /payload/revolution/os/OSContext.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct { 8 | u32 gpr[32]; 9 | u32 cr; 10 | u32 lr; 11 | u32 ctr; 12 | u32 xer; 13 | f64 fpr[32]; 14 | u32 fpscr_pad; 15 | u32 fpscr; 16 | u32 srr0; 17 | u32 srr1; 18 | u16 mode; 19 | u16 state; 20 | u32 gqr[8]; 21 | u32 psf_pad; 22 | f64 psf[32]; 23 | } OSContext; 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /payload/revolution/os/OSExec.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct { 8 | u32 valid; 9 | u32 resetCode; 10 | u32 bootDol; 11 | void* arenaLo; 12 | void* arenaHi; 13 | u32 argsUseDefault; 14 | void* args; 15 | } OSExecParams; 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | -------------------------------------------------------------------------------- /payload/revolution/os/OSLog.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | 5 | void OSReport(const char* format, ...); 6 | #define DEBUG_REPORT(...) if (DEBUG) { OSReport(__VA_ARGS__); } 7 | 8 | #ifdef __cplusplus 9 | } 10 | #endif 11 | -------------------------------------------------------------------------------- /payload/revolution/os/OSModule.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct OSModuleInfo OSModuleInfo; 8 | 9 | typedef struct { 10 | OSModuleInfo* next; 11 | OSModuleInfo* prev; 12 | } OSModuleLink; 13 | 14 | typedef struct { 15 | OSModuleInfo* head; 16 | OSModuleInfo* tail; 17 | } OSModuleQueue; 18 | 19 | struct OSModuleInfo { 20 | u32 id; 21 | OSModuleLink link; 22 | u32 numSections; 23 | u32 sectionInfoOffset; 24 | u32 nameOffset; 25 | u32 nameSize; 26 | u32 version; 27 | }; 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | -------------------------------------------------------------------------------- /payload/revolution/os/OSMutex.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | struct OSMutex { 9 | OSThreadQueue queue; 10 | OSThread* thread; 11 | s32 count; 12 | OSMutexLink link; 13 | }; 14 | 15 | void OSLockMutex(OSMutex* mutex); 16 | void OSUnlockMutex(OSMutex* mutex); 17 | BOOL OSTryLockMutex(OSMutex* mutex); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /payload/revolution/os/OSThread.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | typedef struct OSThread OSThread; 9 | typedef struct OSThreadQueue OSThreadQueue; 10 | typedef struct OSThreadLink OSThreadLink; 11 | 12 | typedef struct OSMutex OSMutex; 13 | typedef struct OSMutexQueue OSMutexQueue; 14 | typedef struct OSMutexLink OSMutexLink; 15 | 16 | struct OSThreadQueue { 17 | OSThread* head; 18 | OSThread* tail; 19 | }; 20 | 21 | struct OSThreadLink { 22 | OSThread* next; 23 | OSThread* prev; 24 | }; 25 | 26 | struct OSMutexQueue { 27 | OSMutex* head; 28 | OSMutex* tail; 29 | }; 30 | 31 | struct OSMutexLink { 32 | OSMutex* next; 33 | OSMutex* prev; 34 | }; 35 | 36 | struct OSThread { 37 | OSContext context; 38 | u16 state; 39 | u16 attr; 40 | s32 suspend; 41 | s32 priority; 42 | s32 basePriority; 43 | void* exitVal; 44 | OSThreadQueue* queue; 45 | OSThreadLink link; 46 | OSThreadQueue queueJoin; 47 | OSMutex* mutex; 48 | OSMutexQueue queueMutex; 49 | OSThreadLink linkActive; 50 | u8* stackBase; 51 | u32* stackEnd; 52 | s32 error; 53 | void* specificData[2]; 54 | }; 55 | 56 | OSThread* OSGetCurrentThread(); 57 | 58 | s32 OSDisableScheduler(); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | -------------------------------------------------------------------------------- /payload/revolution/os/OSTitle.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | BOOL OSIsTitleInstalled(u64 titleId); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | -------------------------------------------------------------------------------- /payload/revolution/sc.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef enum { 8 | SC_LANG_JAPANESE, 9 | SC_LANG_ENGLISH, 10 | SC_LANG_GERMAN, 11 | SC_LANG_FRENCH, 12 | SC_LANG_SPANISH, 13 | SC_LANG_ITALIAN, 14 | SC_LANG_DUTCH, 15 | SC_LANG_SIMP_CHINESE, 16 | SC_LANG_TRAD_CHINESE, 17 | SC_LANG_KOREAN, 18 | } SCLanguage; 19 | 20 | u8 SCGetLanguage(); 21 | char* SCGetProductCode(); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /payload/revolution/vi.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void VIWaitForRetrace(); 8 | 9 | #ifdef __cplusplus 10 | } 11 | #endif 12 | -------------------------------------------------------------------------------- /payload/revolutionex/net/NETDigest.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | inline u16 NETReadSwappedBytes16(const u16* src) { 8 | return (u16)__lhbrx(src, 0); 9 | } 10 | 11 | inline u32 NETReadSwappedBytes32(const u32* src) { 12 | return (u32)__lwbrx(src, 0); 13 | } 14 | 15 | inline void NETWriteSwappedBytes16(u16* dst, u16 val) { 16 | __sthbrx(val, dst, 0); 17 | } 18 | 19 | inline void NETWriteSwappedBytes32(u32* dst, u32 val) { 20 | __stwbrx(val, dst, 0); 21 | } 22 | 23 | u32 NETCalcCRC32(const void* data, u32 dataSize); 24 | 25 | typedef struct { 26 | u32 h[5]; // H0, H1, H2, H3, H4 27 | u8 block[64]; // current message block 28 | u32 pool; // current message length 29 | u32 blocks_low; // total blocks in bytes 30 | u32 blocks_high; 31 | } NETSHA1Context; 32 | 33 | void NETSHA1Init(NETSHA1Context* context); 34 | void NETSHA1Update(NETSHA1Context* context, const void* input, u32 length); 35 | void NETSHA1Fill(NETSHA1Context* context, u8 input, u32 length); 36 | void NETSHA1GetDigest(NETSHA1Context* context, void* digest); 37 | 38 | inline void NETCalcSHA1(void* digest, const void* input, u32 length) { 39 | NETSHA1Context context; 40 | 41 | NETSHA1Init(&context); 42 | NETSHA1Update(&context, input, length); 43 | NETSHA1GetDigest(&context, digest); 44 | } 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | -------------------------------------------------------------------------------- /payload/revolutionex/nhttp/NHTTP.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int NHTTPAddPostDataAscii(NHTTPReq* req, const char* label, const char* value); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /payload/revolutionex/nhttp/NHTTPInternal.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct NHTTPRes NHTTPRes; 8 | typedef struct NHTTPReq NHTTPReq; 9 | typedef struct NHTTPReqList NHTTPReqList; 10 | typedef struct NHTTPDataList NHTTPDataList; 11 | 12 | typedef void* (*NHTTPAlloc)(u32 size, int align); 13 | typedef void (*NHTTPFree)(void* ptr); 14 | typedef int (*NHTTPPostSend)(const char* label, char** value, u32* length, int offset, void* param); 15 | 16 | struct NHTTPReq { 17 | volatile int doCancel; 18 | int isStarted; 19 | int isSSL; 20 | int isProxy; 21 | int isRawData; 22 | 23 | int hostLen; 24 | int hostDescLen; 25 | 26 | int method; 27 | int port; 28 | char* url; 29 | char* hostname; 30 | 31 | NHTTPRes* res; 32 | NHTTPDataList* headerList; 33 | NHTTPDataList* postDataList; 34 | 35 | char tagPost[20]; 36 | 37 | char basicUsernamePassword[90]; 38 | int basicUsernamePasswordLen; 39 | 40 | int sslId; 41 | const char* clientCert; 42 | size_t clientCertSize; 43 | const char* privateKey; 44 | size_t privateKeySize; 45 | const char* rootCA; 46 | size_t rootCASize; 47 | int useClientCertDefault; 48 | u32 verifyOption; 49 | int encodingType; 50 | 51 | u32 disableVerifyOption; 52 | u32 rootCAId; 53 | u32 clientCertId; 54 | 55 | char proxyAddr[256]; 56 | int proxyPort; 57 | char proxyUsernamePassword[90]; 58 | int proxyUsernamePasswordLen; 59 | 60 | u32 soRecvSize; 61 | 62 | const char* rawPostData; 63 | u32 rawPostDataLen; 64 | 65 | NHTTPPostSend postSendCallback; 66 | }; 67 | 68 | struct NHTTPReqList { 69 | NHTTPReqList* prev; 70 | NHTTPReqList* next; 71 | int id; 72 | NHTTPReq* req; 73 | void* socket; 74 | }; 75 | 76 | struct NHTTPDataList { 77 | struct NHTTPDataList* prev; 78 | struct NHTTPDataList* next; 79 | const char* label; 80 | const char* value; 81 | u32 length; 82 | int isBinary; 83 | }; 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | -------------------------------------------------------------------------------- /payload/revolutionex/so/SOBasic.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef enum { 8 | SO_PF_UNSPECIFIED = 0, 9 | SO_PF_IPV4 = 2, 10 | SO_PF_IPV6 = 23, 11 | } SOProtocolFamily; 12 | 13 | typedef enum { 14 | SO_SOCK_TCP = 1, 15 | SO_SOCK_UDP = 2, 16 | } SOSocketType; 17 | 18 | typedef enum { 19 | SO_IPPROTO_ICMP = 1, 20 | SO_IPPROTO_IGMP = 2, 21 | SO_IPPROTO_TCP = 6, 22 | SO_IPPROTO_UDP = 17, 23 | } SOProtocolType; 24 | 25 | typedef struct { 26 | u8 len; // size of socket address structure 27 | u8 family; // address family 28 | u16 port; // port number 29 | u32 addr; // ip address 30 | } SOSockAddrIn; 31 | 32 | typedef struct { 33 | char* name; 34 | char** aliases; 35 | s16 addrType; 36 | s16 length; 37 | u32** addrList; 38 | } SOHostEnt; 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | -------------------------------------------------------------------------------- /payload/wiimmfi/Auth.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace Wiimmfi { 7 | namespace Auth { 8 | 9 | /////////////// 10 | // Constants // 11 | /////////////// 12 | 13 | // The possible console types 14 | enum ConsoleType { 15 | CONSOLE_WII = 0x0000, 16 | CONSOLE_WII_MINI = 0x0C01, 17 | CONSOLE_WII_U = 0xCAFE, 18 | CONSOLE_DOLPHIN = 0xFFFF, 19 | }; 20 | 21 | // The payload version we pretend to be on 22 | // This is because the server currently does not let us join with the correct version number 23 | static const char PAYLOAD_VERSION[] = "96"; 24 | 25 | // The patcher type 26 | // This is the pre-encoded version of "OpenPayload" 27 | static const char PATCHER_TYPE[] = "T3BlblBheWxvYWQA"; 28 | 29 | // The heading of each response type 30 | static const char RESPONSE_P2PPORT[] = "p2pport="; 31 | static const char RESPONSE_CONSOLE_ASSIGN[] = "msg="; 32 | static const char RESPONSE_TOKEN[] = "xy="; 33 | 34 | /////////////// 35 | // Functions // 36 | /////////////// 37 | 38 | // Append the aforementioned parameters to the login request, along with some others 39 | void AppendAuthParameters(NHTTPReq* req); 40 | 41 | // Parses the login response 42 | void ParseAuthResponse(const char* response); 43 | 44 | /////////////// 45 | // Variables // 46 | /////////////// 47 | 48 | // The base64-encoded console certificate 49 | extern char sConsoleCert[DWC_Base64GetEncodedSize(IOSECCCertSize)+1]; 50 | 51 | // The console assignment message 52 | // We cannot use an offline message since we need a component of the received one for assignment to work 53 | extern wchar_t* sConsoleAssignMessage; 54 | 55 | } // namespace Auth 56 | } // namespace Wiimmfi 57 | -------------------------------------------------------------------------------- /payload/wiimmfi/Challenge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace Wiimmfi { 6 | namespace Challenge { 7 | 8 | char sChallenge[9]; 9 | 10 | void Save(const char* challenge) { 11 | DEBUG_REPORT("[WIIMMFI_AUTH] Received challenge: %s\n", challenge) 12 | strcpy(sChallenge, challenge); 13 | } 14 | 15 | void Send(qr2_buffer* buffer) { 16 | 17 | // Check if the buffer has the required space for the extra key-value pair 18 | const u32 requiredSpace = sizeof("challenge") + sizeof(sChallenge); 19 | if (buffer->dataSize + requiredSpace > sizeof(buffer->data)) { 20 | DEBUG_REPORT("[WIIMMFI_AUTH] Not enough memory to append challenge!\n") 21 | return; 22 | } 23 | 24 | // Copy the key 25 | char* dest = &buffer->data[buffer->dataSize - 1]; 26 | strcpy(dest, "challenge"); 27 | 28 | // Copy the challenge 29 | strshift(dest, "challenge"); 30 | strcpy(dest, sChallenge); 31 | 32 | // Update the buffer size and store the terminating null byte 33 | buffer->dataSize += requiredSpace; 34 | buffer->data[buffer->dataSize - 1] = '\0'; 35 | } 36 | 37 | } // namespace Challenge 38 | } // namespace Wiimmfi 39 | -------------------------------------------------------------------------------- /payload/wiimmfi/Challenge.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Wiimmfi { 5 | namespace Challenge { 6 | 7 | // Saves the received challenge 8 | void Save(const char* challenge); 9 | 10 | // Sends the saved challenge 11 | void Send(qr2_buffer* buffer); 12 | 13 | } // namespace Challenge 14 | } // namespace Wiimmfi 15 | -------------------------------------------------------------------------------- /payload/wiimmfi/ConnectionMatrix.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace Wiimmfi { 10 | namespace ConnectionMatrix { 11 | 12 | u32 sRecvConnMtx[12]; 13 | 14 | void ResetRecv() { 15 | 16 | // Get the node info for the aid, if it's null reset the received matrix 17 | for (int aid = 0; aid < 12; aid++) { 18 | if (!DWCi_NodeInfoList_GetNodeInfoForAid(aid)) 19 | sRecvConnMtx[aid] = 0; 20 | } 21 | } 22 | 23 | void Update() { 24 | 25 | // Failsafe 26 | if (!stpMatchCnt) 27 | return; 28 | 29 | // Lock interrupts 30 | nw4r::ut::AutoInterruptLock lock; 31 | 32 | // Compute the connection matrix 33 | u32 aidsConnectedToMe = 0; 34 | for (int i = 0; i < stpMatchCnt->nodeInfoList.nodeCount; i++) { 35 | u32 aid = stpMatchCnt->nodeInfoList.nodeInfos[i].aid; 36 | if (DWCi_GetGT2Connection(aid)) 37 | aidsConnectedToMe |= 1 << i; 38 | } 39 | 40 | // Report it to the server and share it with the clients 41 | Reporting::ReportConnectionMatrix(aidsConnectedToMe); 42 | MatchCommand::SendConnMtxCommand(aidsConnectedToMe); 43 | } 44 | 45 | } // namespace ConnectionMatrix 46 | } // namespace Wiimmfi 47 | -------------------------------------------------------------------------------- /payload/wiimmfi/ConnectionMatrix.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Wiimmfi { 4 | namespace ConnectionMatrix { 5 | 6 | /////////////// 7 | // Functions // 8 | /////////////// 9 | 10 | // Resets the received connection matrixes 11 | void ResetRecv(); 12 | 13 | // Updates the connection matrix and shares it with the server and the connected clients 14 | void Update(); 15 | 16 | /////////////// 17 | // Variables // 18 | /////////////// 19 | 20 | // The other clients' received connection matrixes 21 | // Currently unused 22 | extern u32 sRecvConnMtx[12]; 23 | 24 | } // namespace ConnectionMatrix 25 | } // namespace Wiimmfi 26 | -------------------------------------------------------------------------------- /payload/wiimmfi/Delay.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace Wiimmfi { 6 | namespace Delay { 7 | 8 | u32 sMatchStartTime; 9 | u32 sCumulativeDelay; 10 | u32 sCurrentDelay; 11 | 12 | u32 GetTime() { 13 | 14 | // If we are on Dolphin, use the IOCTL 15 | if (DolphinDevice::Open()) { 16 | u32 time = DolphinDevice::GetElapsedTime(); 17 | return (time != 0) ? time : current_time(); 18 | } 19 | 20 | // Else just use the game function 21 | return current_time(); 22 | } 23 | 24 | void Calc(u32 frameCount) { 25 | 26 | // Do not do anything if the frame count is 0 27 | if (frameCount == 0) 28 | return; 29 | 30 | // If the match start time is not set, do so 31 | if (sMatchStartTime == 0) 32 | sMatchStartTime = GetTime(); 33 | 34 | // Calculate the total frames elapsed since race start 35 | u32 timeElapsed = GetTime() - sMatchStartTime; 36 | float framesElapsed = timeElapsed / (1000.0f / 60.0f); 37 | u32 framesElapsed32 = (u32)framesElapsed; 38 | 39 | // Calculate the delay 40 | int delay = framesElapsed32 - frameCount - sCumulativeDelay; 41 | if (delay > 0) { 42 | sCurrentDelay = delay; 43 | DEBUG_REPORT("[WIIMMFI_TIME] Detected delay of %d frames\n", delay); 44 | } 45 | } 46 | 47 | u32 Apply(u32 timer) { 48 | 49 | // Get the current delay and transfer it to the cumulative delay 50 | int currDelay = sCurrentDelay; 51 | sCumulativeDelay += currDelay; 52 | 53 | // Reset the current delay and return the updated timer 54 | sCurrentDelay = 0; 55 | return timer + currDelay + 1; 56 | } 57 | 58 | } // namespace Delay 59 | } // namespace Wiimmfi 60 | -------------------------------------------------------------------------------- /payload/wiimmfi/Delay.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Wiimmfi { 4 | namespace Delay { 5 | 6 | /////////////// 7 | // Functions // 8 | /////////////// 9 | 10 | // Calculates the delay 11 | void Calc(u32 frameCount); 12 | 13 | // Applies the delay to the given timer 14 | u32 Apply(u32 timer); 15 | 16 | /////////////// 17 | // Variables // 18 | /////////////// 19 | 20 | // The time the match started 21 | extern u32 sMatchStartTime; 22 | 23 | // The delay accumulated during the entire match 24 | extern u32 sCumulativeDelay; 25 | 26 | // The delay accumulated between the latest two frames 27 | extern u32 sCurrentDelay; 28 | 29 | } // namespace Delay 30 | } // namespace Wiimmfi 31 | -------------------------------------------------------------------------------- /payload/wiimmfi/Domains.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // NOTE: regular Kamek does not support kmWriteArea, up to you to deal with this 4 | 5 | // Authentication server 6 | kmWriteArea(0x8027A428, "http://naswii.wiimmfi.de/ac"); 7 | 8 | // Profanity check server (i think) 9 | kmWriteArea(0x8027A4A8, "http://naswii.wiimmfi.de/pr"); 10 | 11 | // Various domain replacements 12 | kmWriteArea(0x8027AD68, "wiimmfi.de"); // AVAILABLE 13 | kmWriteArea(0x8027B4D8, "wiimmfi.de"); // GPCM 14 | kmWriteArea(0x8027BEF0, "wiimmfi.de"); // GPSP 15 | kmWriteArea(0x8027D091, "wiimmfi.de"); // MASTER 16 | kmWriteArea(0x8027DCAB, "wiimmfi.de"); // NATNEG1 17 | kmWriteArea(0x8027DCC7, "wiimmfi.de"); // NATNEG2 18 | kmWriteArea(0x8027DCE3, "wiimmfi.de"); // NATNEG3 19 | kmWriteArea(0x8027DE33, "wiimmfi.de"); // MS 20 | 21 | // SAKE domains for completeness' sake (pun intended) 22 | kmWriteArea(0x80279D58, "http://%s.sake.gs.wiimmfi.de/SakeStorageServer/StorageServer.asmx"); 23 | kmWriteArea(0x80279DA4, "http://%s.sake.gs.wiimmfi.de/SakeFileServer/upload.asmx"); 24 | kmWriteArea(0x80279DE4, "http://%s.sake.gs.wiimmfi.de/SakeFileServer/download.asmx"); 25 | kmWriteArea(0x8027DEB7, "wiimmfi.de"); 26 | kmWriteArea(0x8027E0A0, "http://%s.sake.gs.wiimmfi.de/SakeStorageServer/StorageServer.asmx"); 27 | kmWriteArea(0x8089A6B8, "http://mariokartwii.sake.gs.wiimmfi.de/SakeFileServer/ghostdownload.aspx?gameid=1687®ion=0"); 28 | kmWriteArea(0x8089ABD0, "http://mariokartwii.race.gs.wiimmfi.de/RaceService/NintendoRacingService.asmx"); 29 | kmWriteArea(0x8089AC25, "http://mariokartwii.race.gs.wiimmfi.de/RaceService/NintendoRacingService.asmx"); 30 | kmWriteArea(0x8089AC85, "%s://mariokartwii.sake.gs.wiimmfi.de/SakeFileServer/ghostupload.aspx?gameid=%d®ionid=%d&courseid=%d&score=%d&pid=%d&playerinfo=%s%s"); 31 | kmWrite8(0x8089AD16, '\0'); 32 | -------------------------------------------------------------------------------- /payload/wiimmfi/Kick.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Wiimmfi { 9 | namespace Kick { 10 | 11 | u32 sAidsToBeKicked = 0; 12 | bool sMustEndRace = false; 13 | 14 | void ScheduleForAID(int aid) { 15 | DEBUG_REPORT("[WIIMMFI_KICK] Scheduled kick for aid %d\n", aid) 16 | sAidsToBeKicked |= (1 << aid); 17 | } 18 | 19 | void ScheduleForAIDs(u32 aids) { 20 | DEBUG_REPORT("[WIIMMFI_KICK] Scheduled kick for aids %08X\n", aids) 21 | sAidsToBeKicked |= aids; 22 | } 23 | 24 | void ScheduleForEveryone() { 25 | DEBUG_REPORT("[WIIMMFI_KICK] Scheduled kick for all aids\n") 26 | sAidsToBeKicked = 0xFFFFFFFF; 27 | } 28 | 29 | void CalcKick() { 30 | 31 | // If the aid bitfield is empty, bail 32 | if (!sAidsToBeKicked) 33 | return; 34 | 35 | // Lock interrupts 36 | nw4r::ut::AutoInterruptLock lock; 37 | DEBUG_REPORT("[WIIMMFI_KICK] Running kick task with aids %08X\n", sAidsToBeKicked) 38 | 39 | // If the bitfield is full, close all connections immediately 40 | if (sAidsToBeKicked == 0xFFFFFFFF) 41 | DWC_CloseAllConnectionsHard(); 42 | 43 | // Otherwise kick each aid separately 44 | else { 45 | for (int i = 0; i < 12; i++) { 46 | if (sAidsToBeKicked >> i & 1) 47 | DWC_CloseConnectionHard(i); 48 | } 49 | } 50 | 51 | // Reset the bitfield 52 | sAidsToBeKicked = 0; 53 | } 54 | 55 | int ParseKickMessage(GPConnection conn, char* data) { 56 | 57 | // Ignore kick commands if we don't have the necessary structures 58 | if (!stpMatchCnt || stpMatchCnt->nodeInfoList.nodeCount > 1) 59 | return GP_ERROR_NONE; 60 | 61 | // If the kick command isn't found, bail 62 | char* kickCmd = strstr(data, KICK_MSG); 63 | if (!kickCmd) 64 | return GP_ERROR_NONE; 65 | 66 | // Obtain the kick type 67 | strshift(kickCmd, KICK_MSG); 68 | u32 kickType = strtoul(kickCmd, nullptr, 10); 69 | DEBUG_REPORT("[WIIMMFI_KICK] Received kick type ", kickType) 70 | 71 | // Act based on the kick type 72 | switch (kickType) { 73 | 74 | // Use CloseConnectionHard to kick everyone (HOST ONLY) 75 | case EVERYONE: 76 | DEBUG_REPORT("EVERYONE\n") 77 | if (!DWC_IsServerMyself()) { 78 | DEBUG_REPORT("[WIIMMFI_KICK] But ignored (not host).\n") 79 | break; 80 | } 81 | 82 | ScheduleForEveryone(); 83 | break; 84 | 85 | // Pretend to cause a network error and kick ourselves 86 | case SELF: 87 | DEBUG_REPORT("SELF\n") 88 | DWCi_HandleGPError(GP_ERROR_NETWORK); 89 | return GP_ERROR_MEMORY; 90 | 91 | // Force end the race 92 | case END_RACE: 93 | DEBUG_REPORT("END_RACE\n") 94 | sMustEndRace = true; 95 | break; 96 | 97 | // Kick a specific player (HOST ONLY) 98 | case SPECIFIC_PLAYER: 99 | DEBUG_REPORT("PLAYER\n") 100 | if (!DWC_IsServerMyself()) { 101 | DEBUG_REPORT("[WIIMMFI_KICK] But ignored (not host).\n") 102 | break; 103 | } 104 | 105 | // Get the kickpid parameter, if not found bail 106 | char* pidKickParam = strstr(kickCmd, KICK_MSG_PARAM_PID); 107 | if (!pidKickParam) { 108 | DEBUG_REPORT("[WIIMMFI_KICK] But ignored (no PID specified).\n") 109 | break; 110 | } 111 | 112 | // Shift the string and read the pid to an integer 113 | strshift(pidKickParam, KICK_MSG_PARAM_PID); 114 | u32 pidToKick = strtoul(pidKickParam, nullptr, 10); 115 | 116 | // Get the node info 117 | // If it exists, kick the corresponding aid 118 | DWCNodeInfo* node = DWCi_NodeInfoList_GetNodeInfoForProfileId(pidToKick); 119 | if (!node) { 120 | DEBUG_REPORT("[WIIMMFI_KICK] But ignored (AID not found).\n") 121 | break; 122 | } 123 | 124 | ScheduleForAID(node->aid); 125 | break; 126 | 127 | default: 128 | DEBUG_REPORT("UNKNOWN (%d)\n", kickType); 129 | } 130 | 131 | return GP_ERROR_NONE; 132 | } 133 | 134 | } // namespace Kick 135 | } // namespace Wiimmfi 136 | -------------------------------------------------------------------------------- /payload/wiimmfi/Kick.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Wiimmfi { 5 | namespace Kick { 6 | 7 | /////////////// 8 | // Constants // 9 | /////////////// 10 | 11 | // The possible kick types 12 | enum Type { 13 | NONE, 14 | EVERYONE, 15 | SELF, 16 | END_RACE, 17 | SPECIFIC_PLAYER, 18 | }; 19 | 20 | // The server message for kicking and pid to kick 21 | static const char KICK_MSG[] = "\\wiimmfi\\kick"; 22 | static const char KICK_MSG_PARAM_PID[] = "\\kickpid\\"; 23 | 24 | /////////////// 25 | // Functions // 26 | /////////////// 27 | 28 | // Schedules a kick for the given AID 29 | void ScheduleForAID(int aid); 30 | 31 | // Schedules a kick for the AIDs in the given bitmap 32 | void ScheduleForAIDs(u32 aidMap); 33 | 34 | // Schedules a kick for everyone in the room 35 | void ScheduleForEveryone(); 36 | 37 | // Runs the kicking task 38 | void CalcKick(); 39 | 40 | // Parses a kick message received from the server 41 | int ParseKickMessage(GPConnection conn, char* data); 42 | 43 | /////////////// 44 | // Variables // 45 | /////////////// 46 | 47 | // If the race should be stopped immediately (used by kick type END_RACE) 48 | extern bool sMustEndRace; 49 | 50 | } // namespace Kick 51 | } // namespace Wiimmfi 52 | -------------------------------------------------------------------------------- /payload/wiimmfi/MatchCommand.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Wiimmfi { 4 | namespace MatchCommand { 5 | 6 | //////////////// 7 | // Structures // 8 | //////////////// 9 | 10 | // The structure for DWC_CMD_CONN_FAIL_MTX 11 | // This command is sent by client A to the host to tell them client B could not complete NATNEG with them 12 | // The host then sends a NEW_PID_AID command to client B to try and solve the problem quicker 13 | struct DWCMatchCommandConnFailMtx { 14 | u32 connFailMtx; 15 | }; 16 | 17 | // The structure for DWC_CMD_CONN_MTX 18 | // This command is sent by client A to client B to inform them of the aids connected to them 19 | // This is used by client B to route network packets through a random aid (chosen among those connected to 20 | // A and including the host) in case P2P fails. The entire feature seems to be unused, however 21 | struct DWCMatchCommandConnMtx { 22 | u32 connMtx; 23 | }; 24 | 25 | /////////////// 26 | // Functions // 27 | /////////////// 28 | 29 | // Parse custom commands 30 | // Returns true if the command was recognized and parsed 31 | bool ProcessRecvMatchCommand(u8 cmd, int profileId, u32 publicIp, u16 publicPort, void* cmdData, int dataLen); 32 | 33 | // Sends a DWC_CMD_CONN_FAIL_MTX command to the host 34 | // The data required for the command is in the arguments 35 | void SendConnFailMtxCommand(u32 aidsConnectedToHost, u32 aidsConnectedToMe); 36 | 37 | // Sends a DWC_CMD_CONN_MTX command to all the connected clients 38 | // The data required for the command is in the arguments 39 | void SendConnMtxCommand(u32 aidsConnectedToMe); 40 | 41 | } // namespace MatchCommand 42 | } // namespace Wiimmfi 43 | -------------------------------------------------------------------------------- /payload/wiimmfi/Natify.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace Wiimmfi { 12 | namespace Natify { 13 | 14 | bool sDoingNatify; 15 | NatifyData sNatifyData; 16 | 17 | void Callback(BOOL success, NAT* theNat) { 18 | 19 | // If NATify was successful, copy the data over 20 | sDoingNatify = false; 21 | if (success) { 22 | 23 | DEBUG_REPORT("[NATIFY] NATify done for PID %d\n", stpMatchCnt->profileId) 24 | sNatifyData.profileId = stpMatchCnt->profileId; 25 | sNatifyData.portRestricted = nat.portRestricted; 26 | sNatifyData.ipRestricted = nat.ipRestricted; 27 | sNatifyData.natPromiscuity = nat.promiscuity; 28 | sNatifyData.natType = nat.type; 29 | sNatifyData.natMappingScheme = nat.mappingScheme; 30 | sNatifyData.qr2Compatible = nat.qr2Compatible; 31 | } 32 | } 33 | 34 | int CopyData(u8* buffer) { 35 | memcpy(buffer, &sNatifyData, sizeof(sNatifyData)); 36 | return sizeof(sNatifyData) + 1; 37 | } 38 | 39 | void Start() { 40 | DEBUG_REPORT("[NATIFY] Started NATify procedure\n") 41 | sDoingNatify = true; 42 | NNStartNatDetection(Callback); 43 | } 44 | 45 | void Update() { 46 | if (sDoingNatify) 47 | NegotiateThink(nullptr); 48 | } 49 | 50 | } // namespace Natify 51 | } // namespace Wiimmfi 52 | -------------------------------------------------------------------------------- /payload/wiimmfi/Natify.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #pragma pack(push, 1) 3 | 4 | namespace Wiimmfi { 5 | namespace Natify { 6 | 7 | //////////////// 8 | // Structures // 9 | //////////////// 10 | 11 | // The data saved on NATify success 12 | struct NatifyData { 13 | u32 profileId; 14 | bool portRestricted; 15 | bool ipRestricted; 16 | u8 natPromiscuity; 17 | u8 natType; 18 | u8 natMappingScheme; 19 | bool qr2Compatible; 20 | }; 21 | 22 | /////////////// 23 | // Functions // 24 | /////////////// 25 | 26 | // Copies the NATify result data into the given buffer 27 | // Returns the size of the copied data 28 | int CopyData(u8* buffer); 29 | 30 | // Start NATify procedure 31 | void Start(); 32 | 33 | // Update NATify procedure until it succeeds 34 | void Update(); 35 | 36 | } // namespace Natify 37 | } // namespace Wiimmfi 38 | 39 | #pragma pack(pop) 40 | -------------------------------------------------------------------------------- /payload/wiimmfi/Natneg.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace Wiimmfi { 6 | namespace Natneg { 7 | 8 | // Updates the NATNEG timers for Fast NATNEG 9 | void CalcTimers(bool connectedToHost); 10 | 11 | // Override of DWCi_GT2ConnectAttemptCallback to accept multiple incoming connections at once 12 | void ConnectAttemptCallback(GT2Socket socket, GT2Connection conn, u32 ip, u16 port, int latency, 13 | const char* msg, int msgLen); 14 | 15 | // Override of DWCi_GT2ConnectedCallback to accept multiple incoming connections at once 16 | void ConnectedCallback(GT2Connection conn, GT2Result result, const char* msg, int msgLen); 17 | 18 | // Improves the next NATNEG node choosing algorithm used by Nintendo by choosing the lowest 19 | // retry time and ignoring the maximum retry count limit 20 | DWCNodeInfo* GetNextMeshMakingNode(); 21 | 22 | // Checks NATNEG attempts to prevent the host from disconnecting due to repeated NATNEG failures 23 | // with the same client 24 | // Returns true if the attempt should count toward the Error 86420 threshold 25 | bool PreventRepeatNATNEGFail(u32 failedPid); 26 | 27 | // Attempt to recover from a SYN-ACK timeout (i think) 28 | void RecoverSynAckTimeout(); 29 | 30 | // Stops NATNEG after a certain amount of time has passed (only applies to guests) 31 | void StopNATNEGAfterTime(); 32 | 33 | } // namespace Natneg 34 | } // namespace Wiimmfi 35 | -------------------------------------------------------------------------------- /payload/wiimmfi/Port.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | u16 Wiimmfi::Port::sPort; 5 | -------------------------------------------------------------------------------- /payload/wiimmfi/Port.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Wiimmfi { 4 | namespace Port { 5 | 6 | // The P2P port received from Wiimmfi in the authentication stage 7 | extern u16 sPort; 8 | 9 | } // namespace Port 10 | } // namespace Wiimmfi 11 | -------------------------------------------------------------------------------- /payload/wiimmfi/Reporting.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Contains all Wiimmfi telemetry 5 | namespace Wiimmfi { 6 | namespace Reporting { 7 | 8 | /////////////// 9 | // Constants // 10 | /////////////// 11 | 12 | // Constants for formatting SHA1 hashes 13 | static const int HASH_STRING_SIZE = sizeof("1234567812345678123456781234567812345678"); 14 | static const char HASH_STRING_FMT[] = "%08x%08x%08x%08x%08x"; 15 | 16 | /////////////// 17 | // Functions // 18 | /////////////// 19 | 20 | // Reports the AID to PID map when it changes 21 | void ReportAIDPIDMap(); 22 | 23 | // Reports the battle results - UNUSED 24 | // void ReportBattleResults(); 25 | 26 | // Reports various Common.szs subfiles that can be modified for cheating 27 | void ReportCommonSubfiles(); 28 | 29 | // Reports the connection matrix 30 | void ReportConnectionMatrix(u32 aidsConnectedToMe); 31 | 32 | // Reports various course subfiles for possible track identification/cheat detection 33 | void ReportCourseSubfiles(); 34 | 35 | // Reports the race finish time of the given local player 36 | void ReportFinishTime(u8 playerIdx); 37 | 38 | // Reports the frame count at certain intervals 39 | void ReportFrameCount(u32 frameCount); 40 | 41 | // Reports a room start 42 | void ReportFriendRoomStart(RKNetROOMPacket* packet); 43 | 44 | // Reports the AID of the host when it changes 45 | void ReportHostSlotChange(); 46 | 47 | // Reports a match state change, if it has happened 48 | void ReportMatchStateChange(); 49 | 50 | // Reports the race stage 51 | void ReportRaceStage(u32 stage); 52 | 53 | // Reports a region change 54 | void ReportRegionChange(); 55 | 56 | // Reports information extracted from the SELECT packet 57 | void ReportSELECTInfo(); 58 | 59 | // Reports host disconnections 60 | void ReportServerDown(u32 cmd, u32 pid, u32* data); 61 | 62 | // Reports the console signature and certificate 63 | void ReportSignatureAndCert(); 64 | 65 | // Reports NATNEG suspend updates 66 | void ReportSuspendUpdate(); 67 | 68 | // Reports the given track SHA1 hash 69 | void ReportTrackHash(u32* hash, u8 courseId); 70 | 71 | /////////////// 72 | // Variables // 73 | /////////////// 74 | 75 | // The next frame when a frame report will be sent 76 | extern u32 sTargetFrameCount; 77 | 78 | } // namespace Reporting 79 | } // namespace Wiimmfi 80 | -------------------------------------------------------------------------------- /payload/wiimmfi/RoomStall.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace Wiimmfi { 8 | namespace RoomStall { 9 | 10 | u16 sKickTimer; 11 | 12 | void Init() { 13 | sKickTimer = 0; 14 | } 15 | 16 | void Update() { 17 | 18 | // Check if the player is the host, if not bail 19 | if (!RKNetController::instance->isPlayerHost()) 20 | return; 21 | 22 | // Update the timer and check that it hasn't reached the threshold 23 | if (sKickTimer++ < KICK_THRESHOLD_TIME) 24 | return; 25 | 26 | // Reset the timer if the threshold is reached 27 | sKickTimer = 0; 28 | 29 | // Get the full aid map 30 | RKNetController::Sub* sub = RKNetController::instance->getCurrentSub(); 31 | RKNetSELECTHandler* sel = RKNetSELECTHandler::instance; 32 | u32 aidMap = sub->availableAids | (1 << sub->myAid); 33 | 34 | // Get the list of aids that have not completed the loading procedure, depending on the phase 35 | u32 incompleteAids = 0; 36 | switch(sel->sendPacket.phase) { 37 | 38 | case RKNetSELECTPacket::PREPARE: 39 | incompleteAids = (~sel->aidsWithNewSelect) & aidMap; 40 | if (incompleteAids == 0) 41 | incompleteAids = (~sel->aidsWithNewRaceSettings) & aidMap; 42 | break; 43 | 44 | case RKNetSELECTPacket::VOTING: 45 | incompleteAids = (~sel->aidsThatHaveVoted) & aidMap; 46 | if (incompleteAids == 0) 47 | incompleteAids = (~sel->aidsWithVoteData) & aidMap; 48 | break; 49 | 50 | default: 51 | break; 52 | } 53 | 54 | // Kick the AIDs 55 | DEBUG_REPORT("[WIIMMFI_KICK] Detected room stall with AIDs %08X\n", incompleteAids) 56 | Kick::ScheduleForAIDs(incompleteAids); 57 | } 58 | 59 | } // namespace RoomStall 60 | } // namespace Wiimmfi 61 | -------------------------------------------------------------------------------- /payload/wiimmfi/RoomStall.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Wiimmfi { 4 | namespace RoomStall { 5 | 6 | /////////////// 7 | // Constants // 8 | /////////////// 9 | 10 | // The timer before stalled users are kicked, in frames 11 | static const int KICK_THRESHOLD_TIME = 60 * 60; 12 | 13 | /////////////// 14 | // Functions // 15 | /////////////// 16 | 17 | // Initializes the room stall timer 18 | void Init(); 19 | 20 | // Updates the room stall timer and kicks players if necessary 21 | void Update(); 22 | 23 | } // namespace RoomStall 24 | } // namespace Wiimmfi 25 | -------------------------------------------------------------------------------- /payload/wiimmfi/Security.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Wiimmfi { 9 | namespace Security { 10 | 11 | // TODO rewrite with worldwide support 12 | bool IsPacketSectionSizeValid(int section, u32 sectionSize) { 13 | 14 | // Skip empty sections 15 | if (sectionSize == 0) 16 | return true; 17 | 18 | // The check depends on each section 19 | u32 destSize = RKNetController::packetBufferSizes[section]; 20 | switch (section) { 21 | 22 | // For EVENT packets, ensure the size fits the buffer as it is variable 23 | case RKNetRACEPacketHeader::EVENT: 24 | return sectionSize <= destSize; 25 | 26 | // For ROOM/SELECT packets, ensure the size matches one of the two possible values 27 | case RKNetRACEPacketHeader::ROOM_SELECT: 28 | return (sectionSize == sizeof(RKNetROOMPacket) || sectionSize == sizeof(RKNetSELECTPacket)); 29 | 30 | // For RACEDATA and ITEM packets, ensure the size is either half or the full buffer size 31 | case RKNetRACEPacketHeader::RACEDATA: 32 | case RKNetRACEPacketHeader::ITEM: 33 | return (sectionSize == destSize / 2 || sectionSize == destSize); 34 | 35 | // For all other sections, match exactly the default size 36 | default: 37 | return sectionSize == destSize; 38 | } 39 | } 40 | 41 | // Code ported from WiiLink24's WFC patcher 42 | bool ValidateRACEPacket(u32 aid, RKNetRACEPacketHeader* data, u32 dataLength) { 43 | 44 | // Verify each section size is valid 45 | // Do this separately as the sizes may be valid but may not add up 46 | u32 expectedPacketSize = 0; 47 | for (int i = 0; i < RKNetRACEPacketHeader::SECTION_COUNT; i++) { 48 | expectedPacketSize += data->sizes[i]; 49 | if (!IsPacketSectionSizeValid(i, data->sizes[i])) 50 | return false; 51 | } 52 | 53 | // Ensure the declared sizes match the cumulative size 54 | if (dataLength < expectedPacketSize) 55 | return false; 56 | 57 | // Verify each section's data is valid 58 | u8* packetData = (u8*)data; 59 | for (int i = 0; i < RKNetRACEPacketHeader::SECTION_COUNT; i++) { 60 | if (!ModSupport::IsPacketSectionDataValid(i, packetData, data->sizes[i])) 61 | return false; 62 | 63 | packetData += data->sizes[i]; 64 | } 65 | 66 | // All checks passed, we're ready to go! 67 | return true; 68 | } 69 | 70 | } // namespace Security 71 | } // namespace Wiimmfi 72 | -------------------------------------------------------------------------------- /payload/wiimmfi/Security.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace Wiimmfi { 5 | namespace Security { 6 | 7 | // Validates a RACE packet to prevent invalid data from being transmitted 8 | // This function assumes a full packet header, adjust checks accordingly 9 | // Returns true if valid 10 | bool ValidateRACEPacket(u32 aid, RKNetRACEPacketHeader* data, u32 dataLength); 11 | 12 | } // namespace Security 13 | } // namespace Wiimmfi 14 | -------------------------------------------------------------------------------- /payload/wiimmfi/Status.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace Wiimmfi { 13 | namespace Status { 14 | 15 | char* sToken; 16 | char sScrambledToken[96]; 17 | 18 | void DecodeToken(const char* encodedToken) { 19 | 20 | // Get the decoded token size 21 | int encodedLen = strlen(encodedToken); 22 | int decodedLen = DWC_Base64Decode(encodedToken, encodedLen, nullptr, 0); 23 | sToken = new (KAMEK_HEAP, 32) char[decodedLen+1]; 24 | 25 | // Decode the token 26 | decodedLen = DWC_Base64Decode(encodedToken, encodedLen, sToken, decodedLen); 27 | sToken[decodedLen] = '\0'; 28 | 29 | // Start by filling an ASCII table 30 | for (int i = 0; i < strlenconst(sScrambledToken); i++) { 31 | sScrambledToken[i] = i + ' '; 32 | } 33 | 34 | // Check if the token was decoded correctly 35 | if (decodedLen > 0) { 36 | 37 | // Run ASCII substitution 38 | const char key[] = "0123456789,abcdefghijklmnopqrstuvwxyz|=+-_"; 39 | for (int i = 0; i < decodedLen && i < strlenconst(key); i++) { 40 | char c = sToken[i]; 41 | char pos = key[i]; 42 | sScrambledToken[pos - ' '] = c; 43 | } 44 | } 45 | } 46 | 47 | void ScrambleMessage(char* msg, int msgLen) { 48 | for (int i = 0; i < msgLen; i++) { 49 | u8 c = msg[i] - ' '; 50 | if (c < strlenconst(sScrambledToken)) 51 | msg[i] = sScrambledToken[c]; 52 | } 53 | } 54 | 55 | void SendMessage(const char* key, const char* value, int integerValue) { 56 | 57 | // Check that the match control structure exists 58 | if (!stpMatchCnt || !stpMatchCnt->gpConnection) 59 | return; 60 | 61 | // Get connection 62 | GPConnection conn = stpMatchCnt->gpConnection; 63 | if (!*conn) { 64 | DEBUG_REPORT("[WIIMMFI_REPORT] Connection not initialized, discarding message\n") 65 | return; 66 | } 67 | 68 | // Print the message to the buffer 69 | DEBUG_REPORT("[WIIMMFI_REPORT] %s=%s,%d\n", key, value, integerValue) 70 | char buffer[599]; 71 | int len = snprintf(buffer, sizeof(buffer), "\\xy\\%s\\v\\1\\id\\%d\\msg\\%s\\final\\", 72 | key, integerValue, value); 73 | 74 | // If the printed string did not fit in the buffer, bail 75 | if (len > sizeof(buffer)) { 76 | DEBUG_REPORT("[WIIMMFI_REPORT] Message length exceeded buffer (size=%d), discarding\n", len) 77 | return; 78 | } 79 | 80 | // Scramble the message 81 | ScrambleMessage(buffer + strlenconst(STATUS_HEADER), 82 | len - strlenconst(STATUS_TERMINATOR) - strlenconst(STATUS_HEADER)); 83 | 84 | // Lock interrupts and append message 85 | { 86 | nw4r::ut::AutoInterruptLock lock; 87 | gpiAppendStringToBuffer(conn, &(*conn)->outputBuffer, buffer); 88 | } 89 | } 90 | 91 | } // namespace Status 92 | } // namespace Wiimmfi 93 | -------------------------------------------------------------------------------- /payload/wiimmfi/Status.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace Wiimmfi { 4 | namespace Status { 5 | 6 | /////////////// 7 | // Constants // 8 | /////////////// 9 | 10 | // Header and terminator string for each status report 11 | static const char STATUS_HEADER[] = "\\xy\\"; 12 | static const char STATUS_TERMINATOR[] = "\\final\\"; 13 | 14 | /////////////// 15 | // Functions // 16 | /////////////// 17 | 18 | // Decode the token received from the server and scrambles it 19 | void DecodeToken(const char* encodedToken); 20 | 21 | // Sends a status message to the server 22 | void SendMessage(const char* key, const char* value, int integerValue = -1); 23 | 24 | /////////////// 25 | // Variables // 26 | /////////////// 27 | 28 | // The token received on login (will be deleted on network shutdown) 29 | extern char* sToken; 30 | 31 | } // namespace Port 32 | } // namespace Wiimmfi 33 | --------------------------------------------------------------------------------