/**************************************************************************** * * * Project64-audio - A Nintendo 64 audio plugin. * * http://www.pj64-emu.com/ * * Copyright (C) 2017 Project64. All rights reserved. * * Copyright (C) 2015 Gilles Siberlin * * Copyright (C) 2007-2009 Richard Goedeken * * Copyright (C) 2007-2008 Ebenblues * * Copyright (C) 2003 JttL * * Copyright (C) 2002 Hacktarux * * * * License: * * GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * * * ****************************************************************************/ #include #ifdef _WIN32 #include #else #include #endif #include "audio_1.1.h" #include "Version.h" #include #include #include "AudioSettings.h" #include "trace.h" #include "AudioMain.h" #include "ConfigUI.h" #include "SettingsID.h" #ifdef _WIN32 void SetTimerResolution ( void ); #endif #define ENDIAN_SWAP_BYTE (~0 & 0x7 & 3) #define BES(address) ((address) ^ ENDIAN_SWAP_BYTE) /* Read header for type definition */ AUDIO_INFO g_AudioInfo; bool g_PluginInit = false; bool g_romopen = false; uint32_t g_Dacrate = 0, hack = 0; #ifdef _WIN32 DirectSoundDriver * g_SoundDriver = NULL; #else OpenSLESDriver * g_SoundDriver = NULL; #endif void PluginInit(void) { if (g_PluginInit) { return; } SetupTrace(); SetupAudioSettings(); StartTrace(); #ifdef _WIN32 SetTimerResolution(); #endif g_PluginInit = true; } EXPORT void CALL PluginLoaded(void) { PluginInit(); WriteTrace(TraceAudioInterface, TraceDebug, "Called"); if (g_settings != NULL) { g_settings->SetSyncViaAudioEnabled(true); } } EXPORT void CALL AiDacrateChanged(int SystemType) { WriteTrace(TraceAudioInterface, TraceDebug, "Start (SystemType: %d)", SystemType); if (!g_PluginInit) { WriteTrace(TraceAudioInterface, TraceNotice, "Plugin has not been initilized"); WriteTrace(TraceAudioInterface, TraceDebug, "Done"); return; } if (g_SoundDriver && g_Dacrate != *g_AudioInfo.AI_DACRATE_REG) { g_Dacrate = *g_AudioInfo.AI_DACRATE_REG & 0x00003FFF; if (g_Dacrate != *g_AudioInfo.AI_DACRATE_REG) { WriteTrace(TraceAudioInterface, TraceNotice, "Unknown/reserved bits in AI_DACRATE_REG set. 0x%08X", *g_AudioInfo.AI_DACRATE_REG); } uint32_t video_clock = 0, BufferSize = 0, Frequency = 0, divider = 0; switch (SystemType) { case SYSTEM_NTSC: video_clock = 48681812; break; case SYSTEM_PAL: video_clock = 49656530; break; case SYSTEM_MPAL: video_clock = 48628316; break; } Frequency = (video_clock / (g_Dacrate + 1)); if (Frequency < 8000) { WriteTrace(TraceAudioDriver, TraceDebug, "Not Audio Data!"); return; } switch (g_settings->GetBuffer()) { case 1: divider = 50; break; case 2: divider = 45; break; case 3: divider = 40; break; case 4: divider = 30; break; case 5: divider = 25; break; case 6: divider = 20; break; case 7: divider = 15; break; } BufferSize = (Frequency / divider) + 3 & ~0x3; if (hack == 'BH' && SystemType != SYSTEM_PAL) BufferSize -= 16; g_SoundDriver->AI_SetFrequency(Frequency, BufferSize); } WriteTrace(TraceAudioInterface, TraceDebug, "Done"); } EXPORT void CALL AiLenChanged(void) { WriteTrace(TraceAudioInterface, TraceDebug, "Start (DRAM_ADDR = 0x%X Len = 0x%X)", *g_AudioInfo.AI_DRAM_ADDR_REG, *g_AudioInfo.AI_LEN_REG); if (g_SoundDriver && g_settings->AudioEnabled()) { uint32_t Len = *g_AudioInfo.AI_LEN_REG & 0x3FFF8; uint8_t * Buffer = (g_AudioInfo.RDRAM + (*g_AudioInfo.AI_DRAM_ADDR_REG & 0x00FFFFF8)); g_SoundDriver->AI_LenChanged(Buffer, Len); } WriteTrace(TraceAudioInterface, TraceDebug, "Done"); } EXPORT uint32_t CALL AiReadLength(void) { WriteTrace(TraceAudioInterface, TraceDebug, "Start"); uint32_t len = 0; if (g_SoundDriver != NULL) { *g_AudioInfo.AI_LEN_REG = g_SoundDriver->AI_ReadLength(); len = *g_AudioInfo.AI_LEN_REG; } WriteTrace(TraceAudioInterface, TraceDebug, "Done (len: 0x%X)", len); return len; } EXPORT void CALL AiUpdate(int32_t Wait) { WriteTrace(TraceAudioInterface, TraceDebug, "Start (Wait: %s)", Wait ? "true" : "false"); if (g_SoundDriver) { g_SoundDriver->AI_Update(Wait != 0); } else { pjutil::Sleep(1); // TODO: Fixme -- Ai Update appears to be problematic } WriteTrace(TraceAudioInterface, TraceDebug, "Done"); } EXPORT void CALL CloseDLL(void) { WriteTrace(TraceAudioInterface, TraceDebug, "Called"); if (g_SoundDriver != NULL) { g_SoundDriver->AI_Shutdown(); delete g_SoundDriver; g_SoundDriver = NULL; } CleanupAudioSettings(); StopTrace(); } EXPORT void CALL DllAbout(void * /*hParent*/) { WriteTrace(TraceAudioInterface, TraceDebug, "Called"); } EXPORT void CALL DllConfig(void * hParent) { #ifdef _WIN32 ConfigAudio(hParent); if (g_SoundDriver) { g_SoundDriver->SetVolume(g_settings->GetVolume()); } #endif } EXPORT void CALL DllTest(void * /*hParent*/) { WriteTrace(TraceAudioInterface, TraceDebug, "Called"); } EXPORT void CALL GetDllInfo(PLUGIN_INFO * PluginInfo) { PluginInfo->Version = 0x0101; PluginInfo->Type = PLUGIN_TYPE_AUDIO; #ifdef _DEBUG sprintf(PluginInfo->Name, "Project64 Audio Plugin (Debug): %s", VER_FILE_VERSION_STR); #else sprintf(PluginInfo->Name, "Project64 Audio Plugin: %s", VER_FILE_VERSION_STR); #endif PluginInfo->MemoryBswaped = true; PluginInfo->NormalMemory = false; } EXPORT int32_t CALL InitiateAudio(AUDIO_INFO Audio_Info) { WriteTrace(TraceAudioInterface, TraceDebug, "Start"); if (g_SoundDriver != NULL) { g_SoundDriver->AI_Shutdown(); delete g_SoundDriver; } g_AudioInfo = Audio_Info; #ifdef _WIN32 g_SoundDriver = new DirectSoundDriver; #else g_SoundDriver = new OpenSLESDriver; #endif const uint16_t cart_ID = 0x0000 | (g_AudioInfo.HEADER[BES(0x3C)] << 8) | (g_AudioInfo.HEADER[BES(0x3D)] << 0) ; hack = cart_ID; WriteTrace(TraceAudioInterface, TraceDebug, "Done (res: true)"); return true; } EXPORT void CALL RomOpen() { WriteTrace(TraceAudioInterface, TraceDebug, "Start"); g_romopen = true; g_settings->ReadSettings(); if (g_SoundDriver) { g_SoundDriver->AI_Startup(); } WriteTrace(TraceAudioInterface, TraceDebug, "Done"); } EXPORT void CALL RomClosed(void) { WriteTrace(TraceAudioInterface, TraceDebug, "Start"); g_Dacrate = 0; if (g_SoundDriver) { g_SoundDriver->AI_Shutdown(); } g_romopen = false; WriteTrace(TraceAudioInterface, TraceDebug, "Done"); } EXPORT void CALL ProcessAList(void) { WriteTrace(TraceAudioInterface, TraceDebug, "Called"); } #ifdef _WIN32 #include #endif extern "C" void UseUnregisteredSetting(int /*SettingID*/) { WriteTrace(TraceAudioInterface, TraceDebug, "Called"); #ifdef _WIN32 DebugBreak(); #endif } #ifdef _WIN32 void SetTimerResolution(void) { HMODULE hMod = GetModuleHandle("ntdll.dll"); if (hMod != NULL) { typedef LONG(NTAPI* tNtSetTimerResolution)(IN ULONG DesiredResolution, IN BOOLEAN SetResolution, OUT PULONG CurrentResolution); tNtSetTimerResolution NtSetTimerResolution = (tNtSetTimerResolution)GetProcAddress(hMod, "NtSetTimerResolution"); ULONG CurrentResolution = 0; NtSetTimerResolution(10000, TRUE, &CurrentResolution); } } #endif