mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 21:27:52 -04:00
f8bc883d48
* Use sleepthread in RPC loop * Keep a pointer to current IOP thread * Implement IOP thread scheduling based on priority And implement DelayThread as an actual delay. * Run IOP flat out * Use information from scheduler in wait_run_iop * Lock sif mutex in set_rpc_queue * always use kernel dispatch with wait_run * Loop in dispatch until no thread is ready * Use timestamp for next wakeup instead of duration * Wrap IOP thread entrypoints for safety Libco threads are not supposed to return from their entrypoint * Use a queue for IOP thread wakeups from EE thread
184 lines
3.9 KiB
C++
184 lines
3.9 KiB
C++
#include "sif_ee.h"
|
|
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <unordered_map>
|
|
|
|
#include "common/util/Assert.h"
|
|
#include "common/util/FileUtil.h"
|
|
|
|
#include "game/runtime.h"
|
|
#include "game/system/iop_thread.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") || !strcmp(name, "host0:bin/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) {
|
|
FILE* fp = nullptr;
|
|
auto name = file_util::get_file_path({filename});
|
|
switch (flag) {
|
|
case SCE_RDONLY: {
|
|
fp = file_util::open_file(name.c_str(), "rb");
|
|
} break;
|
|
|
|
default: {
|
|
fp = file_util::open_file(name.c_str(), "w");
|
|
} break;
|
|
}
|
|
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) {
|
|
auto kv = sce_fds.find(fd);
|
|
if (kv == sce_fds.end()) {
|
|
ASSERT(false);
|
|
return -1;
|
|
} else {
|
|
return fwrite(buf, 1, nbyte, kv->second);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace ee
|