prime/src/musyx/hw_dolphin.c

176 lines
4.0 KiB
C

#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);
synthInfo.numSamples = 0x20;
*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(); }