diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index b01b54a5c..1273c4b2a 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -25,9 +25,12 @@ AudioSystem::AudioSystem(Emulator* emulator) : // Create the run loop used for any windows/etc. // This must be done on the thread we create the driver. run_loop_ = xe_run_loop_create(); + + lock_ = xe_mutex_alloc(); } AudioSystem::~AudioSystem() { + xe_mutex_free(lock_); } X_STATUS AudioSystem::Setup() { @@ -61,6 +64,8 @@ void AudioSystem::ThreadStart() { Initialize(); XEASSERTNOTNULL(driver_); + auto processor = emulator_->processor(); + // Main run loop. while (running_) { // Peek main run loop. @@ -72,6 +77,14 @@ void AudioSystem::ThreadStart() { } // Pump worker. + // mehhh + xe_mutex_lock(lock_); + auto clients = clients_; + xe_mutex_unlock(lock_); + for (auto it = clients.begin(); it != clients.end(); ++it) { + processor->ExecuteInterrupt( + 0, it->callback, it->wrapped_callback_arg, 0); + } //worker_->Pump(); Sleep(1000); @@ -100,6 +113,16 @@ void AudioSystem::Shutdown() { xe_run_loop_release(run_loop_); } +void AudioSystem::RegisterClient( + uint32_t callback, uint32_t callback_arg) { + uint32_t ptr = (uint32_t)memory()->HeapAlloc(0, 0x4, 0); + auto mem = memory()->membase(); + XESETUINT32BE(mem + ptr, callback_arg); + xe_mutex_lock(lock_); + clients_.push_back({ callback, callback_arg, ptr }); + xe_mutex_unlock(lock_); +} + bool AudioSystem::HandlesRegister(uint64_t addr) { return (addr & 0xFFFF0000) == 0x7FEA0000; } diff --git a/src/xenia/apu/audio_system.h b/src/xenia/apu/audio_system.h index 9fe552e04..e3f756691 100644 --- a/src/xenia/apu/audio_system.h +++ b/src/xenia/apu/audio_system.h @@ -35,6 +35,9 @@ public: virtual X_STATUS Setup(); virtual void Shutdown(); + void RegisterClient(uint32_t callback, uint32_t callback_arg); + //void UnregisterClient(); + bool HandlesRegister(uint64_t addr); virtual uint64_t ReadRegister(uint64_t addr); virtual void WriteRegister(uint64_t addr, uint64_t value); @@ -70,6 +73,14 @@ protected: xe_run_loop_ref run_loop_; xe_thread_ref thread_; bool running_; + xe_mutex_t* lock_; + + typedef struct { + uint32_t callback; + uint32_t callback_arg; + uint32_t wrapped_callback_arg; + } RenderDriverClient; + std::vector clients_; AudioDriver* driver_; }; diff --git a/src/xenia/apu/nop/nop_audio_system.cc b/src/xenia/apu/nop/nop_audio_system.cc index f6fc92edd..3354229af 100644 --- a/src/xenia/apu/nop/nop_audio_system.cc +++ b/src/xenia/apu/nop/nop_audio_system.cc @@ -33,6 +33,7 @@ void NopAudioSystem::Initialize() { } void NopAudioSystem::Pump() { + // } void NopAudioSystem::Shutdown() { diff --git a/src/xenia/kernel/xboxkrnl_audio.cc b/src/xenia/kernel/xboxkrnl_audio.cc index 0406c6e90..68f47a6b2 100644 --- a/src/xenia/kernel/xboxkrnl_audio.cc +++ b/src/xenia/kernel/xboxkrnl_audio.cc @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -75,7 +76,59 @@ SHIM_CALL XAudioGetSpeakerConfig_shim( "XAudioGetSpeakerConfig(%.8X)", config_ptr); - SHIM_SET_MEM_32(config_ptr, 1); // ? + SHIM_SET_MEM_32(config_ptr, 1); + + SHIM_SET_RETURN(X_ERROR_SUCCESS); +} + + +SHIM_CALL XAudioRegisterRenderDriverClient_shim( + PPCContext* ppc_state, KernelState* state) { + uint32_t callback_ptr = SHIM_GET_ARG_32(0); + uint32_t driver_ptr = SHIM_GET_ARG_32(1); + + uint32_t callback = SHIM_MEM_32(callback_ptr + 0); + uint32_t callback_arg = SHIM_MEM_32(callback_ptr + 4); + + XELOGD( + "XAudioRegisterRenderDriverClient(%.8X(%.8X, %.8X), %.8X)", + callback_ptr, callback, callback_arg, driver_ptr); + + auto audio_system = state->emulator()->audio_system(); + audio_system->RegisterClient(callback, callback_arg); + + SHIM_SET_MEM_32(driver_ptr, 0xAADD1100); + + SHIM_SET_RETURN(X_ERROR_SUCCESS); +} + + +SHIM_CALL XAudioUnregisterRenderDriverClient_shim( + PPCContext* ppc_state, KernelState* state) { + uint32_t driver_ptr = SHIM_GET_ARG_32(0); + + XELOGD( + "XAudioUnregisterRenderDriverClient(%.8X)", + driver_ptr); + + auto audio_system = state->emulator()->audio_system(); + //audio_system->UnregisterClient(...); + + SHIM_SET_RETURN(X_ERROR_SUCCESS); +} + + +SHIM_CALL XAudioSubmitRenderDriverFrame_shim( + PPCContext* ppc_state, KernelState* state) { + uint32_t driver_ptr = SHIM_GET_ARG_32(0); + uint32_t samples_ptr = SHIM_GET_ARG_32(1); + + XELOGD( + "XAudioSubmitRenderDriverFrame(%.8X, %.8X)", + driver_ptr, samples_ptr); + + auto audio_system = state->emulator()->audio_system(); + //audio_system->SubmitFrame(); SHIM_SET_RETURN(X_ERROR_SUCCESS); } @@ -111,4 +164,8 @@ void xe::kernel::xboxkrnl::RegisterAudioExports( SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetVoiceCategoryVolume, state); SHIM_SET_MAPPING("xboxkrnl.exe", XAudioGetSpeakerConfig, state); + + SHIM_SET_MAPPING("xboxkrnl.exe", XAudioRegisterRenderDriverClient, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XAudioUnregisterRenderDriverClient, state); + SHIM_SET_MAPPING("xboxkrnl.exe", XAudioSubmitRenderDriverFrame, state); }