Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added savedata0 support #226

Merged
merged 3 commits into from
May 7, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/emulator/host/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ include/host/import_fn.h
include/host/sfo.h
include/host/state.h
include/host/version.h
include/host/app_util.h
src/host.cpp
src/sfo.cpp
version.cpp
Expand Down
44 changes: 44 additions & 0 deletions src/emulator/host/include/host/app_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#pragma once

#include <mem/ptr.h>

#include <array>
#include <map>
#include <mutex>
#include <tuple>

#include <psp2/apputil.h>

namespace emu {

struct SceAppUtilSaveDataSaveItem {
const Ptr<char> dataPath;
const Ptr<void> buf;
uint32_t pad;
SceOff offset;
int mode;
uint8_t reserved[36];
};

struct SceAppUtilSaveDataFile {
const Ptr<char> filePath;
Ptr<void> buf;
SceSize bufSize;
SceOff offset;
unsigned int mode;
unsigned int progDelta;
uint8_t reserved[32];
};

struct SceAppUtilSaveDataFileSlot {
unsigned int id;
Ptr<SceAppUtilSaveDataSlotParam> slotParam;
uint8_t reserved[32];
};

struct SceAppUtilSaveDataRemoveItem {
const Ptr<char> dataPath;
int mode;
uint8_t reserved[36];
};
};
1 change: 1 addition & 0 deletions src/emulator/io/include/io/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ typedef std::map<SceUID, DirPtr> DirEntries;

struct IOState {
std::string app0_prefix;
std::string savedata0_path;
ZipPtr vpk;
SceUID next_fd = 0;
TtyFiles tty_files;
Expand Down
22 changes: 22 additions & 0 deletions src/emulator/io/src/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,18 +124,27 @@ bool init(IOState &io, const char *pref_path) {
uma0 += "uma0";
const std::string ux0_data = ux0 + "/data";
const std::string uma0_data = uma0 + "/data";
const std::string ux0_user = ux0 + "/user";
const std::string ux0_user00 = ux0_user + "/00";
const std::string ux0_savedata = ux0_user00 + "/savedata";

#ifdef WIN32
CreateDirectoryA(ux0.c_str(), nullptr);
CreateDirectoryA(ux0_data.c_str(), nullptr);
CreateDirectoryA(uma0.c_str(), nullptr);
CreateDirectoryA(uma0_data.c_str(), nullptr);
CreateDirectoryA(ux0_user.c_str(), nullptr);
CreateDirectoryA(ux0_user00.c_str(), nullptr);
CreateDirectoryA(ux0_savedata.c_str(), nullptr);
#else
const int mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
mkdir(ux0.c_str(), mode);
mkdir(ux0_data.c_str(), mode);
mkdir(uma0.c_str(), mode);
mkdir(uma0_data.c_str(), mode);
mkdir(ux0_user.c_str(), mode);
mkdir(ux0_user00.c_str(), mode);
mkdir(ux0_savedata.c_str(), mode);
#endif

return true;
Expand Down Expand Up @@ -191,6 +200,19 @@ SceUID open_file(IOState &io, const std::string &path_, int flags, const char *p
}
}

// Redirect savedata0:/ to ux0:/user/00/savedata/<title_id>
if (device == VitaIoDevice::SAVEDATA0) {
std::string fixed_path = path.substr(10);
auto start_path = fixed_path.find('/');
if (start_path != std::string::npos) {
fixed_path = fixed_path.substr(start_path);
fixed_path.insert(0, io.savedata0_path);

path = fixed_path;
device = VitaIoDevice::UX0;
}
}

switch (device) {
case VitaIoDevice::TTY0: {
assert(flags >= 0);
Expand Down
2 changes: 1 addition & 1 deletion src/emulator/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ int main(int argc, char *argv[]) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);

Ptr<const void> entry_point;
if (!load_vpk(entry_point, host.game_title, host.title_id, host.kernel, host.io, host.mem, host.sfo_handle, path)) {
if (!load_vpk(entry_point, host, path)) {
std::string message = "Failed to load \"";
message += wide_to_utf(path);
message += "\"";
Expand Down
94 changes: 82 additions & 12 deletions src/emulator/modules/SceAppUtil/SceAppUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#include <psp2/apputil.h>
#include <psp2/system_param.h>

#include <host/app_util.h>
#include <io/functions.h>

EXPORT(int, sceAppUtilAddCookieWebBrowser) {
return unimplemented("sceAppUtilAddCookieWebBrowser");
}
Expand Down Expand Up @@ -144,12 +147,53 @@ EXPORT(int, sceAppUtilResetCookieWebBrowser) {
return unimplemented("sceAppUtilResetCookieWebBrowser");
}

EXPORT(int, sceAppUtilSaveDataDataRemove) {
return unimplemented("sceAppUtilSaveDataDataRemove");
EXPORT(int, sceAppUtilSaveDataDataRemove, emu::SceAppUtilSaveDataFileSlot *slot, emu::SceAppUtilSaveDataRemoveItem *files, unsigned int fileNum, SceAppUtilSaveDataMountPoint *mountPoint) {
for (unsigned int i = 0; i < fileNum; i++) {
std::string file_path = "savedata0:/";
file_path += files[i].dataPath.get(host.mem);
switch (files[i].mode) {
case SCE_APPUTIL_SAVEDATA_DATA_REMOVE_MODE_DEFAULT:
remove_file(file_path.c_str(), host.pref_path.c_str());
break;
default: // Directory remotion
remove_dir(file_path.c_str(), host.pref_path.c_str());
break;
}
}

std::string slot_path = "savedata0:/SlotParam_";
slot_path += std::to_string(slot->id);
slot_path += ".bin";
remove_file(slot_path.c_str(), host.pref_path.c_str());
return 0;
}

EXPORT(int, sceAppUtilSaveDataDataSave) {
return unimplemented("sceAppUtilSaveDataDataSave");
EXPORT(int, sceAppUtilSaveDataDataSave, emu::SceAppUtilSaveDataFileSlot *slot, emu::SceAppUtilSaveDataFile *files, unsigned int fileNum, SceAppUtilSaveDataMountPoint *mountPoint, SceSize *requiredSizeKB) {
SceUID fd;

for (unsigned int i = 0; i < fileNum; i++) {
std::string file_path = "savedata0:/";
file_path += files[i].filePath.get(host.mem);
switch (files[i].mode) {
case SCE_APPUTIL_SAVEDATA_DATA_SAVE_MODE_FILE:
fd = open_file(host.io, file_path, SCE_O_WRONLY | SCE_O_CREAT, host.pref_path.c_str());
seek_file(fd, files[i].offset, SCE_SEEK_SET, host.io);
write_file(fd, files[i].buf.get(host.mem), files[i].bufSize, host.io);
close_file(host.io, fd);
break;
default: // Directory creation
create_dir(file_path.c_str(), 0777, host.pref_path.c_str());
break;
}
}

std::string slot_path = "savedata0:/SlotParam_";
slot_path += std::to_string(slot->id);
slot_path += ".bin";
fd = open_file(host.io, slot_path, SCE_O_WRONLY | SCE_O_CREAT, host.pref_path.c_str());
write_file(fd, &slot->slotParam, sizeof(SceAppUtilSaveDataSlotParam), host.io);
close_file(host.io, fd);
return 0;
}

EXPORT(int, sceAppUtilSaveDataGetQuota) {
Expand All @@ -160,24 +204,50 @@ EXPORT(int, sceAppUtilSaveDataMount) {
return unimplemented("sceAppUtilSaveDataMount");
}

EXPORT(int, sceAppUtilSaveDataSlotCreate) {
return unimplemented("sceAppUtilSaveDataSlotCreate");
EXPORT(int, sceAppUtilSaveDataSlotCreate, unsigned int slotId, SceAppUtilSaveDataSlotParam *param, SceAppUtilSaveDataMountPoint *mountPoint) {
std::string slot_path = "savedata0:/SlotParam_";
slot_path += std::to_string(slotId);
slot_path += ".bin";
SceUID fd = open_file(host.io, slot_path, SCE_O_WRONLY | SCE_O_CREAT, host.pref_path.c_str());
write_file(fd, param, sizeof(SceAppUtilSaveDataSlotParam), host.io);
close_file(host.io, fd);
return 0;
}

EXPORT(int, sceAppUtilSaveDataSlotDelete) {
return unimplemented("sceAppUtilSaveDataSlotDelete");
EXPORT(int, sceAppUtilSaveDataSlotDelete, unsigned int slotId, SceAppUtilSaveDataMountPoint *mountPoint) {
std::string slot_path = "savedata0:/SlotParam_";
slot_path += std::to_string(slotId);
slot_path += ".bin";
remove_file(slot_path.c_str(), host.pref_path.c_str());
return 0;
}

EXPORT(int, sceAppUtilSaveDataSlotGetParam) {
return unimplemented("sceAppUtilSaveDataSlotGetParam");
EXPORT(int, sceAppUtilSaveDataSlotGetParam, unsigned int slotId, SceAppUtilSaveDataSlotParam *param, SceAppUtilSaveDataMountPoint *mountPoint) {
std::string slot_path = "savedata0:/SlotParam_";
slot_path += std::to_string(slotId);
slot_path += ".bin";
SceUID fd = open_file(host.io, slot_path, SCE_O_RDONLY, host.pref_path.c_str());
if (fd < 0)
return RET_ERROR(__func__, SCE_APPUTIL_ERROR_SAVEDATA_SLOT_NOT_FOUND);
read_file(param, host.io, fd, sizeof(SceAppUtilSaveDataSlotParam));
close_file(host.io, fd);
return 0;
}

EXPORT(int, sceAppUtilSaveDataSlotSearch) {
return unimplemented("sceAppUtilSaveDataSlotSearch");
}

EXPORT(int, sceAppUtilSaveDataSlotSetParam) {
return unimplemented("sceAppUtilSaveDataSlotSetParam");
EXPORT(int, sceAppUtilSaveDataSlotSetParam, unsigned int slotId, SceAppUtilSaveDataSlotParam *param, SceAppUtilSaveDataMountPoint *mountPoint) {
std::string slot_path = "savedata0:/SlotParam_";
slot_path += std::to_string(slotId);
slot_path += ".bin";
SceUID fd = open_file(host.io, slot_path, SCE_O_WRONLY, host.pref_path.c_str());
if (fd < 0)
return RET_ERROR(__func__, SCE_APPUTIL_ERROR_SAVEDATA_SLOT_NOT_FOUND);
write_file(fd, param, sizeof(SceAppUtilSaveDataSlotParam), host.io);
close_file(host.io, fd);
return 0;
}

EXPORT(int, sceAppUtilSaveDataUmount) {
Expand Down
39 changes: 25 additions & 14 deletions src/emulator/vpk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <kernel/state.h>

#include <host/sfo.h>
#include <host/state.h>
#include <io/state.h>
#include <util/log.h>
#include <util/string_convert.h>
Expand Down Expand Up @@ -59,7 +60,7 @@ static bool read_file_from_zip(Buffer &buf, FILE *&vpk_fp, const char *file, con
return true;
}

bool load_vpk(Ptr<const void> &entry_point, std::string &game_title, std::string &title_id, KernelState &kernel, IOState &io, MemState &mem, SfoFile &sfo_file, const std::wstring &path) {
bool load_vpk(Ptr<const void> &entry_point, HostState &host, const std::wstring &path) {
const ZipPtr zip(new mz_zip_archive, delete_zip);
std::memset(zip.get(), 0, sizeof(*zip));

Expand Down Expand Up @@ -97,43 +98,53 @@ bool load_vpk(Ptr<const void> &entry_point, std::string &game_title, std::string
return false;
}

load_sfo(sfo_file, params);
load_sfo(host.sfo_handle, params);

find_data(game_title, sfo_file, "TITLE");
find_data(title_id, sfo_file, "TITLE_ID");
find_data(host.game_title, host.sfo_handle, "TITLE");
find_data(host.title_id, host.sfo_handle, "TITLE_ID");
std::string category;
find_data(category, sfo_file, "CATEGORY");
find_data(category, host.sfo_handle, "CATEGORY");

LOG_INFO("Path: {}", wide_to_utf(path));
LOG_INFO("Title: {}", game_title);
LOG_INFO("Serial: {}", title_id);
LOG_INFO("Title: {}", host.game_title);
LOG_INFO("Serial: {}", host.title_id);
LOG_INFO("Category: {}", category);

io.app0_prefix = "";
host.io.app0_prefix = "";

Buffer eboot;
if (!read_file_from_zip(eboot, vpk_fp, "eboot.bin", zip)) {
std::string eboot_path = title_id + "/eboot.bin";
std::string eboot_path = host.title_id + "/eboot.bin";
if (!read_file_from_zip(eboot, vpk_fp, eboot_path.c_str(), zip)) {
return false;
} else {
io.app0_prefix = title_id + "/";
host.io.app0_prefix = host.title_id + "/";
}
}

Buffer libc;
std::string libc_path = io.app0_prefix + "sce_module/libc.suprx";
std::string libc_path = host.io.app0_prefix + "sce_module/libc.suprx";
if (read_file_from_zip(libc, vpk_fp, libc_path.c_str(), zip)) {
if (load_self(entry_point, kernel, mem, libc.data(), "app0:sce_module/libc.suprx") == 0) {
if (load_self(entry_point, host.kernel, host.mem, libc.data(), "app0:sce_module/libc.suprx") == 0) {
LOG_INFO("LIBC loaded");
}
}

if (load_self(entry_point, kernel, mem, eboot.data(), "app0:eboot.bin") < 0) {
if (load_self(entry_point, host.kernel, host.mem, eboot.data(), "app0:eboot.bin") < 0) {
return false;
}

io.vpk = zip;
std::string savedata_path = host.pref_path + "ux0/user/00/savedata/" + host.title_id;

#ifdef WIN32
CreateDirectoryA(savedata_path.c_str(), nullptr);
#else
const int mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
mkdir(savedata_path.c_str(), mode);
#endif

host.io.savedata0_path = "ux0:/user/00/savedata/" + host.title_id + "/";
host.io.vpk = zip;

return true;
}
7 changes: 2 additions & 5 deletions src/emulator/vpk.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@

#include <string>

struct KernelState;
struct IOState;
struct MemState;
struct SfoFile;
struct HostState;
template <class T>
class Ptr;

bool load_vpk(Ptr<const void> &entry_point, std::string &game_title, std::string &title_id, KernelState &kernel, IOState &io, MemState &mem, SfoFile &sfo_file, const std::wstring &path);
bool load_vpk(Ptr<const void> &entry_point, HostState &host, const std::wstring &path);