mirror of
https://github.com/open-goal/jak-project
synced 2026-08-15 04:51:00 -04:00
Add the STR RPC to overlord and game code (#134)
* work in progress streaming rpc, simple test is working * actually add the test * debug windows failure * windows fix maybe * windows 2 * use str-load-status * update types
This commit is contained in:
@@ -79,26 +79,10 @@ void fake_iso_init_globals() {
|
||||
int FS_Init(u8* buffer) {
|
||||
(void)buffer;
|
||||
|
||||
// get path to next/data/fake_iso.txt, the map file.
|
||||
char fakeiso_path[512];
|
||||
strcpy(fakeiso_path, file_util::get_file_path({"game", "fake_iso.txt"}).c_str());
|
||||
|
||||
// open the map.
|
||||
FILE* fp = fopen(fakeiso_path, "r");
|
||||
assert(fp);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size_t len = ftell(fp);
|
||||
rewind(fp);
|
||||
char* fakeiso = (char*)malloc(len + 1);
|
||||
if (fread(fakeiso, len, 1, fp) != 1) {
|
||||
#ifdef __linux__
|
||||
assert(false);
|
||||
#endif
|
||||
}
|
||||
fakeiso[len] = '\0';
|
||||
auto config_str = file_util::read_text_file(file_util::get_file_path({"game", "fake_iso.txt"}));
|
||||
const char* ptr = config_str.c_str();
|
||||
|
||||
// loop over lines
|
||||
char* ptr = fakeiso;
|
||||
while (*ptr) {
|
||||
// newlines
|
||||
while (*ptr && *ptr == '\n')
|
||||
@@ -127,7 +111,7 @@ int FS_Init(u8* buffer) {
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (*ptr && (*ptr != '\n') && (*ptr != ' ') && i < 128) {
|
||||
while (*ptr && (*ptr != '\n') && (*ptr != ' ') && (*ptr != EOF) && i < 128) {
|
||||
e->file_path[i] = *ptr;
|
||||
ptr++;
|
||||
i++;
|
||||
@@ -145,8 +129,6 @@ int FS_Init(u8* buffer) {
|
||||
sFiles[i].location = i;
|
||||
}
|
||||
|
||||
free(fakeiso);
|
||||
|
||||
// TODO load tweak music.
|
||||
|
||||
return 0;
|
||||
@@ -201,6 +183,7 @@ static const char* get_file_path(FileRecord* fr) {
|
||||
*/
|
||||
uint32_t FS_GetLength(FileRecord* fr) {
|
||||
const char* path = get_file_path(fr);
|
||||
file_util::assert_file_exists(path, "fake_iso FS_GetLength");
|
||||
FILE* fp = fopen(path, "rb");
|
||||
assert(fp);
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
+12
-12
@@ -43,7 +43,7 @@ s32 str_thread;
|
||||
s32 play_thread;
|
||||
u8 gVagDir[VAGDIR_SIZE];
|
||||
u32 gPlayPos;
|
||||
RPC_Dgo_Cmd sRPCBuff[1]; // todo move...
|
||||
static RPC_Dgo_Cmd sRPCBuff[1]; // todo move...
|
||||
DgoCommand scmd;
|
||||
|
||||
void iso_init_globals() {
|
||||
@@ -171,16 +171,16 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// thread_param.attr = TH_C;
|
||||
// thread_param.initPriority = 97;
|
||||
// thread_param.stackSize = 0x800;
|
||||
// thread_param.option = 0;
|
||||
// thread_param.entry = (void*)STRThread;
|
||||
// strcpy(thread_param.name, "STRThread");
|
||||
// str_thread = CreateThread(&thread_param);
|
||||
// if(str_thread <= 0) {
|
||||
// return 1;
|
||||
// }
|
||||
thread_param.attr = TH_C;
|
||||
thread_param.initPriority = 97;
|
||||
thread_param.stackSize = 0x800;
|
||||
thread_param.option = 0;
|
||||
thread_param.entry = (void*)STRThread;
|
||||
strcpy(thread_param.name, "STRThread");
|
||||
str_thread = CreateThread(&thread_param);
|
||||
if (str_thread <= 0) {
|
||||
return 1;
|
||||
}
|
||||
//
|
||||
// thread_param.attr = TH_C;
|
||||
// thread_param.initPriority = 97;
|
||||
@@ -196,7 +196,7 @@ u32 InitISOFS(const char* fs_mode, const char* loading_screen) {
|
||||
// Start the threads!
|
||||
StartThread(iso_thread, 0);
|
||||
StartThread(dgo_thread, 0);
|
||||
// StartThread(str_thread, 0);
|
||||
StartThread(str_thread, 0);
|
||||
// StartThread(play_thread, 0);
|
||||
|
||||
// wait for ISO Thread to initialize
|
||||
|
||||
@@ -7,7 +7,7 @@ using namespace iop;
|
||||
/*!
|
||||
* Load a File to IOP memory (blocking)
|
||||
*/
|
||||
void LoadISOFileToIOP(FileRecord* file, void* addr, uint32_t length) {
|
||||
s32 LoadISOFileToIOP(FileRecord* file, void* addr, uint32_t length) {
|
||||
// printf("[OVERLORD] LoadISOFileToIOP %s, %d/%d bytes\n", file->name, length, file->size);
|
||||
spdlog::debug("[OVERLORD] LoadISOFileToIOP {}, {}/{} bytes", file->name, length, file->size);
|
||||
IsoCommandLoadSingle cmd;
|
||||
@@ -23,12 +23,14 @@ void LoadISOFileToIOP(FileRecord* file, void* addr, uint32_t length) {
|
||||
if (cmd.status) {
|
||||
cmd.length_to_copy = 0;
|
||||
}
|
||||
|
||||
return cmd.length_to_copy;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Load a File to IOP memory (blocking)
|
||||
*/
|
||||
void LoadISOFileToEE(FileRecord* file, uint32_t addr, uint32_t length) {
|
||||
s32 LoadISOFileToEE(FileRecord* file, uint32_t addr, uint32_t length) {
|
||||
// printf("[OVERLORD] LoadISOFileToEE %s, %d/%d bytes\n", file->name, length, file->size);
|
||||
spdlog::debug("[OVERLORD] LoadISOFileToEE {}, {}/{} bytes", file->name, length, file->size);
|
||||
IsoCommandLoadSingle cmd;
|
||||
@@ -44,4 +46,24 @@ void LoadISOFileToEE(FileRecord* file, uint32_t addr, uint32_t length) {
|
||||
if (cmd.status) {
|
||||
cmd.length_to_copy = 0;
|
||||
}
|
||||
|
||||
return cmd.length_to_copy;
|
||||
}
|
||||
|
||||
s32 LoadISOFileChunkToEE(FileRecord* file, uint32_t dest_addr, uint32_t length, uint32_t offset) {
|
||||
spdlog::debug("[OVERLORD] LoadISOFileChunkToEE {} : {} offset {}\n", file->name, length, offset);
|
||||
IsoCommandLoadSingle cmd;
|
||||
cmd.cmd_id = LOAD_TO_EE_OFFSET_CMD_ID;
|
||||
cmd.messagebox_to_reply = 0;
|
||||
cmd.thread_id = GetThreadId();
|
||||
cmd.file_record = file;
|
||||
cmd.dest_addr = (u8*)(u64)dest_addr;
|
||||
cmd.length = length;
|
||||
cmd.offset = offset;
|
||||
SendMbx(iso_mbx, &cmd);
|
||||
SleepThread();
|
||||
if (cmd.status) {
|
||||
cmd.length_to_copy = 0;
|
||||
}
|
||||
return cmd.length_to_copy;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef JAK_V2_ISO_API_H
|
||||
#define JAK_V2_ISO_API_H
|
||||
#include "isocommon.h"
|
||||
|
||||
void LoadISOFileToIOP(FileRecord* file, void* addr, uint32_t length);
|
||||
void LoadISOFileToEE(FileRecord* file, uint32_t ee_addr, uint32_t length);
|
||||
|
||||
#endif // JAK_V2_ISO_API_H
|
||||
s32 LoadISOFileToIOP(FileRecord* file, void* addr, uint32_t length);
|
||||
s32 LoadISOFileToEE(FileRecord* file, uint32_t ee_addr, uint32_t length);
|
||||
s32 LoadISOFileChunkToEE(FileRecord* file, uint32_t dest_addr, uint32_t length, uint32_t offset);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <string>
|
||||
#include "common/common_types.h"
|
||||
#include "common/link_types.h"
|
||||
#include "game/common/overlord_common.h"
|
||||
|
||||
constexpr int PRI_STACK_LENGTH = 4; // number of queued commands per priority
|
||||
constexpr int N_PRIORITIES = 4; // number of priorities
|
||||
@@ -30,7 +31,6 @@ constexpr int LOAD_TO_IOP_CMD_ID = 0x101; // command to load to iop
|
||||
constexpr int LOAD_TO_EE_OFFSET_CMD_ID = 0x102; // command to load file to ee with offset.
|
||||
constexpr int LOAD_DGO_CMD_ID = 0x200; // command to load DGO
|
||||
|
||||
constexpr int SECTOR_SIZE = 0x800; // media sector size
|
||||
constexpr int MAX_ISO_FILES = 350; // maximum files on FS
|
||||
constexpr int MAX_OPEN_FILES = 16; // maximum number of open files at a time.
|
||||
|
||||
@@ -51,7 +51,7 @@ struct FileRecord {
|
||||
*/
|
||||
struct LoadStackEntry {
|
||||
FileRecord* fr;
|
||||
uint32_t location;
|
||||
uint32_t location; // sectors.
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -185,5 +185,6 @@ extern IsoFs* isofs;
|
||||
extern s32 iso_mbx;
|
||||
|
||||
void MakeISOName(char* dst, const char* src);
|
||||
void ISONameFromAnimationName(char* dst, const char* src);
|
||||
|
||||
#endif // JAK_V2_ISOCOMMON_H
|
||||
|
||||
+132
-3
@@ -1,12 +1,141 @@
|
||||
#include <assert.h>
|
||||
#include "stream.h"
|
||||
/*!
|
||||
* @file stream.cpp
|
||||
* OVERLORD streaming driver.
|
||||
* Supports loading a file directly to the EE, or loading chunks of a chunked file.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include "stream.h"
|
||||
#include "game/sce/iop.h"
|
||||
#include "game/common/str_rpc_types.h"
|
||||
#include "game/overlord/isocommon.h"
|
||||
#include "game/overlord/iso_api.h"
|
||||
|
||||
using namespace iop;
|
||||
|
||||
static RPC_Str_Cmd sRPCBuf;
|
||||
void* RPC_STR(unsigned int fno, void* _cmd, int y);
|
||||
|
||||
/*!
|
||||
* We cache the chunk file headers so we can avoid seeking to the chunk header each time we
|
||||
* need to load another chunk, even if we load chunks out of order.
|
||||
*/
|
||||
struct CacheEntry {
|
||||
// the record for the chunk file described.
|
||||
FileRecord* fr = nullptr;
|
||||
// counts down from INT32_MAX - 1 each time we have a cache miss.
|
||||
s32 countdown = 0;
|
||||
// the actual cached data.
|
||||
StrFileHeader header;
|
||||
};
|
||||
|
||||
// the actual header cache.
|
||||
constexpr int STR_INDEX_CACHE_SIZE = 4;
|
||||
CacheEntry sCache[STR_INDEX_CACHE_SIZE];
|
||||
|
||||
void stream_init_globals() {
|
||||
memset(&sRPCBuf, 0, sizeof(RPC_Str_Cmd));
|
||||
}
|
||||
|
||||
/*!
|
||||
* Run the STR RPC handler.
|
||||
*/
|
||||
u32 STRThread() {
|
||||
assert(false);
|
||||
sceSifQueueData dq;
|
||||
sceSifServeData serve;
|
||||
|
||||
CpuDisableIntr();
|
||||
sceSifInitRpc(0);
|
||||
sceSifSetRpcQueue(&dq, GetThreadId());
|
||||
sceSifRegisterRpc(&serve, STR_RPC_ID, RPC_STR, &sRPCBuf, nullptr, nullptr, &dq);
|
||||
CpuEnableIntr();
|
||||
sceSifRpcLoop(&dq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 PLAYThread() {
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* The STR RPC handler.
|
||||
*/
|
||||
void* RPC_STR(unsigned int fno, void* _cmd, int y) {
|
||||
(void)fno;
|
||||
(void)y;
|
||||
auto* cmd = (RPC_Str_Cmd*)_cmd;
|
||||
printf("RPC STR runs!\n");
|
||||
if (cmd->chunk_id < 0) {
|
||||
// it's _not_ a stream file. So we just treat it like a normal load.
|
||||
|
||||
// find the file with the given name
|
||||
auto file_record = isofs->find(cmd->name);
|
||||
if (file_record == nullptr) {
|
||||
// file not found!
|
||||
printf("[OVERLORD STR] Failed to find file %s for loading.\n", cmd->name);
|
||||
cmd->result = STR_RPC_RESULT_ERROR;
|
||||
} else {
|
||||
// load directly to the EE
|
||||
cmd->length = LoadISOFileToEE(file_record, cmd->ee_addr, cmd->length);
|
||||
if (cmd->length) {
|
||||
// successful load!
|
||||
cmd->result = STR_RPC_RESULT_DONE;
|
||||
} else {
|
||||
// there was an error loading.
|
||||
cmd->result = STR_RPC_RESULT_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// it's a chunked file. These are only animations - these have a separate naming scheme.
|
||||
char animation_iso_name[128];
|
||||
ISONameFromAnimationName(animation_iso_name, cmd->name);
|
||||
auto file_record = isofs->find_in(animation_iso_name);
|
||||
|
||||
if (!file_record) {
|
||||
// didn't find the file
|
||||
printf("[OVERLORD STR] Failed to find animation %s\n", cmd->name);
|
||||
cmd->result = STR_RPC_RESULT_ERROR;
|
||||
} else {
|
||||
// found it! See if we've cached this animation's header.
|
||||
int cache_entry = 0;
|
||||
int oldest = INT32_MAX;
|
||||
int oldest_idx = -1;
|
||||
while (cache_entry < STR_INDEX_CACHE_SIZE && sCache[cache_entry].fr != file_record) {
|
||||
sCache[cache_entry].countdown--;
|
||||
if (sCache[cache_entry].countdown < oldest) {
|
||||
oldest_idx = cache_entry;
|
||||
oldest = sCache[cache_entry].countdown;
|
||||
}
|
||||
cache_entry++;
|
||||
}
|
||||
|
||||
if (cache_entry == STR_INDEX_CACHE_SIZE) {
|
||||
// cache miss, we need to load the header to the header cache on the IOP
|
||||
cache_entry = oldest_idx;
|
||||
sCache[oldest_idx].fr = file_record;
|
||||
sCache[oldest_idx].countdown = INT32_MAX - 1;
|
||||
if (!LoadISOFileToIOP(file_record, &sCache[oldest_idx].header, sizeof(StrFileHeader))) {
|
||||
printf("[OVERLORD STR] Failed to load chunk file header for animation %s\n", cmd->name);
|
||||
cmd->result = 1;
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
|
||||
// load data, using the cached header to find the location of the chunk.
|
||||
if (!LoadISOFileChunkToEE(file_record, cmd->ee_addr,
|
||||
sCache[cache_entry].header.sizes[cmd->chunk_id],
|
||||
sCache[cache_entry].header.sectors[cmd->chunk_id])) {
|
||||
printf("[OVERLORD STR] Failed to load chunk %d for animation %s\n", cmd->chunk_id,
|
||||
cmd->name);
|
||||
cmd->result = 1;
|
||||
} else {
|
||||
// successful load!
|
||||
cmd->length = sCache[cache_entry].header.sizes[cmd->chunk_id];
|
||||
cmd->result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Command result %d\n", cmd->result);
|
||||
return cmd;
|
||||
}
|
||||
@@ -6,5 +6,6 @@
|
||||
#include "common/common_types.h"
|
||||
u32 STRThread();
|
||||
u32 PLAYThread();
|
||||
void stream_init_globals();
|
||||
|
||||
#endif // JAK_V2_STREAM_H
|
||||
|
||||
Reference in New Issue
Block a user