summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorLPFaint99 <lpfaint99@gmail.com>2009-07-06 02:10:26 +0000
committerLPFaint99 <lpfaint99@gmail.com>2009-07-06 02:10:26 +0000
commita41c1b2d0a9fab51f8a75ccdb7dba0890f766820 (patch)
tree5cc47f2330d83ece993db6443e944c103235821b /Source/Core
parent23f3e327e2f96843b0deebafddef12d195d73381 (diff)
add *.user, Win32, and x64 build dir to ignore list for DebuggerUICommon and Unit Tests
add *.aps to ignore list for DolphinWX dir add eol-style native to 120 or so files git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3689 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/AudioCommon/Src/AudioCommon.cpp176
-rw-r--r--Source/Core/AudioCommon/Src/AudioCommon.h80
-rw-r--r--Source/Core/AudioCommon/Src/AudioCommonConfig.cpp104
-rw-r--r--Source/Core/AudioCommon/Src/AudioCommonConfig.h100
-rw-r--r--Source/Core/AudioCommon/Src/OpenALStream.cpp340
-rw-r--r--Source/Core/AudioCommon/Src/OpenALStream.h148
-rw-r--r--Source/Core/AudioCommon/Src/aldlist.cpp682
-rw-r--r--Source/Core/AudioCommon/Src/aldlist.h102
-rw-r--r--Source/Core/Common/Src/SymbolDB.cpp118
-rw-r--r--Source/Core/Common/Src/SymbolDB.h244
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_apple.h48
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_linux.h50
-rw-r--r--Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_win32.h382
-rw-r--r--Source/Core/DSPCore/Src/DSPAnalyzer.cpp266
-rw-r--r--Source/Core/DSPCore/Src/DSPAnalyzer.h98
-rw-r--r--Source/Core/DSPCore/Src/DSPBreakpoints.cpp38
-rw-r--r--Source/Core/DSPCore/Src/DSPBreakpoints.h126
-rw-r--r--Source/Core/DSPCore/Src/DSPCodeUtil.cpp470
-rw-r--r--Source/Core/DSPCore/Src/DSPCodeUtil.h86
-rw-r--r--Source/Core/DSPCore/Src/DSPCore.cpp512
-rw-r--r--Source/Core/DSPCore/Src/DSPCore.h480
-rw-r--r--Source/Core/DSPCore/Src/DSPHost.h70
-rw-r--r--Source/Core/DSPCore/Src/DSPIntCCUtil.cpp280
-rw-r--r--Source/Core/DSPCore/Src/DSPIntCCUtil.h78
-rw-r--r--Source/Core/DSPCore/Src/DSPInterpreter.h342
-rw-r--r--Source/Core/DSPCore/Src/DSPJit.cpp44
-rw-r--r--Source/Core/DSPCore/Src/DSPJit.h56
-rw-r--r--Source/Core/DSPCore/Src/DSPTables.cpp1166
-rw-r--r--Source/Core/DSPCore/Src/DSPTables.h336
-rw-r--r--Source/Core/DSPCore/Src/DspIntArithmetic.cpp1468
-rw-r--r--Source/Core/DSPCore/Src/DspIntBranch.cpp498
-rw-r--r--Source/Core/DSPCore/Src/DspIntLoadStore.cpp532
-rw-r--r--Source/Core/DSPCore/Src/DspIntMisc.cpp404
-rw-r--r--Source/Core/DSPCore/Src/DspIntMultiplier.cpp1004
-rw-r--r--Source/Core/DSPCore/Src/LabelMap.cpp170
-rw-r--r--Source/Core/DSPCore/Src/LabelMap.h110
-rw-r--r--Source/Core/DSPCore/Src/assemble.cpp2032
-rw-r--r--Source/Core/DSPCore/Src/assemble.h278
-rw-r--r--Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.cpp46
-rw-r--r--Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h72
-rw-r--r--Source/Core/DiscIO/Src/NANDContentLoader.h200
-rw-r--r--Source/Core/DiscIO/Src/VolumeWad.h104
-rw-r--r--Source/Core/DiscIO/Src/WiiWad.cpp312
-rw-r--r--Source/Core/DiscIO/Src/WiiWad.h156
-rw-r--r--Source/Core/DolphinWX/Src/NetEvent.cpp576
-rw-r--r--Source/Core/DolphinWX/Src/NetFunctions.cpp1180
-rw-r--r--Source/Core/DolphinWX/Src/NetSockets.cpp1190
-rw-r--r--Source/Core/DolphinWX/Src/NetWindow.cpp1110
-rw-r--r--Source/Core/DolphinWX/Src/NetWindow.h634
-rw-r--r--Source/Core/DolphinWX/Src/Summarize.h252
-rw-r--r--Source/Core/DolphinWX/resources/Dolphin.xpm258
-rw-r--r--Source/Core/DolphinWX/resources/Flag_Europe.xpm166
-rw-r--r--Source/Core/DolphinWX/resources/Flag_France.xpm160
-rw-r--r--Source/Core/DolphinWX/resources/Flag_Japan.xpm204
-rw-r--r--Source/Core/DolphinWX/resources/Flag_Taiwan.xpm246
-rw-r--r--Source/Core/DolphinWX/resources/Flag_USA.xpm130
-rw-r--r--Source/Core/VideoCommon/Src/AVIDump.cpp358
-rw-r--r--Source/Core/VideoCommon/Src/BPFunctions.h118
-rw-r--r--Source/Core/VideoCommon/Src/BPStructs.cpp1220
-rw-r--r--Source/Core/VideoCommon/Src/BPStructs.h54
-rw-r--r--Source/Core/VideoCommon/Src/HiresTextures.cpp308
61 files changed, 11286 insertions, 11286 deletions
diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp
index 9e7100451a..8c7ca0a524 100644
--- a/Source/Core/AudioCommon/Src/AudioCommon.cpp
+++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp
@@ -1,88 +1,88 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "AudioCommon.h"
-#include "Mixer.h"
-#include "DSoundStream.h"
-#include "AOSoundStream.h"
-#include "NullSoundStream.h"
-#include "OpenALStream.h"
-
-namespace AudioCommon
-{
- SoundStream *InitSoundStream(CMixer *mixer)
- {
- if (!mixer)
- mixer = new CMixer();
-
- std::string backend = ac_Config.sBackend;
- if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd);
- if (backend == BACKEND_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
- if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
- if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
-
- if (soundStream != NULL) {
- ac_Config.Update();
- if (soundStream->Start()) {
- // Start the sound recording
- /*
- if (ac_Config.record) {
- soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
- }
- */
-
- return soundStream;
- }
- PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str());
- }
-
- PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
-
- delete soundStream;
- soundStream = new NullSound(mixer);
- soundStream->Start();
-
- return NULL;
- }
-
- void ShutdownSoundStream()
- {
- NOTICE_LOG(DSPHLE, "Shutting down sound stream");
-
- if (soundStream)
- {
- soundStream->Stop();
- soundStream->StopLogAudio();
- delete soundStream;
- soundStream = NULL;
- }
-
- INFO_LOG(DSPHLE, "Done shutting down sound stream");
- }
-
- std::vector<std::string> GetSoundBackends()
- {
- std::vector<std::string> backends;
-
- if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
- if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
- if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
- if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
-
- return backends;
- }
-}
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "AudioCommon.h"
+#include "Mixer.h"
+#include "DSoundStream.h"
+#include "AOSoundStream.h"
+#include "NullSoundStream.h"
+#include "OpenALStream.h"
+
+namespace AudioCommon
+{
+ SoundStream *InitSoundStream(CMixer *mixer)
+ {
+ if (!mixer)
+ mixer = new CMixer();
+
+ std::string backend = ac_Config.sBackend;
+ if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd);
+ if (backend == BACKEND_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
+ if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
+ if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
+
+ if (soundStream != NULL) {
+ ac_Config.Update();
+ if (soundStream->Start()) {
+ // Start the sound recording
+ /*
+ if (ac_Config.record) {
+ soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
+ }
+ */
+
+ return soundStream;
+ }
+ PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str());
+ }
+
+ PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
+
+ delete soundStream;
+ soundStream = new NullSound(mixer);
+ soundStream->Start();
+
+ return NULL;
+ }
+
+ void ShutdownSoundStream()
+ {
+ NOTICE_LOG(DSPHLE, "Shutting down sound stream");
+
+ if (soundStream)
+ {
+ soundStream->Stop();
+ soundStream->StopLogAudio();
+ delete soundStream;
+ soundStream = NULL;
+ }
+
+ INFO_LOG(DSPHLE, "Done shutting down sound stream");
+ }
+
+ std::vector<std::string> GetSoundBackends()
+ {
+ std::vector<std::string> backends;
+
+ if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
+ if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
+ if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
+ if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
+
+ return backends;
+ }
+}
diff --git a/Source/Core/AudioCommon/Src/AudioCommon.h b/Source/Core/AudioCommon/Src/AudioCommon.h
index ba0a1a7e87..2e61b3491f 100644
--- a/Source/Core/AudioCommon/Src/AudioCommon.h
+++ b/Source/Core/AudioCommon/Src/AudioCommon.h
@@ -1,40 +1,40 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _AUDIO_COMMON_H_
-#define _AUDIO_COMMON_H_
-
-#include "Common.h"
-#include "AudioCommonConfig.h"
-#include "../../../PluginSpecs/pluginspecs_dsp.h"
-#include "SoundStream.h"
-
-
-class CMixer;
-
-extern DSPInitialize g_dspInitialize;
-extern SoundStream *soundStream;
-extern AudioCommonConfig ac_Config;
-
-namespace AudioCommon
-{
- SoundStream *InitSoundStream(CMixer *mixer = NULL);
- void ShutdownSoundStream();
- std::vector<std::string> GetSoundBackends();
-}
-
-#endif // _AUDIO_COMMON_H_
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _AUDIO_COMMON_H_
+#define _AUDIO_COMMON_H_
+
+#include "Common.h"
+#include "AudioCommonConfig.h"
+#include "../../../PluginSpecs/pluginspecs_dsp.h"
+#include "SoundStream.h"
+
+
+class CMixer;
+
+extern DSPInitialize g_dspInitialize;
+extern SoundStream *soundStream;
+extern AudioCommonConfig ac_Config;
+
+namespace AudioCommon
+{
+ SoundStream *InitSoundStream(CMixer *mixer = NULL);
+ void ShutdownSoundStream();
+ std::vector<std::string> GetSoundBackends();
+}
+
+#endif // _AUDIO_COMMON_H_
diff --git a/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp b/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp
index fd58aa2c50..90ef0461a4 100644
--- a/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp
+++ b/Source/Core/AudioCommon/Src/AudioCommonConfig.cpp
@@ -1,52 +1,52 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "AudioCommon.h"
-AudioCommonConfig ac_Config;
-
-// Load from given file
-void AudioCommonConfig::Load(IniFile &file) {
- file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
- file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
- file.Get("Config", "Volume", &m_Volume, 75);
-#ifdef _WIN32
- file.Get("Config", "Backend", &sBackend, "DSound");
-#elif defined(__APPLE__)
- std::string temp;
- file.Get("Config", "Backend", &temp, "AOSound");
- strncpy(sBackend, temp.c_str(), 128);
-#else
- file.Get("Config", "Backend", &sBackend, "AOSound");
-#endif
-}
-
-// Set the values for the file
-void AudioCommonConfig::Set(IniFile &file) {
- file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
- file.Set("Config", "EnableThrottle", m_EnableThrottle);
- file.Set("Config", "Backend", sBackend);
- file.Set("Config", "Volume", m_Volume);
-}
-
-// Update according to the values (stream/mixer)
-void AudioCommonConfig::Update() {
- if (soundStream) {
- soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
- soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
- soundStream->SetVolume(m_Volume);
- }
-}
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "AudioCommon.h"
+AudioCommonConfig ac_Config;
+
+// Load from given file
+void AudioCommonConfig::Load(IniFile &file) {
+ file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
+ file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
+ file.Get("Config", "Volume", &m_Volume, 75);
+#ifdef _WIN32
+ file.Get("Config", "Backend", &sBackend, "DSound");
+#elif defined(__APPLE__)
+ std::string temp;
+ file.Get("Config", "Backend", &temp, "AOSound");
+ strncpy(sBackend, temp.c_str(), 128);
+#else
+ file.Get("Config", "Backend", &sBackend, "AOSound");
+#endif
+}
+
+// Set the values for the file
+void AudioCommonConfig::Set(IniFile &file) {
+ file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
+ file.Set("Config", "EnableThrottle", m_EnableThrottle);
+ file.Set("Config", "Backend", sBackend);
+ file.Set("Config", "Volume", m_Volume);
+}
+
+// Update according to the values (stream/mixer)
+void AudioCommonConfig::Update() {
+ if (soundStream) {
+ soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
+ soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
+ soundStream->SetVolume(m_Volume);
+ }
+}
diff --git a/Source/Core/AudioCommon/Src/AudioCommonConfig.h b/Source/Core/AudioCommon/Src/AudioCommonConfig.h
index 53507325f9..b43b0e5e81 100644
--- a/Source/Core/AudioCommon/Src/AudioCommonConfig.h
+++ b/Source/Core/AudioCommon/Src/AudioCommonConfig.h
@@ -1,50 +1,50 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _AUDIO_COMMON_CONFIG_H_
-#define _AUDIO_COMMON_CONFIG_H_
-
-#include <string>
-#include "IniFile.h"
-
-// Backend Types
-#define BACKEND_DIRECTSOUND "DSound"
-#define BACKEND_AOSOUND "AOSound"
-#define BACKEND_OPENAL "OpenAL"
-#define BACKEND_NULL "NullSound"
-struct AudioCommonConfig
-{
- bool m_EnableDTKMusic;
- bool m_EnableThrottle;
- int m_Volume;
-#ifdef __APPLE__
- char sBackend[128];
-#else
- std::string sBackend;
-#endif
-
- // Load from given file
- void Load(IniFile &file);
-
- // Set the values for the file
- void Set(IniFile &file);
-
- // Update according to the values (stream/mixer)
- void Update();
-};
-
-#endif //AUDIO_COMMON_CONFIG
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _AUDIO_COMMON_CONFIG_H_
+#define _AUDIO_COMMON_CONFIG_H_
+
+#include <string>
+#include "IniFile.h"
+
+// Backend Types
+#define BACKEND_DIRECTSOUND "DSound"
+#define BACKEND_AOSOUND "AOSound"
+#define BACKEND_OPENAL "OpenAL"
+#define BACKEND_NULL "NullSound"
+struct AudioCommonConfig
+{
+ bool m_EnableDTKMusic;
+ bool m_EnableThrottle;
+ int m_Volume;
+#ifdef __APPLE__
+ char sBackend[128];
+#else
+ std::string sBackend;
+#endif
+
+ // Load from given file
+ void Load(IniFile &file);
+
+ // Set the values for the file
+ void Set(IniFile &file);
+
+ // Update according to the values (stream/mixer)
+ void Update();
+};
+
+#endif //AUDIO_COMMON_CONFIG
diff --git a/Source/Core/AudioCommon/Src/OpenALStream.cpp b/Source/Core/AudioCommon/Src/OpenALStream.cpp
index 9787734d9e..749e6ae793 100644
--- a/Source/Core/AudioCommon/Src/OpenALStream.cpp
+++ b/Source/Core/AudioCommon/Src/OpenALStream.cpp
@@ -1,170 +1,170 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "aldlist.h"
-#include "OpenALStream.h"
-
-#if defined HAVE_OPENAL && HAVE_OPENAL
-
-#define AUDIO_NUMBUFFERS (4)
-//#define AUDIO_SERVICE_UPDATE_PERIOD (20)
-
-bool OpenALStream::Start()
-{
- ALDeviceList *pDeviceList = NULL;
- ALCcontext *pContext = NULL;
- ALCdevice *pDevice = NULL;
- bool bReturn = false;
-
- pDeviceList = new ALDeviceList();
- if ((pDeviceList) && (pDeviceList->GetNumDevices()))
- {
- pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
- if (pDevice)
- {
- pContext = alcCreateContext(pDevice, NULL);
- if (pContext)
- {
- alcMakeContextCurrent(pContext);
- thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
- bReturn = true;
- }
- else
- {
- alcCloseDevice(pDevice);
- PanicAlert("OpenAL: can't create context for device %s", pDevice);
- }
- } else {
- PanicAlert("OpenAL: can't open device %s", pDevice);
- }
-
-
- delete pDeviceList;
- } else {
- PanicAlert("OpenAL: can't find sound devices");
- }
-
- return bReturn;
-}
-
-void OpenALStream::Stop()
-{
- ALCcontext *pContext;
- ALCdevice *pDevice;
-
- soundCriticalSection.Enter();
- threadData = 1;
- // kick the thread if it's waiting
- soundSyncEvent.Set();
- soundCriticalSection.Leave();
- delete thread;
-
- pContext = alcGetCurrentContext();
- pDevice = alcGetContextsDevice(pContext);
-
- alcMakeContextCurrent(NULL);
- alcDestroyContext(pContext);
- alcCloseDevice(pDevice);
-
- soundSyncEvent.Shutdown();
- thread = NULL;
-}
-
-void OpenALStream::Update()
-{
- //if (m_mixer->GetDataSize()) //here need debug
- {
- soundSyncEvent.Set();
- }
-}
-
-THREAD_RETURN OpenALStream::ThreadFunc(void* args)
-{
- (reinterpret_cast<OpenALStream *>(args))->SoundLoop();
- return 0;
-}
-
-void OpenALStream::SoundLoop()
-{
- ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
- ALuint uiSource = 0;
- ALenum err;
- u32 ulFrequency = m_mixer->GetSampleRate();
- // Generate some AL Buffers for streaming
- alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
- // Generate a Source to playback the Buffers
- alGenSources(1, &uiSource);
-
- memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
-//*
- for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
- {
- // pay load fake data
- alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
- alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
- }
-//*/
- alSourcePlay(uiSource);
- err = alGetError();
-
- while (!threadData)
- {
- soundCriticalSection.Enter();
- int numBytesToRender = 32768; //ya, this is a hack, we need real data count
- /*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
- soundCriticalSection.Leave();
-
- //if (numBytesRender) //here need debug
- {
- ALint iBuffersProcessed = 0;
- alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
-
- if (iBuffersProcessed)
- {
- // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
- ALuint uiTempBuffer = 0;
- alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
-/*
- soundCriticalSection.Enter();
- int numBytesToRender = 32768; //ya, this is a hack, we need real data count
- m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
- soundCriticalSection.Leave();
-
- unsigned long ulBytesWritten = 0;
-*/
- //if (numBytesRender)
- {
- alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
- }
- alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
- }
- }
-
- if (!threadData)
- soundSyncEvent.Wait();
- }
- alSourceStop(uiSource);
- alSourcei(uiSource, AL_BUFFER, 0);
-
- // Clean up buffers and sources
- alDeleteSources(1, &uiSource);
- alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
-
-}
-
-#endif //HAVE_OPENAL
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "aldlist.h"
+#include "OpenALStream.h"
+
+#if defined HAVE_OPENAL && HAVE_OPENAL
+
+#define AUDIO_NUMBUFFERS (4)
+//#define AUDIO_SERVICE_UPDATE_PERIOD (20)
+
+bool OpenALStream::Start()
+{
+ ALDeviceList *pDeviceList = NULL;
+ ALCcontext *pContext = NULL;
+ ALCdevice *pDevice = NULL;
+ bool bReturn = false;
+
+ pDeviceList = new ALDeviceList();
+ if ((pDeviceList) && (pDeviceList->GetNumDevices()))
+ {
+ pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
+ if (pDevice)
+ {
+ pContext = alcCreateContext(pDevice, NULL);
+ if (pContext)
+ {
+ alcMakeContextCurrent(pContext);
+ thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
+ bReturn = true;
+ }
+ else
+ {
+ alcCloseDevice(pDevice);
+ PanicAlert("OpenAL: can't create context for device %s", pDevice);
+ }
+ } else {
+ PanicAlert("OpenAL: can't open device %s", pDevice);
+ }
+
+
+ delete pDeviceList;
+ } else {
+ PanicAlert("OpenAL: can't find sound devices");
+ }
+
+ return bReturn;
+}
+
+void OpenALStream::Stop()
+{
+ ALCcontext *pContext;
+ ALCdevice *pDevice;
+
+ soundCriticalSection.Enter();
+ threadData = 1;
+ // kick the thread if it's waiting
+ soundSyncEvent.Set();
+ soundCriticalSection.Leave();
+ delete thread;
+
+ pContext = alcGetCurrentContext();
+ pDevice = alcGetContextsDevice(pContext);
+
+ alcMakeContextCurrent(NULL);
+ alcDestroyContext(pContext);
+ alcCloseDevice(pDevice);
+
+ soundSyncEvent.Shutdown();
+ thread = NULL;
+}
+
+void OpenALStream::Update()
+{
+ //if (m_mixer->GetDataSize()) //here need debug
+ {
+ soundSyncEvent.Set();
+ }
+}
+
+THREAD_RETURN OpenALStream::ThreadFunc(void* args)
+{
+ (reinterpret_cast<OpenALStream *>(args))->SoundLoop();
+ return 0;
+}
+
+void OpenALStream::SoundLoop()
+{
+ ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
+ ALuint uiSource = 0;
+ ALenum err;
+ u32 ulFrequency = m_mixer->GetSampleRate();
+ // Generate some AL Buffers for streaming
+ alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
+ // Generate a Source to playback the Buffers
+ alGenSources(1, &uiSource);
+
+ memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
+//*
+ for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
+ {
+ // pay load fake data
+ alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
+ alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
+ }
+//*/
+ alSourcePlay(uiSource);
+ err = alGetError();
+
+ while (!threadData)
+ {
+ soundCriticalSection.Enter();
+ int numBytesToRender = 32768; //ya, this is a hack, we need real data count
+ /*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
+ soundCriticalSection.Leave();
+
+ //if (numBytesRender) //here need debug
+ {
+ ALint iBuffersProcessed = 0;
+ alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
+
+ if (iBuffersProcessed)
+ {
+ // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
+ ALuint uiTempBuffer = 0;
+ alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
+/*
+ soundCriticalSection.Enter();
+ int numBytesToRender = 32768; //ya, this is a hack, we need real data count
+ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
+ soundCriticalSection.Leave();
+
+ unsigned long ulBytesWritten = 0;
+*/
+ //if (numBytesRender)
+ {
+ alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
+ }
+ alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
+ }
+ }
+
+ if (!threadData)
+ soundSyncEvent.Wait();
+ }
+ alSourceStop(uiSource);
+ alSourcei(uiSource, AL_BUFFER, 0);
+
+ // Clean up buffers and sources
+ alDeleteSources(1, &uiSource);
+ alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
+
+}
+
+#endif //HAVE_OPENAL
+
diff --git a/Source/Core/AudioCommon/Src/OpenALStream.h b/Source/Core/AudioCommon/Src/OpenALStream.h
index 4624807006..83f9dc1341 100644
--- a/Source/Core/AudioCommon/Src/OpenALStream.h
+++ b/Source/Core/AudioCommon/Src/OpenALStream.h
@@ -1,74 +1,74 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _OPENALSTREAM_H_
-#define _OPENALSTREAM_H_
-
-#include "Common.h"
-#include "SoundStream.h"
-#include "Thread.h"
-
-
-#if defined HAVE_OPENAL && HAVE_OPENAL
-#ifdef _WIN32
-#include "../../../../Externals/OpenAL/include/al.h"
-#include "../../../../Externals/OpenAL/include/alc.h"
-#elif defined(__APPLE__)
-#include "openal/al.h"
-#include "openal/alc.h"
-#else
-#include "AL/al.h"
-#include "AL/alc.h"
-#endif // WIN32
-// public use
-#define SFX_MAX_SOURCE 1
-#define OAL_BUFFER_SIZE 1024*1024
-#endif
-
-
-class OpenALStream: public SoundStream
-{
-#if defined HAVE_OPENAL && HAVE_OPENAL
-public:
- OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
- virtual ~OpenALStream() {};
-
- virtual bool Start();
- virtual void SoundLoop();
- virtual void Stop();
- static bool isValid() { return true; }
- virtual bool usesMixer() const { return true; }
- virtual void Update();
-
- static THREAD_RETURN ThreadFunc(void* args);
-
-private:
- Common::Thread *thread;
- Common::CriticalSection soundCriticalSection;
- Common::Event soundSyncEvent;
-
- short realtimeBuffer[OAL_BUFFER_SIZE];
-#else
-public:
- OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
-#endif // HAVE_OPENAL
-};
-
-
-
-
-#endif // OPENALSTREAM
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _OPENALSTREAM_H_
+#define _OPENALSTREAM_H_
+
+#include "Common.h"
+#include "SoundStream.h"
+#include "Thread.h"
+
+
+#if defined HAVE_OPENAL && HAVE_OPENAL
+#ifdef _WIN32
+#include "../../../../Externals/OpenAL/include/al.h"
+#include "../../../../Externals/OpenAL/include/alc.h"
+#elif defined(__APPLE__)
+#include "openal/al.h"
+#include "openal/alc.h"
+#else
+#include "AL/al.h"
+#include "AL/alc.h"
+#endif // WIN32
+// public use
+#define SFX_MAX_SOURCE 1
+#define OAL_BUFFER_SIZE 1024*1024
+#endif
+
+
+class OpenALStream: public SoundStream
+{
+#if defined HAVE_OPENAL && HAVE_OPENAL
+public:
+ OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
+ virtual ~OpenALStream() {};
+
+ virtual bool Start();
+ virtual void SoundLoop();
+ virtual void Stop();
+ static bool isValid() { return true; }
+ virtual bool usesMixer() const { return true; }
+ virtual void Update();
+
+ static THREAD_RETURN ThreadFunc(void* args);
+
+private:
+ Common::Thread *thread;
+ Common::CriticalSection soundCriticalSection;
+ Common::Event soundSyncEvent;
+
+ short realtimeBuffer[OAL_BUFFER_SIZE];
+#else
+public:
+ OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
+#endif // HAVE_OPENAL
+};
+
+
+
+
+#endif // OPENALSTREAM
diff --git a/Source/Core/AudioCommon/Src/aldlist.cpp b/Source/Core/AudioCommon/Src/aldlist.cpp
index 1992271680..34e9f778d9 100644
--- a/Source/Core/AudioCommon/Src/aldlist.cpp
+++ b/Source/Core/AudioCommon/Src/aldlist.cpp
@@ -1,341 +1,341 @@
-/*
- * Copyright (c) 2006, Creative Labs Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are permitted provided
- * that the following conditions are met:
- *
- * * Redistributions of source code must retain the above copyright notice, this list of conditions and
- * the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
- * and the following disclaimer in the documentation and/or other materials provided with the distribution.
- * * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
- * promote products derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "Common.h"
-#include "aldlist.h"
-#include "../../../../Externals/OpenAL/include/al.h"
-#include "../../../../Externals/OpenAL/include/alc.h"
-
-
-/*
- * Init call
- */
-ALDeviceList::ALDeviceList()
-{
- ALDEVICEINFO ALDeviceInfo;
- char *devices;
- s32 index;
- const char *defaultDeviceName = NULL;
- const char *actualDeviceName = NULL;
-
- // DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
- vDeviceInfo.empty();
- vDeviceInfo.reserve(10);
-
- defaultDeviceIndex = 0;
-
- // grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
- //if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
- if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
- {
- devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
- defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
- index = 0;
- // go through device list (each device terminated with a single NULL, list terminated with double NULL)
- while (devices != NULL && strlen(devices) > 0)
- {
- if (strcmp(defaultDeviceName, devices) == 0)
- {
- defaultDeviceIndex = index;
- }
- ALCdevice *device = alcOpenDevice(devices);
- if (device)
- {
- ALCcontext *context = alcCreateContext(device, NULL);
- if (context)
- {
- alcMakeContextCurrent(context);
- // if new actual device name isn't already in the list, then add it...
- actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
- bool bNewName = true;
- for (s32 i = 0; i < GetNumDevices(); i++)
- {
- if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
- {
- bNewName = false;
- }
- }
- if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
- {
- ALDeviceInfo.bSelected = true;
- ALDeviceInfo.strDeviceName = actualDeviceName;
- alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
- alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
-
- ALDeviceInfo.pvstrExtensions = new vector<string>;
-
- // Check for ALC Extensions
- if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
- if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
-
- // Check for AL Extensions
- if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
-
- if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
- if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
-
- if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
- if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
- if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
- if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
-
- if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
- ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
-
- // Get Source Count
- ALDeviceInfo.uiSourceCount = GetMaxNumSources();
-
- vDeviceInfo.push_back(ALDeviceInfo);
- }
- alcMakeContextCurrent(NULL);
- alcDestroyContext(context);
- }
- alcCloseDevice(device);
- }
- devices += strlen(devices) + 1;
- index += 1;
- }
- }
- //}
-
- ResetFilters();
-}
-
-/*
- * Exit call
- */
-ALDeviceList::~ALDeviceList()
-{
- for (u32 i = 0; i < vDeviceInfo.size(); i++) {
- if (vDeviceInfo[i].pvstrExtensions) {
- vDeviceInfo[i].pvstrExtensions->empty();
- delete vDeviceInfo[i].pvstrExtensions;
- }
- }
-
- vDeviceInfo.empty();
-}
-
-/*
- * Returns the number of devices in the complete device list
- */
-s32 ALDeviceList::GetNumDevices()
-{
- return (s32)vDeviceInfo.size();
-}
-
-/*
- * Returns the device name at an index in the complete device list
- */
-char * ALDeviceList::GetDeviceName(s32 index)
-{
- if (index < GetNumDevices())
- return (char *)vDeviceInfo[index].strDeviceName.c_str();
- else
- return NULL;
-}
-
-/*
- * Returns the major and minor version numbers for a device at a specified index in the complete list
- */
-void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
-{
- if (index < GetNumDevices()) {
- if (major)
- *major = vDeviceInfo[index].iMajorVersion;
- if (minor)
- *minor = vDeviceInfo[index].iMinorVersion;
- }
- return;
-}
-
-/*
- * Returns the maximum number of Sources that can be generate on the given device
- */
-u32 ALDeviceList::GetMaxNumSources(s32 index)
-{
- if (index < GetNumDevices())
- return vDeviceInfo[index].uiSourceCount;
- else
- return 0;
-}
-
-/*
- * Checks if the extension is supported on the given device
- */
-bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
-{
- bool bReturn = false;
-
- if (index < GetNumDevices()) {
- for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
- if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
- bReturn = true;
- break;
- }
- }
- }
-
- return bReturn;
-}
-
-/*
- * returns the index of the default device in the complete device list
- */
-s32 ALDeviceList::GetDefaultDevice()
-{
- return defaultDeviceIndex;
-}
-
-/*
- * Deselects devices which don't have the specified minimum version
- */
-void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
-{
- s32 dMajor = 0, dMinor = 0;
- for (u32 i = 0; i < vDeviceInfo.size(); i++) {
- GetDeviceVersion(i, &dMajor, &dMinor);
- if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
- vDeviceInfo[i].bSelected = false;
- }
- }
-}
-
-/*
- * Deselects devices which don't have the specified maximum version
- */
-void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
-{
- s32 dMajor = 0, dMinor = 0;
- for (u32 i = 0; i < vDeviceInfo.size(); i++) {
- GetDeviceVersion(i, &dMajor, &dMinor);
- if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
- vDeviceInfo[i].bSelected = false;
- }
- }
-}
-
-/*
- * Deselects device which don't support the given extension name
- */
-void ALDeviceList::FilterDevicesExtension(char *szExtName)
-{
- bool bFound;
-
- for (u32 i = 0; i < vDeviceInfo.size(); i++) {
- bFound = false;
- for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
- if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
- bFound = true;
- break;
- }
- }
- if (!bFound)
- vDeviceInfo[i].bSelected = false;
- }
-}
-
-/*
- * Resets all filtering, such that all devices are in the list
- */
-void ALDeviceList::ResetFilters()
-{
- for (s32 i = 0; i < GetNumDevices(); i++) {
- vDeviceInfo[i].bSelected = true;
- }
- filterIndex = 0;
-}
-
-/*
- * Gets index of first filtered device
- */
-s32 ALDeviceList::GetFirstFilteredDevice()
-{
- s32 i;
-
- for (i = 0; i < GetNumDevices(); i++) {
- if (vDeviceInfo[i].bSelected == true) {
- break;
- }
- }
- filterIndex = i + 1;
- return i;
-}
-
-/*
- * Gets index of next filtered device
- */
-s32 ALDeviceList::GetNextFilteredDevice()
-{
- s32 i;
-
- for (i = filterIndex; i < GetNumDevices(); i++) {
- if (vDeviceInfo[i].bSelected == true) {
- break;
- }
- }
- filterIndex = i + 1;
- return i;
-}
-
-/*
- * Internal function to detemine max number of Sources that can be generated
- */
-u32 ALDeviceList::GetMaxNumSources()
-{
- ALuint uiSources[256];
- u32 iSourceCount = 0;
-
- // Clear AL Error Code
- alGetError();
-
- // Generate up to 256 Sources, checking for any errors
- for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
- {
- alGenSources(1, &uiSources[iSourceCount]);
- if (alGetError() != AL_NO_ERROR)
- break;
- }
-
- // Release the Sources
- alDeleteSources(iSourceCount, uiSources);
- if (alGetError() != AL_NO_ERROR)
- {
- for (u32 i = 0; i < 256; i++)
- {
- alDeleteSources(1, &uiSources[i]);
- }
- }
-
- return iSourceCount;
-}
+/*
+ * Copyright (c) 2006, Creative Labs Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and
+ * the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
+ * and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
+ * promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "Common.h"
+#include "aldlist.h"
+#include "../../../../Externals/OpenAL/include/al.h"
+#include "../../../../Externals/OpenAL/include/alc.h"
+
+
+/*
+ * Init call
+ */
+ALDeviceList::ALDeviceList()
+{
+ ALDEVICEINFO ALDeviceInfo;
+ char *devices;
+ s32 index;
+ const char *defaultDeviceName = NULL;
+ const char *actualDeviceName = NULL;
+
+ // DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
+ vDeviceInfo.empty();
+ vDeviceInfo.reserve(10);
+
+ defaultDeviceIndex = 0;
+
+ // grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
+ //if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
+ if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
+ {
+ devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
+ defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
+ index = 0;
+ // go through device list (each device terminated with a single NULL, list terminated with double NULL)
+ while (devices != NULL && strlen(devices) > 0)
+ {
+ if (strcmp(defaultDeviceName, devices) == 0)
+ {
+ defaultDeviceIndex = index;
+ }
+ ALCdevice *device = alcOpenDevice(devices);
+ if (device)
+ {
+ ALCcontext *context = alcCreateContext(device, NULL);
+ if (context)
+ {
+ alcMakeContextCurrent(context);
+ // if new actual device name isn't already in the list, then add it...
+ actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
+ bool bNewName = true;
+ for (s32 i = 0; i < GetNumDevices(); i++)
+ {
+ if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
+ {
+ bNewName = false;
+ }
+ }
+ if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
+ {
+ ALDeviceInfo.bSelected = true;
+ ALDeviceInfo.strDeviceName = actualDeviceName;
+ alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
+ alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
+
+ ALDeviceInfo.pvstrExtensions = new vector<string>;
+
+ // Check for ALC Extensions
+ if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
+ if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
+
+ // Check for AL Extensions
+ if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
+
+ if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
+ if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
+
+ if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
+ if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
+ if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
+ if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
+
+ if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
+ ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
+
+ // Get Source Count
+ ALDeviceInfo.uiSourceCount = GetMaxNumSources();
+
+ vDeviceInfo.push_back(ALDeviceInfo);
+ }
+ alcMakeContextCurrent(NULL);
+ alcDestroyContext(context);
+ }
+ alcCloseDevice(device);
+ }
+ devices += strlen(devices) + 1;
+ index += 1;
+ }
+ }
+ //}
+
+ ResetFilters();
+}
+
+/*
+ * Exit call
+ */
+ALDeviceList::~ALDeviceList()
+{
+ for (u32 i = 0; i < vDeviceInfo.size(); i++) {
+ if (vDeviceInfo[i].pvstrExtensions) {
+ vDeviceInfo[i].pvstrExtensions->empty();
+ delete vDeviceInfo[i].pvstrExtensions;
+ }
+ }
+
+ vDeviceInfo.empty();
+}
+
+/*
+ * Returns the number of devices in the complete device list
+ */
+s32 ALDeviceList::GetNumDevices()
+{
+ return (s32)vDeviceInfo.size();
+}
+
+/*
+ * Returns the device name at an index in the complete device list
+ */
+char * ALDeviceList::GetDeviceName(s32 index)
+{
+ if (index < GetNumDevices())
+ return (char *)vDeviceInfo[index].strDeviceName.c_str();
+ else
+ return NULL;
+}
+
+/*
+ * Returns the major and minor version numbers for a device at a specified index in the complete list
+ */
+void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
+{
+ if (index < GetNumDevices()) {
+ if (major)
+ *major = vDeviceInfo[index].iMajorVersion;
+ if (minor)
+ *minor = vDeviceInfo[index].iMinorVersion;
+ }
+ return;
+}
+
+/*
+ * Returns the maximum number of Sources that can be generate on the given device
+ */
+u32 ALDeviceList::GetMaxNumSources(s32 index)
+{
+ if (index < GetNumDevices())
+ return vDeviceInfo[index].uiSourceCount;
+ else
+ return 0;
+}
+
+/*
+ * Checks if the extension is supported on the given device
+ */
+bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
+{
+ bool bReturn = false;
+
+ if (index < GetNumDevices()) {
+ for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
+ if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
+ bReturn = true;
+ break;
+ }
+ }
+ }
+
+ return bReturn;
+}
+
+/*
+ * returns the index of the default device in the complete device list
+ */
+s32 ALDeviceList::GetDefaultDevice()
+{
+ return defaultDeviceIndex;
+}
+
+/*
+ * Deselects devices which don't have the specified minimum version
+ */
+void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
+{
+ s32 dMajor = 0, dMinor = 0;
+ for (u32 i = 0; i < vDeviceInfo.size(); i++) {
+ GetDeviceVersion(i, &dMajor, &dMinor);
+ if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
+ vDeviceInfo[i].bSelected = false;
+ }
+ }
+}
+
+/*
+ * Deselects devices which don't have the specified maximum version
+ */
+void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
+{
+ s32 dMajor = 0, dMinor = 0;
+ for (u32 i = 0; i < vDeviceInfo.size(); i++) {
+ GetDeviceVersion(i, &dMajor, &dMinor);
+ if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
+ vDeviceInfo[i].bSelected = false;
+ }
+ }
+}
+
+/*
+ * Deselects device which don't support the given extension name
+ */
+void ALDeviceList::FilterDevicesExtension(char *szExtName)
+{
+ bool bFound;
+
+ for (u32 i = 0; i < vDeviceInfo.size(); i++) {
+ bFound = false;
+ for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
+ if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
+ bFound = true;
+ break;
+ }
+ }
+ if (!bFound)
+ vDeviceInfo[i].bSelected = false;
+ }
+}
+
+/*
+ * Resets all filtering, such that all devices are in the list
+ */
+void ALDeviceList::ResetFilters()
+{
+ for (s32 i = 0; i < GetNumDevices(); i++) {
+ vDeviceInfo[i].bSelected = true;
+ }
+ filterIndex = 0;
+}
+
+/*
+ * Gets index of first filtered device
+ */
+s32 ALDeviceList::GetFirstFilteredDevice()
+{
+ s32 i;
+
+ for (i = 0; i < GetNumDevices(); i++) {
+ if (vDeviceInfo[i].bSelected == true) {
+ break;
+ }
+ }
+ filterIndex = i + 1;
+ return i;
+}
+
+/*
+ * Gets index of next filtered device
+ */
+s32 ALDeviceList::GetNextFilteredDevice()
+{
+ s32 i;
+
+ for (i = filterIndex; i < GetNumDevices(); i++) {
+ if (vDeviceInfo[i].bSelected == true) {
+ break;
+ }
+ }
+ filterIndex = i + 1;
+ return i;
+}
+
+/*
+ * Internal function to detemine max number of Sources that can be generated
+ */
+u32 ALDeviceList::GetMaxNumSources()
+{
+ ALuint uiSources[256];
+ u32 iSourceCount = 0;
+
+ // Clear AL Error Code
+ alGetError();
+
+ // Generate up to 256 Sources, checking for any errors
+ for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
+ {
+ alGenSources(1, &uiSources[iSourceCount]);
+ if (alGetError() != AL_NO_ERROR)
+ break;
+ }
+
+ // Release the Sources
+ alDeleteSources(iSourceCount, uiSources);
+ if (alGetError() != AL_NO_ERROR)
+ {
+ for (u32 i = 0; i < 256; i++)
+ {
+ alDeleteSources(1, &uiSources[i]);
+ }
+ }
+
+ return iSourceCount;
+}
diff --git a/Source/Core/AudioCommon/Src/aldlist.h b/Source/Core/AudioCommon/Src/aldlist.h
index cea2fe41f6..645b759660 100644
--- a/Source/Core/AudioCommon/Src/aldlist.h
+++ b/Source/Core/AudioCommon/Src/aldlist.h
@@ -1,51 +1,51 @@
-#ifndef ALDEVICELIST_H
-#define ALDEVICELIST_H
-
-#include "CommonTypes.h"
-#ifdef _WIN32
-#pragma warning(disable: 4786) //disable warning "identifier was truncated to
- //'255' characters in the browser information"
-#endif
-#include <vector>
-#include <string>
-
-using namespace std;
-
-typedef struct
-{
- string strDeviceName;
- s32 iMajorVersion;
- s32 iMinorVersion;
- u32 uiSourceCount;
- vector<string> *pvstrExtensions;
- bool bSelected;
-} ALDEVICEINFO, *LPALDEVICEINFO;
-
-class ALDeviceList
-{
-private:
- vector<ALDEVICEINFO> vDeviceInfo;
- s32 defaultDeviceIndex;
- s32 filterIndex;
-
-public:
- ALDeviceList ();
- ~ALDeviceList ();
- s32 GetNumDevices();
- char *GetDeviceName(s32 index);
- void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
- u32 GetMaxNumSources(s32 index);
- bool IsExtensionSupported(s32 index, char *szExtName);
- s32 GetDefaultDevice();
- void FilterDevicesMinVer(s32 major, s32 minor);
- void FilterDevicesMaxVer(s32 major, s32 minor);
- void FilterDevicesExtension(char *szExtName);
- void ResetFilters();
- s32 GetFirstFilteredDevice();
- s32 GetNextFilteredDevice();
-
-private:
- u32 GetMaxNumSources();
-};
-
-#endif // ALDEVICELIST_H
+#ifndef ALDEVICELIST_H
+#define ALDEVICELIST_H
+
+#include "CommonTypes.h"
+#ifdef _WIN32
+#pragma warning(disable: 4786) //disable warning "identifier was truncated to
+ //'255' characters in the browser information"
+#endif
+#include <vector>
+#include <string>
+
+using namespace std;
+
+typedef struct
+{
+ string strDeviceName;
+ s32 iMajorVersion;
+ s32 iMinorVersion;
+ u32 uiSourceCount;
+ vector<string> *pvstrExtensions;
+ bool bSelected;
+} ALDEVICEINFO, *LPALDEVICEINFO;
+
+class ALDeviceList
+{
+private:
+ vector<ALDEVICEINFO> vDeviceInfo;
+ s32 defaultDeviceIndex;
+ s32 filterIndex;
+
+public:
+ ALDeviceList ();
+ ~ALDeviceList ();
+ s32 GetNumDevices();
+ char *GetDeviceName(s32 index);
+ void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
+ u32 GetMaxNumSources(s32 index);
+ bool IsExtensionSupported(s32 index, char *szExtName);
+ s32 GetDefaultDevice();
+ void FilterDevicesMinVer(s32 major, s32 minor);
+ void FilterDevicesMaxVer(s32 major, s32 minor);
+ void FilterDevicesExtension(char *szExtName);
+ void ResetFilters();
+ s32 GetFirstFilteredDevice();
+ s32 GetNextFilteredDevice();
+
+private:
+ u32 GetMaxNumSources();
+};
+
+#endif // ALDEVICELIST_H
diff --git a/Source/Core/Common/Src/SymbolDB.cpp b/Source/Core/Common/Src/SymbolDB.cpp
index 86161b6b9c..7752b484e2 100644
--- a/Source/Core/Common/Src/SymbolDB.cpp
+++ b/Source/Core/Common/Src/SymbolDB.cpp
@@ -1,59 +1,59 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// 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 "SymbolDB.h"
-
-
-void SymbolDB::List()
-{
- for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
- {
- DEBUG_LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
- }
- INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
-}
-
-void SymbolDB::Clear(const char *prefix)
-{
- // TODO: honor prefix
- functions.clear();
- checksumToFunction.clear();
-}
-
-void SymbolDB::Index()
-{
- int i = 0;
- for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
- {
- iter->second.index = i++;
- }
-}
-
-Symbol *SymbolDB::GetSymbolFromName(const char *name)
-{
- for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
- {
- if (!strcmp(iter->second.name.c_str(), name))
- return &iter->second;
- }
- return 0;
-}
-
-void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
-{
- functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
-}
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// 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 "SymbolDB.h"
+
+
+void SymbolDB::List()
+{
+ for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
+ {
+ DEBUG_LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
+ }
+ INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
+}
+
+void SymbolDB::Clear(const char *prefix)
+{
+ // TODO: honor prefix
+ functions.clear();
+ checksumToFunction.clear();
+}
+
+void SymbolDB::Index()
+{
+ int i = 0;
+ for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
+ {
+ iter->second.index = i++;
+ }
+}
+
+Symbol *SymbolDB::GetSymbolFromName(const char *name)
+{
+ for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
+ {
+ if (!strcmp(iter->second.name.c_str(), name))
+ return &iter->second;
+ }
+ return 0;
+}
+
+void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
+{
+ functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
+}
diff --git a/Source/Core/Common/Src/SymbolDB.h b/Source/Core/Common/Src/SymbolDB.h
index dc6ba56f23..41d22a0b44 100644
--- a/Source/Core/Common/Src/SymbolDB.h
+++ b/Source/Core/Common/Src/SymbolDB.h
@@ -1,122 +1,122 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// 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/
-
-
-// This file contains a generic symbol map implementation. For CPU-specific
-// magic, derive and extend.
-
-#ifndef _SYMBOL_DB_H
-#define _SYMBOL_DB_H
-
-#include <string>
-#include <map>
-
-#include "Common.h"
-
-struct SCall
-{
- SCall(u32 a, u32 b) :
- function(a),
- callAddress(b)
- {}
- u32 function;
- u32 callAddress;
-};
-
-struct Symbol
-{
- enum {
- SYMBOL_FUNCTION = 0,
- SYMBOL_DATA = 1,
- };
-
- Symbol() :
- hash(0),
- address(0),
- flags(0),
- size(0),
- numCalls(0),
- type(SYMBOL_FUNCTION),
- analyzed(0)
- {}
-
- std::string name;
- std::vector<SCall> callers; //addresses of functions that call this function
- std::vector<SCall> calls; //addresses of functions that are called by this function
- u32 hash; //use for HLE function finding
- u32 address;
- u32 flags;
- int size;
- int numCalls;
- int type;
- int index; // only used for coloring the disasm view
- int analyzed;
-};
-
-enum
-{
- FFLAG_TIMERINSTRUCTIONS=(1<<0),
- FFLAG_LEAF=(1<<1),
- FFLAG_ONLYCALLSNICELEAFS=(1<<2),
- FFLAG_EVIL=(1<<3),
- FFLAG_RFI=(1<<4),
- FFLAG_STRAIGHT=(1<<5)
-};
-
-
-
-class SymbolDB
-{
-public:
- typedef std::map<u32, Symbol> XFuncMap;
- typedef std::map<u32, Symbol*> XFuncPtrMap;
-
-protected:
- XFuncMap functions;
- XFuncPtrMap checksumToFunction;
-
-public:
- SymbolDB() {}
- virtual ~SymbolDB() {}
- virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
- virtual Symbol *AddFunction(u32 startAddr) { return 0;}
-
- void AddCompleteSymbol(const Symbol &symbol);
-
- Symbol *GetSymbolFromName(const char *name);
- Symbol *GetSymbolFromHash(u32 hash) {
- XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
- if (iter != checksumToFunction.end())
- return iter->second;
- else
- return 0;
- }
-
- const XFuncMap &Symbols() const {return functions;}
- XFuncMap &AccessSymbols() {return functions;}
-
- // deprecated
- XFuncMap::iterator GetIterator() { return functions.begin(); }
- XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
- XFuncMap::iterator End() { return functions.end(); }
-
- void Clear(const char *prefix = "");
- void List();
- void Index();
-};
-
-#endif
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// 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/
+
+
+// This file contains a generic symbol map implementation. For CPU-specific
+// magic, derive and extend.
+
+#ifndef _SYMBOL_DB_H
+#define _SYMBOL_DB_H
+
+#include <string>
+#include <map>
+
+#include "Common.h"
+
+struct SCall
+{
+ SCall(u32 a, u32 b) :
+ function(a),
+ callAddress(b)
+ {}
+ u32 function;
+ u32 callAddress;
+};
+
+struct Symbol
+{
+ enum {
+ SYMBOL_FUNCTION = 0,
+ SYMBOL_DATA = 1,
+ };
+
+ Symbol() :
+ hash(0),
+ address(0),
+ flags(0),
+ size(0),
+ numCalls(0),
+ type(SYMBOL_FUNCTION),
+ analyzed(0)
+ {}
+
+ std::string name;
+ std::vector<SCall> callers; //addresses of functions that call this function
+ std::vector<SCall> calls; //addresses of functions that are called by this function
+ u32 hash; //use for HLE function finding
+ u32 address;
+ u32 flags;
+ int size;
+ int numCalls;
+ int type;
+ int index; // only used for coloring the disasm view
+ int analyzed;
+};
+
+enum
+{
+ FFLAG_TIMERINSTRUCTIONS=(1<<0),
+ FFLAG_LEAF=(1<<1),
+ FFLAG_ONLYCALLSNICELEAFS=(1<<2),
+ FFLAG_EVIL=(1<<3),
+ FFLAG_RFI=(1<<4),
+ FFLAG_STRAIGHT=(1<<5)
+};
+
+
+
+class SymbolDB
+{
+public:
+ typedef std::map<u32, Symbol> XFuncMap;
+ typedef std::map<u32, Symbol*> XFuncPtrMap;
+
+protected:
+ XFuncMap functions;
+ XFuncPtrMap checksumToFunction;
+
+public:
+ SymbolDB() {}
+ virtual ~SymbolDB() {}
+ virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
+ virtual Symbol *AddFunction(u32 startAddr) { return 0;}
+
+ void AddCompleteSymbol(const Symbol &symbol);
+
+ Symbol *GetSymbolFromName(const char *name);
+ Symbol *GetSymbolFromHash(u32 hash) {
+ XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
+ if (iter != checksumToFunction.end())
+ return iter->second;
+ else
+ return 0;
+ }
+
+ const XFuncMap &Symbols() const {return functions;}
+ XFuncMap &AccessSymbols() {return functions;}
+
+ // deprecated
+ XFuncMap::iterator GetIterator() { return functions.begin(); }
+ XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
+ XFuncMap::iterator End() { return functions.end(); }
+
+ void Clear(const char *prefix = "");
+ void List();
+ void Index();
+};
+
+#endif
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_apple.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_apple.h
index dd69c3f751..e6aeadca75 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_apple.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_apple.h
@@ -1,24 +1,24 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
-//Add support for apple keycodes
-};
-
-u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
-//Add support for apple keycodes
-};
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
+//Add support for apple keycodes
+};
+
+u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
+//Add support for apple keycodes
+};
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_linux.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_linux.h
index a451184ac1..80b7a093e5 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_linux.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_linux.h
@@ -1,25 +1,25 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
-//Add support for Linux keycodes
-};
-
-u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
-//Add support for Linux keycodes
-};
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
+//Add support for Linux keycodes
+};
+
+u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
+//Add support for Linux keycodes
+};
+
diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_win32.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_win32.h
index 9cb31e31b4..1b7e06724c 100644
--- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_win32.h
+++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_Usb_Kbd_win32.h
@@ -1,192 +1,192 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2A, // Backspace
- 0x2B, // Tab
- 0x00, 0x00,
- 0x00, // Clear
- 0x28, // Return
- 0x00, 0x00,
- 0x00, // Shift
- 0x00, // Control
- 0x00, // ALT
- 0x48, // Pause
- 0x39, // Capital
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x29, // Escape
- 0x00, 0x00, 0x00, 0x00,
- 0x2C, // Space
- 0x4B, // Prior
- 0x4E, // Next
- 0x4D, // End
- 0x4A, // Home
- 0x50, // Left
- 0x52, // Up
- 0x4F, // Right
- 0x51, // Down
- 0x00, 0x00, 0x00,
- 0x46, // Print screen
- 0x49, // Insert
- 0x4C, // Delete
- 0x00,
- // 0 -> 9
- 0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00,
- // A -> Z
- 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
- 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
- 0x1C, 0x1D,
- 0x00, 0x00, 0x00, 0x00,
- 0x00,
- // Numpad 0 -> 9
- 0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61,
- 0x55, // Multiply
- 0x57, // Add
- 0x00, // Separator
- 0x56, // Substract
- 0x63, // Decimal
- 0x54, // Divide
- // F1 -> F12
- 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
- 0x42, 0x43, 0x44, 0x45,
- // F13 -> F24
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x53, // Numlock
- 0x47, // Scroll lock
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Modifier keys
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x33, // ';'
- 0x2E, // Plus
- 0x36, // Comma
- 0x2D, // Minus
- 0x37, // Period
- 0x38, // '/'
- 0x35, // '~'
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
- 0x2F, // '['
- 0x32, // '\'
- 0x30, // ']'
- 0x34, // '''
- 0x00, //
- 0x00, // Nothing interesting past this point.
-
-};
-
-u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x2A, // Backspace
- 0x2B, // Tab
- 0x00, 0x00,
- 0x00, // Clear
- 0x28, // Return
- 0x00, 0x00,
- 0x00, // Shift
- 0x00, // Control
- 0x00, // ALT
- 0x48, // Pause
- 0x39, // Capital
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x29, // Escape
- 0x00, 0x00, 0x00, 0x00,
- 0x2C, // Space
- 0x4B, // Prior
- 0x4E, // Next
- 0x4D, // End
- 0x4A, // Home
- 0x50, // Left
- 0x52, // Up
- 0x4F, // Right
- 0x51, // Down
- 0x00, 0x00, 0x00,
- 0x46, // Print screen
- 0x49, // Insert
- 0x4C, // Delete
- 0x00,
- // 0 -> 9
- 0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
- 0x25, 0x26,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00,
- // A -> Z
- 0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
- 0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
- 0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
- 0x1C, 0x1A,
- 0x00, 0x00, 0x00, 0x00,
- 0x00,
- // Numpad 0 -> 9
- 0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
- 0x60, 0x61,
- 0x55, // Multiply
- 0x57, // Add
- 0x00, // Separator
- 0x56, // Substract
- 0x63, // Decimal
- 0x54, // Divide
- // F1 -> F12
- 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
- 0x42, 0x43, 0x44, 0x45,
- // F13 -> F24
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x53, // Numlock
- 0x47, // Scroll lock
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- // Modifier keys
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x30, // '$'
- 0x2E, // Plus
- 0x10, // Comma
- 0x00, // Minus
- 0x36, // Period
- 0x37, // '/'
- 0x34, // 'ù'
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00,
- 0x2D, // ')'
- 0x32, // '\'
- 0x2F, // '^'
- 0x00, // '²'
- 0x38, // '!'
- 0x00, // Nothing interesting past this point.
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2A, // Backspace
+ 0x2B, // Tab
+ 0x00, 0x00,
+ 0x00, // Clear
+ 0x28, // Return
+ 0x00, 0x00,
+ 0x00, // Shift
+ 0x00, // Control
+ 0x00, // ALT
+ 0x48, // Pause
+ 0x39, // Capital
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x29, // Escape
+ 0x00, 0x00, 0x00, 0x00,
+ 0x2C, // Space
+ 0x4B, // Prior
+ 0x4E, // Next
+ 0x4D, // End
+ 0x4A, // Home
+ 0x50, // Left
+ 0x52, // Up
+ 0x4F, // Right
+ 0x51, // Down
+ 0x00, 0x00, 0x00,
+ 0x46, // Print screen
+ 0x49, // Insert
+ 0x4C, // Delete
+ 0x00,
+ // 0 -> 9
+ 0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+ // A -> Z
+ 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
+ 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
+ 0x1C, 0x1D,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+ // Numpad 0 -> 9
+ 0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61,
+ 0x55, // Multiply
+ 0x57, // Add
+ 0x00, // Separator
+ 0x56, // Substract
+ 0x63, // Decimal
+ 0x54, // Divide
+ // F1 -> F12
+ 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
+ 0x42, 0x43, 0x44, 0x45,
+ // F13 -> F24
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x53, // Numlock
+ 0x47, // Scroll lock
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Modifier keys
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x33, // ';'
+ 0x2E, // Plus
+ 0x36, // Comma
+ 0x2D, // Minus
+ 0x37, // Period
+ 0x38, // '/'
+ 0x35, // '~'
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+ 0x2F, // '['
+ 0x32, // '\'
+ 0x30, // ']'
+ 0x34, // '''
+ 0x00, //
+ 0x00, // Nothing interesting past this point.
+
+};
+
+u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
+
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2A, // Backspace
+ 0x2B, // Tab
+ 0x00, 0x00,
+ 0x00, // Clear
+ 0x28, // Return
+ 0x00, 0x00,
+ 0x00, // Shift
+ 0x00, // Control
+ 0x00, // ALT
+ 0x48, // Pause
+ 0x39, // Capital
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x29, // Escape
+ 0x00, 0x00, 0x00, 0x00,
+ 0x2C, // Space
+ 0x4B, // Prior
+ 0x4E, // Next
+ 0x4D, // End
+ 0x4A, // Home
+ 0x50, // Left
+ 0x52, // Up
+ 0x4F, // Right
+ 0x51, // Down
+ 0x00, 0x00, 0x00,
+ 0x46, // Print screen
+ 0x49, // Insert
+ 0x4C, // Delete
+ 0x00,
+ // 0 -> 9
+ 0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
+ 0x25, 0x26,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+ // A -> Z
+ 0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
+ 0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
+ 0x1C, 0x1A,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+ // Numpad 0 -> 9
+ 0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61,
+ 0x55, // Multiply
+ 0x57, // Add
+ 0x00, // Separator
+ 0x56, // Substract
+ 0x63, // Decimal
+ 0x54, // Divide
+ // F1 -> F12
+ 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
+ 0x42, 0x43, 0x44, 0x45,
+ // F13 -> F24
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x53, // Numlock
+ 0x47, // Scroll lock
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ // Modifier keys
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x30, // '$'
+ 0x2E, // Plus
+ 0x10, // Comma
+ 0x00, // Minus
+ 0x36, // Period
+ 0x37, // '/'
+ 0x34, // 'ù'
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00,
+ 0x2D, // ')'
+ 0x32, // '\'
+ 0x2F, // '^'
+ 0x00, // '²'
+ 0x38, // '!'
+ 0x00, // Nothing interesting past this point.
+
}; \ No newline at end of file
diff --git a/Source/Core/DSPCore/Src/DSPAnalyzer.cpp b/Source/Core/DSPCore/Src/DSPAnalyzer.cpp
index db08157299..e851d44ba0 100644
--- a/Source/Core/DSPCore/Src/DSPAnalyzer.cpp
+++ b/Source/Core/DSPCore/Src/DSPAnalyzer.cpp
@@ -1,133 +1,133 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "DSPAnalyzer.h"
-#include "DSPInterpreter.h"
-#include "DSPTables.h"
-#include "DSPMemoryMap.h"
-
-namespace DSPAnalyzer {
-
-// Holds data about all instructions in RAM.
-u8 code_flags[ISPACE];
-
-// Good candidates for idle skipping is mail wait loops. If we're time slicing
-// between the main CPU and the DSP, if the DSP runs into one of these, it might
-// as well give up its time slice immediately, after executing once.
-
-// Max signature length is 6. A 0 in a signature is ignored.
-#define NUM_IDLE_SIGS 5
-#define MAX_IDLE_SIG_SIZE 6
-
-// 0xFFFF means ignore.
-const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
-{
- // From AX:
- { 0x26fc, // LRS $30, @DMBH
- 0x02c0, 0x8000, // ANDCF $30, #0x8000
- 0x029d, 0xFFFF, // JLZ 0x027a
- 0, 0 }, // RET
- { 0x27fc, // LRS $31, @DMBH
- 0x03c0, 0x8000, // ANDCF $31, #0x8000
- 0x029d, 0xFFFF, // JLZ 0x027a
- 0, 0 }, // RET
- { 0x26fe, // LRS $30, @CMBH
- 0x02c0, 0x8000, // ANDCF $30, #0x8000
- 0x029c, 0xFFFF, // JLNZ 0x0280
- 0, 0 }, // RET
- { 0x27fe, // LRS $31, @CMBH
- 0x03c0, 0x8000, // ANDCF $31, #0x8000
- 0x029c, 0xFFFF, // JLNZ 0x0280
- 0, 0 }, // RET
-
- // From Zelda:
- { 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
- 0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
- 0x029c, 0xFFFF, // JLNZ 0x05cf
- 0 }
-};
-
-void Reset()
-{
- memset(code_flags, 0, sizeof(code_flags));
-}
-
-void AnalyzeRange(int start_addr, int end_addr)
-{
- // First we run an extremely simplified version of a disassembler to find
- // where all instructions start.
-
- // This may not be 100% accurate in case of jump tables!
- // It could get desynced, which would be bad. We'll see if that's an issue.
- int addr = start_addr;
- while (addr < end_addr)
- {
- UDSPInstruction inst = dsp_imem_read(addr);
- const DSPOPCTemplate *opcode = GetOpTemplate(inst);
- if (!opcode)
- {
- addr++;
- continue;
- }
- code_flags[addr] |= CODE_START_OF_INST;
- addr += opcode->size;
-
- // Look for loops.
- if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
- // BLOOP, BLOOPI
- u16 loop_end = dsp_imem_read(addr + 1);
- code_flags[loop_end] |= CODE_LOOP_END;
- } else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
- // LOOP, LOOPI
- code_flags[addr + 1] |= CODE_LOOP_END;
- }
- }
-
- // Next, we'll scan for potential idle skips.
- for (int s = 0; s < NUM_IDLE_SIGS; s++)
- {
- for (int addr = start_addr; addr < end_addr; addr++)
- {
- bool found = false;
- for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
- {
- if (idle_skip_sigs[s][i] == 0)
- found = true;
- if (idle_skip_sigs[s][i] == 0xFFFF)
- continue;
- if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
- break;
- }
- if (found)
- {
- NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
- code_flags[addr] |= CODE_IDLE_SKIP;
- // TODO: actually use this flag somewhere.
- }
- }
- }
- NOTICE_LOG(DSPLLE, "Finished analysis.");
-}
-
-void Analyze()
-{
- Reset();
- AnalyzeRange(0x0000, 0x1000); // IRAM
- AnalyzeRange(0x8000, 0x9000); // IROM
-}
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "DSPAnalyzer.h"
+#include "DSPInterpreter.h"
+#include "DSPTables.h"
+#include "DSPMemoryMap.h"
+
+namespace DSPAnalyzer {
+
+// Holds data about all instructions in RAM.
+u8 code_flags[ISPACE];
+
+// Good candidates for idle skipping is mail wait loops. If we're time slicing
+// between the main CPU and the DSP, if the DSP runs into one of these, it might
+// as well give up its time slice immediately, after executing once.
+
+// Max signature length is 6. A 0 in a signature is ignored.
+#define NUM_IDLE_SIGS 5
+#define MAX_IDLE_SIG_SIZE 6
+
+// 0xFFFF means ignore.
+const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
+{
+ // From AX:
+ { 0x26fc, // LRS $30, @DMBH
+ 0x02c0, 0x8000, // ANDCF $30, #0x8000
+ 0x029d, 0xFFFF, // JLZ 0x027a
+ 0, 0 }, // RET
+ { 0x27fc, // LRS $31, @DMBH
+ 0x03c0, 0x8000, // ANDCF $31, #0x8000
+ 0x029d, 0xFFFF, // JLZ 0x027a
+ 0, 0 }, // RET
+ { 0x26fe, // LRS $30, @CMBH
+ 0x02c0, 0x8000, // ANDCF $30, #0x8000
+ 0x029c, 0xFFFF, // JLNZ 0x0280
+ 0, 0 }, // RET
+ { 0x27fe, // LRS $31, @CMBH
+ 0x03c0, 0x8000, // ANDCF $31, #0x8000
+ 0x029c, 0xFFFF, // JLNZ 0x0280
+ 0, 0 }, // RET
+
+ // From Zelda:
+ { 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
+ 0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
+ 0x029c, 0xFFFF, // JLNZ 0x05cf
+ 0 }
+};
+
+void Reset()
+{
+ memset(code_flags, 0, sizeof(code_flags));
+}
+
+void AnalyzeRange(int start_addr, int end_addr)
+{
+ // First we run an extremely simplified version of a disassembler to find
+ // where all instructions start.
+
+ // This may not be 100% accurate in case of jump tables!
+ // It could get desynced, which would be bad. We'll see if that's an issue.
+ int addr = start_addr;
+ while (addr < end_addr)
+ {
+ UDSPInstruction inst = dsp_imem_read(addr);
+ const DSPOPCTemplate *opcode = GetOpTemplate(inst);
+ if (!opcode)
+ {
+ addr++;
+ continue;
+ }
+ code_flags[addr] |= CODE_START_OF_INST;
+ addr += opcode->size;
+
+ // Look for loops.
+ if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
+ // BLOOP, BLOOPI
+ u16 loop_end = dsp_imem_read(addr + 1);
+ code_flags[loop_end] |= CODE_LOOP_END;
+ } else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
+ // LOOP, LOOPI
+ code_flags[addr + 1] |= CODE_LOOP_END;
+ }
+ }
+
+ // Next, we'll scan for potential idle skips.
+ for (int s = 0; s < NUM_IDLE_SIGS; s++)
+ {
+ for (int addr = start_addr; addr < end_addr; addr++)
+ {
+ bool found = false;
+ for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
+ {
+ if (idle_skip_sigs[s][i] == 0)
+ found = true;
+ if (idle_skip_sigs[s][i] == 0xFFFF)
+ continue;
+ if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
+ break;
+ }
+ if (found)
+ {
+ NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
+ code_flags[addr] |= CODE_IDLE_SKIP;
+ // TODO: actually use this flag somewhere.
+ }
+ }
+ }
+ NOTICE_LOG(DSPLLE, "Finished analysis.");
+}
+
+void Analyze()
+{
+ Reset();
+ AnalyzeRange(0x0000, 0x1000); // IRAM
+ AnalyzeRange(0x8000, 0x9000); // IROM
+}
+
+} // namespace
diff --git a/Source/Core/DSPCore/Src/DSPAnalyzer.h b/Source/Core/DSPCore/Src/DSPAnalyzer.h
index 1b29ede4af..65b83a205b 100644
--- a/Source/Core/DSPCore/Src/DSPAnalyzer.h
+++ b/Source/Core/DSPCore/Src/DSPAnalyzer.h
@@ -1,49 +1,49 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Basic code analysis.
-
-#include "DSPInterpreter.h"
-
-namespace DSPAnalyzer {
-
-#define ISPACE 65536
-
-// Useful things to detect:
-// * Loop endpoints - so that we can avoid checking for loops every cycle.
-
-enum
-{
- CODE_START_OF_INST = 1,
- CODE_IDLE_SKIP = 2,
- CODE_LOOP_END = 4,
-};
-
-// Easy to query array covering the whole of instruction memory.
-// Just index by address.
-// This one will be helpful for debuggers and jits.
-extern u8 code_flags[ISPACE];
-
-// This one should be called every time IRAM changes - which is basically
-// every time that a new ucode gets uploaded, and never else. At that point,
-// we can do as much static analysis as we want - but we should always throw
-// all old analysis away. Luckily the entire address space is only 64K code
-// words and the actual code space 8K instructions in total, so we can do
-// some pretty expensive analysis if necessary.
-void Analyze();
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Basic code analysis.
+
+#include "DSPInterpreter.h"
+
+namespace DSPAnalyzer {
+
+#define ISPACE 65536
+
+// Useful things to detect:
+// * Loop endpoints - so that we can avoid checking for loops every cycle.
+
+enum
+{
+ CODE_START_OF_INST = 1,
+ CODE_IDLE_SKIP = 2,
+ CODE_LOOP_END = 4,
+};
+
+// Easy to query array covering the whole of instruction memory.
+// Just index by address.
+// This one will be helpful for debuggers and jits.
+extern u8 code_flags[ISPACE];
+
+// This one should be called every time IRAM changes - which is basically
+// every time that a new ucode gets uploaded, and never else. At that point,
+// we can do as much static analysis as we want - but we should always throw
+// all old analysis away. Luckily the entire address space is only 64K code
+// words and the actual code space 8K instructions in total, so we can do
+// some pretty expensive analysis if necessary.
+void Analyze();
+
+} // namespace
diff --git a/Source/Core/DSPCore/Src/DSPBreakpoints.cpp b/Source/Core/DSPCore/Src/DSPBreakpoints.cpp
index ec48a249fc..0d1537ed1d 100644
--- a/Source/Core/DSPCore/Src/DSPBreakpoints.cpp
+++ b/Source/Core/DSPCore/Src/DSPBreakpoints.cpp
@@ -1,19 +1,19 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "DSPBreakpoints.h"
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "DSPBreakpoints.h"
+
diff --git a/Source/Core/DSPCore/Src/DSPBreakpoints.h b/Source/Core/DSPCore/Src/DSPBreakpoints.h
index 98ff5f609d..752c1f9080 100644
--- a/Source/Core/DSPCore/Src/DSPBreakpoints.h
+++ b/Source/Core/DSPCore/Src/DSPBreakpoints.h
@@ -1,63 +1,63 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _DSP_BREAKPOINTS
-#define _DSP_BREAKPOINTS
-
-#include "Common.h"
-
-// super fast breakpoints for a limited range.
-// To be used interchangably with the BreakPoints class.
-class DSPBreakpoints
-{
-public:
- DSPBreakpoints() {Clear();}
- // is address breakpoint
- bool IsAddressBreakPoint(u32 addr) {
- return b[addr] != 0;
- }
-
- // AddBreakPoint
- bool Add(u32 addr, bool temp=false) {
- bool was_one = b[addr] != 0;
- if (!was_one) {
- b[addr] = temp ? 2 : 1;
- return true;
- } else {
- return false;
- }
- }
- // Remove Breakpoint
- bool Remove(u32 addr) {
- bool was_one = b[addr] != 0;
- b[addr] = 0;
- return was_one;
- }
- void Clear() {
- for (int i = 0; i < 65536; i++)
- b[i] = 0;
- }
-
- void DeleteByAddress(u32 addr) {
- b[addr] = 0;
- }
-
-private:
- u8 b[65536];
-};
-
-#endif
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _DSP_BREAKPOINTS
+#define _DSP_BREAKPOINTS
+
+#include "Common.h"
+
+// super fast breakpoints for a limited range.
+// To be used interchangably with the BreakPoints class.
+class DSPBreakpoints
+{
+public:
+ DSPBreakpoints() {Clear();}
+ // is address breakpoint
+ bool IsAddressBreakPoint(u32 addr) {
+ return b[addr] != 0;
+ }
+
+ // AddBreakPoint
+ bool Add(u32 addr, bool temp=false) {
+ bool was_one = b[addr] != 0;
+ if (!was_one) {
+ b[addr] = temp ? 2 : 1;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ // Remove Breakpoint
+ bool Remove(u32 addr) {
+ bool was_one = b[addr] != 0;
+ b[addr] = 0;
+ return was_one;
+ }
+ void Clear() {
+ for (int i = 0; i < 65536; i++)
+ b[i] = 0;
+ }
+
+ void DeleteByAddress(u32 addr) {
+ b[addr] = 0;
+ }
+
+private:
+ u8 b[65536];
+};
+
+#endif
diff --git a/Source/Core/DSPCore/Src/DSPCodeUtil.cpp b/Source/Core/DSPCore/Src/DSPCodeUtil.cpp
index 3f81b67e04..d0dd510949 100644
--- a/Source/Core/DSPCore/Src/DSPCodeUtil.cpp
+++ b/Source/Core/DSPCore/Src/DSPCodeUtil.cpp
@@ -1,235 +1,235 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 <iostream>
-#include <vector>
-
-#include "Common.h"
-#include "FileUtil.h"
-#include "StringUtil.h"
-#include "DSPCodeUtil.h"
-#include "assemble.h"
-#include "disassemble.h"
-
-
-bool Assemble(const char *text, std::vector<u16> &code)
-{
- AssemblerSettings settings;
- settings.pc = 0;
- // settings.decode_registers = false;
- // settings.decode_names = false;
- settings.print_tabs = false;
- settings.ext_separator = '\'';
-
- // TODO: fix the terrible api of the assembler.
- DSPAssembler assembler(settings);
- if (!assembler.Assemble(text, code)) {
- std::cerr << assembler.GetErrorString() << std::endl;
- return false;
- }
-
- return true;
-}
-
-bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
-{
- if (code.empty())
- return false;
-
- AssemblerSettings settings;
-
- // These two prevent roundtripping.
- settings.show_hex = false;
- settings.show_pc = line_numbers;
- settings.ext_separator = '\'';
- settings.decode_names = false;
- settings.decode_registers = true;
-
- DSPDisassembler disasm(settings);
- bool success = disasm.Disassemble(0, code, 0x0000, text);
- return success;
-}
-
-bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
-{
- if (code1.size() != code2.size())
- printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
- u32 count_equal = 0;
- const int min_size = (int)std::min(code1.size(), code2.size());
-
- AssemblerSettings settings;
- DSPDisassembler disassembler(settings);
- for (int i = 0; i < min_size; i++)
- {
- if (code1[i] == code2[i])
- count_equal++;
- else
- {
- std::string line1, line2;
- u16 pc = i;
- disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
- pc = i;
- disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
- printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
- }
- }
- if (code2.size() != code1.size())
- {
- printf("Extra code words:\n");
- const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
- for (int i = min_size; i < (int)longest.size(); i++)
- {
- u16 pc = i;
- std::string line;
- disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
- printf("!! %s\n", line.c_str());
- }
- }
- printf("Equal instruction words: %i / %i\n", count_equal, min_size);
- return code1.size() == code2.size() && code1.size() == count_equal;
-}
-
-void GenRandomCode(int size, std::vector<u16> &code)
-{
- code.resize(size);
- for (int i = 0; i < size; i++)
- {
- code[i] = rand() ^ (rand() << 8);
- }
-}
-
-void CodeToHeader(const std::vector<u16> &code, std::string _filename,
- const char *name, std::string &header)
-{
- std::vector<u16> code_copy = code;
- // Add some nops at the end to align the size a bit.
- while (code_copy.size() & 7)
- code_copy.push_back(0);
- char buffer[1024];
- header.clear();
- header.reserve(code.size() * 4);
- header.append("#define NUM_UCODES 1\n\n");
- std::string filename;
- SplitPath(_filename, NULL, &filename, NULL);
- header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
- header.append("#ifndef _MSCVER\n");
- header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
- header.append("#else\n");
- header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
- header.append("#endif\n\n");
-
- header.append("\t{\n\t\t");
- for (u32 j = 0; j < code.size(); j++)
- {
- if (j && ((j & 15) == 0))
- header.append("\n\t\t");
- sprintf(buffer, "0x%04x, ", code[j]);
- header.append(buffer);
- }
- header.append("\n\t},\n");
-
- header.append("};\n");
-}
-
-void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
- int numCodes, const char *name, std::string &header)
-{
- char buffer[1024];
- int reserveSize = 0;
- for(int i = 0; i < numCodes; i++)
- reserveSize += (int)codes[i].size();
-
-
- header.clear();
- header.reserve(reserveSize * 4);
- sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
- header.append(buffer);
- header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
- for (int i = 0; i < numCodes; i++)
- {
- std::string filename;
- if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
- filename = filenames->at(i);
- sprintf(buffer, "\t\"%s\",\n", filename.c_str());
- header.append(buffer);
- }
- header.append("};\n\n");
- header.append("#ifndef _MSCVER\n");
- header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
- header.append("#else\n");
- header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
- header.append("#endif\n\n");
-
- for(int i = 0; i < numCodes; i++) {
- if(codes[i].size() == 0)
- continue;
-
- std::vector<u16> code_copy = codes[i];
- // Add some nops at the end to align the size a bit.
- while (code_copy.size() & 7)
- code_copy.push_back(0);
-
- header.append("\t{\n\t\t");
- for (u32 j = 0; j < codes[i].size(); j++)
- {
- if (j && ((j & 15) == 0))
- header.append("\n\t\t");
- sprintf(buffer, "0x%04x, ", codes[i][j]);
- header.append(buffer);
- }
- header.append("\n\t},\n");
- }
- header.append("};\n");
-}
-
-void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
-{
- str.resize(code.size() * 2);
- for (int i = 0; i < (int)code.size(); i++)
- {
- str[i * 2 + 0] = code[i] >> 8;
- str[i * 2 + 1] = code[i] & 0xff;
- }
-}
-
-void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
-{
- code.resize(str.size() / 2);
- for (int i = 0; i < (int)code.size(); i++)
- {
- code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
- }
-}
-
-bool LoadBinary(const char *filename, std::vector<u16> &code)
-{
- std::string buffer;
- if (!File::ReadFileToString(false, filename, buffer))
- return false;
-
- BinaryStringBEToCode(buffer, code);
- return true;
-}
-
-bool SaveBinary(const std::vector<u16> &code, const char *filename)
-{
- std::string buffer;
- CodeToBinaryStringBE(code, buffer);
- if (!File::WriteStringToFile(false, buffer, filename))
- return false;
- return true;
-}
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 <iostream>
+#include <vector>
+
+#include "Common.h"
+#include "FileUtil.h"
+#include "StringUtil.h"
+#include "DSPCodeUtil.h"
+#include "assemble.h"
+#include "disassemble.h"
+
+
+bool Assemble(const char *text, std::vector<u16> &code)
+{
+ AssemblerSettings settings;
+ settings.pc = 0;
+ // settings.decode_registers = false;
+ // settings.decode_names = false;
+ settings.print_tabs = false;
+ settings.ext_separator = '\'';
+
+ // TODO: fix the terrible api of the assembler.
+ DSPAssembler assembler(settings);
+ if (!assembler.Assemble(text, code)) {
+ std::cerr << assembler.GetErrorString() << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
+{
+ if (code.empty())
+ return false;
+
+ AssemblerSettings settings;
+
+ // These two prevent roundtripping.
+ settings.show_hex = false;
+ settings.show_pc = line_numbers;
+ settings.ext_separator = '\'';
+ settings.decode_names = false;
+ settings.decode_registers = true;
+
+ DSPDisassembler disasm(settings);
+ bool success = disasm.Disassemble(0, code, 0x0000, text);
+ return success;
+}
+
+bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
+{
+ if (code1.size() != code2.size())
+ printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
+ u32 count_equal = 0;
+ const int min_size = (int)std::min(code1.size(), code2.size());
+
+ AssemblerSettings settings;
+ DSPDisassembler disassembler(settings);
+ for (int i = 0; i < min_size; i++)
+ {
+ if (code1[i] == code2[i])
+ count_equal++;
+ else
+ {
+ std::string line1, line2;
+ u16 pc = i;
+ disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
+ pc = i;
+ disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
+ printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
+ }
+ }
+ if (code2.size() != code1.size())
+ {
+ printf("Extra code words:\n");
+ const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
+ for (int i = min_size; i < (int)longest.size(); i++)
+ {
+ u16 pc = i;
+ std::string line;
+ disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
+ printf("!! %s\n", line.c_str());
+ }
+ }
+ printf("Equal instruction words: %i / %i\n", count_equal, min_size);
+ return code1.size() == code2.size() && code1.size() == count_equal;
+}
+
+void GenRandomCode(int size, std::vector<u16> &code)
+{
+ code.resize(size);
+ for (int i = 0; i < size; i++)
+ {
+ code[i] = rand() ^ (rand() << 8);
+ }
+}
+
+void CodeToHeader(const std::vector<u16> &code, std::string _filename,
+ const char *name, std::string &header)
+{
+ std::vector<u16> code_copy = code;
+ // Add some nops at the end to align the size a bit.
+ while (code_copy.size() & 7)
+ code_copy.push_back(0);
+ char buffer[1024];
+ header.clear();
+ header.reserve(code.size() * 4);
+ header.append("#define NUM_UCODES 1\n\n");
+ std::string filename;
+ SplitPath(_filename, NULL, &filename, NULL);
+ header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
+ header.append("#ifndef _MSCVER\n");
+ header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
+ header.append("#else\n");
+ header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
+ header.append("#endif\n\n");
+
+ header.append("\t{\n\t\t");
+ for (u32 j = 0; j < code.size(); j++)
+ {
+ if (j && ((j & 15) == 0))
+ header.append("\n\t\t");
+ sprintf(buffer, "0x%04x, ", code[j]);
+ header.append(buffer);
+ }
+ header.append("\n\t},\n");
+
+ header.append("};\n");
+}
+
+void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
+ int numCodes, const char *name, std::string &header)
+{
+ char buffer[1024];
+ int reserveSize = 0;
+ for(int i = 0; i < numCodes; i++)
+ reserveSize += (int)codes[i].size();
+
+
+ header.clear();
+ header.reserve(reserveSize * 4);
+ sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
+ header.append(buffer);
+ header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
+ for (int i = 0; i < numCodes; i++)
+ {
+ std::string filename;
+ if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
+ filename = filenames->at(i);
+ sprintf(buffer, "\t\"%s\",\n", filename.c_str());
+ header.append(buffer);
+ }
+ header.append("};\n\n");
+ header.append("#ifndef _MSCVER\n");
+ header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
+ header.append("#else\n");
+ header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
+ header.append("#endif\n\n");
+
+ for(int i = 0; i < numCodes; i++) {
+ if(codes[i].size() == 0)
+ continue;
+
+ std::vector<u16> code_copy = codes[i];
+ // Add some nops at the end to align the size a bit.
+ while (code_copy.size() & 7)
+ code_copy.push_back(0);
+
+ header.append("\t{\n\t\t");
+ for (u32 j = 0; j < codes[i].size(); j++)
+ {
+ if (j && ((j & 15) == 0))
+ header.append("\n\t\t");
+ sprintf(buffer, "0x%04x, ", codes[i][j]);
+ header.append(buffer);
+ }
+ header.append("\n\t},\n");
+ }
+ header.append("};\n");
+}
+
+void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
+{
+ str.resize(code.size() * 2);
+ for (int i = 0; i < (int)code.size(); i++)
+ {
+ str[i * 2 + 0] = code[i] >> 8;
+ str[i * 2 + 1] = code[i] & 0xff;
+ }
+}
+
+void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
+{
+ code.resize(str.size() / 2);
+ for (int i = 0; i < (int)code.size(); i++)
+ {
+ code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
+ }
+}
+
+bool LoadBinary(const char *filename, std::vector<u16> &code)
+{
+ std::string buffer;
+ if (!File::ReadFileToString(false, filename, buffer))
+ return false;
+
+ BinaryStringBEToCode(buffer, code);
+ return true;
+}
+
+bool SaveBinary(const std::vector<u16> &code, const char *filename)
+{
+ std::string buffer;
+ CodeToBinaryStringBE(code, buffer);
+ if (!File::WriteStringToFile(false, buffer, filename))
+ return false;
+ return true;
+}
diff --git a/Source/Core/DSPCore/Src/DSPCodeUtil.h b/Source/Core/DSPCore/Src/DSPCodeUtil.h
index 3d204e359e..bcf4a78048 100644
--- a/Source/Core/DSPCore/Src/DSPCodeUtil.h
+++ b/Source/Core/DSPCore/Src/DSPCodeUtil.h
@@ -1,43 +1,43 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _DSPCODEUTIL_H
-#define _DSPCODEUTIL_H
-
-#include <string>
-#include <vector>
-
-#include "Common.h"
-
-bool Assemble(const char *text, std::vector<u16> &code);
-bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
-bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
-void GenRandomCode(int size, std::vector<u16> &code);
-void CodeToHeader(const std::vector<u16> &code, std::string _filename,
- const char *name, std::string &header);
-void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
- int numCodes, const char *name, std::string &header);
-
-// Big-endian, for writing straight to file using File::WriteStringToFile.
-void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
-void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
-
-// Load code (big endian binary).
-bool LoadBinary(const char *filename, std::vector<u16> &code);
-bool SaveBinary(const std::vector<u16> &code, const char *filename);
-
-#endif // _DSPCODEUTIL_H
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _DSPCODEUTIL_H
+#define _DSPCODEUTIL_H
+
+#include <string>
+#include <vector>
+
+#include "Common.h"
+
+bool Assemble(const char *text, std::vector<u16> &code);
+bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
+bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
+void GenRandomCode(int size, std::vector<u16> &code);
+void CodeToHeader(const std::vector<u16> &code, std::string _filename,
+ const char *name, std::string &header);
+void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
+ int numCodes, const char *name, std::string &header);
+
+// Big-endian, for writing straight to file using File::WriteStringToFile.
+void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
+void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
+
+// Load code (big endian binary).
+bool LoadBinary(const char *filename, std::vector<u16> &code);
+bool SaveBinary(const std::vector<u16> &code, const char *filename);
+
+#endif // _DSPCODEUTIL_H
diff --git a/Source/Core/DSPCore/Src/DSPCore.cpp b/Source/Core/DSPCore/Src/DSPCore.cpp
index c143852251..0dafd25259 100644
--- a/Source/Core/DSPCore/Src/DSPCore.cpp
+++ b/Source/Core/DSPCore/Src/DSPCore.cpp
@@ -1,256 +1,256 @@
-/*====================================================================
-
- filename: gdsp_interpreter.cpp
- project: GCemu
- created: 2004-6-18
- mail: duddie@walla.com
-
- Copyright (c) 2005 Duddie & Tratax
-
- 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; either version 2
- of the License, or (at your option) any later version.
-
- 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 for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- ====================================================================*/
-
-#include "Common.h"
-#include "Thread.h"
-#include "DSPCore.h"
-#include "DSPHost.h"
-#include "DSPAnalyzer.h"
-#include "MemoryUtil.h"
-
-#include "DSPHWInterface.h"
-#include "DSPIntUtil.h"
-
-SDSP g_dsp;
-DSPBreakpoints dsp_breakpoints;
-DSPCoreState core_state = DSPCORE_RUNNING;
-Common::Event step_event;
-
-static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
-{
- FILE *pFile = fopen(fname, "rb");
- const size_t size_in_bytes = size_in_words * sizeof(u16);
- if (pFile)
- {
- size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
- if (read_bytes != size_in_bytes)
- {
- PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
- fclose(pFile);
- return false;
- }
- fclose(pFile);
-
- // Byteswap the rom.
- for (int i = 0; i < DSP_IROM_SIZE; i++)
- rom[i] = Common::swap16(rom[i]);
-
- return true;
- }
- // Always keep ROMs write protected.
- WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
- return false;
-}
-
-bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
-{
- g_dsp.step_counter = 0;
-
- g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
- g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
- g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
- g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
-
- // Fill roms with zeros.
- memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
- memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
-
- // Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
- LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
- LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
-
- for (int i = 0; i < 32; i++)
- {
- g_dsp.r[i] = 0;
- }
-
- for (int i = 0; i < 4; i++)
- {
- g_dsp.reg_stack_ptr[i] = 0;
- for (int j = 0; j < DSP_STACK_DEPTH; j++)
- {
- g_dsp.reg_stack[i][j] = 0;
- }
- }
-
- // Fill IRAM with HALT opcodes.
- for (int i = 0; i < DSP_IRAM_SIZE; i++)
- {
- g_dsp.iram[i] = 0x0021; // HALT opcode
- }
-
- // Just zero out DRAM.
- for (int i = 0; i < DSP_DRAM_SIZE; i++)
- {
- g_dsp.dram[i] = 0;
- }
-
- // Copied from a real console after the custom UCode has been loaded.
- // These are the indexing wrapping registers.
- g_dsp.r[DSP_REG_WR0] = 0xffff;
- g_dsp.r[DSP_REG_WR1] = 0xffff;
- g_dsp.r[DSP_REG_WR2] = 0xffff;
- g_dsp.r[DSP_REG_WR3] = 0xffff;
-
- g_dsp.cr = 0x804;
- gdsp_ifx_init();
-
- // Mostly keep IRAM write protected. We unprotect only when DMA-ing
- // in new ucodes.
- WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
- DSPAnalyzer::Analyze();
-
- step_event.Init();
- return true;
-}
-
-void DSPCore_Shutdown()
-{
- step_event.Shutdown();
- FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
- FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
- FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
- FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
-}
-
-void DSPCore_Reset()
-{
- _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
- g_dsp.pc = DSP_RESET_VECTOR;
- g_dsp.exception_in_progress_hack = false;
-
- g_dsp.r[DSP_REG_WR0] = 0xffff;
- g_dsp.r[DSP_REG_WR1] = 0xffff;
- g_dsp.r[DSP_REG_WR2] = 0xffff;
- g_dsp.r[DSP_REG_WR3] = 0xffff;
-
-}
-
-void DSPCore_SetException(u8 level)
-{
- g_dsp.exceptions |= 1 << level;
-}
-
-void DSPCore_CheckExternalInterrupt()
-{
- // check if there is an external interrupt
- if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
- {
-#ifdef DEBUG_EXP
- NOTICE_LOG(DSPLLE, "trying External interupt fired");
-#endif
- if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
- {
-#ifdef DEBUG_EXP
- NOTICE_LOG(DSPLLE, "External interupt fired");
-#endif
- // level 7 is the interrupt exception
- DSPCore_SetException(EXP_INT);
-
- g_dsp.cr &= ~CR_EXTERNAL_INT;
- }
- }
-}
-
-void DSPCore_CheckExceptions()
-{
- if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
-#ifdef DEBUG_EXP
- NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
-#endif
- // check exceptions
- for (int i = 0; i < 8; i++) {
- // Seems 7 must pass or zelda dies
- if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
- if (g_dsp.exceptions & (1 << i)) {
- _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
-
- dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
- dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
-
- g_dsp.pc = i * 2;
- g_dsp.exceptions &= ~(1 << i);
-#ifdef DEBUG_EXP
- NOTICE_LOG(DSPLLE, "exception %d fired");
-#endif
- g_dsp.exception_in_progress_hack = true;
- break;
- }
- }
- }
- }
-}
-
-// Delegate to JIT (when it is written) or interpreter as appropriate.
-// Handle state changes and stepping.
-int DSPCore_RunCycles(int cycles)
-{
- while (cycles > 0) {
- reswitch:
- switch (core_state)
- {
- case DSPCORE_RUNNING:
-#if 1 // Set to 0 to disable breakpoints, for a speed boost.
- cycles = DSPInterpreter::RunCyclesDebug(cycles);
-#else
- cycles = DSPInterpreter::RunCycles(cycles);
-#endif
- break;
-
- case DSPCORE_STEPPING:
- step_event.Wait();
- if (core_state != DSPCORE_STEPPING)
- goto reswitch;
-
- DSPInterpreter::Step();
- cycles--;
-
- DSPHost_UpdateDebugger();
- break;
- }
- }
- return cycles;
-}
-
-void DSPCore_SetState(DSPCoreState new_state)
-{
- core_state = new_state;
- // kick the event, in case we are waiting
- if (new_state == DSPCORE_RUNNING)
- step_event.Set();
- // Sleep(10);
- DSPHost_UpdateDebugger();
-}
-
-DSPCoreState DSPCore_GetState()
-{
- return core_state;
-}
-
-void DSPCore_Step()
-{
- if (core_state == DSPCORE_STEPPING)
- step_event.Set();
-}
+/*====================================================================
+
+ filename: gdsp_interpreter.cpp
+ project: GCemu
+ created: 2004-6-18
+ mail: duddie@walla.com
+
+ Copyright (c) 2005 Duddie & Tratax
+
+ 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; either version 2
+ of the License, or (at your option) any later version.
+
+ 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ ====================================================================*/
+
+#include "Common.h"
+#include "Thread.h"
+#include "DSPCore.h"
+#include "DSPHost.h"
+#include "DSPAnalyzer.h"
+#include "MemoryUtil.h"
+
+#include "DSPHWInterface.h"
+#include "DSPIntUtil.h"
+
+SDSP g_dsp;
+DSPBreakpoints dsp_breakpoints;
+DSPCoreState core_state = DSPCORE_RUNNING;
+Common::Event step_event;
+
+static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
+{
+ FILE *pFile = fopen(fname, "rb");
+ const size_t size_in_bytes = size_in_words * sizeof(u16);
+ if (pFile)
+ {
+ size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
+ if (read_bytes != size_in_bytes)
+ {
+ PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
+ fclose(pFile);
+ return false;
+ }
+ fclose(pFile);
+
+ // Byteswap the rom.
+ for (int i = 0; i < DSP_IROM_SIZE; i++)
+ rom[i] = Common::swap16(rom[i]);
+
+ return true;
+ }
+ // Always keep ROMs write protected.
+ WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
+ return false;
+}
+
+bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
+{
+ g_dsp.step_counter = 0;
+
+ g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
+ g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
+ g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
+ g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
+
+ // Fill roms with zeros.
+ memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
+ memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
+
+ // Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
+ LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
+ LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
+
+ for (int i = 0; i < 32; i++)
+ {
+ g_dsp.r[i] = 0;
+ }
+
+ for (int i = 0; i < 4; i++)
+ {
+ g_dsp.reg_stack_ptr[i] = 0;
+ for (int j = 0; j < DSP_STACK_DEPTH; j++)
+ {
+ g_dsp.reg_stack[i][j] = 0;
+ }
+ }
+
+ // Fill IRAM with HALT opcodes.
+ for (int i = 0; i < DSP_IRAM_SIZE; i++)
+ {
+ g_dsp.iram[i] = 0x0021; // HALT opcode
+ }
+
+ // Just zero out DRAM.
+ for (int i = 0; i < DSP_DRAM_SIZE; i++)
+ {
+ g_dsp.dram[i] = 0;
+ }
+
+ // Copied from a real console after the custom UCode has been loaded.
+ // These are the indexing wrapping registers.
+ g_dsp.r[DSP_REG_WR0] = 0xffff;
+ g_dsp.r[DSP_REG_WR1] = 0xffff;
+ g_dsp.r[DSP_REG_WR2] = 0xffff;
+ g_dsp.r[DSP_REG_WR3] = 0xffff;
+
+ g_dsp.cr = 0x804;
+ gdsp_ifx_init();
+
+ // Mostly keep IRAM write protected. We unprotect only when DMA-ing
+ // in new ucodes.
+ WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
+ DSPAnalyzer::Analyze();
+
+ step_event.Init();
+ return true;
+}
+
+void DSPCore_Shutdown()
+{
+ step_event.Shutdown();
+ FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
+ FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
+ FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
+ FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
+}
+
+void DSPCore_Reset()
+{
+ _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
+ g_dsp.pc = DSP_RESET_VECTOR;
+ g_dsp.exception_in_progress_hack = false;
+
+ g_dsp.r[DSP_REG_WR0] = 0xffff;
+ g_dsp.r[DSP_REG_WR1] = 0xffff;
+ g_dsp.r[DSP_REG_WR2] = 0xffff;
+ g_dsp.r[DSP_REG_WR3] = 0xffff;
+
+}
+
+void DSPCore_SetException(u8 level)
+{
+ g_dsp.exceptions |= 1 << level;
+}
+
+void DSPCore_CheckExternalInterrupt()
+{
+ // check if there is an external interrupt
+ if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
+ {
+#ifdef DEBUG_EXP
+ NOTICE_LOG(DSPLLE, "trying External interupt fired");
+#endif
+ if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
+ {
+#ifdef DEBUG_EXP
+ NOTICE_LOG(DSPLLE, "External interupt fired");
+#endif
+ // level 7 is the interrupt exception
+ DSPCore_SetException(EXP_INT);
+
+ g_dsp.cr &= ~CR_EXTERNAL_INT;
+ }
+ }
+}
+
+void DSPCore_CheckExceptions()
+{
+ if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
+#ifdef DEBUG_EXP
+ NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
+#endif
+ // check exceptions
+ for (int i = 0; i < 8; i++) {
+ // Seems 7 must pass or zelda dies
+ if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
+ if (g_dsp.exceptions & (1 << i)) {
+ _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
+
+ dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
+ dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
+
+ g_dsp.pc = i * 2;
+ g_dsp.exceptions &= ~(1 << i);
+#ifdef DEBUG_EXP
+ NOTICE_LOG(DSPLLE, "exception %d fired");
+#endif
+ g_dsp.exception_in_progress_hack = true;
+ break;
+ }
+ }
+ }
+ }
+}
+
+// Delegate to JIT (when it is written) or interpreter as appropriate.
+// Handle state changes and stepping.
+int DSPCore_RunCycles(int cycles)
+{
+ while (cycles > 0) {
+ reswitch:
+ switch (core_state)
+ {
+ case DSPCORE_RUNNING:
+#if 1 // Set to 0 to disable breakpoints, for a speed boost.
+ cycles = DSPInterpreter::RunCyclesDebug(cycles);
+#else
+ cycles = DSPInterpreter::RunCycles(cycles);
+#endif
+ break;
+
+ case DSPCORE_STEPPING:
+ step_event.Wait();
+ if (core_state != DSPCORE_STEPPING)
+ goto reswitch;
+
+ DSPInterpreter::Step();
+ cycles--;
+
+ DSPHost_UpdateDebugger();
+ break;
+ }
+ }
+ return cycles;
+}
+
+void DSPCore_SetState(DSPCoreState new_state)
+{
+ core_state = new_state;
+ // kick the event, in case we are waiting
+ if (new_state == DSPCORE_RUNNING)
+ step_event.Set();
+ // Sleep(10);
+ DSPHost_UpdateDebugger();
+}
+
+DSPCoreState DSPCore_GetState()
+{
+ return core_state;
+}
+
+void DSPCore_Step()
+{
+ if (core_state == DSPCORE_STEPPING)
+ step_event.Set();
+}
diff --git a/Source/Core/DSPCore/Src/DSPCore.h b/Source/Core/DSPCore/Src/DSPCore.h
index 24d31eed48..b1293e70f6 100644
--- a/Source/Core/DSPCore/Src/DSPCore.h
+++ b/Source/Core/DSPCore/Src/DSPCore.h
@@ -1,240 +1,240 @@
-/*====================================================================
-
- filename: DSPCore.h
- project: GCemu
- created: 2004-6-18
- mail: duddie@walla.com
-
- Copyright (c) 2005 Duddie & Tratax
-
- 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; either version 2
- of the License, or (at your option) any later version.
-
- 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 for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- ====================================================================*/
-
-#ifndef _DSPCORE_H
-#define _DSPCORE_H
-
-#include "DSPBreakpoints.h"
-
-#define DSP_IRAM_BYTE_SIZE 0x2000
-#define DSP_IRAM_SIZE 0x1000
-#define DSP_IRAM_MASK 0x0fff
-
-#define DSP_IROM_BYTE_SIZE 0x2000
-#define DSP_IROM_SIZE 0x1000
-#define DSP_IROM_MASK 0x0fff
-
-#define DSP_DRAM_BYTE_SIZE 0x2000
-#define DSP_DRAM_SIZE 0x1000
-#define DSP_DRAM_MASK 0x0fff
-
-#define DSP_COEF_BYTE_SIZE 0x2000
-#define DSP_COEF_SIZE 0x1000
-#define DSP_COEF_MASK 0x0fff
-
-#define DSP_RESET_VECTOR 0x8000
-
-#define DSP_STACK_DEPTH 0x20
-#define DSP_STACK_MASK 0x1f
-
-#define DSP_CR_IMEM 2
-#define DSP_CR_DMEM 0
-#define DSP_CR_TO_CPU 1
-#define DSP_CR_FROM_CPU 0
-
-
-// Register table taken from libasnd
-#define DSP_REG_AR0 0x00 // address registers
-#define DSP_REG_AR1 0x01
-#define DSP_REG_AR2 0x02
-#define DSP_REG_AR3 0x03
-
-#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
-#define DSP_REG_IX1 0x05
-#define DSP_REG_IX2 0x06
-#define DSP_REG_IX3 0x07
-
-#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
-#define DSP_REG_WR1 0x09
-#define DSP_REG_WR2 0x0a
-#define DSP_REG_WR3 0x0b
-
-#define DSP_REG_ST0 0x0c // stacks.
-#define DSP_REG_ST1 0x0d
-#define DSP_REG_ST2 0x0e
-#define DSP_REG_ST3 0x0f
-
-#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
-#define DSP_REG_SR 0x13
-
-#define DSP_REG_PRODL 0x14 // product.
-#define DSP_REG_PRODM 0x15
-#define DSP_REG_PRODH 0x16
-#define DSP_REG_PRODM2 0x17
-
-#define DSP_REG_AXL0 0x18
-#define DSP_REG_AXL1 0x19
-#define DSP_REG_AXH0 0x1a
-#define DSP_REG_AXH1 0x1b
-
-#define DSP_REG_ACC0 0x1c // accumulator (global)
-#define DSP_REG_ACC1 0x1d
-
-#define DSP_REG_ACL0 0x1c // Low accumulator
-#define DSP_REG_ACL1 0x1d
-#define DSP_REG_ACM0 0x1e // Mid accumulator
-#define DSP_REG_ACM1 0x1f
-#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
-#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
-
-// Hardware registers address
-
-#define DSP_COEF_A1_0 0xa0
-
-#define DSP_DSMAH 0xce
-#define DSP_DSMAL 0xcf
-#define DSP_DSCR 0xc9 // DSP DMA Control Reg
-#define DSP_DSPA 0xcd // DSP DMA Block Length
-#define DSP_DSBL 0xcb // DSP DMA DMEM Address
-#define DSP_DSMAH 0xce // DSP DMA Mem Address H
-#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
-
-#define DSP_FORMAT 0xd1
-#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
-#define DSP_ACSAH 0xd4
-#define DSP_ACSAL 0xd5
-#define DSP_ACEAH 0xd6
-#define DSP_ACEAL 0xd7
-#define DSP_ACCAH 0xd8
-#define DSP_ACCAL 0xd9
-#define DSP_PRED_SCALE 0xda
-#define DSP_YN1 0xdb
-#define DSP_YN2 0xdc
-#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
-#define DSP_GAIN 0xde
-
-#define DSP_DIRQ 0xfb // DSP Irq Rest
-#define DSP_DMBH 0xfc // DSP Mailbox H
-#define DSP_DMBL 0xfd // DSP Mailbox L
-#define DSP_CMBH 0xfe // CPU Mailbox H
-#define DSP_CMBL 0xff // CPU Mailbox L
-
-#define DMA_TO_DSP 0
-#define DMA_TO_CPU 1
-
-// Stacks
-#define DSP_STACK_C 0
-#define DSP_STACK_D 1
-
-// cr (Not g_dsp.r[CR]) bits
-// See HW/DSP.cpp.
-#define CR_HALT 0x0004
-#define CR_EXTERNAL_INT 0x0002
-
-
-// SR bits
-#define SR_CARRY 0x0001
-#define SR_2 0x0002 // overflow???
-#define SR_ARITH_ZERO 0x0004
-#define SR_SIGN 0x0008
-#define SR_10 0x0010 // seem to be set by tst
-#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
-#define SR_LOGIC_ZERO 0x0040
-#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
-#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
-#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
-#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
-#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
-
-// This should be the bits affected by CMP. Does not include logic zero.
-#define SR_CMP_MASK 0x3f
-
-// exceptions vector
-#define EXP_RESET 0 // 0x0000
-#define EXP_STOVF 1 // 0x0002 stack under/over flow
-#define EXP_4 2 // 0x0004
-#define EXP_6 3 // 0x0006
-#define EXP_8 4 // 0x0008
-#define EXP_ACCOV 5 // 0x000a accelerator address overflow
-#define EXP_c 6 // 0x000c
-#define EXP_INT 7 // 0x000e external int? (mail?)
-
-struct SDSP
-{
- u16 r[32];
- u16 pc;
-#if PROFILE
- u16 err_pc;
-#endif
-
- // This is NOT the same cr as r[DSP_REG_CR].
- // This register is shared with the main emulation, see DSP.cpp
- // The plugin has control over 0x0C07 of this reg.
- // Bits are defined in a struct in DSP.cpp.
- u16 cr;
-
- u8 reg_stack_ptr[4];
- u8 exceptions; // pending exceptions?
- bool exception_in_progress_hack; // is this the same as "exception enabled"?
-
- // Let's make stack depth 32 for now. The real DSP has different depths
- // for the different stacks, but it would be strange if any ucode relied on stack
- // overflows since on the DSP, when the stack overflows, you're screwed.
- u16 reg_stack[4][DSP_STACK_DEPTH];
-
- // For debugging.
- u32 iram_crc;
- u64 step_counter;
-
- // When state saving, all of the above can just be memcpy'd into the save state.
- // The below needs special handling.
- u16 *iram;
- u16 *dram;
- u16 *irom;
- u16 *coef;
-
- // This one doesn't really belong here.
- u8 *cpu_ram;
-};
-
-extern SDSP g_dsp;
-extern DSPBreakpoints dsp_breakpoints;
-
-bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
-
-void DSPCore_Reset();
-void DSPCore_Shutdown(); // Frees all allocated memory.
-
-void DSPCore_CheckExternalInterrupt();
-void DSPCore_CheckExceptions();
-
-// sets a flag in the pending exception register.
-void DSPCore_SetException(u8 level);
-
-enum DSPCoreState
-{
- DSPCORE_RUNNING = 0,
- DSPCORE_STEPPING = 1,
-};
-
-int DSPCore_RunCycles(int cycles);
-
-// These are meant to be called from the UI thread.
-void DSPCore_SetState(DSPCoreState new_state);
-DSPCoreState DSPCore_GetState();
-
-void DSPCore_Step();
-
-#endif // _DSPCORE_H
+/*====================================================================
+
+ filename: DSPCore.h
+ project: GCemu
+ created: 2004-6-18
+ mail: duddie@walla.com
+
+ Copyright (c) 2005 Duddie & Tratax
+
+ 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; either version 2
+ of the License, or (at your option) any later version.
+
+ 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ ====================================================================*/
+
+#ifndef _DSPCORE_H
+#define _DSPCORE_H
+
+#include "DSPBreakpoints.h"
+
+#define DSP_IRAM_BYTE_SIZE 0x2000
+#define DSP_IRAM_SIZE 0x1000
+#define DSP_IRAM_MASK 0x0fff
+
+#define DSP_IROM_BYTE_SIZE 0x2000
+#define DSP_IROM_SIZE 0x1000
+#define DSP_IROM_MASK 0x0fff
+
+#define DSP_DRAM_BYTE_SIZE 0x2000
+#define DSP_DRAM_SIZE 0x1000
+#define DSP_DRAM_MASK 0x0fff
+
+#define DSP_COEF_BYTE_SIZE 0x2000
+#define DSP_COEF_SIZE 0x1000
+#define DSP_COEF_MASK 0x0fff
+
+#define DSP_RESET_VECTOR 0x8000
+
+#define DSP_STACK_DEPTH 0x20
+#define DSP_STACK_MASK 0x1f
+
+#define DSP_CR_IMEM 2
+#define DSP_CR_DMEM 0
+#define DSP_CR_TO_CPU 1
+#define DSP_CR_FROM_CPU 0
+
+
+// Register table taken from libasnd
+#define DSP_REG_AR0 0x00 // address registers
+#define DSP_REG_AR1 0x01
+#define DSP_REG_AR2 0x02
+#define DSP_REG_AR3 0x03
+
+#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
+#define DSP_REG_IX1 0x05
+#define DSP_REG_IX2 0x06
+#define DSP_REG_IX3 0x07
+
+#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
+#define DSP_REG_WR1 0x09
+#define DSP_REG_WR2 0x0a
+#define DSP_REG_WR3 0x0b
+
+#define DSP_REG_ST0 0x0c // stacks.
+#define DSP_REG_ST1 0x0d
+#define DSP_REG_ST2 0x0e
+#define DSP_REG_ST3 0x0f
+
+#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
+#define DSP_REG_SR 0x13
+
+#define DSP_REG_PRODL 0x14 // product.
+#define DSP_REG_PRODM 0x15
+#define DSP_REG_PRODH 0x16
+#define DSP_REG_PRODM2 0x17
+
+#define DSP_REG_AXL0 0x18
+#define DSP_REG_AXL1 0x19
+#define DSP_REG_AXH0 0x1a
+#define DSP_REG_AXH1 0x1b
+
+#define DSP_REG_ACC0 0x1c // accumulator (global)
+#define DSP_REG_ACC1 0x1d
+
+#define DSP_REG_ACL0 0x1c // Low accumulator
+#define DSP_REG_ACL1 0x1d
+#define DSP_REG_ACM0 0x1e // Mid accumulator
+#define DSP_REG_ACM1 0x1f
+#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
+#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
+
+// Hardware registers address
+
+#define DSP_COEF_A1_0 0xa0
+
+#define DSP_DSMAH 0xce
+#define DSP_DSMAL 0xcf
+#define DSP_DSCR 0xc9 // DSP DMA Control Reg
+#define DSP_DSPA 0xcd // DSP DMA Block Length
+#define DSP_DSBL 0xcb // DSP DMA DMEM Address
+#define DSP_DSMAH 0xce // DSP DMA Mem Address H
+#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
+
+#define DSP_FORMAT 0xd1
+#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
+#define DSP_ACSAH 0xd4
+#define DSP_ACSAL 0xd5
+#define DSP_ACEAH 0xd6
+#define DSP_ACEAL 0xd7
+#define DSP_ACCAH 0xd8
+#define DSP_ACCAL 0xd9
+#define DSP_PRED_SCALE 0xda
+#define DSP_YN1 0xdb
+#define DSP_YN2 0xdc
+#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
+#define DSP_GAIN 0xde
+
+#define DSP_DIRQ 0xfb // DSP Irq Rest
+#define DSP_DMBH 0xfc // DSP Mailbox H
+#define DSP_DMBL 0xfd // DSP Mailbox L
+#define DSP_CMBH 0xfe // CPU Mailbox H
+#define DSP_CMBL 0xff // CPU Mailbox L
+
+#define DMA_TO_DSP 0
+#define DMA_TO_CPU 1
+
+// Stacks
+#define DSP_STACK_C 0
+#define DSP_STACK_D 1
+
+// cr (Not g_dsp.r[CR]) bits
+// See HW/DSP.cpp.
+#define CR_HALT 0x0004
+#define CR_EXTERNAL_INT 0x0002
+
+
+// SR bits
+#define SR_CARRY 0x0001
+#define SR_2 0x0002 // overflow???
+#define SR_ARITH_ZERO 0x0004
+#define SR_SIGN 0x0008
+#define SR_10 0x0010 // seem to be set by tst
+#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
+#define SR_LOGIC_ZERO 0x0040
+#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
+#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
+#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
+#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
+#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
+
+// This should be the bits affected by CMP. Does not include logic zero.
+#define SR_CMP_MASK 0x3f
+
+// exceptions vector
+#define EXP_RESET 0 // 0x0000
+#define EXP_STOVF 1 // 0x0002 stack under/over flow
+#define EXP_4 2 // 0x0004
+#define EXP_6 3 // 0x0006
+#define EXP_8 4 // 0x0008
+#define EXP_ACCOV 5 // 0x000a accelerator address overflow
+#define EXP_c 6 // 0x000c
+#define EXP_INT 7 // 0x000e external int? (mail?)
+
+struct SDSP
+{
+ u16 r[32];
+ u16 pc;
+#if PROFILE
+ u16 err_pc;
+#endif
+
+ // This is NOT the same cr as r[DSP_REG_CR].
+ // This register is shared with the main emulation, see DSP.cpp
+ // The plugin has control over 0x0C07 of this reg.
+ // Bits are defined in a struct in DSP.cpp.
+ u16 cr;
+
+ u8 reg_stack_ptr[4];
+ u8 exceptions; // pending exceptions?
+ bool exception_in_progress_hack; // is this the same as "exception enabled"?
+
+ // Let's make stack depth 32 for now. The real DSP has different depths
+ // for the different stacks, but it would be strange if any ucode relied on stack
+ // overflows since on the DSP, when the stack overflows, you're screwed.
+ u16 reg_stack[4][DSP_STACK_DEPTH];
+
+ // For debugging.
+ u32 iram_crc;
+ u64 step_counter;
+
+ // When state saving, all of the above can just be memcpy'd into the save state.
+ // The below needs special handling.
+ u16 *iram;
+ u16 *dram;
+ u16 *irom;
+ u16 *coef;
+
+ // This one doesn't really belong here.
+ u8 *cpu_ram;
+};
+
+extern SDSP g_dsp;
+extern DSPBreakpoints dsp_breakpoints;
+
+bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
+
+void DSPCore_Reset();
+void DSPCore_Shutdown(); // Frees all allocated memory.
+
+void DSPCore_CheckExternalInterrupt();
+void DSPCore_CheckExceptions();
+
+// sets a flag in the pending exception register.
+void DSPCore_SetException(u8 level);
+
+enum DSPCoreState
+{
+ DSPCORE_RUNNING = 0,
+ DSPCORE_STEPPING = 1,
+};
+
+int DSPCore_RunCycles(int cycles);
+
+// These are meant to be called from the UI thread.
+void DSPCore_SetState(DSPCoreState new_state);
+DSPCoreState DSPCore_GetState();
+
+void DSPCore_Step();
+
+#endif // _DSPCORE_H
diff --git a/Source/Core/DSPCore/Src/DSPHost.h b/Source/Core/DSPCore/Src/DSPHost.h
index 60791deeb1..0abddd85f3 100644
--- a/Source/Core/DSPCore/Src/DSPHost.h
+++ b/Source/Core/DSPCore/Src/DSPHost.h
@@ -1,35 +1,35 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _DSPHOST_H
-#define _DSPHOST_H
-
-// The user of the DSPCore library must supply a few functions so that the
-// emulation core can access the environment it runs in. If the emulation
-// core isn't used, for example in an asm/disasm tool, then most of these
-// can be stubbed out.
-#define DEBUG_EXP 1
-
-u8 DSPHost_ReadHostMemory(u32 addr);
-void DSPHost_WriteHostMemory(u8 value, u32 addr);
-bool DSPHost_OnThread();
-bool DSPHost_Running();
-void DSPHost_InterruptRequest();
-u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
-void DSPHost_UpdateDebugger();
-
-#endif
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _DSPHOST_H
+#define _DSPHOST_H
+
+// The user of the DSPCore library must supply a few functions so that the
+// emulation core can access the environment it runs in. If the emulation
+// core isn't used, for example in an asm/disasm tool, then most of these
+// can be stubbed out.
+#define DEBUG_EXP 1
+
+u8 DSPHost_ReadHostMemory(u32 addr);
+void DSPHost_WriteHostMemory(u8 value, u32 addr);
+bool DSPHost_OnThread();
+bool DSPHost_Running();
+void DSPHost_InterruptRequest();
+u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
+void DSPHost_UpdateDebugger();
+
+#endif
diff --git a/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp b/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp
index bb391a4a91..171a783331 100644
--- a/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp
+++ b/Source/Core/DSPCore/Src/DSPIntCCUtil.cpp
@@ -1,140 +1,140 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie and Tratax (c) 2004
-
-
-// HELPER FUNCTIONS
-
-#include "DSPIntCCUtil.h"
-#include "DSPCore.h"
-#include "DSPInterpreter.h"
-
-namespace DSPInterpreter {
-
-void Update_SR_Register64(s64 _Value)
-{
- g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
-
- if (_Value < 0)
- {
- g_dsp.r[DSP_REG_SR] |= SR_SIGN;
- }
-
- if (_Value == 0)
- {
- g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
- }
-
- // weird
- if ((_Value >> 62) == 0)
- {
- g_dsp.r[DSP_REG_SR] |= 0x20;
- }
-}
-
-void Update_SR_Register16(s16 _Value)
-{
- g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
-
- if (_Value < 0)
- {
- g_dsp.r[DSP_REG_SR] |= SR_SIGN;
- }
-
- if (_Value == 0)
- {
- g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
- }
-
- // weird
- if ((_Value >> 14) == 0)
- {
- g_dsp.r[DSP_REG_SR] |= 0x20;
- }
-}
-
-void Update_SR_LZ(s64 value) {
-
- if (value == 0)
- {
- g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
- }
- else
- {
- g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
- }
-
-}
-
-int GetMultiplyModifier()
-{
- if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
- return 1;
- else
- return 2;
-}
-
-inline bool isCarry() {
- return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
-}
-inline bool isSign() {
- return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
-}
-inline bool isZero() {
- return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
-}
-
-//see gdsp_registers.h for flags
-bool CheckCondition(u8 _Condition)
-{
- switch (_Condition & 0xf)
- {
- case 0x0: //NS - NOT SIGN
- return !isSign();
- case 0x1: // S - SIGN
- return isSign();
- case 0x2: // G - GREATER
- return !isSign() && !isZero();
- case 0x3: // LE - LESS EQUAL
- return isSign() || isZero();
- case 0x4: // NZ - NOT ZERO
- return !isZero();
- case 0x5: // Z - ZERO
- return isZero();
- case 0x6: // L - LESS
- // Should be that once we set 0x01
- return !isCarry();
- // if (isSign())
- case 0x7: // GE - GREATER EQUAL
- // Should be that once we set 0x01
- return isCarry();
- // if (! isSign() || isZero())
- case 0xc: // LNZ - LOGIC NOT ZERO
- return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
- case 0xd: // LZ - LOGIC ZERO
- return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
-
- case 0xf: // Empty - always true.
- return true;
- default:
- ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
- return false;
- }
-}
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie and Tratax (c) 2004
+
+
+// HELPER FUNCTIONS
+
+#include "DSPIntCCUtil.h"
+#include "DSPCore.h"
+#include "DSPInterpreter.h"
+
+namespace DSPInterpreter {
+
+void Update_SR_Register64(s64 _Value)
+{
+ g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
+
+ if (_Value < 0)
+ {
+ g_dsp.r[DSP_REG_SR] |= SR_SIGN;
+ }
+
+ if (_Value == 0)
+ {
+ g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
+ }
+
+ // weird
+ if ((_Value >> 62) == 0)
+ {
+ g_dsp.r[DSP_REG_SR] |= 0x20;
+ }
+}
+
+void Update_SR_Register16(s16 _Value)
+{
+ g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
+
+ if (_Value < 0)
+ {
+ g_dsp.r[DSP_REG_SR] |= SR_SIGN;
+ }
+
+ if (_Value == 0)
+ {
+ g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
+ }
+
+ // weird
+ if ((_Value >> 14) == 0)
+ {
+ g_dsp.r[DSP_REG_SR] |= 0x20;
+ }
+}
+
+void Update_SR_LZ(s64 value) {
+
+ if (value == 0)
+ {
+ g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
+ }
+ else
+ {
+ g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
+ }
+
+}
+
+int GetMultiplyModifier()
+{
+ if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
+ return 1;
+ else
+ return 2;
+}
+
+inline bool isCarry() {
+ return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
+}
+inline bool isSign() {
+ return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
+}
+inline bool isZero() {
+ return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
+}
+
+//see gdsp_registers.h for flags
+bool CheckCondition(u8 _Condition)
+{
+ switch (_Condition & 0xf)
+ {
+ case 0x0: //NS - NOT SIGN
+ return !isSign();
+ case 0x1: // S - SIGN
+ return isSign();
+ case 0x2: // G - GREATER
+ return !isSign() && !isZero();
+ case 0x3: // LE - LESS EQUAL
+ return isSign() || isZero();
+ case 0x4: // NZ - NOT ZERO
+ return !isZero();
+ case 0x5: // Z - ZERO
+ return isZero();
+ case 0x6: // L - LESS
+ // Should be that once we set 0x01
+ return !isCarry();
+ // if (isSign())
+ case 0x7: // GE - GREATER EQUAL
+ // Should be that once we set 0x01
+ return isCarry();
+ // if (! isSign() || isZero())
+ case 0xc: // LNZ - LOGIC NOT ZERO
+ return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
+ case 0xd: // LZ - LOGIC ZERO
+ return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
+
+ case 0xf: // Empty - always true.
+ return true;
+ default:
+ ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
+ return false;
+ }
+}
+
+} // namespace
diff --git a/Source/Core/DSPCore/Src/DSPIntCCUtil.h b/Source/Core/DSPCore/Src/DSPIntCCUtil.h
index def95e0b97..135e861062 100644
--- a/Source/Core/DSPCore/Src/DSPIntCCUtil.h
+++ b/Source/Core/DSPCore/Src/DSPIntCCUtil.h
@@ -1,39 +1,39 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie and Tratax (c) 2004
-
-#ifndef _GDSP_CONDITION_CODES_H
-#define _GDSP_CONDITION_CODES_H
-
-// Anything to do with SR and conditions goes here.
-
-#include "Common.h"
-
-namespace DSPInterpreter {
-
-bool CheckCondition(u8 _Condition);
-
-int GetMultiplyModifier();
-
-void Update_SR_Register16(s16 _Value);
-void Update_SR_Register64(s64 _Value);
-void Update_SR_LZ(s64 value);
-
-} // namespace
-
-#endif // _GDSP_CONDITION_CODES_H
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie and Tratax (c) 2004
+
+#ifndef _GDSP_CONDITION_CODES_H
+#define _GDSP_CONDITION_CODES_H
+
+// Anything to do with SR and conditions goes here.
+
+#include "Common.h"
+
+namespace DSPInterpreter {
+
+bool CheckCondition(u8 _Condition);
+
+int GetMultiplyModifier();
+
+void Update_SR_Register16(s16 _Value);
+void Update_SR_Register64(s64 _Value);
+void Update_SR_LZ(s64 value);
+
+} // namespace
+
+#endif // _GDSP_CONDITION_CODES_H
diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.h b/Source/Core/DSPCore/Src/DSPInterpreter.h
index d8f4d84f58..fe5f1afcc9 100644
--- a/Source/Core/DSPCore/Src/DSPInterpreter.h
+++ b/Source/Core/DSPCore/Src/DSPInterpreter.h
@@ -1,171 +1,171 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _DSPINTERPRETER_H
-#define _DSPINTERPRETER_H
-
-#include "DSPTables.h"
-
-#define DSP_REG_MASK 0x1f
-
-namespace DSPInterpreter {
-
-void Step();
-void Run();
-
-// If these simply return the same number of cycles as was passed into them,
-// chances are that the DSP is halted.
-// The difference between them is that the debug one obeys breakpoints.
-int RunCycles(int cycles);
-int RunCyclesDebug(int cycles);
-
-void Stop();
-
-void WriteCR(u16 val);
-u16 ReadCR();
-
-
-typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
-
-// All the opcode functions.
-void unknown(const UDSPInstruction& opc);
-void call(const UDSPInstruction& opc);
-void callr(const UDSPInstruction& opc);
-void ifcc(const UDSPInstruction& opc);
-void jcc(const UDSPInstruction& opc);
-void jmprcc(const UDSPInstruction& opc);
-void ret(const UDSPInstruction& opc);
-void halt(const UDSPInstruction& opc);
-void loop(const UDSPInstruction& opc);
-void loopi(const UDSPInstruction& opc);
-void bloop(const UDSPInstruction& opc);
-void bloopi(const UDSPInstruction& opc);
-void mrr(const UDSPInstruction& opc);
-void lrr(const UDSPInstruction& opc);
-void lrrd(const UDSPInstruction& opc);
-void lrri(const UDSPInstruction& opc);
-void lrrn(const UDSPInstruction& opc);
-void srr(const UDSPInstruction& opc);
-void srrd(const UDSPInstruction& opc);
-void srri(const UDSPInstruction& opc);
-void srrn(const UDSPInstruction& opc);
-void lri(const UDSPInstruction& opc);
-void lris(const UDSPInstruction& opc);
-void lr(const UDSPInstruction& opc);
-void sr(const UDSPInstruction& opc);
-void si(const UDSPInstruction& opc);
-void tstaxh(const UDSPInstruction& opc);
-void clr(const UDSPInstruction& opc);
-void clrl(const UDSPInstruction& opc);
-void clrp(const UDSPInstruction& opc);
-void mulc(const UDSPInstruction& opc);
-void cmpar(const UDSPInstruction& opc);
-void cmp(const UDSPInstruction& opc);
-void tst(const UDSPInstruction& opc);
-void addaxl(const UDSPInstruction& opc);
-void addarn(const UDSPInstruction& opc);
-void mulcac(const UDSPInstruction& opc);
-void movr(const UDSPInstruction& opc);
-void movax(const UDSPInstruction& opc);
-void xorr(const UDSPInstruction& opc);
-void andr(const UDSPInstruction& opc);
-void andc(const UDSPInstruction& opc);
-void orr(const UDSPInstruction& opc);
-void orc(const UDSPInstruction& opc);
-void orf(const UDSPInstruction& opc);
-void add(const UDSPInstruction& opc);
-void addp(const UDSPInstruction& opc);
-void cmpis(const UDSPInstruction& opc);
-void addpaxz(const UDSPInstruction& opc);
-void movpz(const UDSPInstruction& opc);
-void decm(const UDSPInstruction& opc);
-void dec(const UDSPInstruction& opc);
-void inc(const UDSPInstruction& opc);
-void incm(const UDSPInstruction& opc);
-void neg(const UDSPInstruction& opc);
-void addax(const UDSPInstruction& opc);
-void addr(const UDSPInstruction& opc);
-void subr(const UDSPInstruction& opc);
-void subp(const UDSPInstruction& opc);
-void subax(const UDSPInstruction& opc);
-void addis(const UDSPInstruction& opc);
-void addi(const UDSPInstruction& opc);
-void lsl16(const UDSPInstruction& opc);
-void madd(const UDSPInstruction& opc);
-void msub(const UDSPInstruction& opc);
-void lsr16(const UDSPInstruction& opc);
-void asr16(const UDSPInstruction& opc);
-void lsl(const UDSPInstruction& opc);
-void lsr(const UDSPInstruction& opc);
-void asl(const UDSPInstruction& opc);
-void asr(const UDSPInstruction& opc);
-void lsrn(const UDSPInstruction& opc);
-void asrn(const UDSPInstruction& opc);
-void dar(const UDSPInstruction& opc);
-void iar(const UDSPInstruction& opc);
-void sbclr(const UDSPInstruction& opc);
-void sbset(const UDSPInstruction& opc);
-void mov(const UDSPInstruction& opc);
-void movp(const UDSPInstruction& opc);
-void mul(const UDSPInstruction& opc);
-void mulac(const UDSPInstruction& opc);
-void mulmv(const UDSPInstruction& opc);
-void mulmvz(const UDSPInstruction& opc);
-void mulx(const UDSPInstruction& opc);
-void mulxac(const UDSPInstruction& opc);
-void mulxmv(const UDSPInstruction& opc);
-void mulxmvz(const UDSPInstruction& opc);
-void mulcmvz(const UDSPInstruction& opc);
-void mulcmv(const UDSPInstruction& opc);
-void movnp(const UDSPInstruction& opc);
-void sub(const UDSPInstruction& opc);
-void maddx(const UDSPInstruction& opc);
-void msubx(const UDSPInstruction& opc);
-void maddc(const UDSPInstruction& opc);
-void msubc(const UDSPInstruction& opc);
-void srs(const UDSPInstruction& opc);
-void lrs(const UDSPInstruction& opc);
-void nx(const UDSPInstruction& opc);
-void cmpi(const UDSPInstruction& opc);
-void rti(const UDSPInstruction& opc);
-void ilrr(const UDSPInstruction& opc);
-void ilrrd(const UDSPInstruction& opc);
-void ilrri(const UDSPInstruction& opc);
-void ilrrn(const UDSPInstruction& opc);
-void andcf(const UDSPInstruction& opc);
-void andf(const UDSPInstruction& opc);
-void xori(const UDSPInstruction& opc);
-void andi(const UDSPInstruction& opc);
-void ori(const UDSPInstruction& opc);
-
-// FIXME inside
-void srbith(const UDSPInstruction& opc);
-
-// END OF FIXMEs
-
-// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
-void tstaxl(const UDSPInstruction& opc);
-// The mysterious a100
-
-// END OF UNIMPLEMENTED
-
-// Helpers
-inline void tsta(int reg);
-
-} // namespace
-
-#endif // _DSPINTERPRETER_H
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _DSPINTERPRETER_H
+#define _DSPINTERPRETER_H
+
+#include "DSPTables.h"
+
+#define DSP_REG_MASK 0x1f
+
+namespace DSPInterpreter {
+
+void Step();
+void Run();
+
+// If these simply return the same number of cycles as was passed into them,
+// chances are that the DSP is halted.
+// The difference between them is that the debug one obeys breakpoints.
+int RunCycles(int cycles);
+int RunCyclesDebug(int cycles);
+
+void Stop();
+
+void WriteCR(u16 val);
+u16 ReadCR();
+
+
+typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
+
+// All the opcode functions.
+void unknown(const UDSPInstruction& opc);
+void call(const UDSPInstruction& opc);
+void callr(const UDSPInstruction& opc);
+void ifcc(const UDSPInstruction& opc);
+void jcc(const UDSPInstruction& opc);
+void jmprcc(const UDSPInstruction& opc);
+void ret(const UDSPInstruction& opc);
+void halt(const UDSPInstruction& opc);
+void loop(const UDSPInstruction& opc);
+void loopi(const UDSPInstruction& opc);
+void bloop(const UDSPInstruction& opc);
+void bloopi(const UDSPInstruction& opc);
+void mrr(const UDSPInstruction& opc);
+void lrr(const UDSPInstruction& opc);
+void lrrd(const UDSPInstruction& opc);
+void lrri(const UDSPInstruction& opc);
+void lrrn(const UDSPInstruction& opc);
+void srr(const UDSPInstruction& opc);
+void srrd(const UDSPInstruction& opc);
+void srri(const UDSPInstruction& opc);
+void srrn(const UDSPInstruction& opc);
+void lri(const UDSPInstruction& opc);
+void lris(const UDSPInstruction& opc);
+void lr(const UDSPInstruction& opc);
+void sr(const UDSPInstruction& opc);
+void si(const UDSPInstruction& opc);
+void tstaxh(const UDSPInstruction& opc);
+void clr(const UDSPInstruction& opc);
+void clrl(const UDSPInstruction& opc);
+void clrp(const UDSPInstruction& opc);
+void mulc(const UDSPInstruction& opc);
+void cmpar(const UDSPInstruction& opc);
+void cmp(const UDSPInstruction& opc);
+void tst(const UDSPInstruction& opc);
+void addaxl(const UDSPInstruction& opc);
+void addarn(const UDSPInstruction& opc);
+void mulcac(const UDSPInstruction& opc);
+void movr(const UDSPInstruction& opc);
+void movax(const UDSPInstruction& opc);
+void xorr(const UDSPInstruction& opc);
+void andr(const UDSPInstruction& opc);
+void andc(const UDSPInstruction& opc);
+void orr(const UDSPInstruction& opc);
+void orc(const UDSPInstruction& opc);
+void orf(const UDSPInstruction& opc);
+void add(const UDSPInstruction& opc);
+void addp(const UDSPInstruction& opc);
+void cmpis(const UDSPInstruction& opc);
+void addpaxz(const UDSPInstruction& opc);
+void movpz(const UDSPInstruction& opc);
+void decm(const UDSPInstruction& opc);
+void dec(const UDSPInstruction& opc);
+void inc(const UDSPInstruction& opc);
+void incm(const UDSPInstruction& opc);
+void neg(const UDSPInstruction& opc);
+void addax(const UDSPInstruction& opc);
+void addr(const UDSPInstruction& opc);
+void subr(const UDSPInstruction& opc);
+void subp(const UDSPInstruction& opc);
+void subax(const UDSPInstruction& opc);
+void addis(const UDSPInstruction& opc);
+void addi(const UDSPInstruction& opc);
+void lsl16(const UDSPInstruction& opc);
+void madd(const UDSPInstruction& opc);
+void msub(const UDSPInstruction& opc);
+void lsr16(const UDSPInstruction& opc);
+void asr16(const UDSPInstruction& opc);
+void lsl(const UDSPInstruction& opc);
+void lsr(const UDSPInstruction& opc);
+void asl(const UDSPInstruction& opc);
+void asr(const UDSPInstruction& opc);
+void lsrn(const UDSPInstruction& opc);
+void asrn(const UDSPInstruction& opc);
+void dar(const UDSPInstruction& opc);
+void iar(const UDSPInstruction& opc);
+void sbclr(const UDSPInstruction& opc);
+void sbset(const UDSPInstruction& opc);
+void mov(const UDSPInstruction& opc);
+void movp(const UDSPInstruction& opc);
+void mul(const UDSPInstruction& opc);
+void mulac(const UDSPInstruction& opc);
+void mulmv(const UDSPInstruction& opc);
+void mulmvz(const UDSPInstruction& opc);
+void mulx(const UDSPInstruction& opc);
+void mulxac(const UDSPInstruction& opc);
+void mulxmv(const UDSPInstruction& opc);
+void mulxmvz(const UDSPInstruction& opc);
+void mulcmvz(const UDSPInstruction& opc);
+void mulcmv(const UDSPInstruction& opc);
+void movnp(const UDSPInstruction& opc);
+void sub(const UDSPInstruction& opc);
+void maddx(const UDSPInstruction& opc);
+void msubx(const UDSPInstruction& opc);
+void maddc(const UDSPInstruction& opc);
+void msubc(const UDSPInstruction& opc);
+void srs(const UDSPInstruction& opc);
+void lrs(const UDSPInstruction& opc);
+void nx(const UDSPInstruction& opc);
+void cmpi(const UDSPInstruction& opc);
+void rti(const UDSPInstruction& opc);
+void ilrr(const UDSPInstruction& opc);
+void ilrrd(const UDSPInstruction& opc);
+void ilrri(const UDSPInstruction& opc);
+void ilrrn(const UDSPInstruction& opc);
+void andcf(const UDSPInstruction& opc);
+void andf(const UDSPInstruction& opc);
+void xori(const UDSPInstruction& opc);
+void andi(const UDSPInstruction& opc);
+void ori(const UDSPInstruction& opc);
+
+// FIXME inside
+void srbith(const UDSPInstruction& opc);
+
+// END OF FIXMEs
+
+// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
+void tstaxl(const UDSPInstruction& opc);
+// The mysterious a100
+
+// END OF UNIMPLEMENTED
+
+// Helpers
+inline void tsta(int reg);
+
+} // namespace
+
+#endif // _DSPINTERPRETER_H
diff --git a/Source/Core/DSPCore/Src/DSPJit.cpp b/Source/Core/DSPCore/Src/DSPJit.cpp
index cbf7d1ebeb..540380f6de 100644
--- a/Source/Core/DSPCore/Src/DSPJit.cpp
+++ b/Source/Core/DSPCore/Src/DSPJit.cpp
@@ -1,22 +1,22 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "DSPJit.h"
-
-namespace DSPJit {
-
-};
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "DSPJit.h"
+
+namespace DSPJit {
+
+};
diff --git a/Source/Core/DSPCore/Src/DSPJit.h b/Source/Core/DSPCore/Src/DSPJit.h
index 32e34672e2..9f05faedf1 100644
--- a/Source/Core/DSPCore/Src/DSPJit.h
+++ b/Source/Core/DSPCore/Src/DSPJit.h
@@ -1,28 +1,28 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _DSPJIT_H
-#define _DSPJIT_H
-
-namespace DSPJit {
-
-// TODO(XK): Fill
-
-
-} // namespace
-
-#endif // _DSPJIT_H
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _DSPJIT_H
+#define _DSPJIT_H
+
+namespace DSPJit {
+
+// TODO(XK): Fill
+
+
+} // namespace
+
+#endif // _DSPJIT_H
diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp
index 4913e0cc60..b9162de01a 100644
--- a/Source/Core/DSPCore/Src/DSPTables.cpp
+++ b/Source/Core/DSPCore/Src/DSPTables.cpp
@@ -1,583 +1,583 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
-
-/* NOTES BY HERMES:
-
-LZ flag: original opcodes andf and andcf are swaped. Also "jzr" and "jnz" are swaped but now named 'jlz' and 'jlnz'
-As you can see it obtain the same result but now LZ=1 correctly
-
-Added conditional instructions:
-
-conditional names:
-
-NZ -> NOT ZERO
-Z -> ZERO
-
-NS -> NOT SIGN
-S -> SIGN
-
-LZ -> LOGIC ZERO (only used with andcf-andf instructions?)
-LNZ -> LOGIC NOT ZERO
-
-G -> GREATER
-LE-> LESS EQUAL
-
-GE-> GREATER EQUAL
-L -> LESS
-
-Examples:
-
-jnz, ifs, retlnz
-
-*/
-
-
-#include "Common.h"
-#include "DSPTables.h"
-
-#include "DSPInterpreter.h"
-#include "DSPJit.h"
-#include "DSPIntExtOps.h"
-
-void nop(const UDSPInstruction& opc)
-{
- // The real nop is 0. Anything else is bad.
- if (opc.hex)
- DSPInterpreter::unknown(opc);
-}
-
-// Unknown Ops
-// All AX games: a100
-// Zelda Four Swords: 02ca
-
-// TODO: Fill up the tables with the corresponding instructions
-const DSPOPCTemplate opcodes[] =
-{
- {"NOP", 0x0000, 0xffff, nop, nop, 1, 0, {}, NULL, NULL},
-
- {"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL},
- {"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL},
-
- {"HALT", 0x0021, 0xffff, DSPInterpreter::halt, nop, 1, 0, {}, NULL, NULL},
-
- {"RETNS", 0x02d0, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETS", 0x02d1, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETG", 0x02d2, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETLE", 0x02d3, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETNZ", 0x02d4, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETZ", 0x02d5, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETL", 0x02d6, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETGE", 0x02d7, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETLNZ", 0x02dc, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RETLZ", 0x02dd, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RET", 0x02df, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
- {"RTI", 0x02ff, 0xffff, DSPInterpreter::rti, nop, 1, 0, {}, NULL, NULL},
-
- {"CALLNS", 0x02b0, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLS", 0x02b1, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLG", 0x02b2, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLLE", 0x02b3, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLNE", 0x02b4, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLZ", 0x02b5, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLL", 0x02b6, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLGE", 0x02b7, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLLNZ", 0x02bc, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALLLZ", 0x02bd, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"CALL", 0x02bf, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
-
- {"IFNS", 0x0270, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFS", 0x0271, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFG", 0x0272, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFLE", 0x0273, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFNZ", 0x0274, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFZ", 0x0275, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFL", 0x0276, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFGE", 0x0277, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFLNZ", 0x027c, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IFLZ", 0x027d, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
- {"IF", 0x027f, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, // This is just nop
-
- {"JNS", 0x0290, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JS", 0x0291, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JG", 0x0292, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JLE", 0x0293, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JNZ", 0x0294, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JZ", 0x0295, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JL", 0x0296, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JGE", 0x0297, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JLNZ", 0x029c, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
-
-
- {"JRNS", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRS", 0x1701, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRG", 0x1702, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRLE", 0x1703, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRNZ", 0x1704, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRZ", 0x1705, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRL", 0x1706, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRGE", 0x1707, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRLNZ", 0x170c, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JRLZ", 0x170d, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"JMPR", 0x170f, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
-
- {"CALLRNS", 0x1710, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRS", 0x1711, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRG", 0x1712, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRLE", 0x1713, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRNZ", 0x1714, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRZ", 0x1715, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRL", 0x1716, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRGE", 0x1717, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRLNZ",0x171c, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLRLZ", 0x171d, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
- {"CALLR", 0x171f, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
-
- {"SBCLR", 0x1200, 0xfff8, DSPInterpreter::sbclr, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, NULL, NULL},
- {"SBSET", 0x1300, 0xfff8, DSPInterpreter::sbset, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, NULL, NULL},
-
- // actually, given the masks these should probably be 0x3f. need investigation.
- {"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL},
- {"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL},
- {"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL},
- {"ASR", 0x14c0, 0xfec0, DSPInterpreter::asr, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL},
-
- // discovered by ector!
- {"LSRN", 0x02ca, 0xffff, DSPInterpreter::lsrn, nop, 1, 0, {}, NULL, NULL},
- {"ASRN", 0x02cb, 0xffff, DSPInterpreter::asrn, nop, 1, 0, {}, NULL, NULL},
-
- {"LRI", 0x0080, 0xffe0, DSPInterpreter::lri, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"LR", 0x00c0, 0xffe0, DSPInterpreter::lr, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"SR", 0x00e0, 0xffe0, DSPInterpreter::sr, nop, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
-
- {"MRR", 0x1c00, 0xfc00, DSPInterpreter::mrr, nop, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
-
- {"SI", 0x1600, 0xff00, DSPInterpreter::si, nop, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
-
- {"LRS", 0x2000, 0xf800, DSPInterpreter::lrs, nop, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}}, NULL, NULL},
- {"SRS", 0x2800, 0xf800, DSPInterpreter::srs, nop, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}}, NULL, NULL},
-
- {"LRIS", 0x0800, 0xf800, DSPInterpreter::lris, nop, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
-
- {"ADDIS", 0x0400, 0xfe00, DSPInterpreter::addis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
- {"CMPIS", 0x0600, 0xfe00, DSPInterpreter::cmpis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
- {"ANDI", 0x0240, 0xfeff, DSPInterpreter::andi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,},
- {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andcf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,},
-
- {"XORI", 0x0220, 0xfeff, DSPInterpreter::xori, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"ANDF", 0x02a0, 0xfeff, DSPInterpreter::andf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
-
- {"ORI", 0x0260, 0xfeff, DSPInterpreter::ori, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"ORF", 0x02e0, 0xfeff, DSPInterpreter::orf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, // Hermes: ??? (has it commented out)
-
- {"ADDI", 0x0200, 0xfeff, DSPInterpreter::addi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, // F|RES: missing S64
- {"CMPI", 0x0280, 0xfeff, DSPInterpreter::cmpi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
-
- {"ILRR", 0x0210, 0xfedc, DSPInterpreter::ilrr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL},
- {"ILRRD", 0x0214, 0xfedc, DSPInterpreter::ilrrd, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, // Hermes doesn't list this
- {"ILRRI", 0x0218, 0xfedc, DSPInterpreter::ilrri, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL},
- {"ILRRN", 0x0222, 0xfedc, DSPInterpreter::ilrrn, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL},
-
- // load and store value pointed by indexing reg and increment; LRR/SRR variants
- {"LRR", 0x1800, 0xff80, DSPInterpreter::lrr, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL},
- {"LRRD", 0x1880, 0xff80, DSPInterpreter::lrrd, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL},
- {"LRRI", 0x1900, 0xff80, DSPInterpreter::lrri, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL},
- {"LRRN", 0x1980, 0xff80, DSPInterpreter::lrrn, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL},
-
- {"SRR", 0x1a00, 0xff80, DSPInterpreter::srr, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
- {"SRRD", 0x1a80, 0xff80, DSPInterpreter::srrd, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
- {"SRRI", 0x1b00, 0xff80, DSPInterpreter::srri, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
- {"SRRN", 0x1b80, 0xff80, DSPInterpreter::srrn, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
-
- // LOOPS
- {"LOOP", 0x0040, 0xffe0, DSPInterpreter::loop, nop, 1, 1, {{P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
- {"BLOOP", 0x0060, 0xffe0, DSPInterpreter::bloop, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
- {"LOOPI", 0x1000, 0xff00, DSPInterpreter::loopi, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
- {"BLOOPI", 0x1100, 0xff00, DSPInterpreter::bloopi, nop, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
-
- {"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, nop, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, NULL, NULL},
-
-
- // opcodes that can be extended
- // extended opcodes, note size of opcode will be set to 0
-
- {"NX", 0x8000, 0xf700, DSPInterpreter::nx, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"M2", 0x8a00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"M0", 0x8b00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"CLR15", 0x8c00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"SET15", 0x8d00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"SET16", 0x8e00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"SET40", 0x8f00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
-
- {"INCM", 0x7400, 0xfeff, DSPInterpreter::incm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"INC", 0x7600, 0xfeff, DSPInterpreter::inc, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"DECM", 0x7800, 0xfeff, DSPInterpreter::decm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"DEC", 0x7a00, 0xfeff, DSPInterpreter::dec, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"NEG", 0x7c00, 0xfeff, DSPInterpreter::neg, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MOVNP", 0x7e00, 0xfeff, DSPInterpreter::movnp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
-
- {"TST", 0xb100, 0xf7ff, DSPInterpreter::tst, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- // Definitely not TSTAXL, it affects one of the accumulators. (a100 or a900, same op, one parameter).
- {"TSTAXL", 0xa100, 0xffff, DSPInterpreter::tstaxl, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"TSTAXH", 0x8600, 0xfeff, DSPInterpreter::tstaxh, nop, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"CMP", 0x8200, 0xffff, DSPInterpreter::cmp, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- // This op does NOT exist, at least not under this name, in duddie's docs!
- {"CMPAR" , 0xc100, 0xe7ff, DSPInterpreter::cmpar, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"CLRL", 0xfc00, 0xffff, DSPInterpreter::clrl, nop, 1 | P_EXT, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acl0
- {"CLR", 0x8100, 0xf7ff, DSPInterpreter::clr, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acc0
- {"CLRP", 0x8400, 0xffff, DSPInterpreter::clrp, nop, 1 | P_EXT, 0, {}, },
-
- {"MOV", 0x6c00, 0xfeff, DSPInterpreter::mov, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MOVAX", 0x6800, 0xfcff, DSPInterpreter::movax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MOVR", 0x6000, 0xf8ff, DSPInterpreter::movr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MOVP", 0x6e00, 0xfeff, DSPInterpreter::movp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MOVPZ", 0xfe00, 0xfeff, DSPInterpreter::movpz, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"ADDPAXZ", 0xf800, 0xfcff, DSPInterpreter::addpaxz, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, //Think the args are wrong
- {"ADDP", 0x4e00, 0xfeff, DSPInterpreter::addp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"LSL16", 0xf000, 0xfeff, DSPInterpreter::lsl16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"LSR16", 0xf400, 0xfeff, DSPInterpreter::lsr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"ASR16", 0x9100, 0xf7ff, DSPInterpreter::asr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"XORR", 0x3000, 0xfcff, DSPInterpreter::xorr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"ANDR", 0x3400, 0xfcff, DSPInterpreter::andr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"ORR", 0x3800, 0xfcff, DSPInterpreter::orr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"ANDC", 0x3C00, 0xfeff, DSPInterpreter::andc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this
- {"ORC", 0x3E00, 0xfeff, DSPInterpreter::orc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this
-
- {"MULX", 0xa000, 0xe7ff, DSPInterpreter::mulx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULXMVZ", 0xa200, 0xe6ff, DSPInterpreter::mulxmvz, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULXAC", 0xa400, 0xe6ff, DSPInterpreter::mulxac, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULXMV", 0xa600, 0xe6ff, DSPInterpreter::mulxmv, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"MUL", 0x9000, 0xf7ff, DSPInterpreter::mul, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULMVZ", 0x9200, 0xf6ff, DSPInterpreter::mulmvz, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULAC", 0x9400, 0xf6ff, DSPInterpreter::mulac, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULMV", 0x9600, 0xf6ff, DSPInterpreter::mulmv, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"MULC", 0xc000, 0xe7ff, DSPInterpreter::mulc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULCMVZ", 0xc200, 0xe6ff, DSPInterpreter::mulcmvz, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULCAC", 0xc400, 0xe6ff, DSPInterpreter::mulcac, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MULCMV", 0xc600, 0xe6ff, DSPInterpreter::mulcmv, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"ADDR", 0x4000, 0xf8ff, DSPInterpreter::addr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"ADDAX", 0x4800, 0xfcff, DSPInterpreter::addax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"ADD", 0x4c00, 0xfeff, DSPInterpreter::add, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"ADDAXL", 0x7000, 0xfcff, DSPInterpreter::addaxl, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"SUBR", 0x5000, 0xf8ff, DSPInterpreter::subr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"SUBAX", 0x5800, 0xfcff, DSPInterpreter::subax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"SUB", 0x5c00, 0xfeff, DSPInterpreter::sub, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"SUBP", 0x5e00, 0xfeff, DSPInterpreter::subp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-
- {"MADD", 0xf200, 0xfeff, DSPInterpreter::madd, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MSUB", 0xf600, 0xfeff, DSPInterpreter::msub , nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MADDX", 0xe000, 0xfcff, DSPInterpreter::maddx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MSUBX", 0xe400, 0xfcff, DSPInterpreter::msubx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MADDC", 0xe800, 0xfcff, DSPInterpreter::maddc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
- {"MSUBC", 0xec00, 0xfcff, DSPInterpreter::msubc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
-};
-
-const DSPOPCTemplate cw =
- {"CW", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, NULL, NULL,};
-
-
-const DSPOPCTemplate opcodes_ext[] =
-{
- // FIXME: guessing this is cr need checking
- {"DR", 0x0004, 0x00fc, nop, /*DSPInterpreter::Ext::dr*/ nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,},
- {"IR", 0x0008, 0x00fc, nop, /*DSPInterpreter::Ext::ir*/ nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,},
- {"NR", 0x000c, 0x00fc, nop, /*DSPInterpreter::Ext::nr*/ nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,},
- {"MV", 0x0010, 0x00f0, nop, /*DSPInterpreter::Ext::mv*/ nop, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}}, NULL, NULL,},
-
- {"S", 0x0020, 0x00e4, nop, /*DSPInterpreter::Ext::s*/ nop, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, NULL, NULL,},
- {"SN", 0x0024, 0x00e4, nop, /*DSPInterpreter::Ext::sn*/ nop, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, NULL, NULL,},
-
- {"L", 0x0040, 0x00c4, nop, /*DSPInterpreter::Ext::l*/ nop, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
- {"LN", 0x0044, 0x00c4, nop, /*DSPInterpreter::Ext::ln*/ nop, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
-
- {"LS", 0x0080, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,},
- {"SL", 0x0082, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,},
- {"LSN", 0x0084, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,},
- {"SLN", 0x0086, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,},
- {"LSM", 0x0088, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,},
- {"SLM", 0x008a, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,},
- {"LSNM", 0x008c, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,},
- {"SLNM", 0x008e, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,},
-
- /* FIXME: what are the LDX functions for? they have the same opcode as LD ones but different mask
- {"LDX", 0x00c0, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},
- {"LDXN", 0x00c4, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},
- {"LDXM", 0x00c8, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},
- {"LDXNM", 0x00cc, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},*/
-
- {"LD", 0x00c0, 0x00cc, nop, /*DSPInterpreter::Ext::ld*/ nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
- {"LDN", 0x00c4, 0x00cc, nop, /*DSPInterpreter::Ext::ldn*/ nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
- {"LDM", 0x00c8, 0x00cc, nop, /*DSPInterpreter::Ext::ldm*/ nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
- {"LDNM", 0x00cc, 0x00cc, nop, /*DSPInterpreter::Ext::ldnm*/ nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
-
- {"XXX", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, NULL, NULL,},
-};
-
-const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate);
-const int opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate);
-
-const pdlabel_t pdlabels[] =
-{
- {0xffa0, "COEF_A1_0", "COEF_A1_0",},
- {0xffa1, "COEF_A2_0", "COEF_A2_0",},
- {0xffa2, "COEF_A1_1", "COEF_A1_1",},
- {0xffa3, "COEF_A2_1", "COEF_A2_1",},
- {0xffa4, "COEF_A1_2", "COEF_A1_2",},
- {0xffa5, "COEF_A2_2", "COEF_A2_2",},
- {0xffa6, "COEF_A1_3", "COEF_A1_3",},
- {0xffa7, "COEF_A2_3", "COEF_A2_3",},
- {0xffa8, "COEF_A1_4", "COEF_A1_4",},
- {0xffa9, "COEF_A2_4", "COEF_A2_4",},
- {0xffaa, "COEF_A1_5", "COEF_A1_5",},
- {0xffab, "COEF_A2_5", "COEF_A2_5",},
- {0xffac, "COEF_A1_6", "COEF_A1_6",},
- {0xffad, "COEF_A2_6", "COEF_A2_6",},
- {0xffae, "COEF_A1_7", "COEF_A1_7",},
- {0xffaf, "COEF_A2_7", "COEF_A2_7",},
-
- {0xffb0, "0xffb0", 0,},
- {0xffb1, "0xffb1", 0,},
- {0xffb2, "0xffb2", 0,},
- {0xffb3, "0xffb3", 0,},
- {0xffb4, "0xffb4", 0,},
- {0xffb5, "0xffb5", 0,},
- {0xffb6, "0xffb6", 0,},
- {0xffb7, "0xffb7", 0,},
- {0xffb8, "0xffb8", 0,},
- {0xffb9, "0xffb9", 0,},
- {0xffba, "0xffba", 0,},
- {0xffbb, "0xffbb", 0,},
- {0xffbc, "0xffbc", 0,},
- {0xffbd, "0xffbd", 0,},
- {0xffbe, "0xffbe", 0,},
- {0xffbf, "0xffbf", 0,},
-
- {0xffc0, "0xffc0", 0,},
- {0xffc1, "0xffc1", 0,},
- {0xffc2, "0xffc2", 0,},
- {0xffc3, "0xffc3", 0,},
- {0xffc4, "0xffc4", 0,},
- {0xffc5, "0xffc5", 0,},
- {0xffc6, "0xffc6", 0,},
- {0xffc7, "0xffc7", 0,},
- {0xffc8, "0xffc8", 0,},
- {0xffc9, "DSCR", "DSP DMA Control Reg",},
- {0xffca, "0xffca", 0,},
- {0xffcb, "DSBL", "DSP DMA Block Length",},
- {0xffcc, "0xffcc", 0,},
- {0xffcd, "DSPA", "DSP DMA DMEM Address",},
- {0xffce, "DSMAH", "DSP DMA Mem Address H",},
- {0xffcf, "DSMAL", "DSP DMA Mem Address L",},
-
- {0xffd0, "0xffd0",0,},
- {0xffd1, "SampleFormat", "SampleFormat",},
- {0xffd2, "0xffd2",0,},
- {0xffd3, "UnkZelda", "Unk Zelda reads/writes from/to it",},
- {0xffd4, "ACSAH", "Accelerator start address H",},
- {0xffd5, "ACSAL", "Accelerator start address L",},
- {0xffd6, "ACEAH", "Accelerator end address H",},
- {0xffd7, "ACEAL", "Accelerator end address L",},
- {0xffd8, "ACCAH", "Accelerator current address H",},
- {0xffd9, "ACCAL", "Accelerator current address L",},
- {0xffda, "pred_scale", "pred_scale",},
- {0xffdb, "yn1", "yn1",},
- {0xffdc, "yn2", "yn2",},
- {0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",},
- {0xffde, "GAIN", "Gain",},
- {0xffdf, "0xffdf", 0,},
-
- {0xffe0, "0xffe0",0,},
- {0xffe1, "0xffe1",0,},
- {0xffe2, "0xffe2",0,},
- {0xffe3, "0xffe3",0,},
- {0xffe4, "0xffe4",0,},
- {0xffe5, "0xffe5",0,},
- {0xffe6, "0xffe6",0,},
- {0xffe7, "0xffe7",0,},
- {0xffe8, "0xffe8",0,},
- {0xffe9, "0xffe9",0,},
- {0xffea, "0xffea",0,},
- {0xffeb, "0xffeb",0,},
- {0xffec, "0xffec",0,},
- {0xffed, "0xffed",0,},
- {0xffee, "0xffee",0,},
- {0xffef, "AMDM", "ARAM DMA Request Mask",},
-
- {0xfff0, "0xfff0",0,},
- {0xfff1, "0xfff1",0,},
- {0xfff2, "0xfff2",0,},
- {0xfff3, "0xfff3",0,},
- {0xfff4, "0xfff4",0,},
- {0xfff5, "0xfff5",0,},
- {0xfff6, "0xfff6",0,},
- {0xfff7, "0xfff7",0,},
- {0xfff8, "0xfff8",0,},
- {0xfff9, "0xfff9",0,},
- {0xfffa, "0xfffa",0,},
- {0xfffb, "DIRQ", "DSP IRQ Request",},
- {0xfffc, "DMBH", "DSP Mailbox H",},
- {0xfffd, "DMBL", "DSP Mailbox L",},
- {0xfffe, "CMBH", "CPU Mailbox H",},
- {0xffff, "CMBL", "CPU Mailbox L",},
-};
-
-const u32 pdlabels_size = sizeof(pdlabels) / sizeof(pdlabel_t);
-
-const pdlabel_t regnames[] =
-{
- {0x00, "AR0", "Addr Reg 00",},
- {0x01, "AR1", "Addr Reg 01",},
- {0x02, "AR2", "Addr Reg 02",},
- {0x03, "AR3", "Addr Reg 03",},
- {0x04, "IX0", "Index Reg 0",},
- {0x05, "IX1", "Index Reg 1",},
- {0x06, "IX2", "Index Reg 2",},
- {0x07, "IX3", "Index Reg 3",},
- {0x08, "WR0", "Wrapping Register 0",},
- {0x09, "WR1", "Wrapping Register 1",},
- {0x0a, "WR2", "Wrapping Register 2",},
- {0x0b, "WR3", "Wrapping Register 3",},
- {0x0c, "ST0", "Call stack",},
- {0x0d, "ST1", "Data stack",},
- {0x0e, "ST2", "Loop addr stack",},
- {0x0f, "ST3", "Loop counter",},
- {0x10, "AC0.H", "Accu High 0",},
- {0x11, "AC1.H", "Accu High 1",},
- {0x12, "CR", "Config Register",},
- {0x13, "SR", "Special Register",},
- {0x14, "PROD.L", "Prod L",},
- {0x15, "PROD.M1", "Prod M1",},
- {0x16, "PROD.H", "Prod H",},
- {0x17, "PROD.M2", "Prod M2",},
- {0x18, "AX0.L", "Extra Accu L 0",},
- {0x19, "AX1.L", "Extra Accu L 1",},
- {0x1a, "AX0.H", "Extra Accu H 0",},
- {0x1b, "AX1.H", "Extra Accu H 1",},
- {0x1c, "AC0.L", "Accu Low 0",},
- {0x1d, "AC1.L", "Accu Low 1",},
- {0x1e, "AC0.M", "Accu Mid 0",},
- {0x1f, "AC1.M", "Accu Mid 1",},
-
- // To resolve combined register names.
- {0x20, "ACC0", "Accu Full 0",},
- {0x21, "ACC1", "Accu Full 1",},
- {0x22, "AX0", "Extra Accu 0",},
- {0x23, "AX1", "Extra Accu 1",},
-};
-
-u8 opSize[OPTABLE_SIZE];
-dspInstFunc opTable[OPTABLE_SIZE];
-dspInstFunc prologueTable[OPTABLE_SIZE];
-dspInstFunc epilogueTable[OPTABLE_SIZE];
-
-const char* pdname(u16 val)
-{
- static char tmpstr[12]; // nasty
-
- for (int i = 0; i < (int)(sizeof(pdlabels) / sizeof(pdlabel_t)); i++)
- {
- if (pdlabels[i].addr == val)
- return pdlabels[i].name;
- }
-
- sprintf(tmpstr, "0x%04x", val);
- return tmpstr;
-}
-
-const char *pdregname(int val)
-{
- return regnames[val].name;
-}
-
-const char *pdregnamelong(int val)
-{
- return regnames[val].description;
-}
-
-const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst)
-{
- for (int i = 0; i < opcodes_size; i++)
- {
- u16 mask = opcodes[i].opcode_mask;
- if (opcodes[i].size & P_EXT) {
- // Ignore extension bits.
- mask &= 0xFF00;
- }
- if ((mask & inst.hex) == opcodes[i].opcode)
- return &opcodes[i];
- }
- return NULL;
-}
-
-
-// This function could use the above GetOpTemplate, but then we'd lose the
-// nice property that it catches colliding op masks.
-void InitInstructionTable()
-{
- for (int i = 0; i < OPTABLE_SIZE; i++)
- {
- opTable[i] = DSPInterpreter::unknown;
- prologueTable[i] = NULL;
- epilogueTable[i] = NULL;
- opSize[i] = 0;
- }
-
- for (int i = 0; i < OPTABLE_SIZE; i++)
- {
- for (int j = 0; j < opcodes_size; j++)
- {
- u16 mask = opcodes[j].opcode_mask;
- if (opcodes[j].size & P_EXT) {
- // Ignore extension bits.
- mask &= 0xFF00;
- }
- if ((mask & i) == opcodes[j].opcode)
- {
- if (opTable[i] == DSPInterpreter::unknown)
- {
- opTable[i] = opcodes[j].interpFunc;
- opSize[i] = opcodes[j].size & 3;
- prologueTable[i] = opcodes[j].prologue;
- epilogueTable[i] = opcodes[j].epilogue;
- }
- else
- {
- ERROR_LOG(DSPLLE, "opcode table place %d already in use for %s", i, opcodes[j].name);
- }
- }
- }
- }
-}
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
+
+/* NOTES BY HERMES:
+
+LZ flag: original opcodes andf and andcf are swaped. Also "jzr" and "jnz" are swaped but now named 'jlz' and 'jlnz'
+As you can see it obtain the same result but now LZ=1 correctly
+
+Added conditional instructions:
+
+conditional names:
+
+NZ -> NOT ZERO
+Z -> ZERO
+
+NS -> NOT SIGN
+S -> SIGN
+
+LZ -> LOGIC ZERO (only used with andcf-andf instructions?)
+LNZ -> LOGIC NOT ZERO
+
+G -> GREATER
+LE-> LESS EQUAL
+
+GE-> GREATER EQUAL
+L -> LESS
+
+Examples:
+
+jnz, ifs, retlnz
+
+*/
+
+
+#include "Common.h"
+#include "DSPTables.h"
+
+#include "DSPInterpreter.h"
+#include "DSPJit.h"
+#include "DSPIntExtOps.h"
+
+void nop(const UDSPInstruction& opc)
+{
+ // The real nop is 0. Anything else is bad.
+ if (opc.hex)
+ DSPInterpreter::unknown(opc);
+}
+
+// Unknown Ops
+// All AX games: a100
+// Zelda Four Swords: 02ca
+
+// TODO: Fill up the tables with the corresponding instructions
+const DSPOPCTemplate opcodes[] =
+{
+ {"NOP", 0x0000, 0xffff, nop, nop, 1, 0, {}, NULL, NULL},
+
+ {"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL},
+ {"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL},
+
+ {"HALT", 0x0021, 0xffff, DSPInterpreter::halt, nop, 1, 0, {}, NULL, NULL},
+
+ {"RETNS", 0x02d0, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETS", 0x02d1, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETG", 0x02d2, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETLE", 0x02d3, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETNZ", 0x02d4, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETZ", 0x02d5, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETL", 0x02d6, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETGE", 0x02d7, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETLNZ", 0x02dc, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RETLZ", 0x02dd, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RET", 0x02df, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
+ {"RTI", 0x02ff, 0xffff, DSPInterpreter::rti, nop, 1, 0, {}, NULL, NULL},
+
+ {"CALLNS", 0x02b0, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLS", 0x02b1, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLG", 0x02b2, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLLE", 0x02b3, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLNE", 0x02b4, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLZ", 0x02b5, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLL", 0x02b6, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLGE", 0x02b7, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLLNZ", 0x02bc, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALLLZ", 0x02bd, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"CALL", 0x02bf, 0xffff, DSPInterpreter::call, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+
+ {"IFNS", 0x0270, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFS", 0x0271, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFG", 0x0272, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFLE", 0x0273, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFNZ", 0x0274, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFZ", 0x0275, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFL", 0x0276, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFGE", 0x0277, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFLNZ", 0x027c, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IFLZ", 0x027d, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL},
+ {"IF", 0x027f, 0xffff, DSPInterpreter::ifcc, nop, 1, 0, {}, NULL, NULL}, // This is just nop
+
+ {"JNS", 0x0290, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JS", 0x0291, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JG", 0x0292, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JLE", 0x0293, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JNZ", 0x0294, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JZ", 0x0295, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JL", 0x0296, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JGE", 0x0297, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JLNZ", 0x029c, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+
+
+ {"JRNS", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRS", 0x1701, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRG", 0x1702, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRLE", 0x1703, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRNZ", 0x1704, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRZ", 0x1705, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRL", 0x1706, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRGE", 0x1707, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRLNZ", 0x170c, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JRLZ", 0x170d, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"JMPR", 0x170f, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+
+ {"CALLRNS", 0x1710, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRS", 0x1711, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRG", 0x1712, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRLE", 0x1713, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRNZ", 0x1714, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRZ", 0x1715, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRL", 0x1716, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRGE", 0x1717, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRLNZ",0x171c, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLRLZ", 0x171d, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+ {"CALLR", 0x171f, 0xff1f, DSPInterpreter::callr, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
+
+ {"SBCLR", 0x1200, 0xfff8, DSPInterpreter::sbclr, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, NULL, NULL},
+ {"SBSET", 0x1300, 0xfff8, DSPInterpreter::sbset, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}}, NULL, NULL},
+
+ // actually, given the masks these should probably be 0x3f. need investigation.
+ {"LSL", 0x1400, 0xfec0, DSPInterpreter::lsl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL},
+ {"LSR", 0x1440, 0xfec0, DSPInterpreter::lsr, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL},
+ {"ASL", 0x1480, 0xfec0, DSPInterpreter::asl, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL},
+ {"ASR", 0x14c0, 0xfec0, DSPInterpreter::asr, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}}, NULL, NULL},
+
+ // discovered by ector!
+ {"LSRN", 0x02ca, 0xffff, DSPInterpreter::lsrn, nop, 1, 0, {}, NULL, NULL},
+ {"ASRN", 0x02cb, 0xffff, DSPInterpreter::asrn, nop, 1, 0, {}, NULL, NULL},
+
+ {"LRI", 0x0080, 0xffe0, DSPInterpreter::lri, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"LR", 0x00c0, 0xffe0, DSPInterpreter::lr, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"SR", 0x00e0, 0xffe0, DSPInterpreter::sr, nop, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
+
+ {"MRR", 0x1c00, 0xfc00, DSPInterpreter::mrr, nop, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
+
+ {"SI", 0x1600, 0xff00, DSPInterpreter::si, nop, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
+
+ {"LRS", 0x2000, 0xf800, DSPInterpreter::lrs, nop, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}}, NULL, NULL},
+ {"SRS", 0x2800, 0xf800, DSPInterpreter::srs, nop, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}}, NULL, NULL},
+
+ {"LRIS", 0x0800, 0xf800, DSPInterpreter::lris, nop, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
+
+ {"ADDIS", 0x0400, 0xfe00, DSPInterpreter::addis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
+ {"CMPIS", 0x0600, 0xfe00, DSPInterpreter::cmpis, nop, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
+ {"ANDI", 0x0240, 0xfeff, DSPInterpreter::andi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,},
+ {"ANDCF", 0x02c0, 0xfeff, DSPInterpreter::andcf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL,},
+
+ {"XORI", 0x0220, 0xfeff, DSPInterpreter::xori, nop, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"ANDF", 0x02a0, 0xfeff, DSPInterpreter::andf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
+
+ {"ORI", 0x0260, 0xfeff, DSPInterpreter::ori, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"ORF", 0x02e0, 0xfeff, DSPInterpreter::orf, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, // Hermes: ??? (has it commented out)
+
+ {"ADDI", 0x0200, 0xfeff, DSPInterpreter::addi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL}, // F|RES: missing S64
+ {"CMPI", 0x0280, 0xfeff, DSPInterpreter::cmpi, nop, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}}, NULL, NULL},
+
+ {"ILRR", 0x0210, 0xfedc, DSPInterpreter::ilrr, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL},
+ {"ILRRD", 0x0214, 0xfedc, DSPInterpreter::ilrrd, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL}, // Hermes doesn't list this
+ {"ILRRI", 0x0218, 0xfedc, DSPInterpreter::ilrri, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL},
+ {"ILRRN", 0x0222, 0xfedc, DSPInterpreter::ilrrn, nop, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL},
+
+ // load and store value pointed by indexing reg and increment; LRR/SRR variants
+ {"LRR", 0x1800, 0xff80, DSPInterpreter::lrr, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL},
+ {"LRRD", 0x1880, 0xff80, DSPInterpreter::lrrd, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL},
+ {"LRRI", 0x1900, 0xff80, DSPInterpreter::lrri, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL},
+ {"LRRN", 0x1980, 0xff80, DSPInterpreter::lrrn, nop, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}}, NULL, NULL},
+
+ {"SRR", 0x1a00, 0xff80, DSPInterpreter::srr, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
+ {"SRRD", 0x1a80, 0xff80, DSPInterpreter::srrd, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
+ {"SRRI", 0x1b00, 0xff80, DSPInterpreter::srri, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
+ {"SRRN", 0x1b80, 0xff80, DSPInterpreter::srrn, nop, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
+
+ // LOOPS
+ {"LOOP", 0x0040, 0xffe0, DSPInterpreter::loop, nop, 1, 1, {{P_REG, 1, 0, 0, 0x001f}}, NULL, NULL},
+ {"BLOOP", 0x0060, 0xffe0, DSPInterpreter::bloop, nop, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+ {"LOOPI", 0x1000, 0xff00, DSPInterpreter::loopi, nop, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}}, NULL, NULL},
+ {"BLOOPI", 0x1100, 0xff00, DSPInterpreter::bloopi, nop, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_ADDR_I, 2, 1, 0, 0xffff}}, NULL, NULL},
+
+ {"ADDARN", 0x0010, 0xfff0, DSPInterpreter::addarn, nop, 1, 2, {{P_REG, 1, 0, 0, 0x0003}, {P_REG04, 1, 0, 2, 0x000c}}, NULL, NULL},
+
+
+ // opcodes that can be extended
+ // extended opcodes, note size of opcode will be set to 0
+
+ {"NX", 0x8000, 0xf700, DSPInterpreter::nx, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"M2", 0x8a00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"M0", 0x8b00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"CLR15", 0x8c00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"SET15", 0x8d00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"SET16", 0x8e00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"SET40", 0x8f00, 0xffff, DSPInterpreter::srbith, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+
+ {"INCM", 0x7400, 0xfeff, DSPInterpreter::incm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"INC", 0x7600, 0xfeff, DSPInterpreter::inc, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"DECM", 0x7800, 0xfeff, DSPInterpreter::decm, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"DEC", 0x7a00, 0xfeff, DSPInterpreter::dec, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"NEG", 0x7c00, 0xfeff, DSPInterpreter::neg, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MOVNP", 0x7e00, 0xfeff, DSPInterpreter::movnp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+
+ {"TST", 0xb100, 0xf7ff, DSPInterpreter::tst, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ // Definitely not TSTAXL, it affects one of the accumulators. (a100 or a900, same op, one parameter).
+ {"TSTAXL", 0xa100, 0xffff, DSPInterpreter::tstaxl, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"TSTAXH", 0x8600, 0xfeff, DSPInterpreter::tstaxh, nop, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"CMP", 0x8200, 0xffff, DSPInterpreter::cmp, nop, 1 | P_EXT, 0, {}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ // This op does NOT exist, at least not under this name, in duddie's docs!
+ {"CMPAR" , 0xc100, 0xe7ff, DSPInterpreter::cmpar, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"CLRL", 0xfc00, 0xffff, DSPInterpreter::clrl, nop, 1 | P_EXT, 1, {{P_ACCL, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acl0
+ {"CLR", 0x8100, 0xf7ff, DSPInterpreter::clr, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // clear acc0
+ {"CLRP", 0x8400, 0xffff, DSPInterpreter::clrp, nop, 1 | P_EXT, 0, {}, },
+
+ {"MOV", 0x6c00, 0xfeff, DSPInterpreter::mov, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MOVAX", 0x6800, 0xfcff, DSPInterpreter::movax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MOVR", 0x6000, 0xf8ff, DSPInterpreter::movr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MOVP", 0x6e00, 0xfeff, DSPInterpreter::movp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MOVPZ", 0xfe00, 0xfeff, DSPInterpreter::movpz, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"ADDPAXZ", 0xf800, 0xfcff, DSPInterpreter::addpaxz, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, //Think the args are wrong
+ {"ADDP", 0x4e00, 0xfeff, DSPInterpreter::addp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"LSL16", 0xf000, 0xfeff, DSPInterpreter::lsl16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"LSR16", 0xf400, 0xfeff, DSPInterpreter::lsr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"ASR16", 0x9100, 0xf7ff, DSPInterpreter::asr16, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"XORR", 0x3000, 0xfcff, DSPInterpreter::xorr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"ANDR", 0x3400, 0xfcff, DSPInterpreter::andr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"ORR", 0x3800, 0xfcff, DSPInterpreter::orr, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"ANDC", 0x3C00, 0xfeff, DSPInterpreter::andc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this
+ {"ORC", 0x3E00, 0xfeff, DSPInterpreter::orc, nop, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi}, // Hermes doesn't list this
+
+ {"MULX", 0xa000, 0xe7ff, DSPInterpreter::mulx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULXMVZ", 0xa200, 0xe6ff, DSPInterpreter::mulxmvz, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULXAC", 0xa400, 0xe6ff, DSPInterpreter::mulxac, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULXMV", 0xa600, 0xe6ff, DSPInterpreter::mulxmv, nop, 1 | P_EXT, 3, {{P_REGM18, 1, 0, 11, 0x1000}, {P_REGM19, 1, 0, 10, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"MUL", 0x9000, 0xf7ff, DSPInterpreter::mul, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULMVZ", 0x9200, 0xf6ff, DSPInterpreter::mulmvz, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULAC", 0x9400, 0xf6ff, DSPInterpreter::mulac, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULMV", 0x9600, 0xf6ff, DSPInterpreter::mulmv, nop, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"MULC", 0xc000, 0xe7ff, DSPInterpreter::mulc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULCMVZ", 0xc200, 0xe6ff, DSPInterpreter::mulcmvz, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULCAC", 0xc400, 0xe6ff, DSPInterpreter::mulcac, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MULCMV", 0xc600, 0xe6ff, DSPInterpreter::mulcmv, nop, 1 | P_EXT, 3, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"ADDR", 0x4000, 0xf8ff, DSPInterpreter::addr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"ADDAX", 0x4800, 0xfcff, DSPInterpreter::addax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"ADD", 0x4c00, 0xfeff, DSPInterpreter::add, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"ADDAXL", 0x7000, 0xfcff, DSPInterpreter::addaxl, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"SUBR", 0x5000, 0xf8ff, DSPInterpreter::subr, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"SUBAX", 0x5800, 0xfcff, DSPInterpreter::subax, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"SUB", 0x5c00, 0xfeff, DSPInterpreter::sub, nop, 1 | P_EXT, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_ACC_D, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"SUBP", 0x5e00, 0xfeff, DSPInterpreter::subp, nop, 1 | P_EXT, 1, {{P_ACC, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+
+ {"MADD", 0xf200, 0xfeff, DSPInterpreter::madd, nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MSUB", 0xf600, 0xfeff, DSPInterpreter::msub , nop, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MADDX", 0xe000, 0xfcff, DSPInterpreter::maddx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MSUBX", 0xe400, 0xfcff, DSPInterpreter::msubx, nop, 1 | P_EXT, 2, {{P_REGM18, 1, 0, 8, 0x0200}, {P_REGM19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MADDC", 0xe800, 0xfcff, DSPInterpreter::maddc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+ {"MSUBC", 0xec00, 0xfcff, DSPInterpreter::msubc, nop, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}}, dsp_op_ext_ops_pro, dsp_op_ext_ops_epi},
+};
+
+const DSPOPCTemplate cw =
+ {"CW", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}}, NULL, NULL,};
+
+
+const DSPOPCTemplate opcodes_ext[] =
+{
+ // FIXME: guessing this is cr need checking
+ {"DR", 0x0004, 0x00fc, nop, /*DSPInterpreter::Ext::dr*/ nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+ {"IR", 0x0008, 0x00fc, nop, /*DSPInterpreter::Ext::ir*/ nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+ {"NR", 0x000c, 0x00fc, nop, /*DSPInterpreter::Ext::nr*/ nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+ {"MV", 0x0010, 0x00f0, nop, /*DSPInterpreter::Ext::mv*/ nop, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}}, NULL, NULL,},
+
+ {"S", 0x0020, 0x00e4, nop, /*DSPInterpreter::Ext::s*/ nop, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, NULL, NULL,},
+ {"SN", 0x0024, 0x00e4, nop, /*DSPInterpreter::Ext::sn*/ nop, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}}, NULL, NULL,},
+
+ {"L", 0x0040, 0x00c4, nop, /*DSPInterpreter::Ext::l*/ nop, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+ {"LN", 0x0044, 0x00c4, nop, /*DSPInterpreter::Ext::ln*/ nop, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+
+ {"LS", 0x0080, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,},
+ {"SL", 0x0082, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,},
+ {"LSN", 0x0084, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,},
+ {"SLN", 0x0086, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,},
+ {"LSM", 0x0088, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,},
+ {"SLM", 0x008a, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,},
+ {"LSNM", 0x008c, 0x00ce, nop, nop, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}}, NULL, NULL,},
+ {"SLNM", 0x008e, 0x00ce, nop, nop, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}}, NULL, NULL,},
+
+ /* FIXME: what are the LDX functions for? they have the same opcode as LD ones but different mask
+ {"LDX", 0x00c0, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},
+ {"LDXN", 0x00c4, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},
+ {"LDXM", 0x00c8, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},
+ {"LDXNM", 0x00cc, 0x00cf, nop, nop, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}}, NULL, NULL,},*/
+
+ {"LD", 0x00c0, 0x00cc, nop, /*DSPInterpreter::Ext::ld*/ nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+ {"LDN", 0x00c4, 0x00cc, nop, /*DSPInterpreter::Ext::ldn*/ nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+ {"LDM", 0x00c8, 0x00cc, nop, /*DSPInterpreter::Ext::ldm*/ nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+ {"LDNM", 0x00cc, 0x00cc, nop, /*DSPInterpreter::Ext::ldnm*/ nop, 1, 3, {{P_REGM18, 1, 0, 4, 0x0020}, {P_REGM19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}}, NULL, NULL,},
+
+ {"XXX", 0x0000, 0x0000, nop, nop, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}}, NULL, NULL,},
+};
+
+const int opcodes_size = sizeof(opcodes) / sizeof(DSPOPCTemplate);
+const int opcodes_ext_size = sizeof(opcodes_ext) / sizeof(DSPOPCTemplate);
+
+const pdlabel_t pdlabels[] =
+{
+ {0xffa0, "COEF_A1_0", "COEF_A1_0",},
+ {0xffa1, "COEF_A2_0", "COEF_A2_0",},
+ {0xffa2, "COEF_A1_1", "COEF_A1_1",},
+ {0xffa3, "COEF_A2_1", "COEF_A2_1",},
+ {0xffa4, "COEF_A1_2", "COEF_A1_2",},
+ {0xffa5, "COEF_A2_2", "COEF_A2_2",},
+ {0xffa6, "COEF_A1_3", "COEF_A1_3",},
+ {0xffa7, "COEF_A2_3", "COEF_A2_3",},
+ {0xffa8, "COEF_A1_4", "COEF_A1_4",},
+ {0xffa9, "COEF_A2_4", "COEF_A2_4",},
+ {0xffaa, "COEF_A1_5", "COEF_A1_5",},
+ {0xffab, "COEF_A2_5", "COEF_A2_5",},
+ {0xffac, "COEF_A1_6", "COEF_A1_6",},
+ {0xffad, "COEF_A2_6", "COEF_A2_6",},
+ {0xffae, "COEF_A1_7", "COEF_A1_7",},
+ {0xffaf, "COEF_A2_7", "COEF_A2_7",},
+
+ {0xffb0, "0xffb0", 0,},
+ {0xffb1, "0xffb1", 0,},
+ {0xffb2, "0xffb2", 0,},
+ {0xffb3, "0xffb3", 0,},
+ {0xffb4, "0xffb4", 0,},
+ {0xffb5, "0xffb5", 0,},
+ {0xffb6, "0xffb6", 0,},
+ {0xffb7, "0xffb7", 0,},
+ {0xffb8, "0xffb8", 0,},
+ {0xffb9, "0xffb9", 0,},
+ {0xffba, "0xffba", 0,},
+ {0xffbb, "0xffbb", 0,},
+ {0xffbc, "0xffbc", 0,},
+ {0xffbd, "0xffbd", 0,},
+ {0xffbe, "0xffbe", 0,},
+ {0xffbf, "0xffbf", 0,},
+
+ {0xffc0, "0xffc0", 0,},
+ {0xffc1, "0xffc1", 0,},
+ {0xffc2, "0xffc2", 0,},
+ {0xffc3, "0xffc3", 0,},
+ {0xffc4, "0xffc4", 0,},
+ {0xffc5, "0xffc5", 0,},
+ {0xffc6, "0xffc6", 0,},
+ {0xffc7, "0xffc7", 0,},
+ {0xffc8, "0xffc8", 0,},
+ {0xffc9, "DSCR", "DSP DMA Control Reg",},
+ {0xffca, "0xffca", 0,},
+ {0xffcb, "DSBL", "DSP DMA Block Length",},
+ {0xffcc, "0xffcc", 0,},
+ {0xffcd, "DSPA", "DSP DMA DMEM Address",},
+ {0xffce, "DSMAH", "DSP DMA Mem Address H",},
+ {0xffcf, "DSMAL", "DSP DMA Mem Address L",},
+
+ {0xffd0, "0xffd0",0,},
+ {0xffd1, "SampleFormat", "SampleFormat",},
+ {0xffd2, "0xffd2",0,},
+ {0xffd3, "UnkZelda", "Unk Zelda reads/writes from/to it",},
+ {0xffd4, "ACSAH", "Accelerator start address H",},
+ {0xffd5, "ACSAL", "Accelerator start address L",},
+ {0xffd6, "ACEAH", "Accelerator end address H",},
+ {0xffd7, "ACEAL", "Accelerator end address L",},
+ {0xffd8, "ACCAH", "Accelerator current address H",},
+ {0xffd9, "ACCAL", "Accelerator current address L",},
+ {0xffda, "pred_scale", "pred_scale",},
+ {0xffdb, "yn1", "yn1",},
+ {0xffdc, "yn2", "yn2",},
+ {0xffdd, "ARAM", "Direct Read from ARAM (uses ADPCM)",},
+ {0xffde, "GAIN", "Gain",},
+ {0xffdf, "0xffdf", 0,},
+
+ {0xffe0, "0xffe0",0,},
+ {0xffe1, "0xffe1",0,},
+ {0xffe2, "0xffe2",0,},
+ {0xffe3, "0xffe3",0,},
+ {0xffe4, "0xffe4",0,},
+ {0xffe5, "0xffe5",0,},
+ {0xffe6, "0xffe6",0,},
+ {0xffe7, "0xffe7",0,},
+ {0xffe8, "0xffe8",0,},
+ {0xffe9, "0xffe9",0,},
+ {0xffea, "0xffea",0,},
+ {0xffeb, "0xffeb",0,},
+ {0xffec, "0xffec",0,},
+ {0xffed, "0xffed",0,},
+ {0xffee, "0xffee",0,},
+ {0xffef, "AMDM", "ARAM DMA Request Mask",},
+
+ {0xfff0, "0xfff0",0,},
+ {0xfff1, "0xfff1",0,},
+ {0xfff2, "0xfff2",0,},
+ {0xfff3, "0xfff3",0,},
+ {0xfff4, "0xfff4",0,},
+ {0xfff5, "0xfff5",0,},
+ {0xfff6, "0xfff6",0,},
+ {0xfff7, "0xfff7",0,},
+ {0xfff8, "0xfff8",0,},
+ {0xfff9, "0xfff9",0,},
+ {0xfffa, "0xfffa",0,},
+ {0xfffb, "DIRQ", "DSP IRQ Request",},
+ {0xfffc, "DMBH", "DSP Mailbox H",},
+ {0xfffd, "DMBL", "DSP Mailbox L",},
+ {0xfffe, "CMBH", "CPU Mailbox H",},
+ {0xffff, "CMBL", "CPU Mailbox L",},
+};
+
+const u32 pdlabels_size = sizeof(pdlabels) / sizeof(pdlabel_t);
+
+const pdlabel_t regnames[] =
+{
+ {0x00, "AR0", "Addr Reg 00",},
+ {0x01, "AR1", "Addr Reg 01",},
+ {0x02, "AR2", "Addr Reg 02",},
+ {0x03, "AR3", "Addr Reg 03",},
+ {0x04, "IX0", "Index Reg 0",},
+ {0x05, "IX1", "Index Reg 1",},
+ {0x06, "IX2", "Index Reg 2",},
+ {0x07, "IX3", "Index Reg 3",},
+ {0x08, "WR0", "Wrapping Register 0",},
+ {0x09, "WR1", "Wrapping Register 1",},
+ {0x0a, "WR2", "Wrapping Register 2",},
+ {0x0b, "WR3", "Wrapping Register 3",},
+ {0x0c, "ST0", "Call stack",},
+ {0x0d, "ST1", "Data stack",},
+ {0x0e, "ST2", "Loop addr stack",},
+ {0x0f, "ST3", "Loop counter",},
+ {0x10, "AC0.H", "Accu High 0",},
+ {0x11, "AC1.H", "Accu High 1",},
+ {0x12, "CR", "Config Register",},
+ {0x13, "SR", "Special Register",},
+ {0x14, "PROD.L", "Prod L",},
+ {0x15, "PROD.M1", "Prod M1",},
+ {0x16, "PROD.H", "Prod H",},
+ {0x17, "PROD.M2", "Prod M2",},
+ {0x18, "AX0.L", "Extra Accu L 0",},
+ {0x19, "AX1.L", "Extra Accu L 1",},
+ {0x1a, "AX0.H", "Extra Accu H 0",},
+ {0x1b, "AX1.H", "Extra Accu H 1",},
+ {0x1c, "AC0.L", "Accu Low 0",},
+ {0x1d, "AC1.L", "Accu Low 1",},
+ {0x1e, "AC0.M", "Accu Mid 0",},
+ {0x1f, "AC1.M", "Accu Mid 1",},
+
+ // To resolve combined register names.
+ {0x20, "ACC0", "Accu Full 0",},
+ {0x21, "ACC1", "Accu Full 1",},
+ {0x22, "AX0", "Extra Accu 0",},
+ {0x23, "AX1", "Extra Accu 1",},
+};
+
+u8 opSize[OPTABLE_SIZE];
+dspInstFunc opTable[OPTABLE_SIZE];
+dspInstFunc prologueTable[OPTABLE_SIZE];
+dspInstFunc epilogueTable[OPTABLE_SIZE];
+
+const char* pdname(u16 val)
+{
+ static char tmpstr[12]; // nasty
+
+ for (int i = 0; i < (int)(sizeof(pdlabels) / sizeof(pdlabel_t)); i++)
+ {
+ if (pdlabels[i].addr == val)
+ return pdlabels[i].name;
+ }
+
+ sprintf(tmpstr, "0x%04x", val);
+ return tmpstr;
+}
+
+const char *pdregname(int val)
+{
+ return regnames[val].name;
+}
+
+const char *pdregnamelong(int val)
+{
+ return regnames[val].description;
+}
+
+const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst)
+{
+ for (int i = 0; i < opcodes_size; i++)
+ {
+ u16 mask = opcodes[i].opcode_mask;
+ if (opcodes[i].size & P_EXT) {
+ // Ignore extension bits.
+ mask &= 0xFF00;
+ }
+ if ((mask & inst.hex) == opcodes[i].opcode)
+ return &opcodes[i];
+ }
+ return NULL;
+}
+
+
+// This function could use the above GetOpTemplate, but then we'd lose the
+// nice property that it catches colliding op masks.
+void InitInstructionTable()
+{
+ for (int i = 0; i < OPTABLE_SIZE; i++)
+ {
+ opTable[i] = DSPInterpreter::unknown;
+ prologueTable[i] = NULL;
+ epilogueTable[i] = NULL;
+ opSize[i] = 0;
+ }
+
+ for (int i = 0; i < OPTABLE_SIZE; i++)
+ {
+ for (int j = 0; j < opcodes_size; j++)
+ {
+ u16 mask = opcodes[j].opcode_mask;
+ if (opcodes[j].size & P_EXT) {
+ // Ignore extension bits.
+ mask &= 0xFF00;
+ }
+ if ((mask & i) == opcodes[j].opcode)
+ {
+ if (opTable[i] == DSPInterpreter::unknown)
+ {
+ opTable[i] = opcodes[j].interpFunc;
+ opSize[i] = opcodes[j].size & 3;
+ prologueTable[i] = opcodes[j].prologue;
+ epilogueTable[i] = opcodes[j].epilogue;
+ }
+ else
+ {
+ ERROR_LOG(DSPLLE, "opcode table place %d already in use for %s", i, opcodes[j].name);
+ }
+ }
+ }
+ }
+}
diff --git a/Source/Core/DSPCore/Src/DSPTables.h b/Source/Core/DSPCore/Src/DSPTables.h
index 8e0f66207c..a56a112b72 100644
--- a/Source/Core/DSPCore/Src/DSPTables.h
+++ b/Source/Core/DSPCore/Src/DSPTables.h
@@ -1,168 +1,168 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
-
-#ifndef _DSPTABLES_H
-#define _DSPTABLES_H
-
-#include "Common.h"
-
-// The non-ADDR ones that end with _D are the opposite one - if the bit specify
-// ACC0, then ACC_D will be ACC1.
-
-// The values of these are very important.
-// For the reg ones, the value >> 8 is the base register.
-// & 0x80 means it's a "D".
-
-enum partype_t
-{
- P_NONE = 0x0000,
- P_VAL = 0x0001,
- P_IMM = 0x0002,
- P_MEM = 0x0003,
- P_STR = 0x0004,
- P_ADDR_I = 0x0005,
- P_ADDR_D = 0x0006,
- P_REG = 0x8000,
- P_REG04 = P_REG | 0x0400, // IX
- P_REG08 = P_REG | 0x0800,
- P_REG18 = P_REG | 0x1800,
- P_REGM18 = P_REG | 0x1810, // used in multiply instructions
- P_REG19 = P_REG | 0x1900,
- P_REGM19 = P_REG | 0x1910, // used in multiply instructions
- P_REG1A = P_REG | 0x1a80,
- P_REG1C = P_REG | 0x1c00,
-// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
- P_ACC_D = P_REG | 0x1c80,
- P_ACCL = P_REG | 0x1c00, // used for low part of accum
- P_ACCM = P_REG | 0x1e00, // used for mid part of accum
- // The following are not in gcdsptool
- P_ACCM_D = P_REG | 0x1e80,
- P_ACC = P_REG | 0x2000, // used for full accum.
- P_AX = P_REG | 0x2200,
- P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
- P_REF = P_REG | 0x4000,
- P_PRG = P_REF | P_REG,
-
- // The following seem like junk:
- // P_REG10 = P_REG | 0x1000,
- // P_AX_D = P_REG | 0x2280,
-};
-
-#define P_EXT 0x80
-
-#define OPTABLE_SIZE 65536
-
-union UDSPInstruction
-{
- u16 hex;
-
- UDSPInstruction(u16 _hex) { hex = _hex; }
- UDSPInstruction() { hex = 0; }
-
- struct
- {
- signed shift : 6;
- unsigned negating : 1;
- unsigned arithmetic : 1;
- unsigned areg : 1;
- unsigned op : 7;
- };
- struct
- {
- unsigned ushift : 6;
- };
-
- // TODO: Figure out more instruction structures (add structs here)
-};
-
-typedef void (*dspInstFunc)(const UDSPInstruction&);
-
-struct param2_t
-{
- partype_t type;
- u8 size;
- u8 loc;
- s8 lshift;
- u16 mask;
-};
-
-typedef struct
-{
- const char *name;
- u16 opcode;
- u16 opcode_mask;
-
- dspInstFunc interpFunc;
- dspInstFunc jitFunc;
-
- u8 size;
- u8 param_count;
- param2_t params[8];
- dspInstFunc prologue;
- dspInstFunc epilogue;
-} DSPOPCTemplate;
-
-typedef DSPOPCTemplate opc_t;
-
-// Opcodes
-extern const DSPOPCTemplate opcodes[];
-extern const int opcodes_size;
-extern const DSPOPCTemplate opcodes_ext[];
-extern const int opcodes_ext_size;
-extern u8 opSize[OPTABLE_SIZE];
-extern const DSPOPCTemplate cw;
-
-extern dspInstFunc opTable[];
-extern dspInstFunc prologueTable[OPTABLE_SIZE];
-extern dspInstFunc epilogueTable[OPTABLE_SIZE];
-
-// Predefined labels
-struct pdlabel_t
-{
- u16 addr;
- const char* name;
- const char* description;
-};
-
-extern const pdlabel_t regnames[];
-extern const pdlabel_t pdlabels[];
-extern const u32 pdlabels_size;
-
-const char *pdname(u16 val);
-const char *pdregname(int val);
-const char *pdregnamelong(int val);
-
-void InitInstructionTable();
-
-inline void ExecuteInstruction(const UDSPInstruction& inst)
-{
- // TODO: Move the prologuetable calls into the relevant instructions themselves.
- // Better not do things like this until things work correctly though.
- if (prologueTable[inst.hex])
- prologueTable[inst.hex](inst);
- opTable[inst.hex](inst);
- if (epilogueTable[inst.hex])
- epilogueTable[inst.hex](inst);
-}
-
-// This one's pretty slow, try to use it only at init or seldomly.
-// returns NULL if no matching instruction.
-const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
-
-#endif // _DSPTABLES_H
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
+
+#ifndef _DSPTABLES_H
+#define _DSPTABLES_H
+
+#include "Common.h"
+
+// The non-ADDR ones that end with _D are the opposite one - if the bit specify
+// ACC0, then ACC_D will be ACC1.
+
+// The values of these are very important.
+// For the reg ones, the value >> 8 is the base register.
+// & 0x80 means it's a "D".
+
+enum partype_t
+{
+ P_NONE = 0x0000,
+ P_VAL = 0x0001,
+ P_IMM = 0x0002,
+ P_MEM = 0x0003,
+ P_STR = 0x0004,
+ P_ADDR_I = 0x0005,
+ P_ADDR_D = 0x0006,
+ P_REG = 0x8000,
+ P_REG04 = P_REG | 0x0400, // IX
+ P_REG08 = P_REG | 0x0800,
+ P_REG18 = P_REG | 0x1800,
+ P_REGM18 = P_REG | 0x1810, // used in multiply instructions
+ P_REG19 = P_REG | 0x1900,
+ P_REGM19 = P_REG | 0x1910, // used in multiply instructions
+ P_REG1A = P_REG | 0x1a80,
+ P_REG1C = P_REG | 0x1c00,
+// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
+ P_ACC_D = P_REG | 0x1c80,
+ P_ACCL = P_REG | 0x1c00, // used for low part of accum
+ P_ACCM = P_REG | 0x1e00, // used for mid part of accum
+ // The following are not in gcdsptool
+ P_ACCM_D = P_REG | 0x1e80,
+ P_ACC = P_REG | 0x2000, // used for full accum.
+ P_AX = P_REG | 0x2200,
+ P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
+ P_REF = P_REG | 0x4000,
+ P_PRG = P_REF | P_REG,
+
+ // The following seem like junk:
+ // P_REG10 = P_REG | 0x1000,
+ // P_AX_D = P_REG | 0x2280,
+};
+
+#define P_EXT 0x80
+
+#define OPTABLE_SIZE 65536
+
+union UDSPInstruction
+{
+ u16 hex;
+
+ UDSPInstruction(u16 _hex) { hex = _hex; }
+ UDSPInstruction() { hex = 0; }
+
+ struct
+ {
+ signed shift : 6;
+ unsigned negating : 1;
+ unsigned arithmetic : 1;
+ unsigned areg : 1;
+ unsigned op : 7;
+ };
+ struct
+ {
+ unsigned ushift : 6;
+ };
+
+ // TODO: Figure out more instruction structures (add structs here)
+};
+
+typedef void (*dspInstFunc)(const UDSPInstruction&);
+
+struct param2_t
+{
+ partype_t type;
+ u8 size;
+ u8 loc;
+ s8 lshift;
+ u16 mask;
+};
+
+typedef struct
+{
+ const char *name;
+ u16 opcode;
+ u16 opcode_mask;
+
+ dspInstFunc interpFunc;
+ dspInstFunc jitFunc;
+
+ u8 size;
+ u8 param_count;
+ param2_t params[8];
+ dspInstFunc prologue;
+ dspInstFunc epilogue;
+} DSPOPCTemplate;
+
+typedef DSPOPCTemplate opc_t;
+
+// Opcodes
+extern const DSPOPCTemplate opcodes[];
+extern const int opcodes_size;
+extern const DSPOPCTemplate opcodes_ext[];
+extern const int opcodes_ext_size;
+extern u8 opSize[OPTABLE_SIZE];
+extern const DSPOPCTemplate cw;
+
+extern dspInstFunc opTable[];
+extern dspInstFunc prologueTable[OPTABLE_SIZE];
+extern dspInstFunc epilogueTable[OPTABLE_SIZE];
+
+// Predefined labels
+struct pdlabel_t
+{
+ u16 addr;
+ const char* name;
+ const char* description;
+};
+
+extern const pdlabel_t regnames[];
+extern const pdlabel_t pdlabels[];
+extern const u32 pdlabels_size;
+
+const char *pdname(u16 val);
+const char *pdregname(int val);
+const char *pdregnamelong(int val);
+
+void InitInstructionTable();
+
+inline void ExecuteInstruction(const UDSPInstruction& inst)
+{
+ // TODO: Move the prologuetable calls into the relevant instructions themselves.
+ // Better not do things like this until things work correctly though.
+ if (prologueTable[inst.hex])
+ prologueTable[inst.hex](inst);
+ opTable[inst.hex](inst);
+ if (epilogueTable[inst.hex])
+ epilogueTable[inst.hex](inst);
+}
+
+// This one's pretty slow, try to use it only at init or seldomly.
+// returns NULL if no matching instruction.
+const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
+
+#endif // _DSPTABLES_H
diff --git a/Source/Core/DSPCore/Src/DspIntArithmetic.cpp b/Source/Core/DSPCore/Src/DspIntArithmetic.cpp
index 83b7791516..45b16ddf16 100644
--- a/Source/Core/DSPCore/Src/DspIntArithmetic.cpp
+++ b/Source/Core/DSPCore/Src/DspIntArithmetic.cpp
@@ -1,734 +1,734 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie and Tratax (c) 2004
-
-#include "DSPInterpreter.h"
-#include "DSPIntCCUtil.h"
-#include "DSPIntUtil.h"
-
-// Arithmetic and accumulator control.
-
-namespace DSPInterpreter {
-
-// CLR $acR
-// 1000 r001 xxxx xxxx
-// Clears accumulator $acR
-void clr(const UDSPInstruction& opc)
-{
- u8 reg = (opc.hex >> 11) & 0x1;
-
- dsp_set_long_acc(reg, 0);
-
- Update_SR_Register64((s64)0); // really?
-}
-
-// CLRL $acR.l
-// 1111 110r xxxx xxxx
-// Clears $acR.l - low 16 bits of accumulator $acR.
-void clrl(const UDSPInstruction& opc)
-{
- u16 reg = DSP_REG_ACL0 + ((opc.hex >> 11) & 0x1);
- g_dsp.r[reg] = 0;
-
- // Should this be 64bit?
- // nakee: it says the whole reg in duddie's doc sounds weird
- Update_SR_Register64((s64)reg);
-}
-
-
-// ADDAXL $acD, $axS.l
-// 0111 00sd xxxx xxxx
-// Adds secondary accumulator $axS.l to accumulator register $acD.
-void addaxl(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 9) & 0x1;
- u8 dreg = (opc.hex >> 8) & 0x1;
-
- s64 acc = dsp_get_long_acc(dreg);
- s64 acx = dsp_get_ax_l(sreg);
-
- acc += acx;
-
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// TSTAXH $axR.h
-// 1000 011r xxxx xxxx
-// Test high part of secondary accumulator $axR.h.
-void tstaxh(const UDSPInstruction& opc)
-{
- u8 reg = (opc.hex >> 8) & 0x1;
- s16 val = dsp_get_ax_h(reg);
-
- Update_SR_Register16(val);
-}
-
-// SUB $acD, $ac(1-D)
-// 0101 110d xxxx xxxx
-// Subtracts accumulator $ac(1-D) from accumulator register $acD.
-void sub(const UDSPInstruction& opc)
-{
- u8 D = (opc.hex >> 8) & 0x1;
- s64 acc1 = dsp_get_long_acc(D);
- s64 acc2 = dsp_get_long_acc(1 - D);
-
- acc1 -= acc2;
-
- dsp_set_long_acc(D, acc1);
-
- Update_SR_Register64(acc1);
-}
-
-// MOVR $acD, $axS.R
-// 0110 0srd xxxx xxxx
-// Moves register $axS.R (sign extended) to middle accumulator $acD.hm.
-// Sets $acD.l to 0.
-// TODO: Check what happens to acD.h.
-void movr(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
- u8 sreg = ((opc.hex >> 9) & 0x3) + DSP_REG_AXL0;
-
- s64 acc = (s16)g_dsp.r[sreg];
- acc <<= 16;
- acc &= ~0xffff;
-
- dsp_set_long_acc(areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// MOVAX $acD, $axS
-// 0110 10sd xxxx xxxx
-// Moves secondary accumulator $axS to accumulator $axD.
-void movax(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x1;
- u8 sreg = (opc.hex >> 9) & 0x1;
-
- s64 acx = dsp_get_long_acx(sreg);
- dsp_set_long_acc(dreg, acx);
-
- Update_SR_Register64(acx);
-}
-
-// XORR $acD.m, $axS.h
-// 0011 00sd xxxx xxxx
-// Logic XOR (exclusive or) middle part of accumulator $acD.m with
-// high part of secondary accumulator $axS.h.
-void xorr(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 9) & 0x1;
- u8 dreg = (opc.hex >> 8) & 0x1;
-
- g_dsp.r[DSP_REG_ACM0 + dreg] ^= g_dsp.r[DSP_REG_AXH0 + sreg];
-
- s64 acc = dsp_get_long_acc(dreg);
- Update_SR_Register64(acc);
-}
-
-// ANDR $acD.m, $axS.h
-// 0011 01sd xxxx xxxx
-// Logic AND middle part of accumulator $acD.m with high part of
-// secondary accumulator $axS.h.
-void andr(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 9) & 0x1;
- u8 dreg = (opc.hex >> 8) & 0x1;
-
- g_dsp.r[DSP_REG_ACM0 + dreg] &= g_dsp.r[DSP_REG_AXH0 + sreg];
-
- s64 acc = dsp_get_long_acc(dreg);
-
- Update_SR_Register64(acc);
-}
-
-// ORR $acD.m, $axS.h
-// 0011 10sd xxxx xxxx
-// Logic OR middle part of accumulator $acD.m with high part of
-// secondary accumulator $axS.h.
-void orr(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 9) & 0x1;
- u8 dreg = (opc.hex >> 8) & 0x1;
-
- g_dsp.r[DSP_REG_ACM0 + dreg] |= g_dsp.r[DSP_REG_AXH0 + sreg];
-
- s64 acc = dsp_get_long_acc(dreg);
-
- Update_SR_Register64(acc);
-}
-
-// ANDC $acD.m, $ac(1-D).m
-// 0011 110d xxxx xxxx
-// Logic AND middle part of accumulator $acD.m with middle part of
-// accumulator $ax(1-D).m.s
-void andc(const UDSPInstruction& opc)
-{
- u8 D = (opc.hex >> 8) & 0x1;
-
- u16 ac1 = dsp_get_acc_m(D);
- u16 ac2 = dsp_get_acc_m(1 - D);
-
- dsp_set_long_acc(D, ac1 & ac2);
-
- Update_SR_Register64(dsp_get_long_acc(D));
-}
-
-// ORC $acD.m, $ac(1-D).m
-// 0011 111d xxxx xxxx
-// Logic OR middle part of accumulator $acD.m with middle part of
-// accumulator $ax(1-D).m.
-void orc(const UDSPInstruction& opc)
-{
- u8 D = (opc.hex >> 8) & 0x1;
-
- u16 ac1 = dsp_get_acc_m(D);
- u16 ac2 = dsp_get_acc_m(1 - D);
-
- dsp_set_long_acc(D, ac1 | ac2);
-
- Update_SR_Register64(dsp_get_long_acc(D));
-}
-
-void orf(const UDSPInstruction& opc)
-{
- ERROR_LOG(DSPLLE, "orf not implemented");
-}
-
-// Hermes switched andf and andcf, so check to make sure they are still correct
-// ANDCF $acD.m, #I
-// 0000 001r 1100 0000
-// iiii iiii iiii iiii
-// Set logic zero (LZ) flag in status register $sr if result of logic AND of
-// accumulator mid part $acD.m with immediate value I is equal I.
-void andcf(const UDSPInstruction& opc)
-{
- u8 reg = (opc.hex >> 8) & 0x1;
- u16 imm = dsp_fetch_code();
- u16 val = dsp_get_acc_m(reg);
-
- Update_SR_LZ(((val & imm) == imm) ? 0 : 1);
-}
-
-// Hermes switched andf and andcf, so check to make sure they are still correct
-
-// ANDF $acD.m, #I
-// 0000 001r 1010 0000
-// iiii iiii iiii iiii
-// Set logic zero (LZ) flag in status register $sr if result of logical AND
-// operation of accumulator mid part $acD.m with immediate value I is equal
-// immediate value 0.
-void andf(const UDSPInstruction& opc)
-{
- u8 reg = DSP_REG_ACM0 + ((opc.hex >> 8) & 0x1);
- u16 imm = dsp_fetch_code();
- u16 val = g_dsp.r[reg];
-
- Update_SR_LZ(((val & imm) == 0) ? 0 : 1);
-}
-
-// CMPI $amD, #I
-// 0000 001r 1000 0000
-// iiii iiii iiii iiii
-// Compares mid accumulator $acD.hm ($amD) with sign extended immediate value I.
-// Although flags are being set regarding whole accumulator register.
-void cmpi(const UDSPInstruction& opc)
-{
- int reg = (opc.hex >> 8) & 0x1;
-
- // Immediate is considered to be at M level in the 40-bit accumulator.
- s64 imm = (s64)(s16)dsp_fetch_code() << 16;
- s64 val = dsp_get_long_acc(reg);
- Update_SR_Register64(val - imm);
-}
-
-// XORI $acD.m, #I
-// 0000 001r 0010 0000
-// iiii iiii iiii iiii
-// Logic exclusive or (XOR) of accumulator mid part $acD.m with
-// immediate value I.
-void xori(const UDSPInstruction& opc)
-{
- u8 reg = DSP_REG_ACM0 + ((opc.hex >> 8) & 0x1);
- u16 imm = dsp_fetch_code();
- g_dsp.r[reg] ^= imm;
-
- Update_SR_Register16((s16)g_dsp.r[reg]);
-}
-
-// ANDI $acD.m, #I
-// 0000 001r 0100 0000
-// iiii iiii iiii iiii
-// Logic AND of accumulator mid part $acD.m with immediate value I.
-void andi(const UDSPInstruction& opc)
-{
- u8 reg = DSP_REG_ACM0 + ((opc.hex >> 8) & 0x1);
- u16 imm = dsp_fetch_code();
- g_dsp.r[reg] &= imm;
-
- Update_SR_Register16((s16)g_dsp.r[reg]);
-}
-
-
-// F|RES: i am not sure if this shouldnt be the whole ACC
-// ORI $acD.m, #I
-// 0000 001r 0110 0000
-// iiii iiii iiii iiii
-// Logic OR of accumulator mid part $acD.m with immediate value I.
-void ori(const UDSPInstruction& opc)
-{
- u8 reg = DSP_REG_ACM0 + ((opc.hex >> 8) & 0x1);
- u16 imm = dsp_fetch_code();
- g_dsp.r[reg] |= imm;
-
- Update_SR_Register16((s16)g_dsp.r[reg]);
-}
-
-//-------------------------------------------------------------
-
-
-// ADD $acD, $ac(1-D)
-// 0100 110d xxxx xxxx
-// Adds accumulator $ac(1-D) to accumulator register $acD.
-void add(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
- s64 acc0 = dsp_get_long_acc(0);
- s64 acc1 = dsp_get_long_acc(1);
-
- s64 res = acc0 + acc1;
-
- dsp_set_long_acc(areg, res);
-
- Update_SR_Register64(res);
-}
-
-// ADDP $acD
-// 0100 111d xxxx xxxx
-// Adds product register to accumulator register.
-void addp(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
- acc += dsp_get_long_prod();
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// SUBP $acD
-// 0101 111d xxxx xxxx
-// Subtracts product register from accumulator register.
-void subp(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x1;
- s64 acc = dsp_get_long_acc(dreg);
- acc -= dsp_get_long_prod();
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-
-// CMPIS $acD, #I
-// 0000 011d iiii iiii
-// Compares accumulator with short immediate. Comaprison is executed
-// by subtracting short immediate (8bit sign extended) from mid accumulator
-// $acD.hm and computing flags based on whole accumulator $acD.
-void cmpis(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
-
- s64 acc = dsp_get_long_acc(areg);
- s64 val = (s8)opc.hex;
- val <<= 16;
-
- s64 res = acc - val;
-
- Update_SR_Register64(res);
-}
-
-
-// DECM $acsD
-// 0111 100d xxxx xxxx
-// Decrement 24-bit mid-accumulator $acsD.
-void decm(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x01;
-
- s64 sub = 0x10000;
- s64 acc = dsp_get_long_acc(dreg);
- acc -= sub;
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// DEC $acD
-// 0111 101d xxxx xxxx
-// Decrement accumulator $acD.
-void dec(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x01;
-
- s64 acc = dsp_get_long_acc(dreg) - 1;
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// INCM $acsD
-// 0111 010d xxxx xxxx
-// Increment 24-bit mid-accumulator $acsD.
-void incm(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x1;
-
- s64 sub = 0x10000;
- s64 acc = dsp_get_long_acc(dreg);
- acc += sub;
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// INC $acD
-// 0111 011d xxxx xxxx
-// Increment accumulator $acD.
-void inc(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x1;
-
- s64 acc = dsp_get_long_acc(dreg) + 1;
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// NEG $acD
-// 0111 110d xxxx xxxx
-// Negate accumulator $acD.
-void neg(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
-
- s64 acc = dsp_get_long_acc(areg);
- acc = 0 - acc;
- dsp_set_long_acc(areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// MOV $acD, $ac(1-D)
-// 0110 110d xxxx xxxx
-// Moves accumulator $ax(1-D) to accumulator $axD.
-void mov(const UDSPInstruction& opc)
-{
- u8 D = (opc.hex >> 8) & 0x1;
- u64 acc = dsp_get_long_acc(1 - D);
- dsp_set_long_acc(D, acc);
-
- Update_SR_Register64(acc);
-}
-
-// ADDAX $acD, $axS
-// 0100 10sd xxxx xxxx
-// Adds secondary accumulator $axS to accumulator register $acD.
-void addax(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
- u8 sreg = (opc.hex >> 9) & 0x1;
-
- s64 ax = dsp_get_long_acx(sreg);
- s64 acc = dsp_get_long_acc(areg);
- acc += ax;
- dsp_set_long_acc(areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// ADDR $acD, $(DSP_REG_AXL0+S)
-// 0100 0ssd xxxx xxxx
-// Adds register $(DSP_REG_AXL0+S) to accumulator $acD register.
-void addr(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
- u8 sreg = ((opc.hex >> 9) & 0x3) + DSP_REG_AXL0;
-
- s64 ax = (s16)g_dsp.r[sreg];
- ax <<= 16;
-
- s64 acc = dsp_get_long_acc(areg);
- acc += ax;
- dsp_set_long_acc(areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// SUBR $acD, $(DSP_REG_AXL0+S)
-// 0101 0ssd xxxx xxxx
-// Subtracts register $(DSP_REG_AXL0+S) from accumulator $acD register.
-void subr(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
- u8 sreg = ((opc.hex >> 9) & 0x3) + DSP_REG_AXL0;
-
- s64 ax = (s16)g_dsp.r[sreg];
- ax <<= 16;
-
- s64 acc = dsp_get_long_acc(areg);
- acc -= ax;
- dsp_set_long_acc(areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// SUBAX $acD, $axS
-// 0101 10sd xxxx xxxx
-// Subtracts secondary accumulator $axS from accumulator register $acD.
-void subax(const UDSPInstruction& opc)
-{
- int regD = (opc.hex >> 8) & 0x1;
- int regS = (opc.hex >> 9) & 0x1;
-
- s64 acc = dsp_get_long_acc(regD) - dsp_get_long_acx(regS);
-
- dsp_set_long_acc(regD, acc);
- Update_SR_Register64(acc);
-}
-
-// ADDIS $acD, #I
-// 0000 010d iiii iiii
-// Adds short immediate (8-bit sign extended) to mid accumulator $acD.hm.
-void addis(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
-
- s64 Imm = (s8)(u8)opc.hex;
- Imm <<= 16;
- s64 acc = dsp_get_long_acc(areg);
- acc += Imm;
- dsp_set_long_acc(areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// ADDI $amR, #I
-// 0000 001r 0000 0000
-// iiii iiii iiii iiii
-// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm.
-void addi(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
-
- s64 sub = (s16)dsp_fetch_code();
- sub <<= 16;
- s64 acc = dsp_get_long_acc(areg);
- acc += sub;
- dsp_set_long_acc(areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// LSL16 $acR
-// 1111 000r xxxx xxxx
-// Logically shifts left accumulator $acR by 16.
-void lsl16(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
-
- s64 acc = dsp_get_long_acc(areg);
- acc <<= 16;
- dsp_set_long_acc(areg, acc);
- Update_SR_Register64(acc);
-}
-
-// LSR16 $acR
-// 1111 010r xxxx xxxx
-// Logically shifts right accumulator $acR by 16.
-void lsr16(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 8) & 0x1;
-
- u64 acc = dsp_get_long_acc(areg);
-
- acc >>= 16;
- dsp_set_long_acc(areg, acc);
- Update_SR_Register64(acc);
-}
-
-// ASR16 $acR
-// 1001 r001 xxxx xxxx
-// Arithmetically shifts right accumulator $acR by 16.
-void asr16(const UDSPInstruction& opc)
-{
- u8 areg = (opc.hex >> 11) & 0x1;
-
- s64 acc = dsp_get_long_acc(areg);
-
- acc >>= 16;
- dsp_set_long_acc(areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// LSL $acR, #I
-// 0001 010r 00ii iiii
-// Logically shifts left accumulator $acR by number specified by value I.
-void lsl(const UDSPInstruction& opc)
-{
- u16 shift = opc.ushift;
- u64 acc = dsp_get_long_acc(opc.areg);
-
- acc <<= shift;
- dsp_set_long_acc(opc.areg, acc);
- Update_SR_Register64(acc);
-}
-
-// LSR $acR, #I
-// 0001 010r 01ii iiii
-// Logically shifts left accumulator $acR by number specified by value
-// calculated by negating sign extended bits 0-6.
-void lsr(const UDSPInstruction& opc)
-{
- u16 shift = -opc.ushift;
- u64 acc = dsp_get_long_acc(opc.areg);
- // Lop off the extraneous sign extension our 64-bit fake accum causes
- acc &= 0x000000FFFFFFFFFFULL;
- acc >>= shift;
- dsp_set_long_acc(opc.areg, (s64)acc);
- Update_SR_Register64(acc);
-}
-
-// ASL $acR, #I
-// 0001 010r 10ii iiii
-// Logically shifts left accumulator $acR by number specified by value I.
-void asl(const UDSPInstruction& opc)
-{
- u16 shift = opc.ushift;
-
- // arithmetic shift
- u64 acc = dsp_get_long_acc(opc.areg);
- acc <<= shift;
-
- dsp_set_long_acc(opc.areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// ASR $acR, #I
-// 0001 010r 11ii iiii
-// Arithmetically shifts right accumulator $acR by number specified by
-// value calculated by negating sign extended bits 0-6.
-void asr(const UDSPInstruction& opc)
-{
- u16 shift = -opc.ushift;
-
- // arithmetic shift
- s64 acc = dsp_get_long_acc(opc.areg);
- acc >>= shift;
-
- dsp_set_long_acc(opc.areg, acc);
-
- Update_SR_Register64(acc);
-}
-
-
-// (NEW)
-// LSRN (fixed parameters)
-// 0000 0010 1100 1010
-// Logically shifts right accumulator $ACC0 by signed 16-bit value $AC1.M
-// (if value negative, becomes left shift).
-void lsrn(const UDSPInstruction& opc)
-{
- s16 shift = (s16)g_dsp.r[DSP_REG_ACM1];
- u64 acc = dsp_get_long_acc(0);
- // Lop off the extraneous sign extension our 64-bit fake accum causes
- acc &= 0x000000FFFFFFFFFFULL;
- if (shift > 0) {
- acc >>= shift;
- } else if (shift < 0) {
- acc <<= -shift;
- }
- dsp_set_long_acc(0, (s64)acc);
- Update_SR_Register64(acc);
-}
-
-// (NEW)
-// ASRN (fixed parameters)
-// 0000 0010 1100 1011
-// Arithmetically shifts right accumulator $ACC0 by signed 16-bit value $AC1.M
-// (if value negative, becomes left shift).
-void asrn(const UDSPInstruction& opc)
-{
- s16 shift = (s16)g_dsp.r[DSP_REG_ACM1];
- s64 acc = dsp_get_long_acc(0);
- if (shift > 0) {
- acc >>= shift;
- } else if (shift < 0) {
- acc <<= -shift;
- }
- dsp_set_long_acc(0, acc);
- Update_SR_Register64(acc);
-}
-
-
-// CMPAR $acS axR.h
-// 1100 0001 xxxx xxxx
-// Compares accumulator $acS with accumulator axR.h.
-// Not described by Duddie's doc - at least not as a separate instruction.
-void cmpar(const UDSPInstruction& opc)
-{
- u8 rreg = ((opc.hex >> 12) & 0x1) + DSP_REG_AXH0;
- u8 sreg = (opc.hex >> 11) & 0x1;
-
- // we compare
- s64 rr = (s16)g_dsp.r[rreg];
- rr <<= 16;
-
- s64 sr = dsp_get_long_acc(sreg);
-
- Update_SR_Register64(sr - rr);
-}
-
-// CMP
-// 1000 0010 xxxx xxxx
-// Compares accumulator $ac0 with accumulator $ac1.
-void cmp(const UDSPInstruction& opc)
-{
- s64 acc0 = dsp_get_long_acc(0);
- s64 acc1 = dsp_get_long_acc(1);
-
- Update_SR_Register64(acc0 - acc1);
-}
-
-// TST
-// 1011 r001 xxxx xxxx
-// Test accumulator %acR.
-void tst(const UDSPInstruction& opc)
-{
- s8 reg = (opc.hex >> 11) & 0x1;
- s64 acc = dsp_get_long_acc(reg);
-
- Update_SR_Register64(acc);
-}
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie and Tratax (c) 2004
+
+#include "DSPInterpreter.h"
+#include "DSPIntCCUtil.h"
+#include "DSPIntUtil.h"
+
+// Arithmetic and accumulator control.
+
+namespace DSPInterpreter {
+
+// CLR $acR
+// 1000 r001 xxxx xxxx
+// Clears accumulator $acR
+void clr(const UDSPInstruction& opc)
+{
+ u8 reg = (opc.hex >> 11) & 0x1;
+
+ dsp_set_long_acc(reg, 0);
+
+ Update_SR_Register64((s64)0); // really?
+}
+
+// CLRL $acR.l
+// 1111 110r xxxx xxxx
+// Clears $acR.l - low 16 bits of accumulator $acR.
+void clrl(const UDSPInstruction& opc)
+{
+ u16 reg = DSP_REG_ACL0 + ((opc.hex >> 11) & 0x1);
+ g_dsp.r[reg] = 0;
+
+ // Should this be 64bit?
+ // nakee: it says the whole reg in duddie's doc sounds weird
+ Update_SR_Register64((s64)reg);
+}
+
+
+// ADDAXL $acD, $axS.l
+// 0111 00sd xxxx xxxx
+// Adds secondary accumulator $axS.l to accumulator register $acD.
+void addaxl(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 9) & 0x1;
+ u8 dreg = (opc.hex >> 8) & 0x1;
+
+ s64 acc = dsp_get_long_acc(dreg);
+ s64 acx = dsp_get_ax_l(sreg);
+
+ acc += acx;
+
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// TSTAXH $axR.h
+// 1000 011r xxxx xxxx
+// Test high part of secondary accumulator $axR.h.
+void tstaxh(const UDSPInstruction& opc)
+{
+ u8 reg = (opc.hex >> 8) & 0x1;
+ s16 val = dsp_get_ax_h(reg);
+
+ Update_SR_Register16(val);
+}
+
+// SUB $acD, $ac(1-D)
+// 0101 110d xxxx xxxx
+// Subtracts accumulator $ac(1-D) from accumulator register $acD.
+void sub(const UDSPInstruction& opc)
+{
+ u8 D = (opc.hex >> 8) & 0x1;
+ s64 acc1 = dsp_get_long_acc(D);
+ s64 acc2 = dsp_get_long_acc(1 - D);
+
+ acc1 -= acc2;
+
+ dsp_set_long_acc(D, acc1);
+
+ Update_SR_Register64(acc1);
+}
+
+// MOVR $acD, $axS.R
+// 0110 0srd xxxx xxxx
+// Moves register $axS.R (sign extended) to middle accumulator $acD.hm.
+// Sets $acD.l to 0.
+// TODO: Check what happens to acD.h.
+void movr(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+ u8 sreg = ((opc.hex >> 9) & 0x3) + DSP_REG_AXL0;
+
+ s64 acc = (s16)g_dsp.r[sreg];
+ acc <<= 16;
+ acc &= ~0xffff;
+
+ dsp_set_long_acc(areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// MOVAX $acD, $axS
+// 0110 10sd xxxx xxxx
+// Moves secondary accumulator $axS to accumulator $axD.
+void movax(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x1;
+ u8 sreg = (opc.hex >> 9) & 0x1;
+
+ s64 acx = dsp_get_long_acx(sreg);
+ dsp_set_long_acc(dreg, acx);
+
+ Update_SR_Register64(acx);
+}
+
+// XORR $acD.m, $axS.h
+// 0011 00sd xxxx xxxx
+// Logic XOR (exclusive or) middle part of accumulator $acD.m with
+// high part of secondary accumulator $axS.h.
+void xorr(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 9) & 0x1;
+ u8 dreg = (opc.hex >> 8) & 0x1;
+
+ g_dsp.r[DSP_REG_ACM0 + dreg] ^= g_dsp.r[DSP_REG_AXH0 + sreg];
+
+ s64 acc = dsp_get_long_acc(dreg);
+ Update_SR_Register64(acc);
+}
+
+// ANDR $acD.m, $axS.h
+// 0011 01sd xxxx xxxx
+// Logic AND middle part of accumulator $acD.m with high part of
+// secondary accumulator $axS.h.
+void andr(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 9) & 0x1;
+ u8 dreg = (opc.hex >> 8) & 0x1;
+
+ g_dsp.r[DSP_REG_ACM0 + dreg] &= g_dsp.r[DSP_REG_AXH0 + sreg];
+
+ s64 acc = dsp_get_long_acc(dreg);
+
+ Update_SR_Register64(acc);
+}
+
+// ORR $acD.m, $axS.h
+// 0011 10sd xxxx xxxx
+// Logic OR middle part of accumulator $acD.m with high part of
+// secondary accumulator $axS.h.
+void orr(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 9) & 0x1;
+ u8 dreg = (opc.hex >> 8) & 0x1;
+
+ g_dsp.r[DSP_REG_ACM0 + dreg] |= g_dsp.r[DSP_REG_AXH0 + sreg];
+
+ s64 acc = dsp_get_long_acc(dreg);
+
+ Update_SR_Register64(acc);
+}
+
+// ANDC $acD.m, $ac(1-D).m
+// 0011 110d xxxx xxxx
+// Logic AND middle part of accumulator $acD.m with middle part of
+// accumulator $ax(1-D).m.s
+void andc(const UDSPInstruction& opc)
+{
+ u8 D = (opc.hex >> 8) & 0x1;
+
+ u16 ac1 = dsp_get_acc_m(D);
+ u16 ac2 = dsp_get_acc_m(1 - D);
+
+ dsp_set_long_acc(D, ac1 & ac2);
+
+ Update_SR_Register64(dsp_get_long_acc(D));
+}
+
+// ORC $acD.m, $ac(1-D).m
+// 0011 111d xxxx xxxx
+// Logic OR middle part of accumulator $acD.m with middle part of
+// accumulator $ax(1-D).m.
+void orc(const UDSPInstruction& opc)
+{
+ u8 D = (opc.hex >> 8) & 0x1;
+
+ u16 ac1 = dsp_get_acc_m(D);
+ u16 ac2 = dsp_get_acc_m(1 - D);
+
+ dsp_set_long_acc(D, ac1 | ac2);
+
+ Update_SR_Register64(dsp_get_long_acc(D));
+}
+
+void orf(const UDSPInstruction& opc)
+{
+ ERROR_LOG(DSPLLE, "orf not implemented");
+}
+
+// Hermes switched andf and andcf, so check to make sure they are still correct
+// ANDCF $acD.m, #I
+// 0000 001r 1100 0000
+// iiii iiii iiii iiii
+// Set logic zero (LZ) flag in status register $sr if result of logic AND of
+// accumulator mid part $acD.m with immediate value I is equal I.
+void andcf(const UDSPInstruction& opc)
+{
+ u8 reg = (opc.hex >> 8) & 0x1;
+ u16 imm = dsp_fetch_code();
+ u16 val = dsp_get_acc_m(reg);
+
+ Update_SR_LZ(((val & imm) == imm) ? 0 : 1);
+}
+
+// Hermes switched andf and andcf, so check to make sure they are still correct
+
+// ANDF $acD.m, #I
+// 0000 001r 1010 0000
+// iiii iiii iiii iiii
+// Set logic zero (LZ) flag in status register $sr if result of logical AND
+// operation of accumulator mid part $acD.m with immediate value I is equal
+// immediate value 0.
+void andf(const UDSPInstruction& opc)
+{
+ u8 reg = DSP_REG_ACM0 + ((opc.hex >> 8) & 0x1);
+ u16 imm = dsp_fetch_code();
+ u16 val = g_dsp.r[reg];
+
+ Update_SR_LZ(((val & imm) == 0) ? 0 : 1);
+}
+
+// CMPI $amD, #I
+// 0000 001r 1000 0000
+// iiii iiii iiii iiii
+// Compares mid accumulator $acD.hm ($amD) with sign extended immediate value I.
+// Although flags are being set regarding whole accumulator register.
+void cmpi(const UDSPInstruction& opc)
+{
+ int reg = (opc.hex >> 8) & 0x1;
+
+ // Immediate is considered to be at M level in the 40-bit accumulator.
+ s64 imm = (s64)(s16)dsp_fetch_code() << 16;
+ s64 val = dsp_get_long_acc(reg);
+ Update_SR_Register64(val - imm);
+}
+
+// XORI $acD.m, #I
+// 0000 001r 0010 0000
+// iiii iiii iiii iiii
+// Logic exclusive or (XOR) of accumulator mid part $acD.m with
+// immediate value I.
+void xori(const UDSPInstruction& opc)
+{
+ u8 reg = DSP_REG_ACM0 + ((opc.hex >> 8) & 0x1);
+ u16 imm = dsp_fetch_code();
+ g_dsp.r[reg] ^= imm;
+
+ Update_SR_Register16((s16)g_dsp.r[reg]);
+}
+
+// ANDI $acD.m, #I
+// 0000 001r 0100 0000
+// iiii iiii iiii iiii
+// Logic AND of accumulator mid part $acD.m with immediate value I.
+void andi(const UDSPInstruction& opc)
+{
+ u8 reg = DSP_REG_ACM0 + ((opc.hex >> 8) & 0x1);
+ u16 imm = dsp_fetch_code();
+ g_dsp.r[reg] &= imm;
+
+ Update_SR_Register16((s16)g_dsp.r[reg]);
+}
+
+
+// F|RES: i am not sure if this shouldnt be the whole ACC
+// ORI $acD.m, #I
+// 0000 001r 0110 0000
+// iiii iiii iiii iiii
+// Logic OR of accumulator mid part $acD.m with immediate value I.
+void ori(const UDSPInstruction& opc)
+{
+ u8 reg = DSP_REG_ACM0 + ((opc.hex >> 8) & 0x1);
+ u16 imm = dsp_fetch_code();
+ g_dsp.r[reg] |= imm;
+
+ Update_SR_Register16((s16)g_dsp.r[reg]);
+}
+
+//-------------------------------------------------------------
+
+
+// ADD $acD, $ac(1-D)
+// 0100 110d xxxx xxxx
+// Adds accumulator $ac(1-D) to accumulator register $acD.
+void add(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+ s64 acc0 = dsp_get_long_acc(0);
+ s64 acc1 = dsp_get_long_acc(1);
+
+ s64 res = acc0 + acc1;
+
+ dsp_set_long_acc(areg, res);
+
+ Update_SR_Register64(res);
+}
+
+// ADDP $acD
+// 0100 111d xxxx xxxx
+// Adds product register to accumulator register.
+void addp(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x1;
+ s64 acc = dsp_get_long_acc(dreg);
+ acc += dsp_get_long_prod();
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// SUBP $acD
+// 0101 111d xxxx xxxx
+// Subtracts product register from accumulator register.
+void subp(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x1;
+ s64 acc = dsp_get_long_acc(dreg);
+ acc -= dsp_get_long_prod();
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+
+// CMPIS $acD, #I
+// 0000 011d iiii iiii
+// Compares accumulator with short immediate. Comaprison is executed
+// by subtracting short immediate (8bit sign extended) from mid accumulator
+// $acD.hm and computing flags based on whole accumulator $acD.
+void cmpis(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+
+ s64 acc = dsp_get_long_acc(areg);
+ s64 val = (s8)opc.hex;
+ val <<= 16;
+
+ s64 res = acc - val;
+
+ Update_SR_Register64(res);
+}
+
+
+// DECM $acsD
+// 0111 100d xxxx xxxx
+// Decrement 24-bit mid-accumulator $acsD.
+void decm(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x01;
+
+ s64 sub = 0x10000;
+ s64 acc = dsp_get_long_acc(dreg);
+ acc -= sub;
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// DEC $acD
+// 0111 101d xxxx xxxx
+// Decrement accumulator $acD.
+void dec(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x01;
+
+ s64 acc = dsp_get_long_acc(dreg) - 1;
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// INCM $acsD
+// 0111 010d xxxx xxxx
+// Increment 24-bit mid-accumulator $acsD.
+void incm(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x1;
+
+ s64 sub = 0x10000;
+ s64 acc = dsp_get_long_acc(dreg);
+ acc += sub;
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// INC $acD
+// 0111 011d xxxx xxxx
+// Increment accumulator $acD.
+void inc(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x1;
+
+ s64 acc = dsp_get_long_acc(dreg) + 1;
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// NEG $acD
+// 0111 110d xxxx xxxx
+// Negate accumulator $acD.
+void neg(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+
+ s64 acc = dsp_get_long_acc(areg);
+ acc = 0 - acc;
+ dsp_set_long_acc(areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// MOV $acD, $ac(1-D)
+// 0110 110d xxxx xxxx
+// Moves accumulator $ax(1-D) to accumulator $axD.
+void mov(const UDSPInstruction& opc)
+{
+ u8 D = (opc.hex >> 8) & 0x1;
+ u64 acc = dsp_get_long_acc(1 - D);
+ dsp_set_long_acc(D, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// ADDAX $acD, $axS
+// 0100 10sd xxxx xxxx
+// Adds secondary accumulator $axS to accumulator register $acD.
+void addax(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+ u8 sreg = (opc.hex >> 9) & 0x1;
+
+ s64 ax = dsp_get_long_acx(sreg);
+ s64 acc = dsp_get_long_acc(areg);
+ acc += ax;
+ dsp_set_long_acc(areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// ADDR $acD, $(DSP_REG_AXL0+S)
+// 0100 0ssd xxxx xxxx
+// Adds register $(DSP_REG_AXL0+S) to accumulator $acD register.
+void addr(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+ u8 sreg = ((opc.hex >> 9) & 0x3) + DSP_REG_AXL0;
+
+ s64 ax = (s16)g_dsp.r[sreg];
+ ax <<= 16;
+
+ s64 acc = dsp_get_long_acc(areg);
+ acc += ax;
+ dsp_set_long_acc(areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// SUBR $acD, $(DSP_REG_AXL0+S)
+// 0101 0ssd xxxx xxxx
+// Subtracts register $(DSP_REG_AXL0+S) from accumulator $acD register.
+void subr(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+ u8 sreg = ((opc.hex >> 9) & 0x3) + DSP_REG_AXL0;
+
+ s64 ax = (s16)g_dsp.r[sreg];
+ ax <<= 16;
+
+ s64 acc = dsp_get_long_acc(areg);
+ acc -= ax;
+ dsp_set_long_acc(areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// SUBAX $acD, $axS
+// 0101 10sd xxxx xxxx
+// Subtracts secondary accumulator $axS from accumulator register $acD.
+void subax(const UDSPInstruction& opc)
+{
+ int regD = (opc.hex >> 8) & 0x1;
+ int regS = (opc.hex >> 9) & 0x1;
+
+ s64 acc = dsp_get_long_acc(regD) - dsp_get_long_acx(regS);
+
+ dsp_set_long_acc(regD, acc);
+ Update_SR_Register64(acc);
+}
+
+// ADDIS $acD, #I
+// 0000 010d iiii iiii
+// Adds short immediate (8-bit sign extended) to mid accumulator $acD.hm.
+void addis(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+
+ s64 Imm = (s8)(u8)opc.hex;
+ Imm <<= 16;
+ s64 acc = dsp_get_long_acc(areg);
+ acc += Imm;
+ dsp_set_long_acc(areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// ADDI $amR, #I
+// 0000 001r 0000 0000
+// iiii iiii iiii iiii
+// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm.
+void addi(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+
+ s64 sub = (s16)dsp_fetch_code();
+ sub <<= 16;
+ s64 acc = dsp_get_long_acc(areg);
+ acc += sub;
+ dsp_set_long_acc(areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// LSL16 $acR
+// 1111 000r xxxx xxxx
+// Logically shifts left accumulator $acR by 16.
+void lsl16(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+
+ s64 acc = dsp_get_long_acc(areg);
+ acc <<= 16;
+ dsp_set_long_acc(areg, acc);
+ Update_SR_Register64(acc);
+}
+
+// LSR16 $acR
+// 1111 010r xxxx xxxx
+// Logically shifts right accumulator $acR by 16.
+void lsr16(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 8) & 0x1;
+
+ u64 acc = dsp_get_long_acc(areg);
+
+ acc >>= 16;
+ dsp_set_long_acc(areg, acc);
+ Update_SR_Register64(acc);
+}
+
+// ASR16 $acR
+// 1001 r001 xxxx xxxx
+// Arithmetically shifts right accumulator $acR by 16.
+void asr16(const UDSPInstruction& opc)
+{
+ u8 areg = (opc.hex >> 11) & 0x1;
+
+ s64 acc = dsp_get_long_acc(areg);
+
+ acc >>= 16;
+ dsp_set_long_acc(areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// LSL $acR, #I
+// 0001 010r 00ii iiii
+// Logically shifts left accumulator $acR by number specified by value I.
+void lsl(const UDSPInstruction& opc)
+{
+ u16 shift = opc.ushift;
+ u64 acc = dsp_get_long_acc(opc.areg);
+
+ acc <<= shift;
+ dsp_set_long_acc(opc.areg, acc);
+ Update_SR_Register64(acc);
+}
+
+// LSR $acR, #I
+// 0001 010r 01ii iiii
+// Logically shifts left accumulator $acR by number specified by value
+// calculated by negating sign extended bits 0-6.
+void lsr(const UDSPInstruction& opc)
+{
+ u16 shift = -opc.ushift;
+ u64 acc = dsp_get_long_acc(opc.areg);
+ // Lop off the extraneous sign extension our 64-bit fake accum causes
+ acc &= 0x000000FFFFFFFFFFULL;
+ acc >>= shift;
+ dsp_set_long_acc(opc.areg, (s64)acc);
+ Update_SR_Register64(acc);
+}
+
+// ASL $acR, #I
+// 0001 010r 10ii iiii
+// Logically shifts left accumulator $acR by number specified by value I.
+void asl(const UDSPInstruction& opc)
+{
+ u16 shift = opc.ushift;
+
+ // arithmetic shift
+ u64 acc = dsp_get_long_acc(opc.areg);
+ acc <<= shift;
+
+ dsp_set_long_acc(opc.areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// ASR $acR, #I
+// 0001 010r 11ii iiii
+// Arithmetically shifts right accumulator $acR by number specified by
+// value calculated by negating sign extended bits 0-6.
+void asr(const UDSPInstruction& opc)
+{
+ u16 shift = -opc.ushift;
+
+ // arithmetic shift
+ s64 acc = dsp_get_long_acc(opc.areg);
+ acc >>= shift;
+
+ dsp_set_long_acc(opc.areg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+
+// (NEW)
+// LSRN (fixed parameters)
+// 0000 0010 1100 1010
+// Logically shifts right accumulator $ACC0 by signed 16-bit value $AC1.M
+// (if value negative, becomes left shift).
+void lsrn(const UDSPInstruction& opc)
+{
+ s16 shift = (s16)g_dsp.r[DSP_REG_ACM1];
+ u64 acc = dsp_get_long_acc(0);
+ // Lop off the extraneous sign extension our 64-bit fake accum causes
+ acc &= 0x000000FFFFFFFFFFULL;
+ if (shift > 0) {
+ acc >>= shift;
+ } else if (shift < 0) {
+ acc <<= -shift;
+ }
+ dsp_set_long_acc(0, (s64)acc);
+ Update_SR_Register64(acc);
+}
+
+// (NEW)
+// ASRN (fixed parameters)
+// 0000 0010 1100 1011
+// Arithmetically shifts right accumulator $ACC0 by signed 16-bit value $AC1.M
+// (if value negative, becomes left shift).
+void asrn(const UDSPInstruction& opc)
+{
+ s16 shift = (s16)g_dsp.r[DSP_REG_ACM1];
+ s64 acc = dsp_get_long_acc(0);
+ if (shift > 0) {
+ acc >>= shift;
+ } else if (shift < 0) {
+ acc <<= -shift;
+ }
+ dsp_set_long_acc(0, acc);
+ Update_SR_Register64(acc);
+}
+
+
+// CMPAR $acS axR.h
+// 1100 0001 xxxx xxxx
+// Compares accumulator $acS with accumulator axR.h.
+// Not described by Duddie's doc - at least not as a separate instruction.
+void cmpar(const UDSPInstruction& opc)
+{
+ u8 rreg = ((opc.hex >> 12) & 0x1) + DSP_REG_AXH0;
+ u8 sreg = (opc.hex >> 11) & 0x1;
+
+ // we compare
+ s64 rr = (s16)g_dsp.r[rreg];
+ rr <<= 16;
+
+ s64 sr = dsp_get_long_acc(sreg);
+
+ Update_SR_Register64(sr - rr);
+}
+
+// CMP
+// 1000 0010 xxxx xxxx
+// Compares accumulator $ac0 with accumulator $ac1.
+void cmp(const UDSPInstruction& opc)
+{
+ s64 acc0 = dsp_get_long_acc(0);
+ s64 acc1 = dsp_get_long_acc(1);
+
+ Update_SR_Register64(acc0 - acc1);
+}
+
+// TST
+// 1011 r001 xxxx xxxx
+// Test accumulator %acR.
+void tst(const UDSPInstruction& opc)
+{
+ s8 reg = (opc.hex >> 11) & 0x1;
+ s64 acc = dsp_get_long_acc(reg);
+
+ Update_SR_Register64(acc);
+}
+
+} // namespace
diff --git a/Source/Core/DSPCore/Src/DspIntBranch.cpp b/Source/Core/DSPCore/Src/DspIntBranch.cpp
index f37cc71ba0..721428d8f0 100644
--- a/Source/Core/DSPCore/Src/DspIntBranch.cpp
+++ b/Source/Core/DSPCore/Src/DspIntBranch.cpp
@@ -1,249 +1,249 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie and Tratax (c) 2004
-
-#include "DSPInterpreter.h"
-#include "DSPCore.h"
-#include "DSPMemoryMap.h"
-#include "DSPStacks.h"
-
-#include "DSPIntCCUtil.h"
-#include "DSPIntUtil.h"
-
-namespace DSPInterpreter {
-
-// Generic call implementation
-// CALLcc addressA
-// 0000 0010 1011 cccc
-// aaaa aaaa aaaa aaaa
-// Call function if condition cc has been met. Push program counter of
-// instruction following "call" to $st0. Set program counter to address
-// represented by value that follows this "call" instruction.
-void call(const UDSPInstruction& opc)
-{
- // must be outside the if.
- u16 dest = dsp_fetch_code();
- if (CheckCondition(opc.hex & 0xf))
- {
- dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
- g_dsp.pc = dest;
- }
-}
-
-// Generic callr implementation
-// CALLRcc $R
-// 0001 0111 rrr1 cccc
-// Call function if condition cc has been met. Push program counter of
-// instruction following "call" to call stack $st0. Set program counter to
-// register $R.
-void callr(const UDSPInstruction& opc)
-{
- if (CheckCondition(opc.hex & 0xf))
- {
- u8 reg = (opc.hex >> 5) & 0x7;
- u16 addr = dsp_op_read_reg(reg);
- dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
- g_dsp.pc = addr;
- }
-}
-
-// Generic if implementation
-// IFcc
-// 0000 0010 0111 cccc
-// Execute following opcode if the condition has been met.
-void ifcc(const UDSPInstruction& opc)
-{
- if (!CheckCondition(opc.hex & 0xf))
- {
- // skip the next opcode - we have to lookup its size.
- g_dsp.pc += opSize[dsp_peek_code()];
- }
-}
-
-// Generic jmp implementation
-// Jcc addressA
-// 0000 0010 1001 cccc
-// aaaa aaaa aaaa aaaa
-// Jump to addressA if condition cc has been met. Set program counter to
-// address represented by value that follows this "jmp" instruction.
-void jcc(const UDSPInstruction& opc)
-{
- u16 dest = dsp_fetch_code();
- if (CheckCondition(opc.hex & 0xf))
- {
- g_dsp.pc = dest;
- }
-}
-
-// Generic jmpr implementation
-// JMPcc $R
-// 0001 0111 rrr0 cccc
-// Jump to address; set program counter to a value from register $R.
-void jmprcc(const UDSPInstruction& opc)
-{
- if (CheckCondition(opc.hex & 0xf))
- {
- u8 reg = (opc.hex >> 5) & 0x7;
- g_dsp.pc = dsp_op_read_reg(reg);
- }
-}
-
-// Generic ret implementation
-// RETcc
-// 0000 0010 1101 cccc
-// Return from subroutine if condition cc has been met. Pops stored PC
-// from call stack $st0 and sets $pc to this location.
-void ret(const UDSPInstruction& opc)
-{
- if (CheckCondition(opc.hex & 0xf))
- {
- g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
- }
-}
-
-// RTI
-// 0000 0010 1111 1111
-// Return from exception. Pops stored status register $sr from data stack
-// $st1 and program counter PC from call stack $st0 and sets $pc to this
-// location.
-void rti(const UDSPInstruction& opc)
-{
- g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
- g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
-
- g_dsp.exception_in_progress_hack = false;
-}
-
-// HALT
-// 0000 0000 0020 0001
-// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
-void halt(const UDSPInstruction& opc)
-{
- g_dsp.cr |= 0x4;
- g_dsp.pc--;
-}
-
-
-// LOOP handling: Loop stack is used to control execution of repeated blocks of
-// instructions. Whenever there is value on stack $st2 and current PC is equal
-// value at $st2, then value at stack $st3 is decremented. If value is not zero
-// then PC is modified with calue from call stack $st0. Otherwise values from
-// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
-// continues at next opcode.
-
-
-// LOOP $R
-// 0000 0000 010r rrrr
-// Repeatedly execute following opcode until counter specified by value
-// from register $R reaches zero. Each execution decrement counter. Register
-// $R remains unchanged. If register $R is set to zero at the beginning of loop
-// then looped instruction will not get executed.
-// Actually, this instruction simply prepares the loop stacks for the above.
-// The looping hardware takes care of the rest.
-void loop(const UDSPInstruction& opc)
-{
- u16 reg = opc.hex & 0x1f;
- u16 cnt = g_dsp.r[reg];
- u16 loop_pc = g_dsp.pc;
-
- if (cnt)
- {
- dsp_reg_store_stack(0, g_dsp.pc);
- dsp_reg_store_stack(2, loop_pc);
- dsp_reg_store_stack(3, cnt);
- }
-}
-
-// LOOPI #I
-// 0001 0000 iiii iiii
-// Repeatedly execute following opcode until counter specified by
-// immediate value I reaches zero. Each execution decrement counter. If
-// immediate value I is set to zero at the beginning of loop then looped
-// instruction will not get executed.
-// Actually, this instruction simply prepares the loop stacks for the above.
-// The looping hardware takes care of the rest.
-void loopi(const UDSPInstruction& opc)
-{
- u16 cnt = opc.hex & 0xff;
- u16 loop_pc = g_dsp.pc;
-
- if (cnt)
- {
- dsp_reg_store_stack(0, g_dsp.pc);
- dsp_reg_store_stack(2, loop_pc);
- dsp_reg_store_stack(3, cnt);
- }
-}
-
-
-// BLOOP $R, addrA
-// 0000 0000 011r rrrr
-// aaaa aaaa aaaa aaaa
-// Repeatedly execute block of code starting at following opcode until
-// counter specified by value from register $R reaches zero. Block ends at
-// specified address addrA inclusive, ie. opcode at addrA is the last opcode
-// included in loop. Counter is pushed on loop stack $st3, end of block address
-// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
-// Up to 4 nested loops is allowed.
-void bloop(const UDSPInstruction& opc)
-{
- u16 reg = opc.hex & 0x1f;
- u16 cnt = g_dsp.r[reg];
- u16 loop_pc = dsp_fetch_code();
-
- if (cnt)
- {
- dsp_reg_store_stack(0, g_dsp.pc);
- dsp_reg_store_stack(2, loop_pc);
- dsp_reg_store_stack(3, cnt);
- }
- else
- {
- g_dsp.pc = loop_pc;
- g_dsp.pc += opSize[dsp_peek_code()];
- }
-}
-
-// BLOOPI #I, addrA
-// 0001 0001 iiii iiii
-// aaaa aaaa aaaa aaaa
-// Repeatedly execute block of code starting at following opcode until
-// counter specified by immediate value I reaches zero. Block ends at specified
-// address addrA inclusive, ie. opcode at addrA is the last opcode included in
-// loop. Counter is pushed on loop stack $st3, end of block address is pushed
-// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
-// nested loops is allowed.
-void bloopi(const UDSPInstruction& opc)
-{
- u16 cnt = opc.hex & 0xff;
- u16 loop_pc = dsp_fetch_code();
-
- if (cnt)
- {
- dsp_reg_store_stack(0, g_dsp.pc);
- dsp_reg_store_stack(2, loop_pc);
- dsp_reg_store_stack(3, cnt);
- }
- else
- {
- g_dsp.pc = loop_pc;
- g_dsp.pc += opSize[dsp_peek_code()];
- }
-}
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie and Tratax (c) 2004
+
+#include "DSPInterpreter.h"
+#include "DSPCore.h"
+#include "DSPMemoryMap.h"
+#include "DSPStacks.h"
+
+#include "DSPIntCCUtil.h"
+#include "DSPIntUtil.h"
+
+namespace DSPInterpreter {
+
+// Generic call implementation
+// CALLcc addressA
+// 0000 0010 1011 cccc
+// aaaa aaaa aaaa aaaa
+// Call function if condition cc has been met. Push program counter of
+// instruction following "call" to $st0. Set program counter to address
+// represented by value that follows this "call" instruction.
+void call(const UDSPInstruction& opc)
+{
+ // must be outside the if.
+ u16 dest = dsp_fetch_code();
+ if (CheckCondition(opc.hex & 0xf))
+ {
+ dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
+ g_dsp.pc = dest;
+ }
+}
+
+// Generic callr implementation
+// CALLRcc $R
+// 0001 0111 rrr1 cccc
+// Call function if condition cc has been met. Push program counter of
+// instruction following "call" to call stack $st0. Set program counter to
+// register $R.
+void callr(const UDSPInstruction& opc)
+{
+ if (CheckCondition(opc.hex & 0xf))
+ {
+ u8 reg = (opc.hex >> 5) & 0x7;
+ u16 addr = dsp_op_read_reg(reg);
+ dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
+ g_dsp.pc = addr;
+ }
+}
+
+// Generic if implementation
+// IFcc
+// 0000 0010 0111 cccc
+// Execute following opcode if the condition has been met.
+void ifcc(const UDSPInstruction& opc)
+{
+ if (!CheckCondition(opc.hex & 0xf))
+ {
+ // skip the next opcode - we have to lookup its size.
+ g_dsp.pc += opSize[dsp_peek_code()];
+ }
+}
+
+// Generic jmp implementation
+// Jcc addressA
+// 0000 0010 1001 cccc
+// aaaa aaaa aaaa aaaa
+// Jump to addressA if condition cc has been met. Set program counter to
+// address represented by value that follows this "jmp" instruction.
+void jcc(const UDSPInstruction& opc)
+{
+ u16 dest = dsp_fetch_code();
+ if (CheckCondition(opc.hex & 0xf))
+ {
+ g_dsp.pc = dest;
+ }
+}
+
+// Generic jmpr implementation
+// JMPcc $R
+// 0001 0111 rrr0 cccc
+// Jump to address; set program counter to a value from register $R.
+void jmprcc(const UDSPInstruction& opc)
+{
+ if (CheckCondition(opc.hex & 0xf))
+ {
+ u8 reg = (opc.hex >> 5) & 0x7;
+ g_dsp.pc = dsp_op_read_reg(reg);
+ }
+}
+
+// Generic ret implementation
+// RETcc
+// 0000 0010 1101 cccc
+// Return from subroutine if condition cc has been met. Pops stored PC
+// from call stack $st0 and sets $pc to this location.
+void ret(const UDSPInstruction& opc)
+{
+ if (CheckCondition(opc.hex & 0xf))
+ {
+ g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
+ }
+}
+
+// RTI
+// 0000 0010 1111 1111
+// Return from exception. Pops stored status register $sr from data stack
+// $st1 and program counter PC from call stack $st0 and sets $pc to this
+// location.
+void rti(const UDSPInstruction& opc)
+{
+ g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
+ g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
+
+ g_dsp.exception_in_progress_hack = false;
+}
+
+// HALT
+// 0000 0000 0020 0001
+// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
+void halt(const UDSPInstruction& opc)
+{
+ g_dsp.cr |= 0x4;
+ g_dsp.pc--;
+}
+
+
+// LOOP handling: Loop stack is used to control execution of repeated blocks of
+// instructions. Whenever there is value on stack $st2 and current PC is equal
+// value at $st2, then value at stack $st3 is decremented. If value is not zero
+// then PC is modified with calue from call stack $st0. Otherwise values from
+// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
+// continues at next opcode.
+
+
+// LOOP $R
+// 0000 0000 010r rrrr
+// Repeatedly execute following opcode until counter specified by value
+// from register $R reaches zero. Each execution decrement counter. Register
+// $R remains unchanged. If register $R is set to zero at the beginning of loop
+// then looped instruction will not get executed.
+// Actually, this instruction simply prepares the loop stacks for the above.
+// The looping hardware takes care of the rest.
+void loop(const UDSPInstruction& opc)
+{
+ u16 reg = opc.hex & 0x1f;
+ u16 cnt = g_dsp.r[reg];
+ u16 loop_pc = g_dsp.pc;
+
+ if (cnt)
+ {
+ dsp_reg_store_stack(0, g_dsp.pc);
+ dsp_reg_store_stack(2, loop_pc);
+ dsp_reg_store_stack(3, cnt);
+ }
+}
+
+// LOOPI #I
+// 0001 0000 iiii iiii
+// Repeatedly execute following opcode until counter specified by
+// immediate value I reaches zero. Each execution decrement counter. If
+// immediate value I is set to zero at the beginning of loop then looped
+// instruction will not get executed.
+// Actually, this instruction simply prepares the loop stacks for the above.
+// The looping hardware takes care of the rest.
+void loopi(const UDSPInstruction& opc)
+{
+ u16 cnt = opc.hex & 0xff;
+ u16 loop_pc = g_dsp.pc;
+
+ if (cnt)
+ {
+ dsp_reg_store_stack(0, g_dsp.pc);
+ dsp_reg_store_stack(2, loop_pc);
+ dsp_reg_store_stack(3, cnt);
+ }
+}
+
+
+// BLOOP $R, addrA
+// 0000 0000 011r rrrr
+// aaaa aaaa aaaa aaaa
+// Repeatedly execute block of code starting at following opcode until
+// counter specified by value from register $R reaches zero. Block ends at
+// specified address addrA inclusive, ie. opcode at addrA is the last opcode
+// included in loop. Counter is pushed on loop stack $st3, end of block address
+// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
+// Up to 4 nested loops is allowed.
+void bloop(const UDSPInstruction& opc)
+{
+ u16 reg = opc.hex & 0x1f;
+ u16 cnt = g_dsp.r[reg];
+ u16 loop_pc = dsp_fetch_code();
+
+ if (cnt)
+ {
+ dsp_reg_store_stack(0, g_dsp.pc);
+ dsp_reg_store_stack(2, loop_pc);
+ dsp_reg_store_stack(3, cnt);
+ }
+ else
+ {
+ g_dsp.pc = loop_pc;
+ g_dsp.pc += opSize[dsp_peek_code()];
+ }
+}
+
+// BLOOPI #I, addrA
+// 0001 0001 iiii iiii
+// aaaa aaaa aaaa aaaa
+// Repeatedly execute block of code starting at following opcode until
+// counter specified by immediate value I reaches zero. Block ends at specified
+// address addrA inclusive, ie. opcode at addrA is the last opcode included in
+// loop. Counter is pushed on loop stack $st3, end of block address is pushed
+// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
+// nested loops is allowed.
+void bloopi(const UDSPInstruction& opc)
+{
+ u16 cnt = opc.hex & 0xff;
+ u16 loop_pc = dsp_fetch_code();
+
+ if (cnt)
+ {
+ dsp_reg_store_stack(0, g_dsp.pc);
+ dsp_reg_store_stack(2, loop_pc);
+ dsp_reg_store_stack(3, cnt);
+ }
+ else
+ {
+ g_dsp.pc = loop_pc;
+ g_dsp.pc += opSize[dsp_peek_code()];
+ }
+}
+
+} // namespace
diff --git a/Source/Core/DSPCore/Src/DspIntLoadStore.cpp b/Source/Core/DSPCore/Src/DspIntLoadStore.cpp
index 5346a4ed41..b2603f6c54 100644
--- a/Source/Core/DSPCore/Src/DspIntLoadStore.cpp
+++ b/Source/Core/DSPCore/Src/DspIntLoadStore.cpp
@@ -1,266 +1,266 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie and Tratax (c) 2004
-
-#include "DSPInterpreter.h"
-
-#include "DSPMemoryMap.h"
-#include "DSPIntUtil.h"
-
-namespace DSPInterpreter {
-
-// SRS @M, $(0x18+S)
-// 0010 1sss mmmm mmmm
-// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
-// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
-// lower 8 bits are from the 8-bit immediate.
-// Note: pc+=2 in duddie's doc seems wrong
-void srs(const UDSPInstruction& opc)
-{
- u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
- u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
- dsp_dmem_write(addr, g_dsp.r[reg]);
-}
-
-// LRS $(0x18+D), @M
-// 0010 0ddd mmmm mmmm
-// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
-// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
-// lower 8 bits are from the 8-bit immediate.
-void lrs(const UDSPInstruction& opc)
-{
- u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
- u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
- g_dsp.r[reg] = dsp_dmem_read(addr);
-}
-
-// LR $D, @M
-// 0000 0000 110d dddd
-// mmmm mmmm mmmm mmmm
-// Move value from data memory pointed by address M to register $D.
-// FIXME: Perform additional operation depending on destination register.
-void lr(const UDSPInstruction& opc)
-{
- u8 reg = opc.hex & DSP_REG_MASK;
- u16 addr = dsp_fetch_code();
- u16 val = dsp_dmem_read(addr);
- dsp_op_write_reg(reg, val);
- dsp_conditional_extend_accum(reg);
-}
-
-// SR @M, $S
-// 0000 0000 111s ssss
-// mmmm mmmm mmmm mmmm
-// Store value from register $S to a memory pointed by address M.
-// FIXME: Perform additional operation depending on destination register.
-void sr(const UDSPInstruction& opc)
-{
- u8 reg = opc.hex & DSP_REG_MASK;
- u16 addr = dsp_fetch_code();
- u16 val = dsp_op_read_reg(reg);
- dsp_dmem_write(addr, val);
-}
-
-// SI @M, #I
-// 0001 0110 mmmm mmmm
-// iiii iiii iiii iiii
-// Store 16-bit immediate value I to a memory location pointed by address
-// M (M is 8-bit value sign extended).
-void si(const UDSPInstruction& opc)
-{
- u16 addr = (s8)opc.hex;
- u16 imm = dsp_fetch_code();
- dsp_dmem_write(addr, imm);
-}
-
-// LRR $D, @$S
-// 0001 1000 0ssd dddd
-// Move value from data memory pointed by addressing register $S to register $D.
-// FIXME: Perform additional operation depending on destination register.
-void lrr(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 5) & 0x3;
- u8 dreg = opc.hex & 0x1f;
-
- u16 val = dsp_dmem_read(g_dsp.r[sreg]);
- dsp_op_write_reg(dreg, val);
-}
-
-// LRRD $D, @$S
-// 0001 1000 1ssd dddd
-// Move value from data memory pointed by addressing register $S toregister $D.
-// Decrement register $S.
-// FIXME: Perform additional operation depending on destination register.
-void lrrd(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 5) & 0x3;
- u8 dreg = opc.hex & 0x1f;
-
- u16 val = dsp_dmem_read(g_dsp.r[sreg]);
- dsp_op_write_reg(dreg, val);
- dsp_decrement_addr_reg(sreg);
-}
-
-// LRRI $D, @$S
-// 0001 1001 0ssd dddd
-// Move value from data memory pointed by addressing register $S to register $D.
-// Increment register $S.
-// FIXME: Perform additional operation depending on destination register.
-void lrri(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 5) & 0x3;
- u8 dreg = opc.hex & 0x1f;
-
- u16 val = dsp_dmem_read(g_dsp.r[sreg]);
- dsp_op_write_reg(dreg, val);
- dsp_increment_addr_reg(sreg);
-}
-
-// LRRN $D, @$S
-// 0001 1001 1ssd dddd
-// Move value from data memory pointed by addressing register $S to register $D.
-// Add indexing register $(0x4+S) to register $S.
-// FIXME: Perform additional operation depending on destination register.
-void lrrn(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 5) & 0x3;
- u8 dreg = opc.hex & 0x1f;
-
- u16 val = dsp_dmem_read(g_dsp.r[sreg]);
- dsp_op_write_reg(dreg, val);
- // g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
- dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
-}
-
-// SRR @$D, $S
-// 0001 1010 0dds ssss
-// Store value from source register $S to a memory location pointed by
-// addressing register $D.
-// FIXME: Perform additional operation depending on source register.
-void srr(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 5) & 0x3;
- u8 sreg = opc.hex & 0x1f;
-
- u16 val = dsp_op_read_reg(sreg);
- dsp_dmem_write(g_dsp.r[dreg], val);
-}
-
-// SRRD @$D, $S
-// 0001 1010 1dds ssss
-// Store value from source register $S to a memory location pointed by
-// addressing register $D. Decrement register $D.
-// FIXME: Perform additional operation depending on source register.
-void srrd(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 5) & 0x3;
- u8 sreg = opc.hex & 0x1f;
-
- u16 val = dsp_op_read_reg(sreg);
- dsp_dmem_write(g_dsp.r[dreg], val);
- dsp_decrement_addr_reg(dreg);
-}
-
-// SRRI @$D, $S
-// 0001 1011 0dds ssss
-// Store value from source register $S to a memory location pointed by
-// addressing register $D. Increment register $D.
-// FIXME: Perform additional operation depending on source register.
-void srri(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 5) & 0x3;
- u8 sreg = opc.hex & 0x1f;
-
- u16 val = dsp_op_read_reg(sreg);
- dsp_dmem_write(g_dsp.r[dreg], val);
- dsp_increment_addr_reg(dreg);
-}
-
-// SRRN @$D, $S
-// 0001 1011 1dds ssss
-// Store value from source register $S to a memory location pointed by
-// addressing register $D. Add DSP_REG_IX0 register to register $D.
-// FIXME: Perform additional operation depending on source register.
-void srrn(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 5) & 0x3;
- u8 sreg = opc.hex & 0x1f;
-
- u16 val = dsp_op_read_reg(sreg);
- dsp_dmem_write(g_dsp.r[dreg], val);
- // g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
- dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
-}
-
-// ILRR $acD.m, @$arS
-// 0000 001d 0001 00ss
-// Move value from instruction memory pointed by addressing register
-// $arS to mid accumulator register $acD.m.
-void ilrr(const UDSPInstruction& opc)
-{
- u16 reg = opc.hex & 0x3;
- u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
-
- g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
-}
-
-// ILRRD $acD.m, @$arS
-// 0000 001d 0001 01ss
-// Move value from instruction memory pointed by addressing register
-// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
-void ilrrd(const UDSPInstruction& opc)
-{
- u16 reg = opc.hex & 0x3;
- u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
-
- g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
-
- dsp_decrement_addr_reg(reg);
-}
-
-// ILRRI $acD.m, @$S
-// 0000 001d 0001 10ss
-// Move value from instruction memory pointed by addressing register
-// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
-void ilrri(const UDSPInstruction& opc)
-{
- u16 reg = opc.hex & 0x3;
- u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
-
- g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
-
- dsp_increment_addr_reg(reg);
-}
-
-// ILRRN $acD.m, @$arS
-// 0000 001d 0001 11ss
-// Move value from instruction memory pointed by addressing register
-// $arS to mid accumulator register $acD.m. Add corresponding indexing
-// register $ixS to addressing register $arS.
-void ilrrn(const UDSPInstruction& opc)
-{
- u16 reg = opc.hex & 0x3;
- u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
-
- g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
-
- // g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
- dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
-}
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie and Tratax (c) 2004
+
+#include "DSPInterpreter.h"
+
+#include "DSPMemoryMap.h"
+#include "DSPIntUtil.h"
+
+namespace DSPInterpreter {
+
+// SRS @M, $(0x18+S)
+// 0010 1sss mmmm mmmm
+// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
+// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
+// lower 8 bits are from the 8-bit immediate.
+// Note: pc+=2 in duddie's doc seems wrong
+void srs(const UDSPInstruction& opc)
+{
+ u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
+ u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
+ dsp_dmem_write(addr, g_dsp.r[reg]);
+}
+
+// LRS $(0x18+D), @M
+// 0010 0ddd mmmm mmmm
+// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
+// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
+// lower 8 bits are from the 8-bit immediate.
+void lrs(const UDSPInstruction& opc)
+{
+ u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
+ u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
+ g_dsp.r[reg] = dsp_dmem_read(addr);
+}
+
+// LR $D, @M
+// 0000 0000 110d dddd
+// mmmm mmmm mmmm mmmm
+// Move value from data memory pointed by address M to register $D.
+// FIXME: Perform additional operation depending on destination register.
+void lr(const UDSPInstruction& opc)
+{
+ u8 reg = opc.hex & DSP_REG_MASK;
+ u16 addr = dsp_fetch_code();
+ u16 val = dsp_dmem_read(addr);
+ dsp_op_write_reg(reg, val);
+ dsp_conditional_extend_accum(reg);
+}
+
+// SR @M, $S
+// 0000 0000 111s ssss
+// mmmm mmmm mmmm mmmm
+// Store value from register $S to a memory pointed by address M.
+// FIXME: Perform additional operation depending on destination register.
+void sr(const UDSPInstruction& opc)
+{
+ u8 reg = opc.hex & DSP_REG_MASK;
+ u16 addr = dsp_fetch_code();
+ u16 val = dsp_op_read_reg(reg);
+ dsp_dmem_write(addr, val);
+}
+
+// SI @M, #I
+// 0001 0110 mmmm mmmm
+// iiii iiii iiii iiii
+// Store 16-bit immediate value I to a memory location pointed by address
+// M (M is 8-bit value sign extended).
+void si(const UDSPInstruction& opc)
+{
+ u16 addr = (s8)opc.hex;
+ u16 imm = dsp_fetch_code();
+ dsp_dmem_write(addr, imm);
+}
+
+// LRR $D, @$S
+// 0001 1000 0ssd dddd
+// Move value from data memory pointed by addressing register $S to register $D.
+// FIXME: Perform additional operation depending on destination register.
+void lrr(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 5) & 0x3;
+ u8 dreg = opc.hex & 0x1f;
+
+ u16 val = dsp_dmem_read(g_dsp.r[sreg]);
+ dsp_op_write_reg(dreg, val);
+}
+
+// LRRD $D, @$S
+// 0001 1000 1ssd dddd
+// Move value from data memory pointed by addressing register $S toregister $D.
+// Decrement register $S.
+// FIXME: Perform additional operation depending on destination register.
+void lrrd(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 5) & 0x3;
+ u8 dreg = opc.hex & 0x1f;
+
+ u16 val = dsp_dmem_read(g_dsp.r[sreg]);
+ dsp_op_write_reg(dreg, val);
+ dsp_decrement_addr_reg(sreg);
+}
+
+// LRRI $D, @$S
+// 0001 1001 0ssd dddd
+// Move value from data memory pointed by addressing register $S to register $D.
+// Increment register $S.
+// FIXME: Perform additional operation depending on destination register.
+void lrri(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 5) & 0x3;
+ u8 dreg = opc.hex & 0x1f;
+
+ u16 val = dsp_dmem_read(g_dsp.r[sreg]);
+ dsp_op_write_reg(dreg, val);
+ dsp_increment_addr_reg(sreg);
+}
+
+// LRRN $D, @$S
+// 0001 1001 1ssd dddd
+// Move value from data memory pointed by addressing register $S to register $D.
+// Add indexing register $(0x4+S) to register $S.
+// FIXME: Perform additional operation depending on destination register.
+void lrrn(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 5) & 0x3;
+ u8 dreg = opc.hex & 0x1f;
+
+ u16 val = dsp_dmem_read(g_dsp.r[sreg]);
+ dsp_op_write_reg(dreg, val);
+ // g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
+ dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
+}
+
+// SRR @$D, $S
+// 0001 1010 0dds ssss
+// Store value from source register $S to a memory location pointed by
+// addressing register $D.
+// FIXME: Perform additional operation depending on source register.
+void srr(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 5) & 0x3;
+ u8 sreg = opc.hex & 0x1f;
+
+ u16 val = dsp_op_read_reg(sreg);
+ dsp_dmem_write(g_dsp.r[dreg], val);
+}
+
+// SRRD @$D, $S
+// 0001 1010 1dds ssss
+// Store value from source register $S to a memory location pointed by
+// addressing register $D. Decrement register $D.
+// FIXME: Perform additional operation depending on source register.
+void srrd(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 5) & 0x3;
+ u8 sreg = opc.hex & 0x1f;
+
+ u16 val = dsp_op_read_reg(sreg);
+ dsp_dmem_write(g_dsp.r[dreg], val);
+ dsp_decrement_addr_reg(dreg);
+}
+
+// SRRI @$D, $S
+// 0001 1011 0dds ssss
+// Store value from source register $S to a memory location pointed by
+// addressing register $D. Increment register $D.
+// FIXME: Perform additional operation depending on source register.
+void srri(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 5) & 0x3;
+ u8 sreg = opc.hex & 0x1f;
+
+ u16 val = dsp_op_read_reg(sreg);
+ dsp_dmem_write(g_dsp.r[dreg], val);
+ dsp_increment_addr_reg(dreg);
+}
+
+// SRRN @$D, $S
+// 0001 1011 1dds ssss
+// Store value from source register $S to a memory location pointed by
+// addressing register $D. Add DSP_REG_IX0 register to register $D.
+// FIXME: Perform additional operation depending on source register.
+void srrn(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 5) & 0x3;
+ u8 sreg = opc.hex & 0x1f;
+
+ u16 val = dsp_op_read_reg(sreg);
+ dsp_dmem_write(g_dsp.r[dreg], val);
+ // g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
+ dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
+}
+
+// ILRR $acD.m, @$arS
+// 0000 001d 0001 00ss
+// Move value from instruction memory pointed by addressing register
+// $arS to mid accumulator register $acD.m.
+void ilrr(const UDSPInstruction& opc)
+{
+ u16 reg = opc.hex & 0x3;
+ u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
+
+ g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
+}
+
+// ILRRD $acD.m, @$arS
+// 0000 001d 0001 01ss
+// Move value from instruction memory pointed by addressing register
+// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
+void ilrrd(const UDSPInstruction& opc)
+{
+ u16 reg = opc.hex & 0x3;
+ u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
+
+ g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
+
+ dsp_decrement_addr_reg(reg);
+}
+
+// ILRRI $acD.m, @$S
+// 0000 001d 0001 10ss
+// Move value from instruction memory pointed by addressing register
+// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
+void ilrri(const UDSPInstruction& opc)
+{
+ u16 reg = opc.hex & 0x3;
+ u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
+
+ g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
+
+ dsp_increment_addr_reg(reg);
+}
+
+// ILRRN $acD.m, @$arS
+// 0000 001d 0001 11ss
+// Move value from instruction memory pointed by addressing register
+// $arS to mid accumulator register $acD.m. Add corresponding indexing
+// register $ixS to addressing register $arS.
+void ilrrn(const UDSPInstruction& opc)
+{
+ u16 reg = opc.hex & 0x3;
+ u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
+
+ g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
+
+ // g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
+ dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
+}
+
+} // namespace
diff --git a/Source/Core/DSPCore/Src/DspIntMisc.cpp b/Source/Core/DSPCore/Src/DspIntMisc.cpp
index df60210d98..3b9deee559 100644
--- a/Source/Core/DSPCore/Src/DspIntMisc.cpp
+++ b/Source/Core/DSPCore/Src/DspIntMisc.cpp
@@ -1,202 +1,202 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie and Tratax (c) 2004
-
-
-#include "DSPInterpreter.h"
-
-#include "DSPCore.h"
-#include "DSPIntUtil.h"
-
-namespace DSPInterpreter {
-
-void unknown(const UDSPInstruction& opc)
-{
- //_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
- ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
-}
-
-// MRR $D, $S
-// 0001 11dd ddds ssss
-// Move value from register $S to register $D.
-// FIXME: Perform additional operation depending on destination register.
-void mrr(const UDSPInstruction& opc)
-{
- u8 sreg = opc.hex & 0x1f;
- u8 dreg = (opc.hex >> 5) & 0x1f;
-
- u16 val = dsp_op_read_reg(sreg);
- dsp_op_write_reg(dreg, val);
-}
-
-// LRI $D, #I
-// 0000 0000 100d dddd
-// iiii iiii iiii iiii
-// Load immediate value I to register $D.
-// FIXME: Perform additional operation depending on destination register.
-
-// DSPSpy discovery: This, and possibly other instructions that load a register,
-// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
-// to the whole accumulator! This does not happen in S16 mode.
-void lri(const UDSPInstruction& opc)
-{
- u8 reg = opc.hex & DSP_REG_MASK;
- u16 imm = dsp_fetch_code();
- dsp_op_write_reg(reg, imm);
- dsp_conditional_extend_accum(reg);
-}
-
-// LRIS $(0x18+D), #I
-// 0000 1ddd iiii iiii
-// Load immediate value I (8-bit sign extended) to accumulator register.
-// FIXME: Perform additional operation depending on destination register.
-void lris(const UDSPInstruction& opc)
-{
- u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
- u16 imm = (s8)opc.hex;
- dsp_op_write_reg(reg, imm);
- dsp_conditional_extend_accum(reg);
-}
-
-
-// TSTAXL $acR
-// 1000 r001 xxxx xxxx
-// r specifies one of the main accumulators.
-// Definitely not a test instruction - it changes the accums.
-// Not affected by m0/m2. Not affected by s16/s40.
-void tstaxl(const UDSPInstruction& opc)
-{
- // This is probably all wrong.
- //u8 reg = (opc.hex >> 8) & 0x1;
- //s16 val = dsp_get_ax_l(reg);
- //Update_SR_Register16(val);
-}
-
-// ADDARN $arD, $ixS
-// 0000 0000 0001 ssdd
-// Adds indexing register $ixS to an addressing register $arD.
-void addarn(const UDSPInstruction& opc)
-{
- u8 dreg = opc.hex & 0x3;
- u8 sreg = (opc.hex >> 2) & 0x3;
-
- // g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
-
- dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
-
- // It is critical for the Zelda ucode that this one wraps correctly.
-}
-
-// NX
-// 1000 -000 xxxx xxxx
-// No operation, but can be extended with extended opcode.
-void nx(const UDSPInstruction& opc)
-{
- // This opcode is supposed to do nothing - it's used if you want to use
- // an opcode extension but not do anything. At least according to duddie.
-}
-
-//-------------------------------------------------------------
-// DAR $arD ?
-// 0000 0000 0000 01dd
-// Decrement address register $arD.
-void dar(const UDSPInstruction& opc)
-{
- dsp_decrement_addr_reg(opc.hex & 0x3);
-}
-
-// IAR $arD ?
-// 0000 0000 0000 10dd
-// Increment address register $arD.
-void iar(const UDSPInstruction& opc)
-{
- dsp_increment_addr_reg(opc.hex & 0x3);
-}
-
-// SBCLR #I
-// 0001 0011 0000 0iii
-// bit of status register $sr. Bit number is calculated by adding 6 to
-// immediate value I.
-void sbclr(const UDSPInstruction& opc)
-{
- u8 bit = (opc.hex & 0xff) + 6;
- g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
-}
-
-// SBSET #I
-// 0001 0010 0000 0iii
-// Set bit of status register $sr. Bit number is calculated by adding 6 to
-// immediate value I.
-void sbset(const UDSPInstruction& opc)
-{
- u8 bit = (opc.hex & 0xff) + 6;
- g_dsp.r[DSP_REG_SR] |= (1 << bit);
-}
-
-
-// FIXME inside
-// This is a bunch of flag setters, flipping bits in SR. So far so good,
-// but it's harder to know exactly what effect they have.
-// M0/M2 change the multiplier mode (it can multiply by 2 for free).
-//
-// SET16 changes something very important: see the LRI instruction above.
-// Hermes' demo sets the following defaults:
-// SET40
-// CLR15
-// M0
-void srbith(const UDSPInstruction& opc)
-{
- switch ((opc.hex >> 8) & 0xf)
- {
- // M0 seems to be the default. M2 is used in functions in Zelda
- // and then reset with M0 at the end. Like the other bits here, it's
- // done around loops with lots of multiplications.
- // I've confirmed with DSPSpy that they flip this bit.
- case 0xa: // M2
- g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
- break;
- case 0xb: // M0
- g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
- break;
-
- // If set, treat multiplicands as unsigned.
- // If clear, treat them as signed.
- case 0xc: // CLR15
- g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
- break;
- case 0xd: // SET15
- g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
- break;
-
- // Automatic 40-bit sign extension when loading ACx.M.
- // 40 seems to be the default.
- // Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
- case 0xe: // SET16 (really, clear SR's 0x4000)
- g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
- break;
-
- case 0xf: // SET40 (really, set SR's 0x4000)
- g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
- break;
-
- default:
- break;
- }
-}
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie and Tratax (c) 2004
+
+
+#include "DSPInterpreter.h"
+
+#include "DSPCore.h"
+#include "DSPIntUtil.h"
+
+namespace DSPInterpreter {
+
+void unknown(const UDSPInstruction& opc)
+{
+ //_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
+ ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
+}
+
+// MRR $D, $S
+// 0001 11dd ddds ssss
+// Move value from register $S to register $D.
+// FIXME: Perform additional operation depending on destination register.
+void mrr(const UDSPInstruction& opc)
+{
+ u8 sreg = opc.hex & 0x1f;
+ u8 dreg = (opc.hex >> 5) & 0x1f;
+
+ u16 val = dsp_op_read_reg(sreg);
+ dsp_op_write_reg(dreg, val);
+}
+
+// LRI $D, #I
+// 0000 0000 100d dddd
+// iiii iiii iiii iiii
+// Load immediate value I to register $D.
+// FIXME: Perform additional operation depending on destination register.
+
+// DSPSpy discovery: This, and possibly other instructions that load a register,
+// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
+// to the whole accumulator! This does not happen in S16 mode.
+void lri(const UDSPInstruction& opc)
+{
+ u8 reg = opc.hex & DSP_REG_MASK;
+ u16 imm = dsp_fetch_code();
+ dsp_op_write_reg(reg, imm);
+ dsp_conditional_extend_accum(reg);
+}
+
+// LRIS $(0x18+D), #I
+// 0000 1ddd iiii iiii
+// Load immediate value I (8-bit sign extended) to accumulator register.
+// FIXME: Perform additional operation depending on destination register.
+void lris(const UDSPInstruction& opc)
+{
+ u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
+ u16 imm = (s8)opc.hex;
+ dsp_op_write_reg(reg, imm);
+ dsp_conditional_extend_accum(reg);
+}
+
+
+// TSTAXL $acR
+// 1000 r001 xxxx xxxx
+// r specifies one of the main accumulators.
+// Definitely not a test instruction - it changes the accums.
+// Not affected by m0/m2. Not affected by s16/s40.
+void tstaxl(const UDSPInstruction& opc)
+{
+ // This is probably all wrong.
+ //u8 reg = (opc.hex >> 8) & 0x1;
+ //s16 val = dsp_get_ax_l(reg);
+ //Update_SR_Register16(val);
+}
+
+// ADDARN $arD, $ixS
+// 0000 0000 0001 ssdd
+// Adds indexing register $ixS to an addressing register $arD.
+void addarn(const UDSPInstruction& opc)
+{
+ u8 dreg = opc.hex & 0x3;
+ u8 sreg = (opc.hex >> 2) & 0x3;
+
+ // g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
+
+ dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
+
+ // It is critical for the Zelda ucode that this one wraps correctly.
+}
+
+// NX
+// 1000 -000 xxxx xxxx
+// No operation, but can be extended with extended opcode.
+void nx(const UDSPInstruction& opc)
+{
+ // This opcode is supposed to do nothing - it's used if you want to use
+ // an opcode extension but not do anything. At least according to duddie.
+}
+
+//-------------------------------------------------------------
+// DAR $arD ?
+// 0000 0000 0000 01dd
+// Decrement address register $arD.
+void dar(const UDSPInstruction& opc)
+{
+ dsp_decrement_addr_reg(opc.hex & 0x3);
+}
+
+// IAR $arD ?
+// 0000 0000 0000 10dd
+// Increment address register $arD.
+void iar(const UDSPInstruction& opc)
+{
+ dsp_increment_addr_reg(opc.hex & 0x3);
+}
+
+// SBCLR #I
+// 0001 0011 0000 0iii
+// bit of status register $sr. Bit number is calculated by adding 6 to
+// immediate value I.
+void sbclr(const UDSPInstruction& opc)
+{
+ u8 bit = (opc.hex & 0xff) + 6;
+ g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
+}
+
+// SBSET #I
+// 0001 0010 0000 0iii
+// Set bit of status register $sr. Bit number is calculated by adding 6 to
+// immediate value I.
+void sbset(const UDSPInstruction& opc)
+{
+ u8 bit = (opc.hex & 0xff) + 6;
+ g_dsp.r[DSP_REG_SR] |= (1 << bit);
+}
+
+
+// FIXME inside
+// This is a bunch of flag setters, flipping bits in SR. So far so good,
+// but it's harder to know exactly what effect they have.
+// M0/M2 change the multiplier mode (it can multiply by 2 for free).
+//
+// SET16 changes something very important: see the LRI instruction above.
+// Hermes' demo sets the following defaults:
+// SET40
+// CLR15
+// M0
+void srbith(const UDSPInstruction& opc)
+{
+ switch ((opc.hex >> 8) & 0xf)
+ {
+ // M0 seems to be the default. M2 is used in functions in Zelda
+ // and then reset with M0 at the end. Like the other bits here, it's
+ // done around loops with lots of multiplications.
+ // I've confirmed with DSPSpy that they flip this bit.
+ case 0xa: // M2
+ g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
+ break;
+ case 0xb: // M0
+ g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
+ break;
+
+ // If set, treat multiplicands as unsigned.
+ // If clear, treat them as signed.
+ case 0xc: // CLR15
+ g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
+ break;
+ case 0xd: // SET15
+ g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
+ break;
+
+ // Automatic 40-bit sign extension when loading ACx.M.
+ // 40 seems to be the default.
+ // Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
+ case 0xe: // SET16 (really, clear SR's 0x4000)
+ g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
+ break;
+
+ case 0xf: // SET40 (really, set SR's 0x4000)
+ g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
+ break;
+
+ default:
+ break;
+ }
+}
+
+} // namespace
diff --git a/Source/Core/DSPCore/Src/DspIntMultiplier.cpp b/Source/Core/DSPCore/Src/DspIntMultiplier.cpp
index bf2e29fd62..13167e6fae 100644
--- a/Source/Core/DSPCore/Src/DspIntMultiplier.cpp
+++ b/Source/Core/DSPCore/Src/DspIntMultiplier.cpp
@@ -1,502 +1,502 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-// Additional copyrights go to Duddie and Tratax (c) 2004
-
-
-// Multiplier and product register control
-
-#include "DSPInterpreter.h"
-
-#include "DSPIntCCUtil.h"
-#include "DSPIntUtil.h"
-
-namespace DSPInterpreter {
-
-// Sets prod as a side effect.
-// Only MULX family instructions have unsigned support.
-s64 dsp_multiply_conditional_unsigned(u16 a, u16 b)
-{
- s64 prod;
-#if 0 // Makes games sound horrible. TODO: activate and figure out why - it's been verified through DSPSpy :/
- if (g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)
- prod = (u64)a * (u64)b; // won't overflow 32-bits
- else
-#endif
- prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
-
- // Conditionally multiply by 2.
- if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
- prod <<= 1;
-
- // Store the product, and return it, in case the caller wants to read it.
- dsp_set_long_prod(prod);
- return prod;
-}
-
-// Sets prod as a side effect.
-s64 dsp_multiply(u16 a, u16 b)
-{
- s64 prod;
- prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
-
- // Conditionally multiply by 2.
- if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
- prod <<= 1;
-
- // Store the product, and return it, in case the caller wants to read it.
- dsp_set_long_prod(prod);
- return prod;
-}
-
-s64 dsp_multiply_add(u16 a, u16 b)
-{
- s64 prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
-
- // Conditionally multiply by 2.
- if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
- prod <<= 1;
-
- // Add the original prod value.
- prod += dsp_get_long_prod();
-
- // Store the product, and return it, in case the caller wants to read it.
- dsp_set_long_prod(prod);
- return prod;
-}
-
-s64 dsp_multiply_sub(u16 a, u16 b)
-{
- s64 prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
-
- // Conditionally multiply by 2.
- if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
- prod <<= 1;
-
- // Subtract from the original prod value.
- prod = dsp_get_long_prod() - prod;
-
- // Store the product, and return it, in case the caller wants to read it.
- dsp_set_long_prod(prod);
- return prod;
-}
-
-
-
-// CLRP
-// 1000 0100 xxxx xxxx
-// Clears product register $prod.
-void clrp(const UDSPInstruction& opc)
-{
- // Magic numbers taken from duddie's doc
- // These are probably a bad idea to put here.
- g_dsp.r[0x14] = 0x0000;
- g_dsp.r[0x15] = 0xfff0;
- g_dsp.r[0x16] = 0x00ff;
- g_dsp.r[0x17] = 0x0010;
-}
-
-// MOVP $acD
-// 0110 111d xxxx xxxx
-// Moves multiply product from $prod register to accumulator $acD register.
-void movp(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x1;
-
- s64 prod = dsp_get_long_prod();
- dsp_set_long_acc(dreg, prod);
-
- Update_SR_Register64(prod);
-}
-
-// MOVNP $acD
-// 0111 111d xxxx xxxx
-// Moves negative of multiply product from $prod register to accumulator
-// $acD register.
-void movnp(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x1;
-
- s64 prod = dsp_get_long_prod();
- s64 acc = -prod;
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// ADDPAXZ $acD, $axS
-// 1111 10sd xxxx xxxx
-// Adds secondary accumulator $axS to product register and stores result
-// in accumulator register. Low 16-bits of $acD ($acD.l) are set to 0.
-void addpaxz(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x1;
- u8 sreg = (opc.hex >> 9) & 0x1;
-
- s64 prod = dsp_get_long_prod() & ~0xffff; // hm, should we really mask here?
- s64 ax = dsp_get_long_acx(sreg);
- s64 acc = (prod + ax) & ~0xffff;
-
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// MOVPZ $acD
-// 1111 111d xxxx xxxx
-// Moves multiply product from $prod register to accumulator $acD
-// register and sets $acD.l to 0
-void movpz(const UDSPInstruction& opc)
-{
- u8 dreg = (opc.hex >> 8) & 0x01;
-
- // overwrite acc and clear low part
- s64 prod = dsp_get_long_prod();
- s64 acc = prod & ~0xffff;
- dsp_set_long_acc(dreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-
-// MULC $acS.m, $axT.h
-// 110s t000 xxxx xxxx
-// Multiply mid part of accumulator register $acS.m by high part $axS.h of
-// secondary accumulator $axS (treat them both as signed).
-void mulc(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 11) & 0x1;
- u8 treg = (opc.hex >> 12) & 0x1;
- s64 prod = dsp_multiply(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
- Update_SR_Register64(prod);
-}
-
-// MULCMVZ $acS.m, $axT.h, $acR
-// 110s t01r xxxx xxxx
-// (fixed possible bug in duddie's description, s->t)
-// Multiply mid part of accumulator register $acS.m by high part $axT.h of
-// secondary accumulator $axT (treat them both as signed). Move product
-// register before multiplication to accumulator $acR, set low part of
-// accumulator $acR.l to zero.
-void mulcmvz(const UDSPInstruction& opc)
-{
- s64 TempProd = dsp_get_long_prod();
-
- // update prod
- u8 sreg = (opc.hex >> 12) & 0x1;
- u8 treg = (opc.hex >> 11) & 0x1;
- dsp_multiply(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
-
- // update acc
- u8 rreg = (opc.hex >> 8) & 0x1;
- s64 acc = TempProd & ~0xffff; // clear lower 4 bytes
- dsp_set_long_acc(rreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-// MULCMV $acS.m, $axT.h, $acR
-// 110s t11r xxxx xxxx
-// Multiply mid part of accumulator register $acS.m by high part $axT.h of
-// secondary accumulator $axT (treat them both as signed). Move product
-// register before multiplication to accumulator $acR.
-// possible mistake in duddie's doc axT.h rather than axS.h
-void mulcmv(const UDSPInstruction& opc)
-{
- s64 old_prod = dsp_get_long_prod();
-
- // update prod
- u8 sreg = (opc.hex >> 12) & 0x1;
- u8 treg = (opc.hex >> 11) & 0x1;
- dsp_multiply(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
-
- // update acc
- u8 rreg = (opc.hex >> 8) & 0x1;
- dsp_set_long_acc(rreg, old_prod);
-
- Update_SR_Register64(old_prod);
-}
-
-// MULCAC $acS.m, $axT.h, $acR
-// 110s t10r xxxx xxxx
-// Multiply mid part of accumulator register $acS.m by high part $axS.h of
-// secondary accumulator $axS (treat them both as signed). Add product
-// register before multiplication to accumulator $acR.
-void mulcac(const UDSPInstruction& opc)
-{
- s64 old_prod = dsp_get_long_prod();
-
- // update prod
- u8 sreg = (opc.hex >> 12) & 0x1;
- u8 treg = (opc.hex >> 11) & 0x1;
- dsp_multiply(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
-
- // update acc
- u8 rreg = (opc.hex >> 8) & 0x1;
- s64 acc = old_prod + dsp_get_long_acc(rreg);
- dsp_set_long_acc(rreg, acc);
-
- Update_SR_Register64(acc);
-}
-
-
-// MUL $axS.l, $axS.h
-// 1001 s000 xxxx xxxx
-// Multiply low part $axS.l of secondary accumulator $axS by high part
-// $axS.h of secondary accumulator $axS (treat them both as signed).
-void mul(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 11) & 0x1;
- s64 prod = dsp_multiply(dsp_get_ax_h(sreg), dsp_get_ax_l(sreg));
- // FIXME: no update in duddie's docs
- Update_SR_Register64(prod);
-}
-
-// MULAC $axS.l, $axS.h, $acR
-// 1001 s10r xxxx xxxx
-// Add product register to accumulator register $acR. Multiply low part
-// $axS.l of secondary accumulator $axS by high part $axS.h of secondary
-// accumulator $axS (treat them both as signed).
-void mulac(const UDSPInstruction& opc)
-{
- // add old prod to acc
- u8 rreg = (opc.hex >> 8) & 0x1;
- s64 acR = dsp_get_long_acc(rreg) + dsp_get_long_prod();
- dsp_set_long_acc(rreg, acR);
-
- // calculate new prod
- u8 sreg = (opc.hex >> 11) & 0x1;
- s64 prod = dsp_multiply(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
-
- // FIXME: no update in duddie's docs
- Update_SR_Register64(prod);
-}
-
-// MULMV $axS.l, $axS.h, $acR
-// 1001 s11r xxxx xxxx
-// Move product register to accumulator register $acR. Multiply low part
-// $axS.l of secondary accumulator $axS by high part $axS.h of secondary
-// accumulator $axS (treat them both as signed).
-void mulmv(const UDSPInstruction& opc)
-{
- u8 rreg = (opc.hex >> 8) & 0x1;
- u8 sreg = ((opc.hex >> 11) & 0x1);
- s64 prod = dsp_get_long_prod();
- s64 acc = prod;
- dsp_set_long_acc(rreg, acc);
-
- prod = dsp_multiply(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
- Update_SR_Register64(prod);
-}
-
-// MULMVZ $axS.l, $axS.h, $acR
-// 1001 s01r xxxx xxxx
-// Move product register to accumulator register $acR and clear low part
-// of accumulator register $acR.l. Multiply low part $axS.l of secondary
-// accumulator $axS by high part $axS.h of secondary accumulator $axS (treat
-// them both as signed).
-void mulmvz(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 11) & 0x1;
- u8 rreg = (opc.hex >> 8) & 0x1;
-
- // overwrite acc and clear low part
- s64 prod = dsp_get_long_prod();
- s64 acc = prod & ~0xffff;
- dsp_set_long_acc(rreg, acc);
-
- // math prod
- prod = dsp_multiply(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
- Update_SR_Register64(prod);
-}
-
-// MULX $ax0.S, $ax1.T
-// 101s t000 xxxx xxxx
-// Multiply one part $ax0 by one part $ax1 (treat them both as signed).
-// Part is selected by S and T bits. Zero selects low part, one selects high part.
-void mulx(const UDSPInstruction& opc)
-{
- u8 sreg = ((opc.hex >> 12) & 0x1);
- u8 treg = ((opc.hex >> 11) & 0x1);
-
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
-
- s64 prod = dsp_multiply_conditional_unsigned(val1, val2);
- Update_SR_Register64(prod);
-}
-
-// MULXAC $ax0.S, $ax1.T, $acR
-// 101s t01r xxxx xxxx
-// Add product register to accumulator register $acR. Multiply one part
-// $ax0 by one part $ax1 (treat them both as signed). Part is selected by S and
-// T bits. Zero selects low part, one selects high part.
-void mulxac(const UDSPInstruction& opc)
-{
- // add old prod to acc
- u8 rreg = (opc.hex >> 8) & 0x1;
- s64 acR = dsp_get_long_acc(rreg) + dsp_get_long_prod();
- dsp_set_long_acc(rreg, acR);
-
- // math new prod
- u8 sreg = (opc.hex >> 12) & 0x1;
- u8 treg = (opc.hex >> 11) & 0x1;
-
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
-
- s64 prod = dsp_multiply_conditional_unsigned(val1, val2);
- Update_SR_Register64(prod);
-}
-
-// MULXMV $ax0.S, $ax1.T, $acR
-// 101s t11r xxxx xxxx
-// Move product register to accumulator register $acR. Multiply one part
-// $ax0 by one part $ax1 (treat them both as signed). Part is selected by S and
-// T bits. Zero selects low part, one selects high part.
-void mulxmv(const UDSPInstruction& opc)
-{
- // add old prod to acc
- u8 rreg = ((opc.hex >> 8) & 0x1);
- s64 acR = dsp_get_long_prod();
- dsp_set_long_acc(rreg, acR);
-
- // math new prod
- u8 sreg = (opc.hex >> 12) & 0x1;
- u8 treg = (opc.hex >> 11) & 0x1;
-
- s16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- s16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
-
- s64 prod = dsp_multiply_conditional_unsigned(val1, val2);
- Update_SR_Register64(prod);
-}
-
-// MULXMV $ax0.S, $ax1.T, $acR
-// 101s t01r xxxx xxxx
-// Move product register to accumulator register $acR and clear low part
-// of accumulator register $acR.l. Multiply one part $ax0 by one part $ax1 (treat
-// them both as signed). Part is selected by S and T bits. Zero selects low part,
-// one selects high part.
-void mulxmvz(const UDSPInstruction& opc)
-{
- // overwrite acc and clear low part
- u8 rreg = (opc.hex >> 8) & 0x1;
- s64 prod = dsp_get_long_prod();
- s64 acc = prod & ~0xffff;
- dsp_set_long_acc(rreg, acc);
-
- // math prod
- u8 sreg = (opc.hex >> 12) & 0x1;
- u8 treg = (opc.hex >> 11) & 0x1;
-
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
-
- prod = dsp_multiply_conditional_unsigned(val1, val2);
- Update_SR_Register64(prod);
-}
-
-// MADDX ax0.S ax1.T
-// 1110 00st xxxx xxxx
-// Multiply one part of secondary accumulator $ax0 (selected by S) by
-// one part of secondary accumulator $ax1 (selected by T) (treat them both as
-// signed) and add result to product register.
-void maddx(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 9) & 0x1;
- u8 treg = (opc.hex >> 8) & 0x1;
-
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
-
- s64 prod = dsp_multiply_add(val1, val2);
- Update_SR_Register64(prod);
-}
-
-// MSUBX $(0x18+S*2), $(0x19+T*2)
-// 1110 01st xxxx xxxx
-// Multiply one part of secondary accumulator $ax0 (selected by S) by
-// one part of secondary accumulator $ax1 (selected by T) (treat them both as
-// signed) and subtract result from product register.
-void msubx(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 9) & 0x1;
- u8 treg = (opc.hex >> 8) & 0x1;
-
- u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
- u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
-
- s64 prod = dsp_multiply_sub(val1, val2);
- Update_SR_Register64(prod);
-}
-
-// MADDC $acS.m, $axT.h
-// 1110 10st xxxx xxxx
-// Multiply middle part of accumulator $acS.m by high part of secondary
-// accumulator $axT.h (treat them both as signed) and add result to product
-// register.
-void maddc(const UDSPInstruction& opc)
-{
- u32 sreg = (opc.hex >> 9) & 0x1;
- u32 treg = (opc.hex >> 8) & 0x1;
-
- s64 prod = dsp_multiply_add(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
- Update_SR_Register64(prod);
-}
-
-// MSUBC $acS.m, $axT.h
-// 1110 11st xxxx xxxx
-// Multiply middle part of accumulator $acS.m by high part of secondary
-// accumulator $axT.h (treat them both as signed) and subtract result from
-// product register.
-void msubc(const UDSPInstruction& opc)
-{
- u32 sreg = (opc.hex >> 9) & 0x1;
- u32 treg = (opc.hex >> 8) & 0x1;
-
- s64 prod = dsp_multiply_sub(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
- Update_SR_Register64(prod);
-}
-
-// MADD $axS.l, $axS.h
-// 1111 001s xxxx xxxx
-// Multiply low part $axS.l of secondary accumulator $axS by high part
-// $axS.h of secondary accumulator $axS (treat them both as signed) and add
-// result to product register.
-void madd(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 8) & 0x1;
-
- s64 prod = dsp_multiply_add(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
- Update_SR_Register64(prod);
-}
-
-// MSUB $axS.l, $axS.h
-// 1111 011s xxxx xxxx
-// Multiply low part $axS.l of secondary accumulator $axS by high part
-// $axS.h of secondary accumulator $axS (treat them both as signed) and
-// subtract result from product register.
-void msub(const UDSPInstruction& opc)
-{
- u8 sreg = (opc.hex >> 8) & 0x1;
-
- s64 prod = dsp_multiply_sub(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
- Update_SR_Register64(prod);
-}
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+// Additional copyrights go to Duddie and Tratax (c) 2004
+
+
+// Multiplier and product register control
+
+#include "DSPInterpreter.h"
+
+#include "DSPIntCCUtil.h"
+#include "DSPIntUtil.h"
+
+namespace DSPInterpreter {
+
+// Sets prod as a side effect.
+// Only MULX family instructions have unsigned support.
+s64 dsp_multiply_conditional_unsigned(u16 a, u16 b)
+{
+ s64 prod;
+#if 0 // Makes games sound horrible. TODO: activate and figure out why - it's been verified through DSPSpy :/
+ if (g_dsp.r[DSP_REG_SR] & SR_MUL_UNSIGNED)
+ prod = (u64)a * (u64)b; // won't overflow 32-bits
+ else
+#endif
+ prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
+
+ // Conditionally multiply by 2.
+ if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
+ prod <<= 1;
+
+ // Store the product, and return it, in case the caller wants to read it.
+ dsp_set_long_prod(prod);
+ return prod;
+}
+
+// Sets prod as a side effect.
+s64 dsp_multiply(u16 a, u16 b)
+{
+ s64 prod;
+ prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
+
+ // Conditionally multiply by 2.
+ if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
+ prod <<= 1;
+
+ // Store the product, and return it, in case the caller wants to read it.
+ dsp_set_long_prod(prod);
+ return prod;
+}
+
+s64 dsp_multiply_add(u16 a, u16 b)
+{
+ s64 prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
+
+ // Conditionally multiply by 2.
+ if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
+ prod <<= 1;
+
+ // Add the original prod value.
+ prod += dsp_get_long_prod();
+
+ // Store the product, and return it, in case the caller wants to read it.
+ dsp_set_long_prod(prod);
+ return prod;
+}
+
+s64 dsp_multiply_sub(u16 a, u16 b)
+{
+ s64 prod = (s32)(s16)a * (s32)(s16)b; // won't overflow 32-bits
+
+ // Conditionally multiply by 2.
+ if ((g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) == 0)
+ prod <<= 1;
+
+ // Subtract from the original prod value.
+ prod = dsp_get_long_prod() - prod;
+
+ // Store the product, and return it, in case the caller wants to read it.
+ dsp_set_long_prod(prod);
+ return prod;
+}
+
+
+
+// CLRP
+// 1000 0100 xxxx xxxx
+// Clears product register $prod.
+void clrp(const UDSPInstruction& opc)
+{
+ // Magic numbers taken from duddie's doc
+ // These are probably a bad idea to put here.
+ g_dsp.r[0x14] = 0x0000;
+ g_dsp.r[0x15] = 0xfff0;
+ g_dsp.r[0x16] = 0x00ff;
+ g_dsp.r[0x17] = 0x0010;
+}
+
+// MOVP $acD
+// 0110 111d xxxx xxxx
+// Moves multiply product from $prod register to accumulator $acD register.
+void movp(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x1;
+
+ s64 prod = dsp_get_long_prod();
+ dsp_set_long_acc(dreg, prod);
+
+ Update_SR_Register64(prod);
+}
+
+// MOVNP $acD
+// 0111 111d xxxx xxxx
+// Moves negative of multiply product from $prod register to accumulator
+// $acD register.
+void movnp(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x1;
+
+ s64 prod = dsp_get_long_prod();
+ s64 acc = -prod;
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// ADDPAXZ $acD, $axS
+// 1111 10sd xxxx xxxx
+// Adds secondary accumulator $axS to product register and stores result
+// in accumulator register. Low 16-bits of $acD ($acD.l) are set to 0.
+void addpaxz(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x1;
+ u8 sreg = (opc.hex >> 9) & 0x1;
+
+ s64 prod = dsp_get_long_prod() & ~0xffff; // hm, should we really mask here?
+ s64 ax = dsp_get_long_acx(sreg);
+ s64 acc = (prod + ax) & ~0xffff;
+
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// MOVPZ $acD
+// 1111 111d xxxx xxxx
+// Moves multiply product from $prod register to accumulator $acD
+// register and sets $acD.l to 0
+void movpz(const UDSPInstruction& opc)
+{
+ u8 dreg = (opc.hex >> 8) & 0x01;
+
+ // overwrite acc and clear low part
+ s64 prod = dsp_get_long_prod();
+ s64 acc = prod & ~0xffff;
+ dsp_set_long_acc(dreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+
+// MULC $acS.m, $axT.h
+// 110s t000 xxxx xxxx
+// Multiply mid part of accumulator register $acS.m by high part $axS.h of
+// secondary accumulator $axS (treat them both as signed).
+void mulc(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 11) & 0x1;
+ u8 treg = (opc.hex >> 12) & 0x1;
+ s64 prod = dsp_multiply(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
+ Update_SR_Register64(prod);
+}
+
+// MULCMVZ $acS.m, $axT.h, $acR
+// 110s t01r xxxx xxxx
+// (fixed possible bug in duddie's description, s->t)
+// Multiply mid part of accumulator register $acS.m by high part $axT.h of
+// secondary accumulator $axT (treat them both as signed). Move product
+// register before multiplication to accumulator $acR, set low part of
+// accumulator $acR.l to zero.
+void mulcmvz(const UDSPInstruction& opc)
+{
+ s64 TempProd = dsp_get_long_prod();
+
+ // update prod
+ u8 sreg = (opc.hex >> 12) & 0x1;
+ u8 treg = (opc.hex >> 11) & 0x1;
+ dsp_multiply(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
+
+ // update acc
+ u8 rreg = (opc.hex >> 8) & 0x1;
+ s64 acc = TempProd & ~0xffff; // clear lower 4 bytes
+ dsp_set_long_acc(rreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+// MULCMV $acS.m, $axT.h, $acR
+// 110s t11r xxxx xxxx
+// Multiply mid part of accumulator register $acS.m by high part $axT.h of
+// secondary accumulator $axT (treat them both as signed). Move product
+// register before multiplication to accumulator $acR.
+// possible mistake in duddie's doc axT.h rather than axS.h
+void mulcmv(const UDSPInstruction& opc)
+{
+ s64 old_prod = dsp_get_long_prod();
+
+ // update prod
+ u8 sreg = (opc.hex >> 12) & 0x1;
+ u8 treg = (opc.hex >> 11) & 0x1;
+ dsp_multiply(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
+
+ // update acc
+ u8 rreg = (opc.hex >> 8) & 0x1;
+ dsp_set_long_acc(rreg, old_prod);
+
+ Update_SR_Register64(old_prod);
+}
+
+// MULCAC $acS.m, $axT.h, $acR
+// 110s t10r xxxx xxxx
+// Multiply mid part of accumulator register $acS.m by high part $axS.h of
+// secondary accumulator $axS (treat them both as signed). Add product
+// register before multiplication to accumulator $acR.
+void mulcac(const UDSPInstruction& opc)
+{
+ s64 old_prod = dsp_get_long_prod();
+
+ // update prod
+ u8 sreg = (opc.hex >> 12) & 0x1;
+ u8 treg = (opc.hex >> 11) & 0x1;
+ dsp_multiply(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
+
+ // update acc
+ u8 rreg = (opc.hex >> 8) & 0x1;
+ s64 acc = old_prod + dsp_get_long_acc(rreg);
+ dsp_set_long_acc(rreg, acc);
+
+ Update_SR_Register64(acc);
+}
+
+
+// MUL $axS.l, $axS.h
+// 1001 s000 xxxx xxxx
+// Multiply low part $axS.l of secondary accumulator $axS by high part
+// $axS.h of secondary accumulator $axS (treat them both as signed).
+void mul(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 11) & 0x1;
+ s64 prod = dsp_multiply(dsp_get_ax_h(sreg), dsp_get_ax_l(sreg));
+ // FIXME: no update in duddie's docs
+ Update_SR_Register64(prod);
+}
+
+// MULAC $axS.l, $axS.h, $acR
+// 1001 s10r xxxx xxxx
+// Add product register to accumulator register $acR. Multiply low part
+// $axS.l of secondary accumulator $axS by high part $axS.h of secondary
+// accumulator $axS (treat them both as signed).
+void mulac(const UDSPInstruction& opc)
+{
+ // add old prod to acc
+ u8 rreg = (opc.hex >> 8) & 0x1;
+ s64 acR = dsp_get_long_acc(rreg) + dsp_get_long_prod();
+ dsp_set_long_acc(rreg, acR);
+
+ // calculate new prod
+ u8 sreg = (opc.hex >> 11) & 0x1;
+ s64 prod = dsp_multiply(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
+
+ // FIXME: no update in duddie's docs
+ Update_SR_Register64(prod);
+}
+
+// MULMV $axS.l, $axS.h, $acR
+// 1001 s11r xxxx xxxx
+// Move product register to accumulator register $acR. Multiply low part
+// $axS.l of secondary accumulator $axS by high part $axS.h of secondary
+// accumulator $axS (treat them both as signed).
+void mulmv(const UDSPInstruction& opc)
+{
+ u8 rreg = (opc.hex >> 8) & 0x1;
+ u8 sreg = ((opc.hex >> 11) & 0x1);
+ s64 prod = dsp_get_long_prod();
+ s64 acc = prod;
+ dsp_set_long_acc(rreg, acc);
+
+ prod = dsp_multiply(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
+ Update_SR_Register64(prod);
+}
+
+// MULMVZ $axS.l, $axS.h, $acR
+// 1001 s01r xxxx xxxx
+// Move product register to accumulator register $acR and clear low part
+// of accumulator register $acR.l. Multiply low part $axS.l of secondary
+// accumulator $axS by high part $axS.h of secondary accumulator $axS (treat
+// them both as signed).
+void mulmvz(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 11) & 0x1;
+ u8 rreg = (opc.hex >> 8) & 0x1;
+
+ // overwrite acc and clear low part
+ s64 prod = dsp_get_long_prod();
+ s64 acc = prod & ~0xffff;
+ dsp_set_long_acc(rreg, acc);
+
+ // math prod
+ prod = dsp_multiply(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
+ Update_SR_Register64(prod);
+}
+
+// MULX $ax0.S, $ax1.T
+// 101s t000 xxxx xxxx
+// Multiply one part $ax0 by one part $ax1 (treat them both as signed).
+// Part is selected by S and T bits. Zero selects low part, one selects high part.
+void mulx(const UDSPInstruction& opc)
+{
+ u8 sreg = ((opc.hex >> 12) & 0x1);
+ u8 treg = ((opc.hex >> 11) & 0x1);
+
+ u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
+ u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
+
+ s64 prod = dsp_multiply_conditional_unsigned(val1, val2);
+ Update_SR_Register64(prod);
+}
+
+// MULXAC $ax0.S, $ax1.T, $acR
+// 101s t01r xxxx xxxx
+// Add product register to accumulator register $acR. Multiply one part
+// $ax0 by one part $ax1 (treat them both as signed). Part is selected by S and
+// T bits. Zero selects low part, one selects high part.
+void mulxac(const UDSPInstruction& opc)
+{
+ // add old prod to acc
+ u8 rreg = (opc.hex >> 8) & 0x1;
+ s64 acR = dsp_get_long_acc(rreg) + dsp_get_long_prod();
+ dsp_set_long_acc(rreg, acR);
+
+ // math new prod
+ u8 sreg = (opc.hex >> 12) & 0x1;
+ u8 treg = (opc.hex >> 11) & 0x1;
+
+ u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
+ u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
+
+ s64 prod = dsp_multiply_conditional_unsigned(val1, val2);
+ Update_SR_Register64(prod);
+}
+
+// MULXMV $ax0.S, $ax1.T, $acR
+// 101s t11r xxxx xxxx
+// Move product register to accumulator register $acR. Multiply one part
+// $ax0 by one part $ax1 (treat them both as signed). Part is selected by S and
+// T bits. Zero selects low part, one selects high part.
+void mulxmv(const UDSPInstruction& opc)
+{
+ // add old prod to acc
+ u8 rreg = ((opc.hex >> 8) & 0x1);
+ s64 acR = dsp_get_long_prod();
+ dsp_set_long_acc(rreg, acR);
+
+ // math new prod
+ u8 sreg = (opc.hex >> 12) & 0x1;
+ u8 treg = (opc.hex >> 11) & 0x1;
+
+ s16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
+ s16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
+
+ s64 prod = dsp_multiply_conditional_unsigned(val1, val2);
+ Update_SR_Register64(prod);
+}
+
+// MULXMV $ax0.S, $ax1.T, $acR
+// 101s t01r xxxx xxxx
+// Move product register to accumulator register $acR and clear low part
+// of accumulator register $acR.l. Multiply one part $ax0 by one part $ax1 (treat
+// them both as signed). Part is selected by S and T bits. Zero selects low part,
+// one selects high part.
+void mulxmvz(const UDSPInstruction& opc)
+{
+ // overwrite acc and clear low part
+ u8 rreg = (opc.hex >> 8) & 0x1;
+ s64 prod = dsp_get_long_prod();
+ s64 acc = prod & ~0xffff;
+ dsp_set_long_acc(rreg, acc);
+
+ // math prod
+ u8 sreg = (opc.hex >> 12) & 0x1;
+ u8 treg = (opc.hex >> 11) & 0x1;
+
+ u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
+ u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
+
+ prod = dsp_multiply_conditional_unsigned(val1, val2);
+ Update_SR_Register64(prod);
+}
+
+// MADDX ax0.S ax1.T
+// 1110 00st xxxx xxxx
+// Multiply one part of secondary accumulator $ax0 (selected by S) by
+// one part of secondary accumulator $ax1 (selected by T) (treat them both as
+// signed) and add result to product register.
+void maddx(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 9) & 0x1;
+ u8 treg = (opc.hex >> 8) & 0x1;
+
+ u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
+ u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
+
+ s64 prod = dsp_multiply_add(val1, val2);
+ Update_SR_Register64(prod);
+}
+
+// MSUBX $(0x18+S*2), $(0x19+T*2)
+// 1110 01st xxxx xxxx
+// Multiply one part of secondary accumulator $ax0 (selected by S) by
+// one part of secondary accumulator $ax1 (selected by T) (treat them both as
+// signed) and subtract result from product register.
+void msubx(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 9) & 0x1;
+ u8 treg = (opc.hex >> 8) & 0x1;
+
+ u16 val1 = (sreg == 0) ? dsp_get_ax_l(0) : dsp_get_ax_h(0);
+ u16 val2 = (treg == 0) ? dsp_get_ax_l(1) : dsp_get_ax_h(1);
+
+ s64 prod = dsp_multiply_sub(val1, val2);
+ Update_SR_Register64(prod);
+}
+
+// MADDC $acS.m, $axT.h
+// 1110 10st xxxx xxxx
+// Multiply middle part of accumulator $acS.m by high part of secondary
+// accumulator $axT.h (treat them both as signed) and add result to product
+// register.
+void maddc(const UDSPInstruction& opc)
+{
+ u32 sreg = (opc.hex >> 9) & 0x1;
+ u32 treg = (opc.hex >> 8) & 0x1;
+
+ s64 prod = dsp_multiply_add(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
+ Update_SR_Register64(prod);
+}
+
+// MSUBC $acS.m, $axT.h
+// 1110 11st xxxx xxxx
+// Multiply middle part of accumulator $acS.m by high part of secondary
+// accumulator $axT.h (treat them both as signed) and subtract result from
+// product register.
+void msubc(const UDSPInstruction& opc)
+{
+ u32 sreg = (opc.hex >> 9) & 0x1;
+ u32 treg = (opc.hex >> 8) & 0x1;
+
+ s64 prod = dsp_multiply_sub(dsp_get_acc_m(sreg), dsp_get_ax_h(treg));
+ Update_SR_Register64(prod);
+}
+
+// MADD $axS.l, $axS.h
+// 1111 001s xxxx xxxx
+// Multiply low part $axS.l of secondary accumulator $axS by high part
+// $axS.h of secondary accumulator $axS (treat them both as signed) and add
+// result to product register.
+void madd(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 8) & 0x1;
+
+ s64 prod = dsp_multiply_add(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
+ Update_SR_Register64(prod);
+}
+
+// MSUB $axS.l, $axS.h
+// 1111 011s xxxx xxxx
+// Multiply low part $axS.l of secondary accumulator $axS by high part
+// $axS.h of secondary accumulator $axS (treat them both as signed) and
+// subtract result from product register.
+void msub(const UDSPInstruction& opc)
+{
+ u8 sreg = (opc.hex >> 8) & 0x1;
+
+ s64 prod = dsp_multiply_sub(dsp_get_ax_l(sreg), dsp_get_ax_h(sreg));
+ Update_SR_Register64(prod);
+}
+
+} // namespace
diff --git a/Source/Core/DSPCore/Src/LabelMap.cpp b/Source/Core/DSPCore/Src/LabelMap.cpp
index 6d3a475857..2765d302b9 100644
--- a/Source/Core/DSPCore/Src/LabelMap.cpp
+++ b/Source/Core/DSPCore/Src/LabelMap.cpp
@@ -1,85 +1,85 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "LabelMap.h"
-#include "DSPTables.h"
-
-LabelMap::LabelMap()
-{
-
-}
-
-void LabelMap::RegisterDefaults()
-{
- for (int i = 0; i < 0x24; i++)
- {
- if (regnames[i].name)
- RegisterLabel(regnames[i].name, regnames[i].addr);
- }
- for (int i = 0; i < (int)pdlabels_size; i++)
- {
- if (pdlabels[i].name)
- RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
- }
-}
-
-void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
-{
- u16 old_value;
- if (GetLabelValue(label, &old_value) && old_value != lval)
- {
- printf("WARNING: Redefined label %s to %04x - old value %04x\n",
- label.c_str(), lval, old_value);
- DeleteLabel(label);
- }
- labels.push_back(label_t(label, lval, type));
-}
-
-void LabelMap::DeleteLabel(const std::string &label)
-{
- for (std::vector<label_t>::iterator iter = labels.begin();
- iter != labels.end(); ++iter)
- {
- if (!label.compare(iter->name))
- {
- labels.erase(iter);
- return;
- }
- }
-}
-
-bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
-{
- for (u32 i = 0; i < labels.size(); i++)
- {
- if (!label.compare(labels[i].name))
- {
- if (type & labels[i].type) {
- *value = labels[i].addr;
- return true;
- } else {
- printf("WARNING: Wrong label type requested. %s\n", label.c_str());
- }
- }
- }
- return false;
-}
-
-void LabelMap::Clear()
-{
- labels.clear();
-}
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "LabelMap.h"
+#include "DSPTables.h"
+
+LabelMap::LabelMap()
+{
+
+}
+
+void LabelMap::RegisterDefaults()
+{
+ for (int i = 0; i < 0x24; i++)
+ {
+ if (regnames[i].name)
+ RegisterLabel(regnames[i].name, regnames[i].addr);
+ }
+ for (int i = 0; i < (int)pdlabels_size; i++)
+ {
+ if (pdlabels[i].name)
+ RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
+ }
+}
+
+void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
+{
+ u16 old_value;
+ if (GetLabelValue(label, &old_value) && old_value != lval)
+ {
+ printf("WARNING: Redefined label %s to %04x - old value %04x\n",
+ label.c_str(), lval, old_value);
+ DeleteLabel(label);
+ }
+ labels.push_back(label_t(label, lval, type));
+}
+
+void LabelMap::DeleteLabel(const std::string &label)
+{
+ for (std::vector<label_t>::iterator iter = labels.begin();
+ iter != labels.end(); ++iter)
+ {
+ if (!label.compare(iter->name))
+ {
+ labels.erase(iter);
+ return;
+ }
+ }
+}
+
+bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
+{
+ for (u32 i = 0; i < labels.size(); i++)
+ {
+ if (!label.compare(labels[i].name))
+ {
+ if (type & labels[i].type) {
+ *value = labels[i].addr;
+ return true;
+ } else {
+ printf("WARNING: Wrong label type requested. %s\n", label.c_str());
+ }
+ }
+ }
+ return false;
+}
+
+void LabelMap::Clear()
+{
+ labels.clear();
+}
diff --git a/Source/Core/DSPCore/Src/LabelMap.h b/Source/Core/DSPCore/Src/LabelMap.h
index 3b37712204..6fceef7347 100644
--- a/Source/Core/DSPCore/Src/LabelMap.h
+++ b/Source/Core/DSPCore/Src/LabelMap.h
@@ -1,55 +1,55 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _LABELMAP_H
-#define _LABELMAP_H
-
-#include <string>
-#include <vector>
-
-#include "Common.h"
-
-enum LabelType
-{
- LABEL_IADDR = 1, // Jump addresses, etc
- LABEL_DADDR = 2, // Data addresses, etc
- LABEL_VALUE = 4,
- LABEL_ANY = 0xFF,
-};
-
-class LabelMap
-{
- struct label_t
- {
- label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
- std::string name;
- s32 addr;
- LabelType type;
- };
- std::vector<label_t> labels;
-
-public:
- LabelMap();
- ~LabelMap() { }
- void RegisterDefaults();
- void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
- void DeleteLabel(const std::string &label);
- bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
- void Clear();
-};
-
-#endif // _LABELMAP_H
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _LABELMAP_H
+#define _LABELMAP_H
+
+#include <string>
+#include <vector>
+
+#include "Common.h"
+
+enum LabelType
+{
+ LABEL_IADDR = 1, // Jump addresses, etc
+ LABEL_DADDR = 2, // Data addresses, etc
+ LABEL_VALUE = 4,
+ LABEL_ANY = 0xFF,
+};
+
+class LabelMap
+{
+ struct label_t
+ {
+ label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
+ std::string name;
+ s32 addr;
+ LabelType type;
+ };
+ std::vector<label_t> labels;
+
+public:
+ LabelMap();
+ ~LabelMap() { }
+ void RegisterDefaults();
+ void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
+ void DeleteLabel(const std::string &label);
+ bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
+ void Clear();
+};
+
+#endif // _LABELMAP_H
diff --git a/Source/Core/DSPCore/Src/assemble.cpp b/Source/Core/DSPCore/Src/assemble.cpp
index 2f14d70381..7516b4182f 100644
--- a/Source/Core/DSPCore/Src/assemble.cpp
+++ b/Source/Core/DSPCore/Src/assemble.cpp
@@ -1,1016 +1,1016 @@
-/*====================================================================
-
-$Id: assemble.cpp,v 1.3 2008-11-11 01:04:26 wntrmute Exp $
-
-project: GameCube DSP Tool (gcdsp)
-mail: duddie@walla.com
-
-Copyright (c) 2005 Duddie
-
-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; either version 2
-of the License, or (at your option) any later version.
-
-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 for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-Revision 1.4 2008/10/04 10:30:00 Hermes
-added function to export the code to .h file
-added support for '/ *' '* /' and '//' for comentaries
-added some sintax detection when use registers
-
-$Log: not supported by cvs2svn $
-Revision 1.2 2005/09/14 02:19:29 wntrmute
-added header guards
-use standard main function
-
-Revision 1.1 2005/08/24 22:13:34 wntrmute
-Initial import
-
-
-====================================================================*/
-
-#include <cstdio>
-#include <cstdlib>
-
-#include <map>
-#include <iostream>
-#include <fstream>
-
-#include "Common.h"
-#include "FileUtil.h"
-#include "DSPInterpreter.h"
-#include "DSPTables.h"
-#include "disassemble.h"
-#include "assemble.h"
-
-static const char *err_string[] =
-{
- "",
- "Unknown Error",
- "Unknown opcode",
- "Not enough parameters",
- "Too many parameters",
- "Wrong parameter",
- "Expected parameter of type 'string'",
- "Expected parameter of type 'value'",
- "Expected parameter of type 'register'",
- "Expected parameter of type 'memory pointer'",
- "Expected parameter of type 'immediate'",
- "Incorrect binary value",
- "Incorrect hexadecimal value",
- "Incorrect decimal value",
- "Label already exists",
- "Label not defined",
- "No matching brackets",
- "This opcode cannot be extended",
- "Given extending params for non extensible opcode",
- "Wrong parameter: must be accumulator register",
- "Wrong parameter: must be mid accumulator register",
- "Invalid register",
- "Number out of range"
-};
-
-DSPAssembler::DSPAssembler(const AssemblerSettings &settings) :
- m_cur_addr(0),
- m_cur_pass(0),
- m_current_param(0),
- settings_(settings),
- gdg_buffer(NULL)
-{
-}
-
-DSPAssembler::~DSPAssembler()
-{
- if(gdg_buffer)
- free(gdg_buffer);
-}
-
-bool DSPAssembler::Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers)
-{
- if (line_numbers)
- line_numbers->clear();
- const char *fname = "tmp.asm";
- if (!File::WriteStringToFile(true, text, fname))
- return false;
- InitPass(1);
- if (!AssembleFile(fname, 1))
- return false;
-
- // We now have the size of the output buffer
- if (m_totalSize > 0)
- {
- gdg_buffer = (char *)malloc(m_totalSize * sizeof(u16) + 4);
- if(!gdg_buffer)
- return false;
-
- memset(gdg_buffer, 0, m_totalSize * sizeof(u16));
- } else
- return false;
-
- InitPass(2);
- if (!AssembleFile(fname, 2))
- return false;
-
- code.resize(m_totalSize);
- for (int i = 0; i < m_totalSize; i++) {
- code[i] = *(u16 *)(gdg_buffer + i * 2);
- }
-
- if(gdg_buffer) {
- free(gdg_buffer);
- gdg_buffer = NULL;
- }
-
- last_error_str = "(no errors)";
- last_error = ERR_OK;
-
- return true;
-}
-
-void DSPAssembler::ShowError(err_t err_code, const char *extra_info)
-{
- failed = true;
- char error_buffer[1024];
- char *buf_ptr = error_buffer;
- buf_ptr += sprintf(buf_ptr, "%i : %s ", code_line, cur_line.c_str());
- if (!extra_info)
- extra_info = "-";
-
- if (m_current_param == 0)
- buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d : %s\n", err_string[err_code], code_line, extra_info);
- else
- buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d Param: %d : %s\n",
- err_string[err_code], code_line, m_current_param, extra_info);
- last_error_str = error_buffer;
- last_error = err_code;
-}
-
-char *skip_spaces(char *ptr)
-{
- while (*ptr == ' ')
- ptr++;
- return ptr;
-}
-
-const char *skip_spaces(const char *ptr)
-{
- while (*ptr == ' ')
- ptr++;
- return ptr;
-}
-
-// Parse a standalone value - it can be a number in one of several formats or a label.
-s32 DSPAssembler::ParseValue(const char *str)
-{
- bool negative = false;
- s32 val = 0;
- const char *ptr = str;
-
- if (ptr[0] == '#')
- {
- ptr++;
- negative = true; // Wow! Double # (needed one to get in here) negates???
- }
- if (ptr[0] == '-')
- {
- ptr++;
- negative = true;
- }
- if (ptr[0] == '0')
- {
- if (ptr[1] >= '0' && ptr[1] <= '9')
- {
- for (int i = 0; ptr[i] != 0; i++)
- {
- val *= 10;
- if (ptr[i] >= '0' && ptr[i] <= '9')
- val += ptr[i] - '0';
- else
- ShowError(ERR_INCORRECT_DEC, str);
- }
- }
- else
- {
- switch (ptr[1])
- {
- case 'X': // hex
- for (int i = 2 ; ptr[i] != 0 ; i++)
- {
- val <<= 4;
- if (ptr[i] >= 'a' && ptr[i] <= 'f')
- val += (ptr[i]-'a'+10);
- else if (ptr[i] >= 'A' && ptr[i] <= 'F')
- val += (ptr[i]-'A'+10);
- else if (ptr[i] >= '0' && ptr[i] <= '9')
- val += (ptr[i] - '0');
- else
- ShowError(ERR_INCORRECT_HEX, str);
- }
- break;
- case '\'': // binary
- for (int i = 2; ptr[i] != 0; i++)
- {
- val *=2;
- if(ptr[i] >= '0' && ptr[i] <= '1')
- val += ptr[i] - '0';
- else
- ShowError(ERR_INCORRECT_BIN, str);
- }
- break;
- default:
- // value is 0 or error
- val = 0;
- break;
- }
- }
- }
- else
- {
- // Symbol starts with a digit - it's a dec number.
- if (ptr[0] >= '0' && ptr[0] <= '9')
- {
- for (int i = 0; ptr[i] != 0; i++)
- {
- val *= 10;
- if (ptr[i] >= '0' && ptr[i] <= '9')
- val += ptr[i] - '0';
- else
- ShowError(ERR_INCORRECT_DEC, str);
- }
- }
- else // Everything else is a label.
- {
- // Lookup label
- u16 value;
- if (labels.GetLabelValue(ptr, &value))
- return value;
- if (m_cur_pass == 2)
- ShowError(ERR_UNKNOWN_LABEL, str);
- }
- }
- if (negative)
- return -val;
- return val;
-}
-
-// Modifies both src and dst!
-// What does it do, really??
-char *DSPAssembler::FindBrackets(char *src, char *dst)
-{
- s32 len = (s32) strlen(src);
- s32 first = -1;
- s32 count = 0;
- s32 i, j;
- j = 0;
- for (i = 0 ; i < len ; i++)
- {
- if (src[i] == '(')
- {
- if (first < 0)
- {
- count = 1;
- src[i] = 0x0;
- first = i;
- }
- else
- {
- count++;
- dst[j++] = src[i];
- }
- }
- else if (src[i] == ')')
- {
- if (--count == 0)
- {
- dst[j] = 0;
- return &src[i+1];
- }
- else
- {
- dst[j++] = src[i];
- }
- }
- else
- {
- if (first >= 0)
- dst[j++] = src[i];
- }
- }
- if (count)
- ShowError(ERR_NO_MATCHING_BRACKETS);
- return NULL;
-}
-
-// Bizarre in-place expression evaluator.
-u32 DSPAssembler::ParseExpression(const char *ptr)
-{
- char *pbuf;
- s32 val = 0;
-
- char *d_buffer = (char *)malloc(1024);
- char *s_buffer = (char *)malloc(1024);
- strcpy(s_buffer, ptr);
-
- while ((pbuf = FindBrackets(s_buffer, d_buffer)) != NULL)
- {
- val = ParseExpression(d_buffer);
- sprintf(d_buffer, "%s%d%s", s_buffer, val, pbuf);
- strcpy(s_buffer, d_buffer);
- }
-
- int j = 0;
- for (int i = 0; i < ((s32)strlen(s_buffer) + 1) ; i++)
- {
- char c = s_buffer[i];
- if (c != ' ')
- d_buffer[j++] = c;
- }
-
- for (int i = 0; i < ((s32)strlen(d_buffer) + 1) ; i++)
- {
- char c = d_buffer[i];
- if (c == '-')
- {
- if (i == 0)
- c = '#';
- else
- {
- switch (d_buffer[i - 1])
- {
- case '/':
- case '%':
- case '*':
- c = '#';
- }
- }
- }
- d_buffer[i] = c;
- }
-
- while ((pbuf = strstr(d_buffer, "+")) != NULL)
- {
- *pbuf = 0x0;
- val = ParseExpression(d_buffer) + ParseExpression(pbuf+1);
- sprintf(d_buffer, "%d", val);
- }
-
- while ((pbuf = strstr(d_buffer, "-")) != NULL)
- {
- *pbuf = 0x0;
- val = ParseExpression(d_buffer) - ParseExpression(pbuf+1);
- if (val < 0)
- {
- val = 0x10000 + (val & 0xffff); // ATTENTION: avoid a terrible bug!!! number cannot write with '-' in sprintf
- fprintf(stderr, "WARNING: Number Underflow at Line: %d \n", code_line);
- }
- sprintf(d_buffer, "%d", val);
- }
-
- while ((pbuf = strstr(d_buffer, "*")) != NULL)
- {
- *pbuf = 0x0;
- val = ParseExpression(d_buffer) * ParseExpression(pbuf+1);
- sprintf(d_buffer, "%d", val);
- }
-
- while ((pbuf = strstr(d_buffer, "/")) != NULL)
- {
- *pbuf = 0x0;
- val = ParseExpression(d_buffer) / ParseExpression(pbuf+1);
- sprintf(d_buffer, "%d", val);
- }
-
- while ((pbuf = strstr(d_buffer, "|")) != NULL)
- {
- *pbuf = 0x0;
- val = ParseExpression(d_buffer) | ParseExpression(pbuf+1);
- sprintf(d_buffer, "%d", val);
- }
-
- while ((pbuf = strstr(d_buffer, "&")) != NULL)
- {
- *pbuf = 0x0;
- val = ParseExpression(d_buffer) & ParseExpression(pbuf+1);
- sprintf(d_buffer, "%d", val);
- }
-
- val = ParseValue(d_buffer);
- free(d_buffer);
- free(s_buffer);
- return val;
-}
-
-// Destroys parstr
-u32 DSPAssembler::GetParams(char *parstr, param_t *par)
-{
- u32 count = 0;
- char *tmpstr = skip_spaces(parstr);
- tmpstr = strtok(tmpstr, ",\x00");
- for (int i = 0; i < 10; i++)
- {
- if (tmpstr == NULL)
- break;
- tmpstr = skip_spaces(tmpstr);
- if (strlen(tmpstr) == 0)
- break;
- if (tmpstr)
- count++;
- else
- break;
-
- par[i].type = P_NONE;
- switch (tmpstr[0])
- {
- case '"':
- par[i].str = strtok(tmpstr, "\"");
- par[i].type = P_STR;
- break;
- case '#':
- par[i].val = ParseExpression(tmpstr + 1);
- par[i].type = P_IMM;
- break;
- case '@':
- if (tmpstr[1] == '$')
- {
- par[i].val = ParseExpression(tmpstr + 2);
- par[i].type = P_PRG;
- }
- else
- {
- par[i].val = ParseExpression(tmpstr + 1);
- par[i].type = P_MEM;
- }
- break;
- case '$':
- par[i].val = ParseExpression(tmpstr + 1);
- par[i].type = P_REG;
- break;
-
- default:
- par[i].val = ParseExpression(tmpstr);
- par[i].type = P_VAL;
- break;
- }
- tmpstr = strtok(NULL, ",\x00");
- }
- return count;
-}
-
-const opc_t *DSPAssembler::FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size)
-{
- if (opcode[0] == 'C' && opcode[1] == 'W')
- return &cw;
-
- AliasMap::const_iterator alias_iter = aliases.find(opcode);
- if (alias_iter != aliases.end())
- opcode = alias_iter->second.c_str();
- for (int i = 0; i < opcod_size; i++)
- {
- const opc_t *opc = &opcod[i];
- if (strcmp(opc->name, opcode) == 0)
- {
- if (par_count < opc->param_count)
- {
- ShowError(ERR_NOT_ENOUGH_PARAMETERS);
- }
- if (par_count > opc->param_count)
- {
- ShowError(ERR_TOO_MANY_PARAMETERS);
- }
- return opc;
- }
- }
- ShowError(ERR_UNKNOWN_OPCODE);
- return NULL;
-}
-
-// weird...
-u16 get_mask_shifted_down(u16 mask)
-{
- while (!(mask & 1))
- mask >>= 1;
- return mask;
-}
-
-bool DSPAssembler::VerifyParams(const opc_t *opc, param_t *par, int count, bool ext)
-{
- for (int i = 0; i < count; i++)
- {
- const int current_param = i + 1; // just for display.
- if (opc->params[i].type != par[i].type || (par[i].type & P_REG))
- {
- if (par[i].type == P_VAL &&
- (opc->params[i].type == P_ADDR_I || opc->params[i].type == P_ADDR_D))
- {
- // Data and instruction addresses are valid as VAL values.
- continue;
- }
-
- if ((opc->params[i].type & P_REG) && (par[i].type & P_REG))
- {
- // Just a temp. Should be replaced with more purposeful vars.
- int value;
-
- // modified by Hermes: test the register range
- switch ((unsigned)opc->params[i].type)
- {
- case P_REG18:
- case P_REG19:
- case P_REG1A:
- value = (opc->params[i].type >> 8) & 31;
- if ((int)par[i].val < value ||
- (int)par[i].val > value + get_mask_shifted_down(opc->params[i].mask))
- {
- if (ext) fprintf(stderr, "(ext) ");
- fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param);
- ShowError(ERR_INVALID_REGISTER);
- }
- break;
- case P_PRG:
- if ((int)par[i].val < 0 || (int)par[i].val > 0x3)
- {
- if (ext) fprintf(stderr, "(ext) ");
- fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param);
- ShowError(ERR_INVALID_REGISTER);
- }
- break;
- case P_ACC:
- if ((int)par[i].val < 0x20 || (int)par[i].val > 0x21)
- {
- if (ext) fprintf(stderr, "(ext) ");
- if (par[i].val >= 0x1e && par[i].val <= 0x1f) {
- fprintf(stderr, "%i : %s", code_line, cur_line.c_str());
- fprintf(stderr, "WARNING: $ACM%d register used instead of $ACC%d register Line: %d Param: %d Ext: %d\n",
- (par[i].val & 1), (par[i].val & 1), code_line, current_param, ext);
- }
- else if (par[i].val >= 0x1c && par[i].val <= 0x1d) {
- fprintf(stderr, "WARNING: $ACL%d register used instead of $ACC%d register Line: %d Param: %d\n",
- (par[i].val & 1), (par[i].val & 1), code_line, current_param);
- }
- else
- ShowError(ERR_WRONG_PARAMETER_ACC);
- }
- break;
- case P_ACCM:
- if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f)
- {
- if (ext) fprintf(stderr, "(ext) ");
- if (par[i].val >= 0x1c && par[i].val <= 0x1d)
- fprintf(stderr, "WARNING: $ACL%d register used instead of $ACM%d register Line: %d Param: %d\n",
- (par[i].val & 1), (par[i].val & 1), code_line, current_param);
- else if (par[i].val >= 0x20 && par[i].val <= 0x21)
- fprintf(stderr, "WARNING: $ACC%d register used instead of $ACM%d register Line: %d Param: %d\n",
- (par[i].val & 1), (par[i].val & 1), code_line, current_param);
- else
- ShowError(ERR_WRONG_PARAMETER_ACC);
- }
- break;
-
- case P_ACCL:
- if ((int)par[i].val < 0x1c || (int)par[i].val > 0x1d)
- {
- if (ext) fprintf(stderr, "(ext) ");
- if (par[i].val >= 0x1e && par[i].val <= 0x1f)
- {
- fprintf(stderr, "%s", cur_line.c_str());
- fprintf(stderr, "WARNING: $ACM%d register used instead of $ACL%d register Line: %d Param: %d\n",
- (par[i].val & 1), (par[i].val & 1), code_line, current_param);
- }
- else if (par[i].val >= 0x20 && par[i].val <= 0x21) {
- fprintf(stderr, "%s", cur_line.c_str());
- fprintf(stderr, "WARNING: $ACC%d register used instead of $ACL%d register Line: %d Param: %d\n",
- (par[i].val & 1), (par[i].val & 1), code_line, current_param);
- }
- else
- ShowError(ERR_WRONG_PARAMETER_ACC);
- }
- break;
-/* case P_ACCM_D: //P_ACC_MID:
- if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f)
- {
- ShowError(ERR_WRONG_PARAMETER_MID_ACC);
- }
- break;*/
- }
- continue;
- }
-
- switch (par[i].type & (P_REG | 7))
- {
- case P_REG:
- if (ext) fprintf(stderr, "(ext) ");
- ShowError(ERR_EXPECTED_PARAM_REG);
- break;
- case P_MEM:
- if (ext) fprintf(stderr, "(ext) ");
- ShowError(ERR_EXPECTED_PARAM_MEM);
- break;
- case P_VAL:
- if (ext) fprintf(stderr, "(ext) ");
- ShowError(ERR_EXPECTED_PARAM_VAL);
- break;
- case P_IMM:
- if (ext) fprintf(stderr, "(ext) ");
- ShowError(ERR_EXPECTED_PARAM_IMM);
- break;
- }
- ShowError(ERR_WRONG_PARAMETER);
- break;
- }
- else if ((opc->params[i].type & 3) != 0 && (par[i].type & 3) != 0)
- {
- // modified by Hermes: test NUMBER range
- int value = get_mask_shifted_down(opc->params[i].mask);
- unsigned int valueu = 0xffff & ~(value >> 1);
- if ((int)par[i].val < 0)
- {
- if (value == 7) // value 7 por sbclr/sbset
- {
- fprintf(stderr,"Value must be from 0x0 to 0x%x\n", value);
- ShowError(ERR_OUT_RANGE_NUMBER);
- }
- else if (opc->params[i].type == P_MEM)
- {
- if (value < 256)
- fprintf(stderr, "Address value must be from 0x%x to 0x%x\n",valueu, (value>>1));
- else
- fprintf(stderr, "Address value must be from 0x0 to 0x%x\n", value);
-
- ShowError(ERR_OUT_RANGE_NUMBER);
- }
- else if ((int)par[i].val < -((value >> 1) + 1))
- {
- if (value < 128)
- fprintf(stderr, "Value must be from -0x%x to 0x%x, is %i\n",
- (value >> 1) + 1, value >> 1, par[i].val);
- else
- fprintf(stderr, "Value must be from -0x%x to 0x%x or 0x0 to 0x%x, is %i\n",
- (value >> 1) + 1, value >> 1, value, par[i].val);
-
- ShowError(ERR_OUT_RANGE_NUMBER);
- }
- }
- else
- {
- if (value == 7) // value 7 por sbclr/sbset
- {
- if (par[i].val > (unsigned)value)
- {
- fprintf(stderr,"Value must be from 0x%x to 0x%x, is %i\n",valueu, value, par[i].val);
- ShowError(ERR_OUT_RANGE_NUMBER);
- }
- }
- else if (opc->params[i].type == P_MEM)
- {
- if (value < 256)
- value >>= 1; // addressing 8 bit with sign
- if (par[i].val > (unsigned)value &&
- (par[i].val < valueu || par[i].val > (unsigned)0xffff))
- {
- if (value < 256)
- fprintf(stderr,"Address value must be from 0x%x to 0x%x, is %04x\n", valueu, value, par[i].val);
- else
- fprintf(stderr,"Address value must be minor of 0x%x\n", value+1);
- ShowError(ERR_OUT_RANGE_NUMBER);
- }
- }
- else
- {
- if (value < 128)
- value >>= 1; // special case ASL/ASR/LSL/LSR
- if (par[i].val > (unsigned)value)
- {
- if (value < 64)
- fprintf(stderr,"Value must be from -0x%x to 0x%x, is %i\n", (value + 1), value, par[i].val);
- else
- fprintf(stderr,"Value must be minor of 0x%x, is %i\n", value + 1, par[i].val);
- ShowError(ERR_OUT_RANGE_NUMBER);
- }
- }
- }
- continue;
- }
- }
- m_current_param = 0;
- return true;
-}
-
-
-// Merge opcode with params.
-void DSPAssembler::BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf)
-{
- outbuf[m_cur_addr] |= opc->opcode;
- for (u32 i = 0; i < par_count; i++)
- {
- // Ignore the "reverse" parameters since they are implicit.
- if (opc->params[i].type != P_ACC_D && opc->params[i].type != P_ACCM_D)
- {
- u16 t16 = outbuf[m_cur_addr + opc->params[i].loc];
- u16 v16 = par[i].val;
- if (opc->params[i].lshift > 0)
- v16 <<= opc->params[i].lshift;
- else
- v16 >>= -opc->params[i].lshift;
- v16 &= opc->params[i].mask;
- outbuf[m_cur_addr + opc->params[i].loc] = t16 | v16;
- }
- }
-}
-
-void DSPAssembler::InitPass(int pass)
-{
- failed = false;
- if (pass == 1)
- {
- // Reset label table. Pre-populate with hw addresses and registers.
- labels.Clear();
- labels.RegisterDefaults();
- aliases.clear();
- aliases["S15"] = "SET15";
- aliases["S16"] = "SET16";
- aliases["S40"] = "SET40";
- }
- m_cur_addr = 0;
- m_totalSize = 0;
- cur_segment = SEGMENT_CODE;
- segment_addr[SEGMENT_CODE] = 0;
- segment_addr[SEGMENT_DATA] = 0;
- segment_addr[SEGMENT_OVERLAY] = 0;
-}
-
-bool DSPAssembler::AssembleFile(const char *fname, int pass)
-{
- int disable_text = 0; // modified by Hermes
-
- std::ifstream fsrc(fname);
-
- if (fsrc.fail())
- {
- std::cerr << "Cannot open file " << fname << std::endl;
- return false;
- }
-
- //printf("%s: Pass %d\n", fname, pass);
- code_line = 0;
- m_cur_pass = pass;
-
-#define LINEBUF_SIZE 1024
- char line[LINEBUF_SIZE] = {0};
- while (!failed && !fsrc.fail() && !fsrc.eof())
- {
- int opcode_size = 0;
- fsrc.getline(line, LINEBUF_SIZE);
- if(fsrc.fail())
- break;
-
- cur_line = line;
- //printf("A: %s\n", line);
- code_line++;
-
- param_t params[10] = {{0}};
- param_t params_ext[10] = {{0}};
-
- bool upper = true;
- for (int i = 0; i < LINEBUF_SIZE; i++)
- {
- char c = line[i];
- // This stuff handles /**/ and // comments.
- // modified by Hermes : added // and /* */ for long commentaries
- if (c == '/')
- {
- if (i < 1023)
- {
- if (line[i+1] == '/')
- c = 0x00;
- else if (line[i+1] == '*')
- {
- // toggle comment mode.
- disable_text = !disable_text;
- }
- }
- }
- else if (c == '*')
- {
- if (i < 1023 && line[i+1] == '/' && disable_text)
- {
- disable_text = 0;
- c = 32;
- line[i + 1] = 32;
- }
- }
-
- // turn text into spaces if disable_text is on (in a comment).
- if (disable_text && ((unsigned char)c) > 32) c = 32;
-
- if (c == 0x0a || c == 0x0d || c == ';')
- c = 0x00;
- if (c == 0x09) // tabs to spaces
- c = ' ';
- if (c == '"')
- upper = !upper;
- if (upper && c >= 'a' && c <= 'z') // convert to uppercase
- c = c - 'a' + 'A';
- line[i] = c;
- if (c == 0)
- break; // modified by Hermes
- }
- char *ptr = line;
-
- std::string label;
-
- size_t col_pos = std::string(line).find(":");
- if (col_pos != std::string::npos)
- {
- bool valid = true;
-
- for(int j = 0; j < (int)col_pos; j++)
- {
- if (j == 0)
- if (!((ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_')))
- valid = false;
- if (!((ptr[j] >= '0' && ptr[j] <= '9') || (ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_')))
- valid = false;
- }
- if (valid)
- {
- label = std::string(line).substr(0, col_pos);
- ptr += col_pos + 1;
- }
- }
-
- char *opcode = NULL;
- opcode = strtok(ptr, " ");
- char *opcode_ext = NULL;
-
- u32 params_count = 0;
- u32 params_count_ext = 0;
- if (opcode)
- {
- if ((opcode_ext = strstr(opcode, "'")) != NULL)
- {
- opcode_ext[0] = '\0';
- opcode_ext++;
- if (strlen(opcode_ext) == 0)
- opcode_ext = NULL;
- }
- // now we have opcode and label
-
- params_count = 0;
- params_count_ext = 0;
-
- char *paramstr = strtok(NULL, "\0");
- char *paramstr_ext = 0;
- // there is valid opcode so probably we have parameters
-
- if (paramstr)
- {
- if ((paramstr_ext = strstr(paramstr, ":")) != NULL)
- {
- paramstr_ext[0] = '\0';
- paramstr_ext++;
- }
- }
-
- if (paramstr)
- params_count = GetParams(paramstr, params);
- if (paramstr_ext)
- params_count_ext = GetParams(paramstr_ext, params_ext);
- }
-
- if (!label.empty())
- {
- // there is a valid label so lets store it in labels table
- u32 lval = m_cur_addr;
- if (opcode)
- {
- if (strcmp(opcode, "EQU") == 0)
- {
- lval = params[0].val;
- opcode = NULL;
- }
- }
- if (pass == 1)
- labels.RegisterLabel(label, lval);
- }
-
- if (opcode == NULL)
- continue;
-
- // check if opcode is reserved compiler word
- if (strcmp("INCLUDE", opcode) == 0)
- {
- if (params[0].type == P_STR)
- {
- char *tmpstr;
- u32 thisCodeline = code_line;
-
- if (include_dir.size())
- {
- tmpstr = (char *)malloc(include_dir.size() + strlen(params[0].str) + 2);
- sprintf(tmpstr, "%s/%s", include_dir.c_str(), params[0].str);
- }
- else
- {
- tmpstr = (char *)malloc(strlen(params[0].str) + 1);
- strcpy(tmpstr, params[0].str);
- }
-
- AssembleFile(tmpstr, pass);
-
- code_line = thisCodeline;
-
- free(tmpstr);
- }
- else
- ShowError(ERR_EXPECTED_PARAM_STR);
- continue;
- }
-
- if (strcmp("INCDIR", opcode) == 0)
- {
- if (params[0].type == P_STR)
- include_dir = params[0].str;
- else
- ShowError(ERR_EXPECTED_PARAM_STR);
- continue;
- }
-
- if (strcmp("ORG", opcode) == 0)
- {
- if (params[0].type == P_VAL)
- m_cur_addr = params[0].val;
- else
- ShowError(ERR_EXPECTED_PARAM_VAL);
- continue;
- }
-
- if (strcmp("SEGMENT", opcode) == 0)
- {
- if (params[0].type == P_STR)
- {
- segment_addr[cur_segment] = m_cur_addr;
- if (strcmp("DATA", params[0].str) == 0)
- cur_segment = SEGMENT_DATA;
- if (strcmp("CODE", params[0].str) == 0)
- cur_segment = SEGMENT_CODE;
- m_cur_addr = segment_addr[cur_segment];
- }
- else
- ShowError(ERR_EXPECTED_PARAM_STR);
- continue;
- }
-
- const opc_t *opc = FindOpcode(opcode, params_count, opcodes, opcodes_size);
- if (!opc)
- opc = &cw;
-
- opcode_size = opc->size & ~P_EXT;
-
- VerifyParams(opc, params, params_count);
-
- const opc_t *opc_ext = NULL;
- // Check for opcode extensions.
- if (opc->size & P_EXT)
- {
- if (opcode_ext)
- {
- opc_ext = FindOpcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size);
- VerifyParams(opc_ext, params_ext, params_count_ext, true);
- }
- else if (params_count_ext)
- ShowError(ERR_EXT_PAR_NOT_EXT);
- }
- else
- {
- if (opcode_ext)
- ShowError(ERR_EXT_CANT_EXTEND_OPCODE);
- if (params_count_ext)
- ShowError(ERR_EXT_PAR_NOT_EXT);
- }
-
- if (pass == 2)
- {
- // generate binary
- ((u16 *)gdg_buffer)[m_cur_addr] = 0x0000;
- BuildCode(opc, params, params_count, (u16 *)gdg_buffer);
- if (opc_ext)
- BuildCode(opc_ext, params_ext, params_count_ext, (u16 *)gdg_buffer);
- }
-
- m_cur_addr += opcode_size;
- m_totalSize += opcode_size;
- };
-
- if (!failed)
- fsrc.close();
-
- return !failed;
-}
+/*====================================================================
+
+$Id: assemble.cpp,v 1.3 2008-11-11 01:04:26 wntrmute Exp $
+
+project: GameCube DSP Tool (gcdsp)
+mail: duddie@walla.com
+
+Copyright (c) 2005 Duddie
+
+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; either version 2
+of the License, or (at your option) any later version.
+
+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 for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+Revision 1.4 2008/10/04 10:30:00 Hermes
+added function to export the code to .h file
+added support for '/ *' '* /' and '//' for comentaries
+added some sintax detection when use registers
+
+$Log: not supported by cvs2svn $
+Revision 1.2 2005/09/14 02:19:29 wntrmute
+added header guards
+use standard main function
+
+Revision 1.1 2005/08/24 22:13:34 wntrmute
+Initial import
+
+
+====================================================================*/
+
+#include <cstdio>
+#include <cstdlib>
+
+#include <map>
+#include <iostream>
+#include <fstream>
+
+#include "Common.h"
+#include "FileUtil.h"
+#include "DSPInterpreter.h"
+#include "DSPTables.h"
+#include "disassemble.h"
+#include "assemble.h"
+
+static const char *err_string[] =
+{
+ "",
+ "Unknown Error",
+ "Unknown opcode",
+ "Not enough parameters",
+ "Too many parameters",
+ "Wrong parameter",
+ "Expected parameter of type 'string'",
+ "Expected parameter of type 'value'",
+ "Expected parameter of type 'register'",
+ "Expected parameter of type 'memory pointer'",
+ "Expected parameter of type 'immediate'",
+ "Incorrect binary value",
+ "Incorrect hexadecimal value",
+ "Incorrect decimal value",
+ "Label already exists",
+ "Label not defined",
+ "No matching brackets",
+ "This opcode cannot be extended",
+ "Given extending params for non extensible opcode",
+ "Wrong parameter: must be accumulator register",
+ "Wrong parameter: must be mid accumulator register",
+ "Invalid register",
+ "Number out of range"
+};
+
+DSPAssembler::DSPAssembler(const AssemblerSettings &settings) :
+ m_cur_addr(0),
+ m_cur_pass(0),
+ m_current_param(0),
+ settings_(settings),
+ gdg_buffer(NULL)
+{
+}
+
+DSPAssembler::~DSPAssembler()
+{
+ if(gdg_buffer)
+ free(gdg_buffer);
+}
+
+bool DSPAssembler::Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers)
+{
+ if (line_numbers)
+ line_numbers->clear();
+ const char *fname = "tmp.asm";
+ if (!File::WriteStringToFile(true, text, fname))
+ return false;
+ InitPass(1);
+ if (!AssembleFile(fname, 1))
+ return false;
+
+ // We now have the size of the output buffer
+ if (m_totalSize > 0)
+ {
+ gdg_buffer = (char *)malloc(m_totalSize * sizeof(u16) + 4);
+ if(!gdg_buffer)
+ return false;
+
+ memset(gdg_buffer, 0, m_totalSize * sizeof(u16));
+ } else
+ return false;
+
+ InitPass(2);
+ if (!AssembleFile(fname, 2))
+ return false;
+
+ code.resize(m_totalSize);
+ for (int i = 0; i < m_totalSize; i++) {
+ code[i] = *(u16 *)(gdg_buffer + i * 2);
+ }
+
+ if(gdg_buffer) {
+ free(gdg_buffer);
+ gdg_buffer = NULL;
+ }
+
+ last_error_str = "(no errors)";
+ last_error = ERR_OK;
+
+ return true;
+}
+
+void DSPAssembler::ShowError(err_t err_code, const char *extra_info)
+{
+ failed = true;
+ char error_buffer[1024];
+ char *buf_ptr = error_buffer;
+ buf_ptr += sprintf(buf_ptr, "%i : %s ", code_line, cur_line.c_str());
+ if (!extra_info)
+ extra_info = "-";
+
+ if (m_current_param == 0)
+ buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d : %s\n", err_string[err_code], code_line, extra_info);
+ else
+ buf_ptr += sprintf(buf_ptr, "ERROR: %s Line: %d Param: %d : %s\n",
+ err_string[err_code], code_line, m_current_param, extra_info);
+ last_error_str = error_buffer;
+ last_error = err_code;
+}
+
+char *skip_spaces(char *ptr)
+{
+ while (*ptr == ' ')
+ ptr++;
+ return ptr;
+}
+
+const char *skip_spaces(const char *ptr)
+{
+ while (*ptr == ' ')
+ ptr++;
+ return ptr;
+}
+
+// Parse a standalone value - it can be a number in one of several formats or a label.
+s32 DSPAssembler::ParseValue(const char *str)
+{
+ bool negative = false;
+ s32 val = 0;
+ const char *ptr = str;
+
+ if (ptr[0] == '#')
+ {
+ ptr++;
+ negative = true; // Wow! Double # (needed one to get in here) negates???
+ }
+ if (ptr[0] == '-')
+ {
+ ptr++;
+ negative = true;
+ }
+ if (ptr[0] == '0')
+ {
+ if (ptr[1] >= '0' && ptr[1] <= '9')
+ {
+ for (int i = 0; ptr[i] != 0; i++)
+ {
+ val *= 10;
+ if (ptr[i] >= '0' && ptr[i] <= '9')
+ val += ptr[i] - '0';
+ else
+ ShowError(ERR_INCORRECT_DEC, str);
+ }
+ }
+ else
+ {
+ switch (ptr[1])
+ {
+ case 'X': // hex
+ for (int i = 2 ; ptr[i] != 0 ; i++)
+ {
+ val <<= 4;
+ if (ptr[i] >= 'a' && ptr[i] <= 'f')
+ val += (ptr[i]-'a'+10);
+ else if (ptr[i] >= 'A' && ptr[i] <= 'F')
+ val += (ptr[i]-'A'+10);
+ else if (ptr[i] >= '0' && ptr[i] <= '9')
+ val += (ptr[i] - '0');
+ else
+ ShowError(ERR_INCORRECT_HEX, str);
+ }
+ break;
+ case '\'': // binary
+ for (int i = 2; ptr[i] != 0; i++)
+ {
+ val *=2;
+ if(ptr[i] >= '0' && ptr[i] <= '1')
+ val += ptr[i] - '0';
+ else
+ ShowError(ERR_INCORRECT_BIN, str);
+ }
+ break;
+ default:
+ // value is 0 or error
+ val = 0;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // Symbol starts with a digit - it's a dec number.
+ if (ptr[0] >= '0' && ptr[0] <= '9')
+ {
+ for (int i = 0; ptr[i] != 0; i++)
+ {
+ val *= 10;
+ if (ptr[i] >= '0' && ptr[i] <= '9')
+ val += ptr[i] - '0';
+ else
+ ShowError(ERR_INCORRECT_DEC, str);
+ }
+ }
+ else // Everything else is a label.
+ {
+ // Lookup label
+ u16 value;
+ if (labels.GetLabelValue(ptr, &value))
+ return value;
+ if (m_cur_pass == 2)
+ ShowError(ERR_UNKNOWN_LABEL, str);
+ }
+ }
+ if (negative)
+ return -val;
+ return val;
+}
+
+// Modifies both src and dst!
+// What does it do, really??
+char *DSPAssembler::FindBrackets(char *src, char *dst)
+{
+ s32 len = (s32) strlen(src);
+ s32 first = -1;
+ s32 count = 0;
+ s32 i, j;
+ j = 0;
+ for (i = 0 ; i < len ; i++)
+ {
+ if (src[i] == '(')
+ {
+ if (first < 0)
+ {
+ count = 1;
+ src[i] = 0x0;
+ first = i;
+ }
+ else
+ {
+ count++;
+ dst[j++] = src[i];
+ }
+ }
+ else if (src[i] == ')')
+ {
+ if (--count == 0)
+ {
+ dst[j] = 0;
+ return &src[i+1];
+ }
+ else
+ {
+ dst[j++] = src[i];
+ }
+ }
+ else
+ {
+ if (first >= 0)
+ dst[j++] = src[i];
+ }
+ }
+ if (count)
+ ShowError(ERR_NO_MATCHING_BRACKETS);
+ return NULL;
+}
+
+// Bizarre in-place expression evaluator.
+u32 DSPAssembler::ParseExpression(const char *ptr)
+{
+ char *pbuf;
+ s32 val = 0;
+
+ char *d_buffer = (char *)malloc(1024);
+ char *s_buffer = (char *)malloc(1024);
+ strcpy(s_buffer, ptr);
+
+ while ((pbuf = FindBrackets(s_buffer, d_buffer)) != NULL)
+ {
+ val = ParseExpression(d_buffer);
+ sprintf(d_buffer, "%s%d%s", s_buffer, val, pbuf);
+ strcpy(s_buffer, d_buffer);
+ }
+
+ int j = 0;
+ for (int i = 0; i < ((s32)strlen(s_buffer) + 1) ; i++)
+ {
+ char c = s_buffer[i];
+ if (c != ' ')
+ d_buffer[j++] = c;
+ }
+
+ for (int i = 0; i < ((s32)strlen(d_buffer) + 1) ; i++)
+ {
+ char c = d_buffer[i];
+ if (c == '-')
+ {
+ if (i == 0)
+ c = '#';
+ else
+ {
+ switch (d_buffer[i - 1])
+ {
+ case '/':
+ case '%':
+ case '*':
+ c = '#';
+ }
+ }
+ }
+ d_buffer[i] = c;
+ }
+
+ while ((pbuf = strstr(d_buffer, "+")) != NULL)
+ {
+ *pbuf = 0x0;
+ val = ParseExpression(d_buffer) + ParseExpression(pbuf+1);
+ sprintf(d_buffer, "%d", val);
+ }
+
+ while ((pbuf = strstr(d_buffer, "-")) != NULL)
+ {
+ *pbuf = 0x0;
+ val = ParseExpression(d_buffer) - ParseExpression(pbuf+1);
+ if (val < 0)
+ {
+ val = 0x10000 + (val & 0xffff); // ATTENTION: avoid a terrible bug!!! number cannot write with '-' in sprintf
+ fprintf(stderr, "WARNING: Number Underflow at Line: %d \n", code_line);
+ }
+ sprintf(d_buffer, "%d", val);
+ }
+
+ while ((pbuf = strstr(d_buffer, "*")) != NULL)
+ {
+ *pbuf = 0x0;
+ val = ParseExpression(d_buffer) * ParseExpression(pbuf+1);
+ sprintf(d_buffer, "%d", val);
+ }
+
+ while ((pbuf = strstr(d_buffer, "/")) != NULL)
+ {
+ *pbuf = 0x0;
+ val = ParseExpression(d_buffer) / ParseExpression(pbuf+1);
+ sprintf(d_buffer, "%d", val);
+ }
+
+ while ((pbuf = strstr(d_buffer, "|")) != NULL)
+ {
+ *pbuf = 0x0;
+ val = ParseExpression(d_buffer) | ParseExpression(pbuf+1);
+ sprintf(d_buffer, "%d", val);
+ }
+
+ while ((pbuf = strstr(d_buffer, "&")) != NULL)
+ {
+ *pbuf = 0x0;
+ val = ParseExpression(d_buffer) & ParseExpression(pbuf+1);
+ sprintf(d_buffer, "%d", val);
+ }
+
+ val = ParseValue(d_buffer);
+ free(d_buffer);
+ free(s_buffer);
+ return val;
+}
+
+// Destroys parstr
+u32 DSPAssembler::GetParams(char *parstr, param_t *par)
+{
+ u32 count = 0;
+ char *tmpstr = skip_spaces(parstr);
+ tmpstr = strtok(tmpstr, ",\x00");
+ for (int i = 0; i < 10; i++)
+ {
+ if (tmpstr == NULL)
+ break;
+ tmpstr = skip_spaces(tmpstr);
+ if (strlen(tmpstr) == 0)
+ break;
+ if (tmpstr)
+ count++;
+ else
+ break;
+
+ par[i].type = P_NONE;
+ switch (tmpstr[0])
+ {
+ case '"':
+ par[i].str = strtok(tmpstr, "\"");
+ par[i].type = P_STR;
+ break;
+ case '#':
+ par[i].val = ParseExpression(tmpstr + 1);
+ par[i].type = P_IMM;
+ break;
+ case '@':
+ if (tmpstr[1] == '$')
+ {
+ par[i].val = ParseExpression(tmpstr + 2);
+ par[i].type = P_PRG;
+ }
+ else
+ {
+ par[i].val = ParseExpression(tmpstr + 1);
+ par[i].type = P_MEM;
+ }
+ break;
+ case '$':
+ par[i].val = ParseExpression(tmpstr + 1);
+ par[i].type = P_REG;
+ break;
+
+ default:
+ par[i].val = ParseExpression(tmpstr);
+ par[i].type = P_VAL;
+ break;
+ }
+ tmpstr = strtok(NULL, ",\x00");
+ }
+ return count;
+}
+
+const opc_t *DSPAssembler::FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size)
+{
+ if (opcode[0] == 'C' && opcode[1] == 'W')
+ return &cw;
+
+ AliasMap::const_iterator alias_iter = aliases.find(opcode);
+ if (alias_iter != aliases.end())
+ opcode = alias_iter->second.c_str();
+ for (int i = 0; i < opcod_size; i++)
+ {
+ const opc_t *opc = &opcod[i];
+ if (strcmp(opc->name, opcode) == 0)
+ {
+ if (par_count < opc->param_count)
+ {
+ ShowError(ERR_NOT_ENOUGH_PARAMETERS);
+ }
+ if (par_count > opc->param_count)
+ {
+ ShowError(ERR_TOO_MANY_PARAMETERS);
+ }
+ return opc;
+ }
+ }
+ ShowError(ERR_UNKNOWN_OPCODE);
+ return NULL;
+}
+
+// weird...
+u16 get_mask_shifted_down(u16 mask)
+{
+ while (!(mask & 1))
+ mask >>= 1;
+ return mask;
+}
+
+bool DSPAssembler::VerifyParams(const opc_t *opc, param_t *par, int count, bool ext)
+{
+ for (int i = 0; i < count; i++)
+ {
+ const int current_param = i + 1; // just for display.
+ if (opc->params[i].type != par[i].type || (par[i].type & P_REG))
+ {
+ if (par[i].type == P_VAL &&
+ (opc->params[i].type == P_ADDR_I || opc->params[i].type == P_ADDR_D))
+ {
+ // Data and instruction addresses are valid as VAL values.
+ continue;
+ }
+
+ if ((opc->params[i].type & P_REG) && (par[i].type & P_REG))
+ {
+ // Just a temp. Should be replaced with more purposeful vars.
+ int value;
+
+ // modified by Hermes: test the register range
+ switch ((unsigned)opc->params[i].type)
+ {
+ case P_REG18:
+ case P_REG19:
+ case P_REG1A:
+ value = (opc->params[i].type >> 8) & 31;
+ if ((int)par[i].val < value ||
+ (int)par[i].val > value + get_mask_shifted_down(opc->params[i].mask))
+ {
+ if (ext) fprintf(stderr, "(ext) ");
+ fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param);
+ ShowError(ERR_INVALID_REGISTER);
+ }
+ break;
+ case P_PRG:
+ if ((int)par[i].val < 0 || (int)par[i].val > 0x3)
+ {
+ if (ext) fprintf(stderr, "(ext) ");
+ fprintf(stderr, "%s (param %i)", cur_line.c_str(), current_param);
+ ShowError(ERR_INVALID_REGISTER);
+ }
+ break;
+ case P_ACC:
+ if ((int)par[i].val < 0x20 || (int)par[i].val > 0x21)
+ {
+ if (ext) fprintf(stderr, "(ext) ");
+ if (par[i].val >= 0x1e && par[i].val <= 0x1f) {
+ fprintf(stderr, "%i : %s", code_line, cur_line.c_str());
+ fprintf(stderr, "WARNING: $ACM%d register used instead of $ACC%d register Line: %d Param: %d Ext: %d\n",
+ (par[i].val & 1), (par[i].val & 1), code_line, current_param, ext);
+ }
+ else if (par[i].val >= 0x1c && par[i].val <= 0x1d) {
+ fprintf(stderr, "WARNING: $ACL%d register used instead of $ACC%d register Line: %d Param: %d\n",
+ (par[i].val & 1), (par[i].val & 1), code_line, current_param);
+ }
+ else
+ ShowError(ERR_WRONG_PARAMETER_ACC);
+ }
+ break;
+ case P_ACCM:
+ if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f)
+ {
+ if (ext) fprintf(stderr, "(ext) ");
+ if (par[i].val >= 0x1c && par[i].val <= 0x1d)
+ fprintf(stderr, "WARNING: $ACL%d register used instead of $ACM%d register Line: %d Param: %d\n",
+ (par[i].val & 1), (par[i].val & 1), code_line, current_param);
+ else if (par[i].val >= 0x20 && par[i].val <= 0x21)
+ fprintf(stderr, "WARNING: $ACC%d register used instead of $ACM%d register Line: %d Param: %d\n",
+ (par[i].val & 1), (par[i].val & 1), code_line, current_param);
+ else
+ ShowError(ERR_WRONG_PARAMETER_ACC);
+ }
+ break;
+
+ case P_ACCL:
+ if ((int)par[i].val < 0x1c || (int)par[i].val > 0x1d)
+ {
+ if (ext) fprintf(stderr, "(ext) ");
+ if (par[i].val >= 0x1e && par[i].val <= 0x1f)
+ {
+ fprintf(stderr, "%s", cur_line.c_str());
+ fprintf(stderr, "WARNING: $ACM%d register used instead of $ACL%d register Line: %d Param: %d\n",
+ (par[i].val & 1), (par[i].val & 1), code_line, current_param);
+ }
+ else if (par[i].val >= 0x20 && par[i].val <= 0x21) {
+ fprintf(stderr, "%s", cur_line.c_str());
+ fprintf(stderr, "WARNING: $ACC%d register used instead of $ACL%d register Line: %d Param: %d\n",
+ (par[i].val & 1), (par[i].val & 1), code_line, current_param);
+ }
+ else
+ ShowError(ERR_WRONG_PARAMETER_ACC);
+ }
+ break;
+/* case P_ACCM_D: //P_ACC_MID:
+ if ((int)par[i].val < 0x1e || (int)par[i].val > 0x1f)
+ {
+ ShowError(ERR_WRONG_PARAMETER_MID_ACC);
+ }
+ break;*/
+ }
+ continue;
+ }
+
+ switch (par[i].type & (P_REG | 7))
+ {
+ case P_REG:
+ if (ext) fprintf(stderr, "(ext) ");
+ ShowError(ERR_EXPECTED_PARAM_REG);
+ break;
+ case P_MEM:
+ if (ext) fprintf(stderr, "(ext) ");
+ ShowError(ERR_EXPECTED_PARAM_MEM);
+ break;
+ case P_VAL:
+ if (ext) fprintf(stderr, "(ext) ");
+ ShowError(ERR_EXPECTED_PARAM_VAL);
+ break;
+ case P_IMM:
+ if (ext) fprintf(stderr, "(ext) ");
+ ShowError(ERR_EXPECTED_PARAM_IMM);
+ break;
+ }
+ ShowError(ERR_WRONG_PARAMETER);
+ break;
+ }
+ else if ((opc->params[i].type & 3) != 0 && (par[i].type & 3) != 0)
+ {
+ // modified by Hermes: test NUMBER range
+ int value = get_mask_shifted_down(opc->params[i].mask);
+ unsigned int valueu = 0xffff & ~(value >> 1);
+ if ((int)par[i].val < 0)
+ {
+ if (value == 7) // value 7 por sbclr/sbset
+ {
+ fprintf(stderr,"Value must be from 0x0 to 0x%x\n", value);
+ ShowError(ERR_OUT_RANGE_NUMBER);
+ }
+ else if (opc->params[i].type == P_MEM)
+ {
+ if (value < 256)
+ fprintf(stderr, "Address value must be from 0x%x to 0x%x\n",valueu, (value>>1));
+ else
+ fprintf(stderr, "Address value must be from 0x0 to 0x%x\n", value);
+
+ ShowError(ERR_OUT_RANGE_NUMBER);
+ }
+ else if ((int)par[i].val < -((value >> 1) + 1))
+ {
+ if (value < 128)
+ fprintf(stderr, "Value must be from -0x%x to 0x%x, is %i\n",
+ (value >> 1) + 1, value >> 1, par[i].val);
+ else
+ fprintf(stderr, "Value must be from -0x%x to 0x%x or 0x0 to 0x%x, is %i\n",
+ (value >> 1) + 1, value >> 1, value, par[i].val);
+
+ ShowError(ERR_OUT_RANGE_NUMBER);
+ }
+ }
+ else
+ {
+ if (value == 7) // value 7 por sbclr/sbset
+ {
+ if (par[i].val > (unsigned)value)
+ {
+ fprintf(stderr,"Value must be from 0x%x to 0x%x, is %i\n",valueu, value, par[i].val);
+ ShowError(ERR_OUT_RANGE_NUMBER);
+ }
+ }
+ else if (opc->params[i].type == P_MEM)
+ {
+ if (value < 256)
+ value >>= 1; // addressing 8 bit with sign
+ if (par[i].val > (unsigned)value &&
+ (par[i].val < valueu || par[i].val > (unsigned)0xffff))
+ {
+ if (value < 256)
+ fprintf(stderr,"Address value must be from 0x%x to 0x%x, is %04x\n", valueu, value, par[i].val);
+ else
+ fprintf(stderr,"Address value must be minor of 0x%x\n", value+1);
+ ShowError(ERR_OUT_RANGE_NUMBER);
+ }
+ }
+ else
+ {
+ if (value < 128)
+ value >>= 1; // special case ASL/ASR/LSL/LSR
+ if (par[i].val > (unsigned)value)
+ {
+ if (value < 64)
+ fprintf(stderr,"Value must be from -0x%x to 0x%x, is %i\n", (value + 1), value, par[i].val);
+ else
+ fprintf(stderr,"Value must be minor of 0x%x, is %i\n", value + 1, par[i].val);
+ ShowError(ERR_OUT_RANGE_NUMBER);
+ }
+ }
+ }
+ continue;
+ }
+ }
+ m_current_param = 0;
+ return true;
+}
+
+
+// Merge opcode with params.
+void DSPAssembler::BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf)
+{
+ outbuf[m_cur_addr] |= opc->opcode;
+ for (u32 i = 0; i < par_count; i++)
+ {
+ // Ignore the "reverse" parameters since they are implicit.
+ if (opc->params[i].type != P_ACC_D && opc->params[i].type != P_ACCM_D)
+ {
+ u16 t16 = outbuf[m_cur_addr + opc->params[i].loc];
+ u16 v16 = par[i].val;
+ if (opc->params[i].lshift > 0)
+ v16 <<= opc->params[i].lshift;
+ else
+ v16 >>= -opc->params[i].lshift;
+ v16 &= opc->params[i].mask;
+ outbuf[m_cur_addr + opc->params[i].loc] = t16 | v16;
+ }
+ }
+}
+
+void DSPAssembler::InitPass(int pass)
+{
+ failed = false;
+ if (pass == 1)
+ {
+ // Reset label table. Pre-populate with hw addresses and registers.
+ labels.Clear();
+ labels.RegisterDefaults();
+ aliases.clear();
+ aliases["S15"] = "SET15";
+ aliases["S16"] = "SET16";
+ aliases["S40"] = "SET40";
+ }
+ m_cur_addr = 0;
+ m_totalSize = 0;
+ cur_segment = SEGMENT_CODE;
+ segment_addr[SEGMENT_CODE] = 0;
+ segment_addr[SEGMENT_DATA] = 0;
+ segment_addr[SEGMENT_OVERLAY] = 0;
+}
+
+bool DSPAssembler::AssembleFile(const char *fname, int pass)
+{
+ int disable_text = 0; // modified by Hermes
+
+ std::ifstream fsrc(fname);
+
+ if (fsrc.fail())
+ {
+ std::cerr << "Cannot open file " << fname << std::endl;
+ return false;
+ }
+
+ //printf("%s: Pass %d\n", fname, pass);
+ code_line = 0;
+ m_cur_pass = pass;
+
+#define LINEBUF_SIZE 1024
+ char line[LINEBUF_SIZE] = {0};
+ while (!failed && !fsrc.fail() && !fsrc.eof())
+ {
+ int opcode_size = 0;
+ fsrc.getline(line, LINEBUF_SIZE);
+ if(fsrc.fail())
+ break;
+
+ cur_line = line;
+ //printf("A: %s\n", line);
+ code_line++;
+
+ param_t params[10] = {{0}};
+ param_t params_ext[10] = {{0}};
+
+ bool upper = true;
+ for (int i = 0; i < LINEBUF_SIZE; i++)
+ {
+ char c = line[i];
+ // This stuff handles /**/ and // comments.
+ // modified by Hermes : added // and /* */ for long commentaries
+ if (c == '/')
+ {
+ if (i < 1023)
+ {
+ if (line[i+1] == '/')
+ c = 0x00;
+ else if (line[i+1] == '*')
+ {
+ // toggle comment mode.
+ disable_text = !disable_text;
+ }
+ }
+ }
+ else if (c == '*')
+ {
+ if (i < 1023 && line[i+1] == '/' && disable_text)
+ {
+ disable_text = 0;
+ c = 32;
+ line[i + 1] = 32;
+ }
+ }
+
+ // turn text into spaces if disable_text is on (in a comment).
+ if (disable_text && ((unsigned char)c) > 32) c = 32;
+
+ if (c == 0x0a || c == 0x0d || c == ';')
+ c = 0x00;
+ if (c == 0x09) // tabs to spaces
+ c = ' ';
+ if (c == '"')
+ upper = !upper;
+ if (upper && c >= 'a' && c <= 'z') // convert to uppercase
+ c = c - 'a' + 'A';
+ line[i] = c;
+ if (c == 0)
+ break; // modified by Hermes
+ }
+ char *ptr = line;
+
+ std::string label;
+
+ size_t col_pos = std::string(line).find(":");
+ if (col_pos != std::string::npos)
+ {
+ bool valid = true;
+
+ for(int j = 0; j < (int)col_pos; j++)
+ {
+ if (j == 0)
+ if (!((ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_')))
+ valid = false;
+ if (!((ptr[j] >= '0' && ptr[j] <= '9') || (ptr[j] >= 'A' && ptr[j] <= 'Z') || (ptr[j] == '_')))
+ valid = false;
+ }
+ if (valid)
+ {
+ label = std::string(line).substr(0, col_pos);
+ ptr += col_pos + 1;
+ }
+ }
+
+ char *opcode = NULL;
+ opcode = strtok(ptr, " ");
+ char *opcode_ext = NULL;
+
+ u32 params_count = 0;
+ u32 params_count_ext = 0;
+ if (opcode)
+ {
+ if ((opcode_ext = strstr(opcode, "'")) != NULL)
+ {
+ opcode_ext[0] = '\0';
+ opcode_ext++;
+ if (strlen(opcode_ext) == 0)
+ opcode_ext = NULL;
+ }
+ // now we have opcode and label
+
+ params_count = 0;
+ params_count_ext = 0;
+
+ char *paramstr = strtok(NULL, "\0");
+ char *paramstr_ext = 0;
+ // there is valid opcode so probably we have parameters
+
+ if (paramstr)
+ {
+ if ((paramstr_ext = strstr(paramstr, ":")) != NULL)
+ {
+ paramstr_ext[0] = '\0';
+ paramstr_ext++;
+ }
+ }
+
+ if (paramstr)
+ params_count = GetParams(paramstr, params);
+ if (paramstr_ext)
+ params_count_ext = GetParams(paramstr_ext, params_ext);
+ }
+
+ if (!label.empty())
+ {
+ // there is a valid label so lets store it in labels table
+ u32 lval = m_cur_addr;
+ if (opcode)
+ {
+ if (strcmp(opcode, "EQU") == 0)
+ {
+ lval = params[0].val;
+ opcode = NULL;
+ }
+ }
+ if (pass == 1)
+ labels.RegisterLabel(label, lval);
+ }
+
+ if (opcode == NULL)
+ continue;
+
+ // check if opcode is reserved compiler word
+ if (strcmp("INCLUDE", opcode) == 0)
+ {
+ if (params[0].type == P_STR)
+ {
+ char *tmpstr;
+ u32 thisCodeline = code_line;
+
+ if (include_dir.size())
+ {
+ tmpstr = (char *)malloc(include_dir.size() + strlen(params[0].str) + 2);
+ sprintf(tmpstr, "%s/%s", include_dir.c_str(), params[0].str);
+ }
+ else
+ {
+ tmpstr = (char *)malloc(strlen(params[0].str) + 1);
+ strcpy(tmpstr, params[0].str);
+ }
+
+ AssembleFile(tmpstr, pass);
+
+ code_line = thisCodeline;
+
+ free(tmpstr);
+ }
+ else
+ ShowError(ERR_EXPECTED_PARAM_STR);
+ continue;
+ }
+
+ if (strcmp("INCDIR", opcode) == 0)
+ {
+ if (params[0].type == P_STR)
+ include_dir = params[0].str;
+ else
+ ShowError(ERR_EXPECTED_PARAM_STR);
+ continue;
+ }
+
+ if (strcmp("ORG", opcode) == 0)
+ {
+ if (params[0].type == P_VAL)
+ m_cur_addr = params[0].val;
+ else
+ ShowError(ERR_EXPECTED_PARAM_VAL);
+ continue;
+ }
+
+ if (strcmp("SEGMENT", opcode) == 0)
+ {
+ if (params[0].type == P_STR)
+ {
+ segment_addr[cur_segment] = m_cur_addr;
+ if (strcmp("DATA", params[0].str) == 0)
+ cur_segment = SEGMENT_DATA;
+ if (strcmp("CODE", params[0].str) == 0)
+ cur_segment = SEGMENT_CODE;
+ m_cur_addr = segment_addr[cur_segment];
+ }
+ else
+ ShowError(ERR_EXPECTED_PARAM_STR);
+ continue;
+ }
+
+ const opc_t *opc = FindOpcode(opcode, params_count, opcodes, opcodes_size);
+ if (!opc)
+ opc = &cw;
+
+ opcode_size = opc->size & ~P_EXT;
+
+ VerifyParams(opc, params, params_count);
+
+ const opc_t *opc_ext = NULL;
+ // Check for opcode extensions.
+ if (opc->size & P_EXT)
+ {
+ if (opcode_ext)
+ {
+ opc_ext = FindOpcode(opcode_ext, params_count_ext, opcodes_ext, opcodes_ext_size);
+ VerifyParams(opc_ext, params_ext, params_count_ext, true);
+ }
+ else if (params_count_ext)
+ ShowError(ERR_EXT_PAR_NOT_EXT);
+ }
+ else
+ {
+ if (opcode_ext)
+ ShowError(ERR_EXT_CANT_EXTEND_OPCODE);
+ if (params_count_ext)
+ ShowError(ERR_EXT_PAR_NOT_EXT);
+ }
+
+ if (pass == 2)
+ {
+ // generate binary
+ ((u16 *)gdg_buffer)[m_cur_addr] = 0x0000;
+ BuildCode(opc, params, params_count, (u16 *)gdg_buffer);
+ if (opc_ext)
+ BuildCode(opc_ext, params_ext, params_count_ext, (u16 *)gdg_buffer);
+ }
+
+ m_cur_addr += opcode_size;
+ m_totalSize += opcode_size;
+ };
+
+ if (!failed)
+ fsrc.close();
+
+ return !failed;
+}
diff --git a/Source/Core/DSPCore/Src/assemble.h b/Source/Core/DSPCore/Src/assemble.h
index 304b97aaab..f140d0e69e 100644
--- a/Source/Core/DSPCore/Src/assemble.h
+++ b/Source/Core/DSPCore/Src/assemble.h
@@ -1,139 +1,139 @@
-/*====================================================================
-
- project: GameCube DSP Tool (gcdsp)
- created: 2005.03.04
- mail: duddie@walla.com
-
- Copyright (c) 2005 Duddie
-
- 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; either version 2
- of the License, or (at your option) any later version.
-
- 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 for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- ====================================================================*/
-
-#ifndef _DSP_ASSEMBLE_H
-#define _DSP_ASSEMBLE_H
-
-#include <string>
-#include <map>
-
-#include "Common.h"
-#include "disassemble.h"
-#include "DSPTables.h"
-#include "LabelMap.h"
-
-enum err_t
-{
- ERR_OK = 0,
- ERR_UNKNOWN,
- ERR_UNKNOWN_OPCODE,
- ERR_NOT_ENOUGH_PARAMETERS,
- ERR_TOO_MANY_PARAMETERS,
- ERR_WRONG_PARAMETER,
- ERR_EXPECTED_PARAM_STR,
- ERR_EXPECTED_PARAM_VAL,
- ERR_EXPECTED_PARAM_REG,
- ERR_EXPECTED_PARAM_MEM,
- ERR_EXPECTED_PARAM_IMM,
- ERR_INCORRECT_BIN,
- ERR_INCORRECT_HEX,
- ERR_INCORRECT_DEC,
- ERR_LABEL_EXISTS,
- ERR_UNKNOWN_LABEL,
- ERR_NO_MATCHING_BRACKETS,
- ERR_EXT_CANT_EXTEND_OPCODE,
- ERR_EXT_PAR_NOT_EXT,
- ERR_WRONG_PARAMETER_ACC,
- ERR_WRONG_PARAMETER_MID_ACC,
- ERR_INVALID_REGISTER,
- ERR_OUT_RANGE_NUMBER
-};
-
-
-// Unless you want labels to carry over between files, you probably
-// want to create a new DSPAssembler for every file you assemble.
-class DSPAssembler
-{
-public:
- DSPAssembler(const AssemblerSettings &settings);
- ~DSPAssembler();
-
- // line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
- // one for each word of code, indicating the source assembler code line number it came from.
-
- // If returns false, call GetErrorString to get some text to present to the user.
- bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
-
- std::string GetErrorString() const { return last_error_str; }
- err_t GetError() const { return last_error; }
-
-private:
- struct param_t
- {
- u32 val;
- partype_t type;
- char *str;
- };
-
- enum segment_t
- {
- SEGMENT_CODE = 0,
- SEGMENT_DATA,
- SEGMENT_OVERLAY,
- SEGMENT_MAX
- };
-
- // Utility functions
- s32 ParseValue(const char *str);
- u32 ParseExpression(const char *ptr);
-
- u32 GetParams(char *parstr, param_t *par);
-
- void InitPass(int pass);
- bool AssembleFile(const char *fname, int pass);
-
- void ShowError(err_t err_code, const char *extra_info = NULL);
- // void ShowWarning(err_t err_code, const char *extra_info = NULL);
-
- char *FindBrackets(char *src, char *dst);
- const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
- bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
- void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
-
- char *gdg_buffer;
-
- std::string include_dir;
- std::string cur_line;
-
- u32 m_cur_addr;
- int m_totalSize;
- u8 m_cur_pass;
-
- LabelMap labels;
-
- u32 code_line;
- bool failed;
- std::string last_error_str;
- err_t last_error;
-
- typedef std::map<std::string, std::string> AliasMap;
- AliasMap aliases;
-
- segment_t cur_segment;
- u32 segment_addr[SEGMENT_MAX];
- int m_current_param;
- const AssemblerSettings settings_;
-};
-
-#endif // _DSP_ASSEMBLE_H
+/*====================================================================
+
+ project: GameCube DSP Tool (gcdsp)
+ created: 2005.03.04
+ mail: duddie@walla.com
+
+ Copyright (c) 2005 Duddie
+
+ 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; either version 2
+ of the License, or (at your option) any later version.
+
+ 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ ====================================================================*/
+
+#ifndef _DSP_ASSEMBLE_H
+#define _DSP_ASSEMBLE_H
+
+#include <string>
+#include <map>
+
+#include "Common.h"
+#include "disassemble.h"
+#include "DSPTables.h"
+#include "LabelMap.h"
+
+enum err_t
+{
+ ERR_OK = 0,
+ ERR_UNKNOWN,
+ ERR_UNKNOWN_OPCODE,
+ ERR_NOT_ENOUGH_PARAMETERS,
+ ERR_TOO_MANY_PARAMETERS,
+ ERR_WRONG_PARAMETER,
+ ERR_EXPECTED_PARAM_STR,
+ ERR_EXPECTED_PARAM_VAL,
+ ERR_EXPECTED_PARAM_REG,
+ ERR_EXPECTED_PARAM_MEM,
+ ERR_EXPECTED_PARAM_IMM,
+ ERR_INCORRECT_BIN,
+ ERR_INCORRECT_HEX,
+ ERR_INCORRECT_DEC,
+ ERR_LABEL_EXISTS,
+ ERR_UNKNOWN_LABEL,
+ ERR_NO_MATCHING_BRACKETS,
+ ERR_EXT_CANT_EXTEND_OPCODE,
+ ERR_EXT_PAR_NOT_EXT,
+ ERR_WRONG_PARAMETER_ACC,
+ ERR_WRONG_PARAMETER_MID_ACC,
+ ERR_INVALID_REGISTER,
+ ERR_OUT_RANGE_NUMBER
+};
+
+
+// Unless you want labels to carry over between files, you probably
+// want to create a new DSPAssembler for every file you assemble.
+class DSPAssembler
+{
+public:
+ DSPAssembler(const AssemblerSettings &settings);
+ ~DSPAssembler();
+
+ // line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
+ // one for each word of code, indicating the source assembler code line number it came from.
+
+ // If returns false, call GetErrorString to get some text to present to the user.
+ bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
+
+ std::string GetErrorString() const { return last_error_str; }
+ err_t GetError() const { return last_error; }
+
+private:
+ struct param_t
+ {
+ u32 val;
+ partype_t type;
+ char *str;
+ };
+
+ enum segment_t
+ {
+ SEGMENT_CODE = 0,
+ SEGMENT_DATA,
+ SEGMENT_OVERLAY,
+ SEGMENT_MAX
+ };
+
+ // Utility functions
+ s32 ParseValue(const char *str);
+ u32 ParseExpression(const char *ptr);
+
+ u32 GetParams(char *parstr, param_t *par);
+
+ void InitPass(int pass);
+ bool AssembleFile(const char *fname, int pass);
+
+ void ShowError(err_t err_code, const char *extra_info = NULL);
+ // void ShowWarning(err_t err_code, const char *extra_info = NULL);
+
+ char *FindBrackets(char *src, char *dst);
+ const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
+ bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
+ void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
+
+ char *gdg_buffer;
+
+ std::string include_dir;
+ std::string cur_line;
+
+ u32 m_cur_addr;
+ int m_totalSize;
+ u8 m_cur_pass;
+
+ LabelMap labels;
+
+ u32 code_line;
+ bool failed;
+ std::string last_error_str;
+ err_t last_error;
+
+ typedef std::map<std::string, std::string> AliasMap;
+ AliasMap aliases;
+
+ segment_t cur_segment;
+ u32 segment_addr[SEGMENT_MAX];
+ int m_current_param;
+ const AssemblerSettings settings_;
+};
+
+#endif // _DSP_ASSEMBLE_H
diff --git a/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.cpp b/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.cpp
index 6ee1e213b7..db1b28c09a 100644
--- a/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.cpp
+++ b/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.cpp
@@ -1,23 +1,23 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// 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 "DebuggerUIUtil.h"
-
-// The default font
-wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));
-
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// 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 "DebuggerUIUtil.h"
+
+// The default font
+wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));
+
diff --git a/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h b/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h
index fc75e9478e..12f11a2b62 100644
--- a/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h
+++ b/Source/Core/DebuggerUICommon/Src/DebuggerUIUtil.h
@@ -1,36 +1,36 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// 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/
-
-#ifndef _DEBUGGER_UI_UTIL_H
-#define _DEBUGGER_UI_UTIL_H
-
-#include <wx/wx.h>
-
-#define wxUSE_XPM_IN_MSW 1
-#define USE_XPM_BITMAPS 1
-
-// Defined in CodeWindow.cpp
-extern wxFont DebuggerFont;
-
-// define this to use XPMs everywhere (by default, BMPs are used under Win)
-// BMPs use less space, but aren't compiled into the executable on other platforms
-
-#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
-#error You need to enable XPM support to use XPM bitmaps with toolbar!
-#endif // USE_XPM_BITMAPS
-
-#endif
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// 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/
+
+#ifndef _DEBUGGER_UI_UTIL_H
+#define _DEBUGGER_UI_UTIL_H
+
+#include <wx/wx.h>
+
+#define wxUSE_XPM_IN_MSW 1
+#define USE_XPM_BITMAPS 1
+
+// Defined in CodeWindow.cpp
+extern wxFont DebuggerFont;
+
+// define this to use XPMs everywhere (by default, BMPs are used under Win)
+// BMPs use less space, but aren't compiled into the executable on other platforms
+
+#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
+#error You need to enable XPM support to use XPM bitmaps with toolbar!
+#endif // USE_XPM_BITMAPS
+
+#endif
diff --git a/Source/Core/DiscIO/Src/NANDContentLoader.h b/Source/Core/DiscIO/Src/NANDContentLoader.h
index 0494eba5c7..c4fe87911a 100644
--- a/Source/Core/DiscIO/Src/NANDContentLoader.h
+++ b/Source/Core/DiscIO/Src/NANDContentLoader.h
@@ -1,100 +1,100 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _NAND_CONTENT_LOADER_H
-#define _NAND_CONTENT_LOADER_H
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "Common.h"
-#include "Blob.h"
-#include "Volume.h"
-
-namespace DiscIO
-{
-
-struct SNANDContent
-{
- u32 m_ContentID;
- u16 m_Index;
- u16 m_Type;
- u32 m_Size;
- u8 m_SHA1Hash[20];
- u8 m_Header[36]; //all of the above
-
- u8* m_pData;
-};
-
-// pure virtual interface so just the NANDContentManager can create these files only
-class INANDContentLoader
-{
-public:
-
- INANDContentLoader() {}
-
- virtual ~INANDContentLoader() {}
-
- virtual bool IsValid() const = 0;
- virtual u64 GetTitleID() const = 0;
- virtual u16 GetIosVersion() const = 0;
- virtual u32 GetBootIndex() const = 0;
- virtual size_t GetContentSize() const = 0;
- virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
- virtual const u8* GetTicketView() const = 0;
- virtual const u8* GetTmdHeader() const = 0;
- virtual const std::vector<SNANDContent>& GetContent() const = 0;
- virtual const u16 GetTitleVersion() const = 0;
- virtual const u16 GetNumEntries() const = 0;
- virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
-
- enum
- {
- TICKET_VIEW_SIZE = 0x58,
- TMD_HEADER_SIZE = 0x1e4,
- CONTENT_HEADER_SIZE = 0x24
- };
-};
-
-
-// we open the NAND Content files to often... lets cache them
-class CNANDContentManager
-{
-public:
-
- static CNANDContentManager& Access() { return m_Instance; }
-
- const INANDContentLoader& GetNANDLoader(const std::string& _rName);
-
-private:
-
- CNANDContentManager() {};
-
- ~CNANDContentManager();
-
- static CNANDContentManager m_Instance;
-
- typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
- CNANDContentMap m_Map;
-
-};
-
-}
-
-#endif
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _NAND_CONTENT_LOADER_H
+#define _NAND_CONTENT_LOADER_H
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "Common.h"
+#include "Blob.h"
+#include "Volume.h"
+
+namespace DiscIO
+{
+
+struct SNANDContent
+{
+ u32 m_ContentID;
+ u16 m_Index;
+ u16 m_Type;
+ u32 m_Size;
+ u8 m_SHA1Hash[20];
+ u8 m_Header[36]; //all of the above
+
+ u8* m_pData;
+};
+
+// pure virtual interface so just the NANDContentManager can create these files only
+class INANDContentLoader
+{
+public:
+
+ INANDContentLoader() {}
+
+ virtual ~INANDContentLoader() {}
+
+ virtual bool IsValid() const = 0;
+ virtual u64 GetTitleID() const = 0;
+ virtual u16 GetIosVersion() const = 0;
+ virtual u32 GetBootIndex() const = 0;
+ virtual size_t GetContentSize() const = 0;
+ virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
+ virtual const u8* GetTicketView() const = 0;
+ virtual const u8* GetTmdHeader() const = 0;
+ virtual const std::vector<SNANDContent>& GetContent() const = 0;
+ virtual const u16 GetTitleVersion() const = 0;
+ virtual const u16 GetNumEntries() const = 0;
+ virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
+
+ enum
+ {
+ TICKET_VIEW_SIZE = 0x58,
+ TMD_HEADER_SIZE = 0x1e4,
+ CONTENT_HEADER_SIZE = 0x24
+ };
+};
+
+
+// we open the NAND Content files to often... lets cache them
+class CNANDContentManager
+{
+public:
+
+ static CNANDContentManager& Access() { return m_Instance; }
+
+ const INANDContentLoader& GetNANDLoader(const std::string& _rName);
+
+private:
+
+ CNANDContentManager() {};
+
+ ~CNANDContentManager();
+
+ static CNANDContentManager m_Instance;
+
+ typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
+ CNANDContentMap m_Map;
+
+};
+
+}
+
+#endif
+
diff --git a/Source/Core/DiscIO/Src/VolumeWad.h b/Source/Core/DiscIO/Src/VolumeWad.h
index 6d37d8fdf8..2d72bb0aa9 100644
--- a/Source/Core/DiscIO/Src/VolumeWad.h
+++ b/Source/Core/DiscIO/Src/VolumeWad.h
@@ -1,52 +1,52 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#pragma once
-
-#include "Volume.h"
-#include "Blob.h"
-#include "NANDContentLoader.h"
-
-// --- this volume type is used for Wad files ---
-// Some of this code might look redundant with the CNANDContentLoader class, however,
-// We do not do any decryption here, we do raw read, so things are -Faster-
-
-namespace DiscIO
-{
-class CVolumeWAD : public IVolume
-{
-public:
- CVolumeWAD(IBlobReader* _pReader);
- ~CVolumeWAD();
- bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
- bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
- bool GetTitleID(u8* _pBuffer) const;
- std::string GetUniqueID() const;
- std::string GetMakerID() const;
- std::string GetName() const;
- u32 GetFSTSize() const { return 0; }
- std::string GetApploaderDate() const { return "0"; }
- ECountry GetCountry() const;
- u64 GetSize() const;
-
-private:
- IBlobReader* m_pReader;
- u64 m_titleID;
- u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
-};
-
-} // namespace
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#pragma once
+
+#include "Volume.h"
+#include "Blob.h"
+#include "NANDContentLoader.h"
+
+// --- this volume type is used for Wad files ---
+// Some of this code might look redundant with the CNANDContentLoader class, however,
+// We do not do any decryption here, we do raw read, so things are -Faster-
+
+namespace DiscIO
+{
+class CVolumeWAD : public IVolume
+{
+public:
+ CVolumeWAD(IBlobReader* _pReader);
+ ~CVolumeWAD();
+ bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
+ bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
+ bool GetTitleID(u8* _pBuffer) const;
+ std::string GetUniqueID() const;
+ std::string GetMakerID() const;
+ std::string GetName() const;
+ u32 GetFSTSize() const { return 0; }
+ std::string GetApploaderDate() const { return "0"; }
+ ECountry GetCountry() const;
+ u64 GetSize() const;
+
+private:
+ IBlobReader* m_pReader;
+ u64 m_titleID;
+ u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
+};
+
+} // namespace
diff --git a/Source/Core/DiscIO/Src/WiiWad.cpp b/Source/Core/DiscIO/Src/WiiWad.cpp
index 73f22f31b5..10efafacdf 100644
--- a/Source/Core/DiscIO/Src/WiiWad.cpp
+++ b/Source/Core/DiscIO/Src/WiiWad.cpp
@@ -1,156 +1,156 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "stdafx.h"
-#include "NANDContentLoader.h"
-
-#include <algorithm>
-#include <cctype>
-#include "MathUtil.h"
-#include "FileUtil.h"
-#include "Log.h"
-#include "WiiWad.h"
-
-namespace DiscIO
-{
-
-class CBlobBigEndianReader
-{
-public:
- CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
-
- u32 Read32(u64 _Offset)
- {
- u32 Temp;
- m_rReader.Read(_Offset, 4, (u8*)&Temp);
- return(Common::swap32(Temp));
- }
-
-private:
- DiscIO::IBlobReader& m_rReader;
-};
-
-WiiWAD::WiiWAD(const std::string& _rName)
-{
- DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
- if (pReader == NULL)
- {
- m_Valid = false;
- return;
- }
-
- m_Valid = ParseWAD(*pReader);
- delete pReader;
-}
-
-WiiWAD::~WiiWAD()
-{
- if (m_Valid)
- {
- delete m_pCertificateChain;
- delete m_pTicket;
- delete m_pTMD;
- delete m_pDataApp;
- delete m_pFooter;
- }
-}
-
-u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
-{
- if (_Size > 0)
- {
- u8* pTmpBuffer = new u8[_Size];
- _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
-
- if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
- {
- ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
- PanicAlert("WiiWAD: Could not read from file");
- }
- return pTmpBuffer;
- }
- return NULL;
-}
-
-
-bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
-{
- CBlobBigEndianReader ReaderBig(_rReader);
-
- // get header size
- u32 HeaderSize = ReaderBig.Read32(0);
- if (HeaderSize != 0x20)
- {
- _dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
- return false;
- }
-
- // get header
- u8 Header[0x20];
- _rReader.Read(0, HeaderSize, Header);
- u32 HeaderType = ReaderBig.Read32(0x4);
- if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
- return false;
-
- m_CertificateChainSize = ReaderBig.Read32(0x8);
- u32 Reserved = ReaderBig.Read32(0xC);
- m_TicketSize = ReaderBig.Read32(0x10);
- m_TMDSize = ReaderBig.Read32(0x14);
- m_DataAppSize = ReaderBig.Read32(0x18);
- m_FooterSize = ReaderBig.Read32(0x1C);
- _dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
-
- u32 Offset = 0x40;
- m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
- m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
- m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
- m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
- m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
-
- return true;
-}
-
-bool WiiWAD::IsWiiWAD(const std::string& _rName)
-{
- DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
- if (pReader == NULL)
- return false;
-
- CBlobBigEndianReader Reader(*pReader);
- bool Result = false;
-
- // check for wii wad
- if (Reader.Read32(0x00) == 0x20)
- {
- u32 WADTYpe = Reader.Read32(0x04);
- switch(WADTYpe)
- {
- case 0x49730000:
- case 0x69620000:
- Result = true;
- }
- }
-
- delete pReader;
-
- return Result;
-}
-
-
-
-} // namespace end
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "stdafx.h"
+#include "NANDContentLoader.h"
+
+#include <algorithm>
+#include <cctype>
+#include "MathUtil.h"
+#include "FileUtil.h"
+#include "Log.h"
+#include "WiiWad.h"
+
+namespace DiscIO
+{
+
+class CBlobBigEndianReader
+{
+public:
+ CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
+
+ u32 Read32(u64 _Offset)
+ {
+ u32 Temp;
+ m_rReader.Read(_Offset, 4, (u8*)&Temp);
+ return(Common::swap32(Temp));
+ }
+
+private:
+ DiscIO::IBlobReader& m_rReader;
+};
+
+WiiWAD::WiiWAD(const std::string& _rName)
+{
+ DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
+ if (pReader == NULL)
+ {
+ m_Valid = false;
+ return;
+ }
+
+ m_Valid = ParseWAD(*pReader);
+ delete pReader;
+}
+
+WiiWAD::~WiiWAD()
+{
+ if (m_Valid)
+ {
+ delete m_pCertificateChain;
+ delete m_pTicket;
+ delete m_pTMD;
+ delete m_pDataApp;
+ delete m_pFooter;
+ }
+}
+
+u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
+{
+ if (_Size > 0)
+ {
+ u8* pTmpBuffer = new u8[_Size];
+ _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
+
+ if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
+ {
+ ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
+ PanicAlert("WiiWAD: Could not read from file");
+ }
+ return pTmpBuffer;
+ }
+ return NULL;
+}
+
+
+bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
+{
+ CBlobBigEndianReader ReaderBig(_rReader);
+
+ // get header size
+ u32 HeaderSize = ReaderBig.Read32(0);
+ if (HeaderSize != 0x20)
+ {
+ _dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
+ return false;
+ }
+
+ // get header
+ u8 Header[0x20];
+ _rReader.Read(0, HeaderSize, Header);
+ u32 HeaderType = ReaderBig.Read32(0x4);
+ if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
+ return false;
+
+ m_CertificateChainSize = ReaderBig.Read32(0x8);
+ u32 Reserved = ReaderBig.Read32(0xC);
+ m_TicketSize = ReaderBig.Read32(0x10);
+ m_TMDSize = ReaderBig.Read32(0x14);
+ m_DataAppSize = ReaderBig.Read32(0x18);
+ m_FooterSize = ReaderBig.Read32(0x1C);
+ _dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
+
+ u32 Offset = 0x40;
+ m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
+ m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
+ m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
+ m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
+ m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
+
+ return true;
+}
+
+bool WiiWAD::IsWiiWAD(const std::string& _rName)
+{
+ DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
+ if (pReader == NULL)
+ return false;
+
+ CBlobBigEndianReader Reader(*pReader);
+ bool Result = false;
+
+ // check for wii wad
+ if (Reader.Read32(0x00) == 0x20)
+ {
+ u32 WADTYpe = Reader.Read32(0x04);
+ switch(WADTYpe)
+ {
+ case 0x49730000:
+ case 0x69620000:
+ Result = true;
+ }
+ }
+
+ delete pReader;
+
+ return Result;
+}
+
+
+
+} // namespace end
+
diff --git a/Source/Core/DiscIO/Src/WiiWad.h b/Source/Core/DiscIO/Src/WiiWad.h
index 10b2ad867e..e07df2aa3a 100644
--- a/Source/Core/DiscIO/Src/WiiWad.h
+++ b/Source/Core/DiscIO/Src/WiiWad.h
@@ -1,78 +1,78 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _WII_WAD_H
-#define _WII_WAD_H
-
-#include <string>
-#include <vector>
-#include <map>
-
-#include "Common.h"
-#include "Blob.h"
-#include "Volume.h"
-
-namespace DiscIO
-{
-
-class WiiWAD
-{
-public:
-
- WiiWAD(const std::string& _rName);
-
- ~WiiWAD();
-
- bool IsValid() const { return m_Valid; }
- u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
- u32 GetTicketSize() const { return m_TicketSize; }
- u32 GetTMDSize() const { return m_TMDSize; }
- u32 GetDataAppSize() const { return m_DataAppSize; }
- u32 GetFooterSize() const { return m_FooterSize; }
-
- u8* GetCertificateChain() const { return m_pCertificateChain; }
- u8* GetTicket() const { return m_pTicket; }
- u8* GetTMD() const { return m_pTMD; }
- u8* GetDataApp() const { return m_pDataApp; }
- u8* GetFooter() const { return m_pFooter; }
-
- static bool IsWiiWAD(const std::string& _rName);
-
-private:
-
- bool m_Valid;
-
- u32 m_CertificateChainSize;
- u32 m_TicketSize;
- u32 m_TMDSize;
- u32 m_DataAppSize;
- u32 m_FooterSize;
-
- u8* m_pCertificateChain;
- u8* m_pTicket;
- u8* m_pTMD;
- u8* m_pDataApp;
- u8* m_pFooter;
-
- u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
- bool ParseWAD(DiscIO::IBlobReader& _rReader);
-};
-
-}
-
-#endif
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _WII_WAD_H
+#define _WII_WAD_H
+
+#include <string>
+#include <vector>
+#include <map>
+
+#include "Common.h"
+#include "Blob.h"
+#include "Volume.h"
+
+namespace DiscIO
+{
+
+class WiiWAD
+{
+public:
+
+ WiiWAD(const std::string& _rName);
+
+ ~WiiWAD();
+
+ bool IsValid() const { return m_Valid; }
+ u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
+ u32 GetTicketSize() const { return m_TicketSize; }
+ u32 GetTMDSize() const { return m_TMDSize; }
+ u32 GetDataAppSize() const { return m_DataAppSize; }
+ u32 GetFooterSize() const { return m_FooterSize; }
+
+ u8* GetCertificateChain() const { return m_pCertificateChain; }
+ u8* GetTicket() const { return m_pTicket; }
+ u8* GetTMD() const { return m_pTMD; }
+ u8* GetDataApp() const { return m_pDataApp; }
+ u8* GetFooter() const { return m_pFooter; }
+
+ static bool IsWiiWAD(const std::string& _rName);
+
+private:
+
+ bool m_Valid;
+
+ u32 m_CertificateChainSize;
+ u32 m_TicketSize;
+ u32 m_TMDSize;
+ u32 m_DataAppSize;
+ u32 m_FooterSize;
+
+ u8* m_pCertificateChain;
+ u8* m_pTicket;
+ u8* m_pTMD;
+ u8* m_pDataApp;
+ u8* m_pFooter;
+
+ u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
+ bool ParseWAD(DiscIO::IBlobReader& _rReader);
+};
+
+}
+
+#endif
+
diff --git a/Source/Core/DolphinWX/Src/NetEvent.cpp b/Source/Core/DolphinWX/Src/NetEvent.cpp
index 246879c0a8..6fc7280b1e 100644
--- a/Source/Core/DolphinWX/Src/NetEvent.cpp
+++ b/Source/Core/DolphinWX/Src/NetEvent.cpp
@@ -1,288 +1,288 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "NetWindow.h"
-
-void ClientSide::OnClientData(unsigned char data)
-{
- unsigned char sent = 0;
- u32 buffer_size;
- size_t recv_size;
- char *buffer = NULL;
-
- switch (data)
- {
- case 0x10: // Player joined server
- {
- // Read GameFound
- m_socket.Receive((char*)&sent, 1, recv_size);
-
- // Read nickname
- m_socket.Receive((char*)&buffer_size, 4, recv_size);
- buffer = new char[buffer_size+1];
- m_socket.Receive(buffer, buffer_size+1, recv_size);
- Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
-
- if (sent != 0x1F)
- for (int i = 0; i < 4; i++)
- Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
-
- m_numplayers++;
- Event->SendEvent(HOST_NEWPLAYER);
- break;
- }
- case 0x11: // Player left server
- {
- // Read Nickname
- m_socket.Receive((char*)&buffer_size, 4, recv_size);
- buffer = new char[buffer_size+1];
- m_socket.Receive(buffer, buffer_size+1, recv_size);
-
- Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
-
- m_numplayers--;
- Event->SendEvent(HOST_PLAYERLEFT);
- break;
- }
- case 0x15: // Ping Player
- {
- m_socket.Receive((char*)&buffer_size, 4, recv_size);
- m_socket.Send((const char*)&buffer_size, 4);
-
- break;
- }
- case 0x20: // IP request
- {
- //buffer_size = m_addr.size();
- //m_socket.Send((const char*)&buffer_size, 4);
- m_socket.Send((const char*)&data, 1);
- m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
-
- break;
- }
- case 0x30: // Chat message received from server
- {
- m_socket.Receive((char*)&buffer_size, 4, recv_size);
- buffer = new char[buffer_size+1];
- m_socket.Receive(buffer, buffer_size+1, recv_size);
-
- if (recv_size > 1024)
- {
- //something wrong...
- delete[] buffer;
- return;
- }
-
- Event->AppendText(wxString::FromAscii(buffer));
-
- break;
- }
- case 0x35: // ChangeGame message received
- {
- m_socket.Receive((char*)&buffer_size, 4, recv_size);
- buffer = new char[buffer_size+1];
- m_socket.Receive(buffer, buffer_size+1, recv_size);
-
- m_selectedgame = std::string(buffer);
- Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
-
- // Tell the server if the game's been found
- m_socket.Send((const char*)&data, 1);
- CheckGameFound();
-
- Event->SendEvent(GUI_UPDATE);
-
- break;
- }
- case 0x40: // Ready message received
- {
- m_socket.Receive((char*)&buffer_size, 4, recv_size);
- buffer = new char[buffer_size+1];
- m_socket.Receive(buffer, buffer_size+1, recv_size);
-
- if (recv_size > 1024)
- {
- delete[] buffer;
- return;
- }
-
- Event->AppendText(wxString::FromAscii(buffer));
-
- break;
- }
- case 0x50: // Everyone is Ready message received
- {
- // Load the game and start synching
- m_netptr->LoadGame();
-
- break;
- }
- case 0xA1: // Received pad data from host in versus mode
- {
- if (m_data_received)
- wxThread::Sleep(10);
-
- m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
- m_data_received = true;
-
-#ifdef NET_DEBUG
- char sent[64];
- sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
- Event->AppendText(wxString::FromAscii(sent));
-#endif
- break;
- }
- }
-
- delete[] buffer;
-}
-
-void ServerSide::OnServerData(int sock, unsigned char data)
-{
- size_t recv_size;
- char *buffer = NULL;
- unsigned char sent;
- unsigned int four_bytes;
-
- switch (data)
- {
- case 0x15: // Ping Request
- {
- m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
- m_client[sock].socket.Send((const char*)&four_bytes, 4);
-
- break;
- }
- case 0x20: // IP request response
- {
- buffer = new char[24];
- // Read IP Address
- m_client[sock].socket.Receive(buffer, 24, recv_size);
-
- Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
-
- break;
- }
- case 0x30: // Chat message
- {
- buffer = new char[1024];
-
- m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
- m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
-
- if (recv_size > 1024)
- {
- //something wrong...
- delete[] buffer;
- return;
- }
-
- sent = 0x30;
- // Send to all
- for (int i=0; i < m_numplayers ; i++)
- {
- if (i == sock)
- continue;
-
- m_client[i].socket.Send((const char*)&sent, 1);
-
- m_client[1].socket.Send((const char*)&four_bytes, 4);
- m_client[i].socket.Send(buffer, recv_size);
- }
-
- Event->AppendText(wxString::FromAscii(buffer));
-
- break;
- }
- case 0x35: // Change game response received
- {
- // Receive isGameFound response (0x1F / 0x1A)
- m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
-
- // If game is not found
- if (sent != 0x1F)
- {
- sent = 0x30;
-
- wxString error_str = wxString::Format(
- wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
- four_bytes = (int)error_str.size();
-
- for (int i=0; i < 2; i++)
- Event->AppendText(error_str);
-
- // Send to all
- for (int i=0; i < m_numplayers ; i++)
- {
- if (i == sock)
- continue;
- m_client[i].socket.Send((const char*)&sent, 1);
-
- m_client[i].socket.Send((const char*)&four_bytes, 4);
- m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
- }
- }
-
- break;
- }
- case 0x40: // Ready message received
- {
- std::string buffer_str;
-
- m_client[sock].ready = !m_client[sock].ready;
-
- if (m_client[sock].ready)
- buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
- else
- buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
-
- four_bytes = (int)buffer_str.size();
-
- // Send to all
- for (int i=0; i < m_numplayers ; i++)
- {
- m_client[i].socket.Send((const char*)&data, 1);
-
- m_client[i].socket.Send((const char*)&four_bytes, 4);
- m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
- }
-
- Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
- IsEveryoneReady();
-
- break;
- }
- case 0xA1: // Received pad data from a client
- {
- if (m_data_received)
- wxThread::Sleep(10);
-
- m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
- m_data_received = true;
-
-#ifdef NET_DEBUG
- char sent[64];
- sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
- Event->AppendText(wxString::FromAscii(sent));
-#endif
- break;
- }
- }
-
- delete[] buffer;
-}
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "NetWindow.h"
+
+void ClientSide::OnClientData(unsigned char data)
+{
+ unsigned char sent = 0;
+ u32 buffer_size;
+ size_t recv_size;
+ char *buffer = NULL;
+
+ switch (data)
+ {
+ case 0x10: // Player joined server
+ {
+ // Read GameFound
+ m_socket.Receive((char*)&sent, 1, recv_size);
+
+ // Read nickname
+ m_socket.Receive((char*)&buffer_size, 4, recv_size);
+ buffer = new char[buffer_size+1];
+ m_socket.Receive(buffer, buffer_size+1, recv_size);
+ Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
+
+ if (sent != 0x1F)
+ for (int i = 0; i < 4; i++)
+ Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
+
+ m_numplayers++;
+ Event->SendEvent(HOST_NEWPLAYER);
+ break;
+ }
+ case 0x11: // Player left server
+ {
+ // Read Nickname
+ m_socket.Receive((char*)&buffer_size, 4, recv_size);
+ buffer = new char[buffer_size+1];
+ m_socket.Receive(buffer, buffer_size+1, recv_size);
+
+ Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
+
+ m_numplayers--;
+ Event->SendEvent(HOST_PLAYERLEFT);
+ break;
+ }
+ case 0x15: // Ping Player
+ {
+ m_socket.Receive((char*)&buffer_size, 4, recv_size);
+ m_socket.Send((const char*)&buffer_size, 4);
+
+ break;
+ }
+ case 0x20: // IP request
+ {
+ //buffer_size = m_addr.size();
+ //m_socket.Send((const char*)&buffer_size, 4);
+ m_socket.Send((const char*)&data, 1);
+ m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
+
+ break;
+ }
+ case 0x30: // Chat message received from server
+ {
+ m_socket.Receive((char*)&buffer_size, 4, recv_size);
+ buffer = new char[buffer_size+1];
+ m_socket.Receive(buffer, buffer_size+1, recv_size);
+
+ if (recv_size > 1024)
+ {
+ //something wrong...
+ delete[] buffer;
+ return;
+ }
+
+ Event->AppendText(wxString::FromAscii(buffer));
+
+ break;
+ }
+ case 0x35: // ChangeGame message received
+ {
+ m_socket.Receive((char*)&buffer_size, 4, recv_size);
+ buffer = new char[buffer_size+1];
+ m_socket.Receive(buffer, buffer_size+1, recv_size);
+
+ m_selectedgame = std::string(buffer);
+ Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
+
+ // Tell the server if the game's been found
+ m_socket.Send((const char*)&data, 1);
+ CheckGameFound();
+
+ Event->SendEvent(GUI_UPDATE);
+
+ break;
+ }
+ case 0x40: // Ready message received
+ {
+ m_socket.Receive((char*)&buffer_size, 4, recv_size);
+ buffer = new char[buffer_size+1];
+ m_socket.Receive(buffer, buffer_size+1, recv_size);
+
+ if (recv_size > 1024)
+ {
+ delete[] buffer;
+ return;
+ }
+
+ Event->AppendText(wxString::FromAscii(buffer));
+
+ break;
+ }
+ case 0x50: // Everyone is Ready message received
+ {
+ // Load the game and start synching
+ m_netptr->LoadGame();
+
+ break;
+ }
+ case 0xA1: // Received pad data from host in versus mode
+ {
+ if (m_data_received)
+ wxThread::Sleep(10);
+
+ m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
+ m_data_received = true;
+
+#ifdef NET_DEBUG
+ char sent[64];
+ sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
+ Event->AppendText(wxString::FromAscii(sent));
+#endif
+ break;
+ }
+ }
+
+ delete[] buffer;
+}
+
+void ServerSide::OnServerData(int sock, unsigned char data)
+{
+ size_t recv_size;
+ char *buffer = NULL;
+ unsigned char sent;
+ unsigned int four_bytes;
+
+ switch (data)
+ {
+ case 0x15: // Ping Request
+ {
+ m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
+ m_client[sock].socket.Send((const char*)&four_bytes, 4);
+
+ break;
+ }
+ case 0x20: // IP request response
+ {
+ buffer = new char[24];
+ // Read IP Address
+ m_client[sock].socket.Receive(buffer, 24, recv_size);
+
+ Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
+
+ break;
+ }
+ case 0x30: // Chat message
+ {
+ buffer = new char[1024];
+
+ m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
+ m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
+
+ if (recv_size > 1024)
+ {
+ //something wrong...
+ delete[] buffer;
+ return;
+ }
+
+ sent = 0x30;
+ // Send to all
+ for (int i=0; i < m_numplayers ; i++)
+ {
+ if (i == sock)
+ continue;
+
+ m_client[i].socket.Send((const char*)&sent, 1);
+
+ m_client[1].socket.Send((const char*)&four_bytes, 4);
+ m_client[i].socket.Send(buffer, recv_size);
+ }
+
+ Event->AppendText(wxString::FromAscii(buffer));
+
+ break;
+ }
+ case 0x35: // Change game response received
+ {
+ // Receive isGameFound response (0x1F / 0x1A)
+ m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
+
+ // If game is not found
+ if (sent != 0x1F)
+ {
+ sent = 0x30;
+
+ wxString error_str = wxString::Format(
+ wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
+ four_bytes = (int)error_str.size();
+
+ for (int i=0; i < 2; i++)
+ Event->AppendText(error_str);
+
+ // Send to all
+ for (int i=0; i < m_numplayers ; i++)
+ {
+ if (i == sock)
+ continue;
+ m_client[i].socket.Send((const char*)&sent, 1);
+
+ m_client[i].socket.Send((const char*)&four_bytes, 4);
+ m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
+ }
+ }
+
+ break;
+ }
+ case 0x40: // Ready message received
+ {
+ std::string buffer_str;
+
+ m_client[sock].ready = !m_client[sock].ready;
+
+ if (m_client[sock].ready)
+ buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
+ else
+ buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
+
+ four_bytes = (int)buffer_str.size();
+
+ // Send to all
+ for (int i=0; i < m_numplayers ; i++)
+ {
+ m_client[i].socket.Send((const char*)&data, 1);
+
+ m_client[i].socket.Send((const char*)&four_bytes, 4);
+ m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
+ }
+
+ Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
+ IsEveryoneReady();
+
+ break;
+ }
+ case 0xA1: // Received pad data from a client
+ {
+ if (m_data_received)
+ wxThread::Sleep(10);
+
+ m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
+ m_data_received = true;
+
+#ifdef NET_DEBUG
+ char sent[64];
+ sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
+ Event->AppendText(wxString::FromAscii(sent));
+#endif
+ break;
+ }
+ }
+
+ delete[] buffer;
+}
+
diff --git a/Source/Core/DolphinWX/Src/NetFunctions.cpp b/Source/Core/DolphinWX/Src/NetFunctions.cpp
index fb34fa358f..5c544970b7 100644
--- a/Source/Core/DolphinWX/Src/NetFunctions.cpp
+++ b/Source/Core/DolphinWX/Src/NetFunctions.cpp
@@ -1,590 +1,590 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "NetWindow.h"
-#include "HW/SI_DeviceGCController.h"
-
-NetPlay *NetClass_ptr = NULL;
-
-void NetPlay::IsGameFound(unsigned char * ptr, std::string m_selected)
-{
- m_critical.Enter();
-
- m_selectedGame = m_selected;
-
- if (m_games.find(m_selected) != std::string::npos)
- *ptr = 0x1F;
- else
- *ptr = 0x1A;
-
- m_critical.Leave();
-}
-
-void NetPlay::OnNetEvent(wxCommandEvent& event)
-{
- switch (event.GetId())
- {
- case HOST_FULL:
- {
- AppendText(_(" Server is Full !\n*You have been Disconnected.\n\n"));
- m_isHosting = 2;
- }
- break;
- case HOST_ERROR:
- {
- if (m_isHosting == 0)
- {
- AppendText(_("ERROR : Network Error !\n*You have been Disconnected.\n\n"));
- m_isHosting = 2;
- }
- else
- {
- m_numClients--;
- AppendText( wxString::Format(wxT("ERROR : Network Error !\n"
- "*Player : %s has been dropped from the game.\n\n"),
- (const char *)event.GetString().mb_str()) );
- }
- }
- break;
- case HOST_DISCONNECTED:
- {
- // Event sent from Client's thread, it means that the thread
- // has been killed and so we tell the GUI thread.
- AppendText(_("*Connection to Host lost.\n*You have been Disconnected.\n\n"));
- m_isHosting = 2;
- m_numClients--;
- }
- break;
- case HOST_PLAYERLEFT:
- {
- m_numClients--;
- }
- break;
- case HOST_NEWPLAYER:
- {
- m_numClients++;
- m_NetModel = event.GetInt();
- }
- break;
- case CLIENTS_READY:
- {
- m_clients_ready = true;
-
- // Tell clients everyone is ready...
- if (m_ready)
- LoadGame();
- }
- break;
- case CLIENTS_NOTREADY:
- {
- m_clients_ready = false;
- }
- break;
- case GUI_UPDATE:
- UpdateNetWindow(false);
- break;
- case ADD_TEXT:
- AppendText(event.GetString());
- break;
- case ADD_INFO:
- UpdateNetWindow(true, event.GetString());
- break;
- }
-}
-
-void ServerSide::IsEveryoneReady()
-{
- int nb_ready = 0;
-
- for (int i=0; i < m_numplayers ; i++)
- if (m_client[i].ready)
- nb_ready++;
-
- if (nb_ready == m_numplayers)
- Event->SendEvent(CLIENTS_READY);
- else
- Event->SendEvent(CLIENTS_NOTREADY);
-}
-
-// Actual Core function which is called on every frame
-int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
-{
- if (NetClass_ptr != NULL)
- return NetClass_ptr->GetNetPads(numPAD, PadStatus, PADStatus) ? 1 : 0;
- else
- return 2;
-}
-
-void NetPlay::LoadGame()
-{
- // Two implementations, one "p2p" implementation which sends to peer
- // and receive from peer 2 players max. and another which uses server model
- // and always sends to the server which then send it back to all the clients
- // -> P2P model is faster, but is limited to 2 players
- // -> Server model is slower, but supports up to 4 players
-
- if (m_isHosting == 1)
- {
- long ping[3] = {0};
- unsigned char value = 0x50;
-
- // Get ping
- m_sock_server->Write(0, 0, 0, ping);
- float fping = (ping[0]+ping[1]+ping[2])/(float)m_numClients;
-
- // Tell client everyone is ready
- for (int i=0; i < m_numClients ; i++)
- m_sock_server->Write(i, (const char*)&value, 1);
-
- // Sleep a bit to start the game at more or less the same time than the peer
- wxMilliSleep(fping/2);
-
- m_Logging->AppendText(wxString::Format(wxT("** Everyone is ready... Loading Game ! **\n"
- "** Ping to client(s) is : %f ms\n"), fping));
- }
- else
- m_Logging->AppendText(_("** Everyone is ready... Loading Game ! **\n"));
-
- // TODO : Throttle should be on by default, to avoid stuttering
- //soundStream->GetMixer()->SetThrottle(true);
-
- int line_p = 0;
- int line_n = 0;
-
- m_critical.Enter();
- std::string tmp = m_games.substr(0, m_games.find(m_selectedGame));
-
- for (int i=0; i < (int)tmp.size(); i++)
- if (tmp.c_str()[i] == '\n')
- line_n++;
-
- // Enable
- NetClass_ptr = this;
- m_timer.Start();
- m_data_received = false;
- m_critical.Leave();
-
- // Find corresponding game path
- for (int i=0; i < (int)m_paths.size(); i++)
- {
- if (m_paths.c_str()[i] == '\n')
- line_p++;
-
- if (line_n == line_p) {
- // Game path found, get its string
- int str_pos = line_p > 0 ? i+1 : i;
- int str_end = (int)m_paths.find('\n', str_pos);
- // Boot the selected game
- BootManager::BootCore(m_paths.substr(str_pos, str_end - str_pos));
- break;
- }
- }
-}
-
-bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues)
-{
- if (m_numClients < 1)
- {
- m_Logging->AppendText(_("** WARNING : "
- "Ping too high (>2000ms) or connection lost ! \n"
- "** WARNING : Stopping Netplay... \n"));
- NetClass_ptr = NULL;
- return false;
- }
-
- // Store current pad status in netValues[]
- netValues[0] = (u32)((u8)PadStatus.stickY);
- netValues[0] |= (u32)((u8)PadStatus.stickX << 8);
- netValues[0] |= (u32)((u16)PadStatus.button << 16);
- netValues[0] |= 0x00800000;
- netValues[1] = (u8)PadStatus.triggerRight;
- netValues[1] |= (u32)((u8)PadStatus.triggerLeft << 8);
- netValues[1] |= (u32)((u8)PadStatus.substickY << 16);
- netValues[1] |= (u32)((u8)PadStatus.substickX << 24);
-
- if (m_NetModel == 0) // Use 2 players Model
- {
- if (padnb == 0)
- {
- // Update the timer and increment total frame number
- m_frame++;
-
- if (m_frame == 1)
- {
- // We make sure everyone's pad is enabled
- for (int i = 0; i < m_numClients+1; i++)
- SerialInterface::ChangeDevice(SI_GC_CONTROLLER, i);
-
- // Better disable unused ports
- for (int i = m_numClients+1; i < 4; i++)
- SerialInterface::ChangeDevice(SI_DUMMY, i);
- }
-
- if (m_timer.GetTimeDifference() > 1000)
- m_timer.Update();
-
-#ifdef NET_DEBUG
- char sent[64];
- sprintf(sent, "Sent Values: 0x%08x : 0x%08x \n", netValues[0], netValues[1]);
- m_Logging->AppendText(wxString::FromAscii(sent));
-#endif
- unsigned char player = 0;
-
-#ifdef USE_TCP
- unsigned char init_value = 0xA1;
-
- if (m_isHosting == 1) {
- // Send pads values
- m_sock_server->Write(0, (const char*)&init_value, 1);
- m_sock_server->Write(0, (const char*)netValues, 8);
- }
- else {
- // Send pads values
- m_sock_client->Write((const char*)&init_value, 1);
- m_sock_client->Write((const char*)netValues, 8);
- player = 1;
- }
-#else // UDP
- u32 padsValues[3];
-
- padsValues[0] = m_frame;
- padsValues[1] = netValues[0];
- padsValues[2] = netValues[1];
-
- if (m_isHosting == 1) {
- // Send pads values
- m_sock_server->WriteUDP(0, (const char*)padsValues, 12);
- }
- else {
- // Send pads values
- m_sock_client->WriteUDP((const char*)padsValues, 12);
- player = 1;
- }
-#endif
-
- if (!m_data_received)
- {
- // Save pad values
- m_pads[player].nHi[m_loopframe] = netValues[0];
- m_pads[player].nLow[m_loopframe] = netValues[1];
-
- // Try to read from peer...
- if (m_isHosting == 1)
- m_data_received = m_sock_server->isNewPadData(0, false);
- else
- m_data_received = m_sock_client->isNewPadData(0, false);
-
- if (m_data_received)
- {
- // Set our practical frame delay
- m_frameDelay = m_loopframe;
- m_loopframe = 0;
-
- // First Data has been received !
- m_Logging->AppendText(_("** Data received from Peer. Starting Sync !"));
- m_Logging->AppendText(wxString::Format(wxT(" Frame Delay : %d **\n"), m_frameDelay));
- }
- else {
- if (m_loopframe > 126)
- {
- m_Logging->AppendText(_("** WARNING : "
- "Ping too high (>2000ms) or connection lost ! \n"
- "** WARNING : Stopping Netplay... \n"));
- NetClass_ptr = NULL;
- }
-
- m_loopframe++;
- return false;
- }
- }
-
- if (m_data_received)
- {
- // We have successfully received the data, now use it...
- // If we received data, we can update our pads on each frame, here's the behaviour :
- // we received our init number, so we should receive our pad values on each frames
- // with a frame delay of 'm_frameDelay' frames from the peer. So here, we just wait
- // for the pad status. note : if the peer can't keep up, sending the values
- // (i.e : framerate is too low) we have to wait for it thus slowing down emulation
-
- // Save current pad values, it will be used in 'm_frameDelay' frames :D
- int saveslot = (m_loopframe - 1 < 0 ? m_frameDelay : m_loopframe - 1);
- u32 recvedValues[2];
-
- m_pads[player].nHi[saveslot] = netValues[0];
- m_pads[player].nLow[saveslot] = netValues[1];
-
- // Read the socket for pad values
- if (m_isHosting == 1)
- m_sock_server->isNewPadData(recvedValues, true);
- else
- m_sock_client->isNewPadData(recvedValues, true);
-
- if (player == 0)
- {
- // Store received peer values
- m_pads[1].nHi[m_loopframe] = recvedValues[0];
- m_pads[1].nLow[m_loopframe] = recvedValues[1];
-
- // Apply synced pad values
- netValues[0] = m_pads[0].nHi[m_loopframe];
- netValues[1] = m_pads[0].nLow[m_loopframe];
- }
- else
- {
- // Apply received pad values
- netValues[0] = recvedValues[0];
- netValues[1] = recvedValues[1];
- }
- }
-
-#ifdef NET_DEBUG
- char usedval[64];
- sprintf(usedval, "Player 1 Values: 0x%08x : 0x%08x \n", netValues[0], netValues[1]);
- m_Logging->AppendText(wxString::FromAscii(usedval));
-#endif
- return true;
- }
- else if (padnb == 1)
- {
- if (m_data_received)
- {
- netValues[0] = m_pads[1].nHi[m_loopframe];
- netValues[1] = m_pads[1].nLow[m_loopframe];
-
- // Reset the loop to avoid reading unused values
- if (m_loopframe == m_frameDelay)
- m_loopframe = 0;
- else
- m_loopframe++;
- }
- else
- return false;
-#ifdef NET_DEBUG
- char usedval[64];
- sprintf(usedval, "Player 2 Values: 0x%08x : 0x%08x \n", netValues[0], netValues[1]);
- m_Logging->AppendText(wxString::FromAscii(usedval));
-#endif
-
- return true;
- }
- }
- else
- {
- // TODO : :D
- return false;
- }
-
- return false;
-}
-
-void NetPlay::ChangeSelectedGame(std::string game)
-{
- wxCriticalSectionLocker lock(m_critical);
- if (m_isHosting == 0)
- {
- m_selectedGame = game;
- return;
- }
-
- if (game != m_selectedGame)
- {
- unsigned char value = 0x35;
- int game_size = (int)game.size();
-
- // Send command then Game String
- for (int i=0; i < m_numClients ; i++)
- {
- m_sock_server->Write(i, (const char*)&value, 1); // 0x35 -> Change game
-
- m_sock_server->Write(i, (const char*)&game_size, 4);
- m_sock_server->Write(i, game.c_str(), game_size + 1);
- }
-
- m_selectedGame = game;
- UpdateNetWindow(false);
- m_Logging->AppendText(wxString::Format(wxT("*Game has been changed to : %s\n"), game.c_str()));
- }
-}
-
-void NetPlay::OnQuit(wxCloseEvent& WXUNUSED(event))
-{
- // Disable netplay
- NetClass_ptr = NULL;
-
- // Destroy the Window
- Destroy();
-
- // Then Kill the threads
- if (m_isHosting == 0)
- m_sock_client->Delete();
- else if (m_isHosting == 1) {
- m_sock_server->Delete();
- }
-
-}
-
-void NetPlay::OnDisconnect(wxCommandEvent& WXUNUSED(event))
-{
- wxCloseEvent close;
- OnQuit(close);
-}
-
-bool ClientSide::isNewPadData(u32 *netValues, bool current, bool isVersus)
-{
-#ifdef USE_TCP
- if (current)
- {
- while (1)
- {
- m_CriticalSection.Enter();
- if (m_data_received && isVersus)
- {
- netValues[0] = m_netvalues[0][0];
- netValues[1] = m_netvalues[0][1];
- m_data_received = false;
-
- m_CriticalSection.Leave();
- break;
- }
- m_CriticalSection.Leave();
-
- if (TestDestroy())
- break;
- }
-
- return true;
- }
- else
- wxCriticalSectionLocker lock(m_CriticalSection);
-
- return m_data_received;
-#else
- size_t recv_size;
-
- if (current)
- {
- m_CriticalSection.Enter();
-
- if (isVersus)
- {
- if (m_netvalues[0][1] != 0)
- {
- netValues[0] = m_netvalues[0][1];
- netValues[1] = m_netvalues[0][2];
- }
- else
- {
- while (true)
- {
- u32 frame_saved = m_netvalues[0][0];
- bool pass = RecvT(m_socketUDP, (char*)&m_netvalues[0], 12, recv_size, 5);
-
- if (m_netvalues[0][0] < frame_saved+1)
- continue;
- if (m_netvalues[0][0] > frame_saved+1 || !pass)
- PanicAlert("Network ERROR !");
-
- netValues[0] = m_netvalues[0][1];
- netValues[1] = m_netvalues[0][2];
- break;
- }
- }
- }
-
- m_netvalues[0][1] = 0;
- m_CriticalSection.Leave();
-
- return true;
- }
- else
- return RecvT(m_socketUDP, (char*)&m_netvalues[0], 12, recv_size, 1/1000);
-
-#endif
-
-}
-
-bool ServerSide::isNewPadData(u32 *netValues, bool current, int client)
-{
-#ifdef USE_TCP
- if (current)
- {
- while (1)
- {
- m_CriticalSection.Enter();
- if (m_data_received)
- {
- netValues[0] = m_netvalues[client][0];
- netValues[1] = m_netvalues[client][1];
- m_data_received = false;
-
- m_CriticalSection.Leave();
- break;
- }
- m_CriticalSection.Leave();
-
- if (TestDestroy())
- break;
- }
-
- return true;
- }
- else
- wxCriticalSectionLocker lock(m_CriticalSection);
-
- return m_data_received;
-#else
- size_t recv_size;
-
- if (current)
- {
- m_CriticalSection.Enter();
-
- if (m_netvalues[0][1] != 0)
- {
- netValues[0] = m_netvalues[client][1];
- netValues[1] = m_netvalues[client][2];
- }
- else
- {
- while (true)
- {
- u32 frame_saved = m_netvalues[client][0];
- bool pass = RecvT(m_socketUDP, (char*)&m_netvalues[client], 12, recv_size, 5);
-
- if (m_netvalues[client][0] < frame_saved+1)
- continue;
- if (m_netvalues[client][0] > frame_saved+1 || !pass)
- PanicAlert("Network ERROR !");
-
- netValues[0] = m_netvalues[client][1];
- netValues[1] = m_netvalues[client][2];
- break;
- }
- }
-
- m_netvalues[client][1] = 0;
- m_CriticalSection.Leave();
-
- return true;
- }
- else
- return RecvT(m_socketUDP, (char*)&m_netvalues[client], 12, recv_size, 1/1000);
-
-#endif
-}
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "NetWindow.h"
+#include "HW/SI_DeviceGCController.h"
+
+NetPlay *NetClass_ptr = NULL;
+
+void NetPlay::IsGameFound(unsigned char * ptr, std::string m_selected)
+{
+ m_critical.Enter();
+
+ m_selectedGame = m_selected;
+
+ if (m_games.find(m_selected) != std::string::npos)
+ *ptr = 0x1F;
+ else
+ *ptr = 0x1A;
+
+ m_critical.Leave();
+}
+
+void NetPlay::OnNetEvent(wxCommandEvent& event)
+{
+ switch (event.GetId())
+ {
+ case HOST_FULL:
+ {
+ AppendText(_(" Server is Full !\n*You have been Disconnected.\n\n"));
+ m_isHosting = 2;
+ }
+ break;
+ case HOST_ERROR:
+ {
+ if (m_isHosting == 0)
+ {
+ AppendText(_("ERROR : Network Error !\n*You have been Disconnected.\n\n"));
+ m_isHosting = 2;
+ }
+ else
+ {
+ m_numClients--;
+ AppendText( wxString::Format(wxT("ERROR : Network Error !\n"
+ "*Player : %s has been dropped from the game.\n\n"),
+ (const char *)event.GetString().mb_str()) );
+ }
+ }
+ break;
+ case HOST_DISCONNECTED:
+ {
+ // Event sent from Client's thread, it means that the thread
+ // has been killed and so we tell the GUI thread.
+ AppendText(_("*Connection to Host lost.\n*You have been Disconnected.\n\n"));
+ m_isHosting = 2;
+ m_numClients--;
+ }
+ break;
+ case HOST_PLAYERLEFT:
+ {
+ m_numClients--;
+ }
+ break;
+ case HOST_NEWPLAYER:
+ {
+ m_numClients++;
+ m_NetModel = event.GetInt();
+ }
+ break;
+ case CLIENTS_READY:
+ {
+ m_clients_ready = true;
+
+ // Tell clients everyone is ready...
+ if (m_ready)
+ LoadGame();
+ }
+ break;
+ case CLIENTS_NOTREADY:
+ {
+ m_clients_ready = false;
+ }
+ break;
+ case GUI_UPDATE:
+ UpdateNetWindow(false);
+ break;
+ case ADD_TEXT:
+ AppendText(event.GetString());
+ break;
+ case ADD_INFO:
+ UpdateNetWindow(true, event.GetString());
+ break;
+ }
+}
+
+void ServerSide::IsEveryoneReady()
+{
+ int nb_ready = 0;
+
+ for (int i=0; i < m_numplayers ; i++)
+ if (m_client[i].ready)
+ nb_ready++;
+
+ if (nb_ready == m_numplayers)
+ Event->SendEvent(CLIENTS_READY);
+ else
+ Event->SendEvent(CLIENTS_NOTREADY);
+}
+
+// Actual Core function which is called on every frame
+int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
+{
+ if (NetClass_ptr != NULL)
+ return NetClass_ptr->GetNetPads(numPAD, PadStatus, PADStatus) ? 1 : 0;
+ else
+ return 2;
+}
+
+void NetPlay::LoadGame()
+{
+ // Two implementations, one "p2p" implementation which sends to peer
+ // and receive from peer 2 players max. and another which uses server model
+ // and always sends to the server which then send it back to all the clients
+ // -> P2P model is faster, but is limited to 2 players
+ // -> Server model is slower, but supports up to 4 players
+
+ if (m_isHosting == 1)
+ {
+ long ping[3] = {0};
+ unsigned char value = 0x50;
+
+ // Get ping
+ m_sock_server->Write(0, 0, 0, ping);
+ float fping = (ping[0]+ping[1]+ping[2])/(float)m_numClients;
+
+ // Tell client everyone is ready
+ for (int i=0; i < m_numClients ; i++)
+ m_sock_server->Write(i, (const char*)&value, 1);
+
+ // Sleep a bit to start the game at more or less the same time than the peer
+ wxMilliSleep(fping/2);
+
+ m_Logging->AppendText(wxString::Format(wxT("** Everyone is ready... Loading Game ! **\n"
+ "** Ping to client(s) is : %f ms\n"), fping));
+ }
+ else
+ m_Logging->AppendText(_("** Everyone is ready... Loading Game ! **\n"));
+
+ // TODO : Throttle should be on by default, to avoid stuttering
+ //soundStream->GetMixer()->SetThrottle(true);
+
+ int line_p = 0;
+ int line_n = 0;
+
+ m_critical.Enter();
+ std::string tmp = m_games.substr(0, m_games.find(m_selectedGame));
+
+ for (int i=0; i < (int)tmp.size(); i++)
+ if (tmp.c_str()[i] == '\n')
+ line_n++;
+
+ // Enable
+ NetClass_ptr = this;
+ m_timer.Start();
+ m_data_received = false;
+ m_critical.Leave();
+
+ // Find corresponding game path
+ for (int i=0; i < (int)m_paths.size(); i++)
+ {
+ if (m_paths.c_str()[i] == '\n')
+ line_p++;
+
+ if (line_n == line_p) {
+ // Game path found, get its string
+ int str_pos = line_p > 0 ? i+1 : i;
+ int str_end = (int)m_paths.find('\n', str_pos);
+ // Boot the selected game
+ BootManager::BootCore(m_paths.substr(str_pos, str_end - str_pos));
+ break;
+ }
+ }
+}
+
+bool NetPlay::GetNetPads(u8 padnb, SPADStatus PadStatus, u32 *netValues)
+{
+ if (m_numClients < 1)
+ {
+ m_Logging->AppendText(_("** WARNING : "
+ "Ping too high (>2000ms) or connection lost ! \n"
+ "** WARNING : Stopping Netplay... \n"));
+ NetClass_ptr = NULL;
+ return false;
+ }
+
+ // Store current pad status in netValues[]
+ netValues[0] = (u32)((u8)PadStatus.stickY);
+ netValues[0] |= (u32)((u8)PadStatus.stickX << 8);
+ netValues[0] |= (u32)((u16)PadStatus.button << 16);
+ netValues[0] |= 0x00800000;
+ netValues[1] = (u8)PadStatus.triggerRight;
+ netValues[1] |= (u32)((u8)PadStatus.triggerLeft << 8);
+ netValues[1] |= (u32)((u8)PadStatus.substickY << 16);
+ netValues[1] |= (u32)((u8)PadStatus.substickX << 24);
+
+ if (m_NetModel == 0) // Use 2 players Model
+ {
+ if (padnb == 0)
+ {
+ // Update the timer and increment total frame number
+ m_frame++;
+
+ if (m_frame == 1)
+ {
+ // We make sure everyone's pad is enabled
+ for (int i = 0; i < m_numClients+1; i++)
+ SerialInterface::ChangeDevice(SI_GC_CONTROLLER, i);
+
+ // Better disable unused ports
+ for (int i = m_numClients+1; i < 4; i++)
+ SerialInterface::ChangeDevice(SI_DUMMY, i);
+ }
+
+ if (m_timer.GetTimeDifference() > 1000)
+ m_timer.Update();
+
+#ifdef NET_DEBUG
+ char sent[64];
+ sprintf(sent, "Sent Values: 0x%08x : 0x%08x \n", netValues[0], netValues[1]);
+ m_Logging->AppendText(wxString::FromAscii(sent));
+#endif
+ unsigned char player = 0;
+
+#ifdef USE_TCP
+ unsigned char init_value = 0xA1;
+
+ if (m_isHosting == 1) {
+ // Send pads values
+ m_sock_server->Write(0, (const char*)&init_value, 1);
+ m_sock_server->Write(0, (const char*)netValues, 8);
+ }
+ else {
+ // Send pads values
+ m_sock_client->Write((const char*)&init_value, 1);
+ m_sock_client->Write((const char*)netValues, 8);
+ player = 1;
+ }
+#else // UDP
+ u32 padsValues[3];
+
+ padsValues[0] = m_frame;
+ padsValues[1] = netValues[0];
+ padsValues[2] = netValues[1];
+
+ if (m_isHosting == 1) {
+ // Send pads values
+ m_sock_server->WriteUDP(0, (const char*)padsValues, 12);
+ }
+ else {
+ // Send pads values
+ m_sock_client->WriteUDP((const char*)padsValues, 12);
+ player = 1;
+ }
+#endif
+
+ if (!m_data_received)
+ {
+ // Save pad values
+ m_pads[player].nHi[m_loopframe] = netValues[0];
+ m_pads[player].nLow[m_loopframe] = netValues[1];
+
+ // Try to read from peer...
+ if (m_isHosting == 1)
+ m_data_received = m_sock_server->isNewPadData(0, false);
+ else
+ m_data_received = m_sock_client->isNewPadData(0, false);
+
+ if (m_data_received)
+ {
+ // Set our practical frame delay
+ m_frameDelay = m_loopframe;
+ m_loopframe = 0;
+
+ // First Data has been received !
+ m_Logging->AppendText(_("** Data received from Peer. Starting Sync !"));
+ m_Logging->AppendText(wxString::Format(wxT(" Frame Delay : %d **\n"), m_frameDelay));
+ }
+ else {
+ if (m_loopframe > 126)
+ {
+ m_Logging->AppendText(_("** WARNING : "
+ "Ping too high (>2000ms) or connection lost ! \n"
+ "** WARNING : Stopping Netplay... \n"));
+ NetClass_ptr = NULL;
+ }
+
+ m_loopframe++;
+ return false;
+ }
+ }
+
+ if (m_data_received)
+ {
+ // We have successfully received the data, now use it...
+ // If we received data, we can update our pads on each frame, here's the behaviour :
+ // we received our init number, so we should receive our pad values on each frames
+ // with a frame delay of 'm_frameDelay' frames from the peer. So here, we just wait
+ // for the pad status. note : if the peer can't keep up, sending the values
+ // (i.e : framerate is too low) we have to wait for it thus slowing down emulation
+
+ // Save current pad values, it will be used in 'm_frameDelay' frames :D
+ int saveslot = (m_loopframe - 1 < 0 ? m_frameDelay : m_loopframe - 1);
+ u32 recvedValues[2];
+
+ m_pads[player].nHi[saveslot] = netValues[0];
+ m_pads[player].nLow[saveslot] = netValues[1];
+
+ // Read the socket for pad values
+ if (m_isHosting == 1)
+ m_sock_server->isNewPadData(recvedValues, true);
+ else
+ m_sock_client->isNewPadData(recvedValues, true);
+
+ if (player == 0)
+ {
+ // Store received peer values
+ m_pads[1].nHi[m_loopframe] = recvedValues[0];
+ m_pads[1].nLow[m_loopframe] = recvedValues[1];
+
+ // Apply synced pad values
+ netValues[0] = m_pads[0].nHi[m_loopframe];
+ netValues[1] = m_pads[0].nLow[m_loopframe];
+ }
+ else
+ {
+ // Apply received pad values
+ netValues[0] = recvedValues[0];
+ netValues[1] = recvedValues[1];
+ }
+ }
+
+#ifdef NET_DEBUG
+ char usedval[64];
+ sprintf(usedval, "Player 1 Values: 0x%08x : 0x%08x \n", netValues[0], netValues[1]);
+ m_Logging->AppendText(wxString::FromAscii(usedval));
+#endif
+ return true;
+ }
+ else if (padnb == 1)
+ {
+ if (m_data_received)
+ {
+ netValues[0] = m_pads[1].nHi[m_loopframe];
+ netValues[1] = m_pads[1].nLow[m_loopframe];
+
+ // Reset the loop to avoid reading unused values
+ if (m_loopframe == m_frameDelay)
+ m_loopframe = 0;
+ else
+ m_loopframe++;
+ }
+ else
+ return false;
+#ifdef NET_DEBUG
+ char usedval[64];
+ sprintf(usedval, "Player 2 Values: 0x%08x : 0x%08x \n", netValues[0], netValues[1]);
+ m_Logging->AppendText(wxString::FromAscii(usedval));
+#endif
+
+ return true;
+ }
+ }
+ else
+ {
+ // TODO : :D
+ return false;
+ }
+
+ return false;
+}
+
+void NetPlay::ChangeSelectedGame(std::string game)
+{
+ wxCriticalSectionLocker lock(m_critical);
+ if (m_isHosting == 0)
+ {
+ m_selectedGame = game;
+ return;
+ }
+
+ if (game != m_selectedGame)
+ {
+ unsigned char value = 0x35;
+ int game_size = (int)game.size();
+
+ // Send command then Game String
+ for (int i=0; i < m_numClients ; i++)
+ {
+ m_sock_server->Write(i, (const char*)&value, 1); // 0x35 -> Change game
+
+ m_sock_server->Write(i, (const char*)&game_size, 4);
+ m_sock_server->Write(i, game.c_str(), game_size + 1);
+ }
+
+ m_selectedGame = game;
+ UpdateNetWindow(false);
+ m_Logging->AppendText(wxString::Format(wxT("*Game has been changed to : %s\n"), game.c_str()));
+ }
+}
+
+void NetPlay::OnQuit(wxCloseEvent& WXUNUSED(event))
+{
+ // Disable netplay
+ NetClass_ptr = NULL;
+
+ // Destroy the Window
+ Destroy();
+
+ // Then Kill the threads
+ if (m_isHosting == 0)
+ m_sock_client->Delete();
+ else if (m_isHosting == 1) {
+ m_sock_server->Delete();
+ }
+
+}
+
+void NetPlay::OnDisconnect(wxCommandEvent& WXUNUSED(event))
+{
+ wxCloseEvent close;
+ OnQuit(close);
+}
+
+bool ClientSide::isNewPadData(u32 *netValues, bool current, bool isVersus)
+{
+#ifdef USE_TCP
+ if (current)
+ {
+ while (1)
+ {
+ m_CriticalSection.Enter();
+ if (m_data_received && isVersus)
+ {
+ netValues[0] = m_netvalues[0][0];
+ netValues[1] = m_netvalues[0][1];
+ m_data_received = false;
+
+ m_CriticalSection.Leave();
+ break;
+ }
+ m_CriticalSection.Leave();
+
+ if (TestDestroy())
+ break;
+ }
+
+ return true;
+ }
+ else
+ wxCriticalSectionLocker lock(m_CriticalSection);
+
+ return m_data_received;
+#else
+ size_t recv_size;
+
+ if (current)
+ {
+ m_CriticalSection.Enter();
+
+ if (isVersus)
+ {
+ if (m_netvalues[0][1] != 0)
+ {
+ netValues[0] = m_netvalues[0][1];
+ netValues[1] = m_netvalues[0][2];
+ }
+ else
+ {
+ while (true)
+ {
+ u32 frame_saved = m_netvalues[0][0];
+ bool pass = RecvT(m_socketUDP, (char*)&m_netvalues[0], 12, recv_size, 5);
+
+ if (m_netvalues[0][0] < frame_saved+1)
+ continue;
+ if (m_netvalues[0][0] > frame_saved+1 || !pass)
+ PanicAlert("Network ERROR !");
+
+ netValues[0] = m_netvalues[0][1];
+ netValues[1] = m_netvalues[0][2];
+ break;
+ }
+ }
+ }
+
+ m_netvalues[0][1] = 0;
+ m_CriticalSection.Leave();
+
+ return true;
+ }
+ else
+ return RecvT(m_socketUDP, (char*)&m_netvalues[0], 12, recv_size, 1/1000);
+
+#endif
+
+}
+
+bool ServerSide::isNewPadData(u32 *netValues, bool current, int client)
+{
+#ifdef USE_TCP
+ if (current)
+ {
+ while (1)
+ {
+ m_CriticalSection.Enter();
+ if (m_data_received)
+ {
+ netValues[0] = m_netvalues[client][0];
+ netValues[1] = m_netvalues[client][1];
+ m_data_received = false;
+
+ m_CriticalSection.Leave();
+ break;
+ }
+ m_CriticalSection.Leave();
+
+ if (TestDestroy())
+ break;
+ }
+
+ return true;
+ }
+ else
+ wxCriticalSectionLocker lock(m_CriticalSection);
+
+ return m_data_received;
+#else
+ size_t recv_size;
+
+ if (current)
+ {
+ m_CriticalSection.Enter();
+
+ if (m_netvalues[0][1] != 0)
+ {
+ netValues[0] = m_netvalues[client][1];
+ netValues[1] = m_netvalues[client][2];
+ }
+ else
+ {
+ while (true)
+ {
+ u32 frame_saved = m_netvalues[client][0];
+ bool pass = RecvT(m_socketUDP, (char*)&m_netvalues[client], 12, recv_size, 5);
+
+ if (m_netvalues[client][0] < frame_saved+1)
+ continue;
+ if (m_netvalues[client][0] > frame_saved+1 || !pass)
+ PanicAlert("Network ERROR !");
+
+ netValues[0] = m_netvalues[client][1];
+ netValues[1] = m_netvalues[client][2];
+ break;
+ }
+ }
+
+ m_netvalues[client][1] = 0;
+ m_CriticalSection.Leave();
+
+ return true;
+ }
+ else
+ return RecvT(m_socketUDP, (char*)&m_netvalues[client], 12, recv_size, 1/1000);
+
+#endif
+}
+
diff --git a/Source/Core/DolphinWX/Src/NetSockets.cpp b/Source/Core/DolphinWX/Src/NetSockets.cpp
index 4889eab66d..fe9d065d36 100644
--- a/Source/Core/DolphinWX/Src/NetSockets.cpp
+++ b/Source/Core/DolphinWX/Src/NetSockets.cpp
@@ -1,595 +1,595 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "NetWindow.h"
-
-//--------------------------------
-// GUI EVENTS
-//--------------------------------
-
-void NetEvent::AppendText(const wxString text)
-{
- // I have the feeling SendEvent may be a bit safer/better...
-#if 1
- SendEvent(ADD_TEXT, std::string(text.mb_str()));
-#else
- wxMutexGuiEnter();
- m_netptr->AppendText(text);
- wxMutexGuiLeave();
-#endif
-}
-
-void NetEvent::SendEvent(int EventType, const std::string text, int integer)
-{
- wxCommandEvent event(wxEVT_HOST_COMMAND, wxID_ANY);
-
- event.SetId( EventType );
- event.SetInt( integer );
- event.SetString( wxString::FromAscii(text.c_str()) );
-
- m_netptr->AddPendingEvent(event);
-}
-
-//--------------------------------
-// SERVER SIDE THREAD
-//--------------------------------
-
-ServerSide::ServerSide(NetPlay* netptr, sf::SocketTCP socket, sf::SocketUDP socketUDP, int netmodel, std::string nick)
- : wxThread()
-{
- m_numplayers = 0;
- m_data_received = false;
- m_netmodel = netmodel;
- m_socket = socket;
- m_socketUDP = socketUDP;
- m_netptr = netptr;
- m_nick = nick;
- Event = new NetEvent(m_netptr);
-}
-
-char ServerSide::GetSocket(sf::SocketTCP Socket)
-{
- for (int i=0; i < m_numplayers; i++)
- {
- if(m_client[i].socket == Socket)
- return i;
- }
-
- return 0xE;
-}
-
-bool ServerSide::RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time)
-{
- sf::SelectorUDP Selector;
- sf::IPAddress Addr;
- unsigned short Port;
- Selector.Add(Socket);
-
- if (Selector.Wait(Time) > 0)
- {
- Socket.Receive(Data, Max, Recvd, Addr, Port);
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void *ServerSide::Entry()
-{
- // Add listening socket
- m_selector.Add(m_socket);
-
- while (1)
- {
- char nbSocketReady = m_selector.Wait(0.5);
-
- for (char i = 0; i < nbSocketReady; ++i)
- {
- m_CriticalSection.Enter();
-
- sf::SocketTCP Socket = m_selector.GetSocketReady(i);
-
- if (Socket == m_socket)
- {
- // Incoming connection
- Event->AppendText(_("*Connection Request... "));
-
- sf::SocketTCP Incoming;
- sf::IPAddress Address;
- m_socket.Accept(Incoming, &Address);
-
- unsigned char sent = 0x12;
- if ((m_netmodel == 0 && m_numplayers > 0) || m_numplayers == 3)
- {
- Incoming.Send((const char *)&sent, 1); // Tell it the server is full...
- Incoming.Close(); // Then close the connection
-
- Event->AppendText(_(" Server is Full !\n"));
- }
- else
- {
- Event->AppendText(_(" Connection accepted\n"));
- m_client[m_numplayers].socket = Incoming;
- m_client[m_numplayers].address = Address;
-
- if (SyncValues(m_numplayers, Address))
- {
- // Add it to the selector
- m_selector.Add(Incoming);
- Event->SendEvent(HOST_NEWPLAYER);
-
- m_numplayers++;
- }
- else
- {
- Event->AppendText(_("ERROR : Unable to establish UDP connection !\n"));
- Incoming.Close();
- }
- }
- }
- else
- {
- unsigned char recv;
- int socket_nb;
- size_t recv_size;
- sf::Socket::Status recv_status;
- socket_nb = GetSocket(Socket);
-
- if ((recv_status = Socket.Receive((char *)&recv, 1, recv_size)) == sf::Socket::Done)
- {
-#ifdef NET_DEBUG
- char recv_str[32];
- sprintf(recv_str, "received: 0x%02x | %c\n", recv, recv);
- Event->AppendText(wxString::FromAscii(recv_str));
-#endif
- OnServerData(socket_nb, recv);
- }
- else
- {
- if (recv_status == sf::Socket::Disconnected)
- {
- Event->SendEvent(HOST_PLAYERLEFT);
- m_numplayers--;
-
- std::string player_left = m_client[socket_nb].nick;
- Event->AppendText( wxString::Format(wxT("*Player : %s left the game.\n\n"),
- player_left.c_str()) );
-
- // We need to adjust the struct...
- for (int j = socket_nb; j < m_numplayers; j++)
- {
- m_client[j].socket = m_client[j+1].socket;
- m_client[j].nick = m_client[j+1].nick;
- m_client[j].ready = m_client[j+1].ready;
- }
-
- // Send disconnected message to all
- unsigned char send = 0x11;
- unsigned int str_size = (int)player_left.size();
-
- for (int j=0; j < m_numplayers ; j++)
- {
- m_client[j].socket.Send((const char*)&send, 1);
- m_client[j].socket.Send((const char*)&str_size, 4);
- m_client[j].socket.Send(player_left.c_str(), (int)str_size + 1);
- }
- }
- else
- {
- // Hopefully this should never happen, the client is not
- // Even warned that he is being dropped...
- Event->SendEvent(HOST_ERROR, m_client[socket_nb].nick);
- }
-
- m_selector.Remove(Socket);
- Socket.Close();
- }
- }
-
- m_CriticalSection.Leave();
- }
-
- if(TestDestroy())
- {
- // Stop listening
- m_socket.Close();
-
- // Delete the Thread and close clients sockets
- for (int i=0; i < m_numplayers ; i++)
- m_client[i].socket.Close();
-
- break;
- }
- }
-
- return NULL;
-}
-
-bool ServerSide::SyncValues(unsigned char socketnb, sf::IPAddress Address)
-{
- sf::SocketTCP Socket = m_client[socketnb].socket;
-
- std::string buffer_str = m_netptr->GetSelectedGame();
- char *buffer = NULL;
- unsigned char init_number;
- u32 buffer_size = (u32)buffer_str.size();
- size_t received;
- bool errorUDP = false;
-
- // First, Send the number of connected clients & netmodel
- Socket.Send((const char *)&m_numplayers, 1);
- Socket.Send((const char *)&m_netmodel, 4);
-
- // Send the Game String
- Socket.Send((const char *)&buffer_size, 4);
- Socket.Send(buffer_str.c_str(), buffer_size + 1);
-
- // Send the host Nickname
- buffer_size = (u32)m_nick.size();
- Socket.Send((const char *)&buffer_size, 4);
- Socket.Send(m_nick.c_str(), buffer_size + 1);
-
- // Read client's UDP Port
- Socket.Receive((char *)&m_client[m_numplayers].port, sizeof(short), received);
-
- // Read returned nickname
- Socket.Receive((char *)&buffer_size, 4, received);
- buffer = new char[buffer_size + 1];
- Socket.Receive(buffer, buffer_size + 1, received);
-
- m_client[socketnb].nick = std::string(buffer);
- m_client[socketnb].ready = false;
-
- ///////////////////
- // Test UDP Socket
- ///////////////////
- if (m_socketUDP.Send((const char*)&m_numplayers, 1, Address, m_client[m_numplayers].port) == sf::Socket::Done)
- {
- // Test UDP Socket Receive, 2s timeout
- if (!RecvT(m_socketUDP, (char*)&init_number, 1, received, 2))
- errorUDP = true;
- }
- else
- errorUDP = true;
-
- // Check if the client has the game
- Socket.Receive((char *)&init_number, 1, received);
-
- delete[] buffer;
-
- if (!errorUDP)
- {
- // Send to all connected clients
- if (m_numplayers > 0)
- {
- unsigned char send = 0x10;
- buffer_size = (int)m_client[socketnb].nick.size();
- for (int i=0; i < m_numplayers ; i++)
- {
- // Do not send to connecting player
- if (i == socketnb)
- continue;
-
- m_client[i].socket.Send((const char *)&send, 1); // Init new connection
- m_client[i].socket.Send((const char *)&init_number, 1); // Send Game found ?
- m_client[i].socket.Send((const char *)&buffer_size, 4); // Send client nickname
- m_client[i].socket.Send(m_client[socketnb].nick.c_str(), buffer_size + 1);
- }
- }
-
- Event->AppendText( wxString::Format(wxT("*Connection established to %s (%s:%d)\n"),
- m_client[socketnb].nick.c_str(), Address.ToString().c_str(), m_client[m_numplayers].port) );
-
- if (init_number != 0x1F) // Not Found
- for (int i = 0; i < 4; i++)
- Event->AppendText(_("WARNING : Game Not Found on Client Side !\n"));
-
- // UDP connecton successful
- init_number = 0x16;
- Socket.Send((const char *)&init_number, 1);
- }
- else // UDP Error, disconnect client
- {
- // UDP connecton failed
- init_number = 0x17;
- Socket.Send((const char *)&init_number, 1);
- return false;
- }
-
- return true;
-}
-
-void ServerSide::Write(int socknb, const char *data, size_t size, long *ping)
-{
- wxCriticalSectionLocker lock(m_CriticalSection);
-
- if (ping != NULL)
- {
- // Ask for ping
- unsigned char value = 0x15;
- size_t recv_size;
- u32 four_bytes = 0x101A7FA6;
-
- Common::Timer timer;
- timer.Start();
-
- for (int i=0; i < m_numplayers ; i++)
- {
- m_client[i].socket.Send((const char*)&value, 1);
-
- timer.Update();
- m_client[i].socket.Send((const char*)&four_bytes, 4);
- m_client[i].socket.Receive((char*)&four_bytes, 4, recv_size);
- ping[i] = (long)timer.GetTimeDifference();
- }
-
- return;
- }
-
- // Send the data safely, without intefering with another call
- m_client[socknb].socket.Send(data, size);
-}
-
-void ServerSide::WriteUDP(int socknb, const char *data, size_t size)
-{
- wxCriticalSectionLocker lock(m_CriticalSection);
-
- m_socketUDP.Send(data, size, m_client[socknb].address, m_client[socknb].port);
-}
-
-//--------------------------------
-// CLIENT SIDE THREAD
-//--------------------------------
-
-ClientSide::ClientSide(NetPlay* netptr, sf::SocketTCP socket, sf::SocketUDP socketUDP, std::string addr, std::string nick)
- : wxThread()
-{
- m_numplayers = 0;
- m_data_received = false;
- m_netmodel = 0;
- m_socket = socket;
- m_socketUDP = socketUDP;
- m_port = m_socketUDP.GetPort();
- m_netptr = netptr;
- m_nick = nick;
- m_addr = addr;
- Event = new NetEvent(m_netptr);
-}
-
-bool ClientSide::RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time)
-{
- sf::SelectorUDP Selector;
- sf::IPAddress Addr;
- unsigned short Port;
- Selector.Add(Socket);
-
- if (Selector.Wait(Time) > 0)
- {
- Socket.Receive(Data, Max, Recvd, Addr, Port);
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void *ClientSide::Entry()
-{
- Event->AppendText(_("*Connection Request... "));
-
- // If we get here, the connection is already accepted, however the game may be full
- if (SyncValues())
- {
- // Tell the server if the client has the game
- CheckGameFound();
-
- // Check UDP connection
- unsigned char value;
- size_t val_sz;
- m_socket.Receive((char *)&value, 1, val_sz);
-
- if (value == 0x16) // UDP connection successful
- {
- Event->AppendText(_("Connection successful !\n"));
- Event->AppendText( wxString::Format(wxT("*Connection established to %s (%s)\n*Game is : %s\n"),
- m_hostnick.c_str(), m_addr.c_str(), m_selectedgame.c_str() ) );
- }
- else
- {
- Event->AppendText(_("UDP Connection FAILED !\n"
- "ERROR : Unable to establish UDP Connection, please Check UDP Port forwarding !"));
- m_socket.Close();
- Event->SendEvent(HOST_ERROR);
- return NULL;
- }
- }
- else // Server is Full
- {
- m_socket.Close();
- Event->SendEvent(HOST_FULL);
- return NULL;
- }
-
- m_netptr->ChangeSelectedGame(m_selectedgame);
- Event->SendEvent(HOST_NEWPLAYER, "NULL", m_netmodel);
- Event->SendEvent(GUI_UPDATE);
-
- m_selector.Add(m_socket);
-
- while (1)
- {
- unsigned char recv;
- size_t recv_size;
- sf::Socket::Status recv_status;
-
- // we use a selector because of the useful timeout
- if (m_selector.Wait(0.5) > 0)
- {
- m_CriticalSection.Enter();
-
- if ((recv_status = m_socket.Receive((char *)&recv, 1, recv_size)) == sf::Socket::Done)
- {
-#ifdef NET_DEBUG
- char recv_str[32];
- sprintf(recv_str, "received: 0x%02x | %c\n", recv, recv);
- Event->AppendText(wxString::FromAscii(recv_str));
-#endif
- OnClientData(recv);
- }
- else
- {
- if (recv_status == sf::Socket::Disconnected)
- {
- Event->SendEvent(HOST_DISCONNECTED);
- }
- else
- {
- Event->SendEvent(HOST_ERROR);
- }
-
- m_selector.Remove(m_socket);
- m_socket.Close();
-
- return NULL;
- }
-
- m_CriticalSection.Leave();
- }
-
- if(TestDestroy())
- {
- m_socket.Close();
-
- break;
- }
- }
-
- return NULL;
-}
-
-bool ClientSide::SyncValues()
-{
- unsigned int buffer_size = (int)m_nick.size();
- unsigned char byterecv;
- bool errorUDP;
- char *buffer = NULL;
- size_t recv_size;
-
- unsigned short server_port;
- std::string host = m_addr.substr(0, m_addr.find(':'));
- TryParseInt(m_addr.substr(m_addr.find(':')+1).c_str(), (int *)&server_port);
-
- // First, Read the init number : nbplayers (0-2) or server full (0x12)
- m_socket.Receive((char *)&m_numplayers, 1, recv_size);
- if (m_numplayers == 0x12)
- return false;
- m_socket.Receive((char *)&m_netmodel, 4, recv_size);
-
- // Send client's UDP Port
- m_socket.Send((const char *)&m_port, sizeof(short));
-
- // Send client's nickname
- m_socket.Send((const char *)&buffer_size, 4);
- m_socket.Send(m_nick.c_str(), buffer_size + 1);
-
- // Read the Game String
- m_socket.Receive((char *)&buffer_size, 4, recv_size);
- buffer = new char[buffer_size + 1];
- m_socket.Receive(buffer, buffer_size + 1, recv_size);
- m_selectedgame = std::string(buffer);
-
- // Read the host Nickname
- m_socket.Receive((char *)&buffer_size, 4, recv_size);
- buffer = new char[buffer_size + 1];
- m_socket.Receive(buffer, buffer_size + 1, recv_size);
- m_hostnick = std::string(buffer);
-
- ///////////////////
- // Test UDP Socket
- ///////////////////
- if (m_socketUDP.Send((const char*)&m_numplayers, 1, host.c_str(), server_port) == sf::Socket::Done)
- {
- // Test UDP Socket Receive, 2s timeout
- if (!RecvT(m_socketUDP, (char*)&byterecv, 1, recv_size, 2))
- errorUDP = true;
- }
- else
- errorUDP = true;
-
- delete[] buffer;
- return true;
-}
-
-void ClientSide::CheckGameFound()
-{
- unsigned char send_value;
-
- // Check if the game selected by Host is in Client's Game List
- m_netptr->IsGameFound(&send_value, m_selectedgame);
-
- if (send_value == 0x1F) // Found
- {
- m_socket.Send((const char *)&send_value, 1);
- }
- else
- {
- m_socket.Send((const char *)&send_value, 1);
-
- for (int i = 0; i < 2; i++)
- Event->AppendText(_("WARNING : You do not have the Selected Game !\n"));
- }
-}
-
-void ClientSide::Write(const char *data, size_t size, long *ping)
-{
- wxCriticalSectionLocker lock(m_CriticalSection);
-
- if (ping != NULL)
- {
- // Ask for ping
- unsigned char value = 0x15;
- size_t recv_size;
- int four_bytes = 0x101A7FA6;
-
- Common::Timer timer;
- timer.Start();
-
- m_socket.Send((const char*)&value, 1);
- m_socket.Send((const char*)&four_bytes, 4);
- m_socket.Receive((char*)&four_bytes, 4, recv_size);
-
- *ping = (long)timer.GetTimeElapsed();
-
- return;
- }
-
- m_socket.Send(data, size);
-}
-
-void ClientSide::WriteUDP(const char *data, size_t size)
-{
- wxCriticalSectionLocker lock(m_CriticalSection);
-
- unsigned short server_port;
- std::string host = m_addr.substr(0, m_addr.find(':'));
- TryParseInt(m_addr.substr(m_addr.find(':')+1).c_str(), (int *)&server_port);
-
- m_socketUDP.Send(data, size, host.c_str(), server_port);
-}
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "NetWindow.h"
+
+//--------------------------------
+// GUI EVENTS
+//--------------------------------
+
+void NetEvent::AppendText(const wxString text)
+{
+ // I have the feeling SendEvent may be a bit safer/better...
+#if 1
+ SendEvent(ADD_TEXT, std::string(text.mb_str()));
+#else
+ wxMutexGuiEnter();
+ m_netptr->AppendText(text);
+ wxMutexGuiLeave();
+#endif
+}
+
+void NetEvent::SendEvent(int EventType, const std::string text, int integer)
+{
+ wxCommandEvent event(wxEVT_HOST_COMMAND, wxID_ANY);
+
+ event.SetId( EventType );
+ event.SetInt( integer );
+ event.SetString( wxString::FromAscii(text.c_str()) );
+
+ m_netptr->AddPendingEvent(event);
+}
+
+//--------------------------------
+// SERVER SIDE THREAD
+//--------------------------------
+
+ServerSide::ServerSide(NetPlay* netptr, sf::SocketTCP socket, sf::SocketUDP socketUDP, int netmodel, std::string nick)
+ : wxThread()
+{
+ m_numplayers = 0;
+ m_data_received = false;
+ m_netmodel = netmodel;
+ m_socket = socket;
+ m_socketUDP = socketUDP;
+ m_netptr = netptr;
+ m_nick = nick;
+ Event = new NetEvent(m_netptr);
+}
+
+char ServerSide::GetSocket(sf::SocketTCP Socket)
+{
+ for (int i=0; i < m_numplayers; i++)
+ {
+ if(m_client[i].socket == Socket)
+ return i;
+ }
+
+ return 0xE;
+}
+
+bool ServerSide::RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time)
+{
+ sf::SelectorUDP Selector;
+ sf::IPAddress Addr;
+ unsigned short Port;
+ Selector.Add(Socket);
+
+ if (Selector.Wait(Time) > 0)
+ {
+ Socket.Receive(Data, Max, Recvd, Addr, Port);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void *ServerSide::Entry()
+{
+ // Add listening socket
+ m_selector.Add(m_socket);
+
+ while (1)
+ {
+ char nbSocketReady = m_selector.Wait(0.5);
+
+ for (char i = 0; i < nbSocketReady; ++i)
+ {
+ m_CriticalSection.Enter();
+
+ sf::SocketTCP Socket = m_selector.GetSocketReady(i);
+
+ if (Socket == m_socket)
+ {
+ // Incoming connection
+ Event->AppendText(_("*Connection Request... "));
+
+ sf::SocketTCP Incoming;
+ sf::IPAddress Address;
+ m_socket.Accept(Incoming, &Address);
+
+ unsigned char sent = 0x12;
+ if ((m_netmodel == 0 && m_numplayers > 0) || m_numplayers == 3)
+ {
+ Incoming.Send((const char *)&sent, 1); // Tell it the server is full...
+ Incoming.Close(); // Then close the connection
+
+ Event->AppendText(_(" Server is Full !\n"));
+ }
+ else
+ {
+ Event->AppendText(_(" Connection accepted\n"));
+ m_client[m_numplayers].socket = Incoming;
+ m_client[m_numplayers].address = Address;
+
+ if (SyncValues(m_numplayers, Address))
+ {
+ // Add it to the selector
+ m_selector.Add(Incoming);
+ Event->SendEvent(HOST_NEWPLAYER);
+
+ m_numplayers++;
+ }
+ else
+ {
+ Event->AppendText(_("ERROR : Unable to establish UDP connection !\n"));
+ Incoming.Close();
+ }
+ }
+ }
+ else
+ {
+ unsigned char recv;
+ int socket_nb;
+ size_t recv_size;
+ sf::Socket::Status recv_status;
+ socket_nb = GetSocket(Socket);
+
+ if ((recv_status = Socket.Receive((char *)&recv, 1, recv_size)) == sf::Socket::Done)
+ {
+#ifdef NET_DEBUG
+ char recv_str[32];
+ sprintf(recv_str, "received: 0x%02x | %c\n", recv, recv);
+ Event->AppendText(wxString::FromAscii(recv_str));
+#endif
+ OnServerData(socket_nb, recv);
+ }
+ else
+ {
+ if (recv_status == sf::Socket::Disconnected)
+ {
+ Event->SendEvent(HOST_PLAYERLEFT);
+ m_numplayers--;
+
+ std::string player_left = m_client[socket_nb].nick;
+ Event->AppendText( wxString::Format(wxT("*Player : %s left the game.\n\n"),
+ player_left.c_str()) );
+
+ // We need to adjust the struct...
+ for (int j = socket_nb; j < m_numplayers; j++)
+ {
+ m_client[j].socket = m_client[j+1].socket;
+ m_client[j].nick = m_client[j+1].nick;
+ m_client[j].ready = m_client[j+1].ready;
+ }
+
+ // Send disconnected message to all
+ unsigned char send = 0x11;
+ unsigned int str_size = (int)player_left.size();
+
+ for (int j=0; j < m_numplayers ; j++)
+ {
+ m_client[j].socket.Send((const char*)&send, 1);
+ m_client[j].socket.Send((const char*)&str_size, 4);
+ m_client[j].socket.Send(player_left.c_str(), (int)str_size + 1);
+ }
+ }
+ else
+ {
+ // Hopefully this should never happen, the client is not
+ // Even warned that he is being dropped...
+ Event->SendEvent(HOST_ERROR, m_client[socket_nb].nick);
+ }
+
+ m_selector.Remove(Socket);
+ Socket.Close();
+ }
+ }
+
+ m_CriticalSection.Leave();
+ }
+
+ if(TestDestroy())
+ {
+ // Stop listening
+ m_socket.Close();
+
+ // Delete the Thread and close clients sockets
+ for (int i=0; i < m_numplayers ; i++)
+ m_client[i].socket.Close();
+
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+bool ServerSide::SyncValues(unsigned char socketnb, sf::IPAddress Address)
+{
+ sf::SocketTCP Socket = m_client[socketnb].socket;
+
+ std::string buffer_str = m_netptr->GetSelectedGame();
+ char *buffer = NULL;
+ unsigned char init_number;
+ u32 buffer_size = (u32)buffer_str.size();
+ size_t received;
+ bool errorUDP = false;
+
+ // First, Send the number of connected clients & netmodel
+ Socket.Send((const char *)&m_numplayers, 1);
+ Socket.Send((const char *)&m_netmodel, 4);
+
+ // Send the Game String
+ Socket.Send((const char *)&buffer_size, 4);
+ Socket.Send(buffer_str.c_str(), buffer_size + 1);
+
+ // Send the host Nickname
+ buffer_size = (u32)m_nick.size();
+ Socket.Send((const char *)&buffer_size, 4);
+ Socket.Send(m_nick.c_str(), buffer_size + 1);
+
+ // Read client's UDP Port
+ Socket.Receive((char *)&m_client[m_numplayers].port, sizeof(short), received);
+
+ // Read returned nickname
+ Socket.Receive((char *)&buffer_size, 4, received);
+ buffer = new char[buffer_size + 1];
+ Socket.Receive(buffer, buffer_size + 1, received);
+
+ m_client[socketnb].nick = std::string(buffer);
+ m_client[socketnb].ready = false;
+
+ ///////////////////
+ // Test UDP Socket
+ ///////////////////
+ if (m_socketUDP.Send((const char*)&m_numplayers, 1, Address, m_client[m_numplayers].port) == sf::Socket::Done)
+ {
+ // Test UDP Socket Receive, 2s timeout
+ if (!RecvT(m_socketUDP, (char*)&init_number, 1, received, 2))
+ errorUDP = true;
+ }
+ else
+ errorUDP = true;
+
+ // Check if the client has the game
+ Socket.Receive((char *)&init_number, 1, received);
+
+ delete[] buffer;
+
+ if (!errorUDP)
+ {
+ // Send to all connected clients
+ if (m_numplayers > 0)
+ {
+ unsigned char send = 0x10;
+ buffer_size = (int)m_client[socketnb].nick.size();
+ for (int i=0; i < m_numplayers ; i++)
+ {
+ // Do not send to connecting player
+ if (i == socketnb)
+ continue;
+
+ m_client[i].socket.Send((const char *)&send, 1); // Init new connection
+ m_client[i].socket.Send((const char *)&init_number, 1); // Send Game found ?
+ m_client[i].socket.Send((const char *)&buffer_size, 4); // Send client nickname
+ m_client[i].socket.Send(m_client[socketnb].nick.c_str(), buffer_size + 1);
+ }
+ }
+
+ Event->AppendText( wxString::Format(wxT("*Connection established to %s (%s:%d)\n"),
+ m_client[socketnb].nick.c_str(), Address.ToString().c_str(), m_client[m_numplayers].port) );
+
+ if (init_number != 0x1F) // Not Found
+ for (int i = 0; i < 4; i++)
+ Event->AppendText(_("WARNING : Game Not Found on Client Side !\n"));
+
+ // UDP connecton successful
+ init_number = 0x16;
+ Socket.Send((const char *)&init_number, 1);
+ }
+ else // UDP Error, disconnect client
+ {
+ // UDP connecton failed
+ init_number = 0x17;
+ Socket.Send((const char *)&init_number, 1);
+ return false;
+ }
+
+ return true;
+}
+
+void ServerSide::Write(int socknb, const char *data, size_t size, long *ping)
+{
+ wxCriticalSectionLocker lock(m_CriticalSection);
+
+ if (ping != NULL)
+ {
+ // Ask for ping
+ unsigned char value = 0x15;
+ size_t recv_size;
+ u32 four_bytes = 0x101A7FA6;
+
+ Common::Timer timer;
+ timer.Start();
+
+ for (int i=0; i < m_numplayers ; i++)
+ {
+ m_client[i].socket.Send((const char*)&value, 1);
+
+ timer.Update();
+ m_client[i].socket.Send((const char*)&four_bytes, 4);
+ m_client[i].socket.Receive((char*)&four_bytes, 4, recv_size);
+ ping[i] = (long)timer.GetTimeDifference();
+ }
+
+ return;
+ }
+
+ // Send the data safely, without intefering with another call
+ m_client[socknb].socket.Send(data, size);
+}
+
+void ServerSide::WriteUDP(int socknb, const char *data, size_t size)
+{
+ wxCriticalSectionLocker lock(m_CriticalSection);
+
+ m_socketUDP.Send(data, size, m_client[socknb].address, m_client[socknb].port);
+}
+
+//--------------------------------
+// CLIENT SIDE THREAD
+//--------------------------------
+
+ClientSide::ClientSide(NetPlay* netptr, sf::SocketTCP socket, sf::SocketUDP socketUDP, std::string addr, std::string nick)
+ : wxThread()
+{
+ m_numplayers = 0;
+ m_data_received = false;
+ m_netmodel = 0;
+ m_socket = socket;
+ m_socketUDP = socketUDP;
+ m_port = m_socketUDP.GetPort();
+ m_netptr = netptr;
+ m_nick = nick;
+ m_addr = addr;
+ Event = new NetEvent(m_netptr);
+}
+
+bool ClientSide::RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time)
+{
+ sf::SelectorUDP Selector;
+ sf::IPAddress Addr;
+ unsigned short Port;
+ Selector.Add(Socket);
+
+ if (Selector.Wait(Time) > 0)
+ {
+ Socket.Receive(Data, Max, Recvd, Addr, Port);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void *ClientSide::Entry()
+{
+ Event->AppendText(_("*Connection Request... "));
+
+ // If we get here, the connection is already accepted, however the game may be full
+ if (SyncValues())
+ {
+ // Tell the server if the client has the game
+ CheckGameFound();
+
+ // Check UDP connection
+ unsigned char value;
+ size_t val_sz;
+ m_socket.Receive((char *)&value, 1, val_sz);
+
+ if (value == 0x16) // UDP connection successful
+ {
+ Event->AppendText(_("Connection successful !\n"));
+ Event->AppendText( wxString::Format(wxT("*Connection established to %s (%s)\n*Game is : %s\n"),
+ m_hostnick.c_str(), m_addr.c_str(), m_selectedgame.c_str() ) );
+ }
+ else
+ {
+ Event->AppendText(_("UDP Connection FAILED !\n"
+ "ERROR : Unable to establish UDP Connection, please Check UDP Port forwarding !"));
+ m_socket.Close();
+ Event->SendEvent(HOST_ERROR);
+ return NULL;
+ }
+ }
+ else // Server is Full
+ {
+ m_socket.Close();
+ Event->SendEvent(HOST_FULL);
+ return NULL;
+ }
+
+ m_netptr->ChangeSelectedGame(m_selectedgame);
+ Event->SendEvent(HOST_NEWPLAYER, "NULL", m_netmodel);
+ Event->SendEvent(GUI_UPDATE);
+
+ m_selector.Add(m_socket);
+
+ while (1)
+ {
+ unsigned char recv;
+ size_t recv_size;
+ sf::Socket::Status recv_status;
+
+ // we use a selector because of the useful timeout
+ if (m_selector.Wait(0.5) > 0)
+ {
+ m_CriticalSection.Enter();
+
+ if ((recv_status = m_socket.Receive((char *)&recv, 1, recv_size)) == sf::Socket::Done)
+ {
+#ifdef NET_DEBUG
+ char recv_str[32];
+ sprintf(recv_str, "received: 0x%02x | %c\n", recv, recv);
+ Event->AppendText(wxString::FromAscii(recv_str));
+#endif
+ OnClientData(recv);
+ }
+ else
+ {
+ if (recv_status == sf::Socket::Disconnected)
+ {
+ Event->SendEvent(HOST_DISCONNECTED);
+ }
+ else
+ {
+ Event->SendEvent(HOST_ERROR);
+ }
+
+ m_selector.Remove(m_socket);
+ m_socket.Close();
+
+ return NULL;
+ }
+
+ m_CriticalSection.Leave();
+ }
+
+ if(TestDestroy())
+ {
+ m_socket.Close();
+
+ break;
+ }
+ }
+
+ return NULL;
+}
+
+bool ClientSide::SyncValues()
+{
+ unsigned int buffer_size = (int)m_nick.size();
+ unsigned char byterecv;
+ bool errorUDP;
+ char *buffer = NULL;
+ size_t recv_size;
+
+ unsigned short server_port;
+ std::string host = m_addr.substr(0, m_addr.find(':'));
+ TryParseInt(m_addr.substr(m_addr.find(':')+1).c_str(), (int *)&server_port);
+
+ // First, Read the init number : nbplayers (0-2) or server full (0x12)
+ m_socket.Receive((char *)&m_numplayers, 1, recv_size);
+ if (m_numplayers == 0x12)
+ return false;
+ m_socket.Receive((char *)&m_netmodel, 4, recv_size);
+
+ // Send client's UDP Port
+ m_socket.Send((const char *)&m_port, sizeof(short));
+
+ // Send client's nickname
+ m_socket.Send((const char *)&buffer_size, 4);
+ m_socket.Send(m_nick.c_str(), buffer_size + 1);
+
+ // Read the Game String
+ m_socket.Receive((char *)&buffer_size, 4, recv_size);
+ buffer = new char[buffer_size + 1];
+ m_socket.Receive(buffer, buffer_size + 1, recv_size);
+ m_selectedgame = std::string(buffer);
+
+ // Read the host Nickname
+ m_socket.Receive((char *)&buffer_size, 4, recv_size);
+ buffer = new char[buffer_size + 1];
+ m_socket.Receive(buffer, buffer_size + 1, recv_size);
+ m_hostnick = std::string(buffer);
+
+ ///////////////////
+ // Test UDP Socket
+ ///////////////////
+ if (m_socketUDP.Send((const char*)&m_numplayers, 1, host.c_str(), server_port) == sf::Socket::Done)
+ {
+ // Test UDP Socket Receive, 2s timeout
+ if (!RecvT(m_socketUDP, (char*)&byterecv, 1, recv_size, 2))
+ errorUDP = true;
+ }
+ else
+ errorUDP = true;
+
+ delete[] buffer;
+ return true;
+}
+
+void ClientSide::CheckGameFound()
+{
+ unsigned char send_value;
+
+ // Check if the game selected by Host is in Client's Game List
+ m_netptr->IsGameFound(&send_value, m_selectedgame);
+
+ if (send_value == 0x1F) // Found
+ {
+ m_socket.Send((const char *)&send_value, 1);
+ }
+ else
+ {
+ m_socket.Send((const char *)&send_value, 1);
+
+ for (int i = 0; i < 2; i++)
+ Event->AppendText(_("WARNING : You do not have the Selected Game !\n"));
+ }
+}
+
+void ClientSide::Write(const char *data, size_t size, long *ping)
+{
+ wxCriticalSectionLocker lock(m_CriticalSection);
+
+ if (ping != NULL)
+ {
+ // Ask for ping
+ unsigned char value = 0x15;
+ size_t recv_size;
+ int four_bytes = 0x101A7FA6;
+
+ Common::Timer timer;
+ timer.Start();
+
+ m_socket.Send((const char*)&value, 1);
+ m_socket.Send((const char*)&four_bytes, 4);
+ m_socket.Receive((char*)&four_bytes, 4, recv_size);
+
+ *ping = (long)timer.GetTimeElapsed();
+
+ return;
+ }
+
+ m_socket.Send(data, size);
+}
+
+void ClientSide::WriteUDP(const char *data, size_t size)
+{
+ wxCriticalSectionLocker lock(m_CriticalSection);
+
+ unsigned short server_port;
+ std::string host = m_addr.substr(0, m_addr.find(':'));
+ TryParseInt(m_addr.substr(m_addr.find(':')+1).c_str(), (int *)&server_port);
+
+ m_socketUDP.Send(data, size, host.c_str(), server_port);
+}
diff --git a/Source/Core/DolphinWX/Src/NetWindow.cpp b/Source/Core/DolphinWX/Src/NetWindow.cpp
index 455a6aef8d..01e5436da8 100644
--- a/Source/Core/DolphinWX/Src/NetWindow.cpp
+++ b/Source/Core/DolphinWX/Src/NetWindow.cpp
@@ -1,555 +1,555 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "NetWindow.h"
-
-///////////////////////
-// Main Frame window
-
-BEGIN_EVENT_TABLE(NetPlay, wxFrame)
- EVT_BUTTON(ID_BUTTON_JOIN, NetPlay::OnJoin)
- EVT_BUTTON(ID_BUTTON_HOST, NetPlay::OnHost)
-
- EVT_HOST_COMMAND(wxID_ANY, NetPlay::OnNetEvent)
-
- EVT_CHECKBOX(ID_READY, NetPlay::OnGUIEvent)
- EVT_CHECKBOX(ID_RECORD, NetPlay::OnGUIEvent)
- EVT_BUTTON(ID_CHANGEGAME, NetPlay::OnGUIEvent)
- EVT_BUTTON(ID_BUTTON_GETIP, NetPlay::OnGUIEvent)
- EVT_BUTTON(ID_BUTTON_GETPING, NetPlay::OnGUIEvent)
- EVT_BUTTON(ID_BUTTON_CHAT, NetPlay::OnGUIEvent)
- EVT_TEXT_ENTER(ID_CHAT, NetPlay::OnGUIEvent)
- EVT_BUTTON(ID_BUTTON_QUIT, NetPlay::OnDisconnect)
- EVT_CLOSE(NetPlay::OnQuit)
-END_EVENT_TABLE()
-
-NetPlay::NetPlay(wxWindow* parent, std::string GamePaths, std::string GameNames) :
- wxFrame(parent, wxID_ANY, _T("Net Play"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~ wxMAXIMIZE_BOX)
-{
- m_selectedGame = 'a'; m_hostaddr = 'a';
- m_games = GameNames; m_paths = GamePaths;
- m_isHosting = 2; m_ready = m_clients_ready = false;
- m_loopframe = m_frame = m_NetModel = m_numClients = 0;
-
- DrawGUI();
-}
-
-NetPlay::~NetPlay()
-{
- ConfigIni.Load(CONFIG_FILE);
-
- ConfigIni.Set("Netplay", "Nickname", m_nick);
- ConfigIni.Set("Netplay", "UsedPort", (int)m_port);
- ConfigIni.Set("Netplay", "LastIP", m_address);
-
- ConfigIni.Save(CONFIG_FILE);
-}
-
-void NetPlay::OnJoin(wxCommandEvent& WXUNUSED(event))
-{
- unsigned short server_port;
-
- m_address = std::string(m_ConAddr->GetValue().mb_str());
- m_nick = std::string(m_SetNick->GetValue().mb_str());
-
- sf::IPAddress host = m_address.substr(0, m_address.find(':'));
- std::string port_str = m_address.substr(m_address.find(':') + 1);
-
- TryParseUInt(port_str, (u32*)&server_port); // Server port
- TryParseUInt((const char *)m_SetPort->GetValue().mb_str(), (u32*)&m_port); // User port
-
- if (m_nick.size() > 255)
- m_nick = m_nick.substr(0 , 255);
-
- SetTitle(wxT("Net Play : Connecting to Host..."));
-
- // Create the client socket
- sf::SocketTCP sock_client;
- sf::SocketUDP sock_client_UDP;
-
- if (sock_client.Connect(server_port, host, 1.5) == sf::Socket::Done)
- {
- // Try to Bind the UDP Socket
- if (sock_client_UDP.Bind(m_port))
- {
- m_sock_client = new ClientSide(this, sock_client, sock_client_UDP, m_address, m_nick);
- m_sock_client->Create();
- m_sock_client->Run();
-
- // Create the GUI
- m_isHosting = false;
- DrawNetWindow();
- }
- else
- {
- SetTitle(wxT("Net Play"));
- PanicAlert("Can't Bind UDP socket on the specified Port: %d ! \n"
- "Make sure port is forwarded and not in use !", m_port);
- }
- }
- else
- {
- SetTitle(wxT("Net Play"));
- PanicAlert("Can't connect to the specified IP Address ! \nMake sure Hosting port is forwarded !");
- }
-}
-
-void NetPlay::OnHost(wxCommandEvent& WXUNUSED(event))
-{
- TryParseInt(m_SetPort->GetValue().mb_str(), (int*)&m_port);
-
- m_nick = std::string(m_SetNick->GetValue().mb_str());
-
- if (m_GameList->GetSelection() == wxNOT_FOUND) {
- PanicAlert("No Game Selected ! Please select a Game...");
- return;
- }
- if (!m_SetPort->GetValue().size() || m_port < 1000 || m_port > 65535) {
- PanicAlert("Bad Port entered (%d) ! Please enter a working socket port...", m_port);
- return;
- }
- if (m_nick.size() > 255)
- m_nick = m_nick.substr(0 , 255);
-
- m_NetModel = m_NetMode->GetSelection();
- m_selectedGame = std::string(m_GameList_str[m_GameList->GetSelection()].mb_str());
-
- // Create the listening socket
- sf::SocketTCP sock_server;
- sf::SocketUDP sock_server_UDP;
-
- // Start the listening socket and bind UDP socket port
- if (sock_server.Listen(m_port) && sock_server_UDP.Bind(m_port))
- {
- m_sock_server = new ServerSide(this, sock_server, sock_server_UDP, m_NetModel, m_nick);
- m_sock_server->Create();
- m_sock_server->Run();
-
- // Create the GUI
- m_isHosting = true;
- DrawNetWindow();
- m_Logging->AppendText(wxString::Format(wxT("WARNING : Hosting requires port to be forwarded in firewall!\n"
- "*Creation Successful on port %d : Waiting for peers...\n"), m_port));
- }
- else
- {
- PanicAlert("Could not listen at specified port !\nMake sure hosting port is not in use !");
- return;
- }
-}
-
-void NetPlay::DrawGUI()
-{
- int str_end = -1;
- int str_start = -1;
- wxArrayString netmodes_str;
-
- for(int i = 0; i < (int)m_games.size(); i++)
- {
- str_start = str_end + 1;
- str_end = (int)m_games.find('\n', str_start);
- std::string buffer = m_games.substr(str_start, str_end - str_start);
-
- if (str_end == (int)std::string::npos || buffer.size() < 1)
- break; // we reached the end of the string
-
- m_GameList_str.Add(wxString::FromAscii(buffer.c_str()));
- }
-
- netmodes_str.Add(wxT("P2P Versus (2 players, faster)"));
- // TODO : netmodes_str.Add(wxT("Server Mode (4 players, slower)"));
-
- wxPanel *panel = new wxPanel(this);
-
- // Tabs
- m_Notebook = new wxNotebook(panel, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
- m_Tab_Connect = new wxPanel(m_Notebook, ID_TAB_CONN, wxDefaultPosition, wxDefaultSize);
- m_Notebook->AddPage(m_Tab_Connect, wxT("Connect"));
- m_Tab_Host = new wxPanel(m_Notebook, ID_TAB_HOST, wxDefaultPosition, wxDefaultSize);
- m_Notebook->AddPage(m_Tab_Host, wxT("Host"));
-
- // Tow window, Nickname & Port settings
- m_SetNick_text = new wxStaticText(panel, wxID_ANY, wxT(" Nickname : "), wxDefaultPosition, wxDefaultSize);
- m_SetNick = new wxTextCtrl(panel, ID_SETNICK, wxT("LOLWUT!"), wxDefaultPosition, wxDefaultSize);
- m_SetPort_text = new wxStaticText(panel, wxID_ANY, wxT(" Port to Use : "), wxDefaultPosition, wxDefaultSize);
- m_SetPort = new wxTextCtrl(panel, ID_SETPORT, wxT("12345"), wxDefaultPosition, wxDefaultSize);
-
- // CONNECTION TAB
- m_ConAddr_text = new wxStaticText(m_Tab_Connect, wxID_ANY, wxT(" IP Address :"), wxDefaultPosition, wxDefaultSize);
- m_ConAddr = new wxTextCtrl(m_Tab_Connect, ID_CONNADDR, wxT("127.0.0.1:12345"), wxDefaultPosition, wxSize(250,20), 0);
- m_UseRandomPort = new wxCheckBox(m_Tab_Connect, ID_USE_RANDOMPORT, wxT("Use random client port for connection"));
- m_JoinGame = new wxButton(m_Tab_Connect, ID_BUTTON_JOIN, wxT("Connect"), wxDefaultPosition, wxDefaultSize);
-
- // Sizers CONNECT
- wxBoxSizer* sConnectTop = new wxBoxSizer(wxHORIZONTAL);
- wxBoxSizer* sConnectSizer = new wxBoxSizer(wxVERTICAL);
-
- sConnectTop->Add(m_ConAddr_text, 0, wxALL|wxALIGN_CENTER, 5);
- sConnectTop->Add(m_ConAddr, 1, wxALL|wxEXPAND, 5);
- sConnectTop->Add(m_JoinGame, 0, wxALL|wxALIGN_RIGHT, 5);
- sConnectSizer->Add(sConnectTop, 0, wxALL|wxEXPAND, 5);
- sConnectSizer->Add(m_UseRandomPort, 0, wxALL|wxALIGN_CENTER, 5);
-
- m_Tab_Connect->SetSizer(sConnectSizer);
-
- // HOSTING TAB
- m_GameList_text = new wxStaticText(m_Tab_Host, wxID_ANY,
- wxT("Warning: Use a forwarded port ! Select Game and press Host :"), wxDefaultPosition, wxDefaultSize);
- m_GameList = new wxListBox(m_Tab_Host, ID_GAMELIST, wxDefaultPosition, wxDefaultSize,
- m_GameList_str, wxLB_SINGLE | wxLB_NEEDED_SB);
- m_HostGame = new wxButton(m_Tab_Host, ID_BUTTON_HOST, wxT("Host"), wxDefaultPosition, wxDefaultSize);
- m_NetMode = new wxChoice(m_Tab_Host, ID_NETMODE, wxDefaultPosition, wxDefaultSize, netmodes_str, 0, wxDefaultValidator);
- m_NetMode->SetSelection(0);
-
- // Sizers HOST
- wxBoxSizer *sHostBox = new wxBoxSizer(wxVERTICAL);
- wxBoxSizer *sHostBottom = new wxBoxSizer(wxHORIZONTAL);
-
- sHostBottom->Add(m_NetMode, 0, wxALL|wxALIGN_CENTER, 5);
- sHostBottom->AddStretchSpacer();
- sHostBottom->Add(m_HostGame, 0, wxALL, 10);
-
- sHostBox->Add(m_GameList_text, 0, wxALL|wxALIGN_CENTER, 5);
- sHostBox->Add(m_GameList, 1, wxALL|wxEXPAND, 6);
- sHostBox->Add(sHostBottom, 0, wxALL|wxEXPAND, 1);
-
- m_Tab_Host->SetSizer(sHostBox);
-
- // Main sizers
- wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
- wxBoxSizer* sMain_top = new wxBoxSizer(wxHORIZONTAL);
-
- sMain_top->Add(m_SetNick_text, 0, wxALL|wxALIGN_CENTER, 3);
- sMain_top->Add(m_SetNick, 1, wxALL|wxALIGN_CENTER, 3);
- sMain_top->AddStretchSpacer();
- sMain_top->Add(m_SetPort_text, 0, wxALL|wxALIGN_CENTER, 3);
- sMain_top->Add(m_SetPort, 1, wxALL|wxALIGN_CENTER, 3);
-
- sMain->Add(sMain_top, 0, wxALL|wxEXPAND, 5);
- sMain->Add(m_Notebook, 1, wxALL|wxEXPAND, 5);
-
- // Adjust panel to window's size, and set resizing minimum boundaries
- panel->SetSizerAndFit(sMain);
- sMain->SetSizeHints((wxWindow*)this);
-
- if (ConfigIni.Load(CONFIG_FILE))
- {
- ConfigIni.Get("Netplay", "Nickname", &m_nick, "Unnamed");
- ConfigIni.Get("Netplay", "UsedPort", (int*)&m_port, 12345);
- ConfigIni.Get("Netplay", "LastIP", &m_address, "127.0.0.1:54321");
-
- m_SetNick->SetValue(wxString::FromAscii(m_nick.c_str()));
- m_SetPort->SetValue(wxString::Format(wxT("%d"), m_port));
- m_ConAddr->SetValue(wxString::FromAscii(m_address.c_str()));
- }
-
- Center(); Show();
-}
-
-void NetPlay::DrawNetWindow()
-{
- // Remove everything from the precedent GUI :D
- DestroyChildren();
-
- SetTitle(wxT("Net Play : Connection Window"));
-
- wxPanel *panel = new wxPanel(this);
- wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
- wxBoxSizer* sTop = new wxBoxSizer(wxVERTICAL);
- wxBoxSizer* sBottom = new wxBoxSizer(wxHORIZONTAL);
-
- m_Game_str = new wxButton(panel, wxID_ANY, wxT(" Game : "), wxDefaultPosition, wxSize(400, 25), wxBU_LEFT);
- m_Game_str->Disable();
-
- m_Logging = new wxTextCtrl(panel, ID_LOGGING_TXT, wxEmptyString,
- wxDefaultPosition, wxSize(400, 250),
- wxTE_RICH2 | wxTE_MULTILINE | wxTE_READONLY);
-
- m_Chat = new wxTextCtrl(panel, ID_CHAT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
- m_Chat_ok = new wxButton(panel, ID_BUTTON_CHAT, wxT("Send"));;
-
- m_Ready = new wxCheckBox(panel, ID_READY, wxT("Click here when ready"), wxDefaultPosition, wxDefaultSize, 0);
- m_RecordGame = new wxCheckBox(panel, ID_RECORD, wxT("Record Game Input"), wxDefaultPosition, wxDefaultSize, 0);
- // TODO: Fix the recording ?
- m_RecordGame->Disable();
-
- m_ConInfo_text = new wxStaticText(panel, ID_CONNINFO_TXT, wxT(" Fps : 0 | Ping : 00 ms"));
- m_GetPing = new wxButton(panel, ID_BUTTON_GETPING, wxT("Ping"), wxDefaultPosition, wxDefaultSize);
- m_Disconnect = new wxButton(panel, ID_BUTTON_QUIT, wxT("Disconnect"), wxDefaultPosition, wxDefaultSize);
-
- wxBoxSizer* sChat = new wxBoxSizer(wxHORIZONTAL);
-
- sTop->Add(m_Game_str, 0, wxALL|wxEXPAND, 1);
- sTop->Add(m_Logging, 1, wxALL|wxEXPAND, 5);
- sChat->Add(m_Chat, 1, wxALL|wxEXPAND, 2);
- sChat->Add(m_Chat_ok, 0, wxALL, 2);
- sTop->Add(sChat, 0, wxALL|wxEXPAND, 2);
-
- wxBoxSizer* sBottom0 = new wxBoxSizer(wxHORIZONTAL);
- wxBoxSizer* sBottom1 = new wxBoxSizer(wxHORIZONTAL);
- wxBoxSizer* sBottomM = new wxBoxSizer(wxHORIZONTAL);
- wxBoxSizer* sBottom2 = new wxBoxSizer(wxVERTICAL);
-
- sBottom0->Add(m_Ready, 0, wxALL, 5);
- sBottom0->Add(m_RecordGame, 0, wxALL, 5);
- sBottomM->Add(m_ConInfo_text, 0, wxALL, 5);
- sBottom1->Add(m_Disconnect, 0, wxALL|wxALIGN_LEFT, 5);
- sBottom1->AddStretchSpacer(1);
- sBottom1->Add(m_GetPing, 0, wxALL|wxALIGN_RIGHT, 5);
-
- sBottom2->Add(sBottom0, 0, wxALL, 0);
- sBottom2->Add(sBottomM, 0, wxALL | wxALIGN_LEFT, 0);
- sBottom2->Add(sBottom1, 0, wxALL | wxEXPAND, 5);
-
- sBottom->Add(sBottom2, 2, wxALL | wxEXPAND | wxALIGN_CENTER, 0);
-
- if (m_isHosting)
- {
- m_wtfismyip = new wxButton(panel, ID_BUTTON_GETIP, wxT("What is my IP"));
- m_ChangeGame = new wxButton(panel, ID_CHANGEGAME, wxT("Change Game"));
-
- wxStaticBoxSizer* sBottom3 = new wxStaticBoxSizer(wxVERTICAL, panel, wxT("Host"));
-
- sBottom3->Add(m_ChangeGame, 0, wxALL | wxEXPAND, 5);
- sBottom3->Add(m_wtfismyip, 0, wxALL | wxEXPAND, 5);
- sBottom->Add(sBottom3, 1, wxALL | wxEXPAND, 0);
-
- UpdateNetWindow(false);
- }
-
- sMain->Add(sTop, 1, wxALL | wxEXPAND, 5);
- sMain->Add(sBottom, 0, wxALL | wxEXPAND | wxALIGN_CENTER, 2);
-
- panel->SetSizerAndFit(sMain);
- sMain->SetSizeHints((wxWindow*)this);
-
- Show();
-}
-
-// String of the type : FPSxPINGxFRAME_DELAY
-void NetPlay::UpdateNetWindow(bool update_infos, wxString infos)
-{
- std::vector<std::string> str_arr;
-
- if (update_infos)
- {
- SplitString(std::string(infos.mb_str()), "x", str_arr);
-
- m_ConInfo_text->SetLabel
- (wxString::Format(wxT(" Fps : %s | Ping : %s | Frame Delay : %s"),
- str_arr[0].c_str(), str_arr[1].c_str(),
- str_arr[2].c_str()) );
- }
- else
- {
- m_critical.Enter();
- m_Game_str->SetLabel(wxString::Format(wxT(" Game : %s"), m_selectedGame.c_str()));
- m_critical.Leave();
- }
-}
-
-void NetPlay::OnGUIEvent(wxCommandEvent& event)
-{
- unsigned char value;;
- switch (event.GetId())
- {
- case ID_READY:
- {
- std::string buffer;
- value = 0x40;
-
- if (!m_ready)
- buffer = ">> "+m_nick+" is now ready !\n";
- else
- buffer = ">> "+m_nick+" is now Unready !\n";
-
- m_ready = !m_ready;
-
- if (m_isHosting == 1)
- {
- if (m_numClients > 0)
- {
- int buffer_size = (int)buffer.size();
- for (int i=0; i < m_numClients ; i++)
- {
- m_sock_server->Write(i, (const char*)&value, 1);
-
- m_sock_server->Write(i, (const char*)&buffer_size, 4);
- m_sock_server->Write(i, buffer.c_str(), buffer_size + 1);
- }
- }
-
- m_Logging->AppendText(wxString::FromAscii(buffer.c_str()));
-
- // Everyone is ready
- if (m_ready && m_clients_ready)
- LoadGame();
- }
- else {
- if (m_numClients > 0)
- m_sock_client->Write((const char*)&value, 1); // 0x40 -> Ready
- }
- break;
- }
- case ID_BUTTON_GETIP:
- {
- if (m_numClients == 0) // Get IP Address from the Internet
- {
- // simple IP address caching
- if (m_hostaddr.at(0) != 'a')
- {
- m_Logging->AppendText(wxString::FromAscii(m_hostaddr.c_str()));
- return;
- }
-
- char buffer[8];
- sprintf(buffer, "%d", m_port);
-
- m_hostaddr = "> Your IP is : " + sf::IPAddress::GetPublicAddress().ToString() +
- ':' + std::string(buffer) + '\n';
- m_Logging->AppendText(wxString::FromAscii(m_hostaddr.c_str()));
- }
- else // Ask client to send server IP
- {
- value = 0x20;
- m_sock_server->Write(0, (const char*)&value, 1);
- }
- break;
- }
- case ID_BUTTON_GETPING:
- {
- if (m_numClients == 0)
- return;
-
- long ping[3] = {0};
- float fping;
-
- if (m_isHosting == 1) {
- m_sock_server->Write(0, 0, 0, ping);
- fping = (ping[0]+ping[1]+ping[2])/(float)m_numClients;
- }
- else {
- m_sock_client->Write(0, 0, ping);
- fping = ping[0];
- }
-
- UpdateNetWindow( true, wxString::Format(wxT("000x%fx%d"), fping, (int)ceil(fping/(1000.0/60.0))) );
- break;
- }
- case ID_BUTTON_CHAT:
- case ID_CHAT:
- {
- value = 0x30;
- wxString chat_str = wxString::Format(wxT("> %s : %s\n"), m_nick.c_str(), m_Chat->GetValue().c_str());
- int chat_size = (int)chat_str.size();
-
- // If there's no distant connection, we write but we don't send
- if (m_numClients == 0) {
- m_Logging->AppendText(chat_str);
- return;
- }
- // Max size that we handle is 1024, there's no need for more
- if ((chat_str.size()+1) * sizeof(char) > 1024) {
- m_Logging->AppendText(wxT("ERROR : Packet too large !\n"));
- return;
- }
-
- // Send to all
- if (m_isHosting == 1)
- {
- for (int i=0; i < m_numClients ; i++) {
- // Send Chat command
- m_sock_server->Write(i, (const char*)&value, 1); // 0x30 -> Chat
-
- // Send Chat string
- m_sock_server->Write(i, (const char*)&chat_size, 4);
- m_sock_server->Write(i, chat_str.mb_str(), chat_size + 1);
- }
- }
- else {
- m_sock_client->Write((const char*)&value, 1);
- m_sock_client->Write((const char*)&chat_size, 4);
- m_sock_client->Write(chat_str.mb_str(), chat_size + 1);
- }
-
- m_Chat->Clear();
-
- // Do not wait for the server, just write as soon as sent
- m_Logging->AppendText(chat_str);
-
- break;
- }
- case ID_RECORD:
- // TODO :
- // Record raw pad data
- break;
- case ID_CHANGEGAME:
- {
- GameListPopup PopUp(this, m_GameList_str);
- PopUp.ShowModal();
- break;
- }
- }
-}
-
-/////////////////////////
-// GameList popup window
-
-BEGIN_EVENT_TABLE(GameListPopup, wxDialog)
- EVT_BUTTON(wxID_OK, GameListPopup::OnButtons)
- EVT_BUTTON(wxID_CANCEL, GameListPopup::OnButtons)
-END_EVENT_TABLE()
-
-GameListPopup::GameListPopup(NetPlay *parent, wxArrayString GameNames) :
- wxDialog(parent, wxID_ANY, _T("Choose a Game :"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
-{
- m_netParent = parent;
- m_GameList_str = GameNames;
- m_GameList = new wxListBox(this, ID_GAMELIST, wxDefaultPosition, wxSize(300, 250),
- GameNames, wxLB_SINGLE | wxLB_SORT | wxLB_NEEDED_SB);
- m_Cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize);
- m_Accept = new wxButton(this, wxID_OK, wxT("Apply"), wxDefaultPosition, wxDefaultSize);
-
- wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL);
- wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
-
- sButtons->Add(m_Cancel, 0, wxALL, 0);
- sButtons->AddStretchSpacer(1);
- sButtons->Add(m_Accept, 0, wxALL | wxALIGN_RIGHT, 0);
-
- sMain->Add(m_GameList, 0, wxALL | wxEXPAND, 2);
- sMain->Add(sButtons, 0, wxALL | wxEXPAND, 5);
-
- SetSizerAndFit(sMain);
- Center(); Layout(); Show();
-}
-
-void GameListPopup::OnButtons(wxCommandEvent& event)
-{
- switch (event.GetId())
- {
- case wxID_OK:
- if (m_GameList->GetSelection() != wxNOT_FOUND)
- m_netParent->ChangeSelectedGame(std::string(m_GameList_str[m_GameList->GetSelection()].mb_str()));
- Destroy();
- break;
- case wxID_CANCEL:
- Destroy();
- break;
- }
-}
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "NetWindow.h"
+
+///////////////////////
+// Main Frame window
+
+BEGIN_EVENT_TABLE(NetPlay, wxFrame)
+ EVT_BUTTON(ID_BUTTON_JOIN, NetPlay::OnJoin)
+ EVT_BUTTON(ID_BUTTON_HOST, NetPlay::OnHost)
+
+ EVT_HOST_COMMAND(wxID_ANY, NetPlay::OnNetEvent)
+
+ EVT_CHECKBOX(ID_READY, NetPlay::OnGUIEvent)
+ EVT_CHECKBOX(ID_RECORD, NetPlay::OnGUIEvent)
+ EVT_BUTTON(ID_CHANGEGAME, NetPlay::OnGUIEvent)
+ EVT_BUTTON(ID_BUTTON_GETIP, NetPlay::OnGUIEvent)
+ EVT_BUTTON(ID_BUTTON_GETPING, NetPlay::OnGUIEvent)
+ EVT_BUTTON(ID_BUTTON_CHAT, NetPlay::OnGUIEvent)
+ EVT_TEXT_ENTER(ID_CHAT, NetPlay::OnGUIEvent)
+ EVT_BUTTON(ID_BUTTON_QUIT, NetPlay::OnDisconnect)
+ EVT_CLOSE(NetPlay::OnQuit)
+END_EVENT_TABLE()
+
+NetPlay::NetPlay(wxWindow* parent, std::string GamePaths, std::string GameNames) :
+ wxFrame(parent, wxID_ANY, _T("Net Play"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~ wxMAXIMIZE_BOX)
+{
+ m_selectedGame = 'a'; m_hostaddr = 'a';
+ m_games = GameNames; m_paths = GamePaths;
+ m_isHosting = 2; m_ready = m_clients_ready = false;
+ m_loopframe = m_frame = m_NetModel = m_numClients = 0;
+
+ DrawGUI();
+}
+
+NetPlay::~NetPlay()
+{
+ ConfigIni.Load(CONFIG_FILE);
+
+ ConfigIni.Set("Netplay", "Nickname", m_nick);
+ ConfigIni.Set("Netplay", "UsedPort", (int)m_port);
+ ConfigIni.Set("Netplay", "LastIP", m_address);
+
+ ConfigIni.Save(CONFIG_FILE);
+}
+
+void NetPlay::OnJoin(wxCommandEvent& WXUNUSED(event))
+{
+ unsigned short server_port;
+
+ m_address = std::string(m_ConAddr->GetValue().mb_str());
+ m_nick = std::string(m_SetNick->GetValue().mb_str());
+
+ sf::IPAddress host = m_address.substr(0, m_address.find(':'));
+ std::string port_str = m_address.substr(m_address.find(':') + 1);
+
+ TryParseUInt(port_str, (u32*)&server_port); // Server port
+ TryParseUInt((const char *)m_SetPort->GetValue().mb_str(), (u32*)&m_port); // User port
+
+ if (m_nick.size() > 255)
+ m_nick = m_nick.substr(0 , 255);
+
+ SetTitle(wxT("Net Play : Connecting to Host..."));
+
+ // Create the client socket
+ sf::SocketTCP sock_client;
+ sf::SocketUDP sock_client_UDP;
+
+ if (sock_client.Connect(server_port, host, 1.5) == sf::Socket::Done)
+ {
+ // Try to Bind the UDP Socket
+ if (sock_client_UDP.Bind(m_port))
+ {
+ m_sock_client = new ClientSide(this, sock_client, sock_client_UDP, m_address, m_nick);
+ m_sock_client->Create();
+ m_sock_client->Run();
+
+ // Create the GUI
+ m_isHosting = false;
+ DrawNetWindow();
+ }
+ else
+ {
+ SetTitle(wxT("Net Play"));
+ PanicAlert("Can't Bind UDP socket on the specified Port: %d ! \n"
+ "Make sure port is forwarded and not in use !", m_port);
+ }
+ }
+ else
+ {
+ SetTitle(wxT("Net Play"));
+ PanicAlert("Can't connect to the specified IP Address ! \nMake sure Hosting port is forwarded !");
+ }
+}
+
+void NetPlay::OnHost(wxCommandEvent& WXUNUSED(event))
+{
+ TryParseInt(m_SetPort->GetValue().mb_str(), (int*)&m_port);
+
+ m_nick = std::string(m_SetNick->GetValue().mb_str());
+
+ if (m_GameList->GetSelection() == wxNOT_FOUND) {
+ PanicAlert("No Game Selected ! Please select a Game...");
+ return;
+ }
+ if (!m_SetPort->GetValue().size() || m_port < 1000 || m_port > 65535) {
+ PanicAlert("Bad Port entered (%d) ! Please enter a working socket port...", m_port);
+ return;
+ }
+ if (m_nick.size() > 255)
+ m_nick = m_nick.substr(0 , 255);
+
+ m_NetModel = m_NetMode->GetSelection();
+ m_selectedGame = std::string(m_GameList_str[m_GameList->GetSelection()].mb_str());
+
+ // Create the listening socket
+ sf::SocketTCP sock_server;
+ sf::SocketUDP sock_server_UDP;
+
+ // Start the listening socket and bind UDP socket port
+ if (sock_server.Listen(m_port) && sock_server_UDP.Bind(m_port))
+ {
+ m_sock_server = new ServerSide(this, sock_server, sock_server_UDP, m_NetModel, m_nick);
+ m_sock_server->Create();
+ m_sock_server->Run();
+
+ // Create the GUI
+ m_isHosting = true;
+ DrawNetWindow();
+ m_Logging->AppendText(wxString::Format(wxT("WARNING : Hosting requires port to be forwarded in firewall!\n"
+ "*Creation Successful on port %d : Waiting for peers...\n"), m_port));
+ }
+ else
+ {
+ PanicAlert("Could not listen at specified port !\nMake sure hosting port is not in use !");
+ return;
+ }
+}
+
+void NetPlay::DrawGUI()
+{
+ int str_end = -1;
+ int str_start = -1;
+ wxArrayString netmodes_str;
+
+ for(int i = 0; i < (int)m_games.size(); i++)
+ {
+ str_start = str_end + 1;
+ str_end = (int)m_games.find('\n', str_start);
+ std::string buffer = m_games.substr(str_start, str_end - str_start);
+
+ if (str_end == (int)std::string::npos || buffer.size() < 1)
+ break; // we reached the end of the string
+
+ m_GameList_str.Add(wxString::FromAscii(buffer.c_str()));
+ }
+
+ netmodes_str.Add(wxT("P2P Versus (2 players, faster)"));
+ // TODO : netmodes_str.Add(wxT("Server Mode (4 players, slower)"));
+
+ wxPanel *panel = new wxPanel(this);
+
+ // Tabs
+ m_Notebook = new wxNotebook(panel, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize);
+ m_Tab_Connect = new wxPanel(m_Notebook, ID_TAB_CONN, wxDefaultPosition, wxDefaultSize);
+ m_Notebook->AddPage(m_Tab_Connect, wxT("Connect"));
+ m_Tab_Host = new wxPanel(m_Notebook, ID_TAB_HOST, wxDefaultPosition, wxDefaultSize);
+ m_Notebook->AddPage(m_Tab_Host, wxT("Host"));
+
+ // Tow window, Nickname & Port settings
+ m_SetNick_text = new wxStaticText(panel, wxID_ANY, wxT(" Nickname : "), wxDefaultPosition, wxDefaultSize);
+ m_SetNick = new wxTextCtrl(panel, ID_SETNICK, wxT("LOLWUT!"), wxDefaultPosition, wxDefaultSize);
+ m_SetPort_text = new wxStaticText(panel, wxID_ANY, wxT(" Port to Use : "), wxDefaultPosition, wxDefaultSize);
+ m_SetPort = new wxTextCtrl(panel, ID_SETPORT, wxT("12345"), wxDefaultPosition, wxDefaultSize);
+
+ // CONNECTION TAB
+ m_ConAddr_text = new wxStaticText(m_Tab_Connect, wxID_ANY, wxT(" IP Address :"), wxDefaultPosition, wxDefaultSize);
+ m_ConAddr = new wxTextCtrl(m_Tab_Connect, ID_CONNADDR, wxT("127.0.0.1:12345"), wxDefaultPosition, wxSize(250,20), 0);
+ m_UseRandomPort = new wxCheckBox(m_Tab_Connect, ID_USE_RANDOMPORT, wxT("Use random client port for connection"));
+ m_JoinGame = new wxButton(m_Tab_Connect, ID_BUTTON_JOIN, wxT("Connect"), wxDefaultPosition, wxDefaultSize);
+
+ // Sizers CONNECT
+ wxBoxSizer* sConnectTop = new wxBoxSizer(wxHORIZONTAL);
+ wxBoxSizer* sConnectSizer = new wxBoxSizer(wxVERTICAL);
+
+ sConnectTop->Add(m_ConAddr_text, 0, wxALL|wxALIGN_CENTER, 5);
+ sConnectTop->Add(m_ConAddr, 1, wxALL|wxEXPAND, 5);
+ sConnectTop->Add(m_JoinGame, 0, wxALL|wxALIGN_RIGHT, 5);
+ sConnectSizer->Add(sConnectTop, 0, wxALL|wxEXPAND, 5);
+ sConnectSizer->Add(m_UseRandomPort, 0, wxALL|wxALIGN_CENTER, 5);
+
+ m_Tab_Connect->SetSizer(sConnectSizer);
+
+ // HOSTING TAB
+ m_GameList_text = new wxStaticText(m_Tab_Host, wxID_ANY,
+ wxT("Warning: Use a forwarded port ! Select Game and press Host :"), wxDefaultPosition, wxDefaultSize);
+ m_GameList = new wxListBox(m_Tab_Host, ID_GAMELIST, wxDefaultPosition, wxDefaultSize,
+ m_GameList_str, wxLB_SINGLE | wxLB_NEEDED_SB);
+ m_HostGame = new wxButton(m_Tab_Host, ID_BUTTON_HOST, wxT("Host"), wxDefaultPosition, wxDefaultSize);
+ m_NetMode = new wxChoice(m_Tab_Host, ID_NETMODE, wxDefaultPosition, wxDefaultSize, netmodes_str, 0, wxDefaultValidator);
+ m_NetMode->SetSelection(0);
+
+ // Sizers HOST
+ wxBoxSizer *sHostBox = new wxBoxSizer(wxVERTICAL);
+ wxBoxSizer *sHostBottom = new wxBoxSizer(wxHORIZONTAL);
+
+ sHostBottom->Add(m_NetMode, 0, wxALL|wxALIGN_CENTER, 5);
+ sHostBottom->AddStretchSpacer();
+ sHostBottom->Add(m_HostGame, 0, wxALL, 10);
+
+ sHostBox->Add(m_GameList_text, 0, wxALL|wxALIGN_CENTER, 5);
+ sHostBox->Add(m_GameList, 1, wxALL|wxEXPAND, 6);
+ sHostBox->Add(sHostBottom, 0, wxALL|wxEXPAND, 1);
+
+ m_Tab_Host->SetSizer(sHostBox);
+
+ // Main sizers
+ wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
+ wxBoxSizer* sMain_top = new wxBoxSizer(wxHORIZONTAL);
+
+ sMain_top->Add(m_SetNick_text, 0, wxALL|wxALIGN_CENTER, 3);
+ sMain_top->Add(m_SetNick, 1, wxALL|wxALIGN_CENTER, 3);
+ sMain_top->AddStretchSpacer();
+ sMain_top->Add(m_SetPort_text, 0, wxALL|wxALIGN_CENTER, 3);
+ sMain_top->Add(m_SetPort, 1, wxALL|wxALIGN_CENTER, 3);
+
+ sMain->Add(sMain_top, 0, wxALL|wxEXPAND, 5);
+ sMain->Add(m_Notebook, 1, wxALL|wxEXPAND, 5);
+
+ // Adjust panel to window's size, and set resizing minimum boundaries
+ panel->SetSizerAndFit(sMain);
+ sMain->SetSizeHints((wxWindow*)this);
+
+ if (ConfigIni.Load(CONFIG_FILE))
+ {
+ ConfigIni.Get("Netplay", "Nickname", &m_nick, "Unnamed");
+ ConfigIni.Get("Netplay", "UsedPort", (int*)&m_port, 12345);
+ ConfigIni.Get("Netplay", "LastIP", &m_address, "127.0.0.1:54321");
+
+ m_SetNick->SetValue(wxString::FromAscii(m_nick.c_str()));
+ m_SetPort->SetValue(wxString::Format(wxT("%d"), m_port));
+ m_ConAddr->SetValue(wxString::FromAscii(m_address.c_str()));
+ }
+
+ Center(); Show();
+}
+
+void NetPlay::DrawNetWindow()
+{
+ // Remove everything from the precedent GUI :D
+ DestroyChildren();
+
+ SetTitle(wxT("Net Play : Connection Window"));
+
+ wxPanel *panel = new wxPanel(this);
+ wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
+ wxBoxSizer* sTop = new wxBoxSizer(wxVERTICAL);
+ wxBoxSizer* sBottom = new wxBoxSizer(wxHORIZONTAL);
+
+ m_Game_str = new wxButton(panel, wxID_ANY, wxT(" Game : "), wxDefaultPosition, wxSize(400, 25), wxBU_LEFT);
+ m_Game_str->Disable();
+
+ m_Logging = new wxTextCtrl(panel, ID_LOGGING_TXT, wxEmptyString,
+ wxDefaultPosition, wxSize(400, 250),
+ wxTE_RICH2 | wxTE_MULTILINE | wxTE_READONLY);
+
+ m_Chat = new wxTextCtrl(panel, ID_CHAT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
+ m_Chat_ok = new wxButton(panel, ID_BUTTON_CHAT, wxT("Send"));;
+
+ m_Ready = new wxCheckBox(panel, ID_READY, wxT("Click here when ready"), wxDefaultPosition, wxDefaultSize, 0);
+ m_RecordGame = new wxCheckBox(panel, ID_RECORD, wxT("Record Game Input"), wxDefaultPosition, wxDefaultSize, 0);
+ // TODO: Fix the recording ?
+ m_RecordGame->Disable();
+
+ m_ConInfo_text = new wxStaticText(panel, ID_CONNINFO_TXT, wxT(" Fps : 0 | Ping : 00 ms"));
+ m_GetPing = new wxButton(panel, ID_BUTTON_GETPING, wxT("Ping"), wxDefaultPosition, wxDefaultSize);
+ m_Disconnect = new wxButton(panel, ID_BUTTON_QUIT, wxT("Disconnect"), wxDefaultPosition, wxDefaultSize);
+
+ wxBoxSizer* sChat = new wxBoxSizer(wxHORIZONTAL);
+
+ sTop->Add(m_Game_str, 0, wxALL|wxEXPAND, 1);
+ sTop->Add(m_Logging, 1, wxALL|wxEXPAND, 5);
+ sChat->Add(m_Chat, 1, wxALL|wxEXPAND, 2);
+ sChat->Add(m_Chat_ok, 0, wxALL, 2);
+ sTop->Add(sChat, 0, wxALL|wxEXPAND, 2);
+
+ wxBoxSizer* sBottom0 = new wxBoxSizer(wxHORIZONTAL);
+ wxBoxSizer* sBottom1 = new wxBoxSizer(wxHORIZONTAL);
+ wxBoxSizer* sBottomM = new wxBoxSizer(wxHORIZONTAL);
+ wxBoxSizer* sBottom2 = new wxBoxSizer(wxVERTICAL);
+
+ sBottom0->Add(m_Ready, 0, wxALL, 5);
+ sBottom0->Add(m_RecordGame, 0, wxALL, 5);
+ sBottomM->Add(m_ConInfo_text, 0, wxALL, 5);
+ sBottom1->Add(m_Disconnect, 0, wxALL|wxALIGN_LEFT, 5);
+ sBottom1->AddStretchSpacer(1);
+ sBottom1->Add(m_GetPing, 0, wxALL|wxALIGN_RIGHT, 5);
+
+ sBottom2->Add(sBottom0, 0, wxALL, 0);
+ sBottom2->Add(sBottomM, 0, wxALL | wxALIGN_LEFT, 0);
+ sBottom2->Add(sBottom1, 0, wxALL | wxEXPAND, 5);
+
+ sBottom->Add(sBottom2, 2, wxALL | wxEXPAND | wxALIGN_CENTER, 0);
+
+ if (m_isHosting)
+ {
+ m_wtfismyip = new wxButton(panel, ID_BUTTON_GETIP, wxT("What is my IP"));
+ m_ChangeGame = new wxButton(panel, ID_CHANGEGAME, wxT("Change Game"));
+
+ wxStaticBoxSizer* sBottom3 = new wxStaticBoxSizer(wxVERTICAL, panel, wxT("Host"));
+
+ sBottom3->Add(m_ChangeGame, 0, wxALL | wxEXPAND, 5);
+ sBottom3->Add(m_wtfismyip, 0, wxALL | wxEXPAND, 5);
+ sBottom->Add(sBottom3, 1, wxALL | wxEXPAND, 0);
+
+ UpdateNetWindow(false);
+ }
+
+ sMain->Add(sTop, 1, wxALL | wxEXPAND, 5);
+ sMain->Add(sBottom, 0, wxALL | wxEXPAND | wxALIGN_CENTER, 2);
+
+ panel->SetSizerAndFit(sMain);
+ sMain->SetSizeHints((wxWindow*)this);
+
+ Show();
+}
+
+// String of the type : FPSxPINGxFRAME_DELAY
+void NetPlay::UpdateNetWindow(bool update_infos, wxString infos)
+{
+ std::vector<std::string> str_arr;
+
+ if (update_infos)
+ {
+ SplitString(std::string(infos.mb_str()), "x", str_arr);
+
+ m_ConInfo_text->SetLabel
+ (wxString::Format(wxT(" Fps : %s | Ping : %s | Frame Delay : %s"),
+ str_arr[0].c_str(), str_arr[1].c_str(),
+ str_arr[2].c_str()) );
+ }
+ else
+ {
+ m_critical.Enter();
+ m_Game_str->SetLabel(wxString::Format(wxT(" Game : %s"), m_selectedGame.c_str()));
+ m_critical.Leave();
+ }
+}
+
+void NetPlay::OnGUIEvent(wxCommandEvent& event)
+{
+ unsigned char value;;
+ switch (event.GetId())
+ {
+ case ID_READY:
+ {
+ std::string buffer;
+ value = 0x40;
+
+ if (!m_ready)
+ buffer = ">> "+m_nick+" is now ready !\n";
+ else
+ buffer = ">> "+m_nick+" is now Unready !\n";
+
+ m_ready = !m_ready;
+
+ if (m_isHosting == 1)
+ {
+ if (m_numClients > 0)
+ {
+ int buffer_size = (int)buffer.size();
+ for (int i=0; i < m_numClients ; i++)
+ {
+ m_sock_server->Write(i, (const char*)&value, 1);
+
+ m_sock_server->Write(i, (const char*)&buffer_size, 4);
+ m_sock_server->Write(i, buffer.c_str(), buffer_size + 1);
+ }
+ }
+
+ m_Logging->AppendText(wxString::FromAscii(buffer.c_str()));
+
+ // Everyone is ready
+ if (m_ready && m_clients_ready)
+ LoadGame();
+ }
+ else {
+ if (m_numClients > 0)
+ m_sock_client->Write((const char*)&value, 1); // 0x40 -> Ready
+ }
+ break;
+ }
+ case ID_BUTTON_GETIP:
+ {
+ if (m_numClients == 0) // Get IP Address from the Internet
+ {
+ // simple IP address caching
+ if (m_hostaddr.at(0) != 'a')
+ {
+ m_Logging->AppendText(wxString::FromAscii(m_hostaddr.c_str()));
+ return;
+ }
+
+ char buffer[8];
+ sprintf(buffer, "%d", m_port);
+
+ m_hostaddr = "> Your IP is : " + sf::IPAddress::GetPublicAddress().ToString() +
+ ':' + std::string(buffer) + '\n';
+ m_Logging->AppendText(wxString::FromAscii(m_hostaddr.c_str()));
+ }
+ else // Ask client to send server IP
+ {
+ value = 0x20;
+ m_sock_server->Write(0, (const char*)&value, 1);
+ }
+ break;
+ }
+ case ID_BUTTON_GETPING:
+ {
+ if (m_numClients == 0)
+ return;
+
+ long ping[3] = {0};
+ float fping;
+
+ if (m_isHosting == 1) {
+ m_sock_server->Write(0, 0, 0, ping);
+ fping = (ping[0]+ping[1]+ping[2])/(float)m_numClients;
+ }
+ else {
+ m_sock_client->Write(0, 0, ping);
+ fping = ping[0];
+ }
+
+ UpdateNetWindow( true, wxString::Format(wxT("000x%fx%d"), fping, (int)ceil(fping/(1000.0/60.0))) );
+ break;
+ }
+ case ID_BUTTON_CHAT:
+ case ID_CHAT:
+ {
+ value = 0x30;
+ wxString chat_str = wxString::Format(wxT("> %s : %s\n"), m_nick.c_str(), m_Chat->GetValue().c_str());
+ int chat_size = (int)chat_str.size();
+
+ // If there's no distant connection, we write but we don't send
+ if (m_numClients == 0) {
+ m_Logging->AppendText(chat_str);
+ return;
+ }
+ // Max size that we handle is 1024, there's no need for more
+ if ((chat_str.size()+1) * sizeof(char) > 1024) {
+ m_Logging->AppendText(wxT("ERROR : Packet too large !\n"));
+ return;
+ }
+
+ // Send to all
+ if (m_isHosting == 1)
+ {
+ for (int i=0; i < m_numClients ; i++) {
+ // Send Chat command
+ m_sock_server->Write(i, (const char*)&value, 1); // 0x30 -> Chat
+
+ // Send Chat string
+ m_sock_server->Write(i, (const char*)&chat_size, 4);
+ m_sock_server->Write(i, chat_str.mb_str(), chat_size + 1);
+ }
+ }
+ else {
+ m_sock_client->Write((const char*)&value, 1);
+ m_sock_client->Write((const char*)&chat_size, 4);
+ m_sock_client->Write(chat_str.mb_str(), chat_size + 1);
+ }
+
+ m_Chat->Clear();
+
+ // Do not wait for the server, just write as soon as sent
+ m_Logging->AppendText(chat_str);
+
+ break;
+ }
+ case ID_RECORD:
+ // TODO :
+ // Record raw pad data
+ break;
+ case ID_CHANGEGAME:
+ {
+ GameListPopup PopUp(this, m_GameList_str);
+ PopUp.ShowModal();
+ break;
+ }
+ }
+}
+
+/////////////////////////
+// GameList popup window
+
+BEGIN_EVENT_TABLE(GameListPopup, wxDialog)
+ EVT_BUTTON(wxID_OK, GameListPopup::OnButtons)
+ EVT_BUTTON(wxID_CANCEL, GameListPopup::OnButtons)
+END_EVENT_TABLE()
+
+GameListPopup::GameListPopup(NetPlay *parent, wxArrayString GameNames) :
+ wxDialog(parent, wxID_ANY, _T("Choose a Game :"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE)
+{
+ m_netParent = parent;
+ m_GameList_str = GameNames;
+ m_GameList = new wxListBox(this, ID_GAMELIST, wxDefaultPosition, wxSize(300, 250),
+ GameNames, wxLB_SINGLE | wxLB_SORT | wxLB_NEEDED_SB);
+ m_Cancel = new wxButton(this, wxID_CANCEL, wxT("Cancel"), wxDefaultPosition, wxDefaultSize);
+ m_Accept = new wxButton(this, wxID_OK, wxT("Apply"), wxDefaultPosition, wxDefaultSize);
+
+ wxBoxSizer* sButtons = new wxBoxSizer(wxHORIZONTAL);
+ wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
+
+ sButtons->Add(m_Cancel, 0, wxALL, 0);
+ sButtons->AddStretchSpacer(1);
+ sButtons->Add(m_Accept, 0, wxALL | wxALIGN_RIGHT, 0);
+
+ sMain->Add(m_GameList, 0, wxALL | wxEXPAND, 2);
+ sMain->Add(sButtons, 0, wxALL | wxEXPAND, 5);
+
+ SetSizerAndFit(sMain);
+ Center(); Layout(); Show();
+}
+
+void GameListPopup::OnButtons(wxCommandEvent& event)
+{
+ switch (event.GetId())
+ {
+ case wxID_OK:
+ if (m_GameList->GetSelection() != wxNOT_FOUND)
+ m_netParent->ChangeSelectedGame(std::string(m_GameList_str[m_GameList->GetSelection()].mb_str()));
+ Destroy();
+ break;
+ case wxID_CANCEL:
+ Destroy();
+ break;
+ }
+}
+
diff --git a/Source/Core/DolphinWX/Src/NetWindow.h b/Source/Core/DolphinWX/Src/NetWindow.h
index 7c0c8bd942..c64a97ca15 100644
--- a/Source/Core/DolphinWX/Src/NetWindow.h
+++ b/Source/Core/DolphinWX/Src/NetWindow.h
@@ -1,317 +1,317 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _NETWINDOW_H_
-#define _NETWINDOW_H_
-
-#include <SFML/Network.hpp>
-#include <string>
-#include <wx/wx.h>
-#include <wx/sizer.h>
-#include <wx/dialog.h>
-#include <wx/notebook.h>
-#include <wx/gbsizer.h>
-#include <wx/listbox.h>
-
-#include <wx/thread.h>
-
-#include "Globals.h"
-#include "BootManager.h"
-#include "Common.h"
-#include "Core.h"
-#include "pluginspecs_pad.h"
-#include "HW/SI.h"
-#include "HW/SI_Device.h"
-#include "HW/SI_DeviceGCController.h"
-#include "Timer.h"
-
-#ifdef _DEBUG
- #define NET_DEBUG
-#endif
-
-// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay,
-// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
-// #define USE_TCP
-
-class NetPlay;
-
-struct Netpads {
- int nHi[128];
- int nLow[128];
-};
-
-struct Clients {
- std::string nick;
- sf::SocketTCP socket;
- unsigned short port;
- sf::IPAddress address;
- bool ready;
-};
-
-class NetEvent
-{
- public:
- NetEvent(NetPlay* netptr) { m_netptr = netptr; }
- ~NetEvent() {};
-
- void SendEvent(int EventType, std::string="NULL", int=NULL);
- void AppendText(const wxString text);
-
- private:
- NetPlay *m_netptr;
-};
-
-class ServerSide : public wxThread
-{
- public:
- ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
- ~ServerSide() {};
-
- virtual void *Entry();
-
- void Write(int socknb, const char *data, size_t size, long *ping=NULL);
- void WriteUDP(int socknb, const char *data, size_t size);
- bool isNewPadData(u32 *netValues, bool current, int client=0);
-
- private:
- bool SyncValues(unsigned char, sf::IPAddress);
- bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
- char GetSocket(sf::SocketTCP Socket);
- void OnServerData(int sock, unsigned char data);
- void IsEveryoneReady();
-
- NetPlay *m_netptr;
- NetEvent *Event;
-
- u32 m_netvalues[3][3];
- bool m_data_received; // New Pad data received ?
-
- unsigned char m_numplayers;
- int m_netmodel;
- std::string m_nick;
-
- Clients m_client[3]; // Connected client objects
- sf::SelectorTCP m_selector;
- sf::SocketTCP m_socket; // Server 'listening' socket
- sf::SocketUDP m_socketUDP;
-
- wxCriticalSection m_CriticalSection;
-};
-
-class ClientSide : public wxThread
-{
- public:
- ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
- ~ClientSide() {}
-
- virtual void *Entry();
-
- void Write(const char *data, size_t size, long *ping=NULL);
- void WriteUDP(const char *data, size_t size);
- bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
-
- private:
- bool SyncValues();
- void CheckGameFound();
- void OnClientData(unsigned char data);
- bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
-
- NetPlay *m_netptr;
- NetEvent *Event;
-
- u32 m_netvalues[3][3];
- bool m_data_received; // New Pad data received ?
-
- unsigned char m_numplayers;
- int m_netmodel;
- std::string m_nick;
- std::string m_hostnick;
- std::string m_selectedgame;
-
- sf::SelectorTCP m_selector;
- sf::SocketTCP m_socket; // Client I/O socket
- sf::SocketUDP m_socketUDP;
- unsigned short m_port;
- std::string m_addr; // Contains the server addr
-
- wxCriticalSection m_CriticalSection;
-};
-
-class NetPlay : public wxFrame
-{
- public:
- NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
- ~NetPlay();
-
- void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
- void AppendText(const wxString text) { m_Logging->AppendText(text); }
-
- // Send and receive pads values
- bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
- void ChangeSelectedGame(std::string game);
- void IsGameFound(unsigned char*, std::string);
- std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
-
- void LoadGame();
-
- protected:
- // Protects our vars from being fuxored by threads
- wxCriticalSection m_critical;
-
- // this draws the GUI, ya rly
- void DrawGUI();
- void DrawNetWindow();
-
- // event handlers
- void OnGUIEvent(wxCommandEvent& event);
- void OnDisconnect(wxCommandEvent& event);
- void OnNetEvent(wxCommandEvent& event);
- void OnQuit(wxCloseEvent& event);
-
- void OnJoin(wxCommandEvent& event);
- void OnHost(wxCommandEvent& event);
-
- // Net play vars (used ingame)
- int m_frame;
- int m_lastframe;
- Common::Timer m_timer;
- int m_loopframe;
- int m_frameDelay;
- bool m_data_received;// True if first frame data received
-
- // Basic vars
- std::string m_paths; // Game paths list
- std::string m_games; // Game names list
-
- std::string m_selectedGame;// Selected game's string
- std::string m_hostaddr; // Used with OnGetIP to cache it
- bool m_ready, m_clients_ready;
- std::string m_nick;
-
- int m_NetModel; // Using P2P model (0) or Server model (1)
- int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
- unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
- std::string m_address; // The address entered into connection box
- unsigned short m_port;
-
- Netpads m_pads[4]; // this struct is used to save synced pad values
- IniFile ConfigIni;
-
- // Sockets objects
- ServerSide *m_sock_server;
- ClientSide *m_sock_client;
-
- // -----------
- // GUI objects
- // -----------
- wxNotebook *m_Notebook;
- wxPanel *m_Tab_Connect;
- wxPanel *m_Tab_Host;
- wxStaticText *m_SetNick_text;
- wxTextCtrl *m_SetNick;
- wxChoice *m_NetMode;
-
- // Host tab :
- wxArrayString m_GameList_str;
- wxStaticText *m_GameList_text;
- wxListBox *m_GameList;
- wxStaticText *m_SetPort_text;
- wxTextCtrl *m_SetPort;
- wxButton *m_HostGame;
-
- // Connect tab :
- wxTextCtrl *m_ConAddr;
- wxStaticText *m_ConAddr_text;
- wxButton *m_JoinGame;
- wxCheckBox *m_UseRandomPort;
-
- // Connection window
- wxButton *m_Game_str;
- wxTextCtrl *m_Logging;
- wxTextCtrl *m_Chat;
- wxButton *m_Chat_ok;
- // Right part
- wxButton *m_wtfismyip;
- wxButton *m_ChangeGame;
- // Left Part
- wxButton *m_Disconnect;
- wxStaticText *m_ConInfo_text;
- wxButton *m_GetPing;
- wxCheckBox *m_Ready;
- wxCheckBox *m_RecordGame;
-
- // wxWidgets event table
- DECLARE_EVENT_TABLE()
-};
-
-class GameListPopup : public wxDialog
-{
- public:
- GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
- ~GameListPopup() {}
- protected:
- void OnButtons(wxCommandEvent& event);
- wxArrayString m_GameList_str;
- NetPlay* m_netParent;
- wxListBox *m_GameList;
- wxButton *m_Accept;
- wxButton *m_Cancel;
- DECLARE_EVENT_TABLE()
-};
-
-enum
-{
- ID_NOTEBOOK,
- ID_TAB_HOST,
- ID_TAB_CONN,
- ID_BUTTON_HOST,
- ID_BUTTON_JOIN,
- ID_NETMODE,
- ID_GAMELIST,
- ID_LOGGING_TXT,
- ID_CHAT,
- ID_SETNICK,
- ID_SETPORT,
- ID_CONNADDR,
- ID_CONNINFO_TXT,
- ID_USE_RANDOMPORT,
- ID_BUTTON_GETPING,
- ID_BUTTON_GETIP,
- ID_CHANGEGAME,
- ID_BUTTON_QUIT,
- ID_BUTTON_CHAT,
- ID_READY,
- ID_RECORD,
-
- ID_SOCKET,
- ID_SERVER,
-
- HOST_FULL = 200, // ...
- HOST_ERROR, // Sent on socket error
- HOST_DISCONNECTED,
- HOST_NEWPLAYER,
- HOST_PLAYERLEFT,
- CLIENTS_READY,
- CLIENTS_NOTREADY,
- GUI_UPDATE, // Refresh the shown selectedgame on GUI
- ADD_TEXT, // Add text to m_Logging (string)
- ADD_INFO, // Sent when updating net infos (string)
- NET_EVENT
-};
-
-#endif // _NETWINDOW_H_
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _NETWINDOW_H_
+#define _NETWINDOW_H_
+
+#include <SFML/Network.hpp>
+#include <string>
+#include <wx/wx.h>
+#include <wx/sizer.h>
+#include <wx/dialog.h>
+#include <wx/notebook.h>
+#include <wx/gbsizer.h>
+#include <wx/listbox.h>
+
+#include <wx/thread.h>
+
+#include "Globals.h"
+#include "BootManager.h"
+#include "Common.h"
+#include "Core.h"
+#include "pluginspecs_pad.h"
+#include "HW/SI.h"
+#include "HW/SI_Device.h"
+#include "HW/SI_DeviceGCController.h"
+#include "Timer.h"
+
+#ifdef _DEBUG
+ #define NET_DEBUG
+#endif
+
+// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay,
+// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
+// #define USE_TCP
+
+class NetPlay;
+
+struct Netpads {
+ int nHi[128];
+ int nLow[128];
+};
+
+struct Clients {
+ std::string nick;
+ sf::SocketTCP socket;
+ unsigned short port;
+ sf::IPAddress address;
+ bool ready;
+};
+
+class NetEvent
+{
+ public:
+ NetEvent(NetPlay* netptr) { m_netptr = netptr; }
+ ~NetEvent() {};
+
+ void SendEvent(int EventType, std::string="NULL", int=NULL);
+ void AppendText(const wxString text);
+
+ private:
+ NetPlay *m_netptr;
+};
+
+class ServerSide : public wxThread
+{
+ public:
+ ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
+ ~ServerSide() {};
+
+ virtual void *Entry();
+
+ void Write(int socknb, const char *data, size_t size, long *ping=NULL);
+ void WriteUDP(int socknb, const char *data, size_t size);
+ bool isNewPadData(u32 *netValues, bool current, int client=0);
+
+ private:
+ bool SyncValues(unsigned char, sf::IPAddress);
+ bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
+ char GetSocket(sf::SocketTCP Socket);
+ void OnServerData(int sock, unsigned char data);
+ void IsEveryoneReady();
+
+ NetPlay *m_netptr;
+ NetEvent *Event;
+
+ u32 m_netvalues[3][3];
+ bool m_data_received; // New Pad data received ?
+
+ unsigned char m_numplayers;
+ int m_netmodel;
+ std::string m_nick;
+
+ Clients m_client[3]; // Connected client objects
+ sf::SelectorTCP m_selector;
+ sf::SocketTCP m_socket; // Server 'listening' socket
+ sf::SocketUDP m_socketUDP;
+
+ wxCriticalSection m_CriticalSection;
+};
+
+class ClientSide : public wxThread
+{
+ public:
+ ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
+ ~ClientSide() {}
+
+ virtual void *Entry();
+
+ void Write(const char *data, size_t size, long *ping=NULL);
+ void WriteUDP(const char *data, size_t size);
+ bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
+
+ private:
+ bool SyncValues();
+ void CheckGameFound();
+ void OnClientData(unsigned char data);
+ bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
+
+ NetPlay *m_netptr;
+ NetEvent *Event;
+
+ u32 m_netvalues[3][3];
+ bool m_data_received; // New Pad data received ?
+
+ unsigned char m_numplayers;
+ int m_netmodel;
+ std::string m_nick;
+ std::string m_hostnick;
+ std::string m_selectedgame;
+
+ sf::SelectorTCP m_selector;
+ sf::SocketTCP m_socket; // Client I/O socket
+ sf::SocketUDP m_socketUDP;
+ unsigned short m_port;
+ std::string m_addr; // Contains the server addr
+
+ wxCriticalSection m_CriticalSection;
+};
+
+class NetPlay : public wxFrame
+{
+ public:
+ NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
+ ~NetPlay();
+
+ void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
+ void AppendText(const wxString text) { m_Logging->AppendText(text); }
+
+ // Send and receive pads values
+ bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
+ void ChangeSelectedGame(std::string game);
+ void IsGameFound(unsigned char*, std::string);
+ std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
+
+ void LoadGame();
+
+ protected:
+ // Protects our vars from being fuxored by threads
+ wxCriticalSection m_critical;
+
+ // this draws the GUI, ya rly
+ void DrawGUI();
+ void DrawNetWindow();
+
+ // event handlers
+ void OnGUIEvent(wxCommandEvent& event);
+ void OnDisconnect(wxCommandEvent& event);
+ void OnNetEvent(wxCommandEvent& event);
+ void OnQuit(wxCloseEvent& event);
+
+ void OnJoin(wxCommandEvent& event);
+ void OnHost(wxCommandEvent& event);
+
+ // Net play vars (used ingame)
+ int m_frame;
+ int m_lastframe;
+ Common::Timer m_timer;
+ int m_loopframe;
+ int m_frameDelay;
+ bool m_data_received;// True if first frame data received
+
+ // Basic vars
+ std::string m_paths; // Game paths list
+ std::string m_games; // Game names list
+
+ std::string m_selectedGame;// Selected game's string
+ std::string m_hostaddr; // Used with OnGetIP to cache it
+ bool m_ready, m_clients_ready;
+ std::string m_nick;
+
+ int m_NetModel; // Using P2P model (0) or Server model (1)
+ int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
+ unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
+ std::string m_address; // The address entered into connection box
+ unsigned short m_port;
+
+ Netpads m_pads[4]; // this struct is used to save synced pad values
+ IniFile ConfigIni;
+
+ // Sockets objects
+ ServerSide *m_sock_server;
+ ClientSide *m_sock_client;
+
+ // -----------
+ // GUI objects
+ // -----------
+ wxNotebook *m_Notebook;
+ wxPanel *m_Tab_Connect;
+ wxPanel *m_Tab_Host;
+ wxStaticText *m_SetNick_text;
+ wxTextCtrl *m_SetNick;
+ wxChoice *m_NetMode;
+
+ // Host tab :
+ wxArrayString m_GameList_str;
+ wxStaticText *m_GameList_text;
+ wxListBox *m_GameList;
+ wxStaticText *m_SetPort_text;
+ wxTextCtrl *m_SetPort;
+ wxButton *m_HostGame;
+
+ // Connect tab :
+ wxTextCtrl *m_ConAddr;
+ wxStaticText *m_ConAddr_text;
+ wxButton *m_JoinGame;
+ wxCheckBox *m_UseRandomPort;
+
+ // Connection window
+ wxButton *m_Game_str;
+ wxTextCtrl *m_Logging;
+ wxTextCtrl *m_Chat;
+ wxButton *m_Chat_ok;
+ // Right part
+ wxButton *m_wtfismyip;
+ wxButton *m_ChangeGame;
+ // Left Part
+ wxButton *m_Disconnect;
+ wxStaticText *m_ConInfo_text;
+ wxButton *m_GetPing;
+ wxCheckBox *m_Ready;
+ wxCheckBox *m_RecordGame;
+
+ // wxWidgets event table
+ DECLARE_EVENT_TABLE()
+};
+
+class GameListPopup : public wxDialog
+{
+ public:
+ GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
+ ~GameListPopup() {}
+ protected:
+ void OnButtons(wxCommandEvent& event);
+ wxArrayString m_GameList_str;
+ NetPlay* m_netParent;
+ wxListBox *m_GameList;
+ wxButton *m_Accept;
+ wxButton *m_Cancel;
+ DECLARE_EVENT_TABLE()
+};
+
+enum
+{
+ ID_NOTEBOOK,
+ ID_TAB_HOST,
+ ID_TAB_CONN,
+ ID_BUTTON_HOST,
+ ID_BUTTON_JOIN,
+ ID_NETMODE,
+ ID_GAMELIST,
+ ID_LOGGING_TXT,
+ ID_CHAT,
+ ID_SETNICK,
+ ID_SETPORT,
+ ID_CONNADDR,
+ ID_CONNINFO_TXT,
+ ID_USE_RANDOMPORT,
+ ID_BUTTON_GETPING,
+ ID_BUTTON_GETIP,
+ ID_CHANGEGAME,
+ ID_BUTTON_QUIT,
+ ID_BUTTON_CHAT,
+ ID_READY,
+ ID_RECORD,
+
+ ID_SOCKET,
+ ID_SERVER,
+
+ HOST_FULL = 200, // ...
+ HOST_ERROR, // Sent on socket error
+ HOST_DISCONNECTED,
+ HOST_NEWPLAYER,
+ HOST_PLAYERLEFT,
+ CLIENTS_READY,
+ CLIENTS_NOTREADY,
+ GUI_UPDATE, // Refresh the shown selectedgame on GUI
+ ADD_TEXT, // Add text to m_Logging (string)
+ ADD_INFO, // Sent when updating net infos (string)
+ NET_EVENT
+};
+
+#endif // _NETWINDOW_H_
+
diff --git a/Source/Core/DolphinWX/Src/Summarize.h b/Source/Core/DolphinWX/Src/Summarize.h
index e0f1c68335..49608767ff 100644
--- a/Source/Core/DolphinWX/Src/Summarize.h
+++ b/Source/Core/DolphinWX/Src/Summarize.h
@@ -1,127 +1,127 @@
-// Copyright (C) 2003-2008 Dolphin Project.
-
-// 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/
-
-#ifndef __SUMMARIZE_H__
-#define __SUMMARIZE_H__
-
-std::string Summarize_Plug()
-{
- return StringFromFormat(
- "Plugin Information\n\n"
- "Default GFX Plugin: %s\n"
- "Default DSP Plugin: %s\n"
- "Default PAD Plugin: %s\n"
- "Default WiiMote Plugin: %s\n\n"
- "Current GFX Plugin: %s\n"
- "Current DSP Plugin: %s\n"
- "Current PAD Plugin[0]: %s\n"
- "Current PAD Plugin[1]: %s\n"
- "Current PAD Plugin[2]: %s\n"
- "Current PAD Plugin[3]: %s\n"
- "Current WiiMote Plugin[0]: %s\n",
- SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
- SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
- SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
- SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
- Core::GetStartupParameter().m_strVideoPlugin.c_str(),
- Core::GetStartupParameter().m_strDSPPlugin.c_str(),
- Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
- Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
- Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
- Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
- Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
- );
-}
-
-std::string Summarize_Settings()
-{
- return StringFromFormat(
- "Dolphin Settings\n\n"
- "Always HLE Bios: %s\n"
- "Use Dynarec: %s\n"
- "Use Dual Core: %s\n"
- "DSP Thread: %s\n"
- "Skip Idle: %s\n"
- "Lock Threads: %s\n"
- "Use Dual Core: %s\n"
- "Default GCM: %s\n"
- "DVD Root: %s\n"
- "Optimize Quantizers: %s\n"
- "Enable Cheats: %s\n"
- "Selected Language: %d\n"
- "Memcard A: %s\n"
- "Memcard B: %s\n"
- "Slot A: %d\n"
- "Slot B: %d\n"
- "Serial Port 1: %d\n"
- "Run Compare Server: %s\n"
- "Run Compare Client: %s\n"
- "TLB Hack: %s\n"
- "Frame Limit: %d\n"
- "[Wii]Widescreen: %s\n"
- "[Wii]Progressive Scan: %s\n",
- Core::GetStartupParameter().bHLEBios?"True":"False",
- Core::GetStartupParameter().bUseJIT?"True":"False",
- Core::GetStartupParameter().bUseDualCore?"True":"False",
- Core::GetStartupParameter().bDSPThread?"True":"False",
- Core::GetStartupParameter().bSkipIdle?"True":"False",
- Core::GetStartupParameter().bLockThreads?"True":"False",
- Core::GetStartupParameter().bUseDualCore?"True":"False",
- Core::GetStartupParameter().m_strDefaultGCM.c_str(),
- Core::GetStartupParameter().m_strDVDRoot.c_str(),
- Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
- Core::GetStartupParameter().bEnableCheats?"True":"False",
- Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
- SConfig::GetInstance().m_strMemoryCardA.c_str(),
- SConfig::GetInstance().m_strMemoryCardB.c_str(),
- SConfig::GetInstance().m_EXIDevice[0], //FIXME
- SConfig::GetInstance().m_EXIDevice[1], //FIXME
- SConfig::GetInstance().m_EXIDevice[2], //FIXME
- Core::GetStartupParameter().bRunCompareServer?"True":"False",
- Core::GetStartupParameter().bRunCompareClient?"True":"False",
- Core::GetStartupParameter().iTLBHack?"True":"False",
- SConfig::GetInstance().m_Framelimit*5,
- Core::GetStartupParameter().bWidescreen?"True":"False",
- Core::GetStartupParameter().bProgressiveScan?"True":"False"
- );
-}
-
-std::string Summarize_CPU()
-{
- return StringFromFormat(
- "Processor Information: \n%s\n",
- cpu_info.Summarize().c_str()
- );
-}
-
-std::string Summarize_Drives()
-{
- char ** drives = cdio_get_devices();
- std::string drive;
- for (int i = 0; drives[i] != NULL && i < 24; i++)
- {
-
- drive += StringFromFormat(
- "CD/DVD Drive%d: %s\n",
- i+1,
- drives[i]
- );
- }
- return drive;
-}
-
+// Copyright (C) 2003-2008 Dolphin Project.
+
+// 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/
+
+#ifndef __SUMMARIZE_H__
+#define __SUMMARIZE_H__
+
+std::string Summarize_Plug()
+{
+ return StringFromFormat(
+ "Plugin Information\n\n"
+ "Default GFX Plugin: %s\n"
+ "Default DSP Plugin: %s\n"
+ "Default PAD Plugin: %s\n"
+ "Default WiiMote Plugin: %s\n\n"
+ "Current GFX Plugin: %s\n"
+ "Current DSP Plugin: %s\n"
+ "Current PAD Plugin[0]: %s\n"
+ "Current PAD Plugin[1]: %s\n"
+ "Current PAD Plugin[2]: %s\n"
+ "Current PAD Plugin[3]: %s\n"
+ "Current WiiMote Plugin[0]: %s\n",
+ SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
+ SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
+ SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
+ SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
+ Core::GetStartupParameter().m_strVideoPlugin.c_str(),
+ Core::GetStartupParameter().m_strDSPPlugin.c_str(),
+ Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
+ Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
+ Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
+ Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
+ Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
+ );
+}
+
+std::string Summarize_Settings()
+{
+ return StringFromFormat(
+ "Dolphin Settings\n\n"
+ "Always HLE Bios: %s\n"
+ "Use Dynarec: %s\n"
+ "Use Dual Core: %s\n"
+ "DSP Thread: %s\n"
+ "Skip Idle: %s\n"
+ "Lock Threads: %s\n"
+ "Use Dual Core: %s\n"
+ "Default GCM: %s\n"
+ "DVD Root: %s\n"
+ "Optimize Quantizers: %s\n"
+ "Enable Cheats: %s\n"
+ "Selected Language: %d\n"
+ "Memcard A: %s\n"
+ "Memcard B: %s\n"
+ "Slot A: %d\n"
+ "Slot B: %d\n"
+ "Serial Port 1: %d\n"
+ "Run Compare Server: %s\n"
+ "Run Compare Client: %s\n"
+ "TLB Hack: %s\n"
+ "Frame Limit: %d\n"
+ "[Wii]Widescreen: %s\n"
+ "[Wii]Progressive Scan: %s\n",
+ Core::GetStartupParameter().bHLEBios?"True":"False",
+ Core::GetStartupParameter().bUseJIT?"True":"False",
+ Core::GetStartupParameter().bUseDualCore?"True":"False",
+ Core::GetStartupParameter().bDSPThread?"True":"False",
+ Core::GetStartupParameter().bSkipIdle?"True":"False",
+ Core::GetStartupParameter().bLockThreads?"True":"False",
+ Core::GetStartupParameter().bUseDualCore?"True":"False",
+ Core::GetStartupParameter().m_strDefaultGCM.c_str(),
+ Core::GetStartupParameter().m_strDVDRoot.c_str(),
+ Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
+ Core::GetStartupParameter().bEnableCheats?"True":"False",
+ Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
+ SConfig::GetInstance().m_strMemoryCardA.c_str(),
+ SConfig::GetInstance().m_strMemoryCardB.c_str(),
+ SConfig::GetInstance().m_EXIDevice[0], //FIXME
+ SConfig::GetInstance().m_EXIDevice[1], //FIXME
+ SConfig::GetInstance().m_EXIDevice[2], //FIXME
+ Core::GetStartupParameter().bRunCompareServer?"True":"False",
+ Core::GetStartupParameter().bRunCompareClient?"True":"False",
+ Core::GetStartupParameter().iTLBHack?"True":"False",
+ SConfig::GetInstance().m_Framelimit*5,
+ Core::GetStartupParameter().bWidescreen?"True":"False",
+ Core::GetStartupParameter().bProgressiveScan?"True":"False"
+ );
+}
+
+std::string Summarize_CPU()
+{
+ return StringFromFormat(
+ "Processor Information: \n%s\n",
+ cpu_info.Summarize().c_str()
+ );
+}
+
+std::string Summarize_Drives()
+{
+ char ** drives = cdio_get_devices();
+ std::string drive;
+ for (int i = 0; drives[i] != NULL && i < 24; i++)
+ {
+
+ drive += StringFromFormat(
+ "CD/DVD Drive%d: %s\n",
+ i+1,
+ drives[i]
+ );
+ }
+ return drive;
+}
+
#endif //__SUMMARIZE_H__ \ No newline at end of file
diff --git a/Source/Core/DolphinWX/resources/Dolphin.xpm b/Source/Core/DolphinWX/resources/Dolphin.xpm
index 229eeb0a6a..8d3df77781 100644
--- a/Source/Core/DolphinWX/resources/Dolphin.xpm
+++ b/Source/Core/DolphinWX/resources/Dolphin.xpm
@@ -1,129 +1,129 @@
-/* XPM */
-static const char *Dolphin_xpm[] = {
-"32 32 94 2",
-" c None",
-". c #000000",
-"+ c #1A496C",
-"@ c #091A27",
-"# c #3AA4F0",
-"$ c #3AA3EF",
-"% c #3CA1EA",
-"& c #1A4A6D",
-"* c #3AA2ED",
-"= c #F7FAFA",
-"- c #FFFFFF",
-"; c #FDFDFD",
-"> c #49A1E0",
-", c #3BA2EC",
-"' c #FBFDFC",
-") c #FEFFFD",
-"! c #4EA3E0",
-"~ c #3DA1E9",
-"{ c #D1E1EB",
-"] c #8ABBDE",
-"^ c #F2F6F7",
-"/ c #FAFBFC",
-"( c #CEDEEA",
-"_ c #E5EEF2",
-": c #BBD2E1",
-"< c #B3CFE5",
-"[ c #FFFFFE",
-"} c #FEFFFE",
-"| c #E8F0F3",
-"1 c #E4ECF1",
-"2 c #E5EDF0",
-"3 c #E9F0F3",
-"4 c #FEFEFE",
-"5 c #F9FBFB",
-"6 c #B0CCE0",
-"7 c #FEFEFF",
-"8 c #F9FAFB",
-"9 c #43A1E4",
-"0 c #EFF3F6",
-"a c #F0F5F7",
-"b c #97C1DE",
-"c c #FEFEFD",
-"d c #FDFDFC",
-"e c #97BEDB",
-"f c #FBFCFC",
-"g c #EDF3F6",
-"h c #6EADDA",
-"i c #F3F6F8",
-"j c #3BA1EA",
-"k c #6EADDB",
-"l c #F4F8F9",
-"m c #F1F6F7",
-"n c #3FA1E7",
-"o c #9BC1DD",
-"p c #FCFDFC",
-"q c #FBFDFB",
-"r c #B9D1E1",
-"s c #E0EBF2",
-"t c #D3E3EF",
-"u c #FFFEFE",
-"v c #F2F7F7",
-"w c #D5E4F0",
-"x c #F6F9F9",
-"y c #BDD5E5",
-"z c #EBF1F4",
-"A c #DEEAF2",
-"B c #AAC9DE",
-"C c #FEFFFF",
-"D c #EFF4F6",
-"E c #F8FAFB",
-"F c #A0C4E1",
-"G c #D6E5F0",
-"H c #FAFCFC",
-"I c #BDD5E7",
-"J c #EEF3F7",
-"K c #F3F7FA",
-"L c #C7D8E4",
-"M c #CDDEEC",
-"N c #DAE6ED",
-"O c #9AC2DF",
-"P c #E8EFF4",
-"Q c #ACCDE3",
-"R c #8DBBDC",
-"S c #D5E3EB",
-"T c #FDFFFE",
-"U c #FCFDFD",
-"V c #FEFDFD",
-"W c #F7F9FA",
-"X c #FDFEFD",
-"Y c #E7EFF4",
-"Z c #A4C7E0",
-"` c #F9FDFB",
-" . c #F6FBFC",
-".. c #B8D1E3",
-" . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
-". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
-". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
-"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
-". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
-". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
-". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
-". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
-". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
-". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
-". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
-". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
-". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
-". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
-". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
-". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
-". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
-". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
-". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
-". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
-". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
-". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
-". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
-". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
-". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
-". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
-". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
-". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
-" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
-" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
-" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
-" . . . . . . . . . . . . . . . . . . . . . . . . "};
+/* XPM */
+static const char *Dolphin_xpm[] = {
+"32 32 94 2",
+" c None",
+". c #000000",
+"+ c #1A496C",
+"@ c #091A27",
+"# c #3AA4F0",
+"$ c #3AA3EF",
+"% c #3CA1EA",
+"& c #1A4A6D",
+"* c #3AA2ED",
+"= c #F7FAFA",
+"- c #FFFFFF",
+"; c #FDFDFD",
+"> c #49A1E0",
+", c #3BA2EC",
+"' c #FBFDFC",
+") c #FEFFFD",
+"! c #4EA3E0",
+"~ c #3DA1E9",
+"{ c #D1E1EB",
+"] c #8ABBDE",
+"^ c #F2F6F7",
+"/ c #FAFBFC",
+"( c #CEDEEA",
+"_ c #E5EEF2",
+": c #BBD2E1",
+"< c #B3CFE5",
+"[ c #FFFFFE",
+"} c #FEFFFE",
+"| c #E8F0F3",
+"1 c #E4ECF1",
+"2 c #E5EDF0",
+"3 c #E9F0F3",
+"4 c #FEFEFE",
+"5 c #F9FBFB",
+"6 c #B0CCE0",
+"7 c #FEFEFF",
+"8 c #F9FAFB",
+"9 c #43A1E4",
+"0 c #EFF3F6",
+"a c #F0F5F7",
+"b c #97C1DE",
+"c c #FEFEFD",
+"d c #FDFDFC",
+"e c #97BEDB",
+"f c #FBFCFC",
+"g c #EDF3F6",
+"h c #6EADDA",
+"i c #F3F6F8",
+"j c #3BA1EA",
+"k c #6EADDB",
+"l c #F4F8F9",
+"m c #F1F6F7",
+"n c #3FA1E7",
+"o c #9BC1DD",
+"p c #FCFDFC",
+"q c #FBFDFB",
+"r c #B9D1E1",
+"s c #E0EBF2",
+"t c #D3E3EF",
+"u c #FFFEFE",
+"v c #F2F7F7",
+"w c #D5E4F0",
+"x c #F6F9F9",
+"y c #BDD5E5",
+"z c #EBF1F4",
+"A c #DEEAF2",
+"B c #AAC9DE",
+"C c #FEFFFF",
+"D c #EFF4F6",
+"E c #F8FAFB",
+"F c #A0C4E1",
+"G c #D6E5F0",
+"H c #FAFCFC",
+"I c #BDD5E7",
+"J c #EEF3F7",
+"K c #F3F7FA",
+"L c #C7D8E4",
+"M c #CDDEEC",
+"N c #DAE6ED",
+"O c #9AC2DF",
+"P c #E8EFF4",
+"Q c #ACCDE3",
+"R c #8DBBDC",
+"S c #D5E3EB",
+"T c #FDFFFE",
+"U c #FCFDFD",
+"V c #FEFDFD",
+"W c #F7F9FA",
+"X c #FDFEFD",
+"Y c #E7EFF4",
+"Z c #A4C7E0",
+"` c #F9FDFB",
+" . c #F6FBFC",
+".. c #B8D1E3",
+" . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
+". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
+". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
+"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
+". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
+". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
+". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
+". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
+". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
+". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
+". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
+". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
+". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
+". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
+". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
+". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
+". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
+". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
+". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
+". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
+". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
+". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
+". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
+". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
+". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
+". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
+". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
+". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
+" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
+" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
+" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . "};
diff --git a/Source/Core/DolphinWX/resources/Flag_Europe.xpm b/Source/Core/DolphinWX/resources/Flag_Europe.xpm
index 49ff790a9f..def46811a6 100644
--- a/Source/Core/DolphinWX/resources/Flag_Europe.xpm
+++ b/Source/Core/DolphinWX/resources/Flag_Europe.xpm
@@ -1,83 +1,83 @@
-/* XPM */
-static const char *const Flag_Europe_xpm[] = {
-"96 32 48 1",
-" c None",
-". c #000000",
-"+ c #0000FD",
-"@ c #0000FF",
-"# c #0808F7",
-"$ c #5C5CA3",
-"% c #1717E8",
-"& c #767680",
-"* c #EDED00",
-"= c #A5A54D",
-"- c #2E2EB9",
-"; c #96961A",
-"> c #4A4A8E",
-", c #0000FB",
-"' c #0000F4",
-") c #0808EC",
-"! c #5C5C9B",
-"~ c #1717DD",
-"{ c #0000EE",
-"] c #767677",
-"^ c #A5A547",
-"/ c #0000DD",
-"( c #2E2EA0",
-"_ c #969616",
-": c #4A4A7B",
-"< c #0000D2",
-"[ c #0000C6",
-"} c #0808BF",
-"| c #5C5C7E",
-"1 c #1717B4",
-"2 c #0000B9",
-"3 c #76765C",
-"4 c #A5A537",
-"5 c #0808B3",
-"6 c #5C5C76",
-"7 c #1717A8",
-"8 c #0000A9",
-"9 c #2E2E7A",
-"0 c #969611",
-"a c #4A4A5E",
-"b c #767654",
-"c c #A5A533",
-"d c #000097",
-"e c #2E2E6D",
-"f c #96960F",
-"g c #4A4A54",
-"h c #000081",
-"i c #000077",
-" ",
-" ",
-" ",
-" ",
-" ",
-"................................ ",
-".++++++++++++++++++++++++++++++. ",
-".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
-".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
-".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
-".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
-".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
-".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
-".''''''')!~''''''''')!~''''''''. ",
-".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
-".///////(_://///////(_:////////. ",
-".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
-".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
-".2222222223*4256723*42222222222. ",
-".88888888890a8b*c890a8888888888. ",
-".dddddddddddddefgdddddddddddddd. ",
-".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
-".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
-".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
-"................................ ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" "};
+/* XPM */
+static const char *const Flag_Europe_xpm[] = {
+"96 32 48 1",
+" c None",
+". c #000000",
+"+ c #0000FD",
+"@ c #0000FF",
+"# c #0808F7",
+"$ c #5C5CA3",
+"% c #1717E8",
+"& c #767680",
+"* c #EDED00",
+"= c #A5A54D",
+"- c #2E2EB9",
+"; c #96961A",
+"> c #4A4A8E",
+", c #0000FB",
+"' c #0000F4",
+") c #0808EC",
+"! c #5C5C9B",
+"~ c #1717DD",
+"{ c #0000EE",
+"] c #767677",
+"^ c #A5A547",
+"/ c #0000DD",
+"( c #2E2EA0",
+"_ c #969616",
+": c #4A4A7B",
+"< c #0000D2",
+"[ c #0000C6",
+"} c #0808BF",
+"| c #5C5C7E",
+"1 c #1717B4",
+"2 c #0000B9",
+"3 c #76765C",
+"4 c #A5A537",
+"5 c #0808B3",
+"6 c #5C5C76",
+"7 c #1717A8",
+"8 c #0000A9",
+"9 c #2E2E7A",
+"0 c #969611",
+"a c #4A4A5E",
+"b c #767654",
+"c c #A5A533",
+"d c #000097",
+"e c #2E2E6D",
+"f c #96960F",
+"g c #4A4A54",
+"h c #000081",
+"i c #000077",
+" ",
+" ",
+" ",
+" ",
+" ",
+"................................ ",
+".++++++++++++++++++++++++++++++. ",
+".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
+".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
+".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
+".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
+".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
+".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
+".''''''')!~''''''''')!~''''''''. ",
+".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
+".///////(_://///////(_:////////. ",
+".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
+".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
+".2222222223*4256723*42222222222. ",
+".88888888890a8b*c890a8888888888. ",
+".dddddddddddddefgdddddddddddddd. ",
+".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
+".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
+".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
+"................................ ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/Source/Core/DolphinWX/resources/Flag_France.xpm b/Source/Core/DolphinWX/resources/Flag_France.xpm
index 157277efec..51cde44d8c 100644
--- a/Source/Core/DolphinWX/resources/Flag_France.xpm
+++ b/Source/Core/DolphinWX/resources/Flag_France.xpm
@@ -1,80 +1,80 @@
-/* XPM */
-static const char *const Flag_France_xpm[] = {
-"96 32 45 1",
-" c None",
-". c #000000",
-"+ c #0000FF",
-"@ c #FFFFFF",
-"# c #FF0000",
-"$ c #0000FC",
-"% c #0000F8",
-"& c #FCFCFC",
-"* c #FC0000",
-"= c #0000F2",
-"- c #F8F8F8",
-"; c #F80000",
-"> c #0000EC",
-", c #F2F2F2",
-"' c #F20000",
-") c #0000E3",
-"! c #ECECEC",
-"~ c #EC0000",
-"{ c #0000DB",
-"] c #E3E3E3",
-"^ c #E30000",
-"/ c #0000D2",
-"( c #DBDBDB",
-"_ c #DB0000",
-": c #0000C8",
-"< c #D2D2D2",
-"[ c #D20000",
-"} c #0000BD",
-"| c #C8C8C8",
-"1 c #C80000",
-"2 c #0000B1",
-"3 c #BDBDBD",
-"4 c #BD0000",
-"5 c #0000A3",
-"6 c #B1B1B1",
-"7 c #B10000",
-"8 c #000093",
-"9 c #A3A3A3",
-"0 c #A30000",
-"a c #000080",
-"b c #939393",
-"c c #930000",
-"d c #000077",
-"e c #808080",
-"f c #800000",
-" ",
-" ",
-" ",
-" ",
-" ",
-"................................ ",
-".++++++++++@@@@@@@@@@@#########. ",
-".++++++++++@@@@@@@@@@@#########. ",
-".++++++++++@@@@@@@@@@@#########. ",
-".++++++++++@@@@@@@@@@@#########. ",
-".$$$$$$$$$$@@@@@@@@@@@#########. ",
-".%%%%%%%%%%&&&&&&&&&&&*********. ",
-".==========-----------;;;;;;;;;. ",
-".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
-".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
-".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
-".//////////(((((((((((_________. ",
-".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
-".}}}}}}}}}}|||||||||||111111111. ",
-".222222222233333333333444444444. ",
-".555555555566666666666777777777. ",
-".888888888899999999999000000000. ",
-".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
-".ddddddddddeeeeeeeeeeefffffffff. ",
-"................................ ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" "};
+/* XPM */
+static const char *const Flag_France_xpm[] = {
+"96 32 45 1",
+" c None",
+". c #000000",
+"+ c #0000FF",
+"@ c #FFFFFF",
+"# c #FF0000",
+"$ c #0000FC",
+"% c #0000F8",
+"& c #FCFCFC",
+"* c #FC0000",
+"= c #0000F2",
+"- c #F8F8F8",
+"; c #F80000",
+"> c #0000EC",
+", c #F2F2F2",
+"' c #F20000",
+") c #0000E3",
+"! c #ECECEC",
+"~ c #EC0000",
+"{ c #0000DB",
+"] c #E3E3E3",
+"^ c #E30000",
+"/ c #0000D2",
+"( c #DBDBDB",
+"_ c #DB0000",
+": c #0000C8",
+"< c #D2D2D2",
+"[ c #D20000",
+"} c #0000BD",
+"| c #C8C8C8",
+"1 c #C80000",
+"2 c #0000B1",
+"3 c #BDBDBD",
+"4 c #BD0000",
+"5 c #0000A3",
+"6 c #B1B1B1",
+"7 c #B10000",
+"8 c #000093",
+"9 c #A3A3A3",
+"0 c #A30000",
+"a c #000080",
+"b c #939393",
+"c c #930000",
+"d c #000077",
+"e c #808080",
+"f c #800000",
+" ",
+" ",
+" ",
+" ",
+" ",
+"................................ ",
+".++++++++++@@@@@@@@@@@#########. ",
+".++++++++++@@@@@@@@@@@#########. ",
+".++++++++++@@@@@@@@@@@#########. ",
+".++++++++++@@@@@@@@@@@#########. ",
+".$$$$$$$$$$@@@@@@@@@@@#########. ",
+".%%%%%%%%%%&&&&&&&&&&&*********. ",
+".==========-----------;;;;;;;;;. ",
+".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
+".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
+".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
+".//////////(((((((((((_________. ",
+".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
+".}}}}}}}}}}|||||||||||111111111. ",
+".222222222233333333333444444444. ",
+".555555555566666666666777777777. ",
+".888888888899999999999000000000. ",
+".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
+".ddddddddddeeeeeeeeeeefffffffff. ",
+"................................ ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/Source/Core/DolphinWX/resources/Flag_Japan.xpm b/Source/Core/DolphinWX/resources/Flag_Japan.xpm
index 794bbc0b78..47be025c6b 100644
--- a/Source/Core/DolphinWX/resources/Flag_Japan.xpm
+++ b/Source/Core/DolphinWX/resources/Flag_Japan.xpm
@@ -1,102 +1,102 @@
-/* XPM */
-static const char * const Flag_Japan_xpm[] = {
-"96 32 67 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-"@ c #FECACA",
-"# c #FD8080",
-"$ c #FD6161",
-"% c #FD7676",
-"& c #FEB6B6",
-"* c #FEFEFE",
-"= c #FFEDED",
-"- c #FF4C4C",
-"; c #FF0000",
-"> c #FF2F2F",
-", c #FFD7D7",
-"' c #FEF5F5",
-") c #FE2E2E",
-"! c #FE1313",
-"~ c #FEDDDD",
-"{ c #F9F9F9",
-"] c #FC7777",
-"^ c #FD4545",
-"/ c #F4F4F4",
-"( c #F4F3F3",
-"_ c #FA1313",
-": c #FB0000",
-"< c #FA0000",
-"[ c #F4D4D4",
-"} c #EFEFEF",
-"| c #EFCFCF",
-"1 c #F10000",
-"2 c #EF9F9F",
-"3 c #E4E4E4",
-"4 c #E2BEBE",
-"5 c #DD0000",
-"6 c #E19090",
-"7 c #D9D9D9",
-"8 c #D8D0D0",
-"9 c #CA0404",
-"0 c #CA0000",
-"a c #D5A9A9",
-"b c #D0D0D0",
-"c c #BC4242",
-"d c #B40000",
-"e c #B71A1A",
-"f c #CFCFCF",
-"g c #C6C6C6",
-"h c #BEA7A7",
-"i c #990808",
-"j c #980000",
-"k c #B78787",
-"l c #BBBBBB",
-"m c #A88989",
-"n c #7B0B0B",
-"o c #770000",
-"p c #780202",
-"q c #9E6B6B",
-"r c #AEAEAE",
-"s c #A89C9C",
-"t c #8F4E4E",
-"u c #7F1B1B",
-"v c #7A0A0A",
-"w c #7D1515",
-"x c #8B4242",
-"y c #A48F8F",
-"z c #A0A0A0",
-"A c #8F8F8F",
-"B c #7C7C7C",
-" ",
-" ",
-" ",
-" ",
-" ",
-"................................ ",
-".++++++++++++++++++++++++++++++. ",
-".++++++++++++++++++++++++++++++. ",
-".++++++++++++++++++++++++++++++. ",
-".++++++++++++@#$%&*++++++++++++. ",
-".++++++++++=-;;;;;>,+++++++++++. ",
-".*********');;;;;;;!~**********. ",
-".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
-".////////(_:::::::::<[/////////. ",
-".}}}}}}}}|111111111112}}}}}}}}}. ",
-".333333334555555555556333333333. ",
-".77777777890000000000a777777777. ",
-".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
-".ggggggggghijjjjjjjjkgggggggggg. ",
-".llllllllllmnooooopqlllllllllll. ",
-".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
-".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
-".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
-".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
-"................................ ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" "};
+/* XPM */
+static const char * const Flag_Japan_xpm[] = {
+"96 32 67 1",
+" c None",
+". c #000000",
+"+ c #FFFFFF",
+"@ c #FECACA",
+"# c #FD8080",
+"$ c #FD6161",
+"% c #FD7676",
+"& c #FEB6B6",
+"* c #FEFEFE",
+"= c #FFEDED",
+"- c #FF4C4C",
+"; c #FF0000",
+"> c #FF2F2F",
+", c #FFD7D7",
+"' c #FEF5F5",
+") c #FE2E2E",
+"! c #FE1313",
+"~ c #FEDDDD",
+"{ c #F9F9F9",
+"] c #FC7777",
+"^ c #FD4545",
+"/ c #F4F4F4",
+"( c #F4F3F3",
+"_ c #FA1313",
+": c #FB0000",
+"< c #FA0000",
+"[ c #F4D4D4",
+"} c #EFEFEF",
+"| c #EFCFCF",
+"1 c #F10000",
+"2 c #EF9F9F",
+"3 c #E4E4E4",
+"4 c #E2BEBE",
+"5 c #DD0000",
+"6 c #E19090",
+"7 c #D9D9D9",
+"8 c #D8D0D0",
+"9 c #CA0404",
+"0 c #CA0000",
+"a c #D5A9A9",
+"b c #D0D0D0",
+"c c #BC4242",
+"d c #B40000",
+"e c #B71A1A",
+"f c #CFCFCF",
+"g c #C6C6C6",
+"h c #BEA7A7",
+"i c #990808",
+"j c #980000",
+"k c #B78787",
+"l c #BBBBBB",
+"m c #A88989",
+"n c #7B0B0B",
+"o c #770000",
+"p c #780202",
+"q c #9E6B6B",
+"r c #AEAEAE",
+"s c #A89C9C",
+"t c #8F4E4E",
+"u c #7F1B1B",
+"v c #7A0A0A",
+"w c #7D1515",
+"x c #8B4242",
+"y c #A48F8F",
+"z c #A0A0A0",
+"A c #8F8F8F",
+"B c #7C7C7C",
+" ",
+" ",
+" ",
+" ",
+" ",
+"................................ ",
+".++++++++++++++++++++++++++++++. ",
+".++++++++++++++++++++++++++++++. ",
+".++++++++++++++++++++++++++++++. ",
+".++++++++++++@#$%&*++++++++++++. ",
+".++++++++++=-;;;;;>,+++++++++++. ",
+".*********');;;;;;;!~**********. ",
+".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
+".////////(_:::::::::<[/////////. ",
+".}}}}}}}}|111111111112}}}}}}}}}. ",
+".333333334555555555556333333333. ",
+".77777777890000000000a777777777. ",
+".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
+".ggggggggghijjjjjjjjkgggggggggg. ",
+".llllllllllmnooooopqlllllllllll. ",
+".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
+".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
+".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
+".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
+"................................ ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/Source/Core/DolphinWX/resources/Flag_Taiwan.xpm b/Source/Core/DolphinWX/resources/Flag_Taiwan.xpm
index 6696789270..2dbb119f81 100644
--- a/Source/Core/DolphinWX/resources/Flag_Taiwan.xpm
+++ b/Source/Core/DolphinWX/resources/Flag_Taiwan.xpm
@@ -1,124 +1,124 @@
-/* XPM */
-static const char * Flag_Taiwan_xpm[] = {
-"96 32 89 1",
-" c None",
-". c #000000",
-"# c #000099",
-"$ c #000098",
-"% c #03039A",
-"& c #000094",
-"' c #05059B",
-"( c #050095",
-") c #DC0014",
-"* c #FF0000",
-"+ c #FD0001",
-", c #04049B",
-"- c #000096",
-"! c #020299",
-"0 c #2424A7",
-"1 c #04049A",
-"2 c #000097",
-"3 c #000093",
-"4 c #6262BF",
-"5 c #2828A8",
-"6 c #6C6CC1",
-"7 c #3E3EB1",
-"8 c #3B3BB0",
-"9 c #00008F",
-": c #01019A",
-"; c #1919A3",
-"< c #4040B0",
-"= c #6363C0",
-"> c #D6D6EE",
-"? c #D9D9ED",
-"@ c #C5C5E7",
-"A c #3F3FB0",
-"B c #3D3DAF",
-"C c #020297",
-"D c #010199",
-"E c #5E5EBE",
-"F c #DFDFF2",
-"G c white",
-"H c #BFBFE5",
-"I c #2626A7",
-"J c #4242B0",
-"K c #7D7DCA",
-"L c #FAFAFD",
-"M c #FBFBFD",
-"N c #FCFCFD",
-"O c #FCFCFE",
-"P c #DADAF0",
-"Q c #6A6AC2",
-"R c #1B1BA3",
-"S c #000199",
-"T c #0E0E9B",
-"U c #5858BC",
-"V c #D3D3ED",
-"W c #2727A6",
-"X c #060699",
-"Y c #1212A0",
-"Z c #6464C0",
-"[ c #8080CC",
-"] c #F4F4FA",
-"^ c #F8F8FB",
-"_ c #7070C4",
-"` c #4949B5",
-"a c #000095",
-"b c #040499",
-"c c #000092",
-"d c #6767C2",
-"e c #8686CA",
-"f c #7070C5",
-"g c #2B2BA9",
-"h c #00009A",
-"i c #01049C",
-"j c #1619A4",
-"k c #393CB3",
-"l c #00029A",
-"m c #1619A5",
-"n c #020096",
-"o c #DB0014",
-"p c #FC0001",
-"q c #0A0092",
-"r c #060090",
-"s c #0B0092",
-"t c #0F008E",
-"u c #DD0013",
-"v c #FD0000",
-"w c #E5000F",
-"x c #E6010F",
-"y c #E60110",
-"z c #FB0002",
-"{ c #FE0000",
-" ",
-" ",
-" ",
-" ",
-" ",
-"................................ ",
-".#####$%#&'$$$##()*+***********. ",
-".###$$,-!0&1!$##()*+***********. ",
-".##$#23456789:$#()*+***********. ",
-".###2;<=>?@ABCD#()*+***********. ",
-".###$CEFGGGHI&D$()*+***********. ",
-".##D-JKLMNOPQR-S()*+***********. ",
-".###$TUGGNGVWX$#()*+***********. ",
-".###2YZ[]^P_`aD$()*+***********. ",
-".###$bcdEefg3D$#()*+***********. ",
-".hhhhhijiklm#hhhno*p***********. ",
-".qqqqqqrsrqrqqqqtu*v***********. ",
-".wwwwwwxwywxwwwwwz*{***********. ",
-".******************************. ",
-".{{{{{{{{{{{{{{{{{*{***********. ",
-".******************************. ",
-".******************************. ",
-".******************************. ",
-".******************************. ",
-"................................ ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
+/* XPM */
+static const char * Flag_Taiwan_xpm[] = {
+"96 32 89 1",
+" c None",
+". c #000000",
+"# c #000099",
+"$ c #000098",
+"% c #03039A",
+"& c #000094",
+"' c #05059B",
+"( c #050095",
+") c #DC0014",
+"* c #FF0000",
+"+ c #FD0001",
+", c #04049B",
+"- c #000096",
+"! c #020299",
+"0 c #2424A7",
+"1 c #04049A",
+"2 c #000097",
+"3 c #000093",
+"4 c #6262BF",
+"5 c #2828A8",
+"6 c #6C6CC1",
+"7 c #3E3EB1",
+"8 c #3B3BB0",
+"9 c #00008F",
+": c #01019A",
+"; c #1919A3",
+"< c #4040B0",
+"= c #6363C0",
+"> c #D6D6EE",
+"? c #D9D9ED",
+"@ c #C5C5E7",
+"A c #3F3FB0",
+"B c #3D3DAF",
+"C c #020297",
+"D c #010199",
+"E c #5E5EBE",
+"F c #DFDFF2",
+"G c white",
+"H c #BFBFE5",
+"I c #2626A7",
+"J c #4242B0",
+"K c #7D7DCA",
+"L c #FAFAFD",
+"M c #FBFBFD",
+"N c #FCFCFD",
+"O c #FCFCFE",
+"P c #DADAF0",
+"Q c #6A6AC2",
+"R c #1B1BA3",
+"S c #000199",
+"T c #0E0E9B",
+"U c #5858BC",
+"V c #D3D3ED",
+"W c #2727A6",
+"X c #060699",
+"Y c #1212A0",
+"Z c #6464C0",
+"[ c #8080CC",
+"] c #F4F4FA",
+"^ c #F8F8FB",
+"_ c #7070C4",
+"` c #4949B5",
+"a c #000095",
+"b c #040499",
+"c c #000092",
+"d c #6767C2",
+"e c #8686CA",
+"f c #7070C5",
+"g c #2B2BA9",
+"h c #00009A",
+"i c #01049C",
+"j c #1619A4",
+"k c #393CB3",
+"l c #00029A",
+"m c #1619A5",
+"n c #020096",
+"o c #DB0014",
+"p c #FC0001",
+"q c #0A0092",
+"r c #060090",
+"s c #0B0092",
+"t c #0F008E",
+"u c #DD0013",
+"v c #FD0000",
+"w c #E5000F",
+"x c #E6010F",
+"y c #E60110",
+"z c #FB0002",
+"{ c #FE0000",
+" ",
+" ",
+" ",
+" ",
+" ",
+"................................ ",
+".#####$%#&'$$$##()*+***********. ",
+".###$$,-!0&1!$##()*+***********. ",
+".##$#23456789:$#()*+***********. ",
+".###2;<=>?@ABCD#()*+***********. ",
+".###$CEFGGGHI&D$()*+***********. ",
+".##D-JKLMNOPQR-S()*+***********. ",
+".###$TUGGNGVWX$#()*+***********. ",
+".###2YZ[]^P_`aD$()*+***********. ",
+".###$bcdEefg3D$#()*+***********. ",
+".hhhhhijiklm#hhhno*p***********. ",
+".qqqqqqrsrqrqqqqtu*v***********. ",
+".wwwwwwxwywxwwwwwz*{***********. ",
+".******************************. ",
+".{{{{{{{{{{{{{{{{{*{***********. ",
+".******************************. ",
+".******************************. ",
+".******************************. ",
+".******************************. ",
+"................................ ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
" "}; \ No newline at end of file
diff --git a/Source/Core/DolphinWX/resources/Flag_USA.xpm b/Source/Core/DolphinWX/resources/Flag_USA.xpm
index 90ccbedd8d..0a991bd02e 100644
--- a/Source/Core/DolphinWX/resources/Flag_USA.xpm
+++ b/Source/Core/DolphinWX/resources/Flag_USA.xpm
@@ -1,65 +1,65 @@
-/* XPM */
-static const char * Flag_USA_xpm[] = {
-"96 32 30 1",
-" c None",
-". c #000000",
-"+ c #0000FF",
-"@ c #CE7070",
-"# c #B0BF99",
-"$ c #F1F1F1",
-"% c #FFFFFF",
-"& c #0000FD",
-"* c #CF8484",
-"= c #DA9090",
-"- c #0000F3",
-"; c #B0BF96",
-"> c #0000DF",
-", c #0000CB",
-"' c #B0BF8C",
-") c #D98E8E",
-"! c #0000B5",
-"~ c #CA6C6C",
-"{ c #000098",
-"] c #B0BF80",
-"^ c #000077",
-"/ c #C26464",
-"( c #DBDBDB",
-"_ c #C17676",
-": c #B55757",
-"< c #BBBBBB",
-"[ c #AC6161",
-"} c #A34545",
-"| c #8B8B8B",
-"1 c #8E4343",
-" ",
-" ",
-" ",
-" ",
-" ",
-"................................ ",
-".++++++++++++++@@@@@@@@@@@@@@@@. ",
-".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
-".&&&&&&&&&&&&&&*===============. ",
-".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
-".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
-".,',',',',',',,*))))))))))))))). ",
-".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
-".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
-".^^^^^^^^^^^^^^****************. ",
-".^^^^^^^^^^^^^^@///////////////. ",
-".((((((((((((((((((((((((((((((. ",
-".______________________________. ",
-".::::::::::::::::::::::::::::::. ",
-".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
-".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
-".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
-".||||||||||||||||||||||||||||||. ",
-".111111111111111111111111111111. ",
-"................................ ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" ",
-" "};
+/* XPM */
+static const char * Flag_USA_xpm[] = {
+"96 32 30 1",
+" c None",
+". c #000000",
+"+ c #0000FF",
+"@ c #CE7070",
+"# c #B0BF99",
+"$ c #F1F1F1",
+"% c #FFFFFF",
+"& c #0000FD",
+"* c #CF8484",
+"= c #DA9090",
+"- c #0000F3",
+"; c #B0BF96",
+"> c #0000DF",
+", c #0000CB",
+"' c #B0BF8C",
+") c #D98E8E",
+"! c #0000B5",
+"~ c #CA6C6C",
+"{ c #000098",
+"] c #B0BF80",
+"^ c #000077",
+"/ c #C26464",
+"( c #DBDBDB",
+"_ c #C17676",
+": c #B55757",
+"< c #BBBBBB",
+"[ c #AC6161",
+"} c #A34545",
+"| c #8B8B8B",
+"1 c #8E4343",
+" ",
+" ",
+" ",
+" ",
+" ",
+"................................ ",
+".++++++++++++++@@@@@@@@@@@@@@@@. ",
+".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
+".&&&&&&&&&&&&&&*===============. ",
+".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
+".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
+".,',',',',',',,*))))))))))))))). ",
+".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
+".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
+".^^^^^^^^^^^^^^****************. ",
+".^^^^^^^^^^^^^^@///////////////. ",
+".((((((((((((((((((((((((((((((. ",
+".______________________________. ",
+".::::::::::::::::::::::::::::::. ",
+".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
+".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
+".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
+".||||||||||||||||||||||||||||||. ",
+".111111111111111111111111111111. ",
+"................................ ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
diff --git a/Source/Core/VideoCommon/Src/AVIDump.cpp b/Source/Core/VideoCommon/Src/AVIDump.cpp
index 3447efbacf..acb4fde624 100644
--- a/Source/Core/VideoCommon/Src/AVIDump.cpp
+++ b/Source/Core/VideoCommon/Src/AVIDump.cpp
@@ -1,179 +1,179 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "AVIDump.h"
-#include "tchar.h"
-
-#include <cstdio>
-#include <cstring>
-#include <vfw.h>
-#include <winerror.h>
-
-#include "FileUtil.h"
-#include "CommonPaths.h"
-#include "Log.h"
-
-static HWND m_emuWnd;
-static int m_width;
-static int m_height;
-static LONG m_byteBuffer;
-static LONG m_frameCount;
-static LONG m_totalBytes;
-static PAVIFILE m_file;
-static int m_fileCount;
-static PAVISTREAM m_stream;
-static PAVISTREAM m_streamCompressed;
-static AVISTREAMINFO m_header;
-static AVICOMPRESSOPTIONS m_options;
-static AVICOMPRESSOPTIONS *m_arrayOptions[1];
-static BITMAPINFOHEADER m_bitmap;
-
-bool AVIDump::Start(HWND hWnd, int w, int h)
-{
- m_emuWnd = hWnd;
- m_fileCount = 0;
-
- m_width = w;
- m_height = h;
-
- return CreateFile();
-}
-
-bool AVIDump::CreateFile()
-{
- m_totalBytes = 0;
- m_frameCount = 0;
- char movie_file_name[255];
- sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
- // Create path
- File::CreateFullPath(movie_file_name);
-
- // Ask to delete file
- if (File::Exists(movie_file_name))
- {
- if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
- File::Delete(movie_file_name);
- }
-
- AVIFileInit();
- NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
- // TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
- HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
- if (FAILED(hr)) {
- if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format.");
- if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory.");
- if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file.");
- if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file.");
- if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
- Stop();
- return false;
- }
- SetBitmapFormat();
- NOTICE_LOG(VIDEO, "Setting video format...");
- if (!SetVideoFormat()) {
- NOTICE_LOG(VIDEO, "Setting video format failed");
- Stop();
- return false;
- }
- if (!m_fileCount) {
- if (!SetCompressionOptions()) {
- NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
- Stop();
- return false;
- }
- }
- if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
- NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
- Stop();
- return false;
- }
- if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
- NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
- Stop();
- return false;
- }
-
- return true;
-}
-
-void AVIDump::CloseFile()
-{
- if (m_streamCompressed) {
- AVIStreamClose(m_streamCompressed);
- m_streamCompressed = NULL;
- }
- if (m_stream) {
- AVIStreamClose(m_stream);
- m_stream = NULL;
- }
- if (m_file) {
- AVIFileRelease(m_file);
- m_file = NULL;
- }
- AVIFileExit();
-}
-
-void AVIDump::Stop()
-{
- CloseFile();
- m_fileCount = 0;
- NOTICE_LOG(VIDEO, "Stop");
-}
-
-void AVIDump::AddFrame(char *data)
-{
- AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
- m_totalBytes += m_byteBuffer;
- // Close the recording if the file is more than 2gb
- // VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
- if (m_totalBytes >= 2000000000) {
- CloseFile();
- m_fileCount++;
- CreateFile();
- }
-}
-
-void AVIDump::SetBitmapFormat()
-{
- memset(&m_bitmap, 0, sizeof(m_bitmap));
- m_bitmap.biSize = 0x28;
- m_bitmap.biPlanes = 1;
- m_bitmap.biBitCount = 24;
- m_bitmap.biWidth = m_width;
- m_bitmap.biHeight = m_height;
- m_bitmap.biSizeImage = 3 * m_width * m_height;
-}
-
-bool AVIDump::SetCompressionOptions()
-{
- memset(&m_options, 0, sizeof(m_options));
- m_arrayOptions[0] = &m_options;
-
- return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
-}
-
-bool AVIDump::SetVideoFormat()
-{
- memset(&m_header, 0, sizeof(m_header));
- m_header.fccType = streamtypeVIDEO;
- m_header.dwScale = 1;
- // TODO: Decect FPS using NTSC/PAL
- m_header.dwRate = 60;
- m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
-
- return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
-}
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "AVIDump.h"
+#include "tchar.h"
+
+#include <cstdio>
+#include <cstring>
+#include <vfw.h>
+#include <winerror.h>
+
+#include "FileUtil.h"
+#include "CommonPaths.h"
+#include "Log.h"
+
+static HWND m_emuWnd;
+static int m_width;
+static int m_height;
+static LONG m_byteBuffer;
+static LONG m_frameCount;
+static LONG m_totalBytes;
+static PAVIFILE m_file;
+static int m_fileCount;
+static PAVISTREAM m_stream;
+static PAVISTREAM m_streamCompressed;
+static AVISTREAMINFO m_header;
+static AVICOMPRESSOPTIONS m_options;
+static AVICOMPRESSOPTIONS *m_arrayOptions[1];
+static BITMAPINFOHEADER m_bitmap;
+
+bool AVIDump::Start(HWND hWnd, int w, int h)
+{
+ m_emuWnd = hWnd;
+ m_fileCount = 0;
+
+ m_width = w;
+ m_height = h;
+
+ return CreateFile();
+}
+
+bool AVIDump::CreateFile()
+{
+ m_totalBytes = 0;
+ m_frameCount = 0;
+ char movie_file_name[255];
+ sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
+ // Create path
+ File::CreateFullPath(movie_file_name);
+
+ // Ask to delete file
+ if (File::Exists(movie_file_name))
+ {
+ if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
+ File::Delete(movie_file_name);
+ }
+
+ AVIFileInit();
+ NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
+ // TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
+ HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
+ if (FAILED(hr)) {
+ if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format.");
+ if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory.");
+ if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file.");
+ if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file.");
+ if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
+ Stop();
+ return false;
+ }
+ SetBitmapFormat();
+ NOTICE_LOG(VIDEO, "Setting video format...");
+ if (!SetVideoFormat()) {
+ NOTICE_LOG(VIDEO, "Setting video format failed");
+ Stop();
+ return false;
+ }
+ if (!m_fileCount) {
+ if (!SetCompressionOptions()) {
+ NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
+ Stop();
+ return false;
+ }
+ }
+ if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
+ NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
+ Stop();
+ return false;
+ }
+ if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
+ NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
+ Stop();
+ return false;
+ }
+
+ return true;
+}
+
+void AVIDump::CloseFile()
+{
+ if (m_streamCompressed) {
+ AVIStreamClose(m_streamCompressed);
+ m_streamCompressed = NULL;
+ }
+ if (m_stream) {
+ AVIStreamClose(m_stream);
+ m_stream = NULL;
+ }
+ if (m_file) {
+ AVIFileRelease(m_file);
+ m_file = NULL;
+ }
+ AVIFileExit();
+}
+
+void AVIDump::Stop()
+{
+ CloseFile();
+ m_fileCount = 0;
+ NOTICE_LOG(VIDEO, "Stop");
+}
+
+void AVIDump::AddFrame(char *data)
+{
+ AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
+ m_totalBytes += m_byteBuffer;
+ // Close the recording if the file is more than 2gb
+ // VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
+ if (m_totalBytes >= 2000000000) {
+ CloseFile();
+ m_fileCount++;
+ CreateFile();
+ }
+}
+
+void AVIDump::SetBitmapFormat()
+{
+ memset(&m_bitmap, 0, sizeof(m_bitmap));
+ m_bitmap.biSize = 0x28;
+ m_bitmap.biPlanes = 1;
+ m_bitmap.biBitCount = 24;
+ m_bitmap.biWidth = m_width;
+ m_bitmap.biHeight = m_height;
+ m_bitmap.biSizeImage = 3 * m_width * m_height;
+}
+
+bool AVIDump::SetCompressionOptions()
+{
+ memset(&m_options, 0, sizeof(m_options));
+ m_arrayOptions[0] = &m_options;
+
+ return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
+}
+
+bool AVIDump::SetVideoFormat()
+{
+ memset(&m_header, 0, sizeof(m_header));
+ m_header.fccType = streamtypeVIDEO;
+ m_header.dwScale = 1;
+ // TODO: Decect FPS using NTSC/PAL
+ m_header.dwRate = 60;
+ m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
+
+ return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
+}
diff --git a/Source/Core/VideoCommon/Src/BPFunctions.h b/Source/Core/VideoCommon/Src/BPFunctions.h
index c22e9aa0b6..aa476e0d83 100644
--- a/Source/Core/VideoCommon/Src/BPFunctions.h
+++ b/Source/Core/VideoCommon/Src/BPFunctions.h
@@ -1,60 +1,60 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-
-// ------------------------------------------
-// The plugins has to define these functions
-// ------------------------------------------
-
-#ifndef _BPFUNCTIONS_H_
-#define _BPFUNCTIONS_H_
-
-#include "BPMemory.h"
-#include "VideoCommon.h"
-
-namespace BPFunctions
-{
-
-enum
-{
- CONFIG_ISWII = 0,
- CONFIG_DISABLEFOG,
- CONFIG_SHOWEFBREGIONS
-};
-
-void FlushPipeline();
-void SetGenerationMode(const Bypass &bp);
-void SetScissor(const Bypass &bp);
-void SetLineWidth(const Bypass &bp);
-void SetDepthMode(const Bypass &bp);
-void SetBlendMode(const Bypass &bp);
-void SetDitherMode(const Bypass &bp);
-void SetLogicOpMode(const Bypass &bp);
-void SetColorMask(const Bypass &bp);
-float GetRendererTargetScaleX();
-float GetRendererTargetScaleY();
-void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const bool &scaleByHalf);
-void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight);
-void ClearScreen(const Bypass &bp, const TRectangle &multirc);
-void RestoreRenderState(const Bypass &bp);
-u8 *GetPointer(const u32 &address);
-bool GetConfig(const int &type);
-void SetSamplerState(const Bypass &bp);
-void SetInterlacingMode(const Bypass &bp);
-};
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+
+// ------------------------------------------
+// The plugins has to define these functions
+// ------------------------------------------
+
+#ifndef _BPFUNCTIONS_H_
+#define _BPFUNCTIONS_H_
+
+#include "BPMemory.h"
+#include "VideoCommon.h"
+
+namespace BPFunctions
+{
+
+enum
+{
+ CONFIG_ISWII = 0,
+ CONFIG_DISABLEFOG,
+ CONFIG_SHOWEFBREGIONS
+};
+
+void FlushPipeline();
+void SetGenerationMode(const Bypass &bp);
+void SetScissor(const Bypass &bp);
+void SetLineWidth(const Bypass &bp);
+void SetDepthMode(const Bypass &bp);
+void SetBlendMode(const Bypass &bp);
+void SetDitherMode(const Bypass &bp);
+void SetLogicOpMode(const Bypass &bp);
+void SetColorMask(const Bypass &bp);
+float GetRendererTargetScaleX();
+float GetRendererTargetScaleY();
+void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const bool &scaleByHalf);
+void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight);
+void ClearScreen(const Bypass &bp, const TRectangle &multirc);
+void RestoreRenderState(const Bypass &bp);
+u8 *GetPointer(const u32 &address);
+bool GetConfig(const int &type);
+void SetSamplerState(const Bypass &bp);
+void SetInterlacingMode(const Bypass &bp);
+};
+
#endif // _BPFUNCTIONS_H_ \ No newline at end of file
diff --git a/Source/Core/VideoCommon/Src/BPStructs.cpp b/Source/Core/VideoCommon/Src/BPStructs.cpp
index 19540bfca3..3780edb0b3 100644
--- a/Source/Core/VideoCommon/Src/BPStructs.cpp
+++ b/Source/Core/VideoCommon/Src/BPStructs.cpp
@@ -1,610 +1,610 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 <cmath>
-
-#include "Profiler.h"
-#include "Statistics.h"
-#include "VideoCommon.h"
-#include "PixelShaderManager.h"
-#include "BPFunctions.h"
-#include "BPStructs.h"
-#include "TextureDecoder.h"
-#include "OpcodeDecoding.h"
-#include "VertexLoader.h"
-#include "VertexShaderManager.h"
-
-using namespace BPFunctions;
-
-void BPInit()
-{
- memset(&bpmem, 0, sizeof(bpmem));
- bpmem.bpMask = 0xFFFFFF;
-}
-
-// ----------------------------------------------------------------------------------------------------------
-// Write to the Bypass Memory (Bypass Raster State Registers)
-/* ------------------
- Called:
- At the end of every: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg
- TODO:
- Turn into function table. The (future) DisplayList (DL) jit can then call the functions directly,
- getting rid of dynamic dispatch. Unfortunately, few games use DLs properly - most\
- just stuff geometry in them and don't put state changes there. */
-// ----------------------------------------------------------------------------------------------------------
-void BPWritten(const Bypass& bp)
-{
- // --------------------------------------------------------------------------------------------------------
- // First the pipeline is flushed then update the bpmem with the new value.
- // Some of the BP cases have to call certain functions while others just update the bpmem.
- // some bp cases check the changes variable, because they might not have to be updated all the time
- // NOTE: it seems not all bp cases like checking changes, so calling if (bp.changes == 0 ? false : true)
- // had to be ditched and the games seem to work fine with out it.
- // NOTE2: Yet Another Gamecube Documentation calls them Bypass Registers
- // --------------------------------------------------------------------------------------------------------
-
- // Debugging only, this lets you skip a bp update
- //static int times = 0;
- //static bool enable = false;
-
- //switch (bp.address)
- //{
- //case BPMEM_CONSTANTALPHA:
- // {
- // if (times-- == 0 && enable)
- // return;
- // else
- // break;
- // }
- //default: break;
- //}
-
- FlushPipeline();
- ((u32*)&bpmem)[bp.address] = bp.newvalue;
-
- switch (bp.address)
- {
- case BPMEM_GENMODE: // Set the Generation Mode
- {
- PRIM_LOG("genmode: texgen=%d, col=%d, ms_en=%d, tev=%d, culmode=%d, ind=%d, zfeeze=%d",
- bpmem.genMode.numtexgens, bpmem.genMode.numcolchans,
- bpmem.genMode.ms_en, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode,
- bpmem.genMode.numindstages, bpmem.genMode.zfreeze);
- SetGenerationMode(bp);
- break;
- }
- case BPMEM_IND_MTXA: // Index Matrix Changed
- case BPMEM_IND_MTXB:
- case BPMEM_IND_MTXC:
- case BPMEM_IND_MTXA+3:
- case BPMEM_IND_MTXB+3:
- case BPMEM_IND_MTXC+3:
- case BPMEM_IND_MTXA+6:
- case BPMEM_IND_MTXB+6:
- case BPMEM_IND_MTXC+6:
- PixelShaderManager::SetIndMatrixChanged((bp.address - BPMEM_IND_MTXA) / 3);
- break;
- case BPMEM_RAS1_SS0: // Index Texture Coordinate Scale 0
- PixelShaderManager::SetIndTexScaleChanged(0x03);
- case BPMEM_RAS1_SS1: // Index Texture Coordinate Scale 1
- PixelShaderManager::SetIndTexScaleChanged(0x0c);
- break;
- case BPMEM_SCISSORTL: // Scissor Rectable Top, Left
- case BPMEM_SCISSORBR: // Scissor Rectable Bottom, Right
- case BPMEM_SCISSOROFFSET: // Scissor Offset
- SetScissor(bp);
- break;
- case BPMEM_LINEPTWIDTH: // Line Width
- SetLineWidth(bp);
- break;
- case BPMEM_ZMODE: // Depth Control
- PRIM_LOG("zmode: test=%d, func=%d, upd=%d", bpmem.zmode.testenable, bpmem.zmode.func,
- bpmem.zmode.updateenable);
- SetDepthMode(bp);
- break;
- case BPMEM_BLENDMODE: // Blending Control
- {
- if (bp.changes & 0xFFFF)
- {
- PRIM_LOG("blendmode: en=%d, open=%d, colupd=%d, alphaupd=%d, dst=%d, src=%d, sub=%d, mode=%d",
- bpmem.blendmode.blendenable, bpmem.blendmode.logicopenable, bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate,
- bpmem.blendmode.dstfactor, bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode);
- // Set LogicOp Blending Mode
- if (bp.changes & 2)
- SetLogicOpMode(bp);
- // Set Dithering Mode
- if (bp.changes & 4)
- SetDitherMode(bp);
- // Set Blending Mode
- if (bp.changes & 0xFE1)
- SetBlendMode(bp);
- // Set Color Mask
- if (bp.changes & 0x18)
- SetColorMask(bp);
- }
- break;
- }
- case BPMEM_CONSTANTALPHA: // Set Destination Alpha
- {
- PRIM_LOG("constalpha: alp=%d, en=%d", bpmem.dstalpha.alpha, bpmem.dstalpha.enable);
- PixelShaderManager::SetDestAlpha(bpmem.dstalpha);
- break;
- }
- // This is called when the game is done drawing the new frame (eg: like in DX: Begin(); Draw(); End();)
- // Triggers an interrupt on the PPC side so that the game knows when the GPU has finished drawing.
- // Tokens are similar.
- case BPMEM_SETDRAWDONE:
- switch (bp.newvalue & 0xFF)
- {
- case 0x02:
- g_VideoInitialize.pSetPEFinish(); // may generate interrupt
- DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF));
- break;
-
- default:
- WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bp.newvalue & 0xFFFF));
- break;
- }
- break;
- case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
- g_VideoInitialize.pSetPEToken(static_cast<u16>(bp.newvalue & 0xFFFF), FALSE);
- DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF));
- break;
- case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
- g_VideoInitialize.pSetPEToken(static_cast<u16>(bp.newvalue & 0xFFFF), TRUE);
- DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF));
- break;
- // ------------------------
- // EFB copy command. This copies a rectangle from the EFB to either RAM in a texture format or to XFB as YUYV.
- // It can also optionally clear the EFB while copying from it. To emulate this, we of course copy first and clear afterwards.
- case BPMEM_TRIGGER_EFB_COPY: // Copy EFB Region or Render to the XFB or Clear the screen.
- {
- DVSTARTSUBPROFILE("LoadBPReg:swap");
- // The bottom right is within the rectangle
- // The values in bpmem.copyTexSrcXY and bpmem.copyTexSrcWH are updated in case 0x49 and 0x4a in this function
- TRectangle rc = {
- (int)(bpmem.copyTexSrcXY.x),
- (int)(bpmem.copyTexSrcXY.y),
- (int)((bpmem.copyTexSrcXY.x + bpmem.copyTexSrcWH.x + 1)),
- (int)((bpmem.copyTexSrcXY.y + bpmem.copyTexSrcWH.y + 1))
- };
-
- float MValueX = GetRendererTargetScaleX();
- float MValueY = GetRendererTargetScaleY();
-
- // Need another rc here to get it to scale.
- // Here the bottom right is the out of the rectangle.
- TRectangle multirc = {
- (int)(bpmem.copyTexSrcXY.x * MValueX),
- (int)(bpmem.copyTexSrcXY.y * MValueY),
- (int)((bpmem.copyTexSrcXY.x * MValueX + (bpmem.copyTexSrcWH.x + 1) * MValueX)),
- (int)((bpmem.copyTexSrcXY.y * MValueY + (bpmem.copyTexSrcWH.y + 1) * MValueY))
- };
- UPE_Copy PE_copy;
- PE_copy.Hex = bpmem.triggerEFBCopy;
-
- // Check if we are to copy from the EFB or draw to the XFB
- if (PE_copy.copy_to_xfb == 0)
- {
- if (GetConfig(CONFIG_SHOWEFBREGIONS))
- stats.efb_regions.push_back(rc);
-
- CopyEFB(bp, rc, bpmem.copyTexDest << 5,
- bpmem.zcontrol.pixel_format == PIXELFMT_Z24,
- PE_copy.intensity_fmt > 0,
- ((PE_copy.target_pixel_format / 2) + ((PE_copy.target_pixel_format & 1) * 8)),
- PE_copy.half_scale > 0);
- }
- else
- {
- // We should be able to get away with deactivating the current bbox tracking
- // here. Not sure if there's a better spot to put this.
- // the number of lines copied is determined by the y scale * source efb height
-#ifdef BBOX_SUPPORT
- *g_VideoInitialize.pBBoxActive = false;
-#endif
- const float yScale = bpmem.dispcopyyscale / 256.0f;
- const float xfbLines = ((bpmem.copyTexSrcWH.y + 1.0f) * yScale);
- RenderToXFB(bp, multirc, yScale, xfbLines,
- bpmem.copyTexDest << 5,
- bpmem.copyMipMapStrideChannels << 4,
- (u32)ceil(xfbLines));
- }
-
- // Clear the picture after it's done and submitted, to prepare for the next picture
- if (PE_copy.clear)
- ClearScreen(bp, multirc);
-
- RestoreRenderState(bp);
-
- break;
- }
- case BPMEM_LOADTLUT0: // Load a Texture Look Up Table
- case BPMEM_LOADTLUT1:
- {
- DVSTARTSUBPROFILE("LoadBPReg:GXLoadTlut");
-
- u32 tlutTMemAddr = (bp.newvalue & 0x3FF) << 9;
- u32 tlutXferCount = (bp.newvalue & 0x1FFC00) >> 5;
-
- u8 *ptr = 0;
-
- // TODO - figure out a cleaner way.
- if (GetConfig(CONFIG_ISWII))
- ptr = GetPointer(bpmem.tlutXferSrc << 5);
- else
- ptr = GetPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5);
-
- if (ptr)
- memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount);
- else
- PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5);
-
- // TODO(ector) : kill all textures that use this palette
- // Not sure if it's a good idea, though. For now, we hash texture palettes
- break;
- }
- case BPMEM_FOGRANGE: // Fog Settings Control
- case BPMEM_FOGPARAM0:
- case BPMEM_FOGBMAGNITUDE:
- case BPMEM_FOGBEXPONENT:
- case BPMEM_FOGPARAM3:
- if (!GetConfig(CONFIG_DISABLEFOG))
- PixelShaderManager::SetFogParamChanged();
- break;
- case BPMEM_FOGCOLOR: // Fog Color
- PixelShaderManager::SetFogColorChanged();
- break;
- case BPMEM_ALPHACOMPARE: // Compare Alpha Values
- PRIM_LOG("alphacmp: ref0=%d, ref1=%d, comp0=%d, comp1=%d, logic=%d", bpmem.alphaFunc.ref0,
- bpmem.alphaFunc.ref1, bpmem.alphaFunc.comp0, bpmem.alphaFunc.comp1, bpmem.alphaFunc.logic);
- PixelShaderManager::SetAlpha(bpmem.alphaFunc);
- break;
- case BPMEM_BIAS: // BIAS
- PRIM_LOG("ztex bias=0x%x", bpmem.ztex1.bias);
- PixelShaderManager::SetZTextureBias(bpmem.ztex1.bias);
- break;
- case BPMEM_ZTEX2: // Z Texture type
- {
- if (bp.changes & 3)
- PixelShaderManager::SetZTextureTypeChanged();
- #if defined(_DEBUG) || defined(DEBUGFAST)
- const char* pzop[] = {"DISABLE", "ADD", "REPLACE", "?"};
- const char* pztype[] = {"Z8", "Z16", "Z24", "?"};
- PRIM_LOG("ztex op=%s, type=%s", pzop[bpmem.ztex2.op], pztype[bpmem.ztex2.type]);
- #endif
- break;
- }
- // ----------------------------------
- // Display Copy Filtering Control
- // Fields: Destination, Frame2Field, Gamma, Source
- // TODO: We might have to implement the gamma one, some games might need this, if they are too dark to see.
- // ----------------------------------
- case BPMEM_DISPLAYCOPYFILER:
- case BPMEM_DISPLAYCOPYFILER+1:
- case BPMEM_DISPLAYCOPYFILER+2:
- case BPMEM_DISPLAYCOPYFILER+3:
- case BPMEM_COPYFILTER0: //GXSetCopyFilter
- case BPMEM_COPYFILTER1:
- break;
- case BPMEM_FIELDMASK: // Interlacing Control
- case BPMEM_FIELDMODE:
- SetInterlacingMode(bp);
- break;
- // ---------------------------------------------------
- // Debugging/Profiling info, we don't care about them
- // ---------------------------------------------------
- case BPMEM_CLOCK0: // Some Clock
- case BPMEM_CLOCK1: // Some Clock
- case BPMEM_SU_COUNTER: // Pixel or Poly Count
- case BPMEM_RAS_COUNTER: // Sound Count of something in the Texture Units
- case BPMEM_SETGPMETRIC: // Set the Graphic Processor Metric
- break;
- // ----------------
- // EFB Copy config
- // ----------------
- case BPMEM_EFB_TL: // EFB Source Rect. Top, Left
- case BPMEM_EFB_BR: // EFB Source Rect. Bottom, Right (w, h - 1)
- case BPMEM_EFB_ADDR: // EFB Target Address
- break;
- // --------------
- // Clear Config
- // --------------
- case BPMEM_CLEAR_AR: // Alpha and Red Components
- case BPMEM_CLEAR_GB: // Green and Blue Components
- case BPMEM_CLEAR_Z: // Z Components (24-bit Zbuffer)
- break;
- // -------------------------
- // Bounding Box support
- // -------------------------
- case BPMEM_CLEARBBOX1:
- case BPMEM_CLEARBBOX2: {
-
-#ifdef BBOX_SUPPORT
- // which is which? these are GUESSES!
- if (bp.address == BPMEM_CLEARBBOX1) {
- int right = bp.newvalue >> 10;
- int left = bp.newvalue & 0x3ff;
-
- // We should only set these if bbox is calculated properly.
- g_VideoInitialize.pBBox[0] = left;
- g_VideoInitialize.pBBox[1] = right;
- *g_VideoInitialize.pBBoxActive = true;
- // WARN_LOG(VIDEO, "ClearBBox LR: %i, %08x - %i, %i", bp.address, bp.newvalue, left, right);
- } else {
- int bottom = bp.newvalue >> 10;
- int top = bp.newvalue & 0x3ff;
-
- // We should only set these if bbox is calculated properly.
- g_VideoInitialize.pBBox[2] = top;
- g_VideoInitialize.pBBox[3] = bottom;
- *g_VideoInitialize.pBBoxActive = true;
- // WARN_LOG(VIDEO, "ClearBBox TB: %i, %08x - %i, %i", bp.address, bp.newvalue, top, bottom);
- }
-#endif
- break;
- }
- case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format
- case BPMEM_TEXINVALIDATE: // Used, if game has manual control the Texture Cache, which we don't allow
- case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel
- case BPMEM_COPYYSCALE: // Display Copy Y Scale
- case BPMEM_IREF: /* 24 RID
- 21 BC3 - Ind. Tex Stage 3 NTexCoord
- 18 BI3 - Ind. Tex Stage 3 NTexMap
- 15 BC2 - Ind. Tex Stage 2 NTexCoord
- 12 BI2 - Ind. Tex Stage 2 NTexMap
- 9 BC1 - Ind. Tex Stage 1 NTexCoord
- 6 BI1 - Ind. Tex Stage 1 NTexMap
- 3 BC0 - Ind. Tex Stage 0 NTexCoord
- 0 BI0 - Ind. Tex Stage 0 NTexMap */
- break;
- case BPMEM_TEV_KSEL: // Texture Environment Swap Mode Table 0
- case BPMEM_TEV_KSEL+1:// Texture Environment Swap Mode Table 1
- case BPMEM_TEV_KSEL+2:// Texture Environment Swap Mode Table 2
- case BPMEM_TEV_KSEL+3:// Texture Environment Swap Mode Table 3
- case BPMEM_TEV_KSEL+4:// Texture Environment Swap Mode Table 4
- case BPMEM_TEV_KSEL+5:// Texture Environment Swap Mode Table 5
- case BPMEM_TEV_KSEL+6:// Texture Environment Swap Mode Table 6
- case BPMEM_TEV_KSEL+7:// Texture Environment Swap Mode Table 7
- break;
- case BPMEM_BP_MASK: // This Register can be used to limit to which bits of BP registers is actually written to. the mask is
- // only valid for the next BP command, and will reset itself.
- case BPMEM_IND_IMASK: // Index Mask ?
- break;
- case BPMEM_UNKNOWN: // This is always set to 0xF at boot of any game, so this sounds like a useless reg
- if (bp.newvalue != 0x0F)
- PanicAlert("Unknown is not 0xF! val = 0x%08x", bp.newvalue);
- break;
-
- case BPMEM_UNKNOWN1:
- case BPMEM_UNKNOWN2:
- case BPMEM_UNKNOWN3:
- case BPMEM_UNKNOWN4:
- // Cases added due to: http://code.google.com/p/dolphin-emu/issues/detail?id=360#c90
- // Are these related to BBox?
- break;
-
- // ------------------------------------------------
- // On Default, we try to look for other things
- // before we give up and say its an unknown opcode
- // ------------------------------------------------
- default:
- switch (bp.address & 0xFC) // Texture sampler filter
- {
- // -------------------------
- // Texture Environment Order
- // -------------------------
- case BPMEM_TREF:
- case BPMEM_TREF+1:
- case BPMEM_TREF+2:
- case BPMEM_TREF+3:
- case BPMEM_TREF+4:
- case BPMEM_TREF+5:
- case BPMEM_TREF+6:
- case BPMEM_TREF+7:
- break;
- // ----------------------
- // Set wrap size
- // ----------------------
- case BPMEM_SU_SSIZE:
- case BPMEM_SU_TSIZE:
- case BPMEM_SU_SSIZE+2:
- case BPMEM_SU_TSIZE+2:
- case BPMEM_SU_SSIZE+4:
- case BPMEM_SU_TSIZE+4:
- case BPMEM_SU_SSIZE+6:
- case BPMEM_SU_TSIZE+6:
- case BPMEM_SU_SSIZE+8:
- case BPMEM_SU_TSIZE+8:
- case BPMEM_SU_SSIZE+10:
- case BPMEM_SU_TSIZE+10:
- case BPMEM_SU_SSIZE+12:
- case BPMEM_SU_TSIZE+12:
- case BPMEM_SU_SSIZE+14:
- case BPMEM_SU_TSIZE+14:
- PixelShaderManager::SetTexCoordChanged((bp.address - BPMEM_SU_SSIZE) >> 1);
- break;
- // ------------------------
- // BPMEM_TX_SETMODE0 - (Texture lookup and filtering mode) LOD/BIAS Clamp, MaxAnsio, LODBIAS, DiagLoad, Min Filter, Mag Filter, Wrap T, S
- // BPMEM_TX_SETMODE1 - (LOD Stuff) - Max LOD, Min LOD
- // ------------------------
- case BPMEM_TX_SETMODE0: // (0x90 for linear)
- case BPMEM_TX_SETMODE0+1:
- case BPMEM_TX_SETMODE0+2:
- case BPMEM_TX_SETMODE0+3:
- case BPMEM_TX_SETMODE1:
- case BPMEM_TX_SETMODE1+1:
- case BPMEM_TX_SETMODE1+2:
- case BPMEM_TX_SETMODE1+3:
- case BPMEM_TX_SETMODE0_4:
- case BPMEM_TX_SETMODE0_4+1:
- case BPMEM_TX_SETMODE0_4+2:
- case BPMEM_TX_SETMODE0_4+3:
- case BPMEM_TX_SETMODE1_4:
- case BPMEM_TX_SETMODE1_4+1:
- case BPMEM_TX_SETMODE1_4+2:
- case BPMEM_TX_SETMODE1_4+3:
- SetSamplerState(bp);
- break;
- // --------------------------------------------
- // BPMEM_TX_SETIMAGE0 - Texture width, height, format
- // BPMEM_TX_SETIMAGE1 - even LOD address in TMEM - Image Type, Cache Height, Cache Width, TMEM Offset
- // BPMEM_TX_SETIMAGE2 - odd LOD address in TMEM - Cache Height, Cache Width, TMEM Offset
- // BPMEM_TX_SETIMAGE3 - Address of Texture in main memory
- // --------------------------------------------
- case BPMEM_TX_SETIMAGE0:
- case BPMEM_TX_SETIMAGE0+1:
- case BPMEM_TX_SETIMAGE0+2:
- case BPMEM_TX_SETIMAGE0+3:
- case BPMEM_TX_SETIMAGE0_4:
- case BPMEM_TX_SETIMAGE0_4+1:
- case BPMEM_TX_SETIMAGE0_4+2:
- case BPMEM_TX_SETIMAGE0_4+3:
- case BPMEM_TX_SETIMAGE1:
- case BPMEM_TX_SETIMAGE1+1:
- case BPMEM_TX_SETIMAGE1+2:
- case BPMEM_TX_SETIMAGE1+3:
- case BPMEM_TX_SETIMAGE1_4:
- case BPMEM_TX_SETIMAGE1_4+1:
- case BPMEM_TX_SETIMAGE1_4+2:
- case BPMEM_TX_SETIMAGE1_4+3:
- case BPMEM_TX_SETIMAGE2:
- case BPMEM_TX_SETIMAGE2+1:
- case BPMEM_TX_SETIMAGE2+2:
- case BPMEM_TX_SETIMAGE2+3:
- case BPMEM_TX_SETIMAGE2_4:
- case BPMEM_TX_SETIMAGE2_4+1:
- case BPMEM_TX_SETIMAGE2_4+2:
- case BPMEM_TX_SETIMAGE2_4+3:
- case BPMEM_TX_SETIMAGE3:
- case BPMEM_TX_SETIMAGE3+1:
- case BPMEM_TX_SETIMAGE3+2:
- case BPMEM_TX_SETIMAGE3+3:
- case BPMEM_TX_SETIMAGE3_4:
- case BPMEM_TX_SETIMAGE3_4+1:
- case BPMEM_TX_SETIMAGE3_4+2:
- case BPMEM_TX_SETIMAGE3_4+3:
- break;
- // -------------------------------
- // Set a TLUT
- // BPMEM_TX_SETTLUT - Format, TMEM Offset (offset of TLUT from start of TMEM high bank > > 5)
- // -------------------------------
- case BPMEM_TX_SETTLUT:
- case BPMEM_TX_SETTLUT+1:
- case BPMEM_TX_SETTLUT+2:
- case BPMEM_TX_SETTLUT+3:
- case BPMEM_TX_SETLUT_4:
- case BPMEM_TX_SETLUT_4+1:
- case BPMEM_TX_SETLUT_4+2:
- case BPMEM_TX_SETLUT_4+3:
- break;
- // ---------------------------------------------------
- // Set the TEV Color
- // ---------------------------------------------------
- case BPMEM_TEV_REGISTER_L: // Reg 1
- case BPMEM_TEV_REGISTER_H:
- case BPMEM_TEV_REGISTER_L+2: // Reg 2
- case BPMEM_TEV_REGISTER_H+2:
- case BPMEM_TEV_REGISTER_L+4: // Reg 3
- case BPMEM_TEV_REGISTER_H+4:
- case BPMEM_TEV_REGISTER_L+6: // Reg 4
- case BPMEM_TEV_REGISTER_H+6:
- {
- if (bp.address & 1)
- {
- // don't compare with changes!
- int num = (bp.address >> 1 ) & 0x3;
- PixelShaderManager::SetColorChanged(bpmem.tevregs[num].high.type, num);
- }
- break;
- }
- // ------------------------------------------------
- // On Default, we try to look for other things
- // before we give up and say its an unknown opcode
- // again ...
- // ------------------------------------------------
- default:
- switch (bp.address & 0xF0)
- {
- // --------------
- // Indirect Tev
- // --------------
- case BPMEM_IND_CMD:
- case BPMEM_IND_CMD+1:
- case BPMEM_IND_CMD+2:
- case BPMEM_IND_CMD+3:
- case BPMEM_IND_CMD+4:
- case BPMEM_IND_CMD+5:
- case BPMEM_IND_CMD+6:
- case BPMEM_IND_CMD+7:
- case BPMEM_IND_CMD+8:
- case BPMEM_IND_CMD+9:
- case BPMEM_IND_CMD+10:
- case BPMEM_IND_CMD+11:
- case BPMEM_IND_CMD+12:
- case BPMEM_IND_CMD+13:
- case BPMEM_IND_CMD+14:
- case BPMEM_IND_CMD+15:
- break;
- // --------------------------------------------------
- // Set Color/Alpha of a Tev
- // BPMEM_TEV_COLOR_ENV - Dest, Shift, Clamp, Sub, Bias, Sel A, Sel B, Sel C, Sel D
- // BPMEM_TEV_ALPHA_ENV - Dest, Shift, Clamp, Sub, Bias, Sel A, Sel B, Sel C, Sel D, T Swap, R Swap
- // --------------------------------------------------
- case BPMEM_TEV_COLOR_ENV: // Texture Environment 1
- case BPMEM_TEV_ALPHA_ENV:
- case BPMEM_TEV_COLOR_ENV+2: // Texture Environment 2
- case BPMEM_TEV_ALPHA_ENV+2:
- case BPMEM_TEV_COLOR_ENV+4: // Texture Environment 3
- case BPMEM_TEV_ALPHA_ENV+4:
- case BPMEM_TEV_COLOR_ENV+8: // Texture Environment 4
- case BPMEM_TEV_ALPHA_ENV+8:
- case BPMEM_TEV_COLOR_ENV+10: // Texture Environment 5
- case BPMEM_TEV_ALPHA_ENV+10:
- case BPMEM_TEV_COLOR_ENV+12: // Texture Environment 6
- case BPMEM_TEV_ALPHA_ENV+12:
- case BPMEM_TEV_COLOR_ENV+14: // Texture Environment 7
- case BPMEM_TEV_ALPHA_ENV+14:
- case BPMEM_TEV_COLOR_ENV+16: // Texture Environment 8
- case BPMEM_TEV_ALPHA_ENV+16:
- case BPMEM_TEV_COLOR_ENV+18: // Texture Environment 9
- case BPMEM_TEV_ALPHA_ENV+18:
- case BPMEM_TEV_COLOR_ENV+20: // Texture Environment 10
- case BPMEM_TEV_ALPHA_ENV+20:
- case BPMEM_TEV_COLOR_ENV+22: // Texture Environment 11
- case BPMEM_TEV_ALPHA_ENV+22:
- case BPMEM_TEV_COLOR_ENV+24: // Texture Environment 12
- case BPMEM_TEV_ALPHA_ENV+24:
- case BPMEM_TEV_COLOR_ENV+26: // Texture Environment 13
- case BPMEM_TEV_ALPHA_ENV+26:
- case BPMEM_TEV_COLOR_ENV+28: // Texture Environment 14
- case BPMEM_TEV_ALPHA_ENV+28:
- case BPMEM_TEV_COLOR_ENV+30: // Texture Environment 15
- case BPMEM_TEV_ALPHA_ENV+30:
- case BPMEM_TEV_COLOR_ENV+32: // Texture Environment 16
- case BPMEM_TEV_ALPHA_ENV+32:
- break;
- default:
- WARN_LOG(VIDEO, "Unknown Bypass opcode: address = 0x%08x value = 0x%08x", bp.address, bp.newvalue);
- break;
- }
-
- }
-
- }
-}
-
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 <cmath>
+
+#include "Profiler.h"
+#include "Statistics.h"
+#include "VideoCommon.h"
+#include "PixelShaderManager.h"
+#include "BPFunctions.h"
+#include "BPStructs.h"
+#include "TextureDecoder.h"
+#include "OpcodeDecoding.h"
+#include "VertexLoader.h"
+#include "VertexShaderManager.h"
+
+using namespace BPFunctions;
+
+void BPInit()
+{
+ memset(&bpmem, 0, sizeof(bpmem));
+ bpmem.bpMask = 0xFFFFFF;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+// Write to the Bypass Memory (Bypass Raster State Registers)
+/* ------------------
+ Called:
+ At the end of every: OpcodeDecoding.cpp ExecuteDisplayList > Decode() > LoadBPReg
+ TODO:
+ Turn into function table. The (future) DisplayList (DL) jit can then call the functions directly,
+ getting rid of dynamic dispatch. Unfortunately, few games use DLs properly - most\
+ just stuff geometry in them and don't put state changes there. */
+// ----------------------------------------------------------------------------------------------------------
+void BPWritten(const Bypass& bp)
+{
+ // --------------------------------------------------------------------------------------------------------
+ // First the pipeline is flushed then update the bpmem with the new value.
+ // Some of the BP cases have to call certain functions while others just update the bpmem.
+ // some bp cases check the changes variable, because they might not have to be updated all the time
+ // NOTE: it seems not all bp cases like checking changes, so calling if (bp.changes == 0 ? false : true)
+ // had to be ditched and the games seem to work fine with out it.
+ // NOTE2: Yet Another Gamecube Documentation calls them Bypass Registers
+ // --------------------------------------------------------------------------------------------------------
+
+ // Debugging only, this lets you skip a bp update
+ //static int times = 0;
+ //static bool enable = false;
+
+ //switch (bp.address)
+ //{
+ //case BPMEM_CONSTANTALPHA:
+ // {
+ // if (times-- == 0 && enable)
+ // return;
+ // else
+ // break;
+ // }
+ //default: break;
+ //}
+
+ FlushPipeline();
+ ((u32*)&bpmem)[bp.address] = bp.newvalue;
+
+ switch (bp.address)
+ {
+ case BPMEM_GENMODE: // Set the Generation Mode
+ {
+ PRIM_LOG("genmode: texgen=%d, col=%d, ms_en=%d, tev=%d, culmode=%d, ind=%d, zfeeze=%d",
+ bpmem.genMode.numtexgens, bpmem.genMode.numcolchans,
+ bpmem.genMode.ms_en, bpmem.genMode.numtevstages+1, bpmem.genMode.cullmode,
+ bpmem.genMode.numindstages, bpmem.genMode.zfreeze);
+ SetGenerationMode(bp);
+ break;
+ }
+ case BPMEM_IND_MTXA: // Index Matrix Changed
+ case BPMEM_IND_MTXB:
+ case BPMEM_IND_MTXC:
+ case BPMEM_IND_MTXA+3:
+ case BPMEM_IND_MTXB+3:
+ case BPMEM_IND_MTXC+3:
+ case BPMEM_IND_MTXA+6:
+ case BPMEM_IND_MTXB+6:
+ case BPMEM_IND_MTXC+6:
+ PixelShaderManager::SetIndMatrixChanged((bp.address - BPMEM_IND_MTXA) / 3);
+ break;
+ case BPMEM_RAS1_SS0: // Index Texture Coordinate Scale 0
+ PixelShaderManager::SetIndTexScaleChanged(0x03);
+ case BPMEM_RAS1_SS1: // Index Texture Coordinate Scale 1
+ PixelShaderManager::SetIndTexScaleChanged(0x0c);
+ break;
+ case BPMEM_SCISSORTL: // Scissor Rectable Top, Left
+ case BPMEM_SCISSORBR: // Scissor Rectable Bottom, Right
+ case BPMEM_SCISSOROFFSET: // Scissor Offset
+ SetScissor(bp);
+ break;
+ case BPMEM_LINEPTWIDTH: // Line Width
+ SetLineWidth(bp);
+ break;
+ case BPMEM_ZMODE: // Depth Control
+ PRIM_LOG("zmode: test=%d, func=%d, upd=%d", bpmem.zmode.testenable, bpmem.zmode.func,
+ bpmem.zmode.updateenable);
+ SetDepthMode(bp);
+ break;
+ case BPMEM_BLENDMODE: // Blending Control
+ {
+ if (bp.changes & 0xFFFF)
+ {
+ PRIM_LOG("blendmode: en=%d, open=%d, colupd=%d, alphaupd=%d, dst=%d, src=%d, sub=%d, mode=%d",
+ bpmem.blendmode.blendenable, bpmem.blendmode.logicopenable, bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate,
+ bpmem.blendmode.dstfactor, bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode);
+ // Set LogicOp Blending Mode
+ if (bp.changes & 2)
+ SetLogicOpMode(bp);
+ // Set Dithering Mode
+ if (bp.changes & 4)
+ SetDitherMode(bp);
+ // Set Blending Mode
+ if (bp.changes & 0xFE1)
+ SetBlendMode(bp);
+ // Set Color Mask
+ if (bp.changes & 0x18)
+ SetColorMask(bp);
+ }
+ break;
+ }
+ case BPMEM_CONSTANTALPHA: // Set Destination Alpha
+ {
+ PRIM_LOG("constalpha: alp=%d, en=%d", bpmem.dstalpha.alpha, bpmem.dstalpha.enable);
+ PixelShaderManager::SetDestAlpha(bpmem.dstalpha);
+ break;
+ }
+ // This is called when the game is done drawing the new frame (eg: like in DX: Begin(); Draw(); End();)
+ // Triggers an interrupt on the PPC side so that the game knows when the GPU has finished drawing.
+ // Tokens are similar.
+ case BPMEM_SETDRAWDONE:
+ switch (bp.newvalue & 0xFF)
+ {
+ case 0x02:
+ g_VideoInitialize.pSetPEFinish(); // may generate interrupt
+ DEBUG_LOG(VIDEO, "GXSetDrawDone SetPEFinish (value: 0x%02X)", (bp.newvalue & 0xFFFF));
+ break;
+
+ default:
+ WARN_LOG(VIDEO, "GXSetDrawDone ??? (value 0x%02X)", (bp.newvalue & 0xFFFF));
+ break;
+ }
+ break;
+ case BPMEM_PE_TOKEN_ID: // Pixel Engine Token ID
+ g_VideoInitialize.pSetPEToken(static_cast<u16>(bp.newvalue & 0xFFFF), FALSE);
+ DEBUG_LOG(VIDEO, "SetPEToken 0x%04x", (bp.newvalue & 0xFFFF));
+ break;
+ case BPMEM_PE_TOKEN_INT_ID: // Pixel Engine Interrupt Token ID
+ g_VideoInitialize.pSetPEToken(static_cast<u16>(bp.newvalue & 0xFFFF), TRUE);
+ DEBUG_LOG(VIDEO, "SetPEToken + INT 0x%04x", (bp.newvalue & 0xFFFF));
+ break;
+ // ------------------------
+ // EFB copy command. This copies a rectangle from the EFB to either RAM in a texture format or to XFB as YUYV.
+ // It can also optionally clear the EFB while copying from it. To emulate this, we of course copy first and clear afterwards.
+ case BPMEM_TRIGGER_EFB_COPY: // Copy EFB Region or Render to the XFB or Clear the screen.
+ {
+ DVSTARTSUBPROFILE("LoadBPReg:swap");
+ // The bottom right is within the rectangle
+ // The values in bpmem.copyTexSrcXY and bpmem.copyTexSrcWH are updated in case 0x49 and 0x4a in this function
+ TRectangle rc = {
+ (int)(bpmem.copyTexSrcXY.x),
+ (int)(bpmem.copyTexSrcXY.y),
+ (int)((bpmem.copyTexSrcXY.x + bpmem.copyTexSrcWH.x + 1)),
+ (int)((bpmem.copyTexSrcXY.y + bpmem.copyTexSrcWH.y + 1))
+ };
+
+ float MValueX = GetRendererTargetScaleX();
+ float MValueY = GetRendererTargetScaleY();
+
+ // Need another rc here to get it to scale.
+ // Here the bottom right is the out of the rectangle.
+ TRectangle multirc = {
+ (int)(bpmem.copyTexSrcXY.x * MValueX),
+ (int)(bpmem.copyTexSrcXY.y * MValueY),
+ (int)((bpmem.copyTexSrcXY.x * MValueX + (bpmem.copyTexSrcWH.x + 1) * MValueX)),
+ (int)((bpmem.copyTexSrcXY.y * MValueY + (bpmem.copyTexSrcWH.y + 1) * MValueY))
+ };
+ UPE_Copy PE_copy;
+ PE_copy.Hex = bpmem.triggerEFBCopy;
+
+ // Check if we are to copy from the EFB or draw to the XFB
+ if (PE_copy.copy_to_xfb == 0)
+ {
+ if (GetConfig(CONFIG_SHOWEFBREGIONS))
+ stats.efb_regions.push_back(rc);
+
+ CopyEFB(bp, rc, bpmem.copyTexDest << 5,
+ bpmem.zcontrol.pixel_format == PIXELFMT_Z24,
+ PE_copy.intensity_fmt > 0,
+ ((PE_copy.target_pixel_format / 2) + ((PE_copy.target_pixel_format & 1) * 8)),
+ PE_copy.half_scale > 0);
+ }
+ else
+ {
+ // We should be able to get away with deactivating the current bbox tracking
+ // here. Not sure if there's a better spot to put this.
+ // the number of lines copied is determined by the y scale * source efb height
+#ifdef BBOX_SUPPORT
+ *g_VideoInitialize.pBBoxActive = false;
+#endif
+ const float yScale = bpmem.dispcopyyscale / 256.0f;
+ const float xfbLines = ((bpmem.copyTexSrcWH.y + 1.0f) * yScale);
+ RenderToXFB(bp, multirc, yScale, xfbLines,
+ bpmem.copyTexDest << 5,
+ bpmem.copyMipMapStrideChannels << 4,
+ (u32)ceil(xfbLines));
+ }
+
+ // Clear the picture after it's done and submitted, to prepare for the next picture
+ if (PE_copy.clear)
+ ClearScreen(bp, multirc);
+
+ RestoreRenderState(bp);
+
+ break;
+ }
+ case BPMEM_LOADTLUT0: // Load a Texture Look Up Table
+ case BPMEM_LOADTLUT1:
+ {
+ DVSTARTSUBPROFILE("LoadBPReg:GXLoadTlut");
+
+ u32 tlutTMemAddr = (bp.newvalue & 0x3FF) << 9;
+ u32 tlutXferCount = (bp.newvalue & 0x1FFC00) >> 5;
+
+ u8 *ptr = 0;
+
+ // TODO - figure out a cleaner way.
+ if (GetConfig(CONFIG_ISWII))
+ ptr = GetPointer(bpmem.tlutXferSrc << 5);
+ else
+ ptr = GetPointer((bpmem.tlutXferSrc & 0xFFFFF) << 5);
+
+ if (ptr)
+ memcpy_gc(texMem + tlutTMemAddr, ptr, tlutXferCount);
+ else
+ PanicAlert("Invalid palette pointer %08x %08x %08x", bpmem.tlutXferSrc, bpmem.tlutXferSrc << 5, (bpmem.tlutXferSrc & 0xFFFFF)<< 5);
+
+ // TODO(ector) : kill all textures that use this palette
+ // Not sure if it's a good idea, though. For now, we hash texture palettes
+ break;
+ }
+ case BPMEM_FOGRANGE: // Fog Settings Control
+ case BPMEM_FOGPARAM0:
+ case BPMEM_FOGBMAGNITUDE:
+ case BPMEM_FOGBEXPONENT:
+ case BPMEM_FOGPARAM3:
+ if (!GetConfig(CONFIG_DISABLEFOG))
+ PixelShaderManager::SetFogParamChanged();
+ break;
+ case BPMEM_FOGCOLOR: // Fog Color
+ PixelShaderManager::SetFogColorChanged();
+ break;
+ case BPMEM_ALPHACOMPARE: // Compare Alpha Values
+ PRIM_LOG("alphacmp: ref0=%d, ref1=%d, comp0=%d, comp1=%d, logic=%d", bpmem.alphaFunc.ref0,
+ bpmem.alphaFunc.ref1, bpmem.alphaFunc.comp0, bpmem.alphaFunc.comp1, bpmem.alphaFunc.logic);
+ PixelShaderManager::SetAlpha(bpmem.alphaFunc);
+ break;
+ case BPMEM_BIAS: // BIAS
+ PRIM_LOG("ztex bias=0x%x", bpmem.ztex1.bias);
+ PixelShaderManager::SetZTextureBias(bpmem.ztex1.bias);
+ break;
+ case BPMEM_ZTEX2: // Z Texture type
+ {
+ if (bp.changes & 3)
+ PixelShaderManager::SetZTextureTypeChanged();
+ #if defined(_DEBUG) || defined(DEBUGFAST)
+ const char* pzop[] = {"DISABLE", "ADD", "REPLACE", "?"};
+ const char* pztype[] = {"Z8", "Z16", "Z24", "?"};
+ PRIM_LOG("ztex op=%s, type=%s", pzop[bpmem.ztex2.op], pztype[bpmem.ztex2.type]);
+ #endif
+ break;
+ }
+ // ----------------------------------
+ // Display Copy Filtering Control
+ // Fields: Destination, Frame2Field, Gamma, Source
+ // TODO: We might have to implement the gamma one, some games might need this, if they are too dark to see.
+ // ----------------------------------
+ case BPMEM_DISPLAYCOPYFILER:
+ case BPMEM_DISPLAYCOPYFILER+1:
+ case BPMEM_DISPLAYCOPYFILER+2:
+ case BPMEM_DISPLAYCOPYFILER+3:
+ case BPMEM_COPYFILTER0: //GXSetCopyFilter
+ case BPMEM_COPYFILTER1:
+ break;
+ case BPMEM_FIELDMASK: // Interlacing Control
+ case BPMEM_FIELDMODE:
+ SetInterlacingMode(bp);
+ break;
+ // ---------------------------------------------------
+ // Debugging/Profiling info, we don't care about them
+ // ---------------------------------------------------
+ case BPMEM_CLOCK0: // Some Clock
+ case BPMEM_CLOCK1: // Some Clock
+ case BPMEM_SU_COUNTER: // Pixel or Poly Count
+ case BPMEM_RAS_COUNTER: // Sound Count of something in the Texture Units
+ case BPMEM_SETGPMETRIC: // Set the Graphic Processor Metric
+ break;
+ // ----------------
+ // EFB Copy config
+ // ----------------
+ case BPMEM_EFB_TL: // EFB Source Rect. Top, Left
+ case BPMEM_EFB_BR: // EFB Source Rect. Bottom, Right (w, h - 1)
+ case BPMEM_EFB_ADDR: // EFB Target Address
+ break;
+ // --------------
+ // Clear Config
+ // --------------
+ case BPMEM_CLEAR_AR: // Alpha and Red Components
+ case BPMEM_CLEAR_GB: // Green and Blue Components
+ case BPMEM_CLEAR_Z: // Z Components (24-bit Zbuffer)
+ break;
+ // -------------------------
+ // Bounding Box support
+ // -------------------------
+ case BPMEM_CLEARBBOX1:
+ case BPMEM_CLEARBBOX2: {
+
+#ifdef BBOX_SUPPORT
+ // which is which? these are GUESSES!
+ if (bp.address == BPMEM_CLEARBBOX1) {
+ int right = bp.newvalue >> 10;
+ int left = bp.newvalue & 0x3ff;
+
+ // We should only set these if bbox is calculated properly.
+ g_VideoInitialize.pBBox[0] = left;
+ g_VideoInitialize.pBBox[1] = right;
+ *g_VideoInitialize.pBBoxActive = true;
+ // WARN_LOG(VIDEO, "ClearBBox LR: %i, %08x - %i, %i", bp.address, bp.newvalue, left, right);
+ } else {
+ int bottom = bp.newvalue >> 10;
+ int top = bp.newvalue & 0x3ff;
+
+ // We should only set these if bbox is calculated properly.
+ g_VideoInitialize.pBBox[2] = top;
+ g_VideoInitialize.pBBox[3] = bottom;
+ *g_VideoInitialize.pBBoxActive = true;
+ // WARN_LOG(VIDEO, "ClearBBox TB: %i, %08x - %i, %i", bp.address, bp.newvalue, top, bottom);
+ }
+#endif
+ break;
+ }
+ case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format
+ case BPMEM_TEXINVALIDATE: // Used, if game has manual control the Texture Cache, which we don't allow
+ case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel
+ case BPMEM_COPYYSCALE: // Display Copy Y Scale
+ case BPMEM_IREF: /* 24 RID
+ 21 BC3 - Ind. Tex Stage 3 NTexCoord
+ 18 BI3 - Ind. Tex Stage 3 NTexMap
+ 15 BC2 - Ind. Tex Stage 2 NTexCoord
+ 12 BI2 - Ind. Tex Stage 2 NTexMap
+ 9 BC1 - Ind. Tex Stage 1 NTexCoord
+ 6 BI1 - Ind. Tex Stage 1 NTexMap
+ 3 BC0 - Ind. Tex Stage 0 NTexCoord
+ 0 BI0 - Ind. Tex Stage 0 NTexMap */
+ break;
+ case BPMEM_TEV_KSEL: // Texture Environment Swap Mode Table 0
+ case BPMEM_TEV_KSEL+1:// Texture Environment Swap Mode Table 1
+ case BPMEM_TEV_KSEL+2:// Texture Environment Swap Mode Table 2
+ case BPMEM_TEV_KSEL+3:// Texture Environment Swap Mode Table 3
+ case BPMEM_TEV_KSEL+4:// Texture Environment Swap Mode Table 4
+ case BPMEM_TEV_KSEL+5:// Texture Environment Swap Mode Table 5
+ case BPMEM_TEV_KSEL+6:// Texture Environment Swap Mode Table 6
+ case BPMEM_TEV_KSEL+7:// Texture Environment Swap Mode Table 7
+ break;
+ case BPMEM_BP_MASK: // This Register can be used to limit to which bits of BP registers is actually written to. the mask is
+ // only valid for the next BP command, and will reset itself.
+ case BPMEM_IND_IMASK: // Index Mask ?
+ break;
+ case BPMEM_UNKNOWN: // This is always set to 0xF at boot of any game, so this sounds like a useless reg
+ if (bp.newvalue != 0x0F)
+ PanicAlert("Unknown is not 0xF! val = 0x%08x", bp.newvalue);
+ break;
+
+ case BPMEM_UNKNOWN1:
+ case BPMEM_UNKNOWN2:
+ case BPMEM_UNKNOWN3:
+ case BPMEM_UNKNOWN4:
+ // Cases added due to: http://code.google.com/p/dolphin-emu/issues/detail?id=360#c90
+ // Are these related to BBox?
+ break;
+
+ // ------------------------------------------------
+ // On Default, we try to look for other things
+ // before we give up and say its an unknown opcode
+ // ------------------------------------------------
+ default:
+ switch (bp.address & 0xFC) // Texture sampler filter
+ {
+ // -------------------------
+ // Texture Environment Order
+ // -------------------------
+ case BPMEM_TREF:
+ case BPMEM_TREF+1:
+ case BPMEM_TREF+2:
+ case BPMEM_TREF+3:
+ case BPMEM_TREF+4:
+ case BPMEM_TREF+5:
+ case BPMEM_TREF+6:
+ case BPMEM_TREF+7:
+ break;
+ // ----------------------
+ // Set wrap size
+ // ----------------------
+ case BPMEM_SU_SSIZE:
+ case BPMEM_SU_TSIZE:
+ case BPMEM_SU_SSIZE+2:
+ case BPMEM_SU_TSIZE+2:
+ case BPMEM_SU_SSIZE+4:
+ case BPMEM_SU_TSIZE+4:
+ case BPMEM_SU_SSIZE+6:
+ case BPMEM_SU_TSIZE+6:
+ case BPMEM_SU_SSIZE+8:
+ case BPMEM_SU_TSIZE+8:
+ case BPMEM_SU_SSIZE+10:
+ case BPMEM_SU_TSIZE+10:
+ case BPMEM_SU_SSIZE+12:
+ case BPMEM_SU_TSIZE+12:
+ case BPMEM_SU_SSIZE+14:
+ case BPMEM_SU_TSIZE+14:
+ PixelShaderManager::SetTexCoordChanged((bp.address - BPMEM_SU_SSIZE) >> 1);
+ break;
+ // ------------------------
+ // BPMEM_TX_SETMODE0 - (Texture lookup and filtering mode) LOD/BIAS Clamp, MaxAnsio, LODBIAS, DiagLoad, Min Filter, Mag Filter, Wrap T, S
+ // BPMEM_TX_SETMODE1 - (LOD Stuff) - Max LOD, Min LOD
+ // ------------------------
+ case BPMEM_TX_SETMODE0: // (0x90 for linear)
+ case BPMEM_TX_SETMODE0+1:
+ case BPMEM_TX_SETMODE0+2:
+ case BPMEM_TX_SETMODE0+3:
+ case BPMEM_TX_SETMODE1:
+ case BPMEM_TX_SETMODE1+1:
+ case BPMEM_TX_SETMODE1+2:
+ case BPMEM_TX_SETMODE1+3:
+ case BPMEM_TX_SETMODE0_4:
+ case BPMEM_TX_SETMODE0_4+1:
+ case BPMEM_TX_SETMODE0_4+2:
+ case BPMEM_TX_SETMODE0_4+3:
+ case BPMEM_TX_SETMODE1_4:
+ case BPMEM_TX_SETMODE1_4+1:
+ case BPMEM_TX_SETMODE1_4+2:
+ case BPMEM_TX_SETMODE1_4+3:
+ SetSamplerState(bp);
+ break;
+ // --------------------------------------------
+ // BPMEM_TX_SETIMAGE0 - Texture width, height, format
+ // BPMEM_TX_SETIMAGE1 - even LOD address in TMEM - Image Type, Cache Height, Cache Width, TMEM Offset
+ // BPMEM_TX_SETIMAGE2 - odd LOD address in TMEM - Cache Height, Cache Width, TMEM Offset
+ // BPMEM_TX_SETIMAGE3 - Address of Texture in main memory
+ // --------------------------------------------
+ case BPMEM_TX_SETIMAGE0:
+ case BPMEM_TX_SETIMAGE0+1:
+ case BPMEM_TX_SETIMAGE0+2:
+ case BPMEM_TX_SETIMAGE0+3:
+ case BPMEM_TX_SETIMAGE0_4:
+ case BPMEM_TX_SETIMAGE0_4+1:
+ case BPMEM_TX_SETIMAGE0_4+2:
+ case BPMEM_TX_SETIMAGE0_4+3:
+ case BPMEM_TX_SETIMAGE1:
+ case BPMEM_TX_SETIMAGE1+1:
+ case BPMEM_TX_SETIMAGE1+2:
+ case BPMEM_TX_SETIMAGE1+3:
+ case BPMEM_TX_SETIMAGE1_4:
+ case BPMEM_TX_SETIMAGE1_4+1:
+ case BPMEM_TX_SETIMAGE1_4+2:
+ case BPMEM_TX_SETIMAGE1_4+3:
+ case BPMEM_TX_SETIMAGE2:
+ case BPMEM_TX_SETIMAGE2+1:
+ case BPMEM_TX_SETIMAGE2+2:
+ case BPMEM_TX_SETIMAGE2+3:
+ case BPMEM_TX_SETIMAGE2_4:
+ case BPMEM_TX_SETIMAGE2_4+1:
+ case BPMEM_TX_SETIMAGE2_4+2:
+ case BPMEM_TX_SETIMAGE2_4+3:
+ case BPMEM_TX_SETIMAGE3:
+ case BPMEM_TX_SETIMAGE3+1:
+ case BPMEM_TX_SETIMAGE3+2:
+ case BPMEM_TX_SETIMAGE3+3:
+ case BPMEM_TX_SETIMAGE3_4:
+ case BPMEM_TX_SETIMAGE3_4+1:
+ case BPMEM_TX_SETIMAGE3_4+2:
+ case BPMEM_TX_SETIMAGE3_4+3:
+ break;
+ // -------------------------------
+ // Set a TLUT
+ // BPMEM_TX_SETTLUT - Format, TMEM Offset (offset of TLUT from start of TMEM high bank > > 5)
+ // -------------------------------
+ case BPMEM_TX_SETTLUT:
+ case BPMEM_TX_SETTLUT+1:
+ case BPMEM_TX_SETTLUT+2:
+ case BPMEM_TX_SETTLUT+3:
+ case BPMEM_TX_SETLUT_4:
+ case BPMEM_TX_SETLUT_4+1:
+ case BPMEM_TX_SETLUT_4+2:
+ case BPMEM_TX_SETLUT_4+3:
+ break;
+ // ---------------------------------------------------
+ // Set the TEV Color
+ // ---------------------------------------------------
+ case BPMEM_TEV_REGISTER_L: // Reg 1
+ case BPMEM_TEV_REGISTER_H:
+ case BPMEM_TEV_REGISTER_L+2: // Reg 2
+ case BPMEM_TEV_REGISTER_H+2:
+ case BPMEM_TEV_REGISTER_L+4: // Reg 3
+ case BPMEM_TEV_REGISTER_H+4:
+ case BPMEM_TEV_REGISTER_L+6: // Reg 4
+ case BPMEM_TEV_REGISTER_H+6:
+ {
+ if (bp.address & 1)
+ {
+ // don't compare with changes!
+ int num = (bp.address >> 1 ) & 0x3;
+ PixelShaderManager::SetColorChanged(bpmem.tevregs[num].high.type, num);
+ }
+ break;
+ }
+ // ------------------------------------------------
+ // On Default, we try to look for other things
+ // before we give up and say its an unknown opcode
+ // again ...
+ // ------------------------------------------------
+ default:
+ switch (bp.address & 0xF0)
+ {
+ // --------------
+ // Indirect Tev
+ // --------------
+ case BPMEM_IND_CMD:
+ case BPMEM_IND_CMD+1:
+ case BPMEM_IND_CMD+2:
+ case BPMEM_IND_CMD+3:
+ case BPMEM_IND_CMD+4:
+ case BPMEM_IND_CMD+5:
+ case BPMEM_IND_CMD+6:
+ case BPMEM_IND_CMD+7:
+ case BPMEM_IND_CMD+8:
+ case BPMEM_IND_CMD+9:
+ case BPMEM_IND_CMD+10:
+ case BPMEM_IND_CMD+11:
+ case BPMEM_IND_CMD+12:
+ case BPMEM_IND_CMD+13:
+ case BPMEM_IND_CMD+14:
+ case BPMEM_IND_CMD+15:
+ break;
+ // --------------------------------------------------
+ // Set Color/Alpha of a Tev
+ // BPMEM_TEV_COLOR_ENV - Dest, Shift, Clamp, Sub, Bias, Sel A, Sel B, Sel C, Sel D
+ // BPMEM_TEV_ALPHA_ENV - Dest, Shift, Clamp, Sub, Bias, Sel A, Sel B, Sel C, Sel D, T Swap, R Swap
+ // --------------------------------------------------
+ case BPMEM_TEV_COLOR_ENV: // Texture Environment 1
+ case BPMEM_TEV_ALPHA_ENV:
+ case BPMEM_TEV_COLOR_ENV+2: // Texture Environment 2
+ case BPMEM_TEV_ALPHA_ENV+2:
+ case BPMEM_TEV_COLOR_ENV+4: // Texture Environment 3
+ case BPMEM_TEV_ALPHA_ENV+4:
+ case BPMEM_TEV_COLOR_ENV+8: // Texture Environment 4
+ case BPMEM_TEV_ALPHA_ENV+8:
+ case BPMEM_TEV_COLOR_ENV+10: // Texture Environment 5
+ case BPMEM_TEV_ALPHA_ENV+10:
+ case BPMEM_TEV_COLOR_ENV+12: // Texture Environment 6
+ case BPMEM_TEV_ALPHA_ENV+12:
+ case BPMEM_TEV_COLOR_ENV+14: // Texture Environment 7
+ case BPMEM_TEV_ALPHA_ENV+14:
+ case BPMEM_TEV_COLOR_ENV+16: // Texture Environment 8
+ case BPMEM_TEV_ALPHA_ENV+16:
+ case BPMEM_TEV_COLOR_ENV+18: // Texture Environment 9
+ case BPMEM_TEV_ALPHA_ENV+18:
+ case BPMEM_TEV_COLOR_ENV+20: // Texture Environment 10
+ case BPMEM_TEV_ALPHA_ENV+20:
+ case BPMEM_TEV_COLOR_ENV+22: // Texture Environment 11
+ case BPMEM_TEV_ALPHA_ENV+22:
+ case BPMEM_TEV_COLOR_ENV+24: // Texture Environment 12
+ case BPMEM_TEV_ALPHA_ENV+24:
+ case BPMEM_TEV_COLOR_ENV+26: // Texture Environment 13
+ case BPMEM_TEV_ALPHA_ENV+26:
+ case BPMEM_TEV_COLOR_ENV+28: // Texture Environment 14
+ case BPMEM_TEV_ALPHA_ENV+28:
+ case BPMEM_TEV_COLOR_ENV+30: // Texture Environment 15
+ case BPMEM_TEV_ALPHA_ENV+30:
+ case BPMEM_TEV_COLOR_ENV+32: // Texture Environment 16
+ case BPMEM_TEV_ALPHA_ENV+32:
+ break;
+ default:
+ WARN_LOG(VIDEO, "Unknown Bypass opcode: address = 0x%08x value = 0x%08x", bp.address, bp.newvalue);
+ break;
+ }
+
+ }
+
+ }
+}
+
diff --git a/Source/Core/VideoCommon/Src/BPStructs.h b/Source/Core/VideoCommon/Src/BPStructs.h
index fa1100db29..815b337ad5 100644
--- a/Source/Core/VideoCommon/Src/BPStructs.h
+++ b/Source/Core/VideoCommon/Src/BPStructs.h
@@ -1,27 +1,27 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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/
-
-#ifndef _BPSTRUCTS_H_
-#define _BPSTRUCTS_H_
-
-#include "BPMemory.h"
-
-void BPInit();
-void LoadBPReg(u32 value0);
-void BPReload();
-
-#endif // _BPSTRUCTS_H_
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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/
+
+#ifndef _BPSTRUCTS_H_
+#define _BPSTRUCTS_H_
+
+#include "BPMemory.h"
+
+void BPInit();
+void LoadBPReg(u32 value0);
+void BPReload();
+
+#endif // _BPSTRUCTS_H_
diff --git a/Source/Core/VideoCommon/Src/HiresTextures.cpp b/Source/Core/VideoCommon/Src/HiresTextures.cpp
index 80540b920e..58861fe93b 100644
--- a/Source/Core/VideoCommon/Src/HiresTextures.cpp
+++ b/Source/Core/VideoCommon/Src/HiresTextures.cpp
@@ -1,154 +1,154 @@
-// Copyright (C) 2003-2009 Dolphin Project.
-
-// 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 "HiresTextures.h"
-
-#include <cstring>
-#include <utility>
-#include <algorithm>
-#include "SOIL.h"
-#include "CommonPaths.h"
-#include "FileUtil.h"
-#include "FileSearch.h"
-
-namespace HiresTextures
-{
-
-std::map<std::string, std::string> textureMap;
-
-void Init(const char *gameCode)
-{
- static bool bCheckedDir;
-
- CFileSearch::XStringVector Directories;
- //Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
- char szDir[MAX_PATH];
- sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
- Directories.push_back(std::string(szDir));
-
-
- for (u32 i = 0; i < Directories.size(); i++)
- {
- File::FSTEntry FST_Temp;
- File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
- for (u32 j = 0; j < FST_Temp.children.size(); j++)
- {
- if (FST_Temp.children.at(j).isDirectory)
- {
- bool duplicate = false;
- NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
- for (u32 k = 0; k < Directories.size(); k++)
- {
- NormalizeDirSep(&Directories.at(k));
- if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
- {
- duplicate = true;
- break;
- }
- }
- if (!duplicate)
- Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
- }
- }
- }
-
- CFileSearch::XStringVector Extensions;
- Extensions.push_back("*.png");
- Extensions.push_back("*.bmp");
- Extensions.push_back("*.tga");
- Extensions.push_back("*.dds");
- Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
-
- CFileSearch FileSearch(Extensions, Directories);
- const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
- char code[MAX_PATH];
- sprintf(code, "%s_", gameCode);
-
- if (rFilenames.size() > 0)
- {
- for (u32 i = 0; i < rFilenames.size(); i++)
- {
- std::string FileName;
- SplitPath(rFilenames[i], NULL, &FileName, NULL);
-
- if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end())
- textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
- }
- }
-}
-
-void Shutdown()
-{
- textureMap.clear();
-}
-
-PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
-{
- std::string key(fileName);
-
- if(textureMap.find(key) == textureMap.end())
- return PC_TEX_FMT_NONE;
-
- int width;
- int height;
- int channels;
-
- u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
-
- if (temp == NULL) {
- ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
- SOIL_free_image_data(temp);
- return PC_TEX_FMT_NONE;
- }
-
- if (width > 1024 || height > 1024) {
- ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 1024 pixels tall and wide", textureMap[key].c_str(), width, height);
- SOIL_free_image_data(temp);
- return PC_TEX_FMT_NONE;
- }
-
- int offset = 0;
- PC_TexFormat returnTex;
-
- switch (texformat)
- {
- case GX_TF_I4:
- case GX_TF_I8:
- case GX_TF_IA4:
- case GX_TF_IA8:
- for (int i = 0; i < width * height * 4; i += 4)
- {
- // Rather than use a luminosity function, just use the most intense color for luminance
- data[offset++] = *std::max_element(temp+i, temp+i+3);
- data[offset++] = temp[i+3];
- }
- returnTex = PC_TEX_FMT_IA8;
- break;
- default:
- memcpy(data, temp, width*height*4);
- returnTex = PC_TEX_FMT_RGBA32;
- break;
- }
-
- *pWidth = width;
- *pHeight = height;
- SOIL_free_image_data(temp);
- INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
- return returnTex;
-}
-
-}
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// 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 "HiresTextures.h"
+
+#include <cstring>
+#include <utility>
+#include <algorithm>
+#include "SOIL.h"
+#include "CommonPaths.h"
+#include "FileUtil.h"
+#include "FileSearch.h"
+
+namespace HiresTextures
+{
+
+std::map<std::string, std::string> textureMap;
+
+void Init(const char *gameCode)
+{
+ static bool bCheckedDir;
+
+ CFileSearch::XStringVector Directories;
+ //Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
+ char szDir[MAX_PATH];
+ sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
+ Directories.push_back(std::string(szDir));
+
+
+ for (u32 i = 0; i < Directories.size(); i++)
+ {
+ File::FSTEntry FST_Temp;
+ File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
+ for (u32 j = 0; j < FST_Temp.children.size(); j++)
+ {
+ if (FST_Temp.children.at(j).isDirectory)
+ {
+ bool duplicate = false;
+ NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
+ for (u32 k = 0; k < Directories.size(); k++)
+ {
+ NormalizeDirSep(&Directories.at(k));
+ if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
+ {
+ duplicate = true;
+ break;
+ }
+ }
+ if (!duplicate)
+ Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
+ }
+ }
+ }
+
+ CFileSearch::XStringVector Extensions;
+ Extensions.push_back("*.png");
+ Extensions.push_back("*.bmp");
+ Extensions.push_back("*.tga");
+ Extensions.push_back("*.dds");
+ Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
+
+ CFileSearch FileSearch(Extensions, Directories);
+ const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
+ char code[MAX_PATH];
+ sprintf(code, "%s_", gameCode);
+
+ if (rFilenames.size() > 0)
+ {
+ for (u32 i = 0; i < rFilenames.size(); i++)
+ {
+ std::string FileName;
+ SplitPath(rFilenames[i], NULL, &FileName, NULL);
+
+ if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end())
+ textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
+ }
+ }
+}
+
+void Shutdown()
+{
+ textureMap.clear();
+}
+
+PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
+{
+ std::string key(fileName);
+
+ if(textureMap.find(key) == textureMap.end())
+ return PC_TEX_FMT_NONE;
+
+ int width;
+ int height;
+ int channels;
+
+ u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
+
+ if (temp == NULL) {
+ ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
+ SOIL_free_image_data(temp);
+ return PC_TEX_FMT_NONE;
+ }
+
+ if (width > 1024 || height > 1024) {
+ ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 1024 pixels tall and wide", textureMap[key].c_str(), width, height);
+ SOIL_free_image_data(temp);
+ return PC_TEX_FMT_NONE;
+ }
+
+ int offset = 0;
+ PC_TexFormat returnTex;
+
+ switch (texformat)
+ {
+ case GX_TF_I4:
+ case GX_TF_I8:
+ case GX_TF_IA4:
+ case GX_TF_IA8:
+ for (int i = 0; i < width * height * 4; i += 4)
+ {
+ // Rather than use a luminosity function, just use the most intense color for luminance
+ data[offset++] = *std::max_element(temp+i, temp+i+3);
+ data[offset++] = temp[i+3];
+ }
+ returnTex = PC_TEX_FMT_IA8;
+ break;
+ default:
+ memcpy(data, temp, width*height*4);
+ returnTex = PC_TEX_FMT_RGBA32;
+ break;
+ }
+
+ *pWidth = width;
+ *pHeight = height;
+ SOIL_free_image_data(temp);
+ INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
+ return returnTex;
+}
+
+}