mirror of
https://github.com/open-goal/jak-project
synced 2026-06-23 09:29:56 -04:00
4f537d4a71
This sets up the C Kernel for Jak 3, and makes it possible to build and load code built with `goalc --jak3`. There's not too much interesting here, other than they switched to a system where symbol IDs (unique numbers less than 2^14) are generated at compile time, and those get included in the object file itself. This is kind of annoying, since it means all tools that produce a GOAL object file need to work together to assign unique symbol IDs. And since the symbol IDs can't conflict, and are only a number between 0 and 2^14, you can't just hash and hope for no collisions. We work around this by ignoring the IDs and re-assigning our own. I think this is very similar to what the C Kernel did on early builds of Jak 3 which supported loading old format level files, which didn't have the IDs included. As far as I can tell, this shouldn't cause any problems. It defeats all of their fancy tricks to save memory by not storing the symbol string, but we don't care.
806 lines
23 KiB
C++
806 lines
23 KiB
C++
#include "vag.h"
|
|
|
|
#include <cstring>
|
|
|
|
#include "common/log/log.h"
|
|
#include "common/util/Assert.h"
|
|
|
|
#include "game/overlord/jak2/iso_queue.h"
|
|
#include "game/overlord/jak2/spustreams.h"
|
|
#include "game/overlord/jak2/srpc.h"
|
|
#include "game/overlord/jak2/ssound.h"
|
|
#include "game/overlord/jak2/streamlist.h"
|
|
#include "game/sound/sdshim.h"
|
|
|
|
namespace jak2 {
|
|
VagCmd VagCmds[N_VAG_CMDS];
|
|
int StreamSRAM[N_VAG_CMDS];
|
|
int TrapSRAM[N_VAG_CMDS];
|
|
int StreamVoice[N_VAG_CMDS];
|
|
|
|
// sizes seem sketchy
|
|
// maybe pri 0 is a special 'free' priority.
|
|
VagCmdPriListEntry VagCmdsPriList[11];
|
|
int VagCmdsPriCounter[11];
|
|
int ActiveVagStreams;
|
|
|
|
void CalculateVAGVolumes(VagCmd* cmd, u32* l_out, u32* r_out);
|
|
void StopVAG(VagCmd* cmd, int /*param_2*/);
|
|
|
|
enum VolumeCategory {
|
|
DIALOGUE = 2, // VAG streams. Copied "dialogue" name from jak 1.
|
|
};
|
|
int MasterVolume[17];
|
|
|
|
void vag_init_globals() {
|
|
memset(VagCmds, 0, sizeof(VagCmds));
|
|
memset(StreamSRAM, 0, sizeof(StreamSRAM));
|
|
memset(TrapSRAM, 0, sizeof(TrapSRAM));
|
|
memset(StreamVoice, 0, sizeof(StreamVoice));
|
|
memset(VagCmdsPriList, 0, sizeof(VagCmdsPriList));
|
|
memset(VagCmdsPriCounter, 0, sizeof(VagCmdsPriCounter));
|
|
|
|
for (auto& x : MasterVolume) {
|
|
x = 0x400; // check!!!
|
|
}
|
|
ActiveVagStreams = 0;
|
|
}
|
|
|
|
void InitVagCmds() {
|
|
int cmd_idx = 0;
|
|
for (auto& cmd : VagCmds) {
|
|
for (auto& x : cmd.status_bytes) {
|
|
x = 0;
|
|
}
|
|
// puVar5 is offset 292
|
|
cmd.unk_236 = 0; // puVar5[-0xe] = 0;
|
|
cmd.unk_140 = 0; // puVar5[-0x26] = 0;
|
|
cmd.sb_paused = 1; // *(undefined*)((int)puVar5 + -0x52) = 1;
|
|
cmd.unk_196 = 0; // puVar5[-0x18] = 0;
|
|
cmd.unk_200 = 0; // puVar5[-0x17] = 0;
|
|
cmd.unk_204 = 0; // puVar5[-0x16] = 0;
|
|
cmd.unk_180 = 0; // puVar5[-0x1c] = 0;
|
|
cmd.unk_184 = 0; // puVar5[-0x1b] = 0;
|
|
cmd.unk_188 = 0; // puVar5[-0x1a] = 0;
|
|
cmd.unk_192 = 0; // puVar5[-0x19] = 0;
|
|
cmd.status_bytes[VagCmdByte::BYTE5] = 0; // *(undefined*)((int)puVar5 + -0x4f) = 0;
|
|
cmd.status_bytes[VagCmdByte::BYTE6] = 0; // *(undefined*)((int)puVar5 + -0x4e) = 0;
|
|
cmd.num_processed_chunks = 0; // puVar5[-0xd] = 0;
|
|
cmd.safe_to_change_dma_fields = 1; // puVar5[-0x3a] = 1;
|
|
cmd.xfer_size = 0; // puVar5[-0xc] = 0;
|
|
cmd.sample_rate = 0; // puVar5[-0xb] = 0;
|
|
cmd.unk_260 = 0; // puVar5[-8] = 0;
|
|
cmd.unk_264 = 0x4000; // puVar5[-7] = 0x4000;
|
|
cmd.unk_268 = 0; // puVar5[-6] = 0;
|
|
cmd.header.callback_buffer = nullptr; // puVar5[-0x42] = 0;
|
|
cmd.header.ready_for_data = 1; // puVar5[-0x43] = 1;
|
|
cmd.header.callback = NullCallback; // puVar5[-0x41] = NullCallback;
|
|
cmd.header.lse = nullptr; // puVar5[-0x40] = 0;
|
|
cmd.stereo_sibling = nullptr; // puVar5[-0x3d] = 0;
|
|
cmd.dma_iop_mem_ptr = nullptr; // puVar5[-0x3c] = 0;
|
|
cmd.dma_chan = -1; // puVar5[-0x3b] = 0xffffffff;
|
|
cmd.unk_256_pitch2 = 0; // puVar5[-9] = 0;
|
|
cmd.unk_296 = 0; // puVar5[1] = 0;
|
|
cmd.vec3.x = 0; // puVar5[2] = 0;
|
|
cmd.vec3.y = 0; // puVar5[3] = 0;
|
|
cmd.vec3.z = 0; // puVar5[4] = 0;
|
|
cmd.fo_min = 5; // puVar5[5] = 5;
|
|
cmd.fo_max = 0x1e; // puVar5[6] = 0x1e;
|
|
cmd.fo_curve = 1; // puVar5[7] = 1;
|
|
// puVar5[-0x2b] = *(undefined4*)(StreamSRAM + cmd_idx * 4);
|
|
cmd.spu_stream_dma_mem_addr = StreamSRAM[cmd_idx];
|
|
// puVar5[-0x2a] = *(undefined4*)(TrapSRAM + cmd_idx * 4);
|
|
cmd.spu_trap_mem_addr = TrapSRAM[cmd_idx];
|
|
// pRVar7 = pRVar7 + 1;
|
|
// puVar5[-0x28] = iVar6;
|
|
cmd.idx_in_cmd_arr = cmd_idx;
|
|
// iVar6 = iVar6 + 1;
|
|
cmd.file_record = nullptr; // puVar5[-0x3f] = 0;
|
|
cmd.vag_dir_entry = nullptr; // puVar5[-0x3e] = 0;
|
|
cmd.sb_playing = 0; // *(undefined*)((int)puVar5 + -0x53) = 0;
|
|
cmd.vol_multiplier = 0; // puVar5[-5] = 0;
|
|
cmd.unk_256_pitch2 = 0; // puVar5[-9] = 0;
|
|
cmd.id = 0; // puVar5[-4] = 0;
|
|
cmd.plugin_id = 0; // puVar5[-3] = 0;
|
|
cmd.sound_handler = 0; // puVar5[-0x27] = 0;
|
|
cmd.unk_176 = 0; // puVar5[-0x1d] = 0;
|
|
cmd.priority = 0; // puVar5[-2] = 0;
|
|
cmd.unk_288 = 0; // puVar5[-1] = 0;
|
|
cmd.unk_292 = 0; // *puVar5 = 0;
|
|
cmd.voice = StreamVoice[cmd_idx];
|
|
// puVar5[-0x29] = uVar2;
|
|
// puVar5 = puVar5 + 0x51;
|
|
cmd_idx++;
|
|
}
|
|
|
|
for (auto& entry : VagCmdsPriList) {
|
|
for (auto& c : entry.cmds) {
|
|
c = nullptr;
|
|
}
|
|
}
|
|
|
|
for (auto& c : VagCmdsPriCounter) {
|
|
c = 0;
|
|
}
|
|
VagCmdsPriCounter[0] = 4;
|
|
}
|
|
|
|
/*!
|
|
* Get a VagCmd from VagCmds for the given VagCmd.
|
|
*/
|
|
VagCmd* SmartAllocVagCmd(VagCmd* cmd) {
|
|
VagCmd* selected = nullptr;
|
|
|
|
// first, just try looking for any free commands in the list.
|
|
for (auto& c : VagCmds) {
|
|
if (c.id == 0) {
|
|
// free!
|
|
selected = &c;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// next, try FindNotQueuedVagCmd
|
|
if (!selected) {
|
|
selected = FindNotQueuedVagCmd();
|
|
}
|
|
|
|
// next, try some existing ones.
|
|
if (!selected) {
|
|
int our_priority = cmd->priority;
|
|
|
|
// if we have a nonzero priority, try taking over a lower priority command
|
|
if (our_priority) {
|
|
int check_priority = 0;
|
|
do {
|
|
// loop over other commands at this priority
|
|
int cmd_at_pri_idx = 0;
|
|
do {
|
|
auto* potential_cmd = VagCmdsPriList[check_priority].cmds[cmd_at_pri_idx];
|
|
if (potential_cmd) {
|
|
// this part is a bit strange... as we iterate through lower priority commands, we
|
|
// immediately take the first one with byte11 set to 0. But if this isn't 0, we keep
|
|
// looking. This means that we won't take the lowest priority free command if they have
|
|
// nonzero BYTE11's. (this would make sense if BYTE11 was some exclusive "please don't
|
|
// interrupt me" bit)
|
|
selected = potential_cmd;
|
|
if (selected->status_bytes[VagCmdByte::BYTE11] == 0) {
|
|
// exit immediately
|
|
cmd_at_pri_idx = 4;
|
|
check_priority = cmd->priority;
|
|
}
|
|
}
|
|
cmd_at_pri_idx++;
|
|
} while (cmd_at_pri_idx < 4);
|
|
check_priority++;
|
|
} while (check_priority < our_priority);
|
|
}
|
|
}
|
|
|
|
if (!selected) {
|
|
// failed.
|
|
return nullptr;
|
|
}
|
|
|
|
ActiveVagStreams = ActiveVagStreams + 1;
|
|
if (ActiveVagStreams < 2) {
|
|
WakeSpuStreamsUp();
|
|
}
|
|
return selected;
|
|
}
|
|
|
|
void TerminateVAG(VagCmd* cmd, int /*param_2*/) {
|
|
VagStrListNode vag_node;
|
|
LfoListNode lfo_node;
|
|
// undefined4 auStack32 [2];
|
|
|
|
// if (param_2 == 1) {
|
|
// CpuSuspendIntr(auStack32);
|
|
//}
|
|
|
|
auto* sibling = cmd->stereo_sibling;
|
|
strncpy(vag_node.name, cmd->name, 0x30);
|
|
vag_node.id = cmd->id;
|
|
cmd->sb_scanned = '\0';
|
|
|
|
if (cmd->status_bytes[BYTE5] != '\0') {
|
|
StopVAG(cmd, 0);
|
|
}
|
|
|
|
ReleaseMessage(&cmd->header, 0);
|
|
RemoveVagCmd(cmd, 0);
|
|
FreeVagCmd(cmd, 0);
|
|
|
|
if (sibling != nullptr) {
|
|
sibling->sb_scanned = '\0';
|
|
RemoveVagCmd(sibling, 0);
|
|
FreeVagCmd(sibling, 0);
|
|
}
|
|
|
|
if (cmd->sound_handler) {
|
|
RemoveVagStreamFromList(&vag_node, &PluginStreamsList);
|
|
lfo_node.id = cmd->id;
|
|
lfo_node.plugin_id = cmd->plugin_id;
|
|
RemoveLfoStreamFromList(&lfo_node, &LfoList);
|
|
}
|
|
// printf("termina removing %s (2)\n", vag_node.name);
|
|
|
|
RemoveVagStreamFromList(&vag_node, &EEPlayList);
|
|
// if (param_2 == 1) {
|
|
// CpuResumeIntr(auStack32[0]);
|
|
//}
|
|
}
|
|
|
|
void PauseVAG(VagCmd* cmd, int /*param_2*/) {
|
|
if (!cmd->sb_paused) {
|
|
// if (param_2 == 1) {
|
|
// CpuSuspendIntr(local_20);
|
|
// }
|
|
if (cmd->status_bytes[BYTE11] == '\0') {
|
|
auto* stereo_cmd = cmd->stereo_sibling;
|
|
if (!stereo_cmd) {
|
|
if (cmd->sb_playing != '\0') {
|
|
sceSdSetParam(SD_VP_VOLL | cmd->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | cmd->voice, 0);
|
|
}
|
|
sceSdSetParam(SD_VP_PITCH | cmd->voice, 0);
|
|
sceSdSetSwitch(SD_S_KOFF | CORE_BIT(cmd->voice), VOICE_BIT(cmd->voice));
|
|
if (cmd->status_bytes[BYTE5] == '\0') {
|
|
cmd->spu_addr_to_start_playing = 0;
|
|
} else {
|
|
cmd->spu_addr_to_start_playing = GetSpuRamAddress(cmd);
|
|
}
|
|
cmd->sb_paused = 1;
|
|
} else {
|
|
if (cmd->sb_playing != '\0') {
|
|
sceSdSetParam(SD_VP_VOLL | cmd->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | cmd->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLL | stereo_cmd->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | stereo_cmd->voice, 0);
|
|
}
|
|
sceSdSetParam(SD_VP_PITCH | stereo_cmd->voice, 0);
|
|
sceSdSetParam(SD_VP_PITCH | cmd->voice, 0);
|
|
sceSdSetSwitch(SD_S_KOFF | CORE_BIT(cmd->voice),
|
|
VOICE_BIT(cmd->voice) | VOICE_BIT(stereo_cmd->voice));
|
|
|
|
if (cmd->status_bytes[BYTE5] == '\0') {
|
|
cmd->spu_addr_to_start_playing = 0;
|
|
stereo_cmd->spu_addr_to_start_playing = 0;
|
|
} else {
|
|
u32 ram_addr = GetSpuRamAddress(cmd);
|
|
cmd->spu_addr_to_start_playing = ram_addr & 0xfffffff8;
|
|
stereo_cmd->spu_addr_to_start_playing =
|
|
((ram_addr & 0xfffffff8) - cmd->spu_stream_dma_mem_addr) +
|
|
stereo_cmd->spu_stream_dma_mem_addr;
|
|
}
|
|
cmd->sb_paused = 1;
|
|
stereo_cmd->sb_paused = 1;
|
|
}
|
|
}
|
|
// if (param_2 == 1) {
|
|
// CpuResumeIntr(local_20[0]);
|
|
//}
|
|
}
|
|
}
|
|
|
|
void UnPauseVAG(VagCmd* param_1, int /*param_2*/) {
|
|
if (param_1->sb_paused) {
|
|
// if (param_2 == 1) {
|
|
// CpuSuspendIntr(&local_30);
|
|
//}
|
|
if (param_1->status_bytes[BYTE11] == '\0') {
|
|
auto* stereo_cmd = param_1->stereo_sibling;
|
|
int pitch = CalculateVAGPitch(param_1->pitch1, param_1->unk_256_pitch2);
|
|
u32 vol_l, vol_r;
|
|
CalculateVAGVolumes(param_1, &vol_l, &vol_r);
|
|
if (!stereo_cmd) {
|
|
if (param_1->sb_playing != '\0') {
|
|
sceSdSetParam(SD_VP_PITCH | param_1->voice, pitch);
|
|
if (param_1->spu_addr_to_start_playing != 0) {
|
|
sceSdSetAddr(SD_VA_SSA | param_1->voice, param_1->spu_addr_to_start_playing);
|
|
}
|
|
sceSdSetSwitch(SD_S_KON | CORE_BIT(param_1->voice), VOICE_BIT(param_1->voice));
|
|
sceSdSetParam(SD_VP_VOLL | param_1->voice, vol_l);
|
|
sceSdSetParam(SD_VP_VOLR | param_1->voice, vol_r);
|
|
}
|
|
param_1->sb_paused = 0;
|
|
} else {
|
|
if (param_1->sb_playing != '\0') {
|
|
sceSdSetParam(SD_VP_PITCH | param_1->voice, pitch);
|
|
sceSdSetParam(SD_VP_PITCH | stereo_cmd->voice, pitch);
|
|
if (param_1->spu_addr_to_start_playing != 0) {
|
|
sceSdSetAddr(SD_VA_SSA | param_1->voice, param_1->spu_addr_to_start_playing);
|
|
sceSdSetAddr(SD_VA_SSA | stereo_cmd->voice, stereo_cmd->spu_addr_to_start_playing);
|
|
}
|
|
|
|
sceSdSetSwitch(SD_S_KON | CORE_BIT(param_1->voice),
|
|
VOICE_BIT(param_1->voice) | VOICE_BIT(stereo_cmd->voice));
|
|
sceSdSetParam(SD_VP_VOLL | param_1->voice, vol_l);
|
|
sceSdSetParam(SD_VP_VOLL | stereo_cmd->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | param_1->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | stereo_cmd->voice, vol_r);
|
|
}
|
|
param_1->sb_paused = 0;
|
|
stereo_cmd->sb_paused = 0;
|
|
}
|
|
}
|
|
// if (param_2 == 1) {
|
|
// CpuResumeIntr(local_30);
|
|
//}
|
|
}
|
|
}
|
|
|
|
void RestartVag(VagCmd* param_1, int param_2, int /*param_3*/) {
|
|
// u16 uVar1;
|
|
// int iVar2;
|
|
// RealVagCmd *stereo_sibling;
|
|
// u32 uVar4;
|
|
// int iVar5;
|
|
// undefined4 local_30;
|
|
// undefined2 local_2c [2];
|
|
// undefined2 local_28 [4];
|
|
|
|
// if (param_3 == 1) {
|
|
// CpuSuspendIntr(&local_30);
|
|
//}
|
|
u32 vol_l, vol_r;
|
|
CalculateVAGVolumes(param_1, &vol_l, &vol_r);
|
|
if (param_1->status_bytes[BYTE11] == '\0') {
|
|
auto* stereo_sibling = param_1->stereo_sibling;
|
|
int sram_offset = param_2 ? 0x2000 : 0;
|
|
|
|
int voices = VOICE_BIT(param_1->voice);
|
|
if (stereo_sibling) {
|
|
voices |= VOICE_BIT(stereo_sibling->voice);
|
|
}
|
|
|
|
sceSdSetSwitch(SD_S_KOFF | CORE_BIT(param_1->voice), voices);
|
|
|
|
sceSdSetParam(SD_VP_VOLL | param_1->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | param_1->voice, 0);
|
|
if (stereo_sibling) {
|
|
sceSdSetParam(SD_VP_VOLL | stereo_sibling->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | stereo_sibling->voice, 0);
|
|
}
|
|
|
|
sceSdSetAddr(SD_VA_SSA | param_1->voice, param_1->spu_stream_dma_mem_addr + sram_offset);
|
|
if (stereo_sibling) {
|
|
sceSdSetAddr(SD_VA_SSA | stereo_sibling->voice,
|
|
stereo_sibling->spu_stream_dma_mem_addr + sram_offset);
|
|
}
|
|
|
|
sceSdSetSwitch(SD_S_KON | CORE_BIT(param_1->voice), voices);
|
|
|
|
if (!stereo_sibling) {
|
|
sceSdSetParam(SD_VP_VOLL | param_1->voice, vol_l);
|
|
sceSdSetParam(SD_VP_VOLR | param_1->voice, vol_r);
|
|
} else {
|
|
sceSdSetParam(SD_VP_VOLL | param_1->voice, vol_l);
|
|
sceSdSetParam(SD_VP_VOLL | stereo_sibling->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | param_1->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | stereo_sibling->voice, vol_r);
|
|
}
|
|
}
|
|
// if (param_3 == 1) {
|
|
// CpuResumeIntr(local_30);
|
|
//}
|
|
}
|
|
|
|
void SetVAGVol(VagCmd* cmd, int /*param_2*/) {
|
|
VagCmd* stereo_cmd;
|
|
u32 lvol, rvol;
|
|
|
|
if (cmd == nullptr) {
|
|
return;
|
|
}
|
|
if (cmd->byte4 == '\0') {
|
|
return;
|
|
}
|
|
if (cmd->sb_paused != '\0') {
|
|
return;
|
|
}
|
|
if (cmd->byte11 != '\0') {
|
|
return;
|
|
}
|
|
|
|
if (!cmd->sound_handler) {
|
|
CalculateVAGVolumes(cmd, &lvol, &rvol);
|
|
} else {
|
|
ASSERT_NOT_REACHED();
|
|
// TODO vag 989snd plugin
|
|
// SoundHandler* hnd = cmd->sound_handler;
|
|
// u32 vol =
|
|
// 0x3fff *
|
|
// ((((cmd->vol_multiplier * MasterVolume[hnd->VolGroup]) >> 10) * hnd->Current_Vol) >> 10)
|
|
// >> 10;
|
|
// lvol = (vol * gPanTable[(cmd->unk_176 + 90) % 360].left) >> 10;
|
|
// lvol = (vol * gPanTable[(cmd->unk_176 + 90) % 360].right) >> 10;
|
|
// if (lvol >= 0x4000) {
|
|
// lvol = 0x3fff;
|
|
//}
|
|
// if (rvol >= 0x4000) {
|
|
// rvol = 0x3fff;
|
|
//}
|
|
}
|
|
|
|
// Originally used ProcBatch, buts this is easier to read.
|
|
stereo_cmd = cmd->stereo_sibling;
|
|
if (stereo_cmd) {
|
|
sceSdSetParam(SD_VP_VOLL | cmd->voice, lvol);
|
|
sceSdSetParam(SD_VP_VOLR | cmd->voice, 0);
|
|
|
|
sceSdSetParam(SD_VP_VOLL | stereo_cmd->voice, 0);
|
|
sceSdSetParam(SD_VP_VOLR | stereo_cmd->voice, rvol);
|
|
|
|
sceSdSetParam(SD_VP_PITCH | cmd->voice, CalculateVAGPitch(cmd->pitch1, cmd->unk_256_pitch2));
|
|
sceSdSetParam(SD_VP_PITCH | stereo_cmd->voice,
|
|
CalculateVAGPitch(cmd->pitch1, cmd->unk_256_pitch2));
|
|
} else {
|
|
sceSdSetParam(SD_VP_VOLL | cmd->voice, lvol);
|
|
sceSdSetParam(SD_VP_VOLR | cmd->voice, rvol);
|
|
sceSdSetParam(SD_VP_PITCH | cmd->voice, CalculateVAGPitch(cmd->pitch1, cmd->unk_256_pitch2));
|
|
}
|
|
}
|
|
|
|
void SetVagStreamsNoStart(int param_1, int /*param_2*/) {
|
|
// if (param_2 == 1) {
|
|
// CpuSuspendIntr(local_18);
|
|
//}
|
|
// pRVar2 = VagCmds;
|
|
for (auto& cmd : VagCmds) {
|
|
cmd.status_bytes[VagCmdByte::BYTE23_NOSTART] = param_1;
|
|
}
|
|
// if (param_2 == 1) {
|
|
// CpuResumeIntr(local_18[0]);
|
|
//}
|
|
}
|
|
|
|
void InitVAGCmd(VagCmd* param_1, int param_2) {
|
|
for (auto& x : param_1->status_bytes) {
|
|
x = 0;
|
|
}
|
|
param_1->unk_236 = 0;
|
|
param_1->unk_140 = 0;
|
|
param_1->sb_paused = param_2 ? 1 : 0;
|
|
param_1->unk_264 = 0x4000;
|
|
(param_1->header).callback = NullCallback;
|
|
param_1->dma_chan = -1;
|
|
param_1->fo_min = 5;
|
|
param_1->unk_196 = 0;
|
|
param_1->unk_200 = 0;
|
|
param_1->unk_204 = 0;
|
|
param_1->unk_180 = 0;
|
|
param_1->unk_184 = 0;
|
|
param_1->unk_188 = 0;
|
|
param_1->unk_192 = 0;
|
|
param_1->status_bytes[VagCmdByte::BYTE5] = '\0';
|
|
param_1->status_bytes[VagCmdByte::BYTE5] = '\0';
|
|
param_1->num_processed_chunks = 0;
|
|
param_1->safe_to_change_dma_fields = 1;
|
|
param_1->xfer_size = 0;
|
|
param_1->sample_rate = 0;
|
|
param_1->unk_260 = 0;
|
|
param_1->unk_268 = 0;
|
|
(param_1->header).callback_buffer = nullptr;
|
|
(param_1->header).ready_for_data = 1;
|
|
(param_1->header).lse = nullptr;
|
|
param_1->stereo_sibling = nullptr;
|
|
param_1->dma_iop_mem_ptr = nullptr;
|
|
param_1->unk_256_pitch2 = 0;
|
|
param_1->unk_296 = 0;
|
|
param_1->vec3.x = 0;
|
|
param_1->vec3.y = 0;
|
|
param_1->vec3.z = 0;
|
|
param_1->fo_max = 0x1e;
|
|
param_1->fo_curve = 1;
|
|
}
|
|
|
|
void SetVagStreamsNotScanned() {
|
|
for (auto& cmd : VagCmds) {
|
|
cmd.sb_scanned = 0;
|
|
}
|
|
}
|
|
|
|
void RemoveVagCmd(VagCmd* cmd, int /*param_2*/) {
|
|
// if (param_2 == 1) {
|
|
// CpuSuspendIntr(local_18);
|
|
//}
|
|
VagCmdsPriList[cmd->priority].cmds[cmd->idx_in_cmd_arr] = nullptr;
|
|
if (VagCmdsPriCounter[cmd->priority] < 1) {
|
|
printf("IOP: ======================================================================\n");
|
|
printf("IOP: vag RemoveVagCmd: VagCmdsPriCounter[%d] is zero\n", cmd->priority);
|
|
printf("IOP: ======================================================================\n");
|
|
} else {
|
|
VagCmdsPriCounter[cmd->priority]--;
|
|
}
|
|
VagCmdsPriCounter[0]++;
|
|
// if (param_2 == 1) {
|
|
// CpuResumeIntr(local_18[0]);
|
|
//}
|
|
}
|
|
|
|
VagCmd* FindFreeVagCmd() {
|
|
for (auto& cmd : VagCmds) {
|
|
if (cmd.id == 0) {
|
|
return &cmd;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
VagCmd* FindNotQueuedVagCmd() {
|
|
for (auto& cmd : VagCmds) {
|
|
if (!cmd.sb_scanned && !cmd.status_bytes[BYTE11] && !cmd.status_bytes[BYTE4]) {
|
|
return &cmd;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
VagCmd* FindWhosPlaying() {
|
|
for (auto& cmd : VagCmds) {
|
|
if (!cmd.sb_paused && cmd.sb_playing) {
|
|
return &cmd;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
VagCmd* FindVagStreamId(int id) {
|
|
if (id) {
|
|
for (auto& cmd : VagCmds) {
|
|
if (cmd.id == id) {
|
|
return &cmd;
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
VagCmd* FindVagStreamPluginId(int plugin_id) {
|
|
if (plugin_id) {
|
|
for (auto& cmd : VagCmds) {
|
|
if (cmd.plugin_id == plugin_id) {
|
|
return &cmd;
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
VagCmd* FindVagStreamName(const char* name) {
|
|
for (auto& cmd : VagCmds) {
|
|
if (strcmp(cmd.name, name) == 0) {
|
|
return &cmd;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
/*!
|
|
* Check the global VagCmds array for an existing command with this name or ID.
|
|
*/
|
|
VagCmd* FindThisVagStream(const char* name, int id) {
|
|
for (auto& cmd : VagCmds) {
|
|
if (strcmp(cmd.name, name) == 0 && cmd.id == id) {
|
|
return &cmd;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
int AnyVagRunning() {
|
|
int cnt = 0;
|
|
for (auto& cmd : VagCmds) {
|
|
if (cmd.status_bytes[BYTE4]) {
|
|
cnt++;
|
|
}
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
void FreeVagCmd(VagCmd* cmd, int /*param_2*/) {
|
|
// if (param_2 == 1) {
|
|
// CpuSuspendIntr(local_18);
|
|
//}
|
|
for (auto& x : cmd->status_bytes) {
|
|
x = 0;
|
|
}
|
|
cmd->sb_playing = '\0';
|
|
cmd->sb_paused = 1;
|
|
cmd->sb_scanned = '\0';
|
|
cmd->unk_180 = 0;
|
|
cmd->unk_184 = 0;
|
|
cmd->unk_188 = 0;
|
|
cmd->unk_192 = 0;
|
|
SetVagStreamName(cmd, 0, 0);
|
|
|
|
cmd->name[0] = '\0';
|
|
cmd->unk_264 = 0x4000;
|
|
(cmd->header).callback = NullCallback;
|
|
cmd->unk_140 = 0;
|
|
cmd->pitch1 = 0;
|
|
cmd->file_record = nullptr;
|
|
cmd->vag_dir_entry = nullptr;
|
|
cmd->unk_196 = 0;
|
|
cmd->unk_200 = 0;
|
|
cmd->unk_204 = 0;
|
|
cmd->num_processed_chunks = 0;
|
|
cmd->safe_to_change_dma_fields = 1;
|
|
cmd->xfer_size = 0;
|
|
cmd->sample_rate = 0;
|
|
cmd->unk_260 = 0;
|
|
cmd->unk_268 = 0;
|
|
cmd->vol_multiplier = 0;
|
|
cmd->unk_256_pitch2 = 0;
|
|
cmd->id = 0;
|
|
cmd->plugin_id = 0;
|
|
cmd->sound_handler = 0;
|
|
cmd->priority = 0;
|
|
cmd->unk_288 = 0;
|
|
cmd->unk_292 = 0;
|
|
cmd->unk_296 = 0;
|
|
(cmd->header).callback_buffer = nullptr;
|
|
(cmd->header).ready_for_data = 0;
|
|
(cmd->header).lse = nullptr;
|
|
cmd->dma_iop_mem_ptr = (uint8_t*)0x0;
|
|
cmd->dma_chan = -1;
|
|
cmd->unk_236 = 0;
|
|
if (0 < ActiveVagStreams) {
|
|
ActiveVagStreams--;
|
|
}
|
|
// if (param_2 == 1) {
|
|
// CpuResumeIntr(local_18[0]);
|
|
//}
|
|
}
|
|
|
|
void SetNewVagCmdPri(VagCmd* cmd, int new_pri, int /*param_3*/) {
|
|
// if (param_3 == 1) {
|
|
// CpuSuspendIntr(local_20);
|
|
//}
|
|
if (cmd) {
|
|
VagCmdsPriList[cmd->priority].cmds[cmd->idx_in_cmd_arr] = nullptr;
|
|
if (VagCmdsPriCounter[cmd->priority] < 1) {
|
|
printf("IOP: ======================================================================\n");
|
|
printf("IOP: vag SetNewVagCmdPri: VagCmdsPriCounter[%d] is zero\n", cmd->priority);
|
|
printf("IOP: ======================================================================\n");
|
|
} else {
|
|
VagCmdsPriCounter[cmd->priority]--;
|
|
}
|
|
VagCmdsPriList[new_pri].cmds[cmd->idx_in_cmd_arr] = cmd;
|
|
VagCmdsPriCounter[new_pri]++;
|
|
cmd->priority = new_pri;
|
|
}
|
|
// if (param_3 == 1) {
|
|
// CpuResumeIntr(local_20[0]);
|
|
//}
|
|
}
|
|
|
|
int HowManyBelowThisPriority(int pri, int /*disable_intr*/) {
|
|
int cnt = 0;
|
|
for (int p = 0; p < pri; p++) {
|
|
cnt += VagCmdsPriCounter[p];
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
void StopVAG(VagCmd* cmd, int /*param_2*/) {
|
|
// int *piVar1;
|
|
// int iVar2;
|
|
// u32 uVar3;
|
|
// RealVagCmd *sibling;
|
|
// undefined4 local_20 [2];
|
|
|
|
// if (param_2 == 1) {
|
|
// CpuSuspendIntr(local_20);
|
|
//}
|
|
auto& sibling = cmd->stereo_sibling;
|
|
PauseVAG(cmd, 0);
|
|
if (cmd->status_bytes[BYTE5] != '\0') {
|
|
int val = VOICE_BIT(cmd->voice);
|
|
if (sibling) {
|
|
val = val | VOICE_BIT(sibling->voice);
|
|
}
|
|
sceSdSetSwitch(SD_S_KOFF | CORE_BIT(cmd->voice), val);
|
|
}
|
|
for (auto& x : cmd->status_bytes) {
|
|
x = 0;
|
|
}
|
|
(cmd->header).callback = NullCallback;
|
|
cmd->vol_multiplier = 0;
|
|
cmd->unk_256_pitch2 = 0;
|
|
cmd->id = 0;
|
|
cmd->plugin_id = 0;
|
|
(cmd->header).ready_for_data = 0;
|
|
cmd->sound_handler = 0;
|
|
cmd->unk_140 = 0;
|
|
cmd->pitch1 = 0;
|
|
cmd->unk_180 = 0;
|
|
cmd->unk_184 = 0;
|
|
cmd->unk_188 = 0;
|
|
cmd->unk_192 = 0;
|
|
// if (param_2 == 1) {
|
|
// CpuResumeIntr(local_20[0]);
|
|
//}
|
|
}
|
|
|
|
void VAG_MarkLoopEnd(int8_t* data, int offset) {
|
|
data[offset + -0xf] = '\x03';
|
|
}
|
|
|
|
void VAG_MarkLoopStart(int8_t* param_1) {
|
|
param_1[1] = 6;
|
|
param_1[0x11] = 2;
|
|
}
|
|
|
|
int CalculateVAGPitch(int param_1, int param_2) {
|
|
if (param_2) {
|
|
if (param_2 <= 0) {
|
|
return 0x5f4 * param_1 / (0x5f4 - param_2);
|
|
} else {
|
|
return param_1 * (param_2 + 0x5f4) / 0x5f4;
|
|
}
|
|
}
|
|
|
|
return param_1;
|
|
}
|
|
|
|
void PauseVagStreams() {
|
|
for (auto& cmd : VagCmds) {
|
|
if (cmd.status_bytes[BYTE4] && !cmd.sb_paused) {
|
|
PauseVAG(&cmd, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UnPauseVagStreams() {
|
|
for (auto& cmd : VagCmds) {
|
|
if (cmd.status_bytes[BYTE4] && cmd.sb_paused) {
|
|
UnPauseVAG(&cmd, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetAllVagsVol(int param_1) {
|
|
if (param_1 >= 0) {
|
|
for (auto& VagCmd : VagCmds) {
|
|
if (VagCmd.sound_handler /* && VagCmd.sound_handler->VolGroup == param_1 */) {
|
|
ASSERT_NOT_REACHED();
|
|
SetVAGVol(&VagCmd, 1);
|
|
}
|
|
}
|
|
} else {
|
|
for (auto& VagCmd : VagCmds) {
|
|
SetVAGVol(&VagCmd, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CalculateVAGVolumes(VagCmd* cmd, u32* l_out, u32* r_out) {
|
|
if (cmd->unk_296 == 0) {
|
|
u32 vol = (u32)(cmd->vol_multiplier * MasterVolume[VolumeCategory::DIALOGUE]) >> 6;
|
|
if (vol >= 0x4000) {
|
|
vol = 0x3fff;
|
|
}
|
|
*l_out = vol;
|
|
*r_out = vol;
|
|
} else {
|
|
int fo_vol =
|
|
CalculateFalloffVolume(&cmd->vec3, (u32)(cmd->vol_multiplier * MasterVolume[2]) >> 10,
|
|
cmd->fo_curve, cmd->fo_min, cmd->fo_max);
|
|
|
|
auto* pan = &gPanTable[(630 - CalculateAngle(&cmd->vec3)) % 360];
|
|
*l_out = (pan->left * fo_vol) >> 10;
|
|
*r_out = (pan->right * fo_vol) >> 10;
|
|
|
|
if (*l_out >= 0x4000) {
|
|
*l_out = 0x3fff;
|
|
}
|
|
if (*r_out >= 0x4000) {
|
|
*r_out = 0x3fff;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace jak2
|