diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index f7e0dd79e2..f72a246484 100644 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -44,6 +44,13 @@ int PSPMsgDialog::Init(unsigned int paramAddr) } Memory::ReadStruct(messageDialogAddr, &messageDialog); + // debug info + int optionsNotCoded = ((messageDialog.options | SCE_UTILITY_MSGDIALOG_DEBUG_OPTION_CODED) ^ SCE_UTILITY_MSGDIALOG_DEBUG_OPTION_CODED); + if(optionsNotCoded) + { + ERROR_LOG(HLE,"PSPMsgDialog options not coded : 0x%08x",optionsNotCoded); + } + yesnoChoice = 1; if (messageDialog.type == 0) // number { @@ -56,6 +63,8 @@ int PSPMsgDialog::Init(unsigned int paramAddr) display = DS_MESSAGE; if(messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_YESNO) display = DS_YESNO; + if(messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_OK) + display = DS_OK; if(messageDialog.options & SCE_UTILITY_MSGDIALOG_OPTION_DEFAULT_NO) yesnoChoice = 0; } @@ -189,6 +198,25 @@ int PSPMsgDialog::Update() } EndDraw(); break; + case DS_OK: + StartDraw(); + + DisplayMessage(text); + + // TODO : Dialogs should take control over input and not send them to the game while displaying + DisplayEnterBack(); + if (IsButtonPressed(cancelButtonFlag)) + { + status = SCE_UTILITY_STATUS_FINISHED; + messageDialog.buttonPressed = 3; + } + else if (IsButtonPressed(okButtonFlag)) + { + status = SCE_UTILITY_STATUS_FINISHED; + messageDialog.buttonPressed = 1; + } + EndDraw(); + break; default: status = SCE_UTILITY_STATUS_FINISHED; return 0; diff --git a/Core/Dialog/PSPMsgDialog.h b/Core/Dialog/PSPMsgDialog.h index 779a77f4e6..c738f5e8d5 100644 --- a/Core/Dialog/PSPMsgDialog.h +++ b/Core/Dialog/PSPMsgDialog.h @@ -22,8 +22,11 @@ #define SCE_UTILITY_MSGDIALOG_OPTION_ERROR 0 // Do nothing #define SCE_UTILITY_MSGDIALOG_OPTION_TEXT 0x00000001 #define SCE_UTILITY_MSGDIALOG_OPTION_YESNO 0x00000010 +#define SCE_UTILITY_MSGDIALOG_OPTION_OK 0x00000020 #define SCE_UTILITY_MSGDIALOG_OPTION_DEFAULT_NO 0x00000100 +#define SCE_UTILITY_MSGDIALOG_DEBUG_OPTION_CODED 0x00000131 // OR of all options coded to display warning + struct pspMessageDialog { pspUtilityDialogCommon common; @@ -32,7 +35,7 @@ struct pspMessageDialog unsigned int errorNum; char string[512]; unsigned int options; - unsigned int buttonPressed; // 0=?, 1=Yes, 2=No, 3=Back + unsigned int buttonPressed; // 0=?, 1=Yes/OK, 2=No, 3=Back }; @@ -58,6 +61,7 @@ private : DS_MESSAGE, DS_ERROR, DS_YESNO, + DS_OK }; DisplayState display; diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index b9ee98b671..05afc27d54 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -81,9 +81,12 @@ int PSPSaveDialog::Init(int paramAddr) display = DS_DELETE_LIST_CHOICE; break; case SCE_UTILITY_SAVEDATA_TYPE_SIZES: - display = DS_NONE; - break; case SCE_UTILITY_SAVEDATA_TYPE_LIST: + case SCE_UTILITY_SAVEDATA_TYPE_FILES: + case SCE_UTILITY_SAVEDATA_TYPE_SIZES22: + case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE: + case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE: + case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE: 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) @@ -242,7 +245,7 @@ void PSPSaveDialog::DisplaySaveDataInfo1() char txt[2048]; _dbg_assert_msg_(HLE, sizeof(txt) > sizeof(SaveFileInfo), "Local buffer is too small."); - sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d %lld KB\n%s\n%s" + snprintf(txt,2048,"%s\n%02d/%02d/%d %02d:%02d %lld KB\n%s\n%s" , param.GetFileInfo(currentSelectedSave).title , param.GetFileInfo(currentSelectedSave).modif_time.tm_mday , param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1 @@ -266,7 +269,7 @@ void PSPSaveDialog::DisplaySaveDataInfo2() else { char txt[1024]; - sprintf(txt,"%s\n%02d/%02d/%d %02d:%02d\n%lld KB" + snprintf(txt,1024,"%s\n%02d/%02d/%d %02d:%02d\n%lld KB" , param.GetFileInfo(currentSelectedSave).saveTitle , param.GetFileInfo(currentSelectedSave).modif_time.tm_mday , param.GetFileInfo(currentSelectedSave).modif_time.tm_mon + 1 @@ -671,10 +674,41 @@ int PSPSaveDialog::Update() param.GetPspParam()->result = 0; status = SCE_UTILITY_STATUS_FINISHED; break; - // TODO: Don't know the name? - case 12: - // Pretend we have nothing, always. - param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; + case SCE_UTILITY_SAVEDATA_TYPE_FILES: + if(param.GetFilesList(param.GetPspParam())) + { + param.GetPspParam()->result = 0; + } + else + { + param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; + } + status = SCE_UTILITY_STATUS_FINISHED; + break; + case SCE_UTILITY_SAVEDATA_TYPE_SIZES22: + if(param.GetSizes22(param.GetPspParam())) + { + param.GetPspParam()->result = 0; + } + else + { + param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; + } + status = SCE_UTILITY_STATUS_FINISHED; + break; + case SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE: + case SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE: + if(param.Save(param.GetPspParam(),param.GetSelectedSave())) + param.GetPspParam()->result = 0; + else + param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; + status = SCE_UTILITY_STATUS_FINISHED; + break; + case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE: + if(param.Load(param.GetPspParam(),param.GetSelectedSave())) + param.GetPspParam()->result = 0; + else + param.GetPspParam()->result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; // not sure if correct code status = SCE_UTILITY_STATUS_FINISHED; break; default: diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 52afb9c19f..315f13ba82 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -163,6 +163,8 @@ std::string SavedataParam::GetSaveName(SceUtilitySavedataParam* param) char saveName[21]; memcpy(saveName,param->saveName,20); saveName[20] = 0; + if(strcmp(saveName,"<>") == 0) + return ""; return saveName; } @@ -200,95 +202,129 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) return false; } - u8 *data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->dataBuf)); - std::string dirPath = GetSaveFilePath(param, saveId); if (!pspFileSystem.GetFileInfo(dirPath).exists) pspFileSystem.MkDir(dirPath); - std::string filePath = dirPath+"/"+GetFileName(param); - INFO_LOG(HLE,"Saving file with size %u in %s",param->dataBufSize,filePath.c_str()); - if (!WritePSPFile(filePath, data_, param->dataBufSize)) + if(param->dataBuf != 0) // Can launch save without save data in mode 13 { - ERROR_LOG(HLE,"Error writing file %s",filePath.c_str()); - return false; + std::string filePath = dirPath+"/"+GetFileName(param); + INFO_LOG(HLE,"Saving file with size %u in %s",param->dataBufSize,filePath.c_str()); + u8 *data_ = (u8*)Memory::GetPointer(param->dataBuf); + + if (!WritePSPFile(filePath, data_, param->dataBufSize)) + { + ERROR_LOG(HLE,"Error writing file %s",filePath.c_str()); + return false; + } } - else + + // SAVE PARAM.SFO + ParamSFOData sfoFile; + std::string sfopath = dirPath+"/"+sfoName; + PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath); + if(sfoInfo.exists) // Read old sfo if exist { - // SAVE PARAM.SFO - ParamSFOData sfoFile; - sfoFile.SetValue("TITLE",param->sfoParam.title,128); - sfoFile.SetValue("SAVEDATA_TITLE",param->sfoParam.savedataTitle,128); - sfoFile.SetValue("SAVEDATA_DETAIL",param->sfoParam.detail,1024); - sfoFile.SetValue("PARENTAL_LEVEL",param->sfoParam.parentalLevel,4); - sfoFile.SetValue("CATEGORY","MS",4); - sfoFile.SetValue("SAVEDATA_DIRECTORY",GetSaveDir(param,saveId),64); + u8 *sfoData = new u8[sfoInfo.size]; + size_t sfoSize = sfoInfo.size; + if(ReadPSPFile(sfopath,sfoData,sfoSize)) + { + sfoFile.ReadSFO(sfoData,sfoSize); + delete[] sfoData; + } + } - // For each file, 32 bytes for filename, 32 bytes for file hash (0 in PPSSPP) - u8* tmpData = new u8[3168]; + // Update values + sfoFile.SetValue("TITLE",param->sfoParam.title,128); + sfoFile.SetValue("SAVEDATA_TITLE",param->sfoParam.savedataTitle,128); + sfoFile.SetValue("SAVEDATA_DETAIL",param->sfoParam.detail,1024); + sfoFile.SetValue("PARENTAL_LEVEL",param->sfoParam.parentalLevel,4); + sfoFile.SetValue("CATEGORY","MS",4); + sfoFile.SetValue("SAVEDATA_DIRECTORY",GetSaveDir(param,saveId),64); + + // For each file, 13 bytes for filename, 16 bytes for file hash (0 in PPSSPP), 3 byte for padding + u8* tmpData = sfoFile.GetValueData("SAVEDATA_FILE_LIST", 0); + u8* tmpData2 = 0; + if(tmpData == 0) + { + tmpData2 = new u8[3168]; // 99 filename max + tmpData = tmpData2; memset(tmpData, 0, 3168); - sprintf((char*)tmpData,"%s",GetFileName(param).c_str()); - sfoFile.SetValue("SAVEDATA_FILE_LIST", tmpData, 3168, 3168); - delete[] tmpData; - - // No crypted save, so fill with 0 - tmpData = new u8[128]; - memset(tmpData, 0, 128); - sfoFile.SetValue("SAVEDATA_PARAMS", tmpData, 128, 128); - delete[] tmpData; - - u8 *sfoData; - size_t sfoSize; - sfoFile.WriteSFO(&sfoData,&sfoSize); - std::string sfopath = dirPath+"/"+sfoName; - WritePSPFile(sfopath, sfoData, sfoSize); - delete[] sfoData; - - // SAVE ICON0 - if (param->icon0FileData.buf) + } + if(param->dataBuf != 0) + { + char* fName = (char*)tmpData; + for(int i = 0; i < 99; i++) { - data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->icon0FileData.buf)); - std::string icon0path = dirPath+"/"+icon0Name; - WritePSPFile(icon0path, data_, param->icon0FileData.bufSize); - } - // SAVE ICON1 - if (param->icon1FileData.buf) - { - data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->icon1FileData.buf)); - std::string icon1path = dirPath+"/"+icon1Name; - WritePSPFile(icon1path, data_, param->icon1FileData.bufSize); - } - // SAVE PIC1 - if (param->pic1FileData.buf) - { - data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->pic1FileData.buf)); - std::string pic1path = dirPath+"/"+pic1Name; - WritePSPFile(pic1path, data_, param->pic1FileData.bufSize); - } + if(fName[0] == 0) + break; // End of list + if(strncmp(fName,GetFileName(param).c_str(),20) == 0) + break; // File already in SFO - // Save SND - if (param->snd0FileData.buf) - { - data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->snd0FileData.buf)); - std::string snd0path = dirPath+"/"+snd0Name; - WritePSPFile(snd0path, data_, param->snd0FileData.bufSize); + fName += 32; } + snprintf(fName, 20,"%s",GetFileName(param).c_str()); + } + sfoFile.SetValue("SAVEDATA_FILE_LIST", tmpData, 3168, 3168); + if(tmpData2) + delete[] tmpData2; - // Save Encryption Data - { - EncryptFileInfo encryptInfo; - int dataSize = sizeof(encryptInfo); // version + key + sdkVersion - memset(&encryptInfo,0,dataSize); + // No crypted save, so fill with 0 + tmpData = new u8[128]; + memset(tmpData, 0, 128); + sfoFile.SetValue("SAVEDATA_PARAMS", tmpData, 128, 128); + delete[] tmpData; - encryptInfo.fileVersion = 1; - encryptInfo.sdkVersion = sceKernelGetCompiledSdkVersion(); - if(param->size > 1500) - memcpy(encryptInfo.key,param->key,16); + u8 *sfoData; + size_t sfoSize; + sfoFile.WriteSFO(&sfoData,&sfoSize); + WritePSPFile(sfopath, sfoData, sfoSize); + delete[] sfoData; - std::string encryptInfoPath = dirPath+"/"+"ENCRYPT_INFO.BIN"; - WritePSPFile(encryptInfoPath, (u8*)&encryptInfo, dataSize); - } + // SAVE ICON0 + if (param->icon0FileData.buf) + { + u8* data_ = (u8*)Memory::GetPointer(param->icon0FileData.buf); + std::string icon0path = dirPath+"/"+icon0Name; + WritePSPFile(icon0path, data_, param->icon0FileData.bufSize); + } + // SAVE ICON1 + if (param->icon1FileData.buf) + { + u8* data_ = (u8*)Memory::GetPointer(param->icon1FileData.buf); + std::string icon1path = dirPath+"/"+icon1Name; + WritePSPFile(icon1path, data_, param->icon1FileData.bufSize); + } + // SAVE PIC1 + if (param->pic1FileData.buf) + { + u8* data_ = (u8*)Memory::GetPointer(param->pic1FileData.buf); + std::string pic1path = dirPath+"/"+pic1Name; + WritePSPFile(pic1path, data_, param->pic1FileData.bufSize); + } + + // Save SND + if (param->snd0FileData.buf) + { + u8* data_ = (u8*)Memory::GetPointer(param->snd0FileData.buf); + std::string snd0path = dirPath+"/"+snd0Name; + WritePSPFile(snd0path, data_, param->snd0FileData.bufSize); + } + + // Save Encryption Data + { + EncryptFileInfo encryptInfo; + int dataSize = sizeof(encryptInfo); // version + key + sdkVersion + memset(&encryptInfo,0,dataSize); + + encryptInfo.fileVersion = 1; + encryptInfo.sdkVersion = sceKernelGetCompiledSdkVersion(); + if(param->size > 1500) + memcpy(encryptInfo.key,param->key,16); + + std::string encryptInfoPath = dirPath+"/"+"ENCRYPT_INFO.BIN"; + WritePSPFile(encryptInfoPath, (u8*)&encryptInfo, dataSize); } return true; } @@ -299,7 +335,7 @@ bool SavedataParam::Load(SceUtilitySavedataParam *param, int saveId) return false; } - u8 *data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->dataBuf)); + u8 *data_ = (u8*)Memory::GetPointer(param->dataBuf); std::string dirPath = GetSaveFilePath(param, saveId); if (saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it @@ -317,6 +353,7 @@ bool SavedataParam::Load(SceUtilitySavedataParam *param, int saveId) ERROR_LOG(HLE,"Error reading file %s",filePath.c_str()); return false; } + param->dataSize = param->dataBufSize; return true; } @@ -351,9 +388,6 @@ std::string SavedataParam::GetSpaceText(int size) return std::string(text); } -// From my test, PSP only answer with data for save of size 1500 (sdk < 2) -// Perhaps changed to use mode 22 id SDK >= 2 -// For now we always return results bool SavedataParam::GetSizes(SceUtilitySavedataParam *param) { if (!param) { @@ -449,9 +483,12 @@ bool SavedataParam::GetList(SceUtilitySavedataParam *param) { u32 baseAddr = outputBuffer + (i*72); Memory::Write_U32(0x11FF,baseAddr + 0); // mode - Memory::Write_U64(0,baseAddr + 4); // TODO ctime << this seems to not work, write 0 only on 32bits + Memory::Write_U64(0,baseAddr + 4); // TODO ctime + Memory::Write_U64(0,baseAddr + 12); // TODO unknow Memory::Write_U64(0,baseAddr + 20); // TODO atime + Memory::Write_U64(0,baseAddr + 28); // TODO unknow Memory::Write_U64(0,baseAddr + 36); // TODO mtime + Memory::Write_U64(0,baseAddr + 44); // TODO unknow // folder name without gamename (max 20 u8) std::string outName = validDir[i].name.substr(GetGameName(param).size()); Memory::Memset(baseAddr + 52,0,20); @@ -464,6 +501,65 @@ bool SavedataParam::GetList(SceUtilitySavedataParam *param) return true; } +bool SavedataParam::GetFilesList(SceUtilitySavedataParam *param) +{ + if (!param) + { + return false; + } + + u32 dataAddr = param->fileListAddr; + if(!Memory::IsValidAddress(dataAddr)) + return false; + + // TODO : Need to be checked against more game + + u32 fileInfosAddr = Memory::Read_U32(dataAddr + 24); + + //for Valkyria2, dataAddr+0 and dataAddr+12 has "5" for 5 files + int numFiles = Memory::Read_U32(dataAddr+12); + int foundFiles = 0; + for(int i = 0; i < numFiles; i++) + { + // for each file (80 bytes): + // u32 mode, u32 ??, u64 size, u64 ctime, u64 ??, u64 atime, u64 ???, u64 mtime, u64 ??? + // u8[16] filename (or 13 + padding?) + u32 curFileInfoAddr = fileInfosAddr + i*80; + + char fileName[16]; + strncpy(fileName, Memory::GetCharPointer(curFileInfoAddr + 64),16); + std::string filePath = savePath + GetGameName(param) + GetSaveName(param) + "/" + fileName; + PSPFileInfo info = pspFileSystem.GetFileInfo(filePath); + if(info.exists) + { + Memory::Write_U32(0x21FF, curFileInfoAddr+0); + Memory::Write_U64(info.size, curFileInfoAddr+8); + Memory::Write_U64(0,curFileInfoAddr + 16); // TODO ctime + Memory::Write_U64(0,curFileInfoAddr + 24); // TODO unknow + Memory::Write_U64(0,curFileInfoAddr + 32); // TODO atime + Memory::Write_U64(0,curFileInfoAddr + 40); // TODO unknow + Memory::Write_U64(0,curFileInfoAddr + 48); // TODO mtime + Memory::Write_U64(0,curFileInfoAddr + 56); // TODO unknow + foundFiles++; + } + } + + // TODO : verify if return true if at least 1 file found or only if all found + return foundFiles > 0; +} + +bool SavedataParam::GetSizes22(SceUtilitySavedataParam *param) +{ + if (!param) + { + return false; + } + + // TODO code this + + return false; +} + void SavedataParam::Clear() { if (saveDataList) diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 4a1384a8ac..702dc8b5d4 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -31,7 +31,12 @@ enum SceUtilitySavedataType SCE_UTILITY_SAVEDATA_TYPE_LISTDELETE = 6, SCE_UTILITY_SAVEDATA_TYPE_DELETE = 7, SCE_UTILITY_SAVEDATA_TYPE_SIZES = 8, - SCE_UTILITY_SAVEDATA_TYPE_LIST = 11 + SCE_UTILITY_SAVEDATA_TYPE_LIST = 11, + SCE_UTILITY_SAVEDATA_TYPE_FILES = 12, + SCE_UTILITY_SAVEDATA_TYPE_MAKEDATASECURE = 13, + SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE = 15, + SCE_UTILITY_SAVEDATA_TYPE_WRITEDATASECURE = 17, + SCE_UTILITY_SAVEDATA_TYPE_SIZES22 = 22 } ; // title, savedataTitle, detail: parts of the unencrypted SFO @@ -81,7 +86,7 @@ struct SceUtilitySavedataParam char unused2[3]; /** pointer to a buffer that will contain data file unencrypted data */ - int dataBuf; // Initially void*, but void* in 64bit system take 8 bytes. + u32 dataBuf; // Initially void*, but void* in 64bit system take 8 bytes. /** size of allocated space to dataBuf */ SceSize dataBufSize; SceSize dataSize; // Size of the actual save data @@ -98,9 +103,9 @@ struct SceUtilitySavedataParam int abortStatus; // Function SCE_UTILITY_SAVEDATA_TYPE_SIZES - int msFree; - int msData; - int utilityData; + u32 msFree; + u32 msData; + u32 utilityData; char key[16]; @@ -108,13 +113,13 @@ struct SceUtilitySavedataParam int multiStatus; // Function 11 LIST - int idListAddr; + u32 idListAddr; // Function 12 FILES - int fileListAddr; + u32 fileListAddr; // Function 22 GETSIZES - int sizeAddr; + u32 sizeAddr; }; @@ -147,6 +152,8 @@ public: bool Load(SceUtilitySavedataParam* param, int saveId = -1); bool GetSizes(SceUtilitySavedataParam* param); bool GetList(SceUtilitySavedataParam* param); + bool GetFilesList(SceUtilitySavedataParam* param); + bool GetSizes22(SceUtilitySavedataParam* param); std::string GetGameName(SceUtilitySavedataParam* param); std::string GetSaveName(SceUtilitySavedataParam* param);