2009-07-28 21:32:10 +00:00
|
|
|
// Copyright (C) 2003 Dolphin Project.
|
2009-03-23 09:10:32 +00:00
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, version 2.0.
|
|
|
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
|
|
|
|
// Official SVN repository and contact information can be found at
|
|
|
|
// http://code.google.com/p/dolphin-emu/
|
|
|
|
|
|
|
|
|
|
|
|
#include "Common.h" // Common
|
2010-05-29 21:34:34 +00:00
|
|
|
#include "Atomic.h"
|
2009-03-23 09:10:32 +00:00
|
|
|
#include "CommonTypes.h"
|
2009-07-12 21:58:32 +00:00
|
|
|
#include "LogManager.h"
|
|
|
|
#include "Thread.h"
|
|
|
|
#include "ChunkFile.h"
|
2009-03-23 09:10:32 +00:00
|
|
|
|
|
|
|
#include "Globals.h" // Local
|
2009-06-28 10:24:44 +00:00
|
|
|
#include "DSPInterpreter.h"
|
|
|
|
#include "DSPHWInterface.h"
|
2009-03-23 09:10:32 +00:00
|
|
|
#include "disassemble.h"
|
2009-06-21 08:39:21 +00:00
|
|
|
#include "DSPSymbols.h"
|
2009-03-23 20:55:32 +00:00
|
|
|
#include "Config.h"
|
|
|
|
|
2009-03-26 09:29:14 +00:00
|
|
|
#include "AudioCommon.h"
|
2009-07-12 21:58:32 +00:00
|
|
|
#include "Mixer.h"
|
2009-03-23 09:10:32 +00:00
|
|
|
|
2009-04-01 20:22:43 +00:00
|
|
|
#include "DSPTables.h"
|
2009-05-01 20:06:24 +00:00
|
|
|
#include "DSPCore.h"
|
2009-04-01 20:22:43 +00:00
|
|
|
|
2009-03-29 21:00:26 +00:00
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
|
|
|
#include "DSPConfigDlgLLE.h"
|
2009-07-02 17:11:27 +00:00
|
|
|
DSPConfigDialogLLE* m_ConfigFrame = NULL;
|
2009-07-12 17:08:48 +00:00
|
|
|
#include "Debugger/DSPDebugWindow.h"
|
2009-04-02 12:50:47 +00:00
|
|
|
DSPDebuggerLLE* m_DebuggerFrame = NULL;
|
2009-03-29 21:00:26 +00:00
|
|
|
#endif
|
|
|
|
|
2009-03-23 09:10:32 +00:00
|
|
|
PLUGIN_GLOBALS* globals = NULL;
|
|
|
|
DSPInitialize g_dspInitialize;
|
2009-03-30 06:28:15 +00:00
|
|
|
Common::Thread *g_hDSPThread = NULL;
|
2009-03-23 20:55:32 +00:00
|
|
|
SoundStream *soundStream = NULL;
|
2009-12-23 15:34:14 +00:00
|
|
|
bool g_InitMixer = false;
|
2009-03-23 20:55:32 +00:00
|
|
|
|
2009-03-30 06:28:15 +00:00
|
|
|
bool bIsRunning = false;
|
2010-05-29 21:34:34 +00:00
|
|
|
volatile u32 cycle_count = 0;
|
2009-03-23 09:10:32 +00:00
|
|
|
|
2009-07-02 19:00:27 +00:00
|
|
|
// Standard crap to make wxWidgets happy
|
2009-07-02 17:11:27 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
HINSTANCE g_hInstance;
|
|
|
|
|
2009-03-29 21:00:26 +00:00
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
|
|
|
class wxDLLApp : public wxApp
|
|
|
|
{
|
|
|
|
bool OnInit()
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
2009-07-02 17:11:27 +00:00
|
|
|
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
|
2009-03-29 21:00:26 +00:00
|
|
|
WXDLLIMPEXP_BASE void wxSetInstance(HINSTANCE hInst);
|
|
|
|
#endif
|
|
|
|
|
2009-07-02 17:11:27 +00:00
|
|
|
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
|
|
|
|
DWORD dwReason, // reason called
|
|
|
|
LPVOID lpvReserved) // reserved
|
2009-03-23 09:10:32 +00:00
|
|
|
{
|
|
|
|
switch (dwReason)
|
|
|
|
{
|
2009-03-29 21:00:26 +00:00
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
{
|
2009-07-02 17:11:27 +00:00
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
2009-03-29 21:00:26 +00:00
|
|
|
wxSetInstance((HINSTANCE)hinstDLL);
|
2010-02-22 04:59:57 +00:00
|
|
|
wxInitialize();
|
2009-07-02 17:11:27 +00:00
|
|
|
#endif
|
2009-03-29 21:00:26 +00:00
|
|
|
}
|
2009-07-02 17:11:27 +00:00
|
|
|
break;
|
2009-03-29 21:00:26 +00:00
|
|
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
2009-07-02 17:11:27 +00:00
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
2010-02-22 04:59:57 +00:00
|
|
|
wxUninitialize();
|
2009-07-02 17:11:27 +00:00
|
|
|
#endif
|
2009-03-29 21:00:26 +00:00
|
|
|
break;
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_hInstance = hinstDLL;
|
2009-07-02 17:11:27 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
|
|
|
wxWindow* GetParentedWxWindow(HWND Parent)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
wxSetInstance((HINSTANCE)g_hInstance);
|
|
|
|
#endif
|
|
|
|
wxWindow *win = new wxWindow();
|
|
|
|
#ifdef _WIN32
|
|
|
|
win->SetHWND((WXHWND)Parent);
|
|
|
|
win->AdoptAttributesFromHWND();
|
|
|
|
#endif
|
|
|
|
return win;
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-03-29 21:00:26 +00:00
|
|
|
|
2009-03-23 09:10:32 +00:00
|
|
|
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
|
|
|
|
{
|
|
|
|
_PluginInfo->Version = 0x0100;
|
|
|
|
_PluginInfo->Type = PLUGIN_TYPE_DSP;
|
|
|
|
|
|
|
|
#ifdef DEBUGFAST
|
2010-02-25 12:35:31 +00:00
|
|
|
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (DebugFast)");
|
2009-03-23 09:10:32 +00:00
|
|
|
#else
|
|
|
|
#ifndef _DEBUG
|
2010-02-25 12:35:31 +00:00
|
|
|
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin");
|
2009-03-23 09:10:32 +00:00
|
|
|
#else
|
2010-02-25 12:35:31 +00:00
|
|
|
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (Debug)");
|
2009-03-23 09:10:32 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetDllGlobals(PLUGIN_GLOBALS* _pPluginGlobals)
|
|
|
|
{
|
|
|
|
globals = _pPluginGlobals;
|
|
|
|
LogManager::SetInstance((LogManager *)globals->logManager);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DllConfig(HWND _hParent)
|
2009-03-23 20:55:32 +00:00
|
|
|
{
|
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
2010-02-25 06:12:35 +00:00
|
|
|
wxWindow *frame = GetParentedWxWindow(_hParent);
|
|
|
|
m_ConfigFrame = new DSPConfigDialogLLE(frame);
|
2009-03-23 20:55:32 +00:00
|
|
|
|
2010-02-25 06:12:35 +00:00
|
|
|
// add backends
|
|
|
|
std::vector<std::string> backends = AudioCommon::GetSoundBackends();
|
2009-03-27 14:26:44 +00:00
|
|
|
|
2010-02-25 06:12:35 +00:00
|
|
|
for (std::vector<std::string>::const_iterator iter = backends.begin();
|
|
|
|
iter != backends.end(); ++iter)
|
|
|
|
{
|
|
|
|
m_ConfigFrame->AddBackend((*iter).c_str());
|
|
|
|
}
|
2009-03-23 20:55:32 +00:00
|
|
|
|
2010-02-25 06:12:35 +00:00
|
|
|
// Only allow one open at a time
|
2010-03-05 07:03:44 +00:00
|
|
|
#ifdef _WIN32
|
2010-02-25 06:12:35 +00:00
|
|
|
frame->Disable();
|
|
|
|
m_ConfigFrame->ShowModal();
|
|
|
|
frame->Enable();
|
2010-03-05 07:03:44 +00:00
|
|
|
#else
|
|
|
|
m_ConfigFrame->ShowModal();
|
|
|
|
#endif
|
2010-02-25 06:12:35 +00:00
|
|
|
|
2010-02-23 01:57:26 +00:00
|
|
|
#ifdef _WIN32
|
2010-02-25 17:50:08 +00:00
|
|
|
frame->SetFocus();
|
2010-02-25 06:12:35 +00:00
|
|
|
frame->SetHWND(NULL);
|
2010-02-23 01:57:26 +00:00
|
|
|
#endif
|
2010-02-25 17:50:08 +00:00
|
|
|
|
|
|
|
m_ConfigFrame->Destroy();
|
|
|
|
m_ConfigFrame = NULL;
|
2010-02-25 06:12:35 +00:00
|
|
|
frame->Destroy();
|
2009-03-23 20:55:32 +00:00
|
|
|
#endif
|
|
|
|
}
|
2009-03-23 09:10:32 +00:00
|
|
|
|
2009-03-29 21:00:26 +00:00
|
|
|
void DoState(unsigned char **ptr, int mode)
|
|
|
|
{
|
2009-03-23 09:10:32 +00:00
|
|
|
PointerWrap p(ptr, mode);
|
2009-12-23 15:34:14 +00:00
|
|
|
p.Do(g_InitMixer);
|
2010-01-12 21:38:39 +00:00
|
|
|
|
|
|
|
// Enable this when the HLE is fixed to save/load the same amount of data,
|
|
|
|
// no matter how bogus, so that one can switch LLE->HLE. The other way is unlikely to work very well.
|
|
|
|
#if 0
|
|
|
|
p.Do(g_dsp.r);
|
|
|
|
p.Do(g_dsp.pc);
|
|
|
|
p.Do(g_dsp.err_pc);
|
|
|
|
p.Do(g_dsp.cr);
|
|
|
|
p.Do(g_dsp.reg_stack_ptr);
|
|
|
|
p.Do(g_dsp.exceptions);
|
|
|
|
p.Do(g_dsp.exceptions_in_progress);
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
p.Do(g_dsp.reg_stack[i]);
|
|
|
|
}
|
|
|
|
p.Do(g_dsp.iram_crc);
|
|
|
|
p.Do(g_dsp.step_counter);
|
|
|
|
p.Do(g_dsp.ifx_regs);
|
|
|
|
p.Do(g_dsp.mbox[0]);
|
|
|
|
p.Do(g_dsp.mbox[1]);
|
|
|
|
p.DoArray(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
|
|
|
|
p.DoArray(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
|
|
|
|
#endif
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
Now you can switch between Emulated and Real WiiMotes, connect more Real Wiimotes and even pair them up (if you have MS BT Stack) during gameplay!
All you gotta do is Pause the emulation! That's useful for when your batteries run out during gameplay, for example...
But if you change the WiiMote source (between Emulated, Real or Inactive) you must disconnect and reconnect (Menu Tools -> Connect WiiMote) the WiiMotes affected by the change...
Thanks to jack.fr0st who did all the emulation state notification work!
Now every plugin has a way to know the current emulation state (paused, stopped or playing)
@ayuanx: I thought about doing a PostMessage(g_WiimoteInitialize.hWnd, WM_USER, WIIMOTE_DISCONNECT, current_number); so that the user gets asked to reconnect that WiiMote, trying to avoid having to disconnect and reconnect, but it didn't work because shooting that message only asks to reconnect, doesn't do a disconnect... Do you have any ideas on how to accomplish that?
Also, if anyone could check if Issue 1916 is finally fixed... Or at least when is the cursor being hidden or not...
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4789 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-06 19:26:52 +00:00
|
|
|
void EmuStateChange(PLUGIN_EMUSTATE newState)
|
|
|
|
{
|
2010-01-13 14:18:13 +00:00
|
|
|
DSP_ClearAudioBuffer((newState == PLUGIN_EMUSTATE_PLAY) ? false : true);
|
Now you can switch between Emulated and Real WiiMotes, connect more Real Wiimotes and even pair them up (if you have MS BT Stack) during gameplay!
All you gotta do is Pause the emulation! That's useful for when your batteries run out during gameplay, for example...
But if you change the WiiMote source (between Emulated, Real or Inactive) you must disconnect and reconnect (Menu Tools -> Connect WiiMote) the WiiMotes affected by the change...
Thanks to jack.fr0st who did all the emulation state notification work!
Now every plugin has a way to know the current emulation state (paused, stopped or playing)
@ayuanx: I thought about doing a PostMessage(g_WiimoteInitialize.hWnd, WM_USER, WIIMOTE_DISCONNECT, current_number); so that the user gets asked to reconnect that WiiMote, trying to avoid having to disconnect and reconnect, but it didn't work because shooting that message only asks to reconnect, doesn't do a disconnect... Do you have any ideas on how to accomplish that?
Also, if anyone could check if Issue 1916 is finally fixed... Or at least when is the cursor being hidden or not...
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4789 8ced0084-cf51-0410-be5f-012b33b47a6e
2010-01-06 19:26:52 +00:00
|
|
|
}
|
|
|
|
|
2010-07-19 02:09:34 +00:00
|
|
|
void DllDebugger(void *_hParent, bool Show)
|
2009-03-23 09:10:32 +00:00
|
|
|
{
|
2009-03-30 13:21:22 +00:00
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
2009-06-21 08:39:21 +00:00
|
|
|
if (Show)
|
2010-07-19 02:09:34 +00:00
|
|
|
{
|
|
|
|
if (!m_DebuggerFrame)
|
|
|
|
m_DebuggerFrame = new DSPDebuggerLLE((wxWindow *)_hParent);
|
2009-04-18 19:06:47 +00:00
|
|
|
m_DebuggerFrame->Show();
|
2010-07-19 02:09:34 +00:00
|
|
|
}
|
2009-04-18 19:06:47 +00:00
|
|
|
else
|
2010-07-19 02:09:34 +00:00
|
|
|
{
|
|
|
|
if (m_DebuggerFrame)
|
|
|
|
{
|
|
|
|
m_DebuggerFrame->Close();
|
|
|
|
m_DebuggerFrame->Destroy();
|
|
|
|
m_DebuggerFrame = NULL;
|
|
|
|
}
|
|
|
|
}
|
2009-03-30 13:21:22 +00:00
|
|
|
#endif
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-29 09:35:40 +00:00
|
|
|
// Regular thread
|
2009-03-29 21:00:26 +00:00
|
|
|
THREAD_RETURN dsp_thread(void* lpParameter)
|
2009-03-23 09:10:32 +00:00
|
|
|
{
|
2009-03-30 06:28:15 +00:00
|
|
|
while (bIsRunning)
|
2009-03-23 09:10:32 +00:00
|
|
|
{
|
2010-05-29 21:34:34 +00:00
|
|
|
int cycles = (int)cycle_count;
|
|
|
|
if (cycles > 0) {
|
2010-07-16 12:36:55 +00:00
|
|
|
cycles -= jit ? DSPCore_RunCycles(cycles) : DSPInterpreter::RunCycles(cycles);
|
2010-05-29 21:34:34 +00:00
|
|
|
Common::AtomicAdd(cycle_count, -cycles);
|
2010-04-07 15:04:45 +00:00
|
|
|
}
|
2010-05-29 21:34:34 +00:00
|
|
|
// yield?
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
2009-03-30 06:28:15 +00:00
|
|
|
return 0;
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DSP_DebugBreak()
|
|
|
|
{
|
2009-04-02 12:50:47 +00:00
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
2009-06-28 16:23:40 +00:00
|
|
|
// if (m_DebuggerFrame)
|
|
|
|
// m_DebuggerFrame->DebugBreak();
|
2009-04-02 12:50:47 +00:00
|
|
|
#endif
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Initialize(void *init)
|
|
|
|
{
|
2009-12-23 15:34:14 +00:00
|
|
|
g_InitMixer = false;
|
2009-06-28 16:23:40 +00:00
|
|
|
bool bCanWork = true;
|
2009-03-23 09:10:32 +00:00
|
|
|
g_dspInitialize = *(DSPInitialize*)init;
|
|
|
|
|
2009-03-30 09:55:50 +00:00
|
|
|
g_Config.Load();
|
2009-04-05 15:46:47 +00:00
|
|
|
|
2009-06-07 11:06:40 +00:00
|
|
|
std::string irom_filename = File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + DSP_IROM;
|
|
|
|
std::string coef_filename = File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + DSP_COEF;
|
2010-04-07 15:04:45 +00:00
|
|
|
bCanWork = DSPCore_Init(irom_filename.c_str(), coef_filename.c_str(), AudioCommon::UseJIT());
|
2009-07-02 21:20:47 +00:00
|
|
|
|
2009-03-23 09:10:32 +00:00
|
|
|
g_dsp.cpu_ram = g_dspInitialize.pGetMemoryPointer(0);
|
2009-06-07 11:06:40 +00:00
|
|
|
DSPCore_Reset();
|
2009-04-05 15:46:47 +00:00
|
|
|
|
2009-04-08 20:26:33 +00:00
|
|
|
if (!bCanWork)
|
|
|
|
{
|
2009-07-02 21:20:47 +00:00
|
|
|
PanicAlert("DSPLLE: Failed to initialize plugin, exiting");
|
2009-06-07 11:06:40 +00:00
|
|
|
DSPCore_Shutdown();
|
2009-04-08 12:37:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2009-03-30 06:28:15 +00:00
|
|
|
|
|
|
|
bIsRunning = true;
|
2009-04-05 15:46:47 +00:00
|
|
|
|
2009-04-06 18:47:21 +00:00
|
|
|
InitInstructionTable();
|
|
|
|
|
2009-04-08 20:26:33 +00:00
|
|
|
if (g_dspInitialize.bOnThread)
|
|
|
|
{
|
|
|
|
g_hDSPThread = new Common::Thread(dsp_thread, NULL);
|
|
|
|
}
|
2009-04-18 19:06:47 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_WX) && HAVE_WX
|
2009-06-21 08:39:21 +00:00
|
|
|
if (m_DebuggerFrame)
|
2009-04-18 19:06:47 +00:00
|
|
|
m_DebuggerFrame->Refresh();
|
|
|
|
#endif
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DSP_StopSoundStream()
|
|
|
|
{
|
2009-05-01 22:17:22 +00:00
|
|
|
DSPInterpreter::Stop();
|
2009-04-03 12:21:02 +00:00
|
|
|
bIsRunning = false;
|
2009-04-08 20:26:33 +00:00
|
|
|
if (g_dspInitialize.bOnThread)
|
|
|
|
{
|
|
|
|
delete g_hDSPThread;
|
|
|
|
g_hDSPThread = NULL;
|
|
|
|
}
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
2009-04-06 18:47:21 +00:00
|
|
|
void Shutdown()
|
2009-03-23 09:10:32 +00:00
|
|
|
{
|
2009-03-27 14:26:44 +00:00
|
|
|
AudioCommon::ShutdownSoundStream();
|
2009-06-07 11:06:40 +00:00
|
|
|
DSPCore_Shutdown();
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
u16 DSP_WriteControlRegister(u16 _uFlag)
|
|
|
|
{
|
2009-12-23 15:34:14 +00:00
|
|
|
UDSPControl Temp(_uFlag);
|
|
|
|
if (!g_InitMixer)
|
|
|
|
{
|
|
|
|
if (!Temp.DSPHalt && Temp.DSPInit)
|
|
|
|
{
|
2009-12-25 11:59:04 +00:00
|
|
|
unsigned int AISampleRate, DACSampleRate;
|
|
|
|
g_dspInitialize.pGetSampleRate(AISampleRate, DACSampleRate);
|
|
|
|
soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate));
|
2009-12-23 15:34:14 +00:00
|
|
|
if(!soundStream) PanicAlert("Error starting up sound stream");
|
|
|
|
// Mixer is initialized
|
|
|
|
g_InitMixer = true;
|
|
|
|
}
|
|
|
|
}
|
2009-05-01 22:17:22 +00:00
|
|
|
DSPInterpreter::WriteCR(_uFlag);
|
|
|
|
return DSPInterpreter::ReadCR();
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
u16 DSP_ReadControlRegister()
|
|
|
|
{
|
2009-05-01 22:17:22 +00:00
|
|
|
return DSPInterpreter::ReadCR();
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
u16 DSP_ReadMailboxHigh(bool _CPUMailbox)
|
|
|
|
{
|
|
|
|
if (_CPUMailbox)
|
2009-04-05 15:46:47 +00:00
|
|
|
return gdsp_mbox_read_h(GDSP_MBOX_CPU);
|
2009-03-23 09:10:32 +00:00
|
|
|
else
|
2009-04-05 15:46:47 +00:00
|
|
|
return gdsp_mbox_read_h(GDSP_MBOX_DSP);
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
u16 DSP_ReadMailboxLow(bool _CPUMailbox)
|
|
|
|
{
|
|
|
|
if (_CPUMailbox)
|
2009-04-05 15:46:47 +00:00
|
|
|
return gdsp_mbox_read_l(GDSP_MBOX_CPU);
|
2009-03-23 09:10:32 +00:00
|
|
|
else
|
2009-04-05 15:46:47 +00:00
|
|
|
return gdsp_mbox_read_l(GDSP_MBOX_DSP);
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DSP_WriteMailboxHigh(bool _CPUMailbox, u16 _uHighMail)
|
|
|
|
{
|
|
|
|
if (_CPUMailbox)
|
|
|
|
{
|
|
|
|
if (gdsp_mbox_peek(GDSP_MBOX_CPU) & 0x80000000)
|
|
|
|
{
|
2009-04-06 17:12:05 +00:00
|
|
|
ERROR_LOG(DSPLLE, "Mailbox isnt empty ... strange");
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if PROFILE
|
|
|
|
if ((_uHighMail) == 0xBABE)
|
|
|
|
{
|
|
|
|
ProfilerStart();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
gdsp_mbox_write_h(GDSP_MBOX_CPU, _uHighMail);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-04-06 17:12:05 +00:00
|
|
|
ERROR_LOG(DSPLLE, "CPU cant write to DSP mailbox");
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail)
|
|
|
|
{
|
|
|
|
if (_CPUMailbox)
|
|
|
|
{
|
|
|
|
gdsp_mbox_write_l(GDSP_MBOX_CPU, _uLowMail);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-04-06 17:12:05 +00:00
|
|
|
ERROR_LOG(DSPLLE, "CPU cant write to DSP mailbox");
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DSP_Update(int cycles)
|
|
|
|
{
|
2010-05-30 05:25:32 +00:00
|
|
|
unsigned int dsp_cycles = cycles / 6; //(jit?20:6);
|
2010-05-29 21:34:34 +00:00
|
|
|
|
2009-12-25 11:59:04 +00:00
|
|
|
// Sound stream update job has been handled by AudioDMA routine, which is more efficient
|
|
|
|
/*
|
2009-04-08 20:26:33 +00:00
|
|
|
// This gets called VERY OFTEN. The soundstream update might be expensive so only do it 200 times per second or something.
|
2009-11-14 17:45:35 +00:00
|
|
|
int cycles_between_ss_update;
|
|
|
|
|
|
|
|
if (g_dspInitialize.bWii)
|
|
|
|
cycles_between_ss_update = 121500000 / 200;
|
|
|
|
else
|
|
|
|
cycles_between_ss_update = 81000000 / 200;
|
|
|
|
|
2009-04-08 20:26:33 +00:00
|
|
|
cycle_count += cycles;
|
|
|
|
if (cycle_count > cycles_between_ss_update)
|
|
|
|
{
|
|
|
|
while (cycle_count > cycles_between_ss_update)
|
|
|
|
cycle_count -= cycles_between_ss_update;
|
|
|
|
soundStream->Update();
|
|
|
|
}
|
2009-12-25 11:59:04 +00:00
|
|
|
*/
|
2009-04-08 20:26:33 +00:00
|
|
|
// If we're not on a thread, run cycles here.
|
|
|
|
if (!g_dspInitialize.bOnThread)
|
|
|
|
{
|
2010-04-07 15:04:45 +00:00
|
|
|
// ~1/6th as many cycles as the period PPC-side.
|
2010-05-29 21:34:34 +00:00
|
|
|
DSPCore_RunCycles(dsp_cycles);
|
2010-04-07 15:04:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-05-29 21:34:34 +00:00
|
|
|
// Wait for dsp thread to catch up reasonably. Note: this logic should be thought through.
|
|
|
|
while (cycle_count > dsp_cycles)
|
|
|
|
;
|
|
|
|
Common::AtomicAdd(cycle_count, dsp_cycles);
|
2009-04-08 20:26:33 +00:00
|
|
|
}
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
2009-12-25 11:59:04 +00:00
|
|
|
void DSP_SendAIBuffer(unsigned int address, unsigned int num_samples)
|
2009-03-23 09:10:32 +00:00
|
|
|
{
|
2009-12-23 15:34:14 +00:00
|
|
|
if (!soundStream)
|
|
|
|
return;
|
|
|
|
|
2010-01-12 21:38:39 +00:00
|
|
|
CMixer *pMixer = soundStream->GetMixer();
|
2009-12-23 15:34:14 +00:00
|
|
|
|
2010-01-12 21:38:39 +00:00
|
|
|
if (pMixer != 0 && address != 0)
|
2009-03-26 09:29:14 +00:00
|
|
|
{
|
2010-01-12 21:38:39 +00:00
|
|
|
short *samples = (short *)Memory_Get_Pointer(address);
|
2009-12-25 11:59:04 +00:00
|
|
|
pMixer->PushSamples(samples, num_samples);
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
|
|
|
|
2009-12-23 15:34:14 +00:00
|
|
|
soundStream->Update();
|
2009-03-23 09:10:32 +00:00
|
|
|
}
|
2009-11-07 20:01:39 +00:00
|
|
|
|
2010-01-13 14:18:13 +00:00
|
|
|
void DSP_ClearAudioBuffer(bool mute)
|
2009-11-07 20:01:39 +00:00
|
|
|
{
|
2010-01-12 21:38:39 +00:00
|
|
|
if (soundStream)
|
2010-01-13 14:18:13 +00:00
|
|
|
soundStream->Clear(mute);
|
2009-11-07 20:01:39 +00:00
|
|
|
}
|
|
|
|
|