Files
jak-project/game/sce/sif_ee.cpp
T
water111 403bb5f4de [decomp] game-info (#779)
* support more process stuff

* more of game info

* add ref file

* progress on save
2021-08-22 20:12:47 -04:00

358 lines
8.5 KiB
C++

#include <cstring>
#include "common/util/assert.h"
#include <cstdio>
#include <unordered_map>
#include "common/util/FileUtil.h"
#include "sif_ee.h"
#include "game/system/iop_thread.h"
#include "game/runtime.h"
namespace ee {
namespace {
::IOP* iop;
std::unordered_map<s32, FILE*> sce_fds;
} // namespace
void LIBRARY_sceSif_register(::IOP* i) {
iop = i;
}
void LIBRARY_INIT_sceSif() {
iop = nullptr;
for (auto& kv : sce_fds) {
fclose(kv.second);
}
sce_fds.clear();
}
void sceSifInitRpc(unsigned int mode) {
(void)mode;
}
int sceSifRebootIop(const char* imgfile) {
(void)imgfile;
return 1;
}
int sceSifSyncIop() {
return 1;
}
void sceFsReset() {}
int sceSifLoadModule(const char* name, int arg_size, const char* args) {
if (!strcmp(name, "cdrom0:\\\\DRIVERS\\\\OVERLORD.IRX;1") ||
!strcmp(name, "host0:binee/overlord.irx")) {
const char* src = args;
char* dst = iop->overlord_arg_data;
int cnt;
iop->overlord_argv[0] = nullptr;
for (cnt = 1; src - args < arg_size; cnt++) {
auto len = strlen(src);
memcpy(dst, src, len + 1);
iop->overlord_argv[cnt] = dst;
dst += len + 1;
src += len + 1;
}
iop->overlord_argc = cnt;
for (int i = 0; i < cnt; i++) {
if (iop->overlord_argv[i])
printf("arg %d : %s\n", i, iop->overlord_argv[i]);
}
iop->set_ee_main_mem(g_ee_main_mem);
iop->send_status(IOP_Status::IOP_OVERLORD_INIT);
iop->wait_for_overlord_init_finish();
}
return 1;
}
s32 sceSifCallRpc(sceSifClientData* bd,
u32 fno,
u32 mode,
void* send,
s32 ssize,
void* recv,
s32 rsize,
void* end_func,
void* end_para) {
assert(!end_func);
assert(!end_para);
assert(mode == 1); // async
iop->kernel.sif_rpc(bd->rpcd.id, fno, mode, send, ssize, recv, rsize);
iop->signal_run_iop();
return 0;
}
s32 sceSifCheckStatRpc(sceSifRpcData* bd) {
iop->signal_run_iop();
return iop->kernel.sif_busy(bd->id);
}
s32 sceSifBindRpc(sceSifClientData* bd, u32 request, u32 mode) {
assert(mode == 1); // async
bd->rpcd.id = request;
bd->serve = (sceSifServeData*)1;
return 0;
}
s32 sceOpen(const char* filename, s32 flag) {
auto name = file_util::get_file_path({filename});
FILE* fp = nullptr;
switch (flag) {
case SCE_RDONLY:
fp = fopen(name.c_str(), "r");
break;
default:
assert(false);
}
if (!fp) {
printf("[SCE] sceOpen(%s) failed.\n", name.c_str());
return -1;
}
s32 fp_idx = sce_fds.size() + 1;
sce_fds[fp_idx] = fp;
return fp_idx;
}
s32 sceClose(s32 fd) {
if (fd < 0) {
// todo, what should we really return?
return 0;
}
auto kv = sce_fds.find(fd);
if (kv != sce_fds.end()) {
fclose(kv->second);
sce_fds.erase(fd);
return 0;
} else {
printf("[SCE] sceClose called on invalid fd\n");
return 0;
}
}
s32 sceRead(s32 fd, void* buf, s32 nbyte) {
auto kv = sce_fds.find(fd);
if (kv == sce_fds.end()) {
return -1;
} else {
return fread(buf, 1, nbyte, kv->second);
}
}
s32 sceWrite(s32 fd, const void* buf, s32 nbyte) {
(void)fd;
(void)buf;
(void)nbyte;
assert(false);
return 0;
}
s32 sceLseek(s32 fd, s32 offset, s32 where) {
auto kv = sce_fds.find(fd);
if (kv == sce_fds.end()) {
return -1;
} else {
switch (where) {
case SCE_SEEK_CUR:
fseek(kv->second, offset, SEEK_CUR);
return ftell(kv->second);
case SCE_SEEK_END:
fseek(kv->second, offset, SEEK_END);
return ftell(kv->second);
case SCE_SEEK_SET:
fseek(kv->second, offset, SEEK_SET);
return ftell(kv->second);
default:
assert(false);
return -1;
}
}
}
/*!
* The actual data stored on the memory card.
*/
struct CardData {
// each file has a name and data.
struct File {
std::string name;
std::vector<u8> data;
};
// can be formatted or unformatted card.
u32 is_formatted = 0;
std::unordered_map<std::string, File> files;
};
/*!
* The actual memory card library state + current data.
*/
struct McState {
s32 current_function = -1; // -1 = nothing
s32 current_function_result = 0;
struct McFileHandle {
std::string name;
u32 fd = 0;
s32 mode = 0;
};
std::unordered_map<int, McFileHandle> handles;
// TODO: we should load this data at startup from a memory card file, and save it at each write.
CardData data;
int next_fd = 1;
} g_mc_state;
int sceMcInit() {
g_mc_state = McState();
return 1;
}
s32 sceMcMkdir(s32 port, s32 slot, const char* name) {
assert(port == 0);
assert(slot == 0);
// TODO name
(void)name;
return sceMcResSucceed;
}
s32 sceMcSync(s32 mode, s32* cmd, s32* result) {
// don't care about the mode, all memory card ops are instant.
assert(mode == 1 || mode == 0);
if (g_mc_state.current_function == -1) {
return sceMcExecIdle;
} else {
*cmd = g_mc_state.current_function;
*result = g_mc_state.current_function_result;
g_mc_state.current_function = -1;
return sceMcExecFinish;
}
}
s32 sceMcOpen(s32 port, s32 slot, const char* name, s32 mode) {
assert(port == 0);
assert(slot == 0);
assert(g_mc_state.current_function == -1);
// add existing file, if it does not exist.
auto existing_file = g_mc_state.data.files.find(name);
if (existing_file == g_mc_state.data.files.end()) {
assert(mode & SCE_CREAT);
g_mc_state.data.files[name] = {};
}
// create a handle.
g_mc_state.current_function = sceMcFuncNoOpen;
s32 fd = g_mc_state.next_fd++;
McState::McFileHandle handle;
handle.name = name;
handle.fd = fd;
handle.mode = mode;
g_mc_state.handles[fd] = handle;
g_mc_state.current_function_result = fd;
return 0;
}
s32 sceMcWrite(s32 fd, const void* buff, s32 size) {
assert(g_mc_state.current_function == -1);
assert(size >= 0 && size < (1024 * 1024 * 1024));
auto hand = g_mc_state.handles.find(fd);
assert(hand != g_mc_state.handles.end()); // make sure fd is valid
assert(hand->second.mode & SCE_WRONLY); // make sure we're allowed to write
const auto& file = g_mc_state.data.files.find(hand->second.name);
assert(file != g_mc_state.data.files.end());
file->second.data.resize(size);
memcpy(file->second.data.data(), buff, size);
// TODO: save memcard data to a file.
g_mc_state.current_function = sceMcFuncNoWrite;
g_mc_state.current_function_result = size;
return 0;
}
s32 sceMcClose(s32 fd) {
assert(g_mc_state.current_function == -1);
auto hand = g_mc_state.handles.find(fd);
assert(hand != g_mc_state.handles.end()); // make sure fd is valid
g_mc_state.handles.erase(fd);
g_mc_state.current_function = sceMcFuncNoClose;
g_mc_state.current_function_result = sceMcResSucceed;
return 0;
}
s32 sceMcGetInfo(s32 port, s32 slot, s32* type, s32* free, s32* format) {
assert(g_mc_state.current_function == -1);
assert(port == 0);
assert(slot == 0);
if (type) {
*type = sceMcTypePS2;
}
if (free) {
*free = 2 * 1024; // number of free 1 kB clusters
}
if (format) {
*format = g_mc_state.data.is_formatted;
}
g_mc_state.current_function = sceMcFuncNoCardInfo;
// technically this should return something else the first time you call this function after
// changing cards.
g_mc_state.current_function_result = sceMcResSucceed;
return 0;
}
s32 sceMcFormat(s32 port, s32 slot) {
assert(g_mc_state.current_function == -1);
assert(port == 0);
assert(slot == 0);
g_mc_state.data.is_formatted = true;
g_mc_state.current_function_result = sceMcResSucceed;
g_mc_state.current_function = sceMcFuncNoFormat;
return 0;
}
s32 sceMcUnformat(s32 port, s32 slot) {
assert(g_mc_state.current_function == -1);
assert(port == 0);
assert(slot == 0);
g_mc_state.data.is_formatted = false;
g_mc_state.current_function_result = sceMcResSucceed;
g_mc_state.current_function = sceMcFuncNoUnformat;
return 0;
}
s32 sceMcDelete(s32 port, s32 slot, const char* name) {
assert(g_mc_state.current_function == -1);
assert(port == 0);
assert(slot == 0);
g_mc_state.current_function = sceMcFuncNoDelete;
if (!g_mc_state.data.is_formatted) {
g_mc_state.current_function_result = sceMcResNoFormat;
} else {
auto it = g_mc_state.data.files.find(name);
if (it == g_mc_state.data.files.end()) {
g_mc_state.current_function_result = sceMcResNoEntry;
} else {
// sometimes should be sceMcResNotEmpty, but doesn't matter.
g_mc_state.current_function_result = sceMcResSucceed;
g_mc_state.data.files.erase(it);
}
}
return 0;
}
} // namespace ee