mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-21 18:39:57 +00:00
cellSaveData/cellMsgDialog: implement cellSaveDataDelete
This commit is contained in:
parent
0b720aeb59
commit
896cfd2ade
@ -32,6 +32,9 @@ MsgDialogBase::~MsgDialogBase()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// variable used to immediately get the response from auxiliary message dialogs (callbacks would be async)
|
||||||
|
atomic_t<s32> g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE;
|
||||||
|
|
||||||
// forward declaration for open_msg_dialog
|
// forward declaration for open_msg_dialog
|
||||||
error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam);
|
error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback, vm::ptr<void> userData, vm::ptr<void> extParam);
|
||||||
|
|
||||||
@ -129,7 +132,6 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMs
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO:
|
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO:
|
||||||
{
|
{
|
||||||
if (_type.default_cursor > 1 || _type.progress_bar_count)
|
if (_type.default_cursor > 1 || _type.progress_bar_count)
|
||||||
@ -139,7 +141,6 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMs
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK:
|
case CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK:
|
||||||
{
|
{
|
||||||
if (_type.default_cursor || _type.progress_bar_count)
|
if (_type.default_cursor || _type.progress_bar_count)
|
||||||
@ -149,7 +150,6 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMs
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: return CELL_MSGDIALOG_ERROR_PARAM;
|
default: return CELL_MSGDIALOG_ERROR_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,6 +174,8 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMs
|
|||||||
return CELL_SYSUTIL_ERROR_BUSY;
|
return CELL_SYSUTIL_ERROR_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE;
|
||||||
|
|
||||||
const auto res = manager->create<rsx::overlays::message_dialog>()->show(msgString.get_ptr(), _type, [callback, userData](s32 status)
|
const auto res = manager->create<rsx::overlays::message_dialog>()->show(msgString.get_ptr(), _type, [callback, userData](s32 status)
|
||||||
{
|
{
|
||||||
if (callback)
|
if (callback)
|
||||||
@ -227,6 +229,7 @@ error_code cellMsgDialogOpen2(u32 type, vm::cptr<char> msgString, vm::ptr<CellMs
|
|||||||
// Run asynchronously in GUI thread
|
// Run asynchronously in GUI thread
|
||||||
Emu.CallAfter([&]()
|
Emu.CallAfter([&]()
|
||||||
{
|
{
|
||||||
|
g_last_user_response = CELL_MSGDIALOG_BUTTON_NONE;
|
||||||
dlg->Create(msgString.get_ptr());
|
dlg->Create(msgString.get_ptr());
|
||||||
lv2_obj::awake(&ppu);
|
lv2_obj::awake(&ppu);
|
||||||
});
|
});
|
||||||
|
@ -83,6 +83,8 @@ enum class MsgDialogState
|
|||||||
Close,
|
Close,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern atomic_t<s32> g_last_user_response;
|
||||||
|
|
||||||
error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback = vm::null, vm::ptr<void> userData = vm::null, vm::ptr<void> extParam = vm::null);
|
error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString, vm::ptr<CellMsgDialogCallback> callback = vm::null, vm::ptr<void> userData = vm::null, vm::ptr<void> extParam = vm::null);
|
||||||
error_code open_exit_dialog(const std::string& message, bool is_exit_requested);
|
error_code open_exit_dialog(const std::string& message, bool is_exit_requested);
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "Emu/Cell/Modules/cellSysutil.h"
|
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||||
|
|
||||||
#include "cellSaveData.h"
|
#include "cellSaveData.h"
|
||||||
|
#include "cellMsgDialog.h"
|
||||||
|
|
||||||
#include "Loader/PSF.h"
|
#include "Loader/PSF.h"
|
||||||
#include "Utilities/StrUtil.h"
|
#include "Utilities/StrUtil.h"
|
||||||
@ -89,6 +90,134 @@ vm::gvar<savedata_context> g_savedata_context;
|
|||||||
|
|
||||||
std::mutex g_savedata_mutex;
|
std::mutex g_savedata_mutex;
|
||||||
|
|
||||||
|
static std::vector<SaveDataEntry> get_save_entries(const std::string& base_dir, const std::string& prefix)
|
||||||
|
{
|
||||||
|
std::vector<SaveDataEntry> save_entries;
|
||||||
|
|
||||||
|
if (base_dir.empty() || prefix.empty())
|
||||||
|
{
|
||||||
|
return save_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the saves matching the supplied prefix
|
||||||
|
for (auto&& entry : fs::dir(base_dir))
|
||||||
|
{
|
||||||
|
if (!entry.is_directory || entry.name == "." || entry.name == "..")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.name = vfs::unescape(entry.name);
|
||||||
|
|
||||||
|
if (entry.name.substr(0, prefix.size()) != prefix)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSF parameters
|
||||||
|
const psf::registry psf = psf::load_object(fs::file(base_dir + entry.name + "/PARAM.SFO"));
|
||||||
|
|
||||||
|
if (psf.empty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SaveDataEntry save_entry;
|
||||||
|
save_entry.dirName = psf.at("SAVEDATA_DIRECTORY").as_string();
|
||||||
|
save_entry.listParam = psf.at("SAVEDATA_LIST_PARAM").as_string();
|
||||||
|
save_entry.title = psf.at("TITLE").as_string();
|
||||||
|
save_entry.subtitle = psf.at("SUB_TITLE").as_string();
|
||||||
|
save_entry.details = psf.at("DETAIL").as_string();
|
||||||
|
|
||||||
|
for (const auto entry2 : fs::dir(base_dir + entry.name))
|
||||||
|
{
|
||||||
|
save_entry.size += entry2.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
save_entry.atime = entry.atime;
|
||||||
|
save_entry.mtime = entry.mtime;
|
||||||
|
save_entry.ctime = entry.ctime;
|
||||||
|
if (fs::file icon{base_dir + entry.name + "/ICON0.PNG"})
|
||||||
|
save_entry.iconBuf = icon.to_vector<uchar>();
|
||||||
|
save_entry.isNew = false;
|
||||||
|
save_entries.emplace_back(save_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return save_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_code select_and_delete(ppu_thread& ppu)
|
||||||
|
{
|
||||||
|
std::unique_lock lock(g_savedata_mutex, std::try_to_lock);
|
||||||
|
|
||||||
|
if (!lock)
|
||||||
|
{
|
||||||
|
return CELL_SAVEDATA_ERROR_BUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string base_dir = vfs::get(fmt::format("/dev_hdd0/home/%08u/savedata/", Emu.GetUsrId()));
|
||||||
|
|
||||||
|
auto save_entries = get_save_entries(base_dir, Emu.GetTitleID());
|
||||||
|
|
||||||
|
s32 selected = -1;
|
||||||
|
s32 focused = -1;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// Yield
|
||||||
|
lv2_obj::sleep(ppu);
|
||||||
|
|
||||||
|
// Display Save Data List asynchronously in the GUI thread.
|
||||||
|
selected = Emu.GetCallbacks().get_save_dialog()->ShowSaveDataList(save_entries, focused, SAVEDATA_OP_LIST_DELETE, vm::null);
|
||||||
|
|
||||||
|
// Reschedule
|
||||||
|
if (ppu.check_state())
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Abort if dialog was canceled
|
||||||
|
if (selected == -2)
|
||||||
|
{
|
||||||
|
return CELL_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set focused entry for the next iteration
|
||||||
|
focused = save_entries.empty() ? -1 : selected;
|
||||||
|
|
||||||
|
// Get information from the selected entry
|
||||||
|
SaveDataEntry entry = save_entries[selected];
|
||||||
|
const std::string info = entry.title + "\n" + entry.subtitle + "\n" + entry.details;
|
||||||
|
|
||||||
|
// Get user confirmation
|
||||||
|
std::string msg = "Do you really want to delete this entry?\n\n" + info;
|
||||||
|
error_code res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO, vm::make_str(msg));
|
||||||
|
|
||||||
|
if (res != CELL_OK)
|
||||||
|
{
|
||||||
|
return CELL_SAVEDATA_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_last_user_response.load() == CELL_MSGDIALOG_BUTTON_YES)
|
||||||
|
{
|
||||||
|
// Remove directory
|
||||||
|
const std::string path = base_dir + save_entries[selected].dirName;
|
||||||
|
fs::remove_all(path);
|
||||||
|
|
||||||
|
// Remove entry from the list and reset the selection
|
||||||
|
save_entries.erase(save_entries.cbegin() + selected);
|
||||||
|
selected = -1;
|
||||||
|
|
||||||
|
// Display success message (return value should be irrelevant here)
|
||||||
|
msg = "Successfully removed entry!\n\n" + info;
|
||||||
|
cellSaveData.success("%s", msg);
|
||||||
|
res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_OK, vm::make_str(msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_CANCEL;
|
||||||
|
}
|
||||||
|
|
||||||
static bool savedata_check_args(u32 operation, u32 version, vm::cptr<char> dirName,
|
static bool savedata_check_args(u32 operation, u32 version, vm::cptr<char> dirName,
|
||||||
u32 errDialog, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncFixed funcFixed, PFuncStat funcStat,
|
u32 errDialog, PSetList setList, PSetBuf setBuf, PFuncList funcList, PFuncFixed funcFixed, PFuncStat funcStat,
|
||||||
PFuncFile funcFile, u32 container, u32 unk_op_flags, vm::ptr<void> userdata, u32 userId, PFuncDone funcDone)
|
PFuncFile funcFile, u32 container, u32 unk_op_flags, vm::ptr<void> userdata, u32 userId, PFuncDone funcDone)
|
||||||
@ -1333,18 +1462,18 @@ error_code cellSaveDataListAutoLoad(ppu_thread& ppu, u32 version, u32 errDialog,
|
|||||||
return savedata_op(ppu, SAVEDATA_OP_LIST_AUTO_LOAD, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 2, userdata, 0, vm::null);
|
return savedata_op(ppu, SAVEDATA_OP_LIST_AUTO_LOAD, version, vm::null, errDialog, setList, setBuf, vm::null, funcFixed, funcStat, funcFile, container, 2, userdata, 0, vm::null);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code cellSaveDataDelete2(u32 container)
|
error_code cellSaveDataDelete(ppu_thread& ppu, u32 container)
|
||||||
{
|
{
|
||||||
cellSaveData.todo("cellSaveDataDelete2(container=0x%x)", container);
|
cellSaveData.warning("cellSaveDataDelete(container=0x%x)", container);
|
||||||
|
|
||||||
return CELL_CANCEL;
|
return select_and_delete(ppu);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code cellSaveDataDelete(u32 container)
|
error_code cellSaveDataDelete2(ppu_thread& ppu, u32 container)
|
||||||
{
|
{
|
||||||
cellSaveData.todo("cellSaveDataDelete(container=0x%x)", container);
|
cellSaveData.warning("cellSaveDataDelete2(container=0x%x)", container);
|
||||||
|
|
||||||
return CELL_CANCEL;
|
return select_and_delete(ppu);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code cellSaveDataFixedDelete(ppu_thread& ppu, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
error_code cellSaveDataFixedDelete(ppu_thread& ppu, PSetList setList, PSetBuf setBuf, PFuncFixed funcFixed, PFuncDone funcDone, u32 container, vm::ptr<void> userdata)
|
||||||
|
@ -323,7 +323,10 @@ namespace rsx
|
|||||||
pad::SetIntercepted(false);
|
pad::SetIntercepted(false);
|
||||||
|
|
||||||
if (on_close && use_callback)
|
if (on_close && use_callback)
|
||||||
|
{
|
||||||
|
g_last_user_response = return_code;
|
||||||
on_close(return_code);
|
on_close(return_code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void overlay::refresh()
|
void overlay::refresh()
|
||||||
|
@ -93,12 +93,14 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title)
|
|||||||
|
|
||||||
connect(m_button_yes, &QAbstractButton::clicked, [=]
|
connect(m_button_yes, &QAbstractButton::clicked, [=]
|
||||||
{
|
{
|
||||||
|
g_last_user_response = CELL_MSGDIALOG_BUTTON_YES;
|
||||||
on_close(CELL_MSGDIALOG_BUTTON_YES);
|
on_close(CELL_MSGDIALOG_BUTTON_YES);
|
||||||
m_dialog->accept();
|
m_dialog->accept();
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_button_no, &QAbstractButton::clicked, [=]
|
connect(m_button_no, &QAbstractButton::clicked, [=]
|
||||||
{
|
{
|
||||||
|
g_last_user_response = CELL_MSGDIALOG_BUTTON_NO;
|
||||||
on_close(CELL_MSGDIALOG_BUTTON_NO);
|
on_close(CELL_MSGDIALOG_BUTTON_NO);
|
||||||
m_dialog->accept();
|
m_dialog->accept();
|
||||||
});
|
});
|
||||||
@ -123,6 +125,7 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title)
|
|||||||
|
|
||||||
connect(m_button_ok, &QAbstractButton::clicked, [=]
|
connect(m_button_ok, &QAbstractButton::clicked, [=]
|
||||||
{
|
{
|
||||||
|
g_last_user_response = CELL_MSGDIALOG_BUTTON_OK;
|
||||||
on_close(CELL_MSGDIALOG_BUTTON_OK);
|
on_close(CELL_MSGDIALOG_BUTTON_OK);
|
||||||
m_dialog->accept();
|
m_dialog->accept();
|
||||||
});
|
});
|
||||||
@ -134,6 +137,7 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title)
|
|||||||
{
|
{
|
||||||
if (!type.disable_cancel)
|
if (!type.disable_cancel)
|
||||||
{
|
{
|
||||||
|
g_last_user_response = CELL_MSGDIALOG_BUTTON_ESCAPE;
|
||||||
on_close(CELL_MSGDIALOG_BUTTON_ESCAPE);
|
on_close(CELL_MSGDIALOG_BUTTON_ESCAPE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user