Match and link hw_dolphin

This commit is contained in:
Phillip Stephens 2022-12-16 00:11:11 -08:00
parent cb8d5b0bfe
commit 54b3ccc832
7 changed files with 319 additions and 20 deletions

View File

@ -42,7 +42,9 @@
"stdlib.h": "c", "stdlib.h": "c",
"musyx_priv.h": "c", "musyx_priv.h": "c",
"gxenum.h": "c", "gxenum.h": "c",
"trees.h": "c" "trees.h": "c",
"musyx.h": "c",
"dsp_import.h": "c"
}, },
"files.autoSave": "onFocusChange", "files.autoSave": "onFocusChange",
"files.insertFinalNewline": true, "files.insertFinalNewline": true,

View File

@ -945,7 +945,7 @@ LIBS = [
["musyx/hardware", False], ["musyx/hardware", False],
"musyx/hw_aramdma", "musyx/hw_aramdma",
["musyx/dsp_import", True], ["musyx/dsp_import", True],
"musyx/hw_dolphin", ["musyx/hw_dolphin", True],
["musyx/hw_memory", True], ["musyx/hw_memory", True],
["musyx/creverb_fx", True], ["musyx/creverb_fx", True],
"musyx/creverb", "musyx/creverb",

View File

@ -7,8 +7,8 @@
extern "C" { extern "C" {
#endif #endif
char dspSlave[]; extern char dspSlave[];
short dspSlaveLength; extern ushort dspSlaveLength;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -9,7 +9,8 @@ extern "C" {
typedef struct _SynthInfo { typedef struct _SynthInfo {
u32 freq; u32 freq;
u8 unk[0x20c]; u32 _4;
u8 unk[0x208];
u8 voices; u8 voices;
u8 music; u8 music;
u8 sfx; u8 sfx;
@ -25,11 +26,47 @@ typedef struct DSPVoice {
char data2[0x70 - 0x38]; char data2[0x70 - 0x38];
u16 sampleId; u16 sampleId;
u16 _72; u16 _72;
char data3[0x90 - 0x74]; u32 _74;
u32 _78;
u32 _7c;
u32 _80;
u32 _84;
u32 _88;
u32 _8c;
u32 sampleType; u32 sampleType;
char data4[0xec - 0x94]; u32 _94;
u8 active; u32 _98;
char data5[0xf0 - 0xed]; u32 _9c;
u32 _a0;
u8 _a4;
u8 _a5;
u8 _a6;
u8 _a7;
u32 _a8;
u32 _ac;
u32 _b0;
u32 _b4;
u32 _b8;
u32 _bc;
u16 _c0;
u16 _c2;
u32 _c4;
u32 _c8;
u32 _cc;
u32 _d0;
u32 _d4;
u32 _d8;
u32 _dc;
u32 _e0;
u8 _e4;
u8 _e5;
u8 _e6;
u8 _e7;
u32 _e8;
u8 status;
u8 _ed;
u8 breakSet;
u8 _ef;
u32 itdFlags; u32 itdFlags;
} DSPVoice; } DSPVoice;
@ -39,6 +76,8 @@ typedef s32 (*SND_COMPARE)(u16*, u8*);
void dataInit(u32, s32); /* extern */ void dataInit(u32, s32); /* extern */
void dataInitStack(); /* extern */ void dataInitStack(); /* extern */
s32 hwInit(u32* rate, u8 numVoices, u8 numStudios, u32 flags); /* extern */ s32 hwInit(u32* rate, u8 numVoices, u8 numStudios, u32 flags); /* extern */
void hwEnableIrq();
void hwDisableIrq();
void s3dInit(s32); /* extern */ void s3dInit(s32); /* extern */
void seqInit(); /* extern */ void seqInit(); /* extern */
void streamInit(); /* extern */ void streamInit(); /* extern */
@ -79,6 +118,9 @@ u32 salInitDsp(u32);
u32 salInitDspCtrl(u32, u32, u16); u32 salInitDspCtrl(u32, u32, u16);
u32 salStartAi(); u32 salStartAi();
void* salMalloc(u32 len);
void salFree(void* addr);
/* Stream */ /* Stream */
typedef s32 (*SND_STREAM_UPDATE_CALLBACK)(void * buffer1, u32 len1, void * buffer2, u32 len2, void* user); typedef s32 (*SND_STREAM_UPDATE_CALLBACK)(void * buffer1, u32 len1, void * buffer2, u32 len2, void* user);
typedef struct SND_STREAM_INFO { typedef struct SND_STREAM_INFO {
@ -98,6 +140,9 @@ typedef struct SND_STREAM_INFO {
/* TODO: Figure out what `unk` is */ /* TODO: Figure out what `unk` is */
bool hwAddInput(u8 studio, void* unk); bool hwAddInput(u8 studio, void* unk);
bool hwRemoveInput(u8 studio, void* unk); bool hwRemoveInput(u8 studio, void* unk);
extern u32 dspCmdList;
extern u16 dspCmdFirstSize;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -421,7 +421,7 @@ char dspSlave[0x19E0] ATTRIBUTE_ALIGN(32) = {
0x80, 0x00, 0x02, 0x9C, 0x0C, 0xE6, 0x02, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x02, 0x9C, 0x0C, 0xE6, 0x02, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; };
short dspSlaveLength = sizeof(dspSlave); ushort dspSlaveLength = sizeof(dspSlave);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -6,24 +6,54 @@ u8 salNumVoices;
u8 salMaxStudioNum; u8 salMaxStudioNum;
SND_HOOKS salHooks; SND_HOOKS salHooks;
u8 salTimeOffset; u8 salTimeOffset;
void hwSetTimeOffset(u8 offset);
void snd_handle_irq() { void snd_handle_irq() {
s32 i; u8 i;
u8 j;
if (sndActive == 0) { if (sndActive == 0) {
return; return;
} }
streamCorrectLoops(); streamCorrectLoops();
hwIRQEnterCriticalSection(); hwIRQEnterCritical();
salCtrlDsp(salAiGetDest()); salCtrlDsp(salAiGetDest());
hwIRQLeaveCriticalSection(); hwIRQLeaveCritical();
hwIRQEnterCriticalSection(); hwIRQEnterCritical();
salHandleAuxProcessing(); salHandleAuxProcessing();
hwIRQLeaveCriticalSection(); hwIRQLeaveCritical();
hwIRQEnterCriticalSection(); hwIRQEnterCritical();
salFrame ^= 1; salFrame ^= 1;
salAuxFrame = (salAuxFrame + 1) % 3; salAuxFrame = (salAuxFrame + 1) % 3;
for (i = 0; i < salNumVoices; ++i) {
for (j = 0; j < 5; ++j) {
dspVoice[i].flags[j] = 0;
}
}
hwIRQLeaveCritical();
for (i = 0; i < 5; ++i) {
hwIRQEnterCritical();
hwSetTimeOffset(i);
seqHandle(256);
synthHandle(256);
hwIRQLeaveCritical();
}
hwIRQEnterCritical();
hwSetTimeOffset(0);
s3dHandle();
hwIRQLeaveCritical();
hwIRQEnterCritical();
streamHandle();
hwIRQLeaveCritical();
hwIRQEnterCritical();
vsSampleUpdates();
hwIRQLeaveCritical();
} }
s32 hwInit(u32* rate, u8 numVoices, u8 numStudios, u32 flags) { s32 hwInit(u32* rate, u8 numVoices, u8 numStudios, u32 flags) {
hwInitIrq(); hwInitIrq();
salFrame = 0; salFrame = 0;
@ -60,21 +90,26 @@ void hwExit() {
hwExitIrq(); hwExitIrq();
} }
void hwSetTimeOffset(s8 offset) { salTimeOffset = offset; } void hwSetTimeOffset(u8 offset) { salTimeOffset = offset; }
u8 hwGetTimeOffset() { return salTimeOffset; } u8 hwGetTimeOffset() { return salTimeOffset; }
bool hwIsActive(s32 idx) { return dspVoice[idx].active != 0; } bool hwIsActive(s32 idx) { return dspVoice[idx].status != 0; }
void hwSetMesgCallback(SND_MESSAGE_CALLBACK callback) { salMessageCallback = callback; } void hwSetMesgCallback(SND_MESSAGE_CALLBACK callback) { salMessageCallback = callback; }
void hwSetPriority(s32 idx, s32 priority) { dspVoice[idx].priority = priority; } void hwSetPriority(s32 idx, s32 priority) { dspVoice[idx].priority = priority; }
void hwInitSamplePlayback(s32 vid, u16 sampleId, u32* param_3, int param_4, u32 priority, void hwInitSamplePlayback(s32 vid, u16 sampleId, u32* param_3, u32 param_4, u32 priority,
u32 param_6, int param_7, u32 itdMode) { u32 param_6, u32 param_7, u32 itdMode) {
u8 i; u8 i;
u32 j;
u32 k;
s32 flags; s32 flags;
s32 tmpFlags; s32 tmpFlags;
u32* tmp;
u32 tmp2;
u32 tmp3;
flags = 0; flags = 0;
for (i = 0; i <= salTimeOffset; ++i) { for (i = 0; i <= salTimeOffset; ++i) {
tmpFlags = dspVoice[vid].flags[i]; tmpFlags = dspVoice[vid].flags[i];
@ -87,4 +122,46 @@ void hwInitSamplePlayback(s32 vid, u16 sampleId, u32* param_3, int param_4, u32
dspVoice[vid]._18 = param_6; dspVoice[vid]._18 = param_6;
dspVoice[vid].itdFlags = 0; dspVoice[vid].itdFlags = 0;
dspVoice[vid].sampleId = sampleId; dspVoice[vid].sampleId = sampleId;
tmp = &dspVoice[vid]._74;
for (j = 4; j > 0; --j) {
tmp[0] = param_3[0];
tmp[1] = param_3[1];
tmp += 2;
param_3 += 2;
}
if (param_4 != 0) {
dspVoice[vid]._a4 = 0;
dspVoice[vid]._b8 = 0;
dspVoice[vid]._bc = 0;
dspVoice[vid]._c0 = 0x7FFF;
dspVoice[vid]._c4 = 0;
}
dspVoice[vid]._e4 = 0xff;
dspVoice[vid]._e5 = 0xff;
dspVoice[vid]._e6 = 0xff;
dspVoice[vid]._e7 = 0xff;
if (param_7 != 0) {
hwSetSRCType(vid, 0);
hwSetPolyPhaseFilter(vid, 1);
}
hwSetITDMode(vid, itdMode);
}
void hwBreak(s32 vid) {
if (dspVoice[vid].status == 1 && salTimeOffset == 0) {
dspVoice[vid].breakSet = 1;
}
dspVoice[vid].flags[salTimeOffset] |= 0x20;
}
void hwSetADSR(s32 vid, u32 *param_2, u8 param_3) {
}
void hwOff(s32 vid) {
salDeactivateVoice(&dspVoice[vid]);
} }

175
src/musyx/hw_dolphin.c Normal file
View File

@ -0,0 +1,175 @@
#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._4 = 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(); }