From 3bb7c0c89f0b3cc89949716c708d5816433303ab Mon Sep 17 00:00:00 2001 From: Cuyler36 <24523422+Cuyler36@users.noreply.github.com> Date: Sat, 8 Jun 2024 22:57:45 -0400 Subject: [PATCH] Implement & link jaudio_NES/internal/streamctrl.c --- config/disasm_overrides.yml | 2 + config/dol_slices.yml | 5 + include/dolphin/dvd.h | 131 +++++++++--------- include/jaudio_NES/streamctrl.h | 38 ++++++ src/static/jaudio_NES/internal/streamctrl.c | 143 ++++++++++++++++++++ 5 files changed, 255 insertions(+), 64 deletions(-) create mode 100644 src/static/jaudio_NES/internal/streamctrl.c diff --git a/config/disasm_overrides.yml b/config/disasm_overrides.yml index 2f8ce230..5b331fde 100644 --- a/config/disasm_overrides.yml +++ b/config/disasm_overrides.yml @@ -6,6 +6,7 @@ symbol_aligns: 0x80018920: 32 0x800190e0: 32 0x80019380: 32 + 0x80019760: 32 0x8001a0c0: 32 0x80031d80: 32 0x80207458: 8 # align RunQueue to 0x001251d8 @@ -14,3 +15,4 @@ symbol_aligns: 0x800daaa0: 32 # align texture_cache_data_func to 32 bytes 0x80206f30: 16 # malloc.c align 16 bytes 0x800ab260: 32 + 0x801864b0: 8 # dspbuf align 8 (not sure why this doesn't happen) diff --git a/config/dol_slices.yml b/config/dol_slices.yml index aec7a6ef..2cae983b 100644 --- a/config/dol_slices.yml +++ b/config/dol_slices.yml @@ -84,6 +84,11 @@ jaudio_NES/internal/neosthread.c: .bss: [0x80180020, 0x80186440] .sdata: [0x80217be0, 0x80217be8] .sbss: [0x80218460, 0x80218478] +jaudio_NES/internal/streamctrl.c: + .text: [0x80019380, 0x80019760] + .data: [0x800d01a8, 0x800d0278] + .bss: [0x80186440, 0x801864b0] + .sdata2: [0x80218dc0, 0x80218dd0] jaudio_NES/internal/playercall.c: .text: [0x80019dc0, 0x8001a0c0] .bss: [0x801864d0,0x80186590] diff --git a/include/dolphin/dvd.h b/include/dolphin/dvd.h index aa43e5e4..ad67fd06 100644 --- a/include/dolphin/dvd.h +++ b/include/dolphin/dvd.h @@ -19,89 +19,89 @@ typedef void (*DVDDoneReadCallback)(s32, DVDFileInfo*); typedef void (*DVDOptionalCommandChecker)(DVDCommandBlock* block, DVDLowCallback callback); typedef struct DVDDriveInfo { - u16 revisionLevel; // _00 - u16 deviceCode; // _02 - u32 releaseDate; // _04 - u8 padding[24]; // _08 + u16 revisionLevel; // _00 + u16 deviceCode; // _02 + u32 releaseDate; // _04 + u8 padding[24]; // _08 } DVDDriveInfo; // Struct for DVD information (size 0x20) typedef struct DVDDiskID { - char gameName[4]; // _00 - char company[2]; // _04 - u8 diskNumber; // _06 - u8 gameVersion; // _07 - u8 streaming; // _08 - u8 streamBufSize; // _09, default = 0 - u8 padding[22]; // _0A, all 0s + char gameName[4]; // _00 + char company[2]; // _04 + u8 diskNumber; // _06 + u8 gameVersion; // _07 + u8 streaming; // _08 + u8 streamBufSize; // _09, default = 0 + u8 padding[22]; // _0A, all 0s } DVDDiskID; // Struct for command information (size 0x30). struct DVDCommandBlock { - DVDCommandBlock* next; // _00 - DVDCommandBlock* prev; // _04 - u32 command; // _08 - s32 state; // _0C - u32 offset; // _10 - u32 length; // _14 - void* addr; // _18 - u32 currTransferSize; // _1C - u32 transferredSize; // _20 - DVDDiskID* id; // _24 - DVDCBCallback callback; // _28 - void* userData; // _2C + DVDCommandBlock* next; // _00 + DVDCommandBlock* prev; // _04 + u32 command; // _08 + s32 state; // _0C + u32 offset; // _10 + u32 length; // _14 + void* addr; // _18 + u32 currTransferSize; // _1C + u32 transferredSize; // _20 + DVDDiskID* id; // _24 + DVDCBCallback callback; // _28 + void* userData; // _2C }; // Struct for file information (size 0x3C). // NB: we had this as DVDPlayer previously. struct DVDFileInfo { - DVDCommandBlock cBlock; // _00 - u32 startAddr; // _30 - u32 length; // _34 - DVDCallback callback; // _38 + DVDCommandBlock cBlock; // _00 + u32 startAddr; // _30 + u32 length; // _34 + DVDCallback callback; // _38 }; // Struct for directory information (size 0xC). typedef struct DVDDir { - u32 entryNum; // _00 - u32 location; // _04 - u32 next; // _08 + u32 entryNum; // _00 + u32 location; // _04 + u32 next; // _08 } DVDDir; // Struct for directory entries (size 0xC). typedef struct DVDDirEntry { - u32 entryNum; // _00 - BOOL isDir; // _04 - char* name; // _08 + u32 entryNum; // _00 + BOOL isDir; // _04 + char* name; // _08 } DVDDirEntry; // Struct for handing queues. typedef struct DVDQueue DVDQueue; struct DVDQueue { - DVDQueue* mHead; // _00 - DVDQueue* mTail; // _04 + DVDQueue* mHead; // _00 + DVDQueue* mTail; // _04 }; // DVD Boot information instructions. // Struct 1. typedef struct DVDBB1 { - u32 appLoaderLength; // _00 - void* appLoaderFunc1; // _04 - void* appLoaderFunc2; // _08 - void* appLoaderFunc3; // _0C + u32 appLoaderLength; // _00 + void* appLoaderFunc1; // _04 + void* appLoaderFunc2; // _08 + void* appLoaderFunc3; // _0C } DVDBB1; // Struct 2. typedef struct DVDBB2 { - u32 bootFilePosition; // _00 - u32 FSTPosition; // _04 - u32 FSTLength; // _08 - u32 FSTMaxLength; // _0C - void* FSTAddress; // _10 - u32 userPosition; // _14 - u32 userLength; // _18 - u32 reserved_1C; // _1C + u32 bootFilePosition; // _00 + u32 FSTPosition; // _04 + u32 FSTLength; // _08 + u32 FSTMaxLength; // _0C + void* FSTAddress; // _10 + u32 userPosition; // _14 + u32 userLength; // _18 + u32 reserved_1C; // _1C } DVDBB2; ////////////////////////////////// @@ -143,6 +143,8 @@ s32 DVDGetTransferredSize(DVDFileInfo* fileInfo); DVDDiskID* DVDGetCurrentDiskID(); BOOL DVDCompareDiskID(DVDDiskID* id1, DVDDiskID* id2); DVDLowCallback DVDLowClearCallback(); +BOOL DVDPrepareStreamAsync(DVDFileInfo* fileInfo, u32 length, u32 offset, DVDCallback callback); +s32 DVDCancelStream(DVDCommandBlock* block); BOOL DVDCheckDisk(); @@ -160,36 +162,37 @@ void DVDDumpWaitingQueue(); ////// USEFUL DVD DEFINES //////// // Macro for reading. -#define DVDReadAsync(fileInfo, addr, length, offset, callback) DVDReadAsyncPrio((fileInfo), (addr), (length), (offset), (callback), 2) +#define DVDReadAsync(fileInfo, addr, length, offset, callback) \ + DVDReadAsyncPrio((fileInfo), (addr), (length), (offset), (callback), 2) #define DVDGetFileInfoStatus(fileInfo) DVDGetCommandBlockStatus(&(fileInfo)->cBlock) // Minimum transfer size. #define DVD_MIN_TRANSFER_SIZE 32 // DVD states. -#define DVD_STATE_FATAL_ERROR -1 -#define DVD_STATE_END 0 -#define DVD_STATE_BUSY 1 -#define DVD_STATE_WAITING 2 -#define DVD_STATE_COVER_CLOSED 3 -#define DVD_STATE_NO_DISK 4 -#define DVD_STATE_COVER_OPEN 5 -#define DVD_STATE_WRONG_DISK 6 +#define DVD_STATE_FATAL_ERROR -1 +#define DVD_STATE_END 0 +#define DVD_STATE_BUSY 1 +#define DVD_STATE_WAITING 2 +#define DVD_STATE_COVER_CLOSED 3 +#define DVD_STATE_NO_DISK 4 +#define DVD_STATE_COVER_OPEN 5 +#define DVD_STATE_WRONG_DISK 6 #define DVD_STATE_MOTOR_STOPPED 7 -#define DVD_STATE_PAUSING 8 -#define DVD_STATE_IGNORED 9 -#define DVD_STATE_CANCELED 10 -#define DVD_STATE_RETRY 11 +#define DVD_STATE_PAUSING 8 +#define DVD_STATE_IGNORED 9 +#define DVD_STATE_CANCELED 10 +#define DVD_STATE_RETRY 11 // File info states. #define DVD_FILEINFO_READY 0 -#define DVD_FILEINFO_BUSY 1 +#define DVD_FILEINFO_BUSY 1 // DVD results. -#define DVD_RESULT_GOOD 0 +#define DVD_RESULT_GOOD 0 #define DVD_RESULT_FATAL_ERROR -1 -#define DVD_RESULT_IGNORED -2 -#define DVD_RESULT_CANCELED -3 +#define DVD_RESULT_IGNORED -2 +#define DVD_RESULT_CANCELED -3 #define DVD_AIS_SUCCESS 0 diff --git a/include/jaudio_NES/streamctrl.h b/include/jaudio_NES/streamctrl.h index e2048d92..9cb51872 100644 --- a/include/jaudio_NES/streamctrl.h +++ b/include/jaudio_NES/streamctrl.h @@ -3,6 +3,44 @@ #include "types.h" +/* @unused */ +// Jac_PlayStreamBGM(s32, s32, s32); +// Jac_StopStreamBGM(s32, s32); +// Jac_VolMoveStreamBGM(s32, s32); + +#define JSTREAM_NO_TRACK_ID (-1) +#define JSTREAM_FADEOUT_TIMER (120) + +typedef struct JSTREAM_ { + s32 state; + s32 req_stream_id; + s32 now_stream_id; + f32 fadein_vol; + s32 fadein_vol_timer; + s32 _14; + s32 fadeout_timer; + f32 target_vol1; + s32 change_vol_timer1; + f32 stream_vol; + u32 total_samples; +} JSTREAM; + +typedef enum JSTREAM_STATE_ { + JSTREAM_STATE_STOPPED, + JSTREAM_STATE_REQUEST_STREAM, + JSTREAM_STATE_START, + JSTREAM_STATE_PLAYING, + JSTREAM_STATE_CANCELLED, + JSTREAM_STATE_FADEOUT, + JSTREAM_STATE_STOP, + JSTREAM_STATE_CLEANUP, + + JSTREAM_STATE_NUM +} JSTREAM_STATE; + +extern char J_STREAMNAME[][16]; +extern JSTREAM J_STREAM; + extern void StreamMain(void); #endif diff --git a/src/static/jaudio_NES/internal/streamctrl.c b/src/static/jaudio_NES/internal/streamctrl.c new file mode 100644 index 00000000..1423b852 --- /dev/null +++ b/src/static/jaudio_NES/internal/streamctrl.c @@ -0,0 +1,143 @@ +#include "jaudio_NES/streamctrl.h" + +#include "jaudio_NES/audiowork.h" +#include "jaudio_NES/rate.h" +#include "dolphin/ai.h" +#include "dolphin/dvd.h" + +char J_STREAMNAME[8][16] = { + "/stream00.adp", "/stream01.adp", "/stream02.adp", "/stream03.adp", + "/stream04.adp", "/stream05.adp", "/stream06.adp", "/stream07.adp", +}; + +// clang-format off +JSTREAM J_STREAM = { + JSTREAM_STATE_STOPPED, + JSTREAM_NO_TRACK_ID, JSTREAM_NO_TRACK_ID, + 0.0f, 0, + 0, + 0, + 0.0f, 0, + 0.0f, + 0 +}; +// clang-format on + +/* @fabricated -- necessary for float ordering */ +#pragma force_active on +MATCH_FORCESTRIP static f32 Jac_VolMoveStreamBGM(s32 l, s32 r) { + // AISetStreamVolLeft((s32)(f32)l); + // AISetStreamVolRight((s32)(f32)r); + return l; +} +#pragma force_active reset + +extern void StreamMain(void) { + static DVDFileInfo finfo; + static DVDCommandBlock cmd; + u32 streamed_samples; + u32 trigger; + + switch (J_STREAM.state) { + case JSTREAM_STATE_STOPPED: + break; + + case JSTREAM_STATE_REQUEST_STREAM: + J_STREAM.now_stream_id = J_STREAM.req_stream_id; + J_STREAM.req_stream_id = JSTREAM_NO_TRACK_ID; + if (J_STREAM.now_stream_id == JSTREAM_NO_TRACK_ID) { + J_STREAM.state = JSTREAM_STATE_STOPPED; + } else { + if (DVDOpen(J_STREAMNAME[J_STREAM.now_stream_id], &finfo) == FALSE) { + J_STREAM.now_stream_id = JSTREAM_NO_TRACK_ID; + J_STREAM.state = JSTREAM_STATE_STOPPED; + } else { + J_STREAM.total_samples = finfo.length; + J_STREAM.total_samples = + (J_STREAM.total_samples / 256) * 224; // TODO: should probably make these defines + AISetStreamSampleRate(AI_SAMPLERATE_48KHZ); + if (J_STREAM.fadein_vol_timer == 0) { + J_STREAM.stream_vol = J_STREAM.fadein_vol; + } else { + J_STREAM.stream_vol = 0.0f; + } + + AISetStreamVolLeft((s32)J_STREAM.stream_vol); + AISetStreamVolRight((s32)J_STREAM.stream_vol); + DVDPrepareStreamAsync(&finfo, 0, 0, nullptr); + J_STREAM.state = JSTREAM_STATE_START; + } + } + break; + + case JSTREAM_STATE_START: + if (DVDGetDriveStatus() == DVD_STATE_END) { + AIResetStreamSampleCount(); + AISetStreamPlayState(AI_STREAM_START); + J_STREAM.state = JSTREAM_STATE_PLAYING; + } + break; + + case JSTREAM_STATE_PLAYING: + streamed_samples = AIGetStreamSampleCount(); + trigger = AIGetStreamTrigger(); + + if (J_STREAM.fadein_vol_timer != 0) { + f32 vol = J_STREAM.fadein_vol; + vol -= J_STREAM.stream_vol; + vol /= (f32)J_STREAM.fadein_vol_timer; + J_STREAM.stream_vol += vol; + J_STREAM.fadein_vol_timer--; + AISetStreamVolLeft((s32)J_STREAM.stream_vol); + AISetStreamVolRight((s32)J_STREAM.stream_vol); + } + + if (J_STREAM.change_vol_timer1 != 0) { + f32 vol = J_STREAM.target_vol1; + vol -= J_STREAM.stream_vol; + vol /= (f32)J_STREAM.change_vol_timer1; + J_STREAM.stream_vol += vol; + J_STREAM.change_vol_timer1--; + AISetStreamVolLeft((s32)J_STREAM.stream_vol); + AISetStreamVolRight((s32)J_STREAM.stream_vol); + } + + if ((J_STREAM.total_samples - streamed_samples) < (JAC_FRAMESAMPLES * JSTREAM_FADEOUT_TIMER)) { + J_STREAM.state = JSTREAM_STATE_FADEOUT; + J_STREAM.fadeout_timer = JSTREAM_FADEOUT_TIMER; + } + break; + + case JSTREAM_STATE_CANCELLED: + case JSTREAM_STATE_FADEOUT: + u32 streamed_samples = AIGetStreamSampleCount(); + if (J_STREAM.fadeout_timer != 0 && (J_STREAM.total_samples - streamed_samples) != 0) { + f32 vol = -J_STREAM.stream_vol; + vol /= (f32)J_STREAM.fadeout_timer; + J_STREAM.stream_vol += vol; + J_STREAM.fadeout_timer--; + AISetStreamVolLeft((s32)J_STREAM.stream_vol); + AISetStreamVolRight((s32)J_STREAM.stream_vol); + } else { + DVDCancelStream(&cmd); + J_STREAM.state = JSTREAM_STATE_STOP; + } + break; + + case JSTREAM_STATE_STOP: + if (DVDGetDriveStatus() == DVD_STATE_END) { + AISetStreamPlayState(AI_STREAM_STOP); + J_STREAM.state = JSTREAM_STATE_CLEANUP; + } + break; + + case JSTREAM_STATE_CLEANUP: + if (DVDGetDriveStatus() == DVD_STATE_END) { + DVDClose(&finfo); + J_STREAM.now_stream_id = -1; + J_STREAM.state = JSTREAM_STATE_REQUEST_STREAM; + AISetStreamPlayState(AI_STREAM_STOP); + } + break; + } +}