ppsspp/Core/Dialog/PSPSaveDialog.cpp
2013-07-01 21:07:52 +08:00

1008 lines
32 KiB
C++
Executable File

// 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 "PSPSaveDialog.h"
#include "../Util/PPGeDraw.h"
#include "../HLE/sceCtrl.h"
#include "../HLE/sceUtility.h"
#include "../Core/MemMap.h"
#include "../Config.h"
#include "Core/Reporting.h"
#include "Core/HW/MemoryStick.h"
#include "i18n/i18n.h"
const float FONT_SCALE = 0.55f;
PSPSaveDialog::PSPSaveDialog()
: PSPDialog()
, display(DS_NONE)
, currentSelectedSave(0)
{
param.SetPspParam(0);
}
PSPSaveDialog::~PSPSaveDialog() {
}
int PSPSaveDialog::Init(int paramAddr)
{
// Ignore if already running
if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) {
ERROR_LOG(HLE,"A save request is already running !");
return SCE_ERROR_UTILITY_INVALID_STATUS;
}
requestAddr = paramAddr;
int size = Memory::Read_U32(requestAddr);
memset(&request, 0, sizeof(request));
// Only copy the right size to support different save request format
Memory::Memcpy(&request, requestAddr, size);
Memory::Memcpy(&originalRequest, requestAddr, size);
u32 retval = param.SetPspParam(&request);
INFO_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr);
INFO_LOG(HLE,"Mode: %i", param.GetPspParam()->mode);
yesnoChoice = 1;
switch (param.GetPspParam()->focus)
{
case SCE_UTILITY_SAVEDATA_FOCUS_NAME:
// TODO: This should probably force not using the list?
currentSelectedSave = 0;
break;
case SCE_UTILITY_SAVEDATA_FOCUS_FIRSTLIST:
currentSelectedSave = param.GetFirstListSave();
break;
case SCE_UTILITY_SAVEDATA_FOCUS_LASTLIST:
currentSelectedSave = param.GetLastListSave();
break;
case SCE_UTILITY_SAVEDATA_FOCUS_LATEST:
currentSelectedSave = param.GetLatestSave();
break;
case SCE_UTILITY_SAVEDATA_FOCUS_OLDEST:
currentSelectedSave = param.GetOldestSave();
break;
case SCE_UTILITY_SAVEDATA_FOCUS_FIRSTDATA:
currentSelectedSave = param.GetFirstDataSave();
break;
case SCE_UTILITY_SAVEDATA_FOCUS_LASTDATA:
currentSelectedSave = param.GetLastDataSave();
break;
case SCE_UTILITY_SAVEDATA_FOCUS_FIRSTEMPTY:
currentSelectedSave = param.GetFirstEmptySave();
break;
case SCE_UTILITY_SAVEDATA_FOCUS_LASTEMPTY:
currentSelectedSave = param.GetLastEmptySave();
break;
default:
WARN_LOG(HLE, "Unknown save list focus option: %d", param.GetPspParam()->focus);
currentSelectedSave = 0;
break;
}
switch (param.GetPspParam()->mode)
{
case SCE_UTILITY_SAVEDATA_TYPE_LOAD:
DEBUG_LOG(HLE, "Loading. Title: %s Save: %s File: %s", param.GetGameName(param.GetPspParam()).c_str(), param.GetSaveName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str());
if (param.GetFileInfo(0).size != 0)
display = DS_LOAD_CONFIRM;
else
display = DS_LOAD_NODATA;
break;
case SCE_UTILITY_SAVEDATA_TYPE_AUTOLOAD:
DEBUG_LOG(HLE, "Loading. Title: %s Save: %s File: %s", param.GetGameName(param.GetPspParam()).c_str(), param.GetSaveName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str());
display = DS_NONE;
// Is this necessary?
// currentSelectedSave = param.GetSelectedSave();
break;
case SCE_UTILITY_SAVEDATA_TYPE_LISTLOAD:
DEBUG_LOG(HLE, "Loading. Title: %s Save: %s File: %s", param.GetGameName(param.GetPspParam()).c_str(), param.GetGameName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str());
if(param.GetFilenameCount() == 0)
display = DS_LOAD_NODATA;
else
display = DS_LOAD_LIST_CHOICE;
break;
case SCE_UTILITY_SAVEDATA_TYPE_SAVE:
DEBUG_LOG(HLE, "Saving. Title: %s Save: %s File: %s", param.GetGameName(param.GetPspParam()).c_str(), param.GetGameName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str());
if (param.GetFileInfo(0).size != 0)
{
yesnoChoice = 0;
display = DS_SAVE_CONFIRM_OVERWRITE;
}
else
display = DS_SAVE_CONFIRM;
break;
case SCE_UTILITY_SAVEDATA_TYPE_AUTOSAVE:
DEBUG_LOG(HLE, "Saving. Title: %s Save: %s File: %s", param.GetGameName(param.GetPspParam()).c_str(), param.GetGameName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str());
display = DS_NONE;
// Is this necessary?
// currentSelectedSave = param.GetSelectedSave();
break;
case SCE_UTILITY_SAVEDATA_TYPE_LISTSAVE:
DEBUG_LOG(HLE, "Saving. Title: %s Save: %s File: %s", param.GetGameName(param.GetPspParam()).c_str(), param.GetGameName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str());
display = DS_SAVE_LIST_CHOICE;
break;
case SCE_UTILITY_SAVEDATA_TYPE_LISTDELETE:
DEBUG_LOG(HLE, "Delete. Title: %s Save: %s File: %s", param.GetGameName(param.GetPspParam()).c_str(), param.GetGameName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str());
if(param.GetFilenameCount() == 0)
display = DS_DELETE_NODATA;
else
display = DS_DELETE_LIST_CHOICE;
break;
case SCE_UTILITY_SAVEDATA_TYPE_SIZES:
case SCE_UTILITY_SAVEDATA_TYPE_LIST:
case SCE_UTILITY_SAVEDATA_TYPE_FILES:
case SCE_UTILITY_SAVEDATA_TYPE_GETSIZE:
case SCE_UTILITY_SAVEDATA_TYPE_SINGLEDELETE:
case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE:
case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE:
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE:
case SCE_UTILITY_SAVEDATA_TYPE_READDATA:
case SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA:
display = DS_NONE;
break;
case SCE_UTILITY_SAVEDATA_TYPE_DELETE: // This run on PSP display a list of all save on the PSP. Weird. (Not really, it's to let you free up space)
display = DS_DELETE_LIST_CHOICE;
break;
default:
{
ERROR_LOG_REPORT(HLE, "Load/Save function %d not coded. Title: %s Save: %s File: %s", param.GetPspParam()->mode, param.GetGameName(param.GetPspParam()).c_str(), param.GetGameName(param.GetPspParam()).c_str(), param.GetFileName(param.GetPspParam()).c_str());
param.GetPspParam()->common.result = 0;
status = SCE_UTILITY_STATUS_INITIALIZE;
display = DS_NONE;
return 0; // Return 0 should allow the game to continue, but missing function must be implemented and returning the right value or the game can block.
}
break;
}
status = (int)retval < 0 ? SCE_UTILITY_STATUS_SHUTDOWN : SCE_UTILITY_STATUS_INITIALIZE;
lastButtons = __CtrlPeekButtons();
StartFade(true);
/*INFO_LOG(HLE,"Dump Param :");
INFO_LOG(HLE,"size : %d",param.GetPspParam()->size);
INFO_LOG(HLE,"language : %d",param.GetPspParam()->language);
INFO_LOG(HLE,"buttonSwap : %d",param.GetPspParam()->buttonSwap);
INFO_LOG(HLE,"result : %d",param.GetPspParam()->common.result);
INFO_LOG(HLE,"mode : %d",param.GetPspParam()->mode);
INFO_LOG(HLE,"bind : %d",param.GetPspParam()->bind);
INFO_LOG(HLE,"overwriteMode : %d",param.GetPspParam()->overwriteMode);
INFO_LOG(HLE,"gameName : %s",param.GetGameName(param.GetPspParam()).c_str());
INFO_LOG(HLE,"saveName : %s",param.GetPspParam()->saveName);
INFO_LOG(HLE,"saveNameList : %08x",*((unsigned int*)&param.GetPspParam()->saveNameList));
INFO_LOG(HLE,"fileName : %s",param.GetPspParam()->fileName);
INFO_LOG(HLE,"dataBuf : %08x",*((unsigned int*)&param.GetPspParam()->dataBuf));
INFO_LOG(HLE,"dataBufSize : %u",param.GetPspParam()->dataBufSize);
INFO_LOG(HLE,"dataSize : %u",param.GetPspParam()->dataSize);
INFO_LOG(HLE,"sfo title : %s",param.GetPspParam()->sfoParam.title);
INFO_LOG(HLE,"sfo savedataTitle : %s",param.GetPspParam()->sfoParam.savedataTitle);
INFO_LOG(HLE,"sfo detail : %s",param.GetPspParam()->sfoParam.detail);
INFO_LOG(HLE,"icon0 data : %08x",*((unsigned int*)&param.GetPspParam()->icon0FileData.buf));
INFO_LOG(HLE,"icon0 size : %u",param.GetPspParam()->icon0FileData.bufSize);
INFO_LOG(HLE,"icon1 data : %08x",*((unsigned int*)&param.GetPspParam()->icon1FileData.buf));
INFO_LOG(HLE,"icon1 size : %u",param.GetPspParam()->icon1FileData.bufSize);
INFO_LOG(HLE,"pic1 data : %08x",*((unsigned int*)&param.GetPspParam()->pic1FileData.buf));
INFO_LOG(HLE,"pic1 size : %u",param.GetPspParam()->pic1FileData.bufSize);
INFO_LOG(HLE,"snd0 data : %08x",*((unsigned int*)&param.GetPspParam()->snd0FileData.buf));
INFO_LOG(HLE,"snd0 size : %u",param.GetPspParam()->snd0FileData.bufSize);*/
return retval;
}
const std::string PSPSaveDialog::GetSelectedSaveDirName()
{
switch (param.GetPspParam()->mode)
{
case SCE_UTILITY_SAVEDATA_TYPE_LOAD:
case SCE_UTILITY_SAVEDATA_TYPE_AUTOLOAD:
case SCE_UTILITY_SAVEDATA_TYPE_SAVE:
case SCE_UTILITY_SAVEDATA_TYPE_AUTOSAVE:
return param.GetSaveDirName(param.GetPspParam());
case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE:
case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE:
case SCE_UTILITY_SAVEDATA_TYPE_READDATA:
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE:
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_ERASESECURE:
case SCE_UTILITY_SAVEDATA_TYPE_ERASE:
case SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA:
return param.GetSaveDirName(param.GetPspParam());
// TODO: Maybe also SINGLEDELETE/etc?
// SZIES ignores saveName it seems.
default:
return param.GetSaveDirName(param.GetPspParam(), currentSelectedSave);
break;
}
}
void PSPSaveDialog::DisplayBanner(int which)
{
I18NCategory *d = GetI18NCategory("Dialog");
PPGeDrawRect(0, 0, 480, 23, CalcFadedColor(0x65636358));
const char *title;
switch (which)
{
case DB_SAVE:
title = d->T("Save");
break;
case DB_LOAD:
title = d->T("Load");
break;
case DB_DELETE:
title = d->T("Delete");
break;
default:
title = "";
break;
}
// TODO: Draw a hexagon icon
PPGeDrawImage(10, 6, 12.0f, 12.0f, 1, 10, 1, 10, 10, 10, CalcFadedColor(0xFFFFFFFF));
PPGeDrawText(title, 30, 11, PPGE_ALIGN_VCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF));
}
void PSPSaveDialog::DisplaySaveList(bool canMove)
{
int displayCount = 0;
for (int i = 0; i < param.GetFilenameCount(); i++)
{
int textureColor = 0xFFFFFFFF;
if (param.GetFileInfo(i).size == 0 && param.GetFileInfo(i).textureData == 0)
textureColor = 0xFF777777;
// Calc save image position on screen
float w, h , x, b;
float y = 97;
if (displayCount != currentSelectedSave) {
w = 81;
h = 45;
x = 58.5f;
} else {
w = 144;
h = 80;
x = 27;
b = 1.2;
PPGeDrawRect(x-b, y-b, x+w+b, y, CalcFadedColor(0xD0FFFFFF)); // top border
PPGeDrawRect(x-b, y, x, y+h, CalcFadedColor(0xD0FFFFFF)); // left border
PPGeDrawRect(x-b, y+h, x+w+b, y+h+b, CalcFadedColor(0xD0FFFFFF)); //bottom border
PPGeDrawRect(x+w, y, x+w+b, y+h, CalcFadedColor(0xD0FFFFFF)); //right border
}
if (displayCount < currentSelectedSave)
y -= 13 + 45 * (currentSelectedSave - displayCount);
else if (displayCount > currentSelectedSave)
y += 48 + 45 * (displayCount - currentSelectedSave);
int tw = 256;
int th = 256;
if (param.GetFileInfo(i).textureData != 0) {
tw = param.GetFileInfo(i).textureWidth;
th = param.GetFileInfo(i).textureHeight;
PPGeSetTexture(param.GetFileInfo(i).textureData, param.GetFileInfo(i).textureWidth, param.GetFileInfo(i).textureHeight);
PPGeDrawImage(x, y, w, h, 0, 0, 1, 1, tw, th, textureColor);
} else
PPGeDisableTexture();
PPGeSetDefaultTexture();
displayCount++;
}
if (canMove) {
if (IsButtonPressed(CTRL_UP) && currentSelectedSave > 0)
currentSelectedSave--;
else if (IsButtonPressed(CTRL_DOWN) && currentSelectedSave < (param.GetFilenameCount()-1))
currentSelectedSave++;
}
}
void PSPSaveDialog::DisplaySaveIcon()
{
int textureColor = CalcFadedColor(0xFFFFFFFF);
if (param.GetFileInfo(currentSelectedSave).size == 0)
textureColor = CalcFadedColor(0xFF777777);
// Calc save image position on screen
float w = 144;
float h = 80;
float x = 27;
float y = 97;
int tw = 256;
int th = 256;
if (param.GetFileInfo(currentSelectedSave).textureData != 0) {
tw = param.GetFileInfo(currentSelectedSave).textureWidth;
th = param.GetFileInfo(currentSelectedSave).textureHeight;
PPGeSetTexture(param.GetFileInfo(currentSelectedSave).textureData, param.GetFileInfo(currentSelectedSave).textureWidth, param.GetFileInfo(currentSelectedSave).textureHeight);
} else
PPGeDisableTexture();
PPGeDrawImage(x, y, w, h, 0, 0 ,1 ,1 ,tw, th, textureColor);
if (param.GetFileInfo(currentSelectedSave).textureData != 0)
PPGeSetDefaultTexture();
}
void PSPSaveDialog::DisplaySaveDataInfo1()
{
if (param.GetFileInfo(currentSelectedSave).size == 0) {
I18NCategory *d = GetI18NCategory("Dialog");
PPGeDrawText(d->T("NEW DATA"), 180, 136, PPGE_ALIGN_VCENTER, 0.6f, CalcFadedColor(0xFFFFFFFF));
} else {
char title[512];
char time[512];
char saveTitle[512];
char saveDetail[512];
char am_pm[] = "AM";
char hour_time[10] ;
int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour;
int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min;
switch (g_Config.iTimeFormat) {
case 1:
if (hour > 12) {
strcpy(am_pm, "PM");
hour -= 12;
}
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
break;
case 2:
snprintf(hour_time,10,"%02d:%02d", hour, min);
break;
default:
if (hour > 12) {
strcpy(am_pm, "PM");
hour -= 12;
}
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
}
snprintf(title, 512, "%s", param.GetFileInfo(currentSelectedSave).title);
int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday;
int month = param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1;
int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900;
s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024;
switch (g_Config.iDateFormat) {
case 1:
snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK);
break;
case 2:
snprintf(time, 512, "%02d/%02d/%d %s %lld KB", month, day, year, hour_time, sizeK);
break;
case 3:
snprintf(time, 512, "%02d/%02d/%d %s %lld KB", day, month, year, hour_time, sizeK);
break;
default:
snprintf(time, 512, "%d/%02d/%02d %s %lld KB", year, month, day, hour_time, sizeK);
}
snprintf(saveTitle, 512, "%s", param.GetFileInfo(currentSelectedSave).saveTitle);
snprintf(saveDetail, 512, "%s", param.GetFileInfo(currentSelectedSave).saveDetail);
PPGeDrawRect(180, 136, 980, 137, CalcFadedColor(0xFFFFFFFF));
std::string titleTxt = title;
std::string timeTxt = time;
std::string saveTitleTxt = saveTitle;
std::string saveDetailTxt = saveDetail;
PPGeDrawText(titleTxt.c_str(), 180, 136, PPGE_ALIGN_BOTTOM, 0.6f, CalcFadedColor(0xFFC0C0C0));
PPGeDrawText(timeTxt.c_str(), 180, 137, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawText(saveTitleTxt.c_str(), 175, 159, PPGE_ALIGN_LEFT, 0.55f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawText(saveDetailTxt.c_str(), 175, 181, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
}
}
void PSPSaveDialog::DisplaySaveDataInfo2()
{
if (param.GetFileInfo(currentSelectedSave).size == 0) {
} else {
char txt[1024];
char date[256];
char am_pm[] = "AM";
char hour_time[10] ;
int hour = param.GetFileInfo(currentSelectedSave).modif_time.tm_hour;
int min = param.GetFileInfo(currentSelectedSave).modif_time.tm_min;
switch (g_Config.iTimeFormat) {
case 1:
if (hour > 12) {
strcpy(am_pm, "PM");
hour -= 12;
}
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
break;
case 2:
snprintf(hour_time,10,"%02d:%02d", hour, min);
break;
default:
if (hour > 12) {
strcpy(am_pm, "PM");
hour -= 12;
}
snprintf(hour_time,10,"%02d:%02d %s", hour, min, am_pm);
}
const char *saveTitle = param.GetFileInfo(currentSelectedSave).saveTitle;
int day = param.GetFileInfo(currentSelectedSave).modif_time.tm_mday;
int month = param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1;
int year = param.GetFileInfo(currentSelectedSave).modif_time.tm_year + 1900;
s64 sizeK = param.GetFileInfo(currentSelectedSave).size / 1024;
switch (g_Config.iDateFormat) {
case 1:
snprintf(date, 256, "%d/%02d/%02d", year, month, day);
case 2:
snprintf(date, 256, "%02d/%02d/%d", month, day, year);
break;
case 3:
snprintf(date, 256, "%02d/%02d/%d", day, month, year);
break;
default:
snprintf(date, 256, "%d/%02d/%02d", year, month, day);
}
snprintf(txt, 1024, "%s\n%s %s\n%lld KB", saveTitle, date, hour_time, sizeK);
std::string saveinfoTxt = txt;
PPGeDrawText(saveinfoTxt.c_str(), 8, 200, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
}
}
void PSPSaveDialog::DisplayMessage(std::string text, bool hasYesNo)
{
const float WRAP_WIDTH = 254.0f;
float y = 136.0f, h;
int n;
PPGeMeasureText(0, &h, &n, text.c_str(), FONT_SCALE, PPGE_LINE_WRAP_WORD, WRAP_WIDTH);
float h2 = h * (float)n / 2.0f;
if (hasYesNo)
{
I18NCategory *d = GetI18NCategory("Dialog");
const char *choiceText;
u32 yesColor, noColor;
float x, w;
if (yesnoChoice == 1) {
choiceText = d->T("Yes");
x = 302.0f;
yesColor = 0xFFFFFFFF;
noColor = 0xFFFFFFFF;
}
else {
choiceText = d->T("No");
x = 366.0f;
yesColor = 0xFFFFFFFF;
noColor = 0xFFFFFFFF;
}
PPGeMeasureText(&w, &h, 0, choiceText, FONT_SCALE);
w = w / 2.0f + 5.5f;
h /= 2.0f;
float y2 = y + h2 + 4.0f;
h2 += h + 4.0f;
y = 132.0f - h;
PPGeDrawRect(x - w, y2 - h, x + w, y2 + h, CalcFadedColor(0x20CFCFCF));
PPGeDrawText(d->T("Yes"), 302.0f, y2, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(yesColor));
PPGeDrawText(d->T("No"), 366.0f, y2, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(noColor));
if (IsButtonPressed(CTRL_LEFT) && yesnoChoice == 0) {
yesnoChoice = 1;
}
else if (IsButtonPressed(CTRL_RIGHT) && yesnoChoice == 1) {
yesnoChoice = 0;
}
}
PPGeDrawTextWrapped(text.c_str(), 334.0f, y, WRAP_WIDTH, PPGE_ALIGN_CENTER, FONT_SCALE, CalcFadedColor(0xFFFFFFFF));
float sy = 122.0f - h2, ey = 150.0f + h2;
PPGeDrawRect(202.0f, sy, 466.0f, sy + 1.0f, CalcFadedColor(0xFFFFFFFF));
PPGeDrawRect(202.0f, ey, 466.0f, ey + 1.0f, CalcFadedColor(0xFFFFFFFF));
}
int PSPSaveDialog::Update()
{
switch (status) {
case SCE_UTILITY_STATUS_FINISHED:
status = SCE_UTILITY_STATUS_SHUTDOWN;
break;
default:
break;
}
if (status != SCE_UTILITY_STATUS_RUNNING)
return SCE_ERROR_UTILITY_INVALID_STATUS;
if (!param.GetPspParam()) {
status = SCE_UTILITY_STATUS_SHUTDOWN;
return 0;
}
// The struct may have been updated by the game. This happens in "Where Is My Heart?"
// Check if it has changed, reload it.
// TODO: Cut down on preloading? This rebuilds the list from scratch.
int size = Memory::Read_U32(requestAddr);
if (memcmp(Memory::GetPointer(requestAddr), &originalRequest, size) != 0) {
memset(&request, 0, sizeof(request));
Memory::Memcpy(&request, requestAddr, size);
Memory::Memcpy(&originalRequest, requestAddr, size);
param.SetPspParam(&request);
}
buttons = __CtrlPeekButtons();
UpdateFade();
okButtonImg = I_CIRCLE;
cancelButtonImg = I_CROSS;
okButtonFlag = CTRL_CIRCLE;
cancelButtonFlag = CTRL_CROSS;
if (param.GetPspParam()->common.buttonSwap == 1) {
okButtonImg = I_CROSS;
cancelButtonImg = I_CIRCLE;
okButtonFlag = CTRL_CROSS;
cancelButtonFlag = CTRL_CIRCLE;
}
I18NCategory *d = GetI18NCategory("Dialog");
switch (display)
{
case DS_SAVE_LIST_CHOICE:
StartDraw();
DisplaySaveList();
DisplaySaveDataInfo1();
DisplayButtons(DS_BUTTON_OK | DS_BUTTON_CANCEL);
DisplayBanner(DB_SAVE);
if (IsButtonPressed(cancelButtonFlag)) {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL;
StartFade(false);
} else if (IsButtonPressed(okButtonFlag)) {
// Save exist, ask user confirm
if (param.GetFileInfo(currentSelectedSave).size > 0) {
yesnoChoice = 0;
display = DS_SAVE_CONFIRM_OVERWRITE;
} else {
display = DS_SAVE_SAVING;
if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) {
param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save
display = DS_SAVE_DONE;
} else
display = DS_SAVE_LIST_CHOICE; // This will probably need error message ?
}
}
EndDraw();
break;
case DS_SAVE_CONFIRM:
StartDraw();
DisplaySaveIcon();
DisplaySaveDataInfo2();
DisplayMessage(d->T("Confirm Save", "Do you want to save this data?"), true);
DisplayButtons(DS_BUTTON_OK | DS_BUTTON_CANCEL);
DisplayBanner(DB_SAVE);
if (IsButtonPressed(cancelButtonFlag) || (IsButtonPressed(okButtonFlag) && yesnoChoice == 0)) {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL;
StartFade(false);
} else if (IsButtonPressed(okButtonFlag)) {
display = DS_SAVE_SAVING;
if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) {
param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save
display = DS_SAVE_DONE;
} else {
// TODO: This should probably show an error message?
StartFade(false);
}
}
EndDraw();
break;
case DS_SAVE_CONFIRM_OVERWRITE:
StartDraw();
DisplaySaveIcon();
DisplaySaveDataInfo2();
DisplayMessage(d->T("Do you want to overwrite the data?"), true);
DisplayButtons(DS_BUTTON_OK | DS_BUTTON_CANCEL);
DisplayBanner(DB_SAVE);
if (IsButtonPressed(cancelButtonFlag) || (IsButtonPressed(okButtonFlag) && yesnoChoice == 0)) {
if (param.GetPspParam()->mode != SCE_UTILITY_SAVEDATA_TYPE_SAVE)
display = DS_SAVE_LIST_CHOICE;
else {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL;
StartFade(false);
}
} else if (IsButtonPressed(okButtonFlag)) {
display = DS_SAVE_SAVING;
if (param.Save(param.GetPspParam(), GetSelectedSaveDirName())) {
param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save
display = DS_SAVE_DONE;
} else {
// TODO: This should probably show an error message?
if (param.GetPspParam()->mode != SCE_UTILITY_SAVEDATA_TYPE_SAVE)
display = DS_SAVE_LIST_CHOICE;
else
StartFade(false);
}
}
EndDraw();
break;
case DS_SAVE_SAVING:
StartDraw();
DisplaySaveIcon();
DisplaySaveDataInfo2();
DisplayMessage(d->T("Saving","Saving\nPlease Wait..."));
DisplayBanner(DB_SAVE);
EndDraw();
break;
case DS_SAVE_DONE:
StartDraw();
DisplaySaveIcon();
DisplaySaveDataInfo2();
DisplayMessage(d->T("Save completed"));
DisplayButtons(DS_BUTTON_CANCEL);
DisplayBanner(DB_SAVE);
if (IsButtonPressed(cancelButtonFlag)) {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_SUCCESS;
// Set the save to use for autosave and autoload
param.SetSelectedSave(param.GetFileInfo(currentSelectedSave).idx);
StartFade(false);
}
EndDraw();
break;
case DS_LOAD_LIST_CHOICE:
StartDraw();
DisplaySaveList();
DisplaySaveDataInfo1();
DisplayButtons(DS_BUTTON_OK | DS_BUTTON_CANCEL);
DisplayBanner(DB_LOAD);
if (IsButtonPressed(cancelButtonFlag)) {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL;
StartFade(false);
} else if (IsButtonPressed(okButtonFlag)) {
display = DS_LOAD_LOADING;
if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave))
display = DS_LOAD_DONE;
}
EndDraw();
break;
case DS_LOAD_CONFIRM:
StartDraw();
DisplaySaveIcon();
DisplaySaveDataInfo2();
DisplayMessage(d->T("ConfirmLoad", "Load this data?"), true);
DisplayButtons(DS_BUTTON_OK | DS_BUTTON_CANCEL);
DisplayBanner(DB_LOAD);
if (IsButtonPressed(cancelButtonFlag) || (IsButtonPressed(okButtonFlag) && yesnoChoice == 0)) {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL;
StartFade(false);
} else if (IsButtonPressed(okButtonFlag)) {
display = DS_LOAD_LOADING;
if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave))
display = DS_LOAD_DONE;
else {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL;
StartFade(false);
}
}
EndDraw();
break;
case DS_LOAD_LOADING:
StartDraw();
DisplaySaveIcon();
DisplaySaveDataInfo2();
DisplayMessage(d->T("Loading","Loading\nPlease Wait..."));
DisplayBanner(DB_LOAD);
EndDraw();
break;
case DS_LOAD_DONE:
StartDraw();
DisplaySaveIcon();
DisplaySaveDataInfo2();
DisplayMessage(d->T("Load completed"));
DisplayButtons(DS_BUTTON_CANCEL);
DisplayBanner(DB_LOAD);
if (IsButtonPressed(cancelButtonFlag)) {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_SUCCESS;
// Set the save to use for autosave and autoload
param.SetSelectedSave(param.GetFileInfo(currentSelectedSave).idx);
StartFade(false);
}
EndDraw();
break;
case DS_LOAD_NODATA:
StartDraw();
DisplayMessage(d->T("There is no data"));
DisplayButtons(DS_BUTTON_CANCEL);
DisplayBanner(DB_LOAD);
if (IsButtonPressed(cancelButtonFlag)) {
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA;
StartFade(false);
}
EndDraw();
break;
case DS_DELETE_LIST_CHOICE:
StartDraw();
DisplaySaveList();
DisplaySaveDataInfo1();
DisplayButtons(DS_BUTTON_OK | DS_BUTTON_CANCEL);
DisplayBanner(DB_DELETE);
if (IsButtonPressed(cancelButtonFlag)) {
param.GetPspParam()->common.result = SCE_UTILITY_DIALOG_RESULT_CANCEL;
StartFade(false);
} else if (IsButtonPressed(okButtonFlag)) {
yesnoChoice = 0;
display = DS_DELETE_CONFIRM;
}
EndDraw();
break;
case DS_DELETE_CONFIRM:
StartDraw();
DisplaySaveIcon();
DisplaySaveDataInfo2();
DisplayMessage(d->T("DeleteConfirm",
"This save data will be deleted.\nAre you sure you want to continue?"),
true);
DisplayButtons(DS_BUTTON_OK | DS_BUTTON_CANCEL);
DisplayBanner(DB_DELETE);
if (IsButtonPressed(cancelButtonFlag))
display = DS_DELETE_LIST_CHOICE;
else if (IsButtonPressed(okButtonFlag)) {
if (yesnoChoice == 0)
display = DS_DELETE_LIST_CHOICE;
else {
display = DS_DELETE_DELETING;
if (param.Delete(param.GetPspParam(),currentSelectedSave)) {
param.SetPspParam(param.GetPspParam()); // Optim : Just Update modified save
display = DS_DELETE_DONE;
} else
display = DS_DELETE_LIST_CHOICE; // This will probably need error message ?
}
}
EndDraw();
break;
case DS_DELETE_DELETING:
StartDraw();
DisplayMessage(d->T("Deleting","Deleting\nPlease Wait..."));
DisplayBanner(DB_DELETE);
EndDraw();
break;
case DS_DELETE_DONE:
StartDraw();
DisplayMessage(d->T("Delete completed"));
DisplayButtons(DS_BUTTON_CANCEL);
DisplayBanner(DB_DELETE);
if (IsButtonPressed(cancelButtonFlag)) {
if (param.GetFilenameCount() == 0)
display = DS_DELETE_NODATA;
else
display = DS_DELETE_LIST_CHOICE;
}
EndDraw();
break;
case DS_DELETE_NODATA:
StartDraw();
DisplayMessage(d->T("There is no data"));
DisplayButtons(DS_BUTTON_CANCEL);
DisplayBanner(DB_DELETE);
if (IsButtonPressed(cancelButtonFlag)) {
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_DELETE_NO_DATA;
StartFade(false);
}
EndDraw();
break;
case DS_NONE: // For action which display nothing
{
switch (param.GetPspParam()->mode)
{
case SCE_UTILITY_SAVEDATA_TYPE_LOAD: // Only load and exit
case SCE_UTILITY_SAVEDATA_TYPE_AUTOLOAD:
if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave))
param.GetPspParam()->common.result = 0;
else
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_LOAD_NO_DATA;
status = SCE_UTILITY_STATUS_FINISHED;
break;
case SCE_UTILITY_SAVEDATA_TYPE_SAVE: // Only save and exit
case SCE_UTILITY_SAVEDATA_TYPE_AUTOSAVE:
if (param.Save(param.GetPspParam(), GetSelectedSaveDirName()))
param.GetPspParam()->common.result = 0;
else
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_SAVE_MS_NOSPACE;
status = SCE_UTILITY_STATUS_FINISHED;
break;
case SCE_UTILITY_SAVEDATA_TYPE_SIZES:
param.GetPspParam()->common.result = param.GetSizes(param.GetPspParam());
status = SCE_UTILITY_STATUS_FINISHED;
break;
case SCE_UTILITY_SAVEDATA_TYPE_LIST:
param.GetList(param.GetPspParam());
param.GetPspParam()->common.result = 0;
status = SCE_UTILITY_STATUS_FINISHED;
break;
case SCE_UTILITY_SAVEDATA_TYPE_FILES:
param.GetPspParam()->common.result = param.GetFilesList(param.GetPspParam());
status = SCE_UTILITY_STATUS_FINISHED;
break;
case SCE_UTILITY_SAVEDATA_TYPE_GETSIZE:
{
bool result = param.GetSize(param.GetPspParam());
// TODO: According to JPCSP, should test/verify this part but seems edge casey.
if (MemoryStick_State() != PSP_MEMORYSTICK_STATE_DRIVER_READY)
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_MEMSTICK;
else if (result)
param.GetPspParam()->common.result = 0;
else
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA;
status = SCE_UTILITY_STATUS_FINISHED;
}
break;
case SCE_UTILITY_SAVEDATA_TYPE_DELETEDATA:
// TODO: This should probably actually delete something.
// For now, always say it couldn't be deleted.
WARN_LOG(HLE, "FAKE sceUtilitySavedata DELETEDATA: %s", param.GetPspParam()->saveName);
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_BAD_STATUS;
status = SCE_UTILITY_STATUS_FINISHED;
break;
//case SCE_UTILITY_SAVEDATA_TYPE_AUTODELETE:
case SCE_UTILITY_SAVEDATA_TYPE_SINGLEDELETE:
if (param.Delete(param.GetPspParam(), param.GetSelectedSave()))
param.GetPspParam()->common.result = 0;
else
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_DELETE_NO_DATA;
status = SCE_UTILITY_STATUS_FINISHED;
break;
// TODO: Should reset the directory's other files.
case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE:
if (param.Save(param.GetPspParam(), GetSelectedSaveDirName(), param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE))
param.GetPspParam()->common.result = 0;
else
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA;
status = SCE_UTILITY_STATUS_FINISHED;
break;
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATA:
case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE:
if (param.Save(param.GetPspParam(), GetSelectedSaveDirName(), param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE))
param.GetPspParam()->common.result = 0;
else
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA;
status = SCE_UTILITY_STATUS_FINISHED;
break;
case SCE_UTILITY_SAVEDATA_TYPE_READDATA:
case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE:
if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave, param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE))
param.GetPspParam()->common.result = 0;
else
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; // not sure if correct code
status = SCE_UTILITY_STATUS_FINISHED;
break;
default:
status = SCE_UTILITY_STATUS_FINISHED;
break;
}
}
break;
default:
status = SCE_UTILITY_STATUS_FINISHED;
break;
}
lastButtons = buttons;
if (status == SCE_UTILITY_STATUS_FINISHED)
Memory::Memcpy(requestAddr, &request, request.common.size);
return 0;
}
int PSPSaveDialog::Shutdown(bool force)
{
if (status != SCE_UTILITY_STATUS_FINISHED && !force)
return SCE_ERROR_UTILITY_INVALID_STATUS;
PSPDialog::Shutdown();
param.SetPspParam(0);
return 0;
}
void PSPSaveDialog::DoState(PointerWrap &p)
{
PSPDialog::DoState(p);
p.Do(display);
param.DoState(p);
p.Do(request);
// Just reset it.
bool hasParam = param.GetPspParam() != NULL;
p.Do(hasParam);
if (hasParam)
param.SetPspParam(&request);
p.Do(requestAddr);
p.Do(currentSelectedSave);
p.Do(yesnoChoice);
p.DoMarker("PSPSaveDialog");
}
pspUtilityDialogCommon *PSPSaveDialog::GetCommonParam()
{
return &param.GetPspParam()->common;
}