mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
e81431bd21
Some checks are pending
Build / 🖥️ Windows (push) Waiting to run
Build / 🐧 Linux (push) Waiting to run
Build / 🍎 MacOS (push) Waiting to run
Inform Pages Repo / Generate Documentation (push) Waiting to run
Lint / 📝 Required Checks (push) Waiting to run
Lint / 📝 Optional Checks (push) Waiting to run
Lint / 📝 Formatting (push) Waiting to run
732 lines
22 KiB
C++
732 lines
22 KiB
C++
#include "iso_queue.h"
|
|
|
|
#include "common/log/log.h"
|
|
#include "common/util/Assert.h"
|
|
|
|
#include "game/overlord/jak3/basefile.h"
|
|
#include "game/overlord/jak3/dma.h"
|
|
#include "game/overlord/jak3/iso.h"
|
|
#include "game/overlord/jak3/isocommon.h"
|
|
#include "game/overlord/jak3/pagemanager.h"
|
|
#include "game/overlord/jak3/spustreams.h"
|
|
#include "game/overlord/jak3/vag.h"
|
|
#include "game/sce/iop.h"
|
|
#include "game/sound/sndshim.h"
|
|
|
|
using namespace iop;
|
|
|
|
namespace jak3 {
|
|
s32 g_nPriQueueSema = 0;
|
|
s32 g_VagCmdSema = 0;
|
|
u32 g_auStrmSRAM[6];
|
|
u32 g_auTrapSRAM[6];
|
|
PriStackEntry gPriStack[2];
|
|
extern u32 time_of_last_unknown_rate_drive_op;
|
|
u32 g_cmds_with_speed_total = 0;
|
|
bool unk_time_mode_flag = false;
|
|
ISO_Hdr* g_selected_cmd = nullptr;
|
|
bool unk_time_mflag = 0;
|
|
s32 unk_sector = 0;
|
|
u32 vag_cmd_cnt = 0;
|
|
u32 vag_cmd_used = 0;
|
|
u32 max_vag_cmd_cnt = 0;
|
|
ISO_VAGCommand vag_cmds[16];
|
|
|
|
static constexpr s32 LOOP_END = 1;
|
|
static constexpr s32 LOOP_REPEAT = 2;
|
|
static constexpr s32 LOOP_START = 4;
|
|
|
|
// Empty ADPCM block with loop flags
|
|
|
|
// clang-format off
|
|
u8 VAG_SilentLoop[0x60] = {
|
|
0x0, LOOP_START | LOOP_REPEAT, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
|
0x0, LOOP_REPEAT, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
|
0x0, LOOP_END | LOOP_REPEAT, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
|
|
};
|
|
// clang-format on
|
|
|
|
void jak3_overlord_init_globals_iso_queue() {
|
|
g_nPriQueueSema = 0;
|
|
g_VagCmdSema = 0;
|
|
for (auto& x : gPriStack) {
|
|
x = {};
|
|
}
|
|
g_cmds_with_speed_total = 0;
|
|
unk_time_mode_flag = false;
|
|
g_selected_cmd = nullptr;
|
|
unk_time_mflag = 0;
|
|
unk_sector = 0;
|
|
vag_cmd_cnt = 0;
|
|
vag_cmd_used = 0;
|
|
for (auto& x : vag_cmds) {
|
|
x = {};
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* Added function to check if there is a pending DGO load command.
|
|
* On PC, DOG loads are really the only loading time that users see. If there is a pending
|
|
* DGO load, we can modify logic to take advantage of PCs being dramatically faster than PS2 and
|
|
* get much better load times.
|
|
*/
|
|
bool DgoCmdWaiting() {
|
|
for (auto& level : gPriStack) {
|
|
for (int i = 0; i < level.count; i++) {
|
|
auto* cmd = level.cmds[i];
|
|
|
|
if (cmd && cmd->msg_type == ISO_Hdr::MsgType::DGO_LOAD) {
|
|
if (cmd->m_pBaseFile) {
|
|
auto* file = cmd->m_pBaseFile;
|
|
if (file->m_Buffer.m_nDataLength) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void InitBuffers() {
|
|
SemaParam sema_param;
|
|
sema_param.max_count = 1;
|
|
sema_param.init_count = 1;
|
|
sema_param.attr = 0;
|
|
sema_param.option = 0;
|
|
|
|
g_nPriQueueSema = CreateSema(&sema_param);
|
|
ASSERT(g_nPriQueueSema >= 0);
|
|
get_page_manager()->Initialize();
|
|
|
|
g_auStrmSRAM[0] = 0x5040;
|
|
g_auTrapSRAM[0] = 0x9040;
|
|
snd_SRAMMarkUsed(0x5040, 0x4040);
|
|
g_auStrmSRAM[1] = 0x9080;
|
|
g_auTrapSRAM[1] = 0xd080;
|
|
snd_SRAMMarkUsed(0x9080, 0x4040);
|
|
g_auStrmSRAM[2] = 0xd0c0;
|
|
g_auTrapSRAM[2] = 0x110c0;
|
|
snd_SRAMMarkUsed(0xd0c0, 0x4040);
|
|
g_auStrmSRAM[3] = 0x11100;
|
|
g_auTrapSRAM[3] = 0x15100;
|
|
snd_SRAMMarkUsed(0x11100, 0x4040);
|
|
g_auStrmSRAM[4] = 0x15140; // 86384 - 48
|
|
g_auTrapSRAM[4] = 0x19140;
|
|
snd_SRAMMarkUsed(0x15140, 0x4040);
|
|
g_auStrmSRAM[5] = 0x019180;
|
|
g_auTrapSRAM[5] = 0x001d180;
|
|
snd_SRAMMarkUsed(0x19180, 0x4040);
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
if (!DMA_SendToSPUAndSync(VAG_SilentLoop, 0x30, g_auTrapSRAM[i], nullptr, nullptr)) {
|
|
DelayThread(1000);
|
|
ASSERT_NOT_REACHED();
|
|
break;
|
|
}
|
|
}
|
|
|
|
sema_param.max_count = 1;
|
|
sema_param.attr = 1;
|
|
sema_param.init_count = 1;
|
|
sema_param.option = 0;
|
|
g_VagCmdSema = CreateSema(&sema_param);
|
|
ASSERT(g_VagCmdSema >= 0);
|
|
}
|
|
|
|
int QueueMessage(ISO_Hdr* msg, int pri) {
|
|
msg->status = EIsoStatus::OK_2;
|
|
msg->priority = pri;
|
|
WaitSema(g_nPriQueueSema);
|
|
int queue_idx = (pri == 5) ? 1 : 0;
|
|
bool ok = gPriStack[queue_idx].count != 8;
|
|
if (ok) {
|
|
gPriStack[queue_idx].cmds[gPriStack[queue_idx].count] = msg;
|
|
gPriStack[queue_idx].count++;
|
|
SignalSema(g_nPriQueueSema);
|
|
} else {
|
|
msg->status = EIsoStatus::FAILED_TO_QUEUE_4;
|
|
SignalSema(g_nPriQueueSema);
|
|
ReturnMessage(msg);
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
int UnqueueMessage(ISO_Hdr* msg) {
|
|
WaitSema(g_nPriQueueSema);
|
|
int iVar5 = 0;
|
|
PriStackEntry* stack = gPriStack;
|
|
do {
|
|
int iVar4 = 0;
|
|
ISO_Hdr** cmd = stack->cmds;
|
|
if (0 < stack->count) {
|
|
do {
|
|
if (*cmd == msg)
|
|
break;
|
|
iVar4 = iVar4 + 1;
|
|
cmd++;
|
|
} while (iVar4 < stack->count);
|
|
}
|
|
iVar5 = iVar5 + 1;
|
|
if (iVar4 < stack->count) {
|
|
stack->count = stack->count + -1;
|
|
if (iVar4 < stack->count) {
|
|
ISO_Hdr** ppIVar3 = stack->cmds + iVar4;
|
|
do {
|
|
iVar4 = iVar4 + 1;
|
|
*ppIVar3 = ppIVar3[1];
|
|
ppIVar3 = ppIVar3 + 1;
|
|
} while (iVar4 < stack->count);
|
|
}
|
|
return SignalSema(g_nPriQueueSema);
|
|
}
|
|
stack = stack + 1;
|
|
if (1 < iVar5) {
|
|
return SignalSema(g_nPriQueueSema);
|
|
}
|
|
} while (true);
|
|
}
|
|
|
|
/*!
|
|
* Select which command to read for next
|
|
* This function considers things like seeking time, reading rates of streamed files,
|
|
* and buffer sizing. To be entirely honest, I don't understand it almost at all, and it's not
|
|
* clear that it works as expected. It seems to work good enough, and no commands get entirely
|
|
* starved of data while there are multiple streams.
|
|
*/
|
|
ISO_Hdr* GetMessage() {
|
|
// bool been_a_while;
|
|
// bool bVar2;
|
|
// int now;
|
|
// int iVar3;
|
|
// int iVar4;
|
|
// CISOCDFile *file;
|
|
// CISOCDFile *pCVar5;
|
|
// int iVar6;
|
|
// CPageList *plist;
|
|
// uint uVar7;
|
|
// int iVar8;
|
|
// int iVar9;
|
|
// PriStack *local_t2_216;
|
|
// PriStack *pri_level;
|
|
// CISOCDFile *tfile4;
|
|
// code *pcVar10;
|
|
// CISOCDFile *tfile2;
|
|
// CISOCDFile *tfile3;
|
|
// uint uVar11;
|
|
// ISO_VAGCommand *cmd;
|
|
// int idx_on_level;
|
|
// ISO_VAGCommand **ppIVar12;
|
|
// int iVar13;
|
|
// CBaseFile *tfile;
|
|
// int cmds_total;
|
|
// int iVar14;
|
|
// uint uVar15;
|
|
ISO_Hdr* cmds_array[16];
|
|
u32 read_rates_array[16];
|
|
int num_pages_array[16];
|
|
int unstepped_pages_array[16];
|
|
int remaining_pages_array[16];
|
|
// uint its_been_a_while;
|
|
// int pages_total;
|
|
// int read_rate_total;
|
|
// int min_nospeed_pages_total;
|
|
// int max_pages_total;
|
|
// int min_speed_pages_total;
|
|
// ISO_VAGCommand *selected_cmd;
|
|
// int cmds_with_speed_total;
|
|
// uint cmd2_read_rate;
|
|
// int selected_cmd_rem_sectors;
|
|
// int pri_level_idx;
|
|
|
|
// simple logic to select which command to use next.
|
|
|
|
u32 now = GetSystemTimeLow();
|
|
|
|
bool been_a_while = false;
|
|
if (unk_time_mode_flag == 0) {
|
|
been_a_while = 0x384000 < (now - time_of_last_unknown_rate_drive_op);
|
|
} else {
|
|
unk_time_mode_flag = 0;
|
|
time_of_last_unknown_rate_drive_op = now;
|
|
}
|
|
|
|
s32 cmds_total = 0;
|
|
get_page_manager()->GarbageCollect();
|
|
s32 pages_total = 0;
|
|
s32 read_rate_total = 0;
|
|
s32 min_nospeed_pages_total = 0;
|
|
s32 max_pages_total = 0;
|
|
s32 min_speed_pages_total = 0;
|
|
LAB_000080e4:
|
|
s32 iVar9 = g_cmds_with_speed_total * 400 + 0x2ee;
|
|
s32 iVar13 = 0x7fffffff;
|
|
ISO_Hdr* selected_cmd = nullptr;
|
|
s32 cmds_with_speed_total = 0;
|
|
s32 cmd2_read_rate = 0;
|
|
s32 selected_cmd_rem_sectors = -1;
|
|
s32 pri_level_idx = 1;
|
|
PriStackEntry* pri_level = gPriStack + 1;
|
|
s32 iVar8 = iVar13;
|
|
|
|
// loop over priority levels
|
|
do {
|
|
s32 idx_on_level = pri_level->count + -1;
|
|
|
|
// if any exist on this level
|
|
if (-1 < idx_on_level) {
|
|
ISO_Hdr** ppIVar12 = pri_level->cmds + idx_on_level;
|
|
// iVar14 = cmds_total << 2;
|
|
// loop over commands on this level
|
|
do {
|
|
ISO_Hdr* cmd = *ppIVar12;
|
|
CBaseFile* file = nullptr;
|
|
// iVar4 = iVar14;
|
|
|
|
// basic check if this command is even valid:
|
|
if (cmd && (file = cmd->m_pBaseFile, file) && cmd->status == EIsoStatus::OK_2 &&
|
|
cmd->active_a != 0) {
|
|
u32 read_rate = file->m_ReadRate;
|
|
read_rate_total = read_rate_total + read_rate; // maybe this is an inverse rate...
|
|
|
|
// build up arrays of info for each command
|
|
read_rates_array[cmds_total] = read_rate;
|
|
cmds_array[cmds_total] = cmd;
|
|
|
|
if ((int)read_rate < 1) {
|
|
min_nospeed_pages_total = min_nospeed_pages_total + file->m_Buffer.m_nMinNumPages;
|
|
max_pages_total = max_pages_total + file->m_Buffer.m_nMaxNumPages;
|
|
} else {
|
|
min_speed_pages_total = min_speed_pages_total + file->m_Buffer.m_nMinNumPages;
|
|
cmds_with_speed_total = cmds_with_speed_total + 1;
|
|
}
|
|
|
|
CPageList* plist = file->m_Buffer.m_pPageList;
|
|
|
|
s32 npages = 0;
|
|
if (plist != (CPageList*)0x0) {
|
|
npages = plist->m_nNumPages;
|
|
}
|
|
pages_total = pages_total + npages;
|
|
num_pages_array[cmds_total] = npages;
|
|
|
|
s32 n_untepped_pages = 0;
|
|
if (plist != (CPageList*)0x0) {
|
|
n_untepped_pages = plist->m_nNumUnsteppedPages;
|
|
}
|
|
unstepped_pages_array[cmds_total] = n_untepped_pages;
|
|
|
|
s32 n_remaining_pages = 4;
|
|
if (cmd->callback != RunDGOStateMachine) {
|
|
n_remaining_pages = n_untepped_pages + file->m_LengthPages - file->m_PageOffset;
|
|
// lg::warn("remaining pages is {} = {} + {} - {}", n_remaining_pages, n_untepped_pages,
|
|
// file->m_LengthPages, file->m_PageOffset);
|
|
}
|
|
remaining_pages_array[cmds_total] = n_remaining_pages;
|
|
|
|
if (remaining_pages_array[cmds_total] < 1) {
|
|
remaining_pages_array[cmds_total] = 1;
|
|
}
|
|
|
|
// careful, this increments in a weird spot.
|
|
// I use cmds_total - 1 below...
|
|
int old_cmds_total = cmds_total;
|
|
cmds_total = cmds_total + 1;
|
|
|
|
// iVar4 = iVar14 + 4;
|
|
|
|
// next, we'll determine a desired page cutoff and discard commands where
|
|
// we have enough pages.
|
|
if (read_rate && plist) {
|
|
// 3/4 * mNumPages, this is if our allocated buffer is 75% full.
|
|
s32 desired_pages = (int)(file->m_nNumPages * 0x30) >> 6;
|
|
|
|
// but, we want at least min pages
|
|
if (desired_pages < file->m_Buffer.m_nMinNumPages) {
|
|
desired_pages = file->m_Buffer.m_nMinNumPages;
|
|
}
|
|
|
|
// and we want at least 2
|
|
if (desired_pages < 2) {
|
|
desired_pages = 2;
|
|
}
|
|
|
|
// but, we never want more pages than we plan to eventually read.
|
|
if (remaining_pages_array[old_cmds_total] < desired_pages) {
|
|
desired_pages = remaining_pages_array[old_cmds_total];
|
|
}
|
|
|
|
// if we have that many, we can just forget the command - no point in filling it now.
|
|
if (desired_pages <= unstepped_pages_array[old_cmds_total])
|
|
goto LAB_00008420;
|
|
}
|
|
|
|
s32 iVar14 = iVar9;
|
|
if ((0 < (int)read_rate) &&
|
|
(iVar14 = (int)(file->m_Buffer.m_nDataLength * 1000) / (int)read_rate,
|
|
read_rate == 0)) {
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
|
|
s32 pri = cmd->priority;
|
|
|
|
// really not sure what this is...
|
|
if (been_a_while) {
|
|
if ((read_rate == 0) || (iVar14 < 0x2ee)) {
|
|
been_a_while = false;
|
|
goto LAB_000080e4;
|
|
}
|
|
|
|
// if this isn't the command we said last time.
|
|
if (g_selected_cmd != cmd) {
|
|
s32 current_sector = file->GetSector();
|
|
current_sector = current_sector - unk_sector;
|
|
bool sector_ok = false;
|
|
if (current_sector < 0) {
|
|
current_sector = -current_sector;
|
|
if (unk_time_mflag != 0) {
|
|
LAB_000083ac:
|
|
current_sector = current_sector + 10000000;
|
|
}
|
|
sector_ok = current_sector < iVar13;
|
|
} else {
|
|
sector_ok = current_sector < iVar13;
|
|
if ((0 < current_sector) && (unk_time_mflag == 0))
|
|
goto LAB_000083ac;
|
|
}
|
|
if (sector_ok) {
|
|
iVar13 = current_sector;
|
|
iVar8 = iVar14;
|
|
selected_cmd = cmd;
|
|
cmd2_read_rate = read_rate;
|
|
}
|
|
}
|
|
} else {
|
|
// normal selection logic???
|
|
if ((((iVar14 == iVar8) && (selected_cmd_rem_sectors < pri)) || (iVar14 < iVar8)) &&
|
|
(iVar14 <= iVar9)) {
|
|
iVar8 = iVar14;
|
|
selected_cmd = cmd;
|
|
cmd2_read_rate = read_rate;
|
|
selected_cmd_rem_sectors = pri;
|
|
}
|
|
}
|
|
}
|
|
LAB_00008420:
|
|
idx_on_level = idx_on_level + -1;
|
|
/* WARNING: ptrarith problems */
|
|
ppIVar12 = ppIVar12 + -1;
|
|
// iVar14 = iVar4;
|
|
} while (-1 < idx_on_level);
|
|
}
|
|
pri_level--;
|
|
pri_level_idx = pri_level_idx + -1;
|
|
} while (-1 < pri_level_idx);
|
|
|
|
if (selected_cmd) {
|
|
if (cmd2_read_rate == 0) {
|
|
unk_time_mode_flag = 1;
|
|
time_of_last_unknown_rate_drive_op = now;
|
|
}
|
|
iVar13 = unk_sector;
|
|
if (selected_cmd->m_pBaseFile) {
|
|
iVar13 = selected_cmd->m_pBaseFile->GetSector();
|
|
}
|
|
if (unk_sector < iVar13) {
|
|
unk_time_mflag = 1;
|
|
unk_sector = iVar13;
|
|
} else {
|
|
been_a_while = iVar13 != unk_sector;
|
|
unk_sector = iVar13;
|
|
if (been_a_while) {
|
|
unk_time_mflag = 0;
|
|
unk_sector = iVar13;
|
|
}
|
|
}
|
|
}
|
|
min_speed_pages_total = min_speed_pages_total + min_nospeed_pages_total;
|
|
g_cmds_with_speed_total = cmds_with_speed_total;
|
|
g_selected_cmd = selected_cmd;
|
|
pages_total = get_page_manager()->m_CCache.m_nNumFreePages + pages_total;
|
|
if ((0 < min_speed_pages_total) && (0 < pages_total)) {
|
|
if (min_speed_pages_total == 0) {
|
|
// trap(0x1c00);
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
min_speed_pages_total = (min_nospeed_pages_total * pages_total) / min_speed_pages_total;
|
|
if (min_speed_pages_total < min_nospeed_pages_total) {
|
|
min_speed_pages_total = min_nospeed_pages_total;
|
|
}
|
|
if (max_pages_total < min_speed_pages_total) {
|
|
min_speed_pages_total = max_pages_total;
|
|
}
|
|
pages_total = pages_total - min_speed_pages_total;
|
|
iVar9 = 0;
|
|
iVar13 = min_speed_pages_total;
|
|
iVar8 = pages_total;
|
|
if (0 < cmds_total) {
|
|
// iVar14 = 0;
|
|
iVar13 = min_speed_pages_total;
|
|
iVar8 = pages_total;
|
|
do {
|
|
CBaseFile* tfile = cmds_array[iVar9]->m_pBaseFile;
|
|
if (read_rates_array[iVar9] < 1) {
|
|
s32 uVar11 = (tfile->m_Buffer).m_nMaxNumPages;
|
|
if (max_pages_total == 0) {
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
s32 uVar15 = (tfile->m_Buffer).m_nMinNumPages;
|
|
s32 uVar7 = (int)(uVar11 * min_speed_pages_total) / max_pages_total;
|
|
if ((int)uVar7 < (int)uVar15) {
|
|
uVar7 = uVar15;
|
|
}
|
|
|
|
tfile->m_nNumPages = uVar7;
|
|
if ((int)uVar11 < (int)uVar7) {
|
|
uVar7 = uVar11;
|
|
}
|
|
tfile->m_nNumPages = uVar7;
|
|
if (remaining_pages_array[iVar9] < (int)uVar7) {
|
|
uVar7 = remaining_pages_array[iVar9];
|
|
}
|
|
tfile->m_nNumPages = uVar7;
|
|
// lg::warn("num pages mod {}", uVar7);
|
|
iVar13 = iVar13 - uVar7;
|
|
} else {
|
|
s32 uVar11 = (tfile->m_Buffer).m_nMinNumPages;
|
|
s32 uVar7 = (tfile->m_Buffer).m_nMaxNumPages;
|
|
// lg::warn("taking else case: {} {} {}", uVar11, uVar7, tfile->m_nNumPages);
|
|
|
|
s32 uVar15 = -1;
|
|
if (read_rate_total == 0) {
|
|
LAB_000085e4:
|
|
// lg::warn("going to min! (rrt is {})", read_rate_total);
|
|
uVar15 = uVar11;
|
|
} else {
|
|
if (read_rate_total == 0) {
|
|
ASSERT_NOT_REACHED();
|
|
}
|
|
uVar15 = (read_rates_array[iVar9] * pages_total) / read_rate_total;
|
|
// lg::warn("read rate math is {}", uVar15);
|
|
if ((int)uVar15 < (int)uVar11)
|
|
goto LAB_000085e4;
|
|
}
|
|
|
|
// lg::warn("vals {} {}", uVar7, uVar15);
|
|
if ((int)uVar7 < (int)uVar15) {
|
|
uVar15 = uVar7;
|
|
}
|
|
// lg::warn("vals 2 {} {}", remaining_pages_array[iVar9], uVar15);
|
|
if (remaining_pages_array[iVar9] < (int)uVar15) {
|
|
uVar15 = remaining_pages_array[iVar9];
|
|
}
|
|
iVar8 = iVar8 - uVar15;
|
|
tfile->m_nNumPages = uVar15;
|
|
// lg::warn("num pages mod 2 {}", uVar15);
|
|
}
|
|
iVar9 = iVar9 + 1;
|
|
// iVar14 = iVar9 * 4;
|
|
} while (iVar9 < cmds_total);
|
|
}
|
|
while (0 < iVar13) {
|
|
iVar9 = 0;
|
|
s32 iVar14 = iVar13;
|
|
if (0 < cmds_total) {
|
|
s32 iVar4 = 0;
|
|
iVar14 = iVar13;
|
|
while (0 < iVar14) {
|
|
CBaseFile* tfile2 = cmds_array[iVar4 / 4]->m_pBaseFile;
|
|
iVar9 = iVar9 + 1;
|
|
s32 uVar11;
|
|
if (read_rates_array[iVar4 / 4] == 0 &&
|
|
(uVar11 = tfile2->m_nNumPages, (int)uVar11 < remaining_pages_array[iVar4 / 4]) &&
|
|
((int)uVar11 < tfile2->m_Buffer.m_nMaxNumPages)) {
|
|
tfile2->m_nNumPages = uVar11 + 1;
|
|
iVar14 = iVar14 + -1;
|
|
}
|
|
if (cmds_total <= iVar9)
|
|
break;
|
|
iVar4 = iVar9 * 4;
|
|
}
|
|
}
|
|
been_a_while = iVar13 == iVar14;
|
|
iVar13 = iVar14;
|
|
if (been_a_while) {
|
|
iVar8 = iVar8 + iVar14;
|
|
iVar13 = 0;
|
|
}
|
|
}
|
|
while (0 < iVar8) {
|
|
iVar13 = 0;
|
|
iVar9 = iVar8;
|
|
if (0 < cmds_total) {
|
|
s32 iVar14 = 0;
|
|
iVar9 = iVar8;
|
|
while (0 < iVar9) {
|
|
CBaseFile* tfile4 = cmds_array[iVar14 / 4]->m_pBaseFile;
|
|
iVar13 = iVar13 + 1;
|
|
s32 uVar11;
|
|
if (((0 < read_rates_array[iVar14 / 4]) &&
|
|
(uVar11 = tfile4->m_nNumPages, (int)uVar11 < remaining_pages_array[iVar14 / 4])) &&
|
|
((int)uVar11 < tfile4->m_Buffer.m_nMaxNumPages)) {
|
|
tfile4->m_nNumPages = uVar11 + 1;
|
|
iVar9 = iVar9 + -1;
|
|
}
|
|
if (cmds_total <= iVar13)
|
|
break;
|
|
iVar14 = iVar13 * 4;
|
|
}
|
|
}
|
|
been_a_while = iVar8 == iVar9;
|
|
iVar8 = iVar9;
|
|
if (been_a_while) {
|
|
iVar8 = 0;
|
|
}
|
|
}
|
|
iVar13 = 0;
|
|
if (0 < cmds_total) {
|
|
iVar8 = 0;
|
|
do {
|
|
CBaseFile* tfile3 = cmds_array[iVar8 / 4]->m_pBaseFile;
|
|
|
|
iVar13 = iVar13 + 1;
|
|
s32 uVar11 = tfile3->m_nNumPages;
|
|
// lg::warn("mystery values: {} - {} = {} (from {})", num_pages_array[iVar8 / 4],
|
|
// uVar11,
|
|
// num_pages_array[iVar8 / 4] - uVar11,
|
|
// cmds_array[iVar8 / 4]->m_pBaseFile->m_FileDef->name.data);
|
|
if (((int)uVar11 < num_pages_array[iVar8 / 4]) &&
|
|
(iVar8 = tfile3->RecoverPages(num_pages_array[iVar8 / 4] - uVar11), 0 < iVar8)) {
|
|
get_page_manager()->GarbageCollectPageList(tfile3->m_Buffer.m_pPageList);
|
|
}
|
|
iVar8 = iVar13 * 4;
|
|
} while (iVar13 < cmds_total);
|
|
}
|
|
}
|
|
return selected_cmd;
|
|
}
|
|
|
|
int ProcessMessageData(ISO_Hdr* tgt_msg) {
|
|
EIsoStatus stat;
|
|
s32 ret = 1;
|
|
LAB_000088a4:
|
|
s32 num_remaining = gPriStack[0].count + -1;
|
|
if (num_remaining < 0) {
|
|
return ret;
|
|
}
|
|
auto* cmd_array = gPriStack[0].cmds + num_remaining;
|
|
ISO_Hdr* cmd = nullptr;
|
|
do {
|
|
EIsoStatus (*cb)(ISO_Hdr*) = nullptr;
|
|
cmd = *cmd_array;
|
|
if (cmd && cmd->active_a) {
|
|
stat = cmd->status;
|
|
if (stat == EIsoStatus::OK_2) {
|
|
auto* file = cmd->m_pBaseFile;
|
|
auto* buffer = &file->m_Buffer;
|
|
if (!file) {
|
|
buffer = nullptr;
|
|
}
|
|
if ((buffer && (buffer->m_eBufferType != CBuffer::BufferType::EBT_FREE)) &&
|
|
(cb = cmd->callback, cb != ProcessVAGData)) {
|
|
stat = (cb)(cmd);
|
|
}
|
|
}
|
|
if (stat != EIsoStatus::OK_2)
|
|
break;
|
|
cmd->status = EIsoStatus::OK_2;
|
|
}
|
|
num_remaining = num_remaining + -1;
|
|
cmd_array = cmd_array + -1;
|
|
if (num_remaining < 0) {
|
|
return ret;
|
|
}
|
|
} while (true);
|
|
if (cmd == tgt_msg) {
|
|
ret = 0;
|
|
}
|
|
ReleaseMessage(cmd);
|
|
if (stat != EIsoStatus::IDLE_1) {
|
|
cmd->status = stat;
|
|
ReturnMessage(cmd);
|
|
}
|
|
goto LAB_000088a4;
|
|
}
|
|
|
|
void ReturnMessage(ISO_Hdr* msg) {
|
|
if (msg->mbox_reply == 0) {
|
|
if (msg->thread_to_wake == 0) {
|
|
FreeVAGCommand((ISO_VAGCommand*)msg);
|
|
} else {
|
|
WakeupThread(msg->thread_to_wake);
|
|
}
|
|
} else {
|
|
SendMbx(msg->mbox_reply, msg);
|
|
}
|
|
}
|
|
|
|
void ReleaseMessage(ISO_Hdr* msg) {
|
|
if (GetThreadId() == g_nISOThreadID) {
|
|
auto* file = msg->m_pBaseFile;
|
|
if (file && file->m_Status != EIsoStatus::NONE_0) {
|
|
file->Close();
|
|
}
|
|
UnqueueMessage(msg);
|
|
} else {
|
|
if (msg->msg_type != ISO_Hdr::MsgType::ABADBABE) {
|
|
set_active_a(msg, 0);
|
|
set_active_c(msg, 0);
|
|
msg->msg_type = ISO_Hdr::MsgType::ABADBABE;
|
|
SendMbx(g_nISOMbx, msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
ISO_VAGCommand* GetVAGCommand() {
|
|
int iVar1;
|
|
u32 uVar2;
|
|
u32 uVar3;
|
|
|
|
do {
|
|
while (vag_cmd_cnt == 0x1f) {
|
|
DelayThread(1000);
|
|
}
|
|
do {
|
|
iVar1 = WaitSema(g_VagCmdSema);
|
|
uVar2 = 0;
|
|
} while (iVar1 != 0);
|
|
do {
|
|
uVar3 = uVar2 + 1;
|
|
if (((vag_cmd_used >> (uVar2 & 0x1f) ^ 1U) & 1) != 0) {
|
|
vag_cmd_cnt = vag_cmd_cnt + 1;
|
|
vag_cmd_used = vag_cmd_used | 1 << (uVar2 & 0x1f);
|
|
if (max_vag_cmd_cnt < vag_cmd_cnt) {
|
|
max_vag_cmd_cnt = vag_cmd_cnt;
|
|
}
|
|
SignalSema(g_VagCmdSema);
|
|
return vag_cmds + uVar2;
|
|
}
|
|
uVar2 = uVar3;
|
|
} while ((int)uVar3 < 0x1f);
|
|
SignalSema(g_VagCmdSema);
|
|
} while (true);
|
|
}
|
|
|
|
void FreeVAGCommand(ISO_VAGCommand* param_1) {
|
|
u32 uVar1;
|
|
int iVar2;
|
|
|
|
uVar1 = param_1 - vag_cmds;
|
|
ASSERT(uVar1 < 16);
|
|
if ((uVar1 < 0x1f) && (((vag_cmd_used >> (uVar1 & 0x1f) ^ 1U) & 1) == 0)) {
|
|
do {
|
|
iVar2 = WaitSema(g_VagCmdSema);
|
|
} while (iVar2 != 0);
|
|
vag_cmd_cnt = vag_cmd_cnt - 1;
|
|
vag_cmd_used = vag_cmd_used & ~(1 << (uVar1 & 0x1f));
|
|
SignalSema(g_VagCmdSema);
|
|
}
|
|
}
|
|
|
|
} // namespace jak3
|