Hi, I was recently told about the Level 256 plugin for playing Yo-kai Watch online using local wireless mode (UDS).
I started looking into this with Pokémon ORAS to see if something similar could be done – I managed to find the main USD functions that initialize, create a network, endpoints, etc. I’m attaching the code below.
The last step would then be to use a 3DS (a master node that creates the network), I suppose, and have the clients connect to it. But since it’s local wireless, how can we forward that to a server that would propagate the information? Do we also need to hook into the socket functions and replace the destination IP address with that of the server, or something like that? I’m waiting for your ideas on how to achieve this.
Also, local wireless mode is limited to about ten 3DS systems, so I don’t see how it would be possible for 100 people or more to connect to the network like on the old PSS.
PS: I don’t have two 3DS systems, which greatly limits my ability to test or make progress on the project.
I started looking into this with Pokémon ORAS to see if something similar could be done – I managed to find the main USD functions that initialize, create a network, endpoints, etc. I’m attaching the code below.
The last step would then be to use a 3DS (a master node that creates the network), I suppose, and have the clients connect to it. But since it’s local wireless, how can we forward that to a server that would propagate the information? Do we also need to hook into the socket functions and replace the destination IP address with that of the server, or something like that? I’m waiting for your ideas on how to achieve this.
Also, local wireless mode is limited to about ten 3DS systems, so I don’t see how it would be possible for 100 people or more to connect to the network like on the old PSS.
PS: I don’t have two 3DS systems, which greatly limits my ability to test or make progress on the project.
Code:
#include <CTRPluginFramework.hpp>
#define CALL_ORIGINAL_FUNC( retType, ... ) \
CTRPluginFramework::HookContext::GetCurrent().OriginalFunction< retType >( __VA_ARGS__ );
#define SETUP_HOOK( addr, func ) \
do \
{ \
CTRPluginFramework::Hook hook; \
hook.InitializeForMitm( addr, (u32)func ); \
hook.Enable(); \
} while ( 0 );
#define PRINT( pText, ... ) \
CTRPluginFramework::OSD::Notify( CTRPluginFramework::Utils::Format( pText, __VA_ARGS__ ) )
u32 UDS_Initialize( void* event, void* buffer, u32 bufferSize )
{
u32 res = CALL_ORIGINAL_FUNC( u32, event, buffer, bufferSize );
PRINT( "[UDS::Initialize] res=%08X", res );
return res;
}
u32 UDS_Finalize()
{
u32 res = CALL_ORIGINAL_FUNC( u32 );
PRINT( "[UDS::Finalize] res=%08X", res );
return res;
}
u32 UDS_Scan( void* buffer, u32 bufferSize, u8 subID, u32 localID )
{
u32 res = CALL_ORIGINAL_FUNC( u32, buffer, bufferSize, subID, localID );
PRINT( "[UDS::Scan] res=%08X", res );
return res;
}
u32 UDS_CreateNetwork( u8 subID, u8 max, u32 localID, char* key, u32 length )
{
u32 res = CALL_ORIGINAL_FUNC( u32, subID, max, localID, key, length );
PRINT( "[UDS::CreateNetwork] res=%08X", res );
return res;
}
u32 UDS_DestroyNetwork( void )
{
u32 res = CALL_ORIGINAL_FUNC( u32 );
PRINT( "[UDS::DestroyNetwork] res=%08X", res );
return res;
}
u32 UDS_ConnectNetwork( void* desc, u8 type, char* key, u32 length )
{
u32 res = CALL_ORIGINAL_FUNC( u32, type, key, length );
PRINT( "[UDS::ConnectNetwork] res=%08X", res );
return res;
}
u32 UDS_CreateEndpoint( void* desc )
{
u32 res = CALL_ORIGINAL_FUNC( u32, desc );
PRINT( "[UDS::CreateEndpoint] res=%08X", res );
return res;
}
u32 UDS_DestroyEndpoint( void* desc )
{
u32 res = CALL_ORIGINAL_FUNC( u32, desc );
PRINT( "[UDS::DestroyEndpoint] res=%08X", res );
return res;
}
u32 UDS_SendTo( void* desc, void* data, u32 dataSize, u16 nodeID, u8 port, u8 opt )
{
u32 res = CALL_ORIGINAL_FUNC( u32, desc, data, dataSize, nodeID, port, opt );
PRINT( "[UDS::SendTo] res=%08X", res );
return res;
}
u32 UDS_Attach( void* desc, u16 srcID, u8 port, u32 bufferSize )
{
u32 res = CALL_ORIGINAL_FUNC( u32, desc, srcID, port, bufferSize );
PRINT( "[UDS::Attach] res=%08X", res );
return res;
}
u32 UDS_ReceiveFrom( void* desc, void* buffer, u32* recvSize, u16* srcID, u32 bufferSize, u8 opt )
{
u32 res = CALL_ORIGINAL_FUNC( u32, desc, buffer, recvSize, srcID, bufferSize, opt );
PRINT( "[UDS::ReceiveFrom] res=%08X", res );
return res;
}
void SetupHooks( void )
{
SETUP_HOOK( 0x002C39B8, UDS_Initialize );
SETUP_HOOK( 0x002C5E38, UDS_Finalize );
SETUP_HOOK( 0x002C4B24, UDS_Scan );
SETUP_HOOK( 0x002C3DC0, UDS_CreateNetwork );
SETUP_HOOK( 0x002C41BC, UDS_DestroyNetwork );
SETUP_HOOK( 0x002C3FE0, UDS_ConnectNetwork );
SETUP_HOOK( 0x002C40D4, UDS_CreateEndpoint );
SETUP_HOOK( 0x002C422C, UDS_DestroyEndpoint );
SETUP_HOOK( 0x002C4E14, UDS_SendTo );
SETUP_HOOK( 0x002C4CB8, UDS_Attach );
SETUP_HOOK( 0x002C3BD0, UDS_ReceiveFrom );
}
namespace CTRPluginFramework {
int main( void )
{
SetupHooks();
PluginMenu* menu = new PluginMenu();
menu->SynchronizeWithFrame( true );
menu->Run();
delete menu;
return 0;
}
} // namespace CTRPluginFramework
Last edited by Zetta_D,






