2022-12-16 00:11:11 -08:00
|
|
|
#include "musyx/musyx_priv.h"
|
|
|
|
|
|
|
|
#include "dolphin/dsp.h"
|
|
|
|
#include "musyx/dsp_import.h"
|
|
|
|
|
|
|
|
/* Is this actually what factor 5 did? They specify 0x2000 for the dram size, but the next TU winds
|
|
|
|
* up incorrectly aligned */
|
|
|
|
static u8 dram_image[0x2008] ATTRIBUTE_ALIGN(32);
|
|
|
|
static DSPTaskInfo dsp_task;
|
|
|
|
|
|
|
|
static volatile u32 oldState = 0;
|
|
|
|
static volatile u16 hwIrqLevel = 0;
|
|
|
|
static volatile u32 salDspInitIsDone = 0;
|
|
|
|
static volatile OSTick salLastTick = 0;
|
|
|
|
static volatile u32 salLogicActive = 0;
|
|
|
|
static volatile u32 salLogicIsWaiting = 0;
|
|
|
|
static volatile u32 salDspIsDone = 0;
|
|
|
|
static void* salAIBufferBase = NULL;
|
|
|
|
static u8 salAIBufferIndex = 0;
|
|
|
|
SND_SOME_CALLBACK userCallback = NULL;
|
|
|
|
|
|
|
|
#define DMA_BUFFER_LEN 0x280
|
|
|
|
|
|
|
|
u32 salGetStartDelay();
|
|
|
|
|
|
|
|
void callUserCallback() {
|
|
|
|
if (salLogicActive) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
salLogicActive = 1;
|
|
|
|
OSEnableInterrupts();
|
|
|
|
userCallback();
|
|
|
|
OSDisableInterrupts();
|
|
|
|
salLogicActive = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void salCallback() {
|
|
|
|
salAIBufferIndex = (salAIBufferIndex + 1) % 4;
|
|
|
|
AIInitDMA((((u32)salAIBufferBase - 0x80000000) + (salAIBufferIndex * DMA_BUFFER_LEN)),
|
|
|
|
DMA_BUFFER_LEN);
|
|
|
|
salLastTick = OSGetTick();
|
|
|
|
if (salDspIsDone) {
|
|
|
|
callUserCallback();
|
|
|
|
} else {
|
|
|
|
salLogicIsWaiting = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void dspInitCallback() {
|
|
|
|
salDspIsDone = TRUE;
|
|
|
|
salDspInitIsDone = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void dspResumeCallback() {
|
|
|
|
salDspIsDone = TRUE;
|
|
|
|
if (salLogicIsWaiting) {
|
|
|
|
salLogicIsWaiting = FALSE;
|
|
|
|
if (salLogicActive == FALSE) {
|
|
|
|
salLogicActive = TRUE;
|
|
|
|
OSEnableInterrupts();
|
|
|
|
userCallback();
|
|
|
|
OSDisableInterrupts();
|
|
|
|
salLogicActive = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 salInitAi(SND_SOME_CALLBACK callback, u32 unk, u32* outFreq) {
|
|
|
|
salAIBufferBase = salMalloc(DMA_BUFFER_LEN * 4);
|
|
|
|
if (salAIBufferBase != NULL) {
|
|
|
|
memset(salAIBufferBase, 0, DMA_BUFFER_LEN * 4);
|
|
|
|
DCFlushRange(salAIBufferBase, DMA_BUFFER_LEN * 4);
|
|
|
|
salAIBufferIndex = TRUE;
|
|
|
|
salLogicIsWaiting = FALSE;
|
|
|
|
salDspIsDone = TRUE;
|
|
|
|
salLogicActive = FALSE;
|
|
|
|
userCallback = callback;
|
|
|
|
AIRegisterDMACallback(salCallback);
|
|
|
|
AIInitDMA(OSCachedToPhysical((u32)salAIBufferBase) + (salAIBufferIndex * 0x280), 0x280);
|
2023-02-18 20:27:24 -08:00
|
|
|
synthInfo.numSamples = 0x20;
|
2022-12-16 00:11:11 -08:00
|
|
|
*outFreq = 32000;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 salStartAi() { AIStartDMA(); }
|
|
|
|
|
|
|
|
u32 salExitAi() {
|
|
|
|
AIRegisterDMACallback(NULL);
|
|
|
|
AIStopDMA();
|
|
|
|
salFree(salAIBufferBase);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* salAiGetDest() {
|
|
|
|
return (void*)((u32)salAIBufferBase + (u8)((salAIBufferIndex + 2) % 4) * DMA_BUFFER_LEN);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 salInitDsp() {
|
|
|
|
dsp_task.iram_mmem_addr = (u16*)dspSlave;
|
|
|
|
dsp_task.iram_length = dspSlaveLength;
|
|
|
|
dsp_task.iram_addr = 0;
|
|
|
|
dsp_task.dram_mmem_addr = (u16*)dram_image;
|
|
|
|
dsp_task.dram_length = 0x2000;
|
|
|
|
dsp_task.dram_addr = 0;
|
|
|
|
dsp_task.dsp_init_vector = 0x10;
|
|
|
|
dsp_task.dsp_resume_vector = 0x30;
|
|
|
|
dsp_task.init_cb = dspInitCallback;
|
|
|
|
dsp_task.res_cb = dspResumeCallback;
|
|
|
|
dsp_task.done_cb = NULL;
|
|
|
|
dsp_task.req_cb = NULL;
|
|
|
|
dsp_task.priority = 0;
|
|
|
|
DSPInit();
|
|
|
|
DSPAddTask(&dsp_task);
|
|
|
|
salDspInitIsDone = FALSE;
|
|
|
|
hwEnableIrq();
|
|
|
|
while (!salDspInitIsDone)
|
|
|
|
;
|
|
|
|
hwDisableIrq();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 salExitDsp() {
|
|
|
|
DSPHalt();
|
|
|
|
while (DSPGetDMAStatus())
|
|
|
|
;
|
|
|
|
DSPReset();
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void salStartDsp(u32 cmdList) {
|
|
|
|
salDspIsDone = FALSE;
|
|
|
|
PPCSync();
|
|
|
|
// "Failed assertion ((u32)cmdList & 0x1F)==0"
|
|
|
|
DSPSendMailToDSP(dspCmdFirstSize | 0xbabe0000);
|
|
|
|
|
|
|
|
while (DSPCheckMailToDSP())
|
|
|
|
;
|
|
|
|
DSPSendMailToDSP(cmdList);
|
|
|
|
while (DSPCheckMailToDSP())
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
|
|
|
void salCtrlDsp(u32 unk) {
|
|
|
|
salBuildCommandList(unk, salGetStartDelay());
|
|
|
|
salStartDsp(dspCmdList);
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 salGetStartDelay() { return OSTicksToMicroseconds(OSGetTick() - salLastTick); }
|
|
|
|
|
|
|
|
void hwInitIrq() {
|
|
|
|
oldState = OSDisableInterrupts();
|
|
|
|
hwIrqLevel = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hwExitIrq() {}
|
|
|
|
|
|
|
|
void hwEnableIrq() {
|
|
|
|
if (--hwIrqLevel == 0) {
|
|
|
|
OSRestoreInterrupts(oldState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void hwDisableIrq() {
|
|
|
|
if ((hwIrqLevel++) == 0) {
|
|
|
|
oldState = OSDisableInterrupts();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void hwIRQEnterCritical() { OSDisableInterrupts(); }
|
|
|
|
|
|
|
|
void hwIRQLeaveCritical() { OSEnableInterrupts(); }
|