mirror of
https://github.com/open-goal/jak-project.git
synced 2024-12-02 11:18:14 +00:00
Overlord: Jak2 stream loading (#2096)
Untested lazy copy-paste job from jak1 Pretty confident it's the same logic with a new StrFileHeader struct.
This commit is contained in:
parent
c24cdca380
commit
dfcd203aad
@ -74,15 +74,24 @@ constexpr int STR_RPC_RESULT_DONE = 0;
|
||||
constexpr int SECTOR_TABLE_SIZE = 64;
|
||||
|
||||
// the header of a chunked file
|
||||
struct StrFileHeader {
|
||||
struct StrFileHeaderJ1 {
|
||||
u32 sectors[SECTOR_TABLE_SIZE]; // start of chunk, in sectors. including this sector.
|
||||
u32 sizes[SECTOR_TABLE_SIZE]; // size of chunk, in bytes. always an integer number of sectors
|
||||
};
|
||||
|
||||
// the first sector of a chunked file.
|
||||
struct StrFileHeaderSector : StrFileHeader {
|
||||
struct StrFileHeaderSector : StrFileHeaderJ1 {
|
||||
u32 pad[512 - 128]; // all zero
|
||||
};
|
||||
|
||||
static_assert(sizeof(StrFileHeader) == 0x200, "Sector header size");
|
||||
static_assert(sizeof(StrFileHeaderJ1) == 0x200, "Sector header size");
|
||||
static_assert(sizeof(StrFileHeaderSector) == SECTOR_SIZE, "Sector header size");
|
||||
|
||||
constexpr int SECTOR_TABLE_SIZE_J2 = 512;
|
||||
|
||||
struct StrFileHeaderJ2 {
|
||||
u32 sectors[SECTOR_TABLE_SIZE_J2]; // start of chunk, in sectors. including this sector.
|
||||
u32 sizes[SECTOR_TABLE_SIZE_J2]; // size of chunk, in bytes. always an integer number of sectors
|
||||
};
|
||||
|
||||
static_assert(sizeof(StrFileHeaderJ2) == 0x1000, "Sector header size");
|
||||
|
@ -36,18 +36,25 @@ static u32 global_vag_count = 0;
|
||||
* 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 {
|
||||
struct CacheEntryJ1 {
|
||||
// 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;
|
||||
StrFileHeaderJ1 header;
|
||||
};
|
||||
|
||||
struct CacheEntryJ2 {
|
||||
FileRecord* fr = nullptr;
|
||||
s32 countdown = 0;
|
||||
StrFileHeaderJ2 header;
|
||||
};
|
||||
|
||||
// the actual header cache.
|
||||
constexpr int STR_INDEX_CACHE_SIZE = 4;
|
||||
CacheEntry sCache[STR_INDEX_CACHE_SIZE];
|
||||
CacheEntryJ1 sCacheJ1[STR_INDEX_CACHE_SIZE];
|
||||
CacheEntryJ2 sCacheJ2[STR_INDEX_CACHE_SIZE];
|
||||
|
||||
void stream_init_globals() {
|
||||
memset(&sSTRBufJak1, 0, sizeof(RPC_Str_Cmd_Jak1));
|
||||
@ -135,11 +142,11 @@ void* RPC_STR_jak1(unsigned int fno, void* _cmd, int y) {
|
||||
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) {
|
||||
while (cache_entry < STR_INDEX_CACHE_SIZE && sCacheJ1[cache_entry].fr != file_record) {
|
||||
sCacheJ1[cache_entry].countdown--;
|
||||
if (sCacheJ1[cache_entry].countdown < oldest) {
|
||||
oldest_idx = cache_entry;
|
||||
oldest = sCache[cache_entry].countdown;
|
||||
oldest = sCacheJ1[cache_entry].countdown;
|
||||
}
|
||||
cache_entry++;
|
||||
}
|
||||
@ -147,9 +154,9 @@ void* RPC_STR_jak1(unsigned int fno, void* _cmd, int y) {
|
||||
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))) {
|
||||
sCacheJ1[oldest_idx].fr = file_record;
|
||||
sCacheJ1[oldest_idx].countdown = INT32_MAX - 1;
|
||||
if (!LoadISOFileToIOP(file_record, &sCacheJ1[oldest_idx].header, sizeof(StrFileHeaderJ1))) {
|
||||
printf("[OVERLORD STR] Failed to load chunk file header for animation %s\n", cmd->name);
|
||||
cmd->result = 1;
|
||||
return cmd;
|
||||
@ -158,14 +165,14 @@ void* RPC_STR_jak1(unsigned int fno, void* _cmd, int y) {
|
||||
|
||||
// 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])) {
|
||||
sCacheJ1[cache_entry].header.sizes[cmd->chunk_id],
|
||||
sCacheJ1[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->length = sCacheJ1[cache_entry].header.sizes[cmd->chunk_id];
|
||||
cmd->result = 0;
|
||||
}
|
||||
}
|
||||
@ -202,9 +209,55 @@ void* RPC_STR_jak2(unsigned int fno, void* _cmd, int y) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// TODO - not yet implemented
|
||||
ASSERT_MSG(false, "this branch of RPC_STR has not yet been implemented!");
|
||||
cmd->result = STR_RPC_RESULT_ERROR;
|
||||
// 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->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\n", cmd->basename);
|
||||
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 && sCacheJ2[cache_entry].fr != file_record) {
|
||||
sCacheJ2[cache_entry].countdown--;
|
||||
if (sCacheJ2[cache_entry].countdown < oldest) {
|
||||
oldest_idx = cache_entry;
|
||||
oldest = sCacheJ2[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;
|
||||
sCacheJ2[oldest_idx].fr = file_record;
|
||||
sCacheJ2[oldest_idx].countdown = INT32_MAX - 1;
|
||||
if (!LoadISOFileToIOP(file_record, &sCacheJ2[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,
|
||||
sCacheJ2[cache_entry].header.sizes[cmd->section],
|
||||
sCacheJ2[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 = sCacheJ2[cache_entry].header.sizes[cmd->section];
|
||||
cmd->result = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cmd;
|
||||
|
Loading…
Reference in New Issue
Block a user