mirror of
https://github.com/Vita3K/Vita3K.git
synced 2025-04-02 11:02:10 -04:00
523 lines
19 KiB
C++
523 lines
19 KiB
C++
// Vita3K emulator project
|
|
// Copyright (C) 2025 Vita3K team
|
|
//
|
|
// 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; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// 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 for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License along
|
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
#include <module/module.h>
|
|
|
|
#include <emuenv/app_util.h>
|
|
#include <io/device.h>
|
|
#include <io/functions.h>
|
|
#include <io/io.h>
|
|
#include <io/vfs.h>
|
|
#include <packages/license.h>
|
|
#include <util/safe_time.h>
|
|
#include <util/tracy.h>
|
|
|
|
#ifdef _WIN32
|
|
#include <winsock.h>
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <cstring>
|
|
|
|
TRACY_MODULE_NAME(SceAppUtil);
|
|
|
|
template <>
|
|
std::string to_debug_str<SceSystemParamId>(const MemState &mem, SceSystemParamId type) {
|
|
switch (type) {
|
|
case SCE_SYSTEM_PARAM_ID_LANG:
|
|
return "SCE_SYSTEM_PARAM_ID_LANG";
|
|
case SCE_SYSTEM_PARAM_ID_ENTER_BUTTON:
|
|
return "SCE_SYSTEM_PARAM_ID_ENTER_BUTTON";
|
|
case SCE_SYSTEM_PARAM_ID_USER_NAME:
|
|
return "SCE_SYSTEM_PARAM_ID_USER_NAME";
|
|
case SCE_SYSTEM_PARAM_ID_DATE_FORMAT:
|
|
return "SCE_SYSTEM_PARAM_ID_DATE_FORMAT";
|
|
case SCE_SYSTEM_PARAM_ID_TIME_FORMAT:
|
|
return "SCE_SYSTEM_PARAM_ID_TIME_FORMAT";
|
|
case SCE_SYSTEM_PARAM_ID_TIME_ZONE:
|
|
return "SCE_SYSTEM_PARAM_ID_TIME_ZONE";
|
|
case SCE_SYSTEM_PARAM_ID_SUMMERTIME:
|
|
return "SCE_SYSTEM_PARAM_ID_SUMMERTIME";
|
|
case SCE_SYSTEM_PARAM_ID_MAX_VALUE:
|
|
return "SCE_SYSTEM_PARAM_ID_MAX_VALUE";
|
|
}
|
|
return std::to_string(type);
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAddCookieWebBrowser) {
|
|
TRACY_FUNC(sceAppUtilAddCookieWebBrowser);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAddcontMount) {
|
|
TRACY_FUNC(sceAppUtilAddcontMount);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAddcontUmount) {
|
|
TRACY_FUNC(sceAppUtilAddcontUmount);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseGameCustomData) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseGameCustomData);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseIncomingDialog) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseIncomingDialog);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseLiveArea) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseLiveArea);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseNearGift) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseNearGift);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseNpActivity) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseNpActivity);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseNpAppDataMessage) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseNpAppDataMessage);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseNpBasicJoinablePresence) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseNpBasicJoinablePresence);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseNpInviteMessage) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseNpInviteMessage);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseScreenShotNotification) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseScreenShotNotification);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseSessionInvitation) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseSessionInvitation);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseTeleport) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseTeleport);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseTriggerUtil) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseTriggerUtil);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilAppEventParseWebBrowser) {
|
|
TRACY_FUNC(sceAppUtilAppEventParseWebBrowser);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(SceInt32, sceAppUtilAppParamGetInt, SceAppUtilAppParamId paramId, SceInt32 *value) {
|
|
TRACY_FUNC(sceAppUtilAppParamGetInt, paramId, value);
|
|
if (paramId != SCE_APPUTIL_APPPARAM_ID_SKU_FLAG)
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
|
|
if (!value)
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_NOT_INITIALIZED);
|
|
|
|
*value = emuenv.license.rif[emuenv.io.title_id].sku_flag;
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilBgdlGetStatus) {
|
|
TRACY_FUNC(sceAppUtilBgdlGetStatus);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
static bool is_addcont_exist(EmuEnvState &emuenv, const SceChar8 *path) {
|
|
const auto drm_content_id_path{ emuenv.pref_path / (+VitaIoDevice::ux0)._to_string() / emuenv.io.device_paths.addcont0 / reinterpret_cast<const char *>(path) };
|
|
return (fs::exists(drm_content_id_path) && (!fs::is_empty(drm_content_id_path)));
|
|
}
|
|
|
|
EXPORT(SceInt32, sceAppUtilDrmClose, const SceAppUtilDrmAddcontId *dirName, const SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilDrmClose, dirName, mountPoint);
|
|
if (!dirName)
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
|
|
if (!is_addcont_exist(emuenv, dirName->data))
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_NOT_MOUNTED);
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(SceInt32, sceAppUtilDrmOpen, const SceAppUtilDrmAddcontId *dirName, const SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilDrmOpen, dirName, mountPoint);
|
|
if (!dirName)
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
|
|
if (!is_addcont_exist(emuenv, dirName->data))
|
|
return SCE_ERROR_ERRNO_ENOENT;
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilInit, void *initParam, void *bootParam) {
|
|
TRACY_FUNC(sceAppUtilInit, initParam, bootParam);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilLaunchWebBrowser) {
|
|
TRACY_FUNC(sceAppUtilLaunchWebBrowser);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilMusicMount) {
|
|
TRACY_FUNC(sceAppUtilMusicMount);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilMusicUmount) {
|
|
TRACY_FUNC(sceAppUtilMusicUmount);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilPhotoMount) {
|
|
TRACY_FUNC(sceAppUtilPhotoMount);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilPhotoUmount) {
|
|
TRACY_FUNC(sceAppUtilPhotoUmount);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilPspSaveDataGetDirNameList) {
|
|
TRACY_FUNC(sceAppUtilPspSaveDataGetDirNameList);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilPspSaveDataLoad) {
|
|
TRACY_FUNC(sceAppUtilPspSaveDataLoad);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilReceiveAppEvent) {
|
|
TRACY_FUNC(sceAppUtilReceiveAppEvent);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilResetCookieWebBrowser) {
|
|
TRACY_FUNC(sceAppUtilResetCookieWebBrowser);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
std::string construct_savedata0_path(const std::string &data, const char *ext) {
|
|
return device::construct_normalized_path(VitaIoDevice::savedata0, data, ext);
|
|
}
|
|
|
|
std::string construct_slotparam_path(const unsigned int data) {
|
|
return construct_savedata0_path("SlotParam_" + std::to_string(data), "bin");
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSaveDataDataRemove, SceAppUtilSaveDataFileSlot *slot, SceAppUtilSaveDataRemoveItem *files, unsigned int fileNum, SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilSaveDataDataRemove, slot, files, fileNum, mountPoint);
|
|
for (unsigned int i = 0; i < fileNum; i++) {
|
|
const auto file = fs::path(construct_savedata0_path(files[i].dataPath.get(emuenv.mem)));
|
|
if (fs::is_regular_file(file)) {
|
|
remove_file(emuenv.io, file.string().c_str(), emuenv.pref_path, export_name);
|
|
} else
|
|
remove_dir(emuenv.io, file.string().c_str(), emuenv.pref_path, export_name);
|
|
}
|
|
|
|
if (slot && files[0].mode == SCE_APPUTIL_SAVEDATA_DATA_REMOVE_MODE_DEFAULT) {
|
|
remove_file(emuenv.io, construct_slotparam_path(slot->id).c_str(), emuenv.pref_path, export_name);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSaveDataDataSave, SceAppUtilSaveDataFileSlot *slot, SceAppUtilSaveDataDataSaveItem *files, unsigned int fileNum, SceAppUtilMountPoint *mountPoint, SceSize *requiredSizeKiB) {
|
|
TRACY_FUNC(sceAppUtilSaveDataDataSave, slot, files, fileNum, mountPoint, requiredSizeKiB);
|
|
SceUID fd;
|
|
|
|
if (requiredSizeKiB)
|
|
// requiredSizeKiB must be set to 0 if there is enough space available
|
|
*requiredSizeKiB = 0;
|
|
|
|
for (unsigned int i = 0; i < fileNum; i++) {
|
|
const auto file_path = construct_savedata0_path(files[i].dataPath.get(emuenv.mem));
|
|
switch (files[i].mode) {
|
|
case SCE_APPUTIL_SAVEDATA_DATA_SAVE_MODE_DIRECTORY:
|
|
create_dir(emuenv.io, file_path.c_str(), 0777, emuenv.pref_path, export_name);
|
|
break;
|
|
case SCE_APPUTIL_SAVEDATA_DATA_SAVE_MODE_FILE_TRUNCATE:
|
|
if (files[i].buf) {
|
|
fd = open_file(emuenv.io, file_path.c_str(), SCE_O_WRONLY | SCE_O_CREAT, emuenv.pref_path, export_name);
|
|
seek_file(fd, static_cast<int>(files[i].offset), SCE_SEEK_SET, emuenv.io, export_name);
|
|
write_file(fd, files[i].buf.get(emuenv.mem), files[i].bufSize, emuenv.io, export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
}
|
|
fd = open_file(emuenv.io, file_path.c_str(), SCE_O_WRONLY | SCE_O_APPEND | SCE_O_TRUNC, emuenv.pref_path, export_name);
|
|
truncate_file(fd, files[i].bufSize + files[i].offset, emuenv.io, export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
break;
|
|
case SCE_APPUTIL_SAVEDATA_DATA_SAVE_MODE_FILE:
|
|
default:
|
|
fd = open_file(emuenv.io, file_path.c_str(), SCE_O_WRONLY | SCE_O_CREAT, emuenv.pref_path, export_name);
|
|
seek_file(fd, static_cast<int>(files[i].offset), SCE_SEEK_SET, emuenv.io, export_name);
|
|
write_file(fd, files[i].buf.get(emuenv.mem), files[i].bufSize, emuenv.io, export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (slot && slot->slotParam) {
|
|
SceDateTime modified_time;
|
|
std::time_t time = std::time(0);
|
|
tm local = {};
|
|
|
|
SAFE_LOCALTIME(&time, &local);
|
|
modified_time.year = local.tm_year + 1900;
|
|
modified_time.month = local.tm_mon + 1;
|
|
modified_time.day = local.tm_mday;
|
|
modified_time.hour = local.tm_hour;
|
|
modified_time.minute = local.tm_min;
|
|
modified_time.second = local.tm_sec;
|
|
slot->slotParam.get(emuenv.mem)->modifiedTime = modified_time;
|
|
fd = open_file(emuenv.io, construct_slotparam_path(slot->id).c_str(), SCE_O_WRONLY | SCE_O_CREAT, emuenv.pref_path, export_name);
|
|
write_file(fd, slot->slotParam.get(emuenv.mem), sizeof(SceAppUtilSaveDataSlotParam), emuenv.io, export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSaveDataGetQuota, SceSize *quotaSizeKiB, SceSize *usedSizeKiB, const SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilSaveDataGetQuota, quotaSizeKiB, usedSizeKiB, mountPoint);
|
|
*quotaSizeKiB = vfs::get_space_info(VitaIoDevice::ux0, emuenv.io.device_paths.savedata0, emuenv.pref_path).max_capacity / KiB(1);
|
|
*usedSizeKiB = vfs::get_space_info(VitaIoDevice::ux0, emuenv.io.device_paths.savedata0, emuenv.pref_path).used / KiB(1);
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSaveDataMount) {
|
|
TRACY_FUNC(sceAppUtilSaveDataMount);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSaveDataSlotCreate, unsigned int slotId, SceAppUtilSaveDataSlotParam *param, SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilSaveDataSlotCreate, slotId, param, mountPoint);
|
|
const auto fd = open_file(emuenv.io, construct_slotparam_path(slotId).c_str(), SCE_O_WRONLY | SCE_O_CREAT, emuenv.pref_path, export_name);
|
|
write_file(fd, param, sizeof(SceAppUtilSaveDataSlotParam), emuenv.io, export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSaveDataSlotDelete, unsigned int slotId, SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilSaveDataSlotDelete, slotId, mountPoint);
|
|
remove_file(emuenv.io, construct_slotparam_path(slotId).c_str(), emuenv.pref_path, export_name);
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSaveDataSlotGetParam, unsigned int slotId, SceAppUtilSaveDataSlotParam *param, SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilSaveDataSlotGetParam, slotId, param, mountPoint);
|
|
const auto fd = open_file(emuenv.io, construct_slotparam_path(slotId).c_str(), SCE_O_RDONLY, emuenv.pref_path, export_name);
|
|
if (fd < 0)
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_SAVEDATA_SLOT_NOT_FOUND);
|
|
read_file(param, emuenv.io, fd, sizeof(SceAppUtilSaveDataSlotParam), export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
param->status = 0;
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(SceInt32, sceAppUtilSaveDataSlotSearch, SceAppUtilWorkBuffer *workBuf, const SceAppUtilSaveDataSlotSearchCond *cond,
|
|
SceAppUtilSlotSearchResult *result, const SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilSaveDataSlotSearch, workBuf, cond, result, mountPoint);
|
|
STUBBED("No sort slot list");
|
|
|
|
if (!cond || !result)
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
|
|
if (workBuf)
|
|
result->slotList = Ptr<SceAppUtilSaveDataSlot>(workBuf->buf.address());
|
|
|
|
result->hitNum = 0;
|
|
auto slotList = result->slotList.get(emuenv.mem);
|
|
for (auto i = cond->from; i < (cond->from + cond->range); i++) {
|
|
if (slotList) {
|
|
slotList[i].id = -1;
|
|
slotList[i].status = 0;
|
|
slotList[i].userParam = 0;
|
|
slotList[i].emptyParam = Ptr<SceAppUtilSaveDataSlotEmptyParam>(0);
|
|
}
|
|
|
|
const auto fd = open_file(emuenv.io, construct_slotparam_path(i).c_str(), SCE_O_RDONLY, emuenv.pref_path, export_name);
|
|
switch (cond->type) {
|
|
case SCE_APPUTIL_SAVEDATA_SLOT_SEARCH_TYPE_EXIST_SLOT:
|
|
if (fd > 0) {
|
|
if (slotList) {
|
|
SceAppUtilSaveDataSlotParam param;
|
|
memset(¶m, 0, sizeof(SceAppUtilSaveDataSlotParam));
|
|
read_file(¶m, emuenv.io, fd, sizeof(SceAppUtilSaveDataSlotParam), export_name);
|
|
slotList[result->hitNum].userParam = param.userParam;
|
|
slotList[result->hitNum].status = param.status;
|
|
slotList[result->hitNum].id = i;
|
|
}
|
|
result->hitNum++;
|
|
}
|
|
break;
|
|
case SCE_APPUTIL_SAVEDATA_SLOT_SEARCH_TYPE_EMPTY_SLOT:
|
|
if (fd < 0) {
|
|
if (slotList)
|
|
slotList[result->hitNum].id = i;
|
|
result->hitNum++;
|
|
}
|
|
break;
|
|
default: break;
|
|
}
|
|
|
|
if (fd > 0)
|
|
close_file(emuenv.io, fd, export_name);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(SceInt32, sceAppUtilSaveDataSlotSetParam, SceAppUtilSaveDataSlotId slotId, SceAppUtilSaveDataSlotParam *param, SceAppUtilMountPoint *mountPoint) {
|
|
TRACY_FUNC(sceAppUtilSaveDataSlotSetParam, slotId, param, mountPoint);
|
|
const auto fd = open_file(emuenv.io, construct_slotparam_path(slotId).c_str(), SCE_O_WRONLY, emuenv.pref_path, export_name);
|
|
if (fd < 0)
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_SAVEDATA_SLOT_NOT_FOUND);
|
|
write_file(fd, param, sizeof(SceAppUtilSaveDataSlotParam), emuenv.io, export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
return 0;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSaveDataUmount) {
|
|
TRACY_FUNC(sceAppUtilSaveDataUmount);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
static SceInt32 SafeMemory(EmuEnvState &emuenv, void *buf, SceSize bufSize, SceOff offset, const char *export_name, bool save) {
|
|
std::vector<char> safe_mem(SCE_APPUTIL_SAFEMEMORY_MEMORY_SIZE);
|
|
const auto safe_mem_path = construct_savedata0_path("sce_sys/safemem", "dat");
|
|
SceInt32 res = 0;
|
|
|
|
// Open file when it exist
|
|
const auto fd = open_file(emuenv.io, safe_mem_path.c_str(), SCE_O_RDONLY, emuenv.pref_path, export_name);
|
|
if (fd > 0) {
|
|
// Read file for set data inside safe mem when it exist
|
|
res = read_file(safe_mem.data(), emuenv.io, fd, SCE_APPUTIL_SAFEMEMORY_MEMORY_SIZE, export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
}
|
|
|
|
if ((fd < 0) || save) {
|
|
// When safe mem no exist or in save mode, write it with set buffer inside data
|
|
const auto fd = open_file(emuenv.io, safe_mem_path.c_str(), SCE_O_WRONLY | SCE_O_CREAT, emuenv.pref_path, export_name);
|
|
memcpy(&safe_mem[offset], buf, bufSize);
|
|
write_file(fd, safe_mem.data(), SCE_APPUTIL_SAFEMEMORY_MEMORY_SIZE, emuenv.io, export_name);
|
|
close_file(emuenv.io, fd, export_name);
|
|
} else
|
|
memcpy(buf, &safe_mem[offset], bufSize);
|
|
|
|
return res;
|
|
}
|
|
|
|
EXPORT(SceInt32, sceAppUtilLoadSafeMemory, void *buf, SceSize bufSize, SceOff offset) {
|
|
TRACY_FUNC(sceAppUtilLoadSafeMemory, buf, bufSize, offset);
|
|
if (!buf || (offset + bufSize > SCE_APPUTIL_SAFEMEMORY_MEMORY_SIZE))
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
|
|
const auto res = SafeMemory(emuenv, buf, bufSize, offset, export_name, false);
|
|
|
|
// Load can return 0 when file no exist
|
|
return res > 0 ? bufSize : 0;
|
|
}
|
|
|
|
EXPORT(SceInt32, sceAppUtilSaveSafeMemory, const void *buf, SceSize bufSize, SceOff offset) {
|
|
TRACY_FUNC(sceAppUtilSaveSafeMemory, buf, bufSize, offset);
|
|
if (!buf || (offset + bufSize > SCE_APPUTIL_SAFEMEMORY_MEMORY_SIZE))
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
|
|
SafeMemory(emuenv, const_cast<void *>(buf), bufSize, offset, export_name, true);
|
|
|
|
return bufSize;
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilShutdown) {
|
|
TRACY_FUNC(sceAppUtilShutdown);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilStoreBrowse) {
|
|
TRACY_FUNC(sceAppUtilStoreBrowse);
|
|
return UNIMPLEMENTED();
|
|
}
|
|
|
|
EXPORT(SceInt32, sceAppUtilSystemParamGetInt, SceSystemParamId paramId, SceInt32 *value) {
|
|
TRACY_FUNC(sceAppUtilSystemParamGetInt, paramId, value);
|
|
if (!value)
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
|
|
switch (paramId) {
|
|
case SCE_SYSTEM_PARAM_ID_LANG:
|
|
*value = (SceSystemParamLang)emuenv.cfg.sys_lang;
|
|
return 0;
|
|
case SCE_SYSTEM_PARAM_ID_ENTER_BUTTON:
|
|
*value = (SceSystemParamEnterButtonAssign)emuenv.cfg.sys_button;
|
|
return 0;
|
|
case SCE_SYSTEM_PARAM_ID_DATE_FORMAT:
|
|
*value = (SceSystemParamDateFormat)emuenv.cfg.sys_date_format;
|
|
return 0;
|
|
case SCE_SYSTEM_PARAM_ID_TIME_FORMAT:
|
|
*value = (SceSystemParamTimeFormat)emuenv.cfg.sys_time_format;
|
|
return 0;
|
|
case SCE_SYSTEM_PARAM_ID_TIME_ZONE:
|
|
case SCE_SYSTEM_PARAM_ID_SUMMERTIME:
|
|
STUBBED("No support Time Zone and Summer Time, give 0 value");
|
|
*value = 0;
|
|
return 0;
|
|
default:
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
}
|
|
}
|
|
|
|
EXPORT(int, sceAppUtilSystemParamGetString, unsigned int paramId, SceChar8 *buf, SceSize bufSize) {
|
|
TRACY_FUNC(sceAppUtilSystemParamGetString, paramId, buf, bufSize);
|
|
constexpr auto devname_len = SCE_SYSTEM_PARAM_USERNAME_MAXSIZE;
|
|
char devname[devname_len];
|
|
switch (paramId) {
|
|
case SCE_SYSTEM_PARAM_ID_USER_NAME:
|
|
if (gethostname(devname, devname_len)) {
|
|
// fallback to User Name
|
|
std::strncpy(devname, emuenv.io.user_name.c_str(), sizeof(devname));
|
|
}
|
|
std::strncpy(reinterpret_cast<char *>(buf), devname, sizeof(devname));
|
|
break;
|
|
default:
|
|
return RET_ERROR(SCE_APPUTIL_ERROR_PARAMETER);
|
|
}
|
|
return 0;
|
|
}
|