From f06341af41e3a81758e5efeea733b81be4400946 Mon Sep 17 00:00:00 2001 From: Jcw87 Date: Sun, 22 Oct 2023 23:51:13 -0700 Subject: [PATCH] JASAiCtrl, JASAudioThread, JASDSPBuf, JASDSPChannel, JASDriverIF --- include/JSystem/JAudio/JASAiCtrl.h | 30 ++++ include/JSystem/JAudio/JASAudioThread.h | 30 ++++ include/JSystem/JAudio/JASDSPBuf.h | 24 +++ include/JSystem/JAudio/JASDSPChannel.h | 69 ++++++++ include/JSystem/JAudio/JASDriverIF.h | 31 ++++ include/dolphin/ai/ai.h | 33 ++++ src/JSystem/JAudio/JASAiCtrl.cpp | 218 +++++++++++++++++++++-- src/JSystem/JAudio/JASAudioThread.cpp | 121 ++++++++++++- src/JSystem/JAudio/JASDSPBuf.cpp | 101 ++++++++++- src/JSystem/JAudio/JASDSPChannel.cpp | 222 +++++++++++++++++++++--- src/JSystem/JAudio/JASDriverIF.cpp | 44 +++-- 11 files changed, 855 insertions(+), 68 deletions(-) create mode 100644 include/JSystem/JAudio/JASAiCtrl.h create mode 100644 include/JSystem/JAudio/JASAudioThread.h create mode 100644 include/JSystem/JAudio/JASDSPBuf.h create mode 100644 include/JSystem/JAudio/JASDSPChannel.h create mode 100644 include/JSystem/JAudio/JASDriverIF.h create mode 100644 include/dolphin/ai/ai.h diff --git a/include/JSystem/JAudio/JASAiCtrl.h b/include/JSystem/JAudio/JASAiCtrl.h new file mode 100644 index 000000000..9b757dd77 --- /dev/null +++ b/include/JSystem/JAudio/JASAiCtrl.h @@ -0,0 +1,30 @@ +#ifndef JASAICTRL_H +#define JASAICTRL_H + +#include "dolphin/types.h" + +namespace JASystem { + namespace Kernel { + void init(); + void initSystem(); + void registerMixCallback(s16* (*)(s32), u8); + void vframeWork(); + void updateDac(); + void mixMonoTrack(s16*, s32, s16* (*)(s32)); + void mixMonoTrackWide(s16*, s32, s16* (*)(s32)); + void mixExtraTrack(s16*, s32, s16* (*)(s32)); + void mixInterleaveTrack(s16*, s32, s16* (*)(s32)); + + extern s16* dac[3]; + extern int JASUniversalDacCounter; + extern s16* lastRspMadep; + extern s16* useRspMadep; + extern int vframeWorkRunning; + extern void (*dacCallbackFunc)(s16*, u32); + extern int JASVframeCounter; + extern s16* (*extMixCallback)(s32); + extern u8 extMixMode; + } +} + +#endif /* JASAICTRL_H */ diff --git a/include/JSystem/JAudio/JASAudioThread.h b/include/JSystem/JAudio/JASAudioThread.h new file mode 100644 index 000000000..ca26d7bc5 --- /dev/null +++ b/include/JSystem/JAudio/JASAudioThread.h @@ -0,0 +1,30 @@ +#ifndef JASAUDIOTHREAD_H +#define JASAUDIOTHREAD_H + +#include +#include + +class JKRSolidHeap; + +namespace JASystem { + namespace TAudioThread { + void syncAudio(); + void* audioproc(void*); + void syncDSP(void*); + void setPriority(u8, u8); + void start(JKRSolidHeap*, u32, u32); + + extern OSThread sAudioThread; + extern u8 saAudioStack[4096]; + extern OSMessageQueue sAudioprocMQ; + extern OSMessage saAudioMsgBuf[16]; + extern u32 sAudioprocMQInit; + extern int sbIsPrioritySet; + extern s32 sDSPPrio; + extern s32 sDVDPrio; + extern vs32 snIntCount; + extern int sbIsDSPBoot; + }; +} + +#endif /* JASAUDIOTHREAD_H */ diff --git a/include/JSystem/JAudio/JASDSPBuf.h b/include/JSystem/JAudio/JASDSPBuf.h new file mode 100644 index 000000000..912f310c3 --- /dev/null +++ b/include/JSystem/JAudio/JASDSPBuf.h @@ -0,0 +1,24 @@ +#ifndef JASDSPBUF_H +#define JASDSPBUF_H + +#include "dolphin/types.h" + +namespace JASystem { + namespace TDSP_DACBuffer { + void init(); + void updateDSP(); + s16* mixDSP(s32); + void finishDSPFrame(); + + extern u8 numDSPBuf; + extern int isInit; + extern s16** dsp_buf; + extern u8 writeBuffer; + extern u8 readBuffer; + extern u8 dspStatus; + extern int dacSyncCounter; + extern void (*callback)(s16*, u32); + } +} + +#endif /* JASDSPBUF_H */ diff --git a/include/JSystem/JAudio/JASDSPChannel.h b/include/JSystem/JAudio/JASDSPChannel.h new file mode 100644 index 000000000..53c573cce --- /dev/null +++ b/include/JSystem/JAudio/JASDSPChannel.h @@ -0,0 +1,69 @@ +#ifndef JASDSPCHANNEL_H +#define JASDSPCHANNEL_H + +#include "dolphin/os/OSTime.h" + +namespace JASystem { + namespace DSPInterface { + class DSPBuffer; + } + + extern OSTick history[]; + extern f32 DSP_LIMIT_RATIO; + extern OSTick old_time; + + class TDSPChannel { + public: + void init(u8); + int allocate(u32); + void free(); + bool forceStop(); + void forceDelete(); + void play(); + void stop(); + static void initAll(); + static TDSPChannel* alloc(u32, u32); + static int free(TDSPChannel*, u32); + static TDSPChannel* getLower(); + static TDSPChannel* getLowerActive(); + static bool breakLower(u8); + static bool breakLowerActive(u8); + static void updateAll(); + void onUpdate(u32); + static int getNumBreak(); + ~TDSPChannel(); + TDSPChannel(); + + u8 getNumber() { return mNumber; } + // TODO: inlines + void checkSign(u32); + void isFree(); + void getPriority(); + void getStatus(); + void getCBInterval(); + void decCBInterval(); + void getPriorityTime(); + void setCBInterval(u16); + void setPriorityTime(u16); + void setPriority(u8); + void getLogicalChannel(); + void forceStop(TDSPChannel*); + void release(TDSPChannel*, u32); + + /* 0x00 */ u8 mNumber; + /* 0x01 */ u8 field_0x1; + /* 0x02 */ u8 field_0x2; + /* 0x03 */ u8 field_0x3; + /* 0x04 */ short field_0x4; + /* 0x06 */ short field_0x6; + /* 0x08 */ int field_0x8; + /* 0x0C */ DSPInterface::DSPBuffer* field_0xc; + /* 0x10 */ void* mCallback; + + static int smnFree; + static TDSPChannel* DSPCH; + static int smnUse; + }; +} + +#endif /* JASDSPCHANNEL_H */ diff --git a/include/JSystem/JAudio/JASDriverIF.h b/include/JSystem/JAudio/JASDriverIF.h new file mode 100644 index 000000000..972e473b7 --- /dev/null +++ b/include/JSystem/JAudio/JASDriverIF.h @@ -0,0 +1,31 @@ +#ifndef JASDSPDRIVERIF_H +#define JASDSPDRIVERIF_H + +#include "dolphin/types.h" + +namespace JASystem { + namespace Driver { + struct PanMatrix_ { + /* 0x00 */ f32 field_0x0; + /* 0x04 */ f32 field_0x4; + /* 0x08 */ f32 field_0x8; + }; + + void init(); + void setMixerLevel(f32, f32); + u16 getChannelLevel(); + u16 getAutoLevel(); + void setOutputMode(u32); + u32 getOutputMode(); + u8 getUpdateInterval(); + + extern u16 MAX_MIXERLEVEL; + extern u16 MAX_AUTOMIXERLEVEL; + extern u32 JAS_SYSTEM_OUTPUT_MODE; + extern u8 JAS_UPDATE_INTERVAL; + + extern int C5BASE_PITCHTABLE; + }; +} + +#endif /* JASDSPDRIVERIF_H */ diff --git a/include/dolphin/ai/ai.h b/include/dolphin/ai/ai.h new file mode 100644 index 000000000..0de6e2d9c --- /dev/null +++ b/include/dolphin/ai/ai.h @@ -0,0 +1,33 @@ +#ifndef AI_H +#define AI_H + +#include "dolphin/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*AISCallback)(u32 count); +typedef void (*AIDCallback)(); + +AIDCallback AIRegisterDMACallback(AIDCallback callback); +void AIInitDMA(u32 addr, u32 length); +void AIStartDMA(void); +void AIStopDMA(void); +void AISetStreamPlayState(u32 state); +inline u32 AIGetStreamPlayState(void); +void AISetDSPSampleRate(u32 rate); +u32 AIGetDSPSampleRate(void); +void __AI_set_stream_sample_rate(u32 rate); +u32 AIGetStreamSampleRate(void); +void AISetStreamVolLeft(u8 vol); +u8 AIGetStreamVolLeft(void); +void AISetStreamVolRight(u8 vol); +u8 AIGetStreamVolRight(void); +void AIInit(u8* stack); + +#ifdef __cplusplus +}; +#endif + +#endif /* AI_H */ diff --git a/src/JSystem/JAudio/JASAiCtrl.cpp b/src/JSystem/JAudio/JASAiCtrl.cpp index f5a70943d..079b9cb2a 100644 --- a/src/JSystem/JAudio/JASAiCtrl.cpp +++ b/src/JSystem/JAudio/JASAiCtrl.cpp @@ -3,51 +3,237 @@ // Translation Unit: JASAiCtrl.cpp // -#include "JASAiCtrl.h" -#include "dolphin/types.h" +#include "JSystem/JAudio/JASAiCtrl.h" +#include "JSystem/JAudio/JASCalc.h" +#include "JSystem/JAudio/JASCallback.h" +#include "JSystem/JAudio/JASCmdStack.h" +#include "JSystem/JAudio/JASDSPBuf.h" +#include "JSystem/JAudio/JASProbe.h" +#include "JSystem/JAudio/JASRate.h" +#include "JSystem/JAudio/JASSystemHeap.h" +#include "dolphin/ai/ai.h" +#include "dolphin/os/OSCache.h" +#include "dolphin/os/OSInterrupt.h" /* 8027AE30-8027AE5C .text init__Q28JASystem6KernelFv */ void JASystem::Kernel::init() { - /* Nonmatching */ + resetCallback(); + initSystem(); + portCmdInit(); + Calc::initSinfT(); } +s16* JASystem::Kernel::dac[3]; + /* 8027AE5C-8027AEF8 .text initSystem__Q28JASystem6KernelFv */ void JASystem::Kernel::initSystem() { - /* Nonmatching */ + for (int i = 0; i < 3; i++) { + dac[i] = (s16*)allocFromSysDram(gDacSize * 2); + Calc::bzero(dac[i], gDacSize * 2); + DCStoreRange(dac[i], gDacSize * 2); + } + AIInit(NULL); + AIInitDMA(u32(dac[2]), gDacSize * 2); } +int JASystem::Kernel::JASUniversalDacCounter; +s16* JASystem::Kernel::lastRspMadep; +s16* JASystem::Kernel::useRspMadep; +int JASystem::Kernel::vframeWorkRunning; +void (*JASystem::Kernel::dacCallbackFunc)(s16*, u32); +int JASystem::Kernel::JASVframeCounter; +s16* (*JASystem::Kernel::extMixCallback)(s32); +u8 JASystem::Kernel::extMixMode; + /* 8027AEF8-8027AF04 .text registerMixCallback__Q28JASystem6KernelFPFl_PsUc */ -void JASystem::Kernel::registerMixCallback(short* (*)(long), unsigned char) { - /* Nonmatching */ +void JASystem::Kernel::registerMixCallback(s16* (*param_1)(s32), u8 param_2) { + extMixCallback = param_1; + extMixMode = param_2; } /* 8027AF04-8027B0B8 .text vframeWork__Q28JASystem6KernelFv */ void JASystem::Kernel::vframeWork() { - /* Nonmatching */ + static u32 dacp = 0; + JASVframeCounter++; + s16* buf = TDSP_DACBuffer::mixDSP(gDacSize / 2); + Calc::imixcopy(buf + gFrameSamples, buf, dac[dacp], gDacSize / 2); + if (extMixCallback) { + switch(extMixMode) { + case 0: + mixMonoTrack(dac[dacp], gDacSize / 2, extMixCallback); + break; + case 1: + mixMonoTrackWide(dac[dacp], gDacSize / 2, extMixCallback); + break; + case 2: + mixExtraTrack(dac[dacp], gDacSize / 2, extMixCallback); + break; + case 3: + mixInterleaveTrack(dac[dacp], gDacSize / 2, extMixCallback); + break; + } + } + BOOL enable = OSDisableInterrupts(); + DCStoreRange(dac[dacp], gDacSize * 2); + OSRestoreInterrupts(enable); + lastRspMadep = dac[dacp]; + dacp++; + if (dacp == 3) { + dacp = 0; + } + vframeWorkRunning = 0; } /* 8027B0B8-8027B160 .text updateDac__Q28JASystem6KernelFv */ void JASystem::Kernel::updateDac() { /* Nonmatching */ + if (!useRspMadep) { + useRspMadep = lastRspMadep; + lastRspMadep = NULL; + } + if (useRspMadep) { + AIInitDMA(u32(useRspMadep), gDacSize * 2); + useRspMadep = NULL; + } else { + JASUniversalDacCounter++; + } + if (!lastRspMadep && vframeWorkRunning == 0) { + vframeWork(); + } + //HardStream::main(); + if (dacCallbackFunc) { + dacCallbackFunc(lastRspMadep, gDacSize / 2); + } } /* 8027B160-8027B250 .text mixMonoTrack__Q28JASystem6KernelFPslPFl_Ps */ -void JASystem::Kernel::mixMonoTrack(short*, long, short* (*)(long)) { - /* Nonmatching */ +void JASystem::Kernel::mixMonoTrack(s16* dest, s32 size, s16* (*cb)(s32)) { + probeStart(5, "MONO-MIX"); + s16* src = cb(size); + if (!src) { + return; + } + probeFinish(5); + s16* destPtr = dest; + s16* srcPtr = src; + for (int i = 0; i < size; i++) { + s32 var1 = destPtr[0] + srcPtr[0]; + s16 var2; + if (var1 < -0x8000) { + var2 = -0x7fff; + } else if (var1 > 0x7fff) { + var2 = 0x7fff; + } else { + var2 = var1; + } + destPtr[0] = var2; + var1 = destPtr[1] + srcPtr[0]; + if (var1 < -0x8000) { + var2 = -0x7fff; + } else if (var1 > 0x7fff) { + var2 = 0x7fff; + } else { + var2 = var1; + } + destPtr[1] = var2; + destPtr += 2; + srcPtr++; + } } /* 8027B250-8027B344 .text mixMonoTrackWide__Q28JASystem6KernelFPslPFl_Ps */ -void JASystem::Kernel::mixMonoTrackWide(short*, long, short* (*)(long)) { - /* Nonmatching */ +void JASystem::Kernel::mixMonoTrackWide(s16* dest, s32 size, s16* (*cb)(s32)) { + probeStart(5, "MONO(W)-MIX"); + s16* src = cb(size); + if (!src) { + return; + } + probeFinish(5); + s16* destPtr = dest; + s16* srcPtr = src; + for (int i = 0; i < size; i++) { + s32 var1 = destPtr[0] + srcPtr[0]; + s16 var2; + if (var1 < -0x8000) { + var2 = -0x7fff; + } else if (var1 > 0x7fff) { + var2 = 0x7fff; + } else { + var2 = var1; + } + destPtr[0] = var2; + var1 = destPtr[1] - srcPtr[0]; + if (var1 < -0x8000) { + var2 = -0x7fff; + } else if (var1 > 0x7fff) { + var2 = 0x7fff; + } else { + var2 = var1; + } + destPtr[1] = var2; + destPtr += 2; + srcPtr++; + } } /* 8027B344-8027B464 .text mixExtraTrack__Q28JASystem6KernelFPslPFl_Ps */ -void JASystem::Kernel::mixExtraTrack(short*, long, short* (*)(long)) { - /* Nonmatching */ +void JASystem::Kernel::mixExtraTrack(s16* dest, s32 size, s16* (*cb)(s32)) { + probeStart(5, "DSPMIX"); + s16* src = cb(size); + if (!src) { + return; + } + probeFinish(5); + probeStart(6,"MIXING"); + s16* destPtr = dest; + s16* srcPtr = src; + s16* srcPtr2 = src + gFrameSamples; + for (int i = 0; i < size; i++) { + s32 var1 = destPtr[0] + srcPtr2[0]; + s16 var2; + if (var1 < -0x8000) { + var2 = -0x7fff; + } else if (var1 > 0x7fff) { + var2 = 0x7fff; + } else { + var2 = var1; + } + destPtr[0] = var2; + var1 = destPtr[1] + srcPtr[0]; + if (var1 < -0x8000) { + var2 = -0x7fff; + } else if (var1 > 0x7fff) { + var2 = 0x7fff; + } else { + var2 = var1; + } + destPtr[1] = var2; + destPtr += 2; + srcPtr2++; + srcPtr++; + } + probeFinish(6); } /* 8027B464-8027B500 .text mixInterleaveTrack__Q28JASystem6KernelFPslPFl_Ps */ -void JASystem::Kernel::mixInterleaveTrack(short*, long, short* (*)(long)) { - /* Nonmatching */ +void JASystem::Kernel::mixInterleaveTrack(s16* dest, s32 size, s16* (*cb)(s32)) { + s16* src = cb(size); + if (!src) { + return; + } + s16* destPtr = dest; + for (int i = 0; i < size * 2 ; i++) { + s32 var1 = destPtr[0] + src[0]; + s16 var2; + if (var1 < -0x8000) { + var2 = -0x7fff; + } else if (var1 > 0x7fff) { + var2 = 0x7fff; + } else { + var2 = var1; + } + destPtr[0] = var2; + destPtr++; + src++; + } } - diff --git a/src/JSystem/JAudio/JASAudioThread.cpp b/src/JSystem/JAudio/JASAudioThread.cpp index 622dcfe37..198ce4ce0 100644 --- a/src/JSystem/JAudio/JASAudioThread.cpp +++ b/src/JSystem/JAudio/JASAudioThread.cpp @@ -3,31 +3,138 @@ // Translation Unit: JASAudioThread.cpp // -#include "JASAudioThread.h" -#include "dolphin/types.h" +#include "JSystem/JAudio/JASAudioThread.h" +#include "JSystem/JAudio/JASAiCtrl.h" +#include "JSystem/JAudio/JASDSPBuf.h" +#include "JSystem/JAudio/JASDSPInterface.h" +#include "JSystem/JAudio/JASDriverIF.h" +#include "JSystem/JAudio/JASDvdThread.h" +#include "JSystem/JAudio/JASKernelDebug.h" +#include "JSystem/JAudio/JASProbe.h" +#include "JSystem/JAudio/JASRate.h" +#include "JSystem/JAudio/JASSystemHeap.h" +#include "JSystem/JAudio/dspproc.h" +#include "JSystem/JAudio/dsptask.h" +#include "JSystem/JKernel/JKRThread.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "dolphin/ai/ai.h" + +OSThread JASystem::TAudioThread::sAudioThread; +u8 JASystem::TAudioThread::saAudioStack[4096]; +OSMessageQueue JASystem::TAudioThread::sAudioprocMQ; + +u32 JASystem::TAudioThread::sAudioprocMQInit; +int JASystem::TAudioThread::sbIsPrioritySet; +s32 JASystem::TAudioThread::sDSPPrio; +s32 JASystem::TAudioThread::sDVDPrio; +vs32 JASystem::TAudioThread::snIntCount; +int JASystem::TAudioThread::sbIsDSPBoot; /* 80288F08-80288F88 .text syncAudio__Q28JASystem12TAudioThreadFv */ void JASystem::TAudioThread::syncAudio() { + static u32 first = 1; + if (first == 0) { + Kernel::probeFinish(4); + } + first = 0; + Kernel::probeStart(4, "UPDATE-DAC"); + if (sAudioprocMQInit) { + OSSendMessage(&sAudioprocMQ, NULL, OS_MESSAGE_NOBLOCK); + } /* Nonmatching */ } /* 80288F88-80289130 .text audioproc__Q28JASystem12TAudioThreadFPv */ -void JASystem::TAudioThread::audioproc(void*) { +void* JASystem::TAudioThread::audioproc(void*) { /* Nonmatching */ + JKRThread thread(&sAudioThread, 0); + i_OSInitFastCast(); + OSInitMessageQueue(&sAudioprocMQ, saAudioMsgBuf, 16); + sAudioprocMQInit = 1; + Kernel::init(); + TDSP_DACBuffer::init(); + if (!sbIsDSPBoot) { + DspBoot(syncDSP); + sbIsDSPBoot = 1; + } + Driver::init(); + AISetDSPSampleRate(Kernel::gAiSetting); + AIRegisterDMACallback(syncAudio); + AIStartDMA(); + while (true) { + OSMessage message; + OSReceiveMessage(&sAudioprocMQ, &message, 1); + switch (int(message)) { + case 0: + Kernel::updateDac(); + break; + case 1: + JUT_ASSERT(145, snIntCount != 0); + snIntCount--; + if (snIntCount == 0) { + Kernel::probeFinish(7); + TDSP_DACBuffer::finishDSPFrame(); + } else { + Kernel::probeStart(2, (char*)"SFR_DSP"); + TDSP_DACBuffer::updateDSP(); + Kernel::probeFinish(2); + } + break; + case 2: + break; + case 3: + OSReport("----- Audio thread stops\n"); + OSExitThread(0); + break; + } + } + return NULL; } /* 80289130-802891F0 .text syncDSP__Q28JASystem12TAudioThreadFPv */ void JASystem::TAudioThread::syncDSP(void*) { /* Nonmatching */ + while (!DSPCheckMailFromDSP()) {} + u32 var1 = DSPReadMailFromDSP(); + if (var1 >> 16 != DSPInterface::JAS_DSP_PREFIX) { + OSReport("----- syncDSP : Mail format error %x\n"); + return; + } + if ((var1 & 0xff00) == 0xff00) { + if (sAudioprocMQInit) { + if (!OSSendMessage(&sAudioprocMQ, OSMessage(1), OS_MESSAGE_NOBLOCK)) { + OSReport("----- syncDSP : Send Miss\n"); + } + } else { + DSPReleaseHalt(); + } + } else { + DspFinishWork(var1); + } } /* 802891F0-8028920C .text setPriority__Q28JASystem12TAudioThreadFUcUc */ -void JASystem::TAudioThread::setPriority(unsigned char, unsigned char) { - /* Nonmatching */ +void JASystem::TAudioThread::setPriority(u8 param_1, u8 param_2) { + sbIsPrioritySet = 1; + sDSPPrio = param_1; + sDVDPrio = param_2; } /* 8028920C-802892E0 .text start__Q28JASystem12TAudioThreadFP12JKRSolidHeapUlUl */ -void JASystem::TAudioThread::start(JKRSolidHeap*, unsigned long, unsigned long) { +void JASystem::TAudioThread::start(JKRSolidHeap* param_1, u32 param_2, u32 param_3) { /* Nonmatching */ + if (!sbIsPrioritySet) { + s32 priority = OSGetThreadPriority(OSGetCurrentThread()); + sDSPPrio = priority - 3; + sDVDPrio = priority - 1; + } + Kernel::sysDramSetup(param_1); + Kernel::sysAramSetup(param_2); + Dvd::createThread(sDVDPrio, 0x5a, 0x1000); + Dvd::resumeThread(); + Kernel::stackInit((u64*)saAudioStack, 0x200); + if ((param_3 & 2)) { + OSCreateThread(&sAudioThread, audioproc, NULL, &saAudioStack[sizeof(saAudioStack)], sizeof(saAudioStack), sDSPPrio, 1); + OSResumeThread(&sAudioThread); + } } - diff --git a/src/JSystem/JAudio/JASDSPBuf.cpp b/src/JSystem/JAudio/JASDSPBuf.cpp index e4efe7a51..aa7d7b9e4 100644 --- a/src/JSystem/JAudio/JASDSPBuf.cpp +++ b/src/JSystem/JAudio/JASDSPBuf.cpp @@ -3,26 +3,115 @@ // Translation Unit: JASDSPBuf.cpp // -#include "JASDSPBuf.h" -#include "dolphin/types.h" +#include "JSystem/JAudio/JASDSPBuf.h" +#include "JSystem/JAudio/JASAudioThread.h" +#include "JSystem/JAudio/JASCallback.h" +#include "JSystem/JAudio/JASDSPChannel.h" +#include "JSystem/JAudio/JASDSPInterface.h" +#include "JSystem/JAudio/JASProbe.h" +#include "JSystem/JAudio/JASRate.h" +#include "JSystem/JAudio/JASSystemHeap.h" +#include "JSystem/JAudio/osdsp_task.h" +#include "JSystem/JKernel/JKRSolidHeap.h" +#include "dolphin/os/OS.h" +#include "global.h" + +u8 JASystem::TDSP_DACBuffer::numDSPBuf = 3; +int JASystem::TDSP_DACBuffer::isInit; +s16** JASystem::TDSP_DACBuffer::dsp_buf; +u8 JASystem::TDSP_DACBuffer::writeBuffer; +u8 JASystem::TDSP_DACBuffer::readBuffer; +u8 JASystem::TDSP_DACBuffer::dspStatus; + +static void dummy() { + OSReport("----- JASDSPBuf : DSP-DAC バッファの数を %d にしました\n"); +} /* 802892E0-802893E4 .text init__Q28JASystem14TDSP_DACBufferFv */ void JASystem::TDSP_DACBuffer::init() { /* Nonmatching */ + if (!isInit) { + int r30 = Kernel::gFrameSamples; + writeBuffer = numDSPBuf - 1; + readBuffer = 0; + dsp_buf = new (JASDram, 0x20) s16*[numDSPBuf]; + for (int i = 0; i < numDSPBuf; i++) { + dsp_buf[i] = new (JASDram, 0x20) s16[r30 * 2]; + for (u32 j = 0; j < r30 * 2; j++) { + dsp_buf[i][j] = 0; + } + DCStoreRange(dsp_buf[i], r30 * 4); + } + OSReport("DSP_DAC buffer size : %d\n", r30 * 2); + dspStatus = 0; + isInit = 1; + } } +int JASystem::TDSP_DACBuffer::dacSyncCounter; + /* 802893E4-80289438 .text updateDSP__Q28JASystem14TDSP_DACBufferFv */ void JASystem::TDSP_DACBuffer::updateDSP() { - /* Nonmatching */ + dacSyncCounter++; + Kernel::probeStart(3, "SFR-UPDATE"); + DSPInterface::invalChannelAll(); + Kernel::subframeCallback(); + TDSPChannel::updateAll(); + Kernel::aiCallback(); + Kernel::probeFinish(3); } /* 80289438-80289568 .text mixDSP__Q28JASystem14TDSP_DACBufferFl */ -void JASystem::TDSP_DACBuffer::mixDSP(long) { +s16* JASystem::TDSP_DACBuffer::mixDSP(s32) { /* Nonmatching */ + u8 var4 = readBuffer + 1; + u32 frameSamples = Kernel::gFrameSamples; + if (var4 == numDSPBuf) { + var4 = 0; + } + if (var4 == writeBuffer && numDSPBuf >= 3) { + s16 var1 = dsp_buf[readBuffer][frameSamples / 2 - 1]; + s16 var2 = dsp_buf[readBuffer][frameSamples - 1]; + for (u32 i = 0; i < frameSamples; i++) { + dsp_buf[readBuffer][i] = var1; + } + for (u32 i = frameSamples; i < frameSamples * 2; i++) { + dsp_buf[readBuffer][i] = var2; + } + if (dspStatus == 0) { + OSReport("----- JASDSPBuf::process DACSYNC -- DSP Wait\n"); + finishDSPFrame(); + } + } else { + readBuffer = var4; + DCInvalidateRange(dsp_buf[readBuffer], frameSamples * 4); + if (dspStatus == 0) { + finishDSPFrame(); + } + } + return dsp_buf[readBuffer]; } +void (*JASystem::TDSP_DACBuffer::callback)(s16*, u32); + /* 80289568-8028963C .text finishDSPFrame__Q28JASystem14TDSP_DACBufferFv */ void JASystem::TDSP_DACBuffer::finishDSPFrame() { - /* Nonmatching */ + u8 var2 = writeBuffer + 1; + u32 r31 = Kernel::gFrameSamples; + if (var2 == numDSPBuf) { + var2 = 0; + } + if (var2 == readBuffer) { + dspStatus = 0; + return; + } + writeBuffer = var2; + TAudioThread::snIntCount = Kernel::gSubFrames; + Kernel::probeStart(7, "DSP-MAIN"); + DsyncFrame2(Kernel::gSubFrames, u32(dsp_buf[writeBuffer]), u32(&dsp_buf[writeBuffer][r31])); + dspStatus = 1; + updateDSP(); + if (callback) { + callback(dsp_buf[writeBuffer], r31); + } } - diff --git a/src/JSystem/JAudio/JASDSPChannel.cpp b/src/JSystem/JAudio/JASDSPChannel.cpp index 1fe20ce98..282e2d951 100644 --- a/src/JSystem/JAudio/JASDSPChannel.cpp +++ b/src/JSystem/JAudio/JASDSPChannel.cpp @@ -3,91 +3,262 @@ // Translation Unit: JASDSPChannel.cpp // -#include "JASDSPChannel.h" -#include "dolphin/types.h" +#include "JSystem/JAudio/JASDSPChannel.h" +#include "JSystem/JAudio/JASDSPInterface.h" +#include "JSystem/JAudio/JASRate.h" +#include "JSystem/JAudio/JASSystemHeap.h" +#include "JSystem/JKernel/JKRSolidHeap.h" +#include "JSystem/JUtility/JUTAssert.h" /* 8028963C-80289694 .text init__Q28JASystem11TDSPChannelFUc */ -void JASystem::TDSPChannel::init(unsigned char) { - /* Nonmatching */ +void JASystem::TDSPChannel::init(u8 param_1) { + mNumber = param_1; + field_0x1 = 1; + field_0x8 = 0; + field_0x6 = 0; + mCallback = NULL; + field_0x3 = 0; + field_0x4 = 0; + field_0xc = DSPInterface::getDSPHandle(param_1); } /* 80289694-80289720 .text allocate__Q28JASystem11TDSPChannelFUl */ -void JASystem::TDSPChannel::allocate(unsigned long) { +int JASystem::TDSPChannel::allocate(u32 param_1) { /* Nonmatching */ + if (field_0x1 != 1) { + return false; + } + if (field_0x8 == 0) { + OSReport("sign %x があるのにCH.%d はFREE\n", field_0x8, mNumber); + } + field_0x1 = 0; + field_0x8 = param_1; + field_0x3 = 1; + field_0xc->allocInit(); + return true; } /* 80289720-8028973C .text free__Q28JASystem11TDSPChannelFv */ void JASystem::TDSPChannel::free() { - /* Nonmatching */ + field_0x1 = 1; + field_0x3 = 0; + mCallback = NULL; + field_0x8 = 0; } +JASystem::TDSPChannel* JASystem::TDSPChannel::DSPCH; +int JASystem::TDSPChannel::smnUse; + /* 8028973C-802897E0 .text forceStop__Q28JASystem11TDSPChannelFv */ -void JASystem::TDSPChannel::forceStop() { - /* Nonmatching */ +bool JASystem::TDSPChannel::forceStop() { + if (field_0x1 == 2) { + return false; + } + if (field_0x1 == 1) { + OSReport("----- JASDSPChannel::forceStop Warning! : CH_FREE\n"); + return false; + } + if (field_0xc->field_0x0 == 0) { + return false; + } + smnUse--; + field_0xc->field_0x10a = 1; + field_0xc->flushChannel(); + field_0x1 = 2; + return true; } /* 802897E0-802897F4 .text forceDelete__Q28JASystem11TDSPChannelFv */ void JASystem::TDSPChannel::forceDelete() { - /* Nonmatching */ + field_0x8 = 0; + field_0x3 = 0; + mCallback = NULL; } /* 802897F4-80289844 .text play__Q28JASystem11TDSPChannelFv */ void JASystem::TDSPChannel::play() { - /* Nonmatching */ + if (!mCallback) { + field_0xc->field_0x68 = 0; + } + field_0xc->playStart(); + field_0xc->flushChannel(); } /* 80289844-80289874 .text stop__Q28JASystem11TDSPChannelFv */ void JASystem::TDSPChannel::stop() { - /* Nonmatching */ + field_0xc->field_0x0 = 0; + field_0xc->flushChannel(); } /* 80289874-80289994 .text initAll__Q28JASystem11TDSPChannelFv */ void JASystem::TDSPChannel::initAll() { - /* Nonmatching */ + static int first = 1; + if (first == 0) { + OSReport("---- DSPChannel::initAll : already initialized\n"); + return; + } + DSPCH = new (JASDram, 0x20) TDSPChannel[64]; + JUT_ASSERT(204, DSPCH); + OSReport("----- JASDSPChannel size : %d\n", 0x14); + for (u8 i = 0; i < 64; i++) { + DSPCH[i].init(i); + } + first = 0; } +int JASystem::TDSPChannel::smnFree = 64; + /* 80289994-80289A54 .text alloc__Q28JASystem11TDSPChannelFUlUl */ -void JASystem::TDSPChannel::alloc(unsigned long, unsigned long) { +JASystem::TDSPChannel* JASystem::TDSPChannel::alloc(u32 param_1, u32 param_2) { /* Nonmatching */ + if (param_1) { + OSReport("----- JASDSPChannel::alloc : 多チャネルモードはサポートされていません\n"); + return NULL; + } + int i = 0; + do { + if (DSPCH[i].field_0x1 == 1 && DSPCH[i].allocate(param_2)) { + smnFree--; + smnUse++; + return &DSPCH[i]; + } + i++; + } while(i < 64); + return NULL; } /* 80289A54-80289AF4 .text free__Q28JASystem11TDSPChannelFPQ28JASystem11TDSPChannelUl */ -void JASystem::TDSPChannel::free(JASystem::TDSPChannel*, unsigned long) { - /* Nonmatching */ +int JASystem::TDSPChannel::free(JASystem::TDSPChannel* param_1, u32 param_2) { + if (!param_1) { + OSReport("----- JASDSPChannel::free : NULL のチャネルを解放しようとしました\n"); + return -1; + } + if (param_1->field_0x8 != param_2) { + OSReport("----- JASDSPChannel::free : BAD USERが開放を試みた\n"); + return -2; + } + if (param_1->field_0x1 == 0) { + smnUse--; + } + if (param_1->field_0x1 != 1) { + smnFree++; + } + param_1->free(); + return 0; } /* 80289AF4-80289C0C .text getLower__Q28JASystem11TDSPChannelFv */ -void JASystem::TDSPChannel::getLower() { - /* Nonmatching */ +JASystem::TDSPChannel* JASystem::TDSPChannel::getLower() { + u8 r31 = 0xff; + u8 r30 = 0; + u32 r29 = 0; + for (u8 i = 0; i < 64; i++) { + u8 r27; + TDSPChannel* dspch = DSPCH + i; + if (dspch->field_0x1 == 2) { + continue; + } + if (dspch->field_0x1 == 1) { + r30 = i; + break; + } + if (dspch->mCallback) { + r27 = dspch->field_0x3; + if (r27 <= r31) { + JUT_ASSERT(305, i == dspch->getNumber()); + if (r27 != r31 || dspch->field_0xc->field_0x10c >= r29) { + r29 = dspch->field_0xc->field_0x10c; + r30 = i; + r31 = r27; + } + } + } + } + return DSPCH + r30; } /* 80289C0C-80289D10 .text getLowerActive__Q28JASystem11TDSPChannelFv */ -void JASystem::TDSPChannel::getLowerActive() { +JASystem::TDSPChannel* JASystem::TDSPChannel::getLowerActive() { /* Nonmatching */ + u8 r29 = 0xff; + u8 r28 = 0; + u32 r27 = 0; + for (u8 i = 0; i < 64; i++) { + TDSPChannel* dspch = DSPCH + i; + if (dspch->field_0x1 == 2 || dspch->field_0x1 == 1) { + continue; + } + u8 r30 = dspch->field_0x3; + if (r30 <= r29) { + JUT_ASSERT(345, i == dspch->getNumber()); + if (r30 != r29 || dspch->field_0xc->field_0x10c >= r27) { + r27 = dspch->field_0xc->field_0x10c; + r28 = i; + r29 = r30; + } + } + } + return DSPCH + r28; } /* 80289D10-80289DC8 .text breakLower__Q28JASystem11TDSPChannelFUc */ -void JASystem::TDSPChannel::breakLower(unsigned char) { - /* Nonmatching */ +bool JASystem::TDSPChannel::breakLower(u8 param_1) { + TDSPChannel* dspch = getLower(); + if (dspch->field_0x3 > param_1) { + return false; + } + if (dspch->field_0x1 != 1) { + if (dspch->mCallback) { + dspch->onUpdate(3); + } else { + OSReport("----- BreakLowerDSPchannel : Error:Callback is NULL\n"); + } + dspch->forceStop(); + } else { + OSReport("----- BreakLowerDSPchannel : DSP Ch is FREE %d \n", dspch->mNumber); + return false; + } + return true; } /* 80289DC8-80289E68 .text breakLowerActive__Q28JASystem11TDSPChannelFUc */ -void JASystem::TDSPChannel::breakLowerActive(unsigned char) { - /* Nonmatching */ +bool JASystem::TDSPChannel::breakLowerActive(u8 param_1) { + TDSPChannel* dspch = getLowerActive(); + if (dspch->field_0x3 > param_1) { + return false; + } + if (dspch->field_0x1 != 1) { + if (dspch->mCallback) { + dspch->onUpdate(3); + } + dspch->forceStop(); + } else { + OSReport("----- BreakLowerActiveDSPchannel : DSP Ch is FREE %d\n", dspch->mNumber); + return false; + } + return true; } +f32 JASystem::DSP_LIMIT_RATIO = 1.1f; + /* 80289E68-8028A04C .text updateAll__Q28JASystem11TDSPChannelFv */ void JASystem::TDSPChannel::updateAll() { /* Nonmatching */ + if (Kernel::gSubFrames <= 10) { + OSTick time = OSGetTick(); + OSTick tmp = time - old_time; + old_time = time; + history[Kernel::gSubFrames - TAudioThread::snIntCount] = tmp; + } } /* 8028A04C-8028A08C .text onUpdate__Q28JASystem11TDSPChannelFUl */ -void JASystem::TDSPChannel::onUpdate(unsigned long) { +void JASystem::TDSPChannel::onUpdate(u32) { /* Nonmatching */ } /* 8028A08C-8028A0C0 .text getNumBreak__Q28JASystem11TDSPChannelFv */ -void JASystem::TDSPChannel::getNumBreak() { +int JASystem::TDSPChannel::getNumBreak() { /* Nonmatching */ } @@ -99,5 +270,6 @@ JASystem::TDSPChannel::~TDSPChannel() { /* 8028A0FC-8028A10C .text __ct__Q28JASystem11TDSPChannelFv */ JASystem::TDSPChannel::TDSPChannel() { /* Nonmatching */ + field_0xc = NULL; + mCallback = NULL; } - diff --git a/src/JSystem/JAudio/JASDriverIF.cpp b/src/JSystem/JAudio/JASDriverIF.cpp index 1269d98b3..1fcac9a49 100644 --- a/src/JSystem/JAudio/JASDriverIF.cpp +++ b/src/JSystem/JAudio/JASDriverIF.cpp @@ -3,41 +3,57 @@ // Translation Unit: JASDriverIF.cpp // -#include "JASDriverIF.h" -#include "dolphin/types.h" +#include "JSystem/JAudio/JASDriverIF.h" +#include "JSystem/JAudio/JASDSPChannel.h" +#include "JSystem/JAudio/JASDSPInterface.h" +#include "JSystem/JUtility/JUTAssert.h" /* 8028A978-8028A9A0 .text init__Q28JASystem6DriverFv */ void JASystem::Driver::init() { /* Nonmatching */ + DSPInterface::initBuffer(); + TDSPChannel::initAll(); + //TGlobalChannel::init(); } +u16 JASystem::Driver::MAX_MIXERLEVEL = 0x2ee0; + /* 8028A9A0-8028AAC4 .text setMixerLevel__Q28JASystem6DriverFff */ -void JASystem::Driver::setMixerLevel(float, float) { +void JASystem::Driver::setMixerLevel(f32 channel_level, f32 dsp_level) { /* Nonmatching */ + JUT_ASSERT(58, (0.0 <= channel_level) && (channel_level <= 2.0)); + JUT_ASSERT(59, (0.0 <= dsp_level) && (dsp_level <= 8.0)); + MAX_MIXERLEVEL = channel_level * 16383.5f; + DSPInterface::setDSPMixerLevel(dsp_level); } /* 8028AAC4-8028AACC .text getChannelLevel__Q28JASystem6DriverFv */ -void JASystem::Driver::getChannelLevel() { - /* Nonmatching */ +u16 JASystem::Driver::getChannelLevel() { + return MAX_MIXERLEVEL; } +u16 JASystem::Driver::MAX_AUTOMIXERLEVEL = 0x7fff; + /* 8028AACC-8028AAD4 .text getAutoLevel__Q28JASystem6DriverFv */ -void JASystem::Driver::getAutoLevel() { - /* Nonmatching */ +u16 JASystem::Driver::getAutoLevel() { + return MAX_AUTOMIXERLEVEL; } +u32 JASystem::Driver::JAS_SYSTEM_OUTPUT_MODE = 1; + /* 8028AAD4-8028AADC .text setOutputMode__Q28JASystem6DriverFUl */ -void JASystem::Driver::setOutputMode(unsigned long) { - /* Nonmatching */ +void JASystem::Driver::setOutputMode(u32 param_1) { + JAS_SYSTEM_OUTPUT_MODE = param_1; } /* 8028AADC-8028AAE4 .text getOutputMode__Q28JASystem6DriverFv */ -void JASystem::Driver::getOutputMode() { - /* Nonmatching */ +u32 JASystem::Driver::getOutputMode() { + return JAS_SYSTEM_OUTPUT_MODE; } +u8 JASystem::Driver::JAS_UPDATE_INTERVAL = 1; + /* 8028AAE4-8028AAEC .text getUpdateInterval__Q28JASystem6DriverFv */ -void JASystem::Driver::getUpdateInterval() { - /* Nonmatching */ +u8 JASystem::Driver::getUpdateInterval() { + return JAS_UPDATE_INTERVAL; } -