diff --git a/include/CrossplayHooks.h b/include/CrossplayHooks.h new file mode 100644 index 0000000..2405ee6 --- /dev/null +++ b/include/CrossplayHooks.h @@ -0,0 +1,7 @@ +#ifdef RB3E_WII +#include "rb3/BinStream.h" + +extern void GetUserDataWriteHook(BinStream *this, void *data, int size); +extern void GetUserDataWriteEndianHook(BinStream *this, int size); +extern void GetUserDataReadHook(BinStream *this, void *data, int size); +#endif \ No newline at end of file diff --git a/include/GlobalSymbols.h b/include/GlobalSymbols.h index b157f5e..405f74b 100644 --- a/include/GlobalSymbols.h +++ b/include/GlobalSymbols.h @@ -24,6 +24,10 @@ typedef struct _GlobalSymbols Symbol mirrorMode; Symbol blackBackground; +#ifdef RB3E_WII + Symbol useCrossplayNetcode; +#endif + // gem widgets Symbol greenGem; Symbol redGem; diff --git a/include/PropSyncHooks.h b/include/PropSyncHooks.h new file mode 100644 index 0000000..ac5801f --- /dev/null +++ b/include/PropSyncHooks.h @@ -0,0 +1,3 @@ +#include "rb3/Data.h" + +extern int PropSyncHook(char *value, DataNode *unk, DataArray *dataArray, int unk3, int propOp); \ No newline at end of file diff --git a/include/ports.h b/include/ports.h index 7e3068b..95a423a 100644 --- a/include/ports.h +++ b/include/ports.h @@ -108,6 +108,9 @@ #define PORT_SONGSORTBYRECENT 0x8265bde8 // RecentCmp::__ct #define PORT_FILESTREAM_CT 0x827c3340 // FileStream::__ct (the one that takes a char * path instead of a File object) #define PORT_CHUNKSTREAM_CT 0x827ca488 // ChunkStream::__ct +#define PORT_BINSTREAMWRITE 0x827c4f58 // BinStream::Write +#define PORT_BINSTREAMREAD 0x827c4ea8 // BinStream::Read +#define PORT_BINSTREAMWRITEENDIAN 0x827c5098 // BinStream::WriteEndian // instance addresses #define PORT_MODIFIERMGR_POINTER 0x82dfec08 // pointer to ModifierManager #define PORT_ROCKCENTRALGATEWAY 0x82cc8f60 // address of RockCentralGateway @@ -209,6 +212,10 @@ void DbgPrint(const char *s, ...); #define PORT_GETMETADATA 0x80515510 // BandSongMgr::Data (function renamed from the original name to avoid any confusion with Data.h) #define PORT_GETSONGID 0x8051513c // GetSongID, function used when adding songs to BandSongMgr #define PORT_GETSONGIDFROMSHORTNAME 0x801d0b44 // BandSongMgr::GetSongIDFromShortname +#define PORT_BINSTREAMWRITE 0x80342f48 // BinStream::Write +#define PORT_BINSTREAMREAD 0x80342e7c // BinStream::Read +#define PORT_BINSTREAMWRITEENDIAN 0x800a7638 // BinStream::WriteEndian +#define PORT_PROPSYNCBOOL 0x800fd3d4 // PropSync::Bool // instance addresses #define PORT_MODIFIERMGR_POINTER 0x808fda68 // pointer to ModifierManager #define PORT_ROCKCENTRALGATEWAY 0x80900870 // address of RockCentralGateway diff --git a/include/rb3/BinStream.h b/include/rb3/BinStream.h index 49b12a6..0606110 100644 --- a/include/rb3/BinStream.h +++ b/include/rb3/BinStream.h @@ -28,4 +28,8 @@ struct _BinStream BinStream_vtable *vtable; }; +extern void BinstreamWrite(void *thisBinStream, void *data, int size); +extern void BinstreamRead(void *thisBinStream, void *data, int size); +extern void BinstreamWriteEndian(void *thisBinStream, int size); + #endif // _BINSTREAM_H \ No newline at end of file diff --git a/include/rb3/PropSync.h b/include/rb3/PropSync.h new file mode 100644 index 0000000..15f710b --- /dev/null +++ b/include/rb3/PropSync.h @@ -0,0 +1,3 @@ +#include "rb3/Data.h" + +int PropSyncBool(char *value, DataNode *unk, DataArray *dataArray, int unk3, int propOp); \ No newline at end of file diff --git a/include/rb3_include.h b/include/rb3_include.h index ac1126b..b4a8629 100644 --- a/include/rb3_include.h +++ b/include/rb3_include.h @@ -23,6 +23,7 @@ #include "rb3/MusicLibrary.h" #include "rb3/Object.h" #include "rb3/PassiveMessagesPanel.h" +#include "rb3/PropSync.h" #include "rb3/Random.h" #include "rb3/RockCentralGateway.h" #include "rb3/SongMetadata.h" diff --git a/include/rb3e_include.h b/include/rb3e_include.h index 32be785..f3000b0 100644 --- a/include/rb3e_include.h +++ b/include/rb3e_include.h @@ -4,6 +4,7 @@ #include "rb3_include.h" #include "config.h" #include "crc32.h" +#include "CrossplayHooks.h" #include "DTAFunctions.h" #include "GameHooks.h" #include "GemHooks.h" @@ -18,6 +19,7 @@ #include "OvershellHooks.h" #include "ports.h" #include "ppcasm.h" +#include "PropSyncHooks.h" #include "rb3enhanced.h" #include "SetlistHooks.h" #include "SongHooks.h" diff --git a/source/CrossplayHooks.c b/source/CrossplayHooks.c new file mode 100644 index 0000000..1e85d3f --- /dev/null +++ b/source/CrossplayHooks.c @@ -0,0 +1,91 @@ +#ifdef RB3E_WII + +#include "rb3e_include.h" + +// TODO: Rework every bit of this +// they are fast enough and since they only run once when a player connects, they shouldnt cause any issues, but they are still ugly + +void GetUserDataWriteHook(BinStream *this, void *data, int size) +{ + int i = 0; + char hexString[size * 2 + 1]; // +1 for null terminator + unsigned char *byteData = (unsigned char *)data; + Modifier *crossplayModifier; + + crossplayModifier = ModifierActive(*(int *)PORT_MODIFIERMGR_POINTER, globalSymbols.useCrossplayNetcode, 0); + + if (crossplayModifier->enabled) + { + + int strLength = ((char *)data)[7]; // get the username length + + // i dont care for this way of detecting if the packet is already "ps3ified", figure out a better way to detect it + // TODO: improve this + if (strLength > 15) + { + BinstreamWrite(this, data, size); + return; + } + + // this is what will be stored on the "recent players" list on PS3, its the true PSN/RPCN username + // all nulls causes a syscall for adding recent players to fail, but doesnt impact anything else + char empty[0x24] = {0x69, 0x68, 0x61, 0x74, 0x65, 0x63, 0x6F, 0x6D, 0x70, 0x76, 0x69, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + BinstreamWrite(this, data, 8); // write first 8 bytes + BinstreamWrite(this, data + 8, strLength); // write the original username + BinstreamWrite(this, (void *)empty, 36); // write 36 empty bytes + BinstreamWrite(this, data + 8 + strLength + 4, size - 12 - strLength); // write the rest of the data + } + else + { + BinstreamWrite(this, data, size); + } + return; +} + +void GetUserDataWriteEndianHook(BinStream *this, int size) +{ + Modifier *crossplayModifier; + + crossplayModifier = ModifierActive(*(int *)PORT_MODIFIERMGR_POINTER, globalSymbols.useCrossplayNetcode, 0); + + if (crossplayModifier->enabled) + { + return BinstreamWriteEndian(this, size + 0x20); + } + else + { + return BinstreamWriteEndian(this, size); + } +} + +void GetUserDataReadHook(BinStream *this, void *data, int size) +{ + int streamCounter = 0; + int strLength = 0; + int i = 0; + char empty[0x24] = {0}; + Modifier *crossplayModifier; + + crossplayModifier = ModifierActive(*(int *)PORT_MODIFIERMGR_POINTER, globalSymbols.useCrossplayNetcode, 0); + + if (crossplayModifier->enabled) + { + + BinstreamRead(this, data, 8); + strLength = ((char *)data)[7]; + BinstreamRead(this, (char *)data + 8, strLength); + BinstreamRead(this, (void *)empty, 0x24); + memcpy((char *)data + 8 + strLength, "\x00\x00\x00\x00", 4); // use empty pid on wii + BinstreamRead(this, (char *)data + 8 + strLength + 4, size - 8 - strLength - 0x24); + + unsigned char *byteData = (unsigned char *)data; + } + else + { + BinstreamRead(this, data, size); + } + return; +} + +#endif \ No newline at end of file diff --git a/source/GlobalSymbols.c b/source/GlobalSymbols.c index 4220f61..cd1bce0 100644 --- a/source/GlobalSymbols.c +++ b/source/GlobalSymbols.c @@ -20,6 +20,9 @@ void InitGlobalSymbols() SymbolConstruct(&globalSymbols.colorShuffle, "mod_color_shuffle"); SymbolConstruct(&globalSymbols.forceHopos, "mod_force_hopos"); SymbolConstruct(&globalSymbols.mirrorMode, "mod_mirror_mode"); +#ifdef RB3E_WII + SymbolConstruct(&globalSymbols.useCrossplayNetcode, "mod_use_crossplay_netcode"); +#endif SymbolConstruct(&globalSymbols.greenGem, "gem_green.wid"); SymbolConstruct(&globalSymbols.redGem, "gem_red.wid"); diff --git a/source/LocaleHooks.c b/source/LocaleHooks.c index bb261e9..4ec17da 100644 --- a/source/LocaleHooks.c +++ b/source/LocaleHooks.c @@ -36,6 +36,9 @@ static char *newLocales[][2] = { {"mod_force_hopos", "Force HOPOs"}, {"mod_mirror_mode", "Mirror Mode (Guitar Only)"}, {"mod_color_shuffle", "Gem Color Shuffle"}, +#ifdef RB3E_WII + {"mod_use_crossplay_netcode", "Crossplay (PS3/Wii)"}, +#endif }; static int numNewLocales = sizeof(newLocales) / sizeof(newLocales[0]); diff --git a/source/PropSyncHooks.c b/source/PropSyncHooks.c new file mode 100644 index 0000000..cdb4b33 --- /dev/null +++ b/source/PropSyncHooks.c @@ -0,0 +1,18 @@ +#include "rb3/PropSync.h" + +#ifdef RB3E_WII + +// TODO: find a simpler way to do this, if possible, preferably without needing a hook +int PropSyncHook(char *value, DataNode *unk, DataArray *dataArray, int unk3, int propOp) +{ + if (dataArray->mNodeCount != 0 && dataArray->mNodes->n[0].type == SYMBOL) + { + if (strcmp(dataArray->mNodes->n[0].value.string, "multi_event") == 0) + { + *value = 1; + } + } + + return PropSyncBool(value, unk, dataArray, unk3, propOp); +} +#endif \ No newline at end of file diff --git a/source/_functions.c b/source/_functions.c index 56b1cc3..a1588fe 100644 --- a/source/_functions.c +++ b/source/_functions.c @@ -44,6 +44,9 @@ RB3E_STUB(GetBandUsers) RB3E_STUB(GetBandUserFromSlot) RB3E_STUB(ChunkStreamConstructor) RB3E_STUB(FileStreamConstructor) +RB3E_STUB(BinstreamWrite) +RB3E_STUB(BinstreamRead) +RB3E_STUB(BinstreamWriteEndian) // hooked function stubs RB3E_STUB(Localize) RB3E_STUB(SetVenue) @@ -72,3 +75,4 @@ RB3E_STUB(SongSortByRecent) RB3E_STUB(GetSymbolByGameOrigin) RB3E_STUB(GetGameOriginBySymbol) RB3E_STUB(SongMgrGetRankedSongs) +RB3E_STUB(PropSyncBool) diff --git a/source/rb3enhanced.c b/source/rb3enhanced.c index e769e66..9c0e147 100644 --- a/source/rb3enhanced.c +++ b/source/rb3enhanced.c @@ -100,6 +100,11 @@ void *ModifierManagerConstructorHook(int thisModifierManager, int unk) ExecuteDTA(PORT_ROCKCENTRALGATEWAY, "{do{push_back {find $syscfg modifiers modifiers} (mod_force_hopos)}}"); ExecuteDTA(PORT_ROCKCENTRALGATEWAY, "{do{push_back {find $syscfg modifiers modifiers} (mod_mirror_mode)}}"); ExecuteDTA(PORT_ROCKCENTRALGATEWAY, "{do{push_back {find $syscfg modifiers modifiers} (mod_color_shuffle)}}"); + + // wii specific modifiers +#ifdef RB3E_WII + ExecuteDTA(PORT_ROCKCENTRALGATEWAY, "{do{push_back {find $syscfg modifiers modifiers} (mod_use_crossplay_netcode)}}"); +#endif return ModifierManagerConstructor(thisModifierManager, unk); } @@ -149,6 +154,15 @@ void ApplyPatches() // Patch out erroneous second host header POKE_32(PORT_NASWII_HOST, NOP); + // remove registration of unused wii netmessage (RequestEnterFlowMsg, doesn't exist on PS3 and is unused on Wii, but will fuck up indices in packets on the PS3 side so needs to be removed) + POKE_32(0x8021f974, NOP); + + // change part of Quazal RV short version to 0x1b0 to match PS3 + POKE_32(0x8007b3d4, LI(6, 0x1b0)); + + // disable forced video venues when hosting online on wii + POKE_32(0x80228390, NOP); + // always take the branch to 0x8024a628 so vocals can be selected without a mic plugged in POKE_32(PORT_MICCHECK, 0x42800140); #elif RB3E_XBOX @@ -215,6 +229,9 @@ void InitialiseFunctions() POKE_B(&GetBandUserFromSlot, PORT_GETBANDUSERFROMSLOT); POKE_B(&FileStreamConstructor, PORT_FILESTREAM_CT); POKE_B(&ChunkStreamConstructor, PORT_CHUNKSTREAM_CT); + POKE_B(&BinstreamWrite, PORT_BINSTREAMWRITE); + POKE_B(&BinstreamRead, PORT_BINSTREAMREAD); + POKE_B(&BinstreamWriteEndian, PORT_BINSTREAMWRITEENDIAN); RB3E_MSG("Functions initialized!", NULL); } @@ -246,6 +263,25 @@ void ApplyHooks() #ifdef RB3E_WII // wii exclusive hooks HookFunction(PORT_USBWIIGETTYPE, &UsbWiiGetType, &UsbWiiGetTypeHook); HookFunction(PORT_WIINETINIT_DNSLOOKUP, &StartDNSLookup, &StartDNSLookupHook); + HookFunction(PORT_PROPSYNCBOOL, &PropSyncBool, &PropSyncHook); // hook to restore Wii venue intros for crossplay + + ///////////////////// + // crossplay hooks // + ///////////////////// + + // patch user data in all applicable messages + POKE_BL(0x800b92f8, &GetUserDataWriteHook); + POKE_BL(0x800b8794, &GetUserDataWriteHook); + POKE_BL(0x800b8d2c, &GetUserDataWriteHook); + POKE_BL(0x800b8f7c, &GetUserDataWriteHook); + POKE_BL(0x800b89ec, &GetUserDataReadHook); + POKE_BL(0x800b8dfc, &GetUserDataReadHook); + POKE_BL(0x800b93e0, &GetUserDataReadHook); + POKE_BL(0x800b90c4, &GetUserDataReadHook); + POKE_BL(0x800b9028, &GetUserDataWriteEndianHook); + POKE_BL(0x800b9358, &GetUserDataWriteEndianHook); + POKE_BL(0x800b8d80, &GetUserDataWriteEndianHook); + POKE_BL(0x800b88c4, &GetUserDataWriteEndianHook); #elif RB3E_XBOX // 360 exclusive hooks HookFunction(PORT_STAGEKIT_SET_STATE, &StagekitSetState, &StagekitSetStateHook); HookFunction(PORT_SETSONGNAMEFROMNODE, &SetSongNameFromNode, &SetSongNameFromNodeHook); diff --git a/source/wii_files.c b/source/wii_files.c index 386163c..e19c162 100644 --- a/source/wii_files.c +++ b/source/wii_files.c @@ -27,7 +27,8 @@ char *RB3E_GetRawfilePath(char *path, int root_allowed) int path_length = strlen(path); int i = 0; // if the drive isn't mounted, don't bother - RB3E_Mounted = 0; + if (RB3E_Mounted == 0) + return NULL; // if its bigger than this, we're unsafe, we might buffer overflow if (path_length > sizeof(corrected_path)) return NULL;