Files
jak-project/game/overlord/jak2/stream.cpp
T
ManDude 40b2e93be7 pack tfrag normals into 10 bits (#2625)
Saves 16 bits and lets us align the `color_index` field properly.

This shouldn't improve or decrease performance by any noticeable amount
except maybe in really low end systems.
2023-05-06 02:08:33 +01:00

360 lines
12 KiB
C++

#include "stream.h"
#include <cstring>
#include "common/util/FileUtil.h"
#include "game/common/play_rpc_types.h"
#include "game/common/str_rpc_types.h"
#include "game/overlord/common/iso.h"
#include "game/overlord/common/iso_api.h"
#include "game/overlord/common/isocommon.h"
#include "game/overlord/jak2/iso.h"
#include "game/overlord/jak2/iso_api.h"
#include "game/overlord/jak2/streamlist.h"
#include "game/overlord/jak2/vag.h"
#include "game/runtime.h"
#include "game/sce/iop.h"
using namespace iop;
namespace jak2 {
static RPC_Str_Cmd_Jak2 sSTRBuf;
static RPC_Play_Cmd_Jak2 sPLAYBuf[2]; // called sRPCBuf2
struct CacheEntry {
FileRecord* fr = nullptr;
s32 countdown = 0;
StrFileHeaderJ2 header;
};
constexpr int STR_INDEX_CACHE_SIZE = 4;
CacheEntry sCache[STR_INDEX_CACHE_SIZE];
void stream_init_globals() {
memset(&sSTRBuf, 0, sizeof(RPC_Str_Cmd_Jak2));
memset(&sPLAYBuf, 0, sizeof(RPC_Play_Cmd_Jak2) * 2);
}
/*!
* The STR RPC handler.
*/
void* RPC_STR(unsigned int /*fno*/, void* _cmd, int /*y*/) {
auto* cmd = (RPC_Str_Cmd_Jak2*)_cmd;
if (cmd->section < 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->basename);
if (file_record == nullptr) {
// file not found!
printf("[OVERLORD STR] Failed to find file %s for loading.\n", cmd->basename);
cmd->result = STR_RPC_RESULT_ERROR;
} else {
// load directly to the EE
cmd->maxlen = LoadISOFileToEE(file_record, cmd->address, cmd->maxlen);
if (cmd->maxlen) {
// 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];
file_util::ISONameFromAnimationName(animation_iso_name, cmd->basename);
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 (%s)\n", cmd->basename,
animation_iso_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, (u8*)&sCache[oldest_idx].header,
sizeof(StrFileHeaderJ2))) {
printf("[OVERLORD STR] Failed to load chunk file header for animation %s\n",
cmd->basename);
cmd->result = 1;
return cmd;
}
}
// load data, using the cached header to find the location of the chunk.
if (!LoadISOFileChunkToEE(file_record, cmd->address,
sCache[cache_entry].header.sizes[cmd->section],
sCache[cache_entry].header.sectors[cmd->section])) {
printf("[OVERLORD STR] Failed to load chunk %d for animation %s\n", cmd->section,
cmd->basename);
cmd->result = 1;
} else {
// successful load!
cmd->maxlen = sCache[cache_entry].header.sizes[cmd->section];
cmd->result = 0;
}
}
}
// don't remember why we changed this...
return cmd;
// return nullptr;
}
void* RPC_PLAY([[maybe_unused]] unsigned int fno, void* _cmd, int size) {
// uint16_t uVar1;
VagCmd* pRVar2;
VagStrListNode* iVar3;
VagStrListNode* iVar4;
// RPC_Play_Cmd_Jak2* pRVar3;
// char* __src;
int iVar5;
// int iVar6;
// uint uVar7;
// RPC_Play_Cmd_Jak2* pRVar8;
// int iVar10;
VagStrListNode list_node;
// int local_30;
// int local_2c;
// if (size < 0) {
// size = size + 0xff;
// }
// local_30 = size >> 8;
// local_2c = 0;
int n_messages = size / sizeof(RPC_Play_Cmd_Jak2);
auto* cmd_iter = (RPC_Play_Cmd_Jak2*)_cmd;
for (int i = 0; i < n_messages; i++) {
// printf("RPC_PLAY message %d\n", i);
auto cmd_result = cmd_iter->result;
if (cmd_result == 1) {
for (int s = 0; s < 4; s++) {
if (cmd_iter->names[s].chars[0]) {
strncpy(list_node.name, cmd_iter->names[s].chars, 0x30);
list_node.id = cmd_iter->id[s];
WaitSema(EEStreamsList.sema);
RemoveVagStreamFromList(&list_node, &EEStreamsList);
SignalSema(EEStreamsList.sema);
WaitSema(EEPlayList.sema);
RemoveVagStreamFromList(&list_node, &EEPlayList);
SignalSema(EEPlayList.sema);
}
}
} else {
iVar5 = 9;
if (cmd_result == 2) {
// uVar7 = 0;
// iVar6 = 0x20;
WaitSema(EEStreamsList.sema);
EmptyVagStreamList(&EEStreamsList);
for (int s = 0; s < 4; s++) {
if (cmd_iter->names[s].chars[0] && cmd_iter->id[s]) {
// printf("got queue command %d: %s %d\n", s, cmd_iter->names[s].chars,
// cmd_iter->id[s]);
strncpy(list_node.name, cmd_iter->names[s].chars, 0x30);
list_node.id = cmd_iter->id[s];
list_node.unk_76 = cmd_iter->address & 1 << (s & 0x1f) & 0xf;
list_node.unk_72 = 0;
list_node.unk_80 = cmd_iter->address & 0x10 << (s & 0x1f) & 0xf0;
list_node.prio = iVar5;
pRVar2 = FindThisVagStream(list_node.name, list_node.id);
if (pRVar2 != 0x0) {
pRVar2->unk_288 = list_node.unk_76;
pRVar2->unk_292 = list_node.unk_80;
if (pRVar2->unk_288 != 0) {
pRVar2->byte10 = '\x01';
}
if (pRVar2->unk_292 != 0) {
pRVar2->unk_232 = '\x01';
}
}
InsertVagStreamInList(&list_node, &EEStreamsList);
}
if (iVar5 == 8) {
iVar5 = 2;
} else if (0 < iVar5) {
iVar5 = iVar5 + -1;
}
}
/*
pRVar3 = cmd_iter;
pRVar8 = cmd_iter;
do {
if ((pRVar8->names[0].data[0] != '\0') && (pRVar3->id[0] != 0)) {
strncpy(list_node.name, (char*)((int)cmd_iter->id + iVar6 + -0x10), 0x30);
list_node.id = pRVar3->id[0];
list_node.unk_76 = cmd_iter->address & 1 << (uVar7 & 0x1f) & 0xf;
list_node.unk_72 = 0;
list_node.unk_80 = cmd_iter->address & 0x10 << (uVar7 & 0x1f) & 0xf0;
list_node.prio = iVar5;
pRVar2 = FindThisVagStream(list_node.name, list_node.id);
if (pRVar2 != (RealVagCmd*)0x0) {
pRVar2->unk_288 = list_node.unk_76;
pRVar2->unk_292 = list_node.unk_80;
if (pRVar2->unk_288 != 0) {
pRVar2->byte10 = '\x01';
}
if (pRVar2->unk_292 != 0) {
pRVar2->unk_232 = '\x01';
}
}
InsertVagStreamInList(&list_node, (List*)EEStreamsList);
}
if (iVar5 == 8) {
iVar5 = 2;
} else if (0 < iVar5) {
iVar5 = iVar5 + -1;
}
iVar6 = iVar6 + 0x30;
pRVar3 = (RPC_Play_Cmd*)&pRVar3->address;
uVar7 = uVar7 + 1;
pRVar8 = (RPC_Play_Cmd*)(pRVar8->names[0].data + 0x10);
} while ((int)uVar7 < 4);
*/
SignalSema(EEStreamsList.sema);
} else if (cmd_result == 0) {
iVar5 = 9;
for (int s = 0; s < 4; s++) {
if (cmd_iter->names[s].chars[0] && cmd_iter->id[s]) {
// __src = (char*)((int)cmd_iter->id + iVar10 + -0x10);
strncpy(list_node.name, cmd_iter->names[s].chars, 0x30);
list_node.id = cmd_iter->id[s];
list_node.unk_68 = 0;
list_node.unk_72 = 0;
list_node.prio = iVar5;
pRVar2 = FindThisVagStream(cmd_iter->names[s].chars, cmd_iter->id[s]);
if ((pRVar2 == 0x0) || (pRVar2->byte4 == '\0')) {
// printf(" didn't exist, looks like it needs to be added!\n");
WaitSema(EEPlayList.sema);
iVar3 = (VagStrListNode*)FindVagStreamInList(&list_node, &EEPlayList);
if (iVar3 == (VagStrListNode*)0x0) {
// printf("node also doesn't exist, adding it!\n");
iVar4 = (VagStrListNode*)InsertVagStreamInList(&list_node, &EEPlayList);
iVar4->id = list_node.id;
iVar4->prio = list_node.prio;
iVar4->unk_72 = list_node.unk_72;
iVar4->unk_76 = 0;
iVar4->unk_80 = 0;
iVar4->unk_92 = 0;
iVar4->unk_68 = list_node.unk_68;
strncpy(iVar4->name, list_node.name, 0x30);
}
SignalSema(EEPlayList.sema);
}
}
if (iVar5 == 8) {
iVar5 = 2;
} else if (0 < iVar5) {
iVar5 = iVar5 + -1;
}
}
/*
iVar6 = 0;
iVar10 = 0x20;
pRVar3 = cmd_iter;
pRVar8 = cmd_iter;
do {
if ((pRVar8->names[0].data[0] != '\0') && (pRVar3->id[0] != 0)) {
__src = (char*)((int)cmd_iter->id + iVar10 + -0x10);
strncpy(list_node.name, __src, 0x30);
list_node.id = pRVar3->id[0];
list_node.unk_68 = 0;
list_node.unk_72 = 0;
list_node.prio = iVar5;
pRVar2 = FindThisVagStream(__src, pRVar3->id[0]);
if ((pRVar2 == (RealVagCmd*)0x0) || (pRVar2->byte4 == '\0')) {
WaitSema(EEPlayList._12_4_);
iVar3 = (VagStrListNode*)FindVagStreamInList(&list_node, (List*)EEPlayList);
if (iVar3 == (VagStrListNode*)0x0) {
iVar4 = (VagStrListNode*)InsertVagStreamInList(&list_node, (List*)EEPlayList);
strncpy(iVar4->name, list_node.name, 0x30);
iVar4->id = list_node.id;
iVar4->prio = list_node.prio;
iVar4->unk_72 = list_node.unk_72;
iVar4->unk_76 = 0;
iVar4->unk_80 = 0;
iVar4->unk_92 = 0;
iVar4->unk_68 = list_node.unk_68;
}
SignalSema(EEPlayList._12_4_);
}
}
if (iVar5 == 8) {
iVar5 = 2;
} else if (0 < iVar5) {
iVar5 = iVar5 + -1;
}
iVar10 = iVar10 + 0x30;
pRVar3 = (RPC_Play_Cmd*)&pRVar3->address;
iVar6 = iVar6 + 1;
pRVar8 = (RPC_Play_Cmd*)(pRVar8->names[0].data + 0x10);
} while (iVar6 < 4);
*/
}
}
cmd_iter = cmd_iter + 1;
}
return _cmd;
}
/*!
* Run the STR RPC handler.
*/
u32 STRThread() {
sceSifQueueData dq;
sceSifServeData serve;
CpuDisableIntr();
sceSifInitRpc(0);
sceSifSetRpcQueue(&dq, GetThreadId());
sceSifRegisterRpc(&serve, STR_RPC_ID[g_game_version], RPC_STR, &sSTRBuf, nullptr, nullptr, &dq);
CpuEnableIntr();
sceSifRpcLoop(&dq);
return 0;
}
sceSifServeData* gserve = nullptr;
u32 PLAYThread() {
sceSifQueueData dq;
sceSifServeData serve;
gserve = &serve;
CpuDisableIntr();
sceSifInitRpc(0);
sceSifSetRpcQueue(&dq, GetThreadId());
sceSifRegisterRpc(&serve, PLAY_RPC_ID[g_game_version], RPC_PLAY, sPLAYBuf, nullptr, nullptr, &dq);
CpuEnableIntr();
sceSifRpcLoop(&dq);
return 0;
}
} // namespace jak2