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
This commit is contained in:
LPFaint99 2009-07-06 02:10:26 +00:00
parent 23f3e327e2
commit a41c1b2d0a
94 changed files with 24089 additions and 24089 deletions

View File

@ -1,88 +1,88 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h" #include "AudioCommon.h"
#include "Mixer.h" #include "Mixer.h"
#include "DSoundStream.h" #include "DSoundStream.h"
#include "AOSoundStream.h" #include "AOSoundStream.h"
#include "NullSoundStream.h" #include "NullSoundStream.h"
#include "OpenALStream.h" #include "OpenALStream.h"
namespace AudioCommon namespace AudioCommon
{ {
SoundStream *InitSoundStream(CMixer *mixer) SoundStream *InitSoundStream(CMixer *mixer)
{ {
if (!mixer) if (!mixer)
mixer = new CMixer(); mixer = new CMixer();
std::string backend = ac_Config.sBackend; std::string backend = ac_Config.sBackend;
if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd); 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_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer); if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer); if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
if (soundStream != NULL) { if (soundStream != NULL) {
ac_Config.Update(); ac_Config.Update();
if (soundStream->Start()) { if (soundStream->Start()) {
// Start the sound recording // Start the sound recording
/* /*
if (ac_Config.record) { if (ac_Config.record) {
soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile); soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
} }
*/ */
return soundStream; return soundStream;
} }
PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str()); 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()); PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
delete soundStream; delete soundStream;
soundStream = new NullSound(mixer); soundStream = new NullSound(mixer);
soundStream->Start(); soundStream->Start();
return NULL; return NULL;
} }
void ShutdownSoundStream() void ShutdownSoundStream()
{ {
NOTICE_LOG(DSPHLE, "Shutting down sound stream"); NOTICE_LOG(DSPHLE, "Shutting down sound stream");
if (soundStream) if (soundStream)
{ {
soundStream->Stop(); soundStream->Stop();
soundStream->StopLogAudio(); soundStream->StopLogAudio();
delete soundStream; delete soundStream;
soundStream = NULL; soundStream = NULL;
} }
INFO_LOG(DSPHLE, "Done shutting down sound stream"); INFO_LOG(DSPHLE, "Done shutting down sound stream");
} }
std::vector<std::string> GetSoundBackends() std::vector<std::string> GetSoundBackends()
{ {
std::vector<std::string> backends; std::vector<std::string> backends;
if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND); if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND); if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL); if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
if (NullSound::isValid()) backends.push_back(BACKEND_NULL); if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
return backends; return backends;
} }
} }

View File

@ -1,40 +1,40 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _AUDIO_COMMON_H_ #ifndef _AUDIO_COMMON_H_
#define _AUDIO_COMMON_H_ #define _AUDIO_COMMON_H_
#include "Common.h" #include "Common.h"
#include "AudioCommonConfig.h" #include "AudioCommonConfig.h"
#include "../../../PluginSpecs/pluginspecs_dsp.h" #include "../../../PluginSpecs/pluginspecs_dsp.h"
#include "SoundStream.h" #include "SoundStream.h"
class CMixer; class CMixer;
extern DSPInitialize g_dspInitialize; extern DSPInitialize g_dspInitialize;
extern SoundStream *soundStream; extern SoundStream *soundStream;
extern AudioCommonConfig ac_Config; extern AudioCommonConfig ac_Config;
namespace AudioCommon namespace AudioCommon
{ {
SoundStream *InitSoundStream(CMixer *mixer = NULL); SoundStream *InitSoundStream(CMixer *mixer = NULL);
void ShutdownSoundStream(); void ShutdownSoundStream();
std::vector<std::string> GetSoundBackends(); std::vector<std::string> GetSoundBackends();
} }
#endif // _AUDIO_COMMON_H_ #endif // _AUDIO_COMMON_H_

View File

@ -1,52 +1,52 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h" #include "AudioCommon.h"
AudioCommonConfig ac_Config; AudioCommonConfig ac_Config;
// Load from given file // Load from given file
void AudioCommonConfig::Load(IniFile &file) { void AudioCommonConfig::Load(IniFile &file) {
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true); file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true); file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
file.Get("Config", "Volume", &m_Volume, 75); file.Get("Config", "Volume", &m_Volume, 75);
#ifdef _WIN32 #ifdef _WIN32
file.Get("Config", "Backend", &sBackend, "DSound"); file.Get("Config", "Backend", &sBackend, "DSound");
#elif defined(__APPLE__) #elif defined(__APPLE__)
std::string temp; std::string temp;
file.Get("Config", "Backend", &temp, "AOSound"); file.Get("Config", "Backend", &temp, "AOSound");
strncpy(sBackend, temp.c_str(), 128); strncpy(sBackend, temp.c_str(), 128);
#else #else
file.Get("Config", "Backend", &sBackend, "AOSound"); file.Get("Config", "Backend", &sBackend, "AOSound");
#endif #endif
} }
// Set the values for the file // Set the values for the file
void AudioCommonConfig::Set(IniFile &file) { void AudioCommonConfig::Set(IniFile &file) {
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic); file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
file.Set("Config", "EnableThrottle", m_EnableThrottle); file.Set("Config", "EnableThrottle", m_EnableThrottle);
file.Set("Config", "Backend", sBackend); file.Set("Config", "Backend", sBackend);
file.Set("Config", "Volume", m_Volume); file.Set("Config", "Volume", m_Volume);
} }
// Update according to the values (stream/mixer) // Update according to the values (stream/mixer)
void AudioCommonConfig::Update() { void AudioCommonConfig::Update() {
if (soundStream) { if (soundStream) {
soundStream->GetMixer()->SetThrottle(m_EnableThrottle); soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic); soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
soundStream->SetVolume(m_Volume); soundStream->SetVolume(m_Volume);
} }
} }

View File

@ -1,50 +1,50 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _AUDIO_COMMON_CONFIG_H_ #ifndef _AUDIO_COMMON_CONFIG_H_
#define _AUDIO_COMMON_CONFIG_H_ #define _AUDIO_COMMON_CONFIG_H_
#include <string> #include <string>
#include "IniFile.h" #include "IniFile.h"
// Backend Types // Backend Types
#define BACKEND_DIRECTSOUND "DSound" #define BACKEND_DIRECTSOUND "DSound"
#define BACKEND_AOSOUND "AOSound" #define BACKEND_AOSOUND "AOSound"
#define BACKEND_OPENAL "OpenAL" #define BACKEND_OPENAL "OpenAL"
#define BACKEND_NULL "NullSound" #define BACKEND_NULL "NullSound"
struct AudioCommonConfig struct AudioCommonConfig
{ {
bool m_EnableDTKMusic; bool m_EnableDTKMusic;
bool m_EnableThrottle; bool m_EnableThrottle;
int m_Volume; int m_Volume;
#ifdef __APPLE__ #ifdef __APPLE__
char sBackend[128]; char sBackend[128];
#else #else
std::string sBackend; std::string sBackend;
#endif #endif
// Load from given file // Load from given file
void Load(IniFile &file); void Load(IniFile &file);
// Set the values for the file // Set the values for the file
void Set(IniFile &file); void Set(IniFile &file);
// Update according to the values (stream/mixer) // Update according to the values (stream/mixer)
void Update(); void Update();
}; };
#endif //AUDIO_COMMON_CONFIG #endif //AUDIO_COMMON_CONFIG

View File

@ -1,170 +1,170 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "aldlist.h" #include "aldlist.h"
#include "OpenALStream.h" #include "OpenALStream.h"
#if defined HAVE_OPENAL && HAVE_OPENAL #if defined HAVE_OPENAL && HAVE_OPENAL
#define AUDIO_NUMBUFFERS (4) #define AUDIO_NUMBUFFERS (4)
//#define AUDIO_SERVICE_UPDATE_PERIOD (20) //#define AUDIO_SERVICE_UPDATE_PERIOD (20)
bool OpenALStream::Start() bool OpenALStream::Start()
{ {
ALDeviceList *pDeviceList = NULL; ALDeviceList *pDeviceList = NULL;
ALCcontext *pContext = NULL; ALCcontext *pContext = NULL;
ALCdevice *pDevice = NULL; ALCdevice *pDevice = NULL;
bool bReturn = false; bool bReturn = false;
pDeviceList = new ALDeviceList(); pDeviceList = new ALDeviceList();
if ((pDeviceList) && (pDeviceList->GetNumDevices())) if ((pDeviceList) && (pDeviceList->GetNumDevices()))
{ {
pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice())); pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
if (pDevice) if (pDevice)
{ {
pContext = alcCreateContext(pDevice, NULL); pContext = alcCreateContext(pDevice, NULL);
if (pContext) if (pContext)
{ {
alcMakeContextCurrent(pContext); alcMakeContextCurrent(pContext);
thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this); thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
bReturn = true; bReturn = true;
} }
else else
{ {
alcCloseDevice(pDevice); alcCloseDevice(pDevice);
PanicAlert("OpenAL: can't create context for device %s", pDevice); PanicAlert("OpenAL: can't create context for device %s", pDevice);
} }
} else { } else {
PanicAlert("OpenAL: can't open device %s", pDevice); PanicAlert("OpenAL: can't open device %s", pDevice);
} }
delete pDeviceList; delete pDeviceList;
} else { } else {
PanicAlert("OpenAL: can't find sound devices"); PanicAlert("OpenAL: can't find sound devices");
} }
return bReturn; return bReturn;
} }
void OpenALStream::Stop() void OpenALStream::Stop()
{ {
ALCcontext *pContext; ALCcontext *pContext;
ALCdevice *pDevice; ALCdevice *pDevice;
soundCriticalSection.Enter(); soundCriticalSection.Enter();
threadData = 1; threadData = 1;
// kick the thread if it's waiting // kick the thread if it's waiting
soundSyncEvent.Set(); soundSyncEvent.Set();
soundCriticalSection.Leave(); soundCriticalSection.Leave();
delete thread; delete thread;
pContext = alcGetCurrentContext(); pContext = alcGetCurrentContext();
pDevice = alcGetContextsDevice(pContext); pDevice = alcGetContextsDevice(pContext);
alcMakeContextCurrent(NULL); alcMakeContextCurrent(NULL);
alcDestroyContext(pContext); alcDestroyContext(pContext);
alcCloseDevice(pDevice); alcCloseDevice(pDevice);
soundSyncEvent.Shutdown(); soundSyncEvent.Shutdown();
thread = NULL; thread = NULL;
} }
void OpenALStream::Update() void OpenALStream::Update()
{ {
//if (m_mixer->GetDataSize()) //here need debug //if (m_mixer->GetDataSize()) //here need debug
{ {
soundSyncEvent.Set(); soundSyncEvent.Set();
} }
} }
THREAD_RETURN OpenALStream::ThreadFunc(void* args) THREAD_RETURN OpenALStream::ThreadFunc(void* args)
{ {
(reinterpret_cast<OpenALStream *>(args))->SoundLoop(); (reinterpret_cast<OpenALStream *>(args))->SoundLoop();
return 0; return 0;
} }
void OpenALStream::SoundLoop() void OpenALStream::SoundLoop()
{ {
ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0}; ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
ALuint uiSource = 0; ALuint uiSource = 0;
ALenum err; ALenum err;
u32 ulFrequency = m_mixer->GetSampleRate(); u32 ulFrequency = m_mixer->GetSampleRate();
// Generate some AL Buffers for streaming // Generate some AL Buffers for streaming
alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers); alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
// Generate a Source to playback the Buffers // Generate a Source to playback the Buffers
alGenSources(1, &uiSource); alGenSources(1, &uiSource);
memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short)); memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
//* //*
for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++) for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
{ {
// pay load fake data // pay load fake data
alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency); alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]); alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
} }
//*/ //*/
alSourcePlay(uiSource); alSourcePlay(uiSource);
err = alGetError(); err = alGetError();
while (!threadData) while (!threadData)
{ {
soundCriticalSection.Enter(); soundCriticalSection.Enter();
int numBytesToRender = 32768; //ya, this is a hack, we need real data count int numBytesToRender = 32768; //ya, this is a hack, we need real data count
/*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2); /*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
soundCriticalSection.Leave(); soundCriticalSection.Leave();
//if (numBytesRender) //here need debug //if (numBytesRender) //here need debug
{ {
ALint iBuffersProcessed = 0; ALint iBuffersProcessed = 0;
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed); alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
if (iBuffersProcessed) if (iBuffersProcessed)
{ {
// Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer) // Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
ALuint uiTempBuffer = 0; ALuint uiTempBuffer = 0;
alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer); alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
/* /*
soundCriticalSection.Enter(); soundCriticalSection.Enter();
int numBytesToRender = 32768; //ya, this is a hack, we need real data count int numBytesToRender = 32768; //ya, this is a hack, we need real data count
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2); m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
soundCriticalSection.Leave(); soundCriticalSection.Leave();
unsigned long ulBytesWritten = 0; unsigned long ulBytesWritten = 0;
*/ */
//if (numBytesRender) //if (numBytesRender)
{ {
alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency); alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
} }
alSourceQueueBuffers(uiSource, 1, &uiTempBuffer); alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
} }
} }
if (!threadData) if (!threadData)
soundSyncEvent.Wait(); soundSyncEvent.Wait();
} }
alSourceStop(uiSource); alSourceStop(uiSource);
alSourcei(uiSource, AL_BUFFER, 0); alSourcei(uiSource, AL_BUFFER, 0);
// Clean up buffers and sources // Clean up buffers and sources
alDeleteSources(1, &uiSource); alDeleteSources(1, &uiSource);
alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers); alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
} }
#endif //HAVE_OPENAL #endif //HAVE_OPENAL

View File

@ -1,74 +1,74 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _OPENALSTREAM_H_ #ifndef _OPENALSTREAM_H_
#define _OPENALSTREAM_H_ #define _OPENALSTREAM_H_
#include "Common.h" #include "Common.h"
#include "SoundStream.h" #include "SoundStream.h"
#include "Thread.h" #include "Thread.h"
#if defined HAVE_OPENAL && HAVE_OPENAL #if defined HAVE_OPENAL && HAVE_OPENAL
#ifdef _WIN32 #ifdef _WIN32
#include "../../../../Externals/OpenAL/include/al.h" #include "../../../../Externals/OpenAL/include/al.h"
#include "../../../../Externals/OpenAL/include/alc.h" #include "../../../../Externals/OpenAL/include/alc.h"
#elif defined(__APPLE__) #elif defined(__APPLE__)
#include "openal/al.h" #include "openal/al.h"
#include "openal/alc.h" #include "openal/alc.h"
#else #else
#include "AL/al.h" #include "AL/al.h"
#include "AL/alc.h" #include "AL/alc.h"
#endif // WIN32 #endif // WIN32
// public use // public use
#define SFX_MAX_SOURCE 1 #define SFX_MAX_SOURCE 1
#define OAL_BUFFER_SIZE 1024*1024 #define OAL_BUFFER_SIZE 1024*1024
#endif #endif
class OpenALStream: public SoundStream class OpenALStream: public SoundStream
{ {
#if defined HAVE_OPENAL && HAVE_OPENAL #if defined HAVE_OPENAL && HAVE_OPENAL
public: public:
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}; OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
virtual ~OpenALStream() {}; virtual ~OpenALStream() {};
virtual bool Start(); virtual bool Start();
virtual void SoundLoop(); virtual void SoundLoop();
virtual void Stop(); virtual void Stop();
static bool isValid() { return true; } static bool isValid() { return true; }
virtual bool usesMixer() const { return true; } virtual bool usesMixer() const { return true; }
virtual void Update(); virtual void Update();
static THREAD_RETURN ThreadFunc(void* args); static THREAD_RETURN ThreadFunc(void* args);
private: private:
Common::Thread *thread; Common::Thread *thread;
Common::CriticalSection soundCriticalSection; Common::CriticalSection soundCriticalSection;
Common::Event soundSyncEvent; Common::Event soundSyncEvent;
short realtimeBuffer[OAL_BUFFER_SIZE]; short realtimeBuffer[OAL_BUFFER_SIZE];
#else #else
public: public:
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {} OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
#endif // HAVE_OPENAL #endif // HAVE_OPENAL
}; };
#endif // OPENALSTREAM #endif // OPENALSTREAM

View File

@ -1,341 +1,341 @@
/* /*
* Copyright (c) 2006, Creative Labs Inc. * Copyright (c) 2006, Creative Labs Inc.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, are permitted provided * Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met: * that the following conditions are met:
* *
* * Redistributions of source code must retain the above copyright notice, this list of conditions and * * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer. * the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions * * 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. * 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 * * 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. * 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 * 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 * 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 * 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 * 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) * 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 * 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 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "Common.h" #include "Common.h"
#include "aldlist.h" #include "aldlist.h"
#include "../../../../Externals/OpenAL/include/al.h" #include "../../../../Externals/OpenAL/include/al.h"
#include "../../../../Externals/OpenAL/include/alc.h" #include "../../../../Externals/OpenAL/include/alc.h"
/* /*
* Init call * Init call
*/ */
ALDeviceList::ALDeviceList() ALDeviceList::ALDeviceList()
{ {
ALDEVICEINFO ALDeviceInfo; ALDEVICEINFO ALDeviceInfo;
char *devices; char *devices;
s32 index; s32 index;
const char *defaultDeviceName = NULL; const char *defaultDeviceName = NULL;
const char *actualDeviceName = NULL; const char *actualDeviceName = NULL;
// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support // DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
vDeviceInfo.empty(); vDeviceInfo.empty();
vDeviceInfo.reserve(10); vDeviceInfo.reserve(10);
defaultDeviceIndex = 0; defaultDeviceIndex = 0;
// grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices // grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
//if (LoadOAL10Library(NULL, &ALFunction) == TRUE) { //if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT")) if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
{ {
devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER); devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
index = 0; index = 0;
// go through device list (each device terminated with a single NULL, list terminated with double NULL) // go through device list (each device terminated with a single NULL, list terminated with double NULL)
while (devices != NULL && strlen(devices) > 0) while (devices != NULL && strlen(devices) > 0)
{ {
if (strcmp(defaultDeviceName, devices) == 0) if (strcmp(defaultDeviceName, devices) == 0)
{ {
defaultDeviceIndex = index; defaultDeviceIndex = index;
} }
ALCdevice *device = alcOpenDevice(devices); ALCdevice *device = alcOpenDevice(devices);
if (device) if (device)
{ {
ALCcontext *context = alcCreateContext(device, NULL); ALCcontext *context = alcCreateContext(device, NULL);
if (context) if (context)
{ {
alcMakeContextCurrent(context); alcMakeContextCurrent(context);
// if new actual device name isn't already in the list, then add it... // if new actual device name isn't already in the list, then add it...
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER); actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
bool bNewName = true; bool bNewName = true;
for (s32 i = 0; i < GetNumDevices(); i++) for (s32 i = 0; i < GetNumDevices(); i++)
{ {
if (strcmp(GetDeviceName(i), actualDeviceName) == 0) if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
{ {
bNewName = false; bNewName = false;
} }
} }
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0)) if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
{ {
ALDeviceInfo.bSelected = true; ALDeviceInfo.bSelected = true;
ALDeviceInfo.strDeviceName = actualDeviceName; ALDeviceInfo.strDeviceName = actualDeviceName;
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion); alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion); alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
ALDeviceInfo.pvstrExtensions = new vector<string>; ALDeviceInfo.pvstrExtensions = new vector<string>;
// Check for ALC Extensions // Check for ALC Extensions
if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE) if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE"); ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE) if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX"); ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
// Check for AL Extensions // Check for AL Extensions
if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE) if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET"); ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE) if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE"); ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE) if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE"); ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
if (alIsExtensionPresent("EAX2.0") == AL_TRUE) if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX2.0"); ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
if (alIsExtensionPresent("EAX3.0") == AL_TRUE) if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX3.0"); ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
if (alIsExtensionPresent("EAX4.0") == AL_TRUE) if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX4.0"); ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
if (alIsExtensionPresent("EAX5.0") == AL_TRUE) if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX5.0"); ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
if (alIsExtensionPresent("EAX-RAM") == AL_TRUE) if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM"); ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
// Get Source Count // Get Source Count
ALDeviceInfo.uiSourceCount = GetMaxNumSources(); ALDeviceInfo.uiSourceCount = GetMaxNumSources();
vDeviceInfo.push_back(ALDeviceInfo); vDeviceInfo.push_back(ALDeviceInfo);
} }
alcMakeContextCurrent(NULL); alcMakeContextCurrent(NULL);
alcDestroyContext(context); alcDestroyContext(context);
} }
alcCloseDevice(device); alcCloseDevice(device);
} }
devices += strlen(devices) + 1; devices += strlen(devices) + 1;
index += 1; index += 1;
} }
} }
//} //}
ResetFilters(); ResetFilters();
} }
/* /*
* Exit call * Exit call
*/ */
ALDeviceList::~ALDeviceList() ALDeviceList::~ALDeviceList()
{ {
for (u32 i = 0; i < vDeviceInfo.size(); i++) { for (u32 i = 0; i < vDeviceInfo.size(); i++) {
if (vDeviceInfo[i].pvstrExtensions) { if (vDeviceInfo[i].pvstrExtensions) {
vDeviceInfo[i].pvstrExtensions->empty(); vDeviceInfo[i].pvstrExtensions->empty();
delete vDeviceInfo[i].pvstrExtensions; delete vDeviceInfo[i].pvstrExtensions;
} }
} }
vDeviceInfo.empty(); vDeviceInfo.empty();
} }
/* /*
* Returns the number of devices in the complete device list * Returns the number of devices in the complete device list
*/ */
s32 ALDeviceList::GetNumDevices() s32 ALDeviceList::GetNumDevices()
{ {
return (s32)vDeviceInfo.size(); return (s32)vDeviceInfo.size();
} }
/* /*
* Returns the device name at an index in the complete device list * Returns the device name at an index in the complete device list
*/ */
char * ALDeviceList::GetDeviceName(s32 index) char * ALDeviceList::GetDeviceName(s32 index)
{ {
if (index < GetNumDevices()) if (index < GetNumDevices())
return (char *)vDeviceInfo[index].strDeviceName.c_str(); return (char *)vDeviceInfo[index].strDeviceName.c_str();
else else
return NULL; return NULL;
} }
/* /*
* Returns the major and minor version numbers for a device at a specified index in the complete list * 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) void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
{ {
if (index < GetNumDevices()) { if (index < GetNumDevices()) {
if (major) if (major)
*major = vDeviceInfo[index].iMajorVersion; *major = vDeviceInfo[index].iMajorVersion;
if (minor) if (minor)
*minor = vDeviceInfo[index].iMinorVersion; *minor = vDeviceInfo[index].iMinorVersion;
} }
return; return;
} }
/* /*
* Returns the maximum number of Sources that can be generate on the given device * Returns the maximum number of Sources that can be generate on the given device
*/ */
u32 ALDeviceList::GetMaxNumSources(s32 index) u32 ALDeviceList::GetMaxNumSources(s32 index)
{ {
if (index < GetNumDevices()) if (index < GetNumDevices())
return vDeviceInfo[index].uiSourceCount; return vDeviceInfo[index].uiSourceCount;
else else
return 0; return 0;
} }
/* /*
* Checks if the extension is supported on the given device * Checks if the extension is supported on the given device
*/ */
bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName) bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
{ {
bool bReturn = false; bool bReturn = false;
if (index < GetNumDevices()) { if (index < GetNumDevices()) {
for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) { for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) { if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
bReturn = true; bReturn = true;
break; break;
} }
} }
} }
return bReturn; return bReturn;
} }
/* /*
* returns the index of the default device in the complete device list * returns the index of the default device in the complete device list
*/ */
s32 ALDeviceList::GetDefaultDevice() s32 ALDeviceList::GetDefaultDevice()
{ {
return defaultDeviceIndex; return defaultDeviceIndex;
} }
/* /*
* Deselects devices which don't have the specified minimum version * Deselects devices which don't have the specified minimum version
*/ */
void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor) void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
{ {
s32 dMajor = 0, dMinor = 0; s32 dMajor = 0, dMinor = 0;
for (u32 i = 0; i < vDeviceInfo.size(); i++) { for (u32 i = 0; i < vDeviceInfo.size(); i++) {
GetDeviceVersion(i, &dMajor, &dMinor); GetDeviceVersion(i, &dMajor, &dMinor);
if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) { if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
vDeviceInfo[i].bSelected = false; vDeviceInfo[i].bSelected = false;
} }
} }
} }
/* /*
* Deselects devices which don't have the specified maximum version * Deselects devices which don't have the specified maximum version
*/ */
void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor) void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
{ {
s32 dMajor = 0, dMinor = 0; s32 dMajor = 0, dMinor = 0;
for (u32 i = 0; i < vDeviceInfo.size(); i++) { for (u32 i = 0; i < vDeviceInfo.size(); i++) {
GetDeviceVersion(i, &dMajor, &dMinor); GetDeviceVersion(i, &dMajor, &dMinor);
if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) { if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
vDeviceInfo[i].bSelected = false; vDeviceInfo[i].bSelected = false;
} }
} }
} }
/* /*
* Deselects device which don't support the given extension name * Deselects device which don't support the given extension name
*/ */
void ALDeviceList::FilterDevicesExtension(char *szExtName) void ALDeviceList::FilterDevicesExtension(char *szExtName)
{ {
bool bFound; bool bFound;
for (u32 i = 0; i < vDeviceInfo.size(); i++) { for (u32 i = 0; i < vDeviceInfo.size(); i++) {
bFound = false; bFound = false;
for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) { for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) { if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
bFound = true; bFound = true;
break; break;
} }
} }
if (!bFound) if (!bFound)
vDeviceInfo[i].bSelected = false; vDeviceInfo[i].bSelected = false;
} }
} }
/* /*
* Resets all filtering, such that all devices are in the list * Resets all filtering, such that all devices are in the list
*/ */
void ALDeviceList::ResetFilters() void ALDeviceList::ResetFilters()
{ {
for (s32 i = 0; i < GetNumDevices(); i++) { for (s32 i = 0; i < GetNumDevices(); i++) {
vDeviceInfo[i].bSelected = true; vDeviceInfo[i].bSelected = true;
} }
filterIndex = 0; filterIndex = 0;
} }
/* /*
* Gets index of first filtered device * Gets index of first filtered device
*/ */
s32 ALDeviceList::GetFirstFilteredDevice() s32 ALDeviceList::GetFirstFilteredDevice()
{ {
s32 i; s32 i;
for (i = 0; i < GetNumDevices(); i++) { for (i = 0; i < GetNumDevices(); i++) {
if (vDeviceInfo[i].bSelected == true) { if (vDeviceInfo[i].bSelected == true) {
break; break;
} }
} }
filterIndex = i + 1; filterIndex = i + 1;
return i; return i;
} }
/* /*
* Gets index of next filtered device * Gets index of next filtered device
*/ */
s32 ALDeviceList::GetNextFilteredDevice() s32 ALDeviceList::GetNextFilteredDevice()
{ {
s32 i; s32 i;
for (i = filterIndex; i < GetNumDevices(); i++) { for (i = filterIndex; i < GetNumDevices(); i++) {
if (vDeviceInfo[i].bSelected == true) { if (vDeviceInfo[i].bSelected == true) {
break; break;
} }
} }
filterIndex = i + 1; filterIndex = i + 1;
return i; return i;
} }
/* /*
* Internal function to detemine max number of Sources that can be generated * Internal function to detemine max number of Sources that can be generated
*/ */
u32 ALDeviceList::GetMaxNumSources() u32 ALDeviceList::GetMaxNumSources()
{ {
ALuint uiSources[256]; ALuint uiSources[256];
u32 iSourceCount = 0; u32 iSourceCount = 0;
// Clear AL Error Code // Clear AL Error Code
alGetError(); alGetError();
// Generate up to 256 Sources, checking for any errors // Generate up to 256 Sources, checking for any errors
for (iSourceCount = 0; iSourceCount < 256; iSourceCount++) for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
{ {
alGenSources(1, &uiSources[iSourceCount]); alGenSources(1, &uiSources[iSourceCount]);
if (alGetError() != AL_NO_ERROR) if (alGetError() != AL_NO_ERROR)
break; break;
} }
// Release the Sources // Release the Sources
alDeleteSources(iSourceCount, uiSources); alDeleteSources(iSourceCount, uiSources);
if (alGetError() != AL_NO_ERROR) if (alGetError() != AL_NO_ERROR)
{ {
for (u32 i = 0; i < 256; i++) for (u32 i = 0; i < 256; i++)
{ {
alDeleteSources(1, &uiSources[i]); alDeleteSources(1, &uiSources[i]);
} }
} }
return iSourceCount; return iSourceCount;
} }

View File

@ -1,51 +1,51 @@
#ifndef ALDEVICELIST_H #ifndef ALDEVICELIST_H
#define ALDEVICELIST_H #define ALDEVICELIST_H
#include "CommonTypes.h" #include "CommonTypes.h"
#ifdef _WIN32 #ifdef _WIN32
#pragma warning(disable: 4786) //disable warning "identifier was truncated to #pragma warning(disable: 4786) //disable warning "identifier was truncated to
//'255' characters in the browser information" //'255' characters in the browser information"
#endif #endif
#include <vector> #include <vector>
#include <string> #include <string>
using namespace std; using namespace std;
typedef struct typedef struct
{ {
string strDeviceName; string strDeviceName;
s32 iMajorVersion; s32 iMajorVersion;
s32 iMinorVersion; s32 iMinorVersion;
u32 uiSourceCount; u32 uiSourceCount;
vector<string> *pvstrExtensions; vector<string> *pvstrExtensions;
bool bSelected; bool bSelected;
} ALDEVICEINFO, *LPALDEVICEINFO; } ALDEVICEINFO, *LPALDEVICEINFO;
class ALDeviceList class ALDeviceList
{ {
private: private:
vector<ALDEVICEINFO> vDeviceInfo; vector<ALDEVICEINFO> vDeviceInfo;
s32 defaultDeviceIndex; s32 defaultDeviceIndex;
s32 filterIndex; s32 filterIndex;
public: public:
ALDeviceList (); ALDeviceList ();
~ALDeviceList (); ~ALDeviceList ();
s32 GetNumDevices(); s32 GetNumDevices();
char *GetDeviceName(s32 index); char *GetDeviceName(s32 index);
void GetDeviceVersion(s32 index, s32 *major, s32 *minor); void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
u32 GetMaxNumSources(s32 index); u32 GetMaxNumSources(s32 index);
bool IsExtensionSupported(s32 index, char *szExtName); bool IsExtensionSupported(s32 index, char *szExtName);
s32 GetDefaultDevice(); s32 GetDefaultDevice();
void FilterDevicesMinVer(s32 major, s32 minor); void FilterDevicesMinVer(s32 major, s32 minor);
void FilterDevicesMaxVer(s32 major, s32 minor); void FilterDevicesMaxVer(s32 major, s32 minor);
void FilterDevicesExtension(char *szExtName); void FilterDevicesExtension(char *szExtName);
void ResetFilters(); void ResetFilters();
s32 GetFirstFilteredDevice(); s32 GetFirstFilteredDevice();
s32 GetNextFilteredDevice(); s32 GetNextFilteredDevice();
private: private:
u32 GetMaxNumSources(); u32 GetMaxNumSources();
}; };
#endif // ALDEVICELIST_H #endif // ALDEVICELIST_H

View File

@ -1,59 +1,59 @@
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "SymbolDB.h" #include "SymbolDB.h"
void SymbolDB::List() void SymbolDB::List()
{ {
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++) 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); 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()); INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
} }
void SymbolDB::Clear(const char *prefix) void SymbolDB::Clear(const char *prefix)
{ {
// TODO: honor prefix // TODO: honor prefix
functions.clear(); functions.clear();
checksumToFunction.clear(); checksumToFunction.clear();
} }
void SymbolDB::Index() void SymbolDB::Index()
{ {
int i = 0; int i = 0;
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++) for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{ {
iter->second.index = i++; iter->second.index = i++;
} }
} }
Symbol *SymbolDB::GetSymbolFromName(const char *name) Symbol *SymbolDB::GetSymbolFromName(const char *name)
{ {
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++) for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{ {
if (!strcmp(iter->second.name.c_str(), name)) if (!strcmp(iter->second.name.c_str(), name))
return &iter->second; return &iter->second;
} }
return 0; return 0;
} }
void SymbolDB::AddCompleteSymbol(const Symbol &symbol) void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
{ {
functions.insert(std::pair<u32, Symbol>(symbol.address, symbol)); functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
} }

View File

@ -1,122 +1,122 @@
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// This file contains a generic symbol map implementation. For CPU-specific // This file contains a generic symbol map implementation. For CPU-specific
// magic, derive and extend. // magic, derive and extend.
#ifndef _SYMBOL_DB_H #ifndef _SYMBOL_DB_H
#define _SYMBOL_DB_H #define _SYMBOL_DB_H
#include <string> #include <string>
#include <map> #include <map>
#include "Common.h" #include "Common.h"
struct SCall struct SCall
{ {
SCall(u32 a, u32 b) : SCall(u32 a, u32 b) :
function(a), function(a),
callAddress(b) callAddress(b)
{} {}
u32 function; u32 function;
u32 callAddress; u32 callAddress;
}; };
struct Symbol struct Symbol
{ {
enum { enum {
SYMBOL_FUNCTION = 0, SYMBOL_FUNCTION = 0,
SYMBOL_DATA = 1, SYMBOL_DATA = 1,
}; };
Symbol() : Symbol() :
hash(0), hash(0),
address(0), address(0),
flags(0), flags(0),
size(0), size(0),
numCalls(0), numCalls(0),
type(SYMBOL_FUNCTION), type(SYMBOL_FUNCTION),
analyzed(0) analyzed(0)
{} {}
std::string name; std::string name;
std::vector<SCall> callers; //addresses of functions that call this function std::vector<SCall> callers; //addresses of functions that call this function
std::vector<SCall> calls; //addresses of functions that are called by this function std::vector<SCall> calls; //addresses of functions that are called by this function
u32 hash; //use for HLE function finding u32 hash; //use for HLE function finding
u32 address; u32 address;
u32 flags; u32 flags;
int size; int size;
int numCalls; int numCalls;
int type; int type;
int index; // only used for coloring the disasm view int index; // only used for coloring the disasm view
int analyzed; int analyzed;
}; };
enum enum
{ {
FFLAG_TIMERINSTRUCTIONS=(1<<0), FFLAG_TIMERINSTRUCTIONS=(1<<0),
FFLAG_LEAF=(1<<1), FFLAG_LEAF=(1<<1),
FFLAG_ONLYCALLSNICELEAFS=(1<<2), FFLAG_ONLYCALLSNICELEAFS=(1<<2),
FFLAG_EVIL=(1<<3), FFLAG_EVIL=(1<<3),
FFLAG_RFI=(1<<4), FFLAG_RFI=(1<<4),
FFLAG_STRAIGHT=(1<<5) FFLAG_STRAIGHT=(1<<5)
}; };
class SymbolDB class SymbolDB
{ {
public: public:
typedef std::map<u32, Symbol> XFuncMap; typedef std::map<u32, Symbol> XFuncMap;
typedef std::map<u32, Symbol*> XFuncPtrMap; typedef std::map<u32, Symbol*> XFuncPtrMap;
protected: protected:
XFuncMap functions; XFuncMap functions;
XFuncPtrMap checksumToFunction; XFuncPtrMap checksumToFunction;
public: public:
SymbolDB() {} SymbolDB() {}
virtual ~SymbolDB() {} virtual ~SymbolDB() {}
virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; } virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
virtual Symbol *AddFunction(u32 startAddr) { return 0;} virtual Symbol *AddFunction(u32 startAddr) { return 0;}
void AddCompleteSymbol(const Symbol &symbol); void AddCompleteSymbol(const Symbol &symbol);
Symbol *GetSymbolFromName(const char *name); Symbol *GetSymbolFromName(const char *name);
Symbol *GetSymbolFromHash(u32 hash) { Symbol *GetSymbolFromHash(u32 hash) {
XFuncPtrMap::iterator iter = checksumToFunction.find(hash); XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
if (iter != checksumToFunction.end()) if (iter != checksumToFunction.end())
return iter->second; return iter->second;
else else
return 0; return 0;
} }
const XFuncMap &Symbols() const {return functions;} const XFuncMap &Symbols() const {return functions;}
XFuncMap &AccessSymbols() {return functions;} XFuncMap &AccessSymbols() {return functions;}
// deprecated // deprecated
XFuncMap::iterator GetIterator() { return functions.begin(); } XFuncMap::iterator GetIterator() { return functions.begin(); }
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); } XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
XFuncMap::iterator End() { return functions.end(); } XFuncMap::iterator End() { return functions.end(); }
void Clear(const char *prefix = ""); void Clear(const char *prefix = "");
void List(); void List();
void Index(); void Index();
}; };
#endif #endif

View File

@ -1,24 +1,24 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = { u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
//Add support for apple keycodes //Add support for apple keycodes
}; };
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = { u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
//Add support for apple keycodes //Add support for apple keycodes
}; };

View File

@ -1,25 +1,25 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = { u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
//Add support for Linux keycodes //Add support for Linux keycodes
}; };
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = { u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
//Add support for Linux keycodes //Add support for Linux keycodes
}; };

View File

@ -1,192 +1,192 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = { u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace 0x2A, // Backspace
0x2B, // Tab 0x2B, // Tab
0x00, 0x00, 0x00, 0x00,
0x00, // Clear 0x00, // Clear
0x28, // Return 0x28, // Return
0x00, 0x00, 0x00, 0x00,
0x00, // Shift 0x00, // Shift
0x00, // Control 0x00, // Control
0x00, // ALT 0x00, // ALT
0x48, // Pause 0x48, // Pause
0x39, // Capital 0x39, // Capital
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, // Escape 0x29, // Escape
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2C, // Space 0x2C, // Space
0x4B, // Prior 0x4B, // Prior
0x4E, // Next 0x4E, // Next
0x4D, // End 0x4D, // End
0x4A, // Home 0x4A, // Home
0x50, // Left 0x50, // Left
0x52, // Up 0x52, // Up
0x4F, // Right 0x4F, // Right
0x51, // Down 0x51, // Down
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, // Print screen 0x46, // Print screen
0x49, // Insert 0x49, // Insert
0x4C, // Delete 0x4C, // Delete
0x00, 0x00,
// 0 -> 9 // 0 -> 9
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x25, 0x26,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
// A -> Z // A -> Z
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
0x1C, 0x1D, 0x1C, 0x1D,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
// Numpad 0 -> 9 // Numpad 0 -> 9
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x60, 0x61,
0x55, // Multiply 0x55, // Multiply
0x57, // Add 0x57, // Add
0x00, // Separator 0x00, // Separator
0x56, // Substract 0x56, // Substract
0x63, // Decimal 0x63, // Decimal
0x54, // Divide 0x54, // Divide
// F1 -> F12 // F1 -> F12
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45, 0x42, 0x43, 0x44, 0x45,
// F13 -> F24 // F13 -> F24
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x53, // Numlock 0x53, // Numlock
0x47, // Scroll lock 0x47, // Scroll lock
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, 0x00, 0x00,
// Modifier keys // 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, 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, // ';' 0x33, // ';'
0x2E, // Plus 0x2E, // Plus
0x36, // Comma 0x36, // Comma
0x2D, // Minus 0x2D, // Minus
0x37, // Period 0x37, // Period
0x38, // '/' 0x38, // '/'
0x35, // '~' 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, 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, // '[' 0x2F, // '['
0x32, // '\' 0x32, // '\'
0x30, // ']' 0x30, // ']'
0x34, // ''' 0x34, // '''
0x00, // 0x00, //
0x00, // Nothing interesting past this point. 0x00, // Nothing interesting past this point.
}; };
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = { u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace 0x2A, // Backspace
0x2B, // Tab 0x2B, // Tab
0x00, 0x00, 0x00, 0x00,
0x00, // Clear 0x00, // Clear
0x28, // Return 0x28, // Return
0x00, 0x00, 0x00, 0x00,
0x00, // Shift 0x00, // Shift
0x00, // Control 0x00, // Control
0x00, // ALT 0x00, // ALT
0x48, // Pause 0x48, // Pause
0x39, // Capital 0x39, // Capital
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, // Escape 0x29, // Escape
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2C, // Space 0x2C, // Space
0x4B, // Prior 0x4B, // Prior
0x4E, // Next 0x4E, // Next
0x4D, // End 0x4D, // End
0x4A, // Home 0x4A, // Home
0x50, // Left 0x50, // Left
0x52, // Up 0x52, // Up
0x4F, // Right 0x4F, // Right
0x51, // Down 0x51, // Down
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x46, // Print screen 0x46, // Print screen
0x49, // Insert 0x49, // Insert
0x4C, // Delete 0x4C, // Delete
0x00, 0x00,
// 0 -> 9 // 0 -> 9
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26, 0x25, 0x26,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
// A -> Z // A -> Z
0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13, 0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B, 0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
0x1C, 0x1A, 0x1C, 0x1A,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
// Numpad 0 -> 9 // Numpad 0 -> 9
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x60, 0x61,
0x55, // Multiply 0x55, // Multiply
0x57, // Add 0x57, // Add
0x00, // Separator 0x00, // Separator
0x56, // Substract 0x56, // Substract
0x63, // Decimal 0x63, // Decimal
0x54, // Divide 0x54, // Divide
// F1 -> F12 // F1 -> F12
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45, 0x42, 0x43, 0x44, 0x45,
// F13 -> F24 // F13 -> F24
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x53, // Numlock 0x53, // Numlock
0x47, // Scroll lock 0x47, // Scroll lock
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, 0x00, 0x00,
// Modifier keys // 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, 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, // '$' 0x30, // '$'
0x2E, // Plus 0x2E, // Plus
0x10, // Comma 0x10, // Comma
0x00, // Minus 0x00, // Minus
0x36, // Period 0x36, // Period
0x37, // '/' 0x37, // '/'
0x34, // 'ù' 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, 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, // ')' 0x2D, // ')'
0x32, // '\' 0x32, // '\'
0x2F, // '^' 0x2F, // '^'
0x00, // '²' 0x00, // '²'
0x38, // '!' 0x38, // '!'
0x00, // Nothing interesting past this point. 0x00, // Nothing interesting past this point.
}; };

View File

@ -1,133 +1,133 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DSPAnalyzer.h" #include "DSPAnalyzer.h"
#include "DSPInterpreter.h" #include "DSPInterpreter.h"
#include "DSPTables.h" #include "DSPTables.h"
#include "DSPMemoryMap.h" #include "DSPMemoryMap.h"
namespace DSPAnalyzer { namespace DSPAnalyzer {
// Holds data about all instructions in RAM. // Holds data about all instructions in RAM.
u8 code_flags[ISPACE]; u8 code_flags[ISPACE];
// Good candidates for idle skipping is mail wait loops. If we're time slicing // 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 // 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. // as well give up its time slice immediately, after executing once.
// Max signature length is 6. A 0 in a signature is ignored. // Max signature length is 6. A 0 in a signature is ignored.
#define NUM_IDLE_SIGS 5 #define NUM_IDLE_SIGS 5
#define MAX_IDLE_SIG_SIZE 6 #define MAX_IDLE_SIG_SIZE 6
// 0xFFFF means ignore. // 0xFFFF means ignore.
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] = const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
{ {
// From AX: // From AX:
{ 0x26fc, // LRS $30, @DMBH { 0x26fc, // LRS $30, @DMBH
0x02c0, 0x8000, // ANDCF $30, #0x8000 0x02c0, 0x8000, // ANDCF $30, #0x8000
0x029d, 0xFFFF, // JLZ 0x027a 0x029d, 0xFFFF, // JLZ 0x027a
0, 0 }, // RET 0, 0 }, // RET
{ 0x27fc, // LRS $31, @DMBH { 0x27fc, // LRS $31, @DMBH
0x03c0, 0x8000, // ANDCF $31, #0x8000 0x03c0, 0x8000, // ANDCF $31, #0x8000
0x029d, 0xFFFF, // JLZ 0x027a 0x029d, 0xFFFF, // JLZ 0x027a
0, 0 }, // RET 0, 0 }, // RET
{ 0x26fe, // LRS $30, @CMBH { 0x26fe, // LRS $30, @CMBH
0x02c0, 0x8000, // ANDCF $30, #0x8000 0x02c0, 0x8000, // ANDCF $30, #0x8000
0x029c, 0xFFFF, // JLNZ 0x0280 0x029c, 0xFFFF, // JLNZ 0x0280
0, 0 }, // RET 0, 0 }, // RET
{ 0x27fe, // LRS $31, @CMBH { 0x27fe, // LRS $31, @CMBH
0x03c0, 0x8000, // ANDCF $31, #0x8000 0x03c0, 0x8000, // ANDCF $31, #0x8000
0x029c, 0xFFFF, // JLNZ 0x0280 0x029c, 0xFFFF, // JLNZ 0x0280
0, 0 }, // RET 0, 0 }, // RET
// From Zelda: // From Zelda:
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH { 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000 0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
0x029c, 0xFFFF, // JLNZ 0x05cf 0x029c, 0xFFFF, // JLNZ 0x05cf
0 } 0 }
}; };
void Reset() void Reset()
{ {
memset(code_flags, 0, sizeof(code_flags)); memset(code_flags, 0, sizeof(code_flags));
} }
void AnalyzeRange(int start_addr, int end_addr) void AnalyzeRange(int start_addr, int end_addr)
{ {
// First we run an extremely simplified version of a disassembler to find // First we run an extremely simplified version of a disassembler to find
// where all instructions start. // where all instructions start.
// This may not be 100% accurate in case of jump tables! // 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. // It could get desynced, which would be bad. We'll see if that's an issue.
int addr = start_addr; int addr = start_addr;
while (addr < end_addr) while (addr < end_addr)
{ {
UDSPInstruction inst = dsp_imem_read(addr); UDSPInstruction inst = dsp_imem_read(addr);
const DSPOPCTemplate *opcode = GetOpTemplate(inst); const DSPOPCTemplate *opcode = GetOpTemplate(inst);
if (!opcode) if (!opcode)
{ {
addr++; addr++;
continue; continue;
} }
code_flags[addr] |= CODE_START_OF_INST; code_flags[addr] |= CODE_START_OF_INST;
addr += opcode->size; addr += opcode->size;
// Look for loops. // Look for loops.
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) { if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
// BLOOP, BLOOPI // BLOOP, BLOOPI
u16 loop_end = dsp_imem_read(addr + 1); u16 loop_end = dsp_imem_read(addr + 1);
code_flags[loop_end] |= CODE_LOOP_END; code_flags[loop_end] |= CODE_LOOP_END;
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) { } else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
// LOOP, LOOPI // LOOP, LOOPI
code_flags[addr + 1] |= CODE_LOOP_END; code_flags[addr + 1] |= CODE_LOOP_END;
} }
} }
// Next, we'll scan for potential idle skips. // Next, we'll scan for potential idle skips.
for (int s = 0; s < NUM_IDLE_SIGS; s++) for (int s = 0; s < NUM_IDLE_SIGS; s++)
{ {
for (int addr = start_addr; addr < end_addr; addr++) for (int addr = start_addr; addr < end_addr; addr++)
{ {
bool found = false; bool found = false;
for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++) for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
{ {
if (idle_skip_sigs[s][i] == 0) if (idle_skip_sigs[s][i] == 0)
found = true; found = true;
if (idle_skip_sigs[s][i] == 0xFFFF) if (idle_skip_sigs[s][i] == 0xFFFF)
continue; continue;
if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i)) if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
break; break;
} }
if (found) if (found)
{ {
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr); NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
code_flags[addr] |= CODE_IDLE_SKIP; code_flags[addr] |= CODE_IDLE_SKIP;
// TODO: actually use this flag somewhere. // TODO: actually use this flag somewhere.
} }
} }
} }
NOTICE_LOG(DSPLLE, "Finished analysis."); NOTICE_LOG(DSPLLE, "Finished analysis.");
} }
void Analyze() void Analyze()
{ {
Reset(); Reset();
AnalyzeRange(0x0000, 0x1000); // IRAM AnalyzeRange(0x0000, 0x1000); // IRAM
AnalyzeRange(0x8000, 0x9000); // IROM AnalyzeRange(0x8000, 0x9000); // IROM
} }
} // namespace } // namespace

View File

@ -1,49 +1,49 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Basic code analysis. // Basic code analysis.
#include "DSPInterpreter.h" #include "DSPInterpreter.h"
namespace DSPAnalyzer { namespace DSPAnalyzer {
#define ISPACE 65536 #define ISPACE 65536
// Useful things to detect: // Useful things to detect:
// * Loop endpoints - so that we can avoid checking for loops every cycle. // * Loop endpoints - so that we can avoid checking for loops every cycle.
enum enum
{ {
CODE_START_OF_INST = 1, CODE_START_OF_INST = 1,
CODE_IDLE_SKIP = 2, CODE_IDLE_SKIP = 2,
CODE_LOOP_END = 4, CODE_LOOP_END = 4,
}; };
// Easy to query array covering the whole of instruction memory. // Easy to query array covering the whole of instruction memory.
// Just index by address. // Just index by address.
// This one will be helpful for debuggers and jits. // This one will be helpful for debuggers and jits.
extern u8 code_flags[ISPACE]; extern u8 code_flags[ISPACE];
// This one should be called every time IRAM changes - which is basically // 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, // 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 // 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 // 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 // words and the actual code space 8K instructions in total, so we can do
// some pretty expensive analysis if necessary. // some pretty expensive analysis if necessary.
void Analyze(); void Analyze();
} // namespace } // namespace

View File

@ -1,19 +1,19 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DSPBreakpoints.h" #include "DSPBreakpoints.h"

View File

@ -1,63 +1,63 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DSP_BREAKPOINTS #ifndef _DSP_BREAKPOINTS
#define _DSP_BREAKPOINTS #define _DSP_BREAKPOINTS
#include "Common.h" #include "Common.h"
// super fast breakpoints for a limited range. // super fast breakpoints for a limited range.
// To be used interchangably with the BreakPoints class. // To be used interchangably with the BreakPoints class.
class DSPBreakpoints class DSPBreakpoints
{ {
public: public:
DSPBreakpoints() {Clear();} DSPBreakpoints() {Clear();}
// is address breakpoint // is address breakpoint
bool IsAddressBreakPoint(u32 addr) { bool IsAddressBreakPoint(u32 addr) {
return b[addr] != 0; return b[addr] != 0;
} }
// AddBreakPoint // AddBreakPoint
bool Add(u32 addr, bool temp=false) { bool Add(u32 addr, bool temp=false) {
bool was_one = b[addr] != 0; bool was_one = b[addr] != 0;
if (!was_one) { if (!was_one) {
b[addr] = temp ? 2 : 1; b[addr] = temp ? 2 : 1;
return true; return true;
} else { } else {
return false; return false;
} }
} }
// Remove Breakpoint // Remove Breakpoint
bool Remove(u32 addr) { bool Remove(u32 addr) {
bool was_one = b[addr] != 0; bool was_one = b[addr] != 0;
b[addr] = 0; b[addr] = 0;
return was_one; return was_one;
} }
void Clear() { void Clear() {
for (int i = 0; i < 65536; i++) for (int i = 0; i < 65536; i++)
b[i] = 0; b[i] = 0;
} }
void DeleteByAddress(u32 addr) { void DeleteByAddress(u32 addr) {
b[addr] = 0; b[addr] = 0;
} }
private: private:
u8 b[65536]; u8 b[65536];
}; };
#endif #endif

View File

@ -1,235 +1,235 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "DSPCodeUtil.h" #include "DSPCodeUtil.h"
#include "assemble.h" #include "assemble.h"
#include "disassemble.h" #include "disassemble.h"
bool Assemble(const char *text, std::vector<u16> &code) bool Assemble(const char *text, std::vector<u16> &code)
{ {
AssemblerSettings settings; AssemblerSettings settings;
settings.pc = 0; settings.pc = 0;
// settings.decode_registers = false; // settings.decode_registers = false;
// settings.decode_names = false; // settings.decode_names = false;
settings.print_tabs = false; settings.print_tabs = false;
settings.ext_separator = '\''; settings.ext_separator = '\'';
// TODO: fix the terrible api of the assembler. // TODO: fix the terrible api of the assembler.
DSPAssembler assembler(settings); DSPAssembler assembler(settings);
if (!assembler.Assemble(text, code)) { if (!assembler.Assemble(text, code)) {
std::cerr << assembler.GetErrorString() << std::endl; std::cerr << assembler.GetErrorString() << std::endl;
return false; return false;
} }
return true; return true;
} }
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text) bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
{ {
if (code.empty()) if (code.empty())
return false; return false;
AssemblerSettings settings; AssemblerSettings settings;
// These two prevent roundtripping. // These two prevent roundtripping.
settings.show_hex = false; settings.show_hex = false;
settings.show_pc = line_numbers; settings.show_pc = line_numbers;
settings.ext_separator = '\''; settings.ext_separator = '\'';
settings.decode_names = false; settings.decode_names = false;
settings.decode_registers = true; settings.decode_registers = true;
DSPDisassembler disasm(settings); DSPDisassembler disasm(settings);
bool success = disasm.Disassemble(0, code, 0x0000, text); bool success = disasm.Disassemble(0, code, 0x0000, text);
return success; return success;
} }
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2) bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
{ {
if (code1.size() != code2.size()) if (code1.size() != code2.size())
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size()); printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
u32 count_equal = 0; u32 count_equal = 0;
const int min_size = (int)std::min(code1.size(), code2.size()); const int min_size = (int)std::min(code1.size(), code2.size());
AssemblerSettings settings; AssemblerSettings settings;
DSPDisassembler disassembler(settings); DSPDisassembler disassembler(settings);
for (int i = 0; i < min_size; i++) for (int i = 0; i < min_size; i++)
{ {
if (code1[i] == code2[i]) if (code1[i] == code2[i])
count_equal++; count_equal++;
else else
{ {
std::string line1, line2; std::string line1, line2;
u16 pc = i; u16 pc = i;
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1); disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
pc = i; pc = i;
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2); 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()); 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()) if (code2.size() != code1.size())
{ {
printf("Extra code words:\n"); printf("Extra code words:\n");
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2; const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
for (int i = min_size; i < (int)longest.size(); i++) for (int i = min_size; i < (int)longest.size(); i++)
{ {
u16 pc = i; u16 pc = i;
std::string line; std::string line;
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line); disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
printf("!! %s\n", line.c_str()); printf("!! %s\n", line.c_str());
} }
} }
printf("Equal instruction words: %i / %i\n", count_equal, min_size); printf("Equal instruction words: %i / %i\n", count_equal, min_size);
return code1.size() == code2.size() && code1.size() == count_equal; return code1.size() == code2.size() && code1.size() == count_equal;
} }
void GenRandomCode(int size, std::vector<u16> &code) void GenRandomCode(int size, std::vector<u16> &code)
{ {
code.resize(size); code.resize(size);
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
code[i] = rand() ^ (rand() << 8); code[i] = rand() ^ (rand() << 8);
} }
} }
void CodeToHeader(const std::vector<u16> &code, std::string _filename, void CodeToHeader(const std::vector<u16> &code, std::string _filename,
const char *name, std::string &header) const char *name, std::string &header)
{ {
std::vector<u16> code_copy = code; std::vector<u16> code_copy = code;
// Add some nops at the end to align the size a bit. // Add some nops at the end to align the size a bit.
while (code_copy.size() & 7) while (code_copy.size() & 7)
code_copy.push_back(0); code_copy.push_back(0);
char buffer[1024]; char buffer[1024];
header.clear(); header.clear();
header.reserve(code.size() * 4); header.reserve(code.size() * 4);
header.append("#define NUM_UCODES 1\n\n"); header.append("#define NUM_UCODES 1\n\n");
std::string filename; std::string filename;
SplitPath(_filename, NULL, &filename, NULL); SplitPath(_filename, NULL, &filename, NULL);
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str())); header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
header.append("#ifndef _MSCVER\n"); header.append("#ifndef _MSCVER\n");
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n"); header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
header.append("#else\n"); header.append("#else\n");
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n"); header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
header.append("#endif\n\n"); header.append("#endif\n\n");
header.append("\t{\n\t\t"); header.append("\t{\n\t\t");
for (u32 j = 0; j < code.size(); j++) for (u32 j = 0; j < code.size(); j++)
{ {
if (j && ((j & 15) == 0)) if (j && ((j & 15) == 0))
header.append("\n\t\t"); header.append("\n\t\t");
sprintf(buffer, "0x%04x, ", code[j]); sprintf(buffer, "0x%04x, ", code[j]);
header.append(buffer); header.append(buffer);
} }
header.append("\n\t},\n"); header.append("\n\t},\n");
header.append("};\n"); header.append("};\n");
} }
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames, void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
int numCodes, const char *name, std::string &header) int numCodes, const char *name, std::string &header)
{ {
char buffer[1024]; char buffer[1024];
int reserveSize = 0; int reserveSize = 0;
for(int i = 0; i < numCodes; i++) for(int i = 0; i < numCodes; i++)
reserveSize += (int)codes[i].size(); reserveSize += (int)codes[i].size();
header.clear(); header.clear();
header.reserve(reserveSize * 4); header.reserve(reserveSize * 4);
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes); sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
header.append(buffer); header.append(buffer);
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n"); header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
for (int i = 0; i < numCodes; i++) for (int i = 0; i < numCodes; i++)
{ {
std::string filename; std::string filename;
if (! SplitPath(filenames->at(i), NULL, &filename, NULL)) if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
filename = filenames->at(i); filename = filenames->at(i);
sprintf(buffer, "\t\"%s\",\n", filename.c_str()); sprintf(buffer, "\t\"%s\",\n", filename.c_str());
header.append(buffer); header.append(buffer);
} }
header.append("};\n\n"); header.append("};\n\n");
header.append("#ifndef _MSCVER\n"); header.append("#ifndef _MSCVER\n");
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n"); header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
header.append("#else\n"); header.append("#else\n");
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n"); header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
header.append("#endif\n\n"); header.append("#endif\n\n");
for(int i = 0; i < numCodes; i++) { for(int i = 0; i < numCodes; i++) {
if(codes[i].size() == 0) if(codes[i].size() == 0)
continue; continue;
std::vector<u16> code_copy = codes[i]; std::vector<u16> code_copy = codes[i];
// Add some nops at the end to align the size a bit. // Add some nops at the end to align the size a bit.
while (code_copy.size() & 7) while (code_copy.size() & 7)
code_copy.push_back(0); code_copy.push_back(0);
header.append("\t{\n\t\t"); header.append("\t{\n\t\t");
for (u32 j = 0; j < codes[i].size(); j++) for (u32 j = 0; j < codes[i].size(); j++)
{ {
if (j && ((j & 15) == 0)) if (j && ((j & 15) == 0))
header.append("\n\t\t"); header.append("\n\t\t");
sprintf(buffer, "0x%04x, ", codes[i][j]); sprintf(buffer, "0x%04x, ", codes[i][j]);
header.append(buffer); header.append(buffer);
} }
header.append("\n\t},\n"); header.append("\n\t},\n");
} }
header.append("};\n"); header.append("};\n");
} }
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str) void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
{ {
str.resize(code.size() * 2); str.resize(code.size() * 2);
for (int i = 0; i < (int)code.size(); i++) for (int i = 0; i < (int)code.size(); i++)
{ {
str[i * 2 + 0] = code[i] >> 8; str[i * 2 + 0] = code[i] >> 8;
str[i * 2 + 1] = code[i] & 0xff; str[i * 2 + 1] = code[i] & 0xff;
} }
} }
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code) void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
{ {
code.resize(str.size() / 2); code.resize(str.size() / 2);
for (int i = 0; i < (int)code.size(); i++) for (int i = 0; i < (int)code.size(); i++)
{ {
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]); code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
} }
} }
bool LoadBinary(const char *filename, std::vector<u16> &code) bool LoadBinary(const char *filename, std::vector<u16> &code)
{ {
std::string buffer; std::string buffer;
if (!File::ReadFileToString(false, filename, buffer)) if (!File::ReadFileToString(false, filename, buffer))
return false; return false;
BinaryStringBEToCode(buffer, code); BinaryStringBEToCode(buffer, code);
return true; return true;
} }
bool SaveBinary(const std::vector<u16> &code, const char *filename) bool SaveBinary(const std::vector<u16> &code, const char *filename)
{ {
std::string buffer; std::string buffer;
CodeToBinaryStringBE(code, buffer); CodeToBinaryStringBE(code, buffer);
if (!File::WriteStringToFile(false, buffer, filename)) if (!File::WriteStringToFile(false, buffer, filename))
return false; return false;
return true; return true;
} }

View File

@ -1,43 +1,43 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DSPCODEUTIL_H #ifndef _DSPCODEUTIL_H
#define _DSPCODEUTIL_H #define _DSPCODEUTIL_H
#include <string> #include <string>
#include <vector> #include <vector>
#include "Common.h" #include "Common.h"
bool Assemble(const char *text, std::vector<u16> &code); bool Assemble(const char *text, std::vector<u16> &code);
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text); 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); bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
void GenRandomCode(int size, std::vector<u16> &code); void GenRandomCode(int size, std::vector<u16> &code);
void CodeToHeader(const std::vector<u16> &code, std::string _filename, void CodeToHeader(const std::vector<u16> &code, std::string _filename,
const char *name, std::string &header); const char *name, std::string &header);
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames, void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
int numCodes, const char *name, std::string &header); int numCodes, const char *name, std::string &header);
// Big-endian, for writing straight to file using File::WriteStringToFile. // Big-endian, for writing straight to file using File::WriteStringToFile.
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str); void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code); void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
// Load code (big endian binary). // Load code (big endian binary).
bool LoadBinary(const char *filename, std::vector<u16> &code); bool LoadBinary(const char *filename, std::vector<u16> &code);
bool SaveBinary(const std::vector<u16> &code, const char *filename); bool SaveBinary(const std::vector<u16> &code, const char *filename);
#endif // _DSPCODEUTIL_H #endif // _DSPCODEUTIL_H

View File

@ -1,256 +1,256 @@
/*==================================================================== /*====================================================================
filename: gdsp_interpreter.cpp filename: gdsp_interpreter.cpp
project: GCemu project: GCemu
created: 2004-6-18 created: 2004-6-18
mail: duddie@walla.com mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/ ====================================================================*/
#include "Common.h" #include "Common.h"
#include "Thread.h" #include "Thread.h"
#include "DSPCore.h" #include "DSPCore.h"
#include "DSPHost.h" #include "DSPHost.h"
#include "DSPAnalyzer.h" #include "DSPAnalyzer.h"
#include "MemoryUtil.h" #include "MemoryUtil.h"
#include "DSPHWInterface.h" #include "DSPHWInterface.h"
#include "DSPIntUtil.h" #include "DSPIntUtil.h"
SDSP g_dsp; SDSP g_dsp;
DSPBreakpoints dsp_breakpoints; DSPBreakpoints dsp_breakpoints;
DSPCoreState core_state = DSPCORE_RUNNING; DSPCoreState core_state = DSPCORE_RUNNING;
Common::Event step_event; Common::Event step_event;
static bool LoadRom(const char *fname, int size_in_words, u16 *rom) static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
{ {
FILE *pFile = fopen(fname, "rb"); FILE *pFile = fopen(fname, "rb");
const size_t size_in_bytes = size_in_words * sizeof(u16); const size_t size_in_bytes = size_in_words * sizeof(u16);
if (pFile) if (pFile)
{ {
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile); size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
if (read_bytes != size_in_bytes) if (read_bytes != size_in_bytes)
{ {
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes); PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
fclose(pFile); fclose(pFile);
return false; return false;
} }
fclose(pFile); fclose(pFile);
// Byteswap the rom. // Byteswap the rom.
for (int i = 0; i < DSP_IROM_SIZE; i++) for (int i = 0; i < DSP_IROM_SIZE; i++)
rom[i] = Common::swap16(rom[i]); rom[i] = Common::swap16(rom[i]);
return true; return true;
} }
// Always keep ROMs write protected. // Always keep ROMs write protected.
WriteProtectMemory(g_dsp.irom, size_in_bytes, false); WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
return false; return false;
} }
bool DSPCore_Init(const char *irom_filename, const char *coef_filename) bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
{ {
g_dsp.step_counter = 0; g_dsp.step_counter = 0;
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE); g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE); g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE); g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE); g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
// Fill roms with zeros. // Fill roms with zeros.
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE); memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
memset(g_dsp.coef, 0, DSP_COEF_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. // 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(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef); LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
for (int i = 0; i < 32; i++) for (int i = 0; i < 32; i++)
{ {
g_dsp.r[i] = 0; g_dsp.r[i] = 0;
} }
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
g_dsp.reg_stack_ptr[i] = 0; g_dsp.reg_stack_ptr[i] = 0;
for (int j = 0; j < DSP_STACK_DEPTH; j++) for (int j = 0; j < DSP_STACK_DEPTH; j++)
{ {
g_dsp.reg_stack[i][j] = 0; g_dsp.reg_stack[i][j] = 0;
} }
} }
// Fill IRAM with HALT opcodes. // Fill IRAM with HALT opcodes.
for (int i = 0; i < DSP_IRAM_SIZE; i++) for (int i = 0; i < DSP_IRAM_SIZE; i++)
{ {
g_dsp.iram[i] = 0x0021; // HALT opcode g_dsp.iram[i] = 0x0021; // HALT opcode
} }
// Just zero out DRAM. // Just zero out DRAM.
for (int i = 0; i < DSP_DRAM_SIZE; i++) for (int i = 0; i < DSP_DRAM_SIZE; i++)
{ {
g_dsp.dram[i] = 0; g_dsp.dram[i] = 0;
} }
// Copied from a real console after the custom UCode has been loaded. // Copied from a real console after the custom UCode has been loaded.
// These are the indexing wrapping registers. // These are the indexing wrapping registers.
g_dsp.r[DSP_REG_WR0] = 0xffff; g_dsp.r[DSP_REG_WR0] = 0xffff;
g_dsp.r[DSP_REG_WR1] = 0xffff; g_dsp.r[DSP_REG_WR1] = 0xffff;
g_dsp.r[DSP_REG_WR2] = 0xffff; g_dsp.r[DSP_REG_WR2] = 0xffff;
g_dsp.r[DSP_REG_WR3] = 0xffff; g_dsp.r[DSP_REG_WR3] = 0xffff;
g_dsp.cr = 0x804; g_dsp.cr = 0x804;
gdsp_ifx_init(); gdsp_ifx_init();
// Mostly keep IRAM write protected. We unprotect only when DMA-ing // Mostly keep IRAM write protected. We unprotect only when DMA-ing
// in new ucodes. // in new ucodes.
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false); WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
DSPAnalyzer::Analyze(); DSPAnalyzer::Analyze();
step_event.Init(); step_event.Init();
return true; return true;
} }
void DSPCore_Shutdown() void DSPCore_Shutdown()
{ {
step_event.Shutdown(); step_event.Shutdown();
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE); FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE); FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE); FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE); FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
} }
void DSPCore_Reset() void DSPCore_Reset()
{ {
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception"); _assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
g_dsp.pc = DSP_RESET_VECTOR; g_dsp.pc = DSP_RESET_VECTOR;
g_dsp.exception_in_progress_hack = false; g_dsp.exception_in_progress_hack = false;
g_dsp.r[DSP_REG_WR0] = 0xffff; g_dsp.r[DSP_REG_WR0] = 0xffff;
g_dsp.r[DSP_REG_WR1] = 0xffff; g_dsp.r[DSP_REG_WR1] = 0xffff;
g_dsp.r[DSP_REG_WR2] = 0xffff; g_dsp.r[DSP_REG_WR2] = 0xffff;
g_dsp.r[DSP_REG_WR3] = 0xffff; g_dsp.r[DSP_REG_WR3] = 0xffff;
} }
void DSPCore_SetException(u8 level) void DSPCore_SetException(u8 level)
{ {
g_dsp.exceptions |= 1 << level; g_dsp.exceptions |= 1 << level;
} }
void DSPCore_CheckExternalInterrupt() void DSPCore_CheckExternalInterrupt()
{ {
// check if there is an external interrupt // check if there is an external interrupt
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack) if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
{ {
#ifdef DEBUG_EXP #ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "trying External interupt fired"); NOTICE_LOG(DSPLLE, "trying External interupt fired");
#endif #endif
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE)) if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
{ {
#ifdef DEBUG_EXP #ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "External interupt fired"); NOTICE_LOG(DSPLLE, "External interupt fired");
#endif #endif
// level 7 is the interrupt exception // level 7 is the interrupt exception
DSPCore_SetException(EXP_INT); DSPCore_SetException(EXP_INT);
g_dsp.cr &= ~CR_EXTERNAL_INT; g_dsp.cr &= ~CR_EXTERNAL_INT;
} }
} }
} }
void DSPCore_CheckExceptions() void DSPCore_CheckExceptions()
{ {
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) { if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
#ifdef DEBUG_EXP #ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions); NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
#endif #endif
// check exceptions // check exceptions
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
// Seems 7 must pass or zelda dies // Seems 7 must pass or zelda dies
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) { if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
if (g_dsp.exceptions & (1 << i)) { if (g_dsp.exceptions & (1 << i)) {
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception"); _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_C, g_dsp.pc);
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]); dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
g_dsp.pc = i * 2; g_dsp.pc = i * 2;
g_dsp.exceptions &= ~(1 << i); g_dsp.exceptions &= ~(1 << i);
#ifdef DEBUG_EXP #ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "exception %d fired"); NOTICE_LOG(DSPLLE, "exception %d fired");
#endif #endif
g_dsp.exception_in_progress_hack = true; g_dsp.exception_in_progress_hack = true;
break; break;
} }
} }
} }
} }
} }
// Delegate to JIT (when it is written) or interpreter as appropriate. // Delegate to JIT (when it is written) or interpreter as appropriate.
// Handle state changes and stepping. // Handle state changes and stepping.
int DSPCore_RunCycles(int cycles) int DSPCore_RunCycles(int cycles)
{ {
while (cycles > 0) { while (cycles > 0) {
reswitch: reswitch:
switch (core_state) switch (core_state)
{ {
case DSPCORE_RUNNING: case DSPCORE_RUNNING:
#if 1 // Set to 0 to disable breakpoints, for a speed boost. #if 1 // Set to 0 to disable breakpoints, for a speed boost.
cycles = DSPInterpreter::RunCyclesDebug(cycles); cycles = DSPInterpreter::RunCyclesDebug(cycles);
#else #else
cycles = DSPInterpreter::RunCycles(cycles); cycles = DSPInterpreter::RunCycles(cycles);
#endif #endif
break; break;
case DSPCORE_STEPPING: case DSPCORE_STEPPING:
step_event.Wait(); step_event.Wait();
if (core_state != DSPCORE_STEPPING) if (core_state != DSPCORE_STEPPING)
goto reswitch; goto reswitch;
DSPInterpreter::Step(); DSPInterpreter::Step();
cycles--; cycles--;
DSPHost_UpdateDebugger(); DSPHost_UpdateDebugger();
break; break;
} }
} }
return cycles; return cycles;
} }
void DSPCore_SetState(DSPCoreState new_state) void DSPCore_SetState(DSPCoreState new_state)
{ {
core_state = new_state; core_state = new_state;
// kick the event, in case we are waiting // kick the event, in case we are waiting
if (new_state == DSPCORE_RUNNING) if (new_state == DSPCORE_RUNNING)
step_event.Set(); step_event.Set();
// Sleep(10); // Sleep(10);
DSPHost_UpdateDebugger(); DSPHost_UpdateDebugger();
} }
DSPCoreState DSPCore_GetState() DSPCoreState DSPCore_GetState()
{ {
return core_state; return core_state;
} }
void DSPCore_Step() void DSPCore_Step()
{ {
if (core_state == DSPCORE_STEPPING) if (core_state == DSPCORE_STEPPING)
step_event.Set(); step_event.Set();
} }

View File

@ -1,240 +1,240 @@
/*==================================================================== /*====================================================================
filename: DSPCore.h filename: DSPCore.h
project: GCemu project: GCemu
created: 2004-6-18 created: 2004-6-18
mail: duddie@walla.com mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/ ====================================================================*/
#ifndef _DSPCORE_H #ifndef _DSPCORE_H
#define _DSPCORE_H #define _DSPCORE_H
#include "DSPBreakpoints.h" #include "DSPBreakpoints.h"
#define DSP_IRAM_BYTE_SIZE 0x2000 #define DSP_IRAM_BYTE_SIZE 0x2000
#define DSP_IRAM_SIZE 0x1000 #define DSP_IRAM_SIZE 0x1000
#define DSP_IRAM_MASK 0x0fff #define DSP_IRAM_MASK 0x0fff
#define DSP_IROM_BYTE_SIZE 0x2000 #define DSP_IROM_BYTE_SIZE 0x2000
#define DSP_IROM_SIZE 0x1000 #define DSP_IROM_SIZE 0x1000
#define DSP_IROM_MASK 0x0fff #define DSP_IROM_MASK 0x0fff
#define DSP_DRAM_BYTE_SIZE 0x2000 #define DSP_DRAM_BYTE_SIZE 0x2000
#define DSP_DRAM_SIZE 0x1000 #define DSP_DRAM_SIZE 0x1000
#define DSP_DRAM_MASK 0x0fff #define DSP_DRAM_MASK 0x0fff
#define DSP_COEF_BYTE_SIZE 0x2000 #define DSP_COEF_BYTE_SIZE 0x2000
#define DSP_COEF_SIZE 0x1000 #define DSP_COEF_SIZE 0x1000
#define DSP_COEF_MASK 0x0fff #define DSP_COEF_MASK 0x0fff
#define DSP_RESET_VECTOR 0x8000 #define DSP_RESET_VECTOR 0x8000
#define DSP_STACK_DEPTH 0x20 #define DSP_STACK_DEPTH 0x20
#define DSP_STACK_MASK 0x1f #define DSP_STACK_MASK 0x1f
#define DSP_CR_IMEM 2 #define DSP_CR_IMEM 2
#define DSP_CR_DMEM 0 #define DSP_CR_DMEM 0
#define DSP_CR_TO_CPU 1 #define DSP_CR_TO_CPU 1
#define DSP_CR_FROM_CPU 0 #define DSP_CR_FROM_CPU 0
// Register table taken from libasnd // Register table taken from libasnd
#define DSP_REG_AR0 0x00 // address registers #define DSP_REG_AR0 0x00 // address registers
#define DSP_REG_AR1 0x01 #define DSP_REG_AR1 0x01
#define DSP_REG_AR2 0x02 #define DSP_REG_AR2 0x02
#define DSP_REG_AR3 0x03 #define DSP_REG_AR3 0x03
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments) #define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
#define DSP_REG_IX1 0x05 #define DSP_REG_IX1 0x05
#define DSP_REG_IX2 0x06 #define DSP_REG_IX2 0x06
#define DSP_REG_IX3 0x07 #define DSP_REG_IX3 0x07
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used. #define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
#define DSP_REG_WR1 0x09 #define DSP_REG_WR1 0x09
#define DSP_REG_WR2 0x0a #define DSP_REG_WR2 0x0a
#define DSP_REG_WR3 0x0b #define DSP_REG_WR3 0x0b
#define DSP_REG_ST0 0x0c // stacks. #define DSP_REG_ST0 0x0c // stacks.
#define DSP_REG_ST1 0x0d #define DSP_REG_ST1 0x0d
#define DSP_REG_ST2 0x0e #define DSP_REG_ST2 0x0e
#define DSP_REG_ST3 0x0f #define DSP_REG_ST3 0x0f
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS. #define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
#define DSP_REG_SR 0x13 #define DSP_REG_SR 0x13
#define DSP_REG_PRODL 0x14 // product. #define DSP_REG_PRODL 0x14 // product.
#define DSP_REG_PRODM 0x15 #define DSP_REG_PRODM 0x15
#define DSP_REG_PRODH 0x16 #define DSP_REG_PRODH 0x16
#define DSP_REG_PRODM2 0x17 #define DSP_REG_PRODM2 0x17
#define DSP_REG_AXL0 0x18 #define DSP_REG_AXL0 0x18
#define DSP_REG_AXL1 0x19 #define DSP_REG_AXL1 0x19
#define DSP_REG_AXH0 0x1a #define DSP_REG_AXH0 0x1a
#define DSP_REG_AXH1 0x1b #define DSP_REG_AXH1 0x1b
#define DSP_REG_ACC0 0x1c // accumulator (global) #define DSP_REG_ACC0 0x1c // accumulator (global)
#define DSP_REG_ACC1 0x1d #define DSP_REG_ACC1 0x1d
#define DSP_REG_ACL0 0x1c // Low accumulator #define DSP_REG_ACL0 0x1c // Low accumulator
#define DSP_REG_ACL1 0x1d #define DSP_REG_ACL1 0x1d
#define DSP_REG_ACM0 0x1e // Mid accumulator #define DSP_REG_ACM0 0x1e // Mid accumulator
#define DSP_REG_ACM1 0x1f #define DSP_REG_ACM1 0x1f
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0 #define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1 #define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
// Hardware registers address // Hardware registers address
#define DSP_COEF_A1_0 0xa0 #define DSP_COEF_A1_0 0xa0
#define DSP_DSMAH 0xce #define DSP_DSMAH 0xce
#define DSP_DSMAL 0xcf #define DSP_DSMAL 0xcf
#define DSP_DSCR 0xc9 // DSP DMA Control Reg #define DSP_DSCR 0xc9 // DSP DMA Control Reg
#define DSP_DSPA 0xcd // DSP DMA Block Length #define DSP_DSPA 0xcd // DSP DMA Block Length
#define DSP_DSBL 0xcb // DSP DMA DMEM Address #define DSP_DSBL 0xcb // DSP DMA DMEM Address
#define DSP_DSMAH 0xce // DSP DMA Mem Address H #define DSP_DSMAH 0xce // DSP DMA Mem Address H
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L #define DSP_DSMAL 0xcf // DSP DMA Mem Address L
#define DSP_FORMAT 0xd1 #define DSP_FORMAT 0xd1
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes #define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
#define DSP_ACSAH 0xd4 #define DSP_ACSAH 0xd4
#define DSP_ACSAL 0xd5 #define DSP_ACSAL 0xd5
#define DSP_ACEAH 0xd6 #define DSP_ACEAH 0xd6
#define DSP_ACEAL 0xd7 #define DSP_ACEAL 0xd7
#define DSP_ACCAH 0xd8 #define DSP_ACCAH 0xd8
#define DSP_ACCAL 0xd9 #define DSP_ACCAL 0xd9
#define DSP_PRED_SCALE 0xda #define DSP_PRED_SCALE 0xda
#define DSP_YN1 0xdb #define DSP_YN1 0xdb
#define DSP_YN2 0xdc #define DSP_YN2 0xdc
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX. #define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
#define DSP_GAIN 0xde #define DSP_GAIN 0xde
#define DSP_DIRQ 0xfb // DSP Irq Rest #define DSP_DIRQ 0xfb // DSP Irq Rest
#define DSP_DMBH 0xfc // DSP Mailbox H #define DSP_DMBH 0xfc // DSP Mailbox H
#define DSP_DMBL 0xfd // DSP Mailbox L #define DSP_DMBL 0xfd // DSP Mailbox L
#define DSP_CMBH 0xfe // CPU Mailbox H #define DSP_CMBH 0xfe // CPU Mailbox H
#define DSP_CMBL 0xff // CPU Mailbox L #define DSP_CMBL 0xff // CPU Mailbox L
#define DMA_TO_DSP 0 #define DMA_TO_DSP 0
#define DMA_TO_CPU 1 #define DMA_TO_CPU 1
// Stacks // Stacks
#define DSP_STACK_C 0 #define DSP_STACK_C 0
#define DSP_STACK_D 1 #define DSP_STACK_D 1
// cr (Not g_dsp.r[CR]) bits // cr (Not g_dsp.r[CR]) bits
// See HW/DSP.cpp. // See HW/DSP.cpp.
#define CR_HALT 0x0004 #define CR_HALT 0x0004
#define CR_EXTERNAL_INT 0x0002 #define CR_EXTERNAL_INT 0x0002
// SR bits // SR bits
#define SR_CARRY 0x0001 #define SR_CARRY 0x0001
#define SR_2 0x0002 // overflow??? #define SR_2 0x0002 // overflow???
#define SR_ARITH_ZERO 0x0004 #define SR_ARITH_ZERO 0x0004
#define SR_SIGN 0x0008 #define SR_SIGN 0x0008
#define SR_10 0x0010 // seem to be set by tst #define SR_10 0x0010 // seem to be set by tst
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst) #define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
#define SR_LOGIC_ZERO 0x0040 #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_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_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_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_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. #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. // This should be the bits affected by CMP. Does not include logic zero.
#define SR_CMP_MASK 0x3f #define SR_CMP_MASK 0x3f
// exceptions vector // exceptions vector
#define EXP_RESET 0 // 0x0000 #define EXP_RESET 0 // 0x0000
#define EXP_STOVF 1 // 0x0002 stack under/over flow #define EXP_STOVF 1 // 0x0002 stack under/over flow
#define EXP_4 2 // 0x0004 #define EXP_4 2 // 0x0004
#define EXP_6 3 // 0x0006 #define EXP_6 3 // 0x0006
#define EXP_8 4 // 0x0008 #define EXP_8 4 // 0x0008
#define EXP_ACCOV 5 // 0x000a accelerator address overflow #define EXP_ACCOV 5 // 0x000a accelerator address overflow
#define EXP_c 6 // 0x000c #define EXP_c 6 // 0x000c
#define EXP_INT 7 // 0x000e external int? (mail?) #define EXP_INT 7 // 0x000e external int? (mail?)
struct SDSP struct SDSP
{ {
u16 r[32]; u16 r[32];
u16 pc; u16 pc;
#if PROFILE #if PROFILE
u16 err_pc; u16 err_pc;
#endif #endif
// This is NOT the same cr as r[DSP_REG_CR]. // This is NOT the same cr as r[DSP_REG_CR].
// This register is shared with the main emulation, see DSP.cpp // This register is shared with the main emulation, see DSP.cpp
// The plugin has control over 0x0C07 of this reg. // The plugin has control over 0x0C07 of this reg.
// Bits are defined in a struct in DSP.cpp. // Bits are defined in a struct in DSP.cpp.
u16 cr; u16 cr;
u8 reg_stack_ptr[4]; u8 reg_stack_ptr[4];
u8 exceptions; // pending exceptions? u8 exceptions; // pending exceptions?
bool exception_in_progress_hack; // is this the same as "exception enabled"? 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 // 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 // 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. // overflows since on the DSP, when the stack overflows, you're screwed.
u16 reg_stack[4][DSP_STACK_DEPTH]; u16 reg_stack[4][DSP_STACK_DEPTH];
// For debugging. // For debugging.
u32 iram_crc; u32 iram_crc;
u64 step_counter; u64 step_counter;
// When state saving, all of the above can just be memcpy'd into the save state. // When state saving, all of the above can just be memcpy'd into the save state.
// The below needs special handling. // The below needs special handling.
u16 *iram; u16 *iram;
u16 *dram; u16 *dram;
u16 *irom; u16 *irom;
u16 *coef; u16 *coef;
// This one doesn't really belong here. // This one doesn't really belong here.
u8 *cpu_ram; u8 *cpu_ram;
}; };
extern SDSP g_dsp; extern SDSP g_dsp;
extern DSPBreakpoints dsp_breakpoints; extern DSPBreakpoints dsp_breakpoints;
bool DSPCore_Init(const char *irom_filename, const char *coef_filename); bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
void DSPCore_Reset(); void DSPCore_Reset();
void DSPCore_Shutdown(); // Frees all allocated memory. void DSPCore_Shutdown(); // Frees all allocated memory.
void DSPCore_CheckExternalInterrupt(); void DSPCore_CheckExternalInterrupt();
void DSPCore_CheckExceptions(); void DSPCore_CheckExceptions();
// sets a flag in the pending exception register. // sets a flag in the pending exception register.
void DSPCore_SetException(u8 level); void DSPCore_SetException(u8 level);
enum DSPCoreState enum DSPCoreState
{ {
DSPCORE_RUNNING = 0, DSPCORE_RUNNING = 0,
DSPCORE_STEPPING = 1, DSPCORE_STEPPING = 1,
}; };
int DSPCore_RunCycles(int cycles); int DSPCore_RunCycles(int cycles);
// These are meant to be called from the UI thread. // These are meant to be called from the UI thread.
void DSPCore_SetState(DSPCoreState new_state); void DSPCore_SetState(DSPCoreState new_state);
DSPCoreState DSPCore_GetState(); DSPCoreState DSPCore_GetState();
void DSPCore_Step(); void DSPCore_Step();
#endif // _DSPCORE_H #endif // _DSPCORE_H

View File

@ -1,35 +1,35 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DSPHOST_H #ifndef _DSPHOST_H
#define _DSPHOST_H #define _DSPHOST_H
// The user of the DSPCore library must supply a few functions so that the // 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 // 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 // core isn't used, for example in an asm/disasm tool, then most of these
// can be stubbed out. // can be stubbed out.
#define DEBUG_EXP 1 #define DEBUG_EXP 1
u8 DSPHost_ReadHostMemory(u32 addr); u8 DSPHost_ReadHostMemory(u32 addr);
void DSPHost_WriteHostMemory(u8 value, u32 addr); void DSPHost_WriteHostMemory(u8 value, u32 addr);
bool DSPHost_OnThread(); bool DSPHost_OnThread();
bool DSPHost_Running(); bool DSPHost_Running();
void DSPHost_InterruptRequest(); void DSPHost_InterruptRequest();
u32 DSPHost_CodeLoaded(const u8 *ptr, int size); u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
void DSPHost_UpdateDebugger(); void DSPHost_UpdateDebugger();
#endif #endif

View File

@ -1,140 +1,140 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004 // Additional copyrights go to Duddie and Tratax (c) 2004
// HELPER FUNCTIONS // HELPER FUNCTIONS
#include "DSPIntCCUtil.h" #include "DSPIntCCUtil.h"
#include "DSPCore.h" #include "DSPCore.h"
#include "DSPInterpreter.h" #include "DSPInterpreter.h"
namespace DSPInterpreter { namespace DSPInterpreter {
void Update_SR_Register64(s64 _Value) void Update_SR_Register64(s64 _Value)
{ {
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK; g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
if (_Value < 0) if (_Value < 0)
{ {
g_dsp.r[DSP_REG_SR] |= SR_SIGN; g_dsp.r[DSP_REG_SR] |= SR_SIGN;
} }
if (_Value == 0) if (_Value == 0)
{ {
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO; g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
} }
// weird // weird
if ((_Value >> 62) == 0) if ((_Value >> 62) == 0)
{ {
g_dsp.r[DSP_REG_SR] |= 0x20; g_dsp.r[DSP_REG_SR] |= 0x20;
} }
} }
void Update_SR_Register16(s16 _Value) void Update_SR_Register16(s16 _Value)
{ {
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK; g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
if (_Value < 0) if (_Value < 0)
{ {
g_dsp.r[DSP_REG_SR] |= SR_SIGN; g_dsp.r[DSP_REG_SR] |= SR_SIGN;
} }
if (_Value == 0) if (_Value == 0)
{ {
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO; g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
} }
// weird // weird
if ((_Value >> 14) == 0) if ((_Value >> 14) == 0)
{ {
g_dsp.r[DSP_REG_SR] |= 0x20; g_dsp.r[DSP_REG_SR] |= 0x20;
} }
} }
void Update_SR_LZ(s64 value) { void Update_SR_LZ(s64 value) {
if (value == 0) if (value == 0)
{ {
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO; g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
} }
else else
{ {
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO; g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
} }
} }
int GetMultiplyModifier() int GetMultiplyModifier()
{ {
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY) if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
return 1; return 1;
else else
return 2; return 2;
} }
inline bool isCarry() { inline bool isCarry() {
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false; return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
} }
inline bool isSign() { inline bool isSign() {
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN)); return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
} }
inline bool isZero() { inline bool isZero() {
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false; return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
} }
//see gdsp_registers.h for flags //see gdsp_registers.h for flags
bool CheckCondition(u8 _Condition) bool CheckCondition(u8 _Condition)
{ {
switch (_Condition & 0xf) switch (_Condition & 0xf)
{ {
case 0x0: //NS - NOT SIGN case 0x0: //NS - NOT SIGN
return !isSign(); return !isSign();
case 0x1: // S - SIGN case 0x1: // S - SIGN
return isSign(); return isSign();
case 0x2: // G - GREATER case 0x2: // G - GREATER
return !isSign() && !isZero(); return !isSign() && !isZero();
case 0x3: // LE - LESS EQUAL case 0x3: // LE - LESS EQUAL
return isSign() || isZero(); return isSign() || isZero();
case 0x4: // NZ - NOT ZERO case 0x4: // NZ - NOT ZERO
return !isZero(); return !isZero();
case 0x5: // Z - ZERO case 0x5: // Z - ZERO
return isZero(); return isZero();
case 0x6: // L - LESS case 0x6: // L - LESS
// Should be that once we set 0x01 // Should be that once we set 0x01
return !isCarry(); return !isCarry();
// if (isSign()) // if (isSign())
case 0x7: // GE - GREATER EQUAL case 0x7: // GE - GREATER EQUAL
// Should be that once we set 0x01 // Should be that once we set 0x01
return isCarry(); return isCarry();
// if (! isSign() || isZero()) // if (! isSign() || isZero())
case 0xc: // LNZ - LOGIC NOT ZERO case 0xc: // LNZ - LOGIC NOT ZERO
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO); return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
case 0xd: // LZ - LOGIC ZERO case 0xd: // LZ - LOGIC ZERO
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0; return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
case 0xf: // Empty - always true. case 0xf: // Empty - always true.
return true; return true;
default: default:
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf); ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
return false; return false;
} }
} }
} // namespace } // namespace

View File

@ -1,39 +1,39 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004 // Additional copyrights go to Duddie and Tratax (c) 2004
#ifndef _GDSP_CONDITION_CODES_H #ifndef _GDSP_CONDITION_CODES_H
#define _GDSP_CONDITION_CODES_H #define _GDSP_CONDITION_CODES_H
// Anything to do with SR and conditions goes here. // Anything to do with SR and conditions goes here.
#include "Common.h" #include "Common.h"
namespace DSPInterpreter { namespace DSPInterpreter {
bool CheckCondition(u8 _Condition); bool CheckCondition(u8 _Condition);
int GetMultiplyModifier(); int GetMultiplyModifier();
void Update_SR_Register16(s16 _Value); void Update_SR_Register16(s16 _Value);
void Update_SR_Register64(s64 _Value); void Update_SR_Register64(s64 _Value);
void Update_SR_LZ(s64 value); void Update_SR_LZ(s64 value);
} // namespace } // namespace
#endif // _GDSP_CONDITION_CODES_H #endif // _GDSP_CONDITION_CODES_H

View File

@ -1,171 +1,171 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DSPINTERPRETER_H #ifndef _DSPINTERPRETER_H
#define _DSPINTERPRETER_H #define _DSPINTERPRETER_H
#include "DSPTables.h" #include "DSPTables.h"
#define DSP_REG_MASK 0x1f #define DSP_REG_MASK 0x1f
namespace DSPInterpreter { namespace DSPInterpreter {
void Step(); void Step();
void Run(); void Run();
// If these simply return the same number of cycles as was passed into them, // If these simply return the same number of cycles as was passed into them,
// chances are that the DSP is halted. // chances are that the DSP is halted.
// The difference between them is that the debug one obeys breakpoints. // The difference between them is that the debug one obeys breakpoints.
int RunCycles(int cycles); int RunCycles(int cycles);
int RunCyclesDebug(int cycles); int RunCyclesDebug(int cycles);
void Stop(); void Stop();
void WriteCR(u16 val); void WriteCR(u16 val);
u16 ReadCR(); u16 ReadCR();
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc); typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
// All the opcode functions. // All the opcode functions.
void unknown(const UDSPInstruction& opc); void unknown(const UDSPInstruction& opc);
void call(const UDSPInstruction& opc); void call(const UDSPInstruction& opc);
void callr(const UDSPInstruction& opc); void callr(const UDSPInstruction& opc);
void ifcc(const UDSPInstruction& opc); void ifcc(const UDSPInstruction& opc);
void jcc(const UDSPInstruction& opc); void jcc(const UDSPInstruction& opc);
void jmprcc(const UDSPInstruction& opc); void jmprcc(const UDSPInstruction& opc);
void ret(const UDSPInstruction& opc); void ret(const UDSPInstruction& opc);
void halt(const UDSPInstruction& opc); void halt(const UDSPInstruction& opc);
void loop(const UDSPInstruction& opc); void loop(const UDSPInstruction& opc);
void loopi(const UDSPInstruction& opc); void loopi(const UDSPInstruction& opc);
void bloop(const UDSPInstruction& opc); void bloop(const UDSPInstruction& opc);
void bloopi(const UDSPInstruction& opc); void bloopi(const UDSPInstruction& opc);
void mrr(const UDSPInstruction& opc); void mrr(const UDSPInstruction& opc);
void lrr(const UDSPInstruction& opc); void lrr(const UDSPInstruction& opc);
void lrrd(const UDSPInstruction& opc); void lrrd(const UDSPInstruction& opc);
void lrri(const UDSPInstruction& opc); void lrri(const UDSPInstruction& opc);
void lrrn(const UDSPInstruction& opc); void lrrn(const UDSPInstruction& opc);
void srr(const UDSPInstruction& opc); void srr(const UDSPInstruction& opc);
void srrd(const UDSPInstruction& opc); void srrd(const UDSPInstruction& opc);
void srri(const UDSPInstruction& opc); void srri(const UDSPInstruction& opc);
void srrn(const UDSPInstruction& opc); void srrn(const UDSPInstruction& opc);
void lri(const UDSPInstruction& opc); void lri(const UDSPInstruction& opc);
void lris(const UDSPInstruction& opc); void lris(const UDSPInstruction& opc);
void lr(const UDSPInstruction& opc); void lr(const UDSPInstruction& opc);
void sr(const UDSPInstruction& opc); void sr(const UDSPInstruction& opc);
void si(const UDSPInstruction& opc); void si(const UDSPInstruction& opc);
void tstaxh(const UDSPInstruction& opc); void tstaxh(const UDSPInstruction& opc);
void clr(const UDSPInstruction& opc); void clr(const UDSPInstruction& opc);
void clrl(const UDSPInstruction& opc); void clrl(const UDSPInstruction& opc);
void clrp(const UDSPInstruction& opc); void clrp(const UDSPInstruction& opc);
void mulc(const UDSPInstruction& opc); void mulc(const UDSPInstruction& opc);
void cmpar(const UDSPInstruction& opc); void cmpar(const UDSPInstruction& opc);
void cmp(const UDSPInstruction& opc); void cmp(const UDSPInstruction& opc);
void tst(const UDSPInstruction& opc); void tst(const UDSPInstruction& opc);
void addaxl(const UDSPInstruction& opc); void addaxl(const UDSPInstruction& opc);
void addarn(const UDSPInstruction& opc); void addarn(const UDSPInstruction& opc);
void mulcac(const UDSPInstruction& opc); void mulcac(const UDSPInstruction& opc);
void movr(const UDSPInstruction& opc); void movr(const UDSPInstruction& opc);
void movax(const UDSPInstruction& opc); void movax(const UDSPInstruction& opc);
void xorr(const UDSPInstruction& opc); void xorr(const UDSPInstruction& opc);
void andr(const UDSPInstruction& opc); void andr(const UDSPInstruction& opc);
void andc(const UDSPInstruction& opc); void andc(const UDSPInstruction& opc);
void orr(const UDSPInstruction& opc); void orr(const UDSPInstruction& opc);
void orc(const UDSPInstruction& opc); void orc(const UDSPInstruction& opc);
void orf(const UDSPInstruction& opc); void orf(const UDSPInstruction& opc);
void add(const UDSPInstruction& opc); void add(const UDSPInstruction& opc);
void addp(const UDSPInstruction& opc); void addp(const UDSPInstruction& opc);
void cmpis(const UDSPInstruction& opc); void cmpis(const UDSPInstruction& opc);
void addpaxz(const UDSPInstruction& opc); void addpaxz(const UDSPInstruction& opc);
void movpz(const UDSPInstruction& opc); void movpz(const UDSPInstruction& opc);
void decm(const UDSPInstruction& opc); void decm(const UDSPInstruction& opc);
void dec(const UDSPInstruction& opc); void dec(const UDSPInstruction& opc);
void inc(const UDSPInstruction& opc); void inc(const UDSPInstruction& opc);
void incm(const UDSPInstruction& opc); void incm(const UDSPInstruction& opc);
void neg(const UDSPInstruction& opc); void neg(const UDSPInstruction& opc);
void addax(const UDSPInstruction& opc); void addax(const UDSPInstruction& opc);
void addr(const UDSPInstruction& opc); void addr(const UDSPInstruction& opc);
void subr(const UDSPInstruction& opc); void subr(const UDSPInstruction& opc);
void subp(const UDSPInstruction& opc); void subp(const UDSPInstruction& opc);
void subax(const UDSPInstruction& opc); void subax(const UDSPInstruction& opc);
void addis(const UDSPInstruction& opc); void addis(const UDSPInstruction& opc);
void addi(const UDSPInstruction& opc); void addi(const UDSPInstruction& opc);
void lsl16(const UDSPInstruction& opc); void lsl16(const UDSPInstruction& opc);
void madd(const UDSPInstruction& opc); void madd(const UDSPInstruction& opc);
void msub(const UDSPInstruction& opc); void msub(const UDSPInstruction& opc);
void lsr16(const UDSPInstruction& opc); void lsr16(const UDSPInstruction& opc);
void asr16(const UDSPInstruction& opc); void asr16(const UDSPInstruction& opc);
void lsl(const UDSPInstruction& opc); void lsl(const UDSPInstruction& opc);
void lsr(const UDSPInstruction& opc); void lsr(const UDSPInstruction& opc);
void asl(const UDSPInstruction& opc); void asl(const UDSPInstruction& opc);
void asr(const UDSPInstruction& opc); void asr(const UDSPInstruction& opc);
void lsrn(const UDSPInstruction& opc); void lsrn(const UDSPInstruction& opc);
void asrn(const UDSPInstruction& opc); void asrn(const UDSPInstruction& opc);
void dar(const UDSPInstruction& opc); void dar(const UDSPInstruction& opc);
void iar(const UDSPInstruction& opc); void iar(const UDSPInstruction& opc);
void sbclr(const UDSPInstruction& opc); void sbclr(const UDSPInstruction& opc);
void sbset(const UDSPInstruction& opc); void sbset(const UDSPInstruction& opc);
void mov(const UDSPInstruction& opc); void mov(const UDSPInstruction& opc);
void movp(const UDSPInstruction& opc); void movp(const UDSPInstruction& opc);
void mul(const UDSPInstruction& opc); void mul(const UDSPInstruction& opc);
void mulac(const UDSPInstruction& opc); void mulac(const UDSPInstruction& opc);
void mulmv(const UDSPInstruction& opc); void mulmv(const UDSPInstruction& opc);
void mulmvz(const UDSPInstruction& opc); void mulmvz(const UDSPInstruction& opc);
void mulx(const UDSPInstruction& opc); void mulx(const UDSPInstruction& opc);
void mulxac(const UDSPInstruction& opc); void mulxac(const UDSPInstruction& opc);
void mulxmv(const UDSPInstruction& opc); void mulxmv(const UDSPInstruction& opc);
void mulxmvz(const UDSPInstruction& opc); void mulxmvz(const UDSPInstruction& opc);
void mulcmvz(const UDSPInstruction& opc); void mulcmvz(const UDSPInstruction& opc);
void mulcmv(const UDSPInstruction& opc); void mulcmv(const UDSPInstruction& opc);
void movnp(const UDSPInstruction& opc); void movnp(const UDSPInstruction& opc);
void sub(const UDSPInstruction& opc); void sub(const UDSPInstruction& opc);
void maddx(const UDSPInstruction& opc); void maddx(const UDSPInstruction& opc);
void msubx(const UDSPInstruction& opc); void msubx(const UDSPInstruction& opc);
void maddc(const UDSPInstruction& opc); void maddc(const UDSPInstruction& opc);
void msubc(const UDSPInstruction& opc); void msubc(const UDSPInstruction& opc);
void srs(const UDSPInstruction& opc); void srs(const UDSPInstruction& opc);
void lrs(const UDSPInstruction& opc); void lrs(const UDSPInstruction& opc);
void nx(const UDSPInstruction& opc); void nx(const UDSPInstruction& opc);
void cmpi(const UDSPInstruction& opc); void cmpi(const UDSPInstruction& opc);
void rti(const UDSPInstruction& opc); void rti(const UDSPInstruction& opc);
void ilrr(const UDSPInstruction& opc); void ilrr(const UDSPInstruction& opc);
void ilrrd(const UDSPInstruction& opc); void ilrrd(const UDSPInstruction& opc);
void ilrri(const UDSPInstruction& opc); void ilrri(const UDSPInstruction& opc);
void ilrrn(const UDSPInstruction& opc); void ilrrn(const UDSPInstruction& opc);
void andcf(const UDSPInstruction& opc); void andcf(const UDSPInstruction& opc);
void andf(const UDSPInstruction& opc); void andf(const UDSPInstruction& opc);
void xori(const UDSPInstruction& opc); void xori(const UDSPInstruction& opc);
void andi(const UDSPInstruction& opc); void andi(const UDSPInstruction& opc);
void ori(const UDSPInstruction& opc); void ori(const UDSPInstruction& opc);
// FIXME inside // FIXME inside
void srbith(const UDSPInstruction& opc); void srbith(const UDSPInstruction& opc);
// END OF FIXMEs // END OF FIXMEs
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED // TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
void tstaxl(const UDSPInstruction& opc); void tstaxl(const UDSPInstruction& opc);
// The mysterious a100 // The mysterious a100
// END OF UNIMPLEMENTED // END OF UNIMPLEMENTED
// Helpers // Helpers
inline void tsta(int reg); inline void tsta(int reg);
} // namespace } // namespace
#endif // _DSPINTERPRETER_H #endif // _DSPINTERPRETER_H

View File

@ -1,22 +1,22 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DSPJit.h" #include "DSPJit.h"
namespace DSPJit { namespace DSPJit {
}; };

View File

@ -1,28 +1,28 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DSPJIT_H #ifndef _DSPJIT_H
#define _DSPJIT_H #define _DSPJIT_H
namespace DSPJit { namespace DSPJit {
// TODO(XK): Fill // TODO(XK): Fill
} // namespace } // namespace
#endif // _DSPJIT_H #endif // _DSPJIT_H

File diff suppressed because it is too large Load Diff

View File

@ -1,168 +1,168 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com) // Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
#ifndef _DSPTABLES_H #ifndef _DSPTABLES_H
#define _DSPTABLES_H #define _DSPTABLES_H
#include "Common.h" #include "Common.h"
// The non-ADDR ones that end with _D are the opposite one - if the bit specify // The non-ADDR ones that end with _D are the opposite one - if the bit specify
// ACC0, then ACC_D will be ACC1. // ACC0, then ACC_D will be ACC1.
// The values of these are very important. // The values of these are very important.
// For the reg ones, the value >> 8 is the base register. // For the reg ones, the value >> 8 is the base register.
// & 0x80 means it's a "D". // & 0x80 means it's a "D".
enum partype_t enum partype_t
{ {
P_NONE = 0x0000, P_NONE = 0x0000,
P_VAL = 0x0001, P_VAL = 0x0001,
P_IMM = 0x0002, P_IMM = 0x0002,
P_MEM = 0x0003, P_MEM = 0x0003,
P_STR = 0x0004, P_STR = 0x0004,
P_ADDR_I = 0x0005, P_ADDR_I = 0x0005,
P_ADDR_D = 0x0006, P_ADDR_D = 0x0006,
P_REG = 0x8000, P_REG = 0x8000,
P_REG04 = P_REG | 0x0400, // IX P_REG04 = P_REG | 0x0400, // IX
P_REG08 = P_REG | 0x0800, P_REG08 = P_REG | 0x0800,
P_REG18 = P_REG | 0x1800, P_REG18 = P_REG | 0x1800,
P_REGM18 = P_REG | 0x1810, // used in multiply instructions P_REGM18 = P_REG | 0x1810, // used in multiply instructions
P_REG19 = P_REG | 0x1900, P_REG19 = P_REG | 0x1900,
P_REGM19 = P_REG | 0x1910, // used in multiply instructions P_REGM19 = P_REG | 0x1910, // used in multiply instructions
P_REG1A = P_REG | 0x1a80, P_REG1A = P_REG | 0x1a80,
P_REG1C = P_REG | 0x1c00, P_REG1C = P_REG | 0x1c00,
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value) // P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
P_ACC_D = P_REG | 0x1c80, P_ACC_D = P_REG | 0x1c80,
P_ACCL = P_REG | 0x1c00, // used for low part of accum P_ACCL = P_REG | 0x1c00, // used for low part of accum
P_ACCM = P_REG | 0x1e00, // used for mid part of accum P_ACCM = P_REG | 0x1e00, // used for mid part of accum
// The following are not in gcdsptool // The following are not in gcdsptool
P_ACCM_D = P_REG | 0x1e80, P_ACCM_D = P_REG | 0x1e80,
P_ACC = P_REG | 0x2000, // used for full accum. P_ACC = P_REG | 0x2000, // used for full accum.
P_AX = P_REG | 0x2200, P_AX = P_REG | 0x2200,
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80 P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
P_REF = P_REG | 0x4000, P_REF = P_REG | 0x4000,
P_PRG = P_REF | P_REG, P_PRG = P_REF | P_REG,
// The following seem like junk: // The following seem like junk:
// P_REG10 = P_REG | 0x1000, // P_REG10 = P_REG | 0x1000,
// P_AX_D = P_REG | 0x2280, // P_AX_D = P_REG | 0x2280,
}; };
#define P_EXT 0x80 #define P_EXT 0x80
#define OPTABLE_SIZE 65536 #define OPTABLE_SIZE 65536
union UDSPInstruction union UDSPInstruction
{ {
u16 hex; u16 hex;
UDSPInstruction(u16 _hex) { hex = _hex; } UDSPInstruction(u16 _hex) { hex = _hex; }
UDSPInstruction() { hex = 0; } UDSPInstruction() { hex = 0; }
struct struct
{ {
signed shift : 6; signed shift : 6;
unsigned negating : 1; unsigned negating : 1;
unsigned arithmetic : 1; unsigned arithmetic : 1;
unsigned areg : 1; unsigned areg : 1;
unsigned op : 7; unsigned op : 7;
}; };
struct struct
{ {
unsigned ushift : 6; unsigned ushift : 6;
}; };
// TODO: Figure out more instruction structures (add structs here) // TODO: Figure out more instruction structures (add structs here)
}; };
typedef void (*dspInstFunc)(const UDSPInstruction&); typedef void (*dspInstFunc)(const UDSPInstruction&);
struct param2_t struct param2_t
{ {
partype_t type; partype_t type;
u8 size; u8 size;
u8 loc; u8 loc;
s8 lshift; s8 lshift;
u16 mask; u16 mask;
}; };
typedef struct typedef struct
{ {
const char *name; const char *name;
u16 opcode; u16 opcode;
u16 opcode_mask; u16 opcode_mask;
dspInstFunc interpFunc; dspInstFunc interpFunc;
dspInstFunc jitFunc; dspInstFunc jitFunc;
u8 size; u8 size;
u8 param_count; u8 param_count;
param2_t params[8]; param2_t params[8];
dspInstFunc prologue; dspInstFunc prologue;
dspInstFunc epilogue; dspInstFunc epilogue;
} DSPOPCTemplate; } DSPOPCTemplate;
typedef DSPOPCTemplate opc_t; typedef DSPOPCTemplate opc_t;
// Opcodes // Opcodes
extern const DSPOPCTemplate opcodes[]; extern const DSPOPCTemplate opcodes[];
extern const int opcodes_size; extern const int opcodes_size;
extern const DSPOPCTemplate opcodes_ext[]; extern const DSPOPCTemplate opcodes_ext[];
extern const int opcodes_ext_size; extern const int opcodes_ext_size;
extern u8 opSize[OPTABLE_SIZE]; extern u8 opSize[OPTABLE_SIZE];
extern const DSPOPCTemplate cw; extern const DSPOPCTemplate cw;
extern dspInstFunc opTable[]; extern dspInstFunc opTable[];
extern dspInstFunc prologueTable[OPTABLE_SIZE]; extern dspInstFunc prologueTable[OPTABLE_SIZE];
extern dspInstFunc epilogueTable[OPTABLE_SIZE]; extern dspInstFunc epilogueTable[OPTABLE_SIZE];
// Predefined labels // Predefined labels
struct pdlabel_t struct pdlabel_t
{ {
u16 addr; u16 addr;
const char* name; const char* name;
const char* description; const char* description;
}; };
extern const pdlabel_t regnames[]; extern const pdlabel_t regnames[];
extern const pdlabel_t pdlabels[]; extern const pdlabel_t pdlabels[];
extern const u32 pdlabels_size; extern const u32 pdlabels_size;
const char *pdname(u16 val); const char *pdname(u16 val);
const char *pdregname(int val); const char *pdregname(int val);
const char *pdregnamelong(int val); const char *pdregnamelong(int val);
void InitInstructionTable(); void InitInstructionTable();
inline void ExecuteInstruction(const UDSPInstruction& inst) inline void ExecuteInstruction(const UDSPInstruction& inst)
{ {
// TODO: Move the prologuetable calls into the relevant instructions themselves. // TODO: Move the prologuetable calls into the relevant instructions themselves.
// Better not do things like this until things work correctly though. // Better not do things like this until things work correctly though.
if (prologueTable[inst.hex]) if (prologueTable[inst.hex])
prologueTable[inst.hex](inst); prologueTable[inst.hex](inst);
opTable[inst.hex](inst); opTable[inst.hex](inst);
if (epilogueTable[inst.hex]) if (epilogueTable[inst.hex])
epilogueTable[inst.hex](inst); epilogueTable[inst.hex](inst);
} }
// This one's pretty slow, try to use it only at init or seldomly. // This one's pretty slow, try to use it only at init or seldomly.
// returns NULL if no matching instruction. // returns NULL if no matching instruction.
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst); const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
#endif // _DSPTABLES_H #endif // _DSPTABLES_H

File diff suppressed because it is too large Load Diff

View File

@ -1,249 +1,249 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004 // Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h" #include "DSPInterpreter.h"
#include "DSPCore.h" #include "DSPCore.h"
#include "DSPMemoryMap.h" #include "DSPMemoryMap.h"
#include "DSPStacks.h" #include "DSPStacks.h"
#include "DSPIntCCUtil.h" #include "DSPIntCCUtil.h"
#include "DSPIntUtil.h" #include "DSPIntUtil.h"
namespace DSPInterpreter { namespace DSPInterpreter {
// Generic call implementation // Generic call implementation
// CALLcc addressA // CALLcc addressA
// 0000 0010 1011 cccc // 0000 0010 1011 cccc
// aaaa aaaa aaaa aaaa // aaaa aaaa aaaa aaaa
// Call function if condition cc has been met. Push program counter of // Call function if condition cc has been met. Push program counter of
// instruction following "call" to $st0. Set program counter to address // instruction following "call" to $st0. Set program counter to address
// represented by value that follows this "call" instruction. // represented by value that follows this "call" instruction.
void call(const UDSPInstruction& opc) void call(const UDSPInstruction& opc)
{ {
// must be outside the if. // must be outside the if.
u16 dest = dsp_fetch_code(); u16 dest = dsp_fetch_code();
if (CheckCondition(opc.hex & 0xf)) if (CheckCondition(opc.hex & 0xf))
{ {
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc); dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
g_dsp.pc = dest; g_dsp.pc = dest;
} }
} }
// Generic callr implementation // Generic callr implementation
// CALLRcc $R // CALLRcc $R
// 0001 0111 rrr1 cccc // 0001 0111 rrr1 cccc
// Call function if condition cc has been met. Push program counter of // Call function if condition cc has been met. Push program counter of
// instruction following "call" to call stack $st0. Set program counter to // instruction following "call" to call stack $st0. Set program counter to
// register $R. // register $R.
void callr(const UDSPInstruction& opc) void callr(const UDSPInstruction& opc)
{ {
if (CheckCondition(opc.hex & 0xf)) if (CheckCondition(opc.hex & 0xf))
{ {
u8 reg = (opc.hex >> 5) & 0x7; u8 reg = (opc.hex >> 5) & 0x7;
u16 addr = dsp_op_read_reg(reg); u16 addr = dsp_op_read_reg(reg);
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc); dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
g_dsp.pc = addr; g_dsp.pc = addr;
} }
} }
// Generic if implementation // Generic if implementation
// IFcc // IFcc
// 0000 0010 0111 cccc // 0000 0010 0111 cccc
// Execute following opcode if the condition has been met. // Execute following opcode if the condition has been met.
void ifcc(const UDSPInstruction& opc) void ifcc(const UDSPInstruction& opc)
{ {
if (!CheckCondition(opc.hex & 0xf)) if (!CheckCondition(opc.hex & 0xf))
{ {
// skip the next opcode - we have to lookup its size. // skip the next opcode - we have to lookup its size.
g_dsp.pc += opSize[dsp_peek_code()]; g_dsp.pc += opSize[dsp_peek_code()];
} }
} }
// Generic jmp implementation // Generic jmp implementation
// Jcc addressA // Jcc addressA
// 0000 0010 1001 cccc // 0000 0010 1001 cccc
// aaaa aaaa aaaa aaaa // aaaa aaaa aaaa aaaa
// Jump to addressA if condition cc has been met. Set program counter to // Jump to addressA if condition cc has been met. Set program counter to
// address represented by value that follows this "jmp" instruction. // address represented by value that follows this "jmp" instruction.
void jcc(const UDSPInstruction& opc) void jcc(const UDSPInstruction& opc)
{ {
u16 dest = dsp_fetch_code(); u16 dest = dsp_fetch_code();
if (CheckCondition(opc.hex & 0xf)) if (CheckCondition(opc.hex & 0xf))
{ {
g_dsp.pc = dest; g_dsp.pc = dest;
} }
} }
// Generic jmpr implementation // Generic jmpr implementation
// JMPcc $R // JMPcc $R
// 0001 0111 rrr0 cccc // 0001 0111 rrr0 cccc
// Jump to address; set program counter to a value from register $R. // Jump to address; set program counter to a value from register $R.
void jmprcc(const UDSPInstruction& opc) void jmprcc(const UDSPInstruction& opc)
{ {
if (CheckCondition(opc.hex & 0xf)) if (CheckCondition(opc.hex & 0xf))
{ {
u8 reg = (opc.hex >> 5) & 0x7; u8 reg = (opc.hex >> 5) & 0x7;
g_dsp.pc = dsp_op_read_reg(reg); g_dsp.pc = dsp_op_read_reg(reg);
} }
} }
// Generic ret implementation // Generic ret implementation
// RETcc // RETcc
// 0000 0010 1101 cccc // 0000 0010 1101 cccc
// Return from subroutine if condition cc has been met. Pops stored PC // Return from subroutine if condition cc has been met. Pops stored PC
// from call stack $st0 and sets $pc to this location. // from call stack $st0 and sets $pc to this location.
void ret(const UDSPInstruction& opc) void ret(const UDSPInstruction& opc)
{ {
if (CheckCondition(opc.hex & 0xf)) if (CheckCondition(opc.hex & 0xf))
{ {
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C); g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
} }
} }
// RTI // RTI
// 0000 0010 1111 1111 // 0000 0010 1111 1111
// Return from exception. Pops stored status register $sr from data stack // 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 // $st1 and program counter PC from call stack $st0 and sets $pc to this
// location. // location.
void rti(const UDSPInstruction& opc) void rti(const UDSPInstruction& opc)
{ {
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D); 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.pc = dsp_reg_load_stack(DSP_STACK_C);
g_dsp.exception_in_progress_hack = false; g_dsp.exception_in_progress_hack = false;
} }
// HALT // HALT
// 0000 0000 0020 0001 // 0000 0000 0020 0001
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR. // Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
void halt(const UDSPInstruction& opc) void halt(const UDSPInstruction& opc)
{ {
g_dsp.cr |= 0x4; g_dsp.cr |= 0x4;
g_dsp.pc--; g_dsp.pc--;
} }
// LOOP handling: Loop stack is used to control execution of repeated blocks of // 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 // 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 // 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 // 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 // callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
// continues at next opcode. // continues at next opcode.
// LOOP $R // LOOP $R
// 0000 0000 010r rrrr // 0000 0000 010r rrrr
// Repeatedly execute following opcode until counter specified by value // Repeatedly execute following opcode until counter specified by value
// from register $R reaches zero. Each execution decrement counter. Register // 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 // $R remains unchanged. If register $R is set to zero at the beginning of loop
// then looped instruction will not get executed. // then looped instruction will not get executed.
// Actually, this instruction simply prepares the loop stacks for the above. // Actually, this instruction simply prepares the loop stacks for the above.
// The looping hardware takes care of the rest. // The looping hardware takes care of the rest.
void loop(const UDSPInstruction& opc) void loop(const UDSPInstruction& opc)
{ {
u16 reg = opc.hex & 0x1f; u16 reg = opc.hex & 0x1f;
u16 cnt = g_dsp.r[reg]; u16 cnt = g_dsp.r[reg];
u16 loop_pc = g_dsp.pc; u16 loop_pc = g_dsp.pc;
if (cnt) if (cnt)
{ {
dsp_reg_store_stack(0, g_dsp.pc); dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc); dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt); dsp_reg_store_stack(3, cnt);
} }
} }
// LOOPI #I // LOOPI #I
// 0001 0000 iiii iiii // 0001 0000 iiii iiii
// Repeatedly execute following opcode until counter specified by // Repeatedly execute following opcode until counter specified by
// immediate value I reaches zero. Each execution decrement counter. If // immediate value I reaches zero. Each execution decrement counter. If
// immediate value I is set to zero at the beginning of loop then looped // immediate value I is set to zero at the beginning of loop then looped
// instruction will not get executed. // instruction will not get executed.
// Actually, this instruction simply prepares the loop stacks for the above. // Actually, this instruction simply prepares the loop stacks for the above.
// The looping hardware takes care of the rest. // The looping hardware takes care of the rest.
void loopi(const UDSPInstruction& opc) void loopi(const UDSPInstruction& opc)
{ {
u16 cnt = opc.hex & 0xff; u16 cnt = opc.hex & 0xff;
u16 loop_pc = g_dsp.pc; u16 loop_pc = g_dsp.pc;
if (cnt) if (cnt)
{ {
dsp_reg_store_stack(0, g_dsp.pc); dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc); dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt); dsp_reg_store_stack(3, cnt);
} }
} }
// BLOOP $R, addrA // BLOOP $R, addrA
// 0000 0000 011r rrrr // 0000 0000 011r rrrr
// aaaa aaaa aaaa aaaa // aaaa aaaa aaaa aaaa
// Repeatedly execute block of code starting at following opcode until // Repeatedly execute block of code starting at following opcode until
// counter specified by value from register $R reaches zero. Block ends at // counter specified by value from register $R reaches zero. Block ends at
// specified address addrA inclusive, ie. opcode at addrA is the last opcode // 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 // 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. // is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
// Up to 4 nested loops is allowed. // Up to 4 nested loops is allowed.
void bloop(const UDSPInstruction& opc) void bloop(const UDSPInstruction& opc)
{ {
u16 reg = opc.hex & 0x1f; u16 reg = opc.hex & 0x1f;
u16 cnt = g_dsp.r[reg]; u16 cnt = g_dsp.r[reg];
u16 loop_pc = dsp_fetch_code(); u16 loop_pc = dsp_fetch_code();
if (cnt) if (cnt)
{ {
dsp_reg_store_stack(0, g_dsp.pc); dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc); dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt); dsp_reg_store_stack(3, cnt);
} }
else else
{ {
g_dsp.pc = loop_pc; g_dsp.pc = loop_pc;
g_dsp.pc += opSize[dsp_peek_code()]; g_dsp.pc += opSize[dsp_peek_code()];
} }
} }
// BLOOPI #I, addrA // BLOOPI #I, addrA
// 0001 0001 iiii iiii // 0001 0001 iiii iiii
// aaaa aaaa aaaa aaaa // aaaa aaaa aaaa aaaa
// Repeatedly execute block of code starting at following opcode until // Repeatedly execute block of code starting at following opcode until
// counter specified by immediate value I reaches zero. Block ends at specified // 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 // 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 // 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 // on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
// nested loops is allowed. // nested loops is allowed.
void bloopi(const UDSPInstruction& opc) void bloopi(const UDSPInstruction& opc)
{ {
u16 cnt = opc.hex & 0xff; u16 cnt = opc.hex & 0xff;
u16 loop_pc = dsp_fetch_code(); u16 loop_pc = dsp_fetch_code();
if (cnt) if (cnt)
{ {
dsp_reg_store_stack(0, g_dsp.pc); dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc); dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt); dsp_reg_store_stack(3, cnt);
} }
else else
{ {
g_dsp.pc = loop_pc; g_dsp.pc = loop_pc;
g_dsp.pc += opSize[dsp_peek_code()]; g_dsp.pc += opSize[dsp_peek_code()];
} }
} }
} // namespace } // namespace

View File

@ -1,266 +1,266 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004 // Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h" #include "DSPInterpreter.h"
#include "DSPMemoryMap.h" #include "DSPMemoryMap.h"
#include "DSPIntUtil.h" #include "DSPIntUtil.h"
namespace DSPInterpreter { namespace DSPInterpreter {
// SRS @M, $(0x18+S) // SRS @M, $(0x18+S)
// 0010 1sss mmmm mmmm // 0010 1sss mmmm mmmm
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M. // 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 // 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. // lower 8 bits are from the 8-bit immediate.
// Note: pc+=2 in duddie's doc seems wrong // Note: pc+=2 in duddie's doc seems wrong
void srs(const UDSPInstruction& opc) void srs(const UDSPInstruction& opc)
{ {
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18; u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF); u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
dsp_dmem_write(addr, g_dsp.r[reg]); dsp_dmem_write(addr, g_dsp.r[reg]);
} }
// LRS $(0x18+D), @M // LRS $(0x18+D), @M
// 0010 0ddd mmmm mmmm // 0010 0ddd mmmm mmmm
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D). // 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 // 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. // lower 8 bits are from the 8-bit immediate.
void lrs(const UDSPInstruction& opc) void lrs(const UDSPInstruction& opc)
{ {
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18; u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF); u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
g_dsp.r[reg] = dsp_dmem_read(addr); g_dsp.r[reg] = dsp_dmem_read(addr);
} }
// LR $D, @M // LR $D, @M
// 0000 0000 110d dddd // 0000 0000 110d dddd
// mmmm mmmm mmmm mmmm // mmmm mmmm mmmm mmmm
// Move value from data memory pointed by address M to register $D. // Move value from data memory pointed by address M to register $D.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
void lr(const UDSPInstruction& opc) void lr(const UDSPInstruction& opc)
{ {
u8 reg = opc.hex & DSP_REG_MASK; u8 reg = opc.hex & DSP_REG_MASK;
u16 addr = dsp_fetch_code(); u16 addr = dsp_fetch_code();
u16 val = dsp_dmem_read(addr); u16 val = dsp_dmem_read(addr);
dsp_op_write_reg(reg, val); dsp_op_write_reg(reg, val);
dsp_conditional_extend_accum(reg); dsp_conditional_extend_accum(reg);
} }
// SR @M, $S // SR @M, $S
// 0000 0000 111s ssss // 0000 0000 111s ssss
// mmmm mmmm mmmm mmmm // mmmm mmmm mmmm mmmm
// Store value from register $S to a memory pointed by address M. // Store value from register $S to a memory pointed by address M.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
void sr(const UDSPInstruction& opc) void sr(const UDSPInstruction& opc)
{ {
u8 reg = opc.hex & DSP_REG_MASK; u8 reg = opc.hex & DSP_REG_MASK;
u16 addr = dsp_fetch_code(); u16 addr = dsp_fetch_code();
u16 val = dsp_op_read_reg(reg); u16 val = dsp_op_read_reg(reg);
dsp_dmem_write(addr, val); dsp_dmem_write(addr, val);
} }
// SI @M, #I // SI @M, #I
// 0001 0110 mmmm mmmm // 0001 0110 mmmm mmmm
// iiii iiii iiii iiii // iiii iiii iiii iiii
// Store 16-bit immediate value I to a memory location pointed by address // Store 16-bit immediate value I to a memory location pointed by address
// M (M is 8-bit value sign extended). // M (M is 8-bit value sign extended).
void si(const UDSPInstruction& opc) void si(const UDSPInstruction& opc)
{ {
u16 addr = (s8)opc.hex; u16 addr = (s8)opc.hex;
u16 imm = dsp_fetch_code(); u16 imm = dsp_fetch_code();
dsp_dmem_write(addr, imm); dsp_dmem_write(addr, imm);
} }
// LRR $D, @$S // LRR $D, @$S
// 0001 1000 0ssd dddd // 0001 1000 0ssd dddd
// Move value from data memory pointed by addressing register $S to register $D. // Move value from data memory pointed by addressing register $S to register $D.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
void lrr(const UDSPInstruction& opc) void lrr(const UDSPInstruction& opc)
{ {
u8 sreg = (opc.hex >> 5) & 0x3; u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f; u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]); u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val); dsp_op_write_reg(dreg, val);
} }
// LRRD $D, @$S // LRRD $D, @$S
// 0001 1000 1ssd dddd // 0001 1000 1ssd dddd
// Move value from data memory pointed by addressing register $S toregister $D. // Move value from data memory pointed by addressing register $S toregister $D.
// Decrement register $S. // Decrement register $S.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
void lrrd(const UDSPInstruction& opc) void lrrd(const UDSPInstruction& opc)
{ {
u8 sreg = (opc.hex >> 5) & 0x3; u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f; u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]); u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val); dsp_op_write_reg(dreg, val);
dsp_decrement_addr_reg(sreg); dsp_decrement_addr_reg(sreg);
} }
// LRRI $D, @$S // LRRI $D, @$S
// 0001 1001 0ssd dddd // 0001 1001 0ssd dddd
// Move value from data memory pointed by addressing register $S to register $D. // Move value from data memory pointed by addressing register $S to register $D.
// Increment register $S. // Increment register $S.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
void lrri(const UDSPInstruction& opc) void lrri(const UDSPInstruction& opc)
{ {
u8 sreg = (opc.hex >> 5) & 0x3; u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f; u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]); u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val); dsp_op_write_reg(dreg, val);
dsp_increment_addr_reg(sreg); dsp_increment_addr_reg(sreg);
} }
// LRRN $D, @$S // LRRN $D, @$S
// 0001 1001 1ssd dddd // 0001 1001 1ssd dddd
// Move value from data memory pointed by addressing register $S to register $D. // Move value from data memory pointed by addressing register $S to register $D.
// Add indexing register $(0x4+S) to register $S. // Add indexing register $(0x4+S) to register $S.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
void lrrn(const UDSPInstruction& opc) void lrrn(const UDSPInstruction& opc)
{ {
u8 sreg = (opc.hex >> 5) & 0x3; u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f; u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]); u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val); dsp_op_write_reg(dreg, val);
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg]; // g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]); dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
} }
// SRR @$D, $S // SRR @$D, $S
// 0001 1010 0dds ssss // 0001 1010 0dds ssss
// Store value from source register $S to a memory location pointed by // Store value from source register $S to a memory location pointed by
// addressing register $D. // addressing register $D.
// FIXME: Perform additional operation depending on source register. // FIXME: Perform additional operation depending on source register.
void srr(const UDSPInstruction& opc) void srr(const UDSPInstruction& opc)
{ {
u8 dreg = (opc.hex >> 5) & 0x3; u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f; u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg); u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val); dsp_dmem_write(g_dsp.r[dreg], val);
} }
// SRRD @$D, $S // SRRD @$D, $S
// 0001 1010 1dds ssss // 0001 1010 1dds ssss
// Store value from source register $S to a memory location pointed by // Store value from source register $S to a memory location pointed by
// addressing register $D. Decrement register $D. // addressing register $D. Decrement register $D.
// FIXME: Perform additional operation depending on source register. // FIXME: Perform additional operation depending on source register.
void srrd(const UDSPInstruction& opc) void srrd(const UDSPInstruction& opc)
{ {
u8 dreg = (opc.hex >> 5) & 0x3; u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f; u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg); u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val); dsp_dmem_write(g_dsp.r[dreg], val);
dsp_decrement_addr_reg(dreg); dsp_decrement_addr_reg(dreg);
} }
// SRRI @$D, $S // SRRI @$D, $S
// 0001 1011 0dds ssss // 0001 1011 0dds ssss
// Store value from source register $S to a memory location pointed by // Store value from source register $S to a memory location pointed by
// addressing register $D. Increment register $D. // addressing register $D. Increment register $D.
// FIXME: Perform additional operation depending on source register. // FIXME: Perform additional operation depending on source register.
void srri(const UDSPInstruction& opc) void srri(const UDSPInstruction& opc)
{ {
u8 dreg = (opc.hex >> 5) & 0x3; u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f; u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg); u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val); dsp_dmem_write(g_dsp.r[dreg], val);
dsp_increment_addr_reg(dreg); dsp_increment_addr_reg(dreg);
} }
// SRRN @$D, $S // SRRN @$D, $S
// 0001 1011 1dds ssss // 0001 1011 1dds ssss
// Store value from source register $S to a memory location pointed by // Store value from source register $S to a memory location pointed by
// addressing register $D. Add DSP_REG_IX0 register to register $D. // addressing register $D. Add DSP_REG_IX0 register to register $D.
// FIXME: Perform additional operation depending on source register. // FIXME: Perform additional operation depending on source register.
void srrn(const UDSPInstruction& opc) void srrn(const UDSPInstruction& opc)
{ {
u8 dreg = (opc.hex >> 5) & 0x3; u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f; u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg); u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val); dsp_dmem_write(g_dsp.r[dreg], val);
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg]; // g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]); dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
} }
// ILRR $acD.m, @$arS // ILRR $acD.m, @$arS
// 0000 001d 0001 00ss // 0000 001d 0001 00ss
// Move value from instruction memory pointed by addressing register // Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. // $arS to mid accumulator register $acD.m.
void ilrr(const UDSPInstruction& opc) void ilrr(const UDSPInstruction& opc)
{ {
u16 reg = opc.hex & 0x3; u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1); u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]); g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
} }
// ILRRD $acD.m, @$arS // ILRRD $acD.m, @$arS
// 0000 001d 0001 01ss // 0000 001d 0001 01ss
// Move value from instruction memory pointed by addressing register // Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS. // $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
void ilrrd(const UDSPInstruction& opc) void ilrrd(const UDSPInstruction& opc)
{ {
u16 reg = opc.hex & 0x3; u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1); u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]); g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
dsp_decrement_addr_reg(reg); dsp_decrement_addr_reg(reg);
} }
// ILRRI $acD.m, @$S // ILRRI $acD.m, @$S
// 0000 001d 0001 10ss // 0000 001d 0001 10ss
// Move value from instruction memory pointed by addressing register // Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Increment addressing register $arS. // $arS to mid accumulator register $acD.m. Increment addressing register $arS.
void ilrri(const UDSPInstruction& opc) void ilrri(const UDSPInstruction& opc)
{ {
u16 reg = opc.hex & 0x3; u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1); u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]); g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
dsp_increment_addr_reg(reg); dsp_increment_addr_reg(reg);
} }
// ILRRN $acD.m, @$arS // ILRRN $acD.m, @$arS
// 0000 001d 0001 11ss // 0000 001d 0001 11ss
// Move value from instruction memory pointed by addressing register // Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Add corresponding indexing // $arS to mid accumulator register $acD.m. Add corresponding indexing
// register $ixS to addressing register $arS. // register $ixS to addressing register $arS.
void ilrrn(const UDSPInstruction& opc) void ilrrn(const UDSPInstruction& opc)
{ {
u16 reg = opc.hex & 0x3; u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1); u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]); g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + 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]); dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
} }
} // namespace } // namespace

View File

@ -1,202 +1,202 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004 // Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h" #include "DSPInterpreter.h"
#include "DSPCore.h" #include "DSPCore.h"
#include "DSPIntUtil.h" #include "DSPIntUtil.h"
namespace DSPInterpreter { namespace DSPInterpreter {
void unknown(const UDSPInstruction& opc) void unknown(const UDSPInstruction& opc)
{ {
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception"); //_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); ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
} }
// MRR $D, $S // MRR $D, $S
// 0001 11dd ddds ssss // 0001 11dd ddds ssss
// Move value from register $S to register $D. // Move value from register $S to register $D.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
void mrr(const UDSPInstruction& opc) void mrr(const UDSPInstruction& opc)
{ {
u8 sreg = opc.hex & 0x1f; u8 sreg = opc.hex & 0x1f;
u8 dreg = (opc.hex >> 5) & 0x1f; u8 dreg = (opc.hex >> 5) & 0x1f;
u16 val = dsp_op_read_reg(sreg); u16 val = dsp_op_read_reg(sreg);
dsp_op_write_reg(dreg, val); dsp_op_write_reg(dreg, val);
} }
// LRI $D, #I // LRI $D, #I
// 0000 0000 100d dddd // 0000 0000 100d dddd
// iiii iiii iiii iiii // iiii iiii iiii iiii
// Load immediate value I to register $D. // Load immediate value I to register $D.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
// DSPSpy discovery: This, and possibly other instructions that load a 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 // 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. // to the whole accumulator! This does not happen in S16 mode.
void lri(const UDSPInstruction& opc) void lri(const UDSPInstruction& opc)
{ {
u8 reg = opc.hex & DSP_REG_MASK; u8 reg = opc.hex & DSP_REG_MASK;
u16 imm = dsp_fetch_code(); u16 imm = dsp_fetch_code();
dsp_op_write_reg(reg, imm); dsp_op_write_reg(reg, imm);
dsp_conditional_extend_accum(reg); dsp_conditional_extend_accum(reg);
} }
// LRIS $(0x18+D), #I // LRIS $(0x18+D), #I
// 0000 1ddd iiii iiii // 0000 1ddd iiii iiii
// Load immediate value I (8-bit sign extended) to accumulator register. // Load immediate value I (8-bit sign extended) to accumulator register.
// FIXME: Perform additional operation depending on destination register. // FIXME: Perform additional operation depending on destination register.
void lris(const UDSPInstruction& opc) void lris(const UDSPInstruction& opc)
{ {
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0; u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
u16 imm = (s8)opc.hex; u16 imm = (s8)opc.hex;
dsp_op_write_reg(reg, imm); dsp_op_write_reg(reg, imm);
dsp_conditional_extend_accum(reg); dsp_conditional_extend_accum(reg);
} }
// TSTAXL $acR // TSTAXL $acR
// 1000 r001 xxxx xxxx // 1000 r001 xxxx xxxx
// r specifies one of the main accumulators. // r specifies one of the main accumulators.
// Definitely not a test instruction - it changes the accums. // Definitely not a test instruction - it changes the accums.
// Not affected by m0/m2. Not affected by s16/s40. // Not affected by m0/m2. Not affected by s16/s40.
void tstaxl(const UDSPInstruction& opc) void tstaxl(const UDSPInstruction& opc)
{ {
// This is probably all wrong. // This is probably all wrong.
//u8 reg = (opc.hex >> 8) & 0x1; //u8 reg = (opc.hex >> 8) & 0x1;
//s16 val = dsp_get_ax_l(reg); //s16 val = dsp_get_ax_l(reg);
//Update_SR_Register16(val); //Update_SR_Register16(val);
} }
// ADDARN $arD, $ixS // ADDARN $arD, $ixS
// 0000 0000 0001 ssdd // 0000 0000 0001 ssdd
// Adds indexing register $ixS to an addressing register $arD. // Adds indexing register $ixS to an addressing register $arD.
void addarn(const UDSPInstruction& opc) void addarn(const UDSPInstruction& opc)
{ {
u8 dreg = opc.hex & 0x3; u8 dreg = opc.hex & 0x3;
u8 sreg = (opc.hex >> 2) & 0x3; u8 sreg = (opc.hex >> 2) & 0x3;
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg]; // 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]); 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. // It is critical for the Zelda ucode that this one wraps correctly.
} }
// NX // NX
// 1000 -000 xxxx xxxx // 1000 -000 xxxx xxxx
// No operation, but can be extended with extended opcode. // No operation, but can be extended with extended opcode.
void nx(const UDSPInstruction& opc) void nx(const UDSPInstruction& opc)
{ {
// This opcode is supposed to do nothing - it's used if you want to use // 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. // an opcode extension but not do anything. At least according to duddie.
} }
//------------------------------------------------------------- //-------------------------------------------------------------
// DAR $arD ? // DAR $arD ?
// 0000 0000 0000 01dd // 0000 0000 0000 01dd
// Decrement address register $arD. // Decrement address register $arD.
void dar(const UDSPInstruction& opc) void dar(const UDSPInstruction& opc)
{ {
dsp_decrement_addr_reg(opc.hex & 0x3); dsp_decrement_addr_reg(opc.hex & 0x3);
} }
// IAR $arD ? // IAR $arD ?
// 0000 0000 0000 10dd // 0000 0000 0000 10dd
// Increment address register $arD. // Increment address register $arD.
void iar(const UDSPInstruction& opc) void iar(const UDSPInstruction& opc)
{ {
dsp_increment_addr_reg(opc.hex & 0x3); dsp_increment_addr_reg(opc.hex & 0x3);
} }
// SBCLR #I // SBCLR #I
// 0001 0011 0000 0iii // 0001 0011 0000 0iii
// bit of status register $sr. Bit number is calculated by adding 6 to // bit of status register $sr. Bit number is calculated by adding 6 to
// immediate value I. // immediate value I.
void sbclr(const UDSPInstruction& opc) void sbclr(const UDSPInstruction& opc)
{ {
u8 bit = (opc.hex & 0xff) + 6; u8 bit = (opc.hex & 0xff) + 6;
g_dsp.r[DSP_REG_SR] &= ~(1 << bit); g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
} }
// SBSET #I // SBSET #I
// 0001 0010 0000 0iii // 0001 0010 0000 0iii
// Set bit of status register $sr. Bit number is calculated by adding 6 to // Set bit of status register $sr. Bit number is calculated by adding 6 to
// immediate value I. // immediate value I.
void sbset(const UDSPInstruction& opc) void sbset(const UDSPInstruction& opc)
{ {
u8 bit = (opc.hex & 0xff) + 6; u8 bit = (opc.hex & 0xff) + 6;
g_dsp.r[DSP_REG_SR] |= (1 << bit); g_dsp.r[DSP_REG_SR] |= (1 << bit);
} }
// FIXME inside // FIXME inside
// This is a bunch of flag setters, flipping bits in SR. So far so good, // 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. // but it's harder to know exactly what effect they have.
// M0/M2 change the multiplier mode (it can multiply by 2 for free). // M0/M2 change the multiplier mode (it can multiply by 2 for free).
// //
// SET16 changes something very important: see the LRI instruction above. // SET16 changes something very important: see the LRI instruction above.
// Hermes' demo sets the following defaults: // Hermes' demo sets the following defaults:
// SET40 // SET40
// CLR15 // CLR15
// M0 // M0
void srbith(const UDSPInstruction& opc) void srbith(const UDSPInstruction& opc)
{ {
switch ((opc.hex >> 8) & 0xf) switch ((opc.hex >> 8) & 0xf)
{ {
// M0 seems to be the default. M2 is used in functions in Zelda // 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 // and then reset with M0 at the end. Like the other bits here, it's
// done around loops with lots of multiplications. // done around loops with lots of multiplications.
// I've confirmed with DSPSpy that they flip this bit. // I've confirmed with DSPSpy that they flip this bit.
case 0xa: // M2 case 0xa: // M2
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY; g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
break; break;
case 0xb: // M0 case 0xb: // M0
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY; g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
break; break;
// If set, treat multiplicands as unsigned. // If set, treat multiplicands as unsigned.
// If clear, treat them as signed. // If clear, treat them as signed.
case 0xc: // CLR15 case 0xc: // CLR15
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED; g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
break; break;
case 0xd: // SET15 case 0xd: // SET15
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED; g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
break; break;
// Automatic 40-bit sign extension when loading ACx.M. // Automatic 40-bit sign extension when loading ACx.M.
// 40 seems to be the default. // 40 seems to be the default.
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting. // Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
case 0xe: // SET16 (really, clear SR's 0x4000) case 0xe: // SET16 (really, clear SR's 0x4000)
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT; g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
break; break;
case 0xf: // SET40 (really, set SR's 0x4000) case 0xf: // SET40 (really, set SR's 0x4000)
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT; g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
break; break;
default: default:
break; break;
} }
} }
} // namespace } // namespace

File diff suppressed because it is too large Load Diff

View File

@ -1,85 +1,85 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "LabelMap.h" #include "LabelMap.h"
#include "DSPTables.h" #include "DSPTables.h"
LabelMap::LabelMap() LabelMap::LabelMap()
{ {
} }
void LabelMap::RegisterDefaults() void LabelMap::RegisterDefaults()
{ {
for (int i = 0; i < 0x24; i++) for (int i = 0; i < 0x24; i++)
{ {
if (regnames[i].name) if (regnames[i].name)
RegisterLabel(regnames[i].name, regnames[i].addr); RegisterLabel(regnames[i].name, regnames[i].addr);
} }
for (int i = 0; i < (int)pdlabels_size; i++) for (int i = 0; i < (int)pdlabels_size; i++)
{ {
if (pdlabels[i].name) if (pdlabels[i].name)
RegisterLabel(pdlabels[i].name, pdlabels[i].addr); RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
} }
} }
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type) void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
{ {
u16 old_value; u16 old_value;
if (GetLabelValue(label, &old_value) && old_value != lval) if (GetLabelValue(label, &old_value) && old_value != lval)
{ {
printf("WARNING: Redefined label %s to %04x - old value %04x\n", printf("WARNING: Redefined label %s to %04x - old value %04x\n",
label.c_str(), lval, old_value); label.c_str(), lval, old_value);
DeleteLabel(label); DeleteLabel(label);
} }
labels.push_back(label_t(label, lval, type)); labels.push_back(label_t(label, lval, type));
} }
void LabelMap::DeleteLabel(const std::string &label) void LabelMap::DeleteLabel(const std::string &label)
{ {
for (std::vector<label_t>::iterator iter = labels.begin(); for (std::vector<label_t>::iterator iter = labels.begin();
iter != labels.end(); ++iter) iter != labels.end(); ++iter)
{ {
if (!label.compare(iter->name)) if (!label.compare(iter->name))
{ {
labels.erase(iter); labels.erase(iter);
return; return;
} }
} }
} }
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
{ {
for (u32 i = 0; i < labels.size(); i++) for (u32 i = 0; i < labels.size(); i++)
{ {
if (!label.compare(labels[i].name)) if (!label.compare(labels[i].name))
{ {
if (type & labels[i].type) { if (type & labels[i].type) {
*value = labels[i].addr; *value = labels[i].addr;
return true; return true;
} else { } else {
printf("WARNING: Wrong label type requested. %s\n", label.c_str()); printf("WARNING: Wrong label type requested. %s\n", label.c_str());
} }
} }
} }
return false; return false;
} }
void LabelMap::Clear() void LabelMap::Clear()
{ {
labels.clear(); labels.clear();
} }

View File

@ -1,55 +1,55 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _LABELMAP_H #ifndef _LABELMAP_H
#define _LABELMAP_H #define _LABELMAP_H
#include <string> #include <string>
#include <vector> #include <vector>
#include "Common.h" #include "Common.h"
enum LabelType enum LabelType
{ {
LABEL_IADDR = 1, // Jump addresses, etc LABEL_IADDR = 1, // Jump addresses, etc
LABEL_DADDR = 2, // Data addresses, etc LABEL_DADDR = 2, // Data addresses, etc
LABEL_VALUE = 4, LABEL_VALUE = 4,
LABEL_ANY = 0xFF, LABEL_ANY = 0xFF,
}; };
class LabelMap class LabelMap
{ {
struct label_t struct label_t
{ {
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {} label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
std::string name; std::string name;
s32 addr; s32 addr;
LabelType type; LabelType type;
}; };
std::vector<label_t> labels; std::vector<label_t> labels;
public: public:
LabelMap(); LabelMap();
~LabelMap() { } ~LabelMap() { }
void RegisterDefaults(); void RegisterDefaults();
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE); void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
void DeleteLabel(const std::string &label); void DeleteLabel(const std::string &label);
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const; bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
void Clear(); void Clear();
}; };
#endif // _LABELMAP_H #endif // _LABELMAP_H

File diff suppressed because it is too large Load Diff

View File

@ -1,139 +1,139 @@
/*==================================================================== /*====================================================================
project: GameCube DSP Tool (gcdsp) project: GameCube DSP Tool (gcdsp)
created: 2005.03.04 created: 2005.03.04
mail: duddie@walla.com mail: duddie@walla.com
Copyright (c) 2005 Duddie Copyright (c) 2005 Duddie
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2 as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version. of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/ ====================================================================*/
#ifndef _DSP_ASSEMBLE_H #ifndef _DSP_ASSEMBLE_H
#define _DSP_ASSEMBLE_H #define _DSP_ASSEMBLE_H
#include <string> #include <string>
#include <map> #include <map>
#include "Common.h" #include "Common.h"
#include "disassemble.h" #include "disassemble.h"
#include "DSPTables.h" #include "DSPTables.h"
#include "LabelMap.h" #include "LabelMap.h"
enum err_t enum err_t
{ {
ERR_OK = 0, ERR_OK = 0,
ERR_UNKNOWN, ERR_UNKNOWN,
ERR_UNKNOWN_OPCODE, ERR_UNKNOWN_OPCODE,
ERR_NOT_ENOUGH_PARAMETERS, ERR_NOT_ENOUGH_PARAMETERS,
ERR_TOO_MANY_PARAMETERS, ERR_TOO_MANY_PARAMETERS,
ERR_WRONG_PARAMETER, ERR_WRONG_PARAMETER,
ERR_EXPECTED_PARAM_STR, ERR_EXPECTED_PARAM_STR,
ERR_EXPECTED_PARAM_VAL, ERR_EXPECTED_PARAM_VAL,
ERR_EXPECTED_PARAM_REG, ERR_EXPECTED_PARAM_REG,
ERR_EXPECTED_PARAM_MEM, ERR_EXPECTED_PARAM_MEM,
ERR_EXPECTED_PARAM_IMM, ERR_EXPECTED_PARAM_IMM,
ERR_INCORRECT_BIN, ERR_INCORRECT_BIN,
ERR_INCORRECT_HEX, ERR_INCORRECT_HEX,
ERR_INCORRECT_DEC, ERR_INCORRECT_DEC,
ERR_LABEL_EXISTS, ERR_LABEL_EXISTS,
ERR_UNKNOWN_LABEL, ERR_UNKNOWN_LABEL,
ERR_NO_MATCHING_BRACKETS, ERR_NO_MATCHING_BRACKETS,
ERR_EXT_CANT_EXTEND_OPCODE, ERR_EXT_CANT_EXTEND_OPCODE,
ERR_EXT_PAR_NOT_EXT, ERR_EXT_PAR_NOT_EXT,
ERR_WRONG_PARAMETER_ACC, ERR_WRONG_PARAMETER_ACC,
ERR_WRONG_PARAMETER_MID_ACC, ERR_WRONG_PARAMETER_MID_ACC,
ERR_INVALID_REGISTER, ERR_INVALID_REGISTER,
ERR_OUT_RANGE_NUMBER ERR_OUT_RANGE_NUMBER
}; };
// Unless you want labels to carry over between files, you probably // Unless you want labels to carry over between files, you probably
// want to create a new DSPAssembler for every file you assemble. // want to create a new DSPAssembler for every file you assemble.
class DSPAssembler class DSPAssembler
{ {
public: public:
DSPAssembler(const AssemblerSettings &settings); DSPAssembler(const AssemblerSettings &settings);
~DSPAssembler(); ~DSPAssembler();
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints, // 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. // 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. // 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); bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
std::string GetErrorString() const { return last_error_str; } std::string GetErrorString() const { return last_error_str; }
err_t GetError() const { return last_error; } err_t GetError() const { return last_error; }
private: private:
struct param_t struct param_t
{ {
u32 val; u32 val;
partype_t type; partype_t type;
char *str; char *str;
}; };
enum segment_t enum segment_t
{ {
SEGMENT_CODE = 0, SEGMENT_CODE = 0,
SEGMENT_DATA, SEGMENT_DATA,
SEGMENT_OVERLAY, SEGMENT_OVERLAY,
SEGMENT_MAX SEGMENT_MAX
}; };
// Utility functions // Utility functions
s32 ParseValue(const char *str); s32 ParseValue(const char *str);
u32 ParseExpression(const char *ptr); u32 ParseExpression(const char *ptr);
u32 GetParams(char *parstr, param_t *par); u32 GetParams(char *parstr, param_t *par);
void InitPass(int pass); void InitPass(int pass);
bool AssembleFile(const char *fname, int pass); bool AssembleFile(const char *fname, int pass);
void ShowError(err_t err_code, const char *extra_info = NULL); void ShowError(err_t err_code, const char *extra_info = NULL);
// void ShowWarning(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); char *FindBrackets(char *src, char *dst);
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size); 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); 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); void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
char *gdg_buffer; char *gdg_buffer;
std::string include_dir; std::string include_dir;
std::string cur_line; std::string cur_line;
u32 m_cur_addr; u32 m_cur_addr;
int m_totalSize; int m_totalSize;
u8 m_cur_pass; u8 m_cur_pass;
LabelMap labels; LabelMap labels;
u32 code_line; u32 code_line;
bool failed; bool failed;
std::string last_error_str; std::string last_error_str;
err_t last_error; err_t last_error;
typedef std::map<std::string, std::string> AliasMap; typedef std::map<std::string, std::string> AliasMap;
AliasMap aliases; AliasMap aliases;
segment_t cur_segment; segment_t cur_segment;
u32 segment_addr[SEGMENT_MAX]; u32 segment_addr[SEGMENT_MAX];
int m_current_param; int m_current_param;
const AssemblerSettings settings_; const AssemblerSettings settings_;
}; };
#endif // _DSP_ASSEMBLE_H #endif // _DSP_ASSEMBLE_H

View File

@ -1,23 +1,23 @@
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DebuggerUIUtil.h" #include "DebuggerUIUtil.h"
// The default font // The default font
wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace")); wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));

View File

@ -1,36 +1,36 @@
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DEBUGGER_UI_UTIL_H #ifndef _DEBUGGER_UI_UTIL_H
#define _DEBUGGER_UI_UTIL_H #define _DEBUGGER_UI_UTIL_H
#include <wx/wx.h> #include <wx/wx.h>
#define wxUSE_XPM_IN_MSW 1 #define wxUSE_XPM_IN_MSW 1
#define USE_XPM_BITMAPS 1 #define USE_XPM_BITMAPS 1
// Defined in CodeWindow.cpp // Defined in CodeWindow.cpp
extern wxFont DebuggerFont; extern wxFont DebuggerFont;
// define this to use XPMs everywhere (by default, BMPs are used under Win) // 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 // BMPs use less space, but aren't compiled into the executable on other platforms
#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW #if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
#error You need to enable XPM support to use XPM bitmaps with toolbar! #error You need to enable XPM support to use XPM bitmaps with toolbar!
#endif // USE_XPM_BITMAPS #endif // USE_XPM_BITMAPS
#endif #endif

View File

@ -1,100 +1,100 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _NAND_CONTENT_LOADER_H #ifndef _NAND_CONTENT_LOADER_H
#define _NAND_CONTENT_LOADER_H #define _NAND_CONTENT_LOADER_H
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include "Common.h" #include "Common.h"
#include "Blob.h" #include "Blob.h"
#include "Volume.h" #include "Volume.h"
namespace DiscIO namespace DiscIO
{ {
struct SNANDContent struct SNANDContent
{ {
u32 m_ContentID; u32 m_ContentID;
u16 m_Index; u16 m_Index;
u16 m_Type; u16 m_Type;
u32 m_Size; u32 m_Size;
u8 m_SHA1Hash[20]; u8 m_SHA1Hash[20];
u8 m_Header[36]; //all of the above u8 m_Header[36]; //all of the above
u8* m_pData; u8* m_pData;
}; };
// pure virtual interface so just the NANDContentManager can create these files only // pure virtual interface so just the NANDContentManager can create these files only
class INANDContentLoader class INANDContentLoader
{ {
public: public:
INANDContentLoader() {} INANDContentLoader() {}
virtual ~INANDContentLoader() {} virtual ~INANDContentLoader() {}
virtual bool IsValid() const = 0; virtual bool IsValid() const = 0;
virtual u64 GetTitleID() const = 0; virtual u64 GetTitleID() const = 0;
virtual u16 GetIosVersion() const = 0; virtual u16 GetIosVersion() const = 0;
virtual u32 GetBootIndex() const = 0; virtual u32 GetBootIndex() const = 0;
virtual size_t GetContentSize() const = 0; virtual size_t GetContentSize() const = 0;
virtual const SNANDContent* GetContentByIndex(int _Index) const = 0; virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
virtual const u8* GetTicketView() const = 0; virtual const u8* GetTicketView() const = 0;
virtual const u8* GetTmdHeader() const = 0; virtual const u8* GetTmdHeader() const = 0;
virtual const std::vector<SNANDContent>& GetContent() const = 0; virtual const std::vector<SNANDContent>& GetContent() const = 0;
virtual const u16 GetTitleVersion() const = 0; virtual const u16 GetTitleVersion() const = 0;
virtual const u16 GetNumEntries() const = 0; virtual const u16 GetNumEntries() const = 0;
virtual const DiscIO::IVolume::ECountry GetCountry() const = 0; virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
enum enum
{ {
TICKET_VIEW_SIZE = 0x58, TICKET_VIEW_SIZE = 0x58,
TMD_HEADER_SIZE = 0x1e4, TMD_HEADER_SIZE = 0x1e4,
CONTENT_HEADER_SIZE = 0x24 CONTENT_HEADER_SIZE = 0x24
}; };
}; };
// we open the NAND Content files to often... lets cache them // we open the NAND Content files to often... lets cache them
class CNANDContentManager class CNANDContentManager
{ {
public: public:
static CNANDContentManager& Access() { return m_Instance; } static CNANDContentManager& Access() { return m_Instance; }
const INANDContentLoader& GetNANDLoader(const std::string& _rName); const INANDContentLoader& GetNANDLoader(const std::string& _rName);
private: private:
CNANDContentManager() {}; CNANDContentManager() {};
~CNANDContentManager(); ~CNANDContentManager();
static CNANDContentManager m_Instance; static CNANDContentManager m_Instance;
typedef std::map<std::string, INANDContentLoader*> CNANDContentMap; typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
CNANDContentMap m_Map; CNANDContentMap m_Map;
}; };
} }
#endif #endif

View File

@ -1,52 +1,52 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#pragma once #pragma once
#include "Volume.h" #include "Volume.h"
#include "Blob.h" #include "Blob.h"
#include "NANDContentLoader.h" #include "NANDContentLoader.h"
// --- this volume type is used for Wad files --- // --- this volume type is used for Wad files ---
// Some of this code might look redundant with the CNANDContentLoader class, however, // 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- // We do not do any decryption here, we do raw read, so things are -Faster-
namespace DiscIO namespace DiscIO
{ {
class CVolumeWAD : public IVolume class CVolumeWAD : public IVolume
{ {
public: public:
CVolumeWAD(IBlobReader* _pReader); CVolumeWAD(IBlobReader* _pReader);
~CVolumeWAD(); ~CVolumeWAD();
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const; bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; } bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
bool GetTitleID(u8* _pBuffer) const; bool GetTitleID(u8* _pBuffer) const;
std::string GetUniqueID() const; std::string GetUniqueID() const;
std::string GetMakerID() const; std::string GetMakerID() const;
std::string GetName() const; std::string GetName() const;
u32 GetFSTSize() const { return 0; } u32 GetFSTSize() const { return 0; }
std::string GetApploaderDate() const { return "0"; } std::string GetApploaderDate() const { return "0"; }
ECountry GetCountry() const; ECountry GetCountry() const;
u64 GetSize() const; u64 GetSize() const;
private: private:
IBlobReader* m_pReader; IBlobReader* m_pReader;
u64 m_titleID; u64 m_titleID;
u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size; u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
}; };
} // namespace } // namespace

View File

@ -1,156 +1,156 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "stdafx.h" #include "stdafx.h"
#include "NANDContentLoader.h" #include "NANDContentLoader.h"
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include "MathUtil.h" #include "MathUtil.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "Log.h" #include "Log.h"
#include "WiiWad.h" #include "WiiWad.h"
namespace DiscIO namespace DiscIO
{ {
class CBlobBigEndianReader class CBlobBigEndianReader
{ {
public: public:
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {} CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
u32 Read32(u64 _Offset) u32 Read32(u64 _Offset)
{ {
u32 Temp; u32 Temp;
m_rReader.Read(_Offset, 4, (u8*)&Temp); m_rReader.Read(_Offset, 4, (u8*)&Temp);
return(Common::swap32(Temp)); return(Common::swap32(Temp));
} }
private: private:
DiscIO::IBlobReader& m_rReader; DiscIO::IBlobReader& m_rReader;
}; };
WiiWAD::WiiWAD(const std::string& _rName) WiiWAD::WiiWAD(const std::string& _rName)
{ {
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str()); DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
if (pReader == NULL) if (pReader == NULL)
{ {
m_Valid = false; m_Valid = false;
return; return;
} }
m_Valid = ParseWAD(*pReader); m_Valid = ParseWAD(*pReader);
delete pReader; delete pReader;
} }
WiiWAD::~WiiWAD() WiiWAD::~WiiWAD()
{ {
if (m_Valid) if (m_Valid)
{ {
delete m_pCertificateChain; delete m_pCertificateChain;
delete m_pTicket; delete m_pTicket;
delete m_pTMD; delete m_pTMD;
delete m_pDataApp; delete m_pDataApp;
delete m_pFooter; delete m_pFooter;
} }
} }
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset) u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
{ {
if (_Size > 0) if (_Size > 0)
{ {
u8* pTmpBuffer = new u8[_Size]; u8* pTmpBuffer = new u8[_Size];
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry"); _dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
if (!_rReader.Read(_Offset, _Size, pTmpBuffer)) if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
{ {
ERROR_LOG(DISCIO, "WiiWAD: Could not read from file"); ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
PanicAlert("WiiWAD: Could not read from file"); PanicAlert("WiiWAD: Could not read from file");
} }
return pTmpBuffer; return pTmpBuffer;
} }
return NULL; return NULL;
} }
bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader) bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
{ {
CBlobBigEndianReader ReaderBig(_rReader); CBlobBigEndianReader ReaderBig(_rReader);
// get header size // get header size
u32 HeaderSize = ReaderBig.Read32(0); u32 HeaderSize = ReaderBig.Read32(0);
if (HeaderSize != 0x20) if (HeaderSize != 0x20)
{ {
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20"); _dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
return false; return false;
} }
// get header // get header
u8 Header[0x20]; u8 Header[0x20];
_rReader.Read(0, HeaderSize, Header); _rReader.Read(0, HeaderSize, Header);
u32 HeaderType = ReaderBig.Read32(0x4); u32 HeaderType = ReaderBig.Read32(0x4);
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType)) if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
return false; return false;
m_CertificateChainSize = ReaderBig.Read32(0x8); m_CertificateChainSize = ReaderBig.Read32(0x8);
u32 Reserved = ReaderBig.Read32(0xC); u32 Reserved = ReaderBig.Read32(0xC);
m_TicketSize = ReaderBig.Read32(0x10); m_TicketSize = ReaderBig.Read32(0x10);
m_TMDSize = ReaderBig.Read32(0x14); m_TMDSize = ReaderBig.Read32(0x14);
m_DataAppSize = ReaderBig.Read32(0x18); m_DataAppSize = ReaderBig.Read32(0x18);
m_FooterSize = ReaderBig.Read32(0x1C); m_FooterSize = ReaderBig.Read32(0x1C);
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00"); _dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
u32 Offset = 0x40; u32 Offset = 0x40;
m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 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_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_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_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); m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
return true; return true;
} }
bool WiiWAD::IsWiiWAD(const std::string& _rName) bool WiiWAD::IsWiiWAD(const std::string& _rName)
{ {
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str()); DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
if (pReader == NULL) if (pReader == NULL)
return false; return false;
CBlobBigEndianReader Reader(*pReader); CBlobBigEndianReader Reader(*pReader);
bool Result = false; bool Result = false;
// check for wii wad // check for wii wad
if (Reader.Read32(0x00) == 0x20) if (Reader.Read32(0x00) == 0x20)
{ {
u32 WADTYpe = Reader.Read32(0x04); u32 WADTYpe = Reader.Read32(0x04);
switch(WADTYpe) switch(WADTYpe)
{ {
case 0x49730000: case 0x49730000:
case 0x69620000: case 0x69620000:
Result = true; Result = true;
} }
} }
delete pReader; delete pReader;
return Result; return Result;
} }
} // namespace end } // namespace end

View File

@ -1,78 +1,78 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _WII_WAD_H #ifndef _WII_WAD_H
#define _WII_WAD_H #define _WII_WAD_H
#include <string> #include <string>
#include <vector> #include <vector>
#include <map> #include <map>
#include "Common.h" #include "Common.h"
#include "Blob.h" #include "Blob.h"
#include "Volume.h" #include "Volume.h"
namespace DiscIO namespace DiscIO
{ {
class WiiWAD class WiiWAD
{ {
public: public:
WiiWAD(const std::string& _rName); WiiWAD(const std::string& _rName);
~WiiWAD(); ~WiiWAD();
bool IsValid() const { return m_Valid; } bool IsValid() const { return m_Valid; }
u32 GetCertificateChainSize() const { return m_CertificateChainSize; } u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
u32 GetTicketSize() const { return m_TicketSize; } u32 GetTicketSize() const { return m_TicketSize; }
u32 GetTMDSize() const { return m_TMDSize; } u32 GetTMDSize() const { return m_TMDSize; }
u32 GetDataAppSize() const { return m_DataAppSize; } u32 GetDataAppSize() const { return m_DataAppSize; }
u32 GetFooterSize() const { return m_FooterSize; } u32 GetFooterSize() const { return m_FooterSize; }
u8* GetCertificateChain() const { return m_pCertificateChain; } u8* GetCertificateChain() const { return m_pCertificateChain; }
u8* GetTicket() const { return m_pTicket; } u8* GetTicket() const { return m_pTicket; }
u8* GetTMD() const { return m_pTMD; } u8* GetTMD() const { return m_pTMD; }
u8* GetDataApp() const { return m_pDataApp; } u8* GetDataApp() const { return m_pDataApp; }
u8* GetFooter() const { return m_pFooter; } u8* GetFooter() const { return m_pFooter; }
static bool IsWiiWAD(const std::string& _rName); static bool IsWiiWAD(const std::string& _rName);
private: private:
bool m_Valid; bool m_Valid;
u32 m_CertificateChainSize; u32 m_CertificateChainSize;
u32 m_TicketSize; u32 m_TicketSize;
u32 m_TMDSize; u32 m_TMDSize;
u32 m_DataAppSize; u32 m_DataAppSize;
u32 m_FooterSize; u32 m_FooterSize;
u8* m_pCertificateChain; u8* m_pCertificateChain;
u8* m_pTicket; u8* m_pTicket;
u8* m_pTMD; u8* m_pTMD;
u8* m_pDataApp; u8* m_pDataApp;
u8* m_pFooter; u8* m_pFooter;
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset); u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
bool ParseWAD(DiscIO::IBlobReader& _rReader); bool ParseWAD(DiscIO::IBlobReader& _rReader);
}; };
} }
#endif #endif

View File

@ -1,288 +1,288 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "NetWindow.h" #include "NetWindow.h"
void ClientSide::OnClientData(unsigned char data) void ClientSide::OnClientData(unsigned char data)
{ {
unsigned char sent = 0; unsigned char sent = 0;
u32 buffer_size; u32 buffer_size;
size_t recv_size; size_t recv_size;
char *buffer = NULL; char *buffer = NULL;
switch (data) switch (data)
{ {
case 0x10: // Player joined server case 0x10: // Player joined server
{ {
// Read GameFound // Read GameFound
m_socket.Receive((char*)&sent, 1, recv_size); m_socket.Receive((char*)&sent, 1, recv_size);
// Read nickname // Read nickname
m_socket.Receive((char*)&buffer_size, 4, recv_size); m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1]; buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size); m_socket.Receive(buffer, buffer_size+1, recv_size);
Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer)); Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
if (sent != 0x1F) if (sent != 0x1F)
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
Event->AppendText(_("WARNING : Game Not Found on Client Side!\n")); Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
m_numplayers++; m_numplayers++;
Event->SendEvent(HOST_NEWPLAYER); Event->SendEvent(HOST_NEWPLAYER);
break; break;
} }
case 0x11: // Player left server case 0x11: // Player left server
{ {
// Read Nickname // Read Nickname
m_socket.Receive((char*)&buffer_size, 4, recv_size); m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1]; buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size); m_socket.Receive(buffer, buffer_size+1, recv_size);
Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer)); Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
m_numplayers--; m_numplayers--;
Event->SendEvent(HOST_PLAYERLEFT); Event->SendEvent(HOST_PLAYERLEFT);
break; break;
} }
case 0x15: // Ping Player case 0x15: // Ping Player
{ {
m_socket.Receive((char*)&buffer_size, 4, recv_size); m_socket.Receive((char*)&buffer_size, 4, recv_size);
m_socket.Send((const char*)&buffer_size, 4); m_socket.Send((const char*)&buffer_size, 4);
break; break;
} }
case 0x20: // IP request case 0x20: // IP request
{ {
//buffer_size = m_addr.size(); //buffer_size = m_addr.size();
//m_socket.Send((const char*)&buffer_size, 4); //m_socket.Send((const char*)&buffer_size, 4);
m_socket.Send((const char*)&data, 1); m_socket.Send((const char*)&data, 1);
m_socket.Send(m_addr.c_str(), m_addr.size() + 1); m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
break; break;
} }
case 0x30: // Chat message received from server case 0x30: // Chat message received from server
{ {
m_socket.Receive((char*)&buffer_size, 4, recv_size); m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1]; buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size); m_socket.Receive(buffer, buffer_size+1, recv_size);
if (recv_size > 1024) if (recv_size > 1024)
{ {
//something wrong... //something wrong...
delete[] buffer; delete[] buffer;
return; return;
} }
Event->AppendText(wxString::FromAscii(buffer)); Event->AppendText(wxString::FromAscii(buffer));
break; break;
} }
case 0x35: // ChangeGame message received case 0x35: // ChangeGame message received
{ {
m_socket.Receive((char*)&buffer_size, 4, recv_size); m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1]; buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size); m_socket.Receive(buffer, buffer_size+1, recv_size);
m_selectedgame = std::string(buffer); m_selectedgame = std::string(buffer);
Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer)); Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
// Tell the server if the game's been found // Tell the server if the game's been found
m_socket.Send((const char*)&data, 1); m_socket.Send((const char*)&data, 1);
CheckGameFound(); CheckGameFound();
Event->SendEvent(GUI_UPDATE); Event->SendEvent(GUI_UPDATE);
break; break;
} }
case 0x40: // Ready message received case 0x40: // Ready message received
{ {
m_socket.Receive((char*)&buffer_size, 4, recv_size); m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1]; buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size); m_socket.Receive(buffer, buffer_size+1, recv_size);
if (recv_size > 1024) if (recv_size > 1024)
{ {
delete[] buffer; delete[] buffer;
return; return;
} }
Event->AppendText(wxString::FromAscii(buffer)); Event->AppendText(wxString::FromAscii(buffer));
break; break;
} }
case 0x50: // Everyone is Ready message received case 0x50: // Everyone is Ready message received
{ {
// Load the game and start synching // Load the game and start synching
m_netptr->LoadGame(); m_netptr->LoadGame();
break; break;
} }
case 0xA1: // Received pad data from host in versus mode case 0xA1: // Received pad data from host in versus mode
{ {
if (m_data_received) if (m_data_received)
wxThread::Sleep(10); wxThread::Sleep(10);
m_socket.Receive((char*)m_netvalues[0], 8, recv_size); m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
m_data_received = true; m_data_received = true;
#ifdef NET_DEBUG #ifdef NET_DEBUG
char sent[64]; char sent[64];
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]); sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
Event->AppendText(wxString::FromAscii(sent)); Event->AppendText(wxString::FromAscii(sent));
#endif #endif
break; break;
} }
} }
delete[] buffer; delete[] buffer;
} }
void ServerSide::OnServerData(int sock, unsigned char data) void ServerSide::OnServerData(int sock, unsigned char data)
{ {
size_t recv_size; size_t recv_size;
char *buffer = NULL; char *buffer = NULL;
unsigned char sent; unsigned char sent;
unsigned int four_bytes; unsigned int four_bytes;
switch (data) switch (data)
{ {
case 0x15: // Ping Request case 0x15: // Ping Request
{ {
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size); m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
m_client[sock].socket.Send((const char*)&four_bytes, 4); m_client[sock].socket.Send((const char*)&four_bytes, 4);
break; break;
} }
case 0x20: // IP request response case 0x20: // IP request response
{ {
buffer = new char[24]; buffer = new char[24];
// Read IP Address // Read IP Address
m_client[sock].socket.Receive(buffer, 24, recv_size); m_client[sock].socket.Receive(buffer, 24, recv_size);
Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer)); Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
break; break;
} }
case 0x30: // Chat message case 0x30: // Chat message
{ {
buffer = new char[1024]; buffer = new char[1024];
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size); m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size); m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
if (recv_size > 1024) if (recv_size > 1024)
{ {
//something wrong... //something wrong...
delete[] buffer; delete[] buffer;
return; return;
} }
sent = 0x30; sent = 0x30;
// Send to all // Send to all
for (int i=0; i < m_numplayers ; i++) for (int i=0; i < m_numplayers ; i++)
{ {
if (i == sock) if (i == sock)
continue; continue;
m_client[i].socket.Send((const char*)&sent, 1); m_client[i].socket.Send((const char*)&sent, 1);
m_client[1].socket.Send((const char*)&four_bytes, 4); m_client[1].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(buffer, recv_size); m_client[i].socket.Send(buffer, recv_size);
} }
Event->AppendText(wxString::FromAscii(buffer)); Event->AppendText(wxString::FromAscii(buffer));
break; break;
} }
case 0x35: // Change game response received case 0x35: // Change game response received
{ {
// Receive isGameFound response (0x1F / 0x1A) // Receive isGameFound response (0x1F / 0x1A)
m_client[sock].socket.Receive((char*)&sent, 1, recv_size); m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
// If game is not found // If game is not found
if (sent != 0x1F) if (sent != 0x1F)
{ {
sent = 0x30; sent = 0x30;
wxString error_str = wxString::Format( wxString error_str = wxString::Format(
wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str()); wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
four_bytes = (int)error_str.size(); four_bytes = (int)error_str.size();
for (int i=0; i < 2; i++) for (int i=0; i < 2; i++)
Event->AppendText(error_str); Event->AppendText(error_str);
// Send to all // Send to all
for (int i=0; i < m_numplayers ; i++) for (int i=0; i < m_numplayers ; i++)
{ {
if (i == sock) if (i == sock)
continue; continue;
m_client[i].socket.Send((const char*)&sent, 1); m_client[i].socket.Send((const char*)&sent, 1);
m_client[i].socket.Send((const char*)&four_bytes, 4); m_client[i].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1); m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
} }
} }
break; break;
} }
case 0x40: // Ready message received case 0x40: // Ready message received
{ {
std::string buffer_str; std::string buffer_str;
m_client[sock].ready = !m_client[sock].ready; m_client[sock].ready = !m_client[sock].ready;
if (m_client[sock].ready) if (m_client[sock].ready)
buffer_str = ">> "+m_client[sock].nick+" is now ready !\n"; buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
else else
buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n"; buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
four_bytes = (int)buffer_str.size(); four_bytes = (int)buffer_str.size();
// Send to all // Send to all
for (int i=0; i < m_numplayers ; i++) for (int i=0; i < m_numplayers ; i++)
{ {
m_client[i].socket.Send((const char*)&data, 1); m_client[i].socket.Send((const char*)&data, 1);
m_client[i].socket.Send((const char*)&four_bytes, 4); m_client[i].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1); m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
} }
Event->AppendText(wxString::FromAscii(buffer_str.c_str())); Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
IsEveryoneReady(); IsEveryoneReady();
break; break;
} }
case 0xA1: // Received pad data from a client case 0xA1: // Received pad data from a client
{ {
if (m_data_received) if (m_data_received)
wxThread::Sleep(10); wxThread::Sleep(10);
m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size); m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
m_data_received = true; m_data_received = true;
#ifdef NET_DEBUG #ifdef NET_DEBUG
char sent[64]; char sent[64];
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]); sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
Event->AppendText(wxString::FromAscii(sent)); Event->AppendText(wxString::FromAscii(sent));
#endif #endif
break; break;
} }
} }
delete[] buffer; delete[] buffer;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,317 +1,317 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _NETWINDOW_H_ #ifndef _NETWINDOW_H_
#define _NETWINDOW_H_ #define _NETWINDOW_H_
#include <SFML/Network.hpp> #include <SFML/Network.hpp>
#include <string> #include <string>
#include <wx/wx.h> #include <wx/wx.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/dialog.h> #include <wx/dialog.h>
#include <wx/notebook.h> #include <wx/notebook.h>
#include <wx/gbsizer.h> #include <wx/gbsizer.h>
#include <wx/listbox.h> #include <wx/listbox.h>
#include <wx/thread.h> #include <wx/thread.h>
#include "Globals.h" #include "Globals.h"
#include "BootManager.h" #include "BootManager.h"
#include "Common.h" #include "Common.h"
#include "Core.h" #include "Core.h"
#include "pluginspecs_pad.h" #include "pluginspecs_pad.h"
#include "HW/SI.h" #include "HW/SI.h"
#include "HW/SI_Device.h" #include "HW/SI_Device.h"
#include "HW/SI_DeviceGCController.h" #include "HW/SI_DeviceGCController.h"
#include "Timer.h" #include "Timer.h"
#ifdef _DEBUG #ifdef _DEBUG
#define NET_DEBUG #define NET_DEBUG
#endif #endif
// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay, // 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) // Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
// #define USE_TCP // #define USE_TCP
class NetPlay; class NetPlay;
struct Netpads { struct Netpads {
int nHi[128]; int nHi[128];
int nLow[128]; int nLow[128];
}; };
struct Clients { struct Clients {
std::string nick; std::string nick;
sf::SocketTCP socket; sf::SocketTCP socket;
unsigned short port; unsigned short port;
sf::IPAddress address; sf::IPAddress address;
bool ready; bool ready;
}; };
class NetEvent class NetEvent
{ {
public: public:
NetEvent(NetPlay* netptr) { m_netptr = netptr; } NetEvent(NetPlay* netptr) { m_netptr = netptr; }
~NetEvent() {}; ~NetEvent() {};
void SendEvent(int EventType, std::string="NULL", int=NULL); void SendEvent(int EventType, std::string="NULL", int=NULL);
void AppendText(const wxString text); void AppendText(const wxString text);
private: private:
NetPlay *m_netptr; NetPlay *m_netptr;
}; };
class ServerSide : public wxThread class ServerSide : public wxThread
{ {
public: public:
ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick); ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
~ServerSide() {}; ~ServerSide() {};
virtual void *Entry(); virtual void *Entry();
void Write(int socknb, const char *data, size_t size, long *ping=NULL); void Write(int socknb, const char *data, size_t size, long *ping=NULL);
void WriteUDP(int socknb, const char *data, size_t size); void WriteUDP(int socknb, const char *data, size_t size);
bool isNewPadData(u32 *netValues, bool current, int client=0); bool isNewPadData(u32 *netValues, bool current, int client=0);
private: private:
bool SyncValues(unsigned char, sf::IPAddress); bool SyncValues(unsigned char, sf::IPAddress);
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0); bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
char GetSocket(sf::SocketTCP Socket); char GetSocket(sf::SocketTCP Socket);
void OnServerData(int sock, unsigned char data); void OnServerData(int sock, unsigned char data);
void IsEveryoneReady(); void IsEveryoneReady();
NetPlay *m_netptr; NetPlay *m_netptr;
NetEvent *Event; NetEvent *Event;
u32 m_netvalues[3][3]; u32 m_netvalues[3][3];
bool m_data_received; // New Pad data received ? bool m_data_received; // New Pad data received ?
unsigned char m_numplayers; unsigned char m_numplayers;
int m_netmodel; int m_netmodel;
std::string m_nick; std::string m_nick;
Clients m_client[3]; // Connected client objects Clients m_client[3]; // Connected client objects
sf::SelectorTCP m_selector; sf::SelectorTCP m_selector;
sf::SocketTCP m_socket; // Server 'listening' socket sf::SocketTCP m_socket; // Server 'listening' socket
sf::SocketUDP m_socketUDP; sf::SocketUDP m_socketUDP;
wxCriticalSection m_CriticalSection; wxCriticalSection m_CriticalSection;
}; };
class ClientSide : public wxThread class ClientSide : public wxThread
{ {
public: public:
ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick); ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
~ClientSide() {} ~ClientSide() {}
virtual void *Entry(); virtual void *Entry();
void Write(const char *data, size_t size, long *ping=NULL); void Write(const char *data, size_t size, long *ping=NULL);
void WriteUDP(const char *data, size_t size); void WriteUDP(const char *data, size_t size);
bool isNewPadData(u32 *netValues, bool current, bool isVersus=true); bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
private: private:
bool SyncValues(); bool SyncValues();
void CheckGameFound(); void CheckGameFound();
void OnClientData(unsigned char data); void OnClientData(unsigned char data);
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0); bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
NetPlay *m_netptr; NetPlay *m_netptr;
NetEvent *Event; NetEvent *Event;
u32 m_netvalues[3][3]; u32 m_netvalues[3][3];
bool m_data_received; // New Pad data received ? bool m_data_received; // New Pad data received ?
unsigned char m_numplayers; unsigned char m_numplayers;
int m_netmodel; int m_netmodel;
std::string m_nick; std::string m_nick;
std::string m_hostnick; std::string m_hostnick;
std::string m_selectedgame; std::string m_selectedgame;
sf::SelectorTCP m_selector; sf::SelectorTCP m_selector;
sf::SocketTCP m_socket; // Client I/O socket sf::SocketTCP m_socket; // Client I/O socket
sf::SocketUDP m_socketUDP; sf::SocketUDP m_socketUDP;
unsigned short m_port; unsigned short m_port;
std::string m_addr; // Contains the server addr std::string m_addr; // Contains the server addr
wxCriticalSection m_CriticalSection; wxCriticalSection m_CriticalSection;
}; };
class NetPlay : public wxFrame class NetPlay : public wxFrame
{ {
public: public:
NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = ""); NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
~NetPlay(); ~NetPlay();
void UpdateNetWindow(bool update_infos, wxString=wxT("NULL")); void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
void AppendText(const wxString text) { m_Logging->AppendText(text); } void AppendText(const wxString text) { m_Logging->AppendText(text); }
// Send and receive pads values // Send and receive pads values
bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues); bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
void ChangeSelectedGame(std::string game); void ChangeSelectedGame(std::string game);
void IsGameFound(unsigned char*, std::string); void IsGameFound(unsigned char*, std::string);
std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; } std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
void LoadGame(); void LoadGame();
protected: protected:
// Protects our vars from being fuxored by threads // Protects our vars from being fuxored by threads
wxCriticalSection m_critical; wxCriticalSection m_critical;
// this draws the GUI, ya rly // this draws the GUI, ya rly
void DrawGUI(); void DrawGUI();
void DrawNetWindow(); void DrawNetWindow();
// event handlers // event handlers
void OnGUIEvent(wxCommandEvent& event); void OnGUIEvent(wxCommandEvent& event);
void OnDisconnect(wxCommandEvent& event); void OnDisconnect(wxCommandEvent& event);
void OnNetEvent(wxCommandEvent& event); void OnNetEvent(wxCommandEvent& event);
void OnQuit(wxCloseEvent& event); void OnQuit(wxCloseEvent& event);
void OnJoin(wxCommandEvent& event); void OnJoin(wxCommandEvent& event);
void OnHost(wxCommandEvent& event); void OnHost(wxCommandEvent& event);
// Net play vars (used ingame) // Net play vars (used ingame)
int m_frame; int m_frame;
int m_lastframe; int m_lastframe;
Common::Timer m_timer; Common::Timer m_timer;
int m_loopframe; int m_loopframe;
int m_frameDelay; int m_frameDelay;
bool m_data_received;// True if first frame data received bool m_data_received;// True if first frame data received
// Basic vars // Basic vars
std::string m_paths; // Game paths list std::string m_paths; // Game paths list
std::string m_games; // Game names list std::string m_games; // Game names list
std::string m_selectedGame;// Selected game's string std::string m_selectedGame;// Selected game's string
std::string m_hostaddr; // Used with OnGetIP to cache it std::string m_hostaddr; // Used with OnGetIP to cache it
bool m_ready, m_clients_ready; bool m_ready, m_clients_ready;
std::string m_nick; std::string m_nick;
int m_NetModel; // Using P2P model (0) or Server model (1) int m_NetModel; // Using P2P model (0) or Server model (1)
int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
std::string m_address; // The address entered into connection box std::string m_address; // The address entered into connection box
unsigned short m_port; unsigned short m_port;
Netpads m_pads[4]; // this struct is used to save synced pad values Netpads m_pads[4]; // this struct is used to save synced pad values
IniFile ConfigIni; IniFile ConfigIni;
// Sockets objects // Sockets objects
ServerSide *m_sock_server; ServerSide *m_sock_server;
ClientSide *m_sock_client; ClientSide *m_sock_client;
// ----------- // -----------
// GUI objects // GUI objects
// ----------- // -----------
wxNotebook *m_Notebook; wxNotebook *m_Notebook;
wxPanel *m_Tab_Connect; wxPanel *m_Tab_Connect;
wxPanel *m_Tab_Host; wxPanel *m_Tab_Host;
wxStaticText *m_SetNick_text; wxStaticText *m_SetNick_text;
wxTextCtrl *m_SetNick; wxTextCtrl *m_SetNick;
wxChoice *m_NetMode; wxChoice *m_NetMode;
// Host tab : // Host tab :
wxArrayString m_GameList_str; wxArrayString m_GameList_str;
wxStaticText *m_GameList_text; wxStaticText *m_GameList_text;
wxListBox *m_GameList; wxListBox *m_GameList;
wxStaticText *m_SetPort_text; wxStaticText *m_SetPort_text;
wxTextCtrl *m_SetPort; wxTextCtrl *m_SetPort;
wxButton *m_HostGame; wxButton *m_HostGame;
// Connect tab : // Connect tab :
wxTextCtrl *m_ConAddr; wxTextCtrl *m_ConAddr;
wxStaticText *m_ConAddr_text; wxStaticText *m_ConAddr_text;
wxButton *m_JoinGame; wxButton *m_JoinGame;
wxCheckBox *m_UseRandomPort; wxCheckBox *m_UseRandomPort;
// Connection window // Connection window
wxButton *m_Game_str; wxButton *m_Game_str;
wxTextCtrl *m_Logging; wxTextCtrl *m_Logging;
wxTextCtrl *m_Chat; wxTextCtrl *m_Chat;
wxButton *m_Chat_ok; wxButton *m_Chat_ok;
// Right part // Right part
wxButton *m_wtfismyip; wxButton *m_wtfismyip;
wxButton *m_ChangeGame; wxButton *m_ChangeGame;
// Left Part // Left Part
wxButton *m_Disconnect; wxButton *m_Disconnect;
wxStaticText *m_ConInfo_text; wxStaticText *m_ConInfo_text;
wxButton *m_GetPing; wxButton *m_GetPing;
wxCheckBox *m_Ready; wxCheckBox *m_Ready;
wxCheckBox *m_RecordGame; wxCheckBox *m_RecordGame;
// wxWidgets event table // wxWidgets event table
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
class GameListPopup : public wxDialog class GameListPopup : public wxDialog
{ {
public: public:
GameListPopup(NetPlay *net_ptr, wxArrayString GameNames); GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
~GameListPopup() {} ~GameListPopup() {}
protected: protected:
void OnButtons(wxCommandEvent& event); void OnButtons(wxCommandEvent& event);
wxArrayString m_GameList_str; wxArrayString m_GameList_str;
NetPlay* m_netParent; NetPlay* m_netParent;
wxListBox *m_GameList; wxListBox *m_GameList;
wxButton *m_Accept; wxButton *m_Accept;
wxButton *m_Cancel; wxButton *m_Cancel;
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
}; };
enum enum
{ {
ID_NOTEBOOK, ID_NOTEBOOK,
ID_TAB_HOST, ID_TAB_HOST,
ID_TAB_CONN, ID_TAB_CONN,
ID_BUTTON_HOST, ID_BUTTON_HOST,
ID_BUTTON_JOIN, ID_BUTTON_JOIN,
ID_NETMODE, ID_NETMODE,
ID_GAMELIST, ID_GAMELIST,
ID_LOGGING_TXT, ID_LOGGING_TXT,
ID_CHAT, ID_CHAT,
ID_SETNICK, ID_SETNICK,
ID_SETPORT, ID_SETPORT,
ID_CONNADDR, ID_CONNADDR,
ID_CONNINFO_TXT, ID_CONNINFO_TXT,
ID_USE_RANDOMPORT, ID_USE_RANDOMPORT,
ID_BUTTON_GETPING, ID_BUTTON_GETPING,
ID_BUTTON_GETIP, ID_BUTTON_GETIP,
ID_CHANGEGAME, ID_CHANGEGAME,
ID_BUTTON_QUIT, ID_BUTTON_QUIT,
ID_BUTTON_CHAT, ID_BUTTON_CHAT,
ID_READY, ID_READY,
ID_RECORD, ID_RECORD,
ID_SOCKET, ID_SOCKET,
ID_SERVER, ID_SERVER,
HOST_FULL = 200, // ... HOST_FULL = 200, // ...
HOST_ERROR, // Sent on socket error HOST_ERROR, // Sent on socket error
HOST_DISCONNECTED, HOST_DISCONNECTED,
HOST_NEWPLAYER, HOST_NEWPLAYER,
HOST_PLAYERLEFT, HOST_PLAYERLEFT,
CLIENTS_READY, CLIENTS_READY,
CLIENTS_NOTREADY, CLIENTS_NOTREADY,
GUI_UPDATE, // Refresh the shown selectedgame on GUI GUI_UPDATE, // Refresh the shown selectedgame on GUI
ADD_TEXT, // Add text to m_Logging (string) ADD_TEXT, // Add text to m_Logging (string)
ADD_INFO, // Sent when updating net infos (string) ADD_INFO, // Sent when updating net infos (string)
NET_EVENT NET_EVENT
}; };
#endif // _NETWINDOW_H_ #endif // _NETWINDOW_H_

View File

@ -1,127 +1,127 @@
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef __SUMMARIZE_H__ #ifndef __SUMMARIZE_H__
#define __SUMMARIZE_H__ #define __SUMMARIZE_H__
std::string Summarize_Plug() std::string Summarize_Plug()
{ {
return StringFromFormat( return StringFromFormat(
"Plugin Information\n\n" "Plugin Information\n\n"
"Default GFX Plugin: %s\n" "Default GFX Plugin: %s\n"
"Default DSP Plugin: %s\n" "Default DSP Plugin: %s\n"
"Default PAD Plugin: %s\n" "Default PAD Plugin: %s\n"
"Default WiiMote Plugin: %s\n\n" "Default WiiMote Plugin: %s\n\n"
"Current GFX Plugin: %s\n" "Current GFX Plugin: %s\n"
"Current DSP Plugin: %s\n" "Current DSP Plugin: %s\n"
"Current PAD Plugin[0]: %s\n" "Current PAD Plugin[0]: %s\n"
"Current PAD Plugin[1]: %s\n" "Current PAD Plugin[1]: %s\n"
"Current PAD Plugin[2]: %s\n" "Current PAD Plugin[2]: %s\n"
"Current PAD Plugin[3]: %s\n" "Current PAD Plugin[3]: %s\n"
"Current WiiMote Plugin[0]: %s\n", "Current WiiMote Plugin[0]: %s\n",
SConfig::GetInstance().m_DefaultGFXPlugin.c_str(), SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
SConfig::GetInstance().m_DefaultDSPPlugin.c_str(), SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
SConfig::GetInstance().m_DefaultPADPlugin.c_str(), SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(), SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
Core::GetStartupParameter().m_strVideoPlugin.c_str(), Core::GetStartupParameter().m_strVideoPlugin.c_str(),
Core::GetStartupParameter().m_strDSPPlugin.c_str(), Core::GetStartupParameter().m_strDSPPlugin.c_str(),
Core::GetStartupParameter().m_strPadPlugin[0].c_str(), Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
Core::GetStartupParameter().m_strPadPlugin[1].c_str(), Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
Core::GetStartupParameter().m_strPadPlugin[2].c_str(), Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
Core::GetStartupParameter().m_strPadPlugin[3].c_str(), Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
Core::GetStartupParameter().m_strWiimotePlugin[0].c_str() Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
); );
} }
std::string Summarize_Settings() std::string Summarize_Settings()
{ {
return StringFromFormat( return StringFromFormat(
"Dolphin Settings\n\n" "Dolphin Settings\n\n"
"Always HLE Bios: %s\n" "Always HLE Bios: %s\n"
"Use Dynarec: %s\n" "Use Dynarec: %s\n"
"Use Dual Core: %s\n" "Use Dual Core: %s\n"
"DSP Thread: %s\n" "DSP Thread: %s\n"
"Skip Idle: %s\n" "Skip Idle: %s\n"
"Lock Threads: %s\n" "Lock Threads: %s\n"
"Use Dual Core: %s\n" "Use Dual Core: %s\n"
"Default GCM: %s\n" "Default GCM: %s\n"
"DVD Root: %s\n" "DVD Root: %s\n"
"Optimize Quantizers: %s\n" "Optimize Quantizers: %s\n"
"Enable Cheats: %s\n" "Enable Cheats: %s\n"
"Selected Language: %d\n" "Selected Language: %d\n"
"Memcard A: %s\n" "Memcard A: %s\n"
"Memcard B: %s\n" "Memcard B: %s\n"
"Slot A: %d\n" "Slot A: %d\n"
"Slot B: %d\n" "Slot B: %d\n"
"Serial Port 1: %d\n" "Serial Port 1: %d\n"
"Run Compare Server: %s\n" "Run Compare Server: %s\n"
"Run Compare Client: %s\n" "Run Compare Client: %s\n"
"TLB Hack: %s\n" "TLB Hack: %s\n"
"Frame Limit: %d\n" "Frame Limit: %d\n"
"[Wii]Widescreen: %s\n" "[Wii]Widescreen: %s\n"
"[Wii]Progressive Scan: %s\n", "[Wii]Progressive Scan: %s\n",
Core::GetStartupParameter().bHLEBios?"True":"False", Core::GetStartupParameter().bHLEBios?"True":"False",
Core::GetStartupParameter().bUseJIT?"True":"False", Core::GetStartupParameter().bUseJIT?"True":"False",
Core::GetStartupParameter().bUseDualCore?"True":"False", Core::GetStartupParameter().bUseDualCore?"True":"False",
Core::GetStartupParameter().bDSPThread?"True":"False", Core::GetStartupParameter().bDSPThread?"True":"False",
Core::GetStartupParameter().bSkipIdle?"True":"False", Core::GetStartupParameter().bSkipIdle?"True":"False",
Core::GetStartupParameter().bLockThreads?"True":"False", Core::GetStartupParameter().bLockThreads?"True":"False",
Core::GetStartupParameter().bUseDualCore?"True":"False", Core::GetStartupParameter().bUseDualCore?"True":"False",
Core::GetStartupParameter().m_strDefaultGCM.c_str(), Core::GetStartupParameter().m_strDefaultGCM.c_str(),
Core::GetStartupParameter().m_strDVDRoot.c_str(), Core::GetStartupParameter().m_strDVDRoot.c_str(),
Core::GetStartupParameter().bOptimizeQuantizers?"True":"False", Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
Core::GetStartupParameter().bEnableCheats?"True":"False", Core::GetStartupParameter().bEnableCheats?"True":"False",
Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
SConfig::GetInstance().m_strMemoryCardA.c_str(), SConfig::GetInstance().m_strMemoryCardA.c_str(),
SConfig::GetInstance().m_strMemoryCardB.c_str(), SConfig::GetInstance().m_strMemoryCardB.c_str(),
SConfig::GetInstance().m_EXIDevice[0], //FIXME SConfig::GetInstance().m_EXIDevice[0], //FIXME
SConfig::GetInstance().m_EXIDevice[1], //FIXME SConfig::GetInstance().m_EXIDevice[1], //FIXME
SConfig::GetInstance().m_EXIDevice[2], //FIXME SConfig::GetInstance().m_EXIDevice[2], //FIXME
Core::GetStartupParameter().bRunCompareServer?"True":"False", Core::GetStartupParameter().bRunCompareServer?"True":"False",
Core::GetStartupParameter().bRunCompareClient?"True":"False", Core::GetStartupParameter().bRunCompareClient?"True":"False",
Core::GetStartupParameter().iTLBHack?"True":"False", Core::GetStartupParameter().iTLBHack?"True":"False",
SConfig::GetInstance().m_Framelimit*5, SConfig::GetInstance().m_Framelimit*5,
Core::GetStartupParameter().bWidescreen?"True":"False", Core::GetStartupParameter().bWidescreen?"True":"False",
Core::GetStartupParameter().bProgressiveScan?"True":"False" Core::GetStartupParameter().bProgressiveScan?"True":"False"
); );
} }
std::string Summarize_CPU() std::string Summarize_CPU()
{ {
return StringFromFormat( return StringFromFormat(
"Processor Information: \n%s\n", "Processor Information: \n%s\n",
cpu_info.Summarize().c_str() cpu_info.Summarize().c_str()
); );
} }
std::string Summarize_Drives() std::string Summarize_Drives()
{ {
char ** drives = cdio_get_devices(); char ** drives = cdio_get_devices();
std::string drive; std::string drive;
for (int i = 0; drives[i] != NULL && i < 24; i++) for (int i = 0; drives[i] != NULL && i < 24; i++)
{ {
drive += StringFromFormat( drive += StringFromFormat(
"CD/DVD Drive%d: %s\n", "CD/DVD Drive%d: %s\n",
i+1, i+1,
drives[i] drives[i]
); );
} }
return drive; return drive;
} }
#endif //__SUMMARIZE_H__ #endif //__SUMMARIZE_H__

View File

@ -1,129 +1,129 @@
/* XPM */ /* XPM */
static const char *Dolphin_xpm[] = { static const char *Dolphin_xpm[] = {
"32 32 94 2", "32 32 94 2",
" c None", " c None",
". c #000000", ". c #000000",
"+ c #1A496C", "+ c #1A496C",
"@ c #091A27", "@ c #091A27",
"# c #3AA4F0", "# c #3AA4F0",
"$ c #3AA3EF", "$ c #3AA3EF",
"% c #3CA1EA", "% c #3CA1EA",
"& c #1A4A6D", "& c #1A4A6D",
"* c #3AA2ED", "* c #3AA2ED",
"= c #F7FAFA", "= c #F7FAFA",
"- c #FFFFFF", "- c #FFFFFF",
"; c #FDFDFD", "; c #FDFDFD",
"> c #49A1E0", "> c #49A1E0",
", c #3BA2EC", ", c #3BA2EC",
"' c #FBFDFC", "' c #FBFDFC",
") c #FEFFFD", ") c #FEFFFD",
"! c #4EA3E0", "! c #4EA3E0",
"~ c #3DA1E9", "~ c #3DA1E9",
"{ c #D1E1EB", "{ c #D1E1EB",
"] c #8ABBDE", "] c #8ABBDE",
"^ c #F2F6F7", "^ c #F2F6F7",
"/ c #FAFBFC", "/ c #FAFBFC",
"( c #CEDEEA", "( c #CEDEEA",
"_ c #E5EEF2", "_ c #E5EEF2",
": c #BBD2E1", ": c #BBD2E1",
"< c #B3CFE5", "< c #B3CFE5",
"[ c #FFFFFE", "[ c #FFFFFE",
"} c #FEFFFE", "} c #FEFFFE",
"| c #E8F0F3", "| c #E8F0F3",
"1 c #E4ECF1", "1 c #E4ECF1",
"2 c #E5EDF0", "2 c #E5EDF0",
"3 c #E9F0F3", "3 c #E9F0F3",
"4 c #FEFEFE", "4 c #FEFEFE",
"5 c #F9FBFB", "5 c #F9FBFB",
"6 c #B0CCE0", "6 c #B0CCE0",
"7 c #FEFEFF", "7 c #FEFEFF",
"8 c #F9FAFB", "8 c #F9FAFB",
"9 c #43A1E4", "9 c #43A1E4",
"0 c #EFF3F6", "0 c #EFF3F6",
"a c #F0F5F7", "a c #F0F5F7",
"b c #97C1DE", "b c #97C1DE",
"c c #FEFEFD", "c c #FEFEFD",
"d c #FDFDFC", "d c #FDFDFC",
"e c #97BEDB", "e c #97BEDB",
"f c #FBFCFC", "f c #FBFCFC",
"g c #EDF3F6", "g c #EDF3F6",
"h c #6EADDA", "h c #6EADDA",
"i c #F3F6F8", "i c #F3F6F8",
"j c #3BA1EA", "j c #3BA1EA",
"k c #6EADDB", "k c #6EADDB",
"l c #F4F8F9", "l c #F4F8F9",
"m c #F1F6F7", "m c #F1F6F7",
"n c #3FA1E7", "n c #3FA1E7",
"o c #9BC1DD", "o c #9BC1DD",
"p c #FCFDFC", "p c #FCFDFC",
"q c #FBFDFB", "q c #FBFDFB",
"r c #B9D1E1", "r c #B9D1E1",
"s c #E0EBF2", "s c #E0EBF2",
"t c #D3E3EF", "t c #D3E3EF",
"u c #FFFEFE", "u c #FFFEFE",
"v c #F2F7F7", "v c #F2F7F7",
"w c #D5E4F0", "w c #D5E4F0",
"x c #F6F9F9", "x c #F6F9F9",
"y c #BDD5E5", "y c #BDD5E5",
"z c #EBF1F4", "z c #EBF1F4",
"A c #DEEAF2", "A c #DEEAF2",
"B c #AAC9DE", "B c #AAC9DE",
"C c #FEFFFF", "C c #FEFFFF",
"D c #EFF4F6", "D c #EFF4F6",
"E c #F8FAFB", "E c #F8FAFB",
"F c #A0C4E1", "F c #A0C4E1",
"G c #D6E5F0", "G c #D6E5F0",
"H c #FAFCFC", "H c #FAFCFC",
"I c #BDD5E7", "I c #BDD5E7",
"J c #EEF3F7", "J c #EEF3F7",
"K c #F3F7FA", "K c #F3F7FA",
"L c #C7D8E4", "L c #C7D8E4",
"M c #CDDEEC", "M c #CDDEEC",
"N c #DAE6ED", "N c #DAE6ED",
"O c #9AC2DF", "O c #9AC2DF",
"P c #E8EFF4", "P c #E8EFF4",
"Q c #ACCDE3", "Q c #ACCDE3",
"R c #8DBBDC", "R c #8DBBDC",
"S c #D5E3EB", "S c #D5E3EB",
"T c #FDFFFE", "T c #FDFFFE",
"U c #FCFDFD", "U c #FCFDFD",
"V c #FEFDFD", "V c #FEFDFD",
"W c #F7F9FA", "W c #F7F9FA",
"X c #FDFEFD", "X c #FDFEFD",
"Y c #E7EFF4", "Y c #E7EFF4",
"Z c #A4C7E0", "Z c #A4C7E0",
"` c #F9FDFB", "` c #F9FDFB",
" . c #F6FBFC", " . c #F6FBFC",
".. c #B8D1E3", ".. c #B8D1E3",
" . . + . . . . . . . . . . . . . . . . . . . . . . . . ", " . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ", ". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ", ". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ", "& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ", ". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ", ". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ", ". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ", ". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ", ". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ", ". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ", ". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ", ". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ", ". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ", ". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ", ". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ", ". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ", ". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ", ". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ", ". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ", ". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ", ". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ", ". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ", ". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ", ". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ", ". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ", ". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ", ". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ", ". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ", " . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ", " . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ", " . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
" . . . . . . . . . . . . . . . . . . . . . . . . "}; " . . . . . . . . . . . . . . . . . . . . . . . . "};

View File

@ -1,83 +1,83 @@
/* XPM */ /* XPM */
static const char *const Flag_Europe_xpm[] = { static const char *const Flag_Europe_xpm[] = {
"96 32 48 1", "96 32 48 1",
" c None", " c None",
". c #000000", ". c #000000",
"+ c #0000FD", "+ c #0000FD",
"@ c #0000FF", "@ c #0000FF",
"# c #0808F7", "# c #0808F7",
"$ c #5C5CA3", "$ c #5C5CA3",
"% c #1717E8", "% c #1717E8",
"& c #767680", "& c #767680",
"* c #EDED00", "* c #EDED00",
"= c #A5A54D", "= c #A5A54D",
"- c #2E2EB9", "- c #2E2EB9",
"; c #96961A", "; c #96961A",
"> c #4A4A8E", "> c #4A4A8E",
", c #0000FB", ", c #0000FB",
"' c #0000F4", "' c #0000F4",
") c #0808EC", ") c #0808EC",
"! c #5C5C9B", "! c #5C5C9B",
"~ c #1717DD", "~ c #1717DD",
"{ c #0000EE", "{ c #0000EE",
"] c #767677", "] c #767677",
"^ c #A5A547", "^ c #A5A547",
"/ c #0000DD", "/ c #0000DD",
"( c #2E2EA0", "( c #2E2EA0",
"_ c #969616", "_ c #969616",
": c #4A4A7B", ": c #4A4A7B",
"< c #0000D2", "< c #0000D2",
"[ c #0000C6", "[ c #0000C6",
"} c #0808BF", "} c #0808BF",
"| c #5C5C7E", "| c #5C5C7E",
"1 c #1717B4", "1 c #1717B4",
"2 c #0000B9", "2 c #0000B9",
"3 c #76765C", "3 c #76765C",
"4 c #A5A537", "4 c #A5A537",
"5 c #0808B3", "5 c #0808B3",
"6 c #5C5C76", "6 c #5C5C76",
"7 c #1717A8", "7 c #1717A8",
"8 c #0000A9", "8 c #0000A9",
"9 c #2E2E7A", "9 c #2E2E7A",
"0 c #969611", "0 c #969611",
"a c #4A4A5E", "a c #4A4A5E",
"b c #767654", "b c #767654",
"c c #A5A533", "c c #A5A533",
"d c #000097", "d c #000097",
"e c #2E2E6D", "e c #2E2E6D",
"f c #96960F", "f c #96960F",
"g c #4A4A54", "g c #4A4A54",
"h c #000081", "h c #000081",
"i c #000077", "i c #000077",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
"................................ ", "................................ ",
".++++++++++++++++++++++++++++++. ", ".++++++++++++++++++++++++++++++. ",
".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ", ".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ", ".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ", ".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ", ".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ", ".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ", ".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
".''''''')!~''''''''')!~''''''''. ", ".''''''')!~''''''''')!~''''''''. ",
".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ", ".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
".///////(_://///////(_:////////. ", ".///////(_://///////(_:////////. ",
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ", ".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ", ".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
".2222222223*4256723*42222222222. ", ".2222222223*4256723*42222222222. ",
".88888888890a8b*c890a8888888888. ", ".88888888890a8b*c890a8888888888. ",
".dddddddddddddefgdddddddddddddd. ", ".dddddddddddddefgdddddddddddddd. ",
".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ", ".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ", ".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ", ".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
"................................ ", "................................ ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" "}; " "};

View File

@ -1,80 +1,80 @@
/* XPM */ /* XPM */
static const char *const Flag_France_xpm[] = { static const char *const Flag_France_xpm[] = {
"96 32 45 1", "96 32 45 1",
" c None", " c None",
". c #000000", ". c #000000",
"+ c #0000FF", "+ c #0000FF",
"@ c #FFFFFF", "@ c #FFFFFF",
"# c #FF0000", "# c #FF0000",
"$ c #0000FC", "$ c #0000FC",
"% c #0000F8", "% c #0000F8",
"& c #FCFCFC", "& c #FCFCFC",
"* c #FC0000", "* c #FC0000",
"= c #0000F2", "= c #0000F2",
"- c #F8F8F8", "- c #F8F8F8",
"; c #F80000", "; c #F80000",
"> c #0000EC", "> c #0000EC",
", c #F2F2F2", ", c #F2F2F2",
"' c #F20000", "' c #F20000",
") c #0000E3", ") c #0000E3",
"! c #ECECEC", "! c #ECECEC",
"~ c #EC0000", "~ c #EC0000",
"{ c #0000DB", "{ c #0000DB",
"] c #E3E3E3", "] c #E3E3E3",
"^ c #E30000", "^ c #E30000",
"/ c #0000D2", "/ c #0000D2",
"( c #DBDBDB", "( c #DBDBDB",
"_ c #DB0000", "_ c #DB0000",
": c #0000C8", ": c #0000C8",
"< c #D2D2D2", "< c #D2D2D2",
"[ c #D20000", "[ c #D20000",
"} c #0000BD", "} c #0000BD",
"| c #C8C8C8", "| c #C8C8C8",
"1 c #C80000", "1 c #C80000",
"2 c #0000B1", "2 c #0000B1",
"3 c #BDBDBD", "3 c #BDBDBD",
"4 c #BD0000", "4 c #BD0000",
"5 c #0000A3", "5 c #0000A3",
"6 c #B1B1B1", "6 c #B1B1B1",
"7 c #B10000", "7 c #B10000",
"8 c #000093", "8 c #000093",
"9 c #A3A3A3", "9 c #A3A3A3",
"0 c #A30000", "0 c #A30000",
"a c #000080", "a c #000080",
"b c #939393", "b c #939393",
"c c #930000", "c c #930000",
"d c #000077", "d c #000077",
"e c #808080", "e c #808080",
"f c #800000", "f c #800000",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
"................................ ", "................................ ",
".++++++++++@@@@@@@@@@@#########. ", ".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ", ".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ", ".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ", ".++++++++++@@@@@@@@@@@#########. ",
".$$$$$$$$$$@@@@@@@@@@@#########. ", ".$$$$$$$$$$@@@@@@@@@@@#########. ",
".%%%%%%%%%%&&&&&&&&&&&*********. ", ".%%%%%%%%%%&&&&&&&&&&&*********. ",
".==========-----------;;;;;;;;;. ", ".==========-----------;;;;;;;;;. ",
".>>>>>>>>>>,,,,,,,,,,,'''''''''. ", ".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
".))))))))))!!!!!!!!!!!~~~~~~~~~. ", ".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ", ".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
".//////////(((((((((((_________. ", ".//////////(((((((((((_________. ",
".::::::::::<<<<<<<<<<<[[[[[[[[[. ", ".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
".}}}}}}}}}}|||||||||||111111111. ", ".}}}}}}}}}}|||||||||||111111111. ",
".222222222233333333333444444444. ", ".222222222233333333333444444444. ",
".555555555566666666666777777777. ", ".555555555566666666666777777777. ",
".888888888899999999999000000000. ", ".888888888899999999999000000000. ",
".aaaaaaaaaabbbbbbbbbbbccccccccc. ", ".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
".ddddddddddeeeeeeeeeeefffffffff. ", ".ddddddddddeeeeeeeeeeefffffffff. ",
"................................ ", "................................ ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" "}; " "};

View File

@ -1,102 +1,102 @@
/* XPM */ /* XPM */
static const char * const Flag_Japan_xpm[] = { static const char * const Flag_Japan_xpm[] = {
"96 32 67 1", "96 32 67 1",
" c None", " c None",
". c #000000", ". c #000000",
"+ c #FFFFFF", "+ c #FFFFFF",
"@ c #FECACA", "@ c #FECACA",
"# c #FD8080", "# c #FD8080",
"$ c #FD6161", "$ c #FD6161",
"% c #FD7676", "% c #FD7676",
"& c #FEB6B6", "& c #FEB6B6",
"* c #FEFEFE", "* c #FEFEFE",
"= c #FFEDED", "= c #FFEDED",
"- c #FF4C4C", "- c #FF4C4C",
"; c #FF0000", "; c #FF0000",
"> c #FF2F2F", "> c #FF2F2F",
", c #FFD7D7", ", c #FFD7D7",
"' c #FEF5F5", "' c #FEF5F5",
") c #FE2E2E", ") c #FE2E2E",
"! c #FE1313", "! c #FE1313",
"~ c #FEDDDD", "~ c #FEDDDD",
"{ c #F9F9F9", "{ c #F9F9F9",
"] c #FC7777", "] c #FC7777",
"^ c #FD4545", "^ c #FD4545",
"/ c #F4F4F4", "/ c #F4F4F4",
"( c #F4F3F3", "( c #F4F3F3",
"_ c #FA1313", "_ c #FA1313",
": c #FB0000", ": c #FB0000",
"< c #FA0000", "< c #FA0000",
"[ c #F4D4D4", "[ c #F4D4D4",
"} c #EFEFEF", "} c #EFEFEF",
"| c #EFCFCF", "| c #EFCFCF",
"1 c #F10000", "1 c #F10000",
"2 c #EF9F9F", "2 c #EF9F9F",
"3 c #E4E4E4", "3 c #E4E4E4",
"4 c #E2BEBE", "4 c #E2BEBE",
"5 c #DD0000", "5 c #DD0000",
"6 c #E19090", "6 c #E19090",
"7 c #D9D9D9", "7 c #D9D9D9",
"8 c #D8D0D0", "8 c #D8D0D0",
"9 c #CA0404", "9 c #CA0404",
"0 c #CA0000", "0 c #CA0000",
"a c #D5A9A9", "a c #D5A9A9",
"b c #D0D0D0", "b c #D0D0D0",
"c c #BC4242", "c c #BC4242",
"d c #B40000", "d c #B40000",
"e c #B71A1A", "e c #B71A1A",
"f c #CFCFCF", "f c #CFCFCF",
"g c #C6C6C6", "g c #C6C6C6",
"h c #BEA7A7", "h c #BEA7A7",
"i c #990808", "i c #990808",
"j c #980000", "j c #980000",
"k c #B78787", "k c #B78787",
"l c #BBBBBB", "l c #BBBBBB",
"m c #A88989", "m c #A88989",
"n c #7B0B0B", "n c #7B0B0B",
"o c #770000", "o c #770000",
"p c #780202", "p c #780202",
"q c #9E6B6B", "q c #9E6B6B",
"r c #AEAEAE", "r c #AEAEAE",
"s c #A89C9C", "s c #A89C9C",
"t c #8F4E4E", "t c #8F4E4E",
"u c #7F1B1B", "u c #7F1B1B",
"v c #7A0A0A", "v c #7A0A0A",
"w c #7D1515", "w c #7D1515",
"x c #8B4242", "x c #8B4242",
"y c #A48F8F", "y c #A48F8F",
"z c #A0A0A0", "z c #A0A0A0",
"A c #8F8F8F", "A c #8F8F8F",
"B c #7C7C7C", "B c #7C7C7C",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
"................................ ", "................................ ",
".++++++++++++++++++++++++++++++. ", ".++++++++++++++++++++++++++++++. ",
".++++++++++++++++++++++++++++++. ", ".++++++++++++++++++++++++++++++. ",
".++++++++++++++++++++++++++++++. ", ".++++++++++++++++++++++++++++++. ",
".++++++++++++@#$%&*++++++++++++. ", ".++++++++++++@#$%&*++++++++++++. ",
".++++++++++=-;;;;;>,+++++++++++. ", ".++++++++++=-;;;;;>,+++++++++++. ",
".*********');;;;;;;!~**********. ", ".*********');;;;;;;!~**********. ",
".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ", ".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
".////////(_:::::::::<[/////////. ", ".////////(_:::::::::<[/////////. ",
".}}}}}}}}|111111111112}}}}}}}}}. ", ".}}}}}}}}|111111111112}}}}}}}}}. ",
".333333334555555555556333333333. ", ".333333334555555555556333333333. ",
".77777777890000000000a777777777. ", ".77777777890000000000a777777777. ",
".bbbbbbbbbcdddddddddefbbbbbbbbb. ", ".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
".ggggggggghijjjjjjjjkgggggggggg. ", ".ggggggggghijjjjjjjjkgggggggggg. ",
".llllllllllmnooooopqlllllllllll. ", ".llllllllllmnooooopqlllllllllll. ",
".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ", ".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ", ".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ", ".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ", ".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
"................................ ", "................................ ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" "}; " "};

View File

@ -1,124 +1,124 @@
/* XPM */ /* XPM */
static const char * Flag_Taiwan_xpm[] = { static const char * Flag_Taiwan_xpm[] = {
"96 32 89 1", "96 32 89 1",
" c None", " c None",
". c #000000", ". c #000000",
"# c #000099", "# c #000099",
"$ c #000098", "$ c #000098",
"% c #03039A", "% c #03039A",
"& c #000094", "& c #000094",
"' c #05059B", "' c #05059B",
"( c #050095", "( c #050095",
") c #DC0014", ") c #DC0014",
"* c #FF0000", "* c #FF0000",
"+ c #FD0001", "+ c #FD0001",
", c #04049B", ", c #04049B",
"- c #000096", "- c #000096",
"! c #020299", "! c #020299",
"0 c #2424A7", "0 c #2424A7",
"1 c #04049A", "1 c #04049A",
"2 c #000097", "2 c #000097",
"3 c #000093", "3 c #000093",
"4 c #6262BF", "4 c #6262BF",
"5 c #2828A8", "5 c #2828A8",
"6 c #6C6CC1", "6 c #6C6CC1",
"7 c #3E3EB1", "7 c #3E3EB1",
"8 c #3B3BB0", "8 c #3B3BB0",
"9 c #00008F", "9 c #00008F",
": c #01019A", ": c #01019A",
"; c #1919A3", "; c #1919A3",
"< c #4040B0", "< c #4040B0",
"= c #6363C0", "= c #6363C0",
"> c #D6D6EE", "> c #D6D6EE",
"? c #D9D9ED", "? c #D9D9ED",
"@ c #C5C5E7", "@ c #C5C5E7",
"A c #3F3FB0", "A c #3F3FB0",
"B c #3D3DAF", "B c #3D3DAF",
"C c #020297", "C c #020297",
"D c #010199", "D c #010199",
"E c #5E5EBE", "E c #5E5EBE",
"F c #DFDFF2", "F c #DFDFF2",
"G c white", "G c white",
"H c #BFBFE5", "H c #BFBFE5",
"I c #2626A7", "I c #2626A7",
"J c #4242B0", "J c #4242B0",
"K c #7D7DCA", "K c #7D7DCA",
"L c #FAFAFD", "L c #FAFAFD",
"M c #FBFBFD", "M c #FBFBFD",
"N c #FCFCFD", "N c #FCFCFD",
"O c #FCFCFE", "O c #FCFCFE",
"P c #DADAF0", "P c #DADAF0",
"Q c #6A6AC2", "Q c #6A6AC2",
"R c #1B1BA3", "R c #1B1BA3",
"S c #000199", "S c #000199",
"T c #0E0E9B", "T c #0E0E9B",
"U c #5858BC", "U c #5858BC",
"V c #D3D3ED", "V c #D3D3ED",
"W c #2727A6", "W c #2727A6",
"X c #060699", "X c #060699",
"Y c #1212A0", "Y c #1212A0",
"Z c #6464C0", "Z c #6464C0",
"[ c #8080CC", "[ c #8080CC",
"] c #F4F4FA", "] c #F4F4FA",
"^ c #F8F8FB", "^ c #F8F8FB",
"_ c #7070C4", "_ c #7070C4",
"` c #4949B5", "` c #4949B5",
"a c #000095", "a c #000095",
"b c #040499", "b c #040499",
"c c #000092", "c c #000092",
"d c #6767C2", "d c #6767C2",
"e c #8686CA", "e c #8686CA",
"f c #7070C5", "f c #7070C5",
"g c #2B2BA9", "g c #2B2BA9",
"h c #00009A", "h c #00009A",
"i c #01049C", "i c #01049C",
"j c #1619A4", "j c #1619A4",
"k c #393CB3", "k c #393CB3",
"l c #00029A", "l c #00029A",
"m c #1619A5", "m c #1619A5",
"n c #020096", "n c #020096",
"o c #DB0014", "o c #DB0014",
"p c #FC0001", "p c #FC0001",
"q c #0A0092", "q c #0A0092",
"r c #060090", "r c #060090",
"s c #0B0092", "s c #0B0092",
"t c #0F008E", "t c #0F008E",
"u c #DD0013", "u c #DD0013",
"v c #FD0000", "v c #FD0000",
"w c #E5000F", "w c #E5000F",
"x c #E6010F", "x c #E6010F",
"y c #E60110", "y c #E60110",
"z c #FB0002", "z c #FB0002",
"{ c #FE0000", "{ c #FE0000",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
"................................ ", "................................ ",
".#####$%#&'$$$##()*+***********. ", ".#####$%#&'$$$##()*+***********. ",
".###$$,-!0&1!$##()*+***********. ", ".###$$,-!0&1!$##()*+***********. ",
".##$#23456789:$#()*+***********. ", ".##$#23456789:$#()*+***********. ",
".###2;<=>?@ABCD#()*+***********. ", ".###2;<=>?@ABCD#()*+***********. ",
".###$CEFGGGHI&D$()*+***********. ", ".###$CEFGGGHI&D$()*+***********. ",
".##D-JKLMNOPQR-S()*+***********. ", ".##D-JKLMNOPQR-S()*+***********. ",
".###$TUGGNGVWX$#()*+***********. ", ".###$TUGGNGVWX$#()*+***********. ",
".###2YZ[]^P_`aD$()*+***********. ", ".###2YZ[]^P_`aD$()*+***********. ",
".###$bcdEefg3D$#()*+***********. ", ".###$bcdEefg3D$#()*+***********. ",
".hhhhhijiklm#hhhno*p***********. ", ".hhhhhijiklm#hhhno*p***********. ",
".qqqqqqrsrqrqqqqtu*v***********. ", ".qqqqqqrsrqrqqqqtu*v***********. ",
".wwwwwwxwywxwwwwwz*{***********. ", ".wwwwwwxwywxwwwwwz*{***********. ",
".******************************. ", ".******************************. ",
".{{{{{{{{{{{{{{{{{*{***********. ", ".{{{{{{{{{{{{{{{{{*{***********. ",
".******************************. ", ".******************************. ",
".******************************. ", ".******************************. ",
".******************************. ", ".******************************. ",
".******************************. ", ".******************************. ",
"................................ ", "................................ ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" "}; " "};

View File

@ -1,65 +1,65 @@
/* XPM */ /* XPM */
static const char * Flag_USA_xpm[] = { static const char * Flag_USA_xpm[] = {
"96 32 30 1", "96 32 30 1",
" c None", " c None",
". c #000000", ". c #000000",
"+ c #0000FF", "+ c #0000FF",
"@ c #CE7070", "@ c #CE7070",
"# c #B0BF99", "# c #B0BF99",
"$ c #F1F1F1", "$ c #F1F1F1",
"% c #FFFFFF", "% c #FFFFFF",
"& c #0000FD", "& c #0000FD",
"* c #CF8484", "* c #CF8484",
"= c #DA9090", "= c #DA9090",
"- c #0000F3", "- c #0000F3",
"; c #B0BF96", "; c #B0BF96",
"> c #0000DF", "> c #0000DF",
", c #0000CB", ", c #0000CB",
"' c #B0BF8C", "' c #B0BF8C",
") c #D98E8E", ") c #D98E8E",
"! c #0000B5", "! c #0000B5",
"~ c #CA6C6C", "~ c #CA6C6C",
"{ c #000098", "{ c #000098",
"] c #B0BF80", "] c #B0BF80",
"^ c #000077", "^ c #000077",
"/ c #C26464", "/ c #C26464",
"( c #DBDBDB", "( c #DBDBDB",
"_ c #C17676", "_ c #C17676",
": c #B55757", ": c #B55757",
"< c #BBBBBB", "< c #BBBBBB",
"[ c #AC6161", "[ c #AC6161",
"} c #A34545", "} c #A34545",
"| c #8B8B8B", "| c #8B8B8B",
"1 c #8E4343", "1 c #8E4343",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
"................................ ", "................................ ",
".++++++++++++++@@@@@@@@@@@@@@@@. ", ".++++++++++++++@@@@@@@@@@@@@@@@. ",
".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ", ".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
".&&&&&&&&&&&&&&*===============. ", ".&&&&&&&&&&&&&&*===============. ",
".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ", ".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ", ".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
".,',',',',',',,*))))))))))))))). ", ".,',',',',',',,*))))))))))))))). ",
".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ", ".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ", ".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
".^^^^^^^^^^^^^^****************. ", ".^^^^^^^^^^^^^^****************. ",
".^^^^^^^^^^^^^^@///////////////. ", ".^^^^^^^^^^^^^^@///////////////. ",
".((((((((((((((((((((((((((((((. ", ".((((((((((((((((((((((((((((((. ",
".______________________________. ", ".______________________________. ",
".::::::::::::::::::::::::::::::. ", ".::::::::::::::::::::::::::::::. ",
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ", ".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ", ".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ", ".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
".||||||||||||||||||||||||||||||. ", ".||||||||||||||||||||||||||||||. ",
".111111111111111111111111111111. ", ".111111111111111111111111111111. ",
"................................ ", "................................ ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" ", " ",
" "}; " "};

View File

@ -1,179 +1,179 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "AVIDump.h" #include "AVIDump.h"
#include "tchar.h" #include "tchar.h"
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <vfw.h> #include <vfw.h>
#include <winerror.h> #include <winerror.h>
#include "FileUtil.h" #include "FileUtil.h"
#include "CommonPaths.h" #include "CommonPaths.h"
#include "Log.h" #include "Log.h"
static HWND m_emuWnd; static HWND m_emuWnd;
static int m_width; static int m_width;
static int m_height; static int m_height;
static LONG m_byteBuffer; static LONG m_byteBuffer;
static LONG m_frameCount; static LONG m_frameCount;
static LONG m_totalBytes; static LONG m_totalBytes;
static PAVIFILE m_file; static PAVIFILE m_file;
static int m_fileCount; static int m_fileCount;
static PAVISTREAM m_stream; static PAVISTREAM m_stream;
static PAVISTREAM m_streamCompressed; static PAVISTREAM m_streamCompressed;
static AVISTREAMINFO m_header; static AVISTREAMINFO m_header;
static AVICOMPRESSOPTIONS m_options; static AVICOMPRESSOPTIONS m_options;
static AVICOMPRESSOPTIONS *m_arrayOptions[1]; static AVICOMPRESSOPTIONS *m_arrayOptions[1];
static BITMAPINFOHEADER m_bitmap; static BITMAPINFOHEADER m_bitmap;
bool AVIDump::Start(HWND hWnd, int w, int h) bool AVIDump::Start(HWND hWnd, int w, int h)
{ {
m_emuWnd = hWnd; m_emuWnd = hWnd;
m_fileCount = 0; m_fileCount = 0;
m_width = w; m_width = w;
m_height = h; m_height = h;
return CreateFile(); return CreateFile();
} }
bool AVIDump::CreateFile() bool AVIDump::CreateFile()
{ {
m_totalBytes = 0; m_totalBytes = 0;
m_frameCount = 0; m_frameCount = 0;
char movie_file_name[255]; char movie_file_name[255];
sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount); sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
// Create path // Create path
File::CreateFullPath(movie_file_name); File::CreateFullPath(movie_file_name);
// Ask to delete file // Ask to delete file
if (File::Exists(movie_file_name)) if (File::Exists(movie_file_name))
{ {
if (AskYesNo("Delete the existing file '%s'?", movie_file_name)) if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
File::Delete(movie_file_name); File::Delete(movie_file_name);
} }
AVIFileInit(); AVIFileInit();
NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name); NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
// TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG // 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); HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
if (FAILED(hr)) { 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_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_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_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 == 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"); if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
Stop(); Stop();
return false; return false;
} }
SetBitmapFormat(); SetBitmapFormat();
NOTICE_LOG(VIDEO, "Setting video format..."); NOTICE_LOG(VIDEO, "Setting video format...");
if (!SetVideoFormat()) { if (!SetVideoFormat()) {
NOTICE_LOG(VIDEO, "Setting video format failed"); NOTICE_LOG(VIDEO, "Setting video format failed");
Stop(); Stop();
return false; return false;
} }
if (!m_fileCount) { if (!m_fileCount) {
if (!SetCompressionOptions()) { if (!SetCompressionOptions()) {
NOTICE_LOG(VIDEO, "SetCompressionOptions failed"); NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
Stop(); Stop();
return false; return false;
} }
} }
if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) { if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed"); NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
Stop(); Stop();
return false; return false;
} }
if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) { if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed"); NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
Stop(); Stop();
return false; return false;
} }
return true; return true;
} }
void AVIDump::CloseFile() void AVIDump::CloseFile()
{ {
if (m_streamCompressed) { if (m_streamCompressed) {
AVIStreamClose(m_streamCompressed); AVIStreamClose(m_streamCompressed);
m_streamCompressed = NULL; m_streamCompressed = NULL;
} }
if (m_stream) { if (m_stream) {
AVIStreamClose(m_stream); AVIStreamClose(m_stream);
m_stream = NULL; m_stream = NULL;
} }
if (m_file) { if (m_file) {
AVIFileRelease(m_file); AVIFileRelease(m_file);
m_file = NULL; m_file = NULL;
} }
AVIFileExit(); AVIFileExit();
} }
void AVIDump::Stop() void AVIDump::Stop()
{ {
CloseFile(); CloseFile();
m_fileCount = 0; m_fileCount = 0;
NOTICE_LOG(VIDEO, "Stop"); NOTICE_LOG(VIDEO, "Stop");
} }
void AVIDump::AddFrame(char *data) void AVIDump::AddFrame(char *data)
{ {
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer); AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
m_totalBytes += m_byteBuffer; m_totalBytes += m_byteBuffer;
// Close the recording if the file is more than 2gb // 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. // VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
if (m_totalBytes >= 2000000000) { if (m_totalBytes >= 2000000000) {
CloseFile(); CloseFile();
m_fileCount++; m_fileCount++;
CreateFile(); CreateFile();
} }
} }
void AVIDump::SetBitmapFormat() void AVIDump::SetBitmapFormat()
{ {
memset(&m_bitmap, 0, sizeof(m_bitmap)); memset(&m_bitmap, 0, sizeof(m_bitmap));
m_bitmap.biSize = 0x28; m_bitmap.biSize = 0x28;
m_bitmap.biPlanes = 1; m_bitmap.biPlanes = 1;
m_bitmap.biBitCount = 24; m_bitmap.biBitCount = 24;
m_bitmap.biWidth = m_width; m_bitmap.biWidth = m_width;
m_bitmap.biHeight = m_height; m_bitmap.biHeight = m_height;
m_bitmap.biSizeImage = 3 * m_width * m_height; m_bitmap.biSizeImage = 3 * m_width * m_height;
} }
bool AVIDump::SetCompressionOptions() bool AVIDump::SetCompressionOptions()
{ {
memset(&m_options, 0, sizeof(m_options)); memset(&m_options, 0, sizeof(m_options));
m_arrayOptions[0] = &m_options; m_arrayOptions[0] = &m_options;
return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0); return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
} }
bool AVIDump::SetVideoFormat() bool AVIDump::SetVideoFormat()
{ {
memset(&m_header, 0, sizeof(m_header)); memset(&m_header, 0, sizeof(m_header));
m_header.fccType = streamtypeVIDEO; m_header.fccType = streamtypeVIDEO;
m_header.dwScale = 1; m_header.dwScale = 1;
// TODO: Decect FPS using NTSC/PAL // TODO: Decect FPS using NTSC/PAL
m_header.dwRate = 60; m_header.dwRate = 60;
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage; m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header)); return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
} }

View File

@ -1,60 +1,60 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// ------------------------------------------ // ------------------------------------------
// The plugins has to define these functions // The plugins has to define these functions
// ------------------------------------------ // ------------------------------------------
#ifndef _BPFUNCTIONS_H_ #ifndef _BPFUNCTIONS_H_
#define _BPFUNCTIONS_H_ #define _BPFUNCTIONS_H_
#include "BPMemory.h" #include "BPMemory.h"
#include "VideoCommon.h" #include "VideoCommon.h"
namespace BPFunctions namespace BPFunctions
{ {
enum enum
{ {
CONFIG_ISWII = 0, CONFIG_ISWII = 0,
CONFIG_DISABLEFOG, CONFIG_DISABLEFOG,
CONFIG_SHOWEFBREGIONS CONFIG_SHOWEFBREGIONS
}; };
void FlushPipeline(); void FlushPipeline();
void SetGenerationMode(const Bypass &bp); void SetGenerationMode(const Bypass &bp);
void SetScissor(const Bypass &bp); void SetScissor(const Bypass &bp);
void SetLineWidth(const Bypass &bp); void SetLineWidth(const Bypass &bp);
void SetDepthMode(const Bypass &bp); void SetDepthMode(const Bypass &bp);
void SetBlendMode(const Bypass &bp); void SetBlendMode(const Bypass &bp);
void SetDitherMode(const Bypass &bp); void SetDitherMode(const Bypass &bp);
void SetLogicOpMode(const Bypass &bp); void SetLogicOpMode(const Bypass &bp);
void SetColorMask(const Bypass &bp); void SetColorMask(const Bypass &bp);
float GetRendererTargetScaleX(); float GetRendererTargetScaleX();
float GetRendererTargetScaleY(); 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 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 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 ClearScreen(const Bypass &bp, const TRectangle &multirc);
void RestoreRenderState(const Bypass &bp); void RestoreRenderState(const Bypass &bp);
u8 *GetPointer(const u32 &address); u8 *GetPointer(const u32 &address);
bool GetConfig(const int &type); bool GetConfig(const int &type);
void SetSamplerState(const Bypass &bp); void SetSamplerState(const Bypass &bp);
void SetInterlacingMode(const Bypass &bp); void SetInterlacingMode(const Bypass &bp);
}; };
#endif // _BPFUNCTIONS_H_ #endif // _BPFUNCTIONS_H_

File diff suppressed because it is too large Load Diff

View File

@ -1,27 +1,27 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _BPSTRUCTS_H_ #ifndef _BPSTRUCTS_H_
#define _BPSTRUCTS_H_ #define _BPSTRUCTS_H_
#include "BPMemory.h" #include "BPMemory.h"
void BPInit(); void BPInit();
void LoadBPReg(u32 value0); void LoadBPReg(u32 value0);
void BPReload(); void BPReload();
#endif // _BPSTRUCTS_H_ #endif // _BPSTRUCTS_H_

View File

@ -1,154 +1,154 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "HiresTextures.h" #include "HiresTextures.h"
#include <cstring> #include <cstring>
#include <utility> #include <utility>
#include <algorithm> #include <algorithm>
#include "SOIL.h" #include "SOIL.h"
#include "CommonPaths.h" #include "CommonPaths.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "FileSearch.h" #include "FileSearch.h"
namespace HiresTextures namespace HiresTextures
{ {
std::map<std::string, std::string> textureMap; std::map<std::string, std::string> textureMap;
void Init(const char *gameCode) void Init(const char *gameCode)
{ {
static bool bCheckedDir; static bool bCheckedDir;
CFileSearch::XStringVector Directories; CFileSearch::XStringVector Directories;
//Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR)); //Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
char szDir[MAX_PATH]; char szDir[MAX_PATH];
sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode); sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
Directories.push_back(std::string(szDir)); Directories.push_back(std::string(szDir));
for (u32 i = 0; i < Directories.size(); i++) for (u32 i = 0; i < Directories.size(); i++)
{ {
File::FSTEntry FST_Temp; File::FSTEntry FST_Temp;
File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp); File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
for (u32 j = 0; j < FST_Temp.children.size(); j++) for (u32 j = 0; j < FST_Temp.children.size(); j++)
{ {
if (FST_Temp.children.at(j).isDirectory) if (FST_Temp.children.at(j).isDirectory)
{ {
bool duplicate = false; bool duplicate = false;
NormalizeDirSep(&(FST_Temp.children.at(j).physicalName)); NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
for (u32 k = 0; k < Directories.size(); k++) for (u32 k = 0; k < Directories.size(); k++)
{ {
NormalizeDirSep(&Directories.at(k)); NormalizeDirSep(&Directories.at(k));
if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0) if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
{ {
duplicate = true; duplicate = true;
break; break;
} }
} }
if (!duplicate) if (!duplicate)
Directories.push_back(FST_Temp.children.at(j).physicalName.c_str()); Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
} }
} }
} }
CFileSearch::XStringVector Extensions; CFileSearch::XStringVector Extensions;
Extensions.push_back("*.png"); Extensions.push_back("*.png");
Extensions.push_back("*.bmp"); Extensions.push_back("*.bmp");
Extensions.push_back("*.tga"); Extensions.push_back("*.tga");
Extensions.push_back("*.dds"); Extensions.push_back("*.dds");
Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
CFileSearch FileSearch(Extensions, Directories); CFileSearch FileSearch(Extensions, Directories);
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames(); const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
char code[MAX_PATH]; char code[MAX_PATH];
sprintf(code, "%s_", gameCode); sprintf(code, "%s_", gameCode);
if (rFilenames.size() > 0) if (rFilenames.size() > 0)
{ {
for (u32 i = 0; i < rFilenames.size(); i++) for (u32 i = 0; i < rFilenames.size(); i++)
{ {
std::string FileName; std::string FileName;
SplitPath(rFilenames[i], NULL, &FileName, NULL); SplitPath(rFilenames[i], NULL, &FileName, NULL);
if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end()) 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])); textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
} }
} }
} }
void Shutdown() void Shutdown()
{ {
textureMap.clear(); textureMap.clear();
} }
PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data) PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
{ {
std::string key(fileName); std::string key(fileName);
if(textureMap.find(key) == textureMap.end()) if(textureMap.find(key) == textureMap.end())
return PC_TEX_FMT_NONE; return PC_TEX_FMT_NONE;
int width; int width;
int height; int height;
int channels; int channels;
u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA); u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
if (temp == NULL) { if (temp == NULL) {
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height); ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
SOIL_free_image_data(temp); SOIL_free_image_data(temp);
return PC_TEX_FMT_NONE; return PC_TEX_FMT_NONE;
} }
if (width > 1024 || height > 1024) { 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); 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); SOIL_free_image_data(temp);
return PC_TEX_FMT_NONE; return PC_TEX_FMT_NONE;
} }
int offset = 0; int offset = 0;
PC_TexFormat returnTex; PC_TexFormat returnTex;
switch (texformat) switch (texformat)
{ {
case GX_TF_I4: case GX_TF_I4:
case GX_TF_I8: case GX_TF_I8:
case GX_TF_IA4: case GX_TF_IA4:
case GX_TF_IA8: case GX_TF_IA8:
for (int i = 0; i < width * height * 4; i += 4) for (int i = 0; i < width * height * 4; i += 4)
{ {
// Rather than use a luminosity function, just use the most intense color for luminance // 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++] = *std::max_element(temp+i, temp+i+3);
data[offset++] = temp[i+3]; data[offset++] = temp[i+3];
} }
returnTex = PC_TEX_FMT_IA8; returnTex = PC_TEX_FMT_IA8;
break; break;
default: default:
memcpy(data, temp, width*height*4); memcpy(data, temp, width*height*4);
returnTex = PC_TEX_FMT_RGBA32; returnTex = PC_TEX_FMT_RGBA32;
break; break;
} }
*pWidth = width; *pWidth = width;
*pHeight = height; *pHeight = height;
SOIL_free_image_data(temp); SOIL_free_image_data(temp);
INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str()); INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
return returnTex; return returnTex;
} }
} }

View File

@ -1,18 +1,18 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Dummy file for common to compile // Dummy file for common to compile

View File

@ -1,119 +1,119 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
// Stubs to make DSPCore compile as part of DSPSpy. // Stubs to make DSPCore compile as part of DSPSpy.
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string> #include <string>
#include "Thread.h" #include "Thread.h"
void *AllocateMemoryPages(size_t size) void *AllocateMemoryPages(size_t size)
{ {
return malloc(size); return malloc(size);
} }
void FreeMemoryPages(void *pages, size_t size) void FreeMemoryPages(void *pages, size_t size)
{ {
free(pages); free(pages);
} }
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{ {
} }
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{ {
} }
bool DSPHost_OnThread() bool DSPHost_OnThread()
{ {
return false; return false;
} }
// Well, it's just RAM right? :) // Well, it's just RAM right? :)
u8 DSPHost_ReadHostMemory(u32 address) u8 DSPHost_ReadHostMemory(u32 address)
{ {
u8 *ptr = (u8*)address; u8 *ptr = (u8*)address;
return *ptr; return *ptr;
} }
void DSPHost_WriteHostMemory(u8 value, u32 addr) {} void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
void DSPHost_CodeLoaded(const u8 *code, int size) void DSPHost_CodeLoaded(const u8 *code, int size)
{ {
} }
namespace Common namespace Common
{ {
CriticalSection::CriticalSection(int) CriticalSection::CriticalSection(int)
{ {
} }
CriticalSection::~CriticalSection() CriticalSection::~CriticalSection()
{ {
} }
void CriticalSection::Enter() void CriticalSection::Enter()
{ {
} }
void CriticalSection::Leave() void CriticalSection::Leave()
{ {
} }
} // namespace } // namespace
namespace File namespace File
{ {
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{ {
FILE *f = fopen(filename, text_file ? "w" : "wb"); FILE *f = fopen(filename, text_file ? "w" : "wb");
if (!f) if (!f)
return false; return false;
size_t len = str.size(); size_t len = str.size();
if (len != fwrite(str.data(), 1, str.size(), f)) if (len != fwrite(str.data(), 1, str.size(), f))
{ {
fclose(f); fclose(f);
return false; return false;
} }
fclose(f); fclose(f);
return true; return true;
} }
bool ReadFileToString(bool text_file, const char *filename, std::string &str) bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{ {
FILE *f = fopen(filename, text_file ? "r" : "rb"); FILE *f = fopen(filename, text_file ? "r" : "rb");
if (!f) if (!f)
return false; return false;
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
size_t len = ftell(f); size_t len = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
char *buf = new char[len + 1]; char *buf = new char[len + 1];
buf[fread(buf, 1, len, f)] = 0; buf[fread(buf, 1, len, f)] = 0;
str = std::string(buf, len); str = std::string(buf, len);
fclose(f); fclose(f);
delete [] buf; delete [] buf;
return true; return true;
} }
} }

View File

@ -1,43 +1,43 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "dsp_interface.h" #include "dsp_interface.h"
void IDSP::SendTask(void *addr, u16 iram_addr, u16 len, u16 start) void IDSP::SendTask(void *addr, u16 iram_addr, u16 len, u16 start)
{ {
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(0x80F3A001); SendMailTo(0x80F3A001);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo((u32)addr); SendMailTo((u32)addr);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(0x80F3C002); SendMailTo(0x80F3C002);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(iram_addr); SendMailTo(iram_addr);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(0x80F3A002); SendMailTo(0x80F3A002);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(len); SendMailTo(len);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(0x80F3B002); SendMailTo(0x80F3B002);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(0); SendMailTo(0);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(0x80F3D001); SendMailTo(0x80F3D001);
while (CheckMailTo()); while (CheckMailTo());
SendMailTo(start); SendMailTo(start);
while (CheckMailTo()); while (CheckMailTo());
} }

View File

@ -1,50 +1,50 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DSP_INTERFACE_H #ifndef _DSP_INTERFACE_H
#define _DSP_INTERFACE_H #define _DSP_INTERFACE_H
#include <gccore.h> #include <gccore.h>
// DSPCR bits // DSPCR bits
#define DSPCR_DSPRESET 0x0800 // Reset DSP #define DSPCR_DSPRESET 0x0800 // Reset DSP
#define DSPCR_ARDMA 0x0200 // ARAM dma in progress, if set #define DSPCR_ARDMA 0x0200 // ARAM dma in progress, if set
#define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW) #define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
#define DSPCR_DSPINT 0x0080 // * interrupt active (RWC) #define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
#define DSPCR_ARINTMSK 0x0040 #define DSPCR_ARINTMSK 0x0040
#define DSPCR_ARINT 0x0020 #define DSPCR_ARINT 0x0020
#define DSPCR_AIINTMSK 0x0010 #define DSPCR_AIINTMSK 0x0010
#define DSPCR_AIINT 0x0008 #define DSPCR_AIINT 0x0008
#define DSPCR_HALT 0x0004 // halt DSP #define DSPCR_HALT 0x0004 // halt DSP
#define DSPCR_PIINT 0x0002 // assert DSP PI interrupt #define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
#define DSPCR_RES 0x0001 // reset DSP #define DSPCR_RES 0x0001 // reset DSP
class IDSP { class IDSP {
public: public:
virtual ~IDSP() {} virtual ~IDSP() {}
virtual void Init() = 0; virtual void Init() = 0;
virtual void Reset() = 0; virtual void Reset() = 0;
virtual u32 CheckMailTo() = 0; virtual u32 CheckMailTo() = 0;
virtual void SendMailTo(u32 mail) = 0; virtual void SendMailTo(u32 mail) = 0;
// Yeah, yeah, having a method here makes this not a pure interface - but // Yeah, yeah, having a method here makes this not a pure interface - but
// the implementation does nothing but calling the virtual methods above. // the implementation does nothing but calling the virtual methods above.
void SendTask(void *addr, u16 iram_addr, u16 len, u16 start); void SendTask(void *addr, u16 iram_addr, u16 len, u16 start);
}; };
#endif // _DSP_INTERFACE_H #endif // _DSP_INTERFACE_H

File diff suppressed because it is too large Load Diff

View File

@ -1,68 +1,68 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <gccore.h> #include <gccore.h>
#include <ogcsys.h> #include <ogcsys.h>
#include <ogc/dsp.h> #include <ogc/dsp.h>
#include <ogc/irq.h> #include <ogc/irq.h>
#include <ogc/machine/asm.h> #include <ogc/machine/asm.h>
#include <ogc/machine/processor.h> #include <ogc/machine/processor.h>
#include "dsp_interface.h" #include "dsp_interface.h"
#include "real_dsp.h" #include "real_dsp.h"
static vu16* const _dspReg = (u16*)0xCC005000; static vu16* const _dspReg = (u16*)0xCC005000;
// Handler for DSP interrupt. // Handler for DSP interrupt.
static void dsp_irq_handler(u32 nIrq, void *pCtx) static void dsp_irq_handler(u32 nIrq, void *pCtx)
{ {
// Acknowledge interrupt? // Acknowledge interrupt?
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT)) | DSPCR_DSPINT; _dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT)) | DSPCR_DSPINT;
} }
void RealDSP::Init() void RealDSP::Init()
{ {
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET; _dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET;
_dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)); _dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT));
// This code looks odd - shouldn't we initialize level? // This code looks odd - shouldn't we initialize level?
u32 level; u32 level;
_CPU_ISR_Disable(level); _CPU_ISR_Disable(level);
IRQ_Request(IRQ_DSP_DSP, dsp_irq_handler, NULL); IRQ_Request(IRQ_DSP_DSP, dsp_irq_handler, NULL);
_CPU_ISR_Restore(level); _CPU_ISR_Restore(level);
} }
void RealDSP::Reset() void RealDSP::Reset()
{ {
// Reset the DSP. // Reset the DSP.
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET; _dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET;
_dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)); _dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT));
_dspReg[5] |= DSPCR_RES; _dspReg[5] |= DSPCR_RES;
while (_dspReg[5] & DSPCR_RES) while (_dspReg[5] & DSPCR_RES)
; ;
_dspReg[9] = 0x63; _dspReg[9] = 0x63;
} }
u32 RealDSP::CheckMailTo() u32 RealDSP::CheckMailTo()
{ {
return DSP_CheckMailTo(); return DSP_CheckMailTo();
} }
void RealDSP::SendMailTo(u32 mail) void RealDSP::SendMailTo(u32 mail)
{ {
DSP_SendMailTo(mail); DSP_SendMailTo(mail);
} }

View File

@ -1,31 +1,31 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _REAL_DSP_H #ifndef _REAL_DSP_H
#define _REAL_DSP_H #define _REAL_DSP_H
#include "dsp_interface.h" #include "dsp_interface.h"
class RealDSP : public IDSP { class RealDSP : public IDSP {
public: public:
virtual void Init(); virtual void Init();
virtual void Reset(); virtual void Reset();
virtual u32 CheckMailTo(); virtual u32 CheckMailTo();
virtual void SendMailTo(u32 mail); virtual void SendMailTo(u32 mail);
}; };
#endif // _REAL_DSP_H #endif // _REAL_DSP_H

View File

@ -1,403 +1,403 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "DSPCodeUtil.h" #include "DSPCodeUtil.h"
// Stub out the dsplib host stuff, since this is just a simple cmdline tools. // Stub out the dsplib host stuff, since this is just a simple cmdline tools.
u8 DSPHost_ReadHostMemory(u32 addr) { return 0; } u8 DSPHost_ReadHostMemory(u32 addr) { return 0; }
void DSPHost_WriteHostMemory(u8 value, u32 addr) {} void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
bool DSPHost_OnThread() { return false; } bool DSPHost_OnThread() { return false; }
bool DSPHost_Running() { return true; } bool DSPHost_Running() { return true; }
u32 DSPHost_CodeLoaded(const u8 *ptr, int size) {return 0x1337c0de;} u32 DSPHost_CodeLoaded(const u8 *ptr, int size) {return 0x1337c0de;}
void DSPHost_InterruptRequest() {} void DSPHost_InterruptRequest() {}
void DSPHost_UpdateDebugger() {} void DSPHost_UpdateDebugger() {}
// This test goes from text ASM to binary to text ASM and once again back to binary. // This test goes from text ASM to binary to text ASM and once again back to binary.
// Then the two binaries are compared. // Then the two binaries are compared.
bool RoundTrip(const std::vector<u16> &code1) bool RoundTrip(const std::vector<u16> &code1)
{ {
std::vector<u16> code2; std::vector<u16> code2;
std::string text; std::string text;
if (!Disassemble(code1, false, text)) if (!Disassemble(code1, false, text))
{ {
printf("RoundTrip: Disassembly failed.\n"); printf("RoundTrip: Disassembly failed.\n");
return false; return false;
} }
if (!Assemble(text.c_str(), code2)) if (!Assemble(text.c_str(), code2))
{ {
printf("RoundTrip: Assembly failed.\n"); printf("RoundTrip: Assembly failed.\n");
return false; return false;
} }
if (!Compare(code1, code2)) if (!Compare(code1, code2))
{ {
Disassemble(code1, true, text); Disassemble(code1, true, text);
printf("%s", text.c_str()); printf("%s", text.c_str());
} }
return true; return true;
} }
// This test goes from text ASM to binary to text ASM and once again back to binary. // This test goes from text ASM to binary to text ASM and once again back to binary.
// Very convenient for testing. Then the two binaries are compared. // Very convenient for testing. Then the two binaries are compared.
bool SuperTrip(const char *asm_code) bool SuperTrip(const char *asm_code)
{ {
std::vector<u16> code1, code2; std::vector<u16> code1, code2;
std::string text; std::string text;
if (!Assemble(asm_code, code1)) if (!Assemble(asm_code, code1))
{ {
printf("SuperTrip: First assembly failed\n"); printf("SuperTrip: First assembly failed\n");
return false; return false;
} }
printf("First assembly: %i words\n", (int)code1.size()); printf("First assembly: %i words\n", (int)code1.size());
if (!Disassemble(code1, false, text)) if (!Disassemble(code1, false, text))
{ {
printf("SuperTrip: Disassembly failed\n"); printf("SuperTrip: Disassembly failed\n");
return false; return false;
} }
else else
{ {
printf("Disass:\n"); printf("Disass:\n");
printf("%s", text.c_str()); printf("%s", text.c_str());
} }
if (!Assemble(text.c_str(), code2)) if (!Assemble(text.c_str(), code2))
{ {
printf("SuperTrip: Second assembly failed\n"); printf("SuperTrip: Second assembly failed\n");
return false; return false;
} }
/* /*
std::string text2; std::string text2;
Disassemble(code1, true, &text1); Disassemble(code1, true, &text1);
Disassemble(code2, true, &text2); Disassemble(code2, true, &text2);
File::WriteStringToFile(true, text1, "code1.txt"); File::WriteStringToFile(true, text1, "code1.txt");
File::WriteStringToFile(true, text2, "code2.txt"); File::WriteStringToFile(true, text2, "code2.txt");
*/ */
return true; return true;
} }
void RunAsmTests() void RunAsmTests()
{ {
bool fail = false; bool fail = false;
#define CHK(a) if (!SuperTrip(a)) printf("FAIL\n%s\n", a), fail = true; #define CHK(a) if (!SuperTrip(a)) printf("FAIL\n%s\n", a), fail = true;
// Let's start out easy - a trivial instruction.. // Let's start out easy - a trivial instruction..
CHK(" NOP\n"); CHK(" NOP\n");
// Now let's do several. // Now let's do several.
CHK(" NOP\n" CHK(" NOP\n"
" NOP\n" " NOP\n"
" NOP\n"); " NOP\n");
// Turning it up a notch. // Turning it up a notch.
CHK(" SET16\n" CHK(" SET16\n"
" SET40\n" " SET40\n"
" CLR15\n" " CLR15\n"
" M0\n" " M0\n"
" M2\n"); " M2\n");
// Time to try labels and parameters, and comments. // Time to try labels and parameters, and comments.
CHK("DIRQ_TEST: equ 0xfffb ; DSP Irq Request\n" CHK("DIRQ_TEST: equ 0xfffb ; DSP Irq Request\n"
" si @0xfffc, #0x8888\n" " si @0xfffc, #0x8888\n"
" si @0xfffd, #0xbeef\n" " si @0xfffd, #0xbeef\n"
" si @DIRQ_TEST, #0x0001\n"); " si @DIRQ_TEST, #0x0001\n");
// Let's see if registers roundtrip. Also try predefined labels. // Let's see if registers roundtrip. Also try predefined labels.
CHK(" si @0xfffc, #0x8888\n" CHK(" si @0xfffc, #0x8888\n"
" si @0xfffd, #0xbeef\n" " si @0xfffd, #0xbeef\n"
" si @DIRQ, #0x0001\n"); " si @DIRQ, #0x0001\n");
// Let's try some messy extended instructions. // Let's try some messy extended instructions.
//CHK(" MULMV'SN $AX0.L, $AX0.H, $ACC0 : @$AR2, $AC1.M\n"); //CHK(" MULMV'SN $AX0.L, $AX0.H, $ACC0 : @$AR2, $AC1.M\n");
//" ADDAXL'MV $ACC1, $AX1.L : $AX1.H, $AC1.M\n"); //" ADDAXL'MV $ACC1, $AX1.L : $AX1.H, $AC1.M\n");
// Let's get brutal. We generate random code bytes and make sure that they can // Let's get brutal. We generate random code bytes and make sure that they can
// be roundtripped. We don't expect it to always succeed but it'll be sure to generate // be roundtripped. We don't expect it to always succeed but it'll be sure to generate
// interesting test cases. // interesting test cases.
/* /*
std::vector<u16> hermes; std::vector<u16> hermes;
if (!LoadBinary("testdata/hermes.bin", &hermes)) if (!LoadBinary("testdata/hermes.bin", &hermes))
PanicAlert("Failed to load hermes rom"); PanicAlert("Failed to load hermes rom");
RoundTrip(hermes); RoundTrip(hermes);
*/ */
/* /*
std::vector<u16> code; std::vector<u16> code;
std::string text_orig; std::string text_orig;
File::ReadFileToString(false, "testdata/dsp_test.S", &text_orig); File::ReadFileToString(false, "testdata/dsp_test.S", &text_orig);
if (!Assemble(text_orig.c_str(), &code)) if (!Assemble(text_orig.c_str(), &code))
{ {
printf("SuperTrip: First assembly failed\n"); printf("SuperTrip: First assembly failed\n");
return; return;
}*/ }*/
/* /*
{ {
std::vector<u16> code; std::vector<u16> code;
code.clear(); code.clear();
for (int i = 0; i < sizeof(dsp_test)/4; i++) for (int i = 0; i < sizeof(dsp_test)/4; i++)
{ {
code.push_back(dsp_test[i] >> 16); code.push_back(dsp_test[i] >> 16);
code.push_back(dsp_test[i] & 0xFFFF); code.push_back(dsp_test[i] & 0xFFFF);
} }
SaveBinary(code, "dsp_test2.bin"); SaveBinary(code, "dsp_test2.bin");
RoundTrip(code); RoundTrip(code);
}*/ }*/
//if (Compare(code, hermes)) //if (Compare(code, hermes))
// printf("Successs\n"); // printf("Successs\n");
/* /*
{ {
std::vector<u16> code; std::vector<u16> code;
std::string text; std::string text;
LoadBinary("testdata/dsp_test.bin", &code); LoadBinary("testdata/dsp_test.bin", &code);
Disassemble(code, true, &text); Disassemble(code, true, &text);
Assemble(text.c_str(), &code); Assemble(text.c_str(), &code);
Disassemble(code, true, &text); Disassemble(code, true, &text);
printf("%s", text.c_str()); printf("%s", text.c_str());
}*/ }*/
/* /*
puts("Insane Random Code Test\n"); puts("Insane Random Code Test\n");
std::vector<u16> rand_code; std::vector<u16> rand_code;
GenRandomCode(30, &rand_code); GenRandomCode(30, &rand_code);
std::string rand_code_text; std::string rand_code_text;
Disassemble(rand_code, true, &rand_code_text); Disassemble(rand_code, true, &rand_code_text);
printf("%s", rand_code_text.c_str()); printf("%s", rand_code_text.c_str());
RoundTrip(rand_code); RoundTrip(rand_code);
if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test)) if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))
SuperTrip(dsp_test.c_str()); SuperTrip(dsp_test.c_str());
//.File::ReadFileToString(true, "C:/devkitPro/trunk/libogc/libasnd/dsp_mixer/dsp_mixer.s", &dsp_test); //.File::ReadFileToString(true, "C:/devkitPro/trunk/libogc/libasnd/dsp_mixer/dsp_mixer.s", &dsp_test);
// This is CLOSE to working. Sorry about the local path btw. This is preliminary code. // This is CLOSE to working. Sorry about the local path btw. This is preliminary code.
*/ */
std::string dsp_test; std::string dsp_test;
if (File::ReadFileToString(true, "Testdata/dsp_test.s", dsp_test)) if (File::ReadFileToString(true, "Testdata/dsp_test.s", dsp_test))
fail = fail || !SuperTrip(dsp_test.c_str()); fail = fail || !SuperTrip(dsp_test.c_str());
if (!fail) if (!fail)
printf("All passed!\n"); printf("All passed!\n");
} }
// Usage: // Usage:
// Run internal tests: // Run internal tests:
// dsptool test // dsptool test
// Disassemble a file: // Disassemble a file:
// dsptool -d -o asdf.txt asdf.bin // dsptool -d -o asdf.txt asdf.bin
// Disassemble a file, output to standard output: // Disassemble a file, output to standard output:
// dsptool -d asdf.bin // dsptool -d asdf.bin
// Assemble a file: // Assemble a file:
// dsptool -o asdf.bin asdf.txt // dsptool -o asdf.bin asdf.txt
// Assemble a file, output header: // Assemble a file, output header:
// dsptool -h asdf.h asdf.txt // dsptool -h asdf.h asdf.txt
// So far, all this binary can do is test partially that itself works correctly. // So far, all this binary can do is test partially that itself works correctly.
int main(int argc, const char *argv[]) int main(int argc, const char *argv[])
{ {
if(argc == 1 || (argc == 2 && (!strcmp(argv[1], "--help") || (!strcmp(argv[1], "-?"))))) if(argc == 1 || (argc == 2 && (!strcmp(argv[1], "--help") || (!strcmp(argv[1], "-?")))))
{ {
printf("USAGE: DSPTool [-?] [--help] [-d] [-m] [-o <FILE>] [-h <FILE>] <DSP ASSEMBLER FILE>\n"); printf("USAGE: DSPTool [-?] [--help] [-d] [-m] [-o <FILE>] [-h <FILE>] <DSP ASSEMBLER FILE>\n");
printf("-? / --help: Prints this message\n"); printf("-? / --help: Prints this message\n");
printf("-d: Disassemble\n"); printf("-d: Disassemble\n");
printf("-m: Input file contains a list of files (Header assembly only)\n"); printf("-m: Input file contains a list of files (Header assembly only)\n");
printf("-s: Print the final size in bytes (only)\n"); printf("-s: Print the final size in bytes (only)\n");
printf("-o <OUTPUT FILE>: Results from stdout redirected to a file\n"); printf("-o <OUTPUT FILE>: Results from stdout redirected to a file\n");
printf("-h <HEADER FILE>: Output assembly results to a header\n"); printf("-h <HEADER FILE>: Output assembly results to a header\n");
return 0; return 0;
} }
if (argc == 2 && !strcmp(argv[1], "test")) if (argc == 2 && !strcmp(argv[1], "test"))
{ {
RunAsmTests(); RunAsmTests();
return 0; return 0;
} }
std::string input_name; std::string input_name;
std::string output_header_name; std::string output_header_name;
std::string output_name; std::string output_name;
bool disassemble = false, compare = false, multiple = false, outputSize = false; bool disassemble = false, compare = false, multiple = false, outputSize = false;
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
{ {
if (!strcmp(argv[i], "-d")) if (!strcmp(argv[i], "-d"))
disassemble = true; disassemble = true;
else if (!strcmp(argv[i], "-o")) else if (!strcmp(argv[i], "-o"))
output_name = argv[++i]; output_name = argv[++i];
else if (!strcmp(argv[i], "-h")) else if (!strcmp(argv[i], "-h"))
output_header_name = argv[++i]; output_header_name = argv[++i];
else if (!strcmp(argv[i], "-c")) else if (!strcmp(argv[i], "-c"))
compare = true; compare = true;
else if (!strcmp(argv[i], "-s")) else if (!strcmp(argv[i], "-s"))
outputSize = true; outputSize = true;
else if (!strcmp(argv[i], "-m")) else if (!strcmp(argv[i], "-m"))
multiple = true; multiple = true;
else else
{ {
if (!input_name.empty()) if (!input_name.empty())
{ {
printf("ERROR: Can only take one input file.\n"); printf("ERROR: Can only take one input file.\n");
return 1; return 1;
} }
input_name = argv[i]; input_name = argv[i];
if (!File::Exists(input_name.c_str())) if (!File::Exists(input_name.c_str()))
{ {
printf("ERROR: Input path does not exist.\n"); printf("ERROR: Input path does not exist.\n");
return 1; return 1;
} }
} }
} }
if(multiple && (compare || disassemble || !output_name.empty() || if(multiple && (compare || disassemble || !output_name.empty() ||
input_name.empty())) { input_name.empty())) {
printf("ERROR: Multiple files can only be used with assembly " printf("ERROR: Multiple files can only be used with assembly "
"and must compile a header file.\n"); "and must compile a header file.\n");
return 1; return 1;
} }
if (compare) if (compare)
{ {
// Two binary inputs, let's diff. // Two binary inputs, let's diff.
std::string binary_code; std::string binary_code;
std::vector<u16> code1, code2; std::vector<u16> code1, code2;
File::ReadFileToString(false, input_name.c_str(), binary_code); File::ReadFileToString(false, input_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code1); BinaryStringBEToCode(binary_code, code1);
File::ReadFileToString(false, output_name.c_str(), binary_code); File::ReadFileToString(false, output_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code2); BinaryStringBEToCode(binary_code, code2);
Compare(code1, code2); Compare(code1, code2);
return 0; return 0;
} }
if (disassemble) if (disassemble)
{ {
if (input_name.empty()) if (input_name.empty())
{ {
printf("Disassemble: Must specify input.\n"); printf("Disassemble: Must specify input.\n");
return 1; return 1;
} }
std::string binary_code; std::string binary_code;
std::vector<u16> code; std::vector<u16> code;
File::ReadFileToString(false, input_name.c_str(), binary_code); File::ReadFileToString(false, input_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code); BinaryStringBEToCode(binary_code, code);
std::string text; std::string text;
Disassemble(code, true, text); Disassemble(code, true, text);
if (!output_name.empty()) if (!output_name.empty())
File::WriteStringToFile(true, text, output_name.c_str()); File::WriteStringToFile(true, text, output_name.c_str());
else else
printf("%s", text.c_str()); printf("%s", text.c_str());
} }
else else
{ {
if (input_name.empty()) if (input_name.empty())
{ {
printf("Assemble: Must specify input.\n"); printf("Assemble: Must specify input.\n");
return 1; return 1;
} }
std::string source; std::string source;
if (File::ReadFileToString(true, input_name.c_str(), source)) if (File::ReadFileToString(true, input_name.c_str(), source))
{ {
if(multiple) if(multiple)
{ {
// When specifying a list of files we must compile a header // When specifying a list of files we must compile a header
// (we can't assemble multiple files to one binary) // (we can't assemble multiple files to one binary)
// since we checked it before, we assume output_header_name isn't empty // since we checked it before, we assume output_header_name isn't empty
int lines; int lines;
std::vector<u16> *codes; std::vector<u16> *codes;
std::vector<std::string> files; std::vector<std::string> files;
std::string header, currentSource; std::string header, currentSource;
size_t lastPos = 0, pos = 0; size_t lastPos = 0, pos = 0;
source.append("\n"); source.append("\n");
while((pos = source.find('\n', lastPos)) != std::string::npos) while((pos = source.find('\n', lastPos)) != std::string::npos)
{ {
std::string temp = source.substr(lastPos, pos - lastPos); std::string temp = source.substr(lastPos, pos - lastPos);
if(!temp.empty()) if(!temp.empty())
files.push_back(temp); files.push_back(temp);
lastPos = pos + 1; lastPos = pos + 1;
} }
lines = (int)files.size(); lines = (int)files.size();
if(lines == 0) if(lines == 0)
{ {
printf("ERROR: Must specify at least one file\n"); printf("ERROR: Must specify at least one file\n");
return 1; return 1;
} }
codes = new std::vector<u16>[lines]; codes = new std::vector<u16>[lines];
for(int i = 0; i < lines; i++) for(int i = 0; i < lines; i++)
{ {
if (!File::ReadFileToString(true, files[i].c_str(), currentSource)) if (!File::ReadFileToString(true, files[i].c_str(), currentSource))
{ {
printf("ERROR reading %s, skipping...\n", files[i].c_str()); printf("ERROR reading %s, skipping...\n", files[i].c_str());
lines--; lines--;
} }
else else
{ {
if(!Assemble(currentSource.c_str(), codes[i])) if(!Assemble(currentSource.c_str(), codes[i]))
{ {
printf("Assemble: Assembly of %s failed due to errors\n", printf("Assemble: Assembly of %s failed due to errors\n",
files[i].c_str()); files[i].c_str());
lines--; lines--;
} }
if(outputSize) if(outputSize)
printf("%s: %d\n", files[i].c_str(), codes[i].size()); printf("%s: %d\n", files[i].c_str(), codes[i].size());
} }
} }
CodesToHeader(codes, &files, lines, output_header_name.c_str(), header); CodesToHeader(codes, &files, lines, output_header_name.c_str(), header);
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str()); File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
delete[] codes; delete[] codes;
} }
else else
{ {
std::vector<u16> code; std::vector<u16> code;
if(!Assemble(source.c_str(), code)) { if(!Assemble(source.c_str(), code)) {
printf("Assemble: Assembly failed due to errors\n"); printf("Assemble: Assembly failed due to errors\n");
return 1; return 1;
} }
if(outputSize) if(outputSize)
printf("%s: %d\n", input_name.c_str(), code.size()); printf("%s: %d\n", input_name.c_str(), code.size());
if (!output_name.empty()) if (!output_name.empty())
{ {
std::string binary_code; std::string binary_code;
CodeToBinaryStringBE(code, binary_code); CodeToBinaryStringBE(code, binary_code);
File::WriteStringToFile(false, binary_code, output_name.c_str()); File::WriteStringToFile(false, binary_code, output_name.c_str());
} }
if (!output_header_name.empty()) if (!output_header_name.empty())
{ {
std::string header; std::string header;
CodeToHeader(code, input_name, output_header_name.c_str(), header); CodeToHeader(code, input_name, output_header_name.c_str(), header);
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str()); File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
} }
} }
} }
source.clear(); source.clear();
} }
if(!outputSize) if(!outputSize)
printf("Assembly completed successfully!\n"); printf("Assembly completed successfully!\n");
return 0; return 0;
} }

View File

@ -1,42 +1,42 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Config.h" // Local #include "Config.h" // Local
#include "Globals.h" #include "Globals.h"
#include "DSPHandler.h" #include "DSPHandler.h"
#include "HLEMixer.h" #include "HLEMixer.h"
void HLEMixer::MixUCode(short *samples, int numSamples) { void HLEMixer::MixUCode(short *samples, int numSamples) {
// if this was called directly from the HLE, and not by timeout // if this was called directly from the HLE, and not by timeout
if (g_Config.m_EnableHLEAudio && IsHLEReady()) { if (g_Config.m_EnableHLEAudio && IsHLEReady()) {
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode(); IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
if (pUCode != NULL) if (pUCode != NULL)
pUCode->MixAdd(samples, numSamples); pUCode->MixAdd(samples, numSamples);
} }
} }
void HLEMixer::Premix(short *samples, int numSamples) { void HLEMixer::Premix(short *samples, int numSamples) {
// first get the DTK Music // first get the DTK Music
// if (g_Config.m_EnableDTKMusic) { // if (g_Config.m_EnableDTKMusic) {
// g_dspInitialize.pGetAudioStreaming(samples, numSamples); // g_dspInitialize.pGetAudioStreaming(samples, numSamples);
// } // }
MixUCode(samples, numSamples); MixUCode(samples, numSamples);
} }

View File

@ -1,95 +1,95 @@
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "UCode_Zelda_ADPCM.h" #include "UCode_Zelda_ADPCM.h"
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type) void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type)
{ {
short nibbles[16]; short nibbles[16];
short hist = *histp; short hist = *histp;
short hist2 = *hist2p; short hist2 = *hist2p;
const char *src = input; const char *src = input;
char *dst = (char*)out; char *dst = (char*)out;
// First 2 nibbles are ADPCM scale etc. // First 2 nibbles are ADPCM scale etc.
short delta = 1 << (((*src) >> 4) & 0xf); short delta = 1 << (((*src) >> 4) & 0xf);
short idx = (*src) & 0xf; short idx = (*src) & 0xf;
src++; src++;
if (type == 9) if (type == 9)
{ {
for (int i = 0; i < 16; i = i + 2) { for (int i = 0; i < 16; i = i + 2) {
int j = (*src & 255) >> 4; int j = (*src & 255) >> 4;
nibbles[i] = j; nibbles[i] = j;
j = *src & 255 & 15; j = *src & 255 & 15;
nibbles[i+1] = j; nibbles[i+1] = j;
src++; src++;
} }
for (int i = 0; i < 16; i = i + 1) { for (int i = 0; i < 16; i = i + 1) {
if (nibbles[i] >= 8) if (nibbles[i] >= 8)
nibbles[i] = nibbles[i] - 16; nibbles[i] = nibbles[i] - 16;
} }
} }
else else
{ {
// untested !!! i havnt seen such a sample yet :) // untested !!! i havnt seen such a sample yet :)
for (int i = 0; i < 16; i += 4) for (int i = 0; i < 16; i += 4)
{ {
int j = (*src >> 0) & 0x02; int j = (*src >> 0) & 0x02;
nibbles[i] = j; nibbles[i] = j;
j = (*src >> 2) & 0x02; j = (*src >> 2) & 0x02;
nibbles[i+1] = j; nibbles[i+1] = j;
j = (*src >> 4) & 0x02; j = (*src >> 4) & 0x02;
nibbles[i+2] = j; nibbles[i+2] = j;
j = (*src >> 6) & 0x02; j = (*src >> 6) & 0x02;
nibbles[i+3] = j; nibbles[i+3] = j;
src++; src++;
} }
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
if (nibbles[i] >= 2) if (nibbles[i] >= 2)
nibbles[i] = nibbles[i] - 4; nibbles[i] = nibbles[i] - 4;
} }
} }
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
int sample = (delta * nibbles[i]) << 11; int sample = (delta * nibbles[i]) << 11;
sample += ((long)hist * coef[idx * 2]) + ((long)hist2 * coef[idx * 2 + 1]); sample += ((long)hist * coef[idx * 2]) + ((long)hist2 * coef[idx * 2 + 1]);
sample = sample >> 11; sample = sample >> 11;
if (sample > 32767) { if (sample > 32767) {
sample = 32767; sample = 32767;
} }
if (sample < -32768) { if (sample < -32768) {
sample = -32768; sample = -32768;
} }
*(short*)dst = (short)sample; *(short*)dst = (short)sample;
dst = dst + 2; dst = dst + 2;
hist2 = hist; hist2 = hist;
hist = (short)sample; hist = (short)sample;
} }
*histp = hist; *histp = hist;
*hist2p = hist2; *hist2p = hist2;
} }

View File

@ -1,20 +1,20 @@
// Copyright (C) 2003-2008 Dolphin Project. // Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type); void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type);

View File

@ -1,106 +1,106 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "../Globals.h" #include "../Globals.h"
#include "UCodes.h" #include "UCodes.h"
#include "UCode_Zelda.h" #include "UCode_Zelda.h"
#include "UCode_Zelda_ADPCM.h" #include "UCode_Zelda_ADPCM.h"
#include "../main.h" #include "../main.h"
#include "Mixer.h" #include "Mixer.h"
void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size) void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{ {
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate(); float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16); u32 _ratio = (PB.RatioInt << 16);
s64 ratio = (_ratio * ratioFactor) * 16; s64 ratio = (_ratio * ratioFactor) * 16;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16; s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac; TrueSamplePosition += PB.CurSampleFrac;
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1; int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
u32 pos[2] = {0, 0}; u32 pos[2] = {0, 0};
int i = 0; int i = 0;
if (PB.KeyOff != 0) if (PB.KeyOff != 0)
return; return;
if (PB.NeedsReset) if (PB.NeedsReset)
{ {
PB.RemLength = PB.Length - PB.RestartPos; PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1); PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
} }
_lRestart: _lRestart:
if (PB.ReachedEnd) if (PB.ReachedEnd)
{ {
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
if (PB.RepeatMode == 0) if (PB.RepeatMode == 0)
{ {
PB.KeyOff = 1; PB.KeyOff = 1;
PB.RemLength = 0; PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length; PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
return; return;
} }
else else
{ {
PB.RestartPos = PB.LoopStartPos; PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos; PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1); PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
pos[1] = 0; pos[0] = 0; pos[1] = 0; pos[0] = 0;
} }
} }
while(i < _Size) while(i < _Size)
{ {
s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000; s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000;
TrueSamplePosition += (ratio >> 16); TrueSamplePosition += (ratio >> 16);
_Buffer[i++] = (s32)sample; _Buffer[i++] = (s32)sample;
(*(u64*)&pos) += ratio; (*(u64*)&pos) += ratio;
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length) if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
{ {
PB.ReachedEnd = 1; PB.ReachedEnd = 1;
goto _lRestart; goto _lRestart;
} }
} }
if (PB.RemLength < pos[1]) if (PB.RemLength < pos[1])
{ {
PB.RemLength = 0; PB.RemLength = 0;
PB.ReachedEnd = 1; PB.ReachedEnd = 1;
} }
else else
PB.RemLength -= pos[1]; PB.RemLength -= pos[1];
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF; PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
} }
void CUCode_Zelda::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size) void CUCode_Zelda::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{ {
// TODO: Header, footer and cases this synth actually happens // TODO: Header, footer and cases this synth actually happens
for (int i = 0; i < _Size; i++) for (int i = 0; i < _Size; i++)
_Buffer[i++] = (s32)PB.RatioInt; _Buffer[i++] = (s32)PB.RatioInt;
} }

View File

@ -1,466 +1,466 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "../Globals.h" #include "../Globals.h"
#include "UCodes.h" #include "UCodes.h"
#include "UCode_Zelda.h" #include "UCode_Zelda.h"
#include "UCode_Zelda_ADPCM.h" #include "UCode_Zelda_ADPCM.h"
#include "../main.h" #include "../main.h"
#include "Mixer.h" #include "Mixer.h"
void CUCode_Zelda::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB) void CUCode_Zelda::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB)
{ {
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr); u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
// Perform byteswap // Perform byteswap
for (int i = 0; i < (0x180 / 2); i++) for (int i = 0; i < (0x180 / 2); i++)
((u16*)&PB)[i] = Common::swap16(memory[i]); ((u16*)&PB)[i] = Common::swap16(memory[i]);
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16); PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16); PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16); PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
PB.LoopStartPos = (PB.LoopStartPos << 16) | (PB.LoopStartPos >> 16); PB.LoopStartPos = (PB.LoopStartPos << 16) | (PB.LoopStartPos >> 16);
PB.Length = (PB.Length << 16) | (PB.Length >> 16); PB.Length = (PB.Length << 16) | (PB.Length >> 16);
PB.StartAddr = (PB.StartAddr << 16) | (PB.StartAddr >> 16); PB.StartAddr = (PB.StartAddr << 16) | (PB.StartAddr >> 16);
PB.UnkAddr = (PB.UnkAddr << 16) | (PB.UnkAddr >> 16); PB.UnkAddr = (PB.UnkAddr << 16) | (PB.UnkAddr >> 16);
} }
void CUCode_Zelda::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB) void CUCode_Zelda::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB)
{ {
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr); u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16); PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16); PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16); PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
// Perform byteswap // Perform byteswap
// Only the first 0x100 bytes are written back // Only the first 0x100 bytes are written back
for (int i = 0; i < (0x100 / 2); i++) for (int i = 0; i < (0x100 / 2); i++)
memory[i] = Common::swap16(((u16*)&PB)[i]); memory[i] = Common::swap16(((u16*)&PB)[i]);
} }
void CUCode_Zelda::RenderVoice_PCM16(ZeldaVoicePB &PB, s32* _Buffer, int _Size) void CUCode_Zelda::RenderVoice_PCM16(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{ {
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate(); float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (((PB.RatioInt * 80) + PB.CurSampleFrac) << 4) & 0xFFFF0000; u32 _ratio = (((PB.RatioInt * 80) + PB.CurSampleFrac) << 4) & 0xFFFF0000;
u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor); u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor);
u32 pos[2] = {0, 0}; u32 pos[2] = {0, 0};
int i = 0; int i = 0;
if (PB.KeyOff != 0) if (PB.KeyOff != 0)
return; return;
if (PB.NeedsReset) if (PB.NeedsReset)
{ {
PB.RemLength = PB.Length - PB.RestartPos; PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1); PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
} }
_lRestart: _lRestart:
if (PB.ReachedEnd) if (PB.ReachedEnd)
{ {
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
if (PB.RepeatMode == 0) if (PB.RepeatMode == 0)
{ {
PB.KeyOff = 1; PB.KeyOff = 1;
PB.RemLength = 0; PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length; PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
return; return;
} }
else else
{ {
PB.RestartPos = PB.LoopStartPos; PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos; PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1); PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
pos[1] = 0; pos[0] = 0; pos[1] = 0; pos[0] = 0;
} }
} }
s16 *source; s16 *source;
if (m_CRC == 0xD643001F) if (m_CRC == 0xD643001F)
source = (s16*)(g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr) + PB.CurAddr); source = (s16*)(g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr) + PB.CurAddr);
else else
source = (s16*)(g_dspInitialize.pGetARAMPointer() + PB.CurAddr); source = (s16*)(g_dspInitialize.pGetARAMPointer() + PB.CurAddr);
for (; i < _Size;) for (; i < _Size;)
{ {
s16 sample = Common::swap16(source[pos[1]]); s16 sample = Common::swap16(source[pos[1]]);
_Buffer[i++] = (s32)sample; _Buffer[i++] = (s32)sample;
(*(u64*)&pos) += ratio; (*(u64*)&pos) += ratio;
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length) if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
{ {
PB.ReachedEnd = 1; PB.ReachedEnd = 1;
goto _lRestart; goto _lRestart;
} }
} }
if (PB.RemLength < pos[1]) if (PB.RemLength < pos[1])
{ {
PB.RemLength = 0; PB.RemLength = 0;
PB.ReachedEnd = 1; PB.ReachedEnd = 1;
} }
else else
PB.RemLength -= pos[1]; PB.RemLength -= pos[1];
PB.CurAddr += pos[1] << 1; PB.CurAddr += pos[1] << 1;
// There should be a position fraction as well. // There should be a position fraction as well.
} }
void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size) void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{ {
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate(); float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac; u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor); s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
// initialize "decoder" if the sample is played the first time // initialize "decoder" if the sample is played the first time
if (PB.NeedsReset != 0) if (PB.NeedsReset != 0)
{ {
// This is 0717_ReadOutPBStuff // This is 0717_ReadOutPBStuff
// increment 4fb // increment 4fb
// zelda: // zelda:
// perhaps init or "has played before" // perhaps init or "has played before"
PB.CurBlock = 0x00; PB.CurBlock = 0x00;
PB.YN2 = 0x00; // history1 PB.YN2 = 0x00; // history1
PB.YN1 = 0x00; // history2 PB.YN1 = 0x00; // history2
// Length in samples. // Length in samples.
PB.RemLength = PB.Length; PB.RemLength = PB.Length;
// Copy ARAM addr from r to rw area. // Copy ARAM addr from r to rw area.
PB.CurAddr = PB.StartAddr; PB.CurAddr = PB.StartAddr;
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
PB.CurSampleFrac = 0; PB.CurSampleFrac = 0;
// Looking at Zelda Four Swords // Looking at Zelda Four Swords
// WARN_LOG(DSPHLE, "PB -----: %04x", PB.Unk03); // WARN_LOG(DSPHLE, "PB -----: %04x", PB.Unk03);
// WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0 // WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0
// WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0 // WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0
/// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78); /// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78);
// WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79); // WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79);
// WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31); // WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31);
// WARN_LOG(DSPHLE, "PB Unk36: %04x", PB.Unk36[0]); // WARN_LOG(DSPHLE, "PB Unk36: %04x", PB.Unk36[0]);
// WARN_LOG(DSPHLE, "PB Unk37: %04x", PB.Unk36[1]); // WARN_LOG(DSPHLE, "PB Unk37: %04x", PB.Unk36[1]);
// WARN_LOG(DSPHLE, "PB Unk3c: %04x", PB.Unk3C[0]); // WARN_LOG(DSPHLE, "PB Unk3c: %04x", PB.Unk3C[0]);
// WARN_LOG(DSPHLE, "PB Unk3d: %04x", PB.Unk3C[1]); // WARN_LOG(DSPHLE, "PB Unk3d: %04x", PB.Unk3C[1]);
} }
if (PB.KeyOff != 0) // 0747 early out... i dunno if this can happen because we filter it above if (PB.KeyOff != 0) // 0747 early out... i dunno if this can happen because we filter it above
return; return;
// round upwards how many samples we need to copy, 0759 // round upwards how many samples we need to copy, 0759
// u32 frac = NumberOfSamples & 0xF; // u32 frac = NumberOfSamples & 0xF;
// NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction // NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction
u8 *source; u8 *source;
u32 ram_mask = 1024 * 1024 * 16 - 1; u32 ram_mask = 1024 * 1024 * 16 - 1;
if (m_CRC == 0xD643001F) { if (m_CRC == 0xD643001F) {
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr); source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
ram_mask = 1024 * 1024 * 64 - 1; ram_mask = 1024 * 1024 * 64 - 1;
} }
else else
source = g_dspInitialize.pGetARAMPointer(); source = g_dspInitialize.pGetARAMPointer();
restart: restart:
if (PB.ReachedEnd) if (PB.ReachedEnd)
{ {
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
// HACK: Looping doesn't work. // HACK: Looping doesn't work.
if (true || PB.RepeatMode == 0) if (true || PB.RepeatMode == 0)
{ {
PB.KeyOff = 1; PB.KeyOff = 1;
PB.RemLength = 0; PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length; PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
return; return;
} }
else else
{ {
// This needs adjustment. It's not right for AFC, was just copied from PCM16. // This needs adjustment. It's not right for AFC, was just copied from PCM16.
// We should also probably reinitialize YN1 and YN2 with something - but with what? // We should also probably reinitialize YN1 and YN2 with something - but with what?
PB.RestartPos = PB.LoopStartPos; PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos; PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1); PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
// pos[1] = 0; pos[0] = 0; // pos[1] = 0; pos[0] = 0;
} }
} }
short outbuf[16] = {0}; short outbuf[16] = {0};
u16 prev_yn1 = PB.YN1; u16 prev_yn1 = PB.YN1;
u16 prev_yn2 = PB.YN2; u16 prev_yn2 = PB.YN2;
u32 prev_addr = PB.CurAddr; u32 prev_addr = PB.CurAddr;
// Prefill the decode buffer. // Prefill the decode buffer.
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format); AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
PB.CurAddr += 9; PB.CurAddr += 9;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16; s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac; TrueSamplePosition += PB.CurSampleFrac;
s64 delta = ratio >> 16; // 0x100000000ULL; s64 delta = ratio >> 16; // 0x100000000ULL;
int sampleCount = 0; int sampleCount = 0;
while (sampleCount < _Size) while (sampleCount < _Size)
{ {
int SamplePosition = TrueSamplePosition >> 16; int SamplePosition = TrueSamplePosition >> 16;
_Buffer[sampleCount] = outbuf[SamplePosition & 15]; _Buffer[sampleCount] = outbuf[SamplePosition & 15];
sampleCount++; sampleCount++;
TrueSamplePosition += delta; TrueSamplePosition += delta;
int TargetPosition = TrueSamplePosition >> 16; int TargetPosition = TrueSamplePosition >> 16;
// Decode forwards... // Decode forwards...
while (SamplePosition < TargetPosition) while (SamplePosition < TargetPosition)
{ {
SamplePosition++; SamplePosition++;
PB.RemLength--; PB.RemLength--;
if (PB.RemLength == 0) if (PB.RemLength == 0)
{ {
PB.ReachedEnd = 1; PB.ReachedEnd = 1;
goto restart; goto restart;
} }
// Need new samples! // Need new samples!
if ((SamplePosition & 15) == 0) { if ((SamplePosition & 15) == 0) {
prev_yn1 = PB.YN1; prev_yn1 = PB.YN1;
prev_yn2 = PB.YN2; prev_yn2 = PB.YN2;
prev_addr = PB.CurAddr; prev_addr = PB.CurAddr;
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format); AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
PB.CurAddr += 9; PB.CurAddr += 9;
} }
} }
} }
// Here we should back off to the previous addr/yn1/yn2, since we didn't consume the full last block. // Here we should back off to the previous addr/yn1/yn2, since we didn't consume the full last block.
// We'll have to re-decode it the next time around. // We'll have to re-decode it the next time around.
// if (SamplePosition & 15) { // if (SamplePosition & 15) {
PB.YN2 = prev_yn2; PB.YN2 = prev_yn2;
PB.YN1 = prev_yn1; PB.YN1 = prev_yn1;
PB.CurAddr = prev_addr; PB.CurAddr = prev_addr;
// } // }
PB.NeedsReset = 0; PB.NeedsReset = 0;
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF; PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
// write back // write back
// NumberOfSamples = (NumberOfSamples << 4) | frac; // missing fraction // NumberOfSamples = (NumberOfSamples << 4) | frac; // missing fraction
// i think pTest[0x3a] and pTest[0x3b] got an update after you have decoded some samples... // i think pTest[0x3a] and pTest[0x3b] got an update after you have decoded some samples...
// just decrement them with the number of samples you have played // just decrement them with the number of samples you have played
// and increase the ARAM Offset in pTest[0x38], pTest[0x39] // and increase the ARAM Offset in pTest[0x38], pTest[0x39]
// end of block (Zelda 03b2) // end of block (Zelda 03b2)
} }
// Researching what's actually inside the mysterious 0x21 case // Researching what's actually inside the mysterious 0x21 case
void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s32* _Buffer, int _Size) void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{ {
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate(); float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac; u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor); s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
if (PB.NeedsReset != 0) if (PB.NeedsReset != 0)
{ {
PB.CurBlock = 0x00; PB.CurBlock = 0x00;
// Length in samples. // Length in samples.
PB.RemLength = PB.Length; PB.RemLength = PB.Length;
// Copy ARAM addr from r to rw area. // Copy ARAM addr from r to rw area.
PB.CurAddr = PB.StartAddr; PB.CurAddr = PB.StartAddr;
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
PB.CurSampleFrac = 0; PB.CurSampleFrac = 0;
} }
if (PB.KeyOff != 0) if (PB.KeyOff != 0)
return; return;
u8 *source; u8 *source;
u32 ram_mask = 1024 * 1024 * 16 - 1; u32 ram_mask = 1024 * 1024 * 16 - 1;
if (m_CRC == 0xD643001F) { if (m_CRC == 0xD643001F) {
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr); source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
ram_mask = 1024 * 1024 * 64 - 1; ram_mask = 1024 * 1024 * 64 - 1;
} }
else else
source = g_dspInitialize.pGetARAMPointer(); source = g_dspInitialize.pGetARAMPointer();
//restart: //restart:
if (PB.ReachedEnd) if (PB.ReachedEnd)
{ {
PB.ReachedEnd = 0; PB.ReachedEnd = 0;
// HACK: Looping doesn't work. // HACK: Looping doesn't work.
if (true || PB.RepeatMode == 0) if (true || PB.RepeatMode == 0)
{ {
PB.KeyOff = 1; PB.KeyOff = 1;
PB.RemLength = 0; PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length; PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
return; return;
} }
else else
{ {
// This needs adjustment. It's not right for AFC, was just copied from PCM16. // This needs adjustment. It's not right for AFC, was just copied from PCM16.
// We should also probably reinitialize YN1 and YN2 with something - but with what? // We should also probably reinitialize YN1 and YN2 with something - but with what?
PB.RestartPos = PB.LoopStartPos; PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos; PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1); PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
} }
} }
u32 prev_addr = PB.CurAddr; u32 prev_addr = PB.CurAddr;
// Prefill the decode buffer. // Prefill the decode buffer.
//AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format); //AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
const char *src = (char *)(source + (PB.CurAddr & ram_mask)); const char *src = (char *)(source + (PB.CurAddr & ram_mask));
PB.CurAddr += 9; PB.CurAddr += 9;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16; s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac; TrueSamplePosition += PB.CurSampleFrac;
s64 delta = ratio >> 16; // 0x100000000ULL; s64 delta = ratio >> 16; // 0x100000000ULL;
int sampleCount = 0, realSample = 0; int sampleCount = 0, realSample = 0;
while (sampleCount < _Size) while (sampleCount < _Size)
{ {
_Buffer[sampleCount] = src[realSample] | (src[realSample + 1] << 8) | (src[realSample + 2] << 16) _Buffer[sampleCount] = src[realSample] | (src[realSample + 1] << 8) | (src[realSample + 2] << 16)
| (src[realSample + 3] << 24); | (src[realSample + 3] << 24);
//WARN_LOG(DSPHLE, "The sample: %02x", src[sampleCount]); //WARN_LOG(DSPHLE, "The sample: %02x", src[sampleCount]);
sampleCount++; sampleCount++;
realSample += 4; realSample += 4;
TrueSamplePosition += delta; TrueSamplePosition += delta;
} }
PB.NeedsReset = 0; PB.NeedsReset = 0;
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF; PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
} }
void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size) void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
{ {
//static u16 lastLeft = 0x1FF, lastRight = 0x1FF; //static u16 lastLeft = 0x1FF, lastRight = 0x1FF;
memset(m_TempBuffer, 0, _Size * sizeof(s32)); memset(m_TempBuffer, 0, _Size * sizeof(s32));
if (PB.IsBlank) if (PB.IsBlank)
{ {
s32 sample = (s32)(s16)PB.FixedSample; s32 sample = (s32)(s16)PB.FixedSample;
for (int i = 0; i < _Size; i++) for (int i = 0; i < _Size; i++)
m_TempBuffer[i] = sample; m_TempBuffer[i] = sample;
} }
else else
{ {
// XK: Use this to disable music (GREAT for testing) // XK: Use this to disable music (GREAT for testing)
//if(PB.SoundType == 0x0d00) { //if(PB.SoundType == 0x0d00) {
// PB.NeedsReset = 0; // PB.NeedsReset = 0;
// return; // return;
//} //}
//WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x", //WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x",
// PB.Format, PB.SoundType, PB.Unk29, PB.Unk2a); // PB.Format, PB.SoundType, PB.Unk29, PB.Unk2a);
/*WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x %04x %04x %04x %04x %04x %04x", /*WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x %04x %04x %04x %04x %04x %04x",
PB.Format, PB.SoundType, PB.Format, PB.SoundType,
PB.volumeLeft1, PB.volumeLeft2, PB.volumeRight1, PB.volumeRight2, PB.volumeLeft1, PB.volumeLeft2, PB.volumeRight1, PB.volumeRight2,
PB.volumeUnknown1_1, PB.volumeUnknown1_2, PB.volumeUnknown2_1, PB.volumeUnknown1_1, PB.volumeUnknown1_2, PB.volumeUnknown2_1,
PB.volumeUnknown2_2);*/ PB.volumeUnknown2_2);*/
switch (PB.Format) switch (PB.Format)
{ {
// Synthesized sounds // Synthesized sounds
case 0x0000: // Example: Magic meter filling up in ZWW case 0x0000: // Example: Magic meter filling up in ZWW
case 0x0001: // Example: "Denied" sound when trying to pull out a sword case 0x0001: // Example: "Denied" sound when trying to pull out a sword
// indoors in ZWW // indoors in ZWW
RenderSynth_Waveform(PB, m_TempBuffer, _Size); RenderSynth_Waveform(PB, m_TempBuffer, _Size);
break; break;
case 0x0006: case 0x0006:
WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)"); WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)");
RenderSynth_Constant(PB, m_TempBuffer, _Size); RenderSynth_Constant(PB, m_TempBuffer, _Size);
break; break;
// These are more "synth" formats - square wave, saw wave etc. // These are more "synth" formats - square wave, saw wave etc.
case 0x0002: case 0x0002:
WARN_LOG(DSPHLE, "Synthesizing 0x0002"); WARN_LOG(DSPHLE, "Synthesizing 0x0002");
break; break;
// AFC formats // AFC formats
case 0x0005: // AFC with extra low bitrate (32:5 compression). Not yet seen. case 0x0005: // AFC with extra low bitrate (32:5 compression). Not yet seen.
WARN_LOG(DSPHLE, "5 byte AFC - does it work?"); WARN_LOG(DSPHLE, "5 byte AFC - does it work?");
case 0x0009: // AFC with normal bitrate (32:9 compression). case 0x0009: // AFC with normal bitrate (32:9 compression).
RenderVoice_AFC(PB, m_TempBuffer, _Size); RenderVoice_AFC(PB, m_TempBuffer, _Size);
break; break;
case 0x0010: // PCM16 - normal PCM 16-bit audio. case 0x0010: // PCM16 - normal PCM 16-bit audio.
RenderVoice_PCM16(PB, m_TempBuffer, _Size); RenderVoice_PCM16(PB, m_TempBuffer, _Size);
break; break;
case 0x0008: // Likely PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD. case 0x0008: // Likely PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD.
case 0x0020: case 0x0020:
case 0x0021: // Probably raw sound. Important for Zelda WW. Really need to implement - missing it causes hangs. case 0x0021: // Probably raw sound. Important for Zelda WW. Really need to implement - missing it causes hangs.
WARN_LOG(DSPHLE, "Unimplemented MixAddVoice format in zelda %04x", PB.Format); WARN_LOG(DSPHLE, "Unimplemented MixAddVoice format in zelda %04x", PB.Format);
// This is what 0x20 and 0x21 do on end of voice // This is what 0x20 and 0x21 do on end of voice
PB.RemLength = 0; PB.RemLength = 0;
PB.KeyOff = 1; PB.KeyOff = 1;
// Caution: Use at your own risk. Sounds awful :) // Caution: Use at your own risk. Sounds awful :)
//RenderVoice_Raw(PB, m_TempBuffer, _Size); //RenderVoice_Raw(PB, m_TempBuffer, _Size);
break; break;
default: default:
// TODO: Implement general decoder here // TODO: Implement general decoder here
ERROR_LOG(DSPHLE, "Unknown MixAddVoice format in zelda %04x", PB.Format); ERROR_LOG(DSPHLE, "Unknown MixAddVoice format in zelda %04x", PB.Format);
break; break;
} }
// Necessary for SMG, not for Zelda. Weird. // Necessary for SMG, not for Zelda. Weird.
PB.NeedsReset = 0; PB.NeedsReset = 0;
} }
for (int i = 0; i < _Size; i++) for (int i = 0; i < _Size; i++)
{ {
/*if(PB.volumeLeft2) /*if(PB.volumeLeft2)
lastLeft = PB.volumeLeft2; lastLeft = PB.volumeLeft2;
if(PB.volumeRight2) if(PB.volumeRight2)
lastRight = PB.volumeRight2;*/ lastRight = PB.volumeRight2;*/
// TODO: Some noises in Zelda WW (birds, etc) have a volume of 0 // TODO: Some noises in Zelda WW (birds, etc) have a volume of 0
// Really not sure about the masking here, but it seems to kill off some overly loud // Really not sure about the masking here, but it seems to kill off some overly loud
// sounds in Zelda TP. Needs investigation. // sounds in Zelda TP. Needs investigation.
s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)( s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
(PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005); (PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005);
s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)( s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
(PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005); (PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005);
if (left < -32768) left = -32768; if (left < -32768) left = -32768;
if (left > 32767) left = 32767; if (left > 32767) left = 32767;
_LeftBuffer[i] = left; //(s32)(((float)left * (float)PB.volumeLeft) / 1000.f); _LeftBuffer[i] = left; //(s32)(((float)left * (float)PB.volumeLeft) / 1000.f);
if (right < -32768) right = -32768; if (right < -32768) right = -32768;
if (right > 32767) right = 32767; if (right > 32767) right = 32767;
_RightBuffer[i] = right; //(s32)(((float)right * (float)PB.volumeRight) / 1000.0f); _RightBuffer[i] = right; //(s32)(((float)right * (float)PB.volumeRight) / 1000.0f);
} }
} }

View File

@ -1,179 +1,179 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "DSPDebugInterface.h" #include "DSPDebugInterface.h"
#include "DSPCore.h" #include "DSPCore.h"
#include "disassemble.h" #include "disassemble.h"
#include "DSPSymbols.h" #include "DSPSymbols.h"
#include "DSPMemoryMap.h" #include "DSPMemoryMap.h"
void DSPDebugInterface::disasm(unsigned int address, char *dest, int max_size) void DSPDebugInterface::disasm(unsigned int address, char *dest, int max_size)
{ {
// we'll treat addresses as line numbers. // we'll treat addresses as line numbers.
strncpy(dest, DSPSymbols::GetLineText(address), max_size); strncpy(dest, DSPSymbols::GetLineText(address), max_size);
dest[max_size-1] = 0; dest[max_size-1] = 0;
} }
void DSPDebugInterface::getRawMemoryString(int memory, unsigned int address, char *dest, int max_size) void DSPDebugInterface::getRawMemoryString(int memory, unsigned int address, char *dest, int max_size)
{ {
switch (memory) { switch (memory) {
case 0: // IMEM case 0: // IMEM
switch (address >> 12) { switch (address >> 12) {
case 0: case 0:
case 0x8: case 0x8:
sprintf(dest, "%04x", dsp_imem_read(address)); sprintf(dest, "%04x", dsp_imem_read(address));
break; break;
default: default:
sprintf(dest, "----"); sprintf(dest, "----");
break; break;
} }
break; break;
case 1: // DMEM case 1: // DMEM
switch (address >> 12) { switch (address >> 12) {
case 0: case 0:
case 1: case 1:
sprintf(dest, "%04x", dsp_dmem_read(address)); sprintf(dest, "%04x", dsp_dmem_read(address));
break; break;
default: default:
sprintf(dest, "----"); sprintf(dest, "----");
break; break;
} }
break; break;
} }
} }
unsigned int DSPDebugInterface::readMemory(unsigned int address) unsigned int DSPDebugInterface::readMemory(unsigned int address)
{ {
return 0; //Memory::ReadUnchecked_U32(address); return 0; //Memory::ReadUnchecked_U32(address);
} }
unsigned int DSPDebugInterface::readInstruction(unsigned int address) unsigned int DSPDebugInterface::readInstruction(unsigned int address)
{ {
return 0; //Memory::Read_Instruction(address); return 0; //Memory::Read_Instruction(address);
} }
bool DSPDebugInterface::isAlive() bool DSPDebugInterface::isAlive()
{ {
return true; //Core::GetState() != Core::CORE_UNINITIALIZED; return true; //Core::GetState() != Core::CORE_UNINITIALIZED;
} }
bool DSPDebugInterface::isBreakpoint(unsigned int address) bool DSPDebugInterface::isBreakpoint(unsigned int address)
{ {
int real_addr = DSPSymbols::Line2Addr(address); int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) if (real_addr >= 0)
return dsp_breakpoints.IsAddressBreakPoint(real_addr); return dsp_breakpoints.IsAddressBreakPoint(real_addr);
else else
return false; return false;
} }
void DSPDebugInterface::setBreakpoint(unsigned int address) void DSPDebugInterface::setBreakpoint(unsigned int address)
{ {
int real_addr = DSPSymbols::Line2Addr(address); int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) { if (real_addr >= 0) {
if (dsp_breakpoints.Add(real_addr)) if (dsp_breakpoints.Add(real_addr))
; ;
} }
} }
void DSPDebugInterface::clearBreakpoint(unsigned int address) void DSPDebugInterface::clearBreakpoint(unsigned int address)
{ {
int real_addr = DSPSymbols::Line2Addr(address); int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) { if (real_addr >= 0) {
if (dsp_breakpoints.Remove(real_addr)) if (dsp_breakpoints.Remove(real_addr))
; ;
} }
} }
void DSPDebugInterface::clearAllBreakpoints() { void DSPDebugInterface::clearAllBreakpoints() {
dsp_breakpoints.Clear(); dsp_breakpoints.Clear();
} }
void DSPDebugInterface::toggleBreakpoint(unsigned int address) void DSPDebugInterface::toggleBreakpoint(unsigned int address)
{ {
int real_addr = DSPSymbols::Line2Addr(address); int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) { if (real_addr >= 0) {
if (dsp_breakpoints.IsAddressBreakPoint(real_addr)) if (dsp_breakpoints.IsAddressBreakPoint(real_addr))
dsp_breakpoints.Remove(real_addr); dsp_breakpoints.Remove(real_addr);
else else
dsp_breakpoints.Add(real_addr); dsp_breakpoints.Add(real_addr);
} }
} }
void DSPDebugInterface::insertBLR(unsigned int address) void DSPDebugInterface::insertBLR(unsigned int address)
{ {
PanicAlert("insertBLR functionality not supported in DSP module."); PanicAlert("insertBLR functionality not supported in DSP module.");
} }
// ======================================================= // =======================================================
// Separate the blocks with colors. // Separate the blocks with colors.
// ------------- // -------------
int DSPDebugInterface::getColor(unsigned int address) int DSPDebugInterface::getColor(unsigned int address)
{ {
static const int colors[6] = static const int colors[6] =
{ {
0xd0FFFF, // light cyan 0xd0FFFF, // light cyan
0xFFd0d0, // light red 0xFFd0d0, // light red
0xd8d8FF, // light blue 0xd8d8FF, // light blue
0xFFd0FF, // light purple 0xFFd0FF, // light purple
0xd0FFd0, // light green 0xd0FFd0, // light green
0xFFFFd0, // light yellow 0xFFFFd0, // light yellow
}; };
// Scan backwards so we don't miss it. Hm, actually, let's not - it looks pretty good. // Scan backwards so we don't miss it. Hm, actually, let's not - it looks pretty good.
int addr = -1; int addr = -1;
for (int i = 0; i < 1; i++) for (int i = 0; i < 1; i++)
{ {
addr = DSPSymbols::Line2Addr(address - i); addr = DSPSymbols::Line2Addr(address - i);
if (addr >= 0) if (addr >= 0)
break; break;
} }
if (addr == -1) if (addr == -1)
return 0xFFFFFF; return 0xFFFFFF;
Symbol *symbol = DSPSymbols::g_dsp_symbol_db.GetSymbolFromAddr(addr); Symbol *symbol = DSPSymbols::g_dsp_symbol_db.GetSymbolFromAddr(addr);
if (!symbol) if (!symbol)
return 0xFFFFFF; return 0xFFFFFF;
if (symbol->type != Symbol::SYMBOL_FUNCTION) if (symbol->type != Symbol::SYMBOL_FUNCTION)
return 0xEEEEFF; return 0xEEEEFF;
return colors[symbol->index % 6]; return colors[symbol->index % 6];
} }
// ============= // =============
std::string DSPDebugInterface::getDescription(unsigned int address) std::string DSPDebugInterface::getDescription(unsigned int address)
{ {
return ""; // g_symbolDB.GetDescription(address); return ""; // g_symbolDB.GetDescription(address);
} }
unsigned int DSPDebugInterface::getPC() unsigned int DSPDebugInterface::getPC()
{ {
return DSPSymbols::Addr2Line(g_dsp.pc); return DSPSymbols::Addr2Line(g_dsp.pc);
} }
void DSPDebugInterface::setPC(unsigned int address) void DSPDebugInterface::setPC(unsigned int address)
{ {
int new_pc = DSPSymbols::Line2Addr(address); int new_pc = DSPSymbols::Line2Addr(address);
if (new_pc > 0) if (new_pc > 0)
g_dsp.pc = new_pc; g_dsp.pc = new_pc;
} }
void DSPDebugInterface::runToBreakpoint() void DSPDebugInterface::runToBreakpoint()
{ {
} }

View File

@ -1,33 +1,33 @@
#ifndef _DSPDEBUGINTERFACE_H #ifndef _DSPDEBUGINTERFACE_H
#define _DSPDEBUGINTERFACE_H #define _DSPDEBUGINTERFACE_H
#include <string> #include <string>
#include "DebugInterface.h" #include "DebugInterface.h"
#include "Common.h" #include "Common.h"
class DSPDebugInterface : public DebugInterface class DSPDebugInterface : public DebugInterface
{ {
public: public:
DSPDebugInterface(){} DSPDebugInterface(){}
virtual void disasm(unsigned int address, char *dest, int max_size); virtual void disasm(unsigned int address, char *dest, int max_size);
virtual void getRawMemoryString(int memory, unsigned int address, char *dest, int max_size); virtual void getRawMemoryString(int memory, unsigned int address, char *dest, int max_size);
virtual int getInstructionSize(int instruction) {return 1;} virtual int getInstructionSize(int instruction) {return 1;}
virtual bool isAlive(); virtual bool isAlive();
virtual bool isBreakpoint(unsigned int address); virtual bool isBreakpoint(unsigned int address);
virtual void setBreakpoint(unsigned int address); virtual void setBreakpoint(unsigned int address);
virtual void clearBreakpoint(unsigned int address); virtual void clearBreakpoint(unsigned int address);
virtual void clearAllBreakpoints(); virtual void clearAllBreakpoints();
virtual void toggleBreakpoint(unsigned int address); virtual void toggleBreakpoint(unsigned int address);
virtual unsigned int readMemory(unsigned int address); virtual unsigned int readMemory(unsigned int address);
virtual unsigned int readInstruction(unsigned int address); virtual unsigned int readInstruction(unsigned int address);
virtual unsigned int getPC(); virtual unsigned int getPC();
virtual void setPC(unsigned int address); virtual void setPC(unsigned int address);
virtual void step() {} virtual void step() {}
virtual void runToBreakpoint(); virtual void runToBreakpoint();
virtual void insertBLR(unsigned int address); virtual void insertBLR(unsigned int address);
virtual int getColor(unsigned int address); virtual int getColor(unsigned int address);
virtual std::string getDescription(unsigned int address); virtual std::string getDescription(unsigned int address);
}; };
#endif // _DSPDEBUGINTERFACE_H #endif // _DSPDEBUGINTERFACE_H

View File

@ -1,115 +1,115 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "DSPHost.h" #include "DSPHost.h"
#include "DSPSymbols.h" #include "DSPSymbols.h"
#include "Tools.h" #include "Tools.h"
#include "pluginspecs_dsp.h" #include "pluginspecs_dsp.h"
extern DSPInitialize g_dspInitialize; extern DSPInitialize g_dspInitialize;
#if defined(HAVE_WX) && HAVE_WX #if defined(HAVE_WX) && HAVE_WX
#include "DSPConfigDlgLLE.h" #include "DSPConfigDlgLLE.h"
#include "Debugger/Debugger.h" // For the DSPDebuggerLLE class #include "Debugger/Debugger.h" // For the DSPDebuggerLLE class
extern DSPDebuggerLLE* m_DebuggerFrame; extern DSPDebuggerLLE* m_DebuggerFrame;
#endif #endif
// The user of the DSPCore library must supply a few functions so that the // 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 // 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 // core isn't used, for example in an asm/disasm tool, then most of these
// can be stubbed out. // can be stubbed out.
u8 DSPHost_ReadHostMemory(u32 addr) u8 DSPHost_ReadHostMemory(u32 addr)
{ {
return g_dspInitialize.pARAM_Read_U8(addr); return g_dspInitialize.pARAM_Read_U8(addr);
} }
void DSPHost_WriteHostMemory(u8 value, u32 addr) void DSPHost_WriteHostMemory(u8 value, u32 addr)
{ {
g_dspInitialize.pARAM_Write_U8(value, addr); g_dspInitialize.pARAM_Write_U8(value, addr);
} }
bool DSPHost_OnThread() bool DSPHost_OnThread()
{ {
return g_dspInitialize.bOnThread; return g_dspInitialize.bOnThread;
} }
bool DSPHost_Running() bool DSPHost_Running()
{ {
return !(*g_dspInitialize.pEmulatorState); return !(*g_dspInitialize.pEmulatorState);
} }
void DSPHost_InterruptRequest() void DSPHost_InterruptRequest()
{ {
#ifdef DEBUG_EXP #ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "Firing an interrupt on the PPC ASAP"); NOTICE_LOG(DSPLLE, "Firing an interrupt on the PPC ASAP");
#endif #endif
// Fire an interrupt on the PPC ASAP. // Fire an interrupt on the PPC ASAP.
g_dspInitialize.pGenerateDSPInterrupt(); g_dspInitialize.pGenerateDSPInterrupt();
} }
u32 DSPHost_CodeLoaded(const u8 *ptr, int size) u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
{ {
u32 crc = GenerateCRC(ptr, size); u32 crc = GenerateCRC(ptr, size);
DumpDSPCode(ptr, size, crc); DumpDSPCode(ptr, size, crc);
// this crc is comparable with the HLE plugin // this crc is comparable with the HLE plugin
u32 ector_crc = 0; u32 ector_crc = 0;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
ector_crc ^= ptr[i]; ector_crc ^= ptr[i];
//let's rol //let's rol
ector_crc = (ector_crc << 3) | (ector_crc >> 29); ector_crc = (ector_crc << 3) | (ector_crc >> 29);
} }
DSPSymbols::Clear(); DSPSymbols::Clear();
// Auto load text file - if none just disassemble. // Auto load text file - if none just disassemble.
// TODO: Don't hardcode for Zelda. // TODO: Don't hardcode for Zelda.
NOTICE_LOG(DSPLLE, "CRC: %08x", ector_crc); NOTICE_LOG(DSPLLE, "CRC: %08x", ector_crc);
DSPSymbols::Clear(); DSPSymbols::Clear();
bool success = false; bool success = false;
switch (ector_crc) switch (ector_crc)
{ {
case 0x86840740: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Zelda.txt"); break; case 0x86840740: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Zelda.txt"); break;
case 0x42f64ac4: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Luigi.txt"); break; case 0x42f64ac4: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Luigi.txt"); break;
case 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX1.txt"); break; case 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX1.txt"); break;
default: success = false; break; default: success = false; break;
} }
if (!success) { if (!success) {
DSPSymbols::AutoDisassembly(0x0, 0x1000); DSPSymbols::AutoDisassembly(0x0, 0x1000);
} }
// Always add the ROM. // Always add the ROM.
DSPSymbols::AutoDisassembly(0x8000, 0x9000); DSPSymbols::AutoDisassembly(0x8000, 0x9000);
if (m_DebuggerFrame) if (m_DebuggerFrame)
m_DebuggerFrame->Refresh(); m_DebuggerFrame->Refresh();
return crc; return crc;
} }
void DSPHost_UpdateDebugger() void DSPHost_UpdateDebugger()
{ {
if (m_DebuggerFrame) if (m_DebuggerFrame)
m_DebuggerFrame->Refresh(); m_DebuggerFrame->Refresh();
} }

View File

@ -1,287 +1,287 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <iostream> // I hope this doesn't break anything #include <iostream> // I hope this doesn't break anything
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <list> #include <list>
#include <map> #include <map>
#include <string> #include <string>
#include "Common.h" #include "Common.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "DSPCore.h" #include "DSPCore.h"
#include "DSPSymbols.h" #include "DSPSymbols.h"
#include "disassemble.h" #include "disassemble.h"
namespace DSPSymbols { namespace DSPSymbols {
DSPSymbolDB g_dsp_symbol_db; DSPSymbolDB g_dsp_symbol_db;
std::map<u16, int> addr_to_line; std::map<u16, int> addr_to_line;
std::map<int, u16> line_to_addr; std::map<int, u16> line_to_addr;
std::map<int, const char *> line_to_symbol; std::map<int, const char *> line_to_symbol;
std::vector<std::string> lines; std::vector<std::string> lines;
int line_counter = 0; int line_counter = 0;
int Addr2Line(u16 address) // -1 for not found int Addr2Line(u16 address) // -1 for not found
{ {
std::map<u16, int>::iterator iter = addr_to_line.find(address); std::map<u16, int>::iterator iter = addr_to_line.find(address);
if (iter != addr_to_line.end()) if (iter != addr_to_line.end())
return iter->second; return iter->second;
else else
return -1; return -1;
} }
int Line2Addr(int line) // -1 for not found int Line2Addr(int line) // -1 for not found
{ {
std::map<int, u16>::iterator iter = line_to_addr.find(line); std::map<int, u16>::iterator iter = line_to_addr.find(line);
if (iter != line_to_addr.end()) if (iter != line_to_addr.end())
return iter->second; return iter->second;
else else
return -1; return -1;
} }
const char *GetLineText(int line) const char *GetLineText(int line)
{ {
if (line > 0 && line < (int)lines.size()) if (line > 0 && line < (int)lines.size())
{ {
return lines[line].c_str(); return lines[line].c_str();
} }
else else
return "----"; return "----";
} }
Symbol *DSPSymbolDB::GetSymbolFromAddr(u32 addr) Symbol *DSPSymbolDB::GetSymbolFromAddr(u32 addr)
{ {
XFuncMap::iterator it = functions.find(addr); XFuncMap::iterator it = functions.find(addr);
if (it != functions.end()) if (it != functions.end())
return &it->second; return &it->second;
else else
{ {
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++) for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{ {
if (addr >= iter->second.address && addr < iter->second.address + iter->second.size) if (addr >= iter->second.address && addr < iter->second.address + iter->second.size)
return &iter->second; return &iter->second;
} }
} }
return 0; return 0;
} }
// lower case only // lower case only
bool IsHexDigit(char c) { bool IsHexDigit(char c) {
switch (c) { switch (c) {
case '0': case '0':
case '1': case '1':
case '2': case '2':
case '3': case '3':
case '4': case '4':
case '5': case '5':
case '6': case '6':
case '7': case '7':
case '8': case '8':
case '9': case '9':
case 'a': case 'a':
case 'b': case 'b':
case 'c': case 'c':
case 'd': case 'd':
case 'e': case 'e':
case 'f': case 'f':
return true; return true;
default: default:
return false; return false;
} }
} }
bool IsAlpha(char c) { bool IsAlpha(char c) {
return (c >= 'A' && c <= 'Z') || return (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z'); (c >= 'a' && c <= 'z');
} }
void DisasssembleRange(u16 start, u16 end) void DisasssembleRange(u16 start, u16 end)
{ {
} }
bool ReadAnnotatedAssembly(const char *filename) bool ReadAnnotatedAssembly(const char *filename)
{ {
FILE *f = fopen(filename, "r"); FILE *f = fopen(filename, "r");
if (!f) { if (!f) {
ERROR_LOG(DSPLLE, "Bah! ReadAnnotatedAssembly couldn't find the file %s", filename); ERROR_LOG(DSPLLE, "Bah! ReadAnnotatedAssembly couldn't find the file %s", filename);
return false; return false;
} }
char line[512]; char line[512];
int last_addr = 0; int last_addr = 0;
lines.reserve(3000); lines.reserve(3000);
// Symbol generation // Symbol generation
int brace_count = 0; int brace_count = 0;
bool symbol_in_progress = false; bool symbol_in_progress = false;
int symbol_count = 0; int symbol_count = 0;
Symbol current_symbol; Symbol current_symbol;
while (fgets(line, 512, f)) while (fgets(line, 512, f))
{ {
// Scan string for the first 4-digit hex string. // Scan string for the first 4-digit hex string.
size_t len = strlen(line); size_t len = strlen(line);
int first_hex = -1; int first_hex = -1;
bool hex_found = false; bool hex_found = false;
for (unsigned int i = 0; i < strlen(line); i++) for (unsigned int i = 0; i < strlen(line); i++)
{ {
const char c = line[i]; const char c = line[i];
if (IsHexDigit(c)) if (IsHexDigit(c))
{ {
if (first_hex == -1) if (first_hex == -1)
{ {
first_hex = i; first_hex = i;
} }
else else
{ {
// Remove hex notation // Remove hex notation
if (i == first_hex + 3 && if (i == first_hex + 3 &&
(first_hex == 0 || line[first_hex - 1] != 'x') && (first_hex == 0 || line[first_hex - 1] != 'x') &&
(i >= len - 1 || line[i + 1] == ' ')) (i >= len - 1 || line[i + 1] == ' '))
{ {
hex_found = true; hex_found = true;
break; break;
} }
} }
} else { } else {
if (i - first_hex < 3) if (i - first_hex < 3)
{ {
first_hex = -1; first_hex = -1;
} }
if (IsAlpha(c)) if (IsAlpha(c))
break; break;
} }
} }
// Scan for function starts // Scan for function starts
if (!memcmp(line, "void", 4)) { if (!memcmp(line, "void", 4)) {
char temp[256]; char temp[256];
for (int i = 6; i < len; i++) { for (int i = 6; i < len; i++) {
if (line[i] == '(') { if (line[i] == '(') {
// Yep, got one. // Yep, got one.
memcpy(temp, line + 5, i - 5); memcpy(temp, line + 5, i - 5);
temp[i - 5] = 0; temp[i - 5] = 0;
// Mark symbol so the next hex sets the address // Mark symbol so the next hex sets the address
current_symbol.name = temp; current_symbol.name = temp;
current_symbol.address = 0xFFFF; current_symbol.address = 0xFFFF;
current_symbol.index = symbol_count++; current_symbol.index = symbol_count++;
symbol_in_progress = true; symbol_in_progress = true;
// Reset brace count. // Reset brace count.
brace_count = 0; brace_count = 0;
} }
} }
} }
// Scan for braces // Scan for braces
for (int i = 0; i < (int)len; i++) { for (int i = 0; i < (int)len; i++) {
if (line[i] == '{') if (line[i] == '{')
brace_count++; brace_count++;
if (line[i] == '}') if (line[i] == '}')
{ {
brace_count--; brace_count--;
if (brace_count == 0 && symbol_in_progress) { if (brace_count == 0 && symbol_in_progress) {
// Commit this symbol. // Commit this symbol.
current_symbol.size = last_addr - current_symbol.address + 1; current_symbol.size = last_addr - current_symbol.address + 1;
g_dsp_symbol_db.AddCompleteSymbol(current_symbol); g_dsp_symbol_db.AddCompleteSymbol(current_symbol);
current_symbol.address = 0xFFFF; current_symbol.address = 0xFFFF;
symbol_in_progress = false; symbol_in_progress = false;
} }
} }
} }
if (hex_found) if (hex_found)
{ {
int hex = 0; int hex = 0;
sscanf(line + first_hex, "%04x", &hex); sscanf(line + first_hex, "%04x", &hex);
// Sanity check // Sanity check
if (hex > last_addr + 3 || hex < last_addr - 3) { if (hex > last_addr + 3 || hex < last_addr - 3) {
static int errors = 0; static int errors = 0;
ERROR_LOG(DSPLLE, "Got Insane Hex Digit %04x (%04x) from %s", hex, last_addr, line); ERROR_LOG(DSPLLE, "Got Insane Hex Digit %04x (%04x) from %s", hex, last_addr, line);
errors++; errors++;
if (errors > 10) if (errors > 10)
{ {
fclose(f); fclose(f);
return false; return false;
} }
} }
else else
{ {
// if (line_counter >= 200 && line_counter <= 220) // if (line_counter >= 200 && line_counter <= 220)
// NOTICE_LOG(DSPLLE, "Got Hex Digit %04x from %s, line %i", hex, line, line_counter); // NOTICE_LOG(DSPLLE, "Got Hex Digit %04x from %s, line %i", hex, line, line_counter);
if (symbol_in_progress && current_symbol.address == 0xFFFF) if (symbol_in_progress && current_symbol.address == 0xFFFF)
current_symbol.address = hex; current_symbol.address = hex;
line_to_addr[line_counter] = hex; line_to_addr[line_counter] = hex;
addr_to_line[hex] = line_counter; addr_to_line[hex] = line_counter;
last_addr = hex; last_addr = hex;
} }
} }
lines.push_back(TabsToSpaces(4, line)); lines.push_back(TabsToSpaces(4, line));
line_counter++; line_counter++;
} }
fclose(f); fclose(f);
return true; return true;
} }
void AutoDisassembly(u16 start_addr, u16 end_addr) void AutoDisassembly(u16 start_addr, u16 end_addr)
{ {
AssemblerSettings settings; AssemblerSettings settings;
settings.show_pc = true; settings.show_pc = true;
settings.show_hex = true; settings.show_hex = true;
DSPDisassembler disasm(settings); DSPDisassembler disasm(settings);
u16 addr = start_addr; u16 addr = start_addr;
const u16 *ptr = (start_addr >> 15) ? g_dsp.irom : g_dsp.iram; const u16 *ptr = (start_addr >> 15) ? g_dsp.irom : g_dsp.iram;
while (addr < end_addr) while (addr < end_addr)
{ {
line_to_addr[line_counter] = addr; line_to_addr[line_counter] = addr;
addr_to_line[addr] = line_counter; addr_to_line[addr] = line_counter;
std::string buf; std::string buf;
if (!disasm.DisOpcode(ptr, 0, 2, &addr, buf)) if (!disasm.DisOpcode(ptr, 0, 2, &addr, buf))
{ {
ERROR_LOG(DSPLLE, "disasm failed at %04x", addr); ERROR_LOG(DSPLLE, "disasm failed at %04x", addr);
break; break;
} }
//NOTICE_LOG(DSPLLE, "added %04x %i %s", addr, line_counter, buf.c_str()); //NOTICE_LOG(DSPLLE, "added %04x %i %s", addr, line_counter, buf.c_str());
lines.push_back(buf); lines.push_back(buf);
line_counter++; line_counter++;
} }
} }
void Clear() void Clear()
{ {
addr_to_line.clear(); addr_to_line.clear();
line_to_addr.clear(); line_to_addr.clear();
lines.clear(); lines.clear();
line_counter = 0; line_counter = 0;
} }
} // namespace DSPSymbols } // namespace DSPSymbols

View File

@ -1,54 +1,54 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DSPSYMBOLS_H #ifndef _DSPSYMBOLS_H
#define _DSPSYMBOLS_H #define _DSPSYMBOLS_H
#include "Common.h" #include "Common.h"
#include "SymbolDB.h" #include "SymbolDB.h"
#include "AudioCommon.h" #include "AudioCommon.h"
#include <stdio.h> #include <stdio.h>
namespace DSPSymbols { namespace DSPSymbols {
class DSPSymbolDB : public SymbolDB class DSPSymbolDB : public SymbolDB
{ {
public: public:
DSPSymbolDB() {} DSPSymbolDB() {}
~DSPSymbolDB() {} ~DSPSymbolDB() {}
Symbol *GetSymbolFromAddr(u32 addr); Symbol *GetSymbolFromAddr(u32 addr);
}; };
extern DSPSymbolDB g_dsp_symbol_db; extern DSPSymbolDB g_dsp_symbol_db;
bool ReadAnnotatedAssembly(const char *filename); bool ReadAnnotatedAssembly(const char *filename);
void AutoDisassembly(u16 start_addr, u16 end_addr); void AutoDisassembly(u16 start_addr, u16 end_addr);
void Clear(); void Clear();
int Addr2Line(u16 address); int Addr2Line(u16 address);
int Line2Addr(int line); // -1 for not found int Line2Addr(int line); // -1 for not found
const char *GetLineText(int line); const char *GetLineText(int line);
} // namespace DSPSymbols } // namespace DSPSymbols
#endif #endif

View File

@ -1,228 +1,228 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" // Common #include "Common.h" // Common
#include <iostream> // System #include <iostream> // System
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include "Debugger.h" #include "Debugger.h"
#include "DSPRegisterView.h" #include "DSPRegisterView.h"
#include "CodeView.h" #include "CodeView.h"
#include "../DSPSymbols.h" #include "../DSPSymbols.h"
// Event table and class // Event table and class
BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxFrame) BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxFrame)
EVT_CLOSE(DSPDebuggerLLE::OnClose) EVT_CLOSE(DSPDebuggerLLE::OnClose)
EVT_MENU_RANGE(ID_RUNTOOL, ID_STEPTOOL, DSPDebuggerLLE::OnChangeState) EVT_MENU_RANGE(ID_RUNTOOL, ID_STEPTOOL, DSPDebuggerLLE::OnChangeState)
EVT_MENU(ID_SHOWPCTOOL, DSPDebuggerLLE::OnShowPC) EVT_MENU(ID_SHOWPCTOOL, DSPDebuggerLLE::OnShowPC)
EVT_TEXT(ID_ADDRBOX, DSPDebuggerLLE::OnAddrBoxChange) EVT_TEXT(ID_ADDRBOX, DSPDebuggerLLE::OnAddrBoxChange)
EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange) EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange)
END_EVENT_TABLE() END_EVENT_TABLE()
DSPDebuggerLLE::DSPDebuggerLLE(wxWindow *parent, wxWindowID id, const wxString &title, DSPDebuggerLLE::DSPDebuggerLLE(wxWindow *parent, wxWindowID id, const wxString &title,
const wxPoint &position, const wxSize& size, long style) const wxPoint &position, const wxSize& size, long style)
: wxFrame(parent, id, title, position, size, style) : wxFrame(parent, id, title, position, size, style)
, m_CachedStepCounter(-1) , m_CachedStepCounter(-1)
{ {
CreateGUIControls(); CreateGUIControls();
} }
DSPDebuggerLLE::~DSPDebuggerLLE() DSPDebuggerLLE::~DSPDebuggerLLE()
{ {
} }
void DSPDebuggerLLE::CreateGUIControls() void DSPDebuggerLLE::CreateGUIControls()
{ {
// Basic settings // Basic settings
SetSize(700, 800); SetSize(700, 800);
this->SetSizeHints(700, 800); this->SetSizeHints(700, 800);
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE)); this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
m_Toolbar = CreateToolBar(wxTB_NODIVIDER|wxTB_NOICONS|wxTB_HORZ_TEXT|wxTB_DOCKABLE, ID_TOOLBAR); m_Toolbar = CreateToolBar(wxTB_NODIVIDER|wxTB_NOICONS|wxTB_HORZ_TEXT|wxTB_DOCKABLE, ID_TOOLBAR);
m_Toolbar->AddTool(ID_RUNTOOL, wxT("Run"), wxNullBitmap, wxEmptyString, wxITEM_NORMAL); m_Toolbar->AddTool(ID_RUNTOOL, wxT("Run"), wxNullBitmap, wxEmptyString, wxITEM_NORMAL);
m_Toolbar->AddTool(ID_STEPTOOL, wxT("Step"), wxNullBitmap, wxT("Step Code "), wxITEM_NORMAL); m_Toolbar->AddTool(ID_STEPTOOL, wxT("Step"), wxNullBitmap, wxT("Step Code "), wxITEM_NORMAL);
m_Toolbar->AddTool(ID_SHOWPCTOOL, wxT("Show Pc"), wxNullBitmap, wxT("Show where PC is"), wxITEM_NORMAL); m_Toolbar->AddTool(ID_SHOWPCTOOL, wxT("Show Pc"), wxNullBitmap, wxT("Show where PC is"), wxITEM_NORMAL);
m_Toolbar->AddTool(ID_JUMPTOTOOL, wxT("Jump"), wxNullBitmap, wxT("Jump to a specific Address"), wxITEM_NORMAL); m_Toolbar->AddTool(ID_JUMPTOTOOL, wxT("Jump"), wxNullBitmap, wxT("Jump to a specific Address"), wxITEM_NORMAL);
m_Toolbar->AddSeparator(); m_Toolbar->AddSeparator();
m_Toolbar->AddControl(new wxTextCtrl(m_Toolbar, ID_ADDRBOX, _T(""))); m_Toolbar->AddControl(new wxTextCtrl(m_Toolbar, ID_ADDRBOX, _T("")));
m_Toolbar->Realize(); m_Toolbar->Realize();
wxBoxSizer* sMain = new wxBoxSizer(wxHORIZONTAL); wxBoxSizer* sMain = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL); wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
sizerLeft->Add(m_SymbolList = new wxListBox(this, ID_SYMBOLLIST, wxDefaultPosition, wxSize(140, 100), 0, NULL, wxLB_SORT), sizerLeft->Add(m_SymbolList = new wxListBox(this, ID_SYMBOLLIST, wxDefaultPosition, wxSize(140, 100), 0, NULL, wxLB_SORT),
1, wxEXPAND); 1, wxEXPAND);
m_CodeView = new CCodeView(&debug_interface, &DSPSymbols::g_dsp_symbol_db, this, ID_CODEVIEW); m_CodeView = new CCodeView(&debug_interface, &DSPSymbols::g_dsp_symbol_db, this, ID_CODEVIEW);
m_CodeView->SetPlain(); m_CodeView->SetPlain();
sMain->Add(sizerLeft, 0, wxEXPAND, 0); sMain->Add(sizerLeft, 0, wxEXPAND, 0);
sMain->Add(m_CodeView, 4, wxEXPAND, 0); sMain->Add(m_CodeView, 4, wxEXPAND, 0);
wxStaticLine* m_staticline = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL); wxStaticLine* m_staticline = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
sMain->Add(m_staticline, 0, wxEXPAND|wxALL, 0); sMain->Add(m_staticline, 0, wxEXPAND|wxALL, 0);
m_Regs = new DSPRegisterView(this, ID_DSP_REGS); m_Regs = new DSPRegisterView(this, ID_DSP_REGS);
sMain->Add(m_Regs, 0, wxEXPAND|wxALL, 5); sMain->Add(m_Regs, 0, wxEXPAND|wxALL, 5);
this->SetSizer(sMain); this->SetSizer(sMain);
this->Layout(); this->Layout();
UpdateState(); UpdateState();
} }
void DSPDebuggerLLE::OnClose(wxCloseEvent& event) void DSPDebuggerLLE::OnClose(wxCloseEvent& event)
{ {
Hide(); Hide();
} }
void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event) void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
{ {
switch (event.GetId()) switch (event.GetId())
{ {
case ID_RUNTOOL: case ID_RUNTOOL:
if (DSPCore_GetState() == DSPCORE_RUNNING) if (DSPCore_GetState() == DSPCORE_RUNNING)
DSPCore_SetState(DSPCORE_STEPPING); DSPCore_SetState(DSPCORE_STEPPING);
else else
DSPCore_SetState(DSPCORE_RUNNING); DSPCore_SetState(DSPCORE_RUNNING);
break; break;
case ID_STEPTOOL: case ID_STEPTOOL:
if (DSPCore_GetState() == DSPCORE_STEPPING) if (DSPCore_GetState() == DSPCORE_STEPPING)
DSPCore_Step(); DSPCore_Step();
break; break;
case ID_SHOWPCTOOL: case ID_SHOWPCTOOL:
FocusOnPC(); FocusOnPC();
break; break;
} }
UpdateState(); UpdateState();
} }
void DSPDebuggerLLE::OnShowPC(wxCommandEvent& event) void DSPDebuggerLLE::OnShowPC(wxCommandEvent& event)
{ {
Refresh(); Refresh();
FocusOnPC(); FocusOnPC();
} }
void DSPDebuggerLLE::Refresh() void DSPDebuggerLLE::Refresh()
{ {
UpdateSymbolMap(); UpdateSymbolMap();
UpdateDisAsmListView(); UpdateDisAsmListView();
UpdateRegisterFlags(); UpdateRegisterFlags();
UpdateState(); UpdateState();
} }
void DSPDebuggerLLE::FocusOnPC() void DSPDebuggerLLE::FocusOnPC()
{ {
JumpToAddress(g_dsp.pc); JumpToAddress(g_dsp.pc);
} }
void DSPDebuggerLLE::UpdateState() void DSPDebuggerLLE::UpdateState()
{ {
if (DSPCore_GetState() == DSPCORE_RUNNING) { if (DSPCore_GetState() == DSPCORE_RUNNING) {
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Pause")); m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Pause"));
m_Toolbar->FindById(ID_STEPTOOL)->Enable(false); m_Toolbar->FindById(ID_STEPTOOL)->Enable(false);
} }
else { else {
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Run")); m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Run"));
m_Toolbar->FindById(ID_STEPTOOL)->Enable(true); m_Toolbar->FindById(ID_STEPTOOL)->Enable(true);
} }
m_Toolbar->Realize(); m_Toolbar->Realize();
} }
void DSPDebuggerLLE::UpdateDisAsmListView() void DSPDebuggerLLE::UpdateDisAsmListView()
{ {
if (m_CachedStepCounter == g_dsp.step_counter) if (m_CachedStepCounter == g_dsp.step_counter)
return; return;
// show PC // show PC
FocusOnPC(); FocusOnPC();
m_CachedStepCounter = g_dsp.step_counter; m_CachedStepCounter = g_dsp.step_counter;
m_Regs->Update(); m_Regs->Update();
} }
void DSPDebuggerLLE::UpdateSymbolMap() void DSPDebuggerLLE::UpdateSymbolMap()
{ {
if (g_dsp.dram == NULL) if (g_dsp.dram == NULL)
return; return;
m_SymbolList->Freeze(); // HyperIris: wx style fast filling m_SymbolList->Freeze(); // HyperIris: wx style fast filling
m_SymbolList->Clear(); m_SymbolList->Clear();
for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator(); for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator();
iter != DSPSymbols::g_dsp_symbol_db.End(); iter++) iter != DSPSymbols::g_dsp_symbol_db.End(); iter++)
{ {
int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str())); int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str()));
m_SymbolList->SetClientData(idx, (void*)&iter->second); m_SymbolList->SetClientData(idx, (void*)&iter->second);
} }
m_SymbolList->Thaw(); m_SymbolList->Thaw();
} }
void DSPDebuggerLLE::OnSymbolListChange(wxCommandEvent& event) void DSPDebuggerLLE::OnSymbolListChange(wxCommandEvent& event)
{ {
int index = m_SymbolList->GetSelection(); int index = m_SymbolList->GetSelection();
if (index >= 0) { if (index >= 0) {
Symbol* pSymbol = static_cast<Symbol *>(m_SymbolList->GetClientData(index)); Symbol* pSymbol = static_cast<Symbol *>(m_SymbolList->GetClientData(index));
if (pSymbol != NULL) if (pSymbol != NULL)
{ {
if (pSymbol->type == Symbol::SYMBOL_FUNCTION) if (pSymbol->type == Symbol::SYMBOL_FUNCTION)
{ {
JumpToAddress(pSymbol->address); JumpToAddress(pSymbol->address);
} }
} }
} }
} }
void DSPDebuggerLLE::UpdateRegisterFlags() void DSPDebuggerLLE::UpdateRegisterFlags()
{ {
} }
void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event) void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event)
{ {
wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(ID_ADDRBOX); wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(ID_ADDRBOX);
wxString txt = pAddrCtrl->GetValue(); wxString txt = pAddrCtrl->GetValue();
std::string text(txt.mb_str()); std::string text(txt.mb_str());
text = StripSpaces(text); text = StripSpaces(text);
if (text.size()) if (text.size())
{ {
u32 addr; u32 addr;
sscanf(text.c_str(), "%04x", &addr); sscanf(text.c_str(), "%04x", &addr);
if (JumpToAddress(addr)) if (JumpToAddress(addr))
pAddrCtrl->SetBackgroundColour(*wxWHITE); pAddrCtrl->SetBackgroundColour(*wxWHITE);
else else
pAddrCtrl->SetBackgroundColour(*wxRED); pAddrCtrl->SetBackgroundColour(*wxRED);
} }
event.Skip(1); event.Skip(1);
} }
bool DSPDebuggerLLE::JumpToAddress(u16 addr) bool DSPDebuggerLLE::JumpToAddress(u16 addr)
{ {
int new_line = DSPSymbols::Addr2Line(addr); int new_line = DSPSymbols::Addr2Line(addr);
if (new_line >= 0) { if (new_line >= 0) {
m_CodeView->Center(new_line); m_CodeView->Center(new_line);
return true; return true;
} else { } else {
return false; return false;
} }
} }

View File

@ -1,126 +1,126 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _DSP_DEBUGGER_LLE_H #ifndef _DSP_DEBUGGER_LLE_H
#define _DSP_DEBUGGER_LLE_H #define _DSP_DEBUGGER_LLE_H
// general things // general things
#include <iostream> #include <iostream>
#include <vector> #include <vector>
#include <list> #include <list>
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#include <wx/wx.h> #include <wx/wx.h>
#include <wx/frame.h> #include <wx/frame.h>
#include <wx/button.h> #include <wx/button.h>
#include <wx/stattext.h> #include <wx/stattext.h>
#include <wx/statbox.h> #include <wx/statbox.h>
#include <wx/sizer.h> #include <wx/sizer.h>
#include <wx/listctrl.h> #include <wx/listctrl.h>
#include <wx/statline.h> #include <wx/statline.h>
#include "disassemble.h" #include "disassemble.h"
#include "DSPInterpreter.h" #include "DSPInterpreter.h"
#include "DSPMemoryMap.h" #include "DSPMemoryMap.h"
#include "../DSPDebugInterface.h" #include "../DSPDebugInterface.h"
class DSPRegisterView; class DSPRegisterView;
class CCodeView; class CCodeView;
class DSPDebuggerLLE : public wxFrame class DSPDebuggerLLE : public wxFrame
{ {
public: public:
DSPDebuggerLLE(wxWindow *parent, DSPDebuggerLLE(wxWindow *parent,
wxWindowID id = wxID_ANY, wxWindowID id = wxID_ANY,
const wxString &title = wxT("DSP LLE Debugger"), const wxString &title = wxT("DSP LLE Debugger"),
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize, const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_FRAME_STYLE); long style = wxDEFAULT_FRAME_STYLE);
virtual ~DSPDebuggerLLE(); virtual ~DSPDebuggerLLE();
void Refresh(); void Refresh();
private: private:
DECLARE_EVENT_TABLE(); DECLARE_EVENT_TABLE();
enum enum
{ {
// Toolbar // Toolbar
ID_TOOLBAR = 1000, ID_TOOLBAR = 1000,
ID_RUNTOOL, ID_RUNTOOL,
ID_STEPTOOL, ID_STEPTOOL,
ID_SHOWPCTOOL, ID_SHOWPCTOOL,
ID_ADDRBOX, ID_ADDRBOX,
ID_JUMPTOTOOL, ID_JUMPTOTOOL,
ID_DISASMDUMPTOOL, ID_DISASMDUMPTOOL,
ID_CHECK_ASSERTINT, ID_CHECK_ASSERTINT,
ID_CHECK_HALT, ID_CHECK_HALT,
ID_CHECK_INIT, ID_CHECK_INIT,
ID_SYMBOLLIST, ID_SYMBOLLIST,
// Code view // Code view
ID_CODEVIEW, ID_CODEVIEW,
// Register View // Register View
ID_DSP_REGS, ID_DSP_REGS,
}; };
// Disasm listctrl columns // Disasm listctrl columns
enum enum
{ {
COLUMN_BP, COLUMN_BP,
COLUMN_FUNCTION, COLUMN_FUNCTION,
COLUMN_ADDRESS, COLUMN_ADDRESS,
COLUMN_MNEMONIC, COLUMN_MNEMONIC,
COLUMN_OPCODE, COLUMN_OPCODE,
COLUMN_EXT, COLUMN_EXT,
COLUMN_PARAM, COLUMN_PARAM,
}; };
DSPDebugInterface debug_interface; DSPDebugInterface debug_interface;
u64 m_CachedStepCounter; u64 m_CachedStepCounter;
// GUI updaters // GUI updaters
void UpdateDisAsmListView(); void UpdateDisAsmListView();
void UpdateRegisterFlags(); void UpdateRegisterFlags();
void UpdateSymbolMap(); void UpdateSymbolMap();
void UpdateState(); void UpdateState();
// GUI items // GUI items
wxToolBar* m_Toolbar; wxToolBar* m_Toolbar;
CCodeView* m_CodeView; CCodeView* m_CodeView;
DSPRegisterView* m_Regs; DSPRegisterView* m_Regs;
wxListBox* m_SymbolList; wxListBox* m_SymbolList;
void OnClose(wxCloseEvent& event); void OnClose(wxCloseEvent& event);
void OnChangeState(wxCommandEvent& event); void OnChangeState(wxCommandEvent& event);
void OnShowPC(wxCommandEvent& event); void OnShowPC(wxCommandEvent& event);
void OnRightClick(wxListEvent& event); void OnRightClick(wxListEvent& event);
void OnDoubleClick(wxListEvent& event); void OnDoubleClick(wxListEvent& event);
void OnAddrBoxChange(wxCommandEvent& event); void OnAddrBoxChange(wxCommandEvent& event);
void OnSymbolListChange(wxCommandEvent& event); void OnSymbolListChange(wxCommandEvent& event);
bool JumpToAddress(u16 addr); bool JumpToAddress(u16 addr);
void CreateGUIControls(); void CreateGUIControls();
void FocusOnPC(); void FocusOnPC();
void UnselectAll(); void UnselectAll();
}; };
#endif //_DSP_DEBUGGER_LLE_H #endif //_DSP_DEBUGGER_LLE_H

View File

@ -1,336 +1,336 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "BPFunctions.h" #include "BPFunctions.h"
#include "D3DBase.h" #include "D3DBase.h"
#include "Config.h" #include "Config.h"
#include "Common.h" #include "Common.h"
#include "TextureCache.h" #include "TextureCache.h"
#include "VertexManager.h" #include "VertexManager.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "Utils.h" #include "Utils.h"
bool textureChanged[8]; bool textureChanged[8];
const bool renderFog = false; const bool renderFog = false;
using namespace D3D; using namespace D3D;
// State translation lookup tables // State translation lookup tables
static const D3DBLEND d3dSrcFactors[8] = static const D3DBLEND d3dSrcFactors[8] =
{ {
D3DBLEND_ZERO, D3DBLEND_ZERO,
D3DBLEND_ONE, D3DBLEND_ONE,
D3DBLEND_DESTCOLOR, D3DBLEND_DESTCOLOR,
D3DBLEND_INVDESTCOLOR, D3DBLEND_INVDESTCOLOR,
D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA, D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA D3DBLEND_INVDESTALPHA
}; };
static const D3DBLEND d3dDestFactors[8] = static const D3DBLEND d3dDestFactors[8] =
{ {
D3DBLEND_ZERO, D3DBLEND_ZERO,
D3DBLEND_ONE, D3DBLEND_ONE,
D3DBLEND_SRCCOLOR, D3DBLEND_SRCCOLOR,
D3DBLEND_INVSRCCOLOR, D3DBLEND_INVSRCCOLOR,
D3DBLEND_SRCALPHA, D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA, D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA, D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA D3DBLEND_INVDESTALPHA
}; };
static const D3DCULL d3dCullModes[4] = static const D3DCULL d3dCullModes[4] =
{ {
D3DCULL_NONE, D3DCULL_NONE,
D3DCULL_CCW, D3DCULL_CCW,
D3DCULL_CW, D3DCULL_CW,
D3DCULL_CCW D3DCULL_CCW
}; };
static const D3DCMPFUNC d3dCmpFuncs[8] = static const D3DCMPFUNC d3dCmpFuncs[8] =
{ {
D3DCMP_NEVER, D3DCMP_NEVER,
D3DCMP_LESS, D3DCMP_LESS,
D3DCMP_EQUAL, D3DCMP_EQUAL,
D3DCMP_LESSEQUAL, D3DCMP_LESSEQUAL,
D3DCMP_GREATER, D3DCMP_GREATER,
D3DCMP_NOTEQUAL, D3DCMP_NOTEQUAL,
D3DCMP_GREATEREQUAL, D3DCMP_GREATEREQUAL,
D3DCMP_ALWAYS D3DCMP_ALWAYS
}; };
static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] = static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
{ {
D3DTEXF_NONE, D3DTEXF_NONE,
D3DTEXF_POINT, D3DTEXF_POINT,
D3DTEXF_ANISOTROPIC, D3DTEXF_ANISOTROPIC,
D3DTEXF_LINEAR, //reserved D3DTEXF_LINEAR, //reserved
}; };
static const D3DTEXTUREADDRESS d3dClamps[4] = static const D3DTEXTUREADDRESS d3dClamps[4] =
{ {
D3DTADDRESS_CLAMP, D3DTADDRESS_CLAMP,
D3DTADDRESS_WRAP, D3DTADDRESS_WRAP,
D3DTADDRESS_MIRROR, D3DTADDRESS_MIRROR,
D3DTADDRESS_WRAP //reserved D3DTADDRESS_WRAP //reserved
}; };
namespace BPFunctions namespace BPFunctions
{ {
void FlushPipeline() void FlushPipeline()
{ {
VertexManager::Flush(); VertexManager::Flush();
} }
void SetGenerationMode(const Bypass &bp) void SetGenerationMode(const Bypass &bp)
{ {
// dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]); // dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
Renderer::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]); Renderer::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
if (bpmem.genMode.cullmode == 3) if (bpmem.genMode.cullmode == 3)
{ {
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0); // dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, 0); Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, 0);
} }
else else
{ {
DWORD write = 0; DWORD write = 0;
if (bpmem.blendmode.alphaupdate) if (bpmem.blendmode.alphaupdate)
write = D3DCOLORWRITEENABLE_ALPHA; write = D3DCOLORWRITEENABLE_ALPHA;
if (bpmem.blendmode.colorupdate) if (bpmem.blendmode.colorupdate)
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, write); // dev->SetRenderState(D3DRS_COLORWRITEENABLE, write);
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write); Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
} }
} }
void SetScissor(const Bypass &bp) void SetScissor(const Bypass &bp)
{ {
Renderer::SetScissorRect(); Renderer::SetScissorRect();
} }
void SetLineWidth(const Bypass &bp) void SetLineWidth(const Bypass &bp)
{ {
// We can't change line width in D3D unless we use ID3DXLine // We can't change line width in D3D unless we use ID3DXLine
float psize = float(bpmem.lineptwidth.pointsize) * 6.0f; float psize = float(bpmem.lineptwidth.pointsize) * 6.0f;
Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize)); Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize));
} }
void SetDepthMode(const Bypass &bp) void SetDepthMode(const Bypass &bp)
{ {
if (bpmem.zmode.testenable) if (bpmem.zmode.testenable)
{ {
// dev->SetRenderState(D3DRS_ZENABLE, TRUE); // dev->SetRenderState(D3DRS_ZENABLE, TRUE);
// dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable); // dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
// dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]); // dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]);
Renderer::SetRenderState(D3DRS_ZENABLE, TRUE); Renderer::SetRenderState(D3DRS_ZENABLE, TRUE);
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable); Renderer::SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
Renderer::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func]); Renderer::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func]);
} }
else else
{ {
// if the test is disabled write is disabled too // if the test is disabled write is disabled too
// dev->SetRenderState(D3DRS_ZENABLE, FALSE); // dev->SetRenderState(D3DRS_ZENABLE, FALSE);
// dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); // dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
Renderer::SetRenderState(D3DRS_ZENABLE, FALSE); Renderer::SetRenderState(D3DRS_ZENABLE, FALSE);
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, FALSE); Renderer::SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
} }
//if (!bpmem.zmode.updateenable) //if (!bpmem.zmode.updateenable)
// Renderer::SetRenderMode(Renderer::RM_Normal); // Renderer::SetRenderMode(Renderer::RM_Normal);
} }
void SetBlendMode(const Bypass &bp) void SetBlendMode(const Bypass &bp)
{ {
if (bp.changes & 1) if (bp.changes & 1)
Renderer::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable); Renderer::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable);
D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor]; D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor];
D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor]; D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor];
if (bp.changes & 0x700) if (bp.changes & 0x700)
Renderer::SetRenderState(D3DRS_SRCBLEND, src); Renderer::SetRenderState(D3DRS_SRCBLEND, src);
if (bp.changes & 0xE0) { if (bp.changes & 0xE0) {
if (!bpmem.blendmode.subtract) if (!bpmem.blendmode.subtract)
{ {
Renderer::SetRenderState(D3DRS_DESTBLEND, dst); Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
} }
else else
{ {
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
} }
} }
if (bp.changes & 0x800) if (bp.changes & 0x800)
{ {
if (bpmem.blendmode.subtract) if (bpmem.blendmode.subtract)
{ {
Renderer::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); Renderer::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
} }
else else
{ {
Renderer::SetRenderState(D3DRS_SRCBLEND, src); Renderer::SetRenderState(D3DRS_SRCBLEND, src);
Renderer::SetRenderState(D3DRS_DESTBLEND, dst); Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
} }
Renderer::SetRenderState(D3DRS_BLENDOP, bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD); Renderer::SetRenderState(D3DRS_BLENDOP, bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD);
} }
} }
void SetDitherMode(const Bypass &bp) void SetDitherMode(const Bypass &bp)
{ {
Renderer::SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither); Renderer::SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither);
} }
void SetLogicOpMode(const Bypass &bp) void SetLogicOpMode(const Bypass &bp)
{ {
// Logic op blending. D3D can't do this but can fake some modes. // Logic op blending. D3D can't do this but can fake some modes.
} }
void SetColorMask(const Bypass &bp) void SetColorMask(const Bypass &bp)
{ {
DWORD write = 0; DWORD write = 0;
if (bpmem.blendmode.alphaupdate) if (bpmem.blendmode.alphaupdate)
write = D3DCOLORWRITEENABLE_ALPHA; write = D3DCOLORWRITEENABLE_ALPHA;
if (bpmem.blendmode.colorupdate) if (bpmem.blendmode.colorupdate)
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE; write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write); Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
} }
float GetRendererTargetScaleX() float GetRendererTargetScaleX()
{ {
return Renderer::GetXScale(); return Renderer::GetXScale();
} }
float GetRendererTargetScaleY() float GetRendererTargetScaleY()
{ {
return Renderer::GetYScale(); return Renderer::GetYScale();
} }
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const bool &scaleByHalf) void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const bool &scaleByHalf)
{ {
RECT rec = { rc.left, rc.top, rc.right, rc.bottom }; RECT rec = { rc.left, rc.top, rc.right, rc.bottom };
TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest<<5, &rec); TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest<<5, &rec);
} }
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight) void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight)
{ {
Renderer::SwapBuffers(); Renderer::SwapBuffers();
PRIM_LOG("Renderer::SwapBuffers()"); PRIM_LOG("Renderer::SwapBuffers()");
g_VideoInitialize.pCopiedToXFB(); g_VideoInitialize.pCopiedToXFB();
} }
void ClearScreen(const Bypass &bp, const TRectangle &multirc) void ClearScreen(const Bypass &bp, const TRectangle &multirc)
{ {
// it seems that the GC is able to alpha blend on color-fill // it seems that the GC is able to alpha blend on color-fill
// we cant do that so if alpha is != 255 we skip it // we cant do that so if alpha is != 255 we skip it
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
// Since clear operations use the source rectangle, we have to do // Since clear operations use the source rectangle, we have to do
// regular renders // regular renders
DWORD clearflags = 0; DWORD clearflags = 0;
D3DCOLOR col = 0; D3DCOLOR col = 0;
float clearZ = 0; float clearZ = 0;
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate) if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
{ {
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate) if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
col = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; col = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
// clearflags |= D3DCLEAR_TARGET; set to break animal crossing :p // clearflags |= D3DCLEAR_TARGET; set to break animal crossing :p
} }
// clear z-buffer // clear z-buffer
if (bpmem.zmode.updateenable) if (bpmem.zmode.updateenable)
{ {
clearZ = (float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF); clearZ = (float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF);
if (clearZ > 1.0f) clearZ = 1.0f; if (clearZ > 1.0f) clearZ = 1.0f;
if (clearZ < 0.0f) clearZ = 0.0f; if (clearZ < 0.0f) clearZ = 0.0f;
clearflags |= D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL; clearflags |= D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
} }
D3D::dev->Clear(0, NULL, clearflags, col, clearZ, 0); D3D::dev->Clear(0, NULL, clearflags, col, clearZ, 0);
} }
void RestoreRenderState(const Bypass &bp) void RestoreRenderState(const Bypass &bp)
{ {
//Renderer::SetRenderMode(Renderer::RM_Normal); //Renderer::SetRenderMode(Renderer::RM_Normal);
} }
bool GetConfig(const int &type) bool GetConfig(const int &type)
{ {
switch (type) switch (type)
{ {
case CONFIG_ISWII: case CONFIG_ISWII:
return g_VideoInitialize.bWii; return g_VideoInitialize.bWii;
case CONFIG_DISABLEFOG: case CONFIG_DISABLEFOG:
return false; return false;
case CONFIG_SHOWEFBREGIONS: case CONFIG_SHOWEFBREGIONS:
return false; return false;
default: default:
PanicAlert("GetConfig Error: Unknown Config Type!"); PanicAlert("GetConfig Error: Unknown Config Type!");
return false; return false;
} }
} }
u8 *GetPointer(const u32 &address) u8 *GetPointer(const u32 &address)
{ {
return g_VideoInitialize.pGetMemoryPointer(address); return g_VideoInitialize.pGetMemoryPointer(address);
} }
void SetSamplerState(const Bypass &bp) void SetSamplerState(const Bypass &bp)
{ {
FourTexUnits &tex = bpmem.tex[(bp.address & 0xE0) == 0xA0]; FourTexUnits &tex = bpmem.tex[(bp.address & 0xE0) == 0xA0];
int stage = (bp.address & 3);//(addr>>4)&2; int stage = (bp.address & 3);//(addr>>4)&2;
TexMode0 &tm0 = tex.texMode0[stage]; TexMode0 &tm0 = tex.texMode0[stage];
D3DTEXTUREFILTERTYPE min, mag, mip; D3DTEXTUREFILTERTYPE min, mag, mip;
if (g_Config.bForceFiltering) if (g_Config.bForceFiltering)
{ {
min = mag = mip = D3DTEXF_LINEAR; min = mag = mip = D3DTEXF_LINEAR;
} }
else else
{ {
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT; min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT; mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
mip = d3dMipFilters[tm0.min_filter & 3]; mip = d3dMipFilters[tm0.min_filter & 3];
} }
if ((bp.address & 0xE0) == 0xA0) if ((bp.address & 0xE0) == 0xA0)
stage += 4; stage += 4;
if (g_Config.bForceMaxAniso) if (g_Config.bForceMaxAniso)
{ {
mag = D3DTEXF_ANISOTROPIC; mag = D3DTEXF_ANISOTROPIC;
mip = D3DTEXF_ANISOTROPIC; mip = D3DTEXF_ANISOTROPIC;
min = D3DTEXF_ANISOTROPIC; min = D3DTEXF_ANISOTROPIC;
} }
dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min); dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min);
dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag); dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag);
dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip); dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip);
dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 16); dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 16);
dev->SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]); dev->SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
dev->SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]); dev->SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
//wip //wip
//dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f); //dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f);
//char temp[256]; //char temp[256];
//sprintf(temp,"lod %f",tm0.lod_bias/4.0f); //sprintf(temp,"lod %f",tm0.lod_bias/4.0f);
//g_VideoInitialize.pLog(temp); //g_VideoInitialize.pLog(temp);
} }
void SetInterlacingMode(const Bypass &bp) void SetInterlacingMode(const Bypass &bp)
{ {
// TODO // TODO
} }
}; };

View File

@ -1,212 +1,212 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "BPFunctions.h" #include "BPFunctions.h"
#include "Globals.h" #include "Globals.h"
#include "Profiler.h" #include "Profiler.h"
#include "Config.h" #include "Config.h"
#include "VertexManager.h" #include "VertexManager.h"
#include "Render.h" #include "Render.h"
#include "TextureMngr.h" #include "TextureMngr.h"
#include "TextureConverter.h" #include "TextureConverter.h"
#include "VertexShaderManager.h" #include "VertexShaderManager.h"
#include "XFB.h" #include "XFB.h"
#include "main.h" #include "main.h"
namespace BPFunctions namespace BPFunctions
{ {
// ---------------------------------------------- // ----------------------------------------------
// State translation lookup tables // State translation lookup tables
// Reference: Yet Another Gamecube Documentation // Reference: Yet Another Gamecube Documentation
// ---------------------------------------------- // ----------------------------------------------
static const GLenum glCmpFuncs[8] = { static const GLenum glCmpFuncs[8] = {
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
}; };
static const GLenum glLogicOpCodes[16] = { static const GLenum glLogicOpCodes[16] = {
GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP, GL_XOR, GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP, GL_XOR,
GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET
}; };
void FlushPipeline() void FlushPipeline()
{ {
VertexManager::Flush(); VertexManager::Flush();
} }
void SetGenerationMode(const Bypass &bp) void SetGenerationMode(const Bypass &bp)
{ {
// none, ccw, cw, ccw // none, ccw, cw, ccw
if (bpmem.genMode.cullmode > 0) if (bpmem.genMode.cullmode > 0)
{ {
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW); glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW);
} }
else else
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
} }
void SetScissor(const Bypass &bp) void SetScissor(const Bypass &bp)
{ {
if (!Renderer::SetScissorRect()) if (!Renderer::SetScissorRect())
if (bp.address == BPMEM_SCISSORBR) if (bp.address == BPMEM_SCISSORBR)
ERROR_LOG(VIDEO, "bad scissor!"); ERROR_LOG(VIDEO, "bad scissor!");
} }
void SetLineWidth(const Bypass &bp) void SetLineWidth(const Bypass &bp)
{ {
float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f; float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f;
if (bpmem.lineptwidth.linesize > 0) if (bpmem.lineptwidth.linesize > 0)
glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths
if (bpmem.lineptwidth.pointsize > 0) if (bpmem.lineptwidth.pointsize > 0)
glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f); glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f);
} }
void SetDepthMode(const Bypass &bp) void SetDepthMode(const Bypass &bp)
{ {
if (bpmem.zmode.testenable) if (bpmem.zmode.testenable)
{ {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthMask(bpmem.zmode.updateenable ? GL_TRUE : GL_FALSE); glDepthMask(bpmem.zmode.updateenable ? GL_TRUE : GL_FALSE);
glDepthFunc(glCmpFuncs[bpmem.zmode.func]); glDepthFunc(glCmpFuncs[bpmem.zmode.func]);
} }
else else
{ {
// if the test is disabled write is disabled too // if the test is disabled write is disabled too
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE); glDepthMask(GL_FALSE);
} }
} }
void SetBlendMode(const Bypass &bp) void SetBlendMode(const Bypass &bp)
{ {
Renderer::SetBlendMode(false); Renderer::SetBlendMode(false);
} }
void SetDitherMode(const Bypass &bp) void SetDitherMode(const Bypass &bp)
{ {
if (bpmem.blendmode.dither) if (bpmem.blendmode.dither)
glEnable(GL_DITHER); glEnable(GL_DITHER);
else else
glDisable(GL_DITHER); glDisable(GL_DITHER);
} }
void SetLogicOpMode(const Bypass &bp) void SetLogicOpMode(const Bypass &bp)
{ {
if (bpmem.blendmode.logicopenable) if (bpmem.blendmode.logicopenable)
{ {
glEnable(GL_COLOR_LOGIC_OP); glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]); glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
} }
else else
glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_COLOR_LOGIC_OP);
} }
void SetColorMask(const Bypass &bp) void SetColorMask(const Bypass &bp)
{ {
Renderer::SetColorMask(); Renderer::SetColorMask();
} }
float GetRendererTargetScaleX() float GetRendererTargetScaleX()
{ {
return Renderer::GetTargetScaleX(); return Renderer::GetTargetScaleX();
} }
float GetRendererTargetScaleY() float GetRendererTargetScaleY()
{ {
return Renderer::GetTargetScaleY(); return Renderer::GetTargetScaleY();
} }
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const bool &scaleByHalf) void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const bool &scaleByHalf)
{ {
// bpmem.zcontrol.pixel_format to PIXELFMT_Z24 is when the game wants to copy from ZBuffer (Zbuffer uses 24-bit Format) // bpmem.zcontrol.pixel_format to PIXELFMT_Z24 is when the game wants to copy from ZBuffer (Zbuffer uses 24-bit Format)
if (!g_Config.bEFBCopyDisable) if (!g_Config.bEFBCopyDisable)
if (g_Config.bCopyEFBToRAM) // To RAM if (g_Config.bCopyEFBToRAM) // To RAM
TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc); TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
else // To OGL Texture else // To OGL Texture
TextureMngr::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc); TextureMngr::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
} }
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight) void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight)
{ {
Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, multirc); Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, multirc);
} }
void ClearScreen(const Bypass &bp, const TRectangle &multirc) void ClearScreen(const Bypass &bp, const TRectangle &multirc)
{ {
// Update the view port for clearing the picture // Update the view port for clearing the picture
glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight()); glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
// Always set the scissor in case it was set by the game and has not been reset // Always set the scissor in case it was set by the game and has not been reset
glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom), glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom),
(multirc.right - multirc.left), (multirc.bottom - multirc.top)); (multirc.right - multirc.left), (multirc.bottom - multirc.top));
// --------------------------- // ---------------------------
VertexShaderManager::SetViewportChanged(); VertexShaderManager::SetViewportChanged();
// Since clear operations use the source rectangle, we have to do // Since clear operations use the source rectangle, we have to do
// regular renders (glClear clears the entire buffer) // regular renders (glClear clears the entire buffer)
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate || bpmem.zmode.updateenable) if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate || bpmem.zmode.updateenable)
{ {
GLbitfield bits = 0; GLbitfield bits = 0;
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate) if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
{ {
u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB; u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
// Alpha may or may not be present depending on the EFB pixel format. // Alpha may or may not be present depending on the EFB pixel format.
GLclampf clearAlpha = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) ? GLclampf clearAlpha = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) ?
((clearColor>>24) & 0xff)*(1/255.0f) : 1.0f; ((clearColor>>24) & 0xff)*(1/255.0f) : 1.0f;
glClearColor(((clearColor>>16) & 0xff)*(1/255.0f), glClearColor(((clearColor>>16) & 0xff)*(1/255.0f),
((clearColor>>8 ) & 0xff)*(1/255.0f), ((clearColor>>8 ) & 0xff)*(1/255.0f),
((clearColor>>0 ) & 0xff)*(1/255.0f), ((clearColor>>0 ) & 0xff)*(1/255.0f),
clearAlpha); clearAlpha);
bits |= GL_COLOR_BUFFER_BIT; bits |= GL_COLOR_BUFFER_BIT;
} }
if (bpmem.zmode.updateenable) if (bpmem.zmode.updateenable)
{ {
glClearDepth((float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF)); glClearDepth((float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF));
bits |= GL_DEPTH_BUFFER_BIT; bits |= GL_DEPTH_BUFFER_BIT;
} }
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glClear(bits); glClear(bits);
} }
} }
void RestoreRenderState(const Bypass &bp) void RestoreRenderState(const Bypass &bp)
{ {
Renderer::RestoreGLState(); Renderer::RestoreGLState();
} }
bool GetConfig(const int &type) bool GetConfig(const int &type)
{ {
switch (type) switch (type)
{ {
case CONFIG_ISWII: case CONFIG_ISWII:
return g_VideoInitialize.bWii; return g_VideoInitialize.bWii;
case CONFIG_DISABLEFOG: case CONFIG_DISABLEFOG:
return g_Config.bDisableFog; return g_Config.bDisableFog;
case CONFIG_SHOWEFBREGIONS: case CONFIG_SHOWEFBREGIONS:
return g_Config.bShowEFBCopyRegions; return g_Config.bShowEFBCopyRegions;
default: default:
PanicAlert("GetConfig Error: Unknown Config Type!"); PanicAlert("GetConfig Error: Unknown Config Type!");
return false; return false;
} }
} }
u8 *GetPointer(const u32 &address) u8 *GetPointer(const u32 &address)
{ {
return g_VideoInitialize.pGetMemoryPointer(address); return g_VideoInitialize.pGetMemoryPointer(address);
} }
void SetSamplerState(const Bypass &bp) void SetSamplerState(const Bypass &bp)
{ {
// TODO // TODO
} }
void SetInterlacingMode(const Bypass &bp) void SetInterlacingMode(const Bypass &bp)
{ {
// TODO // TODO
} }
}; };

View File

@ -1,451 +1,451 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Globals.h" #include "Globals.h"
#include "FramebufferManager.h" #include "FramebufferManager.h"
#include "TextureConverter.h" #include "TextureConverter.h"
#include "XFB.h" #include "XFB.h"
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples) void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
{ {
m_targetWidth = targetWidth; m_targetWidth = targetWidth;
m_targetHeight = targetHeight; m_targetHeight = targetHeight;
m_msaaSamples = msaaSamples; m_msaaSamples = msaaSamples;
m_msaaCoverageSamples = msaaCoverageSamples; m_msaaCoverageSamples = msaaCoverageSamples;
// The EFB can be set to different pixel formats by the game through the // The EFB can be set to different pixel formats by the game through the
// BPMEM_ZCOMPARE register (which should probably have a different name). // BPMEM_ZCOMPARE register (which should probably have a different name).
// They are: // They are:
// - 24-bit RGB (8-bit components) with 24-bit Z // - 24-bit RGB (8-bit components) with 24-bit Z
// - 24-bit RGBA (6-bit components) with 24-bit Z // - 24-bit RGBA (6-bit components) with 24-bit Z
// - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z // - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z
// We only use one EFB format here: 32-bit ARGB with 24-bit Z. // We only use one EFB format here: 32-bit ARGB with 24-bit Z.
// Multisampling depends on user settings. // Multisampling depends on user settings.
// The distinction becomes important for certain operations, i.e. the // The distinction becomes important for certain operations, i.e. the
// alpha channel should be ignored if the EFB does not have one. // alpha channel should be ignored if the EFB does not have one.
// Create EFB target. // Create EFB target.
glGenFramebuffersEXT(1, &m_efbFramebuffer); glGenFramebuffersEXT(1, &m_efbFramebuffer);
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
{ {
// EFB targets will be textures in non-MSAA mode. // EFB targets will be textures in non-MSAA mode.
GLuint glObj[2]; GLuint glObj[2];
glGenTextures(2, glObj); glGenTextures(2, glObj);
m_efbColor = glObj[0]; m_efbColor = glObj[0];
m_efbDepth = glObj[1]; m_efbDepth = glObj[1];
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Bind target textures to the EFB framebuffer. // Bind target textures to the EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
} }
else else
{ {
// EFB targets will be renderbuffers in MSAA mode (required by OpenGL). // EFB targets will be renderbuffers in MSAA mode (required by OpenGL).
// Resolve targets will be created to transfer EFB to RAM textures. // Resolve targets will be created to transfer EFB to RAM textures.
// XFB framebuffer will be created to transfer EFB to XFB texture. // XFB framebuffer will be created to transfer EFB to XFB texture.
// Create EFB target renderbuffers. // Create EFB target renderbuffers.
GLuint glObj[2]; GLuint glObj[2];
glGenRenderbuffersEXT(2, glObj); glGenRenderbuffersEXT(2, glObj);
m_efbColor = glObj[0]; m_efbColor = glObj[0];
m_efbDepth = glObj[1]; m_efbDepth = glObj[1];
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
if (m_msaaCoverageSamples) if (m_msaaCoverageSamples)
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
else else
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
if (m_msaaCoverageSamples) if (m_msaaCoverageSamples)
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
else else
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight); glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// Bind target renderbuffers to EFB framebuffer. // Bind target renderbuffers to EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
// Create resolved targets for transferring multisampled EFB to texture. // Create resolved targets for transferring multisampled EFB to texture.
glGenFramebuffersEXT(1, &m_resolvedFramebuffer); glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
glGenTextures(2, glObj); glGenTextures(2, glObj);
m_resolvedColorTexture = glObj[0]; m_resolvedColorTexture = glObj[0];
m_resolvedDepthTexture = glObj[1]; m_resolvedDepthTexture = glObj[1];
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Bind resolved textures to resolved framebuffer. // Bind resolved textures to resolved framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
// Return to EFB framebuffer. // Return to EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
} }
// Create XFB framebuffer; targets will be created elsewhere. // Create XFB framebuffer; targets will be created elsewhere.
glGenFramebuffersEXT(1, &m_xfbFramebuffer); glGenFramebuffersEXT(1, &m_xfbFramebuffer);
// EFB framebuffer is currently bound. // EFB framebuffer is currently bound.
} }
void FramebufferManager::Shutdown() void FramebufferManager::Shutdown()
{ {
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GLuint glObj[3]; GLuint glObj[3];
// Note: OpenGL deletion functions silently ignore parameters of "0". // Note: OpenGL deletion functions silently ignore parameters of "0".
glObj[0] = m_efbFramebuffer; glObj[0] = m_efbFramebuffer;
glObj[1] = m_resolvedFramebuffer; glObj[1] = m_resolvedFramebuffer;
glObj[2] = m_xfbFramebuffer; glObj[2] = m_xfbFramebuffer;
glDeleteFramebuffersEXT(3, glObj); glDeleteFramebuffersEXT(3, glObj);
m_efbFramebuffer = 0; m_efbFramebuffer = 0;
m_xfbFramebuffer = 0; m_xfbFramebuffer = 0;
glObj[0] = m_resolvedColorTexture; glObj[0] = m_resolvedColorTexture;
glObj[1] = m_resolvedDepthTexture; glObj[1] = m_resolvedDepthTexture;
glObj[2] = m_realXFBSource.texture; glObj[2] = m_realXFBSource.texture;
glDeleteTextures(3, glObj); glDeleteTextures(3, glObj);
m_resolvedColorTexture = 0; m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0; m_resolvedDepthTexture = 0;
m_realXFBSource.texture = 0; m_realXFBSource.texture = 0;
glObj[0] = m_efbColor; glObj[0] = m_efbColor;
glObj[1] = m_efbDepth; glObj[1] = m_efbDepth;
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
glDeleteTextures(2, glObj); glDeleteTextures(2, glObj);
else else
glDeleteRenderbuffersEXT(2, glObj); glDeleteRenderbuffersEXT(2, glObj);
m_efbColor = 0; m_efbColor = 0;
m_efbDepth = 0; m_efbDepth = 0;
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it) for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
{ {
glDeleteTextures(1, &it->xfbSource.texture); glDeleteTextures(1, &it->xfbSource.texture);
} }
m_virtualXFBList.clear(); m_virtualXFBList.clear();
} }
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc) void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{ {
if (g_Config.bUseXFB) if (g_Config.bUseXFB)
copyToRealXFB(xfbAddr, dstWidth, dstHeight, sourceRc); copyToRealXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
else else
copyToVirtualXFB(xfbAddr, dstWidth, dstHeight, sourceRc); copyToVirtualXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
} }
const XFBSource* FramebufferManager::GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight) const XFBSource* FramebufferManager::GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{ {
if (g_Config.bUseXFB) if (g_Config.bUseXFB)
return getRealXFBSource(xfbAddr, srcWidth, srcHeight); return getRealXFBSource(xfbAddr, srcWidth, srcHeight);
else else
return getVirtualXFBSource(xfbAddr, srcWidth, srcHeight); return getVirtualXFBSource(xfbAddr, srcWidth, srcHeight);
} }
GLuint FramebufferManager::GetEFBColorTexture(const TRectangle& sourceRc) const GLuint FramebufferManager::GetEFBColorTexture(const TRectangle& sourceRc) const
{ {
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
{ {
return m_efbColor; return m_efbColor;
} }
else else
{ {
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is // Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
// required. // required.
// Flip source rectangle upside-down for OpenGL. // Flip source rectangle upside-down for OpenGL.
TRectangle glRect; TRectangle glRect;
sourceRc.FlipYPosition(m_targetHeight, &glRect); sourceRc.FlipYPosition(m_targetHeight, &glRect);
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight); glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
// Resolve. // Resolve.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glBlitFramebufferEXT( glBlitFramebufferEXT(
glRect.left, glRect.top, glRect.right, glRect.bottom, glRect.left, glRect.top, glRect.right, glRect.bottom,
glRect.left, glRect.top, glRect.right, glRect.bottom, glRect.left, glRect.top, glRect.right, glRect.bottom,
GL_COLOR_BUFFER_BIT, GL_NEAREST GL_COLOR_BUFFER_BIT, GL_NEAREST
); );
// Return to EFB. // Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
return m_resolvedColorTexture; return m_resolvedColorTexture;
} }
} }
GLuint FramebufferManager::GetEFBDepthTexture(const TRectangle& sourceRc) const GLuint FramebufferManager::GetEFBDepthTexture(const TRectangle& sourceRc) const
{ {
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
{ {
return m_efbDepth; return m_efbDepth;
} }
else else
{ {
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is // Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
// required. // required.
// Flip source rectangle upside-down for OpenGL. // Flip source rectangle upside-down for OpenGL.
TRectangle glRect; TRectangle glRect;
sourceRc.FlipYPosition(m_targetHeight, &glRect); sourceRc.FlipYPosition(m_targetHeight, &glRect);
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight); glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
// Resolve. // Resolve.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glBlitFramebufferEXT( glBlitFramebufferEXT(
glRect.left, glRect.top, glRect.right, glRect.bottom, glRect.left, glRect.top, glRect.right, glRect.bottom,
glRect.left, glRect.top, glRect.right, glRect.bottom, glRect.left, glRect.top, glRect.right, glRect.bottom,
GL_DEPTH_BUFFER_BIT, GL_NEAREST GL_DEPTH_BUFFER_BIT, GL_NEAREST
); );
// Return to EFB. // Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
return m_resolvedDepthTexture; return m_resolvedDepthTexture;
} }
} }
FramebufferManager::VirtualXFBListType::iterator FramebufferManager::VirtualXFBListType::iterator
FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height) FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
{ {
u32 srcLower = xfbAddr; u32 srcLower = xfbAddr;
u32 srcUpper = xfbAddr + 2 * width * height; u32 srcUpper = xfbAddr + 2 * width * height;
VirtualXFBListType::iterator it; VirtualXFBListType::iterator it;
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it) for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
{ {
u32 dstLower = it->xfbAddr; u32 dstLower = it->xfbAddr;
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight; u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper)) if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
return it; return it;
} }
// That address is not in the Virtual XFB list. // That address is not in the Virtual XFB list.
return m_virtualXFBList.end(); return m_virtualXFBList.end();
} }
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc) void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{ {
u8* pXFB = Memory_GetPtr(xfbAddr); u8* pXFB = Memory_GetPtr(xfbAddr);
if (!pXFB) if (!pXFB)
{ {
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address"); WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
return; return;
} }
XFB_Write(pXFB, sourceRc, dstWidth, dstHeight); XFB_Write(pXFB, sourceRc, dstWidth, dstHeight);
} }
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc) void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{ {
GLuint xfbTexture; GLuint xfbTexture;
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, dstWidth, dstHeight); VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, dstWidth, dstHeight);
if (it != m_virtualXFBList.end()) if (it != m_virtualXFBList.end())
{ {
// Overwrite an existing Virtual XFB. // Overwrite an existing Virtual XFB.
it->xfbAddr = xfbAddr; it->xfbAddr = xfbAddr;
it->xfbWidth = dstWidth; it->xfbWidth = dstWidth;
it->xfbHeight = dstHeight; it->xfbHeight = dstHeight;
it->xfbSource.texWidth = m_targetWidth; it->xfbSource.texWidth = m_targetWidth;
it->xfbSource.texHeight = m_targetHeight; it->xfbSource.texHeight = m_targetHeight;
it->xfbSource.sourceRc = sourceRc; it->xfbSource.sourceRc = sourceRc;
xfbTexture = it->xfbSource.texture; xfbTexture = it->xfbSource.texture;
// Move this Virtual XFB to the front of the list. // Move this Virtual XFB to the front of the list.
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it); m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
} }
else else
{ {
// Create a new Virtual XFB and place it at the front of the list. // Create a new Virtual XFB and place it at the front of the list.
glGenTextures(1, &xfbTexture); glGenTextures(1, &xfbTexture);
#if 0 // XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible. #if 0 // XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
if (m_msaaSamples > 1) if (m_msaaSamples > 1)
#else #else
if (s_bHaveFramebufferBlit) if (s_bHaveFramebufferBlit)
#endif #endif
{ {
// In MSAA mode, allocate the texture image here. In non-MSAA mode, // In MSAA mode, allocate the texture image here. In non-MSAA mode,
// the image will be allocated by glCopyTexImage2D (later). // the image will be allocated by glCopyTexImage2D (later).
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, m_targetWidth, m_targetHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, m_targetWidth, m_targetHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
} }
VirtualXFB newVirt; VirtualXFB newVirt;
newVirt.xfbAddr = xfbAddr; newVirt.xfbAddr = xfbAddr;
newVirt.xfbWidth = dstWidth; newVirt.xfbWidth = dstWidth;
newVirt.xfbHeight = dstHeight; newVirt.xfbHeight = dstHeight;
newVirt.xfbSource.texture = xfbTexture; newVirt.xfbSource.texture = xfbTexture;
newVirt.xfbSource.texWidth = m_targetWidth; newVirt.xfbSource.texWidth = m_targetWidth;
newVirt.xfbSource.texHeight = m_targetHeight; newVirt.xfbSource.texHeight = m_targetHeight;
newVirt.xfbSource.sourceRc = sourceRc; newVirt.xfbSource.sourceRc = sourceRc;
// Add the new Virtual XFB to the list // Add the new Virtual XFB to the list
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB) if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
{ {
// List overflowed; delete the oldest. // List overflowed; delete the oldest.
glDeleteTextures(1, &m_virtualXFBList.back().xfbSource.texture); glDeleteTextures(1, &m_virtualXFBList.back().xfbSource.texture);
m_virtualXFBList.pop_back(); m_virtualXFBList.pop_back();
} }
m_virtualXFBList.push_front(newVirt); m_virtualXFBList.push_front(newVirt);
} }
// Copy EFB to XFB texture // Copy EFB to XFB texture
#if 0 #if 0
if (m_msaaSamples <= 1) if (m_msaaSamples <= 1)
#else #else
if (!s_bHaveFramebufferBlit) if (!s_bHaveFramebufferBlit)
#endif #endif
{ {
// Just copy the EFB directly. // Just copy the EFB directly.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, m_targetWidth, m_targetHeight, 0); glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, m_targetWidth, m_targetHeight, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
} }
else else
{ {
// OpenGL cannot copy directly from a multisampled framebuffer, so use // OpenGL cannot copy directly from a multisampled framebuffer, so use
// EXT_framebuffer_blit. // EXT_framebuffer_blit.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_xfbFramebuffer); glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_xfbFramebuffer);
// Bind texture. // Bind texture.
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbTexture, 0); glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbTexture, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
glBlitFramebufferEXT( glBlitFramebufferEXT(
0, 0, m_targetWidth, m_targetHeight, 0, 0, m_targetWidth, m_targetHeight,
0, 0, m_targetWidth, m_targetHeight, 0, 0, m_targetWidth, m_targetHeight,
GL_COLOR_BUFFER_BIT, GL_NEAREST GL_COLOR_BUFFER_BIT, GL_NEAREST
); );
// Unbind texture. // Unbind texture.
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
// Return to EFB. // Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
} }
} }
const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight) const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{ {
m_realXFBSource.texWidth = XFB_WIDTH; m_realXFBSource.texWidth = XFB_WIDTH;
m_realXFBSource.texHeight = XFB_HEIGHT; m_realXFBSource.texHeight = XFB_HEIGHT;
m_realXFBSource.sourceRc.left = 0; m_realXFBSource.sourceRc.left = 0;
m_realXFBSource.sourceRc.top = 0; m_realXFBSource.sourceRc.top = 0;
m_realXFBSource.sourceRc.right = srcWidth; m_realXFBSource.sourceRc.right = srcWidth;
m_realXFBSource.sourceRc.bottom = srcHeight; m_realXFBSource.sourceRc.bottom = srcHeight;
if (!m_realXFBSource.texture) if (!m_realXFBSource.texture)
{ {
glGenTextures(1, &m_realXFBSource.texture); glGenTextures(1, &m_realXFBSource.texture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, XFB_WIDTH, XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, XFB_WIDTH, XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
} }
// Decode YUYV data from GameCube RAM // Decode YUYV data from GameCube RAM
TextureConverter::DecodeToTexture(xfbAddr, srcWidth, srcHeight, m_realXFBSource.texture); TextureConverter::DecodeToTexture(xfbAddr, srcWidth, srcHeight, m_realXFBSource.texture);
return &m_realXFBSource; return &m_realXFBSource;
} }
const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight) const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{ {
if (m_virtualXFBList.size() == 0) if (m_virtualXFBList.size() == 0)
{ {
// No Virtual XFBs available. // No Virtual XFBs available.
return NULL; return NULL;
} }
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, srcWidth, srcHeight); VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, srcWidth, srcHeight);
if (it == m_virtualXFBList.end()) if (it == m_virtualXFBList.end())
{ {
// Virtual XFB is not in the list, so return the most recently rendered // Virtual XFB is not in the list, so return the most recently rendered
// one. // one.
it = m_virtualXFBList.begin(); it = m_virtualXFBList.begin();
} }
return &it->xfbSource; return &it->xfbSource;
} }

View File

@ -1,152 +1,152 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _FRAMEBUFFERMANAGER_H_ #ifndef _FRAMEBUFFERMANAGER_H_
#define _FRAMEBUFFERMANAGER_H_ #define _FRAMEBUFFERMANAGER_H_
#include <list> #include <list>
#include "GLUtil.h" #include "GLUtil.h"
// On the GameCube, the game sends a request for the graphics processor to // On the GameCube, the game sends a request for the graphics processor to
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM // transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
// called the XFB (External Framebuffer). The size and location of the XFB is // called the XFB (External Framebuffer). The size and location of the XFB is
// decided at the time of the copy, and the format is always YUYV. The video // decided at the time of the copy, and the format is always YUYV. The video
// interface is given a pointer to the XFB, which will be decoded and // interface is given a pointer to the XFB, which will be decoded and
// displayed on the TV. // displayed on the TV.
// //
// There are two ways for Dolphin to emulate this: // There are two ways for Dolphin to emulate this:
// //
// Real XFB mode: // Real XFB mode:
// //
// Dolphin will behave like the GameCube and encode the EFB to // Dolphin will behave like the GameCube and encode the EFB to
// a portion of GameCube RAM. The emulated video interface will decode the data // a portion of GameCube RAM. The emulated video interface will decode the data
// for output to the screen. // for output to the screen.
// //
// Advantages: Behaves exactly like the GameCube. // Advantages: Behaves exactly like the GameCube.
// Disadvantages: Resolution will be limited. // Disadvantages: Resolution will be limited.
// //
// Virtual XFB mode: // Virtual XFB mode:
// //
// When a request is made to copy the EFB to an XFB, Dolphin // When a request is made to copy the EFB to an XFB, Dolphin
// will remember the RAM location and size of the XFB in a Virtual XFB list. // will remember the RAM location and size of the XFB in a Virtual XFB list.
// The video interface will look up the XFB in the list and use the enhanced // The video interface will look up the XFB in the list and use the enhanced
// data stored there, if available. // data stored there, if available.
// //
// Advantages: Enables high resolution graphics, better than real hardware. // Advantages: Enables high resolution graphics, better than real hardware.
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is // Disadvantages: If the GameCube CPU writes directly to the XFB (which is
// possible but uncommon), the Virtual XFB will not capture this information. // possible but uncommon), the Virtual XFB will not capture this information.
// There may be multiple XFBs in GameCube RAM. This is the maximum number to // There may be multiple XFBs in GameCube RAM. This is the maximum number to
// virtualize. // virtualize.
const int MAX_VIRTUAL_XFB = 4; const int MAX_VIRTUAL_XFB = 4;
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper) inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{ {
return ( return (
(aLower >= bLower && aLower < bUpper) || (aLower >= bLower && aLower < bUpper) ||
(aUpper >= bLower && aUpper < bUpper) || (aUpper >= bLower && aUpper < bUpper) ||
(bLower >= aLower && bLower < aUpper) || (bLower >= aLower && bLower < aUpper) ||
(bUpper >= aLower && bUpper < aUpper) (bUpper >= aLower && bUpper < aUpper)
); );
} }
struct XFBSource struct XFBSource
{ {
XFBSource() : XFBSource() :
texture(0) texture(0)
{} {}
GLuint texture; GLuint texture;
int texWidth; int texWidth;
int texHeight; int texHeight;
TRectangle sourceRc; TRectangle sourceRc;
}; };
class FramebufferManager class FramebufferManager
{ {
public: public:
FramebufferManager() : FramebufferManager() :
m_efbFramebuffer(0), m_efbFramebuffer(0),
m_efbColor(0), m_efbColor(0),
m_efbDepth(0), m_efbDepth(0),
m_resolvedFramebuffer(0), m_resolvedFramebuffer(0),
m_resolvedColorTexture(0), m_resolvedColorTexture(0),
m_resolvedDepthTexture(0), m_resolvedDepthTexture(0),
m_xfbFramebuffer(0) m_xfbFramebuffer(0)
{} {}
void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples); void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
void Shutdown(); void Shutdown();
// sourceRc is in GL target coordinates, not GameCube EFB coordinates! // sourceRc is in GL target coordinates, not GameCube EFB coordinates!
// TODO: Clean that up. // TODO: Clean that up.
void CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc); void CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
const XFBSource* GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight); const XFBSource* GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
// To get the EFB in texture form, these functions may have to transfer // To get the EFB in texture form, these functions may have to transfer
// the EFB to a resolved texture first. // the EFB to a resolved texture first.
GLuint GetEFBColorTexture(const TRectangle& sourceRc) const; GLuint GetEFBColorTexture(const TRectangle& sourceRc) const;
GLuint GetEFBDepthTexture(const TRectangle& sourceRc) const; GLuint GetEFBDepthTexture(const TRectangle& sourceRc) const;
GLuint GetEFBFramebuffer() const { return m_efbFramebuffer; } GLuint GetEFBFramebuffer() const { return m_efbFramebuffer; }
private: private:
struct VirtualXFB struct VirtualXFB
{ {
// Address and size in GameCube RAM // Address and size in GameCube RAM
u32 xfbAddr; u32 xfbAddr;
u32 xfbWidth; u32 xfbWidth;
u32 xfbHeight; u32 xfbHeight;
XFBSource xfbSource; XFBSource xfbSource;
}; };
typedef std::list<VirtualXFB> VirtualXFBListType; typedef std::list<VirtualXFB> VirtualXFBListType;
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height); VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
void copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc); void copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
void copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc); void copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
const XFBSource* getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight); const XFBSource* getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
const XFBSource* getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight); const XFBSource* getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
int m_targetWidth; int m_targetWidth;
int m_targetHeight; int m_targetHeight;
int m_msaaSamples; int m_msaaSamples;
int m_msaaCoverageSamples; int m_msaaCoverageSamples;
GLuint m_efbFramebuffer; GLuint m_efbFramebuffer;
GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
// Only used in MSAA mode. // Only used in MSAA mode.
GLuint m_resolvedFramebuffer; GLuint m_resolvedFramebuffer;
GLuint m_resolvedColorTexture; GLuint m_resolvedColorTexture;
GLuint m_resolvedDepthTexture; GLuint m_resolvedDepthTexture;
GLuint m_xfbFramebuffer; // Only used in MSAA mode GLuint m_xfbFramebuffer; // Only used in MSAA mode
XFBSource m_realXFBSource; // Only used in Real XFB mode XFBSource m_realXFBSource; // Only used in Real XFB mode
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
}; };
#endif #endif

View File

@ -1,89 +1,89 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "VideoCommon.h" #include "VideoCommon.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "Config.h" #include "Config.h"
#include "GLUtil.h" #include "GLUtil.h"
#include "PostProcessing.h" #include "PostProcessing.h"
#include "PixelShaderCache.h" #include "PixelShaderCache.h"
namespace PostProcessing namespace PostProcessing
{ {
static std::string s_currentShader; static std::string s_currentShader;
static FRAGMENTSHADER s_shader; static FRAGMENTSHADER s_shader;
void Init() void Init()
{ {
s_currentShader = ""; s_currentShader = "";
} }
void Shutdown() void Shutdown()
{ {
s_shader.Destroy(); s_shader.Destroy();
} }
void ReloadShader() void ReloadShader()
{ {
s_currentShader = ""; s_currentShader = "";
} }
bool ApplyShader() bool ApplyShader()
{ {
if (s_currentShader != "User/Shaders/" + g_Config.sPostProcessingShader + ".txt") if (s_currentShader != "User/Shaders/" + g_Config.sPostProcessingShader + ".txt")
{ {
// Set immediately to prevent endless recompiles on failure. // Set immediately to prevent endless recompiles on failure.
if (!g_Config.sPostProcessingShader.empty()) if (!g_Config.sPostProcessingShader.empty())
s_currentShader = "User/Shaders/" + g_Config.sPostProcessingShader + ".txt"; s_currentShader = "User/Shaders/" + g_Config.sPostProcessingShader + ".txt";
else else
s_currentShader.clear(); s_currentShader.clear();
s_shader.Destroy(); s_shader.Destroy();
if (!s_currentShader.empty()) if (!s_currentShader.empty())
{ {
std::string code; std::string code;
if (File::ReadFileToString(true, s_currentShader.c_str(), code)) if (File::ReadFileToString(true, s_currentShader.c_str(), code))
{ {
if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str())) if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
{ {
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str()); ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
} }
} }
else else
{ {
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str()); ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
} }
} }
} }
if (s_shader.glprogid != 0) if (s_shader.glprogid != 0)
{ {
glEnable(GL_FRAGMENT_PROGRAM_ARB); glEnable(GL_FRAGMENT_PROGRAM_ARB);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_shader.glprogid); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_shader.glprogid);
return true; return true;
} }
else else
{ {
glDisable(GL_FRAGMENT_PROGRAM_ARB); glDisable(GL_FRAGMENT_PROGRAM_ARB);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
return false; return false;
} }
} }
} // namespace } // namespace

View File

@ -1,36 +1,36 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#ifndef _POSTPROCESSING_H_ #ifndef _POSTPROCESSING_H_
#define _POSTPROCESSING_H_ #define _POSTPROCESSING_H_
#include "VideoCommon.h" #include "VideoCommon.h"
#include "GLUtil.h" #include "GLUtil.h"
namespace PostProcessing namespace PostProcessing
{ {
void Init(); void Init();
void Shutdown(); void Shutdown();
void ReloadShader(); void ReloadShader();
// Returns false if no shader was applied. // Returns false if no shader was applied.
bool ApplyShader(); bool ApplyShader();
} // namespace } // namespace
#endif // _POSTPROCESSING_H_ #endif // _POSTPROCESSING_H_

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,108 +1,108 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
#include <ogcsys.h> #include <ogcsys.h>
#include <gccore.h> #include <gccore.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>
#include <math.h> #include <math.h>
#include <wiiuse/wpad.h> #include <wiiuse/wpad.h>
// Pull in the assembly functions. // Pull in the assembly functions.
extern "C" { extern "C" {
void TestFRES1(u32 *fpscr, float *result, float *result2); void TestFRES1(u32 *fpscr, float *result, float *result2);
}; };
int doreload=0, dooff=0; int doreload=0, dooff=0;
void reload() { doreload=1; } void reload() { doreload=1; }
void shutdown() { dooff=1; } void shutdown() { dooff=1; }
void Compare(const char *a, const char *b) { void Compare(const char *a, const char *b) {
if (!strcmp(a, b)) { if (!strcmp(a, b)) {
printf("SUCCESS - %s\n", a); printf("SUCCESS - %s\n", a);
} else { } else {
printf("FAIL - %s != \n" printf("FAIL - %s != \n"
" %s\n", a, b); " %s\n", a, b);
} }
} }
void TestDivision() { void TestDivision() {
double a, b, c, d, e; double a, b, c, d, e;
a = 1.0; a = 1.0;
b = 0.0; b = 0.0;
c = a / b; c = a / b;
d = b / a; d = b / a;
e = sqrt(-1); e = sqrt(-1);
char temp[100]; char temp[100];
sprintf(temp, "%1.1f %1.1f %1.1f %1.1f %1.1f", a, b, c, d, e); sprintf(temp, "%1.1f %1.1f %1.1f %1.1f %1.1f", a, b, c, d, e);
Compare(temp, "1.0 0.0 inf 0.0 nan"); Compare(temp, "1.0 0.0 inf 0.0 nan");
} }
void TestFres() { void TestFres() {
u32 fpscr[2]; u32 fpscr[2];
float out, out2; float out, out2;
TestFRES1(fpscr, &out, &out2); TestFRES1(fpscr, &out, &out2);
char temp[100]; char temp[100];
sprintf(temp, "%08x %1.1f %1.1f", fpscr[1], out, out2); sprintf(temp, "%08x %1.1f %1.1f", fpscr[1], out, out2);
Compare(temp, "86002004 inf 0.0"); Compare(temp, "86002004 inf 0.0");
} }
void TestNormalize() { void TestNormalize() {
//float a[3] = {2,2,2}; //float a[3] = {2,2,2};
//d_guVecNormalize(a); //d_guVecNormalize(a);
//printf("%f %f %f\n", a[0], a[1], a[2]); //printf("%f %f %f\n", a[0], a[1], a[2]);
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
void *xfb[2]; void *xfb[2];
int fbi = 0; int fbi = 0;
GXRModeObj *rmode = NULL; GXRModeObj *rmode = NULL;
VIDEO_Init(); VIDEO_Init();
PAD_Init(); PAD_Init();
WPAD_Init(); WPAD_Init();
rmode = VIDEO_GetPreferredMode(NULL); rmode = VIDEO_GetPreferredMode(NULL);
// double buffering, prevents flickering (is it needed for LCD TV? i don't have one to test) // double buffering, prevents flickering (is it needed for LCD TV? i don't have one to test)
xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
VIDEO_Configure(rmode); VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb[0]); VIDEO_SetNextFramebuffer(xfb[0]);
VIDEO_SetBlack(FALSE); VIDEO_SetBlack(FALSE);
VIDEO_Flush(); VIDEO_Flush();
VIDEO_WaitVSync(); VIDEO_WaitVSync();
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync(); if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
SYS_SetResetCallback(reload); SYS_SetResetCallback(reload);
SYS_SetPowerCallback(shutdown); SYS_SetPowerCallback(shutdown);
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR); WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight); WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
printf(" "); printf(" ");
printf("Tests\n\n"); printf("Tests\n\n");
TestDivision(); TestDivision();
TestFres(); TestFres();
while (!doreload && !dooff) { while (!doreload && !dooff) {
WPAD_ScanPads(); WPAD_ScanPads();
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
exit(0); exit(0);
VIDEO_SetNextFramebuffer(xfb[fbi]); VIDEO_SetNextFramebuffer(xfb[fbi]);
VIDEO_Flush(); VIDEO_Flush();
VIDEO_WaitVSync(); VIDEO_WaitVSync();
} }
if(doreload) return 0; if(doreload) return 0;
if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0); if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0);
return 0; return 0;
} }

View File

@ -61,37 +61,37 @@ int main()
} }
} }
void Initialise() void Initialise()
{ {
// Initialise the video system // Initialise the video system
VIDEO_Init(); VIDEO_Init();
// This function initialises the attached controllers // This function initialises the attached controllers
PAD_Init(); PAD_Init();
// Obtain the preferred video mode from the system // Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu // This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL); rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region // Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf // Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode // Set up the video registers with the chosen mode
VIDEO_Configure(rmode); VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is // Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb); VIDEO_SetNextFramebuffer(xfb);
// Make the display visible // Make the display visible
VIDEO_SetBlack(FALSE); VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware // Flush the video register changes to the hardware
VIDEO_Flush(); VIDEO_Flush();
// Wait for Video setup to complete // Wait for Video setup to complete
VIDEO_WaitVSync(); VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
} }

View File

@ -1,72 +1,72 @@
#include <gccore.h> #include <gccore.h>
#include <malloc.h> #include <malloc.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ogcsys.h> #include <ogcsys.h>
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
#include <iostream> #include <iostream>
#include <debug.h> #include <debug.h>
#include <math.h> #include <math.h>
static void *xfb = NULL; static void *xfb = NULL;
u32 first_frame = 1; u32 first_frame = 1;
GXRModeObj *rmode; GXRModeObj *rmode;
void Initialise(); void Initialise();
int main() int main()
{ {
Initialise(); Initialise();
time_t gc_time; time_t gc_time;
gc_time = time(NULL); gc_time = time(NULL);
srand(gc_time); srand(gc_time);
while(1) while(1)
{ {
gc_time = time(NULL); gc_time = time(NULL);
std::cout<<"\x1b[10;0HGC RTC time is"<<ctime(&gc_time); std::cout<<"\x1b[10;0HGC RTC time is"<<ctime(&gc_time);
VIDEO_WaitVSync(); VIDEO_WaitVSync();
} }
} }
void Initialise() void Initialise()
{ {
// Initialise the video system // Initialise the video system
VIDEO_Init(); VIDEO_Init();
// This function initialises the attached controllers // This function initialises the attached controllers
PAD_Init(); PAD_Init();
// Obtain the preferred video mode from the system // Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu // This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL); rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region // Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf // Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode // Set up the video registers with the chosen mode
VIDEO_Configure(rmode); VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is // Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb); VIDEO_SetNextFramebuffer(xfb);
// Make the display visible // Make the display visible
VIDEO_SetBlack(FALSE); VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware // Flush the video register changes to the hardware
VIDEO_Flush(); VIDEO_Flush();
// Wait for Video setup to complete // Wait for Video setup to complete
VIDEO_WaitVSync(); VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
} }

View File

@ -1,72 +1,72 @@
#include <gccore.h> #include <gccore.h>
#include <malloc.h> #include <malloc.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ogcsys.h> #include <ogcsys.h>
#include <time.h> #include <time.h>
#include <sys/time.h> #include <sys/time.h>
#include <iostream> #include <iostream>
#include <debug.h> #include <debug.h>
#include <math.h> #include <math.h>
static void *xfb = NULL; static void *xfb = NULL;
u32 first_frame = 1; u32 first_frame = 1;
GXRModeObj *rmode; GXRModeObj *rmode;
void Initialise(); void Initialise();
int main() int main()
{ {
Initialise(); Initialise();
time_t wii_time; time_t wii_time;
wii_time = time(NULL); wii_time = time(NULL);
srand(wii_time); srand(wii_time);
while(1) while(1)
{ {
wii_time = time(NULL); wii_time = time(NULL);
std::cout<<"\x1b[10;0HWii RTC time is"<<ctime(&wii_time); std::cout<<"\x1b[10;0HWii RTC time is"<<ctime(&wii_time);
VIDEO_WaitVSync(); VIDEO_WaitVSync();
} }
} }
void Initialise() void Initialise()
{ {
// Initialise the video system // Initialise the video system
VIDEO_Init(); VIDEO_Init();
// This function initialises the attached controllers // This function initialises the attached controllers
PAD_Init(); PAD_Init();
// Obtain the preferred video mode from the system // Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu // This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL); rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region // Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf // Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode // Set up the video registers with the chosen mode
VIDEO_Configure(rmode); VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is // Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb); VIDEO_SetNextFramebuffer(xfb);
// Make the display visible // Make the display visible
VIDEO_SetBlack(FALSE); VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware // Flush the video register changes to the hardware
VIDEO_Flush(); VIDEO_Flush();
// Wait for Video setup to complete // Wait for Video setup to complete
VIDEO_WaitVSync(); VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
} }

View File

@ -1,142 +1,142 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // 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 // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
#include "StringUtil.h" #include "StringUtil.h"
#include "MathUtil.h" #include "MathUtil.h"
#include "PowerPC/PowerPC.h" #include "PowerPC/PowerPC.h"
#include "HW/SI_DeviceGCController.h" #include "HW/SI_DeviceGCController.h"
using namespace std; using namespace std;
int fail_count = 0; int fail_count = 0;
#define EXPECT_TRUE(a) \ #define EXPECT_TRUE(a) \
if (!a) { \ if (!a) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is false" << endl; \ cout << "FAIL (" __FUNCTION__ "): " << #a << " is false" << endl; \
cout << "Value: " << a << endl << "Expected: true" << endl; \ cout << "Value: " << a << endl << "Expected: true" << endl; \
fail_count++; \ fail_count++; \
} }
#define EXPECT_FALSE(a) \ #define EXPECT_FALSE(a) \
if (a) { \ if (a) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is true" << endl; \ cout << "FAIL (" __FUNCTION__ "): " << #a << " is true" << endl; \
cout << "Value: " << a << endl << "Expected: false" << endl; \ cout << "Value: " << a << endl << "Expected: false" << endl; \
fail_count++; \ fail_count++; \
} }
#define EXPECT_EQ(a, b) \ #define EXPECT_EQ(a, b) \
if ((a) != (b)) { \ if ((a) != (b)) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is not equal to " << #b << endl; \ cout << "FAIL (" __FUNCTION__ "): " << #a << " is not equal to " << #b << endl; \
cout << "Actual: " << a << endl << "Expected: " << b << endl; \ cout << "Actual: " << a << endl << "Expected: " << b << endl; \
fail_count++; \ fail_count++; \
} }
void CoreTests() void CoreTests()
{ {
} }
void MathTests() void MathTests()
{ {
// Tests that our fp classifier is correct. // Tests that our fp classifier is correct.
EXPECT_EQ(MathUtil::ClassifyDouble(1.0), MathUtil::PPC_FPCLASS_PN); EXPECT_EQ(MathUtil::ClassifyDouble(1.0), MathUtil::PPC_FPCLASS_PN);
EXPECT_EQ(MathUtil::ClassifyDouble(-1.0), MathUtil::PPC_FPCLASS_NN); EXPECT_EQ(MathUtil::ClassifyDouble(-1.0), MathUtil::PPC_FPCLASS_NN);
EXPECT_EQ(MathUtil::ClassifyDouble(1235223.0), MathUtil::PPC_FPCLASS_PN); EXPECT_EQ(MathUtil::ClassifyDouble(1235223.0), MathUtil::PPC_FPCLASS_PN);
EXPECT_EQ(MathUtil::ClassifyDouble(-1263221.0), MathUtil::PPC_FPCLASS_NN); EXPECT_EQ(MathUtil::ClassifyDouble(-1263221.0), MathUtil::PPC_FPCLASS_NN);
EXPECT_EQ(MathUtil::ClassifyDouble(1.0E-308), MathUtil::PPC_FPCLASS_PD); EXPECT_EQ(MathUtil::ClassifyDouble(1.0E-308), MathUtil::PPC_FPCLASS_PD);
EXPECT_EQ(MathUtil::ClassifyDouble(-1.0E-308), MathUtil::PPC_FPCLASS_ND); EXPECT_EQ(MathUtil::ClassifyDouble(-1.0E-308), MathUtil::PPC_FPCLASS_ND);
EXPECT_EQ(MathUtil::ClassifyDouble(0.0), MathUtil::PPC_FPCLASS_PZ); EXPECT_EQ(MathUtil::ClassifyDouble(0.0), MathUtil::PPC_FPCLASS_PZ);
EXPECT_EQ(MathUtil::ClassifyDouble(-0.0), MathUtil::PPC_FPCLASS_NZ); EXPECT_EQ(MathUtil::ClassifyDouble(-0.0), MathUtil::PPC_FPCLASS_NZ);
EXPECT_EQ(MathUtil::ClassifyDouble(HUGE_VAL), MathUtil::PPC_FPCLASS_PINF); // weird #define for infinity EXPECT_EQ(MathUtil::ClassifyDouble(HUGE_VAL), MathUtil::PPC_FPCLASS_PINF); // weird #define for infinity
EXPECT_EQ(MathUtil::ClassifyDouble(-HUGE_VAL), MathUtil::PPC_FPCLASS_NINF); EXPECT_EQ(MathUtil::ClassifyDouble(-HUGE_VAL), MathUtil::PPC_FPCLASS_NINF);
EXPECT_EQ(MathUtil::ClassifyDouble(sqrt(-1.0)), MathUtil::PPC_FPCLASS_QNAN); EXPECT_EQ(MathUtil::ClassifyDouble(sqrt(-1.0)), MathUtil::PPC_FPCLASS_QNAN);
// Float version // Float version
EXPECT_EQ(MathUtil::ClassifyFloat(1.0f), MathUtil::PPC_FPCLASS_PN); EXPECT_EQ(MathUtil::ClassifyFloat(1.0f), MathUtil::PPC_FPCLASS_PN);
EXPECT_EQ(MathUtil::ClassifyFloat(-1.0f), MathUtil::PPC_FPCLASS_NN); EXPECT_EQ(MathUtil::ClassifyFloat(-1.0f), MathUtil::PPC_FPCLASS_NN);
EXPECT_EQ(MathUtil::ClassifyFloat(1235223.0f), MathUtil::PPC_FPCLASS_PN); EXPECT_EQ(MathUtil::ClassifyFloat(1235223.0f), MathUtil::PPC_FPCLASS_PN);
EXPECT_EQ(MathUtil::ClassifyFloat(-1263221.0f), MathUtil::PPC_FPCLASS_NN); EXPECT_EQ(MathUtil::ClassifyFloat(-1263221.0f), MathUtil::PPC_FPCLASS_NN);
EXPECT_EQ(MathUtil::ClassifyFloat(1.0E-43f), MathUtil::PPC_FPCLASS_PD); EXPECT_EQ(MathUtil::ClassifyFloat(1.0E-43f), MathUtil::PPC_FPCLASS_PD);
EXPECT_EQ(MathUtil::ClassifyFloat(-1.0E-43f), MathUtil::PPC_FPCLASS_ND); EXPECT_EQ(MathUtil::ClassifyFloat(-1.0E-43f), MathUtil::PPC_FPCLASS_ND);
EXPECT_EQ(MathUtil::ClassifyFloat(0.0f), MathUtil::PPC_FPCLASS_PZ); EXPECT_EQ(MathUtil::ClassifyFloat(0.0f), MathUtil::PPC_FPCLASS_PZ);
EXPECT_EQ(MathUtil::ClassifyFloat(-0.0f), MathUtil::PPC_FPCLASS_NZ); EXPECT_EQ(MathUtil::ClassifyFloat(-0.0f), MathUtil::PPC_FPCLASS_NZ);
EXPECT_EQ(MathUtil::ClassifyFloat((float)HUGE_VAL), MathUtil::PPC_FPCLASS_PINF); // weird #define for infinity EXPECT_EQ(MathUtil::ClassifyFloat((float)HUGE_VAL), MathUtil::PPC_FPCLASS_PINF); // weird #define for infinity
EXPECT_EQ(MathUtil::ClassifyFloat((float)-HUGE_VAL), MathUtil::PPC_FPCLASS_NINF); EXPECT_EQ(MathUtil::ClassifyFloat((float)-HUGE_VAL), MathUtil::PPC_FPCLASS_NINF);
EXPECT_EQ(MathUtil::ClassifyFloat(sqrtf(-1.0f)), MathUtil::PPC_FPCLASS_QNAN); EXPECT_EQ(MathUtil::ClassifyFloat(sqrtf(-1.0f)), MathUtil::PPC_FPCLASS_QNAN);
EXPECT_FALSE(MathUtil::IsNAN(1.0)); EXPECT_FALSE(MathUtil::IsNAN(1.0));
EXPECT_TRUE(MathUtil::IsNAN(sqrt(-1.0))); EXPECT_TRUE(MathUtil::IsNAN(sqrt(-1.0)));
EXPECT_FALSE(MathUtil::IsSNAN(sqrt(-1.0))); EXPECT_FALSE(MathUtil::IsSNAN(sqrt(-1.0)));
// EXPECT_TRUE(MathUtil::IsQNAN(sqrt(-1.0))); // Hmm... // EXPECT_TRUE(MathUtil::IsQNAN(sqrt(-1.0))); // Hmm...
EXPECT_EQ(pow2(2.0), 4.0); EXPECT_EQ(pow2(2.0), 4.0);
EXPECT_EQ(pow2(-2.0), 4.0); EXPECT_EQ(pow2(-2.0), 4.0);
} }
void StringTests() void StringTests()
{ {
EXPECT_EQ(StripSpaces(" abc "), "abc"); EXPECT_EQ(StripSpaces(" abc "), "abc");
EXPECT_EQ(StripNewline(" abc \n"), " abc "); EXPECT_EQ(StripNewline(" abc \n"), " abc ");
EXPECT_EQ(StripNewline(" abc \n "), " abc \n "); EXPECT_EQ(StripNewline(" abc \n "), " abc \n ");
EXPECT_EQ(StripQuotes("\"abc\""), "abc"); EXPECT_EQ(StripQuotes("\"abc\""), "abc");
EXPECT_EQ(StripQuotes("\"abc\" "), "\"abc\" "); EXPECT_EQ(StripQuotes("\"abc\" "), "\"abc\" ");
EXPECT_EQ(TabsToSpaces(4, "a\tb"), "a b"); EXPECT_EQ(TabsToSpaces(4, "a\tb"), "a b");
} }
int main(int argc, _TCHAR* argv[]) int main(int argc, _TCHAR* argv[])
{ {
CoreTests(); CoreTests();
MathTests(); MathTests();
StringTests(); StringTests();
if (fail_count == 0) if (fail_count == 0)
{ {
printf("All tests passed.\n"); printf("All tests passed.\n");
} }
return 0; return 0;
} }
// Pretend that we are a host so we can link to core.... urgh. // Pretend that we are a host so we can link to core.... urgh.
//============================================================== //==============================================================
void Host_UpdateMainFrame(){} void Host_UpdateMainFrame(){}
void Host_UpdateDisasmDialog(){} void Host_UpdateDisasmDialog(){}
void Host_UpdateLogDisplay(){} void Host_UpdateLogDisplay(){}
void Host_UpdateMemoryView(){} void Host_UpdateMemoryView(){}
void Host_NotifyMapLoaded(){} void Host_NotifyMapLoaded(){}
void Host_UpdateBreakPointView(){} void Host_UpdateBreakPointView(){}
void Host_SetDebugMode(bool enable){} void Host_SetDebugMode(bool enable){}
void Host_SetWaitCursor(bool enable){} void Host_SetWaitCursor(bool enable){}
void Host_UpdateStatusBar(const char* _pText, int Filed = 0){} void Host_UpdateStatusBar(const char* _pText, int Filed = 0){}
#ifdef SETUP_TIMER_WAITING #ifdef SETUP_TIMER_WAITING
void Host_UpdateGUI(){} void Host_UpdateGUI(){}
#endif #endif
void Host_SysMessage(const char *fmt, ...){} void Host_SysMessage(const char *fmt, ...){}
void Host_SetWiiMoteConnectionState(int _State){} void Host_SetWiiMoteConnectionState(int _State){}
void Host_UpdateLeds(int bits){} void Host_UpdateLeds(int bits){}
void Host_UpdateSpeakerStatus(int index, int bits){} void Host_UpdateSpeakerStatus(int index, int bits){}
void Host_UpdateStatus(){} void Host_UpdateStatus(){}
int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus) int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
{ {
return 0; return 0;
} }