Files
ppsspp/UI/ImposeHome.h
T
LunaMooandClaude Opus 5.5 90cea302b9 HOME button quit screen, with the firmware's art when available
As on a PSP: pressing HOME in a game shows "Do you want to quit the game?"
over it. The game keeps running but gets no input while it's up (sceCtrl
samples are blanked). Left/right picks Yes or No, the confirm button (our
Confirmation button setting, or what compat forces) chooses, the other face
button or HOME closes it, and Yes/No can be tapped. The volume keys change
the game volume a step at a time, shown on the volume bar.

Yes runs the game's registered exit callback first, like the PSP does,
showing "Please wait..." meanwhile. Then, if the XMB launched the game, the
XMB is booted again; otherwise it's back to the game browser, like Exit to
menu. If the callback hasn't ended the game in 10 s, it's quit anyway. Not
in the XMB itself, the PS1 emulator (its own HOME menu) or GE dumps.

It lives in UI/ImposeHome.cpp; EmuScreen only feeds it input and frames and
draws it over the PSP display.

With a firmware dump installed, it's drawn with the firmware's own art from
flash0:/kd/resource/impose.rsc, which is what impose.prx draws it from:
prerendered text for each system language (the question, Yes/No normal and
highlighted, Enter/Back, Please wait...), the button icons, the lines, the
volume bar, the battery and the clock glyphs. The format is documented in
ImposeHome.cpp. Without one, the same screen is drawn with our font and
simple shapes at the same positions.

Where impose.rsc doesn't say where things go, the layout follows
impose_02g.prx (6.61), decrypted and disassembled:
- The screen is filled with 0x9CE7 (#393939); the images are opaque.
- Lines at (80, 96) and (80, 175); impose.prx grows them from the middle
  when it opens, which isn't done here.
- Volume bar: the speaker at (28, 223), 30 steps from x 62, 12 apart. It
  shows our game volume in the PSP's 30 steps.
- Button guide: the cross icon always left, the circle right, "Enter" and
  "Back" next to whichever confirms and cancels.
- Status bar: the battery at (450, 5) (60% and up full, 30% two bars, 12%
  one, then empty), the clock ending next to it at y 5: "M/D H:MM", or
  "D/M" for the DD/MM/YYYY format, no leading zero on the month, day or
  hour, AM/PM for the 12-hour clock.

The clock is the emulated PSP's local time (__RtcGetCurrentLocalTime, new),
in the system's date and time formats. The battery is this device's, since
the emulated PSP's is always full; a device without one shows it full.
For that, Windows now reports -1 for SYSPROP_BATTERY_PERCENTAGE without a
battery (was 100), as SDL already did; SDL polls the battery even when the
status overlay doesn't show it, and the overlay leaves it out when there's
none.

Core side: __CtrlSetGameInputBlocked; __KernelCanExitToVSH and
__KernelRequestExitToVSH to quit to the XMB from outside a syscall; and
__KernelInvokeRegisteredExitCallback(toVSH), so a callback that returns
without exiting ends in the XMB rather than powering down.

New strings: "Do you want to quit the game?", "Please wait..." (Dialog).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NB244iFpvm14JH2FbwHXeQ
2026-10-26 11:39:48 +01:00

79 lines
2.6 KiB
C++

// Copyright (c) 2026- 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/.
#pragma once
#include <cstdint>
#include <memory>
#include "Common/Math/geom2d.h"
class UIContext;
struct TouchInput;
class ImposeArt;
// The PSP's HOME screen ("Do you want to quit the game?"), which impose.prx draws over a running
// game. Owned by EmuScreen, which feeds it input and frames and draws it over the PSP display.
// See ImposeHome.cpp for how it follows the firmware, and the firmware art it uses when there is
// a firmware dump.
class ImposeHomeScreen {
public:
ImposeHomeScreen();
~ImposeHomeScreen();
// What EmuScreen has to do after an update.
enum class Action {
NONE,
LEAVE_GAME, // Quit to the game browser, like Exit to menu.
};
// Once a frame. running: the game is running (booted, CPU running, no reboot pending).
// onTop: EmuScreen is the top screen, so the HOME screen may take input.
Action Update(bool running, bool onTop);
// Touch input while open. True if it took it.
bool Touch(const TouchInput &touch);
// screen: where the PSP's 480x272 display is, in UI coordinates.
void Draw(UIContext &dc, const Bounds &screen);
bool IsOpen() const { return state_ != State::CLOSED; }
void Close();
void DeviceLost();
private:
enum class State {
CLOSED,
ASKING, // Yes / No.
QUITTING, // "Please wait...", while the game's exit callback runs.
};
void Open();
void Choose(bool quit);
void FinishQuit();
Action TakeAction();
State state_ = State::CLOSED;
bool yes_ = false; // Which option is highlighted.
uint32_t lastButtons_ = 0;
// After choosing Yes, while the game's exit callback runs: when to stop waiting and quit anyway.
double deadline_ = -1.0;
Action pendingAction_ = Action::NONE;
// Where Yes and No were last drawn, for touch.
Bounds yesBounds_{};
Bounds noBounds_{};
// The firmware's own artwork, when a firmware dump is installed.
std::unique_ptr<ImposeArt> art_;
};