mirror of
				https://github.com/hedge-dev/UnleashedRecomp.git
				synced 2025-10-30 07:11:05 +00:00 
			
		
		
		
	audio gaming
This commit is contained in:
		
							parent
							
								
									2122f247ac
								
							
						
					
					
						commit
						baf24bb36a
					
				
					 10 changed files with 180 additions and 7 deletions
				
			
		|  | @ -4,6 +4,10 @@ file(GLOB "*.cpp") | |||
| 
 | ||||
| add_compile_definitions(SWA_IMPL) | ||||
| add_compile_definitions(SDL_MAIN_HANDLED) | ||||
| 
 | ||||
| # Microsoft wtf? | ||||
| add_compile_definitions(_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR ) | ||||
| 
 | ||||
| add_compile_options( | ||||
|     "/D_HAS_EXCEPTIONS=0" | ||||
|     "/fp:strict" | ||||
|  | @ -41,6 +45,7 @@ set(SWA_GPU_CXX_SOURCES | |||
| 
 | ||||
| set(SWA_APU_CXX_SOURCES | ||||
|     "apu/audio.cpp" | ||||
|     "apu/driver/xaudio_driver.cpp" | ||||
| ) | ||||
| 
 | ||||
| set(SWA_HID_CXX_SOURCES | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver) | ||||
| { | ||||
|     *driver = AUDIO_DRIVER_KEY; | ||||
|     XAudioRegisterClient(KeFindHostFunction(*callback), callback[1]); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
|  | @ -15,7 +16,8 @@ uint32_t XAudioUnregisterRenderDriverClient(DWORD driver) | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| uint32_t XAudioSubmitRenderDriverFrame(XLPDWORD callback, XLPDWORD driver) | ||||
| uint32_t XAudioSubmitRenderDriverFrame(uint32_t driver, void* samples) | ||||
| { | ||||
|     XAudioSubmitFrame(samples); | ||||
|     return 0; | ||||
| } | ||||
|  |  | |||
|  | @ -1,5 +1,11 @@ | |||
| #pragma once | ||||
| 
 | ||||
| SWA_API uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver); | ||||
| SWA_API uint32_t XAudioUnregisterRenderDriverClient(DWORD driver); | ||||
| SWA_API uint32_t XAudioSubmitRenderDriverFrame(XLPDWORD callback, XLPDWORD driver); | ||||
| #ifdef SWA_IMPL | ||||
| void XAudioInitializeSystem(); | ||||
| void XAudioRegisterClient(PPCFunc* callback, uint32_t param); | ||||
| void XAudioSubmitFrame(void* samples); | ||||
| #endif | ||||
| 
 | ||||
| uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver); | ||||
| uint32_t XAudioUnregisterRenderDriverClient(DWORD driver); | ||||
| uint32_t XAudioSubmitRenderDriverFrame(uint32_t driver, void* samples); | ||||
|  |  | |||
							
								
								
									
										120
									
								
								UnleashedRecomp/apu/driver/xaudio_driver.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								UnleashedRecomp/apu/driver/xaudio_driver.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | |||
| #include <stdafx.h> | ||||
| #include "xaudio_driver.h" | ||||
| #include <xaudio2.h> | ||||
| 
 | ||||
| #include <cpu/code_cache.h> | ||||
| #include <cpu/guest_thread.h> | ||||
| #include <cpu/guest_code.h> | ||||
| #include <cpu/ppc_context.h> | ||||
| 
 | ||||
| #define XAUDIO_DRIVER_KEY (uint32_t)('XAUD') | ||||
| 
 | ||||
| PPCFunc* g_clientCallback{}; | ||||
| DWORD g_clientCallbackParam{}; | ||||
| DWORD g_driverThread{}; | ||||
| 
 | ||||
| // TODO: Should use a counted ptr
 | ||||
| IXAudio2* g_audio{}; | ||||
| IXAudio2MasteringVoice* g_masteringVoice{}; | ||||
| IXAudio2SourceVoice* g_sourceVoice{}; | ||||
| 
 | ||||
| constexpr uint32_t g_semaphoreCount = 16; | ||||
| constexpr uint32_t g_audioFrameSize = 256 * 6; | ||||
| HANDLE g_audioSemaphore{ CreateSemaphoreA(nullptr, g_semaphoreCount, g_semaphoreCount, nullptr) }; | ||||
| uint32_t g_audioFrames[g_audioFrameSize * g_semaphoreCount]; | ||||
| uint32_t g_audioFrameIndex = 0; | ||||
| 
 | ||||
| class VoiceCallback : public IXAudio2VoiceCallback | ||||
| { | ||||
|     void OnVoiceProcessingPassStart(UINT32 BytesRequired) override {} | ||||
|     void OnVoiceProcessingPassEnd() override {} | ||||
| 
 | ||||
|     void OnBufferStart(void* pBufferContext) override {} | ||||
|     void OnBufferEnd(void* pBufferContext) override | ||||
|     { | ||||
|         ReleaseSemaphore(g_audioSemaphore, 1, nullptr); | ||||
|     } | ||||
| 
 | ||||
|     void OnStreamEnd() override {} | ||||
| 
 | ||||
|     void OnLoopEnd(void* pBufferContext) override {} | ||||
|     void OnVoiceError(void* pBufferContext, HRESULT Error) override {} | ||||
| } gVoiceCallback; | ||||
| 
 | ||||
| inline PPC_FUNC(DriverLoop) | ||||
| { | ||||
|     GuestThread::SetThreadName(GetCurrentThreadId(), "Audio Driver"); | ||||
| 
 | ||||
|     auto* cpu = GetPPCContext(); | ||||
|     while (true) | ||||
|     { | ||||
|         if (!g_clientCallback) | ||||
|         { | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         WaitForSingleObject(g_audioSemaphore, INFINITE); | ||||
| 
 | ||||
|         cpu->r3.u64 = g_clientCallbackParam; | ||||
|         GuestCode::Run(g_clientCallback, cpu); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void XAudioInitializeSystem() | ||||
| { | ||||
|     if (g_audio) | ||||
|     { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     //reinterpret_cast<decltype(&XAudio2Create)>(
 | ||||
|     //	GetProcAddress(LoadLibraryA("XAudio2_8.dll"), "XAudio2Create"))(&gAudio, 0, 1);
 | ||||
| 
 | ||||
|     XAudio2Create(&g_audio); | ||||
|     g_audio->CreateMasteringVoice(&g_masteringVoice); | ||||
| 
 | ||||
|     WAVEFORMATIEEEFLOATEX format{}; | ||||
|     format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; | ||||
|     format.Format.cbSize = sizeof(format) - sizeof(format.Format); | ||||
|     format.Format.nChannels = 6; | ||||
|     format.Format.nSamplesPerSec = 48000; | ||||
|     format.Format.wBitsPerSample = 32; | ||||
|     format.Format.nBlockAlign = (format.Format.nChannels * format.Format.wBitsPerSample) / 8; | ||||
|     format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * format.Format.nBlockAlign; | ||||
| 
 | ||||
|     format.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; | ||||
|     format.Samples.wValidBitsPerSample = format.Format.wBitsPerSample; | ||||
|     format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT | | ||||
|         SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT; | ||||
| 
 | ||||
|     g_audio->CreateSourceVoice(&g_sourceVoice, &format.Format, 0, 1024, &gVoiceCallback); | ||||
|     g_sourceVoice->Start(); | ||||
| 
 | ||||
|     KeInsertHostFunction(XAUDIO_DRIVER_KEY, DriverLoop); | ||||
|     GuestThread::Start(XAUDIO_DRIVER_KEY, 0, 0, &g_driverThread); | ||||
| } | ||||
| 
 | ||||
| void XAudioRegisterClient(PPCFunc* callback, uint32_t param) | ||||
| { | ||||
|     g_clientCallback = callback; | ||||
|     g_clientCallbackParam = param; | ||||
| } | ||||
| 
 | ||||
| void XAudioSubmitFrame(void* samples) | ||||
| { | ||||
|     uint32_t* audioFrame = &g_audioFrames[g_audioFrameSize * g_audioFrameIndex]; | ||||
|     g_audioFrameIndex = (g_audioFrameIndex + 1) % g_semaphoreCount; | ||||
| 
 | ||||
|     for (size_t i = 0; i < 256; i++) | ||||
|     { | ||||
|         for (size_t j = 0; j < 6; j++) | ||||
|             audioFrame[i * 6 + j] = std::byteswap(((uint32_t*)samples)[j * 256 + i]); | ||||
|     } | ||||
| 
 | ||||
|     XAUDIO2_BUFFER buffer{}; | ||||
|     buffer.pAudioData = (BYTE*)audioFrame; | ||||
|     buffer.AudioBytes = 256 * 6 * sizeof(float); | ||||
|     buffer.PlayLength = 256; | ||||
| 
 | ||||
|     g_sourceVoice->SubmitSourceBuffer(&buffer); | ||||
| } | ||||
|  | @ -36,7 +36,12 @@ void* CodeCache::Find(uint32_t guest) const | |||
|     return *reinterpret_cast<void**>(bucket + static_cast<uint64_t>(guest) * 2); | ||||
| } | ||||
| 
 | ||||
| PPCFunc* KeFindHostFunction(uint32_t guest) | ||||
| SWA_API PPCFunc* KeFindHostFunction(uint32_t guest) | ||||
| { | ||||
|     return static_cast<PPCFunc*>(gCodeCache.Find(guest)); | ||||
| } | ||||
| 
 | ||||
| SWA_API void KeInsertHostFunction(uint32_t guest, PPCFunc* function) | ||||
| { | ||||
|     gCodeCache.Insert(guest, function); | ||||
| } | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ struct CodeCache | |||
|     void* Find(uint32_t guest) const; | ||||
| }; | ||||
| 
 | ||||
| PPCFunc* KeFindHostFunction(uint32_t guest); | ||||
| SWA_API PPCFunc* KeFindHostFunction(uint32_t guest); | ||||
| SWA_API void KeInsertHostFunction(uint32_t guest, PPCFunc* function); | ||||
| 
 | ||||
| extern CodeCache gCodeCache; | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| #pragma once | ||||
| #include "ppc_context.h" | ||||
| #include "memory.h" | ||||
| #include <kernel/memory.h> | ||||
| 
 | ||||
| struct GuestCode  | ||||
| { | ||||
|  |  | |||
|  | @ -133,6 +133,21 @@ DWORD SetThreadIdealProcessorImpl(uint32_t hThread, DWORD dwIdealProcessor) | |||
|     return SetThreadIdealProcessor((HANDLE)hThread, dwIdealProcessor); | ||||
| } | ||||
| 
 | ||||
| GUEST_FUNCTION_HOOK(sub_831B0ED0, memcpy); | ||||
| GUEST_FUNCTION_HOOK(sub_831CCB98, memcpy); | ||||
| GUEST_FUNCTION_HOOK(sub_831CEAE0, memcpy); | ||||
| GUEST_FUNCTION_HOOK(sub_831CEE04, memcpy); | ||||
| GUEST_FUNCTION_HOOK(sub_831CF2D0, memcpy); | ||||
| GUEST_FUNCTION_HOOK(sub_831CF660, memcpy); | ||||
| GUEST_FUNCTION_HOOK(sub_831B1358, memcpy); | ||||
| GUEST_FUNCTION_HOOK(sub_831B5E00, memmove); | ||||
| GUEST_FUNCTION_HOOK(sub_831B0BA0, memset); | ||||
| GUEST_FUNCTION_HOOK(sub_831CCAA0, memset); | ||||
| 
 | ||||
| GUEST_FUNCTION_HOOK(sub_82BD4CA8, OutputDebugStringA); | ||||
| 
 | ||||
| GUEST_FUNCTION_HOOK(sub_82DFA2E8, SetThreadNameImpl); | ||||
| GUEST_FUNCTION_HOOK(sub_82BD57A8, GetThreadPriorityImpl); | ||||
| GUEST_FUNCTION_HOOK(sub_82BD5910, SetThreadIdealProcessorImpl); | ||||
| 
 | ||||
| GUEST_FUNCTION_STUB(sub_82BD58F8); // Some function that updates the TEB, don't really care since the field is not set
 | ||||
|  |  | |||
|  | @ -13,6 +13,22 @@ void* VdGetGlobalDevice() | |||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
| // CApplication::Update
 | ||||
| PPC_FUNC_IMPL(__imp__sub_822C1130); | ||||
| PPC_FUNC(sub_822C1130) | ||||
| { | ||||
|     SDL_PumpEvents(); | ||||
|     SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); | ||||
| 
 | ||||
|     __imp__sub_822C1130(ctx, base); | ||||
| } | ||||
| 
 | ||||
| // Skip logo
 | ||||
| PPC_FUNC(sub_82547DF0) | ||||
| { | ||||
|     sub_825517C8(ctx, base); | ||||
| } | ||||
| 
 | ||||
| // Direct3D stubs
 | ||||
| GUEST_FUNCTION_STUB(sub_824EB290); | ||||
| GUEST_FUNCTION_STUB(sub_82BDA8C0); | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #include <kernel/io/file_system.h> | ||||
| #include <file.h> | ||||
| #include <xex.h> | ||||
| #include <apu/audio.h> | ||||
| 
 | ||||
| #define GAME_XEX_PATH "game:\\default.xex" | ||||
| 
 | ||||
|  | @ -52,6 +53,8 @@ void KiSystemStartup() | |||
| 
 | ||||
|     // OS mounts game data to D:
 | ||||
|     XamContentCreateEx(0, "D", &gameContent, OPEN_EXISTING, nullptr, nullptr, 0, 0, nullptr); | ||||
| 
 | ||||
|     XAudioInitializeSystem(); | ||||
| } | ||||
| 
 | ||||
| uint32_t LdrLoadModule(const char* path) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Sajid
						Sajid