sceUtility: fix the system param string size check and the adhoc channel error

Two things utility/systemparam caught:

A negative size passed to sceUtilityGetSystemParamString went through
Memory::IsValidRange, where it became an enormous range and came back
as a generic -1. The PSP just reports that the string doesn't fit, same
as any other size too small to hold it.

sceUtilityGetSystemParamInt returned 0x800ADF4 for an automatic adhoc
channel unconditionally. The FIXME there wondered whether the hardware
only does that once adhocctl is initialized - it does. Before any adhoc
module is up, which is the state nearly every game asks this in, the
hardware returns 0 and writes the channel out.

Fixes utility/systemparam/systemparam, moved to tests_good.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01JvJR8oJNSCimCM9KXVLjfq
This commit is contained in:
Henrik RydgårdandClaude Opus 5 committed 2026-09-04 18:12:24 -06:00
1 parent 68fd30bbba
commit d675b467c1
2 files changed
+12 -4

No files matched your search

+11 -3
View File
@@ -46,6 +46,7 @@
#include "Core/HLE/sceAtrac.h"
#include "Core/HLE/sceUtility.h"
#include "Core/HLE/sceNet.h"
#include "Core/HLE/sceNetAdhoc.h"
#include "Core/Dialog/PSPDialog.h"
#include "Core/Dialog/PSPSaveDialog.h"
@@ -1220,19 +1221,23 @@ static u32 sceUtilitySetSystemParamString(u32 id, u32 strPtr)
}
static u32 sceUtilityGetSystemParamString(u32 id, u32 destAddr, int destSize) {
if (!Memory::IsValidRange(destAddr, destSize)) {
// A size that isn't positive can't hold the string, and that's what the PSP reports - not a
// bad-buffer error. Range checking it first would turn a negative size into a huge range.
if (destSize > 0 && !Memory::IsValidRange(destAddr, destSize)) {
// TODO: What error code?
return hleLogError(Log::sceUtility, -1);
}
char *buf = (char *)Memory::GetPointerWriteUnchecked(destAddr);
switch (id) {
case PSP_SYSTEMPARAM_ID_STRING_NICKNAME:
{
// If there's not enough space for the string and null terminator, fail.
if (destSize <= (int)g_Config.sNickName.length())
return SCE_ERROR_UTILITY_STRING_TOO_LONG;
char *buf = (char *)Memory::GetPointerWriteUnchecked(destAddr);
// TODO: should we zero-pad the output as strncpy does? And what are the semantics for the terminating null if destSize == length?
strncpy(buf, g_Config.sNickName.c_str(), destSize);
break;
}
default:
return hleLogError(Log::sceUtility, SCE_ERROR_UTILITY_INVALID_SYSTEM_PARAM_ID);
@@ -1263,7 +1268,10 @@ static u32 sceUtilityGetSystemParamInt(u32 id, u32 destaddr) {
switch (id) {
case PSP_SYSTEMPARAM_ID_INT_ADHOC_CHANNEL:
param = g_Config.iWlanAdhocChannel;
if (param == PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC) {
// Only once adhocctl is up. The FIXME below wondered whether this error depends on that,
// and it does - utility/systemparam gets a plain 0 out of the hardware before any adhoc
// module is initialized, which is the state nearly every game asks this in.
if (param == PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC && netAdhocctlInited) {
// FIXME: Actually.. it's always returning 0x800ADF4 regardless using Auto channel or Not, and regardless the connection state either,
// Not sure whether this error code only returned after Adhocctl Initialized (ie. netAdhocctlInited) or also before initialized.
// FIXME: Outputted channel (might be unchanged?) either 0 when not connected to a group yet (ie. adhocctlState == ADHOCCTL_STATE_DISCONNECTED),
+1 -1
View File
@@ -362,6 +362,7 @@ tests_good = [
"utility/savedata/autosave",
"utility/savedata/filelist",
"utility/savedata/makedata",
"utility/systemparam/systemparam",
"umd/callbacks/umd",
"umd/register",
"video/mpeg/ringbuffer/avail",
@@ -496,7 +497,6 @@ tests_next = [
#"utility/savedata/saveemptyfilename",
"utility/savedata/secureversion",
"utility/savedata/sizes",
"utility/systemparam/systemparam",
"video/mpeg/basic",
"video/pmf/pmf",
"video/pmf_simple/pmf_simple",