CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Core/Dialog/PSPDialog.cpp
Views: 1401
1
// Copyright (c) 2012- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
#include "Common/Data/Text/I18n.h"
19
20
#include "Common/Serialize/Serializer.h"
21
#include "Common/Serialize/SerializeFuncs.h"
22
#include "Common/StringUtils.h"
23
#include "Core/Config.h"
24
#include "Core/System.h"
25
#include "Core/CoreTiming.h"
26
#include "Core/Dialog/PSPDialog.h"
27
#include "Core/HLE/sceCtrl.h"
28
#include "Core/HLE/scePower.h"
29
#include "Core/HLE/sceUtility.h"
30
#include "Core/MemMapHelpers.h"
31
#include "Core/Util/PPGeDraw.h"
32
33
#define FADE_TIME 1.0
34
const float FONT_SCALE = 0.55f;
35
36
PSPDialog::PSPDialog(UtilityDialogType type) : dialogType_(type) {
37
}
38
39
PSPDialog::~PSPDialog() {
40
}
41
42
void PSPDialog::InitCommon() {
43
UpdateCommon();
44
45
if (GetCommonParam() && GetCommonParam()->language != g_Config.GetPSPLanguage()) {
46
WARN_LOG(Log::sceUtility, "Game requested language %d, ignoring and using user language", GetCommonParam()->language);
47
}
48
}
49
50
void PSPDialog::UpdateCommon() {
51
okButtonImg = ImageID("I_CIRCLE");
52
cancelButtonImg = ImageID("I_CROSS");
53
okButtonFlag = CTRL_CIRCLE;
54
cancelButtonFlag = CTRL_CROSS;
55
if (GetCommonParam() && GetCommonParam()->buttonSwap == 1) {
56
okButtonImg = ImageID("I_CROSS");
57
cancelButtonImg = ImageID("I_CIRCLE");
58
okButtonFlag = CTRL_CROSS;
59
cancelButtonFlag = CTRL_CIRCLE;
60
}
61
}
62
63
PSPDialog::DialogStatus PSPDialog::GetStatus() {
64
if (pendingStatusTicks != 0 && CoreTiming::GetTicks() >= pendingStatusTicks) {
65
bool changeAllowed = true;
66
if (pendingStatus == SCE_UTILITY_STATUS_NONE && status == SCE_UTILITY_STATUS_SHUTDOWN) {
67
FinishVolatile();
68
} else if (pendingStatus == SCE_UTILITY_STATUS_RUNNING && status == SCE_UTILITY_STATUS_INITIALIZE) {
69
if (!volatileLocked_) {
70
volatileLocked_ = KernelVolatileMemLock(0, 0, 0) == 0;
71
changeAllowed = volatileLocked_;
72
}
73
}
74
if (changeAllowed) {
75
status = pendingStatus;
76
pendingStatusTicks = 0;
77
}
78
}
79
80
PSPDialog::DialogStatus retval = status;
81
if (UseAutoStatus()) {
82
if (status == SCE_UTILITY_STATUS_SHUTDOWN)
83
status = SCE_UTILITY_STATUS_NONE;
84
if (status == SCE_UTILITY_STATUS_INITIALIZE)
85
status = SCE_UTILITY_STATUS_RUNNING;
86
}
87
return retval;
88
}
89
90
void PSPDialog::ChangeStatus(DialogStatus newStatus, int delayUs) {
91
if (delayUs <= 0) {
92
if (newStatus == SCE_UTILITY_STATUS_NONE && status == SCE_UTILITY_STATUS_SHUTDOWN) {
93
FinishVolatile();
94
} else if (newStatus == SCE_UTILITY_STATUS_RUNNING && status == SCE_UTILITY_STATUS_INITIALIZE) {
95
if (!volatileLocked_) {
96
// TODO: Should probably make the status pending instead?
97
volatileLocked_ = KernelVolatileMemLock(0, 0, 0) == 0;
98
}
99
}
100
status = newStatus;
101
pendingStatus = newStatus;
102
pendingStatusTicks = 0;
103
} else {
104
pendingStatus = newStatus;
105
pendingStatusTicks = CoreTiming::GetTicks() + usToCycles(delayUs);
106
}
107
}
108
109
void PSPDialog::FinishVolatile() {
110
if (!volatileLocked_)
111
return;
112
113
if (KernelVolatileMemUnlock(0) == 0) {
114
volatileLocked_ = false;
115
// Simulate modifications to volatile memory.
116
Memory::Memset(PSP_GetVolatileMemoryStart(), 0, PSP_GetVolatileMemoryEnd() - PSP_GetVolatileMemoryStart());
117
}
118
}
119
120
int PSPDialog::FinishInit() {
121
if (ReadStatus() != SCE_UTILITY_STATUS_INITIALIZE)
122
return -1;
123
// The thread already locked.
124
volatileLocked_ = true;
125
ChangeStatus(SCE_UTILITY_STATUS_RUNNING, 0);
126
return 0;
127
}
128
129
int PSPDialog::FinishShutdown() {
130
if (ReadStatus() != SCE_UTILITY_STATUS_SHUTDOWN)
131
return -1;
132
ChangeStatus(SCE_UTILITY_STATUS_NONE, 0);
133
return 0;
134
}
135
136
void PSPDialog::ChangeStatusInit(int delayUs) {
137
ChangeStatus(SCE_UTILITY_STATUS_INITIALIZE, 0);
138
139
auto params = GetCommonParam();
140
if (params)
141
UtilityDialogInitialize(DialogType(), delayUs, params->accessThread);
142
else
143
ChangeStatus(SCE_UTILITY_STATUS_RUNNING, delayUs);
144
}
145
146
void PSPDialog::ChangeStatusShutdown(int delayUs) {
147
// If we're doing shutdown right away and skipped start, we don't run the dialog thread.
148
bool skipDialogShutdown = status == SCE_UTILITY_STATUS_NONE && pendingStatus == SCE_UTILITY_STATUS_NONE;
149
ChangeStatus(SCE_UTILITY_STATUS_SHUTDOWN, 0);
150
151
auto params = GetCommonParam();
152
if (params && !skipDialogShutdown)
153
UtilityDialogShutdown(DialogType(), delayUs, params->accessThread);
154
else
155
ChangeStatus(SCE_UTILITY_STATUS_NONE, delayUs);
156
}
157
158
void PSPDialog::StartDraw()
159
{
160
PPGeBegin();
161
PPGeDrawRect(0, 0, 480, 272, CalcFadedColor(0x20000000));
162
}
163
164
void PSPDialog::EndDraw()
165
{
166
PPGeEnd();
167
}
168
169
int PSPDialog::Shutdown(bool force)
170
{
171
if (force) {
172
ChangeStatus(SCE_UTILITY_STATUS_NONE, 0);
173
} else {
174
ChangeStatus(SCE_UTILITY_STATUS_SHUTDOWN, 0);
175
}
176
return 0;
177
}
178
179
void PSPDialog::StartFade(bool fadeIn_)
180
{
181
isFading = true;
182
fadeTimer = 0;
183
fadeIn = fadeIn_;
184
}
185
186
void PSPDialog::UpdateFade(int animSpeed) {
187
if (isFading) {
188
fadeTimer += 1.0f/30.0f * animSpeed; // Probably need a more real value of delta time
189
if (fadeTimer < FADE_TIME) {
190
if (fadeIn)
191
fadeValue = (u32) (fadeTimer / FADE_TIME * 255);
192
else
193
fadeValue = 255 - (u32) (fadeTimer / FADE_TIME * 255);
194
} else {
195
fadeValue = (fadeIn ? 255 : 0);
196
isFading = false;
197
if (!fadeIn) {
198
FinishFadeOut();
199
}
200
}
201
}
202
}
203
204
void PSPDialog::FinishFadeOut() {
205
ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
206
}
207
208
u32 PSPDialog::CalcFadedColor(u32 inColor) const {
209
u32 alpha = inColor >> 24;
210
alpha = alpha * fadeValue / 255;
211
return (inColor & 0x00FFFFFF) | (alpha << 24);
212
}
213
214
void PSPDialog::DoState(PointerWrap &p) {
215
auto s = p.Section("PSPDialog", 1, 3);
216
if (!s)
217
return;
218
219
Do(p, status);
220
Do(p, lastButtons);
221
Do(p, buttons);
222
Do(p, fadeTimer);
223
Do(p, isFading);
224
Do(p, fadeIn);
225
Do(p, fadeValue);
226
227
// I don't think we should save these two... Let's just ignore them for now for compat.
228
int okButtonImg = 0;
229
Do(p, okButtonImg);
230
int cancelButtonImg = 0;
231
Do(p, cancelButtonImg);
232
233
Do(p, okButtonFlag);
234
Do(p, cancelButtonFlag);
235
236
if (s >= 2) {
237
Do(p, pendingStatus);
238
Do(p, pendingStatusTicks);
239
} else {
240
pendingStatusTicks = 0;
241
}
242
243
if (s >= 3) {
244
Do(p, volatileLocked_);
245
} else {
246
volatileLocked_ = false;
247
}
248
}
249
250
pspUtilityDialogCommon *PSPDialog::GetCommonParam()
251
{
252
// FIXME
253
return 0;
254
}
255
256
void PSPDialog::UpdateButtons()
257
{
258
lastButtons = __CtrlPeekButtons();
259
buttons = __CtrlReadLatch();
260
}
261
262
bool PSPDialog::IsButtonPressed(int checkButton)
263
{
264
return !isFading && (buttons & checkButton);
265
}
266
267
bool PSPDialog::IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThreshold, int framesHeldRepeatRate)
268
{
269
bool btnWasHeldLastFrame = (lastButtons & checkButton) && (__CtrlPeekButtons() & checkButton);
270
if (!isFading && btnWasHeldLastFrame) {
271
framesHeld++;
272
}
273
else {
274
framesHeld = 0;
275
return false;
276
}
277
278
// It's considered held for dialog purposes after 30 frames (~0.5 seconds),
279
// and set to repeat every 10 frames, by default.
280
if (framesHeld >= framesHeldThreshold && ((framesHeld % framesHeldRepeatRate) == 0))
281
return true;
282
283
return false;
284
}
285
286
PPGeStyle PSPDialog::FadedStyle(PPGeAlign align, float scale) {
287
PPGeStyle textStyle;
288
textStyle.align = align;
289
textStyle.scale = scale;
290
textStyle.color = CalcFadedColor(textStyle.color);
291
textStyle.hasShadow = true;
292
textStyle.shadowColor = CalcFadedColor(textStyle.shadowColor);
293
return textStyle;
294
}
295
296
PPGeImageStyle PSPDialog::FadedImageStyle() {
297
PPGeImageStyle style;
298
style.color = CalcFadedColor(style.color);
299
return style;
300
}
301
302
void PSPDialog::DisplayButtons(int flags, std::string_view caption) {
303
bool useCaption = false;
304
char safeCaption[65] = {0};
305
if (!caption.empty()) {
306
useCaption = true;
307
truncate_cpy(safeCaption, sizeof(safeCaption), caption);
308
}
309
310
PPGeStyle textStyle = FadedStyle(PPGeAlign::BOX_LEFT, FONT_SCALE);
311
312
auto di = GetI18NCategory(I18NCat::DIALOG);
313
float x1 = 183.5f, x2 = 261.5f;
314
if (GetCommonParam()->buttonSwap == 1) {
315
x1 = 261.5f;
316
x2 = 183.5f;
317
}
318
if (flags & DS_BUTTON_OK) {
319
std::string_view text = useCaption ? safeCaption : di->T("Enter");
320
PPGeDrawImage(okButtonImg, x2, 256, 11.5f, 11.5f, textStyle);
321
PPGeDrawText(text, x2 + 14.5f, 252, textStyle);
322
}
323
if (flags & DS_BUTTON_CANCEL) {
324
std::string_view text = useCaption ? safeCaption : di->T("Back");
325
PPGeDrawImage(cancelButtonImg, x1, 256, 11.5f, 11.5f, textStyle);
326
PPGeDrawText(text, x1 + 14.5f, 252, textStyle);
327
}
328
}
329
330
int PSPDialog::GetConfirmButton() {
331
if (PSP_CoreParameter().compat.flags().ForceCircleButtonConfirm) {
332
return CTRL_CIRCLE;
333
}
334
return g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CROSS : CTRL_CIRCLE;
335
}
336
337
int PSPDialog::GetCancelButton() {
338
if (PSP_CoreParameter().compat.flags().ForceCircleButtonConfirm) {
339
return CTRL_CROSS;
340
}
341
return g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CIRCLE : CTRL_CROSS;
342
}
343
344