diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 8a5e464e32..5eed0de3be 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -19,6 +19,7 @@ #include "../System.h" #include "image/png_load.h" #include "../HLE/sceKernelMemory.h" +#include "../ELF/ParamSFO.h" std::string icon0Name = "ICON0.PNG"; std::string icon1Name = "ICON1.PNG"; @@ -45,8 +46,7 @@ void SavedataParam::Init() } } - -std::string SavedataParam::GetSaveFilePath(SceUtilitySavedataParam* param, int saveId) +std::string SavedataParam::GetSaveDir(SceUtilitySavedataParam* param, int saveId) { if (!param) { return ""; @@ -56,7 +56,16 @@ std::string SavedataParam::GetSaveFilePath(SceUtilitySavedataParam* param, int s if(saveId >= 0 && saveNameListDataCount > 0) // if user selection, use it dirPath = std::string(GetGameName(param))+GetFilename(saveId); - return savePath + dirPath; + return dirPath; +} + +std::string SavedataParam::GetSaveFilePath(SceUtilitySavedataParam* param, int saveId) +{ + if (!param) { + return ""; + } + + return savePath + GetSaveDir(param,saveId); } std::string SavedataParam::GetGameName(SceUtilitySavedataParam* param) @@ -134,9 +143,27 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, int saveId) { pspFileSystem.CloseFile(handle); - // TODO SAVE PARAM.SFO - /*data_ = (u8*)Memory::GetPointer(*((unsigned int*)¶m->dataBuf)); - writeDataToFile(false, );*/ + // 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.savedataTitle,1024); + sfoFile.SetValue("PARENTAL_LEVEL",param->sfoParam.parentalLevel,4); + sfoFile.SetValue("CATEGORY","MS",4); + sfoFile.SetValue("SAVEDATA_DIRECTORY",GetSaveDir(param,saveId),64); + sfoFile.SetValue("SAVEDATA_FILE_LIST","",3168); + sfoFile.SetValue("SAVEDATA_PARAMS","",128); + u8* sfoData; + size_t sfoSize; + sfoFile.WriteSFO(&sfoData,&sfoSize); + std::string sfopath = dirPath+"/"+sfoName; + handle = pspFileSystem.OpenFile(sfopath,(FileAccess)(FILEACCESS_WRITE | FILEACCESS_CREATE)); + if(handle) + { + pspFileSystem.WriteFile(handle, sfoData, sfoSize); + pspFileSystem.CloseFile(handle); + } + delete[] sfoData; // SAVE ICON0 if(param->icon0FileData.buf) diff --git a/Core/Dialog/SavedataParam.h b/Core/Dialog/SavedataParam.h index 90af709700..6330e7d0f2 100644 --- a/Core/Dialog/SavedataParam.h +++ b/Core/Dialog/SavedataParam.h @@ -134,6 +134,7 @@ class SavedataParam public: static void Init(); std::string GetSaveFilePath(SceUtilitySavedataParam* param, int saveId = -1); + std::string GetSaveDir(SceUtilitySavedataParam* param, int saveId = -1); bool Delete(SceUtilitySavedataParam* param, int saveId = -1); bool Save(SceUtilitySavedataParam* param, int saveId = -1); bool Load(SceUtilitySavedataParam* param, int saveId = -1); diff --git a/Core/ELF/ParamSFO.cpp b/Core/ELF/ParamSFO.cpp index a86e6c77b8..e2b423b29e 100644 --- a/Core/ELF/ParamSFO.cpp +++ b/Core/ELF/ParamSFO.cpp @@ -38,22 +38,48 @@ struct IndexTable u32 data_table_offset; /* Offset of the param_data from start of data_table */ }; -void ParseDataString(const char *key, const char *utfdata, ParamSFOData *sfodata, int maxlen = 0) +void ParamSFOData::SetValue(std::string key, unsigned int value, int max_size) { - std::string data; - if (maxlen) - data = std::string(utfdata, maxlen); - else - data = std::string(utfdata); - if (!strcmp(key, "DISC_ID")) { - sfodata->discID = data; - } else if (!strcmp(key, "TITLE")) { - sfodata->title = data; + values[key].type = VT_INT; + values[key].i_value = value; + values[key].max_size = max_size; +} +void ParamSFOData::SetValue(std::string key, std::string value, int max_size) +{ + if(key == "ACCOUNT_ID" || + key == "PADDING" || + key == "PARAMS" || + key == "PARAMS2" || + key == "SAVEDATA_FILE_LIST" || + key == "SAVEDATA_PARAMS") + { + values[key].type = VT_UTF8_SPE; } + else + { + values[key].type = VT_UTF8; + } + values[key].s_value = value; + values[key].max_size = max_size; +} + +int ParamSFOData::GetValueInt(std::string key) +{ + std::map::iterator it = values.find(key); + if(it == values.end() || it->second.type != VT_INT) + return 0; + return it->second.i_value; +} +std::string ParamSFOData::GetValueString(std::string key) +{ + std::map::iterator it = values.find(key); + if(it == values.end() || (it->second.type != VT_UTF8 && it->second.type != VT_UTF8_SPE)) + return ""; + return it->second.s_value; } // I'm so sorry Ced but this is highly endian unsafe :( -bool ParseParamSFO(const u8 *paramsfo, size_t size, ParamSFOData *data) +bool ParamSFOData::ReadSFO(const u8 *paramsfo, size_t size) { const Header *header = (const Header *)paramsfo; if (header->magic != 0x46535000) @@ -75,6 +101,7 @@ bool ParseParamSFO(const u8 *paramsfo, size_t size, ParamSFOData *data) { // Unsigned int const u32 *data = (const u32 *)(data_start + indexTables[i].data_table_offset); + SetValue(key,*data,indexTables[i].param_max_len); DEBUG_LOG(LOADER, "%s %08x", key, *data); } break; @@ -83,7 +110,7 @@ bool ParseParamSFO(const u8 *paramsfo, size_t size, ParamSFOData *data) { const char *utfdata = (const char *)(data_start + indexTables[i].data_table_offset); DEBUG_LOG(LOADER, "%s %s", key, utfdata); - ParseDataString(key, utfdata, data, indexTables[i].param_len); + SetValue(key,std::string(utfdata,indexTables[i].param_len),indexTables[i].param_max_len); } break; case 0x0204: @@ -91,7 +118,7 @@ bool ParseParamSFO(const u8 *paramsfo, size_t size, ParamSFOData *data) { const char *utfdata = (const char *)(data_start + indexTables[i].data_table_offset); DEBUG_LOG(LOADER, "%s %s", key, utfdata); - ParseDataString(key, utfdata, data, indexTables[i].param_len); + SetValue(key,std::string(utfdata,indexTables[i].param_len),indexTables[i].param_max_len); } break; } @@ -99,3 +126,92 @@ bool ParseParamSFO(const u8 *paramsfo, size_t size, ParamSFOData *data) return true; } + +bool ParamSFOData::WriteSFO(u8 **paramsfo, size_t *size) +{ + size_t total_size = 0; + size_t key_size = 0; + size_t data_size = 0; + + Header header; + header.magic = 0x46535000; + header.version = 0x00000101; + header.index_table_entries = 0; + + total_size += sizeof(Header); + + // Get size info + for(std::map::iterator it = values.begin(); it != values.end(); it++) + { + key_size += it->first.size()+1; + data_size += it->second.max_size; + + header.index_table_entries++; + } + + // Padding + while((key_size%4)) key_size++; + + header.key_table_start = sizeof(Header) + header.index_table_entries * sizeof(IndexTable); + header.data_table_start = header.key_table_start + key_size; + + total_size += sizeof(IndexTable) * header.index_table_entries; + total_size += key_size; + total_size += data_size; + *size = total_size; + + u8* data = new u8[total_size]; + *paramsfo = data; + memset(data,0,total_size); + memcpy(data,&header,sizeof(Header)); + + // Now fill + IndexTable *index_ptr = (IndexTable*)(data + sizeof(Header)); + u8* key_ptr = data + header.key_table_start; + u8* data_ptr = data + header.data_table_start; + + for(std::map::iterator it = values.begin(); it != values.end(); it++) + { + u16 offset = (u16)(key_ptr - (data+header.key_table_start)); + index_ptr->key_table_offset = offset; + offset = (u16)(data_ptr - (data+header.data_table_start)); + index_ptr->data_table_offset = offset; + index_ptr->param_max_len = it->second.max_size; + if(it->second.type == VT_INT) + { + index_ptr->param_fmt = 0x0404; + index_ptr->param_len = 4; + + *(int*)data_ptr = it->second.i_value; + } + else if(it->second.type == VT_UTF8_SPE) + { + index_ptr->param_fmt = 0x0004; + index_ptr->param_len = it->second.s_value.size()+1; + + memcpy(data_ptr,it->second.s_value.c_str(),index_ptr->param_len); + data_ptr[index_ptr->param_len] = 0; + } + else if(it->second.type == VT_UTF8) + { + index_ptr->param_fmt = 0x0204; + index_ptr->param_len = it->second.s_value.size()+1; + + memcpy(data_ptr,it->second.s_value.c_str(),index_ptr->param_len); + data_ptr[index_ptr->param_len] = 0; + } + + memcpy(key_ptr,it->first.c_str(),it->first.size()); + key_ptr[it->first.size()] = 0; + + data_ptr += index_ptr->param_max_len; + key_ptr += it->first.size()+1; + index_ptr++; + + } + + return true; + + +} + diff --git a/Core/ELF/ParamSFO.h b/Core/ELF/ParamSFO.h index f92bef1a5a..3d3441c521 100644 --- a/Core/ELF/ParamSFO.h +++ b/Core/ELF/ParamSFO.h @@ -18,11 +18,35 @@ #pragma once +#include -struct ParamSFOData +class ParamSFOData { - std::string discID; - std::string title; // utf-8 +public: + void SetValue(std::string key, unsigned int value, int max_size); + void SetValue(std::string key, std::string value, int max_size); + + int GetValueInt(std::string key); + std::string GetValueString(std::string key); + + bool ReadSFO(const u8 *paramsfo, size_t size); + bool WriteSFO(u8 **paramsfo, size_t *size); +private: + + enum ValueType + { + VT_INT, + VT_UTF8, + VT_UTF8_SPE + }; + struct ValueData + { + ValueType type; + int max_size; + std::string s_value; + int i_value; + }; + + std::map values; }; -bool ParseParamSFO(const u8 *paramsfo, size_t size, ParamSFOData *data); \ No newline at end of file diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index ae628e760a..afc8cad456 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -78,10 +78,10 @@ bool Load_PSP_ISO(const char *filename, std::string *error_string) pspFileSystem.ReadFile(fd, paramsfo, fileInfo.size); pspFileSystem.CloseFile(fd); ParamSFOData data; - if (ParseParamSFO(paramsfo, (size_t)fileInfo.size, &data)) + if (data.ReadSFO(paramsfo, (size_t)fileInfo.size)) { char title[1024]; - sprintf(title, "%s : %s", data.discID.c_str(), data.title.c_str()); + sprintf(title, "%s : %s", data.GetValueString("DISC_ID").c_str(), data.GetValueString("TITLE").c_str()); INFO_LOG(LOADER, "%s", title); host->SetWindowTitle(title); }