diff --git a/src/duskpsp/network/networkpsp.c b/src/duskpsp/network/networkpsp.c index 7cb09db6..0fabb08c 100644 --- a/src/duskpsp/network/networkpsp.c +++ b/src/duskpsp/network/networkpsp.c @@ -9,8 +9,11 @@ #include "util/memory.h" #include "util/string.h" #include "assert/assert.h" -#include "display/displaysdl2.h" -#include "display/shader/shadergl.h" +#include "time/time.h" + +// How long to wait for sceNetApctlConnect() to reach +// PSP_NET_APCTL_STATE_GOT_IP before giving up and reporting failure. +#define NETWORK_PSP_CONNECT_TIMEOUT 15.0f errorret_t networkPSPInit() { // Requests the PSP to load the network modules. @@ -18,7 +21,7 @@ errorret_t networkPSPInit() { 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); @@ -54,129 +57,55 @@ errorret_t networkPSPInit() { } errorret_t networkPSPUpdate() { - int ret; - if(NETWORK.state == NETWORK_STATE_CONNECTING) { - switch(sceUtilityNetconfGetStatus()) { - case PSP_UTILITY_DIALOG_INIT: - break; + if(NETWORK.state != NETWORK_STATE_CONNECTING) errorOk(); - case PSP_UTILITY_DIALOG_NONE: - NETWORK.state = NETWORK_STATE_DISCONNECTED; - errorThrow("PSP Netconf dialog disappeared without result"); - break; + int apState = 0; + int ret = sceNetApctlGetState(&apState); - case PSP_UTILITY_DIALOG_VISIBLE: - // The dialog renders using whatever GL state we leave lying - // around, immediately before it draws - it doesn't set up its - // own blend/cull/depth/texture state from scratch. Match exactly - // what our own text rendering uses (displaySetState's - // BLEND-only flags, plus shaderUnlitSetMaterial's texture/color - // setup), otherwise its text/icons render missing while its - // untextured chrome still appears fine. - glDisable(GL_CULL_FACE); - errorChain(errorGLCheck()); - glDisable(GL_DEPTH_TEST); - errorChain(errorGLCheck()); - glEnable(GL_BLEND); - errorChain(errorGLCheck()); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - errorChain(errorGLCheck()); + if(ret < 0 || TIME.time >= NETWORK.platform.connectTimeoutAt) { + NETWORK.state = NETWORK_STATE_DISCONNECTED; - glEnable(GL_TEXTURE_2D); - errorChain(errorGLCheck()); - glBindTexture(GL_TEXTURE_2D, TEXTURE_WHITE.id); - errorChain(errorGLCheck()); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - errorChain(errorGLCheck()); - glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - errorChain(errorGLCheck()); - SHADER_LEGACY.boundTextureId = TEXTURE_WHITE.id; + assertNotNull( + NETWORK.platform.onFailed, + "Network platform onFailed callback should be set." + ); - // pspGL defers actually applying state to the GPU until the - // next real draw call - the calls above alone may be no-ops - // on hardware. Force a flush with a degenerate (zero-area, so - // nothing actually rasterizes) triangle. - const float_t degenerate[3 * 5] = { - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - }; - const GLsizei stride = sizeof(float_t) * 5; - glVertexPointer(3, GL_FLOAT, stride, °enerate[0]); - errorChain(errorGLCheck()); - glTexCoordPointer(2, GL_FLOAT, stride, °enerate[3]); - errorChain(errorGLCheck()); - glDrawArrays(GL_TRIANGLES, 0, 3); - errorChain(errorGLCheck()); + sceNetApctlDisconnect(); - // 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(errorIsNotOk(err)) { - 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() - ); + errorret_t err = networkPSPTerm(); + if(errorIsNotOk(err)) { + 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); + errorOk(); + } + + 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); } errorOk(); } errorret_t networkPSPDispose() { - sceUtilityNetconfGetStatus(); errorCatch(errorPrint(networkPSPTerm())); sceUtilityUnloadNetModule(PSP_NET_MODULE_HTTP); sceUtilityUnloadNetModule(PSP_NET_MODULE_INET); sceUtilityUnloadNetModule(PSP_NET_MODULE_COMMON); - + errorOk(); } @@ -214,30 +143,14 @@ void networkPSPRequestConnection( 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) + // Connect using the first saved connection profile - no dialog, no GU + // rendering involved. If this fails to even start (e.g. no profile + // exists), let networkPSPUpdate() report it the same way as any other + // connection failure on the very next frame, rather than crashing here. + ret = sceNetApctlConnect(1); + NETWORK.platform.connectTimeoutAt = ( + ret >= 0 ? TIME.time + NETWORK_PSP_CONNECT_TIMEOUT : TIME.time ); - - 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( @@ -249,6 +162,8 @@ void networkPSPRequestDisconnection( "Network host should be in a disconnecting state." ); + sceNetApctlDisconnect(); + errorret_t err = networkPSPTerm(); if(errorIsNotOk(err)) { errorCatch(errorPrint(err)); diff --git a/src/duskpsp/network/networkpsp.h b/src/duskpsp/network/networkpsp.h index e8b50889..fd7ddf6b 100644 --- a/src/duskpsp/network/networkpsp.h +++ b/src/duskpsp/network/networkpsp.h @@ -8,13 +8,13 @@ #pragma once #include "error/error.h" #include "network/networkinfo.h" -#include "system/systempsp.h" #include #include #include #include #include #include +#include #include // #define NETWORK_HTTP_PENDING_MAX 4 @@ -28,8 +28,9 @@ // #define NETWORK_PSP_AGENT "DuskEngine/1.0" typedef struct { - pspUtilityNetconfData dialogData; - struct pspUtilityNetconfAdhoc dialogAdhoc; + // Deadline (TIME.time) for the current sceNetApctlConnect() attempt + // to reach PSP_NET_APCTL_STATE_GOT_IP before it's reported as failed. + float_t connectTimeoutAt; // Used during establishing connection void *onConnectedUser; @@ -40,7 +41,7 @@ typedef struct { /** * Initializes the PSP Network manager. This will NOT do network connecting, * only prep it for being able to connect in future. - * + * * @return Error state (if any). */ errorret_t networkPSPInit(); @@ -48,7 +49,7 @@ errorret_t networkPSPInit(); /** * Called each frame for handling PSP requests, basically this is where all * communication between the HTTP thread and the main thread happens. - * + * * @return Error state (if any). */ errorret_t networkPSPUpdate(); @@ -56,21 +57,22 @@ errorret_t networkPSPUpdate(); /** * Disposes the PSP Network manager, this will clean all resources and, if the * network is connected, it will disconnect it safely. - * + * * @return Error state (if any). */ errorret_t networkPSPDispose(); /** * Checks if the PSP network is connected. - * + * * @return True if the PSP is connected to a network, false otherwise. */ bool_t networkPSPIsConnected(); /** - * Requests the PSP to connect to a network (Shows the Wi-Fi connected). - * + * Requests the PSP to connect to a network, using the first saved + * connection profile via sceNetApctlConnect() - no dialog is shown. + * * @param onConnected Callback connected successfully. * @param onFailed Callback if the connection failed. * @param onDisconnect Callback when connection is lost. @@ -85,7 +87,7 @@ void networkPSPRequestConnection( /** * Requests the PSP to disconnect from the network. - * + * * @param onComplete Callback when disconnection is complete. * @param user User data to pass to the callback. */ @@ -95,16 +97,15 @@ void networkPSPRequestDisconnection( ); /** - * Disposes the PSP sce net libraries, doesn't unload the modules and won't - * term the dialog if it's active. - * + * Disposes the PSP sce net libraries, doesn't unload the modules. + * * @return Error state (if any). */ errorret_t networkPSPTerm(); /** * Gets the network information for the currently active network connection. - * + * * @return Network information for the currently active network connection. */ networkinfo_t networkPSPGetInfo(); \ No newline at end of file diff --git a/src/duskpsp/system/systempsp.c b/src/duskpsp/system/systempsp.c index 47dbbc94..b4825ef1 100644 --- a/src/duskpsp/system/systempsp.c +++ b/src/duskpsp/system/systempsp.c @@ -9,7 +9,6 @@ #include "input/input.h" #include "util/string.h" #include "assert/assert.h" -#include "network/network.h" errorret_t systemInitPSP() { // Bind ACCEPT and CANCEL binds. @@ -46,10 +45,6 @@ errorret_t systemInitPSP() { } systemdialogtype_t systemGetActiveDialogTypePSP() { - if(NETWORK.state == NETWORK_STATE_CONNECTING) { - return SYSTEM_DIALOG_TYPE_TICK_BLOCKING; - } - return SYSTEM_DIALOG_TYPE_NONE; }