diff --git a/librecomp/src/ai.cpp b/librecomp/src/ai.cpp index 0195f2b..8c5aa50 100644 --- a/librecomp/src/ai.cpp +++ b/librecomp/src/ai.cpp @@ -25,5 +25,5 @@ extern "C" void osAiGetLength_recomp(uint8_t* rdram, recomp_context* ctx) { } extern "C" void osAiGetStatus_recomp(uint8_t* rdram, recomp_context* ctx) { - ctx->r2 = 0x00000000; // Pretend the audio DMAs finish instantly + ctx->r2 = osAiGetStatus(); } diff --git a/ultramodern/include/ultramodern/ultra64.h b/ultramodern/include/ultramodern/ultra64.h index 71a412f..b48a73f 100644 --- a/ultramodern/include/ultramodern/ultra64.h +++ b/ultramodern/include/ultramodern/ultra64.h @@ -295,6 +295,8 @@ int osSetTimer(RDRAM_ARG PTR(OSTimer) timer, OSTime countdown, OSTime interval, int osStopTimer(RDRAM_ARG PTR(OSTimer) timer); u32 osVirtualToPhysical(PTR(void) addr); +u32 osAiGetStatus(); + /* Controller interface */ s32 osContInit(RDRAM_ARG PTR(OSMesgQueue), u8*, PTR(OSContStatus)); diff --git a/ultramodern/src/audio.cpp b/ultramodern/src/audio.cpp index 3198be0..d8c3aee 100644 --- a/ultramodern/src/audio.cpp +++ b/ultramodern/src/audio.cpp @@ -6,6 +6,8 @@ static uint32_t sample_rate = 48000; static ultramodern::audio_callbacks_t audio_callbacks; +std::atomic recent_frames_queued = 0; + void ultramodern::set_audio_callbacks(const ultramodern::audio_callbacks_t& callbacks) { audio_callbacks = callbacks; } @@ -65,3 +67,25 @@ uint32_t ultramodern::get_remaining_audio_bytes() { } return buffered_byte_count; } + +extern "C" u32 osAiGetStatus() { + uint32_t cur_frame_count = 0; + if (audio_callbacks.get_frames_remaining != nullptr) { + cur_frame_count = audio_callbacks.get_frames_remaining(); + } + + uint32_t samples_per_vi = (sample_rate / 60); + if (cur_frame_count > static_cast(buffer_offset_frames * samples_per_vi)) { + cur_frame_count -= static_cast(buffer_offset_frames * samples_per_vi); + } + else { + cur_frame_count = 0; + } + + // Check if the most recently queued samples are playing, if not then consider the DMA as incomplete. + if (cur_frame_count > recent_frames_queued.load()) { + return 0x80000000; + } + + return 0x0; +}