jak-project/game/overlord/jak3/spustreams.cpp
water111 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
[wip] Jak 3 Overlord (#3567)
2024-07-26 09:42:28 -04:00

1066 lines
32 KiB
C++

#include "spustreams.h"
#include <cstring>
#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/iso_queue.h"
#include "game/overlord/jak3/ssound.h"
#include "game/overlord/jak3/streamlist.h"
#include "game/overlord/jak3/vag.h"
#include "game/sce/iop.h"
#include "game/sound/sdshim.h"
namespace jak3 {
using namespace iop;
void jak3_overlord_init_globals_spustreams() {}
u32 bswap_read32(u32 param_1) {
return param_1 >> 0x18 | ((int)param_1 >> 8 & 0xff00U) | (param_1 & 0xff00) << 8 |
param_1 << 0x18;
}
void UpdateIsoBuffer(ISO_VAGCommand* cmd, int length) {
ASSERT(cmd);
ASSERT(cmd->m_pBaseFile);
auto* file = cmd->m_pBaseFile;
int transfer_size = cmd->xfer_size;
// advance progress in file
file->m_Buffer.m_pCurrentData += length;
// this part is weird - we've advanced the current data pointer, and now we're updating the
// size field in the buffer. But, we're potentially adjusting the size in between these.
// This means that our m_pCurrentData + m_DataLength may go off the end of the buffer??
int tranferred_already = -length;
if (transfer_size < length) {
tranferred_already = -transfer_size;
length = transfer_size;
// ASSERT_NOT_REACHED(); // for now...
}
cmd->xfer_size = transfer_size + tranferred_already;
file->m_Buffer.AddData(-length);
cmd->num_isobuffered_chunks = cmd->num_isobuffered_chunks + 1;
}
/*!
* Callback for handling VAG data. This transfers data from the Page buffers to SPU memory.
*/
EIsoStatus ProcessVAGData(ISO_Hdr* _msg) {
int spu_addr;
u32 uVar1;
int iVar2;
u32 val;
uint8_t* iop_mem;
int* piVar4;
int iVar5;
int iVar6;
ISO_VAGCommand* sibling;
u32 val2;
CBuffer* buffer;
CBaseFile* file;
int length;
// int iVar9;
// undefined4 local_28[2];
bool got_chunks;
ASSERT(_msg);
auto* msg = (ISO_VAGCommand*)_msg;
ASSERT(msg->m_pBaseFile);
file = msg->m_pBaseFile;
ASSERT(file->m_ProcessDataSemaphore != -1);
// lock the semaphore
// lg::error("--------------- proces vag!!! {}\n", msg->name);
WaitSema(file->m_ProcessDataSemaphore);
buffer = &file->m_Buffer;
if (msg->unk_gvsp_flag) {
lg::error("unk gvsp flag set in process data - no more needed??");
}
// reject if errored/stopped - in this case no more data is needed.
if (msg->unk_gvsp_flag || msg->flags.stop || msg->flags.file_disappeared ||
msg->flags.stereo_secondary) {
goto exit;
}
// reject if error.
if (msg->error != 0) {
file->m_Buffer.m_nDataLength = 0;
goto exit;
}
// reject if dma in progress - wait for that to finish first
if (msg->safe_to_modify_dma == 0) {
goto exit;
}
// determine the length we need to do an upload.
sibling = msg->stereo_sibling;
got_chunks = msg->num_isobuffered_chunks != 0;
length = 0x2000;
if (sibling) {
length = 0x4000;
}
// reject if not enough data.
if (got_chunks) {
int desired_length = length;
if (msg->xfer_size < length) {
desired_length = msg->xfer_size;
}
if ((int)file->m_Buffer.m_nDataLength < desired_length) {
lg::warn("ProcessVAG data is starved.");
goto exit;
}
}
// reject if no buffer
if (!buffer->m_pPageList || !buffer->m_pPageList->m_pCurrentActivePage)
goto exit;
// update buffer so it handles page crossing
file->CheckPageBoundary();
CPage* page;
// add ref count to the page.
if (!buffer->m_pPageList || ((page = buffer->m_pPageList->m_pCurrentActivePage,
!page || (spu_addr = page->AddRef(), spu_addr < 1))))
goto exit;
// make sure the page has the right state. I think this should never really happen, but I guess
// they are paranoid.
if (page->input_state != CPage::State::READ_DONE) {
int status = page->ReleaseRef();
ASSERT(status >= 0);
goto exit;
}
if (got_chunks) { // if we've already started streaming, all way have to do is update.
if (msg->num_isobuffered_chunks & 1u) {
int vag_transfer_size = msg->xfer_size;
if ((length < vag_transfer_size) || ((u32)msg->unk_spu_mem_offset < 0x4000)) {
VAG_MarkLoopEnd(file->m_Buffer.m_pCurrentData, 0x2000);
VAG_MarkLoopStart(file->m_Buffer.m_pCurrentData);
if (sibling) {
VAG_MarkLoopEnd(file->m_Buffer.m_pCurrentData, 0x4000);
VAG_MarkLoopStart(file->m_Buffer.m_pCurrentData + 0x2000);
}
} else {
spu_addr = 0x2010;
if ((0x1f < (int)vag_transfer_size) &&
(spu_addr = vag_transfer_size + 0x1ff0, sibling != (ISO_VAGCommand*)0x0)) {
spu_addr = ((int)(vag_transfer_size + (vag_transfer_size >> 0x1f)) >> 1) + 0x1ff0;
}
msg->unk_spu_mem_offset = spu_addr;
if (sibling != (ISO_VAGCommand*)0x0) {
sibling->unk_spu_mem_offset = msg->unk_spu_mem_offset;
}
}
// CpuSuspendIntr(local_28);
iop_mem = file->m_Buffer.m_pCurrentData;
spu_addr = msg->stream_sram + 0x2000;
} else {
int vag_transfer_size = msg->xfer_size;
if ((length < (int)vag_transfer_size) || ((u32)msg->unk_spu_mem_offset < 0x4000)) {
VAG_MarkLoopEnd(file->m_Buffer.m_pCurrentData, 0x2000);
VAG_MarkLoopStart(file->m_Buffer.m_pCurrentData);
if (sibling) {
VAG_MarkLoopEnd(file->m_Buffer.m_pCurrentData, 0x4000);
VAG_MarkLoopStart(file->m_Buffer.m_pCurrentData + 0x2000);
}
} else {
spu_addr = 0x10;
if ((0x1f < (int)vag_transfer_size) &&
(spu_addr = vag_transfer_size - 0x10, sibling != (ISO_VAGCommand*)0x0)) {
spu_addr = ((int)(vag_transfer_size + (vag_transfer_size >> 0x1f)) >> 1) + -0x10;
}
msg->unk_spu_mem_offset = spu_addr;
if (sibling != (ISO_VAGCommand*)0x0) {
sibling->unk_spu_mem_offset = msg->unk_spu_mem_offset;
}
}
// CpuSuspendIntr(local_28);
iop_mem = file->m_Buffer.m_pCurrentData;
spu_addr = msg->stream_sram;
}
spu_addr = DMA_SendToSPUAndSync(iop_mem, 0x2000, spu_addr, msg, page);
if (spu_addr != 0) {
set_active_b(msg, 0);
goto LAB_000106a0;
}
LAB_0001067c:
//
{
int status = page->ReleaseRef();
ASSERT(status >= 0);
}
} else {
// we're starting the vag file! check the header:
piVar4 = (int*)file->m_Buffer.m_pCurrentData;
if ((*piVar4 != 0x70474156) && (*piVar4 != 0x56414770)) {
lg::error("Invalid VAG data is 0x{:x}", *piVar4);
ASSERT_NOT_REACHED(); // invalid data
msg->error = 1;
file->m_Buffer.m_nDataLength = 0;
int status = page->ReleaseRef();
ASSERT(status >= 0);
goto exit;
}
// read the rate/xfer size.
val = piVar4[4];
msg->vag_file_rate = val;
val2 = piVar4[3];
msg->unk_gvsp_cntr = 0;
msg->xfer_size = val2;
if (*piVar4 == 0x70474156) {
uVar1 = bswap_read32(val);
msg->vag_file_rate = uVar1;
uVar1 = bswap_read32(val2);
msg->xfer_size = uVar1;
}
// lg::die("xfer size is {}", msg->xfer_size);
// set sibling properties
if (sibling) {
spu_addr = msg->xfer_size;
sibling->vag_file_rate = msg->vag_file_rate;
sibling->xfer_size = spu_addr;
sibling->unk_gvsp_cntr = 0;
}
spu_addr = msg->xfer_size;
if (sibling != (ISO_VAGCommand*)0x0) {
spu_addr = spu_addr >> 1;
}
uVar1 = spu_addr + 0x30;
if ((uVar1 & 0x1fff) != 0) {
uVar1 = (uVar1 - (uVar1 & 0x1fff)) + 0x2000;
}
if (sibling != (ISO_VAGCommand*)0x0) {
uVar1 = uVar1 * 2;
}
uVar1 = (uVar1 + 0x7fff) >> 0xf;
if (uVar1 == 0) {
uVar1 = 1;
}
file->m_LengthPages = uVar1;
iVar6 = msg->vag_file_rate;
iVar5 = msg->xfer_size;
spu_addr = iVar5 + 0x30;
msg->unk_spu_mem_offset = 0x4000;
msg->xfer_size = spu_addr;
uVar1 = (u32)(iVar6 << 0xc) / 48000;
msg->pitch1_file = uVar1;
msg->pitch1 = uVar1;
if (spu_addr < 0x2001) {
iVar2 = 0x10;
if (0x1f < spu_addr) {
iVar2 = iVar5 + 0x20;
}
msg->unk_spu_mem_offset = iVar2;
if (sibling != (ISO_VAGCommand*)0x0) {
sibling->xfer_size = msg->xfer_size;
sibling->unk_spu_mem_offset = msg->unk_spu_mem_offset;
sibling->vag_file_rate = iVar6;
sibling->pitch1 = msg->pitch1;
sibling->pitch1_file = msg->pitch1_file;
sibling->xfer_size = msg->xfer_size;
sibling->unk_spu_mem_offset = msg->unk_spu_mem_offset;
sibling->unk_gvsp_cntr = 0;
}
}
// CpuSuspendIntr(local_28);
spu_addr =
DMA_SendToSPUAndSync(file->m_Buffer.m_pCurrentData, 0x2000, msg->stream_sram, msg, page);
if (spu_addr == 0)
goto LAB_0001067c;
msg->position_for_ee = 0;
msg->unk_gvsp_len = 0;
if (sibling) { // added.
sibling->position_for_ee = 0;
}
LAB_000106a0:
UpdateIsoBuffer(msg, length);
}
// CpuResumeIntr(local_28[0]);
exit:
SignalSema(file->m_ProcessDataSemaphore);
return EIsoStatus::OK_2;
}
u32 GetSpuRamAddress(ISO_VAGCommand* cmd) {
return sceSdGetAddr(SD_VA_NAX | cmd->voice);
u32 voice = cmd->voice;
u32 current_addr = cmd->stream_sram;
BlockUntilVoiceSafe(voice, 0xf00);
u32 sce_addr = sceSdGetAddr(voice | 0x2240);
// lg::info("sce addr {}", sce_addr);
if ((sce_addr < current_addr) || (current_addr + 0x4040 <= sce_addr)) {
ASSERT_NOT_REACHED();
sce_addr = current_addr + 0x4040;
}
return sce_addr;
}
u32 GetVAGStreamPos(ISO_VAGCommand* cmd) {
u32 uVar1;
int iVar2;
u32 uVar3;
u32 uVar4;
ISO_VAGCommand* sibling;
u32 uVar5;
// undefined4 local_20[2];
sibling = cmd->stereo_sibling;
if (cmd->id == 0) {
cmd->position_for_ee = 0;
if (sibling == (ISO_VAGCommand*)0x0) {
return 0;
}
sibling->position_for_ee = 0;
return 0;
}
if (cmd->flags.file_disappeared != 0) {
cmd->position_for_ee = cmd->clockd;
if (sibling == (ISO_VAGCommand*)0x0) {
return 0;
}
sibling->position_for_ee = sibling->clockd;
return 0;
}
if (((cmd->flags.running == 0) || (cmd->flags.saw_chunks1 == 0)) || (cmd->flags.paused != 0)) {
cmd->position_for_ee = cmd->clocka;
if (sibling == (ISO_VAGCommand*)0x0) {
return 0;
}
sibling->position_for_ee = sibling->clocka;
return 0;
}
if (cmd->flags.stereo_secondary != 0) {
cmd->position_for_ee = cmd->clocka;
return 0;
}
// CpuSuspendIntr(local_20);
uVar1 = GetSpuRamAddress(cmd);
uVar5 = 0;
// lg::info("offset is {}, {} - {}\n", uVar1 - cmd->stream_sram, uVar1, cmd->stream_sram);
uVar1 = uVar1 - cmd->stream_sram;
if (sibling != (ISO_VAGCommand*)0x0) {
uVar5 = GetSpuRamAddress(sibling);
uVar5 = uVar5 - sibling->stream_sram;
}
// CpuResumeIntr(local_20[0]);
if (sibling != (ISO_VAGCommand*)0x0) {
if (((uVar1 < 0x4000) && (uVar5 < 0x4000)) &&
((cmd->flags.bit20 == 0 && (sibling->flags.bit20 == 0)))) {
iVar2 = (int)((uVar1 - uVar5) * 0x40000) >> 0x12;
if (iVar2 < 0) {
iVar2 = -iVar2;
}
if (4 < iVar2) {
PauseVAG(cmd);
uVar1 = cmd->current_spu_address - cmd->stream_sram;
uVar5 = sibling->current_spu_address - sibling->stream_sram;
UnPauseVAG(cmd);
}
}
if (sibling == (ISO_VAGCommand*)0x0)
goto LAB_00011010;
// CpuSuspendIntr(local_20);
// lg::info("inner values are: {} {}", uVar1, uVar5);
if ((0x4000 < uVar1) && (cmd->flags.bit20 == 0)) {
cmd->flags.bit20 = 1;
cmd->flags.bit21 = 0;
cmd->flags.bit22 = 0;
sibling->flags.bit20 = 1;
sibling->flags.bit21 = 0;
sibling->flags.bit22 = 0;
}
if (uVar5 < 0x4001) {
if (uVar1 < 0x2000) {
if (cmd->flags.bit21 == 0) {
cmd->unk_gvsp_cntr = cmd->unk_gvsp_cntr + 1;
cmd->flags.bit21 = 1;
cmd->flags.bit22 = 0;
LAB_000109b8:
cmd->flags.bit20 = 0;
}
} else {
if (cmd->flags.bit22 == 0) {
cmd->unk_gvsp_cntr = cmd->unk_gvsp_cntr + 1;
cmd->flags.bit22 = 1;
cmd->flags.bit21 = 0;
goto LAB_000109b8;
}
}
if (uVar5 < 0x2000) {
if (sibling->flags.bit21 == 0) {
sibling->unk_gvsp_cntr = sibling->unk_gvsp_cntr + 1;
sibling->flags.bit21 = 1;
sibling->flags.bit22 = 0;
LAB_00010a1c:
sibling->flags.bit20 = 0;
}
} else {
if (sibling->flags.bit22 == 0) {
sibling->unk_gvsp_cntr = sibling->unk_gvsp_cntr + 1;
sibling->flags.bit22 = 1;
sibling->flags.bit21 = 0;
goto LAB_00010a1c;
}
}
} else {
if (sibling->flags.bit20 == 0) {
cmd->flags.bit20 = 1;
cmd->flags.bit21 = 0;
cmd->flags.bit22 = 0;
sibling->flags.bit20 = 1;
sibling->flags.bit21 = 0;
sibling->flags.bit22 = 0;
}
}
// lg::info("bits are {} {} {}\n", cmd->flags.bit20, cmd->flags.bit21, cmd->flags.bit22);
// CpuResumeIntr(local_20[0]);
if (cmd->unk_gvsp_flag != 0)
goto switchD_00010a60_caseD_1;
// lg::info("switching {}", cmd->unk_gvsp_state2);
switch (cmd->unk_gvsp_state2) {
case 0:
if ((((cmd->flags.dma_complete_even_chunk_count == 0) || (cmd->flags.bit21 == 0)) ||
(sibling->flags.dma_complete_even_chunk_count == 0)) ||
(sibling->flags.bit21 == 0))
goto switchD_00010a60_caseD_1;
cmd->flags.dma_complete_even_chunk_count = 0;
cmd->unk_gvsp_state2 = 2;
sibling->flags.dma_complete_even_chunk_count = 0;
sibling->unk_gvsp_state2 = 2;
case 2:
if ((cmd->flags.dma_complete_odd_chunk_count == 0) ||
(sibling->flags.dma_complete_odd_chunk_count == 0)) {
if ((cmd->flags.bit20 != 0) || (sibling->flags.bit20 != 0)) {
uVar1 = 0x2000;
uVar5 = 0x2000;
cmd->flags.bit17 = 1;
cmd->flags.bit16 = 0;
cmd->unk_gvsp_state2 = 4;
sibling->flags.bit17 = 1;
sibling->unk_gvsp_state2 = 4;
LAB_00010efc:
sibling->flags.bit16 = 0;
}
goto switchD_00010a60_caseD_1;
}
if ((cmd->flags.bit20 == 0) && (sibling->flags.bit20 == 0)) {
BlockUntilVoiceSafe(cmd->voice, 0xf00);
BlockUntilVoiceSafe(sibling->voice, 0xf00);
// CpuSuspendIntr(local_20);
// lg::info("sax case 1 (stream)");
sceSdSetAddr(cmd->voice | 0x2140, cmd->stream_sram + 0x2000);
sceSdSetAddr(sibling->voice | 0x2140, sibling->stream_sram + 0x2000);
iVar2 = 3;
cmd->flags.bit15 = 1;
cmd->flags.bit14 = 0;
cmd->flags.bit13 = 0;
sibling->flags.bit15 = 1;
sibling->flags.bit14 = 0;
LAB_00010d78:
sibling->flags.bit13 = 0;
LAB_00010e78:
cmd->unk_gvsp_state2 = iVar2;
sibling->unk_gvsp_state2 = iVar2;
// CpuResumeIntr(local_20[0]);
goto switchD_00010a60_caseD_1;
}
LAB_00010bc4:
RestartVag(cmd, 1);
uVar1 = 0x2000;
iVar2 = 9;
uVar5 = 0x2000;
break;
default:
goto switchD_00010a60_caseD_1;
case 3:
// lg::info("case 3 bits: ({} {}) ({} {})\n", cmd->flags.bit20, cmd->flags.bit22,
// sibling->flags.bit20, sibling->flags.bit22);
if ((cmd->flags.bit20 != 0) || (sibling->flags.bit20 != 0))
goto LAB_00010bc4;
if ((cmd->flags.bit22 == 0) || (sibling->flags.bit22 == 0))
goto switchD_00010a60_caseD_1;
BlockUntilVoiceSafe(cmd->voice, 0xf00);
BlockUntilVoiceSafe(sibling->voice, 0xf00);
// CpuSuspendIntr(local_20);
// lg::info("sax case 2 (trap)");
sceSdSetAddr(cmd->voice | 0x2140, cmd->trap_sram);
sceSdSetAddr(sibling->voice | 0x2140, sibling->trap_sram);
iVar2 = 5;
cmd->flags.bit13 = 1;
cmd->flags.bit14 = 0;
cmd->flags.bit15 = 0;
sibling->flags.bit13 = 1;
sibling->flags.bit14 = 0;
sibling->flags.bit15 = 0;
cmd->flags.dma_complete_odd_chunk_count = 0;
sibling->flags.dma_complete_odd_chunk_count = 0;
goto LAB_00010e78;
case 4:
uVar1 = cmd->unk_gvsp_len;
uVar5 = sibling->unk_gvsp_len;
if ((cmd->flags.dma_complete_odd_chunk_count == 0) ||
(sibling->flags.dma_complete_odd_chunk_count == 0))
goto switchD_00010a60_caseD_1;
RestartVag(cmd, 1);
iVar2 = 9;
break;
case 5:
if ((cmd->flags.dma_complete_even_chunk_count == 0) ||
(sibling->flags.dma_complete_even_chunk_count == 0)) {
if (cmd->flags.bit20 == 0)
goto switchD_00010a60_caseD_1;
cmd->flags.bit16 = 1;
cmd->flags.bit17 = 0;
cmd->unk_gvsp_state2 = 7;
uVar1 = 0x4000;
uVar5 = 0x4000;
sibling->flags.bit16 = 1;
sibling->unk_gvsp_state2 = 7;
goto LAB_00010db0;
}
if ((cmd->flags.bit20 != 0) || (sibling->flags.bit20 != 0))
goto LAB_00010dd8;
BlockUntilVoiceSafe(cmd->voice, 0xf00);
BlockUntilVoiceSafe(sibling->voice, 0xf00);
// CpuSuspendIntr(local_20);
// lg::info("sax case 3 (stream)");
sceSdSetAddr(cmd->voice | 0x2140, cmd->stream_sram);
sceSdSetAddr(sibling->voice | 0x2140, sibling->stream_sram);
iVar2 = 6;
cmd->flags.bit14 = 1;
cmd->flags.bit15 = 0;
cmd->flags.bit13 = 0;
sibling->flags.bit14 = 1;
sibling->flags.bit15 = 0;
goto LAB_00010d78;
case 6:
if ((cmd->flags.bit20 == 0) && (sibling->flags.bit20 == 0)) {
if ((cmd->flags.bit21 == 0) || (sibling->flags.bit21 == 0))
goto switchD_00010a60_caseD_1;
BlockUntilVoiceSafe(cmd->voice, 0xf00);
BlockUntilVoiceSafe(sibling->voice, 0xf00);
// CpuSuspendIntr(local_20);
// lg::info("sax case 4 (trap)");
sceSdSetAddr(cmd->voice | 0x2140, cmd->trap_sram);
sceSdSetAddr(sibling->voice | 0x2140, sibling->trap_sram);
cmd->flags.bit13 = 1;
cmd->flags.bit14 = 0;
cmd->flags.bit15 = 0;
iVar2 = 2;
sibling->flags.bit13 = 1;
sibling->flags.bit14 = 0;
sibling->flags.bit15 = 0;
cmd->flags.dma_complete_even_chunk_count = 0;
sibling->flags.dma_complete_even_chunk_count = 0;
goto LAB_00010e78;
}
LAB_00010dd8:
RestartVag(cmd, 0);
uVar1 = 0x4000;
iVar2 = 8;
uVar5 = 0x4000;
break;
case 7:
uVar1 = cmd->unk_gvsp_len;
uVar5 = uVar1;
if ((cmd->flags.dma_complete_even_chunk_count == 0) ||
(uVar5 = uVar1, sibling->flags.dma_complete_even_chunk_count == 0))
goto switchD_00010a60_caseD_1;
RestartVag(cmd, 0);
iVar2 = 8;
uVar5 = uVar1;
break;
case 8:
if ((cmd->flags.bit21 == 0) || (sibling->flags.bit21 == 0)) {
uVar1 = cmd->unk_gvsp_len;
uVar5 = uVar1;
goto switchD_00010a60_caseD_1;
}
cmd->unk_gvsp_state2 = 6;
cmd->flags.bit16 = 0;
sibling->unk_gvsp_state2 = 6;
goto LAB_00010efc;
case 9:
if ((cmd->flags.bit22 == 0) || (sibling->flags.bit22 == 0)) {
uVar1 = cmd->unk_gvsp_len;
uVar5 = sibling->unk_gvsp_len;
goto switchD_00010a60_caseD_1;
}
cmd->unk_gvsp_state2 = 3;
cmd->flags.bit17 = 0;
sibling->unk_gvsp_state2 = 3;
LAB_00010db0:
sibling->flags.bit17 = 0;
goto switchD_00010a60_caseD_1;
}
cmd->unk_gvsp_state2 = iVar2;
sibling->unk_gvsp_state2 = iVar2;
switchD_00010a60_caseD_1:
if (cmd->unk_gvsp_cntr == 0) {
cmd->clockc = uVar1;
sibling->clockc = uVar1;
} else {
iVar2 = sibling->unk_gvsp_cntr;
cmd->clockc = uVar1 + cmd->unk_gvsp_cntr * 0x2000 + -0x2000;
sibling->clockc = uVar5 + iVar2 * 0x2000 + -0x2000;
if (0x2000 < uVar1) {
cmd->clockc = cmd->clockc + -0x2000;
}
if (0x2000 < uVar5) {
sibling->clockc = sibling->clockc + -0x2000;
}
}
uVar4 = cmd->vag_file_rate;
if (uVar4 == 0) {
uVar3 = 0;
} else {
uVar3 = (u32)(cmd->clockc * 0x1c0) / uVar4;
if (uVar4 == 0) {
ASSERT_NOT_REACHED();
}
}
iVar2 = sibling->clockc;
uVar4 = sibling->vag_file_rate;
cmd->unk_gvsp_len = uVar1;
cmd->position_for_ee = uVar3 << 2;
cmd->clocka = uVar3 << 2;
if (uVar4 == 0) {
uVar1 = 0;
} else {
uVar1 = (u32)(iVar2 * 0x1c0) / uVar4;
if (uVar4 == 0) {
ASSERT_NOT_REACHED();
}
}
sibling->unk_gvsp_len = uVar5;
sibling->position_for_ee = uVar1 << 2;
sibling->clocka = uVar1 << 2;
return 0;
}
LAB_00011010:
if (uVar1 < 0x4001) {
if (uVar1 < 0x2000) {
if (cmd->flags.bit21 == 0) {
cmd->unk_gvsp_cntr = cmd->unk_gvsp_cntr + 1;
cmd->flags.bit21 = 1;
cmd->flags.bit22 = 0;
LAB_00011098:
cmd->flags.bit20 = 0;
}
} else {
if (cmd->flags.bit22 == 0) {
cmd->unk_gvsp_cntr = cmd->unk_gvsp_cntr + 1;
cmd->flags.bit22 = 1;
cmd->flags.bit21 = 0;
goto LAB_00011098;
}
}
} else {
if (cmd->flags.bit20 == 0) {
cmd->flags.bit20 = 1;
cmd->flags.bit21 = 0;
cmd->flags.bit22 = 0;
}
}
if (cmd->unk_gvsp_flag != 0)
goto switchD_000110d0_caseD_1;
switch (cmd->unk_gvsp_state2) {
case 0:
if ((cmd->flags.dma_complete_even_chunk_count == 0) || (cmd->flags.bit21 == 0))
goto switchD_000110d0_caseD_1;
cmd->unk_gvsp_state2 = 2;
cmd->flags.dma_complete_even_chunk_count = 0;
switchD_000110d0_caseD_2:
if (cmd->flags.dma_complete_odd_chunk_count == 0) {
if (cmd->flags.bit20 != 0) {
uVar1 = 0x2000;
iVar2 = 4;
cmd->flags.bit17 = 1;
LAB_00011368:
cmd->unk_gvsp_state2 = iVar2;
cmd->flags.bit16 = 0;
}
} else {
if (cmd->flags.bit20 == 0) {
BlockUntilVoiceSafe(cmd->voice, 0xf00);
// CpuSuspendIntr(local_20);
sceSdSetAddr(cmd->voice | 0x2140, cmd->stream_sram + 0x2000);
cmd->flags.bit15 = 1;
cmd->unk_gvsp_state2 = 3;
cmd->flags.bit14 = 0;
LAB_00011284:
cmd->flags.bit13 = 0;
LAB_00011324:;
// CpuResumeIntr(local_20[0]);
} else {
LAB_00011188:
RestartVag(cmd, 1);
uVar1 = 0x2000;
LAB_0001120c:
iVar2 = 9;
LAB_00011350:
cmd->unk_gvsp_state2 = iVar2;
}
}
switchD_000110d0_caseD_1:
if (cmd->unk_gvsp_cntr == 0) {
cmd->clockc = uVar1;
} else {
iVar2 = uVar1 + cmd->unk_gvsp_cntr * 0x2000;
cmd->clockc = iVar2 + -0x2000;
if (0x2000 < uVar1) {
cmd->clockc = iVar2 + -0x4000;
}
}
uVar5 = cmd->vag_file_rate;
if (uVar5 == 0) {
uVar4 = 0;
} else {
uVar4 = (u32)(cmd->clockc * 0x1c0) / uVar5;
if (uVar5 == 0) {
// trap(0x1c00);
ASSERT_NOT_REACHED();
}
}
cmd->unk_gvsp_len = uVar1;
cmd->position_for_ee = uVar4 << 2;
cmd->clocka = uVar4 << 2;
return 0;
default:
goto switchD_000110d0_caseD_1;
case 2:
goto switchD_000110d0_caseD_2;
case 3:
if (cmd->flags.bit20 != 0)
goto LAB_00011188;
if (cmd->flags.bit22 == 0)
goto switchD_000110d0_caseD_1;
BlockUntilVoiceSafe(cmd->voice, 0xf00);
// CpuSuspendIntr(local_20);
sceSdSetAddr(cmd->voice | 0x2140, cmd->trap_sram);
cmd->flags.bit13 = 1;
cmd->unk_gvsp_state2 = 5;
cmd->flags.bit14 = 0;
cmd->flags.bit15 = 0;
cmd->flags.dma_complete_odd_chunk_count = 0;
goto LAB_00011324;
case 4:
uVar1 = cmd->unk_gvsp_len;
if (cmd->flags.dma_complete_odd_chunk_count == 0)
goto switchD_000110d0_caseD_1;
RestartVag(cmd, 1);
goto LAB_0001120c;
case 5:
if (cmd->flags.dma_complete_even_chunk_count == 0) {
if (cmd->flags.bit20 == 0)
goto switchD_000110d0_caseD_1;
uVar1 = 0x4000;
cmd->flags.bit16 = 1;
iVar2 = 7;
goto LAB_000112a0;
}
if (cmd->flags.bit20 != 0)
goto LAB_000112bc;
BlockUntilVoiceSafe(cmd->voice, 0xf00);
// CpuSuspendIntr(local_20);
sceSdSetAddr(cmd->voice | 0x2140, cmd->stream_sram);
cmd->flags.bit14 = 1;
cmd->unk_gvsp_state2 = 6;
cmd->flags.bit15 = 0;
goto LAB_00011284;
case 6:
if (cmd->flags.bit20 == 0) {
if (cmd->flags.bit21 == 0)
goto switchD_000110d0_caseD_1;
BlockUntilVoiceSafe(cmd->voice, 0xf00);
// CpuSuspendIntr(local_20);
sceSdSetAddr(cmd->voice | 0x2140, cmd->trap_sram);
cmd->flags.bit13 = 1;
cmd->unk_gvsp_state2 = 2;
cmd->flags.bit14 = 0;
cmd->flags.bit15 = 0;
cmd->flags.dma_complete_even_chunk_count = 0;
goto LAB_00011324;
}
LAB_000112bc:
RestartVag(cmd, 0);
uVar1 = 0x4000;
goto LAB_0001134c;
case 7:
uVar1 = cmd->unk_gvsp_len;
if (cmd->flags.dma_complete_even_chunk_count == 0)
goto switchD_000110d0_caseD_1;
RestartVag(cmd, 0);
LAB_0001134c:
iVar2 = 8;
goto LAB_00011350;
case 8:
iVar2 = 6;
if (cmd->flags.bit21 == 0) {
LAB_00011374:
uVar1 = cmd->unk_gvsp_len;
goto switchD_000110d0_caseD_1;
}
goto LAB_00011368;
case 9:
iVar2 = 3;
if (cmd->flags.bit22 == 0)
goto LAB_00011374;
LAB_000112a0:
cmd->unk_gvsp_state2 = iVar2;
cmd->flags.bit17 = 0;
goto switchD_000110d0_caseD_1;
}
}
u32 CheckVAGStreamProgress(ISO_VAGCommand* cmd) {
u32 uVar1;
u32 last_offset_in_stream_sram;
ISO_VAGCommand* pIVar3;
if (cmd->flags.file_disappeared == 0) {
if (cmd->flags.stereo_secondary != 0) {
return 1;
}
if (cmd->error != 0) {
return 0;
}
if ((cmd->flags.bit20 != 0) && (cmd->unk_gvsp_flag != 0)) {
return 0;
}
if (cmd->flags.saw_chunks1 == 0) {
return 1;
}
if (cmd->flags.paused != 0) {
return 1;
}
uVar1 = cmd->unk_spu_mem_offset;
pIVar3 = cmd->stereo_sibling;
last_offset_in_stream_sram = cmd->unk_gvsp_len;
if ((uVar1 < 0x4000) && (((last_offset_in_stream_sram < 0x2001 && (uVar1 < 0x2001)) ||
((0x1fff < last_offset_in_stream_sram && (0x1fff < uVar1)))))) {
if (uVar1 <= (last_offset_in_stream_sram & 0xfffffff0)) {
return 0;
}
// CpuSuspendIntr(local_18);
if ((cmd->unk_gvsp_flag == 0) &&
(last_offset_in_stream_sram < (u32)cmd->unk_spu_mem_offset)) {
BlockUntilVoiceSafe(cmd->voice, 0xf00);
sceSdSetAddr(cmd->voice | 0x2140, cmd->stream_sram + cmd->unk_spu_mem_offset);
cmd->unk_gvsp_flag = 1;
if (pIVar3 != (ISO_VAGCommand*)0x0) {
BlockUntilVoiceSafe(pIVar3->voice, 0xf00);
sceSdSetAddr(pIVar3->voice | 0x2140, pIVar3->stream_sram + cmd->unk_spu_mem_offset);
pIVar3->unk_gvsp_flag = 1;
}
}
set_active_a(cmd, 0);
set_active_b(cmd, 0);
// CpuResumeIntr(local_18[0]);
return 1;
}
if (cmd->flags.saw_chunks1 == 0) {
return 1;
}
if (cmd->active_b != 0) {
return 1;
}
if (cmd->safe_to_modify_dma == 0) {
return 1;
}
if (cmd->unk_gvsp_flag != 0) {
return 1;
}
if (last_offset_in_stream_sram < 0x2000) {
uVar1 = cmd->num_isobuffered_chunks;
} else {
uVar1 = cmd->num_isobuffered_chunks ^ 1;
}
if ((uVar1 & 1) == 0) {
return 1;
}
set_active_b(cmd, 1);
}
return 1;
}
void StopVagStream(ISO_VAGCommand* cmd) {
ISO_VAGCommand* sibling;
VagStreamData vsd;
// undefined auStack72 [36];
// int local_24;
// int local_20;
// undefined4 local_18 [2];
// CpuSuspendIntr(local_18);
sibling = cmd->stereo_sibling;
cmd->flags.saw_chunks1 = 0;
if (sibling != (ISO_VAGCommand*)0x0) {
sibling->flags.saw_chunks1 = 0;
}
if ((cmd->music_flag == 0) && (cmd->maybe_sound_handler != 0)) {
PauseVAG(cmd);
strncpy(vsd.name, cmd->name, 0x30);
vsd.id = cmd->id;
// RemoveVagStreamFromList(&vsd, &g_PluginStreamsList);
RemoveVagStreamFromList(&vsd, &g_EEPlayList);
// local_20 = cmd->plugin_id;
// local_24 = cmd->id;
// RemoveLfoStreamFromList(auStack72,&g_LfoStreamsList);
} else {
PauseVAG(cmd);
cmd->flags.stop = 1;
if (sibling != (ISO_VAGCommand*)0x0) {
PauseVAG(sibling);
cmd->flags.stop = 1;
}
}
// CpuResumeIntr(local_18[0]);
}
void ProcessStreamData() {
EIsoStatus iVar2;
CBuffer* pCVar3;
ISO_VAGCommand* msg;
int iVar5;
ISO_VAGCommand** ppIVar6;
WaitSema(g_nPriQueueSema);
if (gPriStack[1].count < 8) {
iVar5 = gPriStack[1].count + -1;
if (-1 < iVar5) {
ppIVar6 = (ISO_VAGCommand**)gPriStack[0].cmds + iVar5;
do {
msg = ppIVar6[9];
if (msg != (ISO_VAGCommand*)0x0) {
// lg::warn("process stream data for {}, {} {} {}\n", msg->name,
// (msg->status == EIsoStatus::OK_2), (msg->active_b != 0),
// (msg->active_c != 0));
if (((msg->status == EIsoStatus::OK_2) && (msg->active_b != 0)) && (msg->active_c != 0)) {
auto* file = msg->m_pBaseFile;
pCVar3 = &file->m_Buffer;
if (!file) {
pCVar3 = (CBuffer*)0x0;
}
if (((pCVar3 != (CBuffer*)0x0) &&
(pCVar3->m_eBufferType != CBuffer::BufferType::EBT_FREE)) &&
(msg->callback == ProcessVAGData)) {
iVar2 = ProcessVAGData(msg);
msg->status = iVar2;
if ((iVar2 != EIsoStatus::OK_2) && (msg->safe_to_modify_dma != 0)) {
ReleaseMessage(msg);
}
}
}
if (msg->status != EIsoStatus::OK_2) {
ReleaseMessage(msg);
}
}
iVar5 = iVar5 + -1;
ppIVar6 = ppIVar6 + -1;
} while (-1 < iVar5);
}
}
SignalSema(g_nPriQueueSema);
}
void CheckVagStreamsProgress() {
int now;
int iVar1;
bool* flags;
int iVar2;
u32* times;
ISO_VAGCommand* cmd;
if ((g_bVagCmdsInitialized != 0) && (g_bSoundEnable != 0)) {
now = GetSystemTimeLow();
times = voice_key_times;
flags = voice_key_flags;
iVar2 = 0x2f;
do {
iVar2 = iVar2 + -1;
if ((*flags != 0) && (0x17ff < (u32)(*times - now))) {
*flags = 0;
}
flags = flags + 1;
times = times + 1;
} while (-1 < iVar2);
if ((g_bRecentlyKeyedVoice != 0) && (0x17ff < (u32)(g_nTimeOfLastVoiceKey - now))) {
g_bRecentlyKeyedVoice = 0;
}
iVar2 = 5;
ProcessStreamData();
// CpuSuspendIntr(local_18);
cmd = g_aVagCmds;
do {
if (((cmd->flags.saw_chunks1 != 0) ||
((cmd->flags.running != 0 && (cmd->flags.file_disappeared != 0)))) ||
((cmd->active_b != 0 && (cmd->id != 0)))) {
iVar1 = CheckVAGStreamProgress(cmd);
if (iVar1 == 0) {
if (cmd->flags.stereo_secondary == 0) {
StopVagStream(cmd);
}
} else {
GetVAGStreamPos(cmd);
}
}
iVar2 = iVar2 + -1;
cmd = cmd + 1;
} while (-1 < iVar2);
// CpuResumeIntr(local_18[0]);
}
}
void BlockUntilAllVoicesSafe() {
int now;
int last_time;
last_time = g_nTimeOfLastVoiceKey;
if (g_bRecentlyKeyedVoice != 0) {
do {
now = GetSystemTimeLow();
} while ((u32)(now - last_time) < 0x900);
}
}
void BlockUntilVoiceSafe(int voice, u32 delay) {
int iVar1;
int iVar2;
if (voice_key_flags[voice] != 0) {
iVar2 = voice_key_times[voice];
do {
iVar1 = GetSystemTimeLow();
} while ((u32)(iVar1 - iVar2) < delay);
}
}
void MarkVoiceKeyedOnOff(int voice, u32 time) {
g_nTimeOfLastVoiceKey = time;
voice_key_times[voice] = time;
voice_key_flags[voice] = 1;
g_bRecentlyKeyedVoice = 1;
}
} // namespace jak3