~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to Core/Dialog/PSPMsgDialog.cpp

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 "Core/Dialog/PSPMsgDialog.h"
 
19
#include "Core/Util/PPGeDraw.h"
 
20
#include "Core/HLE/sceCtrl.h"
 
21
#include "Core/MemMapHelpers.h"
 
22
#include "Core/Reporting.h"
 
23
#include "Common/ChunkFile.h"
 
24
#include "i18n/i18n.h"
 
25
#include "util/text/utf8.h"
 
26
 
 
27
static const float FONT_SCALE = 0.65f;
 
28
 
 
29
// These are rough, it seems to take a long time to init, and probably depends on threads.
 
30
// TODO: This takes like 700ms on a PSP but that's annoyingly long.
 
31
const static int MSG_INIT_DELAY_US = 300000;
 
32
const static int MSG_SHUTDOWN_DELAY_US = 26000;
 
33
 
 
34
PSPMsgDialog::PSPMsgDialog()
 
35
        : PSPDialog()
 
36
        , flag(0)
 
37
{
 
38
}
 
39
 
 
40
PSPMsgDialog::~PSPMsgDialog() {
 
41
}
 
42
 
 
43
int PSPMsgDialog::Init(unsigned int paramAddr) {
 
44
        // Ignore if already running
 
45
        if (GetStatus() != SCE_UTILITY_STATUS_NONE) {
 
46
                ERROR_LOG_REPORT(SCEUTILITY, "sceUtilityMsgDialogInitStart: invalid status");
 
47
                return 0;
 
48
        }
 
49
 
 
50
        messageDialogAddr = paramAddr;
 
51
        if (!Memory::IsValidAddress(messageDialogAddr))
 
52
        {
 
53
                return 0;
 
54
        }
 
55
        int size = Memory::Read_U32(paramAddr);
 
56
        memset(&messageDialog,0,sizeof(messageDialog));
 
57
        // Only copy the right size to support different request format
 
58
        Memory::Memcpy(&messageDialog,paramAddr,size);
 
59
 
 
60
        // debug info
 
61
        int optionsNotCoded = messageDialog.options & ~SCE_UTILITY_MSGDIALOG_OPTION_SUPPORTED;
 
62
        if(optionsNotCoded)
 
63
        {
 
64
                ERROR_LOG_REPORT(SCEUTILITY, "PSPMsgDialog options not coded : 0x%08x", optionsNotCoded);
 
65
        }
 
66
 
 
67
        flag = 0;
 
68
 
 
69
        // Check request invalidity
 
70
        if(messageDialog.type == 0 && !(messageDialog.errorNum & 0x80000000))
 
71
        {
 
72
                flag |= DS_ERROR;
 
73
                messageDialog.result = SCE_UTILITY_MSGDIALOG_ERROR_ERRORCODEINVALID;
 
74
        }
 
75
        else if(size == SCE_UTILITY_MSGDIALOG_SIZE_V2 && messageDialog.type == 1)
 
76
        {
 
77
                unsigned int validOp = SCE_UTILITY_MSGDIALOG_OPTION_TEXTSOUND |
 
78
                                SCE_UTILITY_MSGDIALOG_OPTION_YESNO |
 
79
                                SCE_UTILITY_MSGDIALOG_OPTION_DEFAULT_NO;
 
80
                if (((messageDialog.options | validOp) ^ validOp) != 0)
 
81
                {
 
82
                        flag |= DS_ERROR;
 
83
                        messageDialog.result = SCE_UTILITY_MSGDIALOG_ERROR_BADOPTION;
 
84
                }
 
85
        }
 
86
        else if(size == SCE_UTILITY_MSGDIALOG_SIZE_V3)
 
87
        {
 
88
                if((messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_DEFAULT_NO) &&
 
89
                                !(messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_YESNO))
 
90
                {
 
91
                        flag |= DS_ERROR;
 
92
                        messageDialog.result = SCE_UTILITY_MSGDIALOG_ERROR_BADOPTION;
 
93
                }
 
94
                if (messageDialog.options & ~SCE_UTILITY_MSGDIALOG_OPTION_SUPPORTED)
 
95
                {
 
96
                        flag |= DS_ERROR;
 
97
                        messageDialog.result = SCE_UTILITY_MSGDIALOG_ERROR_BADOPTION;
 
98
                }
 
99
        }
 
100
 
 
101
        if(flag == 0)
 
102
        {
 
103
                yesnoChoice = 1;
 
104
                if(messageDialog.type == 1)
 
105
                        flag |= DS_MSG;
 
106
                if(messageDialog.type == 0)
 
107
                        flag |= DS_ERRORMSG;
 
108
                if((messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_YESNO) &&
 
109
                                ((size == SCE_UTILITY_MSGDIALOG_SIZE_V3) ||
 
110
                                                (size == SCE_UTILITY_MSGDIALOG_SIZE_V2 && messageDialog.type == 1)))
 
111
                        flag |= DS_YESNO;
 
112
                if(messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_DEFAULT_NO)
 
113
                {
 
114
                        yesnoChoice = 0;
 
115
                        flag |= DS_DEFNO;
 
116
                }
 
117
                if((messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_OK) && (size == SCE_UTILITY_MSGDIALOG_SIZE_V3))
 
118
                {
 
119
                        yesnoChoice = 1;
 
120
                        flag |= DS_OK;
 
121
                }
 
122
                if((flag & DS_YESNO) || (flag & DS_OK))
 
123
                        flag |= DS_VALIDBUTTON;
 
124
                if(!((messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_NOCANCEL)  && (size == SCE_UTILITY_MSGDIALOG_SIZE_V3)))
 
125
                        flag |= DS_CANCELBUTTON;
 
126
                if(messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_NOSOUND)
 
127
                        flag |= DS_NOSOUND;
 
128
        }
 
129
 
 
130
        if (flag & DS_ERRORMSG) {
 
131
                snprintf(msgText, 512, "Error code: %08x", messageDialog.errorNum);
 
132
        } else {
 
133
                strncpy(msgText, messageDialog.string, 512);
 
134
        }
 
135
 
 
136
        ChangeStatusInit(MSG_INIT_DELAY_US);
 
137
 
 
138
        UpdateButtons();
 
139
        StartFade(true);
 
140
        return 0;
 
141
}
 
142
 
 
143
void PSPMsgDialog::DisplayMessage(std::string text, bool hasYesNo, bool hasOK)
 
144
{
 
145
        float WRAP_WIDTH = 300.0f;
 
146
        if (UTF8StringNonASCIICount(text.c_str()) > 3)
 
147
                WRAP_WIDTH = 372.0f;
 
148
        
 
149
        float y = 140.0f;
 
150
        float h, sy ,ey;
 
151
        int n;
 
152
        PPGeMeasureText(0, &h, &n, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);
 
153
        float h2 = h * n / 2.0f;
 
154
        ey = y + h2 + 20.0f;
 
155
 
 
156
        if (hasYesNo)
 
157
        {
 
158
                I18NCategory *di = GetI18NCategory("Dialog");
 
159
                const char *choiceText;
 
160
                u32 yesColor, noColor;
 
161
                float x, w;
 
162
                if (yesnoChoice == 1) {
 
163
                        choiceText = di->T("Yes");
 
164
                        x = 204.0f;
 
165
                        yesColor = 0xFFFFFFFF;
 
166
                        noColor  = 0xFFFFFFFF;
 
167
                }
 
168
                else {
 
169
                        choiceText = di->T("No");
 
170
                        x = 273.0f;
 
171
                        yesColor = 0xFFFFFFFF;
 
172
                        noColor  = 0xFFFFFFFF;
 
173
                }
 
174
                PPGeMeasureText(&w, &h, 0, choiceText, FONT_SCALE);
 
175
                w = 15.0f;
 
176
                h = 8.0f;
 
177
                float y2 = y + h2 + 8.0f;
 
178
                h2 += h + 5.0f;
 
179
                y = 135.0f - h;
 
180
                PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x6DCFCFCF));
 
181
                PPGeDrawText(di->T("Yes"), 204.0f, y2 + 1.0f, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0x80000000));
 
182
                PPGeDrawText(di->T("Yes"), 203.0f, y2 - 1.0f, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(yesColor));
 
183
                PPGeDrawText(di->T("No"), 273.0f, y2 + 1.0f, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0x80000000));
 
184
                PPGeDrawText(di->T("No"), 272.0f, y2 - 1.0f, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(noColor));
 
185
                if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) {
 
186
                        yesnoChoice = 1;
 
187
                }
 
188
                else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) {
 
189
                        yesnoChoice = 0;
 
190
                }
 
191
                ey = y2 + 25.0f;
 
192
        } 
 
193
        
 
194
        if (hasOK) {
 
195
                I18NCategory *di = GetI18NCategory("Dialog");
 
196
                float x, w;
 
197
                x = 240.0f;
 
198
                w = 15.0f;
 
199
                h = 8.0f;
 
200
                float y2 = y + h2 + 8.0f;
 
201
                h2 += h + 5.0f;
 
202
                y = 135.0f - h;
 
203
                PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x6DCFCFCF));
 
204
                PPGeDrawText(di->T("OK"), 240.0f, y2 + 1.0f, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0x80000000));
 
205
                PPGeDrawText(di->T("OK"), 239.0f, y2 - 1.0f, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF));
 
206
                ey = y2 + 25.0f;
 
207
        }
 
208
 
 
209
        PPGeDrawTextWrapped(text.c_str(), 241.0f, y+2, WRAP_WIDTH, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0x80000000));
 
210
        PPGeDrawTextWrapped(text.c_str(), 240.0f, y, WRAP_WIDTH, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF));
 
211
        sy = 125.0f - h2;
 
212
        PPGeDrawRect(40.0f, sy, 440.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF));
 
213
        PPGeDrawRect(40.0f, ey, 440.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF));
 
214
}
 
215
 
 
216
int PSPMsgDialog::Update(int animSpeed) {
 
217
        if (GetStatus() != SCE_UTILITY_STATUS_RUNNING) {
 
218
                return SCE_ERROR_UTILITY_INVALID_STATUS;
 
219
        }
 
220
 
 
221
        if (flag & (DS_ERROR | DS_ABORT)) {
 
222
                ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0);
 
223
        } else {
 
224
                UpdateButtons();
 
225
                UpdateFade(animSpeed);
 
226
 
 
227
                okButtonImg = I_CIRCLE;
 
228
                cancelButtonImg = I_CROSS;
 
229
                okButtonFlag = CTRL_CIRCLE;
 
230
                cancelButtonFlag = CTRL_CROSS;
 
231
                if (messageDialog.common.buttonSwap == 1)
 
232
                {
 
233
                        okButtonImg = I_CROSS;
 
234
                        cancelButtonImg = I_CIRCLE;
 
235
                        okButtonFlag = CTRL_CROSS;
 
236
                        cancelButtonFlag = CTRL_CIRCLE;
 
237
                }
 
238
 
 
239
                StartDraw();
 
240
                // white -> RGB(168,173,189), black -> RGB(129,134,150)
 
241
                // (255 - a) + (x * a / 255) = 173,  x * a / 255 = 134
 
242
                // a = 255 - w + b = 158, x = b * 255 / a = ?
 
243
                // but is not drawn using x * a + y * (255 - a) here?
 
244
                //PPGeDrawRect(0, 0, 480, 272, CalcFadedColor(0x9EF2D8D0));
 
245
                PPGeDrawRect(0, 0, 480, 272, CalcFadedColor(0xC0C8B2AC));
 
246
 
 
247
                if ((flag & DS_MSG) || (flag & DS_ERRORMSG))
 
248
                        DisplayMessage(msgText, (flag & DS_YESNO) != 0, (flag & DS_OK) != 0);
 
249
 
 
250
                if (flag & (DS_OK | DS_VALIDBUTTON)) 
 
251
                        DisplayButtons(DS_BUTTON_OK, messageDialog.common.size == SCE_UTILITY_MSGDIALOG_SIZE_V3 ? messageDialog.okayButton : NULL);
 
252
 
 
253
                if (flag & DS_CANCELBUTTON)
 
254
                        DisplayButtons(DS_BUTTON_CANCEL, messageDialog.common.size == SCE_UTILITY_MSGDIALOG_SIZE_V3 ? messageDialog.cancelButton : NULL);
 
255
 
 
256
                if (IsButtonPressed(cancelButtonFlag) && (flag & DS_CANCELBUTTON))
 
257
                {
 
258
                        if(messageDialog.common.size == SCE_UTILITY_MSGDIALOG_SIZE_V3 ||
 
259
                                        ((messageDialog.common.size == SCE_UTILITY_MSGDIALOG_SIZE_V2) && (flag & DS_YESNO)))
 
260
                                messageDialog.buttonPressed = 3;
 
261
                        else
 
262
                                messageDialog.buttonPressed = 0;
 
263
                        StartFade(false);
 
264
                }
 
265
                else if (IsButtonPressed(okButtonFlag) && (flag & DS_VALIDBUTTON))
 
266
                {
 
267
                        if (yesnoChoice == 0)
 
268
                        {
 
269
                                messageDialog.buttonPressed = 2;
 
270
                        }
 
271
                        else
 
272
                        {
 
273
                                messageDialog.buttonPressed = 1;
 
274
                        }
 
275
                        StartFade(false);
 
276
                }
 
277
 
 
278
 
 
279
                EndDraw();
 
280
 
 
281
                messageDialog.result = 0;
 
282
        }
 
283
 
 
284
        Memory::Memcpy(messageDialogAddr, &messageDialog ,messageDialog.common.size);
 
285
        return 0;
 
286
}
 
287
 
 
288
int PSPMsgDialog::Abort() {
 
289
        // Katekyoushi Hitman Reborn! Battle Arena expects this to fail when not running.
 
290
        if (GetStatus() != SCE_UTILITY_STATUS_RUNNING) {
 
291
                return SCE_ERROR_UTILITY_INVALID_STATUS;
 
292
        } else {
 
293
                // Status is not actually changed until Update().
 
294
                flag |= DS_ABORT;
 
295
                return 0;
 
296
        }
 
297
}
 
298
 
 
299
int PSPMsgDialog::Shutdown(bool force) {
 
300
        if (GetStatus() != SCE_UTILITY_STATUS_FINISHED && !force)
 
301
                return SCE_ERROR_UTILITY_INVALID_STATUS;
 
302
 
 
303
        PSPDialog::Shutdown(force);
 
304
        if (!force) {
 
305
                ChangeStatusShutdown(MSG_SHUTDOWN_DELAY_US);
 
306
        }
 
307
 
 
308
        return 0;
 
309
}
 
310
 
 
311
void PSPMsgDialog::DoState(PointerWrap &p)
 
312
{
 
313
        PSPDialog::DoState(p);
 
314
 
 
315
        auto s = p.Section("PSPMsgDialog", 1);
 
316
        if (!s)
 
317
                return;
 
318
 
 
319
        p.Do(flag);
 
320
        p.Do(messageDialog);
 
321
        p.Do(messageDialogAddr);
 
322
        p.DoArray(msgText, sizeof(msgText));
 
323
        p.Do(yesnoChoice);
 
324
}
 
325
 
 
326
pspUtilityDialogCommon *PSPMsgDialog::GetCommonParam()
 
327
{
 
328
        return &messageDialog.common;
 
329
}