From 17bfb3beaf1d2b67348d9258bfe2c5e32d5b4db6 Mon Sep 17 00:00:00 2001 From: Zion Date: Fri, 15 Dec 2017 16:03:49 -0800 Subject: [PATCH] various memory access violation fixes (and friends) (#3930) * various memory access violation fixes * Another fix, for motorstorm demo * Better stub cellGameUpdateCheckStartAsync and FinishAsync, Fixes #3934 --- rpcs3/Emu/Cell/Modules/cellGame.cpp | 22 ++++++++++++---------- rpcs3/Emu/Cell/Modules/cellNetCtl.cpp | 17 ++++++++++++++--- rpcs3/Emu/Cell/Modules/cellUserInfo.cpp | 5 ++++- rpcs3/Emu/Cell/lv2/sys_fs.cpp | 15 ++++++++++++--- 4 files changed, 42 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGame.cpp b/rpcs3/Emu/Cell/Modules/cellGame.cpp index b08973f55f..3d1d89a01b 100644 --- a/rpcs3/Emu/Cell/Modules/cellGame.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGame.cpp @@ -144,7 +144,7 @@ s32 cellHddGameCheck(ppu_thread& ppu, u32 version, vm::cptr dirName, u32 e // TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else) const auto& psf = psf::load_object(fs::file(local_dir +"/PARAM.SFO")); - // Some following fields may be zero in old FW 1.00 version PARAM.SFO + // Some following fields may be zero in old FW 1.00 version PARAM.SFO if (psf.count("PARENTAL_LEVEL") != 0) get->getParam.parentalLevel = psf.at("PARENTAL_LEVEL").as_integer(); if (psf.count("ATTRIBUTE") != 0) get->getParam.attribute = psf.at("ATTRIBUTE").as_integer(); if (psf.count("RESOLUTION") != 0) get->getParam.resolution = psf.at("RESOLUTION").as_integer(); @@ -246,6 +246,8 @@ error_code cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptr size->sysSizeKB = 0; } + if (!type) + return CELL_GAME_ERROR_PARAM; // According to testing (in debug mode) cellGameBootCheck doesn't return an error code, when PARAM.SFO doesn't exist. psf::registry sfo = psf::load_object(fs::file(vfs::get("/app_home/../PARAM.SFO"))); @@ -266,7 +268,7 @@ error_code cellGameBootCheck(vm::ptr type, vm::ptr attributes, vm::ptr { *type = CELL_GAME_GAMETYPE_HDD; *attributes = 0; // TODO - if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID()); + if (dirName) strcpy_trunc(*dirName, Emu.GetTitleID()); if (!fxm::make(Emu.GetTitleID(), std::move(sfo))) { @@ -321,7 +323,7 @@ error_code cellGamePatchCheck(vm::ptr size, vm::ptr r { return CELL_GAME_ERROR_BUSY; } - + return CELL_OK; } @@ -375,7 +377,7 @@ error_code cellGameContentPermit(vm::ptr contentInfoPa } const auto prm = fxm::get(); - + if (!prm) { return CELL_GAME_ERROR_FAILURE; @@ -412,7 +414,7 @@ error_code cellGameContentPermit(vm::ptr contentInfoPa strcpy_trunc(*contentInfoPath, dir); strcpy_trunc(*usrdirPath, dir + "/USRDIR"); verify(HERE), fxm::remove(); - + return CELL_OK; } @@ -420,7 +422,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr { cellGame.error("cellGameDataCheckCreate2(version=0x%x, dirName=%s, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container); - //older sdk. it might not care about game type. + //older sdk. it might not care about game type. if (version != CELL_GAMEDATA_VERSION_CURRENT || errDialog > 1) { @@ -439,7 +441,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr // TODO: Use the free space of the computer's HDD where RPCS3 is being run. cbGet->hddFreeSizeKB = 40000000; //40 GB - + strcpy_trunc(cbGet->contentInfoPath, dir); strcpy_trunc(cbGet->gameDataPath, dir + "/USRDIR"); @@ -466,7 +468,7 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr funcStat(ppu, cbResult, cbGet, cbSet); - + switch ((s32)cbResult->result) { @@ -475,8 +477,8 @@ error_code cellGameDataCheckCreate2(ppu_thread& ppu, u32 version, vm::cptr cellGame.warning("cellGameDataCheckCreate2(): callback returned CELL_GAMEDATA_CBRESULT_OK_CANCEL"); return CELL_OK; - - case CELL_GAMEDATA_CBRESULT_OK: + + case CELL_GAMEDATA_CBRESULT_OK: //game confirmed that it wants to create directory if (!fs::is_dir(vfs::get(dir + "/USRDIR")) && !fs::create_path(vfs::get(dir + "/USRDIR"))) { diff --git a/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp b/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp index 1f252e24fc..5d7f265ffd 100644 --- a/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp +++ b/rpcs3/Emu/Cell/Modules/cellNetCtl.cpp @@ -202,7 +202,7 @@ error_code cellNetCtlGetNatInfo(vm::ptr natInfo) cellNetCtl.error("cellNetCtlGetNatInfo : CELL_NET_CTL_ERROR_INVALID_SIZE"); return CELL_NET_CTL_ERROR_INVALID_SIZE; } - + return CELL_OK; } @@ -266,15 +266,26 @@ error_code cellGameUpdateTerm() return CELL_OK; } -error_code cellGameUpdateCheckStartAsync(vm::cptr param, vm::ptr cb_func, vm::ptr userdata) +error_code cellGameUpdateCheckStartAsync(ppu_thread& ppu, vm::cptr param, vm::ptr cb_func, vm::ptr userdata) { cellNetCtl.todo("cellGameUpdateCheckStartAsync(param=*0x%x, cb_func=*0x%x, userdata=*0x%x)", param, cb_func, userdata); + sysutil_register_cb([=](ppu_thread& ppu) -> s32 + { + cb_func(ppu, CELL_OK, CELL_OK, userdata); + return CELL_OK; + }); return CELL_OK; } -error_code cellGameUpdateCheckFinishAsync(vm::ptr cb_func, vm::ptr userdata) +error_code cellGameUpdateCheckFinishAsync(ppu_thread& ppu, vm::ptr cb_func, vm::ptr userdata) { cellNetCtl.todo("cellGameUpdateCheckFinishAsync(cb_func=*0x%x, userdata=*0x%x)", cb_func, userdata); + const u32 PROCESSING_COMPLETE = 5; + sysutil_register_cb([=](ppu_thread& ppu) -> s32 + { + cb_func(ppu, PROCESSING_COMPLETE, CELL_OK, userdata); + return CELL_OK; + }); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellUserInfo.cpp b/rpcs3/Emu/Cell/Modules/cellUserInfo.cpp index 5e613b7437..29c3432c30 100644 --- a/rpcs3/Emu/Cell/Modules/cellUserInfo.cpp +++ b/rpcs3/Emu/Cell/Modules/cellUserInfo.cpp @@ -40,6 +40,9 @@ error_code cellUserInfoGetStat(u32 id, vm::ptr stat) id = 1; } + if (!stat) + return CELL_USERINFO_ERROR_PARAM; + const std::string& path = vfs::get(fmt::format("/dev_hdd0/home/%08d/", id)); if (!fs::is_dir(path)) @@ -104,7 +107,7 @@ error_code cellUserInfoGetList(vm::ptr listNum, vm::ptr path, s32 flags, vm::ptr fd, s32 mode if (size == 8) { - // check for sdata + // check for sdata if (*casted_arg == 0x18000000010) { // check if the file has the NPD header, or else assume its not encrypted @@ -315,7 +315,7 @@ error_code sys_fs_open(vm::cptr path, s32 flags, vm::ptr fd, s32 mode file.reset(std::move(sdata_file)); } } - // edata + // edata else if (*casted_arg == 0x2) { // check if the file has the NPD header, or else assume its not encrypted @@ -514,6 +514,9 @@ error_code sys_fs_stat(vm::cptr path, vm::ptr sb) { sys_fs.warning("sys_fs_stat(path=%s, sb=*0x%x)", path, sb); + if (!path) + return CELL_EFAULT; + const std::string local_path = vfs::get(path.get_ptr()); if (local_path.empty()) @@ -629,7 +632,7 @@ error_code sys_fs_rename(vm::cptr from, vm::cptr to) { return CELL_ENOTMOUNTED; } - + if (local_to == "/" || local_from == "/") { return CELL_EPERM; @@ -687,6 +690,12 @@ error_code sys_fs_unlink(vm::cptr path) { sys_fs.warning("sys_fs_unlink(path=%s)", path); + // If path is just an empty string + if (!*path.get_ptr()) + { + return CELL_ENOENT; + } + const std::string local_path = vfs::get(path.get_ptr()); if (local_path.empty())