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
+88 -88
View File
@@ -1,88 +1,88 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h"
#include "Mixer.h"
#include "DSoundStream.h"
#include "AOSoundStream.h"
#include "NullSoundStream.h"
#include "OpenALStream.h"
namespace AudioCommon
{
SoundStream *InitSoundStream(CMixer *mixer)
{
if (!mixer)
mixer = new CMixer();
std::string backend = ac_Config.sBackend;
if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd);
if (backend == BACKEND_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
if (soundStream != NULL) {
ac_Config.Update();
if (soundStream->Start()) {
// Start the sound recording
/*
if (ac_Config.record) {
soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
}
*/
return soundStream;
}
PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str());
}
PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
delete soundStream;
soundStream = new NullSound(mixer);
soundStream->Start();
return NULL;
}
void ShutdownSoundStream()
{
NOTICE_LOG(DSPHLE, "Shutting down sound stream");
if (soundStream)
{
soundStream->Stop();
soundStream->StopLogAudio();
delete soundStream;
soundStream = NULL;
}
INFO_LOG(DSPHLE, "Done shutting down sound stream");
}
std::vector<std::string> GetSoundBackends()
{
std::vector<std::string> backends;
if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
return backends;
}
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h"
#include "Mixer.h"
#include "DSoundStream.h"
#include "AOSoundStream.h"
#include "NullSoundStream.h"
#include "OpenALStream.h"
namespace AudioCommon
{
SoundStream *InitSoundStream(CMixer *mixer)
{
if (!mixer)
mixer = new CMixer();
std::string backend = ac_Config.sBackend;
if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd);
if (backend == BACKEND_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
if (soundStream != NULL) {
ac_Config.Update();
if (soundStream->Start()) {
// Start the sound recording
/*
if (ac_Config.record) {
soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
}
*/
return soundStream;
}
PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str());
}
PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
delete soundStream;
soundStream = new NullSound(mixer);
soundStream->Start();
return NULL;
}
void ShutdownSoundStream()
{
NOTICE_LOG(DSPHLE, "Shutting down sound stream");
if (soundStream)
{
soundStream->Stop();
soundStream->StopLogAudio();
delete soundStream;
soundStream = NULL;
}
INFO_LOG(DSPHLE, "Done shutting down sound stream");
}
std::vector<std::string> GetSoundBackends()
{
std::vector<std::string> backends;
if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
return backends;
}
}
+40 -40
View File
@@ -1,40 +1,40 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _AUDIO_COMMON_H_
#define _AUDIO_COMMON_H_
#include "Common.h"
#include "AudioCommonConfig.h"
#include "../../../PluginSpecs/pluginspecs_dsp.h"
#include "SoundStream.h"
class CMixer;
extern DSPInitialize g_dspInitialize;
extern SoundStream *soundStream;
extern AudioCommonConfig ac_Config;
namespace AudioCommon
{
SoundStream *InitSoundStream(CMixer *mixer = NULL);
void ShutdownSoundStream();
std::vector<std::string> GetSoundBackends();
}
#endif // _AUDIO_COMMON_H_
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _AUDIO_COMMON_H_
#define _AUDIO_COMMON_H_
#include "Common.h"
#include "AudioCommonConfig.h"
#include "../../../PluginSpecs/pluginspecs_dsp.h"
#include "SoundStream.h"
class CMixer;
extern DSPInitialize g_dspInitialize;
extern SoundStream *soundStream;
extern AudioCommonConfig ac_Config;
namespace AudioCommon
{
SoundStream *InitSoundStream(CMixer *mixer = NULL);
void ShutdownSoundStream();
std::vector<std::string> GetSoundBackends();
}
#endif // _AUDIO_COMMON_H_
@@ -1,52 +1,52 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h"
AudioCommonConfig ac_Config;
// Load from given file
void AudioCommonConfig::Load(IniFile &file) {
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
file.Get("Config", "Volume", &m_Volume, 75);
#ifdef _WIN32
file.Get("Config", "Backend", &sBackend, "DSound");
#elif defined(__APPLE__)
std::string temp;
file.Get("Config", "Backend", &temp, "AOSound");
strncpy(sBackend, temp.c_str(), 128);
#else
file.Get("Config", "Backend", &sBackend, "AOSound");
#endif
}
// Set the values for the file
void AudioCommonConfig::Set(IniFile &file) {
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
file.Set("Config", "EnableThrottle", m_EnableThrottle);
file.Set("Config", "Backend", sBackend);
file.Set("Config", "Volume", m_Volume);
}
// Update according to the values (stream/mixer)
void AudioCommonConfig::Update() {
if (soundStream) {
soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
soundStream->SetVolume(m_Volume);
}
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AudioCommon.h"
AudioCommonConfig ac_Config;
// Load from given file
void AudioCommonConfig::Load(IniFile &file) {
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
file.Get("Config", "Volume", &m_Volume, 75);
#ifdef _WIN32
file.Get("Config", "Backend", &sBackend, "DSound");
#elif defined(__APPLE__)
std::string temp;
file.Get("Config", "Backend", &temp, "AOSound");
strncpy(sBackend, temp.c_str(), 128);
#else
file.Get("Config", "Backend", &sBackend, "AOSound");
#endif
}
// Set the values for the file
void AudioCommonConfig::Set(IniFile &file) {
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
file.Set("Config", "EnableThrottle", m_EnableThrottle);
file.Set("Config", "Backend", sBackend);
file.Set("Config", "Volume", m_Volume);
}
// Update according to the values (stream/mixer)
void AudioCommonConfig::Update() {
if (soundStream) {
soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
soundStream->SetVolume(m_Volume);
}
}
+50 -50
View File
@@ -1,50 +1,50 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _AUDIO_COMMON_CONFIG_H_
#define _AUDIO_COMMON_CONFIG_H_
#include <string>
#include "IniFile.h"
// Backend Types
#define BACKEND_DIRECTSOUND "DSound"
#define BACKEND_AOSOUND "AOSound"
#define BACKEND_OPENAL "OpenAL"
#define BACKEND_NULL "NullSound"
struct AudioCommonConfig
{
bool m_EnableDTKMusic;
bool m_EnableThrottle;
int m_Volume;
#ifdef __APPLE__
char sBackend[128];
#else
std::string sBackend;
#endif
// Load from given file
void Load(IniFile &file);
// Set the values for the file
void Set(IniFile &file);
// Update according to the values (stream/mixer)
void Update();
};
#endif //AUDIO_COMMON_CONFIG
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _AUDIO_COMMON_CONFIG_H_
#define _AUDIO_COMMON_CONFIG_H_
#include <string>
#include "IniFile.h"
// Backend Types
#define BACKEND_DIRECTSOUND "DSound"
#define BACKEND_AOSOUND "AOSound"
#define BACKEND_OPENAL "OpenAL"
#define BACKEND_NULL "NullSound"
struct AudioCommonConfig
{
bool m_EnableDTKMusic;
bool m_EnableThrottle;
int m_Volume;
#ifdef __APPLE__
char sBackend[128];
#else
std::string sBackend;
#endif
// Load from given file
void Load(IniFile &file);
// Set the values for the file
void Set(IniFile &file);
// Update according to the values (stream/mixer)
void Update();
};
#endif //AUDIO_COMMON_CONFIG
+170 -170
View File
@@ -1,170 +1,170 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "aldlist.h"
#include "OpenALStream.h"
#if defined HAVE_OPENAL && HAVE_OPENAL
#define AUDIO_NUMBUFFERS (4)
//#define AUDIO_SERVICE_UPDATE_PERIOD (20)
bool OpenALStream::Start()
{
ALDeviceList *pDeviceList = NULL;
ALCcontext *pContext = NULL;
ALCdevice *pDevice = NULL;
bool bReturn = false;
pDeviceList = new ALDeviceList();
if ((pDeviceList) && (pDeviceList->GetNumDevices()))
{
pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
if (pDevice)
{
pContext = alcCreateContext(pDevice, NULL);
if (pContext)
{
alcMakeContextCurrent(pContext);
thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
bReturn = true;
}
else
{
alcCloseDevice(pDevice);
PanicAlert("OpenAL: can't create context for device %s", pDevice);
}
} else {
PanicAlert("OpenAL: can't open device %s", pDevice);
}
delete pDeviceList;
} else {
PanicAlert("OpenAL: can't find sound devices");
}
return bReturn;
}
void OpenALStream::Stop()
{
ALCcontext *pContext;
ALCdevice *pDevice;
soundCriticalSection.Enter();
threadData = 1;
// kick the thread if it's waiting
soundSyncEvent.Set();
soundCriticalSection.Leave();
delete thread;
pContext = alcGetCurrentContext();
pDevice = alcGetContextsDevice(pContext);
alcMakeContextCurrent(NULL);
alcDestroyContext(pContext);
alcCloseDevice(pDevice);
soundSyncEvent.Shutdown();
thread = NULL;
}
void OpenALStream::Update()
{
//if (m_mixer->GetDataSize()) //here need debug
{
soundSyncEvent.Set();
}
}
THREAD_RETURN OpenALStream::ThreadFunc(void* args)
{
(reinterpret_cast<OpenALStream *>(args))->SoundLoop();
return 0;
}
void OpenALStream::SoundLoop()
{
ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
ALuint uiSource = 0;
ALenum err;
u32 ulFrequency = m_mixer->GetSampleRate();
// Generate some AL Buffers for streaming
alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
// Generate a Source to playback the Buffers
alGenSources(1, &uiSource);
memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
//*
for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
{
// pay load fake data
alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
}
//*/
alSourcePlay(uiSource);
err = alGetError();
while (!threadData)
{
soundCriticalSection.Enter();
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
/*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
soundCriticalSection.Leave();
//if (numBytesRender) //here need debug
{
ALint iBuffersProcessed = 0;
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
if (iBuffersProcessed)
{
// Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
ALuint uiTempBuffer = 0;
alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
/*
soundCriticalSection.Enter();
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
soundCriticalSection.Leave();
unsigned long ulBytesWritten = 0;
*/
//if (numBytesRender)
{
alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
}
alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
}
}
if (!threadData)
soundSyncEvent.Wait();
}
alSourceStop(uiSource);
alSourcei(uiSource, AL_BUFFER, 0);
// Clean up buffers and sources
alDeleteSources(1, &uiSource);
alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
}
#endif //HAVE_OPENAL
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "aldlist.h"
#include "OpenALStream.h"
#if defined HAVE_OPENAL && HAVE_OPENAL
#define AUDIO_NUMBUFFERS (4)
//#define AUDIO_SERVICE_UPDATE_PERIOD (20)
bool OpenALStream::Start()
{
ALDeviceList *pDeviceList = NULL;
ALCcontext *pContext = NULL;
ALCdevice *pDevice = NULL;
bool bReturn = false;
pDeviceList = new ALDeviceList();
if ((pDeviceList) && (pDeviceList->GetNumDevices()))
{
pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
if (pDevice)
{
pContext = alcCreateContext(pDevice, NULL);
if (pContext)
{
alcMakeContextCurrent(pContext);
thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
bReturn = true;
}
else
{
alcCloseDevice(pDevice);
PanicAlert("OpenAL: can't create context for device %s", pDevice);
}
} else {
PanicAlert("OpenAL: can't open device %s", pDevice);
}
delete pDeviceList;
} else {
PanicAlert("OpenAL: can't find sound devices");
}
return bReturn;
}
void OpenALStream::Stop()
{
ALCcontext *pContext;
ALCdevice *pDevice;
soundCriticalSection.Enter();
threadData = 1;
// kick the thread if it's waiting
soundSyncEvent.Set();
soundCriticalSection.Leave();
delete thread;
pContext = alcGetCurrentContext();
pDevice = alcGetContextsDevice(pContext);
alcMakeContextCurrent(NULL);
alcDestroyContext(pContext);
alcCloseDevice(pDevice);
soundSyncEvent.Shutdown();
thread = NULL;
}
void OpenALStream::Update()
{
//if (m_mixer->GetDataSize()) //here need debug
{
soundSyncEvent.Set();
}
}
THREAD_RETURN OpenALStream::ThreadFunc(void* args)
{
(reinterpret_cast<OpenALStream *>(args))->SoundLoop();
return 0;
}
void OpenALStream::SoundLoop()
{
ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
ALuint uiSource = 0;
ALenum err;
u32 ulFrequency = m_mixer->GetSampleRate();
// Generate some AL Buffers for streaming
alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
// Generate a Source to playback the Buffers
alGenSources(1, &uiSource);
memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
//*
for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
{
// pay load fake data
alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
}
//*/
alSourcePlay(uiSource);
err = alGetError();
while (!threadData)
{
soundCriticalSection.Enter();
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
/*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
soundCriticalSection.Leave();
//if (numBytesRender) //here need debug
{
ALint iBuffersProcessed = 0;
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
if (iBuffersProcessed)
{
// Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
ALuint uiTempBuffer = 0;
alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
/*
soundCriticalSection.Enter();
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
soundCriticalSection.Leave();
unsigned long ulBytesWritten = 0;
*/
//if (numBytesRender)
{
alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
}
alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
}
}
if (!threadData)
soundSyncEvent.Wait();
}
alSourceStop(uiSource);
alSourcei(uiSource, AL_BUFFER, 0);
// Clean up buffers and sources
alDeleteSources(1, &uiSource);
alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
}
#endif //HAVE_OPENAL
+74 -74
View File
@@ -1,74 +1,74 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _OPENALSTREAM_H_
#define _OPENALSTREAM_H_
#include "Common.h"
#include "SoundStream.h"
#include "Thread.h"
#if defined HAVE_OPENAL && HAVE_OPENAL
#ifdef _WIN32
#include "../../../../Externals/OpenAL/include/al.h"
#include "../../../../Externals/OpenAL/include/alc.h"
#elif defined(__APPLE__)
#include "openal/al.h"
#include "openal/alc.h"
#else
#include "AL/al.h"
#include "AL/alc.h"
#endif // WIN32
// public use
#define SFX_MAX_SOURCE 1
#define OAL_BUFFER_SIZE 1024*1024
#endif
class OpenALStream: public SoundStream
{
#if defined HAVE_OPENAL && HAVE_OPENAL
public:
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
virtual ~OpenALStream() {};
virtual bool Start();
virtual void SoundLoop();
virtual void Stop();
static bool isValid() { return true; }
virtual bool usesMixer() const { return true; }
virtual void Update();
static THREAD_RETURN ThreadFunc(void* args);
private:
Common::Thread *thread;
Common::CriticalSection soundCriticalSection;
Common::Event soundSyncEvent;
short realtimeBuffer[OAL_BUFFER_SIZE];
#else
public:
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
#endif // HAVE_OPENAL
};
#endif // OPENALSTREAM
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _OPENALSTREAM_H_
#define _OPENALSTREAM_H_
#include "Common.h"
#include "SoundStream.h"
#include "Thread.h"
#if defined HAVE_OPENAL && HAVE_OPENAL
#ifdef _WIN32
#include "../../../../Externals/OpenAL/include/al.h"
#include "../../../../Externals/OpenAL/include/alc.h"
#elif defined(__APPLE__)
#include "openal/al.h"
#include "openal/alc.h"
#else
#include "AL/al.h"
#include "AL/alc.h"
#endif // WIN32
// public use
#define SFX_MAX_SOURCE 1
#define OAL_BUFFER_SIZE 1024*1024
#endif
class OpenALStream: public SoundStream
{
#if defined HAVE_OPENAL && HAVE_OPENAL
public:
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
virtual ~OpenALStream() {};
virtual bool Start();
virtual void SoundLoop();
virtual void Stop();
static bool isValid() { return true; }
virtual bool usesMixer() const { return true; }
virtual void Update();
static THREAD_RETURN ThreadFunc(void* args);
private:
Common::Thread *thread;
Common::CriticalSection soundCriticalSection;
Common::Event soundSyncEvent;
short realtimeBuffer[OAL_BUFFER_SIZE];
#else
public:
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
#endif // HAVE_OPENAL
};
#endif // OPENALSTREAM
+341 -341
View File
@@ -1,341 +1,341 @@
/*
* Copyright (c) 2006, Creative Labs Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "Common.h"
#include "aldlist.h"
#include "../../../../Externals/OpenAL/include/al.h"
#include "../../../../Externals/OpenAL/include/alc.h"
/*
* Init call
*/
ALDeviceList::ALDeviceList()
{
ALDEVICEINFO ALDeviceInfo;
char *devices;
s32 index;
const char *defaultDeviceName = NULL;
const char *actualDeviceName = NULL;
// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
vDeviceInfo.empty();
vDeviceInfo.reserve(10);
defaultDeviceIndex = 0;
// grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
//if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
{
devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
index = 0;
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
while (devices != NULL && strlen(devices) > 0)
{
if (strcmp(defaultDeviceName, devices) == 0)
{
defaultDeviceIndex = index;
}
ALCdevice *device = alcOpenDevice(devices);
if (device)
{
ALCcontext *context = alcCreateContext(device, NULL);
if (context)
{
alcMakeContextCurrent(context);
// if new actual device name isn't already in the list, then add it...
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
bool bNewName = true;
for (s32 i = 0; i < GetNumDevices(); i++)
{
if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
{
bNewName = false;
}
}
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
{
ALDeviceInfo.bSelected = true;
ALDeviceInfo.strDeviceName = actualDeviceName;
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
ALDeviceInfo.pvstrExtensions = new vector<string>;
// Check for ALC Extensions
if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
// Check for AL Extensions
if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
// Get Source Count
ALDeviceInfo.uiSourceCount = GetMaxNumSources();
vDeviceInfo.push_back(ALDeviceInfo);
}
alcMakeContextCurrent(NULL);
alcDestroyContext(context);
}
alcCloseDevice(device);
}
devices += strlen(devices) + 1;
index += 1;
}
}
//}
ResetFilters();
}
/*
* Exit call
*/
ALDeviceList::~ALDeviceList()
{
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
if (vDeviceInfo[i].pvstrExtensions) {
vDeviceInfo[i].pvstrExtensions->empty();
delete vDeviceInfo[i].pvstrExtensions;
}
}
vDeviceInfo.empty();
}
/*
* Returns the number of devices in the complete device list
*/
s32 ALDeviceList::GetNumDevices()
{
return (s32)vDeviceInfo.size();
}
/*
* Returns the device name at an index in the complete device list
*/
char * ALDeviceList::GetDeviceName(s32 index)
{
if (index < GetNumDevices())
return (char *)vDeviceInfo[index].strDeviceName.c_str();
else
return NULL;
}
/*
* Returns the major and minor version numbers for a device at a specified index in the complete list
*/
void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
{
if (index < GetNumDevices()) {
if (major)
*major = vDeviceInfo[index].iMajorVersion;
if (minor)
*minor = vDeviceInfo[index].iMinorVersion;
}
return;
}
/*
* Returns the maximum number of Sources that can be generate on the given device
*/
u32 ALDeviceList::GetMaxNumSources(s32 index)
{
if (index < GetNumDevices())
return vDeviceInfo[index].uiSourceCount;
else
return 0;
}
/*
* Checks if the extension is supported on the given device
*/
bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
{
bool bReturn = false;
if (index < GetNumDevices()) {
for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
bReturn = true;
break;
}
}
}
return bReturn;
}
/*
* returns the index of the default device in the complete device list
*/
s32 ALDeviceList::GetDefaultDevice()
{
return defaultDeviceIndex;
}
/*
* Deselects devices which don't have the specified minimum version
*/
void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
{
s32 dMajor = 0, dMinor = 0;
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
GetDeviceVersion(i, &dMajor, &dMinor);
if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
vDeviceInfo[i].bSelected = false;
}
}
}
/*
* Deselects devices which don't have the specified maximum version
*/
void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
{
s32 dMajor = 0, dMinor = 0;
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
GetDeviceVersion(i, &dMajor, &dMinor);
if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
vDeviceInfo[i].bSelected = false;
}
}
}
/*
* Deselects device which don't support the given extension name
*/
void ALDeviceList::FilterDevicesExtension(char *szExtName)
{
bool bFound;
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
bFound = false;
for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
bFound = true;
break;
}
}
if (!bFound)
vDeviceInfo[i].bSelected = false;
}
}
/*
* Resets all filtering, such that all devices are in the list
*/
void ALDeviceList::ResetFilters()
{
for (s32 i = 0; i < GetNumDevices(); i++) {
vDeviceInfo[i].bSelected = true;
}
filterIndex = 0;
}
/*
* Gets index of first filtered device
*/
s32 ALDeviceList::GetFirstFilteredDevice()
{
s32 i;
for (i = 0; i < GetNumDevices(); i++) {
if (vDeviceInfo[i].bSelected == true) {
break;
}
}
filterIndex = i + 1;
return i;
}
/*
* Gets index of next filtered device
*/
s32 ALDeviceList::GetNextFilteredDevice()
{
s32 i;
for (i = filterIndex; i < GetNumDevices(); i++) {
if (vDeviceInfo[i].bSelected == true) {
break;
}
}
filterIndex = i + 1;
return i;
}
/*
* Internal function to detemine max number of Sources that can be generated
*/
u32 ALDeviceList::GetMaxNumSources()
{
ALuint uiSources[256];
u32 iSourceCount = 0;
// Clear AL Error Code
alGetError();
// Generate up to 256 Sources, checking for any errors
for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
{
alGenSources(1, &uiSources[iSourceCount]);
if (alGetError() != AL_NO_ERROR)
break;
}
// Release the Sources
alDeleteSources(iSourceCount, uiSources);
if (alGetError() != AL_NO_ERROR)
{
for (u32 i = 0; i < 256; i++)
{
alDeleteSources(1, &uiSources[i]);
}
}
return iSourceCount;
}
/*
* Copyright (c) 2006, Creative Labs Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
* the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "Common.h"
#include "aldlist.h"
#include "../../../../Externals/OpenAL/include/al.h"
#include "../../../../Externals/OpenAL/include/alc.h"
/*
* Init call
*/
ALDeviceList::ALDeviceList()
{
ALDEVICEINFO ALDeviceInfo;
char *devices;
s32 index;
const char *defaultDeviceName = NULL;
const char *actualDeviceName = NULL;
// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
vDeviceInfo.empty();
vDeviceInfo.reserve(10);
defaultDeviceIndex = 0;
// grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
//if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
{
devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
index = 0;
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
while (devices != NULL && strlen(devices) > 0)
{
if (strcmp(defaultDeviceName, devices) == 0)
{
defaultDeviceIndex = index;
}
ALCdevice *device = alcOpenDevice(devices);
if (device)
{
ALCcontext *context = alcCreateContext(device, NULL);
if (context)
{
alcMakeContextCurrent(context);
// if new actual device name isn't already in the list, then add it...
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
bool bNewName = true;
for (s32 i = 0; i < GetNumDevices(); i++)
{
if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
{
bNewName = false;
}
}
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
{
ALDeviceInfo.bSelected = true;
ALDeviceInfo.strDeviceName = actualDeviceName;
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
ALDeviceInfo.pvstrExtensions = new vector<string>;
// Check for ALC Extensions
if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
// Check for AL Extensions
if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
// Get Source Count
ALDeviceInfo.uiSourceCount = GetMaxNumSources();
vDeviceInfo.push_back(ALDeviceInfo);
}
alcMakeContextCurrent(NULL);
alcDestroyContext(context);
}
alcCloseDevice(device);
}
devices += strlen(devices) + 1;
index += 1;
}
}
//}
ResetFilters();
}
/*
* Exit call
*/
ALDeviceList::~ALDeviceList()
{
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
if (vDeviceInfo[i].pvstrExtensions) {
vDeviceInfo[i].pvstrExtensions->empty();
delete vDeviceInfo[i].pvstrExtensions;
}
}
vDeviceInfo.empty();
}
/*
* Returns the number of devices in the complete device list
*/
s32 ALDeviceList::GetNumDevices()
{
return (s32)vDeviceInfo.size();
}
/*
* Returns the device name at an index in the complete device list
*/
char * ALDeviceList::GetDeviceName(s32 index)
{
if (index < GetNumDevices())
return (char *)vDeviceInfo[index].strDeviceName.c_str();
else
return NULL;
}
/*
* Returns the major and minor version numbers for a device at a specified index in the complete list
*/
void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
{
if (index < GetNumDevices()) {
if (major)
*major = vDeviceInfo[index].iMajorVersion;
if (minor)
*minor = vDeviceInfo[index].iMinorVersion;
}
return;
}
/*
* Returns the maximum number of Sources that can be generate on the given device
*/
u32 ALDeviceList::GetMaxNumSources(s32 index)
{
if (index < GetNumDevices())
return vDeviceInfo[index].uiSourceCount;
else
return 0;
}
/*
* Checks if the extension is supported on the given device
*/
bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
{
bool bReturn = false;
if (index < GetNumDevices()) {
for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
bReturn = true;
break;
}
}
}
return bReturn;
}
/*
* returns the index of the default device in the complete device list
*/
s32 ALDeviceList::GetDefaultDevice()
{
return defaultDeviceIndex;
}
/*
* Deselects devices which don't have the specified minimum version
*/
void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
{
s32 dMajor = 0, dMinor = 0;
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
GetDeviceVersion(i, &dMajor, &dMinor);
if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
vDeviceInfo[i].bSelected = false;
}
}
}
/*
* Deselects devices which don't have the specified maximum version
*/
void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
{
s32 dMajor = 0, dMinor = 0;
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
GetDeviceVersion(i, &dMajor, &dMinor);
if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
vDeviceInfo[i].bSelected = false;
}
}
}
/*
* Deselects device which don't support the given extension name
*/
void ALDeviceList::FilterDevicesExtension(char *szExtName)
{
bool bFound;
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
bFound = false;
for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
bFound = true;
break;
}
}
if (!bFound)
vDeviceInfo[i].bSelected = false;
}
}
/*
* Resets all filtering, such that all devices are in the list
*/
void ALDeviceList::ResetFilters()
{
for (s32 i = 0; i < GetNumDevices(); i++) {
vDeviceInfo[i].bSelected = true;
}
filterIndex = 0;
}
/*
* Gets index of first filtered device
*/
s32 ALDeviceList::GetFirstFilteredDevice()
{
s32 i;
for (i = 0; i < GetNumDevices(); i++) {
if (vDeviceInfo[i].bSelected == true) {
break;
}
}
filterIndex = i + 1;
return i;
}
/*
* Gets index of next filtered device
*/
s32 ALDeviceList::GetNextFilteredDevice()
{
s32 i;
for (i = filterIndex; i < GetNumDevices(); i++) {
if (vDeviceInfo[i].bSelected == true) {
break;
}
}
filterIndex = i + 1;
return i;
}
/*
* Internal function to detemine max number of Sources that can be generated
*/
u32 ALDeviceList::GetMaxNumSources()
{
ALuint uiSources[256];
u32 iSourceCount = 0;
// Clear AL Error Code
alGetError();
// Generate up to 256 Sources, checking for any errors
for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
{
alGenSources(1, &uiSources[iSourceCount]);
if (alGetError() != AL_NO_ERROR)
break;
}
// Release the Sources
alDeleteSources(iSourceCount, uiSources);
if (alGetError() != AL_NO_ERROR)
{
for (u32 i = 0; i < 256; i++)
{
alDeleteSources(1, &uiSources[i]);
}
}
return iSourceCount;
}
+51 -51
View File
@@ -1,51 +1,51 @@
#ifndef ALDEVICELIST_H
#define ALDEVICELIST_H
#include "CommonTypes.h"
#ifdef _WIN32
#pragma warning(disable: 4786) //disable warning "identifier was truncated to
//'255' characters in the browser information"
#endif
#include <vector>
#include <string>
using namespace std;
typedef struct
{
string strDeviceName;
s32 iMajorVersion;
s32 iMinorVersion;
u32 uiSourceCount;
vector<string> *pvstrExtensions;
bool bSelected;
} ALDEVICEINFO, *LPALDEVICEINFO;
class ALDeviceList
{
private:
vector<ALDEVICEINFO> vDeviceInfo;
s32 defaultDeviceIndex;
s32 filterIndex;
public:
ALDeviceList ();
~ALDeviceList ();
s32 GetNumDevices();
char *GetDeviceName(s32 index);
void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
u32 GetMaxNumSources(s32 index);
bool IsExtensionSupported(s32 index, char *szExtName);
s32 GetDefaultDevice();
void FilterDevicesMinVer(s32 major, s32 minor);
void FilterDevicesMaxVer(s32 major, s32 minor);
void FilterDevicesExtension(char *szExtName);
void ResetFilters();
s32 GetFirstFilteredDevice();
s32 GetNextFilteredDevice();
private:
u32 GetMaxNumSources();
};
#endif // ALDEVICELIST_H
#ifndef ALDEVICELIST_H
#define ALDEVICELIST_H
#include "CommonTypes.h"
#ifdef _WIN32
#pragma warning(disable: 4786) //disable warning "identifier was truncated to
//'255' characters in the browser information"
#endif
#include <vector>
#include <string>
using namespace std;
typedef struct
{
string strDeviceName;
s32 iMajorVersion;
s32 iMinorVersion;
u32 uiSourceCount;
vector<string> *pvstrExtensions;
bool bSelected;
} ALDEVICEINFO, *LPALDEVICEINFO;
class ALDeviceList
{
private:
vector<ALDEVICEINFO> vDeviceInfo;
s32 defaultDeviceIndex;
s32 filterIndex;
public:
ALDeviceList ();
~ALDeviceList ();
s32 GetNumDevices();
char *GetDeviceName(s32 index);
void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
u32 GetMaxNumSources(s32 index);
bool IsExtensionSupported(s32 index, char *szExtName);
s32 GetDefaultDevice();
void FilterDevicesMinVer(s32 major, s32 minor);
void FilterDevicesMaxVer(s32 major, s32 minor);
void FilterDevicesExtension(char *szExtName);
void ResetFilters();
s32 GetFirstFilteredDevice();
s32 GetNextFilteredDevice();
private:
u32 GetMaxNumSources();
};
#endif // ALDEVICELIST_H
+59 -59
View File
@@ -1,59 +1,59 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "SymbolDB.h"
void SymbolDB::List()
{
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{
DEBUG_LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
}
INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
}
void SymbolDB::Clear(const char *prefix)
{
// TODO: honor prefix
functions.clear();
checksumToFunction.clear();
}
void SymbolDB::Index()
{
int i = 0;
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{
iter->second.index = i++;
}
}
Symbol *SymbolDB::GetSymbolFromName(const char *name)
{
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{
if (!strcmp(iter->second.name.c_str(), name))
return &iter->second;
}
return 0;
}
void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
{
functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "SymbolDB.h"
void SymbolDB::List()
{
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{
DEBUG_LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
}
INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
}
void SymbolDB::Clear(const char *prefix)
{
// TODO: honor prefix
functions.clear();
checksumToFunction.clear();
}
void SymbolDB::Index()
{
int i = 0;
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{
iter->second.index = i++;
}
}
Symbol *SymbolDB::GetSymbolFromName(const char *name)
{
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{
if (!strcmp(iter->second.name.c_str(), name))
return &iter->second;
}
return 0;
}
void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
{
functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
}
+122 -122
View File
@@ -1,122 +1,122 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// This file contains a generic symbol map implementation. For CPU-specific
// magic, derive and extend.
#ifndef _SYMBOL_DB_H
#define _SYMBOL_DB_H
#include <string>
#include <map>
#include "Common.h"
struct SCall
{
SCall(u32 a, u32 b) :
function(a),
callAddress(b)
{}
u32 function;
u32 callAddress;
};
struct Symbol
{
enum {
SYMBOL_FUNCTION = 0,
SYMBOL_DATA = 1,
};
Symbol() :
hash(0),
address(0),
flags(0),
size(0),
numCalls(0),
type(SYMBOL_FUNCTION),
analyzed(0)
{}
std::string name;
std::vector<SCall> callers; //addresses of functions that call this function
std::vector<SCall> calls; //addresses of functions that are called by this function
u32 hash; //use for HLE function finding
u32 address;
u32 flags;
int size;
int numCalls;
int type;
int index; // only used for coloring the disasm view
int analyzed;
};
enum
{
FFLAG_TIMERINSTRUCTIONS=(1<<0),
FFLAG_LEAF=(1<<1),
FFLAG_ONLYCALLSNICELEAFS=(1<<2),
FFLAG_EVIL=(1<<3),
FFLAG_RFI=(1<<4),
FFLAG_STRAIGHT=(1<<5)
};
class SymbolDB
{
public:
typedef std::map<u32, Symbol> XFuncMap;
typedef std::map<u32, Symbol*> XFuncPtrMap;
protected:
XFuncMap functions;
XFuncPtrMap checksumToFunction;
public:
SymbolDB() {}
virtual ~SymbolDB() {}
virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
virtual Symbol *AddFunction(u32 startAddr) { return 0;}
void AddCompleteSymbol(const Symbol &symbol);
Symbol *GetSymbolFromName(const char *name);
Symbol *GetSymbolFromHash(u32 hash) {
XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
if (iter != checksumToFunction.end())
return iter->second;
else
return 0;
}
const XFuncMap &Symbols() const {return functions;}
XFuncMap &AccessSymbols() {return functions;}
// deprecated
XFuncMap::iterator GetIterator() { return functions.begin(); }
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
XFuncMap::iterator End() { return functions.end(); }
void Clear(const char *prefix = "");
void List();
void Index();
};
#endif
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// This file contains a generic symbol map implementation. For CPU-specific
// magic, derive and extend.
#ifndef _SYMBOL_DB_H
#define _SYMBOL_DB_H
#include <string>
#include <map>
#include "Common.h"
struct SCall
{
SCall(u32 a, u32 b) :
function(a),
callAddress(b)
{}
u32 function;
u32 callAddress;
};
struct Symbol
{
enum {
SYMBOL_FUNCTION = 0,
SYMBOL_DATA = 1,
};
Symbol() :
hash(0),
address(0),
flags(0),
size(0),
numCalls(0),
type(SYMBOL_FUNCTION),
analyzed(0)
{}
std::string name;
std::vector<SCall> callers; //addresses of functions that call this function
std::vector<SCall> calls; //addresses of functions that are called by this function
u32 hash; //use for HLE function finding
u32 address;
u32 flags;
int size;
int numCalls;
int type;
int index; // only used for coloring the disasm view
int analyzed;
};
enum
{
FFLAG_TIMERINSTRUCTIONS=(1<<0),
FFLAG_LEAF=(1<<1),
FFLAG_ONLYCALLSNICELEAFS=(1<<2),
FFLAG_EVIL=(1<<3),
FFLAG_RFI=(1<<4),
FFLAG_STRAIGHT=(1<<5)
};
class SymbolDB
{
public:
typedef std::map<u32, Symbol> XFuncMap;
typedef std::map<u32, Symbol*> XFuncPtrMap;
protected:
XFuncMap functions;
XFuncPtrMap checksumToFunction;
public:
SymbolDB() {}
virtual ~SymbolDB() {}
virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
virtual Symbol *AddFunction(u32 startAddr) { return 0;}
void AddCompleteSymbol(const Symbol &symbol);
Symbol *GetSymbolFromName(const char *name);
Symbol *GetSymbolFromHash(u32 hash) {
XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
if (iter != checksumToFunction.end())
return iter->second;
else
return 0;
}
const XFuncMap &Symbols() const {return functions;}
XFuncMap &AccessSymbols() {return functions;}
// deprecated
XFuncMap::iterator GetIterator() { return functions.begin(); }
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
XFuncMap::iterator End() { return functions.end(); }
void Clear(const char *prefix = "");
void List();
void Index();
};
#endif
@@ -1,24 +1,24 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
//Add support for apple keycodes
};
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
//Add support for apple keycodes
};
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
//Add support for apple keycodes
};
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
//Add support for apple keycodes
};
@@ -1,25 +1,25 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
//Add support for Linux keycodes
};
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
//Add support for Linux keycodes
};
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
//Add support for Linux keycodes
};
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
//Add support for Linux keycodes
};
@@ -1,192 +1,192 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace
0x2B, // Tab
0x00, 0x00,
0x00, // Clear
0x28, // Return
0x00, 0x00,
0x00, // Shift
0x00, // Control
0x00, // ALT
0x48, // Pause
0x39, // Capital
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, // Escape
0x00, 0x00, 0x00, 0x00,
0x2C, // Space
0x4B, // Prior
0x4E, // Next
0x4D, // End
0x4A, // Home
0x50, // Left
0x52, // Up
0x4F, // Right
0x51, // Down
0x00, 0x00, 0x00,
0x46, // Print screen
0x49, // Insert
0x4C, // Delete
0x00,
// 0 -> 9
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
// A -> Z
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
0x1C, 0x1D,
0x00, 0x00, 0x00, 0x00,
0x00,
// Numpad 0 -> 9
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61,
0x55, // Multiply
0x57, // Add
0x00, // Separator
0x56, // Substract
0x63, // Decimal
0x54, // Divide
// F1 -> F12
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45,
// F13 -> F24
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x53, // Numlock
0x47, // Scroll lock
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Modifier keys
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x33, // ';'
0x2E, // Plus
0x36, // Comma
0x2D, // Minus
0x37, // Period
0x38, // '/'
0x35, // '~'
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x2F, // '['
0x32, // '\'
0x30, // ']'
0x34, // '''
0x00, //
0x00, // Nothing interesting past this point.
};
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace
0x2B, // Tab
0x00, 0x00,
0x00, // Clear
0x28, // Return
0x00, 0x00,
0x00, // Shift
0x00, // Control
0x00, // ALT
0x48, // Pause
0x39, // Capital
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, // Escape
0x00, 0x00, 0x00, 0x00,
0x2C, // Space
0x4B, // Prior
0x4E, // Next
0x4D, // End
0x4A, // Home
0x50, // Left
0x52, // Up
0x4F, // Right
0x51, // Down
0x00, 0x00, 0x00,
0x46, // Print screen
0x49, // Insert
0x4C, // Delete
0x00,
// 0 -> 9
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
// A -> Z
0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
0x1C, 0x1A,
0x00, 0x00, 0x00, 0x00,
0x00,
// Numpad 0 -> 9
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61,
0x55, // Multiply
0x57, // Add
0x00, // Separator
0x56, // Substract
0x63, // Decimal
0x54, // Divide
// F1 -> F12
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45,
// F13 -> F24
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x53, // Numlock
0x47, // Scroll lock
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Modifier keys
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x30, // '$'
0x2E, // Plus
0x10, // Comma
0x00, // Minus
0x36, // Period
0x37, // '/'
0x34, // 'ù'
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x2D, // ')'
0x32, // '\'
0x2F, // '^'
0x00, // '²'
0x38, // '!'
0x00, // Nothing interesting past this point.
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace
0x2B, // Tab
0x00, 0x00,
0x00, // Clear
0x28, // Return
0x00, 0x00,
0x00, // Shift
0x00, // Control
0x00, // ALT
0x48, // Pause
0x39, // Capital
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, // Escape
0x00, 0x00, 0x00, 0x00,
0x2C, // Space
0x4B, // Prior
0x4E, // Next
0x4D, // End
0x4A, // Home
0x50, // Left
0x52, // Up
0x4F, // Right
0x51, // Down
0x00, 0x00, 0x00,
0x46, // Print screen
0x49, // Insert
0x4C, // Delete
0x00,
// 0 -> 9
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
// A -> Z
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
0x1C, 0x1D,
0x00, 0x00, 0x00, 0x00,
0x00,
// Numpad 0 -> 9
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61,
0x55, // Multiply
0x57, // Add
0x00, // Separator
0x56, // Substract
0x63, // Decimal
0x54, // Divide
// F1 -> F12
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45,
// F13 -> F24
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x53, // Numlock
0x47, // Scroll lock
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Modifier keys
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x33, // ';'
0x2E, // Plus
0x36, // Comma
0x2D, // Minus
0x37, // Period
0x38, // '/'
0x35, // '~'
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x2F, // '['
0x32, // '\'
0x30, // ']'
0x34, // '''
0x00, //
0x00, // Nothing interesting past this point.
};
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, // Backspace
0x2B, // Tab
0x00, 0x00,
0x00, // Clear
0x28, // Return
0x00, 0x00,
0x00, // Shift
0x00, // Control
0x00, // ALT
0x48, // Pause
0x39, // Capital
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x29, // Escape
0x00, 0x00, 0x00, 0x00,
0x2C, // Space
0x4B, // Prior
0x4E, // Next
0x4D, // End
0x4A, // Home
0x50, // Left
0x52, // Up
0x4F, // Right
0x51, // Down
0x00, 0x00, 0x00,
0x46, // Print screen
0x49, // Insert
0x4C, // Delete
0x00,
// 0 -> 9
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
0x25, 0x26,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00,
// A -> Z
0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
0x1C, 0x1A,
0x00, 0x00, 0x00, 0x00,
0x00,
// Numpad 0 -> 9
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61,
0x55, // Multiply
0x57, // Add
0x00, // Separator
0x56, // Substract
0x63, // Decimal
0x54, // Divide
// F1 -> F12
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
0x42, 0x43, 0x44, 0x45,
// F13 -> F24
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x53, // Numlock
0x47, // Scroll lock
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Modifier keys
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x30, // '$'
0x2E, // Plus
0x10, // Comma
0x00, // Minus
0x36, // Period
0x37, // '/'
0x34, // 'ù'
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
0x2D, // ')'
0x32, // '\'
0x2F, // '^'
0x00, // '²'
0x38, // '!'
0x00, // Nothing interesting past this point.
};
+133 -133
View File
@@ -1,133 +1,133 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPAnalyzer.h"
#include "DSPInterpreter.h"
#include "DSPTables.h"
#include "DSPMemoryMap.h"
namespace DSPAnalyzer {
// Holds data about all instructions in RAM.
u8 code_flags[ISPACE];
// Good candidates for idle skipping is mail wait loops. If we're time slicing
// between the main CPU and the DSP, if the DSP runs into one of these, it might
// as well give up its time slice immediately, after executing once.
// Max signature length is 6. A 0 in a signature is ignored.
#define NUM_IDLE_SIGS 5
#define MAX_IDLE_SIG_SIZE 6
// 0xFFFF means ignore.
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
{
// From AX:
{ 0x26fc, // LRS $30, @DMBH
0x02c0, 0x8000, // ANDCF $30, #0x8000
0x029d, 0xFFFF, // JLZ 0x027a
0, 0 }, // RET
{ 0x27fc, // LRS $31, @DMBH
0x03c0, 0x8000, // ANDCF $31, #0x8000
0x029d, 0xFFFF, // JLZ 0x027a
0, 0 }, // RET
{ 0x26fe, // LRS $30, @CMBH
0x02c0, 0x8000, // ANDCF $30, #0x8000
0x029c, 0xFFFF, // JLNZ 0x0280
0, 0 }, // RET
{ 0x27fe, // LRS $31, @CMBH
0x03c0, 0x8000, // ANDCF $31, #0x8000
0x029c, 0xFFFF, // JLNZ 0x0280
0, 0 }, // RET
// From Zelda:
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
0x029c, 0xFFFF, // JLNZ 0x05cf
0 }
};
void Reset()
{
memset(code_flags, 0, sizeof(code_flags));
}
void AnalyzeRange(int start_addr, int end_addr)
{
// First we run an extremely simplified version of a disassembler to find
// where all instructions start.
// This may not be 100% accurate in case of jump tables!
// It could get desynced, which would be bad. We'll see if that's an issue.
int addr = start_addr;
while (addr < end_addr)
{
UDSPInstruction inst = dsp_imem_read(addr);
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
if (!opcode)
{
addr++;
continue;
}
code_flags[addr] |= CODE_START_OF_INST;
addr += opcode->size;
// Look for loops.
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
// BLOOP, BLOOPI
u16 loop_end = dsp_imem_read(addr + 1);
code_flags[loop_end] |= CODE_LOOP_END;
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
// LOOP, LOOPI
code_flags[addr + 1] |= CODE_LOOP_END;
}
}
// Next, we'll scan for potential idle skips.
for (int s = 0; s < NUM_IDLE_SIGS; s++)
{
for (int addr = start_addr; addr < end_addr; addr++)
{
bool found = false;
for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
{
if (idle_skip_sigs[s][i] == 0)
found = true;
if (idle_skip_sigs[s][i] == 0xFFFF)
continue;
if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
break;
}
if (found)
{
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
code_flags[addr] |= CODE_IDLE_SKIP;
// TODO: actually use this flag somewhere.
}
}
}
NOTICE_LOG(DSPLLE, "Finished analysis.");
}
void Analyze()
{
Reset();
AnalyzeRange(0x0000, 0x1000); // IRAM
AnalyzeRange(0x8000, 0x9000); // IROM
}
} // namespace
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPAnalyzer.h"
#include "DSPInterpreter.h"
#include "DSPTables.h"
#include "DSPMemoryMap.h"
namespace DSPAnalyzer {
// Holds data about all instructions in RAM.
u8 code_flags[ISPACE];
// Good candidates for idle skipping is mail wait loops. If we're time slicing
// between the main CPU and the DSP, if the DSP runs into one of these, it might
// as well give up its time slice immediately, after executing once.
// Max signature length is 6. A 0 in a signature is ignored.
#define NUM_IDLE_SIGS 5
#define MAX_IDLE_SIG_SIZE 6
// 0xFFFF means ignore.
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
{
// From AX:
{ 0x26fc, // LRS $30, @DMBH
0x02c0, 0x8000, // ANDCF $30, #0x8000
0x029d, 0xFFFF, // JLZ 0x027a
0, 0 }, // RET
{ 0x27fc, // LRS $31, @DMBH
0x03c0, 0x8000, // ANDCF $31, #0x8000
0x029d, 0xFFFF, // JLZ 0x027a
0, 0 }, // RET
{ 0x26fe, // LRS $30, @CMBH
0x02c0, 0x8000, // ANDCF $30, #0x8000
0x029c, 0xFFFF, // JLNZ 0x0280
0, 0 }, // RET
{ 0x27fe, // LRS $31, @CMBH
0x03c0, 0x8000, // ANDCF $31, #0x8000
0x029c, 0xFFFF, // JLNZ 0x0280
0, 0 }, // RET
// From Zelda:
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
0x029c, 0xFFFF, // JLNZ 0x05cf
0 }
};
void Reset()
{
memset(code_flags, 0, sizeof(code_flags));
}
void AnalyzeRange(int start_addr, int end_addr)
{
// First we run an extremely simplified version of a disassembler to find
// where all instructions start.
// This may not be 100% accurate in case of jump tables!
// It could get desynced, which would be bad. We'll see if that's an issue.
int addr = start_addr;
while (addr < end_addr)
{
UDSPInstruction inst = dsp_imem_read(addr);
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
if (!opcode)
{
addr++;
continue;
}
code_flags[addr] |= CODE_START_OF_INST;
addr += opcode->size;
// Look for loops.
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
// BLOOP, BLOOPI
u16 loop_end = dsp_imem_read(addr + 1);
code_flags[loop_end] |= CODE_LOOP_END;
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
// LOOP, LOOPI
code_flags[addr + 1] |= CODE_LOOP_END;
}
}
// Next, we'll scan for potential idle skips.
for (int s = 0; s < NUM_IDLE_SIGS; s++)
{
for (int addr = start_addr; addr < end_addr; addr++)
{
bool found = false;
for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
{
if (idle_skip_sigs[s][i] == 0)
found = true;
if (idle_skip_sigs[s][i] == 0xFFFF)
continue;
if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
break;
}
if (found)
{
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
code_flags[addr] |= CODE_IDLE_SKIP;
// TODO: actually use this flag somewhere.
}
}
}
NOTICE_LOG(DSPLLE, "Finished analysis.");
}
void Analyze()
{
Reset();
AnalyzeRange(0x0000, 0x1000); // IRAM
AnalyzeRange(0x8000, 0x9000); // IROM
}
} // namespace
+49 -49
View File
@@ -1,49 +1,49 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Basic code analysis.
#include "DSPInterpreter.h"
namespace DSPAnalyzer {
#define ISPACE 65536
// Useful things to detect:
// * Loop endpoints - so that we can avoid checking for loops every cycle.
enum
{
CODE_START_OF_INST = 1,
CODE_IDLE_SKIP = 2,
CODE_LOOP_END = 4,
};
// Easy to query array covering the whole of instruction memory.
// Just index by address.
// This one will be helpful for debuggers and jits.
extern u8 code_flags[ISPACE];
// This one should be called every time IRAM changes - which is basically
// every time that a new ucode gets uploaded, and never else. At that point,
// we can do as much static analysis as we want - but we should always throw
// all old analysis away. Luckily the entire address space is only 64K code
// words and the actual code space 8K instructions in total, so we can do
// some pretty expensive analysis if necessary.
void Analyze();
} // namespace
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Basic code analysis.
#include "DSPInterpreter.h"
namespace DSPAnalyzer {
#define ISPACE 65536
// Useful things to detect:
// * Loop endpoints - so that we can avoid checking for loops every cycle.
enum
{
CODE_START_OF_INST = 1,
CODE_IDLE_SKIP = 2,
CODE_LOOP_END = 4,
};
// Easy to query array covering the whole of instruction memory.
// Just index by address.
// This one will be helpful for debuggers and jits.
extern u8 code_flags[ISPACE];
// This one should be called every time IRAM changes - which is basically
// every time that a new ucode gets uploaded, and never else. At that point,
// we can do as much static analysis as we want - but we should always throw
// all old analysis away. Luckily the entire address space is only 64K code
// words and the actual code space 8K instructions in total, so we can do
// some pretty expensive analysis if necessary.
void Analyze();
} // namespace
+19 -19
View File
@@ -1,19 +1,19 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPBreakpoints.h"
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPBreakpoints.h"
+63 -63
View File
@@ -1,63 +1,63 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSP_BREAKPOINTS
#define _DSP_BREAKPOINTS
#include "Common.h"
// super fast breakpoints for a limited range.
// To be used interchangably with the BreakPoints class.
class DSPBreakpoints
{
public:
DSPBreakpoints() {Clear();}
// is address breakpoint
bool IsAddressBreakPoint(u32 addr) {
return b[addr] != 0;
}
// AddBreakPoint
bool Add(u32 addr, bool temp=false) {
bool was_one = b[addr] != 0;
if (!was_one) {
b[addr] = temp ? 2 : 1;
return true;
} else {
return false;
}
}
// Remove Breakpoint
bool Remove(u32 addr) {
bool was_one = b[addr] != 0;
b[addr] = 0;
return was_one;
}
void Clear() {
for (int i = 0; i < 65536; i++)
b[i] = 0;
}
void DeleteByAddress(u32 addr) {
b[addr] = 0;
}
private:
u8 b[65536];
};
#endif
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSP_BREAKPOINTS
#define _DSP_BREAKPOINTS
#include "Common.h"
// super fast breakpoints for a limited range.
// To be used interchangably with the BreakPoints class.
class DSPBreakpoints
{
public:
DSPBreakpoints() {Clear();}
// is address breakpoint
bool IsAddressBreakPoint(u32 addr) {
return b[addr] != 0;
}
// AddBreakPoint
bool Add(u32 addr, bool temp=false) {
bool was_one = b[addr] != 0;
if (!was_one) {
b[addr] = temp ? 2 : 1;
return true;
} else {
return false;
}
}
// Remove Breakpoint
bool Remove(u32 addr) {
bool was_one = b[addr] != 0;
b[addr] = 0;
return was_one;
}
void Clear() {
for (int i = 0; i < 65536; i++)
b[i] = 0;
}
void DeleteByAddress(u32 addr) {
b[addr] = 0;
}
private:
u8 b[65536];
};
#endif
+235 -235
View File
@@ -1,235 +1,235 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <iostream>
#include <vector>
#include "Common.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "DSPCodeUtil.h"
#include "assemble.h"
#include "disassemble.h"
bool Assemble(const char *text, std::vector<u16> &code)
{
AssemblerSettings settings;
settings.pc = 0;
// settings.decode_registers = false;
// settings.decode_names = false;
settings.print_tabs = false;
settings.ext_separator = '\'';
// TODO: fix the terrible api of the assembler.
DSPAssembler assembler(settings);
if (!assembler.Assemble(text, code)) {
std::cerr << assembler.GetErrorString() << std::endl;
return false;
}
return true;
}
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
{
if (code.empty())
return false;
AssemblerSettings settings;
// These two prevent roundtripping.
settings.show_hex = false;
settings.show_pc = line_numbers;
settings.ext_separator = '\'';
settings.decode_names = false;
settings.decode_registers = true;
DSPDisassembler disasm(settings);
bool success = disasm.Disassemble(0, code, 0x0000, text);
return success;
}
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
{
if (code1.size() != code2.size())
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
u32 count_equal = 0;
const int min_size = (int)std::min(code1.size(), code2.size());
AssemblerSettings settings;
DSPDisassembler disassembler(settings);
for (int i = 0; i < min_size; i++)
{
if (code1[i] == code2[i])
count_equal++;
else
{
std::string line1, line2;
u16 pc = i;
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
pc = i;
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
}
}
if (code2.size() != code1.size())
{
printf("Extra code words:\n");
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
for (int i = min_size; i < (int)longest.size(); i++)
{
u16 pc = i;
std::string line;
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
printf("!! %s\n", line.c_str());
}
}
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
return code1.size() == code2.size() && code1.size() == count_equal;
}
void GenRandomCode(int size, std::vector<u16> &code)
{
code.resize(size);
for (int i = 0; i < size; i++)
{
code[i] = rand() ^ (rand() << 8);
}
}
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
const char *name, std::string &header)
{
std::vector<u16> code_copy = code;
// Add some nops at the end to align the size a bit.
while (code_copy.size() & 7)
code_copy.push_back(0);
char buffer[1024];
header.clear();
header.reserve(code.size() * 4);
header.append("#define NUM_UCODES 1\n\n");
std::string filename;
SplitPath(_filename, NULL, &filename, NULL);
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
header.append("#ifndef _MSCVER\n");
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
header.append("#else\n");
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
header.append("#endif\n\n");
header.append("\t{\n\t\t");
for (u32 j = 0; j < code.size(); j++)
{
if (j && ((j & 15) == 0))
header.append("\n\t\t");
sprintf(buffer, "0x%04x, ", code[j]);
header.append(buffer);
}
header.append("\n\t},\n");
header.append("};\n");
}
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
int numCodes, const char *name, std::string &header)
{
char buffer[1024];
int reserveSize = 0;
for(int i = 0; i < numCodes; i++)
reserveSize += (int)codes[i].size();
header.clear();
header.reserve(reserveSize * 4);
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
header.append(buffer);
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
for (int i = 0; i < numCodes; i++)
{
std::string filename;
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
filename = filenames->at(i);
sprintf(buffer, "\t\"%s\",\n", filename.c_str());
header.append(buffer);
}
header.append("};\n\n");
header.append("#ifndef _MSCVER\n");
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
header.append("#else\n");
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
header.append("#endif\n\n");
for(int i = 0; i < numCodes; i++) {
if(codes[i].size() == 0)
continue;
std::vector<u16> code_copy = codes[i];
// Add some nops at the end to align the size a bit.
while (code_copy.size() & 7)
code_copy.push_back(0);
header.append("\t{\n\t\t");
for (u32 j = 0; j < codes[i].size(); j++)
{
if (j && ((j & 15) == 0))
header.append("\n\t\t");
sprintf(buffer, "0x%04x, ", codes[i][j]);
header.append(buffer);
}
header.append("\n\t},\n");
}
header.append("};\n");
}
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
{
str.resize(code.size() * 2);
for (int i = 0; i < (int)code.size(); i++)
{
str[i * 2 + 0] = code[i] >> 8;
str[i * 2 + 1] = code[i] & 0xff;
}
}
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
{
code.resize(str.size() / 2);
for (int i = 0; i < (int)code.size(); i++)
{
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
}
}
bool LoadBinary(const char *filename, std::vector<u16> &code)
{
std::string buffer;
if (!File::ReadFileToString(false, filename, buffer))
return false;
BinaryStringBEToCode(buffer, code);
return true;
}
bool SaveBinary(const std::vector<u16> &code, const char *filename)
{
std::string buffer;
CodeToBinaryStringBE(code, buffer);
if (!File::WriteStringToFile(false, buffer, filename))
return false;
return true;
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <iostream>
#include <vector>
#include "Common.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "DSPCodeUtil.h"
#include "assemble.h"
#include "disassemble.h"
bool Assemble(const char *text, std::vector<u16> &code)
{
AssemblerSettings settings;
settings.pc = 0;
// settings.decode_registers = false;
// settings.decode_names = false;
settings.print_tabs = false;
settings.ext_separator = '\'';
// TODO: fix the terrible api of the assembler.
DSPAssembler assembler(settings);
if (!assembler.Assemble(text, code)) {
std::cerr << assembler.GetErrorString() << std::endl;
return false;
}
return true;
}
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
{
if (code.empty())
return false;
AssemblerSettings settings;
// These two prevent roundtripping.
settings.show_hex = false;
settings.show_pc = line_numbers;
settings.ext_separator = '\'';
settings.decode_names = false;
settings.decode_registers = true;
DSPDisassembler disasm(settings);
bool success = disasm.Disassemble(0, code, 0x0000, text);
return success;
}
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
{
if (code1.size() != code2.size())
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
u32 count_equal = 0;
const int min_size = (int)std::min(code1.size(), code2.size());
AssemblerSettings settings;
DSPDisassembler disassembler(settings);
for (int i = 0; i < min_size; i++)
{
if (code1[i] == code2[i])
count_equal++;
else
{
std::string line1, line2;
u16 pc = i;
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
pc = i;
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
}
}
if (code2.size() != code1.size())
{
printf("Extra code words:\n");
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
for (int i = min_size; i < (int)longest.size(); i++)
{
u16 pc = i;
std::string line;
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
printf("!! %s\n", line.c_str());
}
}
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
return code1.size() == code2.size() && code1.size() == count_equal;
}
void GenRandomCode(int size, std::vector<u16> &code)
{
code.resize(size);
for (int i = 0; i < size; i++)
{
code[i] = rand() ^ (rand() << 8);
}
}
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
const char *name, std::string &header)
{
std::vector<u16> code_copy = code;
// Add some nops at the end to align the size a bit.
while (code_copy.size() & 7)
code_copy.push_back(0);
char buffer[1024];
header.clear();
header.reserve(code.size() * 4);
header.append("#define NUM_UCODES 1\n\n");
std::string filename;
SplitPath(_filename, NULL, &filename, NULL);
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
header.append("#ifndef _MSCVER\n");
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
header.append("#else\n");
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
header.append("#endif\n\n");
header.append("\t{\n\t\t");
for (u32 j = 0; j < code.size(); j++)
{
if (j && ((j & 15) == 0))
header.append("\n\t\t");
sprintf(buffer, "0x%04x, ", code[j]);
header.append(buffer);
}
header.append("\n\t},\n");
header.append("};\n");
}
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
int numCodes, const char *name, std::string &header)
{
char buffer[1024];
int reserveSize = 0;
for(int i = 0; i < numCodes; i++)
reserveSize += (int)codes[i].size();
header.clear();
header.reserve(reserveSize * 4);
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
header.append(buffer);
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
for (int i = 0; i < numCodes; i++)
{
std::string filename;
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
filename = filenames->at(i);
sprintf(buffer, "\t\"%s\",\n", filename.c_str());
header.append(buffer);
}
header.append("};\n\n");
header.append("#ifndef _MSCVER\n");
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
header.append("#else\n");
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
header.append("#endif\n\n");
for(int i = 0; i < numCodes; i++) {
if(codes[i].size() == 0)
continue;
std::vector<u16> code_copy = codes[i];
// Add some nops at the end to align the size a bit.
while (code_copy.size() & 7)
code_copy.push_back(0);
header.append("\t{\n\t\t");
for (u32 j = 0; j < codes[i].size(); j++)
{
if (j && ((j & 15) == 0))
header.append("\n\t\t");
sprintf(buffer, "0x%04x, ", codes[i][j]);
header.append(buffer);
}
header.append("\n\t},\n");
}
header.append("};\n");
}
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
{
str.resize(code.size() * 2);
for (int i = 0; i < (int)code.size(); i++)
{
str[i * 2 + 0] = code[i] >> 8;
str[i * 2 + 1] = code[i] & 0xff;
}
}
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
{
code.resize(str.size() / 2);
for (int i = 0; i < (int)code.size(); i++)
{
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
}
}
bool LoadBinary(const char *filename, std::vector<u16> &code)
{
std::string buffer;
if (!File::ReadFileToString(false, filename, buffer))
return false;
BinaryStringBEToCode(buffer, code);
return true;
}
bool SaveBinary(const std::vector<u16> &code, const char *filename)
{
std::string buffer;
CodeToBinaryStringBE(code, buffer);
if (!File::WriteStringToFile(false, buffer, filename))
return false;
return true;
}
+43 -43
View File
@@ -1,43 +1,43 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPCODEUTIL_H
#define _DSPCODEUTIL_H
#include <string>
#include <vector>
#include "Common.h"
bool Assemble(const char *text, std::vector<u16> &code);
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
void GenRandomCode(int size, std::vector<u16> &code);
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
const char *name, std::string &header);
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
int numCodes, const char *name, std::string &header);
// Big-endian, for writing straight to file using File::WriteStringToFile.
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
// Load code (big endian binary).
bool LoadBinary(const char *filename, std::vector<u16> &code);
bool SaveBinary(const std::vector<u16> &code, const char *filename);
#endif // _DSPCODEUTIL_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPCODEUTIL_H
#define _DSPCODEUTIL_H
#include <string>
#include <vector>
#include "Common.h"
bool Assemble(const char *text, std::vector<u16> &code);
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
void GenRandomCode(int size, std::vector<u16> &code);
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
const char *name, std::string &header);
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
int numCodes, const char *name, std::string &header);
// Big-endian, for writing straight to file using File::WriteStringToFile.
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
// Load code (big endian binary).
bool LoadBinary(const char *filename, std::vector<u16> &code);
bool SaveBinary(const std::vector<u16> &code, const char *filename);
#endif // _DSPCODEUTIL_H
+256 -256
View File
@@ -1,256 +1,256 @@
/*====================================================================
filename: gdsp_interpreter.cpp
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include "Common.h"
#include "Thread.h"
#include "DSPCore.h"
#include "DSPHost.h"
#include "DSPAnalyzer.h"
#include "MemoryUtil.h"
#include "DSPHWInterface.h"
#include "DSPIntUtil.h"
SDSP g_dsp;
DSPBreakpoints dsp_breakpoints;
DSPCoreState core_state = DSPCORE_RUNNING;
Common::Event step_event;
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
{
FILE *pFile = fopen(fname, "rb");
const size_t size_in_bytes = size_in_words * sizeof(u16);
if (pFile)
{
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
if (read_bytes != size_in_bytes)
{
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
fclose(pFile);
return false;
}
fclose(pFile);
// Byteswap the rom.
for (int i = 0; i < DSP_IROM_SIZE; i++)
rom[i] = Common::swap16(rom[i]);
return true;
}
// Always keep ROMs write protected.
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
return false;
}
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
{
g_dsp.step_counter = 0;
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
// Fill roms with zeros.
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
for (int i = 0; i < 32; i++)
{
g_dsp.r[i] = 0;
}
for (int i = 0; i < 4; i++)
{
g_dsp.reg_stack_ptr[i] = 0;
for (int j = 0; j < DSP_STACK_DEPTH; j++)
{
g_dsp.reg_stack[i][j] = 0;
}
}
// Fill IRAM with HALT opcodes.
for (int i = 0; i < DSP_IRAM_SIZE; i++)
{
g_dsp.iram[i] = 0x0021; // HALT opcode
}
// Just zero out DRAM.
for (int i = 0; i < DSP_DRAM_SIZE; i++)
{
g_dsp.dram[i] = 0;
}
// Copied from a real console after the custom UCode has been loaded.
// These are the indexing wrapping registers.
g_dsp.r[DSP_REG_WR0] = 0xffff;
g_dsp.r[DSP_REG_WR1] = 0xffff;
g_dsp.r[DSP_REG_WR2] = 0xffff;
g_dsp.r[DSP_REG_WR3] = 0xffff;
g_dsp.cr = 0x804;
gdsp_ifx_init();
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
// in new ucodes.
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
DSPAnalyzer::Analyze();
step_event.Init();
return true;
}
void DSPCore_Shutdown()
{
step_event.Shutdown();
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
}
void DSPCore_Reset()
{
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
g_dsp.pc = DSP_RESET_VECTOR;
g_dsp.exception_in_progress_hack = false;
g_dsp.r[DSP_REG_WR0] = 0xffff;
g_dsp.r[DSP_REG_WR1] = 0xffff;
g_dsp.r[DSP_REG_WR2] = 0xffff;
g_dsp.r[DSP_REG_WR3] = 0xffff;
}
void DSPCore_SetException(u8 level)
{
g_dsp.exceptions |= 1 << level;
}
void DSPCore_CheckExternalInterrupt()
{
// check if there is an external interrupt
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
{
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "trying External interupt fired");
#endif
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
{
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "External interupt fired");
#endif
// level 7 is the interrupt exception
DSPCore_SetException(EXP_INT);
g_dsp.cr &= ~CR_EXTERNAL_INT;
}
}
}
void DSPCore_CheckExceptions()
{
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
#endif
// check exceptions
for (int i = 0; i < 8; i++) {
// Seems 7 must pass or zelda dies
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
if (g_dsp.exceptions & (1 << i)) {
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
g_dsp.pc = i * 2;
g_dsp.exceptions &= ~(1 << i);
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "exception %d fired");
#endif
g_dsp.exception_in_progress_hack = true;
break;
}
}
}
}
}
// Delegate to JIT (when it is written) or interpreter as appropriate.
// Handle state changes and stepping.
int DSPCore_RunCycles(int cycles)
{
while (cycles > 0) {
reswitch:
switch (core_state)
{
case DSPCORE_RUNNING:
#if 1 // Set to 0 to disable breakpoints, for a speed boost.
cycles = DSPInterpreter::RunCyclesDebug(cycles);
#else
cycles = DSPInterpreter::RunCycles(cycles);
#endif
break;
case DSPCORE_STEPPING:
step_event.Wait();
if (core_state != DSPCORE_STEPPING)
goto reswitch;
DSPInterpreter::Step();
cycles--;
DSPHost_UpdateDebugger();
break;
}
}
return cycles;
}
void DSPCore_SetState(DSPCoreState new_state)
{
core_state = new_state;
// kick the event, in case we are waiting
if (new_state == DSPCORE_RUNNING)
step_event.Set();
// Sleep(10);
DSPHost_UpdateDebugger();
}
DSPCoreState DSPCore_GetState()
{
return core_state;
}
void DSPCore_Step()
{
if (core_state == DSPCORE_STEPPING)
step_event.Set();
}
/*====================================================================
filename: gdsp_interpreter.cpp
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#include "Common.h"
#include "Thread.h"
#include "DSPCore.h"
#include "DSPHost.h"
#include "DSPAnalyzer.h"
#include "MemoryUtil.h"
#include "DSPHWInterface.h"
#include "DSPIntUtil.h"
SDSP g_dsp;
DSPBreakpoints dsp_breakpoints;
DSPCoreState core_state = DSPCORE_RUNNING;
Common::Event step_event;
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
{
FILE *pFile = fopen(fname, "rb");
const size_t size_in_bytes = size_in_words * sizeof(u16);
if (pFile)
{
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
if (read_bytes != size_in_bytes)
{
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
fclose(pFile);
return false;
}
fclose(pFile);
// Byteswap the rom.
for (int i = 0; i < DSP_IROM_SIZE; i++)
rom[i] = Common::swap16(rom[i]);
return true;
}
// Always keep ROMs write protected.
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
return false;
}
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
{
g_dsp.step_counter = 0;
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
// Fill roms with zeros.
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
for (int i = 0; i < 32; i++)
{
g_dsp.r[i] = 0;
}
for (int i = 0; i < 4; i++)
{
g_dsp.reg_stack_ptr[i] = 0;
for (int j = 0; j < DSP_STACK_DEPTH; j++)
{
g_dsp.reg_stack[i][j] = 0;
}
}
// Fill IRAM with HALT opcodes.
for (int i = 0; i < DSP_IRAM_SIZE; i++)
{
g_dsp.iram[i] = 0x0021; // HALT opcode
}
// Just zero out DRAM.
for (int i = 0; i < DSP_DRAM_SIZE; i++)
{
g_dsp.dram[i] = 0;
}
// Copied from a real console after the custom UCode has been loaded.
// These are the indexing wrapping registers.
g_dsp.r[DSP_REG_WR0] = 0xffff;
g_dsp.r[DSP_REG_WR1] = 0xffff;
g_dsp.r[DSP_REG_WR2] = 0xffff;
g_dsp.r[DSP_REG_WR3] = 0xffff;
g_dsp.cr = 0x804;
gdsp_ifx_init();
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
// in new ucodes.
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
DSPAnalyzer::Analyze();
step_event.Init();
return true;
}
void DSPCore_Shutdown()
{
step_event.Shutdown();
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
}
void DSPCore_Reset()
{
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
g_dsp.pc = DSP_RESET_VECTOR;
g_dsp.exception_in_progress_hack = false;
g_dsp.r[DSP_REG_WR0] = 0xffff;
g_dsp.r[DSP_REG_WR1] = 0xffff;
g_dsp.r[DSP_REG_WR2] = 0xffff;
g_dsp.r[DSP_REG_WR3] = 0xffff;
}
void DSPCore_SetException(u8 level)
{
g_dsp.exceptions |= 1 << level;
}
void DSPCore_CheckExternalInterrupt()
{
// check if there is an external interrupt
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
{
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "trying External interupt fired");
#endif
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
{
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "External interupt fired");
#endif
// level 7 is the interrupt exception
DSPCore_SetException(EXP_INT);
g_dsp.cr &= ~CR_EXTERNAL_INT;
}
}
}
void DSPCore_CheckExceptions()
{
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
#endif
// check exceptions
for (int i = 0; i < 8; i++) {
// Seems 7 must pass or zelda dies
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
if (g_dsp.exceptions & (1 << i)) {
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
g_dsp.pc = i * 2;
g_dsp.exceptions &= ~(1 << i);
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "exception %d fired");
#endif
g_dsp.exception_in_progress_hack = true;
break;
}
}
}
}
}
// Delegate to JIT (when it is written) or interpreter as appropriate.
// Handle state changes and stepping.
int DSPCore_RunCycles(int cycles)
{
while (cycles > 0) {
reswitch:
switch (core_state)
{
case DSPCORE_RUNNING:
#if 1 // Set to 0 to disable breakpoints, for a speed boost.
cycles = DSPInterpreter::RunCyclesDebug(cycles);
#else
cycles = DSPInterpreter::RunCycles(cycles);
#endif
break;
case DSPCORE_STEPPING:
step_event.Wait();
if (core_state != DSPCORE_STEPPING)
goto reswitch;
DSPInterpreter::Step();
cycles--;
DSPHost_UpdateDebugger();
break;
}
}
return cycles;
}
void DSPCore_SetState(DSPCoreState new_state)
{
core_state = new_state;
// kick the event, in case we are waiting
if (new_state == DSPCORE_RUNNING)
step_event.Set();
// Sleep(10);
DSPHost_UpdateDebugger();
}
DSPCoreState DSPCore_GetState()
{
return core_state;
}
void DSPCore_Step()
{
if (core_state == DSPCORE_STEPPING)
step_event.Set();
}
+240 -240
View File
@@ -1,240 +1,240 @@
/*====================================================================
filename: DSPCore.h
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#ifndef _DSPCORE_H
#define _DSPCORE_H
#include "DSPBreakpoints.h"
#define DSP_IRAM_BYTE_SIZE 0x2000
#define DSP_IRAM_SIZE 0x1000
#define DSP_IRAM_MASK 0x0fff
#define DSP_IROM_BYTE_SIZE 0x2000
#define DSP_IROM_SIZE 0x1000
#define DSP_IROM_MASK 0x0fff
#define DSP_DRAM_BYTE_SIZE 0x2000
#define DSP_DRAM_SIZE 0x1000
#define DSP_DRAM_MASK 0x0fff
#define DSP_COEF_BYTE_SIZE 0x2000
#define DSP_COEF_SIZE 0x1000
#define DSP_COEF_MASK 0x0fff
#define DSP_RESET_VECTOR 0x8000
#define DSP_STACK_DEPTH 0x20
#define DSP_STACK_MASK 0x1f
#define DSP_CR_IMEM 2
#define DSP_CR_DMEM 0
#define DSP_CR_TO_CPU 1
#define DSP_CR_FROM_CPU 0
// Register table taken from libasnd
#define DSP_REG_AR0 0x00 // address registers
#define DSP_REG_AR1 0x01
#define DSP_REG_AR2 0x02
#define DSP_REG_AR3 0x03
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
#define DSP_REG_IX1 0x05
#define DSP_REG_IX2 0x06
#define DSP_REG_IX3 0x07
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
#define DSP_REG_WR1 0x09
#define DSP_REG_WR2 0x0a
#define DSP_REG_WR3 0x0b
#define DSP_REG_ST0 0x0c // stacks.
#define DSP_REG_ST1 0x0d
#define DSP_REG_ST2 0x0e
#define DSP_REG_ST3 0x0f
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
#define DSP_REG_SR 0x13
#define DSP_REG_PRODL 0x14 // product.
#define DSP_REG_PRODM 0x15
#define DSP_REG_PRODH 0x16
#define DSP_REG_PRODM2 0x17
#define DSP_REG_AXL0 0x18
#define DSP_REG_AXL1 0x19
#define DSP_REG_AXH0 0x1a
#define DSP_REG_AXH1 0x1b
#define DSP_REG_ACC0 0x1c // accumulator (global)
#define DSP_REG_ACC1 0x1d
#define DSP_REG_ACL0 0x1c // Low accumulator
#define DSP_REG_ACL1 0x1d
#define DSP_REG_ACM0 0x1e // Mid accumulator
#define DSP_REG_ACM1 0x1f
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
// Hardware registers address
#define DSP_COEF_A1_0 0xa0
#define DSP_DSMAH 0xce
#define DSP_DSMAL 0xcf
#define DSP_DSCR 0xc9 // DSP DMA Control Reg
#define DSP_DSPA 0xcd // DSP DMA Block Length
#define DSP_DSBL 0xcb // DSP DMA DMEM Address
#define DSP_DSMAH 0xce // DSP DMA Mem Address H
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
#define DSP_FORMAT 0xd1
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
#define DSP_ACSAH 0xd4
#define DSP_ACSAL 0xd5
#define DSP_ACEAH 0xd6
#define DSP_ACEAL 0xd7
#define DSP_ACCAH 0xd8
#define DSP_ACCAL 0xd9
#define DSP_PRED_SCALE 0xda
#define DSP_YN1 0xdb
#define DSP_YN2 0xdc
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
#define DSP_GAIN 0xde
#define DSP_DIRQ 0xfb // DSP Irq Rest
#define DSP_DMBH 0xfc // DSP Mailbox H
#define DSP_DMBL 0xfd // DSP Mailbox L
#define DSP_CMBH 0xfe // CPU Mailbox H
#define DSP_CMBL 0xff // CPU Mailbox L
#define DMA_TO_DSP 0
#define DMA_TO_CPU 1
// Stacks
#define DSP_STACK_C 0
#define DSP_STACK_D 1
// cr (Not g_dsp.r[CR]) bits
// See HW/DSP.cpp.
#define CR_HALT 0x0004
#define CR_EXTERNAL_INT 0x0002
// SR bits
#define SR_CARRY 0x0001
#define SR_2 0x0002 // overflow???
#define SR_ARITH_ZERO 0x0004
#define SR_SIGN 0x0008
#define SR_10 0x0010 // seem to be set by tst
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
#define SR_LOGIC_ZERO 0x0040
#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
// This should be the bits affected by CMP. Does not include logic zero.
#define SR_CMP_MASK 0x3f
// exceptions vector
#define EXP_RESET 0 // 0x0000
#define EXP_STOVF 1 // 0x0002 stack under/over flow
#define EXP_4 2 // 0x0004
#define EXP_6 3 // 0x0006
#define EXP_8 4 // 0x0008
#define EXP_ACCOV 5 // 0x000a accelerator address overflow
#define EXP_c 6 // 0x000c
#define EXP_INT 7 // 0x000e external int? (mail?)
struct SDSP
{
u16 r[32];
u16 pc;
#if PROFILE
u16 err_pc;
#endif
// This is NOT the same cr as r[DSP_REG_CR].
// This register is shared with the main emulation, see DSP.cpp
// The plugin has control over 0x0C07 of this reg.
// Bits are defined in a struct in DSP.cpp.
u16 cr;
u8 reg_stack_ptr[4];
u8 exceptions; // pending exceptions?
bool exception_in_progress_hack; // is this the same as "exception enabled"?
// Let's make stack depth 32 for now. The real DSP has different depths
// for the different stacks, but it would be strange if any ucode relied on stack
// overflows since on the DSP, when the stack overflows, you're screwed.
u16 reg_stack[4][DSP_STACK_DEPTH];
// For debugging.
u32 iram_crc;
u64 step_counter;
// When state saving, all of the above can just be memcpy'd into the save state.
// The below needs special handling.
u16 *iram;
u16 *dram;
u16 *irom;
u16 *coef;
// This one doesn't really belong here.
u8 *cpu_ram;
};
extern SDSP g_dsp;
extern DSPBreakpoints dsp_breakpoints;
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
void DSPCore_Reset();
void DSPCore_Shutdown(); // Frees all allocated memory.
void DSPCore_CheckExternalInterrupt();
void DSPCore_CheckExceptions();
// sets a flag in the pending exception register.
void DSPCore_SetException(u8 level);
enum DSPCoreState
{
DSPCORE_RUNNING = 0,
DSPCORE_STEPPING = 1,
};
int DSPCore_RunCycles(int cycles);
// These are meant to be called from the UI thread.
void DSPCore_SetState(DSPCoreState new_state);
DSPCoreState DSPCore_GetState();
void DSPCore_Step();
#endif // _DSPCORE_H
/*====================================================================
filename: DSPCore.h
project: GCemu
created: 2004-6-18
mail: duddie@walla.com
Copyright (c) 2005 Duddie & Tratax
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#ifndef _DSPCORE_H
#define _DSPCORE_H
#include "DSPBreakpoints.h"
#define DSP_IRAM_BYTE_SIZE 0x2000
#define DSP_IRAM_SIZE 0x1000
#define DSP_IRAM_MASK 0x0fff
#define DSP_IROM_BYTE_SIZE 0x2000
#define DSP_IROM_SIZE 0x1000
#define DSP_IROM_MASK 0x0fff
#define DSP_DRAM_BYTE_SIZE 0x2000
#define DSP_DRAM_SIZE 0x1000
#define DSP_DRAM_MASK 0x0fff
#define DSP_COEF_BYTE_SIZE 0x2000
#define DSP_COEF_SIZE 0x1000
#define DSP_COEF_MASK 0x0fff
#define DSP_RESET_VECTOR 0x8000
#define DSP_STACK_DEPTH 0x20
#define DSP_STACK_MASK 0x1f
#define DSP_CR_IMEM 2
#define DSP_CR_DMEM 0
#define DSP_CR_TO_CPU 1
#define DSP_CR_FROM_CPU 0
// Register table taken from libasnd
#define DSP_REG_AR0 0x00 // address registers
#define DSP_REG_AR1 0x01
#define DSP_REG_AR2 0x02
#define DSP_REG_AR3 0x03
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
#define DSP_REG_IX1 0x05
#define DSP_REG_IX2 0x06
#define DSP_REG_IX3 0x07
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
#define DSP_REG_WR1 0x09
#define DSP_REG_WR2 0x0a
#define DSP_REG_WR3 0x0b
#define DSP_REG_ST0 0x0c // stacks.
#define DSP_REG_ST1 0x0d
#define DSP_REG_ST2 0x0e
#define DSP_REG_ST3 0x0f
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
#define DSP_REG_SR 0x13
#define DSP_REG_PRODL 0x14 // product.
#define DSP_REG_PRODM 0x15
#define DSP_REG_PRODH 0x16
#define DSP_REG_PRODM2 0x17
#define DSP_REG_AXL0 0x18
#define DSP_REG_AXL1 0x19
#define DSP_REG_AXH0 0x1a
#define DSP_REG_AXH1 0x1b
#define DSP_REG_ACC0 0x1c // accumulator (global)
#define DSP_REG_ACC1 0x1d
#define DSP_REG_ACL0 0x1c // Low accumulator
#define DSP_REG_ACL1 0x1d
#define DSP_REG_ACM0 0x1e // Mid accumulator
#define DSP_REG_ACM1 0x1f
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
// Hardware registers address
#define DSP_COEF_A1_0 0xa0
#define DSP_DSMAH 0xce
#define DSP_DSMAL 0xcf
#define DSP_DSCR 0xc9 // DSP DMA Control Reg
#define DSP_DSPA 0xcd // DSP DMA Block Length
#define DSP_DSBL 0xcb // DSP DMA DMEM Address
#define DSP_DSMAH 0xce // DSP DMA Mem Address H
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
#define DSP_FORMAT 0xd1
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
#define DSP_ACSAH 0xd4
#define DSP_ACSAL 0xd5
#define DSP_ACEAH 0xd6
#define DSP_ACEAL 0xd7
#define DSP_ACCAH 0xd8
#define DSP_ACCAL 0xd9
#define DSP_PRED_SCALE 0xda
#define DSP_YN1 0xdb
#define DSP_YN2 0xdc
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
#define DSP_GAIN 0xde
#define DSP_DIRQ 0xfb // DSP Irq Rest
#define DSP_DMBH 0xfc // DSP Mailbox H
#define DSP_DMBL 0xfd // DSP Mailbox L
#define DSP_CMBH 0xfe // CPU Mailbox H
#define DSP_CMBL 0xff // CPU Mailbox L
#define DMA_TO_DSP 0
#define DMA_TO_CPU 1
// Stacks
#define DSP_STACK_C 0
#define DSP_STACK_D 1
// cr (Not g_dsp.r[CR]) bits
// See HW/DSP.cpp.
#define CR_HALT 0x0004
#define CR_EXTERNAL_INT 0x0002
// SR bits
#define SR_CARRY 0x0001
#define SR_2 0x0002 // overflow???
#define SR_ARITH_ZERO 0x0004
#define SR_SIGN 0x0008
#define SR_10 0x0010 // seem to be set by tst
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
#define SR_LOGIC_ZERO 0x0040
#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
// This should be the bits affected by CMP. Does not include logic zero.
#define SR_CMP_MASK 0x3f
// exceptions vector
#define EXP_RESET 0 // 0x0000
#define EXP_STOVF 1 // 0x0002 stack under/over flow
#define EXP_4 2 // 0x0004
#define EXP_6 3 // 0x0006
#define EXP_8 4 // 0x0008
#define EXP_ACCOV 5 // 0x000a accelerator address overflow
#define EXP_c 6 // 0x000c
#define EXP_INT 7 // 0x000e external int? (mail?)
struct SDSP
{
u16 r[32];
u16 pc;
#if PROFILE
u16 err_pc;
#endif
// This is NOT the same cr as r[DSP_REG_CR].
// This register is shared with the main emulation, see DSP.cpp
// The plugin has control over 0x0C07 of this reg.
// Bits are defined in a struct in DSP.cpp.
u16 cr;
u8 reg_stack_ptr[4];
u8 exceptions; // pending exceptions?
bool exception_in_progress_hack; // is this the same as "exception enabled"?
// Let's make stack depth 32 for now. The real DSP has different depths
// for the different stacks, but it would be strange if any ucode relied on stack
// overflows since on the DSP, when the stack overflows, you're screwed.
u16 reg_stack[4][DSP_STACK_DEPTH];
// For debugging.
u32 iram_crc;
u64 step_counter;
// When state saving, all of the above can just be memcpy'd into the save state.
// The below needs special handling.
u16 *iram;
u16 *dram;
u16 *irom;
u16 *coef;
// This one doesn't really belong here.
u8 *cpu_ram;
};
extern SDSP g_dsp;
extern DSPBreakpoints dsp_breakpoints;
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
void DSPCore_Reset();
void DSPCore_Shutdown(); // Frees all allocated memory.
void DSPCore_CheckExternalInterrupt();
void DSPCore_CheckExceptions();
// sets a flag in the pending exception register.
void DSPCore_SetException(u8 level);
enum DSPCoreState
{
DSPCORE_RUNNING = 0,
DSPCORE_STEPPING = 1,
};
int DSPCore_RunCycles(int cycles);
// These are meant to be called from the UI thread.
void DSPCore_SetState(DSPCoreState new_state);
DSPCoreState DSPCore_GetState();
void DSPCore_Step();
#endif // _DSPCORE_H
+35 -35
View File
@@ -1,35 +1,35 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPHOST_H
#define _DSPHOST_H
// The user of the DSPCore library must supply a few functions so that the
// emulation core can access the environment it runs in. If the emulation
// core isn't used, for example in an asm/disasm tool, then most of these
// can be stubbed out.
#define DEBUG_EXP 1
u8 DSPHost_ReadHostMemory(u32 addr);
void DSPHost_WriteHostMemory(u8 value, u32 addr);
bool DSPHost_OnThread();
bool DSPHost_Running();
void DSPHost_InterruptRequest();
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
void DSPHost_UpdateDebugger();
#endif
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPHOST_H
#define _DSPHOST_H
// The user of the DSPCore library must supply a few functions so that the
// emulation core can access the environment it runs in. If the emulation
// core isn't used, for example in an asm/disasm tool, then most of these
// can be stubbed out.
#define DEBUG_EXP 1
u8 DSPHost_ReadHostMemory(u32 addr);
void DSPHost_WriteHostMemory(u8 value, u32 addr);
bool DSPHost_OnThread();
bool DSPHost_Running();
void DSPHost_InterruptRequest();
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
void DSPHost_UpdateDebugger();
#endif
+140 -140
View File
@@ -1,140 +1,140 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
// HELPER FUNCTIONS
#include "DSPIntCCUtil.h"
#include "DSPCore.h"
#include "DSPInterpreter.h"
namespace DSPInterpreter {
void Update_SR_Register64(s64 _Value)
{
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
if (_Value < 0)
{
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
}
if (_Value == 0)
{
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
}
// weird
if ((_Value >> 62) == 0)
{
g_dsp.r[DSP_REG_SR] |= 0x20;
}
}
void Update_SR_Register16(s16 _Value)
{
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
if (_Value < 0)
{
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
}
if (_Value == 0)
{
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
}
// weird
if ((_Value >> 14) == 0)
{
g_dsp.r[DSP_REG_SR] |= 0x20;
}
}
void Update_SR_LZ(s64 value) {
if (value == 0)
{
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
}
else
{
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
}
}
int GetMultiplyModifier()
{
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
return 1;
else
return 2;
}
inline bool isCarry() {
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
}
inline bool isSign() {
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
}
inline bool isZero() {
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
}
//see gdsp_registers.h for flags
bool CheckCondition(u8 _Condition)
{
switch (_Condition & 0xf)
{
case 0x0: //NS - NOT SIGN
return !isSign();
case 0x1: // S - SIGN
return isSign();
case 0x2: // G - GREATER
return !isSign() && !isZero();
case 0x3: // LE - LESS EQUAL
return isSign() || isZero();
case 0x4: // NZ - NOT ZERO
return !isZero();
case 0x5: // Z - ZERO
return isZero();
case 0x6: // L - LESS
// Should be that once we set 0x01
return !isCarry();
// if (isSign())
case 0x7: // GE - GREATER EQUAL
// Should be that once we set 0x01
return isCarry();
// if (! isSign() || isZero())
case 0xc: // LNZ - LOGIC NOT ZERO
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
case 0xd: // LZ - LOGIC ZERO
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
case 0xf: // Empty - always true.
return true;
default:
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
return false;
}
}
} // namespace
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
// HELPER FUNCTIONS
#include "DSPIntCCUtil.h"
#include "DSPCore.h"
#include "DSPInterpreter.h"
namespace DSPInterpreter {
void Update_SR_Register64(s64 _Value)
{
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
if (_Value < 0)
{
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
}
if (_Value == 0)
{
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
}
// weird
if ((_Value >> 62) == 0)
{
g_dsp.r[DSP_REG_SR] |= 0x20;
}
}
void Update_SR_Register16(s16 _Value)
{
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
if (_Value < 0)
{
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
}
if (_Value == 0)
{
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
}
// weird
if ((_Value >> 14) == 0)
{
g_dsp.r[DSP_REG_SR] |= 0x20;
}
}
void Update_SR_LZ(s64 value) {
if (value == 0)
{
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
}
else
{
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
}
}
int GetMultiplyModifier()
{
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
return 1;
else
return 2;
}
inline bool isCarry() {
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
}
inline bool isSign() {
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
}
inline bool isZero() {
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
}
//see gdsp_registers.h for flags
bool CheckCondition(u8 _Condition)
{
switch (_Condition & 0xf)
{
case 0x0: //NS - NOT SIGN
return !isSign();
case 0x1: // S - SIGN
return isSign();
case 0x2: // G - GREATER
return !isSign() && !isZero();
case 0x3: // LE - LESS EQUAL
return isSign() || isZero();
case 0x4: // NZ - NOT ZERO
return !isZero();
case 0x5: // Z - ZERO
return isZero();
case 0x6: // L - LESS
// Should be that once we set 0x01
return !isCarry();
// if (isSign())
case 0x7: // GE - GREATER EQUAL
// Should be that once we set 0x01
return isCarry();
// if (! isSign() || isZero())
case 0xc: // LNZ - LOGIC NOT ZERO
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
case 0xd: // LZ - LOGIC ZERO
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
case 0xf: // Empty - always true.
return true;
default:
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
return false;
}
}
} // namespace
+39 -39
View File
@@ -1,39 +1,39 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
#ifndef _GDSP_CONDITION_CODES_H
#define _GDSP_CONDITION_CODES_H
// Anything to do with SR and conditions goes here.
#include "Common.h"
namespace DSPInterpreter {
bool CheckCondition(u8 _Condition);
int GetMultiplyModifier();
void Update_SR_Register16(s16 _Value);
void Update_SR_Register64(s64 _Value);
void Update_SR_LZ(s64 value);
} // namespace
#endif // _GDSP_CONDITION_CODES_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
#ifndef _GDSP_CONDITION_CODES_H
#define _GDSP_CONDITION_CODES_H
// Anything to do with SR and conditions goes here.
#include "Common.h"
namespace DSPInterpreter {
bool CheckCondition(u8 _Condition);
int GetMultiplyModifier();
void Update_SR_Register16(s16 _Value);
void Update_SR_Register64(s64 _Value);
void Update_SR_LZ(s64 value);
} // namespace
#endif // _GDSP_CONDITION_CODES_H
+171 -171
View File
@@ -1,171 +1,171 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPINTERPRETER_H
#define _DSPINTERPRETER_H
#include "DSPTables.h"
#define DSP_REG_MASK 0x1f
namespace DSPInterpreter {
void Step();
void Run();
// If these simply return the same number of cycles as was passed into them,
// chances are that the DSP is halted.
// The difference between them is that the debug one obeys breakpoints.
int RunCycles(int cycles);
int RunCyclesDebug(int cycles);
void Stop();
void WriteCR(u16 val);
u16 ReadCR();
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
// All the opcode functions.
void unknown(const UDSPInstruction& opc);
void call(const UDSPInstruction& opc);
void callr(const UDSPInstruction& opc);
void ifcc(const UDSPInstruction& opc);
void jcc(const UDSPInstruction& opc);
void jmprcc(const UDSPInstruction& opc);
void ret(const UDSPInstruction& opc);
void halt(const UDSPInstruction& opc);
void loop(const UDSPInstruction& opc);
void loopi(const UDSPInstruction& opc);
void bloop(const UDSPInstruction& opc);
void bloopi(const UDSPInstruction& opc);
void mrr(const UDSPInstruction& opc);
void lrr(const UDSPInstruction& opc);
void lrrd(const UDSPInstruction& opc);
void lrri(const UDSPInstruction& opc);
void lrrn(const UDSPInstruction& opc);
void srr(const UDSPInstruction& opc);
void srrd(const UDSPInstruction& opc);
void srri(const UDSPInstruction& opc);
void srrn(const UDSPInstruction& opc);
void lri(const UDSPInstruction& opc);
void lris(const UDSPInstruction& opc);
void lr(const UDSPInstruction& opc);
void sr(const UDSPInstruction& opc);
void si(const UDSPInstruction& opc);
void tstaxh(const UDSPInstruction& opc);
void clr(const UDSPInstruction& opc);
void clrl(const UDSPInstruction& opc);
void clrp(const UDSPInstruction& opc);
void mulc(const UDSPInstruction& opc);
void cmpar(const UDSPInstruction& opc);
void cmp(const UDSPInstruction& opc);
void tst(const UDSPInstruction& opc);
void addaxl(const UDSPInstruction& opc);
void addarn(const UDSPInstruction& opc);
void mulcac(const UDSPInstruction& opc);
void movr(const UDSPInstruction& opc);
void movax(const UDSPInstruction& opc);
void xorr(const UDSPInstruction& opc);
void andr(const UDSPInstruction& opc);
void andc(const UDSPInstruction& opc);
void orr(const UDSPInstruction& opc);
void orc(const UDSPInstruction& opc);
void orf(const UDSPInstruction& opc);
void add(const UDSPInstruction& opc);
void addp(const UDSPInstruction& opc);
void cmpis(const UDSPInstruction& opc);
void addpaxz(const UDSPInstruction& opc);
void movpz(const UDSPInstruction& opc);
void decm(const UDSPInstruction& opc);
void dec(const UDSPInstruction& opc);
void inc(const UDSPInstruction& opc);
void incm(const UDSPInstruction& opc);
void neg(const UDSPInstruction& opc);
void addax(const UDSPInstruction& opc);
void addr(const UDSPInstruction& opc);
void subr(const UDSPInstruction& opc);
void subp(const UDSPInstruction& opc);
void subax(const UDSPInstruction& opc);
void addis(const UDSPInstruction& opc);
void addi(const UDSPInstruction& opc);
void lsl16(const UDSPInstruction& opc);
void madd(const UDSPInstruction& opc);
void msub(const UDSPInstruction& opc);
void lsr16(const UDSPInstruction& opc);
void asr16(const UDSPInstruction& opc);
void lsl(const UDSPInstruction& opc);
void lsr(const UDSPInstruction& opc);
void asl(const UDSPInstruction& opc);
void asr(const UDSPInstruction& opc);
void lsrn(const UDSPInstruction& opc);
void asrn(const UDSPInstruction& opc);
void dar(const UDSPInstruction& opc);
void iar(const UDSPInstruction& opc);
void sbclr(const UDSPInstruction& opc);
void sbset(const UDSPInstruction& opc);
void mov(const UDSPInstruction& opc);
void movp(const UDSPInstruction& opc);
void mul(const UDSPInstruction& opc);
void mulac(const UDSPInstruction& opc);
void mulmv(const UDSPInstruction& opc);
void mulmvz(const UDSPInstruction& opc);
void mulx(const UDSPInstruction& opc);
void mulxac(const UDSPInstruction& opc);
void mulxmv(const UDSPInstruction& opc);
void mulxmvz(const UDSPInstruction& opc);
void mulcmvz(const UDSPInstruction& opc);
void mulcmv(const UDSPInstruction& opc);
void movnp(const UDSPInstruction& opc);
void sub(const UDSPInstruction& opc);
void maddx(const UDSPInstruction& opc);
void msubx(const UDSPInstruction& opc);
void maddc(const UDSPInstruction& opc);
void msubc(const UDSPInstruction& opc);
void srs(const UDSPInstruction& opc);
void lrs(const UDSPInstruction& opc);
void nx(const UDSPInstruction& opc);
void cmpi(const UDSPInstruction& opc);
void rti(const UDSPInstruction& opc);
void ilrr(const UDSPInstruction& opc);
void ilrrd(const UDSPInstruction& opc);
void ilrri(const UDSPInstruction& opc);
void ilrrn(const UDSPInstruction& opc);
void andcf(const UDSPInstruction& opc);
void andf(const UDSPInstruction& opc);
void xori(const UDSPInstruction& opc);
void andi(const UDSPInstruction& opc);
void ori(const UDSPInstruction& opc);
// FIXME inside
void srbith(const UDSPInstruction& opc);
// END OF FIXMEs
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
void tstaxl(const UDSPInstruction& opc);
// The mysterious a100
// END OF UNIMPLEMENTED
// Helpers
inline void tsta(int reg);
} // namespace
#endif // _DSPINTERPRETER_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPINTERPRETER_H
#define _DSPINTERPRETER_H
#include "DSPTables.h"
#define DSP_REG_MASK 0x1f
namespace DSPInterpreter {
void Step();
void Run();
// If these simply return the same number of cycles as was passed into them,
// chances are that the DSP is halted.
// The difference between them is that the debug one obeys breakpoints.
int RunCycles(int cycles);
int RunCyclesDebug(int cycles);
void Stop();
void WriteCR(u16 val);
u16 ReadCR();
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
// All the opcode functions.
void unknown(const UDSPInstruction& opc);
void call(const UDSPInstruction& opc);
void callr(const UDSPInstruction& opc);
void ifcc(const UDSPInstruction& opc);
void jcc(const UDSPInstruction& opc);
void jmprcc(const UDSPInstruction& opc);
void ret(const UDSPInstruction& opc);
void halt(const UDSPInstruction& opc);
void loop(const UDSPInstruction& opc);
void loopi(const UDSPInstruction& opc);
void bloop(const UDSPInstruction& opc);
void bloopi(const UDSPInstruction& opc);
void mrr(const UDSPInstruction& opc);
void lrr(const UDSPInstruction& opc);
void lrrd(const UDSPInstruction& opc);
void lrri(const UDSPInstruction& opc);
void lrrn(const UDSPInstruction& opc);
void srr(const UDSPInstruction& opc);
void srrd(const UDSPInstruction& opc);
void srri(const UDSPInstruction& opc);
void srrn(const UDSPInstruction& opc);
void lri(const UDSPInstruction& opc);
void lris(const UDSPInstruction& opc);
void lr(const UDSPInstruction& opc);
void sr(const UDSPInstruction& opc);
void si(const UDSPInstruction& opc);
void tstaxh(const UDSPInstruction& opc);
void clr(const UDSPInstruction& opc);
void clrl(const UDSPInstruction& opc);
void clrp(const UDSPInstruction& opc);
void mulc(const UDSPInstruction& opc);
void cmpar(const UDSPInstruction& opc);
void cmp(const UDSPInstruction& opc);
void tst(const UDSPInstruction& opc);
void addaxl(const UDSPInstruction& opc);
void addarn(const UDSPInstruction& opc);
void mulcac(const UDSPInstruction& opc);
void movr(const UDSPInstruction& opc);
void movax(const UDSPInstruction& opc);
void xorr(const UDSPInstruction& opc);
void andr(const UDSPInstruction& opc);
void andc(const UDSPInstruction& opc);
void orr(const UDSPInstruction& opc);
void orc(const UDSPInstruction& opc);
void orf(const UDSPInstruction& opc);
void add(const UDSPInstruction& opc);
void addp(const UDSPInstruction& opc);
void cmpis(const UDSPInstruction& opc);
void addpaxz(const UDSPInstruction& opc);
void movpz(const UDSPInstruction& opc);
void decm(const UDSPInstruction& opc);
void dec(const UDSPInstruction& opc);
void inc(const UDSPInstruction& opc);
void incm(const UDSPInstruction& opc);
void neg(const UDSPInstruction& opc);
void addax(const UDSPInstruction& opc);
void addr(const UDSPInstruction& opc);
void subr(const UDSPInstruction& opc);
void subp(const UDSPInstruction& opc);
void subax(const UDSPInstruction& opc);
void addis(const UDSPInstruction& opc);
void addi(const UDSPInstruction& opc);
void lsl16(const UDSPInstruction& opc);
void madd(const UDSPInstruction& opc);
void msub(const UDSPInstruction& opc);
void lsr16(const UDSPInstruction& opc);
void asr16(const UDSPInstruction& opc);
void lsl(const UDSPInstruction& opc);
void lsr(const UDSPInstruction& opc);
void asl(const UDSPInstruction& opc);
void asr(const UDSPInstruction& opc);
void lsrn(const UDSPInstruction& opc);
void asrn(const UDSPInstruction& opc);
void dar(const UDSPInstruction& opc);
void iar(const UDSPInstruction& opc);
void sbclr(const UDSPInstruction& opc);
void sbset(const UDSPInstruction& opc);
void mov(const UDSPInstruction& opc);
void movp(const UDSPInstruction& opc);
void mul(const UDSPInstruction& opc);
void mulac(const UDSPInstruction& opc);
void mulmv(const UDSPInstruction& opc);
void mulmvz(const UDSPInstruction& opc);
void mulx(const UDSPInstruction& opc);
void mulxac(const UDSPInstruction& opc);
void mulxmv(const UDSPInstruction& opc);
void mulxmvz(const UDSPInstruction& opc);
void mulcmvz(const UDSPInstruction& opc);
void mulcmv(const UDSPInstruction& opc);
void movnp(const UDSPInstruction& opc);
void sub(const UDSPInstruction& opc);
void maddx(const UDSPInstruction& opc);
void msubx(const UDSPInstruction& opc);
void maddc(const UDSPInstruction& opc);
void msubc(const UDSPInstruction& opc);
void srs(const UDSPInstruction& opc);
void lrs(const UDSPInstruction& opc);
void nx(const UDSPInstruction& opc);
void cmpi(const UDSPInstruction& opc);
void rti(const UDSPInstruction& opc);
void ilrr(const UDSPInstruction& opc);
void ilrrd(const UDSPInstruction& opc);
void ilrri(const UDSPInstruction& opc);
void ilrrn(const UDSPInstruction& opc);
void andcf(const UDSPInstruction& opc);
void andf(const UDSPInstruction& opc);
void xori(const UDSPInstruction& opc);
void andi(const UDSPInstruction& opc);
void ori(const UDSPInstruction& opc);
// FIXME inside
void srbith(const UDSPInstruction& opc);
// END OF FIXMEs
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
void tstaxl(const UDSPInstruction& opc);
// The mysterious a100
// END OF UNIMPLEMENTED
// Helpers
inline void tsta(int reg);
} // namespace
#endif // _DSPINTERPRETER_H
+22 -22
View File
@@ -1,22 +1,22 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPJit.h"
namespace DSPJit {
};
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPJit.h"
namespace DSPJit {
};
+28 -28
View File
@@ -1,28 +1,28 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPJIT_H
#define _DSPJIT_H
namespace DSPJit {
// TODO(XK): Fill
} // namespace
#endif // _DSPJIT_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPJIT_H
#define _DSPJIT_H
namespace DSPJit {
// TODO(XK): Fill
} // namespace
#endif // _DSPJIT_H
File diff suppressed because it is too large Load Diff
+168 -168
View File
@@ -1,168 +1,168 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
#ifndef _DSPTABLES_H
#define _DSPTABLES_H
#include "Common.h"
// The non-ADDR ones that end with _D are the opposite one - if the bit specify
// ACC0, then ACC_D will be ACC1.
// The values of these are very important.
// For the reg ones, the value >> 8 is the base register.
// & 0x80 means it's a "D".
enum partype_t
{
P_NONE = 0x0000,
P_VAL = 0x0001,
P_IMM = 0x0002,
P_MEM = 0x0003,
P_STR = 0x0004,
P_ADDR_I = 0x0005,
P_ADDR_D = 0x0006,
P_REG = 0x8000,
P_REG04 = P_REG | 0x0400, // IX
P_REG08 = P_REG | 0x0800,
P_REG18 = P_REG | 0x1800,
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
P_REG19 = P_REG | 0x1900,
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
P_REG1A = P_REG | 0x1a80,
P_REG1C = P_REG | 0x1c00,
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
P_ACC_D = P_REG | 0x1c80,
P_ACCL = P_REG | 0x1c00, // used for low part of accum
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
// The following are not in gcdsptool
P_ACCM_D = P_REG | 0x1e80,
P_ACC = P_REG | 0x2000, // used for full accum.
P_AX = P_REG | 0x2200,
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
P_REF = P_REG | 0x4000,
P_PRG = P_REF | P_REG,
// The following seem like junk:
// P_REG10 = P_REG | 0x1000,
// P_AX_D = P_REG | 0x2280,
};
#define P_EXT 0x80
#define OPTABLE_SIZE 65536
union UDSPInstruction
{
u16 hex;
UDSPInstruction(u16 _hex) { hex = _hex; }
UDSPInstruction() { hex = 0; }
struct
{
signed shift : 6;
unsigned negating : 1;
unsigned arithmetic : 1;
unsigned areg : 1;
unsigned op : 7;
};
struct
{
unsigned ushift : 6;
};
// TODO: Figure out more instruction structures (add structs here)
};
typedef void (*dspInstFunc)(const UDSPInstruction&);
struct param2_t
{
partype_t type;
u8 size;
u8 loc;
s8 lshift;
u16 mask;
};
typedef struct
{
const char *name;
u16 opcode;
u16 opcode_mask;
dspInstFunc interpFunc;
dspInstFunc jitFunc;
u8 size;
u8 param_count;
param2_t params[8];
dspInstFunc prologue;
dspInstFunc epilogue;
} DSPOPCTemplate;
typedef DSPOPCTemplate opc_t;
// Opcodes
extern const DSPOPCTemplate opcodes[];
extern const int opcodes_size;
extern const DSPOPCTemplate opcodes_ext[];
extern const int opcodes_ext_size;
extern u8 opSize[OPTABLE_SIZE];
extern const DSPOPCTemplate cw;
extern dspInstFunc opTable[];
extern dspInstFunc prologueTable[OPTABLE_SIZE];
extern dspInstFunc epilogueTable[OPTABLE_SIZE];
// Predefined labels
struct pdlabel_t
{
u16 addr;
const char* name;
const char* description;
};
extern const pdlabel_t regnames[];
extern const pdlabel_t pdlabels[];
extern const u32 pdlabels_size;
const char *pdname(u16 val);
const char *pdregname(int val);
const char *pdregnamelong(int val);
void InitInstructionTable();
inline void ExecuteInstruction(const UDSPInstruction& inst)
{
// TODO: Move the prologuetable calls into the relevant instructions themselves.
// Better not do things like this until things work correctly though.
if (prologueTable[inst.hex])
prologueTable[inst.hex](inst);
opTable[inst.hex](inst);
if (epilogueTable[inst.hex])
epilogueTable[inst.hex](inst);
}
// This one's pretty slow, try to use it only at init or seldomly.
// returns NULL if no matching instruction.
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
#endif // _DSPTABLES_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
#ifndef _DSPTABLES_H
#define _DSPTABLES_H
#include "Common.h"
// The non-ADDR ones that end with _D are the opposite one - if the bit specify
// ACC0, then ACC_D will be ACC1.
// The values of these are very important.
// For the reg ones, the value >> 8 is the base register.
// & 0x80 means it's a "D".
enum partype_t
{
P_NONE = 0x0000,
P_VAL = 0x0001,
P_IMM = 0x0002,
P_MEM = 0x0003,
P_STR = 0x0004,
P_ADDR_I = 0x0005,
P_ADDR_D = 0x0006,
P_REG = 0x8000,
P_REG04 = P_REG | 0x0400, // IX
P_REG08 = P_REG | 0x0800,
P_REG18 = P_REG | 0x1800,
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
P_REG19 = P_REG | 0x1900,
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
P_REG1A = P_REG | 0x1a80,
P_REG1C = P_REG | 0x1c00,
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
P_ACC_D = P_REG | 0x1c80,
P_ACCL = P_REG | 0x1c00, // used for low part of accum
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
// The following are not in gcdsptool
P_ACCM_D = P_REG | 0x1e80,
P_ACC = P_REG | 0x2000, // used for full accum.
P_AX = P_REG | 0x2200,
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
P_REF = P_REG | 0x4000,
P_PRG = P_REF | P_REG,
// The following seem like junk:
// P_REG10 = P_REG | 0x1000,
// P_AX_D = P_REG | 0x2280,
};
#define P_EXT 0x80
#define OPTABLE_SIZE 65536
union UDSPInstruction
{
u16 hex;
UDSPInstruction(u16 _hex) { hex = _hex; }
UDSPInstruction() { hex = 0; }
struct
{
signed shift : 6;
unsigned negating : 1;
unsigned arithmetic : 1;
unsigned areg : 1;
unsigned op : 7;
};
struct
{
unsigned ushift : 6;
};
// TODO: Figure out more instruction structures (add structs here)
};
typedef void (*dspInstFunc)(const UDSPInstruction&);
struct param2_t
{
partype_t type;
u8 size;
u8 loc;
s8 lshift;
u16 mask;
};
typedef struct
{
const char *name;
u16 opcode;
u16 opcode_mask;
dspInstFunc interpFunc;
dspInstFunc jitFunc;
u8 size;
u8 param_count;
param2_t params[8];
dspInstFunc prologue;
dspInstFunc epilogue;
} DSPOPCTemplate;
typedef DSPOPCTemplate opc_t;
// Opcodes
extern const DSPOPCTemplate opcodes[];
extern const int opcodes_size;
extern const DSPOPCTemplate opcodes_ext[];
extern const int opcodes_ext_size;
extern u8 opSize[OPTABLE_SIZE];
extern const DSPOPCTemplate cw;
extern dspInstFunc opTable[];
extern dspInstFunc prologueTable[OPTABLE_SIZE];
extern dspInstFunc epilogueTable[OPTABLE_SIZE];
// Predefined labels
struct pdlabel_t
{
u16 addr;
const char* name;
const char* description;
};
extern const pdlabel_t regnames[];
extern const pdlabel_t pdlabels[];
extern const u32 pdlabels_size;
const char *pdname(u16 val);
const char *pdregname(int val);
const char *pdregnamelong(int val);
void InitInstructionTable();
inline void ExecuteInstruction(const UDSPInstruction& inst)
{
// TODO: Move the prologuetable calls into the relevant instructions themselves.
// Better not do things like this until things work correctly though.
if (prologueTable[inst.hex])
prologueTable[inst.hex](inst);
opTable[inst.hex](inst);
if (epilogueTable[inst.hex])
epilogueTable[inst.hex](inst);
}
// This one's pretty slow, try to use it only at init or seldomly.
// returns NULL if no matching instruction.
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
#endif // _DSPTABLES_H
File diff suppressed because it is too large Load Diff
+249 -249
View File
@@ -1,249 +1,249 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h"
#include "DSPCore.h"
#include "DSPMemoryMap.h"
#include "DSPStacks.h"
#include "DSPIntCCUtil.h"
#include "DSPIntUtil.h"
namespace DSPInterpreter {
// Generic call implementation
// CALLcc addressA
// 0000 0010 1011 cccc
// aaaa aaaa aaaa aaaa
// Call function if condition cc has been met. Push program counter of
// instruction following "call" to $st0. Set program counter to address
// represented by value that follows this "call" instruction.
void call(const UDSPInstruction& opc)
{
// must be outside the if.
u16 dest = dsp_fetch_code();
if (CheckCondition(opc.hex & 0xf))
{
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
g_dsp.pc = dest;
}
}
// Generic callr implementation
// CALLRcc $R
// 0001 0111 rrr1 cccc
// Call function if condition cc has been met. Push program counter of
// instruction following "call" to call stack $st0. Set program counter to
// register $R.
void callr(const UDSPInstruction& opc)
{
if (CheckCondition(opc.hex & 0xf))
{
u8 reg = (opc.hex >> 5) & 0x7;
u16 addr = dsp_op_read_reg(reg);
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
g_dsp.pc = addr;
}
}
// Generic if implementation
// IFcc
// 0000 0010 0111 cccc
// Execute following opcode if the condition has been met.
void ifcc(const UDSPInstruction& opc)
{
if (!CheckCondition(opc.hex & 0xf))
{
// skip the next opcode - we have to lookup its size.
g_dsp.pc += opSize[dsp_peek_code()];
}
}
// Generic jmp implementation
// Jcc addressA
// 0000 0010 1001 cccc
// aaaa aaaa aaaa aaaa
// Jump to addressA if condition cc has been met. Set program counter to
// address represented by value that follows this "jmp" instruction.
void jcc(const UDSPInstruction& opc)
{
u16 dest = dsp_fetch_code();
if (CheckCondition(opc.hex & 0xf))
{
g_dsp.pc = dest;
}
}
// Generic jmpr implementation
// JMPcc $R
// 0001 0111 rrr0 cccc
// Jump to address; set program counter to a value from register $R.
void jmprcc(const UDSPInstruction& opc)
{
if (CheckCondition(opc.hex & 0xf))
{
u8 reg = (opc.hex >> 5) & 0x7;
g_dsp.pc = dsp_op_read_reg(reg);
}
}
// Generic ret implementation
// RETcc
// 0000 0010 1101 cccc
// Return from subroutine if condition cc has been met. Pops stored PC
// from call stack $st0 and sets $pc to this location.
void ret(const UDSPInstruction& opc)
{
if (CheckCondition(opc.hex & 0xf))
{
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
}
}
// RTI
// 0000 0010 1111 1111
// Return from exception. Pops stored status register $sr from data stack
// $st1 and program counter PC from call stack $st0 and sets $pc to this
// location.
void rti(const UDSPInstruction& opc)
{
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
g_dsp.exception_in_progress_hack = false;
}
// HALT
// 0000 0000 0020 0001
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
void halt(const UDSPInstruction& opc)
{
g_dsp.cr |= 0x4;
g_dsp.pc--;
}
// LOOP handling: Loop stack is used to control execution of repeated blocks of
// instructions. Whenever there is value on stack $st2 and current PC is equal
// value at $st2, then value at stack $st3 is decremented. If value is not zero
// then PC is modified with calue from call stack $st0. Otherwise values from
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
// continues at next opcode.
// LOOP $R
// 0000 0000 010r rrrr
// Repeatedly execute following opcode until counter specified by value
// from register $R reaches zero. Each execution decrement counter. Register
// $R remains unchanged. If register $R is set to zero at the beginning of loop
// then looped instruction will not get executed.
// Actually, this instruction simply prepares the loop stacks for the above.
// The looping hardware takes care of the rest.
void loop(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x1f;
u16 cnt = g_dsp.r[reg];
u16 loop_pc = g_dsp.pc;
if (cnt)
{
dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt);
}
}
// LOOPI #I
// 0001 0000 iiii iiii
// Repeatedly execute following opcode until counter specified by
// immediate value I reaches zero. Each execution decrement counter. If
// immediate value I is set to zero at the beginning of loop then looped
// instruction will not get executed.
// Actually, this instruction simply prepares the loop stacks for the above.
// The looping hardware takes care of the rest.
void loopi(const UDSPInstruction& opc)
{
u16 cnt = opc.hex & 0xff;
u16 loop_pc = g_dsp.pc;
if (cnt)
{
dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt);
}
}
// BLOOP $R, addrA
// 0000 0000 011r rrrr
// aaaa aaaa aaaa aaaa
// Repeatedly execute block of code starting at following opcode until
// counter specified by value from register $R reaches zero. Block ends at
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
// included in loop. Counter is pushed on loop stack $st3, end of block address
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
// Up to 4 nested loops is allowed.
void bloop(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x1f;
u16 cnt = g_dsp.r[reg];
u16 loop_pc = dsp_fetch_code();
if (cnt)
{
dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt);
}
else
{
g_dsp.pc = loop_pc;
g_dsp.pc += opSize[dsp_peek_code()];
}
}
// BLOOPI #I, addrA
// 0001 0001 iiii iiii
// aaaa aaaa aaaa aaaa
// Repeatedly execute block of code starting at following opcode until
// counter specified by immediate value I reaches zero. Block ends at specified
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
// nested loops is allowed.
void bloopi(const UDSPInstruction& opc)
{
u16 cnt = opc.hex & 0xff;
u16 loop_pc = dsp_fetch_code();
if (cnt)
{
dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt);
}
else
{
g_dsp.pc = loop_pc;
g_dsp.pc += opSize[dsp_peek_code()];
}
}
} // namespace
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h"
#include "DSPCore.h"
#include "DSPMemoryMap.h"
#include "DSPStacks.h"
#include "DSPIntCCUtil.h"
#include "DSPIntUtil.h"
namespace DSPInterpreter {
// Generic call implementation
// CALLcc addressA
// 0000 0010 1011 cccc
// aaaa aaaa aaaa aaaa
// Call function if condition cc has been met. Push program counter of
// instruction following "call" to $st0. Set program counter to address
// represented by value that follows this "call" instruction.
void call(const UDSPInstruction& opc)
{
// must be outside the if.
u16 dest = dsp_fetch_code();
if (CheckCondition(opc.hex & 0xf))
{
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
g_dsp.pc = dest;
}
}
// Generic callr implementation
// CALLRcc $R
// 0001 0111 rrr1 cccc
// Call function if condition cc has been met. Push program counter of
// instruction following "call" to call stack $st0. Set program counter to
// register $R.
void callr(const UDSPInstruction& opc)
{
if (CheckCondition(opc.hex & 0xf))
{
u8 reg = (opc.hex >> 5) & 0x7;
u16 addr = dsp_op_read_reg(reg);
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
g_dsp.pc = addr;
}
}
// Generic if implementation
// IFcc
// 0000 0010 0111 cccc
// Execute following opcode if the condition has been met.
void ifcc(const UDSPInstruction& opc)
{
if (!CheckCondition(opc.hex & 0xf))
{
// skip the next opcode - we have to lookup its size.
g_dsp.pc += opSize[dsp_peek_code()];
}
}
// Generic jmp implementation
// Jcc addressA
// 0000 0010 1001 cccc
// aaaa aaaa aaaa aaaa
// Jump to addressA if condition cc has been met. Set program counter to
// address represented by value that follows this "jmp" instruction.
void jcc(const UDSPInstruction& opc)
{
u16 dest = dsp_fetch_code();
if (CheckCondition(opc.hex & 0xf))
{
g_dsp.pc = dest;
}
}
// Generic jmpr implementation
// JMPcc $R
// 0001 0111 rrr0 cccc
// Jump to address; set program counter to a value from register $R.
void jmprcc(const UDSPInstruction& opc)
{
if (CheckCondition(opc.hex & 0xf))
{
u8 reg = (opc.hex >> 5) & 0x7;
g_dsp.pc = dsp_op_read_reg(reg);
}
}
// Generic ret implementation
// RETcc
// 0000 0010 1101 cccc
// Return from subroutine if condition cc has been met. Pops stored PC
// from call stack $st0 and sets $pc to this location.
void ret(const UDSPInstruction& opc)
{
if (CheckCondition(opc.hex & 0xf))
{
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
}
}
// RTI
// 0000 0010 1111 1111
// Return from exception. Pops stored status register $sr from data stack
// $st1 and program counter PC from call stack $st0 and sets $pc to this
// location.
void rti(const UDSPInstruction& opc)
{
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
g_dsp.exception_in_progress_hack = false;
}
// HALT
// 0000 0000 0020 0001
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
void halt(const UDSPInstruction& opc)
{
g_dsp.cr |= 0x4;
g_dsp.pc--;
}
// LOOP handling: Loop stack is used to control execution of repeated blocks of
// instructions. Whenever there is value on stack $st2 and current PC is equal
// value at $st2, then value at stack $st3 is decremented. If value is not zero
// then PC is modified with calue from call stack $st0. Otherwise values from
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
// continues at next opcode.
// LOOP $R
// 0000 0000 010r rrrr
// Repeatedly execute following opcode until counter specified by value
// from register $R reaches zero. Each execution decrement counter. Register
// $R remains unchanged. If register $R is set to zero at the beginning of loop
// then looped instruction will not get executed.
// Actually, this instruction simply prepares the loop stacks for the above.
// The looping hardware takes care of the rest.
void loop(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x1f;
u16 cnt = g_dsp.r[reg];
u16 loop_pc = g_dsp.pc;
if (cnt)
{
dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt);
}
}
// LOOPI #I
// 0001 0000 iiii iiii
// Repeatedly execute following opcode until counter specified by
// immediate value I reaches zero. Each execution decrement counter. If
// immediate value I is set to zero at the beginning of loop then looped
// instruction will not get executed.
// Actually, this instruction simply prepares the loop stacks for the above.
// The looping hardware takes care of the rest.
void loopi(const UDSPInstruction& opc)
{
u16 cnt = opc.hex & 0xff;
u16 loop_pc = g_dsp.pc;
if (cnt)
{
dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt);
}
}
// BLOOP $R, addrA
// 0000 0000 011r rrrr
// aaaa aaaa aaaa aaaa
// Repeatedly execute block of code starting at following opcode until
// counter specified by value from register $R reaches zero. Block ends at
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
// included in loop. Counter is pushed on loop stack $st3, end of block address
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
// Up to 4 nested loops is allowed.
void bloop(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x1f;
u16 cnt = g_dsp.r[reg];
u16 loop_pc = dsp_fetch_code();
if (cnt)
{
dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt);
}
else
{
g_dsp.pc = loop_pc;
g_dsp.pc += opSize[dsp_peek_code()];
}
}
// BLOOPI #I, addrA
// 0001 0001 iiii iiii
// aaaa aaaa aaaa aaaa
// Repeatedly execute block of code starting at following opcode until
// counter specified by immediate value I reaches zero. Block ends at specified
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
// nested loops is allowed.
void bloopi(const UDSPInstruction& opc)
{
u16 cnt = opc.hex & 0xff;
u16 loop_pc = dsp_fetch_code();
if (cnt)
{
dsp_reg_store_stack(0, g_dsp.pc);
dsp_reg_store_stack(2, loop_pc);
dsp_reg_store_stack(3, cnt);
}
else
{
g_dsp.pc = loop_pc;
g_dsp.pc += opSize[dsp_peek_code()];
}
}
} // namespace
+266 -266
View File
@@ -1,266 +1,266 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h"
#include "DSPMemoryMap.h"
#include "DSPIntUtil.h"
namespace DSPInterpreter {
// SRS @M, $(0x18+S)
// 0010 1sss mmmm mmmm
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
// lower 8 bits are from the 8-bit immediate.
// Note: pc+=2 in duddie's doc seems wrong
void srs(const UDSPInstruction& opc)
{
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
dsp_dmem_write(addr, g_dsp.r[reg]);
}
// LRS $(0x18+D), @M
// 0010 0ddd mmmm mmmm
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
// lower 8 bits are from the 8-bit immediate.
void lrs(const UDSPInstruction& opc)
{
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
g_dsp.r[reg] = dsp_dmem_read(addr);
}
// LR $D, @M
// 0000 0000 110d dddd
// mmmm mmmm mmmm mmmm
// Move value from data memory pointed by address M to register $D.
// FIXME: Perform additional operation depending on destination register.
void lr(const UDSPInstruction& opc)
{
u8 reg = opc.hex & DSP_REG_MASK;
u16 addr = dsp_fetch_code();
u16 val = dsp_dmem_read(addr);
dsp_op_write_reg(reg, val);
dsp_conditional_extend_accum(reg);
}
// SR @M, $S
// 0000 0000 111s ssss
// mmmm mmmm mmmm mmmm
// Store value from register $S to a memory pointed by address M.
// FIXME: Perform additional operation depending on destination register.
void sr(const UDSPInstruction& opc)
{
u8 reg = opc.hex & DSP_REG_MASK;
u16 addr = dsp_fetch_code();
u16 val = dsp_op_read_reg(reg);
dsp_dmem_write(addr, val);
}
// SI @M, #I
// 0001 0110 mmmm mmmm
// iiii iiii iiii iiii
// Store 16-bit immediate value I to a memory location pointed by address
// M (M is 8-bit value sign extended).
void si(const UDSPInstruction& opc)
{
u16 addr = (s8)opc.hex;
u16 imm = dsp_fetch_code();
dsp_dmem_write(addr, imm);
}
// LRR $D, @$S
// 0001 1000 0ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// FIXME: Perform additional operation depending on destination register.
void lrr(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val);
}
// LRRD $D, @$S
// 0001 1000 1ssd dddd
// Move value from data memory pointed by addressing register $S toregister $D.
// Decrement register $S.
// FIXME: Perform additional operation depending on destination register.
void lrrd(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val);
dsp_decrement_addr_reg(sreg);
}
// LRRI $D, @$S
// 0001 1001 0ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// Increment register $S.
// FIXME: Perform additional operation depending on destination register.
void lrri(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val);
dsp_increment_addr_reg(sreg);
}
// LRRN $D, @$S
// 0001 1001 1ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// Add indexing register $(0x4+S) to register $S.
// FIXME: Perform additional operation depending on destination register.
void lrrn(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val);
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
}
// SRR @$D, $S
// 0001 1010 0dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D.
// FIXME: Perform additional operation depending on source register.
void srr(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val);
}
// SRRD @$D, $S
// 0001 1010 1dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Decrement register $D.
// FIXME: Perform additional operation depending on source register.
void srrd(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val);
dsp_decrement_addr_reg(dreg);
}
// SRRI @$D, $S
// 0001 1011 0dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Increment register $D.
// FIXME: Perform additional operation depending on source register.
void srri(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val);
dsp_increment_addr_reg(dreg);
}
// SRRN @$D, $S
// 0001 1011 1dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Add DSP_REG_IX0 register to register $D.
// FIXME: Perform additional operation depending on source register.
void srrn(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val);
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
}
// ILRR $acD.m, @$arS
// 0000 001d 0001 00ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m.
void ilrr(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
}
// ILRRD $acD.m, @$arS
// 0000 001d 0001 01ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
void ilrrd(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
dsp_decrement_addr_reg(reg);
}
// ILRRI $acD.m, @$S
// 0000 001d 0001 10ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
void ilrri(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
dsp_increment_addr_reg(reg);
}
// ILRRN $acD.m, @$arS
// 0000 001d 0001 11ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Add corresponding indexing
// register $ixS to addressing register $arS.
void ilrrn(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
}
} // namespace
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h"
#include "DSPMemoryMap.h"
#include "DSPIntUtil.h"
namespace DSPInterpreter {
// SRS @M, $(0x18+S)
// 0010 1sss mmmm mmmm
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
// lower 8 bits are from the 8-bit immediate.
// Note: pc+=2 in duddie's doc seems wrong
void srs(const UDSPInstruction& opc)
{
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
dsp_dmem_write(addr, g_dsp.r[reg]);
}
// LRS $(0x18+D), @M
// 0010 0ddd mmmm mmmm
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
// lower 8 bits are from the 8-bit immediate.
void lrs(const UDSPInstruction& opc)
{
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
g_dsp.r[reg] = dsp_dmem_read(addr);
}
// LR $D, @M
// 0000 0000 110d dddd
// mmmm mmmm mmmm mmmm
// Move value from data memory pointed by address M to register $D.
// FIXME: Perform additional operation depending on destination register.
void lr(const UDSPInstruction& opc)
{
u8 reg = opc.hex & DSP_REG_MASK;
u16 addr = dsp_fetch_code();
u16 val = dsp_dmem_read(addr);
dsp_op_write_reg(reg, val);
dsp_conditional_extend_accum(reg);
}
// SR @M, $S
// 0000 0000 111s ssss
// mmmm mmmm mmmm mmmm
// Store value from register $S to a memory pointed by address M.
// FIXME: Perform additional operation depending on destination register.
void sr(const UDSPInstruction& opc)
{
u8 reg = opc.hex & DSP_REG_MASK;
u16 addr = dsp_fetch_code();
u16 val = dsp_op_read_reg(reg);
dsp_dmem_write(addr, val);
}
// SI @M, #I
// 0001 0110 mmmm mmmm
// iiii iiii iiii iiii
// Store 16-bit immediate value I to a memory location pointed by address
// M (M is 8-bit value sign extended).
void si(const UDSPInstruction& opc)
{
u16 addr = (s8)opc.hex;
u16 imm = dsp_fetch_code();
dsp_dmem_write(addr, imm);
}
// LRR $D, @$S
// 0001 1000 0ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// FIXME: Perform additional operation depending on destination register.
void lrr(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val);
}
// LRRD $D, @$S
// 0001 1000 1ssd dddd
// Move value from data memory pointed by addressing register $S toregister $D.
// Decrement register $S.
// FIXME: Perform additional operation depending on destination register.
void lrrd(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val);
dsp_decrement_addr_reg(sreg);
}
// LRRI $D, @$S
// 0001 1001 0ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// Increment register $S.
// FIXME: Perform additional operation depending on destination register.
void lrri(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val);
dsp_increment_addr_reg(sreg);
}
// LRRN $D, @$S
// 0001 1001 1ssd dddd
// Move value from data memory pointed by addressing register $S to register $D.
// Add indexing register $(0x4+S) to register $S.
// FIXME: Perform additional operation depending on destination register.
void lrrn(const UDSPInstruction& opc)
{
u8 sreg = (opc.hex >> 5) & 0x3;
u8 dreg = opc.hex & 0x1f;
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
dsp_op_write_reg(dreg, val);
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
}
// SRR @$D, $S
// 0001 1010 0dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D.
// FIXME: Perform additional operation depending on source register.
void srr(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val);
}
// SRRD @$D, $S
// 0001 1010 1dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Decrement register $D.
// FIXME: Perform additional operation depending on source register.
void srrd(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val);
dsp_decrement_addr_reg(dreg);
}
// SRRI @$D, $S
// 0001 1011 0dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Increment register $D.
// FIXME: Perform additional operation depending on source register.
void srri(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val);
dsp_increment_addr_reg(dreg);
}
// SRRN @$D, $S
// 0001 1011 1dds ssss
// Store value from source register $S to a memory location pointed by
// addressing register $D. Add DSP_REG_IX0 register to register $D.
// FIXME: Perform additional operation depending on source register.
void srrn(const UDSPInstruction& opc)
{
u8 dreg = (opc.hex >> 5) & 0x3;
u8 sreg = opc.hex & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_dmem_write(g_dsp.r[dreg], val);
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
}
// ILRR $acD.m, @$arS
// 0000 001d 0001 00ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m.
void ilrr(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
}
// ILRRD $acD.m, @$arS
// 0000 001d 0001 01ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
void ilrrd(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
dsp_decrement_addr_reg(reg);
}
// ILRRI $acD.m, @$S
// 0000 001d 0001 10ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
void ilrri(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
dsp_increment_addr_reg(reg);
}
// ILRRN $acD.m, @$arS
// 0000 001d 0001 11ss
// Move value from instruction memory pointed by addressing register
// $arS to mid accumulator register $acD.m. Add corresponding indexing
// register $ixS to addressing register $arS.
void ilrrn(const UDSPInstruction& opc)
{
u16 reg = opc.hex & 0x3;
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
}
} // namespace
+202 -202
View File
@@ -1,202 +1,202 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h"
#include "DSPCore.h"
#include "DSPIntUtil.h"
namespace DSPInterpreter {
void unknown(const UDSPInstruction& opc)
{
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
}
// MRR $D, $S
// 0001 11dd ddds ssss
// Move value from register $S to register $D.
// FIXME: Perform additional operation depending on destination register.
void mrr(const UDSPInstruction& opc)
{
u8 sreg = opc.hex & 0x1f;
u8 dreg = (opc.hex >> 5) & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_op_write_reg(dreg, val);
}
// LRI $D, #I
// 0000 0000 100d dddd
// iiii iiii iiii iiii
// Load immediate value I to register $D.
// FIXME: Perform additional operation depending on destination register.
// DSPSpy discovery: This, and possibly other instructions that load a register,
// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
// to the whole accumulator! This does not happen in S16 mode.
void lri(const UDSPInstruction& opc)
{
u8 reg = opc.hex & DSP_REG_MASK;
u16 imm = dsp_fetch_code();
dsp_op_write_reg(reg, imm);
dsp_conditional_extend_accum(reg);
}
// LRIS $(0x18+D), #I
// 0000 1ddd iiii iiii
// Load immediate value I (8-bit sign extended) to accumulator register.
// FIXME: Perform additional operation depending on destination register.
void lris(const UDSPInstruction& opc)
{
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
u16 imm = (s8)opc.hex;
dsp_op_write_reg(reg, imm);
dsp_conditional_extend_accum(reg);
}
// TSTAXL $acR
// 1000 r001 xxxx xxxx
// r specifies one of the main accumulators.
// Definitely not a test instruction - it changes the accums.
// Not affected by m0/m2. Not affected by s16/s40.
void tstaxl(const UDSPInstruction& opc)
{
// This is probably all wrong.
//u8 reg = (opc.hex >> 8) & 0x1;
//s16 val = dsp_get_ax_l(reg);
//Update_SR_Register16(val);
}
// ADDARN $arD, $ixS
// 0000 0000 0001 ssdd
// Adds indexing register $ixS to an addressing register $arD.
void addarn(const UDSPInstruction& opc)
{
u8 dreg = opc.hex & 0x3;
u8 sreg = (opc.hex >> 2) & 0x3;
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
// It is critical for the Zelda ucode that this one wraps correctly.
}
// NX
// 1000 -000 xxxx xxxx
// No operation, but can be extended with extended opcode.
void nx(const UDSPInstruction& opc)
{
// This opcode is supposed to do nothing - it's used if you want to use
// an opcode extension but not do anything. At least according to duddie.
}
//-------------------------------------------------------------
// DAR $arD ?
// 0000 0000 0000 01dd
// Decrement address register $arD.
void dar(const UDSPInstruction& opc)
{
dsp_decrement_addr_reg(opc.hex & 0x3);
}
// IAR $arD ?
// 0000 0000 0000 10dd
// Increment address register $arD.
void iar(const UDSPInstruction& opc)
{
dsp_increment_addr_reg(opc.hex & 0x3);
}
// SBCLR #I
// 0001 0011 0000 0iii
// bit of status register $sr. Bit number is calculated by adding 6 to
// immediate value I.
void sbclr(const UDSPInstruction& opc)
{
u8 bit = (opc.hex & 0xff) + 6;
g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
}
// SBSET #I
// 0001 0010 0000 0iii
// Set bit of status register $sr. Bit number is calculated by adding 6 to
// immediate value I.
void sbset(const UDSPInstruction& opc)
{
u8 bit = (opc.hex & 0xff) + 6;
g_dsp.r[DSP_REG_SR] |= (1 << bit);
}
// FIXME inside
// This is a bunch of flag setters, flipping bits in SR. So far so good,
// but it's harder to know exactly what effect they have.
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
//
// SET16 changes something very important: see the LRI instruction above.
// Hermes' demo sets the following defaults:
// SET40
// CLR15
// M0
void srbith(const UDSPInstruction& opc)
{
switch ((opc.hex >> 8) & 0xf)
{
// M0 seems to be the default. M2 is used in functions in Zelda
// and then reset with M0 at the end. Like the other bits here, it's
// done around loops with lots of multiplications.
// I've confirmed with DSPSpy that they flip this bit.
case 0xa: // M2
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
break;
case 0xb: // M0
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
break;
// If set, treat multiplicands as unsigned.
// If clear, treat them as signed.
case 0xc: // CLR15
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
break;
case 0xd: // SET15
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
break;
// Automatic 40-bit sign extension when loading ACx.M.
// 40 seems to be the default.
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
case 0xe: // SET16 (really, clear SR's 0x4000)
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
break;
case 0xf: // SET40 (really, set SR's 0x4000)
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
break;
default:
break;
}
}
} // namespace
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Additional copyrights go to Duddie and Tratax (c) 2004
#include "DSPInterpreter.h"
#include "DSPCore.h"
#include "DSPIntUtil.h"
namespace DSPInterpreter {
void unknown(const UDSPInstruction& opc)
{
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
}
// MRR $D, $S
// 0001 11dd ddds ssss
// Move value from register $S to register $D.
// FIXME: Perform additional operation depending on destination register.
void mrr(const UDSPInstruction& opc)
{
u8 sreg = opc.hex & 0x1f;
u8 dreg = (opc.hex >> 5) & 0x1f;
u16 val = dsp_op_read_reg(sreg);
dsp_op_write_reg(dreg, val);
}
// LRI $D, #I
// 0000 0000 100d dddd
// iiii iiii iiii iiii
// Load immediate value I to register $D.
// FIXME: Perform additional operation depending on destination register.
// DSPSpy discovery: This, and possibly other instructions that load a register,
// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
// to the whole accumulator! This does not happen in S16 mode.
void lri(const UDSPInstruction& opc)
{
u8 reg = opc.hex & DSP_REG_MASK;
u16 imm = dsp_fetch_code();
dsp_op_write_reg(reg, imm);
dsp_conditional_extend_accum(reg);
}
// LRIS $(0x18+D), #I
// 0000 1ddd iiii iiii
// Load immediate value I (8-bit sign extended) to accumulator register.
// FIXME: Perform additional operation depending on destination register.
void lris(const UDSPInstruction& opc)
{
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
u16 imm = (s8)opc.hex;
dsp_op_write_reg(reg, imm);
dsp_conditional_extend_accum(reg);
}
// TSTAXL $acR
// 1000 r001 xxxx xxxx
// r specifies one of the main accumulators.
// Definitely not a test instruction - it changes the accums.
// Not affected by m0/m2. Not affected by s16/s40.
void tstaxl(const UDSPInstruction& opc)
{
// This is probably all wrong.
//u8 reg = (opc.hex >> 8) & 0x1;
//s16 val = dsp_get_ax_l(reg);
//Update_SR_Register16(val);
}
// ADDARN $arD, $ixS
// 0000 0000 0001 ssdd
// Adds indexing register $ixS to an addressing register $arD.
void addarn(const UDSPInstruction& opc)
{
u8 dreg = opc.hex & 0x3;
u8 sreg = (opc.hex >> 2) & 0x3;
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
// It is critical for the Zelda ucode that this one wraps correctly.
}
// NX
// 1000 -000 xxxx xxxx
// No operation, but can be extended with extended opcode.
void nx(const UDSPInstruction& opc)
{
// This opcode is supposed to do nothing - it's used if you want to use
// an opcode extension but not do anything. At least according to duddie.
}
//-------------------------------------------------------------
// DAR $arD ?
// 0000 0000 0000 01dd
// Decrement address register $arD.
void dar(const UDSPInstruction& opc)
{
dsp_decrement_addr_reg(opc.hex & 0x3);
}
// IAR $arD ?
// 0000 0000 0000 10dd
// Increment address register $arD.
void iar(const UDSPInstruction& opc)
{
dsp_increment_addr_reg(opc.hex & 0x3);
}
// SBCLR #I
// 0001 0011 0000 0iii
// bit of status register $sr. Bit number is calculated by adding 6 to
// immediate value I.
void sbclr(const UDSPInstruction& opc)
{
u8 bit = (opc.hex & 0xff) + 6;
g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
}
// SBSET #I
// 0001 0010 0000 0iii
// Set bit of status register $sr. Bit number is calculated by adding 6 to
// immediate value I.
void sbset(const UDSPInstruction& opc)
{
u8 bit = (opc.hex & 0xff) + 6;
g_dsp.r[DSP_REG_SR] |= (1 << bit);
}
// FIXME inside
// This is a bunch of flag setters, flipping bits in SR. So far so good,
// but it's harder to know exactly what effect they have.
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
//
// SET16 changes something very important: see the LRI instruction above.
// Hermes' demo sets the following defaults:
// SET40
// CLR15
// M0
void srbith(const UDSPInstruction& opc)
{
switch ((opc.hex >> 8) & 0xf)
{
// M0 seems to be the default. M2 is used in functions in Zelda
// and then reset with M0 at the end. Like the other bits here, it's
// done around loops with lots of multiplications.
// I've confirmed with DSPSpy that they flip this bit.
case 0xa: // M2
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
break;
case 0xb: // M0
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
break;
// If set, treat multiplicands as unsigned.
// If clear, treat them as signed.
case 0xc: // CLR15
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
break;
case 0xd: // SET15
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
break;
// Automatic 40-bit sign extension when loading ACx.M.
// 40 seems to be the default.
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
case 0xe: // SET16 (really, clear SR's 0x4000)
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
break;
case 0xf: // SET40 (really, set SR's 0x4000)
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
break;
default:
break;
}
}
} // namespace
File diff suppressed because it is too large Load Diff
+85 -85
View File
@@ -1,85 +1,85 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "LabelMap.h"
#include "DSPTables.h"
LabelMap::LabelMap()
{
}
void LabelMap::RegisterDefaults()
{
for (int i = 0; i < 0x24; i++)
{
if (regnames[i].name)
RegisterLabel(regnames[i].name, regnames[i].addr);
}
for (int i = 0; i < (int)pdlabels_size; i++)
{
if (pdlabels[i].name)
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
}
}
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
{
u16 old_value;
if (GetLabelValue(label, &old_value) && old_value != lval)
{
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
label.c_str(), lval, old_value);
DeleteLabel(label);
}
labels.push_back(label_t(label, lval, type));
}
void LabelMap::DeleteLabel(const std::string &label)
{
for (std::vector<label_t>::iterator iter = labels.begin();
iter != labels.end(); ++iter)
{
if (!label.compare(iter->name))
{
labels.erase(iter);
return;
}
}
}
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
{
for (u32 i = 0; i < labels.size(); i++)
{
if (!label.compare(labels[i].name))
{
if (type & labels[i].type) {
*value = labels[i].addr;
return true;
} else {
printf("WARNING: Wrong label type requested. %s\n", label.c_str());
}
}
}
return false;
}
void LabelMap::Clear()
{
labels.clear();
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "LabelMap.h"
#include "DSPTables.h"
LabelMap::LabelMap()
{
}
void LabelMap::RegisterDefaults()
{
for (int i = 0; i < 0x24; i++)
{
if (regnames[i].name)
RegisterLabel(regnames[i].name, regnames[i].addr);
}
for (int i = 0; i < (int)pdlabels_size; i++)
{
if (pdlabels[i].name)
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
}
}
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
{
u16 old_value;
if (GetLabelValue(label, &old_value) && old_value != lval)
{
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
label.c_str(), lval, old_value);
DeleteLabel(label);
}
labels.push_back(label_t(label, lval, type));
}
void LabelMap::DeleteLabel(const std::string &label)
{
for (std::vector<label_t>::iterator iter = labels.begin();
iter != labels.end(); ++iter)
{
if (!label.compare(iter->name))
{
labels.erase(iter);
return;
}
}
}
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
{
for (u32 i = 0; i < labels.size(); i++)
{
if (!label.compare(labels[i].name))
{
if (type & labels[i].type) {
*value = labels[i].addr;
return true;
} else {
printf("WARNING: Wrong label type requested. %s\n", label.c_str());
}
}
}
return false;
}
void LabelMap::Clear()
{
labels.clear();
}
+55 -55
View File
@@ -1,55 +1,55 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _LABELMAP_H
#define _LABELMAP_H
#include <string>
#include <vector>
#include "Common.h"
enum LabelType
{
LABEL_IADDR = 1, // Jump addresses, etc
LABEL_DADDR = 2, // Data addresses, etc
LABEL_VALUE = 4,
LABEL_ANY = 0xFF,
};
class LabelMap
{
struct label_t
{
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
std::string name;
s32 addr;
LabelType type;
};
std::vector<label_t> labels;
public:
LabelMap();
~LabelMap() { }
void RegisterDefaults();
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
void DeleteLabel(const std::string &label);
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
void Clear();
};
#endif // _LABELMAP_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _LABELMAP_H
#define _LABELMAP_H
#include <string>
#include <vector>
#include "Common.h"
enum LabelType
{
LABEL_IADDR = 1, // Jump addresses, etc
LABEL_DADDR = 2, // Data addresses, etc
LABEL_VALUE = 4,
LABEL_ANY = 0xFF,
};
class LabelMap
{
struct label_t
{
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
std::string name;
s32 addr;
LabelType type;
};
std::vector<label_t> labels;
public:
LabelMap();
~LabelMap() { }
void RegisterDefaults();
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
void DeleteLabel(const std::string &label);
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
void Clear();
};
#endif // _LABELMAP_H
File diff suppressed because it is too large Load Diff
+139 -139
View File
@@ -1,139 +1,139 @@
/*====================================================================
project: GameCube DSP Tool (gcdsp)
created: 2005.03.04
mail: duddie@walla.com
Copyright (c) 2005 Duddie
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#ifndef _DSP_ASSEMBLE_H
#define _DSP_ASSEMBLE_H
#include <string>
#include <map>
#include "Common.h"
#include "disassemble.h"
#include "DSPTables.h"
#include "LabelMap.h"
enum err_t
{
ERR_OK = 0,
ERR_UNKNOWN,
ERR_UNKNOWN_OPCODE,
ERR_NOT_ENOUGH_PARAMETERS,
ERR_TOO_MANY_PARAMETERS,
ERR_WRONG_PARAMETER,
ERR_EXPECTED_PARAM_STR,
ERR_EXPECTED_PARAM_VAL,
ERR_EXPECTED_PARAM_REG,
ERR_EXPECTED_PARAM_MEM,
ERR_EXPECTED_PARAM_IMM,
ERR_INCORRECT_BIN,
ERR_INCORRECT_HEX,
ERR_INCORRECT_DEC,
ERR_LABEL_EXISTS,
ERR_UNKNOWN_LABEL,
ERR_NO_MATCHING_BRACKETS,
ERR_EXT_CANT_EXTEND_OPCODE,
ERR_EXT_PAR_NOT_EXT,
ERR_WRONG_PARAMETER_ACC,
ERR_WRONG_PARAMETER_MID_ACC,
ERR_INVALID_REGISTER,
ERR_OUT_RANGE_NUMBER
};
// Unless you want labels to carry over between files, you probably
// want to create a new DSPAssembler for every file you assemble.
class DSPAssembler
{
public:
DSPAssembler(const AssemblerSettings &settings);
~DSPAssembler();
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
// one for each word of code, indicating the source assembler code line number it came from.
// If returns false, call GetErrorString to get some text to present to the user.
bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
std::string GetErrorString() const { return last_error_str; }
err_t GetError() const { return last_error; }
private:
struct param_t
{
u32 val;
partype_t type;
char *str;
};
enum segment_t
{
SEGMENT_CODE = 0,
SEGMENT_DATA,
SEGMENT_OVERLAY,
SEGMENT_MAX
};
// Utility functions
s32 ParseValue(const char *str);
u32 ParseExpression(const char *ptr);
u32 GetParams(char *parstr, param_t *par);
void InitPass(int pass);
bool AssembleFile(const char *fname, int pass);
void ShowError(err_t err_code, const char *extra_info = NULL);
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
char *FindBrackets(char *src, char *dst);
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
char *gdg_buffer;
std::string include_dir;
std::string cur_line;
u32 m_cur_addr;
int m_totalSize;
u8 m_cur_pass;
LabelMap labels;
u32 code_line;
bool failed;
std::string last_error_str;
err_t last_error;
typedef std::map<std::string, std::string> AliasMap;
AliasMap aliases;
segment_t cur_segment;
u32 segment_addr[SEGMENT_MAX];
int m_current_param;
const AssemblerSettings settings_;
};
#endif // _DSP_ASSEMBLE_H
/*====================================================================
project: GameCube DSP Tool (gcdsp)
created: 2005.03.04
mail: duddie@walla.com
Copyright (c) 2005 Duddie
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
====================================================================*/
#ifndef _DSP_ASSEMBLE_H
#define _DSP_ASSEMBLE_H
#include <string>
#include <map>
#include "Common.h"
#include "disassemble.h"
#include "DSPTables.h"
#include "LabelMap.h"
enum err_t
{
ERR_OK = 0,
ERR_UNKNOWN,
ERR_UNKNOWN_OPCODE,
ERR_NOT_ENOUGH_PARAMETERS,
ERR_TOO_MANY_PARAMETERS,
ERR_WRONG_PARAMETER,
ERR_EXPECTED_PARAM_STR,
ERR_EXPECTED_PARAM_VAL,
ERR_EXPECTED_PARAM_REG,
ERR_EXPECTED_PARAM_MEM,
ERR_EXPECTED_PARAM_IMM,
ERR_INCORRECT_BIN,
ERR_INCORRECT_HEX,
ERR_INCORRECT_DEC,
ERR_LABEL_EXISTS,
ERR_UNKNOWN_LABEL,
ERR_NO_MATCHING_BRACKETS,
ERR_EXT_CANT_EXTEND_OPCODE,
ERR_EXT_PAR_NOT_EXT,
ERR_WRONG_PARAMETER_ACC,
ERR_WRONG_PARAMETER_MID_ACC,
ERR_INVALID_REGISTER,
ERR_OUT_RANGE_NUMBER
};
// Unless you want labels to carry over between files, you probably
// want to create a new DSPAssembler for every file you assemble.
class DSPAssembler
{
public:
DSPAssembler(const AssemblerSettings &settings);
~DSPAssembler();
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
// one for each word of code, indicating the source assembler code line number it came from.
// If returns false, call GetErrorString to get some text to present to the user.
bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
std::string GetErrorString() const { return last_error_str; }
err_t GetError() const { return last_error; }
private:
struct param_t
{
u32 val;
partype_t type;
char *str;
};
enum segment_t
{
SEGMENT_CODE = 0,
SEGMENT_DATA,
SEGMENT_OVERLAY,
SEGMENT_MAX
};
// Utility functions
s32 ParseValue(const char *str);
u32 ParseExpression(const char *ptr);
u32 GetParams(char *parstr, param_t *par);
void InitPass(int pass);
bool AssembleFile(const char *fname, int pass);
void ShowError(err_t err_code, const char *extra_info = NULL);
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
char *FindBrackets(char *src, char *dst);
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
char *gdg_buffer;
std::string include_dir;
std::string cur_line;
u32 m_cur_addr;
int m_totalSize;
u8 m_cur_pass;
LabelMap labels;
u32 code_line;
bool failed;
std::string last_error_str;
err_t last_error;
typedef std::map<std::string, std::string> AliasMap;
AliasMap aliases;
segment_t cur_segment;
u32 segment_addr[SEGMENT_MAX];
int m_current_param;
const AssemblerSettings settings_;
};
#endif // _DSP_ASSEMBLE_H
@@ -1,23 +1,23 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DebuggerUIUtil.h"
// The default font
wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DebuggerUIUtil.h"
// The default font
wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));
@@ -1,36 +1,36 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DEBUGGER_UI_UTIL_H
#define _DEBUGGER_UI_UTIL_H
#include <wx/wx.h>
#define wxUSE_XPM_IN_MSW 1
#define USE_XPM_BITMAPS 1
// Defined in CodeWindow.cpp
extern wxFont DebuggerFont;
// define this to use XPMs everywhere (by default, BMPs are used under Win)
// BMPs use less space, but aren't compiled into the executable on other platforms
#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
#error You need to enable XPM support to use XPM bitmaps with toolbar!
#endif // USE_XPM_BITMAPS
#endif
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DEBUGGER_UI_UTIL_H
#define _DEBUGGER_UI_UTIL_H
#include <wx/wx.h>
#define wxUSE_XPM_IN_MSW 1
#define USE_XPM_BITMAPS 1
// Defined in CodeWindow.cpp
extern wxFont DebuggerFont;
// define this to use XPMs everywhere (by default, BMPs are used under Win)
// BMPs use less space, but aren't compiled into the executable on other platforms
#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
#error You need to enable XPM support to use XPM bitmaps with toolbar!
#endif // USE_XPM_BITMAPS
#endif
+100 -100
View File
@@ -1,100 +1,100 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _NAND_CONTENT_LOADER_H
#define _NAND_CONTENT_LOADER_H
#include <string>
#include <vector>
#include <map>
#include "Common.h"
#include "Blob.h"
#include "Volume.h"
namespace DiscIO
{
struct SNANDContent
{
u32 m_ContentID;
u16 m_Index;
u16 m_Type;
u32 m_Size;
u8 m_SHA1Hash[20];
u8 m_Header[36]; //all of the above
u8* m_pData;
};
// pure virtual interface so just the NANDContentManager can create these files only
class INANDContentLoader
{
public:
INANDContentLoader() {}
virtual ~INANDContentLoader() {}
virtual bool IsValid() const = 0;
virtual u64 GetTitleID() const = 0;
virtual u16 GetIosVersion() const = 0;
virtual u32 GetBootIndex() const = 0;
virtual size_t GetContentSize() const = 0;
virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
virtual const u8* GetTicketView() const = 0;
virtual const u8* GetTmdHeader() const = 0;
virtual const std::vector<SNANDContent>& GetContent() const = 0;
virtual const u16 GetTitleVersion() const = 0;
virtual const u16 GetNumEntries() const = 0;
virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
enum
{
TICKET_VIEW_SIZE = 0x58,
TMD_HEADER_SIZE = 0x1e4,
CONTENT_HEADER_SIZE = 0x24
};
};
// we open the NAND Content files to often... lets cache them
class CNANDContentManager
{
public:
static CNANDContentManager& Access() { return m_Instance; }
const INANDContentLoader& GetNANDLoader(const std::string& _rName);
private:
CNANDContentManager() {};
~CNANDContentManager();
static CNANDContentManager m_Instance;
typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
CNANDContentMap m_Map;
};
}
#endif
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _NAND_CONTENT_LOADER_H
#define _NAND_CONTENT_LOADER_H
#include <string>
#include <vector>
#include <map>
#include "Common.h"
#include "Blob.h"
#include "Volume.h"
namespace DiscIO
{
struct SNANDContent
{
u32 m_ContentID;
u16 m_Index;
u16 m_Type;
u32 m_Size;
u8 m_SHA1Hash[20];
u8 m_Header[36]; //all of the above
u8* m_pData;
};
// pure virtual interface so just the NANDContentManager can create these files only
class INANDContentLoader
{
public:
INANDContentLoader() {}
virtual ~INANDContentLoader() {}
virtual bool IsValid() const = 0;
virtual u64 GetTitleID() const = 0;
virtual u16 GetIosVersion() const = 0;
virtual u32 GetBootIndex() const = 0;
virtual size_t GetContentSize() const = 0;
virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
virtual const u8* GetTicketView() const = 0;
virtual const u8* GetTmdHeader() const = 0;
virtual const std::vector<SNANDContent>& GetContent() const = 0;
virtual const u16 GetTitleVersion() const = 0;
virtual const u16 GetNumEntries() const = 0;
virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
enum
{
TICKET_VIEW_SIZE = 0x58,
TMD_HEADER_SIZE = 0x1e4,
CONTENT_HEADER_SIZE = 0x24
};
};
// we open the NAND Content files to often... lets cache them
class CNANDContentManager
{
public:
static CNANDContentManager& Access() { return m_Instance; }
const INANDContentLoader& GetNANDLoader(const std::string& _rName);
private:
CNANDContentManager() {};
~CNANDContentManager();
static CNANDContentManager m_Instance;
typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
CNANDContentMap m_Map;
};
}
#endif
+52 -52
View File
@@ -1,52 +1,52 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "Volume.h"
#include "Blob.h"
#include "NANDContentLoader.h"
// --- this volume type is used for Wad files ---
// Some of this code might look redundant with the CNANDContentLoader class, however,
// We do not do any decryption here, we do raw read, so things are -Faster-
namespace DiscIO
{
class CVolumeWAD : public IVolume
{
public:
CVolumeWAD(IBlobReader* _pReader);
~CVolumeWAD();
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
bool GetTitleID(u8* _pBuffer) const;
std::string GetUniqueID() const;
std::string GetMakerID() const;
std::string GetName() const;
u32 GetFSTSize() const { return 0; }
std::string GetApploaderDate() const { return "0"; }
ECountry GetCountry() const;
u64 GetSize() const;
private:
IBlobReader* m_pReader;
u64 m_titleID;
u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
};
} // namespace
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#pragma once
#include "Volume.h"
#include "Blob.h"
#include "NANDContentLoader.h"
// --- this volume type is used for Wad files ---
// Some of this code might look redundant with the CNANDContentLoader class, however,
// We do not do any decryption here, we do raw read, so things are -Faster-
namespace DiscIO
{
class CVolumeWAD : public IVolume
{
public:
CVolumeWAD(IBlobReader* _pReader);
~CVolumeWAD();
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
bool GetTitleID(u8* _pBuffer) const;
std::string GetUniqueID() const;
std::string GetMakerID() const;
std::string GetName() const;
u32 GetFSTSize() const { return 0; }
std::string GetApploaderDate() const { return "0"; }
ECountry GetCountry() const;
u64 GetSize() const;
private:
IBlobReader* m_pReader;
u64 m_titleID;
u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
};
} // namespace
+156 -156
View File
@@ -1,156 +1,156 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "NANDContentLoader.h"
#include <algorithm>
#include <cctype>
#include "MathUtil.h"
#include "FileUtil.h"
#include "Log.h"
#include "WiiWad.h"
namespace DiscIO
{
class CBlobBigEndianReader
{
public:
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
u32 Read32(u64 _Offset)
{
u32 Temp;
m_rReader.Read(_Offset, 4, (u8*)&Temp);
return(Common::swap32(Temp));
}
private:
DiscIO::IBlobReader& m_rReader;
};
WiiWAD::WiiWAD(const std::string& _rName)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
if (pReader == NULL)
{
m_Valid = false;
return;
}
m_Valid = ParseWAD(*pReader);
delete pReader;
}
WiiWAD::~WiiWAD()
{
if (m_Valid)
{
delete m_pCertificateChain;
delete m_pTicket;
delete m_pTMD;
delete m_pDataApp;
delete m_pFooter;
}
}
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
{
if (_Size > 0)
{
u8* pTmpBuffer = new u8[_Size];
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
{
ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
PanicAlert("WiiWAD: Could not read from file");
}
return pTmpBuffer;
}
return NULL;
}
bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
{
CBlobBigEndianReader ReaderBig(_rReader);
// get header size
u32 HeaderSize = ReaderBig.Read32(0);
if (HeaderSize != 0x20)
{
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
return false;
}
// get header
u8 Header[0x20];
_rReader.Read(0, HeaderSize, Header);
u32 HeaderType = ReaderBig.Read32(0x4);
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
return false;
m_CertificateChainSize = ReaderBig.Read32(0x8);
u32 Reserved = ReaderBig.Read32(0xC);
m_TicketSize = ReaderBig.Read32(0x10);
m_TMDSize = ReaderBig.Read32(0x14);
m_DataAppSize = ReaderBig.Read32(0x18);
m_FooterSize = ReaderBig.Read32(0x1C);
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
u32 Offset = 0x40;
m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
return true;
}
bool WiiWAD::IsWiiWAD(const std::string& _rName)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
if (pReader == NULL)
return false;
CBlobBigEndianReader Reader(*pReader);
bool Result = false;
// check for wii wad
if (Reader.Read32(0x00) == 0x20)
{
u32 WADTYpe = Reader.Read32(0x04);
switch(WADTYpe)
{
case 0x49730000:
case 0x69620000:
Result = true;
}
}
delete pReader;
return Result;
}
} // namespace end
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "stdafx.h"
#include "NANDContentLoader.h"
#include <algorithm>
#include <cctype>
#include "MathUtil.h"
#include "FileUtil.h"
#include "Log.h"
#include "WiiWad.h"
namespace DiscIO
{
class CBlobBigEndianReader
{
public:
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
u32 Read32(u64 _Offset)
{
u32 Temp;
m_rReader.Read(_Offset, 4, (u8*)&Temp);
return(Common::swap32(Temp));
}
private:
DiscIO::IBlobReader& m_rReader;
};
WiiWAD::WiiWAD(const std::string& _rName)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
if (pReader == NULL)
{
m_Valid = false;
return;
}
m_Valid = ParseWAD(*pReader);
delete pReader;
}
WiiWAD::~WiiWAD()
{
if (m_Valid)
{
delete m_pCertificateChain;
delete m_pTicket;
delete m_pTMD;
delete m_pDataApp;
delete m_pFooter;
}
}
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
{
if (_Size > 0)
{
u8* pTmpBuffer = new u8[_Size];
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
{
ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
PanicAlert("WiiWAD: Could not read from file");
}
return pTmpBuffer;
}
return NULL;
}
bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
{
CBlobBigEndianReader ReaderBig(_rReader);
// get header size
u32 HeaderSize = ReaderBig.Read32(0);
if (HeaderSize != 0x20)
{
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
return false;
}
// get header
u8 Header[0x20];
_rReader.Read(0, HeaderSize, Header);
u32 HeaderType = ReaderBig.Read32(0x4);
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
return false;
m_CertificateChainSize = ReaderBig.Read32(0x8);
u32 Reserved = ReaderBig.Read32(0xC);
m_TicketSize = ReaderBig.Read32(0x10);
m_TMDSize = ReaderBig.Read32(0x14);
m_DataAppSize = ReaderBig.Read32(0x18);
m_FooterSize = ReaderBig.Read32(0x1C);
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
u32 Offset = 0x40;
m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
return true;
}
bool WiiWAD::IsWiiWAD(const std::string& _rName)
{
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
if (pReader == NULL)
return false;
CBlobBigEndianReader Reader(*pReader);
bool Result = false;
// check for wii wad
if (Reader.Read32(0x00) == 0x20)
{
u32 WADTYpe = Reader.Read32(0x04);
switch(WADTYpe)
{
case 0x49730000:
case 0x69620000:
Result = true;
}
}
delete pReader;
return Result;
}
} // namespace end
+78 -78
View File
@@ -1,78 +1,78 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _WII_WAD_H
#define _WII_WAD_H
#include <string>
#include <vector>
#include <map>
#include "Common.h"
#include "Blob.h"
#include "Volume.h"
namespace DiscIO
{
class WiiWAD
{
public:
WiiWAD(const std::string& _rName);
~WiiWAD();
bool IsValid() const { return m_Valid; }
u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
u32 GetTicketSize() const { return m_TicketSize; }
u32 GetTMDSize() const { return m_TMDSize; }
u32 GetDataAppSize() const { return m_DataAppSize; }
u32 GetFooterSize() const { return m_FooterSize; }
u8* GetCertificateChain() const { return m_pCertificateChain; }
u8* GetTicket() const { return m_pTicket; }
u8* GetTMD() const { return m_pTMD; }
u8* GetDataApp() const { return m_pDataApp; }
u8* GetFooter() const { return m_pFooter; }
static bool IsWiiWAD(const std::string& _rName);
private:
bool m_Valid;
u32 m_CertificateChainSize;
u32 m_TicketSize;
u32 m_TMDSize;
u32 m_DataAppSize;
u32 m_FooterSize;
u8* m_pCertificateChain;
u8* m_pTicket;
u8* m_pTMD;
u8* m_pDataApp;
u8* m_pFooter;
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
bool ParseWAD(DiscIO::IBlobReader& _rReader);
};
}
#endif
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _WII_WAD_H
#define _WII_WAD_H
#include <string>
#include <vector>
#include <map>
#include "Common.h"
#include "Blob.h"
#include "Volume.h"
namespace DiscIO
{
class WiiWAD
{
public:
WiiWAD(const std::string& _rName);
~WiiWAD();
bool IsValid() const { return m_Valid; }
u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
u32 GetTicketSize() const { return m_TicketSize; }
u32 GetTMDSize() const { return m_TMDSize; }
u32 GetDataAppSize() const { return m_DataAppSize; }
u32 GetFooterSize() const { return m_FooterSize; }
u8* GetCertificateChain() const { return m_pCertificateChain; }
u8* GetTicket() const { return m_pTicket; }
u8* GetTMD() const { return m_pTMD; }
u8* GetDataApp() const { return m_pDataApp; }
u8* GetFooter() const { return m_pFooter; }
static bool IsWiiWAD(const std::string& _rName);
private:
bool m_Valid;
u32 m_CertificateChainSize;
u32 m_TicketSize;
u32 m_TMDSize;
u32 m_DataAppSize;
u32 m_FooterSize;
u8* m_pCertificateChain;
u8* m_pTicket;
u8* m_pTMD;
u8* m_pDataApp;
u8* m_pFooter;
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
bool ParseWAD(DiscIO::IBlobReader& _rReader);
};
}
#endif
+288 -288
View File
@@ -1,288 +1,288 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "NetWindow.h"
void ClientSide::OnClientData(unsigned char data)
{
unsigned char sent = 0;
u32 buffer_size;
size_t recv_size;
char *buffer = NULL;
switch (data)
{
case 0x10: // Player joined server
{
// Read GameFound
m_socket.Receive((char*)&sent, 1, recv_size);
// Read nickname
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
if (sent != 0x1F)
for (int i = 0; i < 4; i++)
Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
m_numplayers++;
Event->SendEvent(HOST_NEWPLAYER);
break;
}
case 0x11: // Player left server
{
// Read Nickname
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
m_numplayers--;
Event->SendEvent(HOST_PLAYERLEFT);
break;
}
case 0x15: // Ping Player
{
m_socket.Receive((char*)&buffer_size, 4, recv_size);
m_socket.Send((const char*)&buffer_size, 4);
break;
}
case 0x20: // IP request
{
//buffer_size = m_addr.size();
//m_socket.Send((const char*)&buffer_size, 4);
m_socket.Send((const char*)&data, 1);
m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
break;
}
case 0x30: // Chat message received from server
{
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
if (recv_size > 1024)
{
//something wrong...
delete[] buffer;
return;
}
Event->AppendText(wxString::FromAscii(buffer));
break;
}
case 0x35: // ChangeGame message received
{
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
m_selectedgame = std::string(buffer);
Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
// Tell the server if the game's been found
m_socket.Send((const char*)&data, 1);
CheckGameFound();
Event->SendEvent(GUI_UPDATE);
break;
}
case 0x40: // Ready message received
{
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
if (recv_size > 1024)
{
delete[] buffer;
return;
}
Event->AppendText(wxString::FromAscii(buffer));
break;
}
case 0x50: // Everyone is Ready message received
{
// Load the game and start synching
m_netptr->LoadGame();
break;
}
case 0xA1: // Received pad data from host in versus mode
{
if (m_data_received)
wxThread::Sleep(10);
m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
m_data_received = true;
#ifdef NET_DEBUG
char sent[64];
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
Event->AppendText(wxString::FromAscii(sent));
#endif
break;
}
}
delete[] buffer;
}
void ServerSide::OnServerData(int sock, unsigned char data)
{
size_t recv_size;
char *buffer = NULL;
unsigned char sent;
unsigned int four_bytes;
switch (data)
{
case 0x15: // Ping Request
{
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
m_client[sock].socket.Send((const char*)&four_bytes, 4);
break;
}
case 0x20: // IP request response
{
buffer = new char[24];
// Read IP Address
m_client[sock].socket.Receive(buffer, 24, recv_size);
Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
break;
}
case 0x30: // Chat message
{
buffer = new char[1024];
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
if (recv_size > 1024)
{
//something wrong...
delete[] buffer;
return;
}
sent = 0x30;
// Send to all
for (int i=0; i < m_numplayers ; i++)
{
if (i == sock)
continue;
m_client[i].socket.Send((const char*)&sent, 1);
m_client[1].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(buffer, recv_size);
}
Event->AppendText(wxString::FromAscii(buffer));
break;
}
case 0x35: // Change game response received
{
// Receive isGameFound response (0x1F / 0x1A)
m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
// If game is not found
if (sent != 0x1F)
{
sent = 0x30;
wxString error_str = wxString::Format(
wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
four_bytes = (int)error_str.size();
for (int i=0; i < 2; i++)
Event->AppendText(error_str);
// Send to all
for (int i=0; i < m_numplayers ; i++)
{
if (i == sock)
continue;
m_client[i].socket.Send((const char*)&sent, 1);
m_client[i].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
}
}
break;
}
case 0x40: // Ready message received
{
std::string buffer_str;
m_client[sock].ready = !m_client[sock].ready;
if (m_client[sock].ready)
buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
else
buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
four_bytes = (int)buffer_str.size();
// Send to all
for (int i=0; i < m_numplayers ; i++)
{
m_client[i].socket.Send((const char*)&data, 1);
m_client[i].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
}
Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
IsEveryoneReady();
break;
}
case 0xA1: // Received pad data from a client
{
if (m_data_received)
wxThread::Sleep(10);
m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
m_data_received = true;
#ifdef NET_DEBUG
char sent[64];
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
Event->AppendText(wxString::FromAscii(sent));
#endif
break;
}
}
delete[] buffer;
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "NetWindow.h"
void ClientSide::OnClientData(unsigned char data)
{
unsigned char sent = 0;
u32 buffer_size;
size_t recv_size;
char *buffer = NULL;
switch (data)
{
case 0x10: // Player joined server
{
// Read GameFound
m_socket.Receive((char*)&sent, 1, recv_size);
// Read nickname
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
if (sent != 0x1F)
for (int i = 0; i < 4; i++)
Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
m_numplayers++;
Event->SendEvent(HOST_NEWPLAYER);
break;
}
case 0x11: // Player left server
{
// Read Nickname
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
m_numplayers--;
Event->SendEvent(HOST_PLAYERLEFT);
break;
}
case 0x15: // Ping Player
{
m_socket.Receive((char*)&buffer_size, 4, recv_size);
m_socket.Send((const char*)&buffer_size, 4);
break;
}
case 0x20: // IP request
{
//buffer_size = m_addr.size();
//m_socket.Send((const char*)&buffer_size, 4);
m_socket.Send((const char*)&data, 1);
m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
break;
}
case 0x30: // Chat message received from server
{
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
if (recv_size > 1024)
{
//something wrong...
delete[] buffer;
return;
}
Event->AppendText(wxString::FromAscii(buffer));
break;
}
case 0x35: // ChangeGame message received
{
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
m_selectedgame = std::string(buffer);
Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
// Tell the server if the game's been found
m_socket.Send((const char*)&data, 1);
CheckGameFound();
Event->SendEvent(GUI_UPDATE);
break;
}
case 0x40: // Ready message received
{
m_socket.Receive((char*)&buffer_size, 4, recv_size);
buffer = new char[buffer_size+1];
m_socket.Receive(buffer, buffer_size+1, recv_size);
if (recv_size > 1024)
{
delete[] buffer;
return;
}
Event->AppendText(wxString::FromAscii(buffer));
break;
}
case 0x50: // Everyone is Ready message received
{
// Load the game and start synching
m_netptr->LoadGame();
break;
}
case 0xA1: // Received pad data from host in versus mode
{
if (m_data_received)
wxThread::Sleep(10);
m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
m_data_received = true;
#ifdef NET_DEBUG
char sent[64];
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
Event->AppendText(wxString::FromAscii(sent));
#endif
break;
}
}
delete[] buffer;
}
void ServerSide::OnServerData(int sock, unsigned char data)
{
size_t recv_size;
char *buffer = NULL;
unsigned char sent;
unsigned int four_bytes;
switch (data)
{
case 0x15: // Ping Request
{
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
m_client[sock].socket.Send((const char*)&four_bytes, 4);
break;
}
case 0x20: // IP request response
{
buffer = new char[24];
// Read IP Address
m_client[sock].socket.Receive(buffer, 24, recv_size);
Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
break;
}
case 0x30: // Chat message
{
buffer = new char[1024];
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
if (recv_size > 1024)
{
//something wrong...
delete[] buffer;
return;
}
sent = 0x30;
// Send to all
for (int i=0; i < m_numplayers ; i++)
{
if (i == sock)
continue;
m_client[i].socket.Send((const char*)&sent, 1);
m_client[1].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(buffer, recv_size);
}
Event->AppendText(wxString::FromAscii(buffer));
break;
}
case 0x35: // Change game response received
{
// Receive isGameFound response (0x1F / 0x1A)
m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
// If game is not found
if (sent != 0x1F)
{
sent = 0x30;
wxString error_str = wxString::Format(
wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
four_bytes = (int)error_str.size();
for (int i=0; i < 2; i++)
Event->AppendText(error_str);
// Send to all
for (int i=0; i < m_numplayers ; i++)
{
if (i == sock)
continue;
m_client[i].socket.Send((const char*)&sent, 1);
m_client[i].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
}
}
break;
}
case 0x40: // Ready message received
{
std::string buffer_str;
m_client[sock].ready = !m_client[sock].ready;
if (m_client[sock].ready)
buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
else
buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
four_bytes = (int)buffer_str.size();
// Send to all
for (int i=0; i < m_numplayers ; i++)
{
m_client[i].socket.Send((const char*)&data, 1);
m_client[i].socket.Send((const char*)&four_bytes, 4);
m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
}
Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
IsEveryoneReady();
break;
}
case 0xA1: // Received pad data from a client
{
if (m_data_received)
wxThread::Sleep(10);
m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
m_data_received = true;
#ifdef NET_DEBUG
char sent[64];
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
Event->AppendText(wxString::FromAscii(sent));
#endif
break;
}
}
delete[] buffer;
}
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
+317 -317
View File
@@ -1,317 +1,317 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _NETWINDOW_H_
#define _NETWINDOW_H_
#include <SFML/Network.hpp>
#include <string>
#include <wx/wx.h>
#include <wx/sizer.h>
#include <wx/dialog.h>
#include <wx/notebook.h>
#include <wx/gbsizer.h>
#include <wx/listbox.h>
#include <wx/thread.h>
#include "Globals.h"
#include "BootManager.h"
#include "Common.h"
#include "Core.h"
#include "pluginspecs_pad.h"
#include "HW/SI.h"
#include "HW/SI_Device.h"
#include "HW/SI_DeviceGCController.h"
#include "Timer.h"
#ifdef _DEBUG
#define NET_DEBUG
#endif
// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay,
// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
// #define USE_TCP
class NetPlay;
struct Netpads {
int nHi[128];
int nLow[128];
};
struct Clients {
std::string nick;
sf::SocketTCP socket;
unsigned short port;
sf::IPAddress address;
bool ready;
};
class NetEvent
{
public:
NetEvent(NetPlay* netptr) { m_netptr = netptr; }
~NetEvent() {};
void SendEvent(int EventType, std::string="NULL", int=NULL);
void AppendText(const wxString text);
private:
NetPlay *m_netptr;
};
class ServerSide : public wxThread
{
public:
ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
~ServerSide() {};
virtual void *Entry();
void Write(int socknb, const char *data, size_t size, long *ping=NULL);
void WriteUDP(int socknb, const char *data, size_t size);
bool isNewPadData(u32 *netValues, bool current, int client=0);
private:
bool SyncValues(unsigned char, sf::IPAddress);
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
char GetSocket(sf::SocketTCP Socket);
void OnServerData(int sock, unsigned char data);
void IsEveryoneReady();
NetPlay *m_netptr;
NetEvent *Event;
u32 m_netvalues[3][3];
bool m_data_received; // New Pad data received ?
unsigned char m_numplayers;
int m_netmodel;
std::string m_nick;
Clients m_client[3]; // Connected client objects
sf::SelectorTCP m_selector;
sf::SocketTCP m_socket; // Server 'listening' socket
sf::SocketUDP m_socketUDP;
wxCriticalSection m_CriticalSection;
};
class ClientSide : public wxThread
{
public:
ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
~ClientSide() {}
virtual void *Entry();
void Write(const char *data, size_t size, long *ping=NULL);
void WriteUDP(const char *data, size_t size);
bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
private:
bool SyncValues();
void CheckGameFound();
void OnClientData(unsigned char data);
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
NetPlay *m_netptr;
NetEvent *Event;
u32 m_netvalues[3][3];
bool m_data_received; // New Pad data received ?
unsigned char m_numplayers;
int m_netmodel;
std::string m_nick;
std::string m_hostnick;
std::string m_selectedgame;
sf::SelectorTCP m_selector;
sf::SocketTCP m_socket; // Client I/O socket
sf::SocketUDP m_socketUDP;
unsigned short m_port;
std::string m_addr; // Contains the server addr
wxCriticalSection m_CriticalSection;
};
class NetPlay : public wxFrame
{
public:
NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
~NetPlay();
void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
void AppendText(const wxString text) { m_Logging->AppendText(text); }
// Send and receive pads values
bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
void ChangeSelectedGame(std::string game);
void IsGameFound(unsigned char*, std::string);
std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
void LoadGame();
protected:
// Protects our vars from being fuxored by threads
wxCriticalSection m_critical;
// this draws the GUI, ya rly
void DrawGUI();
void DrawNetWindow();
// event handlers
void OnGUIEvent(wxCommandEvent& event);
void OnDisconnect(wxCommandEvent& event);
void OnNetEvent(wxCommandEvent& event);
void OnQuit(wxCloseEvent& event);
void OnJoin(wxCommandEvent& event);
void OnHost(wxCommandEvent& event);
// Net play vars (used ingame)
int m_frame;
int m_lastframe;
Common::Timer m_timer;
int m_loopframe;
int m_frameDelay;
bool m_data_received;// True if first frame data received
// Basic vars
std::string m_paths; // Game paths list
std::string m_games; // Game names list
std::string m_selectedGame;// Selected game's string
std::string m_hostaddr; // Used with OnGetIP to cache it
bool m_ready, m_clients_ready;
std::string m_nick;
int m_NetModel; // Using P2P model (0) or Server model (1)
int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
std::string m_address; // The address entered into connection box
unsigned short m_port;
Netpads m_pads[4]; // this struct is used to save synced pad values
IniFile ConfigIni;
// Sockets objects
ServerSide *m_sock_server;
ClientSide *m_sock_client;
// -----------
// GUI objects
// -----------
wxNotebook *m_Notebook;
wxPanel *m_Tab_Connect;
wxPanel *m_Tab_Host;
wxStaticText *m_SetNick_text;
wxTextCtrl *m_SetNick;
wxChoice *m_NetMode;
// Host tab :
wxArrayString m_GameList_str;
wxStaticText *m_GameList_text;
wxListBox *m_GameList;
wxStaticText *m_SetPort_text;
wxTextCtrl *m_SetPort;
wxButton *m_HostGame;
// Connect tab :
wxTextCtrl *m_ConAddr;
wxStaticText *m_ConAddr_text;
wxButton *m_JoinGame;
wxCheckBox *m_UseRandomPort;
// Connection window
wxButton *m_Game_str;
wxTextCtrl *m_Logging;
wxTextCtrl *m_Chat;
wxButton *m_Chat_ok;
// Right part
wxButton *m_wtfismyip;
wxButton *m_ChangeGame;
// Left Part
wxButton *m_Disconnect;
wxStaticText *m_ConInfo_text;
wxButton *m_GetPing;
wxCheckBox *m_Ready;
wxCheckBox *m_RecordGame;
// wxWidgets event table
DECLARE_EVENT_TABLE()
};
class GameListPopup : public wxDialog
{
public:
GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
~GameListPopup() {}
protected:
void OnButtons(wxCommandEvent& event);
wxArrayString m_GameList_str;
NetPlay* m_netParent;
wxListBox *m_GameList;
wxButton *m_Accept;
wxButton *m_Cancel;
DECLARE_EVENT_TABLE()
};
enum
{
ID_NOTEBOOK,
ID_TAB_HOST,
ID_TAB_CONN,
ID_BUTTON_HOST,
ID_BUTTON_JOIN,
ID_NETMODE,
ID_GAMELIST,
ID_LOGGING_TXT,
ID_CHAT,
ID_SETNICK,
ID_SETPORT,
ID_CONNADDR,
ID_CONNINFO_TXT,
ID_USE_RANDOMPORT,
ID_BUTTON_GETPING,
ID_BUTTON_GETIP,
ID_CHANGEGAME,
ID_BUTTON_QUIT,
ID_BUTTON_CHAT,
ID_READY,
ID_RECORD,
ID_SOCKET,
ID_SERVER,
HOST_FULL = 200, // ...
HOST_ERROR, // Sent on socket error
HOST_DISCONNECTED,
HOST_NEWPLAYER,
HOST_PLAYERLEFT,
CLIENTS_READY,
CLIENTS_NOTREADY,
GUI_UPDATE, // Refresh the shown selectedgame on GUI
ADD_TEXT, // Add text to m_Logging (string)
ADD_INFO, // Sent when updating net infos (string)
NET_EVENT
};
#endif // _NETWINDOW_H_
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _NETWINDOW_H_
#define _NETWINDOW_H_
#include <SFML/Network.hpp>
#include <string>
#include <wx/wx.h>
#include <wx/sizer.h>
#include <wx/dialog.h>
#include <wx/notebook.h>
#include <wx/gbsizer.h>
#include <wx/listbox.h>
#include <wx/thread.h>
#include "Globals.h"
#include "BootManager.h"
#include "Common.h"
#include "Core.h"
#include "pluginspecs_pad.h"
#include "HW/SI.h"
#include "HW/SI_Device.h"
#include "HW/SI_DeviceGCController.h"
#include "Timer.h"
#ifdef _DEBUG
#define NET_DEBUG
#endif
// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay,
// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
// #define USE_TCP
class NetPlay;
struct Netpads {
int nHi[128];
int nLow[128];
};
struct Clients {
std::string nick;
sf::SocketTCP socket;
unsigned short port;
sf::IPAddress address;
bool ready;
};
class NetEvent
{
public:
NetEvent(NetPlay* netptr) { m_netptr = netptr; }
~NetEvent() {};
void SendEvent(int EventType, std::string="NULL", int=NULL);
void AppendText(const wxString text);
private:
NetPlay *m_netptr;
};
class ServerSide : public wxThread
{
public:
ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
~ServerSide() {};
virtual void *Entry();
void Write(int socknb, const char *data, size_t size, long *ping=NULL);
void WriteUDP(int socknb, const char *data, size_t size);
bool isNewPadData(u32 *netValues, bool current, int client=0);
private:
bool SyncValues(unsigned char, sf::IPAddress);
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
char GetSocket(sf::SocketTCP Socket);
void OnServerData(int sock, unsigned char data);
void IsEveryoneReady();
NetPlay *m_netptr;
NetEvent *Event;
u32 m_netvalues[3][3];
bool m_data_received; // New Pad data received ?
unsigned char m_numplayers;
int m_netmodel;
std::string m_nick;
Clients m_client[3]; // Connected client objects
sf::SelectorTCP m_selector;
sf::SocketTCP m_socket; // Server 'listening' socket
sf::SocketUDP m_socketUDP;
wxCriticalSection m_CriticalSection;
};
class ClientSide : public wxThread
{
public:
ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
~ClientSide() {}
virtual void *Entry();
void Write(const char *data, size_t size, long *ping=NULL);
void WriteUDP(const char *data, size_t size);
bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
private:
bool SyncValues();
void CheckGameFound();
void OnClientData(unsigned char data);
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
NetPlay *m_netptr;
NetEvent *Event;
u32 m_netvalues[3][3];
bool m_data_received; // New Pad data received ?
unsigned char m_numplayers;
int m_netmodel;
std::string m_nick;
std::string m_hostnick;
std::string m_selectedgame;
sf::SelectorTCP m_selector;
sf::SocketTCP m_socket; // Client I/O socket
sf::SocketUDP m_socketUDP;
unsigned short m_port;
std::string m_addr; // Contains the server addr
wxCriticalSection m_CriticalSection;
};
class NetPlay : public wxFrame
{
public:
NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
~NetPlay();
void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
void AppendText(const wxString text) { m_Logging->AppendText(text); }
// Send and receive pads values
bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
void ChangeSelectedGame(std::string game);
void IsGameFound(unsigned char*, std::string);
std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
void LoadGame();
protected:
// Protects our vars from being fuxored by threads
wxCriticalSection m_critical;
// this draws the GUI, ya rly
void DrawGUI();
void DrawNetWindow();
// event handlers
void OnGUIEvent(wxCommandEvent& event);
void OnDisconnect(wxCommandEvent& event);
void OnNetEvent(wxCommandEvent& event);
void OnQuit(wxCloseEvent& event);
void OnJoin(wxCommandEvent& event);
void OnHost(wxCommandEvent& event);
// Net play vars (used ingame)
int m_frame;
int m_lastframe;
Common::Timer m_timer;
int m_loopframe;
int m_frameDelay;
bool m_data_received;// True if first frame data received
// Basic vars
std::string m_paths; // Game paths list
std::string m_games; // Game names list
std::string m_selectedGame;// Selected game's string
std::string m_hostaddr; // Used with OnGetIP to cache it
bool m_ready, m_clients_ready;
std::string m_nick;
int m_NetModel; // Using P2P model (0) or Server model (1)
int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
std::string m_address; // The address entered into connection box
unsigned short m_port;
Netpads m_pads[4]; // this struct is used to save synced pad values
IniFile ConfigIni;
// Sockets objects
ServerSide *m_sock_server;
ClientSide *m_sock_client;
// -----------
// GUI objects
// -----------
wxNotebook *m_Notebook;
wxPanel *m_Tab_Connect;
wxPanel *m_Tab_Host;
wxStaticText *m_SetNick_text;
wxTextCtrl *m_SetNick;
wxChoice *m_NetMode;
// Host tab :
wxArrayString m_GameList_str;
wxStaticText *m_GameList_text;
wxListBox *m_GameList;
wxStaticText *m_SetPort_text;
wxTextCtrl *m_SetPort;
wxButton *m_HostGame;
// Connect tab :
wxTextCtrl *m_ConAddr;
wxStaticText *m_ConAddr_text;
wxButton *m_JoinGame;
wxCheckBox *m_UseRandomPort;
// Connection window
wxButton *m_Game_str;
wxTextCtrl *m_Logging;
wxTextCtrl *m_Chat;
wxButton *m_Chat_ok;
// Right part
wxButton *m_wtfismyip;
wxButton *m_ChangeGame;
// Left Part
wxButton *m_Disconnect;
wxStaticText *m_ConInfo_text;
wxButton *m_GetPing;
wxCheckBox *m_Ready;
wxCheckBox *m_RecordGame;
// wxWidgets event table
DECLARE_EVENT_TABLE()
};
class GameListPopup : public wxDialog
{
public:
GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
~GameListPopup() {}
protected:
void OnButtons(wxCommandEvent& event);
wxArrayString m_GameList_str;
NetPlay* m_netParent;
wxListBox *m_GameList;
wxButton *m_Accept;
wxButton *m_Cancel;
DECLARE_EVENT_TABLE()
};
enum
{
ID_NOTEBOOK,
ID_TAB_HOST,
ID_TAB_CONN,
ID_BUTTON_HOST,
ID_BUTTON_JOIN,
ID_NETMODE,
ID_GAMELIST,
ID_LOGGING_TXT,
ID_CHAT,
ID_SETNICK,
ID_SETPORT,
ID_CONNADDR,
ID_CONNINFO_TXT,
ID_USE_RANDOMPORT,
ID_BUTTON_GETPING,
ID_BUTTON_GETIP,
ID_CHANGEGAME,
ID_BUTTON_QUIT,
ID_BUTTON_CHAT,
ID_READY,
ID_RECORD,
ID_SOCKET,
ID_SERVER,
HOST_FULL = 200, // ...
HOST_ERROR, // Sent on socket error
HOST_DISCONNECTED,
HOST_NEWPLAYER,
HOST_PLAYERLEFT,
CLIENTS_READY,
CLIENTS_NOTREADY,
GUI_UPDATE, // Refresh the shown selectedgame on GUI
ADD_TEXT, // Add text to m_Logging (string)
ADD_INFO, // Sent when updating net infos (string)
NET_EVENT
};
#endif // _NETWINDOW_H_
+126 -126
View File
@@ -1,127 +1,127 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef __SUMMARIZE_H__
#define __SUMMARIZE_H__
std::string Summarize_Plug()
{
return StringFromFormat(
"Plugin Information\n\n"
"Default GFX Plugin: %s\n"
"Default DSP Plugin: %s\n"
"Default PAD Plugin: %s\n"
"Default WiiMote Plugin: %s\n\n"
"Current GFX Plugin: %s\n"
"Current DSP Plugin: %s\n"
"Current PAD Plugin[0]: %s\n"
"Current PAD Plugin[1]: %s\n"
"Current PAD Plugin[2]: %s\n"
"Current PAD Plugin[3]: %s\n"
"Current WiiMote Plugin[0]: %s\n",
SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
Core::GetStartupParameter().m_strVideoPlugin.c_str(),
Core::GetStartupParameter().m_strDSPPlugin.c_str(),
Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
);
}
std::string Summarize_Settings()
{
return StringFromFormat(
"Dolphin Settings\n\n"
"Always HLE Bios: %s\n"
"Use Dynarec: %s\n"
"Use Dual Core: %s\n"
"DSP Thread: %s\n"
"Skip Idle: %s\n"
"Lock Threads: %s\n"
"Use Dual Core: %s\n"
"Default GCM: %s\n"
"DVD Root: %s\n"
"Optimize Quantizers: %s\n"
"Enable Cheats: %s\n"
"Selected Language: %d\n"
"Memcard A: %s\n"
"Memcard B: %s\n"
"Slot A: %d\n"
"Slot B: %d\n"
"Serial Port 1: %d\n"
"Run Compare Server: %s\n"
"Run Compare Client: %s\n"
"TLB Hack: %s\n"
"Frame Limit: %d\n"
"[Wii]Widescreen: %s\n"
"[Wii]Progressive Scan: %s\n",
Core::GetStartupParameter().bHLEBios?"True":"False",
Core::GetStartupParameter().bUseJIT?"True":"False",
Core::GetStartupParameter().bUseDualCore?"True":"False",
Core::GetStartupParameter().bDSPThread?"True":"False",
Core::GetStartupParameter().bSkipIdle?"True":"False",
Core::GetStartupParameter().bLockThreads?"True":"False",
Core::GetStartupParameter().bUseDualCore?"True":"False",
Core::GetStartupParameter().m_strDefaultGCM.c_str(),
Core::GetStartupParameter().m_strDVDRoot.c_str(),
Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
Core::GetStartupParameter().bEnableCheats?"True":"False",
Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
SConfig::GetInstance().m_strMemoryCardA.c_str(),
SConfig::GetInstance().m_strMemoryCardB.c_str(),
SConfig::GetInstance().m_EXIDevice[0], //FIXME
SConfig::GetInstance().m_EXIDevice[1], //FIXME
SConfig::GetInstance().m_EXIDevice[2], //FIXME
Core::GetStartupParameter().bRunCompareServer?"True":"False",
Core::GetStartupParameter().bRunCompareClient?"True":"False",
Core::GetStartupParameter().iTLBHack?"True":"False",
SConfig::GetInstance().m_Framelimit*5,
Core::GetStartupParameter().bWidescreen?"True":"False",
Core::GetStartupParameter().bProgressiveScan?"True":"False"
);
}
std::string Summarize_CPU()
{
return StringFromFormat(
"Processor Information: \n%s\n",
cpu_info.Summarize().c_str()
);
}
std::string Summarize_Drives()
{
char ** drives = cdio_get_devices();
std::string drive;
for (int i = 0; drives[i] != NULL && i < 24; i++)
{
drive += StringFromFormat(
"CD/DVD Drive%d: %s\n",
i+1,
drives[i]
);
}
return drive;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef __SUMMARIZE_H__
#define __SUMMARIZE_H__
std::string Summarize_Plug()
{
return StringFromFormat(
"Plugin Information\n\n"
"Default GFX Plugin: %s\n"
"Default DSP Plugin: %s\n"
"Default PAD Plugin: %s\n"
"Default WiiMote Plugin: %s\n\n"
"Current GFX Plugin: %s\n"
"Current DSP Plugin: %s\n"
"Current PAD Plugin[0]: %s\n"
"Current PAD Plugin[1]: %s\n"
"Current PAD Plugin[2]: %s\n"
"Current PAD Plugin[3]: %s\n"
"Current WiiMote Plugin[0]: %s\n",
SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
Core::GetStartupParameter().m_strVideoPlugin.c_str(),
Core::GetStartupParameter().m_strDSPPlugin.c_str(),
Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
);
}
std::string Summarize_Settings()
{
return StringFromFormat(
"Dolphin Settings\n\n"
"Always HLE Bios: %s\n"
"Use Dynarec: %s\n"
"Use Dual Core: %s\n"
"DSP Thread: %s\n"
"Skip Idle: %s\n"
"Lock Threads: %s\n"
"Use Dual Core: %s\n"
"Default GCM: %s\n"
"DVD Root: %s\n"
"Optimize Quantizers: %s\n"
"Enable Cheats: %s\n"
"Selected Language: %d\n"
"Memcard A: %s\n"
"Memcard B: %s\n"
"Slot A: %d\n"
"Slot B: %d\n"
"Serial Port 1: %d\n"
"Run Compare Server: %s\n"
"Run Compare Client: %s\n"
"TLB Hack: %s\n"
"Frame Limit: %d\n"
"[Wii]Widescreen: %s\n"
"[Wii]Progressive Scan: %s\n",
Core::GetStartupParameter().bHLEBios?"True":"False",
Core::GetStartupParameter().bUseJIT?"True":"False",
Core::GetStartupParameter().bUseDualCore?"True":"False",
Core::GetStartupParameter().bDSPThread?"True":"False",
Core::GetStartupParameter().bSkipIdle?"True":"False",
Core::GetStartupParameter().bLockThreads?"True":"False",
Core::GetStartupParameter().bUseDualCore?"True":"False",
Core::GetStartupParameter().m_strDefaultGCM.c_str(),
Core::GetStartupParameter().m_strDVDRoot.c_str(),
Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
Core::GetStartupParameter().bEnableCheats?"True":"False",
Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
SConfig::GetInstance().m_strMemoryCardA.c_str(),
SConfig::GetInstance().m_strMemoryCardB.c_str(),
SConfig::GetInstance().m_EXIDevice[0], //FIXME
SConfig::GetInstance().m_EXIDevice[1], //FIXME
SConfig::GetInstance().m_EXIDevice[2], //FIXME
Core::GetStartupParameter().bRunCompareServer?"True":"False",
Core::GetStartupParameter().bRunCompareClient?"True":"False",
Core::GetStartupParameter().iTLBHack?"True":"False",
SConfig::GetInstance().m_Framelimit*5,
Core::GetStartupParameter().bWidescreen?"True":"False",
Core::GetStartupParameter().bProgressiveScan?"True":"False"
);
}
std::string Summarize_CPU()
{
return StringFromFormat(
"Processor Information: \n%s\n",
cpu_info.Summarize().c_str()
);
}
std::string Summarize_Drives()
{
char ** drives = cdio_get_devices();
std::string drive;
for (int i = 0; drives[i] != NULL && i < 24; i++)
{
drive += StringFromFormat(
"CD/DVD Drive%d: %s\n",
i+1,
drives[i]
);
}
return drive;
}
#endif //__SUMMARIZE_H__
+129 -129
View File
@@ -1,129 +1,129 @@
/* XPM */
static const char *Dolphin_xpm[] = {
"32 32 94 2",
" c None",
". c #000000",
"+ c #1A496C",
"@ c #091A27",
"# c #3AA4F0",
"$ c #3AA3EF",
"% c #3CA1EA",
"& c #1A4A6D",
"* c #3AA2ED",
"= c #F7FAFA",
"- c #FFFFFF",
"; c #FDFDFD",
"> c #49A1E0",
", c #3BA2EC",
"' c #FBFDFC",
") c #FEFFFD",
"! c #4EA3E0",
"~ c #3DA1E9",
"{ c #D1E1EB",
"] c #8ABBDE",
"^ c #F2F6F7",
"/ c #FAFBFC",
"( c #CEDEEA",
"_ c #E5EEF2",
": c #BBD2E1",
"< c #B3CFE5",
"[ c #FFFFFE",
"} c #FEFFFE",
"| c #E8F0F3",
"1 c #E4ECF1",
"2 c #E5EDF0",
"3 c #E9F0F3",
"4 c #FEFEFE",
"5 c #F9FBFB",
"6 c #B0CCE0",
"7 c #FEFEFF",
"8 c #F9FAFB",
"9 c #43A1E4",
"0 c #EFF3F6",
"a c #F0F5F7",
"b c #97C1DE",
"c c #FEFEFD",
"d c #FDFDFC",
"e c #97BEDB",
"f c #FBFCFC",
"g c #EDF3F6",
"h c #6EADDA",
"i c #F3F6F8",
"j c #3BA1EA",
"k c #6EADDB",
"l c #F4F8F9",
"m c #F1F6F7",
"n c #3FA1E7",
"o c #9BC1DD",
"p c #FCFDFC",
"q c #FBFDFB",
"r c #B9D1E1",
"s c #E0EBF2",
"t c #D3E3EF",
"u c #FFFEFE",
"v c #F2F7F7",
"w c #D5E4F0",
"x c #F6F9F9",
"y c #BDD5E5",
"z c #EBF1F4",
"A c #DEEAF2",
"B c #AAC9DE",
"C c #FEFFFF",
"D c #EFF4F6",
"E c #F8FAFB",
"F c #A0C4E1",
"G c #D6E5F0",
"H c #FAFCFC",
"I c #BDD5E7",
"J c #EEF3F7",
"K c #F3F7FA",
"L c #C7D8E4",
"M c #CDDEEC",
"N c #DAE6ED",
"O c #9AC2DF",
"P c #E8EFF4",
"Q c #ACCDE3",
"R c #8DBBDC",
"S c #D5E3EB",
"T c #FDFFFE",
"U c #FCFDFD",
"V c #FEFDFD",
"W c #F7F9FA",
"X c #FDFEFD",
"Y c #E7EFF4",
"Z c #A4C7E0",
"` c #F9FDFB",
" . c #F6FBFC",
".. c #B8D1E3",
" . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
" . . . . . . . . . . . . . . . . . . . . . . . . "};
/* XPM */
static const char *Dolphin_xpm[] = {
"32 32 94 2",
" c None",
". c #000000",
"+ c #1A496C",
"@ c #091A27",
"# c #3AA4F0",
"$ c #3AA3EF",
"% c #3CA1EA",
"& c #1A4A6D",
"* c #3AA2ED",
"= c #F7FAFA",
"- c #FFFFFF",
"; c #FDFDFD",
"> c #49A1E0",
", c #3BA2EC",
"' c #FBFDFC",
") c #FEFFFD",
"! c #4EA3E0",
"~ c #3DA1E9",
"{ c #D1E1EB",
"] c #8ABBDE",
"^ c #F2F6F7",
"/ c #FAFBFC",
"( c #CEDEEA",
"_ c #E5EEF2",
": c #BBD2E1",
"< c #B3CFE5",
"[ c #FFFFFE",
"} c #FEFFFE",
"| c #E8F0F3",
"1 c #E4ECF1",
"2 c #E5EDF0",
"3 c #E9F0F3",
"4 c #FEFEFE",
"5 c #F9FBFB",
"6 c #B0CCE0",
"7 c #FEFEFF",
"8 c #F9FAFB",
"9 c #43A1E4",
"0 c #EFF3F6",
"a c #F0F5F7",
"b c #97C1DE",
"c c #FEFEFD",
"d c #FDFDFC",
"e c #97BEDB",
"f c #FBFCFC",
"g c #EDF3F6",
"h c #6EADDA",
"i c #F3F6F8",
"j c #3BA1EA",
"k c #6EADDB",
"l c #F4F8F9",
"m c #F1F6F7",
"n c #3FA1E7",
"o c #9BC1DD",
"p c #FCFDFC",
"q c #FBFDFB",
"r c #B9D1E1",
"s c #E0EBF2",
"t c #D3E3EF",
"u c #FFFEFE",
"v c #F2F7F7",
"w c #D5E4F0",
"x c #F6F9F9",
"y c #BDD5E5",
"z c #EBF1F4",
"A c #DEEAF2",
"B c #AAC9DE",
"C c #FEFFFF",
"D c #EFF4F6",
"E c #F8FAFB",
"F c #A0C4E1",
"G c #D6E5F0",
"H c #FAFCFC",
"I c #BDD5E7",
"J c #EEF3F7",
"K c #F3F7FA",
"L c #C7D8E4",
"M c #CDDEEC",
"N c #DAE6ED",
"O c #9AC2DF",
"P c #E8EFF4",
"Q c #ACCDE3",
"R c #8DBBDC",
"S c #D5E3EB",
"T c #FDFFFE",
"U c #FCFDFD",
"V c #FEFDFD",
"W c #F7F9FA",
"X c #FDFEFD",
"Y c #E7EFF4",
"Z c #A4C7E0",
"` c #F9FDFB",
" . c #F6FBFC",
".. c #B8D1E3",
" . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
" . . . . . . . . . . . . . . . . . . . . . . . . "};
+83 -83
View File
@@ -1,83 +1,83 @@
/* XPM */
static const char *const Flag_Europe_xpm[] = {
"96 32 48 1",
" c None",
". c #000000",
"+ c #0000FD",
"@ c #0000FF",
"# c #0808F7",
"$ c #5C5CA3",
"% c #1717E8",
"& c #767680",
"* c #EDED00",
"= c #A5A54D",
"- c #2E2EB9",
"; c #96961A",
"> c #4A4A8E",
", c #0000FB",
"' c #0000F4",
") c #0808EC",
"! c #5C5C9B",
"~ c #1717DD",
"{ c #0000EE",
"] c #767677",
"^ c #A5A547",
"/ c #0000DD",
"( c #2E2EA0",
"_ c #969616",
": c #4A4A7B",
"< c #0000D2",
"[ c #0000C6",
"} c #0808BF",
"| c #5C5C7E",
"1 c #1717B4",
"2 c #0000B9",
"3 c #76765C",
"4 c #A5A537",
"5 c #0808B3",
"6 c #5C5C76",
"7 c #1717A8",
"8 c #0000A9",
"9 c #2E2E7A",
"0 c #969611",
"a c #4A4A5E",
"b c #767654",
"c c #A5A533",
"d c #000097",
"e c #2E2E6D",
"f c #96960F",
"g c #4A4A54",
"h c #000081",
"i c #000077",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".++++++++++++++++++++++++++++++. ",
".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
".''''''')!~''''''''')!~''''''''. ",
".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
".///////(_://///////(_:////////. ",
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
".2222222223*4256723*42222222222. ",
".88888888890a8b*c890a8888888888. ",
".dddddddddddddefgdddddddddddddd. ",
".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
/* XPM */
static const char *const Flag_Europe_xpm[] = {
"96 32 48 1",
" c None",
". c #000000",
"+ c #0000FD",
"@ c #0000FF",
"# c #0808F7",
"$ c #5C5CA3",
"% c #1717E8",
"& c #767680",
"* c #EDED00",
"= c #A5A54D",
"- c #2E2EB9",
"; c #96961A",
"> c #4A4A8E",
", c #0000FB",
"' c #0000F4",
") c #0808EC",
"! c #5C5C9B",
"~ c #1717DD",
"{ c #0000EE",
"] c #767677",
"^ c #A5A547",
"/ c #0000DD",
"( c #2E2EA0",
"_ c #969616",
": c #4A4A7B",
"< c #0000D2",
"[ c #0000C6",
"} c #0808BF",
"| c #5C5C7E",
"1 c #1717B4",
"2 c #0000B9",
"3 c #76765C",
"4 c #A5A537",
"5 c #0808B3",
"6 c #5C5C76",
"7 c #1717A8",
"8 c #0000A9",
"9 c #2E2E7A",
"0 c #969611",
"a c #4A4A5E",
"b c #767654",
"c c #A5A533",
"d c #000097",
"e c #2E2E6D",
"f c #96960F",
"g c #4A4A54",
"h c #000081",
"i c #000077",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".++++++++++++++++++++++++++++++. ",
".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
".''''''')!~''''''''')!~''''''''. ",
".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
".///////(_://///////(_:////////. ",
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
".2222222223*4256723*42222222222. ",
".88888888890a8b*c890a8888888888. ",
".dddddddddddddefgdddddddddddddd. ",
".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
+80 -80
View File
@@ -1,80 +1,80 @@
/* XPM */
static const char *const Flag_France_xpm[] = {
"96 32 45 1",
" c None",
". c #000000",
"+ c #0000FF",
"@ c #FFFFFF",
"# c #FF0000",
"$ c #0000FC",
"% c #0000F8",
"& c #FCFCFC",
"* c #FC0000",
"= c #0000F2",
"- c #F8F8F8",
"; c #F80000",
"> c #0000EC",
", c #F2F2F2",
"' c #F20000",
") c #0000E3",
"! c #ECECEC",
"~ c #EC0000",
"{ c #0000DB",
"] c #E3E3E3",
"^ c #E30000",
"/ c #0000D2",
"( c #DBDBDB",
"_ c #DB0000",
": c #0000C8",
"< c #D2D2D2",
"[ c #D20000",
"} c #0000BD",
"| c #C8C8C8",
"1 c #C80000",
"2 c #0000B1",
"3 c #BDBDBD",
"4 c #BD0000",
"5 c #0000A3",
"6 c #B1B1B1",
"7 c #B10000",
"8 c #000093",
"9 c #A3A3A3",
"0 c #A30000",
"a c #000080",
"b c #939393",
"c c #930000",
"d c #000077",
"e c #808080",
"f c #800000",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ",
".$$$$$$$$$$@@@@@@@@@@@#########. ",
".%%%%%%%%%%&&&&&&&&&&&*********. ",
".==========-----------;;;;;;;;;. ",
".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
".//////////(((((((((((_________. ",
".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
".}}}}}}}}}}|||||||||||111111111. ",
".222222222233333333333444444444. ",
".555555555566666666666777777777. ",
".888888888899999999999000000000. ",
".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
".ddddddddddeeeeeeeeeeefffffffff. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
/* XPM */
static const char *const Flag_France_xpm[] = {
"96 32 45 1",
" c None",
". c #000000",
"+ c #0000FF",
"@ c #FFFFFF",
"# c #FF0000",
"$ c #0000FC",
"% c #0000F8",
"& c #FCFCFC",
"* c #FC0000",
"= c #0000F2",
"- c #F8F8F8",
"; c #F80000",
"> c #0000EC",
", c #F2F2F2",
"' c #F20000",
") c #0000E3",
"! c #ECECEC",
"~ c #EC0000",
"{ c #0000DB",
"] c #E3E3E3",
"^ c #E30000",
"/ c #0000D2",
"( c #DBDBDB",
"_ c #DB0000",
": c #0000C8",
"< c #D2D2D2",
"[ c #D20000",
"} c #0000BD",
"| c #C8C8C8",
"1 c #C80000",
"2 c #0000B1",
"3 c #BDBDBD",
"4 c #BD0000",
"5 c #0000A3",
"6 c #B1B1B1",
"7 c #B10000",
"8 c #000093",
"9 c #A3A3A3",
"0 c #A30000",
"a c #000080",
"b c #939393",
"c c #930000",
"d c #000077",
"e c #808080",
"f c #800000",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ",
".++++++++++@@@@@@@@@@@#########. ",
".$$$$$$$$$$@@@@@@@@@@@#########. ",
".%%%%%%%%%%&&&&&&&&&&&*********. ",
".==========-----------;;;;;;;;;. ",
".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
".//////////(((((((((((_________. ",
".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
".}}}}}}}}}}|||||||||||111111111. ",
".222222222233333333333444444444. ",
".555555555566666666666777777777. ",
".888888888899999999999000000000. ",
".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
".ddddddddddeeeeeeeeeeefffffffff. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
+102 -102
View File
@@ -1,102 +1,102 @@
/* XPM */
static const char * const Flag_Japan_xpm[] = {
"96 32 67 1",
" c None",
". c #000000",
"+ c #FFFFFF",
"@ c #FECACA",
"# c #FD8080",
"$ c #FD6161",
"% c #FD7676",
"& c #FEB6B6",
"* c #FEFEFE",
"= c #FFEDED",
"- c #FF4C4C",
"; c #FF0000",
"> c #FF2F2F",
", c #FFD7D7",
"' c #FEF5F5",
") c #FE2E2E",
"! c #FE1313",
"~ c #FEDDDD",
"{ c #F9F9F9",
"] c #FC7777",
"^ c #FD4545",
"/ c #F4F4F4",
"( c #F4F3F3",
"_ c #FA1313",
": c #FB0000",
"< c #FA0000",
"[ c #F4D4D4",
"} c #EFEFEF",
"| c #EFCFCF",
"1 c #F10000",
"2 c #EF9F9F",
"3 c #E4E4E4",
"4 c #E2BEBE",
"5 c #DD0000",
"6 c #E19090",
"7 c #D9D9D9",
"8 c #D8D0D0",
"9 c #CA0404",
"0 c #CA0000",
"a c #D5A9A9",
"b c #D0D0D0",
"c c #BC4242",
"d c #B40000",
"e c #B71A1A",
"f c #CFCFCF",
"g c #C6C6C6",
"h c #BEA7A7",
"i c #990808",
"j c #980000",
"k c #B78787",
"l c #BBBBBB",
"m c #A88989",
"n c #7B0B0B",
"o c #770000",
"p c #780202",
"q c #9E6B6B",
"r c #AEAEAE",
"s c #A89C9C",
"t c #8F4E4E",
"u c #7F1B1B",
"v c #7A0A0A",
"w c #7D1515",
"x c #8B4242",
"y c #A48F8F",
"z c #A0A0A0",
"A c #8F8F8F",
"B c #7C7C7C",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".++++++++++++++++++++++++++++++. ",
".++++++++++++++++++++++++++++++. ",
".++++++++++++++++++++++++++++++. ",
".++++++++++++@#$%&*++++++++++++. ",
".++++++++++=-;;;;;>,+++++++++++. ",
".*********');;;;;;;!~**********. ",
".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
".////////(_:::::::::<[/////////. ",
".}}}}}}}}|111111111112}}}}}}}}}. ",
".333333334555555555556333333333. ",
".77777777890000000000a777777777. ",
".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
".ggggggggghijjjjjjjjkgggggggggg. ",
".llllllllllmnooooopqlllllllllll. ",
".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
/* XPM */
static const char * const Flag_Japan_xpm[] = {
"96 32 67 1",
" c None",
". c #000000",
"+ c #FFFFFF",
"@ c #FECACA",
"# c #FD8080",
"$ c #FD6161",
"% c #FD7676",
"& c #FEB6B6",
"* c #FEFEFE",
"= c #FFEDED",
"- c #FF4C4C",
"; c #FF0000",
"> c #FF2F2F",
", c #FFD7D7",
"' c #FEF5F5",
") c #FE2E2E",
"! c #FE1313",
"~ c #FEDDDD",
"{ c #F9F9F9",
"] c #FC7777",
"^ c #FD4545",
"/ c #F4F4F4",
"( c #F4F3F3",
"_ c #FA1313",
": c #FB0000",
"< c #FA0000",
"[ c #F4D4D4",
"} c #EFEFEF",
"| c #EFCFCF",
"1 c #F10000",
"2 c #EF9F9F",
"3 c #E4E4E4",
"4 c #E2BEBE",
"5 c #DD0000",
"6 c #E19090",
"7 c #D9D9D9",
"8 c #D8D0D0",
"9 c #CA0404",
"0 c #CA0000",
"a c #D5A9A9",
"b c #D0D0D0",
"c c #BC4242",
"d c #B40000",
"e c #B71A1A",
"f c #CFCFCF",
"g c #C6C6C6",
"h c #BEA7A7",
"i c #990808",
"j c #980000",
"k c #B78787",
"l c #BBBBBB",
"m c #A88989",
"n c #7B0B0B",
"o c #770000",
"p c #780202",
"q c #9E6B6B",
"r c #AEAEAE",
"s c #A89C9C",
"t c #8F4E4E",
"u c #7F1B1B",
"v c #7A0A0A",
"w c #7D1515",
"x c #8B4242",
"y c #A48F8F",
"z c #A0A0A0",
"A c #8F8F8F",
"B c #7C7C7C",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".++++++++++++++++++++++++++++++. ",
".++++++++++++++++++++++++++++++. ",
".++++++++++++++++++++++++++++++. ",
".++++++++++++@#$%&*++++++++++++. ",
".++++++++++=-;;;;;>,+++++++++++. ",
".*********');;;;;;;!~**********. ",
".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
".////////(_:::::::::<[/////////. ",
".}}}}}}}}|111111111112}}}}}}}}}. ",
".333333334555555555556333333333. ",
".77777777890000000000a777777777. ",
".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
".ggggggggghijjjjjjjjkgggggggggg. ",
".llllllllllmnooooopqlllllllllll. ",
".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
+123 -123
View File
@@ -1,124 +1,124 @@
/* XPM */
static const char * Flag_Taiwan_xpm[] = {
"96 32 89 1",
" c None",
". c #000000",
"# c #000099",
"$ c #000098",
"% c #03039A",
"& c #000094",
"' c #05059B",
"( c #050095",
") c #DC0014",
"* c #FF0000",
"+ c #FD0001",
", c #04049B",
"- c #000096",
"! c #020299",
"0 c #2424A7",
"1 c #04049A",
"2 c #000097",
"3 c #000093",
"4 c #6262BF",
"5 c #2828A8",
"6 c #6C6CC1",
"7 c #3E3EB1",
"8 c #3B3BB0",
"9 c #00008F",
": c #01019A",
"; c #1919A3",
"< c #4040B0",
"= c #6363C0",
"> c #D6D6EE",
"? c #D9D9ED",
"@ c #C5C5E7",
"A c #3F3FB0",
"B c #3D3DAF",
"C c #020297",
"D c #010199",
"E c #5E5EBE",
"F c #DFDFF2",
"G c white",
"H c #BFBFE5",
"I c #2626A7",
"J c #4242B0",
"K c #7D7DCA",
"L c #FAFAFD",
"M c #FBFBFD",
"N c #FCFCFD",
"O c #FCFCFE",
"P c #DADAF0",
"Q c #6A6AC2",
"R c #1B1BA3",
"S c #000199",
"T c #0E0E9B",
"U c #5858BC",
"V c #D3D3ED",
"W c #2727A6",
"X c #060699",
"Y c #1212A0",
"Z c #6464C0",
"[ c #8080CC",
"] c #F4F4FA",
"^ c #F8F8FB",
"_ c #7070C4",
"` c #4949B5",
"a c #000095",
"b c #040499",
"c c #000092",
"d c #6767C2",
"e c #8686CA",
"f c #7070C5",
"g c #2B2BA9",
"h c #00009A",
"i c #01049C",
"j c #1619A4",
"k c #393CB3",
"l c #00029A",
"m c #1619A5",
"n c #020096",
"o c #DB0014",
"p c #FC0001",
"q c #0A0092",
"r c #060090",
"s c #0B0092",
"t c #0F008E",
"u c #DD0013",
"v c #FD0000",
"w c #E5000F",
"x c #E6010F",
"y c #E60110",
"z c #FB0002",
"{ c #FE0000",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".#####$%#&'$$$##()*+***********. ",
".###$$,-!0&1!$##()*+***********. ",
".##$#23456789:$#()*+***********. ",
".###2;<=>?@ABCD#()*+***********. ",
".###$CEFGGGHI&D$()*+***********. ",
".##D-JKLMNOPQR-S()*+***********. ",
".###$TUGGNGVWX$#()*+***********. ",
".###2YZ[]^P_`aD$()*+***********. ",
".###$bcdEefg3D$#()*+***********. ",
".hhhhhijiklm#hhhno*p***********. ",
".qqqqqqrsrqrqqqqtu*v***********. ",
".wwwwwwxwywxwwwwwz*{***********. ",
".******************************. ",
".{{{{{{{{{{{{{{{{{*{***********. ",
".******************************. ",
".******************************. ",
".******************************. ",
".******************************. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
/* XPM */
static const char * Flag_Taiwan_xpm[] = {
"96 32 89 1",
" c None",
". c #000000",
"# c #000099",
"$ c #000098",
"% c #03039A",
"& c #000094",
"' c #05059B",
"( c #050095",
") c #DC0014",
"* c #FF0000",
"+ c #FD0001",
", c #04049B",
"- c #000096",
"! c #020299",
"0 c #2424A7",
"1 c #04049A",
"2 c #000097",
"3 c #000093",
"4 c #6262BF",
"5 c #2828A8",
"6 c #6C6CC1",
"7 c #3E3EB1",
"8 c #3B3BB0",
"9 c #00008F",
": c #01019A",
"; c #1919A3",
"< c #4040B0",
"= c #6363C0",
"> c #D6D6EE",
"? c #D9D9ED",
"@ c #C5C5E7",
"A c #3F3FB0",
"B c #3D3DAF",
"C c #020297",
"D c #010199",
"E c #5E5EBE",
"F c #DFDFF2",
"G c white",
"H c #BFBFE5",
"I c #2626A7",
"J c #4242B0",
"K c #7D7DCA",
"L c #FAFAFD",
"M c #FBFBFD",
"N c #FCFCFD",
"O c #FCFCFE",
"P c #DADAF0",
"Q c #6A6AC2",
"R c #1B1BA3",
"S c #000199",
"T c #0E0E9B",
"U c #5858BC",
"V c #D3D3ED",
"W c #2727A6",
"X c #060699",
"Y c #1212A0",
"Z c #6464C0",
"[ c #8080CC",
"] c #F4F4FA",
"^ c #F8F8FB",
"_ c #7070C4",
"` c #4949B5",
"a c #000095",
"b c #040499",
"c c #000092",
"d c #6767C2",
"e c #8686CA",
"f c #7070C5",
"g c #2B2BA9",
"h c #00009A",
"i c #01049C",
"j c #1619A4",
"k c #393CB3",
"l c #00029A",
"m c #1619A5",
"n c #020096",
"o c #DB0014",
"p c #FC0001",
"q c #0A0092",
"r c #060090",
"s c #0B0092",
"t c #0F008E",
"u c #DD0013",
"v c #FD0000",
"w c #E5000F",
"x c #E6010F",
"y c #E60110",
"z c #FB0002",
"{ c #FE0000",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".#####$%#&'$$$##()*+***********. ",
".###$$,-!0&1!$##()*+***********. ",
".##$#23456789:$#()*+***********. ",
".###2;<=>?@ABCD#()*+***********. ",
".###$CEFGGGHI&D$()*+***********. ",
".##D-JKLMNOPQR-S()*+***********. ",
".###$TUGGNGVWX$#()*+***********. ",
".###2YZ[]^P_`aD$()*+***********. ",
".###$bcdEefg3D$#()*+***********. ",
".hhhhhijiklm#hhhno*p***********. ",
".qqqqqqrsrqrqqqqtu*v***********. ",
".wwwwwwxwywxwwwwwz*{***********. ",
".******************************. ",
".{{{{{{{{{{{{{{{{{*{***********. ",
".******************************. ",
".******************************. ",
".******************************. ",
".******************************. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
+65 -65
View File
@@ -1,65 +1,65 @@
/* XPM */
static const char * Flag_USA_xpm[] = {
"96 32 30 1",
" c None",
". c #000000",
"+ c #0000FF",
"@ c #CE7070",
"# c #B0BF99",
"$ c #F1F1F1",
"% c #FFFFFF",
"& c #0000FD",
"* c #CF8484",
"= c #DA9090",
"- c #0000F3",
"; c #B0BF96",
"> c #0000DF",
", c #0000CB",
"' c #B0BF8C",
") c #D98E8E",
"! c #0000B5",
"~ c #CA6C6C",
"{ c #000098",
"] c #B0BF80",
"^ c #000077",
"/ c #C26464",
"( c #DBDBDB",
"_ c #C17676",
": c #B55757",
"< c #BBBBBB",
"[ c #AC6161",
"} c #A34545",
"| c #8B8B8B",
"1 c #8E4343",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".++++++++++++++@@@@@@@@@@@@@@@@. ",
".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
".&&&&&&&&&&&&&&*===============. ",
".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
".,',',',',',',,*))))))))))))))). ",
".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
".^^^^^^^^^^^^^^****************. ",
".^^^^^^^^^^^^^^@///////////////. ",
".((((((((((((((((((((((((((((((. ",
".______________________________. ",
".::::::::::::::::::::::::::::::. ",
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
".||||||||||||||||||||||||||||||. ",
".111111111111111111111111111111. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
/* XPM */
static const char * Flag_USA_xpm[] = {
"96 32 30 1",
" c None",
". c #000000",
"+ c #0000FF",
"@ c #CE7070",
"# c #B0BF99",
"$ c #F1F1F1",
"% c #FFFFFF",
"& c #0000FD",
"* c #CF8484",
"= c #DA9090",
"- c #0000F3",
"; c #B0BF96",
"> c #0000DF",
", c #0000CB",
"' c #B0BF8C",
") c #D98E8E",
"! c #0000B5",
"~ c #CA6C6C",
"{ c #000098",
"] c #B0BF80",
"^ c #000077",
"/ c #C26464",
"( c #DBDBDB",
"_ c #C17676",
": c #B55757",
"< c #BBBBBB",
"[ c #AC6161",
"} c #A34545",
"| c #8B8B8B",
"1 c #8E4343",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".++++++++++++++@@@@@@@@@@@@@@@@. ",
".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
".&&&&&&&&&&&&&&*===============. ",
".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
".,',',',',',',,*))))))))))))))). ",
".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
".^^^^^^^^^^^^^^****************. ",
".^^^^^^^^^^^^^^@///////////////. ",
".((((((((((((((((((((((((((((((. ",
".______________________________. ",
".::::::::::::::::::::::::::::::. ",
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
".||||||||||||||||||||||||||||||. ",
".111111111111111111111111111111. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};
+179 -179
View File
@@ -1,179 +1,179 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AVIDump.h"
#include "tchar.h"
#include <cstdio>
#include <cstring>
#include <vfw.h>
#include <winerror.h>
#include "FileUtil.h"
#include "CommonPaths.h"
#include "Log.h"
static HWND m_emuWnd;
static int m_width;
static int m_height;
static LONG m_byteBuffer;
static LONG m_frameCount;
static LONG m_totalBytes;
static PAVIFILE m_file;
static int m_fileCount;
static PAVISTREAM m_stream;
static PAVISTREAM m_streamCompressed;
static AVISTREAMINFO m_header;
static AVICOMPRESSOPTIONS m_options;
static AVICOMPRESSOPTIONS *m_arrayOptions[1];
static BITMAPINFOHEADER m_bitmap;
bool AVIDump::Start(HWND hWnd, int w, int h)
{
m_emuWnd = hWnd;
m_fileCount = 0;
m_width = w;
m_height = h;
return CreateFile();
}
bool AVIDump::CreateFile()
{
m_totalBytes = 0;
m_frameCount = 0;
char movie_file_name[255];
sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
// Create path
File::CreateFullPath(movie_file_name);
// Ask to delete file
if (File::Exists(movie_file_name))
{
if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
File::Delete(movie_file_name);
}
AVIFileInit();
NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
// TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
if (FAILED(hr)) {
if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format.");
if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory.");
if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file.");
if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file.");
if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
Stop();
return false;
}
SetBitmapFormat();
NOTICE_LOG(VIDEO, "Setting video format...");
if (!SetVideoFormat()) {
NOTICE_LOG(VIDEO, "Setting video format failed");
Stop();
return false;
}
if (!m_fileCount) {
if (!SetCompressionOptions()) {
NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
Stop();
return false;
}
}
if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
Stop();
return false;
}
if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
Stop();
return false;
}
return true;
}
void AVIDump::CloseFile()
{
if (m_streamCompressed) {
AVIStreamClose(m_streamCompressed);
m_streamCompressed = NULL;
}
if (m_stream) {
AVIStreamClose(m_stream);
m_stream = NULL;
}
if (m_file) {
AVIFileRelease(m_file);
m_file = NULL;
}
AVIFileExit();
}
void AVIDump::Stop()
{
CloseFile();
m_fileCount = 0;
NOTICE_LOG(VIDEO, "Stop");
}
void AVIDump::AddFrame(char *data)
{
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
m_totalBytes += m_byteBuffer;
// Close the recording if the file is more than 2gb
// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
if (m_totalBytes >= 2000000000) {
CloseFile();
m_fileCount++;
CreateFile();
}
}
void AVIDump::SetBitmapFormat()
{
memset(&m_bitmap, 0, sizeof(m_bitmap));
m_bitmap.biSize = 0x28;
m_bitmap.biPlanes = 1;
m_bitmap.biBitCount = 24;
m_bitmap.biWidth = m_width;
m_bitmap.biHeight = m_height;
m_bitmap.biSizeImage = 3 * m_width * m_height;
}
bool AVIDump::SetCompressionOptions()
{
memset(&m_options, 0, sizeof(m_options));
m_arrayOptions[0] = &m_options;
return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
}
bool AVIDump::SetVideoFormat()
{
memset(&m_header, 0, sizeof(m_header));
m_header.fccType = streamtypeVIDEO;
m_header.dwScale = 1;
// TODO: Decect FPS using NTSC/PAL
m_header.dwRate = 60;
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "AVIDump.h"
#include "tchar.h"
#include <cstdio>
#include <cstring>
#include <vfw.h>
#include <winerror.h>
#include "FileUtil.h"
#include "CommonPaths.h"
#include "Log.h"
static HWND m_emuWnd;
static int m_width;
static int m_height;
static LONG m_byteBuffer;
static LONG m_frameCount;
static LONG m_totalBytes;
static PAVIFILE m_file;
static int m_fileCount;
static PAVISTREAM m_stream;
static PAVISTREAM m_streamCompressed;
static AVISTREAMINFO m_header;
static AVICOMPRESSOPTIONS m_options;
static AVICOMPRESSOPTIONS *m_arrayOptions[1];
static BITMAPINFOHEADER m_bitmap;
bool AVIDump::Start(HWND hWnd, int w, int h)
{
m_emuWnd = hWnd;
m_fileCount = 0;
m_width = w;
m_height = h;
return CreateFile();
}
bool AVIDump::CreateFile()
{
m_totalBytes = 0;
m_frameCount = 0;
char movie_file_name[255];
sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
// Create path
File::CreateFullPath(movie_file_name);
// Ask to delete file
if (File::Exists(movie_file_name))
{
if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
File::Delete(movie_file_name);
}
AVIFileInit();
NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
// TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
if (FAILED(hr)) {
if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format.");
if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory.");
if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file.");
if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file.");
if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
Stop();
return false;
}
SetBitmapFormat();
NOTICE_LOG(VIDEO, "Setting video format...");
if (!SetVideoFormat()) {
NOTICE_LOG(VIDEO, "Setting video format failed");
Stop();
return false;
}
if (!m_fileCount) {
if (!SetCompressionOptions()) {
NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
Stop();
return false;
}
}
if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
Stop();
return false;
}
if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
Stop();
return false;
}
return true;
}
void AVIDump::CloseFile()
{
if (m_streamCompressed) {
AVIStreamClose(m_streamCompressed);
m_streamCompressed = NULL;
}
if (m_stream) {
AVIStreamClose(m_stream);
m_stream = NULL;
}
if (m_file) {
AVIFileRelease(m_file);
m_file = NULL;
}
AVIFileExit();
}
void AVIDump::Stop()
{
CloseFile();
m_fileCount = 0;
NOTICE_LOG(VIDEO, "Stop");
}
void AVIDump::AddFrame(char *data)
{
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
m_totalBytes += m_byteBuffer;
// Close the recording if the file is more than 2gb
// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
if (m_totalBytes >= 2000000000) {
CloseFile();
m_fileCount++;
CreateFile();
}
}
void AVIDump::SetBitmapFormat()
{
memset(&m_bitmap, 0, sizeof(m_bitmap));
m_bitmap.biSize = 0x28;
m_bitmap.biPlanes = 1;
m_bitmap.biBitCount = 24;
m_bitmap.biWidth = m_width;
m_bitmap.biHeight = m_height;
m_bitmap.biSizeImage = 3 * m_width * m_height;
}
bool AVIDump::SetCompressionOptions()
{
memset(&m_options, 0, sizeof(m_options));
m_arrayOptions[0] = &m_options;
return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
}
bool AVIDump::SetVideoFormat()
{
memset(&m_header, 0, sizeof(m_header));
m_header.fccType = streamtypeVIDEO;
m_header.dwScale = 1;
// TODO: Decect FPS using NTSC/PAL
m_header.dwRate = 60;
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
}
+59 -59
View File
@@ -1,60 +1,60 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// ------------------------------------------
// The plugins has to define these functions
// ------------------------------------------
#ifndef _BPFUNCTIONS_H_
#define _BPFUNCTIONS_H_
#include "BPMemory.h"
#include "VideoCommon.h"
namespace BPFunctions
{
enum
{
CONFIG_ISWII = 0,
CONFIG_DISABLEFOG,
CONFIG_SHOWEFBREGIONS
};
void FlushPipeline();
void SetGenerationMode(const Bypass &bp);
void SetScissor(const Bypass &bp);
void SetLineWidth(const Bypass &bp);
void SetDepthMode(const Bypass &bp);
void SetBlendMode(const Bypass &bp);
void SetDitherMode(const Bypass &bp);
void SetLogicOpMode(const Bypass &bp);
void SetColorMask(const Bypass &bp);
float GetRendererTargetScaleX();
float GetRendererTargetScaleY();
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const bool &scaleByHalf);
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight);
void ClearScreen(const Bypass &bp, const TRectangle &multirc);
void RestoreRenderState(const Bypass &bp);
u8 *GetPointer(const u32 &address);
bool GetConfig(const int &type);
void SetSamplerState(const Bypass &bp);
void SetInterlacingMode(const Bypass &bp);
};
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// ------------------------------------------
// The plugins has to define these functions
// ------------------------------------------
#ifndef _BPFUNCTIONS_H_
#define _BPFUNCTIONS_H_
#include "BPMemory.h"
#include "VideoCommon.h"
namespace BPFunctions
{
enum
{
CONFIG_ISWII = 0,
CONFIG_DISABLEFOG,
CONFIG_SHOWEFBREGIONS
};
void FlushPipeline();
void SetGenerationMode(const Bypass &bp);
void SetScissor(const Bypass &bp);
void SetLineWidth(const Bypass &bp);
void SetDepthMode(const Bypass &bp);
void SetBlendMode(const Bypass &bp);
void SetDitherMode(const Bypass &bp);
void SetLogicOpMode(const Bypass &bp);
void SetColorMask(const Bypass &bp);
float GetRendererTargetScaleX();
float GetRendererTargetScaleY();
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 &copyfmt, const bool &scaleByHalf);
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight);
void ClearScreen(const Bypass &bp, const TRectangle &multirc);
void RestoreRenderState(const Bypass &bp);
u8 *GetPointer(const u32 &address);
bool GetConfig(const int &type);
void SetSamplerState(const Bypass &bp);
void SetInterlacingMode(const Bypass &bp);
};
#endif // _BPFUNCTIONS_H_
File diff suppressed because it is too large Load Diff
+27 -27
View File
@@ -1,27 +1,27 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _BPSTRUCTS_H_
#define _BPSTRUCTS_H_
#include "BPMemory.h"
void BPInit();
void LoadBPReg(u32 value0);
void BPReload();
#endif // _BPSTRUCTS_H_
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _BPSTRUCTS_H_
#define _BPSTRUCTS_H_
#include "BPMemory.h"
void BPInit();
void LoadBPReg(u32 value0);
void BPReload();
#endif // _BPSTRUCTS_H_
+154 -154
View File
@@ -1,154 +1,154 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "HiresTextures.h"
#include <cstring>
#include <utility>
#include <algorithm>
#include "SOIL.h"
#include "CommonPaths.h"
#include "FileUtil.h"
#include "FileSearch.h"
namespace HiresTextures
{
std::map<std::string, std::string> textureMap;
void Init(const char *gameCode)
{
static bool bCheckedDir;
CFileSearch::XStringVector Directories;
//Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
char szDir[MAX_PATH];
sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
Directories.push_back(std::string(szDir));
for (u32 i = 0; i < Directories.size(); i++)
{
File::FSTEntry FST_Temp;
File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
for (u32 j = 0; j < FST_Temp.children.size(); j++)
{
if (FST_Temp.children.at(j).isDirectory)
{
bool duplicate = false;
NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
for (u32 k = 0; k < Directories.size(); k++)
{
NormalizeDirSep(&Directories.at(k));
if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
{
duplicate = true;
break;
}
}
if (!duplicate)
Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
}
}
}
CFileSearch::XStringVector Extensions;
Extensions.push_back("*.png");
Extensions.push_back("*.bmp");
Extensions.push_back("*.tga");
Extensions.push_back("*.dds");
Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
CFileSearch FileSearch(Extensions, Directories);
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
char code[MAX_PATH];
sprintf(code, "%s_", gameCode);
if (rFilenames.size() > 0)
{
for (u32 i = 0; i < rFilenames.size(); i++)
{
std::string FileName;
SplitPath(rFilenames[i], NULL, &FileName, NULL);
if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end())
textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
}
}
}
void Shutdown()
{
textureMap.clear();
}
PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
{
std::string key(fileName);
if(textureMap.find(key) == textureMap.end())
return PC_TEX_FMT_NONE;
int width;
int height;
int channels;
u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
if (temp == NULL) {
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
SOIL_free_image_data(temp);
return PC_TEX_FMT_NONE;
}
if (width > 1024 || height > 1024) {
ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 1024 pixels tall and wide", textureMap[key].c_str(), width, height);
SOIL_free_image_data(temp);
return PC_TEX_FMT_NONE;
}
int offset = 0;
PC_TexFormat returnTex;
switch (texformat)
{
case GX_TF_I4:
case GX_TF_I8:
case GX_TF_IA4:
case GX_TF_IA8:
for (int i = 0; i < width * height * 4; i += 4)
{
// Rather than use a luminosity function, just use the most intense color for luminance
data[offset++] = *std::max_element(temp+i, temp+i+3);
data[offset++] = temp[i+3];
}
returnTex = PC_TEX_FMT_IA8;
break;
default:
memcpy(data, temp, width*height*4);
returnTex = PC_TEX_FMT_RGBA32;
break;
}
*pWidth = width;
*pHeight = height;
SOIL_free_image_data(temp);
INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
return returnTex;
}
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "HiresTextures.h"
#include <cstring>
#include <utility>
#include <algorithm>
#include "SOIL.h"
#include "CommonPaths.h"
#include "FileUtil.h"
#include "FileSearch.h"
namespace HiresTextures
{
std::map<std::string, std::string> textureMap;
void Init(const char *gameCode)
{
static bool bCheckedDir;
CFileSearch::XStringVector Directories;
//Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
char szDir[MAX_PATH];
sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
Directories.push_back(std::string(szDir));
for (u32 i = 0; i < Directories.size(); i++)
{
File::FSTEntry FST_Temp;
File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
for (u32 j = 0; j < FST_Temp.children.size(); j++)
{
if (FST_Temp.children.at(j).isDirectory)
{
bool duplicate = false;
NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
for (u32 k = 0; k < Directories.size(); k++)
{
NormalizeDirSep(&Directories.at(k));
if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
{
duplicate = true;
break;
}
}
if (!duplicate)
Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
}
}
}
CFileSearch::XStringVector Extensions;
Extensions.push_back("*.png");
Extensions.push_back("*.bmp");
Extensions.push_back("*.tga");
Extensions.push_back("*.dds");
Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
CFileSearch FileSearch(Extensions, Directories);
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
char code[MAX_PATH];
sprintf(code, "%s_", gameCode);
if (rFilenames.size() > 0)
{
for (u32 i = 0; i < rFilenames.size(); i++)
{
std::string FileName;
SplitPath(rFilenames[i], NULL, &FileName, NULL);
if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end())
textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
}
}
}
void Shutdown()
{
textureMap.clear();
}
PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
{
std::string key(fileName);
if(textureMap.find(key) == textureMap.end())
return PC_TEX_FMT_NONE;
int width;
int height;
int channels;
u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
if (temp == NULL) {
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
SOIL_free_image_data(temp);
return PC_TEX_FMT_NONE;
}
if (width > 1024 || height > 1024) {
ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 1024 pixels tall and wide", textureMap[key].c_str(), width, height);
SOIL_free_image_data(temp);
return PC_TEX_FMT_NONE;
}
int offset = 0;
PC_TexFormat returnTex;
switch (texformat)
{
case GX_TF_I4:
case GX_TF_I8:
case GX_TF_IA4:
case GX_TF_IA8:
for (int i = 0; i < width * height * 4; i += 4)
{
// Rather than use a luminosity function, just use the most intense color for luminance
data[offset++] = *std::max_element(temp+i, temp+i+3);
data[offset++] = temp[i+3];
}
returnTex = PC_TEX_FMT_IA8;
break;
default:
memcpy(data, temp, width*height*4);
returnTex = PC_TEX_FMT_RGBA32;
break;
}
*pWidth = width;
*pHeight = height;
SOIL_free_image_data(temp);
INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
return returnTex;
}
}
+18 -18
View File
@@ -1,18 +1,18 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Dummy file for common to compile
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Dummy file for common to compile
+119 -119
View File
@@ -1,119 +1,119 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Stubs to make DSPCore compile as part of DSPSpy.
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "Thread.h"
void *AllocateMemoryPages(size_t size)
{
return malloc(size);
}
void FreeMemoryPages(void *pages, size_t size)
{
free(pages);
}
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
}
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
}
bool DSPHost_OnThread()
{
return false;
}
// Well, it's just RAM right? :)
u8 DSPHost_ReadHostMemory(u32 address)
{
u8 *ptr = (u8*)address;
return *ptr;
}
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
void DSPHost_CodeLoaded(const u8 *code, int size)
{
}
namespace Common
{
CriticalSection::CriticalSection(int)
{
}
CriticalSection::~CriticalSection()
{
}
void CriticalSection::Enter()
{
}
void CriticalSection::Leave()
{
}
} // namespace
namespace File
{
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{
FILE *f = fopen(filename, text_file ? "w" : "wb");
if (!f)
return false;
size_t len = str.size();
if (len != fwrite(str.data(), 1, str.size(), f))
{
fclose(f);
return false;
}
fclose(f);
return true;
}
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
FILE *f = fopen(filename, text_file ? "r" : "rb");
if (!f)
return false;
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
char *buf = new char[len + 1];
buf[fread(buf, 1, len, f)] = 0;
str = std::string(buf, len);
fclose(f);
delete [] buf;
return true;
}
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Stubs to make DSPCore compile as part of DSPSpy.
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "Thread.h"
void *AllocateMemoryPages(size_t size)
{
return malloc(size);
}
void FreeMemoryPages(void *pages, size_t size)
{
free(pages);
}
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
}
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{
}
bool DSPHost_OnThread()
{
return false;
}
// Well, it's just RAM right? :)
u8 DSPHost_ReadHostMemory(u32 address)
{
u8 *ptr = (u8*)address;
return *ptr;
}
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
void DSPHost_CodeLoaded(const u8 *code, int size)
{
}
namespace Common
{
CriticalSection::CriticalSection(int)
{
}
CriticalSection::~CriticalSection()
{
}
void CriticalSection::Enter()
{
}
void CriticalSection::Leave()
{
}
} // namespace
namespace File
{
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
{
FILE *f = fopen(filename, text_file ? "w" : "wb");
if (!f)
return false;
size_t len = str.size();
if (len != fwrite(str.data(), 1, str.size(), f))
{
fclose(f);
return false;
}
fclose(f);
return true;
}
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
{
FILE *f = fopen(filename, text_file ? "r" : "rb");
if (!f)
return false;
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
char *buf = new char[len + 1];
buf[fread(buf, 1, len, f)] = 0;
str = std::string(buf, len);
fclose(f);
delete [] buf;
return true;
}
}
+42 -42
View File
@@ -1,43 +1,43 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "dsp_interface.h"
void IDSP::SendTask(void *addr, u16 iram_addr, u16 len, u16 start)
{
while (CheckMailTo());
SendMailTo(0x80F3A001);
while (CheckMailTo());
SendMailTo((u32)addr);
while (CheckMailTo());
SendMailTo(0x80F3C002);
while (CheckMailTo());
SendMailTo(iram_addr);
while (CheckMailTo());
SendMailTo(0x80F3A002);
while (CheckMailTo());
SendMailTo(len);
while (CheckMailTo());
SendMailTo(0x80F3B002);
while (CheckMailTo());
SendMailTo(0);
while (CheckMailTo());
SendMailTo(0x80F3D001);
while (CheckMailTo());
SendMailTo(start);
while (CheckMailTo());
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "dsp_interface.h"
void IDSP::SendTask(void *addr, u16 iram_addr, u16 len, u16 start)
{
while (CheckMailTo());
SendMailTo(0x80F3A001);
while (CheckMailTo());
SendMailTo((u32)addr);
while (CheckMailTo());
SendMailTo(0x80F3C002);
while (CheckMailTo());
SendMailTo(iram_addr);
while (CheckMailTo());
SendMailTo(0x80F3A002);
while (CheckMailTo());
SendMailTo(len);
while (CheckMailTo());
SendMailTo(0x80F3B002);
while (CheckMailTo());
SendMailTo(0);
while (CheckMailTo());
SendMailTo(0x80F3D001);
while (CheckMailTo());
SendMailTo(start);
while (CheckMailTo());
}
+50 -50
View File
@@ -1,50 +1,50 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSP_INTERFACE_H
#define _DSP_INTERFACE_H
#include <gccore.h>
// DSPCR bits
#define DSPCR_DSPRESET 0x0800 // Reset DSP
#define DSPCR_ARDMA 0x0200 // ARAM dma in progress, if set
#define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
#define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
#define DSPCR_ARINTMSK 0x0040
#define DSPCR_ARINT 0x0020
#define DSPCR_AIINTMSK 0x0010
#define DSPCR_AIINT 0x0008
#define DSPCR_HALT 0x0004 // halt DSP
#define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
#define DSPCR_RES 0x0001 // reset DSP
class IDSP {
public:
virtual ~IDSP() {}
virtual void Init() = 0;
virtual void Reset() = 0;
virtual u32 CheckMailTo() = 0;
virtual void SendMailTo(u32 mail) = 0;
// Yeah, yeah, having a method here makes this not a pure interface - but
// the implementation does nothing but calling the virtual methods above.
void SendTask(void *addr, u16 iram_addr, u16 len, u16 start);
};
#endif // _DSP_INTERFACE_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSP_INTERFACE_H
#define _DSP_INTERFACE_H
#include <gccore.h>
// DSPCR bits
#define DSPCR_DSPRESET 0x0800 // Reset DSP
#define DSPCR_ARDMA 0x0200 // ARAM dma in progress, if set
#define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
#define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
#define DSPCR_ARINTMSK 0x0040
#define DSPCR_ARINT 0x0020
#define DSPCR_AIINTMSK 0x0010
#define DSPCR_AIINT 0x0008
#define DSPCR_HALT 0x0004 // halt DSP
#define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
#define DSPCR_RES 0x0001 // reset DSP
class IDSP {
public:
virtual ~IDSP() {}
virtual void Init() = 0;
virtual void Reset() = 0;
virtual u32 CheckMailTo() = 0;
virtual void SendMailTo(u32 mail) = 0;
// Yeah, yeah, having a method here makes this not a pure interface - but
// the implementation does nothing but calling the virtual methods above.
void SendTask(void *addr, u16 iram_addr, u16 len, u16 start);
};
#endif // _DSP_INTERFACE_H
+565 -565
View File
File diff suppressed because it is too large Load Diff
+68 -68
View File
@@ -1,68 +1,68 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <gccore.h>
#include <ogcsys.h>
#include <ogc/dsp.h>
#include <ogc/irq.h>
#include <ogc/machine/asm.h>
#include <ogc/machine/processor.h>
#include "dsp_interface.h"
#include "real_dsp.h"
static vu16* const _dspReg = (u16*)0xCC005000;
// Handler for DSP interrupt.
static void dsp_irq_handler(u32 nIrq, void *pCtx)
{
// Acknowledge interrupt?
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT)) | DSPCR_DSPINT;
}
void RealDSP::Init()
{
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET;
_dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT));
// This code looks odd - shouldn't we initialize level?
u32 level;
_CPU_ISR_Disable(level);
IRQ_Request(IRQ_DSP_DSP, dsp_irq_handler, NULL);
_CPU_ISR_Restore(level);
}
void RealDSP::Reset()
{
// Reset the DSP.
_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] |= DSPCR_RES;
while (_dspReg[5] & DSPCR_RES)
;
_dspReg[9] = 0x63;
}
u32 RealDSP::CheckMailTo()
{
return DSP_CheckMailTo();
}
void RealDSP::SendMailTo(u32 mail)
{
DSP_SendMailTo(mail);
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <gccore.h>
#include <ogcsys.h>
#include <ogc/dsp.h>
#include <ogc/irq.h>
#include <ogc/machine/asm.h>
#include <ogc/machine/processor.h>
#include "dsp_interface.h"
#include "real_dsp.h"
static vu16* const _dspReg = (u16*)0xCC005000;
// Handler for DSP interrupt.
static void dsp_irq_handler(u32 nIrq, void *pCtx)
{
// Acknowledge interrupt?
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT)) | DSPCR_DSPINT;
}
void RealDSP::Init()
{
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET;
_dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT));
// This code looks odd - shouldn't we initialize level?
u32 level;
_CPU_ISR_Disable(level);
IRQ_Request(IRQ_DSP_DSP, dsp_irq_handler, NULL);
_CPU_ISR_Restore(level);
}
void RealDSP::Reset()
{
// Reset the DSP.
_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] |= DSPCR_RES;
while (_dspReg[5] & DSPCR_RES)
;
_dspReg[9] = 0x63;
}
u32 RealDSP::CheckMailTo()
{
return DSP_CheckMailTo();
}
void RealDSP::SendMailTo(u32 mail)
{
DSP_SendMailTo(mail);
}
+31 -31
View File
@@ -1,31 +1,31 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _REAL_DSP_H
#define _REAL_DSP_H
#include "dsp_interface.h"
class RealDSP : public IDSP {
public:
virtual void Init();
virtual void Reset();
virtual u32 CheckMailTo();
virtual void SendMailTo(u32 mail);
};
#endif // _REAL_DSP_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _REAL_DSP_H
#define _REAL_DSP_H
#include "dsp_interface.h"
class RealDSP : public IDSP {
public:
virtual void Init();
virtual void Reset();
virtual u32 CheckMailTo();
virtual void SendMailTo(u32 mail);
};
#endif // _REAL_DSP_H
+403 -403
View File
@@ -1,403 +1,403 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "FileUtil.h"
#include "DSPCodeUtil.h"
// Stub out the dsplib host stuff, since this is just a simple cmdline tools.
u8 DSPHost_ReadHostMemory(u32 addr) { return 0; }
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
bool DSPHost_OnThread() { return false; }
bool DSPHost_Running() { return true; }
u32 DSPHost_CodeLoaded(const u8 *ptr, int size) {return 0x1337c0de;}
void DSPHost_InterruptRequest() {}
void DSPHost_UpdateDebugger() {}
// This test goes from text ASM to binary to text ASM and once again back to binary.
// Then the two binaries are compared.
bool RoundTrip(const std::vector<u16> &code1)
{
std::vector<u16> code2;
std::string text;
if (!Disassemble(code1, false, text))
{
printf("RoundTrip: Disassembly failed.\n");
return false;
}
if (!Assemble(text.c_str(), code2))
{
printf("RoundTrip: Assembly failed.\n");
return false;
}
if (!Compare(code1, code2))
{
Disassemble(code1, true, text);
printf("%s", text.c_str());
}
return true;
}
// 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.
bool SuperTrip(const char *asm_code)
{
std::vector<u16> code1, code2;
std::string text;
if (!Assemble(asm_code, code1))
{
printf("SuperTrip: First assembly failed\n");
return false;
}
printf("First assembly: %i words\n", (int)code1.size());
if (!Disassemble(code1, false, text))
{
printf("SuperTrip: Disassembly failed\n");
return false;
}
else
{
printf("Disass:\n");
printf("%s", text.c_str());
}
if (!Assemble(text.c_str(), code2))
{
printf("SuperTrip: Second assembly failed\n");
return false;
}
/*
std::string text2;
Disassemble(code1, true, &text1);
Disassemble(code2, true, &text2);
File::WriteStringToFile(true, text1, "code1.txt");
File::WriteStringToFile(true, text2, "code2.txt");
*/
return true;
}
void RunAsmTests()
{
bool fail = false;
#define CHK(a) if (!SuperTrip(a)) printf("FAIL\n%s\n", a), fail = true;
// Let's start out easy - a trivial instruction..
CHK(" NOP\n");
// Now let's do several.
CHK(" NOP\n"
" NOP\n"
" NOP\n");
// Turning it up a notch.
CHK(" SET16\n"
" SET40\n"
" CLR15\n"
" M0\n"
" M2\n");
// Time to try labels and parameters, and comments.
CHK("DIRQ_TEST: equ 0xfffb ; DSP Irq Request\n"
" si @0xfffc, #0x8888\n"
" si @0xfffd, #0xbeef\n"
" si @DIRQ_TEST, #0x0001\n");
// Let's see if registers roundtrip. Also try predefined labels.
CHK(" si @0xfffc, #0x8888\n"
" si @0xfffd, #0xbeef\n"
" si @DIRQ, #0x0001\n");
// Let's try some messy extended instructions.
//CHK(" MULMV'SN $AX0.L, $AX0.H, $ACC0 : @$AR2, $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
// be roundtripped. We don't expect it to always succeed but it'll be sure to generate
// interesting test cases.
/*
std::vector<u16> hermes;
if (!LoadBinary("testdata/hermes.bin", &hermes))
PanicAlert("Failed to load hermes rom");
RoundTrip(hermes);
*/
/*
std::vector<u16> code;
std::string text_orig;
File::ReadFileToString(false, "testdata/dsp_test.S", &text_orig);
if (!Assemble(text_orig.c_str(), &code))
{
printf("SuperTrip: First assembly failed\n");
return;
}*/
/*
{
std::vector<u16> code;
code.clear();
for (int i = 0; i < sizeof(dsp_test)/4; i++)
{
code.push_back(dsp_test[i] >> 16);
code.push_back(dsp_test[i] & 0xFFFF);
}
SaveBinary(code, "dsp_test2.bin");
RoundTrip(code);
}*/
//if (Compare(code, hermes))
// printf("Successs\n");
/*
{
std::vector<u16> code;
std::string text;
LoadBinary("testdata/dsp_test.bin", &code);
Disassemble(code, true, &text);
Assemble(text.c_str(), &code);
Disassemble(code, true, &text);
printf("%s", text.c_str());
}*/
/*
puts("Insane Random Code Test\n");
std::vector<u16> rand_code;
GenRandomCode(30, &rand_code);
std::string rand_code_text;
Disassemble(rand_code, true, &rand_code_text);
printf("%s", rand_code_text.c_str());
RoundTrip(rand_code);
if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))
SuperTrip(dsp_test.c_str());
//.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.
*/
std::string dsp_test;
if (File::ReadFileToString(true, "Testdata/dsp_test.s", dsp_test))
fail = fail || !SuperTrip(dsp_test.c_str());
if (!fail)
printf("All passed!\n");
}
// Usage:
// Run internal tests:
// dsptool test
// Disassemble a file:
// dsptool -d -o asdf.txt asdf.bin
// Disassemble a file, output to standard output:
// dsptool -d asdf.bin
// Assemble a file:
// dsptool -o asdf.bin asdf.txt
// Assemble a file, output header:
// dsptool -h asdf.h asdf.txt
// So far, all this binary can do is test partially that itself works correctly.
int main(int argc, const char *argv[])
{
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("-? / --help: Prints this message\n");
printf("-d: Disassemble\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("-o <OUTPUT FILE>: Results from stdout redirected to a file\n");
printf("-h <HEADER FILE>: Output assembly results to a header\n");
return 0;
}
if (argc == 2 && !strcmp(argv[1], "test"))
{
RunAsmTests();
return 0;
}
std::string input_name;
std::string output_header_name;
std::string output_name;
bool disassemble = false, compare = false, multiple = false, outputSize = false;
for (int i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "-d"))
disassemble = true;
else if (!strcmp(argv[i], "-o"))
output_name = argv[++i];
else if (!strcmp(argv[i], "-h"))
output_header_name = argv[++i];
else if (!strcmp(argv[i], "-c"))
compare = true;
else if (!strcmp(argv[i], "-s"))
outputSize = true;
else if (!strcmp(argv[i], "-m"))
multiple = true;
else
{
if (!input_name.empty())
{
printf("ERROR: Can only take one input file.\n");
return 1;
}
input_name = argv[i];
if (!File::Exists(input_name.c_str()))
{
printf("ERROR: Input path does not exist.\n");
return 1;
}
}
}
if(multiple && (compare || disassemble || !output_name.empty() ||
input_name.empty())) {
printf("ERROR: Multiple files can only be used with assembly "
"and must compile a header file.\n");
return 1;
}
if (compare)
{
// Two binary inputs, let's diff.
std::string binary_code;
std::vector<u16> code1, code2;
File::ReadFileToString(false, input_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code1);
File::ReadFileToString(false, output_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code2);
Compare(code1, code2);
return 0;
}
if (disassemble)
{
if (input_name.empty())
{
printf("Disassemble: Must specify input.\n");
return 1;
}
std::string binary_code;
std::vector<u16> code;
File::ReadFileToString(false, input_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code);
std::string text;
Disassemble(code, true, text);
if (!output_name.empty())
File::WriteStringToFile(true, text, output_name.c_str());
else
printf("%s", text.c_str());
}
else
{
if (input_name.empty())
{
printf("Assemble: Must specify input.\n");
return 1;
}
std::string source;
if (File::ReadFileToString(true, input_name.c_str(), source))
{
if(multiple)
{
// When specifying a list of files we must compile a header
// (we can't assemble multiple files to one binary)
// since we checked it before, we assume output_header_name isn't empty
int lines;
std::vector<u16> *codes;
std::vector<std::string> files;
std::string header, currentSource;
size_t lastPos = 0, pos = 0;
source.append("\n");
while((pos = source.find('\n', lastPos)) != std::string::npos)
{
std::string temp = source.substr(lastPos, pos - lastPos);
if(!temp.empty())
files.push_back(temp);
lastPos = pos + 1;
}
lines = (int)files.size();
if(lines == 0)
{
printf("ERROR: Must specify at least one file\n");
return 1;
}
codes = new std::vector<u16>[lines];
for(int i = 0; i < lines; i++)
{
if (!File::ReadFileToString(true, files[i].c_str(), currentSource))
{
printf("ERROR reading %s, skipping...\n", files[i].c_str());
lines--;
}
else
{
if(!Assemble(currentSource.c_str(), codes[i]))
{
printf("Assemble: Assembly of %s failed due to errors\n",
files[i].c_str());
lines--;
}
if(outputSize)
printf("%s: %d\n", files[i].c_str(), codes[i].size());
}
}
CodesToHeader(codes, &files, lines, output_header_name.c_str(), header);
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
delete[] codes;
}
else
{
std::vector<u16> code;
if(!Assemble(source.c_str(), code)) {
printf("Assemble: Assembly failed due to errors\n");
return 1;
}
if(outputSize)
printf("%s: %d\n", input_name.c_str(), code.size());
if (!output_name.empty())
{
std::string binary_code;
CodeToBinaryStringBE(code, binary_code);
File::WriteStringToFile(false, binary_code, output_name.c_str());
}
if (!output_header_name.empty())
{
std::string header;
CodeToHeader(code, input_name, output_header_name.c_str(), header);
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
}
}
}
source.clear();
}
if(!outputSize)
printf("Assembly completed successfully!\n");
return 0;
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "FileUtil.h"
#include "DSPCodeUtil.h"
// Stub out the dsplib host stuff, since this is just a simple cmdline tools.
u8 DSPHost_ReadHostMemory(u32 addr) { return 0; }
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
bool DSPHost_OnThread() { return false; }
bool DSPHost_Running() { return true; }
u32 DSPHost_CodeLoaded(const u8 *ptr, int size) {return 0x1337c0de;}
void DSPHost_InterruptRequest() {}
void DSPHost_UpdateDebugger() {}
// This test goes from text ASM to binary to text ASM and once again back to binary.
// Then the two binaries are compared.
bool RoundTrip(const std::vector<u16> &code1)
{
std::vector<u16> code2;
std::string text;
if (!Disassemble(code1, false, text))
{
printf("RoundTrip: Disassembly failed.\n");
return false;
}
if (!Assemble(text.c_str(), code2))
{
printf("RoundTrip: Assembly failed.\n");
return false;
}
if (!Compare(code1, code2))
{
Disassemble(code1, true, text);
printf("%s", text.c_str());
}
return true;
}
// 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.
bool SuperTrip(const char *asm_code)
{
std::vector<u16> code1, code2;
std::string text;
if (!Assemble(asm_code, code1))
{
printf("SuperTrip: First assembly failed\n");
return false;
}
printf("First assembly: %i words\n", (int)code1.size());
if (!Disassemble(code1, false, text))
{
printf("SuperTrip: Disassembly failed\n");
return false;
}
else
{
printf("Disass:\n");
printf("%s", text.c_str());
}
if (!Assemble(text.c_str(), code2))
{
printf("SuperTrip: Second assembly failed\n");
return false;
}
/*
std::string text2;
Disassemble(code1, true, &text1);
Disassemble(code2, true, &text2);
File::WriteStringToFile(true, text1, "code1.txt");
File::WriteStringToFile(true, text2, "code2.txt");
*/
return true;
}
void RunAsmTests()
{
bool fail = false;
#define CHK(a) if (!SuperTrip(a)) printf("FAIL\n%s\n", a), fail = true;
// Let's start out easy - a trivial instruction..
CHK(" NOP\n");
// Now let's do several.
CHK(" NOP\n"
" NOP\n"
" NOP\n");
// Turning it up a notch.
CHK(" SET16\n"
" SET40\n"
" CLR15\n"
" M0\n"
" M2\n");
// Time to try labels and parameters, and comments.
CHK("DIRQ_TEST: equ 0xfffb ; DSP Irq Request\n"
" si @0xfffc, #0x8888\n"
" si @0xfffd, #0xbeef\n"
" si @DIRQ_TEST, #0x0001\n");
// Let's see if registers roundtrip. Also try predefined labels.
CHK(" si @0xfffc, #0x8888\n"
" si @0xfffd, #0xbeef\n"
" si @DIRQ, #0x0001\n");
// Let's try some messy extended instructions.
//CHK(" MULMV'SN $AX0.L, $AX0.H, $ACC0 : @$AR2, $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
// be roundtripped. We don't expect it to always succeed but it'll be sure to generate
// interesting test cases.
/*
std::vector<u16> hermes;
if (!LoadBinary("testdata/hermes.bin", &hermes))
PanicAlert("Failed to load hermes rom");
RoundTrip(hermes);
*/
/*
std::vector<u16> code;
std::string text_orig;
File::ReadFileToString(false, "testdata/dsp_test.S", &text_orig);
if (!Assemble(text_orig.c_str(), &code))
{
printf("SuperTrip: First assembly failed\n");
return;
}*/
/*
{
std::vector<u16> code;
code.clear();
for (int i = 0; i < sizeof(dsp_test)/4; i++)
{
code.push_back(dsp_test[i] >> 16);
code.push_back(dsp_test[i] & 0xFFFF);
}
SaveBinary(code, "dsp_test2.bin");
RoundTrip(code);
}*/
//if (Compare(code, hermes))
// printf("Successs\n");
/*
{
std::vector<u16> code;
std::string text;
LoadBinary("testdata/dsp_test.bin", &code);
Disassemble(code, true, &text);
Assemble(text.c_str(), &code);
Disassemble(code, true, &text);
printf("%s", text.c_str());
}*/
/*
puts("Insane Random Code Test\n");
std::vector<u16> rand_code;
GenRandomCode(30, &rand_code);
std::string rand_code_text;
Disassemble(rand_code, true, &rand_code_text);
printf("%s", rand_code_text.c_str());
RoundTrip(rand_code);
if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))
SuperTrip(dsp_test.c_str());
//.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.
*/
std::string dsp_test;
if (File::ReadFileToString(true, "Testdata/dsp_test.s", dsp_test))
fail = fail || !SuperTrip(dsp_test.c_str());
if (!fail)
printf("All passed!\n");
}
// Usage:
// Run internal tests:
// dsptool test
// Disassemble a file:
// dsptool -d -o asdf.txt asdf.bin
// Disassemble a file, output to standard output:
// dsptool -d asdf.bin
// Assemble a file:
// dsptool -o asdf.bin asdf.txt
// Assemble a file, output header:
// dsptool -h asdf.h asdf.txt
// So far, all this binary can do is test partially that itself works correctly.
int main(int argc, const char *argv[])
{
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("-? / --help: Prints this message\n");
printf("-d: Disassemble\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("-o <OUTPUT FILE>: Results from stdout redirected to a file\n");
printf("-h <HEADER FILE>: Output assembly results to a header\n");
return 0;
}
if (argc == 2 && !strcmp(argv[1], "test"))
{
RunAsmTests();
return 0;
}
std::string input_name;
std::string output_header_name;
std::string output_name;
bool disassemble = false, compare = false, multiple = false, outputSize = false;
for (int i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "-d"))
disassemble = true;
else if (!strcmp(argv[i], "-o"))
output_name = argv[++i];
else if (!strcmp(argv[i], "-h"))
output_header_name = argv[++i];
else if (!strcmp(argv[i], "-c"))
compare = true;
else if (!strcmp(argv[i], "-s"))
outputSize = true;
else if (!strcmp(argv[i], "-m"))
multiple = true;
else
{
if (!input_name.empty())
{
printf("ERROR: Can only take one input file.\n");
return 1;
}
input_name = argv[i];
if (!File::Exists(input_name.c_str()))
{
printf("ERROR: Input path does not exist.\n");
return 1;
}
}
}
if(multiple && (compare || disassemble || !output_name.empty() ||
input_name.empty())) {
printf("ERROR: Multiple files can only be used with assembly "
"and must compile a header file.\n");
return 1;
}
if (compare)
{
// Two binary inputs, let's diff.
std::string binary_code;
std::vector<u16> code1, code2;
File::ReadFileToString(false, input_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code1);
File::ReadFileToString(false, output_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code2);
Compare(code1, code2);
return 0;
}
if (disassemble)
{
if (input_name.empty())
{
printf("Disassemble: Must specify input.\n");
return 1;
}
std::string binary_code;
std::vector<u16> code;
File::ReadFileToString(false, input_name.c_str(), binary_code);
BinaryStringBEToCode(binary_code, code);
std::string text;
Disassemble(code, true, text);
if (!output_name.empty())
File::WriteStringToFile(true, text, output_name.c_str());
else
printf("%s", text.c_str());
}
else
{
if (input_name.empty())
{
printf("Assemble: Must specify input.\n");
return 1;
}
std::string source;
if (File::ReadFileToString(true, input_name.c_str(), source))
{
if(multiple)
{
// When specifying a list of files we must compile a header
// (we can't assemble multiple files to one binary)
// since we checked it before, we assume output_header_name isn't empty
int lines;
std::vector<u16> *codes;
std::vector<std::string> files;
std::string header, currentSource;
size_t lastPos = 0, pos = 0;
source.append("\n");
while((pos = source.find('\n', lastPos)) != std::string::npos)
{
std::string temp = source.substr(lastPos, pos - lastPos);
if(!temp.empty())
files.push_back(temp);
lastPos = pos + 1;
}
lines = (int)files.size();
if(lines == 0)
{
printf("ERROR: Must specify at least one file\n");
return 1;
}
codes = new std::vector<u16>[lines];
for(int i = 0; i < lines; i++)
{
if (!File::ReadFileToString(true, files[i].c_str(), currentSource))
{
printf("ERROR reading %s, skipping...\n", files[i].c_str());
lines--;
}
else
{
if(!Assemble(currentSource.c_str(), codes[i]))
{
printf("Assemble: Assembly of %s failed due to errors\n",
files[i].c_str());
lines--;
}
if(outputSize)
printf("%s: %d\n", files[i].c_str(), codes[i].size());
}
}
CodesToHeader(codes, &files, lines, output_header_name.c_str(), header);
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
delete[] codes;
}
else
{
std::vector<u16> code;
if(!Assemble(source.c_str(), code)) {
printf("Assemble: Assembly failed due to errors\n");
return 1;
}
if(outputSize)
printf("%s: %d\n", input_name.c_str(), code.size());
if (!output_name.empty())
{
std::string binary_code;
CodeToBinaryStringBE(code, binary_code);
File::WriteStringToFile(false, binary_code, output_name.c_str());
}
if (!output_header_name.empty())
{
std::string header;
CodeToHeader(code, input_name, output_header_name.c_str(), header);
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
}
}
}
source.clear();
}
if(!outputSize)
printf("Assembly completed successfully!\n");
return 0;
}
+42 -42
View File
@@ -1,42 +1,42 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Config.h" // Local
#include "Globals.h"
#include "DSPHandler.h"
#include "HLEMixer.h"
void HLEMixer::MixUCode(short *samples, int numSamples) {
// if this was called directly from the HLE, and not by timeout
if (g_Config.m_EnableHLEAudio && IsHLEReady()) {
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
if (pUCode != NULL)
pUCode->MixAdd(samples, numSamples);
}
}
void HLEMixer::Premix(short *samples, int numSamples) {
// first get the DTK Music
// if (g_Config.m_EnableDTKMusic) {
// g_dspInitialize.pGetAudioStreaming(samples, numSamples);
// }
MixUCode(samples, numSamples);
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Config.h" // Local
#include "Globals.h"
#include "DSPHandler.h"
#include "HLEMixer.h"
void HLEMixer::MixUCode(short *samples, int numSamples) {
// if this was called directly from the HLE, and not by timeout
if (g_Config.m_EnableHLEAudio && IsHLEReady()) {
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
if (pUCode != NULL)
pUCode->MixAdd(samples, numSamples);
}
}
void HLEMixer::Premix(short *samples, int numSamples) {
// first get the DTK Music
// if (g_Config.m_EnableDTKMusic) {
// g_dspInitialize.pGetAudioStreaming(samples, numSamples);
// }
MixUCode(samples, numSamples);
}
@@ -1,95 +1,95 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "UCode_Zelda_ADPCM.h"
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type)
{
short nibbles[16];
short hist = *histp;
short hist2 = *hist2p;
const char *src = input;
char *dst = (char*)out;
// First 2 nibbles are ADPCM scale etc.
short delta = 1 << (((*src) >> 4) & 0xf);
short idx = (*src) & 0xf;
src++;
if (type == 9)
{
for (int i = 0; i < 16; i = i + 2) {
int j = (*src & 255) >> 4;
nibbles[i] = j;
j = *src & 255 & 15;
nibbles[i+1] = j;
src++;
}
for (int i = 0; i < 16; i = i + 1) {
if (nibbles[i] >= 8)
nibbles[i] = nibbles[i] - 16;
}
}
else
{
// untested !!! i havnt seen such a sample yet :)
for (int i = 0; i < 16; i += 4)
{
int j = (*src >> 0) & 0x02;
nibbles[i] = j;
j = (*src >> 2) & 0x02;
nibbles[i+1] = j;
j = (*src >> 4) & 0x02;
nibbles[i+2] = j;
j = (*src >> 6) & 0x02;
nibbles[i+3] = j;
src++;
}
for (int i = 0; i < 16; i++)
{
if (nibbles[i] >= 2)
nibbles[i] = nibbles[i] - 4;
}
}
for (int i = 0; i < 16; i++)
{
int sample = (delta * nibbles[i]) << 11;
sample += ((long)hist * coef[idx * 2]) + ((long)hist2 * coef[idx * 2 + 1]);
sample = sample >> 11;
if (sample > 32767) {
sample = 32767;
}
if (sample < -32768) {
sample = -32768;
}
*(short*)dst = (short)sample;
dst = dst + 2;
hist2 = hist;
hist = (short)sample;
}
*histp = hist;
*hist2p = hist2;
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "UCode_Zelda_ADPCM.h"
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type)
{
short nibbles[16];
short hist = *histp;
short hist2 = *hist2p;
const char *src = input;
char *dst = (char*)out;
// First 2 nibbles are ADPCM scale etc.
short delta = 1 << (((*src) >> 4) & 0xf);
short idx = (*src) & 0xf;
src++;
if (type == 9)
{
for (int i = 0; i < 16; i = i + 2) {
int j = (*src & 255) >> 4;
nibbles[i] = j;
j = *src & 255 & 15;
nibbles[i+1] = j;
src++;
}
for (int i = 0; i < 16; i = i + 1) {
if (nibbles[i] >= 8)
nibbles[i] = nibbles[i] - 16;
}
}
else
{
// untested !!! i havnt seen such a sample yet :)
for (int i = 0; i < 16; i += 4)
{
int j = (*src >> 0) & 0x02;
nibbles[i] = j;
j = (*src >> 2) & 0x02;
nibbles[i+1] = j;
j = (*src >> 4) & 0x02;
nibbles[i+2] = j;
j = (*src >> 6) & 0x02;
nibbles[i+3] = j;
src++;
}
for (int i = 0; i < 16; i++)
{
if (nibbles[i] >= 2)
nibbles[i] = nibbles[i] - 4;
}
}
for (int i = 0; i < 16; i++)
{
int sample = (delta * nibbles[i]) << 11;
sample += ((long)hist * coef[idx * 2]) + ((long)hist2 * coef[idx * 2 + 1]);
sample = sample >> 11;
if (sample > 32767) {
sample = 32767;
}
if (sample < -32768) {
sample = -32768;
}
*(short*)dst = (short)sample;
dst = dst + 2;
hist2 = hist;
hist = (short)sample;
}
*histp = hist;
*hist2p = hist2;
}
@@ -1,20 +1,20 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type);
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type);
@@ -1,106 +1,106 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Zelda.h"
#include "UCode_Zelda_ADPCM.h"
#include "../main.h"
#include "Mixer.h"
void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16);
s64 ratio = (_ratio * ratioFactor) * 16;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac;
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
u32 pos[2] = {0, 0};
int i = 0;
if (PB.KeyOff != 0)
return;
if (PB.NeedsReset)
{
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
PB.ReachedEnd = 0;
}
_lRestart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
if (PB.RepeatMode == 0)
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
return;
}
else
{
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
pos[1] = 0; pos[0] = 0;
}
}
while(i < _Size)
{
s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000;
TrueSamplePosition += (ratio >> 16);
_Buffer[i++] = (s32)sample;
(*(u64*)&pos) += ratio;
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
{
PB.ReachedEnd = 1;
goto _lRestart;
}
}
if (PB.RemLength < pos[1])
{
PB.RemLength = 0;
PB.ReachedEnd = 1;
}
else
PB.RemLength -= pos[1];
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
}
void CUCode_Zelda::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
// TODO: Header, footer and cases this synth actually happens
for (int i = 0; i < _Size; i++)
_Buffer[i++] = (s32)PB.RatioInt;
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Zelda.h"
#include "UCode_Zelda_ADPCM.h"
#include "../main.h"
#include "Mixer.h"
void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16);
s64 ratio = (_ratio * ratioFactor) * 16;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac;
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
u32 pos[2] = {0, 0};
int i = 0;
if (PB.KeyOff != 0)
return;
if (PB.NeedsReset)
{
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
PB.ReachedEnd = 0;
}
_lRestart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
if (PB.RepeatMode == 0)
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
return;
}
else
{
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
pos[1] = 0; pos[0] = 0;
}
}
while(i < _Size)
{
s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000;
TrueSamplePosition += (ratio >> 16);
_Buffer[i++] = (s32)sample;
(*(u64*)&pos) += ratio;
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
{
PB.ReachedEnd = 1;
goto _lRestart;
}
}
if (PB.RemLength < pos[1])
{
PB.RemLength = 0;
PB.ReachedEnd = 1;
}
else
PB.RemLength -= pos[1];
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
}
void CUCode_Zelda::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
// TODO: Header, footer and cases this synth actually happens
for (int i = 0; i < _Size; i++)
_Buffer[i++] = (s32)PB.RatioInt;
}
@@ -1,466 +1,466 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Zelda.h"
#include "UCode_Zelda_ADPCM.h"
#include "../main.h"
#include "Mixer.h"
void CUCode_Zelda::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB)
{
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
// Perform byteswap
for (int i = 0; i < (0x180 / 2); i++)
((u16*)&PB)[i] = Common::swap16(memory[i]);
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
PB.LoopStartPos = (PB.LoopStartPos << 16) | (PB.LoopStartPos >> 16);
PB.Length = (PB.Length << 16) | (PB.Length >> 16);
PB.StartAddr = (PB.StartAddr << 16) | (PB.StartAddr >> 16);
PB.UnkAddr = (PB.UnkAddr << 16) | (PB.UnkAddr >> 16);
}
void CUCode_Zelda::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB)
{
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
// Perform byteswap
// Only the first 0x100 bytes are written back
for (int i = 0; i < (0x100 / 2); i++)
memory[i] = Common::swap16(((u16*)&PB)[i]);
}
void CUCode_Zelda::RenderVoice_PCM16(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (((PB.RatioInt * 80) + PB.CurSampleFrac) << 4) & 0xFFFF0000;
u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor);
u32 pos[2] = {0, 0};
int i = 0;
if (PB.KeyOff != 0)
return;
if (PB.NeedsReset)
{
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
PB.ReachedEnd = 0;
}
_lRestart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
if (PB.RepeatMode == 0)
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
return;
}
else
{
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
pos[1] = 0; pos[0] = 0;
}
}
s16 *source;
if (m_CRC == 0xD643001F)
source = (s16*)(g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr) + PB.CurAddr);
else
source = (s16*)(g_dspInitialize.pGetARAMPointer() + PB.CurAddr);
for (; i < _Size;)
{
s16 sample = Common::swap16(source[pos[1]]);
_Buffer[i++] = (s32)sample;
(*(u64*)&pos) += ratio;
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
{
PB.ReachedEnd = 1;
goto _lRestart;
}
}
if (PB.RemLength < pos[1])
{
PB.RemLength = 0;
PB.ReachedEnd = 1;
}
else
PB.RemLength -= pos[1];
PB.CurAddr += pos[1] << 1;
// There should be a position fraction as well.
}
void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
// initialize "decoder" if the sample is played the first time
if (PB.NeedsReset != 0)
{
// This is 0717_ReadOutPBStuff
// increment 4fb
// zelda:
// perhaps init or "has played before"
PB.CurBlock = 0x00;
PB.YN2 = 0x00; // history1
PB.YN1 = 0x00; // history2
// Length in samples.
PB.RemLength = PB.Length;
// Copy ARAM addr from r to rw area.
PB.CurAddr = PB.StartAddr;
PB.ReachedEnd = 0;
PB.CurSampleFrac = 0;
// Looking at Zelda Four Swords
// WARN_LOG(DSPHLE, "PB -----: %04x", PB.Unk03);
// WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0
// WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0
/// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78);
// WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79);
// WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31);
// WARN_LOG(DSPHLE, "PB Unk36: %04x", PB.Unk36[0]);
// WARN_LOG(DSPHLE, "PB Unk37: %04x", PB.Unk36[1]);
// WARN_LOG(DSPHLE, "PB Unk3c: %04x", PB.Unk3C[0]);
// 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
return;
// round upwards how many samples we need to copy, 0759
// u32 frac = NumberOfSamples & 0xF;
// NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction
u8 *source;
u32 ram_mask = 1024 * 1024 * 16 - 1;
if (m_CRC == 0xD643001F) {
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
ram_mask = 1024 * 1024 * 64 - 1;
}
else
source = g_dspInitialize.pGetARAMPointer();
restart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
// HACK: Looping doesn't work.
if (true || PB.RepeatMode == 0)
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
return;
}
else
{
// 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?
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
// pos[1] = 0; pos[0] = 0;
}
}
short outbuf[16] = {0};
u16 prev_yn1 = PB.YN1;
u16 prev_yn2 = PB.YN2;
u32 prev_addr = PB.CurAddr;
// Prefill the decode buffer.
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
PB.CurAddr += 9;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac;
s64 delta = ratio >> 16; // 0x100000000ULL;
int sampleCount = 0;
while (sampleCount < _Size)
{
int SamplePosition = TrueSamplePosition >> 16;
_Buffer[sampleCount] = outbuf[SamplePosition & 15];
sampleCount++;
TrueSamplePosition += delta;
int TargetPosition = TrueSamplePosition >> 16;
// Decode forwards...
while (SamplePosition < TargetPosition)
{
SamplePosition++;
PB.RemLength--;
if (PB.RemLength == 0)
{
PB.ReachedEnd = 1;
goto restart;
}
// Need new samples!
if ((SamplePosition & 15) == 0) {
prev_yn1 = PB.YN1;
prev_yn2 = PB.YN2;
prev_addr = PB.CurAddr;
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
PB.CurAddr += 9;
}
}
}
// 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.
// if (SamplePosition & 15) {
PB.YN2 = prev_yn2;
PB.YN1 = prev_yn1;
PB.CurAddr = prev_addr;
// }
PB.NeedsReset = 0;
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
// write back
// NumberOfSamples = (NumberOfSamples << 4) | frac; // missing fraction
// 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
// and increase the ARAM Offset in pTest[0x38], pTest[0x39]
// end of block (Zelda 03b2)
}
// Researching what's actually inside the mysterious 0x21 case
void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
if (PB.NeedsReset != 0)
{
PB.CurBlock = 0x00;
// Length in samples.
PB.RemLength = PB.Length;
// Copy ARAM addr from r to rw area.
PB.CurAddr = PB.StartAddr;
PB.ReachedEnd = 0;
PB.CurSampleFrac = 0;
}
if (PB.KeyOff != 0)
return;
u8 *source;
u32 ram_mask = 1024 * 1024 * 16 - 1;
if (m_CRC == 0xD643001F) {
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
ram_mask = 1024 * 1024 * 64 - 1;
}
else
source = g_dspInitialize.pGetARAMPointer();
//restart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
// HACK: Looping doesn't work.
if (true || PB.RepeatMode == 0)
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
return;
}
else
{
// 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?
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
}
}
u32 prev_addr = PB.CurAddr;
// Prefill the decode buffer.
//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));
PB.CurAddr += 9;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac;
s64 delta = ratio >> 16; // 0x100000000ULL;
int sampleCount = 0, realSample = 0;
while (sampleCount < _Size)
{
_Buffer[sampleCount] = src[realSample] | (src[realSample + 1] << 8) | (src[realSample + 2] << 16)
| (src[realSample + 3] << 24);
//WARN_LOG(DSPHLE, "The sample: %02x", src[sampleCount]);
sampleCount++;
realSample += 4;
TrueSamplePosition += delta;
}
PB.NeedsReset = 0;
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
}
void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
{
//static u16 lastLeft = 0x1FF, lastRight = 0x1FF;
memset(m_TempBuffer, 0, _Size * sizeof(s32));
if (PB.IsBlank)
{
s32 sample = (s32)(s16)PB.FixedSample;
for (int i = 0; i < _Size; i++)
m_TempBuffer[i] = sample;
}
else
{
// XK: Use this to disable music (GREAT for testing)
//if(PB.SoundType == 0x0d00) {
// PB.NeedsReset = 0;
// return;
//}
//WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x",
// PB.Format, PB.SoundType, PB.Unk29, PB.Unk2a);
/*WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x %04x %04x %04x %04x %04x %04x",
PB.Format, PB.SoundType,
PB.volumeLeft1, PB.volumeLeft2, PB.volumeRight1, PB.volumeRight2,
PB.volumeUnknown1_1, PB.volumeUnknown1_2, PB.volumeUnknown2_1,
PB.volumeUnknown2_2);*/
switch (PB.Format)
{
// Synthesized sounds
case 0x0000: // Example: Magic meter filling up in ZWW
case 0x0001: // Example: "Denied" sound when trying to pull out a sword
// indoors in ZWW
RenderSynth_Waveform(PB, m_TempBuffer, _Size);
break;
case 0x0006:
WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)");
RenderSynth_Constant(PB, m_TempBuffer, _Size);
break;
// These are more "synth" formats - square wave, saw wave etc.
case 0x0002:
WARN_LOG(DSPHLE, "Synthesizing 0x0002");
break;
// AFC formats
case 0x0005: // AFC with extra low bitrate (32:5 compression). Not yet seen.
WARN_LOG(DSPHLE, "5 byte AFC - does it work?");
case 0x0009: // AFC with normal bitrate (32:9 compression).
RenderVoice_AFC(PB, m_TempBuffer, _Size);
break;
case 0x0010: // PCM16 - normal PCM 16-bit audio.
RenderVoice_PCM16(PB, m_TempBuffer, _Size);
break;
case 0x0008: // Likely PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD.
case 0x0020:
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);
// This is what 0x20 and 0x21 do on end of voice
PB.RemLength = 0;
PB.KeyOff = 1;
// Caution: Use at your own risk. Sounds awful :)
//RenderVoice_Raw(PB, m_TempBuffer, _Size);
break;
default:
// TODO: Implement general decoder here
ERROR_LOG(DSPHLE, "Unknown MixAddVoice format in zelda %04x", PB.Format);
break;
}
// Necessary for SMG, not for Zelda. Weird.
PB.NeedsReset = 0;
}
for (int i = 0; i < _Size; i++)
{
/*if(PB.volumeLeft2)
lastLeft = PB.volumeLeft2;
if(PB.volumeRight2)
lastRight = PB.volumeRight2;*/
// 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
// sounds in Zelda TP. Needs investigation.
s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
(PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005);
s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
(PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005);
if (left < -32768) left = -32768;
if (left > 32767) left = 32767;
_LeftBuffer[i] = left; //(s32)(((float)left * (float)PB.volumeLeft) / 1000.f);
if (right < -32768) right = -32768;
if (right > 32767) right = 32767;
_RightBuffer[i] = right; //(s32)(((float)right * (float)PB.volumeRight) / 1000.0f);
}
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "../Globals.h"
#include "UCodes.h"
#include "UCode_Zelda.h"
#include "UCode_Zelda_ADPCM.h"
#include "../main.h"
#include "Mixer.h"
void CUCode_Zelda::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB)
{
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
// Perform byteswap
for (int i = 0; i < (0x180 / 2); i++)
((u16*)&PB)[i] = Common::swap16(memory[i]);
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
PB.LoopStartPos = (PB.LoopStartPos << 16) | (PB.LoopStartPos >> 16);
PB.Length = (PB.Length << 16) | (PB.Length >> 16);
PB.StartAddr = (PB.StartAddr << 16) | (PB.StartAddr >> 16);
PB.UnkAddr = (PB.UnkAddr << 16) | (PB.UnkAddr >> 16);
}
void CUCode_Zelda::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB)
{
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
// Perform byteswap
// Only the first 0x100 bytes are written back
for (int i = 0; i < (0x100 / 2); i++)
memory[i] = Common::swap16(((u16*)&PB)[i]);
}
void CUCode_Zelda::RenderVoice_PCM16(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (((PB.RatioInt * 80) + PB.CurSampleFrac) << 4) & 0xFFFF0000;
u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor);
u32 pos[2] = {0, 0};
int i = 0;
if (PB.KeyOff != 0)
return;
if (PB.NeedsReset)
{
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
PB.ReachedEnd = 0;
}
_lRestart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
if (PB.RepeatMode == 0)
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
return;
}
else
{
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
pos[1] = 0; pos[0] = 0;
}
}
s16 *source;
if (m_CRC == 0xD643001F)
source = (s16*)(g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr) + PB.CurAddr);
else
source = (s16*)(g_dspInitialize.pGetARAMPointer() + PB.CurAddr);
for (; i < _Size;)
{
s16 sample = Common::swap16(source[pos[1]]);
_Buffer[i++] = (s32)sample;
(*(u64*)&pos) += ratio;
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
{
PB.ReachedEnd = 1;
goto _lRestart;
}
}
if (PB.RemLength < pos[1])
{
PB.RemLength = 0;
PB.ReachedEnd = 1;
}
else
PB.RemLength -= pos[1];
PB.CurAddr += pos[1] << 1;
// There should be a position fraction as well.
}
void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
// initialize "decoder" if the sample is played the first time
if (PB.NeedsReset != 0)
{
// This is 0717_ReadOutPBStuff
// increment 4fb
// zelda:
// perhaps init or "has played before"
PB.CurBlock = 0x00;
PB.YN2 = 0x00; // history1
PB.YN1 = 0x00; // history2
// Length in samples.
PB.RemLength = PB.Length;
// Copy ARAM addr from r to rw area.
PB.CurAddr = PB.StartAddr;
PB.ReachedEnd = 0;
PB.CurSampleFrac = 0;
// Looking at Zelda Four Swords
// WARN_LOG(DSPHLE, "PB -----: %04x", PB.Unk03);
// WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0
// WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0
/// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78);
// WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79);
// WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31);
// WARN_LOG(DSPHLE, "PB Unk36: %04x", PB.Unk36[0]);
// WARN_LOG(DSPHLE, "PB Unk37: %04x", PB.Unk36[1]);
// WARN_LOG(DSPHLE, "PB Unk3c: %04x", PB.Unk3C[0]);
// 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
return;
// round upwards how many samples we need to copy, 0759
// u32 frac = NumberOfSamples & 0xF;
// NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction
u8 *source;
u32 ram_mask = 1024 * 1024 * 16 - 1;
if (m_CRC == 0xD643001F) {
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
ram_mask = 1024 * 1024 * 64 - 1;
}
else
source = g_dspInitialize.pGetARAMPointer();
restart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
// HACK: Looping doesn't work.
if (true || PB.RepeatMode == 0)
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
return;
}
else
{
// 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?
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
// pos[1] = 0; pos[0] = 0;
}
}
short outbuf[16] = {0};
u16 prev_yn1 = PB.YN1;
u16 prev_yn2 = PB.YN2;
u32 prev_addr = PB.CurAddr;
// Prefill the decode buffer.
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
PB.CurAddr += 9;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac;
s64 delta = ratio >> 16; // 0x100000000ULL;
int sampleCount = 0;
while (sampleCount < _Size)
{
int SamplePosition = TrueSamplePosition >> 16;
_Buffer[sampleCount] = outbuf[SamplePosition & 15];
sampleCount++;
TrueSamplePosition += delta;
int TargetPosition = TrueSamplePosition >> 16;
// Decode forwards...
while (SamplePosition < TargetPosition)
{
SamplePosition++;
PB.RemLength--;
if (PB.RemLength == 0)
{
PB.ReachedEnd = 1;
goto restart;
}
// Need new samples!
if ((SamplePosition & 15) == 0) {
prev_yn1 = PB.YN1;
prev_yn2 = PB.YN2;
prev_addr = PB.CurAddr;
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
PB.CurAddr += 9;
}
}
}
// 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.
// if (SamplePosition & 15) {
PB.YN2 = prev_yn2;
PB.YN1 = prev_yn1;
PB.CurAddr = prev_addr;
// }
PB.NeedsReset = 0;
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
// write back
// NumberOfSamples = (NumberOfSamples << 4) | frac; // missing fraction
// 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
// and increase the ARAM Offset in pTest[0x38], pTest[0x39]
// end of block (Zelda 03b2)
}
// Researching what's actually inside the mysterious 0x21 case
void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
{
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
if (PB.NeedsReset != 0)
{
PB.CurBlock = 0x00;
// Length in samples.
PB.RemLength = PB.Length;
// Copy ARAM addr from r to rw area.
PB.CurAddr = PB.StartAddr;
PB.ReachedEnd = 0;
PB.CurSampleFrac = 0;
}
if (PB.KeyOff != 0)
return;
u8 *source;
u32 ram_mask = 1024 * 1024 * 16 - 1;
if (m_CRC == 0xD643001F) {
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
ram_mask = 1024 * 1024 * 64 - 1;
}
else
source = g_dspInitialize.pGetARAMPointer();
//restart:
if (PB.ReachedEnd)
{
PB.ReachedEnd = 0;
// HACK: Looping doesn't work.
if (true || PB.RepeatMode == 0)
{
PB.KeyOff = 1;
PB.RemLength = 0;
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
return;
}
else
{
// 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?
PB.RestartPos = PB.LoopStartPos;
PB.RemLength = PB.Length - PB.RestartPos;
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
}
}
u32 prev_addr = PB.CurAddr;
// Prefill the decode buffer.
//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));
PB.CurAddr += 9;
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
TrueSamplePosition += PB.CurSampleFrac;
s64 delta = ratio >> 16; // 0x100000000ULL;
int sampleCount = 0, realSample = 0;
while (sampleCount < _Size)
{
_Buffer[sampleCount] = src[realSample] | (src[realSample + 1] << 8) | (src[realSample + 2] << 16)
| (src[realSample + 3] << 24);
//WARN_LOG(DSPHLE, "The sample: %02x", src[sampleCount]);
sampleCount++;
realSample += 4;
TrueSamplePosition += delta;
}
PB.NeedsReset = 0;
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
}
void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
{
//static u16 lastLeft = 0x1FF, lastRight = 0x1FF;
memset(m_TempBuffer, 0, _Size * sizeof(s32));
if (PB.IsBlank)
{
s32 sample = (s32)(s16)PB.FixedSample;
for (int i = 0; i < _Size; i++)
m_TempBuffer[i] = sample;
}
else
{
// XK: Use this to disable music (GREAT for testing)
//if(PB.SoundType == 0x0d00) {
// PB.NeedsReset = 0;
// return;
//}
//WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x",
// PB.Format, PB.SoundType, PB.Unk29, PB.Unk2a);
/*WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x %04x %04x %04x %04x %04x %04x",
PB.Format, PB.SoundType,
PB.volumeLeft1, PB.volumeLeft2, PB.volumeRight1, PB.volumeRight2,
PB.volumeUnknown1_1, PB.volumeUnknown1_2, PB.volumeUnknown2_1,
PB.volumeUnknown2_2);*/
switch (PB.Format)
{
// Synthesized sounds
case 0x0000: // Example: Magic meter filling up in ZWW
case 0x0001: // Example: "Denied" sound when trying to pull out a sword
// indoors in ZWW
RenderSynth_Waveform(PB, m_TempBuffer, _Size);
break;
case 0x0006:
WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)");
RenderSynth_Constant(PB, m_TempBuffer, _Size);
break;
// These are more "synth" formats - square wave, saw wave etc.
case 0x0002:
WARN_LOG(DSPHLE, "Synthesizing 0x0002");
break;
// AFC formats
case 0x0005: // AFC with extra low bitrate (32:5 compression). Not yet seen.
WARN_LOG(DSPHLE, "5 byte AFC - does it work?");
case 0x0009: // AFC with normal bitrate (32:9 compression).
RenderVoice_AFC(PB, m_TempBuffer, _Size);
break;
case 0x0010: // PCM16 - normal PCM 16-bit audio.
RenderVoice_PCM16(PB, m_TempBuffer, _Size);
break;
case 0x0008: // Likely PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD.
case 0x0020:
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);
// This is what 0x20 and 0x21 do on end of voice
PB.RemLength = 0;
PB.KeyOff = 1;
// Caution: Use at your own risk. Sounds awful :)
//RenderVoice_Raw(PB, m_TempBuffer, _Size);
break;
default:
// TODO: Implement general decoder here
ERROR_LOG(DSPHLE, "Unknown MixAddVoice format in zelda %04x", PB.Format);
break;
}
// Necessary for SMG, not for Zelda. Weird.
PB.NeedsReset = 0;
}
for (int i = 0; i < _Size; i++)
{
/*if(PB.volumeLeft2)
lastLeft = PB.volumeLeft2;
if(PB.volumeRight2)
lastRight = PB.volumeRight2;*/
// 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
// sounds in Zelda TP. Needs investigation.
s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
(PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005);
s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
(PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005);
if (left < -32768) left = -32768;
if (left > 32767) left = 32767;
_LeftBuffer[i] = left; //(s32)(((float)left * (float)PB.volumeLeft) / 1000.f);
if (right < -32768) right = -32768;
if (right > 32767) right = 32767;
_RightBuffer[i] = right; //(s32)(((float)right * (float)PB.volumeRight) / 1000.0f);
}
}
@@ -1,179 +1,179 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPDebugInterface.h"
#include "DSPCore.h"
#include "disassemble.h"
#include "DSPSymbols.h"
#include "DSPMemoryMap.h"
void DSPDebugInterface::disasm(unsigned int address, char *dest, int max_size)
{
// we'll treat addresses as line numbers.
strncpy(dest, DSPSymbols::GetLineText(address), max_size);
dest[max_size-1] = 0;
}
void DSPDebugInterface::getRawMemoryString(int memory, unsigned int address, char *dest, int max_size)
{
switch (memory) {
case 0: // IMEM
switch (address >> 12) {
case 0:
case 0x8:
sprintf(dest, "%04x", dsp_imem_read(address));
break;
default:
sprintf(dest, "----");
break;
}
break;
case 1: // DMEM
switch (address >> 12) {
case 0:
case 1:
sprintf(dest, "%04x", dsp_dmem_read(address));
break;
default:
sprintf(dest, "----");
break;
}
break;
}
}
unsigned int DSPDebugInterface::readMemory(unsigned int address)
{
return 0; //Memory::ReadUnchecked_U32(address);
}
unsigned int DSPDebugInterface::readInstruction(unsigned int address)
{
return 0; //Memory::Read_Instruction(address);
}
bool DSPDebugInterface::isAlive()
{
return true; //Core::GetState() != Core::CORE_UNINITIALIZED;
}
bool DSPDebugInterface::isBreakpoint(unsigned int address)
{
int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0)
return dsp_breakpoints.IsAddressBreakPoint(real_addr);
else
return false;
}
void DSPDebugInterface::setBreakpoint(unsigned int address)
{
int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) {
if (dsp_breakpoints.Add(real_addr))
;
}
}
void DSPDebugInterface::clearBreakpoint(unsigned int address)
{
int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) {
if (dsp_breakpoints.Remove(real_addr))
;
}
}
void DSPDebugInterface::clearAllBreakpoints() {
dsp_breakpoints.Clear();
}
void DSPDebugInterface::toggleBreakpoint(unsigned int address)
{
int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) {
if (dsp_breakpoints.IsAddressBreakPoint(real_addr))
dsp_breakpoints.Remove(real_addr);
else
dsp_breakpoints.Add(real_addr);
}
}
void DSPDebugInterface::insertBLR(unsigned int address)
{
PanicAlert("insertBLR functionality not supported in DSP module.");
}
// =======================================================
// Separate the blocks with colors.
// -------------
int DSPDebugInterface::getColor(unsigned int address)
{
static const int colors[6] =
{
0xd0FFFF, // light cyan
0xFFd0d0, // light red
0xd8d8FF, // light blue
0xFFd0FF, // light purple
0xd0FFd0, // light green
0xFFFFd0, // light yellow
};
// Scan backwards so we don't miss it. Hm, actually, let's not - it looks pretty good.
int addr = -1;
for (int i = 0; i < 1; i++)
{
addr = DSPSymbols::Line2Addr(address - i);
if (addr >= 0)
break;
}
if (addr == -1)
return 0xFFFFFF;
Symbol *symbol = DSPSymbols::g_dsp_symbol_db.GetSymbolFromAddr(addr);
if (!symbol)
return 0xFFFFFF;
if (symbol->type != Symbol::SYMBOL_FUNCTION)
return 0xEEEEFF;
return colors[symbol->index % 6];
}
// =============
std::string DSPDebugInterface::getDescription(unsigned int address)
{
return ""; // g_symbolDB.GetDescription(address);
}
unsigned int DSPDebugInterface::getPC()
{
return DSPSymbols::Addr2Line(g_dsp.pc);
}
void DSPDebugInterface::setPC(unsigned int address)
{
int new_pc = DSPSymbols::Line2Addr(address);
if (new_pc > 0)
g_dsp.pc = new_pc;
}
void DSPDebugInterface::runToBreakpoint()
{
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "DSPDebugInterface.h"
#include "DSPCore.h"
#include "disassemble.h"
#include "DSPSymbols.h"
#include "DSPMemoryMap.h"
void DSPDebugInterface::disasm(unsigned int address, char *dest, int max_size)
{
// we'll treat addresses as line numbers.
strncpy(dest, DSPSymbols::GetLineText(address), max_size);
dest[max_size-1] = 0;
}
void DSPDebugInterface::getRawMemoryString(int memory, unsigned int address, char *dest, int max_size)
{
switch (memory) {
case 0: // IMEM
switch (address >> 12) {
case 0:
case 0x8:
sprintf(dest, "%04x", dsp_imem_read(address));
break;
default:
sprintf(dest, "----");
break;
}
break;
case 1: // DMEM
switch (address >> 12) {
case 0:
case 1:
sprintf(dest, "%04x", dsp_dmem_read(address));
break;
default:
sprintf(dest, "----");
break;
}
break;
}
}
unsigned int DSPDebugInterface::readMemory(unsigned int address)
{
return 0; //Memory::ReadUnchecked_U32(address);
}
unsigned int DSPDebugInterface::readInstruction(unsigned int address)
{
return 0; //Memory::Read_Instruction(address);
}
bool DSPDebugInterface::isAlive()
{
return true; //Core::GetState() != Core::CORE_UNINITIALIZED;
}
bool DSPDebugInterface::isBreakpoint(unsigned int address)
{
int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0)
return dsp_breakpoints.IsAddressBreakPoint(real_addr);
else
return false;
}
void DSPDebugInterface::setBreakpoint(unsigned int address)
{
int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) {
if (dsp_breakpoints.Add(real_addr))
;
}
}
void DSPDebugInterface::clearBreakpoint(unsigned int address)
{
int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) {
if (dsp_breakpoints.Remove(real_addr))
;
}
}
void DSPDebugInterface::clearAllBreakpoints() {
dsp_breakpoints.Clear();
}
void DSPDebugInterface::toggleBreakpoint(unsigned int address)
{
int real_addr = DSPSymbols::Line2Addr(address);
if (real_addr >= 0) {
if (dsp_breakpoints.IsAddressBreakPoint(real_addr))
dsp_breakpoints.Remove(real_addr);
else
dsp_breakpoints.Add(real_addr);
}
}
void DSPDebugInterface::insertBLR(unsigned int address)
{
PanicAlert("insertBLR functionality not supported in DSP module.");
}
// =======================================================
// Separate the blocks with colors.
// -------------
int DSPDebugInterface::getColor(unsigned int address)
{
static const int colors[6] =
{
0xd0FFFF, // light cyan
0xFFd0d0, // light red
0xd8d8FF, // light blue
0xFFd0FF, // light purple
0xd0FFd0, // light green
0xFFFFd0, // light yellow
};
// Scan backwards so we don't miss it. Hm, actually, let's not - it looks pretty good.
int addr = -1;
for (int i = 0; i < 1; i++)
{
addr = DSPSymbols::Line2Addr(address - i);
if (addr >= 0)
break;
}
if (addr == -1)
return 0xFFFFFF;
Symbol *symbol = DSPSymbols::g_dsp_symbol_db.GetSymbolFromAddr(addr);
if (!symbol)
return 0xFFFFFF;
if (symbol->type != Symbol::SYMBOL_FUNCTION)
return 0xEEEEFF;
return colors[symbol->index % 6];
}
// =============
std::string DSPDebugInterface::getDescription(unsigned int address)
{
return ""; // g_symbolDB.GetDescription(address);
}
unsigned int DSPDebugInterface::getPC()
{
return DSPSymbols::Addr2Line(g_dsp.pc);
}
void DSPDebugInterface::setPC(unsigned int address)
{
int new_pc = DSPSymbols::Line2Addr(address);
if (new_pc > 0)
g_dsp.pc = new_pc;
}
void DSPDebugInterface::runToBreakpoint()
{
}
@@ -1,33 +1,33 @@
#ifndef _DSPDEBUGINTERFACE_H
#define _DSPDEBUGINTERFACE_H
#include <string>
#include "DebugInterface.h"
#include "Common.h"
class DSPDebugInterface : public DebugInterface
{
public:
DSPDebugInterface(){}
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 int getInstructionSize(int instruction) {return 1;}
virtual bool isAlive();
virtual bool isBreakpoint(unsigned int address);
virtual void setBreakpoint(unsigned int address);
virtual void clearBreakpoint(unsigned int address);
virtual void clearAllBreakpoints();
virtual void toggleBreakpoint(unsigned int address);
virtual unsigned int readMemory(unsigned int address);
virtual unsigned int readInstruction(unsigned int address);
virtual unsigned int getPC();
virtual void setPC(unsigned int address);
virtual void step() {}
virtual void runToBreakpoint();
virtual void insertBLR(unsigned int address);
virtual int getColor(unsigned int address);
virtual std::string getDescription(unsigned int address);
};
#endif // _DSPDEBUGINTERFACE_H
#ifndef _DSPDEBUGINTERFACE_H
#define _DSPDEBUGINTERFACE_H
#include <string>
#include "DebugInterface.h"
#include "Common.h"
class DSPDebugInterface : public DebugInterface
{
public:
DSPDebugInterface(){}
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 int getInstructionSize(int instruction) {return 1;}
virtual bool isAlive();
virtual bool isBreakpoint(unsigned int address);
virtual void setBreakpoint(unsigned int address);
virtual void clearBreakpoint(unsigned int address);
virtual void clearAllBreakpoints();
virtual void toggleBreakpoint(unsigned int address);
virtual unsigned int readMemory(unsigned int address);
virtual unsigned int readInstruction(unsigned int address);
virtual unsigned int getPC();
virtual void setPC(unsigned int address);
virtual void step() {}
virtual void runToBreakpoint();
virtual void insertBLR(unsigned int address);
virtual int getColor(unsigned int address);
virtual std::string getDescription(unsigned int address);
};
#endif // _DSPDEBUGINTERFACE_H
+115 -115
View File
@@ -1,115 +1,115 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "DSPHost.h"
#include "DSPSymbols.h"
#include "Tools.h"
#include "pluginspecs_dsp.h"
extern DSPInitialize g_dspInitialize;
#if defined(HAVE_WX) && HAVE_WX
#include "DSPConfigDlgLLE.h"
#include "Debugger/Debugger.h" // For the DSPDebuggerLLE class
extern DSPDebuggerLLE* m_DebuggerFrame;
#endif
// The user of the DSPCore library must supply a few functions so that the
// emulation core can access the environment it runs in. If the emulation
// core isn't used, for example in an asm/disasm tool, then most of these
// can be stubbed out.
u8 DSPHost_ReadHostMemory(u32 addr)
{
return g_dspInitialize.pARAM_Read_U8(addr);
}
void DSPHost_WriteHostMemory(u8 value, u32 addr)
{
g_dspInitialize.pARAM_Write_U8(value, addr);
}
bool DSPHost_OnThread()
{
return g_dspInitialize.bOnThread;
}
bool DSPHost_Running()
{
return !(*g_dspInitialize.pEmulatorState);
}
void DSPHost_InterruptRequest()
{
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "Firing an interrupt on the PPC ASAP");
#endif
// Fire an interrupt on the PPC ASAP.
g_dspInitialize.pGenerateDSPInterrupt();
}
u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
{
u32 crc = GenerateCRC(ptr, size);
DumpDSPCode(ptr, size, crc);
// this crc is comparable with the HLE plugin
u32 ector_crc = 0;
for (int i = 0; i < size; i++)
{
ector_crc ^= ptr[i];
//let's rol
ector_crc = (ector_crc << 3) | (ector_crc >> 29);
}
DSPSymbols::Clear();
// Auto load text file - if none just disassemble.
// TODO: Don't hardcode for Zelda.
NOTICE_LOG(DSPLLE, "CRC: %08x", ector_crc);
DSPSymbols::Clear();
bool success = false;
switch (ector_crc)
{
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 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX1.txt"); break;
default: success = false; break;
}
if (!success) {
DSPSymbols::AutoDisassembly(0x0, 0x1000);
}
// Always add the ROM.
DSPSymbols::AutoDisassembly(0x8000, 0x9000);
if (m_DebuggerFrame)
m_DebuggerFrame->Refresh();
return crc;
}
void DSPHost_UpdateDebugger()
{
if (m_DebuggerFrame)
m_DebuggerFrame->Refresh();
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "DSPHost.h"
#include "DSPSymbols.h"
#include "Tools.h"
#include "pluginspecs_dsp.h"
extern DSPInitialize g_dspInitialize;
#if defined(HAVE_WX) && HAVE_WX
#include "DSPConfigDlgLLE.h"
#include "Debugger/Debugger.h" // For the DSPDebuggerLLE class
extern DSPDebuggerLLE* m_DebuggerFrame;
#endif
// The user of the DSPCore library must supply a few functions so that the
// emulation core can access the environment it runs in. If the emulation
// core isn't used, for example in an asm/disasm tool, then most of these
// can be stubbed out.
u8 DSPHost_ReadHostMemory(u32 addr)
{
return g_dspInitialize.pARAM_Read_U8(addr);
}
void DSPHost_WriteHostMemory(u8 value, u32 addr)
{
g_dspInitialize.pARAM_Write_U8(value, addr);
}
bool DSPHost_OnThread()
{
return g_dspInitialize.bOnThread;
}
bool DSPHost_Running()
{
return !(*g_dspInitialize.pEmulatorState);
}
void DSPHost_InterruptRequest()
{
#ifdef DEBUG_EXP
NOTICE_LOG(DSPLLE, "Firing an interrupt on the PPC ASAP");
#endif
// Fire an interrupt on the PPC ASAP.
g_dspInitialize.pGenerateDSPInterrupt();
}
u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
{
u32 crc = GenerateCRC(ptr, size);
DumpDSPCode(ptr, size, crc);
// this crc is comparable with the HLE plugin
u32 ector_crc = 0;
for (int i = 0; i < size; i++)
{
ector_crc ^= ptr[i];
//let's rol
ector_crc = (ector_crc << 3) | (ector_crc >> 29);
}
DSPSymbols::Clear();
// Auto load text file - if none just disassemble.
// TODO: Don't hardcode for Zelda.
NOTICE_LOG(DSPLLE, "CRC: %08x", ector_crc);
DSPSymbols::Clear();
bool success = false;
switch (ector_crc)
{
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 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX1.txt"); break;
default: success = false; break;
}
if (!success) {
DSPSymbols::AutoDisassembly(0x0, 0x1000);
}
// Always add the ROM.
DSPSymbols::AutoDisassembly(0x8000, 0x9000);
if (m_DebuggerFrame)
m_DebuggerFrame->Refresh();
return crc;
}
void DSPHost_UpdateDebugger()
{
if (m_DebuggerFrame)
m_DebuggerFrame->Refresh();
}
+287 -287
View File
@@ -1,287 +1,287 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <iostream> // I hope this doesn't break anything
#include <stdio.h>
#include <stdarg.h>
#include <list>
#include <map>
#include <string>
#include "Common.h"
#include "StringUtil.h"
#include "DSPCore.h"
#include "DSPSymbols.h"
#include "disassemble.h"
namespace DSPSymbols {
DSPSymbolDB g_dsp_symbol_db;
std::map<u16, int> addr_to_line;
std::map<int, u16> line_to_addr;
std::map<int, const char *> line_to_symbol;
std::vector<std::string> lines;
int line_counter = 0;
int Addr2Line(u16 address) // -1 for not found
{
std::map<u16, int>::iterator iter = addr_to_line.find(address);
if (iter != addr_to_line.end())
return iter->second;
else
return -1;
}
int Line2Addr(int line) // -1 for not found
{
std::map<int, u16>::iterator iter = line_to_addr.find(line);
if (iter != line_to_addr.end())
return iter->second;
else
return -1;
}
const char *GetLineText(int line)
{
if (line > 0 && line < (int)lines.size())
{
return lines[line].c_str();
}
else
return "----";
}
Symbol *DSPSymbolDB::GetSymbolFromAddr(u32 addr)
{
XFuncMap::iterator it = functions.find(addr);
if (it != functions.end())
return &it->second;
else
{
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{
if (addr >= iter->second.address && addr < iter->second.address + iter->second.size)
return &iter->second;
}
}
return 0;
}
// lower case only
bool IsHexDigit(char c) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
return true;
default:
return false;
}
}
bool IsAlpha(char c) {
return (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z');
}
void DisasssembleRange(u16 start, u16 end)
{
}
bool ReadAnnotatedAssembly(const char *filename)
{
FILE *f = fopen(filename, "r");
if (!f) {
ERROR_LOG(DSPLLE, "Bah! ReadAnnotatedAssembly couldn't find the file %s", filename);
return false;
}
char line[512];
int last_addr = 0;
lines.reserve(3000);
// Symbol generation
int brace_count = 0;
bool symbol_in_progress = false;
int symbol_count = 0;
Symbol current_symbol;
while (fgets(line, 512, f))
{
// Scan string for the first 4-digit hex string.
size_t len = strlen(line);
int first_hex = -1;
bool hex_found = false;
for (unsigned int i = 0; i < strlen(line); i++)
{
const char c = line[i];
if (IsHexDigit(c))
{
if (first_hex == -1)
{
first_hex = i;
}
else
{
// Remove hex notation
if (i == first_hex + 3 &&
(first_hex == 0 || line[first_hex - 1] != 'x') &&
(i >= len - 1 || line[i + 1] == ' '))
{
hex_found = true;
break;
}
}
} else {
if (i - first_hex < 3)
{
first_hex = -1;
}
if (IsAlpha(c))
break;
}
}
// Scan for function starts
if (!memcmp(line, "void", 4)) {
char temp[256];
for (int i = 6; i < len; i++) {
if (line[i] == '(') {
// Yep, got one.
memcpy(temp, line + 5, i - 5);
temp[i - 5] = 0;
// Mark symbol so the next hex sets the address
current_symbol.name = temp;
current_symbol.address = 0xFFFF;
current_symbol.index = symbol_count++;
symbol_in_progress = true;
// Reset brace count.
brace_count = 0;
}
}
}
// Scan for braces
for (int i = 0; i < (int)len; i++) {
if (line[i] == '{')
brace_count++;
if (line[i] == '}')
{
brace_count--;
if (brace_count == 0 && symbol_in_progress) {
// Commit this symbol.
current_symbol.size = last_addr - current_symbol.address + 1;
g_dsp_symbol_db.AddCompleteSymbol(current_symbol);
current_symbol.address = 0xFFFF;
symbol_in_progress = false;
}
}
}
if (hex_found)
{
int hex = 0;
sscanf(line + first_hex, "%04x", &hex);
// Sanity check
if (hex > last_addr + 3 || hex < last_addr - 3) {
static int errors = 0;
ERROR_LOG(DSPLLE, "Got Insane Hex Digit %04x (%04x) from %s", hex, last_addr, line);
errors++;
if (errors > 10)
{
fclose(f);
return false;
}
}
else
{
// if (line_counter >= 200 && line_counter <= 220)
// NOTICE_LOG(DSPLLE, "Got Hex Digit %04x from %s, line %i", hex, line, line_counter);
if (symbol_in_progress && current_symbol.address == 0xFFFF)
current_symbol.address = hex;
line_to_addr[line_counter] = hex;
addr_to_line[hex] = line_counter;
last_addr = hex;
}
}
lines.push_back(TabsToSpaces(4, line));
line_counter++;
}
fclose(f);
return true;
}
void AutoDisassembly(u16 start_addr, u16 end_addr)
{
AssemblerSettings settings;
settings.show_pc = true;
settings.show_hex = true;
DSPDisassembler disasm(settings);
u16 addr = start_addr;
const u16 *ptr = (start_addr >> 15) ? g_dsp.irom : g_dsp.iram;
while (addr < end_addr)
{
line_to_addr[line_counter] = addr;
addr_to_line[addr] = line_counter;
std::string buf;
if (!disasm.DisOpcode(ptr, 0, 2, &addr, buf))
{
ERROR_LOG(DSPLLE, "disasm failed at %04x", addr);
break;
}
//NOTICE_LOG(DSPLLE, "added %04x %i %s", addr, line_counter, buf.c_str());
lines.push_back(buf);
line_counter++;
}
}
void Clear()
{
addr_to_line.clear();
line_to_addr.clear();
lines.clear();
line_counter = 0;
}
} // namespace DSPSymbols
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <iostream> // I hope this doesn't break anything
#include <stdio.h>
#include <stdarg.h>
#include <list>
#include <map>
#include <string>
#include "Common.h"
#include "StringUtil.h"
#include "DSPCore.h"
#include "DSPSymbols.h"
#include "disassemble.h"
namespace DSPSymbols {
DSPSymbolDB g_dsp_symbol_db;
std::map<u16, int> addr_to_line;
std::map<int, u16> line_to_addr;
std::map<int, const char *> line_to_symbol;
std::vector<std::string> lines;
int line_counter = 0;
int Addr2Line(u16 address) // -1 for not found
{
std::map<u16, int>::iterator iter = addr_to_line.find(address);
if (iter != addr_to_line.end())
return iter->second;
else
return -1;
}
int Line2Addr(int line) // -1 for not found
{
std::map<int, u16>::iterator iter = line_to_addr.find(line);
if (iter != line_to_addr.end())
return iter->second;
else
return -1;
}
const char *GetLineText(int line)
{
if (line > 0 && line < (int)lines.size())
{
return lines[line].c_str();
}
else
return "----";
}
Symbol *DSPSymbolDB::GetSymbolFromAddr(u32 addr)
{
XFuncMap::iterator it = functions.find(addr);
if (it != functions.end())
return &it->second;
else
{
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
{
if (addr >= iter->second.address && addr < iter->second.address + iter->second.size)
return &iter->second;
}
}
return 0;
}
// lower case only
bool IsHexDigit(char c) {
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
return true;
default:
return false;
}
}
bool IsAlpha(char c) {
return (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z');
}
void DisasssembleRange(u16 start, u16 end)
{
}
bool ReadAnnotatedAssembly(const char *filename)
{
FILE *f = fopen(filename, "r");
if (!f) {
ERROR_LOG(DSPLLE, "Bah! ReadAnnotatedAssembly couldn't find the file %s", filename);
return false;
}
char line[512];
int last_addr = 0;
lines.reserve(3000);
// Symbol generation
int brace_count = 0;
bool symbol_in_progress = false;
int symbol_count = 0;
Symbol current_symbol;
while (fgets(line, 512, f))
{
// Scan string for the first 4-digit hex string.
size_t len = strlen(line);
int first_hex = -1;
bool hex_found = false;
for (unsigned int i = 0; i < strlen(line); i++)
{
const char c = line[i];
if (IsHexDigit(c))
{
if (first_hex == -1)
{
first_hex = i;
}
else
{
// Remove hex notation
if (i == first_hex + 3 &&
(first_hex == 0 || line[first_hex - 1] != 'x') &&
(i >= len - 1 || line[i + 1] == ' '))
{
hex_found = true;
break;
}
}
} else {
if (i - first_hex < 3)
{
first_hex = -1;
}
if (IsAlpha(c))
break;
}
}
// Scan for function starts
if (!memcmp(line, "void", 4)) {
char temp[256];
for (int i = 6; i < len; i++) {
if (line[i] == '(') {
// Yep, got one.
memcpy(temp, line + 5, i - 5);
temp[i - 5] = 0;
// Mark symbol so the next hex sets the address
current_symbol.name = temp;
current_symbol.address = 0xFFFF;
current_symbol.index = symbol_count++;
symbol_in_progress = true;
// Reset brace count.
brace_count = 0;
}
}
}
// Scan for braces
for (int i = 0; i < (int)len; i++) {
if (line[i] == '{')
brace_count++;
if (line[i] == '}')
{
brace_count--;
if (brace_count == 0 && symbol_in_progress) {
// Commit this symbol.
current_symbol.size = last_addr - current_symbol.address + 1;
g_dsp_symbol_db.AddCompleteSymbol(current_symbol);
current_symbol.address = 0xFFFF;
symbol_in_progress = false;
}
}
}
if (hex_found)
{
int hex = 0;
sscanf(line + first_hex, "%04x", &hex);
// Sanity check
if (hex > last_addr + 3 || hex < last_addr - 3) {
static int errors = 0;
ERROR_LOG(DSPLLE, "Got Insane Hex Digit %04x (%04x) from %s", hex, last_addr, line);
errors++;
if (errors > 10)
{
fclose(f);
return false;
}
}
else
{
// if (line_counter >= 200 && line_counter <= 220)
// NOTICE_LOG(DSPLLE, "Got Hex Digit %04x from %s, line %i", hex, line, line_counter);
if (symbol_in_progress && current_symbol.address == 0xFFFF)
current_symbol.address = hex;
line_to_addr[line_counter] = hex;
addr_to_line[hex] = line_counter;
last_addr = hex;
}
}
lines.push_back(TabsToSpaces(4, line));
line_counter++;
}
fclose(f);
return true;
}
void AutoDisassembly(u16 start_addr, u16 end_addr)
{
AssemblerSettings settings;
settings.show_pc = true;
settings.show_hex = true;
DSPDisassembler disasm(settings);
u16 addr = start_addr;
const u16 *ptr = (start_addr >> 15) ? g_dsp.irom : g_dsp.iram;
while (addr < end_addr)
{
line_to_addr[line_counter] = addr;
addr_to_line[addr] = line_counter;
std::string buf;
if (!disasm.DisOpcode(ptr, 0, 2, &addr, buf))
{
ERROR_LOG(DSPLLE, "disasm failed at %04x", addr);
break;
}
//NOTICE_LOG(DSPLLE, "added %04x %i %s", addr, line_counter, buf.c_str());
lines.push_back(buf);
line_counter++;
}
}
void Clear()
{
addr_to_line.clear();
line_to_addr.clear();
lines.clear();
line_counter = 0;
}
} // namespace DSPSymbols
+54 -54
View File
@@ -1,54 +1,54 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPSYMBOLS_H
#define _DSPSYMBOLS_H
#include "Common.h"
#include "SymbolDB.h"
#include "AudioCommon.h"
#include <stdio.h>
namespace DSPSymbols {
class DSPSymbolDB : public SymbolDB
{
public:
DSPSymbolDB() {}
~DSPSymbolDB() {}
Symbol *GetSymbolFromAddr(u32 addr);
};
extern DSPSymbolDB g_dsp_symbol_db;
bool ReadAnnotatedAssembly(const char *filename);
void AutoDisassembly(u16 start_addr, u16 end_addr);
void Clear();
int Addr2Line(u16 address);
int Line2Addr(int line); // -1 for not found
const char *GetLineText(int line);
} // namespace DSPSymbols
#endif
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSPSYMBOLS_H
#define _DSPSYMBOLS_H
#include "Common.h"
#include "SymbolDB.h"
#include "AudioCommon.h"
#include <stdio.h>
namespace DSPSymbols {
class DSPSymbolDB : public SymbolDB
{
public:
DSPSymbolDB() {}
~DSPSymbolDB() {}
Symbol *GetSymbolFromAddr(u32 addr);
};
extern DSPSymbolDB g_dsp_symbol_db;
bool ReadAnnotatedAssembly(const char *filename);
void AutoDisassembly(u16 start_addr, u16 end_addr);
void Clear();
int Addr2Line(u16 address);
int Line2Addr(int line); // -1 for not found
const char *GetLineText(int line);
} // namespace DSPSymbols
#endif
@@ -1,228 +1,228 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h" // Common
#include <iostream> // System
#include <fstream>
#include <sstream>
#include "Debugger.h"
#include "DSPRegisterView.h"
#include "CodeView.h"
#include "../DSPSymbols.h"
// Event table and class
BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxFrame)
EVT_CLOSE(DSPDebuggerLLE::OnClose)
EVT_MENU_RANGE(ID_RUNTOOL, ID_STEPTOOL, DSPDebuggerLLE::OnChangeState)
EVT_MENU(ID_SHOWPCTOOL, DSPDebuggerLLE::OnShowPC)
EVT_TEXT(ID_ADDRBOX, DSPDebuggerLLE::OnAddrBoxChange)
EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange)
END_EVENT_TABLE()
DSPDebuggerLLE::DSPDebuggerLLE(wxWindow *parent, wxWindowID id, const wxString &title,
const wxPoint &position, const wxSize& size, long style)
: wxFrame(parent, id, title, position, size, style)
, m_CachedStepCounter(-1)
{
CreateGUIControls();
}
DSPDebuggerLLE::~DSPDebuggerLLE()
{
}
void DSPDebuggerLLE::CreateGUIControls()
{
// Basic settings
SetSize(700, 800);
this->SetSizeHints(700, 800);
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
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_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_JUMPTOTOOL, wxT("Jump"), wxNullBitmap, wxT("Jump to a specific Address"), wxITEM_NORMAL);
m_Toolbar->AddSeparator();
m_Toolbar->AddControl(new wxTextCtrl(m_Toolbar, ID_ADDRBOX, _T("")));
m_Toolbar->Realize();
wxBoxSizer* sMain = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
sizerLeft->Add(m_SymbolList = new wxListBox(this, ID_SYMBOLLIST, wxDefaultPosition, wxSize(140, 100), 0, NULL, wxLB_SORT),
1, wxEXPAND);
m_CodeView = new CCodeView(&debug_interface, &DSPSymbols::g_dsp_symbol_db, this, ID_CODEVIEW);
m_CodeView->SetPlain();
sMain->Add(sizerLeft, 0, wxEXPAND, 0);
sMain->Add(m_CodeView, 4, wxEXPAND, 0);
wxStaticLine* m_staticline = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
sMain->Add(m_staticline, 0, wxEXPAND|wxALL, 0);
m_Regs = new DSPRegisterView(this, ID_DSP_REGS);
sMain->Add(m_Regs, 0, wxEXPAND|wxALL, 5);
this->SetSizer(sMain);
this->Layout();
UpdateState();
}
void DSPDebuggerLLE::OnClose(wxCloseEvent& event)
{
Hide();
}
void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
{
switch (event.GetId())
{
case ID_RUNTOOL:
if (DSPCore_GetState() == DSPCORE_RUNNING)
DSPCore_SetState(DSPCORE_STEPPING);
else
DSPCore_SetState(DSPCORE_RUNNING);
break;
case ID_STEPTOOL:
if (DSPCore_GetState() == DSPCORE_STEPPING)
DSPCore_Step();
break;
case ID_SHOWPCTOOL:
FocusOnPC();
break;
}
UpdateState();
}
void DSPDebuggerLLE::OnShowPC(wxCommandEvent& event)
{
Refresh();
FocusOnPC();
}
void DSPDebuggerLLE::Refresh()
{
UpdateSymbolMap();
UpdateDisAsmListView();
UpdateRegisterFlags();
UpdateState();
}
void DSPDebuggerLLE::FocusOnPC()
{
JumpToAddress(g_dsp.pc);
}
void DSPDebuggerLLE::UpdateState()
{
if (DSPCore_GetState() == DSPCORE_RUNNING) {
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Pause"));
m_Toolbar->FindById(ID_STEPTOOL)->Enable(false);
}
else {
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Run"));
m_Toolbar->FindById(ID_STEPTOOL)->Enable(true);
}
m_Toolbar->Realize();
}
void DSPDebuggerLLE::UpdateDisAsmListView()
{
if (m_CachedStepCounter == g_dsp.step_counter)
return;
// show PC
FocusOnPC();
m_CachedStepCounter = g_dsp.step_counter;
m_Regs->Update();
}
void DSPDebuggerLLE::UpdateSymbolMap()
{
if (g_dsp.dram == NULL)
return;
m_SymbolList->Freeze(); // HyperIris: wx style fast filling
m_SymbolList->Clear();
for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator();
iter != DSPSymbols::g_dsp_symbol_db.End(); iter++)
{
int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str()));
m_SymbolList->SetClientData(idx, (void*)&iter->second);
}
m_SymbolList->Thaw();
}
void DSPDebuggerLLE::OnSymbolListChange(wxCommandEvent& event)
{
int index = m_SymbolList->GetSelection();
if (index >= 0) {
Symbol* pSymbol = static_cast<Symbol *>(m_SymbolList->GetClientData(index));
if (pSymbol != NULL)
{
if (pSymbol->type == Symbol::SYMBOL_FUNCTION)
{
JumpToAddress(pSymbol->address);
}
}
}
}
void DSPDebuggerLLE::UpdateRegisterFlags()
{
}
void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event)
{
wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(ID_ADDRBOX);
wxString txt = pAddrCtrl->GetValue();
std::string text(txt.mb_str());
text = StripSpaces(text);
if (text.size())
{
u32 addr;
sscanf(text.c_str(), "%04x", &addr);
if (JumpToAddress(addr))
pAddrCtrl->SetBackgroundColour(*wxWHITE);
else
pAddrCtrl->SetBackgroundColour(*wxRED);
}
event.Skip(1);
}
bool DSPDebuggerLLE::JumpToAddress(u16 addr)
{
int new_line = DSPSymbols::Addr2Line(addr);
if (new_line >= 0) {
m_CodeView->Center(new_line);
return true;
} else {
return false;
}
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h" // Common
#include <iostream> // System
#include <fstream>
#include <sstream>
#include "Debugger.h"
#include "DSPRegisterView.h"
#include "CodeView.h"
#include "../DSPSymbols.h"
// Event table and class
BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxFrame)
EVT_CLOSE(DSPDebuggerLLE::OnClose)
EVT_MENU_RANGE(ID_RUNTOOL, ID_STEPTOOL, DSPDebuggerLLE::OnChangeState)
EVT_MENU(ID_SHOWPCTOOL, DSPDebuggerLLE::OnShowPC)
EVT_TEXT(ID_ADDRBOX, DSPDebuggerLLE::OnAddrBoxChange)
EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange)
END_EVENT_TABLE()
DSPDebuggerLLE::DSPDebuggerLLE(wxWindow *parent, wxWindowID id, const wxString &title,
const wxPoint &position, const wxSize& size, long style)
: wxFrame(parent, id, title, position, size, style)
, m_CachedStepCounter(-1)
{
CreateGUIControls();
}
DSPDebuggerLLE::~DSPDebuggerLLE()
{
}
void DSPDebuggerLLE::CreateGUIControls()
{
// Basic settings
SetSize(700, 800);
this->SetSizeHints(700, 800);
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
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_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_JUMPTOTOOL, wxT("Jump"), wxNullBitmap, wxT("Jump to a specific Address"), wxITEM_NORMAL);
m_Toolbar->AddSeparator();
m_Toolbar->AddControl(new wxTextCtrl(m_Toolbar, ID_ADDRBOX, _T("")));
m_Toolbar->Realize();
wxBoxSizer* sMain = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
sizerLeft->Add(m_SymbolList = new wxListBox(this, ID_SYMBOLLIST, wxDefaultPosition, wxSize(140, 100), 0, NULL, wxLB_SORT),
1, wxEXPAND);
m_CodeView = new CCodeView(&debug_interface, &DSPSymbols::g_dsp_symbol_db, this, ID_CODEVIEW);
m_CodeView->SetPlain();
sMain->Add(sizerLeft, 0, wxEXPAND, 0);
sMain->Add(m_CodeView, 4, wxEXPAND, 0);
wxStaticLine* m_staticline = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
sMain->Add(m_staticline, 0, wxEXPAND|wxALL, 0);
m_Regs = new DSPRegisterView(this, ID_DSP_REGS);
sMain->Add(m_Regs, 0, wxEXPAND|wxALL, 5);
this->SetSizer(sMain);
this->Layout();
UpdateState();
}
void DSPDebuggerLLE::OnClose(wxCloseEvent& event)
{
Hide();
}
void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
{
switch (event.GetId())
{
case ID_RUNTOOL:
if (DSPCore_GetState() == DSPCORE_RUNNING)
DSPCore_SetState(DSPCORE_STEPPING);
else
DSPCore_SetState(DSPCORE_RUNNING);
break;
case ID_STEPTOOL:
if (DSPCore_GetState() == DSPCORE_STEPPING)
DSPCore_Step();
break;
case ID_SHOWPCTOOL:
FocusOnPC();
break;
}
UpdateState();
}
void DSPDebuggerLLE::OnShowPC(wxCommandEvent& event)
{
Refresh();
FocusOnPC();
}
void DSPDebuggerLLE::Refresh()
{
UpdateSymbolMap();
UpdateDisAsmListView();
UpdateRegisterFlags();
UpdateState();
}
void DSPDebuggerLLE::FocusOnPC()
{
JumpToAddress(g_dsp.pc);
}
void DSPDebuggerLLE::UpdateState()
{
if (DSPCore_GetState() == DSPCORE_RUNNING) {
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Pause"));
m_Toolbar->FindById(ID_STEPTOOL)->Enable(false);
}
else {
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Run"));
m_Toolbar->FindById(ID_STEPTOOL)->Enable(true);
}
m_Toolbar->Realize();
}
void DSPDebuggerLLE::UpdateDisAsmListView()
{
if (m_CachedStepCounter == g_dsp.step_counter)
return;
// show PC
FocusOnPC();
m_CachedStepCounter = g_dsp.step_counter;
m_Regs->Update();
}
void DSPDebuggerLLE::UpdateSymbolMap()
{
if (g_dsp.dram == NULL)
return;
m_SymbolList->Freeze(); // HyperIris: wx style fast filling
m_SymbolList->Clear();
for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator();
iter != DSPSymbols::g_dsp_symbol_db.End(); iter++)
{
int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str()));
m_SymbolList->SetClientData(idx, (void*)&iter->second);
}
m_SymbolList->Thaw();
}
void DSPDebuggerLLE::OnSymbolListChange(wxCommandEvent& event)
{
int index = m_SymbolList->GetSelection();
if (index >= 0) {
Symbol* pSymbol = static_cast<Symbol *>(m_SymbolList->GetClientData(index));
if (pSymbol != NULL)
{
if (pSymbol->type == Symbol::SYMBOL_FUNCTION)
{
JumpToAddress(pSymbol->address);
}
}
}
}
void DSPDebuggerLLE::UpdateRegisterFlags()
{
}
void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event)
{
wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(ID_ADDRBOX);
wxString txt = pAddrCtrl->GetValue();
std::string text(txt.mb_str());
text = StripSpaces(text);
if (text.size())
{
u32 addr;
sscanf(text.c_str(), "%04x", &addr);
if (JumpToAddress(addr))
pAddrCtrl->SetBackgroundColour(*wxWHITE);
else
pAddrCtrl->SetBackgroundColour(*wxRED);
}
event.Skip(1);
}
bool DSPDebuggerLLE::JumpToAddress(u16 addr)
{
int new_line = DSPSymbols::Addr2Line(addr);
if (new_line >= 0) {
m_CodeView->Center(new_line);
return true;
} else {
return false;
}
}
@@ -1,126 +1,126 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSP_DEBUGGER_LLE_H
#define _DSP_DEBUGGER_LLE_H
// general things
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <algorithm>
#include <wx/wx.h>
#include <wx/frame.h>
#include <wx/button.h>
#include <wx/stattext.h>
#include <wx/statbox.h>
#include <wx/sizer.h>
#include <wx/listctrl.h>
#include <wx/statline.h>
#include "disassemble.h"
#include "DSPInterpreter.h"
#include "DSPMemoryMap.h"
#include "../DSPDebugInterface.h"
class DSPRegisterView;
class CCodeView;
class DSPDebuggerLLE : public wxFrame
{
public:
DSPDebuggerLLE(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString &title = wxT("DSP LLE Debugger"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_FRAME_STYLE);
virtual ~DSPDebuggerLLE();
void Refresh();
private:
DECLARE_EVENT_TABLE();
enum
{
// Toolbar
ID_TOOLBAR = 1000,
ID_RUNTOOL,
ID_STEPTOOL,
ID_SHOWPCTOOL,
ID_ADDRBOX,
ID_JUMPTOTOOL,
ID_DISASMDUMPTOOL,
ID_CHECK_ASSERTINT,
ID_CHECK_HALT,
ID_CHECK_INIT,
ID_SYMBOLLIST,
// Code view
ID_CODEVIEW,
// Register View
ID_DSP_REGS,
};
// Disasm listctrl columns
enum
{
COLUMN_BP,
COLUMN_FUNCTION,
COLUMN_ADDRESS,
COLUMN_MNEMONIC,
COLUMN_OPCODE,
COLUMN_EXT,
COLUMN_PARAM,
};
DSPDebugInterface debug_interface;
u64 m_CachedStepCounter;
// GUI updaters
void UpdateDisAsmListView();
void UpdateRegisterFlags();
void UpdateSymbolMap();
void UpdateState();
// GUI items
wxToolBar* m_Toolbar;
CCodeView* m_CodeView;
DSPRegisterView* m_Regs;
wxListBox* m_SymbolList;
void OnClose(wxCloseEvent& event);
void OnChangeState(wxCommandEvent& event);
void OnShowPC(wxCommandEvent& event);
void OnRightClick(wxListEvent& event);
void OnDoubleClick(wxListEvent& event);
void OnAddrBoxChange(wxCommandEvent& event);
void OnSymbolListChange(wxCommandEvent& event);
bool JumpToAddress(u16 addr);
void CreateGUIControls();
void FocusOnPC();
void UnselectAll();
};
#endif //_DSP_DEBUGGER_LLE_H
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _DSP_DEBUGGER_LLE_H
#define _DSP_DEBUGGER_LLE_H
// general things
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <algorithm>
#include <wx/wx.h>
#include <wx/frame.h>
#include <wx/button.h>
#include <wx/stattext.h>
#include <wx/statbox.h>
#include <wx/sizer.h>
#include <wx/listctrl.h>
#include <wx/statline.h>
#include "disassemble.h"
#include "DSPInterpreter.h"
#include "DSPMemoryMap.h"
#include "../DSPDebugInterface.h"
class DSPRegisterView;
class CCodeView;
class DSPDebuggerLLE : public wxFrame
{
public:
DSPDebuggerLLE(wxWindow *parent,
wxWindowID id = wxID_ANY,
const wxString &title = wxT("DSP LLE Debugger"),
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_FRAME_STYLE);
virtual ~DSPDebuggerLLE();
void Refresh();
private:
DECLARE_EVENT_TABLE();
enum
{
// Toolbar
ID_TOOLBAR = 1000,
ID_RUNTOOL,
ID_STEPTOOL,
ID_SHOWPCTOOL,
ID_ADDRBOX,
ID_JUMPTOTOOL,
ID_DISASMDUMPTOOL,
ID_CHECK_ASSERTINT,
ID_CHECK_HALT,
ID_CHECK_INIT,
ID_SYMBOLLIST,
// Code view
ID_CODEVIEW,
// Register View
ID_DSP_REGS,
};
// Disasm listctrl columns
enum
{
COLUMN_BP,
COLUMN_FUNCTION,
COLUMN_ADDRESS,
COLUMN_MNEMONIC,
COLUMN_OPCODE,
COLUMN_EXT,
COLUMN_PARAM,
};
DSPDebugInterface debug_interface;
u64 m_CachedStepCounter;
// GUI updaters
void UpdateDisAsmListView();
void UpdateRegisterFlags();
void UpdateSymbolMap();
void UpdateState();
// GUI items
wxToolBar* m_Toolbar;
CCodeView* m_CodeView;
DSPRegisterView* m_Regs;
wxListBox* m_SymbolList;
void OnClose(wxCloseEvent& event);
void OnChangeState(wxCommandEvent& event);
void OnShowPC(wxCommandEvent& event);
void OnRightClick(wxListEvent& event);
void OnDoubleClick(wxListEvent& event);
void OnAddrBoxChange(wxCommandEvent& event);
void OnSymbolListChange(wxCommandEvent& event);
bool JumpToAddress(u16 addr);
void CreateGUIControls();
void FocusOnPC();
void UnselectAll();
};
#endif //_DSP_DEBUGGER_LLE_H
+335 -335
View File
@@ -1,336 +1,336 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "BPFunctions.h"
#include "D3DBase.h"
#include "Config.h"
#include "Common.h"
#include "TextureCache.h"
#include "VertexManager.h"
#include "VertexShaderManager.h"
#include "Utils.h"
bool textureChanged[8];
const bool renderFog = false;
using namespace D3D;
// State translation lookup tables
static const D3DBLEND d3dSrcFactors[8] =
{
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_DESTCOLOR,
D3DBLEND_INVDESTCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA
};
static const D3DBLEND d3dDestFactors[8] =
{
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_SRCCOLOR,
D3DBLEND_INVSRCCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA
};
static const D3DCULL d3dCullModes[4] =
{
D3DCULL_NONE,
D3DCULL_CCW,
D3DCULL_CW,
D3DCULL_CCW
};
static const D3DCMPFUNC d3dCmpFuncs[8] =
{
D3DCMP_NEVER,
D3DCMP_LESS,
D3DCMP_EQUAL,
D3DCMP_LESSEQUAL,
D3DCMP_GREATER,
D3DCMP_NOTEQUAL,
D3DCMP_GREATEREQUAL,
D3DCMP_ALWAYS
};
static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
{
D3DTEXF_NONE,
D3DTEXF_POINT,
D3DTEXF_ANISOTROPIC,
D3DTEXF_LINEAR, //reserved
};
static const D3DTEXTUREADDRESS d3dClamps[4] =
{
D3DTADDRESS_CLAMP,
D3DTADDRESS_WRAP,
D3DTADDRESS_MIRROR,
D3DTADDRESS_WRAP //reserved
};
namespace BPFunctions
{
void FlushPipeline()
{
VertexManager::Flush();
}
void SetGenerationMode(const Bypass &bp)
{
// dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
Renderer::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
if (bpmem.genMode.cullmode == 3)
{
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, 0);
}
else
{
DWORD write = 0;
if (bpmem.blendmode.alphaupdate)
write = D3DCOLORWRITEENABLE_ALPHA;
if (bpmem.blendmode.colorupdate)
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, write);
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
}
}
void SetScissor(const Bypass &bp)
{
Renderer::SetScissorRect();
}
void SetLineWidth(const Bypass &bp)
{
// We can't change line width in D3D unless we use ID3DXLine
float psize = float(bpmem.lineptwidth.pointsize) * 6.0f;
Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize));
}
void SetDepthMode(const Bypass &bp)
{
if (bpmem.zmode.testenable)
{
// dev->SetRenderState(D3DRS_ZENABLE, TRUE);
// dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
// dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]);
Renderer::SetRenderState(D3DRS_ZENABLE, TRUE);
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
Renderer::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func]);
}
else
{
// if the test is disabled write is disabled too
// dev->SetRenderState(D3DRS_ZENABLE, FALSE);
// dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
Renderer::SetRenderState(D3DRS_ZENABLE, FALSE);
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
}
//if (!bpmem.zmode.updateenable)
// Renderer::SetRenderMode(Renderer::RM_Normal);
}
void SetBlendMode(const Bypass &bp)
{
if (bp.changes & 1)
Renderer::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable);
D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor];
D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor];
if (bp.changes & 0x700)
Renderer::SetRenderState(D3DRS_SRCBLEND, src);
if (bp.changes & 0xE0) {
if (!bpmem.blendmode.subtract)
{
Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
}
else
{
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
}
if (bp.changes & 0x800)
{
if (bpmem.blendmode.subtract)
{
Renderer::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
else
{
Renderer::SetRenderState(D3DRS_SRCBLEND, src);
Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
}
Renderer::SetRenderState(D3DRS_BLENDOP, bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD);
}
}
void SetDitherMode(const Bypass &bp)
{
Renderer::SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither);
}
void SetLogicOpMode(const Bypass &bp)
{
// Logic op blending. D3D can't do this but can fake some modes.
}
void SetColorMask(const Bypass &bp)
{
DWORD write = 0;
if (bpmem.blendmode.alphaupdate)
write = D3DCOLORWRITEENABLE_ALPHA;
if (bpmem.blendmode.colorupdate)
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
}
float GetRendererTargetScaleX()
{
return Renderer::GetXScale();
}
float GetRendererTargetScaleY()
{
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)
{
RECT rec = { rc.left, rc.top, rc.right, rc.bottom };
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)
{
Renderer::SwapBuffers();
PRIM_LOG("Renderer::SwapBuffers()");
g_VideoInitialize.pCopiedToXFB();
}
void ClearScreen(const Bypass &bp, const TRectangle &multirc)
{
// 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
VertexShaderManager::SetViewportChanged();
// Since clear operations use the source rectangle, we have to do
// regular renders
DWORD clearflags = 0;
D3DCOLOR col = 0;
float clearZ = 0;
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
{
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
col = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
// clearflags |= D3DCLEAR_TARGET; set to break animal crossing :p
}
// clear z-buffer
if (bpmem.zmode.updateenable)
{
clearZ = (float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF);
if (clearZ > 1.0f) clearZ = 1.0f;
if (clearZ < 0.0f) clearZ = 0.0f;
clearflags |= D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
}
D3D::dev->Clear(0, NULL, clearflags, col, clearZ, 0);
}
void RestoreRenderState(const Bypass &bp)
{
//Renderer::SetRenderMode(Renderer::RM_Normal);
}
bool GetConfig(const int &type)
{
switch (type)
{
case CONFIG_ISWII:
return g_VideoInitialize.bWii;
case CONFIG_DISABLEFOG:
return false;
case CONFIG_SHOWEFBREGIONS:
return false;
default:
PanicAlert("GetConfig Error: Unknown Config Type!");
return false;
}
}
u8 *GetPointer(const u32 &address)
{
return g_VideoInitialize.pGetMemoryPointer(address);
}
void SetSamplerState(const Bypass &bp)
{
FourTexUnits &tex = bpmem.tex[(bp.address & 0xE0) == 0xA0];
int stage = (bp.address & 3);//(addr>>4)&2;
TexMode0 &tm0 = tex.texMode0[stage];
D3DTEXTUREFILTERTYPE min, mag, mip;
if (g_Config.bForceFiltering)
{
min = mag = mip = D3DTEXF_LINEAR;
}
else
{
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
mip = d3dMipFilters[tm0.min_filter & 3];
}
if ((bp.address & 0xE0) == 0xA0)
stage += 4;
if (g_Config.bForceMaxAniso)
{
mag = D3DTEXF_ANISOTROPIC;
mip = D3DTEXF_ANISOTROPIC;
min = D3DTEXF_ANISOTROPIC;
}
dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min);
dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag);
dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip);
dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 16);
dev->SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
dev->SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
//wip
//dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f);
//char temp[256];
//sprintf(temp,"lod %f",tm0.lod_bias/4.0f);
//g_VideoInitialize.pLog(temp);
}
void SetInterlacingMode(const Bypass &bp)
{
// TODO
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "BPFunctions.h"
#include "D3DBase.h"
#include "Config.h"
#include "Common.h"
#include "TextureCache.h"
#include "VertexManager.h"
#include "VertexShaderManager.h"
#include "Utils.h"
bool textureChanged[8];
const bool renderFog = false;
using namespace D3D;
// State translation lookup tables
static const D3DBLEND d3dSrcFactors[8] =
{
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_DESTCOLOR,
D3DBLEND_INVDESTCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA
};
static const D3DBLEND d3dDestFactors[8] =
{
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_SRCCOLOR,
D3DBLEND_INVSRCCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA
};
static const D3DCULL d3dCullModes[4] =
{
D3DCULL_NONE,
D3DCULL_CCW,
D3DCULL_CW,
D3DCULL_CCW
};
static const D3DCMPFUNC d3dCmpFuncs[8] =
{
D3DCMP_NEVER,
D3DCMP_LESS,
D3DCMP_EQUAL,
D3DCMP_LESSEQUAL,
D3DCMP_GREATER,
D3DCMP_NOTEQUAL,
D3DCMP_GREATEREQUAL,
D3DCMP_ALWAYS
};
static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
{
D3DTEXF_NONE,
D3DTEXF_POINT,
D3DTEXF_ANISOTROPIC,
D3DTEXF_LINEAR, //reserved
};
static const D3DTEXTUREADDRESS d3dClamps[4] =
{
D3DTADDRESS_CLAMP,
D3DTADDRESS_WRAP,
D3DTADDRESS_MIRROR,
D3DTADDRESS_WRAP //reserved
};
namespace BPFunctions
{
void FlushPipeline()
{
VertexManager::Flush();
}
void SetGenerationMode(const Bypass &bp)
{
// dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
Renderer::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
if (bpmem.genMode.cullmode == 3)
{
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, 0);
}
else
{
DWORD write = 0;
if (bpmem.blendmode.alphaupdate)
write = D3DCOLORWRITEENABLE_ALPHA;
if (bpmem.blendmode.colorupdate)
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, write);
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
}
}
void SetScissor(const Bypass &bp)
{
Renderer::SetScissorRect();
}
void SetLineWidth(const Bypass &bp)
{
// We can't change line width in D3D unless we use ID3DXLine
float psize = float(bpmem.lineptwidth.pointsize) * 6.0f;
Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize));
}
void SetDepthMode(const Bypass &bp)
{
if (bpmem.zmode.testenable)
{
// dev->SetRenderState(D3DRS_ZENABLE, TRUE);
// dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
// dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]);
Renderer::SetRenderState(D3DRS_ZENABLE, TRUE);
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
Renderer::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func]);
}
else
{
// if the test is disabled write is disabled too
// dev->SetRenderState(D3DRS_ZENABLE, FALSE);
// dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
Renderer::SetRenderState(D3DRS_ZENABLE, FALSE);
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
}
//if (!bpmem.zmode.updateenable)
// Renderer::SetRenderMode(Renderer::RM_Normal);
}
void SetBlendMode(const Bypass &bp)
{
if (bp.changes & 1)
Renderer::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable);
D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor];
D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor];
if (bp.changes & 0x700)
Renderer::SetRenderState(D3DRS_SRCBLEND, src);
if (bp.changes & 0xE0) {
if (!bpmem.blendmode.subtract)
{
Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
}
else
{
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
}
if (bp.changes & 0x800)
{
if (bpmem.blendmode.subtract)
{
Renderer::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
else
{
Renderer::SetRenderState(D3DRS_SRCBLEND, src);
Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
}
Renderer::SetRenderState(D3DRS_BLENDOP, bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD);
}
}
void SetDitherMode(const Bypass &bp)
{
Renderer::SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither);
}
void SetLogicOpMode(const Bypass &bp)
{
// Logic op blending. D3D can't do this but can fake some modes.
}
void SetColorMask(const Bypass &bp)
{
DWORD write = 0;
if (bpmem.blendmode.alphaupdate)
write = D3DCOLORWRITEENABLE_ALPHA;
if (bpmem.blendmode.colorupdate)
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
}
float GetRendererTargetScaleX()
{
return Renderer::GetXScale();
}
float GetRendererTargetScaleY()
{
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)
{
RECT rec = { rc.left, rc.top, rc.right, rc.bottom };
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)
{
Renderer::SwapBuffers();
PRIM_LOG("Renderer::SwapBuffers()");
g_VideoInitialize.pCopiedToXFB();
}
void ClearScreen(const Bypass &bp, const TRectangle &multirc)
{
// 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
VertexShaderManager::SetViewportChanged();
// Since clear operations use the source rectangle, we have to do
// regular renders
DWORD clearflags = 0;
D3DCOLOR col = 0;
float clearZ = 0;
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
{
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
col = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
// clearflags |= D3DCLEAR_TARGET; set to break animal crossing :p
}
// clear z-buffer
if (bpmem.zmode.updateenable)
{
clearZ = (float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF);
if (clearZ > 1.0f) clearZ = 1.0f;
if (clearZ < 0.0f) clearZ = 0.0f;
clearflags |= D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
}
D3D::dev->Clear(0, NULL, clearflags, col, clearZ, 0);
}
void RestoreRenderState(const Bypass &bp)
{
//Renderer::SetRenderMode(Renderer::RM_Normal);
}
bool GetConfig(const int &type)
{
switch (type)
{
case CONFIG_ISWII:
return g_VideoInitialize.bWii;
case CONFIG_DISABLEFOG:
return false;
case CONFIG_SHOWEFBREGIONS:
return false;
default:
PanicAlert("GetConfig Error: Unknown Config Type!");
return false;
}
}
u8 *GetPointer(const u32 &address)
{
return g_VideoInitialize.pGetMemoryPointer(address);
}
void SetSamplerState(const Bypass &bp)
{
FourTexUnits &tex = bpmem.tex[(bp.address & 0xE0) == 0xA0];
int stage = (bp.address & 3);//(addr>>4)&2;
TexMode0 &tm0 = tex.texMode0[stage];
D3DTEXTUREFILTERTYPE min, mag, mip;
if (g_Config.bForceFiltering)
{
min = mag = mip = D3DTEXF_LINEAR;
}
else
{
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
mip = d3dMipFilters[tm0.min_filter & 3];
}
if ((bp.address & 0xE0) == 0xA0)
stage += 4;
if (g_Config.bForceMaxAniso)
{
mag = D3DTEXF_ANISOTROPIC;
mip = D3DTEXF_ANISOTROPIC;
min = D3DTEXF_ANISOTROPIC;
}
dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min);
dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag);
dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip);
dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 16);
dev->SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
dev->SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
//wip
//dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f);
//char temp[256];
//sprintf(temp,"lod %f",tm0.lod_bias/4.0f);
//g_VideoInitialize.pLog(temp);
}
void SetInterlacingMode(const Bypass &bp)
{
// TODO
}
};
+212 -212
View File
@@ -1,212 +1,212 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "BPFunctions.h"
#include "Globals.h"
#include "Profiler.h"
#include "Config.h"
#include "VertexManager.h"
#include "Render.h"
#include "TextureMngr.h"
#include "TextureConverter.h"
#include "VertexShaderManager.h"
#include "XFB.h"
#include "main.h"
namespace BPFunctions
{
// ----------------------------------------------
// State translation lookup tables
// Reference: Yet Another Gamecube Documentation
// ----------------------------------------------
static const GLenum glCmpFuncs[8] = {
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
};
static const GLenum glLogicOpCodes[16] = {
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
};
void FlushPipeline()
{
VertexManager::Flush();
}
void SetGenerationMode(const Bypass &bp)
{
// none, ccw, cw, ccw
if (bpmem.genMode.cullmode > 0)
{
glEnable(GL_CULL_FACE);
glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW);
}
else
glDisable(GL_CULL_FACE);
}
void SetScissor(const Bypass &bp)
{
if (!Renderer::SetScissorRect())
if (bp.address == BPMEM_SCISSORBR)
ERROR_LOG(VIDEO, "bad scissor!");
}
void SetLineWidth(const Bypass &bp)
{
float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f;
if (bpmem.lineptwidth.linesize > 0)
glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths
if (bpmem.lineptwidth.pointsize > 0)
glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f);
}
void SetDepthMode(const Bypass &bp)
{
if (bpmem.zmode.testenable)
{
glEnable(GL_DEPTH_TEST);
glDepthMask(bpmem.zmode.updateenable ? GL_TRUE : GL_FALSE);
glDepthFunc(glCmpFuncs[bpmem.zmode.func]);
}
else
{
// if the test is disabled write is disabled too
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
}
}
void SetBlendMode(const Bypass &bp)
{
Renderer::SetBlendMode(false);
}
void SetDitherMode(const Bypass &bp)
{
if (bpmem.blendmode.dither)
glEnable(GL_DITHER);
else
glDisable(GL_DITHER);
}
void SetLogicOpMode(const Bypass &bp)
{
if (bpmem.blendmode.logicopenable)
{
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
}
else
glDisable(GL_COLOR_LOGIC_OP);
}
void SetColorMask(const Bypass &bp)
{
Renderer::SetColorMask();
}
float GetRendererTargetScaleX()
{
return Renderer::GetTargetScaleX();
}
float GetRendererTargetScaleY()
{
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)
{
// 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.bCopyEFBToRAM) // To RAM
TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
else // To OGL Texture
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)
{
Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, multirc);
}
void ClearScreen(const Bypass &bp, const TRectangle &multirc)
{
// Update the view port for clearing the picture
glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
// Always set the scissor in case it was set by the game and has not been reset
glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom),
(multirc.right - multirc.left), (multirc.bottom - multirc.top));
// ---------------------------
VertexShaderManager::SetViewportChanged();
// Since clear operations use the source rectangle, we have to do
// regular renders (glClear clears the entire buffer)
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate || bpmem.zmode.updateenable)
{
GLbitfield bits = 0;
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
{
u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
// Alpha may or may not be present depending on the EFB pixel format.
GLclampf clearAlpha = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) ?
((clearColor>>24) & 0xff)*(1/255.0f) : 1.0f;
glClearColor(((clearColor>>16) & 0xff)*(1/255.0f),
((clearColor>>8 ) & 0xff)*(1/255.0f),
((clearColor>>0 ) & 0xff)*(1/255.0f),
clearAlpha);
bits |= GL_COLOR_BUFFER_BIT;
}
if (bpmem.zmode.updateenable)
{
glClearDepth((float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF));
bits |= GL_DEPTH_BUFFER_BIT;
}
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glClear(bits);
}
}
void RestoreRenderState(const Bypass &bp)
{
Renderer::RestoreGLState();
}
bool GetConfig(const int &type)
{
switch (type)
{
case CONFIG_ISWII:
return g_VideoInitialize.bWii;
case CONFIG_DISABLEFOG:
return g_Config.bDisableFog;
case CONFIG_SHOWEFBREGIONS:
return g_Config.bShowEFBCopyRegions;
default:
PanicAlert("GetConfig Error: Unknown Config Type!");
return false;
}
}
u8 *GetPointer(const u32 &address)
{
return g_VideoInitialize.pGetMemoryPointer(address);
}
void SetSamplerState(const Bypass &bp)
{
// TODO
}
void SetInterlacingMode(const Bypass &bp)
{
// TODO
}
};
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "BPFunctions.h"
#include "Globals.h"
#include "Profiler.h"
#include "Config.h"
#include "VertexManager.h"
#include "Render.h"
#include "TextureMngr.h"
#include "TextureConverter.h"
#include "VertexShaderManager.h"
#include "XFB.h"
#include "main.h"
namespace BPFunctions
{
// ----------------------------------------------
// State translation lookup tables
// Reference: Yet Another Gamecube Documentation
// ----------------------------------------------
static const GLenum glCmpFuncs[8] = {
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
};
static const GLenum glLogicOpCodes[16] = {
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
};
void FlushPipeline()
{
VertexManager::Flush();
}
void SetGenerationMode(const Bypass &bp)
{
// none, ccw, cw, ccw
if (bpmem.genMode.cullmode > 0)
{
glEnable(GL_CULL_FACE);
glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW);
}
else
glDisable(GL_CULL_FACE);
}
void SetScissor(const Bypass &bp)
{
if (!Renderer::SetScissorRect())
if (bp.address == BPMEM_SCISSORBR)
ERROR_LOG(VIDEO, "bad scissor!");
}
void SetLineWidth(const Bypass &bp)
{
float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f;
if (bpmem.lineptwidth.linesize > 0)
glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths
if (bpmem.lineptwidth.pointsize > 0)
glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f);
}
void SetDepthMode(const Bypass &bp)
{
if (bpmem.zmode.testenable)
{
glEnable(GL_DEPTH_TEST);
glDepthMask(bpmem.zmode.updateenable ? GL_TRUE : GL_FALSE);
glDepthFunc(glCmpFuncs[bpmem.zmode.func]);
}
else
{
// if the test is disabled write is disabled too
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
}
}
void SetBlendMode(const Bypass &bp)
{
Renderer::SetBlendMode(false);
}
void SetDitherMode(const Bypass &bp)
{
if (bpmem.blendmode.dither)
glEnable(GL_DITHER);
else
glDisable(GL_DITHER);
}
void SetLogicOpMode(const Bypass &bp)
{
if (bpmem.blendmode.logicopenable)
{
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
}
else
glDisable(GL_COLOR_LOGIC_OP);
}
void SetColorMask(const Bypass &bp)
{
Renderer::SetColorMask();
}
float GetRendererTargetScaleX()
{
return Renderer::GetTargetScaleX();
}
float GetRendererTargetScaleY()
{
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)
{
// 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.bCopyEFBToRAM) // To RAM
TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
else // To OGL Texture
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)
{
Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, multirc);
}
void ClearScreen(const Bypass &bp, const TRectangle &multirc)
{
// Update the view port for clearing the picture
glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
// Always set the scissor in case it was set by the game and has not been reset
glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom),
(multirc.right - multirc.left), (multirc.bottom - multirc.top));
// ---------------------------
VertexShaderManager::SetViewportChanged();
// Since clear operations use the source rectangle, we have to do
// regular renders (glClear clears the entire buffer)
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate || bpmem.zmode.updateenable)
{
GLbitfield bits = 0;
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
{
u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
// Alpha may or may not be present depending on the EFB pixel format.
GLclampf clearAlpha = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) ?
((clearColor>>24) & 0xff)*(1/255.0f) : 1.0f;
glClearColor(((clearColor>>16) & 0xff)*(1/255.0f),
((clearColor>>8 ) & 0xff)*(1/255.0f),
((clearColor>>0 ) & 0xff)*(1/255.0f),
clearAlpha);
bits |= GL_COLOR_BUFFER_BIT;
}
if (bpmem.zmode.updateenable)
{
glClearDepth((float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF));
bits |= GL_DEPTH_BUFFER_BIT;
}
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glClear(bits);
}
}
void RestoreRenderState(const Bypass &bp)
{
Renderer::RestoreGLState();
}
bool GetConfig(const int &type)
{
switch (type)
{
case CONFIG_ISWII:
return g_VideoInitialize.bWii;
case CONFIG_DISABLEFOG:
return g_Config.bDisableFog;
case CONFIG_SHOWEFBREGIONS:
return g_Config.bShowEFBCopyRegions;
default:
PanicAlert("GetConfig Error: Unknown Config Type!");
return false;
}
}
u8 *GetPointer(const u32 &address)
{
return g_VideoInitialize.pGetMemoryPointer(address);
}
void SetSamplerState(const Bypass &bp)
{
// TODO
}
void SetInterlacingMode(const Bypass &bp)
{
// TODO
}
};
@@ -1,451 +1,451 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Globals.h"
#include "FramebufferManager.h"
#include "TextureConverter.h"
#include "XFB.h"
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
{
m_targetWidth = targetWidth;
m_targetHeight = targetHeight;
m_msaaSamples = msaaSamples;
m_msaaCoverageSamples = msaaCoverageSamples;
// The EFB can be set to different pixel formats by the game through the
// BPMEM_ZCOMPARE register (which should probably have a different name).
// They are:
// - 24-bit RGB (8-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
// We only use one EFB format here: 32-bit ARGB with 24-bit Z.
// Multisampling depends on user settings.
// The distinction becomes important for certain operations, i.e. the
// alpha channel should be ignored if the EFB does not have one.
// Create EFB target.
glGenFramebuffersEXT(1, &m_efbFramebuffer);
if (m_msaaSamples <= 1)
{
// EFB targets will be textures in non-MSAA mode.
GLuint glObj[2];
glGenTextures(2, glObj);
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
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);
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);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Bind target textures to the EFB framebuffer.
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_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
GL_REPORT_FBO_ERROR();
}
else
{
// EFB targets will be renderbuffers in MSAA mode (required by OpenGL).
// Resolve targets will be created to transfer EFB to RAM textures.
// XFB framebuffer will be created to transfer EFB to XFB texture.
// Create EFB target renderbuffers.
GLuint glObj[2];
glGenRenderbuffersEXT(2, glObj);
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
if (m_msaaCoverageSamples)
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
else
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
if (m_msaaCoverageSamples)
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
else
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// Bind target renderbuffers to EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
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);
GL_REPORT_FBO_ERROR();
// Create resolved targets for transferring multisampled EFB to texture.
glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
glGenTextures(2, glObj);
m_resolvedColorTexture = glObj[0];
m_resolvedDepthTexture = glObj[1];
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);
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);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Bind resolved textures to resolved framebuffer.
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_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
GL_REPORT_FBO_ERROR();
// Return to EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
}
// Create XFB framebuffer; targets will be created elsewhere.
glGenFramebuffersEXT(1, &m_xfbFramebuffer);
// EFB framebuffer is currently bound.
}
void FramebufferManager::Shutdown()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GLuint glObj[3];
// Note: OpenGL deletion functions silently ignore parameters of "0".
glObj[0] = m_efbFramebuffer;
glObj[1] = m_resolvedFramebuffer;
glObj[2] = m_xfbFramebuffer;
glDeleteFramebuffersEXT(3, glObj);
m_efbFramebuffer = 0;
m_xfbFramebuffer = 0;
glObj[0] = m_resolvedColorTexture;
glObj[1] = m_resolvedDepthTexture;
glObj[2] = m_realXFBSource.texture;
glDeleteTextures(3, glObj);
m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0;
m_realXFBSource.texture = 0;
glObj[0] = m_efbColor;
glObj[1] = m_efbDepth;
if (m_msaaSamples <= 1)
glDeleteTextures(2, glObj);
else
glDeleteRenderbuffersEXT(2, glObj);
m_efbColor = 0;
m_efbDepth = 0;
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
{
glDeleteTextures(1, &it->xfbSource.texture);
}
m_virtualXFBList.clear();
}
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{
if (g_Config.bUseXFB)
copyToRealXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
else
copyToVirtualXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
}
const XFBSource* FramebufferManager::GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{
if (g_Config.bUseXFB)
return getRealXFBSource(xfbAddr, srcWidth, srcHeight);
else
return getVirtualXFBSource(xfbAddr, srcWidth, srcHeight);
}
GLuint FramebufferManager::GetEFBColorTexture(const TRectangle& sourceRc) const
{
if (m_msaaSamples <= 1)
{
return m_efbColor;
}
else
{
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
// required.
// Flip source rectangle upside-down for OpenGL.
TRectangle glRect;
sourceRc.FlipYPosition(m_targetHeight, &glRect);
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glBlitFramebufferEXT(
glRect.left, glRect.top, glRect.right, glRect.bottom,
glRect.left, glRect.top, glRect.right, glRect.bottom,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
return m_resolvedColorTexture;
}
}
GLuint FramebufferManager::GetEFBDepthTexture(const TRectangle& sourceRc) const
{
if (m_msaaSamples <= 1)
{
return m_efbDepth;
}
else
{
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
// required.
// Flip source rectangle upside-down for OpenGL.
TRectangle glRect;
sourceRc.FlipYPosition(m_targetHeight, &glRect);
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glBlitFramebufferEXT(
glRect.left, glRect.top, glRect.right, glRect.bottom,
glRect.left, glRect.top, glRect.right, glRect.bottom,
GL_DEPTH_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
return m_resolvedDepthTexture;
}
}
FramebufferManager::VirtualXFBListType::iterator
FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
{
u32 srcLower = xfbAddr;
u32 srcUpper = xfbAddr + 2 * width * height;
VirtualXFBListType::iterator it;
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
{
u32 dstLower = it->xfbAddr;
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
return it;
}
// That address is not in the Virtual XFB list.
return m_virtualXFBList.end();
}
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{
u8* pXFB = Memory_GetPtr(xfbAddr);
if (!pXFB)
{
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
return;
}
XFB_Write(pXFB, sourceRc, dstWidth, dstHeight);
}
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{
GLuint xfbTexture;
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, dstWidth, dstHeight);
if (it != m_virtualXFBList.end())
{
// Overwrite an existing Virtual XFB.
it->xfbAddr = xfbAddr;
it->xfbWidth = dstWidth;
it->xfbHeight = dstHeight;
it->xfbSource.texWidth = m_targetWidth;
it->xfbSource.texHeight = m_targetHeight;
it->xfbSource.sourceRc = sourceRc;
xfbTexture = it->xfbSource.texture;
// Move this Virtual XFB to the front of the list.
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
}
else
{
// Create a new Virtual XFB and place it at the front of the list.
glGenTextures(1, &xfbTexture);
#if 0 // XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
if (m_msaaSamples > 1)
#else
if (s_bHaveFramebufferBlit)
#endif
{
// In MSAA mode, allocate the texture image here. In non-MSAA mode,
// the image will be allocated by glCopyTexImage2D (later).
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, m_targetWidth, m_targetHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
}
VirtualXFB newVirt;
newVirt.xfbAddr = xfbAddr;
newVirt.xfbWidth = dstWidth;
newVirt.xfbHeight = dstHeight;
newVirt.xfbSource.texture = xfbTexture;
newVirt.xfbSource.texWidth = m_targetWidth;
newVirt.xfbSource.texHeight = m_targetHeight;
newVirt.xfbSource.sourceRc = sourceRc;
// Add the new Virtual XFB to the list
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
{
// List overflowed; delete the oldest.
glDeleteTextures(1, &m_virtualXFBList.back().xfbSource.texture);
m_virtualXFBList.pop_back();
}
m_virtualXFBList.push_front(newVirt);
}
// Copy EFB to XFB texture
#if 0
if (m_msaaSamples <= 1)
#else
if (!s_bHaveFramebufferBlit)
#endif
{
// Just copy the EFB directly.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, m_targetWidth, m_targetHeight, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
}
else
{
// OpenGL cannot copy directly from a multisampled framebuffer, so use
// EXT_framebuffer_blit.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_xfbFramebuffer);
// Bind texture.
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbTexture, 0);
GL_REPORT_FBO_ERROR();
glBlitFramebufferEXT(
0, 0, m_targetWidth, m_targetHeight,
0, 0, m_targetWidth, m_targetHeight,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
// Unbind texture.
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
// Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
}
}
const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{
m_realXFBSource.texWidth = XFB_WIDTH;
m_realXFBSource.texHeight = XFB_HEIGHT;
m_realXFBSource.sourceRc.left = 0;
m_realXFBSource.sourceRc.top = 0;
m_realXFBSource.sourceRc.right = srcWidth;
m_realXFBSource.sourceRc.bottom = srcHeight;
if (!m_realXFBSource.texture)
{
glGenTextures(1, &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);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
}
// Decode YUYV data from GameCube RAM
TextureConverter::DecodeToTexture(xfbAddr, srcWidth, srcHeight, m_realXFBSource.texture);
return &m_realXFBSource;
}
const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{
if (m_virtualXFBList.size() == 0)
{
// No Virtual XFBs available.
return NULL;
}
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, srcWidth, srcHeight);
if (it == m_virtualXFBList.end())
{
// Virtual XFB is not in the list, so return the most recently rendered
// one.
it = m_virtualXFBList.begin();
}
return &it->xfbSource;
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Globals.h"
#include "FramebufferManager.h"
#include "TextureConverter.h"
#include "XFB.h"
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
{
m_targetWidth = targetWidth;
m_targetHeight = targetHeight;
m_msaaSamples = msaaSamples;
m_msaaCoverageSamples = msaaCoverageSamples;
// The EFB can be set to different pixel formats by the game through the
// BPMEM_ZCOMPARE register (which should probably have a different name).
// They are:
// - 24-bit RGB (8-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
// We only use one EFB format here: 32-bit ARGB with 24-bit Z.
// Multisampling depends on user settings.
// The distinction becomes important for certain operations, i.e. the
// alpha channel should be ignored if the EFB does not have one.
// Create EFB target.
glGenFramebuffersEXT(1, &m_efbFramebuffer);
if (m_msaaSamples <= 1)
{
// EFB targets will be textures in non-MSAA mode.
GLuint glObj[2];
glGenTextures(2, glObj);
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
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);
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);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Bind target textures to the EFB framebuffer.
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_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
GL_REPORT_FBO_ERROR();
}
else
{
// EFB targets will be renderbuffers in MSAA mode (required by OpenGL).
// Resolve targets will be created to transfer EFB to RAM textures.
// XFB framebuffer will be created to transfer EFB to XFB texture.
// Create EFB target renderbuffers.
GLuint glObj[2];
glGenRenderbuffersEXT(2, glObj);
m_efbColor = glObj[0];
m_efbDepth = glObj[1];
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
if (m_msaaCoverageSamples)
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
else
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
if (m_msaaCoverageSamples)
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
else
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
// Bind target renderbuffers to EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
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);
GL_REPORT_FBO_ERROR();
// Create resolved targets for transferring multisampled EFB to texture.
glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
glGenTextures(2, glObj);
m_resolvedColorTexture = glObj[0];
m_resolvedDepthTexture = glObj[1];
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);
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);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
// Bind resolved textures to resolved framebuffer.
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_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
GL_REPORT_FBO_ERROR();
// Return to EFB framebuffer.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
}
// Create XFB framebuffer; targets will be created elsewhere.
glGenFramebuffersEXT(1, &m_xfbFramebuffer);
// EFB framebuffer is currently bound.
}
void FramebufferManager::Shutdown()
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
GLuint glObj[3];
// Note: OpenGL deletion functions silently ignore parameters of "0".
glObj[0] = m_efbFramebuffer;
glObj[1] = m_resolvedFramebuffer;
glObj[2] = m_xfbFramebuffer;
glDeleteFramebuffersEXT(3, glObj);
m_efbFramebuffer = 0;
m_xfbFramebuffer = 0;
glObj[0] = m_resolvedColorTexture;
glObj[1] = m_resolvedDepthTexture;
glObj[2] = m_realXFBSource.texture;
glDeleteTextures(3, glObj);
m_resolvedColorTexture = 0;
m_resolvedDepthTexture = 0;
m_realXFBSource.texture = 0;
glObj[0] = m_efbColor;
glObj[1] = m_efbDepth;
if (m_msaaSamples <= 1)
glDeleteTextures(2, glObj);
else
glDeleteRenderbuffersEXT(2, glObj);
m_efbColor = 0;
m_efbDepth = 0;
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
{
glDeleteTextures(1, &it->xfbSource.texture);
}
m_virtualXFBList.clear();
}
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{
if (g_Config.bUseXFB)
copyToRealXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
else
copyToVirtualXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
}
const XFBSource* FramebufferManager::GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{
if (g_Config.bUseXFB)
return getRealXFBSource(xfbAddr, srcWidth, srcHeight);
else
return getVirtualXFBSource(xfbAddr, srcWidth, srcHeight);
}
GLuint FramebufferManager::GetEFBColorTexture(const TRectangle& sourceRc) const
{
if (m_msaaSamples <= 1)
{
return m_efbColor;
}
else
{
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
// required.
// Flip source rectangle upside-down for OpenGL.
TRectangle glRect;
sourceRc.FlipYPosition(m_targetHeight, &glRect);
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glBlitFramebufferEXT(
glRect.left, glRect.top, glRect.right, glRect.bottom,
glRect.left, glRect.top, glRect.right, glRect.bottom,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
return m_resolvedColorTexture;
}
}
GLuint FramebufferManager::GetEFBDepthTexture(const TRectangle& sourceRc) const
{
if (m_msaaSamples <= 1)
{
return m_efbDepth;
}
else
{
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
// required.
// Flip source rectangle upside-down for OpenGL.
TRectangle glRect;
sourceRc.FlipYPosition(m_targetHeight, &glRect);
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
// Resolve.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
glBlitFramebufferEXT(
glRect.left, glRect.top, glRect.right, glRect.bottom,
glRect.left, glRect.top, glRect.right, glRect.bottom,
GL_DEPTH_BUFFER_BIT, GL_NEAREST
);
// Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
return m_resolvedDepthTexture;
}
}
FramebufferManager::VirtualXFBListType::iterator
FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
{
u32 srcLower = xfbAddr;
u32 srcUpper = xfbAddr + 2 * width * height;
VirtualXFBListType::iterator it;
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
{
u32 dstLower = it->xfbAddr;
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
return it;
}
// That address is not in the Virtual XFB list.
return m_virtualXFBList.end();
}
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{
u8* pXFB = Memory_GetPtr(xfbAddr);
if (!pXFB)
{
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
return;
}
XFB_Write(pXFB, sourceRc, dstWidth, dstHeight);
}
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
{
GLuint xfbTexture;
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, dstWidth, dstHeight);
if (it != m_virtualXFBList.end())
{
// Overwrite an existing Virtual XFB.
it->xfbAddr = xfbAddr;
it->xfbWidth = dstWidth;
it->xfbHeight = dstHeight;
it->xfbSource.texWidth = m_targetWidth;
it->xfbSource.texHeight = m_targetHeight;
it->xfbSource.sourceRc = sourceRc;
xfbTexture = it->xfbSource.texture;
// Move this Virtual XFB to the front of the list.
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
}
else
{
// Create a new Virtual XFB and place it at the front of the list.
glGenTextures(1, &xfbTexture);
#if 0 // XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
if (m_msaaSamples > 1)
#else
if (s_bHaveFramebufferBlit)
#endif
{
// In MSAA mode, allocate the texture image here. In non-MSAA mode,
// the image will be allocated by glCopyTexImage2D (later).
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, m_targetWidth, m_targetHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
}
VirtualXFB newVirt;
newVirt.xfbAddr = xfbAddr;
newVirt.xfbWidth = dstWidth;
newVirt.xfbHeight = dstHeight;
newVirt.xfbSource.texture = xfbTexture;
newVirt.xfbSource.texWidth = m_targetWidth;
newVirt.xfbSource.texHeight = m_targetHeight;
newVirt.xfbSource.sourceRc = sourceRc;
// Add the new Virtual XFB to the list
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
{
// List overflowed; delete the oldest.
glDeleteTextures(1, &m_virtualXFBList.back().xfbSource.texture);
m_virtualXFBList.pop_back();
}
m_virtualXFBList.push_front(newVirt);
}
// Copy EFB to XFB texture
#if 0
if (m_msaaSamples <= 1)
#else
if (!s_bHaveFramebufferBlit)
#endif
{
// Just copy the EFB directly.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, m_targetWidth, m_targetHeight, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
}
else
{
// OpenGL cannot copy directly from a multisampled framebuffer, so use
// EXT_framebuffer_blit.
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_xfbFramebuffer);
// Bind texture.
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbTexture, 0);
GL_REPORT_FBO_ERROR();
glBlitFramebufferEXT(
0, 0, m_targetWidth, m_targetHeight,
0, 0, m_targetWidth, m_targetHeight,
GL_COLOR_BUFFER_BIT, GL_NEAREST
);
// Unbind texture.
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
// Return to EFB.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
}
}
const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{
m_realXFBSource.texWidth = XFB_WIDTH;
m_realXFBSource.texHeight = XFB_HEIGHT;
m_realXFBSource.sourceRc.left = 0;
m_realXFBSource.sourceRc.top = 0;
m_realXFBSource.sourceRc.right = srcWidth;
m_realXFBSource.sourceRc.bottom = srcHeight;
if (!m_realXFBSource.texture)
{
glGenTextures(1, &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);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
}
// Decode YUYV data from GameCube RAM
TextureConverter::DecodeToTexture(xfbAddr, srcWidth, srcHeight, m_realXFBSource.texture);
return &m_realXFBSource;
}
const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
{
if (m_virtualXFBList.size() == 0)
{
// No Virtual XFBs available.
return NULL;
}
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, srcWidth, srcHeight);
if (it == m_virtualXFBList.end())
{
// Virtual XFB is not in the list, so return the most recently rendered
// one.
it = m_virtualXFBList.begin();
}
return &it->xfbSource;
}
@@ -1,152 +1,152 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _FRAMEBUFFERMANAGER_H_
#define _FRAMEBUFFERMANAGER_H_
#include <list>
#include "GLUtil.h"
// 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
// 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
// interface is given a pointer to the XFB, which will be decoded and
// displayed on the TV.
//
// There are two ways for Dolphin to emulate this:
//
// Real XFB mode:
//
// Dolphin will behave like the GameCube and encode the EFB to
// a portion of GameCube RAM. The emulated video interface will decode the data
// for output to the screen.
//
// Advantages: Behaves exactly like the GameCube.
// Disadvantages: Resolution will be limited.
//
// Virtual XFB mode:
//
// 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.
// The video interface will look up the XFB in the list and use the enhanced
// data stored there, if available.
//
// Advantages: Enables high resolution graphics, better than real hardware.
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
// 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
// virtualize.
const int MAX_VIRTUAL_XFB = 4;
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return (
(aLower >= bLower && aLower < bUpper) ||
(aUpper >= bLower && aUpper < bUpper) ||
(bLower >= aLower && bLower < aUpper) ||
(bUpper >= aLower && bUpper < aUpper)
);
}
struct XFBSource
{
XFBSource() :
texture(0)
{}
GLuint texture;
int texWidth;
int texHeight;
TRectangle sourceRc;
};
class FramebufferManager
{
public:
FramebufferManager() :
m_efbFramebuffer(0),
m_efbColor(0),
m_efbDepth(0),
m_resolvedFramebuffer(0),
m_resolvedColorTexture(0),
m_resolvedDepthTexture(0),
m_xfbFramebuffer(0)
{}
void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
void Shutdown();
// sourceRc is in GL target coordinates, not GameCube EFB coordinates!
// TODO: Clean that up.
void CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
const XFBSource* GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
// To get the EFB in texture form, these functions may have to transfer
// the EFB to a resolved texture first.
GLuint GetEFBColorTexture(const TRectangle& sourceRc) const;
GLuint GetEFBDepthTexture(const TRectangle& sourceRc) const;
GLuint GetEFBFramebuffer() const { return m_efbFramebuffer; }
private:
struct VirtualXFB
{
// Address and size in GameCube RAM
u32 xfbAddr;
u32 xfbWidth;
u32 xfbHeight;
XFBSource xfbSource;
};
typedef std::list<VirtualXFB> VirtualXFBListType;
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
void copyToRealXFB(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* getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
int m_targetWidth;
int m_targetHeight;
int m_msaaSamples;
int m_msaaCoverageSamples;
GLuint m_efbFramebuffer;
GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
// Only used in MSAA mode.
GLuint m_resolvedFramebuffer;
GLuint m_resolvedColorTexture;
GLuint m_resolvedDepthTexture;
GLuint m_xfbFramebuffer; // Only used in MSAA mode
XFBSource m_realXFBSource; // Only used in Real XFB mode
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
};
#endif
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _FRAMEBUFFERMANAGER_H_
#define _FRAMEBUFFERMANAGER_H_
#include <list>
#include "GLUtil.h"
// 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
// 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
// interface is given a pointer to the XFB, which will be decoded and
// displayed on the TV.
//
// There are two ways for Dolphin to emulate this:
//
// Real XFB mode:
//
// Dolphin will behave like the GameCube and encode the EFB to
// a portion of GameCube RAM. The emulated video interface will decode the data
// for output to the screen.
//
// Advantages: Behaves exactly like the GameCube.
// Disadvantages: Resolution will be limited.
//
// Virtual XFB mode:
//
// 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.
// The video interface will look up the XFB in the list and use the enhanced
// data stored there, if available.
//
// Advantages: Enables high resolution graphics, better than real hardware.
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
// 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
// virtualize.
const int MAX_VIRTUAL_XFB = 4;
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return (
(aLower >= bLower && aLower < bUpper) ||
(aUpper >= bLower && aUpper < bUpper) ||
(bLower >= aLower && bLower < aUpper) ||
(bUpper >= aLower && bUpper < aUpper)
);
}
struct XFBSource
{
XFBSource() :
texture(0)
{}
GLuint texture;
int texWidth;
int texHeight;
TRectangle sourceRc;
};
class FramebufferManager
{
public:
FramebufferManager() :
m_efbFramebuffer(0),
m_efbColor(0),
m_efbDepth(0),
m_resolvedFramebuffer(0),
m_resolvedColorTexture(0),
m_resolvedDepthTexture(0),
m_xfbFramebuffer(0)
{}
void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
void Shutdown();
// sourceRc is in GL target coordinates, not GameCube EFB coordinates!
// TODO: Clean that up.
void CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
const XFBSource* GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
// To get the EFB in texture form, these functions may have to transfer
// the EFB to a resolved texture first.
GLuint GetEFBColorTexture(const TRectangle& sourceRc) const;
GLuint GetEFBDepthTexture(const TRectangle& sourceRc) const;
GLuint GetEFBFramebuffer() const { return m_efbFramebuffer; }
private:
struct VirtualXFB
{
// Address and size in GameCube RAM
u32 xfbAddr;
u32 xfbWidth;
u32 xfbHeight;
XFBSource xfbSource;
};
typedef std::list<VirtualXFB> VirtualXFBListType;
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
void copyToRealXFB(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* getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
int m_targetWidth;
int m_targetHeight;
int m_msaaSamples;
int m_msaaCoverageSamples;
GLuint m_efbFramebuffer;
GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
// Only used in MSAA mode.
GLuint m_resolvedFramebuffer;
GLuint m_resolvedColorTexture;
GLuint m_resolvedDepthTexture;
GLuint m_xfbFramebuffer; // Only used in MSAA mode
XFBSource m_realXFBSource; // Only used in Real XFB mode
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
};
#endif
@@ -1,89 +1,89 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "VideoCommon.h"
#include "FileUtil.h"
#include "Config.h"
#include "GLUtil.h"
#include "PostProcessing.h"
#include "PixelShaderCache.h"
namespace PostProcessing
{
static std::string s_currentShader;
static FRAGMENTSHADER s_shader;
void Init()
{
s_currentShader = "";
}
void Shutdown()
{
s_shader.Destroy();
}
void ReloadShader()
{
s_currentShader = "";
}
bool ApplyShader()
{
if (s_currentShader != "User/Shaders/" + g_Config.sPostProcessingShader + ".txt")
{
// Set immediately to prevent endless recompiles on failure.
if (!g_Config.sPostProcessingShader.empty())
s_currentShader = "User/Shaders/" + g_Config.sPostProcessingShader + ".txt";
else
s_currentShader.clear();
s_shader.Destroy();
if (!s_currentShader.empty())
{
std::string code;
if (File::ReadFileToString(true, s_currentShader.c_str(), code))
{
if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
{
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
}
}
else
{
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
}
}
}
if (s_shader.glprogid != 0)
{
glEnable(GL_FRAGMENT_PROGRAM_ARB);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_shader.glprogid);
return true;
}
else
{
glDisable(GL_FRAGMENT_PROGRAM_ARB);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
return false;
}
}
} // namespace
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "VideoCommon.h"
#include "FileUtil.h"
#include "Config.h"
#include "GLUtil.h"
#include "PostProcessing.h"
#include "PixelShaderCache.h"
namespace PostProcessing
{
static std::string s_currentShader;
static FRAGMENTSHADER s_shader;
void Init()
{
s_currentShader = "";
}
void Shutdown()
{
s_shader.Destroy();
}
void ReloadShader()
{
s_currentShader = "";
}
bool ApplyShader()
{
if (s_currentShader != "User/Shaders/" + g_Config.sPostProcessingShader + ".txt")
{
// Set immediately to prevent endless recompiles on failure.
if (!g_Config.sPostProcessingShader.empty())
s_currentShader = "User/Shaders/" + g_Config.sPostProcessingShader + ".txt";
else
s_currentShader.clear();
s_shader.Destroy();
if (!s_currentShader.empty())
{
std::string code;
if (File::ReadFileToString(true, s_currentShader.c_str(), code))
{
if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
{
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
}
}
else
{
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
}
}
}
if (s_shader.glprogid != 0)
{
glEnable(GL_FRAGMENT_PROGRAM_ARB);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_shader.glprogid);
return true;
}
else
{
glDisable(GL_FRAGMENT_PROGRAM_ARB);
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
return false;
}
}
} // namespace
@@ -1,36 +1,36 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _POSTPROCESSING_H_
#define _POSTPROCESSING_H_
#include "VideoCommon.h"
#include "GLUtil.h"
namespace PostProcessing
{
void Init();
void Shutdown();
void ReloadShader();
// Returns false if no shader was applied.
bool ApplyShader();
} // namespace
#endif // _POSTPROCESSING_H_
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _POSTPROCESSING_H_
#define _POSTPROCESSING_H_
#include "VideoCommon.h"
#include "GLUtil.h"
namespace PostProcessing
{
void Init();
void Shutdown();
void ReloadShader();
// Returns false if no shader was applied.
bool ApplyShader();
} // namespace
#endif // _POSTPROCESSING_H_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+108 -108
View File
@@ -1,108 +1,108 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
#include <stdarg.h>
#include <ctype.h>
#include <math.h>
#include <wiiuse/wpad.h>
// Pull in the assembly functions.
extern "C" {
void TestFRES1(u32 *fpscr, float *result, float *result2);
};
int doreload=0, dooff=0;
void reload() { doreload=1; }
void shutdown() { dooff=1; }
void Compare(const char *a, const char *b) {
if (!strcmp(a, b)) {
printf("SUCCESS - %s\n", a);
} else {
printf("FAIL - %s != \n"
" %s\n", a, b);
}
}
void TestDivision() {
double a, b, c, d, e;
a = 1.0;
b = 0.0;
c = a / b;
d = b / a;
e = sqrt(-1);
char temp[100];
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");
}
void TestFres() {
u32 fpscr[2];
float out, out2;
TestFRES1(fpscr, &out, &out2);
char temp[100];
sprintf(temp, "%08x %1.1f %1.1f", fpscr[1], out, out2);
Compare(temp, "86002004 inf 0.0");
}
void TestNormalize() {
//float a[3] = {2,2,2};
//d_guVecNormalize(a);
//printf("%f %f %f\n", a[0], a[1], a[2]);
}
int main(int argc, char **argv) {
void *xfb[2];
int fbi = 0;
GXRModeObj *rmode = NULL;
VIDEO_Init();
PAD_Init();
WPAD_Init();
rmode = VIDEO_GetPreferredMode(NULL);
// 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[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb[0]);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
SYS_SetResetCallback(reload);
SYS_SetPowerCallback(shutdown);
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
printf(" ");
printf("Tests\n\n");
TestDivision();
TestFres();
while (!doreload && !dooff) {
WPAD_ScanPads();
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
exit(0);
VIDEO_SetNextFramebuffer(xfb[fbi]);
VIDEO_Flush();
VIDEO_WaitVSync();
}
if(doreload) return 0;
if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ogcsys.h>
#include <gccore.h>
#include <stdarg.h>
#include <ctype.h>
#include <math.h>
#include <wiiuse/wpad.h>
// Pull in the assembly functions.
extern "C" {
void TestFRES1(u32 *fpscr, float *result, float *result2);
};
int doreload=0, dooff=0;
void reload() { doreload=1; }
void shutdown() { dooff=1; }
void Compare(const char *a, const char *b) {
if (!strcmp(a, b)) {
printf("SUCCESS - %s\n", a);
} else {
printf("FAIL - %s != \n"
" %s\n", a, b);
}
}
void TestDivision() {
double a, b, c, d, e;
a = 1.0;
b = 0.0;
c = a / b;
d = b / a;
e = sqrt(-1);
char temp[100];
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");
}
void TestFres() {
u32 fpscr[2];
float out, out2;
TestFRES1(fpscr, &out, &out2);
char temp[100];
sprintf(temp, "%08x %1.1f %1.1f", fpscr[1], out, out2);
Compare(temp, "86002004 inf 0.0");
}
void TestNormalize() {
//float a[3] = {2,2,2};
//d_guVecNormalize(a);
//printf("%f %f %f\n", a[0], a[1], a[2]);
}
int main(int argc, char **argv) {
void *xfb[2];
int fbi = 0;
GXRModeObj *rmode = NULL;
VIDEO_Init();
PAD_Init();
WPAD_Init();
rmode = VIDEO_GetPreferredMode(NULL);
// 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[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
VIDEO_Configure(rmode);
VIDEO_SetNextFramebuffer(xfb[0]);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
SYS_SetResetCallback(reload);
SYS_SetPowerCallback(shutdown);
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
printf(" ");
printf("Tests\n\n");
TestDivision();
TestFres();
while (!doreload && !dooff) {
WPAD_ScanPads();
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
exit(0);
VIDEO_SetNextFramebuffer(xfb[fbi]);
VIDEO_Flush();
VIDEO_WaitVSync();
}
if(doreload) return 0;
if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0);
return 0;
}
+33 -33
View File
@@ -61,37 +61,37 @@ int main()
}
}
void Initialise()
{
// Initialise the video system
VIDEO_Init();
// This function initialises the attached controllers
PAD_Init();
// Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
void Initialise()
{
// Initialise the video system
VIDEO_Init();
// This function initialises the attached controllers
PAD_Init();
// Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
+71 -71
View File
@@ -1,72 +1,72 @@
#include <gccore.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <ogcsys.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <debug.h>
#include <math.h>
static void *xfb = NULL;
u32 first_frame = 1;
GXRModeObj *rmode;
void Initialise();
int main()
{
Initialise();
time_t gc_time;
gc_time = time(NULL);
srand(gc_time);
while(1)
{
gc_time = time(NULL);
std::cout<<"\x1b[10;0HGC RTC time is"<<ctime(&gc_time);
VIDEO_WaitVSync();
}
}
void Initialise()
{
// Initialise the video system
VIDEO_Init();
// This function initialises the attached controllers
PAD_Init();
// Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
#include <gccore.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <ogcsys.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <debug.h>
#include <math.h>
static void *xfb = NULL;
u32 first_frame = 1;
GXRModeObj *rmode;
void Initialise();
int main()
{
Initialise();
time_t gc_time;
gc_time = time(NULL);
srand(gc_time);
while(1)
{
gc_time = time(NULL);
std::cout<<"\x1b[10;0HGC RTC time is"<<ctime(&gc_time);
VIDEO_WaitVSync();
}
}
void Initialise()
{
// Initialise the video system
VIDEO_Init();
// This function initialises the attached controllers
PAD_Init();
// Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
@@ -1,72 +1,72 @@
#include <gccore.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <ogcsys.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <debug.h>
#include <math.h>
static void *xfb = NULL;
u32 first_frame = 1;
GXRModeObj *rmode;
void Initialise();
int main()
{
Initialise();
time_t wii_time;
wii_time = time(NULL);
srand(wii_time);
while(1)
{
wii_time = time(NULL);
std::cout<<"\x1b[10;0HWii RTC time is"<<ctime(&wii_time);
VIDEO_WaitVSync();
}
}
void Initialise()
{
// Initialise the video system
VIDEO_Init();
// This function initialises the attached controllers
PAD_Init();
// Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
#include <gccore.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <ogcsys.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
#include <debug.h>
#include <math.h>
static void *xfb = NULL;
u32 first_frame = 1;
GXRModeObj *rmode;
void Initialise();
int main()
{
Initialise();
time_t wii_time;
wii_time = time(NULL);
srand(wii_time);
while(1)
{
wii_time = time(NULL);
std::cout<<"\x1b[10;0HWii RTC time is"<<ctime(&wii_time);
VIDEO_WaitVSync();
}
}
void Initialise()
{
// Initialise the video system
VIDEO_Init();
// This function initialises the attached controllers
PAD_Init();
// Obtain the preferred video mode from the system
// This will correspond to the settings in the Wii menu
rmode = VIDEO_GetPreferredMode(NULL);
// Allocate memory for the display in the uncached region
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
// Initialise the console, required for printf
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
// Set up the video registers with the chosen mode
VIDEO_Configure(rmode);
// Tell the video hardware where our display memory is
VIDEO_SetNextFramebuffer(xfb);
// Make the display visible
VIDEO_SetBlack(FALSE);
// Flush the video register changes to the hardware
VIDEO_Flush();
// Wait for Video setup to complete
VIDEO_WaitVSync();
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
}
+142 -142
View File
@@ -1,142 +1,142 @@
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <cmath>
#include <iostream>
#include "StringUtil.h"
#include "MathUtil.h"
#include "PowerPC/PowerPC.h"
#include "HW/SI_DeviceGCController.h"
using namespace std;
int fail_count = 0;
#define EXPECT_TRUE(a) \
if (!a) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is false" << endl; \
cout << "Value: " << a << endl << "Expected: true" << endl; \
fail_count++; \
}
#define EXPECT_FALSE(a) \
if (a) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is true" << endl; \
cout << "Value: " << a << endl << "Expected: false" << endl; \
fail_count++; \
}
#define EXPECT_EQ(a, b) \
if ((a) != (b)) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is not equal to " << #b << endl; \
cout << "Actual: " << a << endl << "Expected: " << b << endl; \
fail_count++; \
}
void CoreTests()
{
}
void MathTests()
{
// 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_NN);
EXPECT_EQ(MathUtil::ClassifyDouble(1235223.0), MathUtil::PPC_FPCLASS_PN);
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_ND);
EXPECT_EQ(MathUtil::ClassifyDouble(0.0), MathUtil::PPC_FPCLASS_PZ);
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_NINF);
EXPECT_EQ(MathUtil::ClassifyDouble(sqrt(-1.0)), MathUtil::PPC_FPCLASS_QNAN);
// Float version
EXPECT_EQ(MathUtil::ClassifyFloat(1.0f), MathUtil::PPC_FPCLASS_PN);
EXPECT_EQ(MathUtil::ClassifyFloat(-1.0f), MathUtil::PPC_FPCLASS_NN);
EXPECT_EQ(MathUtil::ClassifyFloat(1235223.0f), MathUtil::PPC_FPCLASS_PN);
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_ND);
EXPECT_EQ(MathUtil::ClassifyFloat(0.0f), MathUtil::PPC_FPCLASS_PZ);
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_NINF);
EXPECT_EQ(MathUtil::ClassifyFloat(sqrtf(-1.0f)), MathUtil::PPC_FPCLASS_QNAN);
EXPECT_FALSE(MathUtil::IsNAN(1.0));
EXPECT_TRUE(MathUtil::IsNAN(sqrt(-1.0)));
EXPECT_FALSE(MathUtil::IsSNAN(sqrt(-1.0)));
// EXPECT_TRUE(MathUtil::IsQNAN(sqrt(-1.0))); // Hmm...
EXPECT_EQ(pow2(2.0), 4.0);
EXPECT_EQ(pow2(-2.0), 4.0);
}
void StringTests()
{
EXPECT_EQ(StripSpaces(" abc "), "abc");
EXPECT_EQ(StripNewline(" abc \n"), " abc ");
EXPECT_EQ(StripNewline(" abc \n "), " abc \n ");
EXPECT_EQ(StripQuotes("\"abc\""), "abc");
EXPECT_EQ(StripQuotes("\"abc\" "), "\"abc\" ");
EXPECT_EQ(TabsToSpaces(4, "a\tb"), "a b");
}
int main(int argc, _TCHAR* argv[])
{
CoreTests();
MathTests();
StringTests();
if (fail_count == 0)
{
printf("All tests passed.\n");
}
return 0;
}
// Pretend that we are a host so we can link to core.... urgh.
//==============================================================
void Host_UpdateMainFrame(){}
void Host_UpdateDisasmDialog(){}
void Host_UpdateLogDisplay(){}
void Host_UpdateMemoryView(){}
void Host_NotifyMapLoaded(){}
void Host_UpdateBreakPointView(){}
void Host_SetDebugMode(bool enable){}
void Host_SetWaitCursor(bool enable){}
void Host_UpdateStatusBar(const char* _pText, int Filed = 0){}
#ifdef SETUP_TIMER_WAITING
void Host_UpdateGUI(){}
#endif
void Host_SysMessage(const char *fmt, ...){}
void Host_SetWiiMoteConnectionState(int _State){}
void Host_UpdateLeds(int bits){}
void Host_UpdateSpeakerStatus(int index, int bits){}
void Host_UpdateStatus(){}
int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
{
return 0;
}
// Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include <cmath>
#include <iostream>
#include "StringUtil.h"
#include "MathUtil.h"
#include "PowerPC/PowerPC.h"
#include "HW/SI_DeviceGCController.h"
using namespace std;
int fail_count = 0;
#define EXPECT_TRUE(a) \
if (!a) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is false" << endl; \
cout << "Value: " << a << endl << "Expected: true" << endl; \
fail_count++; \
}
#define EXPECT_FALSE(a) \
if (a) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is true" << endl; \
cout << "Value: " << a << endl << "Expected: false" << endl; \
fail_count++; \
}
#define EXPECT_EQ(a, b) \
if ((a) != (b)) { \
cout << "FAIL (" __FUNCTION__ "): " << #a << " is not equal to " << #b << endl; \
cout << "Actual: " << a << endl << "Expected: " << b << endl; \
fail_count++; \
}
void CoreTests()
{
}
void MathTests()
{
// 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_NN);
EXPECT_EQ(MathUtil::ClassifyDouble(1235223.0), MathUtil::PPC_FPCLASS_PN);
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_ND);
EXPECT_EQ(MathUtil::ClassifyDouble(0.0), MathUtil::PPC_FPCLASS_PZ);
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_NINF);
EXPECT_EQ(MathUtil::ClassifyDouble(sqrt(-1.0)), MathUtil::PPC_FPCLASS_QNAN);
// Float version
EXPECT_EQ(MathUtil::ClassifyFloat(1.0f), MathUtil::PPC_FPCLASS_PN);
EXPECT_EQ(MathUtil::ClassifyFloat(-1.0f), MathUtil::PPC_FPCLASS_NN);
EXPECT_EQ(MathUtil::ClassifyFloat(1235223.0f), MathUtil::PPC_FPCLASS_PN);
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_ND);
EXPECT_EQ(MathUtil::ClassifyFloat(0.0f), MathUtil::PPC_FPCLASS_PZ);
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_NINF);
EXPECT_EQ(MathUtil::ClassifyFloat(sqrtf(-1.0f)), MathUtil::PPC_FPCLASS_QNAN);
EXPECT_FALSE(MathUtil::IsNAN(1.0));
EXPECT_TRUE(MathUtil::IsNAN(sqrt(-1.0)));
EXPECT_FALSE(MathUtil::IsSNAN(sqrt(-1.0)));
// EXPECT_TRUE(MathUtil::IsQNAN(sqrt(-1.0))); // Hmm...
EXPECT_EQ(pow2(2.0), 4.0);
EXPECT_EQ(pow2(-2.0), 4.0);
}
void StringTests()
{
EXPECT_EQ(StripSpaces(" abc "), "abc");
EXPECT_EQ(StripNewline(" abc \n"), " abc ");
EXPECT_EQ(StripNewline(" abc \n "), " abc \n ");
EXPECT_EQ(StripQuotes("\"abc\""), "abc");
EXPECT_EQ(StripQuotes("\"abc\" "), "\"abc\" ");
EXPECT_EQ(TabsToSpaces(4, "a\tb"), "a b");
}
int main(int argc, _TCHAR* argv[])
{
CoreTests();
MathTests();
StringTests();
if (fail_count == 0)
{
printf("All tests passed.\n");
}
return 0;
}
// Pretend that we are a host so we can link to core.... urgh.
//==============================================================
void Host_UpdateMainFrame(){}
void Host_UpdateDisasmDialog(){}
void Host_UpdateLogDisplay(){}
void Host_UpdateMemoryView(){}
void Host_NotifyMapLoaded(){}
void Host_UpdateBreakPointView(){}
void Host_SetDebugMode(bool enable){}
void Host_SetWaitCursor(bool enable){}
void Host_UpdateStatusBar(const char* _pText, int Filed = 0){}
#ifdef SETUP_TIMER_WAITING
void Host_UpdateGUI(){}
#endif
void Host_SysMessage(const char *fmt, ...){}
void Host_SetWiiMoteConnectionState(int _State){}
void Host_UpdateLeds(int bits){}
void Host_UpdateSpeakerStatus(int index, int bits){}
void Host_UpdateStatus(){}
int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
{
return 0;
}