/** * Copyright (c) 2026 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "network/network.h" #include "util/memory.h" #include "util/string.h" #include "assert/assert.h" #include "display/displaysdl2.h" errorret_t networkPSPInit() { // Requests the PSP to load the network modules. int ret; ret = sceUtilityLoadNetModule(PSP_NET_MODULE_COMMON); if(ret < 0) errorThrow("Failed to init NET COMMON: 0x%08X", ret); ret = sceUtilityLoadNetModule(PSP_NET_MODULE_INET); if(ret < 0) errorThrow("Failed to init NET INET: 0x%08X", ret); // ret = sceUtilityLoadNetModule(PSP_NET_MODULE_PARSEURI); // if(ret < 0) errorThrow("Failed to init NET PARSEURI: 0x%08X", ret); // ret = sceUtilityLoadNetModule(PSP_NET_MODULE_PARSEHTTP); // if(ret < 0) errorThrow("Failed to init NET PARSEHTTP: 0x%08X", ret); // ret = sceUtilityLoadNetModule(PSP_NET_MODULE_SSL); // if(ret < 0) errorThrow("Failed to init NET SSL: 0x%08X", ret); // ret = sceUtilityLoadNetModule(PSP_NET_MODULE_HTTP); // if(ret < 0) errorThrow("Failed to init NET HTTP: 0x%08X", ret); // ret = sceSslInit(0x28000); // if(ret < 0) errorThrow("sceSslInit failed: 0x%08X", ret); // ret = sceHttpInit(0x25800); // if(ret < 0) errorThrow("sceHttpInit failed: 0x%08X", ret); // ret = sceHttpsInit(0, 0, 0, 0); // if(ret < 0) errorThrow("sceHttpsInit failed: 0x%08X", ret); // ret = sceHttpsLoadDefaultCert(0, 0); // if(ret < 0) errorThrow("sceHttpsLoadDefaultCert failed: 0x%08X", ret); // ret = sceHttpLoadSystemCookie(); // if(ret < 0) errorThrow("sceHttpLoadSystemCookie failed: 0x%08X", ret); // All good. errorOk(); } errorret_t networkPSPUpdate() { int ret; if(NETWORK.state == NETWORK_STATE_CONNECTING) { switch(sceUtilityNetconfGetStatus()) { case PSP_UTILITY_DIALOG_INIT: break; case PSP_UTILITY_DIALOG_NONE: NETWORK.state = NETWORK_STATE_DISCONNECTED; errorThrow("PSP Netconf dialog disappeared without result"); break; case PSP_UTILITY_DIALOG_VISIBLE: // 1 is mandatory? ret = sceUtilityNetconfUpdate(1); if(ret != 0) { errorThrow("sceUtilityNetconfUpdate failed: 0x%08X", ret); } break; case PSP_UTILITY_DIALOG_QUIT: ret = sceUtilityNetconfShutdownStart(); if(ret != 0) { errorThrow("sceUtilityNetconfShutdownStart failed: 0x%08X", ret); } break; case PSP_UTILITY_DIALOG_FINISHED: // Did we connect? int apState = 0; sceNetApctlGetState(&apState); if(apState == PSP_NET_APCTL_STATE_GOT_IP) { NETWORK.state = NETWORK_STATE_CONNECTED; assertNotNull( NETWORK.platform.onConnected, "Network platform onConnected callback should be set." ); NETWORK.platform.onConnected(NETWORK.platform.onConnectedUser); } else { NETWORK.state = NETWORK_STATE_DISCONNECTED; assertNotNull( NETWORK.platform.onFailed, "Network platform onFailed callback should be set." ); // Kill the PSP network stack. errorret_t err = networkPSPTerm(); if(err.code != ERROR_OK) { errorCatch(errorPrint(err)); } errorret_t error = errorThrowImpl( &NETWORK.errorState, ERROR_NOT_OK, __FILE__, __func__, __LINE__, "Failed to connect to network" ); NETWORK.platform.onFailed(error, NETWORK.platform.onConnectedUser); } break; default: errorThrow("Unknown PSP Netconf dialog status: %d", sceUtilityNetconfGetStatus()); } } errorOk(); } errorret_t networkPSPDispose() { sceUtilityNetconfGetStatus(); errorCatch(errorPrint(networkPSPTerm())); sceUtilityUnloadNetModule(PSP_NET_MODULE_HTTP); sceUtilityUnloadNetModule(PSP_NET_MODULE_INET); sceUtilityUnloadNetModule(PSP_NET_MODULE_COMMON); errorOk(); } bool_t networkPSPIsConnected() { return NETWORK.state == NETWORK_STATE_CONNECTED; } void networkPSPRequestConnection( void (*onConnected)(void *user), void (*onFailed)(errorret_t error, void *user), void (*onDisconnect)(errorret_t error, void *user), void *user ) { assertTrue( NETWORK.state == NETWORK_STATE_CONNECTING, "Network host should be in a connecting state." ); NETWORK.platform.onConnected = onConnected; NETWORK.platform.onFailed = onFailed; NETWORK.platform.onConnectedUser = user; int ret; // Init the PSP network stack. ret = sceNetInit(0x20000, 0x20, 4096, 0x20, 4096); assertTrue(ret >= 0, "Failed to init net: 0x%08X"); ret = sceNetInetInit(); assertTrue(ret >= 0, "Failed to init net inet: 0x%08X"); ret = sceNetResolverInit(); assertTrue(ret >= 0, "Failed to init net resolver: 0x%08X"); ret = sceNetApctlInit(0x1800, 0x30); assertTrue(ret >= 0, "Failed to init net apctl: 0x%08X"); // This is all related to getting the PSP online, refer to; // https://github.com/joel16/CMFileManager-PSP/blob/00dab16c64cd48bf6452fc274a3b898d77c39a8d/app/source/net.cpp#L97 // since I follow this implementation closely. memoryZero(&NETWORK.platform.dialogData, sizeof(NETWORK.platform.dialogData)); memoryZero(&NETWORK.platform.dialogAdhoc, sizeof(NETWORK.platform.dialogAdhoc)); NETWORK.platform.dialogData.base.size = sizeof(pspUtilityNetconfData); NETWORK.platform.dialogData.base.language = systemPSPGetLanguage(); NETWORK.platform.dialogData.base.buttonSwap = systemPSPGetCrossButtonSetting(); NETWORK.platform.dialogData.base.graphicsThread = 17; NETWORK.platform.dialogData.base.accessThread = 19; NETWORK.platform.dialogData.base.fontThread = 18; NETWORK.platform.dialogData.base.soundThread = 16; NETWORK.platform.dialogData.action = PSP_NETCONF_ACTION_CONNECTAP; NETWORK.platform.dialogData.adhocparam = ( &NETWORK.platform.dialogAdhoc ); ret = sceUtilityNetconfInitStart(&NETWORK.platform.dialogData); assertTrue(ret >= 0, "Failed to init netconf"); } void networkPSPRequestDisconnection( void (*onComplete)(void *user), void *user ) { assertTrue( NETWORK.state == NETWORK_STATE_DISCONNECTING, "Network host should be in a disconnecting state." ); errorret_t err = networkPSPTerm(); if(err.code != ERROR_OK) { errorCatch(errorPrint(err)); } NETWORK.state = NETWORK_STATE_DISCONNECTED; onComplete(user); } errorret_t networkPSPTerm() { int ret; ret = sceNetApctlTerm(); if(ret < 0) { errorThrow("Failed to terminate netctl: 0x%08X", ret); } ret = sceNetResolverTerm(); if(ret < 0) { errorThrow("Failed to terminate net resolver: 0x%08X", ret); } ret = sceNetInetTerm(); if(ret < 0) { errorThrow("Failed to terminate net inet: 0x%08X", ret); } ret = sceNetTerm(); if(ret < 0) { errorThrow("Failed to terminate net: 0x%08X", ret); } errorOk(); }