Files
ppsspp/Core/Dialog/PSPScreenshotDialog.cpp
T
Henrik RydgårdandClaude Opus 5.5 6dffcc91d2 Utility: Check request sizes like the firmware
InitStart sizes: Netconf and NpSignin accepted any size, then wrote
common.size bytes back from a 64-68 byte host struct, copying host memory
into PSP RAM. GamedataInstall looked for install files before checking the
size, and the HtmlViewer read options before checking the whole request was
in memory. All the dialogs now check the address, then the sizes
sceUtility_Driver accepts (utility/dialog/sizes), before anything else, as
the firmware does (a bad address is INVALID_ADDRESS), and write back no more
than the struct.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-09-25 12:50:41 -06:00

130 lines
4.0 KiB
C++

// Copyright (c) 2012- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Common/Serialize/Serializer.h"
#include "Common/Serialize/SerializeFuncs.h"
#include "Core/Dialog/PSPDialog.h"
#include "Core/Dialog/PSPScreenshotDialog.h"
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/ErrorCodes.h"
#include "Core/MemMap.h"
#include "Core/Reporting.h"
enum SceUtilityScreenshotType {
SCE_UTILITY_SCREENSHOT_TYPE_GUI = 0,
SCE_UTILITY_SCREENSHOT_TYPE_AUTO = 1,
SCE_UTILITY_SCREENSHOT_TYPE_SAVE = 2,
SCE_UTILITY_SCREENSHOT_TYPE_VIEW = 3,
// Names are just guesses based on status value behavior.
SCE_UTILITY_SCREENSHOT_TYPE_CONT_START = 100,
SCE_UTILITY_SCREENSHOT_TYPE_CONT_FINISH = 101,
SCE_UTILITY_SCREENSHOT_TYPE_CONT_STOP = 102,
};
static const int SCE_UTILITY_SCREENSHOTDIALOG_SIZE_V1 = 436;
static const int SCE_UTILITY_SCREENSHOTDIALOG_SIZE_V2 = 928;
static const int SCE_UTILITY_SCREENSHOTDIALOG_SIZE_V3 = 932;
#if COMMON_LITTLE_ENDIAN
typedef SceUtilityScreenshotType SceUtilityScreenshotType_le;
#else
typedef swap_struct_t<SceUtilityScreenshotType, swap_32_t<SceUtilityScreenshotType> > SceUtilityScreenshotType_le;
#endif
struct SceUtilityScreenshotParams {
pspUtilityDialogCommon base;
SceUtilityScreenshotType_le mode;
// TODO
};
PSPScreenshotDialog::PSPScreenshotDialog(UtilityDialogType type) : PSPDialog(type) {
}
PSPScreenshotDialog::~PSPScreenshotDialog() {
}
int PSPScreenshotDialog::Init(u32 paramAddr) {
// Already running
if (ReadStatus() != SCE_UTILITY_STATUS_NONE && ReadStatus() != SCE_UTILITY_STATUS_SHUTDOWN) {
ERROR_LOG_REPORT(Log::HLE, "sceUtilityScreenshotInitStart(%08x): invalid status", paramAddr);
return SCE_ERROR_UTILITY_INVALID_STATUS;
}
const int check = CheckRequest(paramAddr, { SCE_UTILITY_SCREENSHOTDIALOG_SIZE_V1, SCE_UTILITY_SCREENSHOTDIALOG_SIZE_V2, SCE_UTILITY_SCREENSHOTDIALOG_SIZE_V3 });
if (check < 0) {
ERROR_LOG(Log::HLE, "sceUtilityScreenshotInitStart(%08x): bad request: %08x", paramAddr, check);
return check;
}
params_ = PSPPointer<SceUtilityScreenshotParams>::Create(paramAddr);
mode = params_->mode;
ChangeStatus(SCE_UTILITY_STATUS_INITIALIZE, 0);
InitCommon();
return 0;
}
int PSPScreenshotDialog::Update(int animSpeed) {
UpdateCommon();
if (UseAutoStatus()) {
if (ReadStatus() == SCE_UTILITY_STATUS_INITIALIZE) {
ChangeStatus(SCE_UTILITY_STATUS_RUNNING, 0);
} else if (ReadStatus() == SCE_UTILITY_STATUS_RUNNING) {
if (mode == SCE_UTILITY_SCREENSHOT_TYPE_CONT_START) {
ChangeStatus(SCE_UTILITY_STATUS_SCREENSHOT_UNKNOWN, 0);
} else {
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
}
} else if (ReadStatus() == SCE_UTILITY_STATUS_FINISHED) {
ChangeStatus(SCE_UTILITY_STATUS_SHUTDOWN, 0);
}
}
return 0;
}
int PSPScreenshotDialog::ContStart() {
// Based on JPCSP http://code.google.com/p/jpcsp/source/detail?r=3381
if (ReadStatus() != SCE_UTILITY_STATUS_SCREENSHOT_UNKNOWN)
return SCE_ERROR_UTILITY_INVALID_STATUS;
// Check with JPCSPTrace log of Dream Club Portable
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
return 0;
}
void PSPScreenshotDialog::DoState(PointerWrap &p) {
PSPDialog::DoState(p);
auto s = p.Section("PSPScreenshotDialog", 0, 2);
if (!s)
return;
Do(p, mode);
if (s >= 2) {
Do(p, params_);
}
}
pspUtilityDialogCommon *PSPScreenshotDialog::GetCommonParam() {
if (params_.IsValid())
return &params_->base;
return nullptr;
}