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:
parent
23f3e327e2
commit
a41c1b2d0a
|
@ -1,88 +1,88 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "AudioCommon.h"
|
#include "AudioCommon.h"
|
||||||
#include "Mixer.h"
|
#include "Mixer.h"
|
||||||
#include "DSoundStream.h"
|
#include "DSoundStream.h"
|
||||||
#include "AOSoundStream.h"
|
#include "AOSoundStream.h"
|
||||||
#include "NullSoundStream.h"
|
#include "NullSoundStream.h"
|
||||||
#include "OpenALStream.h"
|
#include "OpenALStream.h"
|
||||||
|
|
||||||
namespace AudioCommon
|
namespace AudioCommon
|
||||||
{
|
{
|
||||||
SoundStream *InitSoundStream(CMixer *mixer)
|
SoundStream *InitSoundStream(CMixer *mixer)
|
||||||
{
|
{
|
||||||
if (!mixer)
|
if (!mixer)
|
||||||
mixer = new CMixer();
|
mixer = new CMixer();
|
||||||
|
|
||||||
std::string backend = ac_Config.sBackend;
|
std::string backend = ac_Config.sBackend;
|
||||||
if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd);
|
if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd);
|
||||||
if (backend == BACKEND_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
|
if (backend == BACKEND_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
|
||||||
if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
|
if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
|
||||||
if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
|
if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
|
||||||
|
|
||||||
if (soundStream != NULL) {
|
if (soundStream != NULL) {
|
||||||
ac_Config.Update();
|
ac_Config.Update();
|
||||||
if (soundStream->Start()) {
|
if (soundStream->Start()) {
|
||||||
// Start the sound recording
|
// Start the sound recording
|
||||||
/*
|
/*
|
||||||
if (ac_Config.record) {
|
if (ac_Config.record) {
|
||||||
soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
|
soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return soundStream;
|
return soundStream;
|
||||||
}
|
}
|
||||||
PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str());
|
PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
|
PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
|
||||||
|
|
||||||
delete soundStream;
|
delete soundStream;
|
||||||
soundStream = new NullSound(mixer);
|
soundStream = new NullSound(mixer);
|
||||||
soundStream->Start();
|
soundStream->Start();
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShutdownSoundStream()
|
void ShutdownSoundStream()
|
||||||
{
|
{
|
||||||
NOTICE_LOG(DSPHLE, "Shutting down sound stream");
|
NOTICE_LOG(DSPHLE, "Shutting down sound stream");
|
||||||
|
|
||||||
if (soundStream)
|
if (soundStream)
|
||||||
{
|
{
|
||||||
soundStream->Stop();
|
soundStream->Stop();
|
||||||
soundStream->StopLogAudio();
|
soundStream->StopLogAudio();
|
||||||
delete soundStream;
|
delete soundStream;
|
||||||
soundStream = NULL;
|
soundStream = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_LOG(DSPHLE, "Done shutting down sound stream");
|
INFO_LOG(DSPHLE, "Done shutting down sound stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetSoundBackends()
|
std::vector<std::string> GetSoundBackends()
|
||||||
{
|
{
|
||||||
std::vector<std::string> backends;
|
std::vector<std::string> backends;
|
||||||
|
|
||||||
if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
|
if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
|
||||||
if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
|
if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
|
||||||
if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
|
if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
|
||||||
if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
|
if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
|
||||||
|
|
||||||
return backends;
|
return backends;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,40 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _AUDIO_COMMON_H_
|
#ifndef _AUDIO_COMMON_H_
|
||||||
#define _AUDIO_COMMON_H_
|
#define _AUDIO_COMMON_H_
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "AudioCommonConfig.h"
|
#include "AudioCommonConfig.h"
|
||||||
#include "../../../PluginSpecs/pluginspecs_dsp.h"
|
#include "../../../PluginSpecs/pluginspecs_dsp.h"
|
||||||
#include "SoundStream.h"
|
#include "SoundStream.h"
|
||||||
|
|
||||||
|
|
||||||
class CMixer;
|
class CMixer;
|
||||||
|
|
||||||
extern DSPInitialize g_dspInitialize;
|
extern DSPInitialize g_dspInitialize;
|
||||||
extern SoundStream *soundStream;
|
extern SoundStream *soundStream;
|
||||||
extern AudioCommonConfig ac_Config;
|
extern AudioCommonConfig ac_Config;
|
||||||
|
|
||||||
namespace AudioCommon
|
namespace AudioCommon
|
||||||
{
|
{
|
||||||
SoundStream *InitSoundStream(CMixer *mixer = NULL);
|
SoundStream *InitSoundStream(CMixer *mixer = NULL);
|
||||||
void ShutdownSoundStream();
|
void ShutdownSoundStream();
|
||||||
std::vector<std::string> GetSoundBackends();
|
std::vector<std::string> GetSoundBackends();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // _AUDIO_COMMON_H_
|
#endif // _AUDIO_COMMON_H_
|
||||||
|
|
|
@ -1,52 +1,52 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "AudioCommon.h"
|
#include "AudioCommon.h"
|
||||||
AudioCommonConfig ac_Config;
|
AudioCommonConfig ac_Config;
|
||||||
|
|
||||||
// Load from given file
|
// Load from given file
|
||||||
void AudioCommonConfig::Load(IniFile &file) {
|
void AudioCommonConfig::Load(IniFile &file) {
|
||||||
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
|
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
|
||||||
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
|
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
|
||||||
file.Get("Config", "Volume", &m_Volume, 75);
|
file.Get("Config", "Volume", &m_Volume, 75);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
file.Get("Config", "Backend", &sBackend, "DSound");
|
file.Get("Config", "Backend", &sBackend, "DSound");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
std::string temp;
|
std::string temp;
|
||||||
file.Get("Config", "Backend", &temp, "AOSound");
|
file.Get("Config", "Backend", &temp, "AOSound");
|
||||||
strncpy(sBackend, temp.c_str(), 128);
|
strncpy(sBackend, temp.c_str(), 128);
|
||||||
#else
|
#else
|
||||||
file.Get("Config", "Backend", &sBackend, "AOSound");
|
file.Get("Config", "Backend", &sBackend, "AOSound");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the values for the file
|
// Set the values for the file
|
||||||
void AudioCommonConfig::Set(IniFile &file) {
|
void AudioCommonConfig::Set(IniFile &file) {
|
||||||
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
|
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
|
||||||
file.Set("Config", "EnableThrottle", m_EnableThrottle);
|
file.Set("Config", "EnableThrottle", m_EnableThrottle);
|
||||||
file.Set("Config", "Backend", sBackend);
|
file.Set("Config", "Backend", sBackend);
|
||||||
file.Set("Config", "Volume", m_Volume);
|
file.Set("Config", "Volume", m_Volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update according to the values (stream/mixer)
|
// Update according to the values (stream/mixer)
|
||||||
void AudioCommonConfig::Update() {
|
void AudioCommonConfig::Update() {
|
||||||
if (soundStream) {
|
if (soundStream) {
|
||||||
soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
|
soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
|
||||||
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
|
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
|
||||||
soundStream->SetVolume(m_Volume);
|
soundStream->SetVolume(m_Volume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +1,50 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _AUDIO_COMMON_CONFIG_H_
|
#ifndef _AUDIO_COMMON_CONFIG_H_
|
||||||
#define _AUDIO_COMMON_CONFIG_H_
|
#define _AUDIO_COMMON_CONFIG_H_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "IniFile.h"
|
#include "IniFile.h"
|
||||||
|
|
||||||
// Backend Types
|
// Backend Types
|
||||||
#define BACKEND_DIRECTSOUND "DSound"
|
#define BACKEND_DIRECTSOUND "DSound"
|
||||||
#define BACKEND_AOSOUND "AOSound"
|
#define BACKEND_AOSOUND "AOSound"
|
||||||
#define BACKEND_OPENAL "OpenAL"
|
#define BACKEND_OPENAL "OpenAL"
|
||||||
#define BACKEND_NULL "NullSound"
|
#define BACKEND_NULL "NullSound"
|
||||||
struct AudioCommonConfig
|
struct AudioCommonConfig
|
||||||
{
|
{
|
||||||
bool m_EnableDTKMusic;
|
bool m_EnableDTKMusic;
|
||||||
bool m_EnableThrottle;
|
bool m_EnableThrottle;
|
||||||
int m_Volume;
|
int m_Volume;
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
char sBackend[128];
|
char sBackend[128];
|
||||||
#else
|
#else
|
||||||
std::string sBackend;
|
std::string sBackend;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Load from given file
|
// Load from given file
|
||||||
void Load(IniFile &file);
|
void Load(IniFile &file);
|
||||||
|
|
||||||
// Set the values for the file
|
// Set the values for the file
|
||||||
void Set(IniFile &file);
|
void Set(IniFile &file);
|
||||||
|
|
||||||
// Update according to the values (stream/mixer)
|
// Update according to the values (stream/mixer)
|
||||||
void Update();
|
void Update();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //AUDIO_COMMON_CONFIG
|
#endif //AUDIO_COMMON_CONFIG
|
||||||
|
|
|
@ -1,170 +1,170 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "aldlist.h"
|
#include "aldlist.h"
|
||||||
#include "OpenALStream.h"
|
#include "OpenALStream.h"
|
||||||
|
|
||||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||||
|
|
||||||
#define AUDIO_NUMBUFFERS (4)
|
#define AUDIO_NUMBUFFERS (4)
|
||||||
//#define AUDIO_SERVICE_UPDATE_PERIOD (20)
|
//#define AUDIO_SERVICE_UPDATE_PERIOD (20)
|
||||||
|
|
||||||
bool OpenALStream::Start()
|
bool OpenALStream::Start()
|
||||||
{
|
{
|
||||||
ALDeviceList *pDeviceList = NULL;
|
ALDeviceList *pDeviceList = NULL;
|
||||||
ALCcontext *pContext = NULL;
|
ALCcontext *pContext = NULL;
|
||||||
ALCdevice *pDevice = NULL;
|
ALCdevice *pDevice = NULL;
|
||||||
bool bReturn = false;
|
bool bReturn = false;
|
||||||
|
|
||||||
pDeviceList = new ALDeviceList();
|
pDeviceList = new ALDeviceList();
|
||||||
if ((pDeviceList) && (pDeviceList->GetNumDevices()))
|
if ((pDeviceList) && (pDeviceList->GetNumDevices()))
|
||||||
{
|
{
|
||||||
pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
|
pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
|
||||||
if (pDevice)
|
if (pDevice)
|
||||||
{
|
{
|
||||||
pContext = alcCreateContext(pDevice, NULL);
|
pContext = alcCreateContext(pDevice, NULL);
|
||||||
if (pContext)
|
if (pContext)
|
||||||
{
|
{
|
||||||
alcMakeContextCurrent(pContext);
|
alcMakeContextCurrent(pContext);
|
||||||
thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
|
thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
|
||||||
bReturn = true;
|
bReturn = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
alcCloseDevice(pDevice);
|
alcCloseDevice(pDevice);
|
||||||
PanicAlert("OpenAL: can't create context for device %s", pDevice);
|
PanicAlert("OpenAL: can't create context for device %s", pDevice);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PanicAlert("OpenAL: can't open device %s", pDevice);
|
PanicAlert("OpenAL: can't open device %s", pDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
delete pDeviceList;
|
delete pDeviceList;
|
||||||
} else {
|
} else {
|
||||||
PanicAlert("OpenAL: can't find sound devices");
|
PanicAlert("OpenAL: can't find sound devices");
|
||||||
}
|
}
|
||||||
|
|
||||||
return bReturn;
|
return bReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALStream::Stop()
|
void OpenALStream::Stop()
|
||||||
{
|
{
|
||||||
ALCcontext *pContext;
|
ALCcontext *pContext;
|
||||||
ALCdevice *pDevice;
|
ALCdevice *pDevice;
|
||||||
|
|
||||||
soundCriticalSection.Enter();
|
soundCriticalSection.Enter();
|
||||||
threadData = 1;
|
threadData = 1;
|
||||||
// kick the thread if it's waiting
|
// kick the thread if it's waiting
|
||||||
soundSyncEvent.Set();
|
soundSyncEvent.Set();
|
||||||
soundCriticalSection.Leave();
|
soundCriticalSection.Leave();
|
||||||
delete thread;
|
delete thread;
|
||||||
|
|
||||||
pContext = alcGetCurrentContext();
|
pContext = alcGetCurrentContext();
|
||||||
pDevice = alcGetContextsDevice(pContext);
|
pDevice = alcGetContextsDevice(pContext);
|
||||||
|
|
||||||
alcMakeContextCurrent(NULL);
|
alcMakeContextCurrent(NULL);
|
||||||
alcDestroyContext(pContext);
|
alcDestroyContext(pContext);
|
||||||
alcCloseDevice(pDevice);
|
alcCloseDevice(pDevice);
|
||||||
|
|
||||||
soundSyncEvent.Shutdown();
|
soundSyncEvent.Shutdown();
|
||||||
thread = NULL;
|
thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALStream::Update()
|
void OpenALStream::Update()
|
||||||
{
|
{
|
||||||
//if (m_mixer->GetDataSize()) //here need debug
|
//if (m_mixer->GetDataSize()) //here need debug
|
||||||
{
|
{
|
||||||
soundSyncEvent.Set();
|
soundSyncEvent.Set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
THREAD_RETURN OpenALStream::ThreadFunc(void* args)
|
THREAD_RETURN OpenALStream::ThreadFunc(void* args)
|
||||||
{
|
{
|
||||||
(reinterpret_cast<OpenALStream *>(args))->SoundLoop();
|
(reinterpret_cast<OpenALStream *>(args))->SoundLoop();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenALStream::SoundLoop()
|
void OpenALStream::SoundLoop()
|
||||||
{
|
{
|
||||||
ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
|
ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
|
||||||
ALuint uiSource = 0;
|
ALuint uiSource = 0;
|
||||||
ALenum err;
|
ALenum err;
|
||||||
u32 ulFrequency = m_mixer->GetSampleRate();
|
u32 ulFrequency = m_mixer->GetSampleRate();
|
||||||
// Generate some AL Buffers for streaming
|
// Generate some AL Buffers for streaming
|
||||||
alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
|
alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
|
||||||
// Generate a Source to playback the Buffers
|
// Generate a Source to playback the Buffers
|
||||||
alGenSources(1, &uiSource);
|
alGenSources(1, &uiSource);
|
||||||
|
|
||||||
memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
|
memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
|
||||||
//*
|
//*
|
||||||
for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
|
for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
|
||||||
{
|
{
|
||||||
// pay load fake data
|
// pay load fake data
|
||||||
alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
|
alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
|
||||||
alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
|
alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
|
||||||
}
|
}
|
||||||
//*/
|
//*/
|
||||||
alSourcePlay(uiSource);
|
alSourcePlay(uiSource);
|
||||||
err = alGetError();
|
err = alGetError();
|
||||||
|
|
||||||
while (!threadData)
|
while (!threadData)
|
||||||
{
|
{
|
||||||
soundCriticalSection.Enter();
|
soundCriticalSection.Enter();
|
||||||
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
|
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
|
||||||
/*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
|
/*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
|
||||||
soundCriticalSection.Leave();
|
soundCriticalSection.Leave();
|
||||||
|
|
||||||
//if (numBytesRender) //here need debug
|
//if (numBytesRender) //here need debug
|
||||||
{
|
{
|
||||||
ALint iBuffersProcessed = 0;
|
ALint iBuffersProcessed = 0;
|
||||||
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
|
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
|
||||||
|
|
||||||
if (iBuffersProcessed)
|
if (iBuffersProcessed)
|
||||||
{
|
{
|
||||||
// Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
|
// Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
|
||||||
ALuint uiTempBuffer = 0;
|
ALuint uiTempBuffer = 0;
|
||||||
alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
|
alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
|
||||||
/*
|
/*
|
||||||
soundCriticalSection.Enter();
|
soundCriticalSection.Enter();
|
||||||
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
|
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
|
||||||
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
|
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
|
||||||
soundCriticalSection.Leave();
|
soundCriticalSection.Leave();
|
||||||
|
|
||||||
unsigned long ulBytesWritten = 0;
|
unsigned long ulBytesWritten = 0;
|
||||||
*/
|
*/
|
||||||
//if (numBytesRender)
|
//if (numBytesRender)
|
||||||
{
|
{
|
||||||
alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
|
alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
|
||||||
}
|
}
|
||||||
alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
|
alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!threadData)
|
if (!threadData)
|
||||||
soundSyncEvent.Wait();
|
soundSyncEvent.Wait();
|
||||||
}
|
}
|
||||||
alSourceStop(uiSource);
|
alSourceStop(uiSource);
|
||||||
alSourcei(uiSource, AL_BUFFER, 0);
|
alSourcei(uiSource, AL_BUFFER, 0);
|
||||||
|
|
||||||
// Clean up buffers and sources
|
// Clean up buffers and sources
|
||||||
alDeleteSources(1, &uiSource);
|
alDeleteSources(1, &uiSource);
|
||||||
alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
|
alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //HAVE_OPENAL
|
#endif //HAVE_OPENAL
|
||||||
|
|
||||||
|
|
|
@ -1,74 +1,74 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _OPENALSTREAM_H_
|
#ifndef _OPENALSTREAM_H_
|
||||||
#define _OPENALSTREAM_H_
|
#define _OPENALSTREAM_H_
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "SoundStream.h"
|
#include "SoundStream.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
|
|
||||||
|
|
||||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "../../../../Externals/OpenAL/include/al.h"
|
#include "../../../../Externals/OpenAL/include/al.h"
|
||||||
#include "../../../../Externals/OpenAL/include/alc.h"
|
#include "../../../../Externals/OpenAL/include/alc.h"
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
#include "openal/al.h"
|
#include "openal/al.h"
|
||||||
#include "openal/alc.h"
|
#include "openal/alc.h"
|
||||||
#else
|
#else
|
||||||
#include "AL/al.h"
|
#include "AL/al.h"
|
||||||
#include "AL/alc.h"
|
#include "AL/alc.h"
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
// public use
|
// public use
|
||||||
#define SFX_MAX_SOURCE 1
|
#define SFX_MAX_SOURCE 1
|
||||||
#define OAL_BUFFER_SIZE 1024*1024
|
#define OAL_BUFFER_SIZE 1024*1024
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class OpenALStream: public SoundStream
|
class OpenALStream: public SoundStream
|
||||||
{
|
{
|
||||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||||
public:
|
public:
|
||||||
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
|
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
|
||||||
virtual ~OpenALStream() {};
|
virtual ~OpenALStream() {};
|
||||||
|
|
||||||
virtual bool Start();
|
virtual bool Start();
|
||||||
virtual void SoundLoop();
|
virtual void SoundLoop();
|
||||||
virtual void Stop();
|
virtual void Stop();
|
||||||
static bool isValid() { return true; }
|
static bool isValid() { return true; }
|
||||||
virtual bool usesMixer() const { return true; }
|
virtual bool usesMixer() const { return true; }
|
||||||
virtual void Update();
|
virtual void Update();
|
||||||
|
|
||||||
static THREAD_RETURN ThreadFunc(void* args);
|
static THREAD_RETURN ThreadFunc(void* args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Common::Thread *thread;
|
Common::Thread *thread;
|
||||||
Common::CriticalSection soundCriticalSection;
|
Common::CriticalSection soundCriticalSection;
|
||||||
Common::Event soundSyncEvent;
|
Common::Event soundSyncEvent;
|
||||||
|
|
||||||
short realtimeBuffer[OAL_BUFFER_SIZE];
|
short realtimeBuffer[OAL_BUFFER_SIZE];
|
||||||
#else
|
#else
|
||||||
public:
|
public:
|
||||||
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
|
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
|
||||||
#endif // HAVE_OPENAL
|
#endif // HAVE_OPENAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // OPENALSTREAM
|
#endif // OPENALSTREAM
|
||||||
|
|
|
@ -1,341 +1,341 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, Creative Labs Inc.
|
* Copyright (c) 2006, Creative Labs Inc.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||||
* that the following conditions are met:
|
* that the following conditions are met:
|
||||||
*
|
*
|
||||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
* the following disclaimer.
|
* the following disclaimer.
|
||||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||||||
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
|
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
|
||||||
* promote products derived from this software without specific prior written permission.
|
* promote products derived from this software without specific prior written permission.
|
||||||
*
|
*
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "aldlist.h"
|
#include "aldlist.h"
|
||||||
#include "../../../../Externals/OpenAL/include/al.h"
|
#include "../../../../Externals/OpenAL/include/al.h"
|
||||||
#include "../../../../Externals/OpenAL/include/alc.h"
|
#include "../../../../Externals/OpenAL/include/alc.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Init call
|
* Init call
|
||||||
*/
|
*/
|
||||||
ALDeviceList::ALDeviceList()
|
ALDeviceList::ALDeviceList()
|
||||||
{
|
{
|
||||||
ALDEVICEINFO ALDeviceInfo;
|
ALDEVICEINFO ALDeviceInfo;
|
||||||
char *devices;
|
char *devices;
|
||||||
s32 index;
|
s32 index;
|
||||||
const char *defaultDeviceName = NULL;
|
const char *defaultDeviceName = NULL;
|
||||||
const char *actualDeviceName = NULL;
|
const char *actualDeviceName = NULL;
|
||||||
|
|
||||||
// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
|
// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
|
||||||
vDeviceInfo.empty();
|
vDeviceInfo.empty();
|
||||||
vDeviceInfo.reserve(10);
|
vDeviceInfo.reserve(10);
|
||||||
|
|
||||||
defaultDeviceIndex = 0;
|
defaultDeviceIndex = 0;
|
||||||
|
|
||||||
// grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
|
// grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
|
||||||
//if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
|
//if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
|
||||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
|
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
|
||||||
{
|
{
|
||||||
devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||||
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||||
index = 0;
|
index = 0;
|
||||||
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
|
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
|
||||||
while (devices != NULL && strlen(devices) > 0)
|
while (devices != NULL && strlen(devices) > 0)
|
||||||
{
|
{
|
||||||
if (strcmp(defaultDeviceName, devices) == 0)
|
if (strcmp(defaultDeviceName, devices) == 0)
|
||||||
{
|
{
|
||||||
defaultDeviceIndex = index;
|
defaultDeviceIndex = index;
|
||||||
}
|
}
|
||||||
ALCdevice *device = alcOpenDevice(devices);
|
ALCdevice *device = alcOpenDevice(devices);
|
||||||
if (device)
|
if (device)
|
||||||
{
|
{
|
||||||
ALCcontext *context = alcCreateContext(device, NULL);
|
ALCcontext *context = alcCreateContext(device, NULL);
|
||||||
if (context)
|
if (context)
|
||||||
{
|
{
|
||||||
alcMakeContextCurrent(context);
|
alcMakeContextCurrent(context);
|
||||||
// if new actual device name isn't already in the list, then add it...
|
// if new actual device name isn't already in the list, then add it...
|
||||||
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||||
bool bNewName = true;
|
bool bNewName = true;
|
||||||
for (s32 i = 0; i < GetNumDevices(); i++)
|
for (s32 i = 0; i < GetNumDevices(); i++)
|
||||||
{
|
{
|
||||||
if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
|
if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
|
||||||
{
|
{
|
||||||
bNewName = false;
|
bNewName = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
|
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
|
||||||
{
|
{
|
||||||
ALDeviceInfo.bSelected = true;
|
ALDeviceInfo.bSelected = true;
|
||||||
ALDeviceInfo.strDeviceName = actualDeviceName;
|
ALDeviceInfo.strDeviceName = actualDeviceName;
|
||||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
|
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
|
||||||
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
|
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
|
||||||
|
|
||||||
ALDeviceInfo.pvstrExtensions = new vector<string>;
|
ALDeviceInfo.pvstrExtensions = new vector<string>;
|
||||||
|
|
||||||
// Check for ALC Extensions
|
// Check for ALC Extensions
|
||||||
if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
|
if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
|
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
|
||||||
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
|
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
|
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
|
||||||
|
|
||||||
// Check for AL Extensions
|
// Check for AL Extensions
|
||||||
if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
|
if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
|
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
|
||||||
|
|
||||||
if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
|
if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
|
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
|
||||||
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
|
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
|
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
|
||||||
|
|
||||||
if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
|
if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
|
ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
|
||||||
if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
|
if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
|
ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
|
||||||
if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
|
if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
|
ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
|
||||||
if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
|
if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
|
ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
|
||||||
|
|
||||||
if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
|
if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
|
||||||
ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
|
ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
|
||||||
|
|
||||||
// Get Source Count
|
// Get Source Count
|
||||||
ALDeviceInfo.uiSourceCount = GetMaxNumSources();
|
ALDeviceInfo.uiSourceCount = GetMaxNumSources();
|
||||||
|
|
||||||
vDeviceInfo.push_back(ALDeviceInfo);
|
vDeviceInfo.push_back(ALDeviceInfo);
|
||||||
}
|
}
|
||||||
alcMakeContextCurrent(NULL);
|
alcMakeContextCurrent(NULL);
|
||||||
alcDestroyContext(context);
|
alcDestroyContext(context);
|
||||||
}
|
}
|
||||||
alcCloseDevice(device);
|
alcCloseDevice(device);
|
||||||
}
|
}
|
||||||
devices += strlen(devices) + 1;
|
devices += strlen(devices) + 1;
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
|
|
||||||
ResetFilters();
|
ResetFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exit call
|
* Exit call
|
||||||
*/
|
*/
|
||||||
ALDeviceList::~ALDeviceList()
|
ALDeviceList::~ALDeviceList()
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||||
if (vDeviceInfo[i].pvstrExtensions) {
|
if (vDeviceInfo[i].pvstrExtensions) {
|
||||||
vDeviceInfo[i].pvstrExtensions->empty();
|
vDeviceInfo[i].pvstrExtensions->empty();
|
||||||
delete vDeviceInfo[i].pvstrExtensions;
|
delete vDeviceInfo[i].pvstrExtensions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vDeviceInfo.empty();
|
vDeviceInfo.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the number of devices in the complete device list
|
* Returns the number of devices in the complete device list
|
||||||
*/
|
*/
|
||||||
s32 ALDeviceList::GetNumDevices()
|
s32 ALDeviceList::GetNumDevices()
|
||||||
{
|
{
|
||||||
return (s32)vDeviceInfo.size();
|
return (s32)vDeviceInfo.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the device name at an index in the complete device list
|
* Returns the device name at an index in the complete device list
|
||||||
*/
|
*/
|
||||||
char * ALDeviceList::GetDeviceName(s32 index)
|
char * ALDeviceList::GetDeviceName(s32 index)
|
||||||
{
|
{
|
||||||
if (index < GetNumDevices())
|
if (index < GetNumDevices())
|
||||||
return (char *)vDeviceInfo[index].strDeviceName.c_str();
|
return (char *)vDeviceInfo[index].strDeviceName.c_str();
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the major and minor version numbers for a device at a specified index in the complete list
|
* Returns the major and minor version numbers for a device at a specified index in the complete list
|
||||||
*/
|
*/
|
||||||
void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
|
void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
|
||||||
{
|
{
|
||||||
if (index < GetNumDevices()) {
|
if (index < GetNumDevices()) {
|
||||||
if (major)
|
if (major)
|
||||||
*major = vDeviceInfo[index].iMajorVersion;
|
*major = vDeviceInfo[index].iMajorVersion;
|
||||||
if (minor)
|
if (minor)
|
||||||
*minor = vDeviceInfo[index].iMinorVersion;
|
*minor = vDeviceInfo[index].iMinorVersion;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the maximum number of Sources that can be generate on the given device
|
* Returns the maximum number of Sources that can be generate on the given device
|
||||||
*/
|
*/
|
||||||
u32 ALDeviceList::GetMaxNumSources(s32 index)
|
u32 ALDeviceList::GetMaxNumSources(s32 index)
|
||||||
{
|
{
|
||||||
if (index < GetNumDevices())
|
if (index < GetNumDevices())
|
||||||
return vDeviceInfo[index].uiSourceCount;
|
return vDeviceInfo[index].uiSourceCount;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks if the extension is supported on the given device
|
* Checks if the extension is supported on the given device
|
||||||
*/
|
*/
|
||||||
bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
|
bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
|
||||||
{
|
{
|
||||||
bool bReturn = false;
|
bool bReturn = false;
|
||||||
|
|
||||||
if (index < GetNumDevices()) {
|
if (index < GetNumDevices()) {
|
||||||
for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
|
for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
|
||||||
if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
|
if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
|
||||||
bReturn = true;
|
bReturn = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bReturn;
|
return bReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns the index of the default device in the complete device list
|
* returns the index of the default device in the complete device list
|
||||||
*/
|
*/
|
||||||
s32 ALDeviceList::GetDefaultDevice()
|
s32 ALDeviceList::GetDefaultDevice()
|
||||||
{
|
{
|
||||||
return defaultDeviceIndex;
|
return defaultDeviceIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deselects devices which don't have the specified minimum version
|
* Deselects devices which don't have the specified minimum version
|
||||||
*/
|
*/
|
||||||
void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
|
void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
|
||||||
{
|
{
|
||||||
s32 dMajor = 0, dMinor = 0;
|
s32 dMajor = 0, dMinor = 0;
|
||||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||||
GetDeviceVersion(i, &dMajor, &dMinor);
|
GetDeviceVersion(i, &dMajor, &dMinor);
|
||||||
if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
|
if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
|
||||||
vDeviceInfo[i].bSelected = false;
|
vDeviceInfo[i].bSelected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deselects devices which don't have the specified maximum version
|
* Deselects devices which don't have the specified maximum version
|
||||||
*/
|
*/
|
||||||
void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
|
void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
|
||||||
{
|
{
|
||||||
s32 dMajor = 0, dMinor = 0;
|
s32 dMajor = 0, dMinor = 0;
|
||||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||||
GetDeviceVersion(i, &dMajor, &dMinor);
|
GetDeviceVersion(i, &dMajor, &dMinor);
|
||||||
if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
|
if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
|
||||||
vDeviceInfo[i].bSelected = false;
|
vDeviceInfo[i].bSelected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deselects device which don't support the given extension name
|
* Deselects device which don't support the given extension name
|
||||||
*/
|
*/
|
||||||
void ALDeviceList::FilterDevicesExtension(char *szExtName)
|
void ALDeviceList::FilterDevicesExtension(char *szExtName)
|
||||||
{
|
{
|
||||||
bool bFound;
|
bool bFound;
|
||||||
|
|
||||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||||
bFound = false;
|
bFound = false;
|
||||||
for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
|
for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
|
||||||
if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
|
if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
|
||||||
bFound = true;
|
bFound = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!bFound)
|
if (!bFound)
|
||||||
vDeviceInfo[i].bSelected = false;
|
vDeviceInfo[i].bSelected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Resets all filtering, such that all devices are in the list
|
* Resets all filtering, such that all devices are in the list
|
||||||
*/
|
*/
|
||||||
void ALDeviceList::ResetFilters()
|
void ALDeviceList::ResetFilters()
|
||||||
{
|
{
|
||||||
for (s32 i = 0; i < GetNumDevices(); i++) {
|
for (s32 i = 0; i < GetNumDevices(); i++) {
|
||||||
vDeviceInfo[i].bSelected = true;
|
vDeviceInfo[i].bSelected = true;
|
||||||
}
|
}
|
||||||
filterIndex = 0;
|
filterIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets index of first filtered device
|
* Gets index of first filtered device
|
||||||
*/
|
*/
|
||||||
s32 ALDeviceList::GetFirstFilteredDevice()
|
s32 ALDeviceList::GetFirstFilteredDevice()
|
||||||
{
|
{
|
||||||
s32 i;
|
s32 i;
|
||||||
|
|
||||||
for (i = 0; i < GetNumDevices(); i++) {
|
for (i = 0; i < GetNumDevices(); i++) {
|
||||||
if (vDeviceInfo[i].bSelected == true) {
|
if (vDeviceInfo[i].bSelected == true) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filterIndex = i + 1;
|
filterIndex = i + 1;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Gets index of next filtered device
|
* Gets index of next filtered device
|
||||||
*/
|
*/
|
||||||
s32 ALDeviceList::GetNextFilteredDevice()
|
s32 ALDeviceList::GetNextFilteredDevice()
|
||||||
{
|
{
|
||||||
s32 i;
|
s32 i;
|
||||||
|
|
||||||
for (i = filterIndex; i < GetNumDevices(); i++) {
|
for (i = filterIndex; i < GetNumDevices(); i++) {
|
||||||
if (vDeviceInfo[i].bSelected == true) {
|
if (vDeviceInfo[i].bSelected == true) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filterIndex = i + 1;
|
filterIndex = i + 1;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Internal function to detemine max number of Sources that can be generated
|
* Internal function to detemine max number of Sources that can be generated
|
||||||
*/
|
*/
|
||||||
u32 ALDeviceList::GetMaxNumSources()
|
u32 ALDeviceList::GetMaxNumSources()
|
||||||
{
|
{
|
||||||
ALuint uiSources[256];
|
ALuint uiSources[256];
|
||||||
u32 iSourceCount = 0;
|
u32 iSourceCount = 0;
|
||||||
|
|
||||||
// Clear AL Error Code
|
// Clear AL Error Code
|
||||||
alGetError();
|
alGetError();
|
||||||
|
|
||||||
// Generate up to 256 Sources, checking for any errors
|
// Generate up to 256 Sources, checking for any errors
|
||||||
for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
|
for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
|
||||||
{
|
{
|
||||||
alGenSources(1, &uiSources[iSourceCount]);
|
alGenSources(1, &uiSources[iSourceCount]);
|
||||||
if (alGetError() != AL_NO_ERROR)
|
if (alGetError() != AL_NO_ERROR)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the Sources
|
// Release the Sources
|
||||||
alDeleteSources(iSourceCount, uiSources);
|
alDeleteSources(iSourceCount, uiSources);
|
||||||
if (alGetError() != AL_NO_ERROR)
|
if (alGetError() != AL_NO_ERROR)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < 256; i++)
|
for (u32 i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
alDeleteSources(1, &uiSources[i]);
|
alDeleteSources(1, &uiSources[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return iSourceCount;
|
return iSourceCount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +1,51 @@
|
||||||
#ifndef ALDEVICELIST_H
|
#ifndef ALDEVICELIST_H
|
||||||
#define ALDEVICELIST_H
|
#define ALDEVICELIST_H
|
||||||
|
|
||||||
#include "CommonTypes.h"
|
#include "CommonTypes.h"
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#pragma warning(disable: 4786) //disable warning "identifier was truncated to
|
#pragma warning(disable: 4786) //disable warning "identifier was truncated to
|
||||||
//'255' characters in the browser information"
|
//'255' characters in the browser information"
|
||||||
#endif
|
#endif
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
string strDeviceName;
|
string strDeviceName;
|
||||||
s32 iMajorVersion;
|
s32 iMajorVersion;
|
||||||
s32 iMinorVersion;
|
s32 iMinorVersion;
|
||||||
u32 uiSourceCount;
|
u32 uiSourceCount;
|
||||||
vector<string> *pvstrExtensions;
|
vector<string> *pvstrExtensions;
|
||||||
bool bSelected;
|
bool bSelected;
|
||||||
} ALDEVICEINFO, *LPALDEVICEINFO;
|
} ALDEVICEINFO, *LPALDEVICEINFO;
|
||||||
|
|
||||||
class ALDeviceList
|
class ALDeviceList
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
vector<ALDEVICEINFO> vDeviceInfo;
|
vector<ALDEVICEINFO> vDeviceInfo;
|
||||||
s32 defaultDeviceIndex;
|
s32 defaultDeviceIndex;
|
||||||
s32 filterIndex;
|
s32 filterIndex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ALDeviceList ();
|
ALDeviceList ();
|
||||||
~ALDeviceList ();
|
~ALDeviceList ();
|
||||||
s32 GetNumDevices();
|
s32 GetNumDevices();
|
||||||
char *GetDeviceName(s32 index);
|
char *GetDeviceName(s32 index);
|
||||||
void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
|
void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
|
||||||
u32 GetMaxNumSources(s32 index);
|
u32 GetMaxNumSources(s32 index);
|
||||||
bool IsExtensionSupported(s32 index, char *szExtName);
|
bool IsExtensionSupported(s32 index, char *szExtName);
|
||||||
s32 GetDefaultDevice();
|
s32 GetDefaultDevice();
|
||||||
void FilterDevicesMinVer(s32 major, s32 minor);
|
void FilterDevicesMinVer(s32 major, s32 minor);
|
||||||
void FilterDevicesMaxVer(s32 major, s32 minor);
|
void FilterDevicesMaxVer(s32 major, s32 minor);
|
||||||
void FilterDevicesExtension(char *szExtName);
|
void FilterDevicesExtension(char *szExtName);
|
||||||
void ResetFilters();
|
void ResetFilters();
|
||||||
s32 GetFirstFilteredDevice();
|
s32 GetFirstFilteredDevice();
|
||||||
s32 GetNextFilteredDevice();
|
s32 GetNextFilteredDevice();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 GetMaxNumSources();
|
u32 GetMaxNumSources();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ALDEVICELIST_H
|
#endif // ALDEVICELIST_H
|
||||||
|
|
|
@ -1,59 +1,59 @@
|
||||||
// Copyright (C) 2003-2008 Dolphin Project.
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "SymbolDB.h"
|
#include "SymbolDB.h"
|
||||||
|
|
||||||
|
|
||||||
void SymbolDB::List()
|
void SymbolDB::List()
|
||||||
{
|
{
|
||||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
{
|
{
|
||||||
DEBUG_LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
|
DEBUG_LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
|
||||||
}
|
}
|
||||||
INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
|
INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolDB::Clear(const char *prefix)
|
void SymbolDB::Clear(const char *prefix)
|
||||||
{
|
{
|
||||||
// TODO: honor prefix
|
// TODO: honor prefix
|
||||||
functions.clear();
|
functions.clear();
|
||||||
checksumToFunction.clear();
|
checksumToFunction.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolDB::Index()
|
void SymbolDB::Index()
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
{
|
{
|
||||||
iter->second.index = i++;
|
iter->second.index = i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *SymbolDB::GetSymbolFromName(const char *name)
|
Symbol *SymbolDB::GetSymbolFromName(const char *name)
|
||||||
{
|
{
|
||||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
{
|
{
|
||||||
if (!strcmp(iter->second.name.c_str(), name))
|
if (!strcmp(iter->second.name.c_str(), name))
|
||||||
return &iter->second;
|
return &iter->second;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
|
void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
|
||||||
{
|
{
|
||||||
functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
|
functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,122 +1,122 @@
|
||||||
// Copyright (C) 2003-2008 Dolphin Project.
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
// This file contains a generic symbol map implementation. For CPU-specific
|
// This file contains a generic symbol map implementation. For CPU-specific
|
||||||
// magic, derive and extend.
|
// magic, derive and extend.
|
||||||
|
|
||||||
#ifndef _SYMBOL_DB_H
|
#ifndef _SYMBOL_DB_H
|
||||||
#define _SYMBOL_DB_H
|
#define _SYMBOL_DB_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
struct SCall
|
struct SCall
|
||||||
{
|
{
|
||||||
SCall(u32 a, u32 b) :
|
SCall(u32 a, u32 b) :
|
||||||
function(a),
|
function(a),
|
||||||
callAddress(b)
|
callAddress(b)
|
||||||
{}
|
{}
|
||||||
u32 function;
|
u32 function;
|
||||||
u32 callAddress;
|
u32 callAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Symbol
|
struct Symbol
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
SYMBOL_FUNCTION = 0,
|
SYMBOL_FUNCTION = 0,
|
||||||
SYMBOL_DATA = 1,
|
SYMBOL_DATA = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
Symbol() :
|
Symbol() :
|
||||||
hash(0),
|
hash(0),
|
||||||
address(0),
|
address(0),
|
||||||
flags(0),
|
flags(0),
|
||||||
size(0),
|
size(0),
|
||||||
numCalls(0),
|
numCalls(0),
|
||||||
type(SYMBOL_FUNCTION),
|
type(SYMBOL_FUNCTION),
|
||||||
analyzed(0)
|
analyzed(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<SCall> callers; //addresses of functions that call this function
|
std::vector<SCall> callers; //addresses of functions that call this function
|
||||||
std::vector<SCall> calls; //addresses of functions that are called by this function
|
std::vector<SCall> calls; //addresses of functions that are called by this function
|
||||||
u32 hash; //use for HLE function finding
|
u32 hash; //use for HLE function finding
|
||||||
u32 address;
|
u32 address;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
int size;
|
int size;
|
||||||
int numCalls;
|
int numCalls;
|
||||||
int type;
|
int type;
|
||||||
int index; // only used for coloring the disasm view
|
int index; // only used for coloring the disasm view
|
||||||
int analyzed;
|
int analyzed;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
FFLAG_TIMERINSTRUCTIONS=(1<<0),
|
FFLAG_TIMERINSTRUCTIONS=(1<<0),
|
||||||
FFLAG_LEAF=(1<<1),
|
FFLAG_LEAF=(1<<1),
|
||||||
FFLAG_ONLYCALLSNICELEAFS=(1<<2),
|
FFLAG_ONLYCALLSNICELEAFS=(1<<2),
|
||||||
FFLAG_EVIL=(1<<3),
|
FFLAG_EVIL=(1<<3),
|
||||||
FFLAG_RFI=(1<<4),
|
FFLAG_RFI=(1<<4),
|
||||||
FFLAG_STRAIGHT=(1<<5)
|
FFLAG_STRAIGHT=(1<<5)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SymbolDB
|
class SymbolDB
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<u32, Symbol> XFuncMap;
|
typedef std::map<u32, Symbol> XFuncMap;
|
||||||
typedef std::map<u32, Symbol*> XFuncPtrMap;
|
typedef std::map<u32, Symbol*> XFuncPtrMap;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
XFuncMap functions;
|
XFuncMap functions;
|
||||||
XFuncPtrMap checksumToFunction;
|
XFuncPtrMap checksumToFunction;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SymbolDB() {}
|
SymbolDB() {}
|
||||||
virtual ~SymbolDB() {}
|
virtual ~SymbolDB() {}
|
||||||
virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
|
virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
|
||||||
virtual Symbol *AddFunction(u32 startAddr) { return 0;}
|
virtual Symbol *AddFunction(u32 startAddr) { return 0;}
|
||||||
|
|
||||||
void AddCompleteSymbol(const Symbol &symbol);
|
void AddCompleteSymbol(const Symbol &symbol);
|
||||||
|
|
||||||
Symbol *GetSymbolFromName(const char *name);
|
Symbol *GetSymbolFromName(const char *name);
|
||||||
Symbol *GetSymbolFromHash(u32 hash) {
|
Symbol *GetSymbolFromHash(u32 hash) {
|
||||||
XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
|
XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
|
||||||
if (iter != checksumToFunction.end())
|
if (iter != checksumToFunction.end())
|
||||||
return iter->second;
|
return iter->second;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFuncMap &Symbols() const {return functions;}
|
const XFuncMap &Symbols() const {return functions;}
|
||||||
XFuncMap &AccessSymbols() {return functions;}
|
XFuncMap &AccessSymbols() {return functions;}
|
||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
XFuncMap::iterator GetIterator() { return functions.begin(); }
|
XFuncMap::iterator GetIterator() { return functions.begin(); }
|
||||||
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
|
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
|
||||||
XFuncMap::iterator End() { return functions.end(); }
|
XFuncMap::iterator End() { return functions.end(); }
|
||||||
|
|
||||||
void Clear(const char *prefix = "");
|
void Clear(const char *prefix = "");
|
||||||
void List();
|
void List();
|
||||||
void Index();
|
void Index();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||||
//Add support for apple keycodes
|
//Add support for apple keycodes
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||||
//Add support for apple keycodes
|
//Add support for apple keycodes
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||||
//Add support for Linux keycodes
|
//Add support for Linux keycodes
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||||
//Add support for Linux keycodes
|
//Add support for Linux keycodes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,192 +1,192 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||||
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x2A, // Backspace
|
0x2A, // Backspace
|
||||||
0x2B, // Tab
|
0x2B, // Tab
|
||||||
0x00, 0x00,
|
0x00, 0x00,
|
||||||
0x00, // Clear
|
0x00, // Clear
|
||||||
0x28, // Return
|
0x28, // Return
|
||||||
0x00, 0x00,
|
0x00, 0x00,
|
||||||
0x00, // Shift
|
0x00, // Shift
|
||||||
0x00, // Control
|
0x00, // Control
|
||||||
0x00, // ALT
|
0x00, // ALT
|
||||||
0x48, // Pause
|
0x48, // Pause
|
||||||
0x39, // Capital
|
0x39, // Capital
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x29, // Escape
|
0x29, // Escape
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x2C, // Space
|
0x2C, // Space
|
||||||
0x4B, // Prior
|
0x4B, // Prior
|
||||||
0x4E, // Next
|
0x4E, // Next
|
||||||
0x4D, // End
|
0x4D, // End
|
||||||
0x4A, // Home
|
0x4A, // Home
|
||||||
0x50, // Left
|
0x50, // Left
|
||||||
0x52, // Up
|
0x52, // Up
|
||||||
0x4F, // Right
|
0x4F, // Right
|
||||||
0x51, // Down
|
0x51, // Down
|
||||||
0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00,
|
||||||
0x46, // Print screen
|
0x46, // Print screen
|
||||||
0x49, // Insert
|
0x49, // Insert
|
||||||
0x4C, // Delete
|
0x4C, // Delete
|
||||||
0x00,
|
0x00,
|
||||||
// 0 -> 9
|
// 0 -> 9
|
||||||
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||||
0x25, 0x26,
|
0x25, 0x26,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00,
|
0x00,
|
||||||
// A -> Z
|
// A -> Z
|
||||||
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
||||||
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
|
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
|
||||||
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
|
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
|
||||||
0x1C, 0x1D,
|
0x1C, 0x1D,
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x00,
|
0x00,
|
||||||
// Numpad 0 -> 9
|
// Numpad 0 -> 9
|
||||||
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||||
0x60, 0x61,
|
0x60, 0x61,
|
||||||
0x55, // Multiply
|
0x55, // Multiply
|
||||||
0x57, // Add
|
0x57, // Add
|
||||||
0x00, // Separator
|
0x00, // Separator
|
||||||
0x56, // Substract
|
0x56, // Substract
|
||||||
0x63, // Decimal
|
0x63, // Decimal
|
||||||
0x54, // Divide
|
0x54, // Divide
|
||||||
// F1 -> F12
|
// F1 -> F12
|
||||||
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
|
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
|
||||||
0x42, 0x43, 0x44, 0x45,
|
0x42, 0x43, 0x44, 0x45,
|
||||||
// F13 -> F24
|
// F13 -> F24
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x53, // Numlock
|
0x53, // Numlock
|
||||||
0x47, // Scroll lock
|
0x47, // Scroll lock
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
// Modifier keys
|
// Modifier keys
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x33, // ';'
|
0x33, // ';'
|
||||||
0x2E, // Plus
|
0x2E, // Plus
|
||||||
0x36, // Comma
|
0x36, // Comma
|
||||||
0x2D, // Minus
|
0x2D, // Minus
|
||||||
0x37, // Period
|
0x37, // Period
|
||||||
0x38, // '/'
|
0x38, // '/'
|
||||||
0x35, // '~'
|
0x35, // '~'
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00,
|
0x00, 0x00,
|
||||||
0x2F, // '['
|
0x2F, // '['
|
||||||
0x32, // '\'
|
0x32, // '\'
|
||||||
0x30, // ']'
|
0x30, // ']'
|
||||||
0x34, // '''
|
0x34, // '''
|
||||||
0x00, //
|
0x00, //
|
||||||
0x00, // Nothing interesting past this point.
|
0x00, // Nothing interesting past this point.
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||||
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x2A, // Backspace
|
0x2A, // Backspace
|
||||||
0x2B, // Tab
|
0x2B, // Tab
|
||||||
0x00, 0x00,
|
0x00, 0x00,
|
||||||
0x00, // Clear
|
0x00, // Clear
|
||||||
0x28, // Return
|
0x28, // Return
|
||||||
0x00, 0x00,
|
0x00, 0x00,
|
||||||
0x00, // Shift
|
0x00, // Shift
|
||||||
0x00, // Control
|
0x00, // Control
|
||||||
0x00, // ALT
|
0x00, // ALT
|
||||||
0x48, // Pause
|
0x48, // Pause
|
||||||
0x39, // Capital
|
0x39, // Capital
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x29, // Escape
|
0x29, // Escape
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x2C, // Space
|
0x2C, // Space
|
||||||
0x4B, // Prior
|
0x4B, // Prior
|
||||||
0x4E, // Next
|
0x4E, // Next
|
||||||
0x4D, // End
|
0x4D, // End
|
||||||
0x4A, // Home
|
0x4A, // Home
|
||||||
0x50, // Left
|
0x50, // Left
|
||||||
0x52, // Up
|
0x52, // Up
|
||||||
0x4F, // Right
|
0x4F, // Right
|
||||||
0x51, // Down
|
0x51, // Down
|
||||||
0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00,
|
||||||
0x46, // Print screen
|
0x46, // Print screen
|
||||||
0x49, // Insert
|
0x49, // Insert
|
||||||
0x4C, // Delete
|
0x4C, // Delete
|
||||||
0x00,
|
0x00,
|
||||||
// 0 -> 9
|
// 0 -> 9
|
||||||
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||||
0x25, 0x26,
|
0x25, 0x26,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00,
|
0x00,
|
||||||
// A -> Z
|
// A -> Z
|
||||||
0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
||||||
0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
|
0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
|
||||||
0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
|
0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
|
||||||
0x1C, 0x1A,
|
0x1C, 0x1A,
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x00,
|
0x00,
|
||||||
// Numpad 0 -> 9
|
// Numpad 0 -> 9
|
||||||
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||||
0x60, 0x61,
|
0x60, 0x61,
|
||||||
0x55, // Multiply
|
0x55, // Multiply
|
||||||
0x57, // Add
|
0x57, // Add
|
||||||
0x00, // Separator
|
0x00, // Separator
|
||||||
0x56, // Substract
|
0x56, // Substract
|
||||||
0x63, // Decimal
|
0x63, // Decimal
|
||||||
0x54, // Divide
|
0x54, // Divide
|
||||||
// F1 -> F12
|
// F1 -> F12
|
||||||
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
|
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
|
||||||
0x42, 0x43, 0x44, 0x45,
|
0x42, 0x43, 0x44, 0x45,
|
||||||
// F13 -> F24
|
// F13 -> F24
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x53, // Numlock
|
0x53, // Numlock
|
||||||
0x47, // Scroll lock
|
0x47, // Scroll lock
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
// Modifier keys
|
// Modifier keys
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00,
|
||||||
0x30, // '$'
|
0x30, // '$'
|
||||||
0x2E, // Plus
|
0x2E, // Plus
|
||||||
0x10, // Comma
|
0x10, // Comma
|
||||||
0x00, // Minus
|
0x00, // Minus
|
||||||
0x36, // Period
|
0x36, // Period
|
||||||
0x37, // '/'
|
0x37, // '/'
|
||||||
0x34, // 'ù'
|
0x34, // 'ù'
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00,
|
0x00, 0x00,
|
||||||
0x2D, // ')'
|
0x2D, // ')'
|
||||||
0x32, // '\'
|
0x32, // '\'
|
||||||
0x2F, // '^'
|
0x2F, // '^'
|
||||||
0x00, // '²'
|
0x00, // '²'
|
||||||
0x38, // '!'
|
0x38, // '!'
|
||||||
0x00, // Nothing interesting past this point.
|
0x00, // Nothing interesting past this point.
|
||||||
|
|
||||||
};
|
};
|
|
@ -1,133 +1,133 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "DSPAnalyzer.h"
|
#include "DSPAnalyzer.h"
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
#include "DSPTables.h"
|
#include "DSPTables.h"
|
||||||
#include "DSPMemoryMap.h"
|
#include "DSPMemoryMap.h"
|
||||||
|
|
||||||
namespace DSPAnalyzer {
|
namespace DSPAnalyzer {
|
||||||
|
|
||||||
// Holds data about all instructions in RAM.
|
// Holds data about all instructions in RAM.
|
||||||
u8 code_flags[ISPACE];
|
u8 code_flags[ISPACE];
|
||||||
|
|
||||||
// Good candidates for idle skipping is mail wait loops. If we're time slicing
|
// Good candidates for idle skipping is mail wait loops. If we're time slicing
|
||||||
// between the main CPU and the DSP, if the DSP runs into one of these, it might
|
// between the main CPU and the DSP, if the DSP runs into one of these, it might
|
||||||
// as well give up its time slice immediately, after executing once.
|
// as well give up its time slice immediately, after executing once.
|
||||||
|
|
||||||
// Max signature length is 6. A 0 in a signature is ignored.
|
// Max signature length is 6. A 0 in a signature is ignored.
|
||||||
#define NUM_IDLE_SIGS 5
|
#define NUM_IDLE_SIGS 5
|
||||||
#define MAX_IDLE_SIG_SIZE 6
|
#define MAX_IDLE_SIG_SIZE 6
|
||||||
|
|
||||||
// 0xFFFF means ignore.
|
// 0xFFFF means ignore.
|
||||||
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
||||||
{
|
{
|
||||||
// From AX:
|
// From AX:
|
||||||
{ 0x26fc, // LRS $30, @DMBH
|
{ 0x26fc, // LRS $30, @DMBH
|
||||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||||
0x029d, 0xFFFF, // JLZ 0x027a
|
0x029d, 0xFFFF, // JLZ 0x027a
|
||||||
0, 0 }, // RET
|
0, 0 }, // RET
|
||||||
{ 0x27fc, // LRS $31, @DMBH
|
{ 0x27fc, // LRS $31, @DMBH
|
||||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||||
0x029d, 0xFFFF, // JLZ 0x027a
|
0x029d, 0xFFFF, // JLZ 0x027a
|
||||||
0, 0 }, // RET
|
0, 0 }, // RET
|
||||||
{ 0x26fe, // LRS $30, @CMBH
|
{ 0x26fe, // LRS $30, @CMBH
|
||||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||||
0, 0 }, // RET
|
0, 0 }, // RET
|
||||||
{ 0x27fe, // LRS $31, @CMBH
|
{ 0x27fe, // LRS $31, @CMBH
|
||||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||||
0, 0 }, // RET
|
0, 0 }, // RET
|
||||||
|
|
||||||
// From Zelda:
|
// From Zelda:
|
||||||
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
||||||
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
||||||
0x029c, 0xFFFF, // JLNZ 0x05cf
|
0x029c, 0xFFFF, // JLNZ 0x05cf
|
||||||
0 }
|
0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
memset(code_flags, 0, sizeof(code_flags));
|
memset(code_flags, 0, sizeof(code_flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalyzeRange(int start_addr, int end_addr)
|
void AnalyzeRange(int start_addr, int end_addr)
|
||||||
{
|
{
|
||||||
// First we run an extremely simplified version of a disassembler to find
|
// First we run an extremely simplified version of a disassembler to find
|
||||||
// where all instructions start.
|
// where all instructions start.
|
||||||
|
|
||||||
// This may not be 100% accurate in case of jump tables!
|
// This may not be 100% accurate in case of jump tables!
|
||||||
// It could get desynced, which would be bad. We'll see if that's an issue.
|
// It could get desynced, which would be bad. We'll see if that's an issue.
|
||||||
int addr = start_addr;
|
int addr = start_addr;
|
||||||
while (addr < end_addr)
|
while (addr < end_addr)
|
||||||
{
|
{
|
||||||
UDSPInstruction inst = dsp_imem_read(addr);
|
UDSPInstruction inst = dsp_imem_read(addr);
|
||||||
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
|
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
|
||||||
if (!opcode)
|
if (!opcode)
|
||||||
{
|
{
|
||||||
addr++;
|
addr++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
code_flags[addr] |= CODE_START_OF_INST;
|
code_flags[addr] |= CODE_START_OF_INST;
|
||||||
addr += opcode->size;
|
addr += opcode->size;
|
||||||
|
|
||||||
// Look for loops.
|
// Look for loops.
|
||||||
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
|
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
|
||||||
// BLOOP, BLOOPI
|
// BLOOP, BLOOPI
|
||||||
u16 loop_end = dsp_imem_read(addr + 1);
|
u16 loop_end = dsp_imem_read(addr + 1);
|
||||||
code_flags[loop_end] |= CODE_LOOP_END;
|
code_flags[loop_end] |= CODE_LOOP_END;
|
||||||
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
|
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
|
||||||
// LOOP, LOOPI
|
// LOOP, LOOPI
|
||||||
code_flags[addr + 1] |= CODE_LOOP_END;
|
code_flags[addr + 1] |= CODE_LOOP_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next, we'll scan for potential idle skips.
|
// Next, we'll scan for potential idle skips.
|
||||||
for (int s = 0; s < NUM_IDLE_SIGS; s++)
|
for (int s = 0; s < NUM_IDLE_SIGS; s++)
|
||||||
{
|
{
|
||||||
for (int addr = start_addr; addr < end_addr; addr++)
|
for (int addr = start_addr; addr < end_addr; addr++)
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
|
for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
|
||||||
{
|
{
|
||||||
if (idle_skip_sigs[s][i] == 0)
|
if (idle_skip_sigs[s][i] == 0)
|
||||||
found = true;
|
found = true;
|
||||||
if (idle_skip_sigs[s][i] == 0xFFFF)
|
if (idle_skip_sigs[s][i] == 0xFFFF)
|
||||||
continue;
|
continue;
|
||||||
if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
|
if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (found)
|
if (found)
|
||||||
{
|
{
|
||||||
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
|
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
|
||||||
code_flags[addr] |= CODE_IDLE_SKIP;
|
code_flags[addr] |= CODE_IDLE_SKIP;
|
||||||
// TODO: actually use this flag somewhere.
|
// TODO: actually use this flag somewhere.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NOTICE_LOG(DSPLLE, "Finished analysis.");
|
NOTICE_LOG(DSPLLE, "Finished analysis.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyze()
|
void Analyze()
|
||||||
{
|
{
|
||||||
Reset();
|
Reset();
|
||||||
AnalyzeRange(0x0000, 0x1000); // IRAM
|
AnalyzeRange(0x0000, 0x1000); // IRAM
|
||||||
AnalyzeRange(0x8000, 0x9000); // IROM
|
AnalyzeRange(0x8000, 0x9000); // IROM
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -1,49 +1,49 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Basic code analysis.
|
// Basic code analysis.
|
||||||
|
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
|
|
||||||
namespace DSPAnalyzer {
|
namespace DSPAnalyzer {
|
||||||
|
|
||||||
#define ISPACE 65536
|
#define ISPACE 65536
|
||||||
|
|
||||||
// Useful things to detect:
|
// Useful things to detect:
|
||||||
// * Loop endpoints - so that we can avoid checking for loops every cycle.
|
// * Loop endpoints - so that we can avoid checking for loops every cycle.
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CODE_START_OF_INST = 1,
|
CODE_START_OF_INST = 1,
|
||||||
CODE_IDLE_SKIP = 2,
|
CODE_IDLE_SKIP = 2,
|
||||||
CODE_LOOP_END = 4,
|
CODE_LOOP_END = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Easy to query array covering the whole of instruction memory.
|
// Easy to query array covering the whole of instruction memory.
|
||||||
// Just index by address.
|
// Just index by address.
|
||||||
// This one will be helpful for debuggers and jits.
|
// This one will be helpful for debuggers and jits.
|
||||||
extern u8 code_flags[ISPACE];
|
extern u8 code_flags[ISPACE];
|
||||||
|
|
||||||
// This one should be called every time IRAM changes - which is basically
|
// This one should be called every time IRAM changes - which is basically
|
||||||
// every time that a new ucode gets uploaded, and never else. At that point,
|
// every time that a new ucode gets uploaded, and never else. At that point,
|
||||||
// we can do as much static analysis as we want - but we should always throw
|
// we can do as much static analysis as we want - but we should always throw
|
||||||
// all old analysis away. Luckily the entire address space is only 64K code
|
// all old analysis away. Luckily the entire address space is only 64K code
|
||||||
// words and the actual code space 8K instructions in total, so we can do
|
// words and the actual code space 8K instructions in total, so we can do
|
||||||
// some pretty expensive analysis if necessary.
|
// some pretty expensive analysis if necessary.
|
||||||
void Analyze();
|
void Analyze();
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "DSPBreakpoints.h"
|
#include "DSPBreakpoints.h"
|
||||||
|
|
||||||
|
|
|
@ -1,63 +1,63 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DSP_BREAKPOINTS
|
#ifndef _DSP_BREAKPOINTS
|
||||||
#define _DSP_BREAKPOINTS
|
#define _DSP_BREAKPOINTS
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
// super fast breakpoints for a limited range.
|
// super fast breakpoints for a limited range.
|
||||||
// To be used interchangably with the BreakPoints class.
|
// To be used interchangably with the BreakPoints class.
|
||||||
class DSPBreakpoints
|
class DSPBreakpoints
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DSPBreakpoints() {Clear();}
|
DSPBreakpoints() {Clear();}
|
||||||
// is address breakpoint
|
// is address breakpoint
|
||||||
bool IsAddressBreakPoint(u32 addr) {
|
bool IsAddressBreakPoint(u32 addr) {
|
||||||
return b[addr] != 0;
|
return b[addr] != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddBreakPoint
|
// AddBreakPoint
|
||||||
bool Add(u32 addr, bool temp=false) {
|
bool Add(u32 addr, bool temp=false) {
|
||||||
bool was_one = b[addr] != 0;
|
bool was_one = b[addr] != 0;
|
||||||
if (!was_one) {
|
if (!was_one) {
|
||||||
b[addr] = temp ? 2 : 1;
|
b[addr] = temp ? 2 : 1;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Remove Breakpoint
|
// Remove Breakpoint
|
||||||
bool Remove(u32 addr) {
|
bool Remove(u32 addr) {
|
||||||
bool was_one = b[addr] != 0;
|
bool was_one = b[addr] != 0;
|
||||||
b[addr] = 0;
|
b[addr] = 0;
|
||||||
return was_one;
|
return was_one;
|
||||||
}
|
}
|
||||||
void Clear() {
|
void Clear() {
|
||||||
for (int i = 0; i < 65536; i++)
|
for (int i = 0; i < 65536; i++)
|
||||||
b[i] = 0;
|
b[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteByAddress(u32 addr) {
|
void DeleteByAddress(u32 addr) {
|
||||||
b[addr] = 0;
|
b[addr] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u8 b[65536];
|
u8 b[65536];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,235 +1,235 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
#include "DSPCodeUtil.h"
|
#include "DSPCodeUtil.h"
|
||||||
#include "assemble.h"
|
#include "assemble.h"
|
||||||
#include "disassemble.h"
|
#include "disassemble.h"
|
||||||
|
|
||||||
|
|
||||||
bool Assemble(const char *text, std::vector<u16> &code)
|
bool Assemble(const char *text, std::vector<u16> &code)
|
||||||
{
|
{
|
||||||
AssemblerSettings settings;
|
AssemblerSettings settings;
|
||||||
settings.pc = 0;
|
settings.pc = 0;
|
||||||
// settings.decode_registers = false;
|
// settings.decode_registers = false;
|
||||||
// settings.decode_names = false;
|
// settings.decode_names = false;
|
||||||
settings.print_tabs = false;
|
settings.print_tabs = false;
|
||||||
settings.ext_separator = '\'';
|
settings.ext_separator = '\'';
|
||||||
|
|
||||||
// TODO: fix the terrible api of the assembler.
|
// TODO: fix the terrible api of the assembler.
|
||||||
DSPAssembler assembler(settings);
|
DSPAssembler assembler(settings);
|
||||||
if (!assembler.Assemble(text, code)) {
|
if (!assembler.Assemble(text, code)) {
|
||||||
std::cerr << assembler.GetErrorString() << std::endl;
|
std::cerr << assembler.GetErrorString() << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
|
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
|
||||||
{
|
{
|
||||||
if (code.empty())
|
if (code.empty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
AssemblerSettings settings;
|
AssemblerSettings settings;
|
||||||
|
|
||||||
// These two prevent roundtripping.
|
// These two prevent roundtripping.
|
||||||
settings.show_hex = false;
|
settings.show_hex = false;
|
||||||
settings.show_pc = line_numbers;
|
settings.show_pc = line_numbers;
|
||||||
settings.ext_separator = '\'';
|
settings.ext_separator = '\'';
|
||||||
settings.decode_names = false;
|
settings.decode_names = false;
|
||||||
settings.decode_registers = true;
|
settings.decode_registers = true;
|
||||||
|
|
||||||
DSPDisassembler disasm(settings);
|
DSPDisassembler disasm(settings);
|
||||||
bool success = disasm.Disassemble(0, code, 0x0000, text);
|
bool success = disasm.Disassemble(0, code, 0x0000, text);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
|
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
|
||||||
{
|
{
|
||||||
if (code1.size() != code2.size())
|
if (code1.size() != code2.size())
|
||||||
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
|
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
|
||||||
u32 count_equal = 0;
|
u32 count_equal = 0;
|
||||||
const int min_size = (int)std::min(code1.size(), code2.size());
|
const int min_size = (int)std::min(code1.size(), code2.size());
|
||||||
|
|
||||||
AssemblerSettings settings;
|
AssemblerSettings settings;
|
||||||
DSPDisassembler disassembler(settings);
|
DSPDisassembler disassembler(settings);
|
||||||
for (int i = 0; i < min_size; i++)
|
for (int i = 0; i < min_size; i++)
|
||||||
{
|
{
|
||||||
if (code1[i] == code2[i])
|
if (code1[i] == code2[i])
|
||||||
count_equal++;
|
count_equal++;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::string line1, line2;
|
std::string line1, line2;
|
||||||
u16 pc = i;
|
u16 pc = i;
|
||||||
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
|
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
|
||||||
pc = i;
|
pc = i;
|
||||||
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
|
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
|
||||||
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
|
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (code2.size() != code1.size())
|
if (code2.size() != code1.size())
|
||||||
{
|
{
|
||||||
printf("Extra code words:\n");
|
printf("Extra code words:\n");
|
||||||
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
|
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
|
||||||
for (int i = min_size; i < (int)longest.size(); i++)
|
for (int i = min_size; i < (int)longest.size(); i++)
|
||||||
{
|
{
|
||||||
u16 pc = i;
|
u16 pc = i;
|
||||||
std::string line;
|
std::string line;
|
||||||
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
|
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
|
||||||
printf("!! %s\n", line.c_str());
|
printf("!! %s\n", line.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
|
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
|
||||||
return code1.size() == code2.size() && code1.size() == count_equal;
|
return code1.size() == code2.size() && code1.size() == count_equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenRandomCode(int size, std::vector<u16> &code)
|
void GenRandomCode(int size, std::vector<u16> &code)
|
||||||
{
|
{
|
||||||
code.resize(size);
|
code.resize(size);
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
code[i] = rand() ^ (rand() << 8);
|
code[i] = rand() ^ (rand() << 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||||
const char *name, std::string &header)
|
const char *name, std::string &header)
|
||||||
{
|
{
|
||||||
std::vector<u16> code_copy = code;
|
std::vector<u16> code_copy = code;
|
||||||
// Add some nops at the end to align the size a bit.
|
// Add some nops at the end to align the size a bit.
|
||||||
while (code_copy.size() & 7)
|
while (code_copy.size() & 7)
|
||||||
code_copy.push_back(0);
|
code_copy.push_back(0);
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
header.clear();
|
header.clear();
|
||||||
header.reserve(code.size() * 4);
|
header.reserve(code.size() * 4);
|
||||||
header.append("#define NUM_UCODES 1\n\n");
|
header.append("#define NUM_UCODES 1\n\n");
|
||||||
std::string filename;
|
std::string filename;
|
||||||
SplitPath(_filename, NULL, &filename, NULL);
|
SplitPath(_filename, NULL, &filename, NULL);
|
||||||
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
|
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
|
||||||
header.append("#ifndef _MSCVER\n");
|
header.append("#ifndef _MSCVER\n");
|
||||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
|
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
|
||||||
header.append("#else\n");
|
header.append("#else\n");
|
||||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||||
header.append("#endif\n\n");
|
header.append("#endif\n\n");
|
||||||
|
|
||||||
header.append("\t{\n\t\t");
|
header.append("\t{\n\t\t");
|
||||||
for (u32 j = 0; j < code.size(); j++)
|
for (u32 j = 0; j < code.size(); j++)
|
||||||
{
|
{
|
||||||
if (j && ((j & 15) == 0))
|
if (j && ((j & 15) == 0))
|
||||||
header.append("\n\t\t");
|
header.append("\n\t\t");
|
||||||
sprintf(buffer, "0x%04x, ", code[j]);
|
sprintf(buffer, "0x%04x, ", code[j]);
|
||||||
header.append(buffer);
|
header.append(buffer);
|
||||||
}
|
}
|
||||||
header.append("\n\t},\n");
|
header.append("\n\t},\n");
|
||||||
|
|
||||||
header.append("};\n");
|
header.append("};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
|
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
|
||||||
int numCodes, const char *name, std::string &header)
|
int numCodes, const char *name, std::string &header)
|
||||||
{
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
int reserveSize = 0;
|
int reserveSize = 0;
|
||||||
for(int i = 0; i < numCodes; i++)
|
for(int i = 0; i < numCodes; i++)
|
||||||
reserveSize += (int)codes[i].size();
|
reserveSize += (int)codes[i].size();
|
||||||
|
|
||||||
|
|
||||||
header.clear();
|
header.clear();
|
||||||
header.reserve(reserveSize * 4);
|
header.reserve(reserveSize * 4);
|
||||||
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
|
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
|
||||||
header.append(buffer);
|
header.append(buffer);
|
||||||
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
|
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
|
||||||
for (int i = 0; i < numCodes; i++)
|
for (int i = 0; i < numCodes; i++)
|
||||||
{
|
{
|
||||||
std::string filename;
|
std::string filename;
|
||||||
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
|
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
|
||||||
filename = filenames->at(i);
|
filename = filenames->at(i);
|
||||||
sprintf(buffer, "\t\"%s\",\n", filename.c_str());
|
sprintf(buffer, "\t\"%s\",\n", filename.c_str());
|
||||||
header.append(buffer);
|
header.append(buffer);
|
||||||
}
|
}
|
||||||
header.append("};\n\n");
|
header.append("};\n\n");
|
||||||
header.append("#ifndef _MSCVER\n");
|
header.append("#ifndef _MSCVER\n");
|
||||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
|
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
|
||||||
header.append("#else\n");
|
header.append("#else\n");
|
||||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||||
header.append("#endif\n\n");
|
header.append("#endif\n\n");
|
||||||
|
|
||||||
for(int i = 0; i < numCodes; i++) {
|
for(int i = 0; i < numCodes; i++) {
|
||||||
if(codes[i].size() == 0)
|
if(codes[i].size() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::vector<u16> code_copy = codes[i];
|
std::vector<u16> code_copy = codes[i];
|
||||||
// Add some nops at the end to align the size a bit.
|
// Add some nops at the end to align the size a bit.
|
||||||
while (code_copy.size() & 7)
|
while (code_copy.size() & 7)
|
||||||
code_copy.push_back(0);
|
code_copy.push_back(0);
|
||||||
|
|
||||||
header.append("\t{\n\t\t");
|
header.append("\t{\n\t\t");
|
||||||
for (u32 j = 0; j < codes[i].size(); j++)
|
for (u32 j = 0; j < codes[i].size(); j++)
|
||||||
{
|
{
|
||||||
if (j && ((j & 15) == 0))
|
if (j && ((j & 15) == 0))
|
||||||
header.append("\n\t\t");
|
header.append("\n\t\t");
|
||||||
sprintf(buffer, "0x%04x, ", codes[i][j]);
|
sprintf(buffer, "0x%04x, ", codes[i][j]);
|
||||||
header.append(buffer);
|
header.append(buffer);
|
||||||
}
|
}
|
||||||
header.append("\n\t},\n");
|
header.append("\n\t},\n");
|
||||||
}
|
}
|
||||||
header.append("};\n");
|
header.append("};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
|
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
|
||||||
{
|
{
|
||||||
str.resize(code.size() * 2);
|
str.resize(code.size() * 2);
|
||||||
for (int i = 0; i < (int)code.size(); i++)
|
for (int i = 0; i < (int)code.size(); i++)
|
||||||
{
|
{
|
||||||
str[i * 2 + 0] = code[i] >> 8;
|
str[i * 2 + 0] = code[i] >> 8;
|
||||||
str[i * 2 + 1] = code[i] & 0xff;
|
str[i * 2 + 1] = code[i] & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
|
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
|
||||||
{
|
{
|
||||||
code.resize(str.size() / 2);
|
code.resize(str.size() / 2);
|
||||||
for (int i = 0; i < (int)code.size(); i++)
|
for (int i = 0; i < (int)code.size(); i++)
|
||||||
{
|
{
|
||||||
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
|
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadBinary(const char *filename, std::vector<u16> &code)
|
bool LoadBinary(const char *filename, std::vector<u16> &code)
|
||||||
{
|
{
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
if (!File::ReadFileToString(false, filename, buffer))
|
if (!File::ReadFileToString(false, filename, buffer))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
BinaryStringBEToCode(buffer, code);
|
BinaryStringBEToCode(buffer, code);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SaveBinary(const std::vector<u16> &code, const char *filename)
|
bool SaveBinary(const std::vector<u16> &code, const char *filename)
|
||||||
{
|
{
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
CodeToBinaryStringBE(code, buffer);
|
CodeToBinaryStringBE(code, buffer);
|
||||||
if (!File::WriteStringToFile(false, buffer, filename))
|
if (!File::WriteStringToFile(false, buffer, filename))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DSPCODEUTIL_H
|
#ifndef _DSPCODEUTIL_H
|
||||||
#define _DSPCODEUTIL_H
|
#define _DSPCODEUTIL_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
bool Assemble(const char *text, std::vector<u16> &code);
|
bool Assemble(const char *text, std::vector<u16> &code);
|
||||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
|
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
|
||||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
|
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
|
||||||
void GenRandomCode(int size, std::vector<u16> &code);
|
void GenRandomCode(int size, std::vector<u16> &code);
|
||||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||||
const char *name, std::string &header);
|
const char *name, std::string &header);
|
||||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
|
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
|
||||||
int numCodes, const char *name, std::string &header);
|
int numCodes, const char *name, std::string &header);
|
||||||
|
|
||||||
// Big-endian, for writing straight to file using File::WriteStringToFile.
|
// Big-endian, for writing straight to file using File::WriteStringToFile.
|
||||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
|
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
|
||||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
|
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
|
||||||
|
|
||||||
// Load code (big endian binary).
|
// Load code (big endian binary).
|
||||||
bool LoadBinary(const char *filename, std::vector<u16> &code);
|
bool LoadBinary(const char *filename, std::vector<u16> &code);
|
||||||
bool SaveBinary(const std::vector<u16> &code, const char *filename);
|
bool SaveBinary(const std::vector<u16> &code, const char *filename);
|
||||||
|
|
||||||
#endif // _DSPCODEUTIL_H
|
#endif // _DSPCODEUTIL_H
|
||||||
|
|
|
@ -1,256 +1,256 @@
|
||||||
/*====================================================================
|
/*====================================================================
|
||||||
|
|
||||||
filename: gdsp_interpreter.cpp
|
filename: gdsp_interpreter.cpp
|
||||||
project: GCemu
|
project: GCemu
|
||||||
created: 2004-6-18
|
created: 2004-6-18
|
||||||
mail: duddie@walla.com
|
mail: duddie@walla.com
|
||||||
|
|
||||||
Copyright (c) 2005 Duddie & Tratax
|
Copyright (c) 2005 Duddie & Tratax
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License
|
modify it under the terms of the GNU General Public License
|
||||||
as published by the Free Software Foundation; either version 2
|
as published by the Free Software Foundation; either version 2
|
||||||
of the License, or (at your option) any later version.
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
====================================================================*/
|
====================================================================*/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include "DSPCore.h"
|
#include "DSPCore.h"
|
||||||
#include "DSPHost.h"
|
#include "DSPHost.h"
|
||||||
#include "DSPAnalyzer.h"
|
#include "DSPAnalyzer.h"
|
||||||
#include "MemoryUtil.h"
|
#include "MemoryUtil.h"
|
||||||
|
|
||||||
#include "DSPHWInterface.h"
|
#include "DSPHWInterface.h"
|
||||||
#include "DSPIntUtil.h"
|
#include "DSPIntUtil.h"
|
||||||
|
|
||||||
SDSP g_dsp;
|
SDSP g_dsp;
|
||||||
DSPBreakpoints dsp_breakpoints;
|
DSPBreakpoints dsp_breakpoints;
|
||||||
DSPCoreState core_state = DSPCORE_RUNNING;
|
DSPCoreState core_state = DSPCORE_RUNNING;
|
||||||
Common::Event step_event;
|
Common::Event step_event;
|
||||||
|
|
||||||
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
|
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
|
||||||
{
|
{
|
||||||
FILE *pFile = fopen(fname, "rb");
|
FILE *pFile = fopen(fname, "rb");
|
||||||
const size_t size_in_bytes = size_in_words * sizeof(u16);
|
const size_t size_in_bytes = size_in_words * sizeof(u16);
|
||||||
if (pFile)
|
if (pFile)
|
||||||
{
|
{
|
||||||
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
|
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
|
||||||
if (read_bytes != size_in_bytes)
|
if (read_bytes != size_in_bytes)
|
||||||
{
|
{
|
||||||
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
|
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
|
|
||||||
// Byteswap the rom.
|
// Byteswap the rom.
|
||||||
for (int i = 0; i < DSP_IROM_SIZE; i++)
|
for (int i = 0; i < DSP_IROM_SIZE; i++)
|
||||||
rom[i] = Common::swap16(rom[i]);
|
rom[i] = Common::swap16(rom[i]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Always keep ROMs write protected.
|
// Always keep ROMs write protected.
|
||||||
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
|
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
|
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
|
||||||
{
|
{
|
||||||
g_dsp.step_counter = 0;
|
g_dsp.step_counter = 0;
|
||||||
|
|
||||||
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
|
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
|
||||||
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
|
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
|
||||||
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
|
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
|
||||||
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
|
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
|
||||||
|
|
||||||
// Fill roms with zeros.
|
// Fill roms with zeros.
|
||||||
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
|
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
|
||||||
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
|
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
|
||||||
|
|
||||||
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
|
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
|
||||||
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
|
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
|
||||||
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
|
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
|
||||||
|
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
g_dsp.r[i] = 0;
|
g_dsp.r[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
g_dsp.reg_stack_ptr[i] = 0;
|
g_dsp.reg_stack_ptr[i] = 0;
|
||||||
for (int j = 0; j < DSP_STACK_DEPTH; j++)
|
for (int j = 0; j < DSP_STACK_DEPTH; j++)
|
||||||
{
|
{
|
||||||
g_dsp.reg_stack[i][j] = 0;
|
g_dsp.reg_stack[i][j] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill IRAM with HALT opcodes.
|
// Fill IRAM with HALT opcodes.
|
||||||
for (int i = 0; i < DSP_IRAM_SIZE; i++)
|
for (int i = 0; i < DSP_IRAM_SIZE; i++)
|
||||||
{
|
{
|
||||||
g_dsp.iram[i] = 0x0021; // HALT opcode
|
g_dsp.iram[i] = 0x0021; // HALT opcode
|
||||||
}
|
}
|
||||||
|
|
||||||
// Just zero out DRAM.
|
// Just zero out DRAM.
|
||||||
for (int i = 0; i < DSP_DRAM_SIZE; i++)
|
for (int i = 0; i < DSP_DRAM_SIZE; i++)
|
||||||
{
|
{
|
||||||
g_dsp.dram[i] = 0;
|
g_dsp.dram[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copied from a real console after the custom UCode has been loaded.
|
// Copied from a real console after the custom UCode has been loaded.
|
||||||
// These are the indexing wrapping registers.
|
// These are the indexing wrapping registers.
|
||||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||||
|
|
||||||
g_dsp.cr = 0x804;
|
g_dsp.cr = 0x804;
|
||||||
gdsp_ifx_init();
|
gdsp_ifx_init();
|
||||||
|
|
||||||
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
|
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
|
||||||
// in new ucodes.
|
// in new ucodes.
|
||||||
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
|
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
|
||||||
DSPAnalyzer::Analyze();
|
DSPAnalyzer::Analyze();
|
||||||
|
|
||||||
step_event.Init();
|
step_event.Init();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCore_Shutdown()
|
void DSPCore_Shutdown()
|
||||||
{
|
{
|
||||||
step_event.Shutdown();
|
step_event.Shutdown();
|
||||||
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
|
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
|
||||||
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
|
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
|
||||||
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
|
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
|
||||||
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
|
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCore_Reset()
|
void DSPCore_Reset()
|
||||||
{
|
{
|
||||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
|
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
|
||||||
g_dsp.pc = DSP_RESET_VECTOR;
|
g_dsp.pc = DSP_RESET_VECTOR;
|
||||||
g_dsp.exception_in_progress_hack = false;
|
g_dsp.exception_in_progress_hack = false;
|
||||||
|
|
||||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCore_SetException(u8 level)
|
void DSPCore_SetException(u8 level)
|
||||||
{
|
{
|
||||||
g_dsp.exceptions |= 1 << level;
|
g_dsp.exceptions |= 1 << level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCore_CheckExternalInterrupt()
|
void DSPCore_CheckExternalInterrupt()
|
||||||
{
|
{
|
||||||
// check if there is an external interrupt
|
// check if there is an external interrupt
|
||||||
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
|
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_EXP
|
#ifdef DEBUG_EXP
|
||||||
NOTICE_LOG(DSPLLE, "trying External interupt fired");
|
NOTICE_LOG(DSPLLE, "trying External interupt fired");
|
||||||
#endif
|
#endif
|
||||||
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
|
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_EXP
|
#ifdef DEBUG_EXP
|
||||||
NOTICE_LOG(DSPLLE, "External interupt fired");
|
NOTICE_LOG(DSPLLE, "External interupt fired");
|
||||||
#endif
|
#endif
|
||||||
// level 7 is the interrupt exception
|
// level 7 is the interrupt exception
|
||||||
DSPCore_SetException(EXP_INT);
|
DSPCore_SetException(EXP_INT);
|
||||||
|
|
||||||
g_dsp.cr &= ~CR_EXTERNAL_INT;
|
g_dsp.cr &= ~CR_EXTERNAL_INT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCore_CheckExceptions()
|
void DSPCore_CheckExceptions()
|
||||||
{
|
{
|
||||||
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
|
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
|
||||||
#ifdef DEBUG_EXP
|
#ifdef DEBUG_EXP
|
||||||
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
|
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
|
||||||
#endif
|
#endif
|
||||||
// check exceptions
|
// check exceptions
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
// Seems 7 must pass or zelda dies
|
// Seems 7 must pass or zelda dies
|
||||||
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
|
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
|
||||||
if (g_dsp.exceptions & (1 << i)) {
|
if (g_dsp.exceptions & (1 << i)) {
|
||||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||||
|
|
||||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||||
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
|
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
|
||||||
|
|
||||||
g_dsp.pc = i * 2;
|
g_dsp.pc = i * 2;
|
||||||
g_dsp.exceptions &= ~(1 << i);
|
g_dsp.exceptions &= ~(1 << i);
|
||||||
#ifdef DEBUG_EXP
|
#ifdef DEBUG_EXP
|
||||||
NOTICE_LOG(DSPLLE, "exception %d fired");
|
NOTICE_LOG(DSPLLE, "exception %d fired");
|
||||||
#endif
|
#endif
|
||||||
g_dsp.exception_in_progress_hack = true;
|
g_dsp.exception_in_progress_hack = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delegate to JIT (when it is written) or interpreter as appropriate.
|
// Delegate to JIT (when it is written) or interpreter as appropriate.
|
||||||
// Handle state changes and stepping.
|
// Handle state changes and stepping.
|
||||||
int DSPCore_RunCycles(int cycles)
|
int DSPCore_RunCycles(int cycles)
|
||||||
{
|
{
|
||||||
while (cycles > 0) {
|
while (cycles > 0) {
|
||||||
reswitch:
|
reswitch:
|
||||||
switch (core_state)
|
switch (core_state)
|
||||||
{
|
{
|
||||||
case DSPCORE_RUNNING:
|
case DSPCORE_RUNNING:
|
||||||
#if 1 // Set to 0 to disable breakpoints, for a speed boost.
|
#if 1 // Set to 0 to disable breakpoints, for a speed boost.
|
||||||
cycles = DSPInterpreter::RunCyclesDebug(cycles);
|
cycles = DSPInterpreter::RunCyclesDebug(cycles);
|
||||||
#else
|
#else
|
||||||
cycles = DSPInterpreter::RunCycles(cycles);
|
cycles = DSPInterpreter::RunCycles(cycles);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DSPCORE_STEPPING:
|
case DSPCORE_STEPPING:
|
||||||
step_event.Wait();
|
step_event.Wait();
|
||||||
if (core_state != DSPCORE_STEPPING)
|
if (core_state != DSPCORE_STEPPING)
|
||||||
goto reswitch;
|
goto reswitch;
|
||||||
|
|
||||||
DSPInterpreter::Step();
|
DSPInterpreter::Step();
|
||||||
cycles--;
|
cycles--;
|
||||||
|
|
||||||
DSPHost_UpdateDebugger();
|
DSPHost_UpdateDebugger();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cycles;
|
return cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCore_SetState(DSPCoreState new_state)
|
void DSPCore_SetState(DSPCoreState new_state)
|
||||||
{
|
{
|
||||||
core_state = new_state;
|
core_state = new_state;
|
||||||
// kick the event, in case we are waiting
|
// kick the event, in case we are waiting
|
||||||
if (new_state == DSPCORE_RUNNING)
|
if (new_state == DSPCORE_RUNNING)
|
||||||
step_event.Set();
|
step_event.Set();
|
||||||
// Sleep(10);
|
// Sleep(10);
|
||||||
DSPHost_UpdateDebugger();
|
DSPHost_UpdateDebugger();
|
||||||
}
|
}
|
||||||
|
|
||||||
DSPCoreState DSPCore_GetState()
|
DSPCoreState DSPCore_GetState()
|
||||||
{
|
{
|
||||||
return core_state;
|
return core_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCore_Step()
|
void DSPCore_Step()
|
||||||
{
|
{
|
||||||
if (core_state == DSPCORE_STEPPING)
|
if (core_state == DSPCORE_STEPPING)
|
||||||
step_event.Set();
|
step_event.Set();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,240 +1,240 @@
|
||||||
/*====================================================================
|
/*====================================================================
|
||||||
|
|
||||||
filename: DSPCore.h
|
filename: DSPCore.h
|
||||||
project: GCemu
|
project: GCemu
|
||||||
created: 2004-6-18
|
created: 2004-6-18
|
||||||
mail: duddie@walla.com
|
mail: duddie@walla.com
|
||||||
|
|
||||||
Copyright (c) 2005 Duddie & Tratax
|
Copyright (c) 2005 Duddie & Tratax
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License
|
modify it under the terms of the GNU General Public License
|
||||||
as published by the Free Software Foundation; either version 2
|
as published by the Free Software Foundation; either version 2
|
||||||
of the License, or (at your option) any later version.
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
====================================================================*/
|
====================================================================*/
|
||||||
|
|
||||||
#ifndef _DSPCORE_H
|
#ifndef _DSPCORE_H
|
||||||
#define _DSPCORE_H
|
#define _DSPCORE_H
|
||||||
|
|
||||||
#include "DSPBreakpoints.h"
|
#include "DSPBreakpoints.h"
|
||||||
|
|
||||||
#define DSP_IRAM_BYTE_SIZE 0x2000
|
#define DSP_IRAM_BYTE_SIZE 0x2000
|
||||||
#define DSP_IRAM_SIZE 0x1000
|
#define DSP_IRAM_SIZE 0x1000
|
||||||
#define DSP_IRAM_MASK 0x0fff
|
#define DSP_IRAM_MASK 0x0fff
|
||||||
|
|
||||||
#define DSP_IROM_BYTE_SIZE 0x2000
|
#define DSP_IROM_BYTE_SIZE 0x2000
|
||||||
#define DSP_IROM_SIZE 0x1000
|
#define DSP_IROM_SIZE 0x1000
|
||||||
#define DSP_IROM_MASK 0x0fff
|
#define DSP_IROM_MASK 0x0fff
|
||||||
|
|
||||||
#define DSP_DRAM_BYTE_SIZE 0x2000
|
#define DSP_DRAM_BYTE_SIZE 0x2000
|
||||||
#define DSP_DRAM_SIZE 0x1000
|
#define DSP_DRAM_SIZE 0x1000
|
||||||
#define DSP_DRAM_MASK 0x0fff
|
#define DSP_DRAM_MASK 0x0fff
|
||||||
|
|
||||||
#define DSP_COEF_BYTE_SIZE 0x2000
|
#define DSP_COEF_BYTE_SIZE 0x2000
|
||||||
#define DSP_COEF_SIZE 0x1000
|
#define DSP_COEF_SIZE 0x1000
|
||||||
#define DSP_COEF_MASK 0x0fff
|
#define DSP_COEF_MASK 0x0fff
|
||||||
|
|
||||||
#define DSP_RESET_VECTOR 0x8000
|
#define DSP_RESET_VECTOR 0x8000
|
||||||
|
|
||||||
#define DSP_STACK_DEPTH 0x20
|
#define DSP_STACK_DEPTH 0x20
|
||||||
#define DSP_STACK_MASK 0x1f
|
#define DSP_STACK_MASK 0x1f
|
||||||
|
|
||||||
#define DSP_CR_IMEM 2
|
#define DSP_CR_IMEM 2
|
||||||
#define DSP_CR_DMEM 0
|
#define DSP_CR_DMEM 0
|
||||||
#define DSP_CR_TO_CPU 1
|
#define DSP_CR_TO_CPU 1
|
||||||
#define DSP_CR_FROM_CPU 0
|
#define DSP_CR_FROM_CPU 0
|
||||||
|
|
||||||
|
|
||||||
// Register table taken from libasnd
|
// Register table taken from libasnd
|
||||||
#define DSP_REG_AR0 0x00 // address registers
|
#define DSP_REG_AR0 0x00 // address registers
|
||||||
#define DSP_REG_AR1 0x01
|
#define DSP_REG_AR1 0x01
|
||||||
#define DSP_REG_AR2 0x02
|
#define DSP_REG_AR2 0x02
|
||||||
#define DSP_REG_AR3 0x03
|
#define DSP_REG_AR3 0x03
|
||||||
|
|
||||||
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
|
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
|
||||||
#define DSP_REG_IX1 0x05
|
#define DSP_REG_IX1 0x05
|
||||||
#define DSP_REG_IX2 0x06
|
#define DSP_REG_IX2 0x06
|
||||||
#define DSP_REG_IX3 0x07
|
#define DSP_REG_IX3 0x07
|
||||||
|
|
||||||
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
|
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
|
||||||
#define DSP_REG_WR1 0x09
|
#define DSP_REG_WR1 0x09
|
||||||
#define DSP_REG_WR2 0x0a
|
#define DSP_REG_WR2 0x0a
|
||||||
#define DSP_REG_WR3 0x0b
|
#define DSP_REG_WR3 0x0b
|
||||||
|
|
||||||
#define DSP_REG_ST0 0x0c // stacks.
|
#define DSP_REG_ST0 0x0c // stacks.
|
||||||
#define DSP_REG_ST1 0x0d
|
#define DSP_REG_ST1 0x0d
|
||||||
#define DSP_REG_ST2 0x0e
|
#define DSP_REG_ST2 0x0e
|
||||||
#define DSP_REG_ST3 0x0f
|
#define DSP_REG_ST3 0x0f
|
||||||
|
|
||||||
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
|
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
|
||||||
#define DSP_REG_SR 0x13
|
#define DSP_REG_SR 0x13
|
||||||
|
|
||||||
#define DSP_REG_PRODL 0x14 // product.
|
#define DSP_REG_PRODL 0x14 // product.
|
||||||
#define DSP_REG_PRODM 0x15
|
#define DSP_REG_PRODM 0x15
|
||||||
#define DSP_REG_PRODH 0x16
|
#define DSP_REG_PRODH 0x16
|
||||||
#define DSP_REG_PRODM2 0x17
|
#define DSP_REG_PRODM2 0x17
|
||||||
|
|
||||||
#define DSP_REG_AXL0 0x18
|
#define DSP_REG_AXL0 0x18
|
||||||
#define DSP_REG_AXL1 0x19
|
#define DSP_REG_AXL1 0x19
|
||||||
#define DSP_REG_AXH0 0x1a
|
#define DSP_REG_AXH0 0x1a
|
||||||
#define DSP_REG_AXH1 0x1b
|
#define DSP_REG_AXH1 0x1b
|
||||||
|
|
||||||
#define DSP_REG_ACC0 0x1c // accumulator (global)
|
#define DSP_REG_ACC0 0x1c // accumulator (global)
|
||||||
#define DSP_REG_ACC1 0x1d
|
#define DSP_REG_ACC1 0x1d
|
||||||
|
|
||||||
#define DSP_REG_ACL0 0x1c // Low accumulator
|
#define DSP_REG_ACL0 0x1c // Low accumulator
|
||||||
#define DSP_REG_ACL1 0x1d
|
#define DSP_REG_ACL1 0x1d
|
||||||
#define DSP_REG_ACM0 0x1e // Mid accumulator
|
#define DSP_REG_ACM0 0x1e // Mid accumulator
|
||||||
#define DSP_REG_ACM1 0x1f
|
#define DSP_REG_ACM1 0x1f
|
||||||
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
|
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
|
||||||
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
|
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
|
||||||
|
|
||||||
// Hardware registers address
|
// Hardware registers address
|
||||||
|
|
||||||
#define DSP_COEF_A1_0 0xa0
|
#define DSP_COEF_A1_0 0xa0
|
||||||
|
|
||||||
#define DSP_DSMAH 0xce
|
#define DSP_DSMAH 0xce
|
||||||
#define DSP_DSMAL 0xcf
|
#define DSP_DSMAL 0xcf
|
||||||
#define DSP_DSCR 0xc9 // DSP DMA Control Reg
|
#define DSP_DSCR 0xc9 // DSP DMA Control Reg
|
||||||
#define DSP_DSPA 0xcd // DSP DMA Block Length
|
#define DSP_DSPA 0xcd // DSP DMA Block Length
|
||||||
#define DSP_DSBL 0xcb // DSP DMA DMEM Address
|
#define DSP_DSBL 0xcb // DSP DMA DMEM Address
|
||||||
#define DSP_DSMAH 0xce // DSP DMA Mem Address H
|
#define DSP_DSMAH 0xce // DSP DMA Mem Address H
|
||||||
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
|
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
|
||||||
|
|
||||||
#define DSP_FORMAT 0xd1
|
#define DSP_FORMAT 0xd1
|
||||||
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
|
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
|
||||||
#define DSP_ACSAH 0xd4
|
#define DSP_ACSAH 0xd4
|
||||||
#define DSP_ACSAL 0xd5
|
#define DSP_ACSAL 0xd5
|
||||||
#define DSP_ACEAH 0xd6
|
#define DSP_ACEAH 0xd6
|
||||||
#define DSP_ACEAL 0xd7
|
#define DSP_ACEAL 0xd7
|
||||||
#define DSP_ACCAH 0xd8
|
#define DSP_ACCAH 0xd8
|
||||||
#define DSP_ACCAL 0xd9
|
#define DSP_ACCAL 0xd9
|
||||||
#define DSP_PRED_SCALE 0xda
|
#define DSP_PRED_SCALE 0xda
|
||||||
#define DSP_YN1 0xdb
|
#define DSP_YN1 0xdb
|
||||||
#define DSP_YN2 0xdc
|
#define DSP_YN2 0xdc
|
||||||
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
|
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
|
||||||
#define DSP_GAIN 0xde
|
#define DSP_GAIN 0xde
|
||||||
|
|
||||||
#define DSP_DIRQ 0xfb // DSP Irq Rest
|
#define DSP_DIRQ 0xfb // DSP Irq Rest
|
||||||
#define DSP_DMBH 0xfc // DSP Mailbox H
|
#define DSP_DMBH 0xfc // DSP Mailbox H
|
||||||
#define DSP_DMBL 0xfd // DSP Mailbox L
|
#define DSP_DMBL 0xfd // DSP Mailbox L
|
||||||
#define DSP_CMBH 0xfe // CPU Mailbox H
|
#define DSP_CMBH 0xfe // CPU Mailbox H
|
||||||
#define DSP_CMBL 0xff // CPU Mailbox L
|
#define DSP_CMBL 0xff // CPU Mailbox L
|
||||||
|
|
||||||
#define DMA_TO_DSP 0
|
#define DMA_TO_DSP 0
|
||||||
#define DMA_TO_CPU 1
|
#define DMA_TO_CPU 1
|
||||||
|
|
||||||
// Stacks
|
// Stacks
|
||||||
#define DSP_STACK_C 0
|
#define DSP_STACK_C 0
|
||||||
#define DSP_STACK_D 1
|
#define DSP_STACK_D 1
|
||||||
|
|
||||||
// cr (Not g_dsp.r[CR]) bits
|
// cr (Not g_dsp.r[CR]) bits
|
||||||
// See HW/DSP.cpp.
|
// See HW/DSP.cpp.
|
||||||
#define CR_HALT 0x0004
|
#define CR_HALT 0x0004
|
||||||
#define CR_EXTERNAL_INT 0x0002
|
#define CR_EXTERNAL_INT 0x0002
|
||||||
|
|
||||||
|
|
||||||
// SR bits
|
// SR bits
|
||||||
#define SR_CARRY 0x0001
|
#define SR_CARRY 0x0001
|
||||||
#define SR_2 0x0002 // overflow???
|
#define SR_2 0x0002 // overflow???
|
||||||
#define SR_ARITH_ZERO 0x0004
|
#define SR_ARITH_ZERO 0x0004
|
||||||
#define SR_SIGN 0x0008
|
#define SR_SIGN 0x0008
|
||||||
#define SR_10 0x0010 // seem to be set by tst
|
#define SR_10 0x0010 // seem to be set by tst
|
||||||
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
|
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
|
||||||
#define SR_LOGIC_ZERO 0x0040
|
#define SR_LOGIC_ZERO 0x0040
|
||||||
#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
|
#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
|
||||||
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
|
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
|
||||||
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
|
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
|
||||||
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
|
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
|
||||||
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
|
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
|
||||||
|
|
||||||
// This should be the bits affected by CMP. Does not include logic zero.
|
// This should be the bits affected by CMP. Does not include logic zero.
|
||||||
#define SR_CMP_MASK 0x3f
|
#define SR_CMP_MASK 0x3f
|
||||||
|
|
||||||
// exceptions vector
|
// exceptions vector
|
||||||
#define EXP_RESET 0 // 0x0000
|
#define EXP_RESET 0 // 0x0000
|
||||||
#define EXP_STOVF 1 // 0x0002 stack under/over flow
|
#define EXP_STOVF 1 // 0x0002 stack under/over flow
|
||||||
#define EXP_4 2 // 0x0004
|
#define EXP_4 2 // 0x0004
|
||||||
#define EXP_6 3 // 0x0006
|
#define EXP_6 3 // 0x0006
|
||||||
#define EXP_8 4 // 0x0008
|
#define EXP_8 4 // 0x0008
|
||||||
#define EXP_ACCOV 5 // 0x000a accelerator address overflow
|
#define EXP_ACCOV 5 // 0x000a accelerator address overflow
|
||||||
#define EXP_c 6 // 0x000c
|
#define EXP_c 6 // 0x000c
|
||||||
#define EXP_INT 7 // 0x000e external int? (mail?)
|
#define EXP_INT 7 // 0x000e external int? (mail?)
|
||||||
|
|
||||||
struct SDSP
|
struct SDSP
|
||||||
{
|
{
|
||||||
u16 r[32];
|
u16 r[32];
|
||||||
u16 pc;
|
u16 pc;
|
||||||
#if PROFILE
|
#if PROFILE
|
||||||
u16 err_pc;
|
u16 err_pc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This is NOT the same cr as r[DSP_REG_CR].
|
// This is NOT the same cr as r[DSP_REG_CR].
|
||||||
// This register is shared with the main emulation, see DSP.cpp
|
// This register is shared with the main emulation, see DSP.cpp
|
||||||
// The plugin has control over 0x0C07 of this reg.
|
// The plugin has control over 0x0C07 of this reg.
|
||||||
// Bits are defined in a struct in DSP.cpp.
|
// Bits are defined in a struct in DSP.cpp.
|
||||||
u16 cr;
|
u16 cr;
|
||||||
|
|
||||||
u8 reg_stack_ptr[4];
|
u8 reg_stack_ptr[4];
|
||||||
u8 exceptions; // pending exceptions?
|
u8 exceptions; // pending exceptions?
|
||||||
bool exception_in_progress_hack; // is this the same as "exception enabled"?
|
bool exception_in_progress_hack; // is this the same as "exception enabled"?
|
||||||
|
|
||||||
// Let's make stack depth 32 for now. The real DSP has different depths
|
// Let's make stack depth 32 for now. The real DSP has different depths
|
||||||
// for the different stacks, but it would be strange if any ucode relied on stack
|
// for the different stacks, but it would be strange if any ucode relied on stack
|
||||||
// overflows since on the DSP, when the stack overflows, you're screwed.
|
// overflows since on the DSP, when the stack overflows, you're screwed.
|
||||||
u16 reg_stack[4][DSP_STACK_DEPTH];
|
u16 reg_stack[4][DSP_STACK_DEPTH];
|
||||||
|
|
||||||
// For debugging.
|
// For debugging.
|
||||||
u32 iram_crc;
|
u32 iram_crc;
|
||||||
u64 step_counter;
|
u64 step_counter;
|
||||||
|
|
||||||
// When state saving, all of the above can just be memcpy'd into the save state.
|
// When state saving, all of the above can just be memcpy'd into the save state.
|
||||||
// The below needs special handling.
|
// The below needs special handling.
|
||||||
u16 *iram;
|
u16 *iram;
|
||||||
u16 *dram;
|
u16 *dram;
|
||||||
u16 *irom;
|
u16 *irom;
|
||||||
u16 *coef;
|
u16 *coef;
|
||||||
|
|
||||||
// This one doesn't really belong here.
|
// This one doesn't really belong here.
|
||||||
u8 *cpu_ram;
|
u8 *cpu_ram;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SDSP g_dsp;
|
extern SDSP g_dsp;
|
||||||
extern DSPBreakpoints dsp_breakpoints;
|
extern DSPBreakpoints dsp_breakpoints;
|
||||||
|
|
||||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
|
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
|
||||||
|
|
||||||
void DSPCore_Reset();
|
void DSPCore_Reset();
|
||||||
void DSPCore_Shutdown(); // Frees all allocated memory.
|
void DSPCore_Shutdown(); // Frees all allocated memory.
|
||||||
|
|
||||||
void DSPCore_CheckExternalInterrupt();
|
void DSPCore_CheckExternalInterrupt();
|
||||||
void DSPCore_CheckExceptions();
|
void DSPCore_CheckExceptions();
|
||||||
|
|
||||||
// sets a flag in the pending exception register.
|
// sets a flag in the pending exception register.
|
||||||
void DSPCore_SetException(u8 level);
|
void DSPCore_SetException(u8 level);
|
||||||
|
|
||||||
enum DSPCoreState
|
enum DSPCoreState
|
||||||
{
|
{
|
||||||
DSPCORE_RUNNING = 0,
|
DSPCORE_RUNNING = 0,
|
||||||
DSPCORE_STEPPING = 1,
|
DSPCORE_STEPPING = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
int DSPCore_RunCycles(int cycles);
|
int DSPCore_RunCycles(int cycles);
|
||||||
|
|
||||||
// These are meant to be called from the UI thread.
|
// These are meant to be called from the UI thread.
|
||||||
void DSPCore_SetState(DSPCoreState new_state);
|
void DSPCore_SetState(DSPCoreState new_state);
|
||||||
DSPCoreState DSPCore_GetState();
|
DSPCoreState DSPCore_GetState();
|
||||||
|
|
||||||
void DSPCore_Step();
|
void DSPCore_Step();
|
||||||
|
|
||||||
#endif // _DSPCORE_H
|
#endif // _DSPCORE_H
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DSPHOST_H
|
#ifndef _DSPHOST_H
|
||||||
#define _DSPHOST_H
|
#define _DSPHOST_H
|
||||||
|
|
||||||
// The user of the DSPCore library must supply a few functions so that the
|
// The user of the DSPCore library must supply a few functions so that the
|
||||||
// emulation core can access the environment it runs in. If the emulation
|
// emulation core can access the environment it runs in. If the emulation
|
||||||
// core isn't used, for example in an asm/disasm tool, then most of these
|
// core isn't used, for example in an asm/disasm tool, then most of these
|
||||||
// can be stubbed out.
|
// can be stubbed out.
|
||||||
#define DEBUG_EXP 1
|
#define DEBUG_EXP 1
|
||||||
|
|
||||||
u8 DSPHost_ReadHostMemory(u32 addr);
|
u8 DSPHost_ReadHostMemory(u32 addr);
|
||||||
void DSPHost_WriteHostMemory(u8 value, u32 addr);
|
void DSPHost_WriteHostMemory(u8 value, u32 addr);
|
||||||
bool DSPHost_OnThread();
|
bool DSPHost_OnThread();
|
||||||
bool DSPHost_Running();
|
bool DSPHost_Running();
|
||||||
void DSPHost_InterruptRequest();
|
void DSPHost_InterruptRequest();
|
||||||
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
|
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
|
||||||
void DSPHost_UpdateDebugger();
|
void DSPHost_UpdateDebugger();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,140 +1,140 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||||
|
|
||||||
|
|
||||||
// HELPER FUNCTIONS
|
// HELPER FUNCTIONS
|
||||||
|
|
||||||
#include "DSPIntCCUtil.h"
|
#include "DSPIntCCUtil.h"
|
||||||
#include "DSPCore.h"
|
#include "DSPCore.h"
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
|
|
||||||
namespace DSPInterpreter {
|
namespace DSPInterpreter {
|
||||||
|
|
||||||
void Update_SR_Register64(s64 _Value)
|
void Update_SR_Register64(s64 _Value)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||||
|
|
||||||
if (_Value < 0)
|
if (_Value < 0)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_Value == 0)
|
if (_Value == 0)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// weird
|
// weird
|
||||||
if ((_Value >> 62) == 0)
|
if ((_Value >> 62) == 0)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update_SR_Register16(s16 _Value)
|
void Update_SR_Register16(s16 _Value)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||||
|
|
||||||
if (_Value < 0)
|
if (_Value < 0)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_Value == 0)
|
if (_Value == 0)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
// weird
|
// weird
|
||||||
if ((_Value >> 14) == 0)
|
if ((_Value >> 14) == 0)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update_SR_LZ(s64 value) {
|
void Update_SR_LZ(s64 value) {
|
||||||
|
|
||||||
if (value == 0)
|
if (value == 0)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
|
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
|
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMultiplyModifier()
|
int GetMultiplyModifier()
|
||||||
{
|
{
|
||||||
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
|
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isCarry() {
|
inline bool isCarry() {
|
||||||
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
|
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
|
||||||
}
|
}
|
||||||
inline bool isSign() {
|
inline bool isSign() {
|
||||||
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
|
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
|
||||||
}
|
}
|
||||||
inline bool isZero() {
|
inline bool isZero() {
|
||||||
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
|
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//see gdsp_registers.h for flags
|
//see gdsp_registers.h for flags
|
||||||
bool CheckCondition(u8 _Condition)
|
bool CheckCondition(u8 _Condition)
|
||||||
{
|
{
|
||||||
switch (_Condition & 0xf)
|
switch (_Condition & 0xf)
|
||||||
{
|
{
|
||||||
case 0x0: //NS - NOT SIGN
|
case 0x0: //NS - NOT SIGN
|
||||||
return !isSign();
|
return !isSign();
|
||||||
case 0x1: // S - SIGN
|
case 0x1: // S - SIGN
|
||||||
return isSign();
|
return isSign();
|
||||||
case 0x2: // G - GREATER
|
case 0x2: // G - GREATER
|
||||||
return !isSign() && !isZero();
|
return !isSign() && !isZero();
|
||||||
case 0x3: // LE - LESS EQUAL
|
case 0x3: // LE - LESS EQUAL
|
||||||
return isSign() || isZero();
|
return isSign() || isZero();
|
||||||
case 0x4: // NZ - NOT ZERO
|
case 0x4: // NZ - NOT ZERO
|
||||||
return !isZero();
|
return !isZero();
|
||||||
case 0x5: // Z - ZERO
|
case 0x5: // Z - ZERO
|
||||||
return isZero();
|
return isZero();
|
||||||
case 0x6: // L - LESS
|
case 0x6: // L - LESS
|
||||||
// Should be that once we set 0x01
|
// Should be that once we set 0x01
|
||||||
return !isCarry();
|
return !isCarry();
|
||||||
// if (isSign())
|
// if (isSign())
|
||||||
case 0x7: // GE - GREATER EQUAL
|
case 0x7: // GE - GREATER EQUAL
|
||||||
// Should be that once we set 0x01
|
// Should be that once we set 0x01
|
||||||
return isCarry();
|
return isCarry();
|
||||||
// if (! isSign() || isZero())
|
// if (! isSign() || isZero())
|
||||||
case 0xc: // LNZ - LOGIC NOT ZERO
|
case 0xc: // LNZ - LOGIC NOT ZERO
|
||||||
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
|
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
|
||||||
case 0xd: // LZ - LOGIC ZERO
|
case 0xd: // LZ - LOGIC ZERO
|
||||||
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
|
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
|
||||||
|
|
||||||
case 0xf: // Empty - always true.
|
case 0xf: // Empty - always true.
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
|
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||||
|
|
||||||
#ifndef _GDSP_CONDITION_CODES_H
|
#ifndef _GDSP_CONDITION_CODES_H
|
||||||
#define _GDSP_CONDITION_CODES_H
|
#define _GDSP_CONDITION_CODES_H
|
||||||
|
|
||||||
// Anything to do with SR and conditions goes here.
|
// Anything to do with SR and conditions goes here.
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
namespace DSPInterpreter {
|
namespace DSPInterpreter {
|
||||||
|
|
||||||
bool CheckCondition(u8 _Condition);
|
bool CheckCondition(u8 _Condition);
|
||||||
|
|
||||||
int GetMultiplyModifier();
|
int GetMultiplyModifier();
|
||||||
|
|
||||||
void Update_SR_Register16(s16 _Value);
|
void Update_SR_Register16(s16 _Value);
|
||||||
void Update_SR_Register64(s64 _Value);
|
void Update_SR_Register64(s64 _Value);
|
||||||
void Update_SR_LZ(s64 value);
|
void Update_SR_LZ(s64 value);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif // _GDSP_CONDITION_CODES_H
|
#endif // _GDSP_CONDITION_CODES_H
|
||||||
|
|
|
@ -1,171 +1,171 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DSPINTERPRETER_H
|
#ifndef _DSPINTERPRETER_H
|
||||||
#define _DSPINTERPRETER_H
|
#define _DSPINTERPRETER_H
|
||||||
|
|
||||||
#include "DSPTables.h"
|
#include "DSPTables.h"
|
||||||
|
|
||||||
#define DSP_REG_MASK 0x1f
|
#define DSP_REG_MASK 0x1f
|
||||||
|
|
||||||
namespace DSPInterpreter {
|
namespace DSPInterpreter {
|
||||||
|
|
||||||
void Step();
|
void Step();
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
// If these simply return the same number of cycles as was passed into them,
|
// If these simply return the same number of cycles as was passed into them,
|
||||||
// chances are that the DSP is halted.
|
// chances are that the DSP is halted.
|
||||||
// The difference between them is that the debug one obeys breakpoints.
|
// The difference between them is that the debug one obeys breakpoints.
|
||||||
int RunCycles(int cycles);
|
int RunCycles(int cycles);
|
||||||
int RunCyclesDebug(int cycles);
|
int RunCyclesDebug(int cycles);
|
||||||
|
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
void WriteCR(u16 val);
|
void WriteCR(u16 val);
|
||||||
u16 ReadCR();
|
u16 ReadCR();
|
||||||
|
|
||||||
|
|
||||||
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
|
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
|
||||||
|
|
||||||
// All the opcode functions.
|
// All the opcode functions.
|
||||||
void unknown(const UDSPInstruction& opc);
|
void unknown(const UDSPInstruction& opc);
|
||||||
void call(const UDSPInstruction& opc);
|
void call(const UDSPInstruction& opc);
|
||||||
void callr(const UDSPInstruction& opc);
|
void callr(const UDSPInstruction& opc);
|
||||||
void ifcc(const UDSPInstruction& opc);
|
void ifcc(const UDSPInstruction& opc);
|
||||||
void jcc(const UDSPInstruction& opc);
|
void jcc(const UDSPInstruction& opc);
|
||||||
void jmprcc(const UDSPInstruction& opc);
|
void jmprcc(const UDSPInstruction& opc);
|
||||||
void ret(const UDSPInstruction& opc);
|
void ret(const UDSPInstruction& opc);
|
||||||
void halt(const UDSPInstruction& opc);
|
void halt(const UDSPInstruction& opc);
|
||||||
void loop(const UDSPInstruction& opc);
|
void loop(const UDSPInstruction& opc);
|
||||||
void loopi(const UDSPInstruction& opc);
|
void loopi(const UDSPInstruction& opc);
|
||||||
void bloop(const UDSPInstruction& opc);
|
void bloop(const UDSPInstruction& opc);
|
||||||
void bloopi(const UDSPInstruction& opc);
|
void bloopi(const UDSPInstruction& opc);
|
||||||
void mrr(const UDSPInstruction& opc);
|
void mrr(const UDSPInstruction& opc);
|
||||||
void lrr(const UDSPInstruction& opc);
|
void lrr(const UDSPInstruction& opc);
|
||||||
void lrrd(const UDSPInstruction& opc);
|
void lrrd(const UDSPInstruction& opc);
|
||||||
void lrri(const UDSPInstruction& opc);
|
void lrri(const UDSPInstruction& opc);
|
||||||
void lrrn(const UDSPInstruction& opc);
|
void lrrn(const UDSPInstruction& opc);
|
||||||
void srr(const UDSPInstruction& opc);
|
void srr(const UDSPInstruction& opc);
|
||||||
void srrd(const UDSPInstruction& opc);
|
void srrd(const UDSPInstruction& opc);
|
||||||
void srri(const UDSPInstruction& opc);
|
void srri(const UDSPInstruction& opc);
|
||||||
void srrn(const UDSPInstruction& opc);
|
void srrn(const UDSPInstruction& opc);
|
||||||
void lri(const UDSPInstruction& opc);
|
void lri(const UDSPInstruction& opc);
|
||||||
void lris(const UDSPInstruction& opc);
|
void lris(const UDSPInstruction& opc);
|
||||||
void lr(const UDSPInstruction& opc);
|
void lr(const UDSPInstruction& opc);
|
||||||
void sr(const UDSPInstruction& opc);
|
void sr(const UDSPInstruction& opc);
|
||||||
void si(const UDSPInstruction& opc);
|
void si(const UDSPInstruction& opc);
|
||||||
void tstaxh(const UDSPInstruction& opc);
|
void tstaxh(const UDSPInstruction& opc);
|
||||||
void clr(const UDSPInstruction& opc);
|
void clr(const UDSPInstruction& opc);
|
||||||
void clrl(const UDSPInstruction& opc);
|
void clrl(const UDSPInstruction& opc);
|
||||||
void clrp(const UDSPInstruction& opc);
|
void clrp(const UDSPInstruction& opc);
|
||||||
void mulc(const UDSPInstruction& opc);
|
void mulc(const UDSPInstruction& opc);
|
||||||
void cmpar(const UDSPInstruction& opc);
|
void cmpar(const UDSPInstruction& opc);
|
||||||
void cmp(const UDSPInstruction& opc);
|
void cmp(const UDSPInstruction& opc);
|
||||||
void tst(const UDSPInstruction& opc);
|
void tst(const UDSPInstruction& opc);
|
||||||
void addaxl(const UDSPInstruction& opc);
|
void addaxl(const UDSPInstruction& opc);
|
||||||
void addarn(const UDSPInstruction& opc);
|
void addarn(const UDSPInstruction& opc);
|
||||||
void mulcac(const UDSPInstruction& opc);
|
void mulcac(const UDSPInstruction& opc);
|
||||||
void movr(const UDSPInstruction& opc);
|
void movr(const UDSPInstruction& opc);
|
||||||
void movax(const UDSPInstruction& opc);
|
void movax(const UDSPInstruction& opc);
|
||||||
void xorr(const UDSPInstruction& opc);
|
void xorr(const UDSPInstruction& opc);
|
||||||
void andr(const UDSPInstruction& opc);
|
void andr(const UDSPInstruction& opc);
|
||||||
void andc(const UDSPInstruction& opc);
|
void andc(const UDSPInstruction& opc);
|
||||||
void orr(const UDSPInstruction& opc);
|
void orr(const UDSPInstruction& opc);
|
||||||
void orc(const UDSPInstruction& opc);
|
void orc(const UDSPInstruction& opc);
|
||||||
void orf(const UDSPInstruction& opc);
|
void orf(const UDSPInstruction& opc);
|
||||||
void add(const UDSPInstruction& opc);
|
void add(const UDSPInstruction& opc);
|
||||||
void addp(const UDSPInstruction& opc);
|
void addp(const UDSPInstruction& opc);
|
||||||
void cmpis(const UDSPInstruction& opc);
|
void cmpis(const UDSPInstruction& opc);
|
||||||
void addpaxz(const UDSPInstruction& opc);
|
void addpaxz(const UDSPInstruction& opc);
|
||||||
void movpz(const UDSPInstruction& opc);
|
void movpz(const UDSPInstruction& opc);
|
||||||
void decm(const UDSPInstruction& opc);
|
void decm(const UDSPInstruction& opc);
|
||||||
void dec(const UDSPInstruction& opc);
|
void dec(const UDSPInstruction& opc);
|
||||||
void inc(const UDSPInstruction& opc);
|
void inc(const UDSPInstruction& opc);
|
||||||
void incm(const UDSPInstruction& opc);
|
void incm(const UDSPInstruction& opc);
|
||||||
void neg(const UDSPInstruction& opc);
|
void neg(const UDSPInstruction& opc);
|
||||||
void addax(const UDSPInstruction& opc);
|
void addax(const UDSPInstruction& opc);
|
||||||
void addr(const UDSPInstruction& opc);
|
void addr(const UDSPInstruction& opc);
|
||||||
void subr(const UDSPInstruction& opc);
|
void subr(const UDSPInstruction& opc);
|
||||||
void subp(const UDSPInstruction& opc);
|
void subp(const UDSPInstruction& opc);
|
||||||
void subax(const UDSPInstruction& opc);
|
void subax(const UDSPInstruction& opc);
|
||||||
void addis(const UDSPInstruction& opc);
|
void addis(const UDSPInstruction& opc);
|
||||||
void addi(const UDSPInstruction& opc);
|
void addi(const UDSPInstruction& opc);
|
||||||
void lsl16(const UDSPInstruction& opc);
|
void lsl16(const UDSPInstruction& opc);
|
||||||
void madd(const UDSPInstruction& opc);
|
void madd(const UDSPInstruction& opc);
|
||||||
void msub(const UDSPInstruction& opc);
|
void msub(const UDSPInstruction& opc);
|
||||||
void lsr16(const UDSPInstruction& opc);
|
void lsr16(const UDSPInstruction& opc);
|
||||||
void asr16(const UDSPInstruction& opc);
|
void asr16(const UDSPInstruction& opc);
|
||||||
void lsl(const UDSPInstruction& opc);
|
void lsl(const UDSPInstruction& opc);
|
||||||
void lsr(const UDSPInstruction& opc);
|
void lsr(const UDSPInstruction& opc);
|
||||||
void asl(const UDSPInstruction& opc);
|
void asl(const UDSPInstruction& opc);
|
||||||
void asr(const UDSPInstruction& opc);
|
void asr(const UDSPInstruction& opc);
|
||||||
void lsrn(const UDSPInstruction& opc);
|
void lsrn(const UDSPInstruction& opc);
|
||||||
void asrn(const UDSPInstruction& opc);
|
void asrn(const UDSPInstruction& opc);
|
||||||
void dar(const UDSPInstruction& opc);
|
void dar(const UDSPInstruction& opc);
|
||||||
void iar(const UDSPInstruction& opc);
|
void iar(const UDSPInstruction& opc);
|
||||||
void sbclr(const UDSPInstruction& opc);
|
void sbclr(const UDSPInstruction& opc);
|
||||||
void sbset(const UDSPInstruction& opc);
|
void sbset(const UDSPInstruction& opc);
|
||||||
void mov(const UDSPInstruction& opc);
|
void mov(const UDSPInstruction& opc);
|
||||||
void movp(const UDSPInstruction& opc);
|
void movp(const UDSPInstruction& opc);
|
||||||
void mul(const UDSPInstruction& opc);
|
void mul(const UDSPInstruction& opc);
|
||||||
void mulac(const UDSPInstruction& opc);
|
void mulac(const UDSPInstruction& opc);
|
||||||
void mulmv(const UDSPInstruction& opc);
|
void mulmv(const UDSPInstruction& opc);
|
||||||
void mulmvz(const UDSPInstruction& opc);
|
void mulmvz(const UDSPInstruction& opc);
|
||||||
void mulx(const UDSPInstruction& opc);
|
void mulx(const UDSPInstruction& opc);
|
||||||
void mulxac(const UDSPInstruction& opc);
|
void mulxac(const UDSPInstruction& opc);
|
||||||
void mulxmv(const UDSPInstruction& opc);
|
void mulxmv(const UDSPInstruction& opc);
|
||||||
void mulxmvz(const UDSPInstruction& opc);
|
void mulxmvz(const UDSPInstruction& opc);
|
||||||
void mulcmvz(const UDSPInstruction& opc);
|
void mulcmvz(const UDSPInstruction& opc);
|
||||||
void mulcmv(const UDSPInstruction& opc);
|
void mulcmv(const UDSPInstruction& opc);
|
||||||
void movnp(const UDSPInstruction& opc);
|
void movnp(const UDSPInstruction& opc);
|
||||||
void sub(const UDSPInstruction& opc);
|
void sub(const UDSPInstruction& opc);
|
||||||
void maddx(const UDSPInstruction& opc);
|
void maddx(const UDSPInstruction& opc);
|
||||||
void msubx(const UDSPInstruction& opc);
|
void msubx(const UDSPInstruction& opc);
|
||||||
void maddc(const UDSPInstruction& opc);
|
void maddc(const UDSPInstruction& opc);
|
||||||
void msubc(const UDSPInstruction& opc);
|
void msubc(const UDSPInstruction& opc);
|
||||||
void srs(const UDSPInstruction& opc);
|
void srs(const UDSPInstruction& opc);
|
||||||
void lrs(const UDSPInstruction& opc);
|
void lrs(const UDSPInstruction& opc);
|
||||||
void nx(const UDSPInstruction& opc);
|
void nx(const UDSPInstruction& opc);
|
||||||
void cmpi(const UDSPInstruction& opc);
|
void cmpi(const UDSPInstruction& opc);
|
||||||
void rti(const UDSPInstruction& opc);
|
void rti(const UDSPInstruction& opc);
|
||||||
void ilrr(const UDSPInstruction& opc);
|
void ilrr(const UDSPInstruction& opc);
|
||||||
void ilrrd(const UDSPInstruction& opc);
|
void ilrrd(const UDSPInstruction& opc);
|
||||||
void ilrri(const UDSPInstruction& opc);
|
void ilrri(const UDSPInstruction& opc);
|
||||||
void ilrrn(const UDSPInstruction& opc);
|
void ilrrn(const UDSPInstruction& opc);
|
||||||
void andcf(const UDSPInstruction& opc);
|
void andcf(const UDSPInstruction& opc);
|
||||||
void andf(const UDSPInstruction& opc);
|
void andf(const UDSPInstruction& opc);
|
||||||
void xori(const UDSPInstruction& opc);
|
void xori(const UDSPInstruction& opc);
|
||||||
void andi(const UDSPInstruction& opc);
|
void andi(const UDSPInstruction& opc);
|
||||||
void ori(const UDSPInstruction& opc);
|
void ori(const UDSPInstruction& opc);
|
||||||
|
|
||||||
// FIXME inside
|
// FIXME inside
|
||||||
void srbith(const UDSPInstruction& opc);
|
void srbith(const UDSPInstruction& opc);
|
||||||
|
|
||||||
// END OF FIXMEs
|
// END OF FIXMEs
|
||||||
|
|
||||||
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
|
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
|
||||||
void tstaxl(const UDSPInstruction& opc);
|
void tstaxl(const UDSPInstruction& opc);
|
||||||
// The mysterious a100
|
// The mysterious a100
|
||||||
|
|
||||||
// END OF UNIMPLEMENTED
|
// END OF UNIMPLEMENTED
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
inline void tsta(int reg);
|
inline void tsta(int reg);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif // _DSPINTERPRETER_H
|
#endif // _DSPINTERPRETER_H
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "DSPJit.h"
|
#include "DSPJit.h"
|
||||||
|
|
||||||
namespace DSPJit {
|
namespace DSPJit {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,28 +1,28 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DSPJIT_H
|
#ifndef _DSPJIT_H
|
||||||
#define _DSPJIT_H
|
#define _DSPJIT_H
|
||||||
|
|
||||||
namespace DSPJit {
|
namespace DSPJit {
|
||||||
|
|
||||||
// TODO(XK): Fill
|
// TODO(XK): Fill
|
||||||
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif // _DSPJIT_H
|
#endif // _DSPJIT_H
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,168 +1,168 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
|
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
|
||||||
|
|
||||||
#ifndef _DSPTABLES_H
|
#ifndef _DSPTABLES_H
|
||||||
#define _DSPTABLES_H
|
#define _DSPTABLES_H
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
// The non-ADDR ones that end with _D are the opposite one - if the bit specify
|
// The non-ADDR ones that end with _D are the opposite one - if the bit specify
|
||||||
// ACC0, then ACC_D will be ACC1.
|
// ACC0, then ACC_D will be ACC1.
|
||||||
|
|
||||||
// The values of these are very important.
|
// The values of these are very important.
|
||||||
// For the reg ones, the value >> 8 is the base register.
|
// For the reg ones, the value >> 8 is the base register.
|
||||||
// & 0x80 means it's a "D".
|
// & 0x80 means it's a "D".
|
||||||
|
|
||||||
enum partype_t
|
enum partype_t
|
||||||
{
|
{
|
||||||
P_NONE = 0x0000,
|
P_NONE = 0x0000,
|
||||||
P_VAL = 0x0001,
|
P_VAL = 0x0001,
|
||||||
P_IMM = 0x0002,
|
P_IMM = 0x0002,
|
||||||
P_MEM = 0x0003,
|
P_MEM = 0x0003,
|
||||||
P_STR = 0x0004,
|
P_STR = 0x0004,
|
||||||
P_ADDR_I = 0x0005,
|
P_ADDR_I = 0x0005,
|
||||||
P_ADDR_D = 0x0006,
|
P_ADDR_D = 0x0006,
|
||||||
P_REG = 0x8000,
|
P_REG = 0x8000,
|
||||||
P_REG04 = P_REG | 0x0400, // IX
|
P_REG04 = P_REG | 0x0400, // IX
|
||||||
P_REG08 = P_REG | 0x0800,
|
P_REG08 = P_REG | 0x0800,
|
||||||
P_REG18 = P_REG | 0x1800,
|
P_REG18 = P_REG | 0x1800,
|
||||||
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
|
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
|
||||||
P_REG19 = P_REG | 0x1900,
|
P_REG19 = P_REG | 0x1900,
|
||||||
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
|
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
|
||||||
P_REG1A = P_REG | 0x1a80,
|
P_REG1A = P_REG | 0x1a80,
|
||||||
P_REG1C = P_REG | 0x1c00,
|
P_REG1C = P_REG | 0x1c00,
|
||||||
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
|
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
|
||||||
P_ACC_D = P_REG | 0x1c80,
|
P_ACC_D = P_REG | 0x1c80,
|
||||||
P_ACCL = P_REG | 0x1c00, // used for low part of accum
|
P_ACCL = P_REG | 0x1c00, // used for low part of accum
|
||||||
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
|
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
|
||||||
// The following are not in gcdsptool
|
// The following are not in gcdsptool
|
||||||
P_ACCM_D = P_REG | 0x1e80,
|
P_ACCM_D = P_REG | 0x1e80,
|
||||||
P_ACC = P_REG | 0x2000, // used for full accum.
|
P_ACC = P_REG | 0x2000, // used for full accum.
|
||||||
P_AX = P_REG | 0x2200,
|
P_AX = P_REG | 0x2200,
|
||||||
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
|
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
|
||||||
P_REF = P_REG | 0x4000,
|
P_REF = P_REG | 0x4000,
|
||||||
P_PRG = P_REF | P_REG,
|
P_PRG = P_REF | P_REG,
|
||||||
|
|
||||||
// The following seem like junk:
|
// The following seem like junk:
|
||||||
// P_REG10 = P_REG | 0x1000,
|
// P_REG10 = P_REG | 0x1000,
|
||||||
// P_AX_D = P_REG | 0x2280,
|
// P_AX_D = P_REG | 0x2280,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define P_EXT 0x80
|
#define P_EXT 0x80
|
||||||
|
|
||||||
#define OPTABLE_SIZE 65536
|
#define OPTABLE_SIZE 65536
|
||||||
|
|
||||||
union UDSPInstruction
|
union UDSPInstruction
|
||||||
{
|
{
|
||||||
u16 hex;
|
u16 hex;
|
||||||
|
|
||||||
UDSPInstruction(u16 _hex) { hex = _hex; }
|
UDSPInstruction(u16 _hex) { hex = _hex; }
|
||||||
UDSPInstruction() { hex = 0; }
|
UDSPInstruction() { hex = 0; }
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
signed shift : 6;
|
signed shift : 6;
|
||||||
unsigned negating : 1;
|
unsigned negating : 1;
|
||||||
unsigned arithmetic : 1;
|
unsigned arithmetic : 1;
|
||||||
unsigned areg : 1;
|
unsigned areg : 1;
|
||||||
unsigned op : 7;
|
unsigned op : 7;
|
||||||
};
|
};
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned ushift : 6;
|
unsigned ushift : 6;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Figure out more instruction structures (add structs here)
|
// TODO: Figure out more instruction structures (add structs here)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*dspInstFunc)(const UDSPInstruction&);
|
typedef void (*dspInstFunc)(const UDSPInstruction&);
|
||||||
|
|
||||||
struct param2_t
|
struct param2_t
|
||||||
{
|
{
|
||||||
partype_t type;
|
partype_t type;
|
||||||
u8 size;
|
u8 size;
|
||||||
u8 loc;
|
u8 loc;
|
||||||
s8 lshift;
|
s8 lshift;
|
||||||
u16 mask;
|
u16 mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
u16 opcode;
|
u16 opcode;
|
||||||
u16 opcode_mask;
|
u16 opcode_mask;
|
||||||
|
|
||||||
dspInstFunc interpFunc;
|
dspInstFunc interpFunc;
|
||||||
dspInstFunc jitFunc;
|
dspInstFunc jitFunc;
|
||||||
|
|
||||||
u8 size;
|
u8 size;
|
||||||
u8 param_count;
|
u8 param_count;
|
||||||
param2_t params[8];
|
param2_t params[8];
|
||||||
dspInstFunc prologue;
|
dspInstFunc prologue;
|
||||||
dspInstFunc epilogue;
|
dspInstFunc epilogue;
|
||||||
} DSPOPCTemplate;
|
} DSPOPCTemplate;
|
||||||
|
|
||||||
typedef DSPOPCTemplate opc_t;
|
typedef DSPOPCTemplate opc_t;
|
||||||
|
|
||||||
// Opcodes
|
// Opcodes
|
||||||
extern const DSPOPCTemplate opcodes[];
|
extern const DSPOPCTemplate opcodes[];
|
||||||
extern const int opcodes_size;
|
extern const int opcodes_size;
|
||||||
extern const DSPOPCTemplate opcodes_ext[];
|
extern const DSPOPCTemplate opcodes_ext[];
|
||||||
extern const int opcodes_ext_size;
|
extern const int opcodes_ext_size;
|
||||||
extern u8 opSize[OPTABLE_SIZE];
|
extern u8 opSize[OPTABLE_SIZE];
|
||||||
extern const DSPOPCTemplate cw;
|
extern const DSPOPCTemplate cw;
|
||||||
|
|
||||||
extern dspInstFunc opTable[];
|
extern dspInstFunc opTable[];
|
||||||
extern dspInstFunc prologueTable[OPTABLE_SIZE];
|
extern dspInstFunc prologueTable[OPTABLE_SIZE];
|
||||||
extern dspInstFunc epilogueTable[OPTABLE_SIZE];
|
extern dspInstFunc epilogueTable[OPTABLE_SIZE];
|
||||||
|
|
||||||
// Predefined labels
|
// Predefined labels
|
||||||
struct pdlabel_t
|
struct pdlabel_t
|
||||||
{
|
{
|
||||||
u16 addr;
|
u16 addr;
|
||||||
const char* name;
|
const char* name;
|
||||||
const char* description;
|
const char* description;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const pdlabel_t regnames[];
|
extern const pdlabel_t regnames[];
|
||||||
extern const pdlabel_t pdlabels[];
|
extern const pdlabel_t pdlabels[];
|
||||||
extern const u32 pdlabels_size;
|
extern const u32 pdlabels_size;
|
||||||
|
|
||||||
const char *pdname(u16 val);
|
const char *pdname(u16 val);
|
||||||
const char *pdregname(int val);
|
const char *pdregname(int val);
|
||||||
const char *pdregnamelong(int val);
|
const char *pdregnamelong(int val);
|
||||||
|
|
||||||
void InitInstructionTable();
|
void InitInstructionTable();
|
||||||
|
|
||||||
inline void ExecuteInstruction(const UDSPInstruction& inst)
|
inline void ExecuteInstruction(const UDSPInstruction& inst)
|
||||||
{
|
{
|
||||||
// TODO: Move the prologuetable calls into the relevant instructions themselves.
|
// TODO: Move the prologuetable calls into the relevant instructions themselves.
|
||||||
// Better not do things like this until things work correctly though.
|
// Better not do things like this until things work correctly though.
|
||||||
if (prologueTable[inst.hex])
|
if (prologueTable[inst.hex])
|
||||||
prologueTable[inst.hex](inst);
|
prologueTable[inst.hex](inst);
|
||||||
opTable[inst.hex](inst);
|
opTable[inst.hex](inst);
|
||||||
if (epilogueTable[inst.hex])
|
if (epilogueTable[inst.hex])
|
||||||
epilogueTable[inst.hex](inst);
|
epilogueTable[inst.hex](inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This one's pretty slow, try to use it only at init or seldomly.
|
// This one's pretty slow, try to use it only at init or seldomly.
|
||||||
// returns NULL if no matching instruction.
|
// returns NULL if no matching instruction.
|
||||||
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
|
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
|
||||||
|
|
||||||
#endif // _DSPTABLES_H
|
#endif // _DSPTABLES_H
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,249 +1,249 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||||
|
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
#include "DSPCore.h"
|
#include "DSPCore.h"
|
||||||
#include "DSPMemoryMap.h"
|
#include "DSPMemoryMap.h"
|
||||||
#include "DSPStacks.h"
|
#include "DSPStacks.h"
|
||||||
|
|
||||||
#include "DSPIntCCUtil.h"
|
#include "DSPIntCCUtil.h"
|
||||||
#include "DSPIntUtil.h"
|
#include "DSPIntUtil.h"
|
||||||
|
|
||||||
namespace DSPInterpreter {
|
namespace DSPInterpreter {
|
||||||
|
|
||||||
// Generic call implementation
|
// Generic call implementation
|
||||||
// CALLcc addressA
|
// CALLcc addressA
|
||||||
// 0000 0010 1011 cccc
|
// 0000 0010 1011 cccc
|
||||||
// aaaa aaaa aaaa aaaa
|
// aaaa aaaa aaaa aaaa
|
||||||
// Call function if condition cc has been met. Push program counter of
|
// Call function if condition cc has been met. Push program counter of
|
||||||
// instruction following "call" to $st0. Set program counter to address
|
// instruction following "call" to $st0. Set program counter to address
|
||||||
// represented by value that follows this "call" instruction.
|
// represented by value that follows this "call" instruction.
|
||||||
void call(const UDSPInstruction& opc)
|
void call(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
// must be outside the if.
|
// must be outside the if.
|
||||||
u16 dest = dsp_fetch_code();
|
u16 dest = dsp_fetch_code();
|
||||||
if (CheckCondition(opc.hex & 0xf))
|
if (CheckCondition(opc.hex & 0xf))
|
||||||
{
|
{
|
||||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||||
g_dsp.pc = dest;
|
g_dsp.pc = dest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic callr implementation
|
// Generic callr implementation
|
||||||
// CALLRcc $R
|
// CALLRcc $R
|
||||||
// 0001 0111 rrr1 cccc
|
// 0001 0111 rrr1 cccc
|
||||||
// Call function if condition cc has been met. Push program counter of
|
// Call function if condition cc has been met. Push program counter of
|
||||||
// instruction following "call" to call stack $st0. Set program counter to
|
// instruction following "call" to call stack $st0. Set program counter to
|
||||||
// register $R.
|
// register $R.
|
||||||
void callr(const UDSPInstruction& opc)
|
void callr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
if (CheckCondition(opc.hex & 0xf))
|
if (CheckCondition(opc.hex & 0xf))
|
||||||
{
|
{
|
||||||
u8 reg = (opc.hex >> 5) & 0x7;
|
u8 reg = (opc.hex >> 5) & 0x7;
|
||||||
u16 addr = dsp_op_read_reg(reg);
|
u16 addr = dsp_op_read_reg(reg);
|
||||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||||
g_dsp.pc = addr;
|
g_dsp.pc = addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic if implementation
|
// Generic if implementation
|
||||||
// IFcc
|
// IFcc
|
||||||
// 0000 0010 0111 cccc
|
// 0000 0010 0111 cccc
|
||||||
// Execute following opcode if the condition has been met.
|
// Execute following opcode if the condition has been met.
|
||||||
void ifcc(const UDSPInstruction& opc)
|
void ifcc(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
if (!CheckCondition(opc.hex & 0xf))
|
if (!CheckCondition(opc.hex & 0xf))
|
||||||
{
|
{
|
||||||
// skip the next opcode - we have to lookup its size.
|
// skip the next opcode - we have to lookup its size.
|
||||||
g_dsp.pc += opSize[dsp_peek_code()];
|
g_dsp.pc += opSize[dsp_peek_code()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic jmp implementation
|
// Generic jmp implementation
|
||||||
// Jcc addressA
|
// Jcc addressA
|
||||||
// 0000 0010 1001 cccc
|
// 0000 0010 1001 cccc
|
||||||
// aaaa aaaa aaaa aaaa
|
// aaaa aaaa aaaa aaaa
|
||||||
// Jump to addressA if condition cc has been met. Set program counter to
|
// Jump to addressA if condition cc has been met. Set program counter to
|
||||||
// address represented by value that follows this "jmp" instruction.
|
// address represented by value that follows this "jmp" instruction.
|
||||||
void jcc(const UDSPInstruction& opc)
|
void jcc(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 dest = dsp_fetch_code();
|
u16 dest = dsp_fetch_code();
|
||||||
if (CheckCondition(opc.hex & 0xf))
|
if (CheckCondition(opc.hex & 0xf))
|
||||||
{
|
{
|
||||||
g_dsp.pc = dest;
|
g_dsp.pc = dest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic jmpr implementation
|
// Generic jmpr implementation
|
||||||
// JMPcc $R
|
// JMPcc $R
|
||||||
// 0001 0111 rrr0 cccc
|
// 0001 0111 rrr0 cccc
|
||||||
// Jump to address; set program counter to a value from register $R.
|
// Jump to address; set program counter to a value from register $R.
|
||||||
void jmprcc(const UDSPInstruction& opc)
|
void jmprcc(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
if (CheckCondition(opc.hex & 0xf))
|
if (CheckCondition(opc.hex & 0xf))
|
||||||
{
|
{
|
||||||
u8 reg = (opc.hex >> 5) & 0x7;
|
u8 reg = (opc.hex >> 5) & 0x7;
|
||||||
g_dsp.pc = dsp_op_read_reg(reg);
|
g_dsp.pc = dsp_op_read_reg(reg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic ret implementation
|
// Generic ret implementation
|
||||||
// RETcc
|
// RETcc
|
||||||
// 0000 0010 1101 cccc
|
// 0000 0010 1101 cccc
|
||||||
// Return from subroutine if condition cc has been met. Pops stored PC
|
// Return from subroutine if condition cc has been met. Pops stored PC
|
||||||
// from call stack $st0 and sets $pc to this location.
|
// from call stack $st0 and sets $pc to this location.
|
||||||
void ret(const UDSPInstruction& opc)
|
void ret(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
if (CheckCondition(opc.hex & 0xf))
|
if (CheckCondition(opc.hex & 0xf))
|
||||||
{
|
{
|
||||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RTI
|
// RTI
|
||||||
// 0000 0010 1111 1111
|
// 0000 0010 1111 1111
|
||||||
// Return from exception. Pops stored status register $sr from data stack
|
// Return from exception. Pops stored status register $sr from data stack
|
||||||
// $st1 and program counter PC from call stack $st0 and sets $pc to this
|
// $st1 and program counter PC from call stack $st0 and sets $pc to this
|
||||||
// location.
|
// location.
|
||||||
void rti(const UDSPInstruction& opc)
|
void rti(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
||||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||||
|
|
||||||
g_dsp.exception_in_progress_hack = false;
|
g_dsp.exception_in_progress_hack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HALT
|
// HALT
|
||||||
// 0000 0000 0020 0001
|
// 0000 0000 0020 0001
|
||||||
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
|
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
|
||||||
void halt(const UDSPInstruction& opc)
|
void halt(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
g_dsp.cr |= 0x4;
|
g_dsp.cr |= 0x4;
|
||||||
g_dsp.pc--;
|
g_dsp.pc--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// LOOP handling: Loop stack is used to control execution of repeated blocks of
|
// LOOP handling: Loop stack is used to control execution of repeated blocks of
|
||||||
// instructions. Whenever there is value on stack $st2 and current PC is equal
|
// instructions. Whenever there is value on stack $st2 and current PC is equal
|
||||||
// value at $st2, then value at stack $st3 is decremented. If value is not zero
|
// value at $st2, then value at stack $st3 is decremented. If value is not zero
|
||||||
// then PC is modified with calue from call stack $st0. Otherwise values from
|
// then PC is modified with calue from call stack $st0. Otherwise values from
|
||||||
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
|
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
|
||||||
// continues at next opcode.
|
// continues at next opcode.
|
||||||
|
|
||||||
|
|
||||||
// LOOP $R
|
// LOOP $R
|
||||||
// 0000 0000 010r rrrr
|
// 0000 0000 010r rrrr
|
||||||
// Repeatedly execute following opcode until counter specified by value
|
// Repeatedly execute following opcode until counter specified by value
|
||||||
// from register $R reaches zero. Each execution decrement counter. Register
|
// from register $R reaches zero. Each execution decrement counter. Register
|
||||||
// $R remains unchanged. If register $R is set to zero at the beginning of loop
|
// $R remains unchanged. If register $R is set to zero at the beginning of loop
|
||||||
// then looped instruction will not get executed.
|
// then looped instruction will not get executed.
|
||||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||||
// The looping hardware takes care of the rest.
|
// The looping hardware takes care of the rest.
|
||||||
void loop(const UDSPInstruction& opc)
|
void loop(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 reg = opc.hex & 0x1f;
|
u16 reg = opc.hex & 0x1f;
|
||||||
u16 cnt = g_dsp.r[reg];
|
u16 cnt = g_dsp.r[reg];
|
||||||
u16 loop_pc = g_dsp.pc;
|
u16 loop_pc = g_dsp.pc;
|
||||||
|
|
||||||
if (cnt)
|
if (cnt)
|
||||||
{
|
{
|
||||||
dsp_reg_store_stack(0, g_dsp.pc);
|
dsp_reg_store_stack(0, g_dsp.pc);
|
||||||
dsp_reg_store_stack(2, loop_pc);
|
dsp_reg_store_stack(2, loop_pc);
|
||||||
dsp_reg_store_stack(3, cnt);
|
dsp_reg_store_stack(3, cnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LOOPI #I
|
// LOOPI #I
|
||||||
// 0001 0000 iiii iiii
|
// 0001 0000 iiii iiii
|
||||||
// Repeatedly execute following opcode until counter specified by
|
// Repeatedly execute following opcode until counter specified by
|
||||||
// immediate value I reaches zero. Each execution decrement counter. If
|
// immediate value I reaches zero. Each execution decrement counter. If
|
||||||
// immediate value I is set to zero at the beginning of loop then looped
|
// immediate value I is set to zero at the beginning of loop then looped
|
||||||
// instruction will not get executed.
|
// instruction will not get executed.
|
||||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||||
// The looping hardware takes care of the rest.
|
// The looping hardware takes care of the rest.
|
||||||
void loopi(const UDSPInstruction& opc)
|
void loopi(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 cnt = opc.hex & 0xff;
|
u16 cnt = opc.hex & 0xff;
|
||||||
u16 loop_pc = g_dsp.pc;
|
u16 loop_pc = g_dsp.pc;
|
||||||
|
|
||||||
if (cnt)
|
if (cnt)
|
||||||
{
|
{
|
||||||
dsp_reg_store_stack(0, g_dsp.pc);
|
dsp_reg_store_stack(0, g_dsp.pc);
|
||||||
dsp_reg_store_stack(2, loop_pc);
|
dsp_reg_store_stack(2, loop_pc);
|
||||||
dsp_reg_store_stack(3, cnt);
|
dsp_reg_store_stack(3, cnt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// BLOOP $R, addrA
|
// BLOOP $R, addrA
|
||||||
// 0000 0000 011r rrrr
|
// 0000 0000 011r rrrr
|
||||||
// aaaa aaaa aaaa aaaa
|
// aaaa aaaa aaaa aaaa
|
||||||
// Repeatedly execute block of code starting at following opcode until
|
// Repeatedly execute block of code starting at following opcode until
|
||||||
// counter specified by value from register $R reaches zero. Block ends at
|
// counter specified by value from register $R reaches zero. Block ends at
|
||||||
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
|
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
|
||||||
// included in loop. Counter is pushed on loop stack $st3, end of block address
|
// included in loop. Counter is pushed on loop stack $st3, end of block address
|
||||||
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
|
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
|
||||||
// Up to 4 nested loops is allowed.
|
// Up to 4 nested loops is allowed.
|
||||||
void bloop(const UDSPInstruction& opc)
|
void bloop(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 reg = opc.hex & 0x1f;
|
u16 reg = opc.hex & 0x1f;
|
||||||
u16 cnt = g_dsp.r[reg];
|
u16 cnt = g_dsp.r[reg];
|
||||||
u16 loop_pc = dsp_fetch_code();
|
u16 loop_pc = dsp_fetch_code();
|
||||||
|
|
||||||
if (cnt)
|
if (cnt)
|
||||||
{
|
{
|
||||||
dsp_reg_store_stack(0, g_dsp.pc);
|
dsp_reg_store_stack(0, g_dsp.pc);
|
||||||
dsp_reg_store_stack(2, loop_pc);
|
dsp_reg_store_stack(2, loop_pc);
|
||||||
dsp_reg_store_stack(3, cnt);
|
dsp_reg_store_stack(3, cnt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_dsp.pc = loop_pc;
|
g_dsp.pc = loop_pc;
|
||||||
g_dsp.pc += opSize[dsp_peek_code()];
|
g_dsp.pc += opSize[dsp_peek_code()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BLOOPI #I, addrA
|
// BLOOPI #I, addrA
|
||||||
// 0001 0001 iiii iiii
|
// 0001 0001 iiii iiii
|
||||||
// aaaa aaaa aaaa aaaa
|
// aaaa aaaa aaaa aaaa
|
||||||
// Repeatedly execute block of code starting at following opcode until
|
// Repeatedly execute block of code starting at following opcode until
|
||||||
// counter specified by immediate value I reaches zero. Block ends at specified
|
// counter specified by immediate value I reaches zero. Block ends at specified
|
||||||
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
|
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
|
||||||
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
|
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
|
||||||
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
|
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
|
||||||
// nested loops is allowed.
|
// nested loops is allowed.
|
||||||
void bloopi(const UDSPInstruction& opc)
|
void bloopi(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 cnt = opc.hex & 0xff;
|
u16 cnt = opc.hex & 0xff;
|
||||||
u16 loop_pc = dsp_fetch_code();
|
u16 loop_pc = dsp_fetch_code();
|
||||||
|
|
||||||
if (cnt)
|
if (cnt)
|
||||||
{
|
{
|
||||||
dsp_reg_store_stack(0, g_dsp.pc);
|
dsp_reg_store_stack(0, g_dsp.pc);
|
||||||
dsp_reg_store_stack(2, loop_pc);
|
dsp_reg_store_stack(2, loop_pc);
|
||||||
dsp_reg_store_stack(3, cnt);
|
dsp_reg_store_stack(3, cnt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_dsp.pc = loop_pc;
|
g_dsp.pc = loop_pc;
|
||||||
g_dsp.pc += opSize[dsp_peek_code()];
|
g_dsp.pc += opSize[dsp_peek_code()];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -1,266 +1,266 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||||
|
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
|
|
||||||
#include "DSPMemoryMap.h"
|
#include "DSPMemoryMap.h"
|
||||||
#include "DSPIntUtil.h"
|
#include "DSPIntUtil.h"
|
||||||
|
|
||||||
namespace DSPInterpreter {
|
namespace DSPInterpreter {
|
||||||
|
|
||||||
// SRS @M, $(0x18+S)
|
// SRS @M, $(0x18+S)
|
||||||
// 0010 1sss mmmm mmmm
|
// 0010 1sss mmmm mmmm
|
||||||
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
|
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
|
||||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||||
// lower 8 bits are from the 8-bit immediate.
|
// lower 8 bits are from the 8-bit immediate.
|
||||||
// Note: pc+=2 in duddie's doc seems wrong
|
// Note: pc+=2 in duddie's doc seems wrong
|
||||||
void srs(const UDSPInstruction& opc)
|
void srs(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||||
dsp_dmem_write(addr, g_dsp.r[reg]);
|
dsp_dmem_write(addr, g_dsp.r[reg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRS $(0x18+D), @M
|
// LRS $(0x18+D), @M
|
||||||
// 0010 0ddd mmmm mmmm
|
// 0010 0ddd mmmm mmmm
|
||||||
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
|
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
|
||||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||||
// lower 8 bits are from the 8-bit immediate.
|
// lower 8 bits are from the 8-bit immediate.
|
||||||
void lrs(const UDSPInstruction& opc)
|
void lrs(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||||
g_dsp.r[reg] = dsp_dmem_read(addr);
|
g_dsp.r[reg] = dsp_dmem_read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LR $D, @M
|
// LR $D, @M
|
||||||
// 0000 0000 110d dddd
|
// 0000 0000 110d dddd
|
||||||
// mmmm mmmm mmmm mmmm
|
// mmmm mmmm mmmm mmmm
|
||||||
// Move value from data memory pointed by address M to register $D.
|
// Move value from data memory pointed by address M to register $D.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void lr(const UDSPInstruction& opc)
|
void lr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = opc.hex & DSP_REG_MASK;
|
u8 reg = opc.hex & DSP_REG_MASK;
|
||||||
u16 addr = dsp_fetch_code();
|
u16 addr = dsp_fetch_code();
|
||||||
u16 val = dsp_dmem_read(addr);
|
u16 val = dsp_dmem_read(addr);
|
||||||
dsp_op_write_reg(reg, val);
|
dsp_op_write_reg(reg, val);
|
||||||
dsp_conditional_extend_accum(reg);
|
dsp_conditional_extend_accum(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SR @M, $S
|
// SR @M, $S
|
||||||
// 0000 0000 111s ssss
|
// 0000 0000 111s ssss
|
||||||
// mmmm mmmm mmmm mmmm
|
// mmmm mmmm mmmm mmmm
|
||||||
// Store value from register $S to a memory pointed by address M.
|
// Store value from register $S to a memory pointed by address M.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void sr(const UDSPInstruction& opc)
|
void sr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = opc.hex & DSP_REG_MASK;
|
u8 reg = opc.hex & DSP_REG_MASK;
|
||||||
u16 addr = dsp_fetch_code();
|
u16 addr = dsp_fetch_code();
|
||||||
u16 val = dsp_op_read_reg(reg);
|
u16 val = dsp_op_read_reg(reg);
|
||||||
dsp_dmem_write(addr, val);
|
dsp_dmem_write(addr, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SI @M, #I
|
// SI @M, #I
|
||||||
// 0001 0110 mmmm mmmm
|
// 0001 0110 mmmm mmmm
|
||||||
// iiii iiii iiii iiii
|
// iiii iiii iiii iiii
|
||||||
// Store 16-bit immediate value I to a memory location pointed by address
|
// Store 16-bit immediate value I to a memory location pointed by address
|
||||||
// M (M is 8-bit value sign extended).
|
// M (M is 8-bit value sign extended).
|
||||||
void si(const UDSPInstruction& opc)
|
void si(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 addr = (s8)opc.hex;
|
u16 addr = (s8)opc.hex;
|
||||||
u16 imm = dsp_fetch_code();
|
u16 imm = dsp_fetch_code();
|
||||||
dsp_dmem_write(addr, imm);
|
dsp_dmem_write(addr, imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRR $D, @$S
|
// LRR $D, @$S
|
||||||
// 0001 1000 0ssd dddd
|
// 0001 1000 0ssd dddd
|
||||||
// Move value from data memory pointed by addressing register $S to register $D.
|
// Move value from data memory pointed by addressing register $S to register $D.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void lrr(const UDSPInstruction& opc)
|
void lrr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||||
u8 dreg = opc.hex & 0x1f;
|
u8 dreg = opc.hex & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||||
dsp_op_write_reg(dreg, val);
|
dsp_op_write_reg(dreg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRRD $D, @$S
|
// LRRD $D, @$S
|
||||||
// 0001 1000 1ssd dddd
|
// 0001 1000 1ssd dddd
|
||||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||||
// Decrement register $S.
|
// Decrement register $S.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void lrrd(const UDSPInstruction& opc)
|
void lrrd(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||||
u8 dreg = opc.hex & 0x1f;
|
u8 dreg = opc.hex & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||||
dsp_op_write_reg(dreg, val);
|
dsp_op_write_reg(dreg, val);
|
||||||
dsp_decrement_addr_reg(sreg);
|
dsp_decrement_addr_reg(sreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRRI $D, @$S
|
// LRRI $D, @$S
|
||||||
// 0001 1001 0ssd dddd
|
// 0001 1001 0ssd dddd
|
||||||
// Move value from data memory pointed by addressing register $S to register $D.
|
// Move value from data memory pointed by addressing register $S to register $D.
|
||||||
// Increment register $S.
|
// Increment register $S.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void lrri(const UDSPInstruction& opc)
|
void lrri(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||||
u8 dreg = opc.hex & 0x1f;
|
u8 dreg = opc.hex & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||||
dsp_op_write_reg(dreg, val);
|
dsp_op_write_reg(dreg, val);
|
||||||
dsp_increment_addr_reg(sreg);
|
dsp_increment_addr_reg(sreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRRN $D, @$S
|
// LRRN $D, @$S
|
||||||
// 0001 1001 1ssd dddd
|
// 0001 1001 1ssd dddd
|
||||||
// Move value from data memory pointed by addressing register $S to register $D.
|
// Move value from data memory pointed by addressing register $S to register $D.
|
||||||
// Add indexing register $(0x4+S) to register $S.
|
// Add indexing register $(0x4+S) to register $S.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void lrrn(const UDSPInstruction& opc)
|
void lrrn(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||||
u8 dreg = opc.hex & 0x1f;
|
u8 dreg = opc.hex & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||||
dsp_op_write_reg(dreg, val);
|
dsp_op_write_reg(dreg, val);
|
||||||
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
|
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
|
||||||
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRR @$D, $S
|
// SRR @$D, $S
|
||||||
// 0001 1010 0dds ssss
|
// 0001 1010 0dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D.
|
// addressing register $D.
|
||||||
// FIXME: Perform additional operation depending on source register.
|
// FIXME: Perform additional operation depending on source register.
|
||||||
void srr(const UDSPInstruction& opc)
|
void srr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||||
u8 sreg = opc.hex & 0x1f;
|
u8 sreg = opc.hex & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_op_read_reg(sreg);
|
u16 val = dsp_op_read_reg(sreg);
|
||||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRRD @$D, $S
|
// SRRD @$D, $S
|
||||||
// 0001 1010 1dds ssss
|
// 0001 1010 1dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D. Decrement register $D.
|
// addressing register $D. Decrement register $D.
|
||||||
// FIXME: Perform additional operation depending on source register.
|
// FIXME: Perform additional operation depending on source register.
|
||||||
void srrd(const UDSPInstruction& opc)
|
void srrd(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||||
u8 sreg = opc.hex & 0x1f;
|
u8 sreg = opc.hex & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_op_read_reg(sreg);
|
u16 val = dsp_op_read_reg(sreg);
|
||||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||||
dsp_decrement_addr_reg(dreg);
|
dsp_decrement_addr_reg(dreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRRI @$D, $S
|
// SRRI @$D, $S
|
||||||
// 0001 1011 0dds ssss
|
// 0001 1011 0dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D. Increment register $D.
|
// addressing register $D. Increment register $D.
|
||||||
// FIXME: Perform additional operation depending on source register.
|
// FIXME: Perform additional operation depending on source register.
|
||||||
void srri(const UDSPInstruction& opc)
|
void srri(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||||
u8 sreg = opc.hex & 0x1f;
|
u8 sreg = opc.hex & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_op_read_reg(sreg);
|
u16 val = dsp_op_read_reg(sreg);
|
||||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||||
dsp_increment_addr_reg(dreg);
|
dsp_increment_addr_reg(dreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRRN @$D, $S
|
// SRRN @$D, $S
|
||||||
// 0001 1011 1dds ssss
|
// 0001 1011 1dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||||
// FIXME: Perform additional operation depending on source register.
|
// FIXME: Perform additional operation depending on source register.
|
||||||
void srrn(const UDSPInstruction& opc)
|
void srrn(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||||
u8 sreg = opc.hex & 0x1f;
|
u8 sreg = opc.hex & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_op_read_reg(sreg);
|
u16 val = dsp_op_read_reg(sreg);
|
||||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||||
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
|
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
|
||||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ILRR $acD.m, @$arS
|
// ILRR $acD.m, @$arS
|
||||||
// 0000 001d 0001 00ss
|
// 0000 001d 0001 00ss
|
||||||
// Move value from instruction memory pointed by addressing register
|
// Move value from instruction memory pointed by addressing register
|
||||||
// $arS to mid accumulator register $acD.m.
|
// $arS to mid accumulator register $acD.m.
|
||||||
void ilrr(const UDSPInstruction& opc)
|
void ilrr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 reg = opc.hex & 0x3;
|
u16 reg = opc.hex & 0x3;
|
||||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||||
|
|
||||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ILRRD $acD.m, @$arS
|
// ILRRD $acD.m, @$arS
|
||||||
// 0000 001d 0001 01ss
|
// 0000 001d 0001 01ss
|
||||||
// Move value from instruction memory pointed by addressing register
|
// Move value from instruction memory pointed by addressing register
|
||||||
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
|
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
|
||||||
void ilrrd(const UDSPInstruction& opc)
|
void ilrrd(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 reg = opc.hex & 0x3;
|
u16 reg = opc.hex & 0x3;
|
||||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||||
|
|
||||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||||
|
|
||||||
dsp_decrement_addr_reg(reg);
|
dsp_decrement_addr_reg(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ILRRI $acD.m, @$S
|
// ILRRI $acD.m, @$S
|
||||||
// 0000 001d 0001 10ss
|
// 0000 001d 0001 10ss
|
||||||
// Move value from instruction memory pointed by addressing register
|
// Move value from instruction memory pointed by addressing register
|
||||||
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
|
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
|
||||||
void ilrri(const UDSPInstruction& opc)
|
void ilrri(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 reg = opc.hex & 0x3;
|
u16 reg = opc.hex & 0x3;
|
||||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||||
|
|
||||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||||
|
|
||||||
dsp_increment_addr_reg(reg);
|
dsp_increment_addr_reg(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ILRRN $acD.m, @$arS
|
// ILRRN $acD.m, @$arS
|
||||||
// 0000 001d 0001 11ss
|
// 0000 001d 0001 11ss
|
||||||
// Move value from instruction memory pointed by addressing register
|
// Move value from instruction memory pointed by addressing register
|
||||||
// $arS to mid accumulator register $acD.m. Add corresponding indexing
|
// $arS to mid accumulator register $acD.m. Add corresponding indexing
|
||||||
// register $ixS to addressing register $arS.
|
// register $ixS to addressing register $arS.
|
||||||
void ilrrn(const UDSPInstruction& opc)
|
void ilrrn(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 reg = opc.hex & 0x3;
|
u16 reg = opc.hex & 0x3;
|
||||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||||
|
|
||||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||||
|
|
||||||
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
|
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
|
||||||
dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
|
dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -1,202 +1,202 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||||
|
|
||||||
|
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
|
|
||||||
#include "DSPCore.h"
|
#include "DSPCore.h"
|
||||||
#include "DSPIntUtil.h"
|
#include "DSPIntUtil.h"
|
||||||
|
|
||||||
namespace DSPInterpreter {
|
namespace DSPInterpreter {
|
||||||
|
|
||||||
void unknown(const UDSPInstruction& opc)
|
void unknown(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||||
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
|
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MRR $D, $S
|
// MRR $D, $S
|
||||||
// 0001 11dd ddds ssss
|
// 0001 11dd ddds ssss
|
||||||
// Move value from register $S to register $D.
|
// Move value from register $S to register $D.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void mrr(const UDSPInstruction& opc)
|
void mrr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 sreg = opc.hex & 0x1f;
|
u8 sreg = opc.hex & 0x1f;
|
||||||
u8 dreg = (opc.hex >> 5) & 0x1f;
|
u8 dreg = (opc.hex >> 5) & 0x1f;
|
||||||
|
|
||||||
u16 val = dsp_op_read_reg(sreg);
|
u16 val = dsp_op_read_reg(sreg);
|
||||||
dsp_op_write_reg(dreg, val);
|
dsp_op_write_reg(dreg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRI $D, #I
|
// LRI $D, #I
|
||||||
// 0000 0000 100d dddd
|
// 0000 0000 100d dddd
|
||||||
// iiii iiii iiii iiii
|
// iiii iiii iiii iiii
|
||||||
// Load immediate value I to register $D.
|
// Load immediate value I to register $D.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
|
|
||||||
// DSPSpy discovery: This, and possibly other instructions that load a register,
|
// DSPSpy discovery: This, and possibly other instructions that load a register,
|
||||||
// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
|
// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
|
||||||
// to the whole accumulator! This does not happen in S16 mode.
|
// to the whole accumulator! This does not happen in S16 mode.
|
||||||
void lri(const UDSPInstruction& opc)
|
void lri(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = opc.hex & DSP_REG_MASK;
|
u8 reg = opc.hex & DSP_REG_MASK;
|
||||||
u16 imm = dsp_fetch_code();
|
u16 imm = dsp_fetch_code();
|
||||||
dsp_op_write_reg(reg, imm);
|
dsp_op_write_reg(reg, imm);
|
||||||
dsp_conditional_extend_accum(reg);
|
dsp_conditional_extend_accum(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRIS $(0x18+D), #I
|
// LRIS $(0x18+D), #I
|
||||||
// 0000 1ddd iiii iiii
|
// 0000 1ddd iiii iiii
|
||||||
// Load immediate value I (8-bit sign extended) to accumulator register.
|
// Load immediate value I (8-bit sign extended) to accumulator register.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void lris(const UDSPInstruction& opc)
|
void lris(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
|
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
|
||||||
u16 imm = (s8)opc.hex;
|
u16 imm = (s8)opc.hex;
|
||||||
dsp_op_write_reg(reg, imm);
|
dsp_op_write_reg(reg, imm);
|
||||||
dsp_conditional_extend_accum(reg);
|
dsp_conditional_extend_accum(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TSTAXL $acR
|
// TSTAXL $acR
|
||||||
// 1000 r001 xxxx xxxx
|
// 1000 r001 xxxx xxxx
|
||||||
// r specifies one of the main accumulators.
|
// r specifies one of the main accumulators.
|
||||||
// Definitely not a test instruction - it changes the accums.
|
// Definitely not a test instruction - it changes the accums.
|
||||||
// Not affected by m0/m2. Not affected by s16/s40.
|
// Not affected by m0/m2. Not affected by s16/s40.
|
||||||
void tstaxl(const UDSPInstruction& opc)
|
void tstaxl(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
// This is probably all wrong.
|
// This is probably all wrong.
|
||||||
//u8 reg = (opc.hex >> 8) & 0x1;
|
//u8 reg = (opc.hex >> 8) & 0x1;
|
||||||
//s16 val = dsp_get_ax_l(reg);
|
//s16 val = dsp_get_ax_l(reg);
|
||||||
//Update_SR_Register16(val);
|
//Update_SR_Register16(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADDARN $arD, $ixS
|
// ADDARN $arD, $ixS
|
||||||
// 0000 0000 0001 ssdd
|
// 0000 0000 0001 ssdd
|
||||||
// Adds indexing register $ixS to an addressing register $arD.
|
// Adds indexing register $ixS to an addressing register $arD.
|
||||||
void addarn(const UDSPInstruction& opc)
|
void addarn(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 dreg = opc.hex & 0x3;
|
u8 dreg = opc.hex & 0x3;
|
||||||
u8 sreg = (opc.hex >> 2) & 0x3;
|
u8 sreg = (opc.hex >> 2) & 0x3;
|
||||||
|
|
||||||
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
|
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
|
||||||
|
|
||||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||||
|
|
||||||
// It is critical for the Zelda ucode that this one wraps correctly.
|
// It is critical for the Zelda ucode that this one wraps correctly.
|
||||||
}
|
}
|
||||||
|
|
||||||
// NX
|
// NX
|
||||||
// 1000 -000 xxxx xxxx
|
// 1000 -000 xxxx xxxx
|
||||||
// No operation, but can be extended with extended opcode.
|
// No operation, but can be extended with extended opcode.
|
||||||
void nx(const UDSPInstruction& opc)
|
void nx(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
// This opcode is supposed to do nothing - it's used if you want to use
|
// This opcode is supposed to do nothing - it's used if you want to use
|
||||||
// an opcode extension but not do anything. At least according to duddie.
|
// an opcode extension but not do anything. At least according to duddie.
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
//-------------------------------------------------------------
|
||||||
// DAR $arD ?
|
// DAR $arD ?
|
||||||
// 0000 0000 0000 01dd
|
// 0000 0000 0000 01dd
|
||||||
// Decrement address register $arD.
|
// Decrement address register $arD.
|
||||||
void dar(const UDSPInstruction& opc)
|
void dar(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
dsp_decrement_addr_reg(opc.hex & 0x3);
|
dsp_decrement_addr_reg(opc.hex & 0x3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IAR $arD ?
|
// IAR $arD ?
|
||||||
// 0000 0000 0000 10dd
|
// 0000 0000 0000 10dd
|
||||||
// Increment address register $arD.
|
// Increment address register $arD.
|
||||||
void iar(const UDSPInstruction& opc)
|
void iar(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
dsp_increment_addr_reg(opc.hex & 0x3);
|
dsp_increment_addr_reg(opc.hex & 0x3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SBCLR #I
|
// SBCLR #I
|
||||||
// 0001 0011 0000 0iii
|
// 0001 0011 0000 0iii
|
||||||
// bit of status register $sr. Bit number is calculated by adding 6 to
|
// bit of status register $sr. Bit number is calculated by adding 6 to
|
||||||
// immediate value I.
|
// immediate value I.
|
||||||
void sbclr(const UDSPInstruction& opc)
|
void sbclr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 bit = (opc.hex & 0xff) + 6;
|
u8 bit = (opc.hex & 0xff) + 6;
|
||||||
g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
|
g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SBSET #I
|
// SBSET #I
|
||||||
// 0001 0010 0000 0iii
|
// 0001 0010 0000 0iii
|
||||||
// Set bit of status register $sr. Bit number is calculated by adding 6 to
|
// Set bit of status register $sr. Bit number is calculated by adding 6 to
|
||||||
// immediate value I.
|
// immediate value I.
|
||||||
void sbset(const UDSPInstruction& opc)
|
void sbset(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 bit = (opc.hex & 0xff) + 6;
|
u8 bit = (opc.hex & 0xff) + 6;
|
||||||
g_dsp.r[DSP_REG_SR] |= (1 << bit);
|
g_dsp.r[DSP_REG_SR] |= (1 << bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// FIXME inside
|
// FIXME inside
|
||||||
// This is a bunch of flag setters, flipping bits in SR. So far so good,
|
// This is a bunch of flag setters, flipping bits in SR. So far so good,
|
||||||
// but it's harder to know exactly what effect they have.
|
// but it's harder to know exactly what effect they have.
|
||||||
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
|
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
|
||||||
//
|
//
|
||||||
// SET16 changes something very important: see the LRI instruction above.
|
// SET16 changes something very important: see the LRI instruction above.
|
||||||
// Hermes' demo sets the following defaults:
|
// Hermes' demo sets the following defaults:
|
||||||
// SET40
|
// SET40
|
||||||
// CLR15
|
// CLR15
|
||||||
// M0
|
// M0
|
||||||
void srbith(const UDSPInstruction& opc)
|
void srbith(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
switch ((opc.hex >> 8) & 0xf)
|
switch ((opc.hex >> 8) & 0xf)
|
||||||
{
|
{
|
||||||
// M0 seems to be the default. M2 is used in functions in Zelda
|
// M0 seems to be the default. M2 is used in functions in Zelda
|
||||||
// and then reset with M0 at the end. Like the other bits here, it's
|
// and then reset with M0 at the end. Like the other bits here, it's
|
||||||
// done around loops with lots of multiplications.
|
// done around loops with lots of multiplications.
|
||||||
// I've confirmed with DSPSpy that they flip this bit.
|
// I've confirmed with DSPSpy that they flip this bit.
|
||||||
case 0xa: // M2
|
case 0xa: // M2
|
||||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
|
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
|
||||||
break;
|
break;
|
||||||
case 0xb: // M0
|
case 0xb: // M0
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
|
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// If set, treat multiplicands as unsigned.
|
// If set, treat multiplicands as unsigned.
|
||||||
// If clear, treat them as signed.
|
// If clear, treat them as signed.
|
||||||
case 0xc: // CLR15
|
case 0xc: // CLR15
|
||||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
|
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
|
||||||
break;
|
break;
|
||||||
case 0xd: // SET15
|
case 0xd: // SET15
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
|
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Automatic 40-bit sign extension when loading ACx.M.
|
// Automatic 40-bit sign extension when loading ACx.M.
|
||||||
// 40 seems to be the default.
|
// 40 seems to be the default.
|
||||||
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
|
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
|
||||||
case 0xe: // SET16 (really, clear SR's 0x4000)
|
case 0xe: // SET16 (really, clear SR's 0x4000)
|
||||||
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
|
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf: // SET40 (really, set SR's 0x4000)
|
case 0xf: // SET40 (really, set SR's 0x4000)
|
||||||
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
|
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,85 +1,85 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "LabelMap.h"
|
#include "LabelMap.h"
|
||||||
#include "DSPTables.h"
|
#include "DSPTables.h"
|
||||||
|
|
||||||
LabelMap::LabelMap()
|
LabelMap::LabelMap()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelMap::RegisterDefaults()
|
void LabelMap::RegisterDefaults()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 0x24; i++)
|
for (int i = 0; i < 0x24; i++)
|
||||||
{
|
{
|
||||||
if (regnames[i].name)
|
if (regnames[i].name)
|
||||||
RegisterLabel(regnames[i].name, regnames[i].addr);
|
RegisterLabel(regnames[i].name, regnames[i].addr);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < (int)pdlabels_size; i++)
|
for (int i = 0; i < (int)pdlabels_size; i++)
|
||||||
{
|
{
|
||||||
if (pdlabels[i].name)
|
if (pdlabels[i].name)
|
||||||
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
|
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
|
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
|
||||||
{
|
{
|
||||||
u16 old_value;
|
u16 old_value;
|
||||||
if (GetLabelValue(label, &old_value) && old_value != lval)
|
if (GetLabelValue(label, &old_value) && old_value != lval)
|
||||||
{
|
{
|
||||||
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
|
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
|
||||||
label.c_str(), lval, old_value);
|
label.c_str(), lval, old_value);
|
||||||
DeleteLabel(label);
|
DeleteLabel(label);
|
||||||
}
|
}
|
||||||
labels.push_back(label_t(label, lval, type));
|
labels.push_back(label_t(label, lval, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelMap::DeleteLabel(const std::string &label)
|
void LabelMap::DeleteLabel(const std::string &label)
|
||||||
{
|
{
|
||||||
for (std::vector<label_t>::iterator iter = labels.begin();
|
for (std::vector<label_t>::iterator iter = labels.begin();
|
||||||
iter != labels.end(); ++iter)
|
iter != labels.end(); ++iter)
|
||||||
{
|
{
|
||||||
if (!label.compare(iter->name))
|
if (!label.compare(iter->name))
|
||||||
{
|
{
|
||||||
labels.erase(iter);
|
labels.erase(iter);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
|
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < labels.size(); i++)
|
for (u32 i = 0; i < labels.size(); i++)
|
||||||
{
|
{
|
||||||
if (!label.compare(labels[i].name))
|
if (!label.compare(labels[i].name))
|
||||||
{
|
{
|
||||||
if (type & labels[i].type) {
|
if (type & labels[i].type) {
|
||||||
*value = labels[i].addr;
|
*value = labels[i].addr;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
printf("WARNING: Wrong label type requested. %s\n", label.c_str());
|
printf("WARNING: Wrong label type requested. %s\n", label.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelMap::Clear()
|
void LabelMap::Clear()
|
||||||
{
|
{
|
||||||
labels.clear();
|
labels.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +1,55 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _LABELMAP_H
|
#ifndef _LABELMAP_H
|
||||||
#define _LABELMAP_H
|
#define _LABELMAP_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
enum LabelType
|
enum LabelType
|
||||||
{
|
{
|
||||||
LABEL_IADDR = 1, // Jump addresses, etc
|
LABEL_IADDR = 1, // Jump addresses, etc
|
||||||
LABEL_DADDR = 2, // Data addresses, etc
|
LABEL_DADDR = 2, // Data addresses, etc
|
||||||
LABEL_VALUE = 4,
|
LABEL_VALUE = 4,
|
||||||
LABEL_ANY = 0xFF,
|
LABEL_ANY = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
class LabelMap
|
class LabelMap
|
||||||
{
|
{
|
||||||
struct label_t
|
struct label_t
|
||||||
{
|
{
|
||||||
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
|
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
|
||||||
std::string name;
|
std::string name;
|
||||||
s32 addr;
|
s32 addr;
|
||||||
LabelType type;
|
LabelType type;
|
||||||
};
|
};
|
||||||
std::vector<label_t> labels;
|
std::vector<label_t> labels;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LabelMap();
|
LabelMap();
|
||||||
~LabelMap() { }
|
~LabelMap() { }
|
||||||
void RegisterDefaults();
|
void RegisterDefaults();
|
||||||
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
|
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
|
||||||
void DeleteLabel(const std::string &label);
|
void DeleteLabel(const std::string &label);
|
||||||
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
|
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
|
||||||
void Clear();
|
void Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _LABELMAP_H
|
#endif // _LABELMAP_H
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,139 +1,139 @@
|
||||||
/*====================================================================
|
/*====================================================================
|
||||||
|
|
||||||
project: GameCube DSP Tool (gcdsp)
|
project: GameCube DSP Tool (gcdsp)
|
||||||
created: 2005.03.04
|
created: 2005.03.04
|
||||||
mail: duddie@walla.com
|
mail: duddie@walla.com
|
||||||
|
|
||||||
Copyright (c) 2005 Duddie
|
Copyright (c) 2005 Duddie
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or
|
This program is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU General Public License
|
modify it under the terms of the GNU General Public License
|
||||||
as published by the Free Software Foundation; either version 2
|
as published by the Free Software Foundation; either version 2
|
||||||
of the License, or (at your option) any later version.
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
====================================================================*/
|
====================================================================*/
|
||||||
|
|
||||||
#ifndef _DSP_ASSEMBLE_H
|
#ifndef _DSP_ASSEMBLE_H
|
||||||
#define _DSP_ASSEMBLE_H
|
#define _DSP_ASSEMBLE_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "disassemble.h"
|
#include "disassemble.h"
|
||||||
#include "DSPTables.h"
|
#include "DSPTables.h"
|
||||||
#include "LabelMap.h"
|
#include "LabelMap.h"
|
||||||
|
|
||||||
enum err_t
|
enum err_t
|
||||||
{
|
{
|
||||||
ERR_OK = 0,
|
ERR_OK = 0,
|
||||||
ERR_UNKNOWN,
|
ERR_UNKNOWN,
|
||||||
ERR_UNKNOWN_OPCODE,
|
ERR_UNKNOWN_OPCODE,
|
||||||
ERR_NOT_ENOUGH_PARAMETERS,
|
ERR_NOT_ENOUGH_PARAMETERS,
|
||||||
ERR_TOO_MANY_PARAMETERS,
|
ERR_TOO_MANY_PARAMETERS,
|
||||||
ERR_WRONG_PARAMETER,
|
ERR_WRONG_PARAMETER,
|
||||||
ERR_EXPECTED_PARAM_STR,
|
ERR_EXPECTED_PARAM_STR,
|
||||||
ERR_EXPECTED_PARAM_VAL,
|
ERR_EXPECTED_PARAM_VAL,
|
||||||
ERR_EXPECTED_PARAM_REG,
|
ERR_EXPECTED_PARAM_REG,
|
||||||
ERR_EXPECTED_PARAM_MEM,
|
ERR_EXPECTED_PARAM_MEM,
|
||||||
ERR_EXPECTED_PARAM_IMM,
|
ERR_EXPECTED_PARAM_IMM,
|
||||||
ERR_INCORRECT_BIN,
|
ERR_INCORRECT_BIN,
|
||||||
ERR_INCORRECT_HEX,
|
ERR_INCORRECT_HEX,
|
||||||
ERR_INCORRECT_DEC,
|
ERR_INCORRECT_DEC,
|
||||||
ERR_LABEL_EXISTS,
|
ERR_LABEL_EXISTS,
|
||||||
ERR_UNKNOWN_LABEL,
|
ERR_UNKNOWN_LABEL,
|
||||||
ERR_NO_MATCHING_BRACKETS,
|
ERR_NO_MATCHING_BRACKETS,
|
||||||
ERR_EXT_CANT_EXTEND_OPCODE,
|
ERR_EXT_CANT_EXTEND_OPCODE,
|
||||||
ERR_EXT_PAR_NOT_EXT,
|
ERR_EXT_PAR_NOT_EXT,
|
||||||
ERR_WRONG_PARAMETER_ACC,
|
ERR_WRONG_PARAMETER_ACC,
|
||||||
ERR_WRONG_PARAMETER_MID_ACC,
|
ERR_WRONG_PARAMETER_MID_ACC,
|
||||||
ERR_INVALID_REGISTER,
|
ERR_INVALID_REGISTER,
|
||||||
ERR_OUT_RANGE_NUMBER
|
ERR_OUT_RANGE_NUMBER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Unless you want labels to carry over between files, you probably
|
// Unless you want labels to carry over between files, you probably
|
||||||
// want to create a new DSPAssembler for every file you assemble.
|
// want to create a new DSPAssembler for every file you assemble.
|
||||||
class DSPAssembler
|
class DSPAssembler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DSPAssembler(const AssemblerSettings &settings);
|
DSPAssembler(const AssemblerSettings &settings);
|
||||||
~DSPAssembler();
|
~DSPAssembler();
|
||||||
|
|
||||||
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
|
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
|
||||||
// one for each word of code, indicating the source assembler code line number it came from.
|
// one for each word of code, indicating the source assembler code line number it came from.
|
||||||
|
|
||||||
// If returns false, call GetErrorString to get some text to present to the user.
|
// If returns false, call GetErrorString to get some text to present to the user.
|
||||||
bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
|
bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
|
||||||
|
|
||||||
std::string GetErrorString() const { return last_error_str; }
|
std::string GetErrorString() const { return last_error_str; }
|
||||||
err_t GetError() const { return last_error; }
|
err_t GetError() const { return last_error; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct param_t
|
struct param_t
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
partype_t type;
|
partype_t type;
|
||||||
char *str;
|
char *str;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum segment_t
|
enum segment_t
|
||||||
{
|
{
|
||||||
SEGMENT_CODE = 0,
|
SEGMENT_CODE = 0,
|
||||||
SEGMENT_DATA,
|
SEGMENT_DATA,
|
||||||
SEGMENT_OVERLAY,
|
SEGMENT_OVERLAY,
|
||||||
SEGMENT_MAX
|
SEGMENT_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
s32 ParseValue(const char *str);
|
s32 ParseValue(const char *str);
|
||||||
u32 ParseExpression(const char *ptr);
|
u32 ParseExpression(const char *ptr);
|
||||||
|
|
||||||
u32 GetParams(char *parstr, param_t *par);
|
u32 GetParams(char *parstr, param_t *par);
|
||||||
|
|
||||||
void InitPass(int pass);
|
void InitPass(int pass);
|
||||||
bool AssembleFile(const char *fname, int pass);
|
bool AssembleFile(const char *fname, int pass);
|
||||||
|
|
||||||
void ShowError(err_t err_code, const char *extra_info = NULL);
|
void ShowError(err_t err_code, const char *extra_info = NULL);
|
||||||
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
|
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
|
||||||
|
|
||||||
char *FindBrackets(char *src, char *dst);
|
char *FindBrackets(char *src, char *dst);
|
||||||
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
|
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
|
||||||
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
|
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
|
||||||
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
|
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
|
||||||
|
|
||||||
char *gdg_buffer;
|
char *gdg_buffer;
|
||||||
|
|
||||||
std::string include_dir;
|
std::string include_dir;
|
||||||
std::string cur_line;
|
std::string cur_line;
|
||||||
|
|
||||||
u32 m_cur_addr;
|
u32 m_cur_addr;
|
||||||
int m_totalSize;
|
int m_totalSize;
|
||||||
u8 m_cur_pass;
|
u8 m_cur_pass;
|
||||||
|
|
||||||
LabelMap labels;
|
LabelMap labels;
|
||||||
|
|
||||||
u32 code_line;
|
u32 code_line;
|
||||||
bool failed;
|
bool failed;
|
||||||
std::string last_error_str;
|
std::string last_error_str;
|
||||||
err_t last_error;
|
err_t last_error;
|
||||||
|
|
||||||
typedef std::map<std::string, std::string> AliasMap;
|
typedef std::map<std::string, std::string> AliasMap;
|
||||||
AliasMap aliases;
|
AliasMap aliases;
|
||||||
|
|
||||||
segment_t cur_segment;
|
segment_t cur_segment;
|
||||||
u32 segment_addr[SEGMENT_MAX];
|
u32 segment_addr[SEGMENT_MAX];
|
||||||
int m_current_param;
|
int m_current_param;
|
||||||
const AssemblerSettings settings_;
|
const AssemblerSettings settings_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _DSP_ASSEMBLE_H
|
#endif // _DSP_ASSEMBLE_H
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
// Copyright (C) 2003-2008 Dolphin Project.
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
#include "DebuggerUIUtil.h"
|
#include "DebuggerUIUtil.h"
|
||||||
|
|
||||||
// The default font
|
// The default font
|
||||||
wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));
|
wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));
|
||||||
|
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
// Copyright (C) 2003-2008 Dolphin Project.
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DEBUGGER_UI_UTIL_H
|
#ifndef _DEBUGGER_UI_UTIL_H
|
||||||
#define _DEBUGGER_UI_UTIL_H
|
#define _DEBUGGER_UI_UTIL_H
|
||||||
|
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
|
|
||||||
#define wxUSE_XPM_IN_MSW 1
|
#define wxUSE_XPM_IN_MSW 1
|
||||||
#define USE_XPM_BITMAPS 1
|
#define USE_XPM_BITMAPS 1
|
||||||
|
|
||||||
// Defined in CodeWindow.cpp
|
// Defined in CodeWindow.cpp
|
||||||
extern wxFont DebuggerFont;
|
extern wxFont DebuggerFont;
|
||||||
|
|
||||||
// define this to use XPMs everywhere (by default, BMPs are used under Win)
|
// define this to use XPMs everywhere (by default, BMPs are used under Win)
|
||||||
// BMPs use less space, but aren't compiled into the executable on other platforms
|
// BMPs use less space, but aren't compiled into the executable on other platforms
|
||||||
|
|
||||||
#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
|
#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
|
||||||
#error You need to enable XPM support to use XPM bitmaps with toolbar!
|
#error You need to enable XPM support to use XPM bitmaps with toolbar!
|
||||||
#endif // USE_XPM_BITMAPS
|
#endif // USE_XPM_BITMAPS
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,100 +1,100 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _NAND_CONTENT_LOADER_H
|
#ifndef _NAND_CONTENT_LOADER_H
|
||||||
#define _NAND_CONTENT_LOADER_H
|
#define _NAND_CONTENT_LOADER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Blob.h"
|
#include "Blob.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
|
|
||||||
struct SNANDContent
|
struct SNANDContent
|
||||||
{
|
{
|
||||||
u32 m_ContentID;
|
u32 m_ContentID;
|
||||||
u16 m_Index;
|
u16 m_Index;
|
||||||
u16 m_Type;
|
u16 m_Type;
|
||||||
u32 m_Size;
|
u32 m_Size;
|
||||||
u8 m_SHA1Hash[20];
|
u8 m_SHA1Hash[20];
|
||||||
u8 m_Header[36]; //all of the above
|
u8 m_Header[36]; //all of the above
|
||||||
|
|
||||||
u8* m_pData;
|
u8* m_pData;
|
||||||
};
|
};
|
||||||
|
|
||||||
// pure virtual interface so just the NANDContentManager can create these files only
|
// pure virtual interface so just the NANDContentManager can create these files only
|
||||||
class INANDContentLoader
|
class INANDContentLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
INANDContentLoader() {}
|
INANDContentLoader() {}
|
||||||
|
|
||||||
virtual ~INANDContentLoader() {}
|
virtual ~INANDContentLoader() {}
|
||||||
|
|
||||||
virtual bool IsValid() const = 0;
|
virtual bool IsValid() const = 0;
|
||||||
virtual u64 GetTitleID() const = 0;
|
virtual u64 GetTitleID() const = 0;
|
||||||
virtual u16 GetIosVersion() const = 0;
|
virtual u16 GetIosVersion() const = 0;
|
||||||
virtual u32 GetBootIndex() const = 0;
|
virtual u32 GetBootIndex() const = 0;
|
||||||
virtual size_t GetContentSize() const = 0;
|
virtual size_t GetContentSize() const = 0;
|
||||||
virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
|
virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
|
||||||
virtual const u8* GetTicketView() const = 0;
|
virtual const u8* GetTicketView() const = 0;
|
||||||
virtual const u8* GetTmdHeader() const = 0;
|
virtual const u8* GetTmdHeader() const = 0;
|
||||||
virtual const std::vector<SNANDContent>& GetContent() const = 0;
|
virtual const std::vector<SNANDContent>& GetContent() const = 0;
|
||||||
virtual const u16 GetTitleVersion() const = 0;
|
virtual const u16 GetTitleVersion() const = 0;
|
||||||
virtual const u16 GetNumEntries() const = 0;
|
virtual const u16 GetNumEntries() const = 0;
|
||||||
virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
|
virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
TICKET_VIEW_SIZE = 0x58,
|
TICKET_VIEW_SIZE = 0x58,
|
||||||
TMD_HEADER_SIZE = 0x1e4,
|
TMD_HEADER_SIZE = 0x1e4,
|
||||||
CONTENT_HEADER_SIZE = 0x24
|
CONTENT_HEADER_SIZE = 0x24
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// we open the NAND Content files to often... lets cache them
|
// we open the NAND Content files to often... lets cache them
|
||||||
class CNANDContentManager
|
class CNANDContentManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static CNANDContentManager& Access() { return m_Instance; }
|
static CNANDContentManager& Access() { return m_Instance; }
|
||||||
|
|
||||||
const INANDContentLoader& GetNANDLoader(const std::string& _rName);
|
const INANDContentLoader& GetNANDLoader(const std::string& _rName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
CNANDContentManager() {};
|
CNANDContentManager() {};
|
||||||
|
|
||||||
~CNANDContentManager();
|
~CNANDContentManager();
|
||||||
|
|
||||||
static CNANDContentManager m_Instance;
|
static CNANDContentManager m_Instance;
|
||||||
|
|
||||||
typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
|
typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
|
||||||
CNANDContentMap m_Map;
|
CNANDContentMap m_Map;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,52 +1,52 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
#include "Blob.h"
|
#include "Blob.h"
|
||||||
#include "NANDContentLoader.h"
|
#include "NANDContentLoader.h"
|
||||||
|
|
||||||
// --- this volume type is used for Wad files ---
|
// --- this volume type is used for Wad files ---
|
||||||
// Some of this code might look redundant with the CNANDContentLoader class, however,
|
// Some of this code might look redundant with the CNANDContentLoader class, however,
|
||||||
// We do not do any decryption here, we do raw read, so things are -Faster-
|
// We do not do any decryption here, we do raw read, so things are -Faster-
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
class CVolumeWAD : public IVolume
|
class CVolumeWAD : public IVolume
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CVolumeWAD(IBlobReader* _pReader);
|
CVolumeWAD(IBlobReader* _pReader);
|
||||||
~CVolumeWAD();
|
~CVolumeWAD();
|
||||||
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
|
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
|
||||||
bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
|
bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
|
||||||
bool GetTitleID(u8* _pBuffer) const;
|
bool GetTitleID(u8* _pBuffer) const;
|
||||||
std::string GetUniqueID() const;
|
std::string GetUniqueID() const;
|
||||||
std::string GetMakerID() const;
|
std::string GetMakerID() const;
|
||||||
std::string GetName() const;
|
std::string GetName() const;
|
||||||
u32 GetFSTSize() const { return 0; }
|
u32 GetFSTSize() const { return 0; }
|
||||||
std::string GetApploaderDate() const { return "0"; }
|
std::string GetApploaderDate() const { return "0"; }
|
||||||
ECountry GetCountry() const;
|
ECountry GetCountry() const;
|
||||||
u64 GetSize() const;
|
u64 GetSize() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IBlobReader* m_pReader;
|
IBlobReader* m_pReader;
|
||||||
u64 m_titleID;
|
u64 m_titleID;
|
||||||
u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
|
u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -1,156 +1,156 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "NANDContentLoader.h"
|
#include "NANDContentLoader.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include "MathUtil.h"
|
#include "MathUtil.h"
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "WiiWad.h"
|
#include "WiiWad.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
|
|
||||||
class CBlobBigEndianReader
|
class CBlobBigEndianReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
|
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
|
||||||
|
|
||||||
u32 Read32(u64 _Offset)
|
u32 Read32(u64 _Offset)
|
||||||
{
|
{
|
||||||
u32 Temp;
|
u32 Temp;
|
||||||
m_rReader.Read(_Offset, 4, (u8*)&Temp);
|
m_rReader.Read(_Offset, 4, (u8*)&Temp);
|
||||||
return(Common::swap32(Temp));
|
return(Common::swap32(Temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DiscIO::IBlobReader& m_rReader;
|
DiscIO::IBlobReader& m_rReader;
|
||||||
};
|
};
|
||||||
|
|
||||||
WiiWAD::WiiWAD(const std::string& _rName)
|
WiiWAD::WiiWAD(const std::string& _rName)
|
||||||
{
|
{
|
||||||
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
|
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
|
||||||
if (pReader == NULL)
|
if (pReader == NULL)
|
||||||
{
|
{
|
||||||
m_Valid = false;
|
m_Valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_Valid = ParseWAD(*pReader);
|
m_Valid = ParseWAD(*pReader);
|
||||||
delete pReader;
|
delete pReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
WiiWAD::~WiiWAD()
|
WiiWAD::~WiiWAD()
|
||||||
{
|
{
|
||||||
if (m_Valid)
|
if (m_Valid)
|
||||||
{
|
{
|
||||||
delete m_pCertificateChain;
|
delete m_pCertificateChain;
|
||||||
delete m_pTicket;
|
delete m_pTicket;
|
||||||
delete m_pTMD;
|
delete m_pTMD;
|
||||||
delete m_pDataApp;
|
delete m_pDataApp;
|
||||||
delete m_pFooter;
|
delete m_pFooter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
|
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
|
||||||
{
|
{
|
||||||
if (_Size > 0)
|
if (_Size > 0)
|
||||||
{
|
{
|
||||||
u8* pTmpBuffer = new u8[_Size];
|
u8* pTmpBuffer = new u8[_Size];
|
||||||
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
|
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
|
||||||
|
|
||||||
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
|
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
|
||||||
{
|
{
|
||||||
ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
|
ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
|
||||||
PanicAlert("WiiWAD: Could not read from file");
|
PanicAlert("WiiWAD: Could not read from file");
|
||||||
}
|
}
|
||||||
return pTmpBuffer;
|
return pTmpBuffer;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
|
bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
|
||||||
{
|
{
|
||||||
CBlobBigEndianReader ReaderBig(_rReader);
|
CBlobBigEndianReader ReaderBig(_rReader);
|
||||||
|
|
||||||
// get header size
|
// get header size
|
||||||
u32 HeaderSize = ReaderBig.Read32(0);
|
u32 HeaderSize = ReaderBig.Read32(0);
|
||||||
if (HeaderSize != 0x20)
|
if (HeaderSize != 0x20)
|
||||||
{
|
{
|
||||||
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
|
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get header
|
// get header
|
||||||
u8 Header[0x20];
|
u8 Header[0x20];
|
||||||
_rReader.Read(0, HeaderSize, Header);
|
_rReader.Read(0, HeaderSize, Header);
|
||||||
u32 HeaderType = ReaderBig.Read32(0x4);
|
u32 HeaderType = ReaderBig.Read32(0x4);
|
||||||
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
|
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_CertificateChainSize = ReaderBig.Read32(0x8);
|
m_CertificateChainSize = ReaderBig.Read32(0x8);
|
||||||
u32 Reserved = ReaderBig.Read32(0xC);
|
u32 Reserved = ReaderBig.Read32(0xC);
|
||||||
m_TicketSize = ReaderBig.Read32(0x10);
|
m_TicketSize = ReaderBig.Read32(0x10);
|
||||||
m_TMDSize = ReaderBig.Read32(0x14);
|
m_TMDSize = ReaderBig.Read32(0x14);
|
||||||
m_DataAppSize = ReaderBig.Read32(0x18);
|
m_DataAppSize = ReaderBig.Read32(0x18);
|
||||||
m_FooterSize = ReaderBig.Read32(0x1C);
|
m_FooterSize = ReaderBig.Read32(0x1C);
|
||||||
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
|
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
|
||||||
|
|
||||||
u32 Offset = 0x40;
|
u32 Offset = 0x40;
|
||||||
m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
|
m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
|
||||||
m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
|
m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
|
||||||
m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
|
m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
|
||||||
m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
|
m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
|
||||||
m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
|
m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WiiWAD::IsWiiWAD(const std::string& _rName)
|
bool WiiWAD::IsWiiWAD(const std::string& _rName)
|
||||||
{
|
{
|
||||||
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
|
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
|
||||||
if (pReader == NULL)
|
if (pReader == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
CBlobBigEndianReader Reader(*pReader);
|
CBlobBigEndianReader Reader(*pReader);
|
||||||
bool Result = false;
|
bool Result = false;
|
||||||
|
|
||||||
// check for wii wad
|
// check for wii wad
|
||||||
if (Reader.Read32(0x00) == 0x20)
|
if (Reader.Read32(0x00) == 0x20)
|
||||||
{
|
{
|
||||||
u32 WADTYpe = Reader.Read32(0x04);
|
u32 WADTYpe = Reader.Read32(0x04);
|
||||||
switch(WADTYpe)
|
switch(WADTYpe)
|
||||||
{
|
{
|
||||||
case 0x49730000:
|
case 0x49730000:
|
||||||
case 0x69620000:
|
case 0x69620000:
|
||||||
Result = true;
|
Result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete pReader;
|
delete pReader;
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace end
|
} // namespace end
|
||||||
|
|
||||||
|
|
|
@ -1,78 +1,78 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _WII_WAD_H
|
#ifndef _WII_WAD_H
|
||||||
#define _WII_WAD_H
|
#define _WII_WAD_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Blob.h"
|
#include "Blob.h"
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
namespace DiscIO
|
namespace DiscIO
|
||||||
{
|
{
|
||||||
|
|
||||||
class WiiWAD
|
class WiiWAD
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WiiWAD(const std::string& _rName);
|
WiiWAD(const std::string& _rName);
|
||||||
|
|
||||||
~WiiWAD();
|
~WiiWAD();
|
||||||
|
|
||||||
bool IsValid() const { return m_Valid; }
|
bool IsValid() const { return m_Valid; }
|
||||||
u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
|
u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
|
||||||
u32 GetTicketSize() const { return m_TicketSize; }
|
u32 GetTicketSize() const { return m_TicketSize; }
|
||||||
u32 GetTMDSize() const { return m_TMDSize; }
|
u32 GetTMDSize() const { return m_TMDSize; }
|
||||||
u32 GetDataAppSize() const { return m_DataAppSize; }
|
u32 GetDataAppSize() const { return m_DataAppSize; }
|
||||||
u32 GetFooterSize() const { return m_FooterSize; }
|
u32 GetFooterSize() const { return m_FooterSize; }
|
||||||
|
|
||||||
u8* GetCertificateChain() const { return m_pCertificateChain; }
|
u8* GetCertificateChain() const { return m_pCertificateChain; }
|
||||||
u8* GetTicket() const { return m_pTicket; }
|
u8* GetTicket() const { return m_pTicket; }
|
||||||
u8* GetTMD() const { return m_pTMD; }
|
u8* GetTMD() const { return m_pTMD; }
|
||||||
u8* GetDataApp() const { return m_pDataApp; }
|
u8* GetDataApp() const { return m_pDataApp; }
|
||||||
u8* GetFooter() const { return m_pFooter; }
|
u8* GetFooter() const { return m_pFooter; }
|
||||||
|
|
||||||
static bool IsWiiWAD(const std::string& _rName);
|
static bool IsWiiWAD(const std::string& _rName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool m_Valid;
|
bool m_Valid;
|
||||||
|
|
||||||
u32 m_CertificateChainSize;
|
u32 m_CertificateChainSize;
|
||||||
u32 m_TicketSize;
|
u32 m_TicketSize;
|
||||||
u32 m_TMDSize;
|
u32 m_TMDSize;
|
||||||
u32 m_DataAppSize;
|
u32 m_DataAppSize;
|
||||||
u32 m_FooterSize;
|
u32 m_FooterSize;
|
||||||
|
|
||||||
u8* m_pCertificateChain;
|
u8* m_pCertificateChain;
|
||||||
u8* m_pTicket;
|
u8* m_pTicket;
|
||||||
u8* m_pTMD;
|
u8* m_pTMD;
|
||||||
u8* m_pDataApp;
|
u8* m_pDataApp;
|
||||||
u8* m_pFooter;
|
u8* m_pFooter;
|
||||||
|
|
||||||
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
|
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
|
||||||
bool ParseWAD(DiscIO::IBlobReader& _rReader);
|
bool ParseWAD(DiscIO::IBlobReader& _rReader);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,288 +1,288 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "NetWindow.h"
|
#include "NetWindow.h"
|
||||||
|
|
||||||
void ClientSide::OnClientData(unsigned char data)
|
void ClientSide::OnClientData(unsigned char data)
|
||||||
{
|
{
|
||||||
unsigned char sent = 0;
|
unsigned char sent = 0;
|
||||||
u32 buffer_size;
|
u32 buffer_size;
|
||||||
size_t recv_size;
|
size_t recv_size;
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
|
|
||||||
switch (data)
|
switch (data)
|
||||||
{
|
{
|
||||||
case 0x10: // Player joined server
|
case 0x10: // Player joined server
|
||||||
{
|
{
|
||||||
// Read GameFound
|
// Read GameFound
|
||||||
m_socket.Receive((char*)&sent, 1, recv_size);
|
m_socket.Receive((char*)&sent, 1, recv_size);
|
||||||
|
|
||||||
// Read nickname
|
// Read nickname
|
||||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||||
buffer = new char[buffer_size+1];
|
buffer = new char[buffer_size+1];
|
||||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||||
Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
|
Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
|
||||||
|
|
||||||
if (sent != 0x1F)
|
if (sent != 0x1F)
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
|
Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
|
||||||
|
|
||||||
m_numplayers++;
|
m_numplayers++;
|
||||||
Event->SendEvent(HOST_NEWPLAYER);
|
Event->SendEvent(HOST_NEWPLAYER);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x11: // Player left server
|
case 0x11: // Player left server
|
||||||
{
|
{
|
||||||
// Read Nickname
|
// Read Nickname
|
||||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||||
buffer = new char[buffer_size+1];
|
buffer = new char[buffer_size+1];
|
||||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||||
|
|
||||||
Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
|
Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
|
||||||
|
|
||||||
m_numplayers--;
|
m_numplayers--;
|
||||||
Event->SendEvent(HOST_PLAYERLEFT);
|
Event->SendEvent(HOST_PLAYERLEFT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x15: // Ping Player
|
case 0x15: // Ping Player
|
||||||
{
|
{
|
||||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||||
m_socket.Send((const char*)&buffer_size, 4);
|
m_socket.Send((const char*)&buffer_size, 4);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x20: // IP request
|
case 0x20: // IP request
|
||||||
{
|
{
|
||||||
//buffer_size = m_addr.size();
|
//buffer_size = m_addr.size();
|
||||||
//m_socket.Send((const char*)&buffer_size, 4);
|
//m_socket.Send((const char*)&buffer_size, 4);
|
||||||
m_socket.Send((const char*)&data, 1);
|
m_socket.Send((const char*)&data, 1);
|
||||||
m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
|
m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x30: // Chat message received from server
|
case 0x30: // Chat message received from server
|
||||||
{
|
{
|
||||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||||
buffer = new char[buffer_size+1];
|
buffer = new char[buffer_size+1];
|
||||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||||
|
|
||||||
if (recv_size > 1024)
|
if (recv_size > 1024)
|
||||||
{
|
{
|
||||||
//something wrong...
|
//something wrong...
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Event->AppendText(wxString::FromAscii(buffer));
|
Event->AppendText(wxString::FromAscii(buffer));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x35: // ChangeGame message received
|
case 0x35: // ChangeGame message received
|
||||||
{
|
{
|
||||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||||
buffer = new char[buffer_size+1];
|
buffer = new char[buffer_size+1];
|
||||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||||
|
|
||||||
m_selectedgame = std::string(buffer);
|
m_selectedgame = std::string(buffer);
|
||||||
Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
|
Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
|
||||||
|
|
||||||
// Tell the server if the game's been found
|
// Tell the server if the game's been found
|
||||||
m_socket.Send((const char*)&data, 1);
|
m_socket.Send((const char*)&data, 1);
|
||||||
CheckGameFound();
|
CheckGameFound();
|
||||||
|
|
||||||
Event->SendEvent(GUI_UPDATE);
|
Event->SendEvent(GUI_UPDATE);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x40: // Ready message received
|
case 0x40: // Ready message received
|
||||||
{
|
{
|
||||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||||
buffer = new char[buffer_size+1];
|
buffer = new char[buffer_size+1];
|
||||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||||
|
|
||||||
if (recv_size > 1024)
|
if (recv_size > 1024)
|
||||||
{
|
{
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Event->AppendText(wxString::FromAscii(buffer));
|
Event->AppendText(wxString::FromAscii(buffer));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x50: // Everyone is Ready message received
|
case 0x50: // Everyone is Ready message received
|
||||||
{
|
{
|
||||||
// Load the game and start synching
|
// Load the game and start synching
|
||||||
m_netptr->LoadGame();
|
m_netptr->LoadGame();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xA1: // Received pad data from host in versus mode
|
case 0xA1: // Received pad data from host in versus mode
|
||||||
{
|
{
|
||||||
if (m_data_received)
|
if (m_data_received)
|
||||||
wxThread::Sleep(10);
|
wxThread::Sleep(10);
|
||||||
|
|
||||||
m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
|
m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
|
||||||
m_data_received = true;
|
m_data_received = true;
|
||||||
|
|
||||||
#ifdef NET_DEBUG
|
#ifdef NET_DEBUG
|
||||||
char sent[64];
|
char sent[64];
|
||||||
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
|
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
|
||||||
Event->AppendText(wxString::FromAscii(sent));
|
Event->AppendText(wxString::FromAscii(sent));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerSide::OnServerData(int sock, unsigned char data)
|
void ServerSide::OnServerData(int sock, unsigned char data)
|
||||||
{
|
{
|
||||||
size_t recv_size;
|
size_t recv_size;
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
unsigned char sent;
|
unsigned char sent;
|
||||||
unsigned int four_bytes;
|
unsigned int four_bytes;
|
||||||
|
|
||||||
switch (data)
|
switch (data)
|
||||||
{
|
{
|
||||||
case 0x15: // Ping Request
|
case 0x15: // Ping Request
|
||||||
{
|
{
|
||||||
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
|
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
|
||||||
m_client[sock].socket.Send((const char*)&four_bytes, 4);
|
m_client[sock].socket.Send((const char*)&four_bytes, 4);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x20: // IP request response
|
case 0x20: // IP request response
|
||||||
{
|
{
|
||||||
buffer = new char[24];
|
buffer = new char[24];
|
||||||
// Read IP Address
|
// Read IP Address
|
||||||
m_client[sock].socket.Receive(buffer, 24, recv_size);
|
m_client[sock].socket.Receive(buffer, 24, recv_size);
|
||||||
|
|
||||||
Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
|
Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x30: // Chat message
|
case 0x30: // Chat message
|
||||||
{
|
{
|
||||||
buffer = new char[1024];
|
buffer = new char[1024];
|
||||||
|
|
||||||
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
|
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
|
||||||
m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
|
m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
|
||||||
|
|
||||||
if (recv_size > 1024)
|
if (recv_size > 1024)
|
||||||
{
|
{
|
||||||
//something wrong...
|
//something wrong...
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sent = 0x30;
|
sent = 0x30;
|
||||||
// Send to all
|
// Send to all
|
||||||
for (int i=0; i < m_numplayers ; i++)
|
for (int i=0; i < m_numplayers ; i++)
|
||||||
{
|
{
|
||||||
if (i == sock)
|
if (i == sock)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_client[i].socket.Send((const char*)&sent, 1);
|
m_client[i].socket.Send((const char*)&sent, 1);
|
||||||
|
|
||||||
m_client[1].socket.Send((const char*)&four_bytes, 4);
|
m_client[1].socket.Send((const char*)&four_bytes, 4);
|
||||||
m_client[i].socket.Send(buffer, recv_size);
|
m_client[i].socket.Send(buffer, recv_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Event->AppendText(wxString::FromAscii(buffer));
|
Event->AppendText(wxString::FromAscii(buffer));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x35: // Change game response received
|
case 0x35: // Change game response received
|
||||||
{
|
{
|
||||||
// Receive isGameFound response (0x1F / 0x1A)
|
// Receive isGameFound response (0x1F / 0x1A)
|
||||||
m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
|
m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
|
||||||
|
|
||||||
// If game is not found
|
// If game is not found
|
||||||
if (sent != 0x1F)
|
if (sent != 0x1F)
|
||||||
{
|
{
|
||||||
sent = 0x30;
|
sent = 0x30;
|
||||||
|
|
||||||
wxString error_str = wxString::Format(
|
wxString error_str = wxString::Format(
|
||||||
wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
|
wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
|
||||||
four_bytes = (int)error_str.size();
|
four_bytes = (int)error_str.size();
|
||||||
|
|
||||||
for (int i=0; i < 2; i++)
|
for (int i=0; i < 2; i++)
|
||||||
Event->AppendText(error_str);
|
Event->AppendText(error_str);
|
||||||
|
|
||||||
// Send to all
|
// Send to all
|
||||||
for (int i=0; i < m_numplayers ; i++)
|
for (int i=0; i < m_numplayers ; i++)
|
||||||
{
|
{
|
||||||
if (i == sock)
|
if (i == sock)
|
||||||
continue;
|
continue;
|
||||||
m_client[i].socket.Send((const char*)&sent, 1);
|
m_client[i].socket.Send((const char*)&sent, 1);
|
||||||
|
|
||||||
m_client[i].socket.Send((const char*)&four_bytes, 4);
|
m_client[i].socket.Send((const char*)&four_bytes, 4);
|
||||||
m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
|
m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0x40: // Ready message received
|
case 0x40: // Ready message received
|
||||||
{
|
{
|
||||||
std::string buffer_str;
|
std::string buffer_str;
|
||||||
|
|
||||||
m_client[sock].ready = !m_client[sock].ready;
|
m_client[sock].ready = !m_client[sock].ready;
|
||||||
|
|
||||||
if (m_client[sock].ready)
|
if (m_client[sock].ready)
|
||||||
buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
|
buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
|
||||||
else
|
else
|
||||||
buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
|
buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
|
||||||
|
|
||||||
four_bytes = (int)buffer_str.size();
|
four_bytes = (int)buffer_str.size();
|
||||||
|
|
||||||
// Send to all
|
// Send to all
|
||||||
for (int i=0; i < m_numplayers ; i++)
|
for (int i=0; i < m_numplayers ; i++)
|
||||||
{
|
{
|
||||||
m_client[i].socket.Send((const char*)&data, 1);
|
m_client[i].socket.Send((const char*)&data, 1);
|
||||||
|
|
||||||
m_client[i].socket.Send((const char*)&four_bytes, 4);
|
m_client[i].socket.Send((const char*)&four_bytes, 4);
|
||||||
m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
|
m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
|
Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
|
||||||
IsEveryoneReady();
|
IsEveryoneReady();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xA1: // Received pad data from a client
|
case 0xA1: // Received pad data from a client
|
||||||
{
|
{
|
||||||
if (m_data_received)
|
if (m_data_received)
|
||||||
wxThread::Sleep(10);
|
wxThread::Sleep(10);
|
||||||
|
|
||||||
m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
|
m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
|
||||||
m_data_received = true;
|
m_data_received = true;
|
||||||
|
|
||||||
#ifdef NET_DEBUG
|
#ifdef NET_DEBUG
|
||||||
char sent[64];
|
char sent[64];
|
||||||
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
|
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
|
||||||
Event->AppendText(wxString::FromAscii(sent));
|
Event->AppendText(wxString::FromAscii(sent));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,317 +1,317 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _NETWINDOW_H_
|
#ifndef _NETWINDOW_H_
|
||||||
#define _NETWINDOW_H_
|
#define _NETWINDOW_H_
|
||||||
|
|
||||||
#include <SFML/Network.hpp>
|
#include <SFML/Network.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#include <wx/notebook.h>
|
#include <wx/notebook.h>
|
||||||
#include <wx/gbsizer.h>
|
#include <wx/gbsizer.h>
|
||||||
#include <wx/listbox.h>
|
#include <wx/listbox.h>
|
||||||
|
|
||||||
#include <wx/thread.h>
|
#include <wx/thread.h>
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "BootManager.h"
|
#include "BootManager.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
#include "pluginspecs_pad.h"
|
#include "pluginspecs_pad.h"
|
||||||
#include "HW/SI.h"
|
#include "HW/SI.h"
|
||||||
#include "HW/SI_Device.h"
|
#include "HW/SI_Device.h"
|
||||||
#include "HW/SI_DeviceGCController.h"
|
#include "HW/SI_DeviceGCController.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#define NET_DEBUG
|
#define NET_DEBUG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay,
|
// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay,
|
||||||
// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
|
// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
|
||||||
// #define USE_TCP
|
// #define USE_TCP
|
||||||
|
|
||||||
class NetPlay;
|
class NetPlay;
|
||||||
|
|
||||||
struct Netpads {
|
struct Netpads {
|
||||||
int nHi[128];
|
int nHi[128];
|
||||||
int nLow[128];
|
int nLow[128];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Clients {
|
struct Clients {
|
||||||
std::string nick;
|
std::string nick;
|
||||||
sf::SocketTCP socket;
|
sf::SocketTCP socket;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
sf::IPAddress address;
|
sf::IPAddress address;
|
||||||
bool ready;
|
bool ready;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NetEvent
|
class NetEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NetEvent(NetPlay* netptr) { m_netptr = netptr; }
|
NetEvent(NetPlay* netptr) { m_netptr = netptr; }
|
||||||
~NetEvent() {};
|
~NetEvent() {};
|
||||||
|
|
||||||
void SendEvent(int EventType, std::string="NULL", int=NULL);
|
void SendEvent(int EventType, std::string="NULL", int=NULL);
|
||||||
void AppendText(const wxString text);
|
void AppendText(const wxString text);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NetPlay *m_netptr;
|
NetPlay *m_netptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServerSide : public wxThread
|
class ServerSide : public wxThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
|
ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
|
||||||
~ServerSide() {};
|
~ServerSide() {};
|
||||||
|
|
||||||
virtual void *Entry();
|
virtual void *Entry();
|
||||||
|
|
||||||
void Write(int socknb, const char *data, size_t size, long *ping=NULL);
|
void Write(int socknb, const char *data, size_t size, long *ping=NULL);
|
||||||
void WriteUDP(int socknb, const char *data, size_t size);
|
void WriteUDP(int socknb, const char *data, size_t size);
|
||||||
bool isNewPadData(u32 *netValues, bool current, int client=0);
|
bool isNewPadData(u32 *netValues, bool current, int client=0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool SyncValues(unsigned char, sf::IPAddress);
|
bool SyncValues(unsigned char, sf::IPAddress);
|
||||||
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
|
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
|
||||||
char GetSocket(sf::SocketTCP Socket);
|
char GetSocket(sf::SocketTCP Socket);
|
||||||
void OnServerData(int sock, unsigned char data);
|
void OnServerData(int sock, unsigned char data);
|
||||||
void IsEveryoneReady();
|
void IsEveryoneReady();
|
||||||
|
|
||||||
NetPlay *m_netptr;
|
NetPlay *m_netptr;
|
||||||
NetEvent *Event;
|
NetEvent *Event;
|
||||||
|
|
||||||
u32 m_netvalues[3][3];
|
u32 m_netvalues[3][3];
|
||||||
bool m_data_received; // New Pad data received ?
|
bool m_data_received; // New Pad data received ?
|
||||||
|
|
||||||
unsigned char m_numplayers;
|
unsigned char m_numplayers;
|
||||||
int m_netmodel;
|
int m_netmodel;
|
||||||
std::string m_nick;
|
std::string m_nick;
|
||||||
|
|
||||||
Clients m_client[3]; // Connected client objects
|
Clients m_client[3]; // Connected client objects
|
||||||
sf::SelectorTCP m_selector;
|
sf::SelectorTCP m_selector;
|
||||||
sf::SocketTCP m_socket; // Server 'listening' socket
|
sf::SocketTCP m_socket; // Server 'listening' socket
|
||||||
sf::SocketUDP m_socketUDP;
|
sf::SocketUDP m_socketUDP;
|
||||||
|
|
||||||
wxCriticalSection m_CriticalSection;
|
wxCriticalSection m_CriticalSection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClientSide : public wxThread
|
class ClientSide : public wxThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
|
ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
|
||||||
~ClientSide() {}
|
~ClientSide() {}
|
||||||
|
|
||||||
virtual void *Entry();
|
virtual void *Entry();
|
||||||
|
|
||||||
void Write(const char *data, size_t size, long *ping=NULL);
|
void Write(const char *data, size_t size, long *ping=NULL);
|
||||||
void WriteUDP(const char *data, size_t size);
|
void WriteUDP(const char *data, size_t size);
|
||||||
bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
|
bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool SyncValues();
|
bool SyncValues();
|
||||||
void CheckGameFound();
|
void CheckGameFound();
|
||||||
void OnClientData(unsigned char data);
|
void OnClientData(unsigned char data);
|
||||||
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
|
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
|
||||||
|
|
||||||
NetPlay *m_netptr;
|
NetPlay *m_netptr;
|
||||||
NetEvent *Event;
|
NetEvent *Event;
|
||||||
|
|
||||||
u32 m_netvalues[3][3];
|
u32 m_netvalues[3][3];
|
||||||
bool m_data_received; // New Pad data received ?
|
bool m_data_received; // New Pad data received ?
|
||||||
|
|
||||||
unsigned char m_numplayers;
|
unsigned char m_numplayers;
|
||||||
int m_netmodel;
|
int m_netmodel;
|
||||||
std::string m_nick;
|
std::string m_nick;
|
||||||
std::string m_hostnick;
|
std::string m_hostnick;
|
||||||
std::string m_selectedgame;
|
std::string m_selectedgame;
|
||||||
|
|
||||||
sf::SelectorTCP m_selector;
|
sf::SelectorTCP m_selector;
|
||||||
sf::SocketTCP m_socket; // Client I/O socket
|
sf::SocketTCP m_socket; // Client I/O socket
|
||||||
sf::SocketUDP m_socketUDP;
|
sf::SocketUDP m_socketUDP;
|
||||||
unsigned short m_port;
|
unsigned short m_port;
|
||||||
std::string m_addr; // Contains the server addr
|
std::string m_addr; // Contains the server addr
|
||||||
|
|
||||||
wxCriticalSection m_CriticalSection;
|
wxCriticalSection m_CriticalSection;
|
||||||
};
|
};
|
||||||
|
|
||||||
class NetPlay : public wxFrame
|
class NetPlay : public wxFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
|
NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
|
||||||
~NetPlay();
|
~NetPlay();
|
||||||
|
|
||||||
void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
|
void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
|
||||||
void AppendText(const wxString text) { m_Logging->AppendText(text); }
|
void AppendText(const wxString text) { m_Logging->AppendText(text); }
|
||||||
|
|
||||||
// Send and receive pads values
|
// Send and receive pads values
|
||||||
bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
|
bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
|
||||||
void ChangeSelectedGame(std::string game);
|
void ChangeSelectedGame(std::string game);
|
||||||
void IsGameFound(unsigned char*, std::string);
|
void IsGameFound(unsigned char*, std::string);
|
||||||
std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
|
std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
|
||||||
|
|
||||||
void LoadGame();
|
void LoadGame();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Protects our vars from being fuxored by threads
|
// Protects our vars from being fuxored by threads
|
||||||
wxCriticalSection m_critical;
|
wxCriticalSection m_critical;
|
||||||
|
|
||||||
// this draws the GUI, ya rly
|
// this draws the GUI, ya rly
|
||||||
void DrawGUI();
|
void DrawGUI();
|
||||||
void DrawNetWindow();
|
void DrawNetWindow();
|
||||||
|
|
||||||
// event handlers
|
// event handlers
|
||||||
void OnGUIEvent(wxCommandEvent& event);
|
void OnGUIEvent(wxCommandEvent& event);
|
||||||
void OnDisconnect(wxCommandEvent& event);
|
void OnDisconnect(wxCommandEvent& event);
|
||||||
void OnNetEvent(wxCommandEvent& event);
|
void OnNetEvent(wxCommandEvent& event);
|
||||||
void OnQuit(wxCloseEvent& event);
|
void OnQuit(wxCloseEvent& event);
|
||||||
|
|
||||||
void OnJoin(wxCommandEvent& event);
|
void OnJoin(wxCommandEvent& event);
|
||||||
void OnHost(wxCommandEvent& event);
|
void OnHost(wxCommandEvent& event);
|
||||||
|
|
||||||
// Net play vars (used ingame)
|
// Net play vars (used ingame)
|
||||||
int m_frame;
|
int m_frame;
|
||||||
int m_lastframe;
|
int m_lastframe;
|
||||||
Common::Timer m_timer;
|
Common::Timer m_timer;
|
||||||
int m_loopframe;
|
int m_loopframe;
|
||||||
int m_frameDelay;
|
int m_frameDelay;
|
||||||
bool m_data_received;// True if first frame data received
|
bool m_data_received;// True if first frame data received
|
||||||
|
|
||||||
// Basic vars
|
// Basic vars
|
||||||
std::string m_paths; // Game paths list
|
std::string m_paths; // Game paths list
|
||||||
std::string m_games; // Game names list
|
std::string m_games; // Game names list
|
||||||
|
|
||||||
std::string m_selectedGame;// Selected game's string
|
std::string m_selectedGame;// Selected game's string
|
||||||
std::string m_hostaddr; // Used with OnGetIP to cache it
|
std::string m_hostaddr; // Used with OnGetIP to cache it
|
||||||
bool m_ready, m_clients_ready;
|
bool m_ready, m_clients_ready;
|
||||||
std::string m_nick;
|
std::string m_nick;
|
||||||
|
|
||||||
int m_NetModel; // Using P2P model (0) or Server model (1)
|
int m_NetModel; // Using P2P model (0) or Server model (1)
|
||||||
int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
|
int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
|
||||||
unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
|
unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
|
||||||
std::string m_address; // The address entered into connection box
|
std::string m_address; // The address entered into connection box
|
||||||
unsigned short m_port;
|
unsigned short m_port;
|
||||||
|
|
||||||
Netpads m_pads[4]; // this struct is used to save synced pad values
|
Netpads m_pads[4]; // this struct is used to save synced pad values
|
||||||
IniFile ConfigIni;
|
IniFile ConfigIni;
|
||||||
|
|
||||||
// Sockets objects
|
// Sockets objects
|
||||||
ServerSide *m_sock_server;
|
ServerSide *m_sock_server;
|
||||||
ClientSide *m_sock_client;
|
ClientSide *m_sock_client;
|
||||||
|
|
||||||
// -----------
|
// -----------
|
||||||
// GUI objects
|
// GUI objects
|
||||||
// -----------
|
// -----------
|
||||||
wxNotebook *m_Notebook;
|
wxNotebook *m_Notebook;
|
||||||
wxPanel *m_Tab_Connect;
|
wxPanel *m_Tab_Connect;
|
||||||
wxPanel *m_Tab_Host;
|
wxPanel *m_Tab_Host;
|
||||||
wxStaticText *m_SetNick_text;
|
wxStaticText *m_SetNick_text;
|
||||||
wxTextCtrl *m_SetNick;
|
wxTextCtrl *m_SetNick;
|
||||||
wxChoice *m_NetMode;
|
wxChoice *m_NetMode;
|
||||||
|
|
||||||
// Host tab :
|
// Host tab :
|
||||||
wxArrayString m_GameList_str;
|
wxArrayString m_GameList_str;
|
||||||
wxStaticText *m_GameList_text;
|
wxStaticText *m_GameList_text;
|
||||||
wxListBox *m_GameList;
|
wxListBox *m_GameList;
|
||||||
wxStaticText *m_SetPort_text;
|
wxStaticText *m_SetPort_text;
|
||||||
wxTextCtrl *m_SetPort;
|
wxTextCtrl *m_SetPort;
|
||||||
wxButton *m_HostGame;
|
wxButton *m_HostGame;
|
||||||
|
|
||||||
// Connect tab :
|
// Connect tab :
|
||||||
wxTextCtrl *m_ConAddr;
|
wxTextCtrl *m_ConAddr;
|
||||||
wxStaticText *m_ConAddr_text;
|
wxStaticText *m_ConAddr_text;
|
||||||
wxButton *m_JoinGame;
|
wxButton *m_JoinGame;
|
||||||
wxCheckBox *m_UseRandomPort;
|
wxCheckBox *m_UseRandomPort;
|
||||||
|
|
||||||
// Connection window
|
// Connection window
|
||||||
wxButton *m_Game_str;
|
wxButton *m_Game_str;
|
||||||
wxTextCtrl *m_Logging;
|
wxTextCtrl *m_Logging;
|
||||||
wxTextCtrl *m_Chat;
|
wxTextCtrl *m_Chat;
|
||||||
wxButton *m_Chat_ok;
|
wxButton *m_Chat_ok;
|
||||||
// Right part
|
// Right part
|
||||||
wxButton *m_wtfismyip;
|
wxButton *m_wtfismyip;
|
||||||
wxButton *m_ChangeGame;
|
wxButton *m_ChangeGame;
|
||||||
// Left Part
|
// Left Part
|
||||||
wxButton *m_Disconnect;
|
wxButton *m_Disconnect;
|
||||||
wxStaticText *m_ConInfo_text;
|
wxStaticText *m_ConInfo_text;
|
||||||
wxButton *m_GetPing;
|
wxButton *m_GetPing;
|
||||||
wxCheckBox *m_Ready;
|
wxCheckBox *m_Ready;
|
||||||
wxCheckBox *m_RecordGame;
|
wxCheckBox *m_RecordGame;
|
||||||
|
|
||||||
// wxWidgets event table
|
// wxWidgets event table
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
class GameListPopup : public wxDialog
|
class GameListPopup : public wxDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
|
GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
|
||||||
~GameListPopup() {}
|
~GameListPopup() {}
|
||||||
protected:
|
protected:
|
||||||
void OnButtons(wxCommandEvent& event);
|
void OnButtons(wxCommandEvent& event);
|
||||||
wxArrayString m_GameList_str;
|
wxArrayString m_GameList_str;
|
||||||
NetPlay* m_netParent;
|
NetPlay* m_netParent;
|
||||||
wxListBox *m_GameList;
|
wxListBox *m_GameList;
|
||||||
wxButton *m_Accept;
|
wxButton *m_Accept;
|
||||||
wxButton *m_Cancel;
|
wxButton *m_Cancel;
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
ID_NOTEBOOK,
|
ID_NOTEBOOK,
|
||||||
ID_TAB_HOST,
|
ID_TAB_HOST,
|
||||||
ID_TAB_CONN,
|
ID_TAB_CONN,
|
||||||
ID_BUTTON_HOST,
|
ID_BUTTON_HOST,
|
||||||
ID_BUTTON_JOIN,
|
ID_BUTTON_JOIN,
|
||||||
ID_NETMODE,
|
ID_NETMODE,
|
||||||
ID_GAMELIST,
|
ID_GAMELIST,
|
||||||
ID_LOGGING_TXT,
|
ID_LOGGING_TXT,
|
||||||
ID_CHAT,
|
ID_CHAT,
|
||||||
ID_SETNICK,
|
ID_SETNICK,
|
||||||
ID_SETPORT,
|
ID_SETPORT,
|
||||||
ID_CONNADDR,
|
ID_CONNADDR,
|
||||||
ID_CONNINFO_TXT,
|
ID_CONNINFO_TXT,
|
||||||
ID_USE_RANDOMPORT,
|
ID_USE_RANDOMPORT,
|
||||||
ID_BUTTON_GETPING,
|
ID_BUTTON_GETPING,
|
||||||
ID_BUTTON_GETIP,
|
ID_BUTTON_GETIP,
|
||||||
ID_CHANGEGAME,
|
ID_CHANGEGAME,
|
||||||
ID_BUTTON_QUIT,
|
ID_BUTTON_QUIT,
|
||||||
ID_BUTTON_CHAT,
|
ID_BUTTON_CHAT,
|
||||||
ID_READY,
|
ID_READY,
|
||||||
ID_RECORD,
|
ID_RECORD,
|
||||||
|
|
||||||
ID_SOCKET,
|
ID_SOCKET,
|
||||||
ID_SERVER,
|
ID_SERVER,
|
||||||
|
|
||||||
HOST_FULL = 200, // ...
|
HOST_FULL = 200, // ...
|
||||||
HOST_ERROR, // Sent on socket error
|
HOST_ERROR, // Sent on socket error
|
||||||
HOST_DISCONNECTED,
|
HOST_DISCONNECTED,
|
||||||
HOST_NEWPLAYER,
|
HOST_NEWPLAYER,
|
||||||
HOST_PLAYERLEFT,
|
HOST_PLAYERLEFT,
|
||||||
CLIENTS_READY,
|
CLIENTS_READY,
|
||||||
CLIENTS_NOTREADY,
|
CLIENTS_NOTREADY,
|
||||||
GUI_UPDATE, // Refresh the shown selectedgame on GUI
|
GUI_UPDATE, // Refresh the shown selectedgame on GUI
|
||||||
ADD_TEXT, // Add text to m_Logging (string)
|
ADD_TEXT, // Add text to m_Logging (string)
|
||||||
ADD_INFO, // Sent when updating net infos (string)
|
ADD_INFO, // Sent when updating net infos (string)
|
||||||
NET_EVENT
|
NET_EVENT
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _NETWINDOW_H_
|
#endif // _NETWINDOW_H_
|
||||||
|
|
||||||
|
|
|
@ -1,127 +1,127 @@
|
||||||
// Copyright (C) 2003-2008 Dolphin Project.
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef __SUMMARIZE_H__
|
#ifndef __SUMMARIZE_H__
|
||||||
#define __SUMMARIZE_H__
|
#define __SUMMARIZE_H__
|
||||||
|
|
||||||
std::string Summarize_Plug()
|
std::string Summarize_Plug()
|
||||||
{
|
{
|
||||||
return StringFromFormat(
|
return StringFromFormat(
|
||||||
"Plugin Information\n\n"
|
"Plugin Information\n\n"
|
||||||
"Default GFX Plugin: %s\n"
|
"Default GFX Plugin: %s\n"
|
||||||
"Default DSP Plugin: %s\n"
|
"Default DSP Plugin: %s\n"
|
||||||
"Default PAD Plugin: %s\n"
|
"Default PAD Plugin: %s\n"
|
||||||
"Default WiiMote Plugin: %s\n\n"
|
"Default WiiMote Plugin: %s\n\n"
|
||||||
"Current GFX Plugin: %s\n"
|
"Current GFX Plugin: %s\n"
|
||||||
"Current DSP Plugin: %s\n"
|
"Current DSP Plugin: %s\n"
|
||||||
"Current PAD Plugin[0]: %s\n"
|
"Current PAD Plugin[0]: %s\n"
|
||||||
"Current PAD Plugin[1]: %s\n"
|
"Current PAD Plugin[1]: %s\n"
|
||||||
"Current PAD Plugin[2]: %s\n"
|
"Current PAD Plugin[2]: %s\n"
|
||||||
"Current PAD Plugin[3]: %s\n"
|
"Current PAD Plugin[3]: %s\n"
|
||||||
"Current WiiMote Plugin[0]: %s\n",
|
"Current WiiMote Plugin[0]: %s\n",
|
||||||
SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
|
SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
|
||||||
SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
|
SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
|
||||||
SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
|
SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
|
||||||
SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
|
SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
|
||||||
Core::GetStartupParameter().m_strVideoPlugin.c_str(),
|
Core::GetStartupParameter().m_strVideoPlugin.c_str(),
|
||||||
Core::GetStartupParameter().m_strDSPPlugin.c_str(),
|
Core::GetStartupParameter().m_strDSPPlugin.c_str(),
|
||||||
Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
|
Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
|
||||||
Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
|
Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
|
||||||
Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
|
Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
|
||||||
Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
|
Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
|
||||||
Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
|
Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Summarize_Settings()
|
std::string Summarize_Settings()
|
||||||
{
|
{
|
||||||
return StringFromFormat(
|
return StringFromFormat(
|
||||||
"Dolphin Settings\n\n"
|
"Dolphin Settings\n\n"
|
||||||
"Always HLE Bios: %s\n"
|
"Always HLE Bios: %s\n"
|
||||||
"Use Dynarec: %s\n"
|
"Use Dynarec: %s\n"
|
||||||
"Use Dual Core: %s\n"
|
"Use Dual Core: %s\n"
|
||||||
"DSP Thread: %s\n"
|
"DSP Thread: %s\n"
|
||||||
"Skip Idle: %s\n"
|
"Skip Idle: %s\n"
|
||||||
"Lock Threads: %s\n"
|
"Lock Threads: %s\n"
|
||||||
"Use Dual Core: %s\n"
|
"Use Dual Core: %s\n"
|
||||||
"Default GCM: %s\n"
|
"Default GCM: %s\n"
|
||||||
"DVD Root: %s\n"
|
"DVD Root: %s\n"
|
||||||
"Optimize Quantizers: %s\n"
|
"Optimize Quantizers: %s\n"
|
||||||
"Enable Cheats: %s\n"
|
"Enable Cheats: %s\n"
|
||||||
"Selected Language: %d\n"
|
"Selected Language: %d\n"
|
||||||
"Memcard A: %s\n"
|
"Memcard A: %s\n"
|
||||||
"Memcard B: %s\n"
|
"Memcard B: %s\n"
|
||||||
"Slot A: %d\n"
|
"Slot A: %d\n"
|
||||||
"Slot B: %d\n"
|
"Slot B: %d\n"
|
||||||
"Serial Port 1: %d\n"
|
"Serial Port 1: %d\n"
|
||||||
"Run Compare Server: %s\n"
|
"Run Compare Server: %s\n"
|
||||||
"Run Compare Client: %s\n"
|
"Run Compare Client: %s\n"
|
||||||
"TLB Hack: %s\n"
|
"TLB Hack: %s\n"
|
||||||
"Frame Limit: %d\n"
|
"Frame Limit: %d\n"
|
||||||
"[Wii]Widescreen: %s\n"
|
"[Wii]Widescreen: %s\n"
|
||||||
"[Wii]Progressive Scan: %s\n",
|
"[Wii]Progressive Scan: %s\n",
|
||||||
Core::GetStartupParameter().bHLEBios?"True":"False",
|
Core::GetStartupParameter().bHLEBios?"True":"False",
|
||||||
Core::GetStartupParameter().bUseJIT?"True":"False",
|
Core::GetStartupParameter().bUseJIT?"True":"False",
|
||||||
Core::GetStartupParameter().bUseDualCore?"True":"False",
|
Core::GetStartupParameter().bUseDualCore?"True":"False",
|
||||||
Core::GetStartupParameter().bDSPThread?"True":"False",
|
Core::GetStartupParameter().bDSPThread?"True":"False",
|
||||||
Core::GetStartupParameter().bSkipIdle?"True":"False",
|
Core::GetStartupParameter().bSkipIdle?"True":"False",
|
||||||
Core::GetStartupParameter().bLockThreads?"True":"False",
|
Core::GetStartupParameter().bLockThreads?"True":"False",
|
||||||
Core::GetStartupParameter().bUseDualCore?"True":"False",
|
Core::GetStartupParameter().bUseDualCore?"True":"False",
|
||||||
Core::GetStartupParameter().m_strDefaultGCM.c_str(),
|
Core::GetStartupParameter().m_strDefaultGCM.c_str(),
|
||||||
Core::GetStartupParameter().m_strDVDRoot.c_str(),
|
Core::GetStartupParameter().m_strDVDRoot.c_str(),
|
||||||
Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
|
Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
|
||||||
Core::GetStartupParameter().bEnableCheats?"True":"False",
|
Core::GetStartupParameter().bEnableCheats?"True":"False",
|
||||||
Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
|
Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
|
||||||
SConfig::GetInstance().m_strMemoryCardA.c_str(),
|
SConfig::GetInstance().m_strMemoryCardA.c_str(),
|
||||||
SConfig::GetInstance().m_strMemoryCardB.c_str(),
|
SConfig::GetInstance().m_strMemoryCardB.c_str(),
|
||||||
SConfig::GetInstance().m_EXIDevice[0], //FIXME
|
SConfig::GetInstance().m_EXIDevice[0], //FIXME
|
||||||
SConfig::GetInstance().m_EXIDevice[1], //FIXME
|
SConfig::GetInstance().m_EXIDevice[1], //FIXME
|
||||||
SConfig::GetInstance().m_EXIDevice[2], //FIXME
|
SConfig::GetInstance().m_EXIDevice[2], //FIXME
|
||||||
Core::GetStartupParameter().bRunCompareServer?"True":"False",
|
Core::GetStartupParameter().bRunCompareServer?"True":"False",
|
||||||
Core::GetStartupParameter().bRunCompareClient?"True":"False",
|
Core::GetStartupParameter().bRunCompareClient?"True":"False",
|
||||||
Core::GetStartupParameter().iTLBHack?"True":"False",
|
Core::GetStartupParameter().iTLBHack?"True":"False",
|
||||||
SConfig::GetInstance().m_Framelimit*5,
|
SConfig::GetInstance().m_Framelimit*5,
|
||||||
Core::GetStartupParameter().bWidescreen?"True":"False",
|
Core::GetStartupParameter().bWidescreen?"True":"False",
|
||||||
Core::GetStartupParameter().bProgressiveScan?"True":"False"
|
Core::GetStartupParameter().bProgressiveScan?"True":"False"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Summarize_CPU()
|
std::string Summarize_CPU()
|
||||||
{
|
{
|
||||||
return StringFromFormat(
|
return StringFromFormat(
|
||||||
"Processor Information: \n%s\n",
|
"Processor Information: \n%s\n",
|
||||||
cpu_info.Summarize().c_str()
|
cpu_info.Summarize().c_str()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Summarize_Drives()
|
std::string Summarize_Drives()
|
||||||
{
|
{
|
||||||
char ** drives = cdio_get_devices();
|
char ** drives = cdio_get_devices();
|
||||||
std::string drive;
|
std::string drive;
|
||||||
for (int i = 0; drives[i] != NULL && i < 24; i++)
|
for (int i = 0; drives[i] != NULL && i < 24; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
drive += StringFromFormat(
|
drive += StringFromFormat(
|
||||||
"CD/DVD Drive%d: %s\n",
|
"CD/DVD Drive%d: %s\n",
|
||||||
i+1,
|
i+1,
|
||||||
drives[i]
|
drives[i]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return drive;
|
return drive;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //__SUMMARIZE_H__
|
#endif //__SUMMARIZE_H__
|
|
@ -1,129 +1,129 @@
|
||||||
/* XPM */
|
/* XPM */
|
||||||
static const char *Dolphin_xpm[] = {
|
static const char *Dolphin_xpm[] = {
|
||||||
"32 32 94 2",
|
"32 32 94 2",
|
||||||
" c None",
|
" c None",
|
||||||
". c #000000",
|
". c #000000",
|
||||||
"+ c #1A496C",
|
"+ c #1A496C",
|
||||||
"@ c #091A27",
|
"@ c #091A27",
|
||||||
"# c #3AA4F0",
|
"# c #3AA4F0",
|
||||||
"$ c #3AA3EF",
|
"$ c #3AA3EF",
|
||||||
"% c #3CA1EA",
|
"% c #3CA1EA",
|
||||||
"& c #1A4A6D",
|
"& c #1A4A6D",
|
||||||
"* c #3AA2ED",
|
"* c #3AA2ED",
|
||||||
"= c #F7FAFA",
|
"= c #F7FAFA",
|
||||||
"- c #FFFFFF",
|
"- c #FFFFFF",
|
||||||
"; c #FDFDFD",
|
"; c #FDFDFD",
|
||||||
"> c #49A1E0",
|
"> c #49A1E0",
|
||||||
", c #3BA2EC",
|
", c #3BA2EC",
|
||||||
"' c #FBFDFC",
|
"' c #FBFDFC",
|
||||||
") c #FEFFFD",
|
") c #FEFFFD",
|
||||||
"! c #4EA3E0",
|
"! c #4EA3E0",
|
||||||
"~ c #3DA1E9",
|
"~ c #3DA1E9",
|
||||||
"{ c #D1E1EB",
|
"{ c #D1E1EB",
|
||||||
"] c #8ABBDE",
|
"] c #8ABBDE",
|
||||||
"^ c #F2F6F7",
|
"^ c #F2F6F7",
|
||||||
"/ c #FAFBFC",
|
"/ c #FAFBFC",
|
||||||
"( c #CEDEEA",
|
"( c #CEDEEA",
|
||||||
"_ c #E5EEF2",
|
"_ c #E5EEF2",
|
||||||
": c #BBD2E1",
|
": c #BBD2E1",
|
||||||
"< c #B3CFE5",
|
"< c #B3CFE5",
|
||||||
"[ c #FFFFFE",
|
"[ c #FFFFFE",
|
||||||
"} c #FEFFFE",
|
"} c #FEFFFE",
|
||||||
"| c #E8F0F3",
|
"| c #E8F0F3",
|
||||||
"1 c #E4ECF1",
|
"1 c #E4ECF1",
|
||||||
"2 c #E5EDF0",
|
"2 c #E5EDF0",
|
||||||
"3 c #E9F0F3",
|
"3 c #E9F0F3",
|
||||||
"4 c #FEFEFE",
|
"4 c #FEFEFE",
|
||||||
"5 c #F9FBFB",
|
"5 c #F9FBFB",
|
||||||
"6 c #B0CCE0",
|
"6 c #B0CCE0",
|
||||||
"7 c #FEFEFF",
|
"7 c #FEFEFF",
|
||||||
"8 c #F9FAFB",
|
"8 c #F9FAFB",
|
||||||
"9 c #43A1E4",
|
"9 c #43A1E4",
|
||||||
"0 c #EFF3F6",
|
"0 c #EFF3F6",
|
||||||
"a c #F0F5F7",
|
"a c #F0F5F7",
|
||||||
"b c #97C1DE",
|
"b c #97C1DE",
|
||||||
"c c #FEFEFD",
|
"c c #FEFEFD",
|
||||||
"d c #FDFDFC",
|
"d c #FDFDFC",
|
||||||
"e c #97BEDB",
|
"e c #97BEDB",
|
||||||
"f c #FBFCFC",
|
"f c #FBFCFC",
|
||||||
"g c #EDF3F6",
|
"g c #EDF3F6",
|
||||||
"h c #6EADDA",
|
"h c #6EADDA",
|
||||||
"i c #F3F6F8",
|
"i c #F3F6F8",
|
||||||
"j c #3BA1EA",
|
"j c #3BA1EA",
|
||||||
"k c #6EADDB",
|
"k c #6EADDB",
|
||||||
"l c #F4F8F9",
|
"l c #F4F8F9",
|
||||||
"m c #F1F6F7",
|
"m c #F1F6F7",
|
||||||
"n c #3FA1E7",
|
"n c #3FA1E7",
|
||||||
"o c #9BC1DD",
|
"o c #9BC1DD",
|
||||||
"p c #FCFDFC",
|
"p c #FCFDFC",
|
||||||
"q c #FBFDFB",
|
"q c #FBFDFB",
|
||||||
"r c #B9D1E1",
|
"r c #B9D1E1",
|
||||||
"s c #E0EBF2",
|
"s c #E0EBF2",
|
||||||
"t c #D3E3EF",
|
"t c #D3E3EF",
|
||||||
"u c #FFFEFE",
|
"u c #FFFEFE",
|
||||||
"v c #F2F7F7",
|
"v c #F2F7F7",
|
||||||
"w c #D5E4F0",
|
"w c #D5E4F0",
|
||||||
"x c #F6F9F9",
|
"x c #F6F9F9",
|
||||||
"y c #BDD5E5",
|
"y c #BDD5E5",
|
||||||
"z c #EBF1F4",
|
"z c #EBF1F4",
|
||||||
"A c #DEEAF2",
|
"A c #DEEAF2",
|
||||||
"B c #AAC9DE",
|
"B c #AAC9DE",
|
||||||
"C c #FEFFFF",
|
"C c #FEFFFF",
|
||||||
"D c #EFF4F6",
|
"D c #EFF4F6",
|
||||||
"E c #F8FAFB",
|
"E c #F8FAFB",
|
||||||
"F c #A0C4E1",
|
"F c #A0C4E1",
|
||||||
"G c #D6E5F0",
|
"G c #D6E5F0",
|
||||||
"H c #FAFCFC",
|
"H c #FAFCFC",
|
||||||
"I c #BDD5E7",
|
"I c #BDD5E7",
|
||||||
"J c #EEF3F7",
|
"J c #EEF3F7",
|
||||||
"K c #F3F7FA",
|
"K c #F3F7FA",
|
||||||
"L c #C7D8E4",
|
"L c #C7D8E4",
|
||||||
"M c #CDDEEC",
|
"M c #CDDEEC",
|
||||||
"N c #DAE6ED",
|
"N c #DAE6ED",
|
||||||
"O c #9AC2DF",
|
"O c #9AC2DF",
|
||||||
"P c #E8EFF4",
|
"P c #E8EFF4",
|
||||||
"Q c #ACCDE3",
|
"Q c #ACCDE3",
|
||||||
"R c #8DBBDC",
|
"R c #8DBBDC",
|
||||||
"S c #D5E3EB",
|
"S c #D5E3EB",
|
||||||
"T c #FDFFFE",
|
"T c #FDFFFE",
|
||||||
"U c #FCFDFD",
|
"U c #FCFDFD",
|
||||||
"V c #FEFDFD",
|
"V c #FEFDFD",
|
||||||
"W c #F7F9FA",
|
"W c #F7F9FA",
|
||||||
"X c #FDFEFD",
|
"X c #FDFEFD",
|
||||||
"Y c #E7EFF4",
|
"Y c #E7EFF4",
|
||||||
"Z c #A4C7E0",
|
"Z c #A4C7E0",
|
||||||
"` c #F9FDFB",
|
"` c #F9FDFB",
|
||||||
" . c #F6FBFC",
|
" . c #F6FBFC",
|
||||||
".. c #B8D1E3",
|
".. c #B8D1E3",
|
||||||
" . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
|
" . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
|
||||||
". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
|
". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
|
||||||
". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
|
". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
|
||||||
"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
|
"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
|
||||||
". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
|
". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
|
||||||
". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
|
". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
|
||||||
". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
|
". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
|
||||||
". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
|
". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
|
||||||
". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
|
". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
|
||||||
". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
|
". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
|
||||||
". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
|
". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
|
||||||
". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
|
". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
|
||||||
". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
|
". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
|
||||||
". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
|
". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
|
||||||
". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
|
". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
|
||||||
". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
|
". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
|
||||||
". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
|
". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
|
||||||
". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
|
". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
|
||||||
". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
|
". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
|
||||||
". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
|
". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
|
||||||
". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
|
". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
|
||||||
". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
|
". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
|
||||||
". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
|
". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
|
||||||
". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
|
". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
|
||||||
". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
|
". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
|
||||||
". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
|
". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
|
||||||
". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
|
". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
|
||||||
". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
|
". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
|
||||||
" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
|
" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
|
||||||
" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
|
" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
|
||||||
" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
|
" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
|
||||||
" . . . . . . . . . . . . . . . . . . . . . . . . "};
|
" . . . . . . . . . . . . . . . . . . . . . . . . "};
|
||||||
|
|
|
@ -1,83 +1,83 @@
|
||||||
/* XPM */
|
/* XPM */
|
||||||
static const char *const Flag_Europe_xpm[] = {
|
static const char *const Flag_Europe_xpm[] = {
|
||||||
"96 32 48 1",
|
"96 32 48 1",
|
||||||
" c None",
|
" c None",
|
||||||
". c #000000",
|
". c #000000",
|
||||||
"+ c #0000FD",
|
"+ c #0000FD",
|
||||||
"@ c #0000FF",
|
"@ c #0000FF",
|
||||||
"# c #0808F7",
|
"# c #0808F7",
|
||||||
"$ c #5C5CA3",
|
"$ c #5C5CA3",
|
||||||
"% c #1717E8",
|
"% c #1717E8",
|
||||||
"& c #767680",
|
"& c #767680",
|
||||||
"* c #EDED00",
|
"* c #EDED00",
|
||||||
"= c #A5A54D",
|
"= c #A5A54D",
|
||||||
"- c #2E2EB9",
|
"- c #2E2EB9",
|
||||||
"; c #96961A",
|
"; c #96961A",
|
||||||
"> c #4A4A8E",
|
"> c #4A4A8E",
|
||||||
", c #0000FB",
|
", c #0000FB",
|
||||||
"' c #0000F4",
|
"' c #0000F4",
|
||||||
") c #0808EC",
|
") c #0808EC",
|
||||||
"! c #5C5C9B",
|
"! c #5C5C9B",
|
||||||
"~ c #1717DD",
|
"~ c #1717DD",
|
||||||
"{ c #0000EE",
|
"{ c #0000EE",
|
||||||
"] c #767677",
|
"] c #767677",
|
||||||
"^ c #A5A547",
|
"^ c #A5A547",
|
||||||
"/ c #0000DD",
|
"/ c #0000DD",
|
||||||
"( c #2E2EA0",
|
"( c #2E2EA0",
|
||||||
"_ c #969616",
|
"_ c #969616",
|
||||||
": c #4A4A7B",
|
": c #4A4A7B",
|
||||||
"< c #0000D2",
|
"< c #0000D2",
|
||||||
"[ c #0000C6",
|
"[ c #0000C6",
|
||||||
"} c #0808BF",
|
"} c #0808BF",
|
||||||
"| c #5C5C7E",
|
"| c #5C5C7E",
|
||||||
"1 c #1717B4",
|
"1 c #1717B4",
|
||||||
"2 c #0000B9",
|
"2 c #0000B9",
|
||||||
"3 c #76765C",
|
"3 c #76765C",
|
||||||
"4 c #A5A537",
|
"4 c #A5A537",
|
||||||
"5 c #0808B3",
|
"5 c #0808B3",
|
||||||
"6 c #5C5C76",
|
"6 c #5C5C76",
|
||||||
"7 c #1717A8",
|
"7 c #1717A8",
|
||||||
"8 c #0000A9",
|
"8 c #0000A9",
|
||||||
"9 c #2E2E7A",
|
"9 c #2E2E7A",
|
||||||
"0 c #969611",
|
"0 c #969611",
|
||||||
"a c #4A4A5E",
|
"a c #4A4A5E",
|
||||||
"b c #767654",
|
"b c #767654",
|
||||||
"c c #A5A533",
|
"c c #A5A533",
|
||||||
"d c #000097",
|
"d c #000097",
|
||||||
"e c #2E2E6D",
|
"e c #2E2E6D",
|
||||||
"f c #96960F",
|
"f c #96960F",
|
||||||
"g c #4A4A54",
|
"g c #4A4A54",
|
||||||
"h c #000081",
|
"h c #000081",
|
||||||
"i c #000077",
|
"i c #000077",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
".++++++++++++++++++++++++++++++. ",
|
".++++++++++++++++++++++++++++++. ",
|
||||||
".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
|
".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
|
||||||
".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
|
".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
|
||||||
".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
|
".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
|
||||||
".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
|
".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
|
||||||
".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
|
".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
|
||||||
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
|
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
|
||||||
".''''''')!~''''''''')!~''''''''. ",
|
".''''''')!~''''''''')!~''''''''. ",
|
||||||
".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
|
".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
|
||||||
".///////(_://///////(_:////////. ",
|
".///////(_://///////(_:////////. ",
|
||||||
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
|
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
|
||||||
".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
|
".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
|
||||||
".2222222223*4256723*42222222222. ",
|
".2222222223*4256723*42222222222. ",
|
||||||
".88888888890a8b*c890a8888888888. ",
|
".88888888890a8b*c890a8888888888. ",
|
||||||
".dddddddddddddefgdddddddddddddd. ",
|
".dddddddddddddefgdddddddddddddd. ",
|
||||||
".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
|
".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
|
||||||
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
|
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
|
||||||
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
|
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" "};
|
" "};
|
||||||
|
|
|
@ -1,80 +1,80 @@
|
||||||
/* XPM */
|
/* XPM */
|
||||||
static const char *const Flag_France_xpm[] = {
|
static const char *const Flag_France_xpm[] = {
|
||||||
"96 32 45 1",
|
"96 32 45 1",
|
||||||
" c None",
|
" c None",
|
||||||
". c #000000",
|
". c #000000",
|
||||||
"+ c #0000FF",
|
"+ c #0000FF",
|
||||||
"@ c #FFFFFF",
|
"@ c #FFFFFF",
|
||||||
"# c #FF0000",
|
"# c #FF0000",
|
||||||
"$ c #0000FC",
|
"$ c #0000FC",
|
||||||
"% c #0000F8",
|
"% c #0000F8",
|
||||||
"& c #FCFCFC",
|
"& c #FCFCFC",
|
||||||
"* c #FC0000",
|
"* c #FC0000",
|
||||||
"= c #0000F2",
|
"= c #0000F2",
|
||||||
"- c #F8F8F8",
|
"- c #F8F8F8",
|
||||||
"; c #F80000",
|
"; c #F80000",
|
||||||
"> c #0000EC",
|
"> c #0000EC",
|
||||||
", c #F2F2F2",
|
", c #F2F2F2",
|
||||||
"' c #F20000",
|
"' c #F20000",
|
||||||
") c #0000E3",
|
") c #0000E3",
|
||||||
"! c #ECECEC",
|
"! c #ECECEC",
|
||||||
"~ c #EC0000",
|
"~ c #EC0000",
|
||||||
"{ c #0000DB",
|
"{ c #0000DB",
|
||||||
"] c #E3E3E3",
|
"] c #E3E3E3",
|
||||||
"^ c #E30000",
|
"^ c #E30000",
|
||||||
"/ c #0000D2",
|
"/ c #0000D2",
|
||||||
"( c #DBDBDB",
|
"( c #DBDBDB",
|
||||||
"_ c #DB0000",
|
"_ c #DB0000",
|
||||||
": c #0000C8",
|
": c #0000C8",
|
||||||
"< c #D2D2D2",
|
"< c #D2D2D2",
|
||||||
"[ c #D20000",
|
"[ c #D20000",
|
||||||
"} c #0000BD",
|
"} c #0000BD",
|
||||||
"| c #C8C8C8",
|
"| c #C8C8C8",
|
||||||
"1 c #C80000",
|
"1 c #C80000",
|
||||||
"2 c #0000B1",
|
"2 c #0000B1",
|
||||||
"3 c #BDBDBD",
|
"3 c #BDBDBD",
|
||||||
"4 c #BD0000",
|
"4 c #BD0000",
|
||||||
"5 c #0000A3",
|
"5 c #0000A3",
|
||||||
"6 c #B1B1B1",
|
"6 c #B1B1B1",
|
||||||
"7 c #B10000",
|
"7 c #B10000",
|
||||||
"8 c #000093",
|
"8 c #000093",
|
||||||
"9 c #A3A3A3",
|
"9 c #A3A3A3",
|
||||||
"0 c #A30000",
|
"0 c #A30000",
|
||||||
"a c #000080",
|
"a c #000080",
|
||||||
"b c #939393",
|
"b c #939393",
|
||||||
"c c #930000",
|
"c c #930000",
|
||||||
"d c #000077",
|
"d c #000077",
|
||||||
"e c #808080",
|
"e c #808080",
|
||||||
"f c #800000",
|
"f c #800000",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
".++++++++++@@@@@@@@@@@#########. ",
|
".++++++++++@@@@@@@@@@@#########. ",
|
||||||
".++++++++++@@@@@@@@@@@#########. ",
|
".++++++++++@@@@@@@@@@@#########. ",
|
||||||
".++++++++++@@@@@@@@@@@#########. ",
|
".++++++++++@@@@@@@@@@@#########. ",
|
||||||
".++++++++++@@@@@@@@@@@#########. ",
|
".++++++++++@@@@@@@@@@@#########. ",
|
||||||
".$$$$$$$$$$@@@@@@@@@@@#########. ",
|
".$$$$$$$$$$@@@@@@@@@@@#########. ",
|
||||||
".%%%%%%%%%%&&&&&&&&&&&*********. ",
|
".%%%%%%%%%%&&&&&&&&&&&*********. ",
|
||||||
".==========-----------;;;;;;;;;. ",
|
".==========-----------;;;;;;;;;. ",
|
||||||
".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
|
".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
|
||||||
".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
|
".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
|
||||||
".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
|
".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
|
||||||
".//////////(((((((((((_________. ",
|
".//////////(((((((((((_________. ",
|
||||||
".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
|
".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
|
||||||
".}}}}}}}}}}|||||||||||111111111. ",
|
".}}}}}}}}}}|||||||||||111111111. ",
|
||||||
".222222222233333333333444444444. ",
|
".222222222233333333333444444444. ",
|
||||||
".555555555566666666666777777777. ",
|
".555555555566666666666777777777. ",
|
||||||
".888888888899999999999000000000. ",
|
".888888888899999999999000000000. ",
|
||||||
".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
|
".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
|
||||||
".ddddddddddeeeeeeeeeeefffffffff. ",
|
".ddddddddddeeeeeeeeeeefffffffff. ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" "};
|
" "};
|
||||||
|
|
|
@ -1,102 +1,102 @@
|
||||||
/* XPM */
|
/* XPM */
|
||||||
static const char * const Flag_Japan_xpm[] = {
|
static const char * const Flag_Japan_xpm[] = {
|
||||||
"96 32 67 1",
|
"96 32 67 1",
|
||||||
" c None",
|
" c None",
|
||||||
". c #000000",
|
". c #000000",
|
||||||
"+ c #FFFFFF",
|
"+ c #FFFFFF",
|
||||||
"@ c #FECACA",
|
"@ c #FECACA",
|
||||||
"# c #FD8080",
|
"# c #FD8080",
|
||||||
"$ c #FD6161",
|
"$ c #FD6161",
|
||||||
"% c #FD7676",
|
"% c #FD7676",
|
||||||
"& c #FEB6B6",
|
"& c #FEB6B6",
|
||||||
"* c #FEFEFE",
|
"* c #FEFEFE",
|
||||||
"= c #FFEDED",
|
"= c #FFEDED",
|
||||||
"- c #FF4C4C",
|
"- c #FF4C4C",
|
||||||
"; c #FF0000",
|
"; c #FF0000",
|
||||||
"> c #FF2F2F",
|
"> c #FF2F2F",
|
||||||
", c #FFD7D7",
|
", c #FFD7D7",
|
||||||
"' c #FEF5F5",
|
"' c #FEF5F5",
|
||||||
") c #FE2E2E",
|
") c #FE2E2E",
|
||||||
"! c #FE1313",
|
"! c #FE1313",
|
||||||
"~ c #FEDDDD",
|
"~ c #FEDDDD",
|
||||||
"{ c #F9F9F9",
|
"{ c #F9F9F9",
|
||||||
"] c #FC7777",
|
"] c #FC7777",
|
||||||
"^ c #FD4545",
|
"^ c #FD4545",
|
||||||
"/ c #F4F4F4",
|
"/ c #F4F4F4",
|
||||||
"( c #F4F3F3",
|
"( c #F4F3F3",
|
||||||
"_ c #FA1313",
|
"_ c #FA1313",
|
||||||
": c #FB0000",
|
": c #FB0000",
|
||||||
"< c #FA0000",
|
"< c #FA0000",
|
||||||
"[ c #F4D4D4",
|
"[ c #F4D4D4",
|
||||||
"} c #EFEFEF",
|
"} c #EFEFEF",
|
||||||
"| c #EFCFCF",
|
"| c #EFCFCF",
|
||||||
"1 c #F10000",
|
"1 c #F10000",
|
||||||
"2 c #EF9F9F",
|
"2 c #EF9F9F",
|
||||||
"3 c #E4E4E4",
|
"3 c #E4E4E4",
|
||||||
"4 c #E2BEBE",
|
"4 c #E2BEBE",
|
||||||
"5 c #DD0000",
|
"5 c #DD0000",
|
||||||
"6 c #E19090",
|
"6 c #E19090",
|
||||||
"7 c #D9D9D9",
|
"7 c #D9D9D9",
|
||||||
"8 c #D8D0D0",
|
"8 c #D8D0D0",
|
||||||
"9 c #CA0404",
|
"9 c #CA0404",
|
||||||
"0 c #CA0000",
|
"0 c #CA0000",
|
||||||
"a c #D5A9A9",
|
"a c #D5A9A9",
|
||||||
"b c #D0D0D0",
|
"b c #D0D0D0",
|
||||||
"c c #BC4242",
|
"c c #BC4242",
|
||||||
"d c #B40000",
|
"d c #B40000",
|
||||||
"e c #B71A1A",
|
"e c #B71A1A",
|
||||||
"f c #CFCFCF",
|
"f c #CFCFCF",
|
||||||
"g c #C6C6C6",
|
"g c #C6C6C6",
|
||||||
"h c #BEA7A7",
|
"h c #BEA7A7",
|
||||||
"i c #990808",
|
"i c #990808",
|
||||||
"j c #980000",
|
"j c #980000",
|
||||||
"k c #B78787",
|
"k c #B78787",
|
||||||
"l c #BBBBBB",
|
"l c #BBBBBB",
|
||||||
"m c #A88989",
|
"m c #A88989",
|
||||||
"n c #7B0B0B",
|
"n c #7B0B0B",
|
||||||
"o c #770000",
|
"o c #770000",
|
||||||
"p c #780202",
|
"p c #780202",
|
||||||
"q c #9E6B6B",
|
"q c #9E6B6B",
|
||||||
"r c #AEAEAE",
|
"r c #AEAEAE",
|
||||||
"s c #A89C9C",
|
"s c #A89C9C",
|
||||||
"t c #8F4E4E",
|
"t c #8F4E4E",
|
||||||
"u c #7F1B1B",
|
"u c #7F1B1B",
|
||||||
"v c #7A0A0A",
|
"v c #7A0A0A",
|
||||||
"w c #7D1515",
|
"w c #7D1515",
|
||||||
"x c #8B4242",
|
"x c #8B4242",
|
||||||
"y c #A48F8F",
|
"y c #A48F8F",
|
||||||
"z c #A0A0A0",
|
"z c #A0A0A0",
|
||||||
"A c #8F8F8F",
|
"A c #8F8F8F",
|
||||||
"B c #7C7C7C",
|
"B c #7C7C7C",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
".++++++++++++++++++++++++++++++. ",
|
".++++++++++++++++++++++++++++++. ",
|
||||||
".++++++++++++++++++++++++++++++. ",
|
".++++++++++++++++++++++++++++++. ",
|
||||||
".++++++++++++++++++++++++++++++. ",
|
".++++++++++++++++++++++++++++++. ",
|
||||||
".++++++++++++@#$%&*++++++++++++. ",
|
".++++++++++++@#$%&*++++++++++++. ",
|
||||||
".++++++++++=-;;;;;>,+++++++++++. ",
|
".++++++++++=-;;;;;>,+++++++++++. ",
|
||||||
".*********');;;;;;;!~**********. ",
|
".*********');;;;;;;!~**********. ",
|
||||||
".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
|
".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
|
||||||
".////////(_:::::::::<[/////////. ",
|
".////////(_:::::::::<[/////////. ",
|
||||||
".}}}}}}}}|111111111112}}}}}}}}}. ",
|
".}}}}}}}}|111111111112}}}}}}}}}. ",
|
||||||
".333333334555555555556333333333. ",
|
".333333334555555555556333333333. ",
|
||||||
".77777777890000000000a777777777. ",
|
".77777777890000000000a777777777. ",
|
||||||
".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
|
".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
|
||||||
".ggggggggghijjjjjjjjkgggggggggg. ",
|
".ggggggggghijjjjjjjjkgggggggggg. ",
|
||||||
".llllllllllmnooooopqlllllllllll. ",
|
".llllllllllmnooooopqlllllllllll. ",
|
||||||
".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
|
".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
|
||||||
".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
|
".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
|
||||||
".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
|
".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
|
||||||
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
|
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" "};
|
" "};
|
||||||
|
|
|
@ -1,124 +1,124 @@
|
||||||
/* XPM */
|
/* XPM */
|
||||||
static const char * Flag_Taiwan_xpm[] = {
|
static const char * Flag_Taiwan_xpm[] = {
|
||||||
"96 32 89 1",
|
"96 32 89 1",
|
||||||
" c None",
|
" c None",
|
||||||
". c #000000",
|
". c #000000",
|
||||||
"# c #000099",
|
"# c #000099",
|
||||||
"$ c #000098",
|
"$ c #000098",
|
||||||
"% c #03039A",
|
"% c #03039A",
|
||||||
"& c #000094",
|
"& c #000094",
|
||||||
"' c #05059B",
|
"' c #05059B",
|
||||||
"( c #050095",
|
"( c #050095",
|
||||||
") c #DC0014",
|
") c #DC0014",
|
||||||
"* c #FF0000",
|
"* c #FF0000",
|
||||||
"+ c #FD0001",
|
"+ c #FD0001",
|
||||||
", c #04049B",
|
", c #04049B",
|
||||||
"- c #000096",
|
"- c #000096",
|
||||||
"! c #020299",
|
"! c #020299",
|
||||||
"0 c #2424A7",
|
"0 c #2424A7",
|
||||||
"1 c #04049A",
|
"1 c #04049A",
|
||||||
"2 c #000097",
|
"2 c #000097",
|
||||||
"3 c #000093",
|
"3 c #000093",
|
||||||
"4 c #6262BF",
|
"4 c #6262BF",
|
||||||
"5 c #2828A8",
|
"5 c #2828A8",
|
||||||
"6 c #6C6CC1",
|
"6 c #6C6CC1",
|
||||||
"7 c #3E3EB1",
|
"7 c #3E3EB1",
|
||||||
"8 c #3B3BB0",
|
"8 c #3B3BB0",
|
||||||
"9 c #00008F",
|
"9 c #00008F",
|
||||||
": c #01019A",
|
": c #01019A",
|
||||||
"; c #1919A3",
|
"; c #1919A3",
|
||||||
"< c #4040B0",
|
"< c #4040B0",
|
||||||
"= c #6363C0",
|
"= c #6363C0",
|
||||||
"> c #D6D6EE",
|
"> c #D6D6EE",
|
||||||
"? c #D9D9ED",
|
"? c #D9D9ED",
|
||||||
"@ c #C5C5E7",
|
"@ c #C5C5E7",
|
||||||
"A c #3F3FB0",
|
"A c #3F3FB0",
|
||||||
"B c #3D3DAF",
|
"B c #3D3DAF",
|
||||||
"C c #020297",
|
"C c #020297",
|
||||||
"D c #010199",
|
"D c #010199",
|
||||||
"E c #5E5EBE",
|
"E c #5E5EBE",
|
||||||
"F c #DFDFF2",
|
"F c #DFDFF2",
|
||||||
"G c white",
|
"G c white",
|
||||||
"H c #BFBFE5",
|
"H c #BFBFE5",
|
||||||
"I c #2626A7",
|
"I c #2626A7",
|
||||||
"J c #4242B0",
|
"J c #4242B0",
|
||||||
"K c #7D7DCA",
|
"K c #7D7DCA",
|
||||||
"L c #FAFAFD",
|
"L c #FAFAFD",
|
||||||
"M c #FBFBFD",
|
"M c #FBFBFD",
|
||||||
"N c #FCFCFD",
|
"N c #FCFCFD",
|
||||||
"O c #FCFCFE",
|
"O c #FCFCFE",
|
||||||
"P c #DADAF0",
|
"P c #DADAF0",
|
||||||
"Q c #6A6AC2",
|
"Q c #6A6AC2",
|
||||||
"R c #1B1BA3",
|
"R c #1B1BA3",
|
||||||
"S c #000199",
|
"S c #000199",
|
||||||
"T c #0E0E9B",
|
"T c #0E0E9B",
|
||||||
"U c #5858BC",
|
"U c #5858BC",
|
||||||
"V c #D3D3ED",
|
"V c #D3D3ED",
|
||||||
"W c #2727A6",
|
"W c #2727A6",
|
||||||
"X c #060699",
|
"X c #060699",
|
||||||
"Y c #1212A0",
|
"Y c #1212A0",
|
||||||
"Z c #6464C0",
|
"Z c #6464C0",
|
||||||
"[ c #8080CC",
|
"[ c #8080CC",
|
||||||
"] c #F4F4FA",
|
"] c #F4F4FA",
|
||||||
"^ c #F8F8FB",
|
"^ c #F8F8FB",
|
||||||
"_ c #7070C4",
|
"_ c #7070C4",
|
||||||
"` c #4949B5",
|
"` c #4949B5",
|
||||||
"a c #000095",
|
"a c #000095",
|
||||||
"b c #040499",
|
"b c #040499",
|
||||||
"c c #000092",
|
"c c #000092",
|
||||||
"d c #6767C2",
|
"d c #6767C2",
|
||||||
"e c #8686CA",
|
"e c #8686CA",
|
||||||
"f c #7070C5",
|
"f c #7070C5",
|
||||||
"g c #2B2BA9",
|
"g c #2B2BA9",
|
||||||
"h c #00009A",
|
"h c #00009A",
|
||||||
"i c #01049C",
|
"i c #01049C",
|
||||||
"j c #1619A4",
|
"j c #1619A4",
|
||||||
"k c #393CB3",
|
"k c #393CB3",
|
||||||
"l c #00029A",
|
"l c #00029A",
|
||||||
"m c #1619A5",
|
"m c #1619A5",
|
||||||
"n c #020096",
|
"n c #020096",
|
||||||
"o c #DB0014",
|
"o c #DB0014",
|
||||||
"p c #FC0001",
|
"p c #FC0001",
|
||||||
"q c #0A0092",
|
"q c #0A0092",
|
||||||
"r c #060090",
|
"r c #060090",
|
||||||
"s c #0B0092",
|
"s c #0B0092",
|
||||||
"t c #0F008E",
|
"t c #0F008E",
|
||||||
"u c #DD0013",
|
"u c #DD0013",
|
||||||
"v c #FD0000",
|
"v c #FD0000",
|
||||||
"w c #E5000F",
|
"w c #E5000F",
|
||||||
"x c #E6010F",
|
"x c #E6010F",
|
||||||
"y c #E60110",
|
"y c #E60110",
|
||||||
"z c #FB0002",
|
"z c #FB0002",
|
||||||
"{ c #FE0000",
|
"{ c #FE0000",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
".#####$%#&'$$$##()*+***********. ",
|
".#####$%#&'$$$##()*+***********. ",
|
||||||
".###$$,-!0&1!$##()*+***********. ",
|
".###$$,-!0&1!$##()*+***********. ",
|
||||||
".##$#23456789:$#()*+***********. ",
|
".##$#23456789:$#()*+***********. ",
|
||||||
".###2;<=>?@ABCD#()*+***********. ",
|
".###2;<=>?@ABCD#()*+***********. ",
|
||||||
".###$CEFGGGHI&D$()*+***********. ",
|
".###$CEFGGGHI&D$()*+***********. ",
|
||||||
".##D-JKLMNOPQR-S()*+***********. ",
|
".##D-JKLMNOPQR-S()*+***********. ",
|
||||||
".###$TUGGNGVWX$#()*+***********. ",
|
".###$TUGGNGVWX$#()*+***********. ",
|
||||||
".###2YZ[]^P_`aD$()*+***********. ",
|
".###2YZ[]^P_`aD$()*+***********. ",
|
||||||
".###$bcdEefg3D$#()*+***********. ",
|
".###$bcdEefg3D$#()*+***********. ",
|
||||||
".hhhhhijiklm#hhhno*p***********. ",
|
".hhhhhijiklm#hhhno*p***********. ",
|
||||||
".qqqqqqrsrqrqqqqtu*v***********. ",
|
".qqqqqqrsrqrqqqqtu*v***********. ",
|
||||||
".wwwwwwxwywxwwwwwz*{***********. ",
|
".wwwwwwxwywxwwwwwz*{***********. ",
|
||||||
".******************************. ",
|
".******************************. ",
|
||||||
".{{{{{{{{{{{{{{{{{*{***********. ",
|
".{{{{{{{{{{{{{{{{{*{***********. ",
|
||||||
".******************************. ",
|
".******************************. ",
|
||||||
".******************************. ",
|
".******************************. ",
|
||||||
".******************************. ",
|
".******************************. ",
|
||||||
".******************************. ",
|
".******************************. ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" "};
|
" "};
|
|
@ -1,65 +1,65 @@
|
||||||
/* XPM */
|
/* XPM */
|
||||||
static const char * Flag_USA_xpm[] = {
|
static const char * Flag_USA_xpm[] = {
|
||||||
"96 32 30 1",
|
"96 32 30 1",
|
||||||
" c None",
|
" c None",
|
||||||
". c #000000",
|
". c #000000",
|
||||||
"+ c #0000FF",
|
"+ c #0000FF",
|
||||||
"@ c #CE7070",
|
"@ c #CE7070",
|
||||||
"# c #B0BF99",
|
"# c #B0BF99",
|
||||||
"$ c #F1F1F1",
|
"$ c #F1F1F1",
|
||||||
"% c #FFFFFF",
|
"% c #FFFFFF",
|
||||||
"& c #0000FD",
|
"& c #0000FD",
|
||||||
"* c #CF8484",
|
"* c #CF8484",
|
||||||
"= c #DA9090",
|
"= c #DA9090",
|
||||||
"- c #0000F3",
|
"- c #0000F3",
|
||||||
"; c #B0BF96",
|
"; c #B0BF96",
|
||||||
"> c #0000DF",
|
"> c #0000DF",
|
||||||
", c #0000CB",
|
", c #0000CB",
|
||||||
"' c #B0BF8C",
|
"' c #B0BF8C",
|
||||||
") c #D98E8E",
|
") c #D98E8E",
|
||||||
"! c #0000B5",
|
"! c #0000B5",
|
||||||
"~ c #CA6C6C",
|
"~ c #CA6C6C",
|
||||||
"{ c #000098",
|
"{ c #000098",
|
||||||
"] c #B0BF80",
|
"] c #B0BF80",
|
||||||
"^ c #000077",
|
"^ c #000077",
|
||||||
"/ c #C26464",
|
"/ c #C26464",
|
||||||
"( c #DBDBDB",
|
"( c #DBDBDB",
|
||||||
"_ c #C17676",
|
"_ c #C17676",
|
||||||
": c #B55757",
|
": c #B55757",
|
||||||
"< c #BBBBBB",
|
"< c #BBBBBB",
|
||||||
"[ c #AC6161",
|
"[ c #AC6161",
|
||||||
"} c #A34545",
|
"} c #A34545",
|
||||||
"| c #8B8B8B",
|
"| c #8B8B8B",
|
||||||
"1 c #8E4343",
|
"1 c #8E4343",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
".++++++++++++++@@@@@@@@@@@@@@@@. ",
|
".++++++++++++++@@@@@@@@@@@@@@@@. ",
|
||||||
".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
|
".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
|
||||||
".&&&&&&&&&&&&&&*===============. ",
|
".&&&&&&&&&&&&&&*===============. ",
|
||||||
".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
|
".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
|
||||||
".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
|
".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
|
||||||
".,',',',',',',,*))))))))))))))). ",
|
".,',',',',',',,*))))))))))))))). ",
|
||||||
".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
|
".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
|
||||||
".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
|
".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
|
||||||
".^^^^^^^^^^^^^^****************. ",
|
".^^^^^^^^^^^^^^****************. ",
|
||||||
".^^^^^^^^^^^^^^@///////////////. ",
|
".^^^^^^^^^^^^^^@///////////////. ",
|
||||||
".((((((((((((((((((((((((((((((. ",
|
".((((((((((((((((((((((((((((((. ",
|
||||||
".______________________________. ",
|
".______________________________. ",
|
||||||
".::::::::::::::::::::::::::::::. ",
|
".::::::::::::::::::::::::::::::. ",
|
||||||
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
|
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
|
||||||
".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
|
".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
|
||||||
".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
|
".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
|
||||||
".||||||||||||||||||||||||||||||. ",
|
".||||||||||||||||||||||||||||||. ",
|
||||||
".111111111111111111111111111111. ",
|
".111111111111111111111111111111. ",
|
||||||
"................................ ",
|
"................................ ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
" "};
|
" "};
|
||||||
|
|
|
@ -1,179 +1,179 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "AVIDump.h"
|
#include "AVIDump.h"
|
||||||
#include "tchar.h"
|
#include "tchar.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <vfw.h>
|
#include <vfw.h>
|
||||||
#include <winerror.h>
|
#include <winerror.h>
|
||||||
|
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
#include "CommonPaths.h"
|
#include "CommonPaths.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
static HWND m_emuWnd;
|
static HWND m_emuWnd;
|
||||||
static int m_width;
|
static int m_width;
|
||||||
static int m_height;
|
static int m_height;
|
||||||
static LONG m_byteBuffer;
|
static LONG m_byteBuffer;
|
||||||
static LONG m_frameCount;
|
static LONG m_frameCount;
|
||||||
static LONG m_totalBytes;
|
static LONG m_totalBytes;
|
||||||
static PAVIFILE m_file;
|
static PAVIFILE m_file;
|
||||||
static int m_fileCount;
|
static int m_fileCount;
|
||||||
static PAVISTREAM m_stream;
|
static PAVISTREAM m_stream;
|
||||||
static PAVISTREAM m_streamCompressed;
|
static PAVISTREAM m_streamCompressed;
|
||||||
static AVISTREAMINFO m_header;
|
static AVISTREAMINFO m_header;
|
||||||
static AVICOMPRESSOPTIONS m_options;
|
static AVICOMPRESSOPTIONS m_options;
|
||||||
static AVICOMPRESSOPTIONS *m_arrayOptions[1];
|
static AVICOMPRESSOPTIONS *m_arrayOptions[1];
|
||||||
static BITMAPINFOHEADER m_bitmap;
|
static BITMAPINFOHEADER m_bitmap;
|
||||||
|
|
||||||
bool AVIDump::Start(HWND hWnd, int w, int h)
|
bool AVIDump::Start(HWND hWnd, int w, int h)
|
||||||
{
|
{
|
||||||
m_emuWnd = hWnd;
|
m_emuWnd = hWnd;
|
||||||
m_fileCount = 0;
|
m_fileCount = 0;
|
||||||
|
|
||||||
m_width = w;
|
m_width = w;
|
||||||
m_height = h;
|
m_height = h;
|
||||||
|
|
||||||
return CreateFile();
|
return CreateFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AVIDump::CreateFile()
|
bool AVIDump::CreateFile()
|
||||||
{
|
{
|
||||||
m_totalBytes = 0;
|
m_totalBytes = 0;
|
||||||
m_frameCount = 0;
|
m_frameCount = 0;
|
||||||
char movie_file_name[255];
|
char movie_file_name[255];
|
||||||
sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
|
sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
|
||||||
// Create path
|
// Create path
|
||||||
File::CreateFullPath(movie_file_name);
|
File::CreateFullPath(movie_file_name);
|
||||||
|
|
||||||
// Ask to delete file
|
// Ask to delete file
|
||||||
if (File::Exists(movie_file_name))
|
if (File::Exists(movie_file_name))
|
||||||
{
|
{
|
||||||
if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
|
if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
|
||||||
File::Delete(movie_file_name);
|
File::Delete(movie_file_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
AVIFileInit();
|
AVIFileInit();
|
||||||
NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
|
NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
|
||||||
// TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
|
// TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
|
||||||
HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
|
HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format.");
|
if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format.");
|
||||||
if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory.");
|
if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory.");
|
||||||
if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file.");
|
if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file.");
|
||||||
if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file.");
|
if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file.");
|
||||||
if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
|
if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
|
||||||
Stop();
|
Stop();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SetBitmapFormat();
|
SetBitmapFormat();
|
||||||
NOTICE_LOG(VIDEO, "Setting video format...");
|
NOTICE_LOG(VIDEO, "Setting video format...");
|
||||||
if (!SetVideoFormat()) {
|
if (!SetVideoFormat()) {
|
||||||
NOTICE_LOG(VIDEO, "Setting video format failed");
|
NOTICE_LOG(VIDEO, "Setting video format failed");
|
||||||
Stop();
|
Stop();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_fileCount) {
|
if (!m_fileCount) {
|
||||||
if (!SetCompressionOptions()) {
|
if (!SetCompressionOptions()) {
|
||||||
NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
|
NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
|
||||||
Stop();
|
Stop();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
|
if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
|
||||||
NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
|
NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
|
||||||
Stop();
|
Stop();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
|
if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
|
||||||
NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
|
NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
|
||||||
Stop();
|
Stop();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVIDump::CloseFile()
|
void AVIDump::CloseFile()
|
||||||
{
|
{
|
||||||
if (m_streamCompressed) {
|
if (m_streamCompressed) {
|
||||||
AVIStreamClose(m_streamCompressed);
|
AVIStreamClose(m_streamCompressed);
|
||||||
m_streamCompressed = NULL;
|
m_streamCompressed = NULL;
|
||||||
}
|
}
|
||||||
if (m_stream) {
|
if (m_stream) {
|
||||||
AVIStreamClose(m_stream);
|
AVIStreamClose(m_stream);
|
||||||
m_stream = NULL;
|
m_stream = NULL;
|
||||||
}
|
}
|
||||||
if (m_file) {
|
if (m_file) {
|
||||||
AVIFileRelease(m_file);
|
AVIFileRelease(m_file);
|
||||||
m_file = NULL;
|
m_file = NULL;
|
||||||
}
|
}
|
||||||
AVIFileExit();
|
AVIFileExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVIDump::Stop()
|
void AVIDump::Stop()
|
||||||
{
|
{
|
||||||
CloseFile();
|
CloseFile();
|
||||||
m_fileCount = 0;
|
m_fileCount = 0;
|
||||||
NOTICE_LOG(VIDEO, "Stop");
|
NOTICE_LOG(VIDEO, "Stop");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVIDump::AddFrame(char *data)
|
void AVIDump::AddFrame(char *data)
|
||||||
{
|
{
|
||||||
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
|
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
|
||||||
m_totalBytes += m_byteBuffer;
|
m_totalBytes += m_byteBuffer;
|
||||||
// Close the recording if the file is more than 2gb
|
// Close the recording if the file is more than 2gb
|
||||||
// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
|
// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
|
||||||
if (m_totalBytes >= 2000000000) {
|
if (m_totalBytes >= 2000000000) {
|
||||||
CloseFile();
|
CloseFile();
|
||||||
m_fileCount++;
|
m_fileCount++;
|
||||||
CreateFile();
|
CreateFile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AVIDump::SetBitmapFormat()
|
void AVIDump::SetBitmapFormat()
|
||||||
{
|
{
|
||||||
memset(&m_bitmap, 0, sizeof(m_bitmap));
|
memset(&m_bitmap, 0, sizeof(m_bitmap));
|
||||||
m_bitmap.biSize = 0x28;
|
m_bitmap.biSize = 0x28;
|
||||||
m_bitmap.biPlanes = 1;
|
m_bitmap.biPlanes = 1;
|
||||||
m_bitmap.biBitCount = 24;
|
m_bitmap.biBitCount = 24;
|
||||||
m_bitmap.biWidth = m_width;
|
m_bitmap.biWidth = m_width;
|
||||||
m_bitmap.biHeight = m_height;
|
m_bitmap.biHeight = m_height;
|
||||||
m_bitmap.biSizeImage = 3 * m_width * m_height;
|
m_bitmap.biSizeImage = 3 * m_width * m_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AVIDump::SetCompressionOptions()
|
bool AVIDump::SetCompressionOptions()
|
||||||
{
|
{
|
||||||
memset(&m_options, 0, sizeof(m_options));
|
memset(&m_options, 0, sizeof(m_options));
|
||||||
m_arrayOptions[0] = &m_options;
|
m_arrayOptions[0] = &m_options;
|
||||||
|
|
||||||
return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
|
return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AVIDump::SetVideoFormat()
|
bool AVIDump::SetVideoFormat()
|
||||||
{
|
{
|
||||||
memset(&m_header, 0, sizeof(m_header));
|
memset(&m_header, 0, sizeof(m_header));
|
||||||
m_header.fccType = streamtypeVIDEO;
|
m_header.fccType = streamtypeVIDEO;
|
||||||
m_header.dwScale = 1;
|
m_header.dwScale = 1;
|
||||||
// TODO: Decect FPS using NTSC/PAL
|
// TODO: Decect FPS using NTSC/PAL
|
||||||
m_header.dwRate = 60;
|
m_header.dwRate = 60;
|
||||||
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
|
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
|
||||||
|
|
||||||
return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
|
return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +1,60 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
// The plugins has to define these functions
|
// The plugins has to define these functions
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
|
|
||||||
#ifndef _BPFUNCTIONS_H_
|
#ifndef _BPFUNCTIONS_H_
|
||||||
#define _BPFUNCTIONS_H_
|
#define _BPFUNCTIONS_H_
|
||||||
|
|
||||||
#include "BPMemory.h"
|
#include "BPMemory.h"
|
||||||
#include "VideoCommon.h"
|
#include "VideoCommon.h"
|
||||||
|
|
||||||
namespace BPFunctions
|
namespace BPFunctions
|
||||||
{
|
{
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CONFIG_ISWII = 0,
|
CONFIG_ISWII = 0,
|
||||||
CONFIG_DISABLEFOG,
|
CONFIG_DISABLEFOG,
|
||||||
CONFIG_SHOWEFBREGIONS
|
CONFIG_SHOWEFBREGIONS
|
||||||
};
|
};
|
||||||
|
|
||||||
void FlushPipeline();
|
void FlushPipeline();
|
||||||
void SetGenerationMode(const Bypass &bp);
|
void SetGenerationMode(const Bypass &bp);
|
||||||
void SetScissor(const Bypass &bp);
|
void SetScissor(const Bypass &bp);
|
||||||
void SetLineWidth(const Bypass &bp);
|
void SetLineWidth(const Bypass &bp);
|
||||||
void SetDepthMode(const Bypass &bp);
|
void SetDepthMode(const Bypass &bp);
|
||||||
void SetBlendMode(const Bypass &bp);
|
void SetBlendMode(const Bypass &bp);
|
||||||
void SetDitherMode(const Bypass &bp);
|
void SetDitherMode(const Bypass &bp);
|
||||||
void SetLogicOpMode(const Bypass &bp);
|
void SetLogicOpMode(const Bypass &bp);
|
||||||
void SetColorMask(const Bypass &bp);
|
void SetColorMask(const Bypass &bp);
|
||||||
float GetRendererTargetScaleX();
|
float GetRendererTargetScaleX();
|
||||||
float GetRendererTargetScaleY();
|
float GetRendererTargetScaleY();
|
||||||
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf);
|
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf);
|
||||||
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight);
|
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight);
|
||||||
void ClearScreen(const Bypass &bp, const TRectangle &multirc);
|
void ClearScreen(const Bypass &bp, const TRectangle &multirc);
|
||||||
void RestoreRenderState(const Bypass &bp);
|
void RestoreRenderState(const Bypass &bp);
|
||||||
u8 *GetPointer(const u32 &address);
|
u8 *GetPointer(const u32 &address);
|
||||||
bool GetConfig(const int &type);
|
bool GetConfig(const int &type);
|
||||||
void SetSamplerState(const Bypass &bp);
|
void SetSamplerState(const Bypass &bp);
|
||||||
void SetInterlacingMode(const Bypass &bp);
|
void SetInterlacingMode(const Bypass &bp);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _BPFUNCTIONS_H_
|
#endif // _BPFUNCTIONS_H_
|
File diff suppressed because it is too large
Load Diff
|
@ -1,27 +1,27 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _BPSTRUCTS_H_
|
#ifndef _BPSTRUCTS_H_
|
||||||
#define _BPSTRUCTS_H_
|
#define _BPSTRUCTS_H_
|
||||||
|
|
||||||
#include "BPMemory.h"
|
#include "BPMemory.h"
|
||||||
|
|
||||||
void BPInit();
|
void BPInit();
|
||||||
void LoadBPReg(u32 value0);
|
void LoadBPReg(u32 value0);
|
||||||
void BPReload();
|
void BPReload();
|
||||||
|
|
||||||
#endif // _BPSTRUCTS_H_
|
#endif // _BPSTRUCTS_H_
|
||||||
|
|
|
@ -1,154 +1,154 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "HiresTextures.h"
|
#include "HiresTextures.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "SOIL.h"
|
#include "SOIL.h"
|
||||||
#include "CommonPaths.h"
|
#include "CommonPaths.h"
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
#include "FileSearch.h"
|
#include "FileSearch.h"
|
||||||
|
|
||||||
namespace HiresTextures
|
namespace HiresTextures
|
||||||
{
|
{
|
||||||
|
|
||||||
std::map<std::string, std::string> textureMap;
|
std::map<std::string, std::string> textureMap;
|
||||||
|
|
||||||
void Init(const char *gameCode)
|
void Init(const char *gameCode)
|
||||||
{
|
{
|
||||||
static bool bCheckedDir;
|
static bool bCheckedDir;
|
||||||
|
|
||||||
CFileSearch::XStringVector Directories;
|
CFileSearch::XStringVector Directories;
|
||||||
//Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
|
//Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
|
||||||
char szDir[MAX_PATH];
|
char szDir[MAX_PATH];
|
||||||
sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
|
sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
|
||||||
Directories.push_back(std::string(szDir));
|
Directories.push_back(std::string(szDir));
|
||||||
|
|
||||||
|
|
||||||
for (u32 i = 0; i < Directories.size(); i++)
|
for (u32 i = 0; i < Directories.size(); i++)
|
||||||
{
|
{
|
||||||
File::FSTEntry FST_Temp;
|
File::FSTEntry FST_Temp;
|
||||||
File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
|
File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
|
||||||
for (u32 j = 0; j < FST_Temp.children.size(); j++)
|
for (u32 j = 0; j < FST_Temp.children.size(); j++)
|
||||||
{
|
{
|
||||||
if (FST_Temp.children.at(j).isDirectory)
|
if (FST_Temp.children.at(j).isDirectory)
|
||||||
{
|
{
|
||||||
bool duplicate = false;
|
bool duplicate = false;
|
||||||
NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
|
NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
|
||||||
for (u32 k = 0; k < Directories.size(); k++)
|
for (u32 k = 0; k < Directories.size(); k++)
|
||||||
{
|
{
|
||||||
NormalizeDirSep(&Directories.at(k));
|
NormalizeDirSep(&Directories.at(k));
|
||||||
if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
|
if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
|
||||||
{
|
{
|
||||||
duplicate = true;
|
duplicate = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!duplicate)
|
if (!duplicate)
|
||||||
Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
|
Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CFileSearch::XStringVector Extensions;
|
CFileSearch::XStringVector Extensions;
|
||||||
Extensions.push_back("*.png");
|
Extensions.push_back("*.png");
|
||||||
Extensions.push_back("*.bmp");
|
Extensions.push_back("*.bmp");
|
||||||
Extensions.push_back("*.tga");
|
Extensions.push_back("*.tga");
|
||||||
Extensions.push_back("*.dds");
|
Extensions.push_back("*.dds");
|
||||||
Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
|
Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
|
||||||
|
|
||||||
CFileSearch FileSearch(Extensions, Directories);
|
CFileSearch FileSearch(Extensions, Directories);
|
||||||
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
|
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
|
||||||
char code[MAX_PATH];
|
char code[MAX_PATH];
|
||||||
sprintf(code, "%s_", gameCode);
|
sprintf(code, "%s_", gameCode);
|
||||||
|
|
||||||
if (rFilenames.size() > 0)
|
if (rFilenames.size() > 0)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < rFilenames.size(); i++)
|
for (u32 i = 0; i < rFilenames.size(); i++)
|
||||||
{
|
{
|
||||||
std::string FileName;
|
std::string FileName;
|
||||||
SplitPath(rFilenames[i], NULL, &FileName, NULL);
|
SplitPath(rFilenames[i], NULL, &FileName, NULL);
|
||||||
|
|
||||||
if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end())
|
if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end())
|
||||||
textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
|
textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
{
|
{
|
||||||
textureMap.clear();
|
textureMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
|
PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
|
||||||
{
|
{
|
||||||
std::string key(fileName);
|
std::string key(fileName);
|
||||||
|
|
||||||
if(textureMap.find(key) == textureMap.end())
|
if(textureMap.find(key) == textureMap.end())
|
||||||
return PC_TEX_FMT_NONE;
|
return PC_TEX_FMT_NONE;
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
int channels;
|
int channels;
|
||||||
|
|
||||||
u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
|
u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
|
||||||
|
|
||||||
if (temp == NULL) {
|
if (temp == NULL) {
|
||||||
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
|
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
|
||||||
SOIL_free_image_data(temp);
|
SOIL_free_image_data(temp);
|
||||||
return PC_TEX_FMT_NONE;
|
return PC_TEX_FMT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width > 1024 || height > 1024) {
|
if (width > 1024 || height > 1024) {
|
||||||
ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 1024 pixels tall and wide", textureMap[key].c_str(), width, height);
|
ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 1024 pixels tall and wide", textureMap[key].c_str(), width, height);
|
||||||
SOIL_free_image_data(temp);
|
SOIL_free_image_data(temp);
|
||||||
return PC_TEX_FMT_NONE;
|
return PC_TEX_FMT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
PC_TexFormat returnTex;
|
PC_TexFormat returnTex;
|
||||||
|
|
||||||
switch (texformat)
|
switch (texformat)
|
||||||
{
|
{
|
||||||
case GX_TF_I4:
|
case GX_TF_I4:
|
||||||
case GX_TF_I8:
|
case GX_TF_I8:
|
||||||
case GX_TF_IA4:
|
case GX_TF_IA4:
|
||||||
case GX_TF_IA8:
|
case GX_TF_IA8:
|
||||||
for (int i = 0; i < width * height * 4; i += 4)
|
for (int i = 0; i < width * height * 4; i += 4)
|
||||||
{
|
{
|
||||||
// Rather than use a luminosity function, just use the most intense color for luminance
|
// Rather than use a luminosity function, just use the most intense color for luminance
|
||||||
data[offset++] = *std::max_element(temp+i, temp+i+3);
|
data[offset++] = *std::max_element(temp+i, temp+i+3);
|
||||||
data[offset++] = temp[i+3];
|
data[offset++] = temp[i+3];
|
||||||
}
|
}
|
||||||
returnTex = PC_TEX_FMT_IA8;
|
returnTex = PC_TEX_FMT_IA8;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
memcpy(data, temp, width*height*4);
|
memcpy(data, temp, width*height*4);
|
||||||
returnTex = PC_TEX_FMT_RGBA32;
|
returnTex = PC_TEX_FMT_RGBA32;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pWidth = width;
|
*pWidth = width;
|
||||||
*pHeight = height;
|
*pHeight = height;
|
||||||
SOIL_free_image_data(temp);
|
SOIL_free_image_data(temp);
|
||||||
INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
|
INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
|
||||||
return returnTex;
|
return returnTex;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Dummy file for common to compile
|
// Dummy file for common to compile
|
||||||
|
|
|
@ -1,119 +1,119 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
// Stubs to make DSPCore compile as part of DSPSpy.
|
// Stubs to make DSPCore compile as part of DSPSpy.
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
|
|
||||||
void *AllocateMemoryPages(size_t size)
|
void *AllocateMemoryPages(size_t size)
|
||||||
{
|
{
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeMemoryPages(void *pages, size_t size)
|
void FreeMemoryPages(void *pages, size_t size)
|
||||||
{
|
{
|
||||||
free(pages);
|
free(pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPHost_OnThread()
|
bool DSPHost_OnThread()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Well, it's just RAM right? :)
|
// Well, it's just RAM right? :)
|
||||||
u8 DSPHost_ReadHostMemory(u32 address)
|
u8 DSPHost_ReadHostMemory(u32 address)
|
||||||
{
|
{
|
||||||
u8 *ptr = (u8*)address;
|
u8 *ptr = (u8*)address;
|
||||||
return *ptr;
|
return *ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
|
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
|
||||||
|
|
||||||
|
|
||||||
void DSPHost_CodeLoaded(const u8 *code, int size)
|
void DSPHost_CodeLoaded(const u8 *code, int size)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace Common
|
namespace Common
|
||||||
{
|
{
|
||||||
|
|
||||||
CriticalSection::CriticalSection(int)
|
CriticalSection::CriticalSection(int)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
CriticalSection::~CriticalSection()
|
CriticalSection::~CriticalSection()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CriticalSection::Enter()
|
void CriticalSection::Enter()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CriticalSection::Leave()
|
void CriticalSection::Leave()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace File
|
namespace File
|
||||||
{
|
{
|
||||||
|
|
||||||
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
|
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(filename, text_file ? "w" : "wb");
|
FILE *f = fopen(filename, text_file ? "w" : "wb");
|
||||||
if (!f)
|
if (!f)
|
||||||
return false;
|
return false;
|
||||||
size_t len = str.size();
|
size_t len = str.size();
|
||||||
if (len != fwrite(str.data(), 1, str.size(), f))
|
if (len != fwrite(str.data(), 1, str.size(), f))
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
|
bool ReadFileToString(bool text_file, const char *filename, std::string &str)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(filename, text_file ? "r" : "rb");
|
FILE *f = fopen(filename, text_file ? "r" : "rb");
|
||||||
if (!f)
|
if (!f)
|
||||||
return false;
|
return false;
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
size_t len = ftell(f);
|
size_t len = ftell(f);
|
||||||
fseek(f, 0, SEEK_SET);
|
fseek(f, 0, SEEK_SET);
|
||||||
char *buf = new char[len + 1];
|
char *buf = new char[len + 1];
|
||||||
buf[fread(buf, 1, len, f)] = 0;
|
buf[fread(buf, 1, len, f)] = 0;
|
||||||
str = std::string(buf, len);
|
str = std::string(buf, len);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
delete [] buf;
|
delete [] buf;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "dsp_interface.h"
|
#include "dsp_interface.h"
|
||||||
|
|
||||||
void IDSP::SendTask(void *addr, u16 iram_addr, u16 len, u16 start)
|
void IDSP::SendTask(void *addr, u16 iram_addr, u16 len, u16 start)
|
||||||
{
|
{
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(0x80F3A001);
|
SendMailTo(0x80F3A001);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo((u32)addr);
|
SendMailTo((u32)addr);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(0x80F3C002);
|
SendMailTo(0x80F3C002);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(iram_addr);
|
SendMailTo(iram_addr);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(0x80F3A002);
|
SendMailTo(0x80F3A002);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(len);
|
SendMailTo(len);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(0x80F3B002);
|
SendMailTo(0x80F3B002);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(0);
|
SendMailTo(0);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(0x80F3D001);
|
SendMailTo(0x80F3D001);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
SendMailTo(start);
|
SendMailTo(start);
|
||||||
while (CheckMailTo());
|
while (CheckMailTo());
|
||||||
}
|
}
|
|
@ -1,50 +1,50 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DSP_INTERFACE_H
|
#ifndef _DSP_INTERFACE_H
|
||||||
#define _DSP_INTERFACE_H
|
#define _DSP_INTERFACE_H
|
||||||
|
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
|
|
||||||
// DSPCR bits
|
// DSPCR bits
|
||||||
#define DSPCR_DSPRESET 0x0800 // Reset DSP
|
#define DSPCR_DSPRESET 0x0800 // Reset DSP
|
||||||
#define DSPCR_ARDMA 0x0200 // ARAM dma in progress, if set
|
#define DSPCR_ARDMA 0x0200 // ARAM dma in progress, if set
|
||||||
#define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
|
#define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
|
||||||
#define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
|
#define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
|
||||||
#define DSPCR_ARINTMSK 0x0040
|
#define DSPCR_ARINTMSK 0x0040
|
||||||
#define DSPCR_ARINT 0x0020
|
#define DSPCR_ARINT 0x0020
|
||||||
#define DSPCR_AIINTMSK 0x0010
|
#define DSPCR_AIINTMSK 0x0010
|
||||||
#define DSPCR_AIINT 0x0008
|
#define DSPCR_AIINT 0x0008
|
||||||
#define DSPCR_HALT 0x0004 // halt DSP
|
#define DSPCR_HALT 0x0004 // halt DSP
|
||||||
#define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
|
#define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
|
||||||
#define DSPCR_RES 0x0001 // reset DSP
|
#define DSPCR_RES 0x0001 // reset DSP
|
||||||
|
|
||||||
class IDSP {
|
class IDSP {
|
||||||
public:
|
public:
|
||||||
virtual ~IDSP() {}
|
virtual ~IDSP() {}
|
||||||
|
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void Reset() = 0;
|
virtual void Reset() = 0;
|
||||||
virtual u32 CheckMailTo() = 0;
|
virtual u32 CheckMailTo() = 0;
|
||||||
virtual void SendMailTo(u32 mail) = 0;
|
virtual void SendMailTo(u32 mail) = 0;
|
||||||
|
|
||||||
// Yeah, yeah, having a method here makes this not a pure interface - but
|
// Yeah, yeah, having a method here makes this not a pure interface - but
|
||||||
// the implementation does nothing but calling the virtual methods above.
|
// the implementation does nothing but calling the virtual methods above.
|
||||||
void SendTask(void *addr, u16 iram_addr, u16 len, u16 start);
|
void SendTask(void *addr, u16 iram_addr, u16 len, u16 start);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _DSP_INTERFACE_H
|
#endif // _DSP_INTERFACE_H
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,68 +1,68 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <ogc/dsp.h>
|
#include <ogc/dsp.h>
|
||||||
#include <ogc/irq.h>
|
#include <ogc/irq.h>
|
||||||
#include <ogc/machine/asm.h>
|
#include <ogc/machine/asm.h>
|
||||||
#include <ogc/machine/processor.h>
|
#include <ogc/machine/processor.h>
|
||||||
|
|
||||||
#include "dsp_interface.h"
|
#include "dsp_interface.h"
|
||||||
#include "real_dsp.h"
|
#include "real_dsp.h"
|
||||||
|
|
||||||
static vu16* const _dspReg = (u16*)0xCC005000;
|
static vu16* const _dspReg = (u16*)0xCC005000;
|
||||||
|
|
||||||
// Handler for DSP interrupt.
|
// Handler for DSP interrupt.
|
||||||
static void dsp_irq_handler(u32 nIrq, void *pCtx)
|
static void dsp_irq_handler(u32 nIrq, void *pCtx)
|
||||||
{
|
{
|
||||||
// Acknowledge interrupt?
|
// Acknowledge interrupt?
|
||||||
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT)) | DSPCR_DSPINT;
|
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT)) | DSPCR_DSPINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RealDSP::Init()
|
void RealDSP::Init()
|
||||||
{
|
{
|
||||||
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET;
|
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET;
|
||||||
_dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT));
|
_dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT));
|
||||||
|
|
||||||
// This code looks odd - shouldn't we initialize level?
|
// This code looks odd - shouldn't we initialize level?
|
||||||
u32 level;
|
u32 level;
|
||||||
_CPU_ISR_Disable(level);
|
_CPU_ISR_Disable(level);
|
||||||
IRQ_Request(IRQ_DSP_DSP, dsp_irq_handler, NULL);
|
IRQ_Request(IRQ_DSP_DSP, dsp_irq_handler, NULL);
|
||||||
_CPU_ISR_Restore(level);
|
_CPU_ISR_Restore(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RealDSP::Reset()
|
void RealDSP::Reset()
|
||||||
{
|
{
|
||||||
// Reset the DSP.
|
// Reset the DSP.
|
||||||
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET;
|
_dspReg[5] = (_dspReg[5] & ~(DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT)) | DSPCR_DSPRESET;
|
||||||
_dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT));
|
_dspReg[5] = (_dspReg[5] & ~(DSPCR_HALT|DSPCR_AIINT|DSPCR_ARINT|DSPCR_DSPINT));
|
||||||
_dspReg[5] |= DSPCR_RES;
|
_dspReg[5] |= DSPCR_RES;
|
||||||
while (_dspReg[5] & DSPCR_RES)
|
while (_dspReg[5] & DSPCR_RES)
|
||||||
;
|
;
|
||||||
_dspReg[9] = 0x63;
|
_dspReg[9] = 0x63;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 RealDSP::CheckMailTo()
|
u32 RealDSP::CheckMailTo()
|
||||||
{
|
{
|
||||||
return DSP_CheckMailTo();
|
return DSP_CheckMailTo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RealDSP::SendMailTo(u32 mail)
|
void RealDSP::SendMailTo(u32 mail)
|
||||||
{
|
{
|
||||||
DSP_SendMailTo(mail);
|
DSP_SendMailTo(mail);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _REAL_DSP_H
|
#ifndef _REAL_DSP_H
|
||||||
#define _REAL_DSP_H
|
#define _REAL_DSP_H
|
||||||
|
|
||||||
#include "dsp_interface.h"
|
#include "dsp_interface.h"
|
||||||
|
|
||||||
class RealDSP : public IDSP {
|
class RealDSP : public IDSP {
|
||||||
public:
|
public:
|
||||||
virtual void Init();
|
virtual void Init();
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
virtual u32 CheckMailTo();
|
virtual u32 CheckMailTo();
|
||||||
virtual void SendMailTo(u32 mail);
|
virtual void SendMailTo(u32 mail);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _REAL_DSP_H
|
#endif // _REAL_DSP_H
|
||||||
|
|
|
@ -1,403 +1,403 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
#include "DSPCodeUtil.h"
|
#include "DSPCodeUtil.h"
|
||||||
|
|
||||||
// Stub out the dsplib host stuff, since this is just a simple cmdline tools.
|
// Stub out the dsplib host stuff, since this is just a simple cmdline tools.
|
||||||
u8 DSPHost_ReadHostMemory(u32 addr) { return 0; }
|
u8 DSPHost_ReadHostMemory(u32 addr) { return 0; }
|
||||||
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
|
void DSPHost_WriteHostMemory(u8 value, u32 addr) {}
|
||||||
bool DSPHost_OnThread() { return false; }
|
bool DSPHost_OnThread() { return false; }
|
||||||
bool DSPHost_Running() { return true; }
|
bool DSPHost_Running() { return true; }
|
||||||
u32 DSPHost_CodeLoaded(const u8 *ptr, int size) {return 0x1337c0de;}
|
u32 DSPHost_CodeLoaded(const u8 *ptr, int size) {return 0x1337c0de;}
|
||||||
void DSPHost_InterruptRequest() {}
|
void DSPHost_InterruptRequest() {}
|
||||||
void DSPHost_UpdateDebugger() {}
|
void DSPHost_UpdateDebugger() {}
|
||||||
|
|
||||||
// This test goes from text ASM to binary to text ASM and once again back to binary.
|
// This test goes from text ASM to binary to text ASM and once again back to binary.
|
||||||
// Then the two binaries are compared.
|
// Then the two binaries are compared.
|
||||||
bool RoundTrip(const std::vector<u16> &code1)
|
bool RoundTrip(const std::vector<u16> &code1)
|
||||||
{
|
{
|
||||||
std::vector<u16> code2;
|
std::vector<u16> code2;
|
||||||
std::string text;
|
std::string text;
|
||||||
if (!Disassemble(code1, false, text))
|
if (!Disassemble(code1, false, text))
|
||||||
{
|
{
|
||||||
printf("RoundTrip: Disassembly failed.\n");
|
printf("RoundTrip: Disassembly failed.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Assemble(text.c_str(), code2))
|
if (!Assemble(text.c_str(), code2))
|
||||||
{
|
{
|
||||||
printf("RoundTrip: Assembly failed.\n");
|
printf("RoundTrip: Assembly failed.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!Compare(code1, code2))
|
if (!Compare(code1, code2))
|
||||||
{
|
{
|
||||||
Disassemble(code1, true, text);
|
Disassemble(code1, true, text);
|
||||||
printf("%s", text.c_str());
|
printf("%s", text.c_str());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test goes from text ASM to binary to text ASM and once again back to binary.
|
// This test goes from text ASM to binary to text ASM and once again back to binary.
|
||||||
// Very convenient for testing. Then the two binaries are compared.
|
// Very convenient for testing. Then the two binaries are compared.
|
||||||
bool SuperTrip(const char *asm_code)
|
bool SuperTrip(const char *asm_code)
|
||||||
{
|
{
|
||||||
std::vector<u16> code1, code2;
|
std::vector<u16> code1, code2;
|
||||||
std::string text;
|
std::string text;
|
||||||
if (!Assemble(asm_code, code1))
|
if (!Assemble(asm_code, code1))
|
||||||
{
|
{
|
||||||
printf("SuperTrip: First assembly failed\n");
|
printf("SuperTrip: First assembly failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
printf("First assembly: %i words\n", (int)code1.size());
|
printf("First assembly: %i words\n", (int)code1.size());
|
||||||
if (!Disassemble(code1, false, text))
|
if (!Disassemble(code1, false, text))
|
||||||
{
|
{
|
||||||
printf("SuperTrip: Disassembly failed\n");
|
printf("SuperTrip: Disassembly failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Disass:\n");
|
printf("Disass:\n");
|
||||||
printf("%s", text.c_str());
|
printf("%s", text.c_str());
|
||||||
}
|
}
|
||||||
if (!Assemble(text.c_str(), code2))
|
if (!Assemble(text.c_str(), code2))
|
||||||
{
|
{
|
||||||
printf("SuperTrip: Second assembly failed\n");
|
printf("SuperTrip: Second assembly failed\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
std::string text2;
|
std::string text2;
|
||||||
Disassemble(code1, true, &text1);
|
Disassemble(code1, true, &text1);
|
||||||
Disassemble(code2, true, &text2);
|
Disassemble(code2, true, &text2);
|
||||||
File::WriteStringToFile(true, text1, "code1.txt");
|
File::WriteStringToFile(true, text1, "code1.txt");
|
||||||
File::WriteStringToFile(true, text2, "code2.txt");
|
File::WriteStringToFile(true, text2, "code2.txt");
|
||||||
*/
|
*/
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunAsmTests()
|
void RunAsmTests()
|
||||||
{
|
{
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
#define CHK(a) if (!SuperTrip(a)) printf("FAIL\n%s\n", a), fail = true;
|
#define CHK(a) if (!SuperTrip(a)) printf("FAIL\n%s\n", a), fail = true;
|
||||||
|
|
||||||
// Let's start out easy - a trivial instruction..
|
// Let's start out easy - a trivial instruction..
|
||||||
CHK(" NOP\n");
|
CHK(" NOP\n");
|
||||||
|
|
||||||
// Now let's do several.
|
// Now let's do several.
|
||||||
CHK(" NOP\n"
|
CHK(" NOP\n"
|
||||||
" NOP\n"
|
" NOP\n"
|
||||||
" NOP\n");
|
" NOP\n");
|
||||||
|
|
||||||
// Turning it up a notch.
|
// Turning it up a notch.
|
||||||
CHK(" SET16\n"
|
CHK(" SET16\n"
|
||||||
" SET40\n"
|
" SET40\n"
|
||||||
" CLR15\n"
|
" CLR15\n"
|
||||||
" M0\n"
|
" M0\n"
|
||||||
" M2\n");
|
" M2\n");
|
||||||
|
|
||||||
// Time to try labels and parameters, and comments.
|
// Time to try labels and parameters, and comments.
|
||||||
CHK("DIRQ_TEST: equ 0xfffb ; DSP Irq Request\n"
|
CHK("DIRQ_TEST: equ 0xfffb ; DSP Irq Request\n"
|
||||||
" si @0xfffc, #0x8888\n"
|
" si @0xfffc, #0x8888\n"
|
||||||
" si @0xfffd, #0xbeef\n"
|
" si @0xfffd, #0xbeef\n"
|
||||||
" si @DIRQ_TEST, #0x0001\n");
|
" si @DIRQ_TEST, #0x0001\n");
|
||||||
|
|
||||||
// Let's see if registers roundtrip. Also try predefined labels.
|
// Let's see if registers roundtrip. Also try predefined labels.
|
||||||
CHK(" si @0xfffc, #0x8888\n"
|
CHK(" si @0xfffc, #0x8888\n"
|
||||||
" si @0xfffd, #0xbeef\n"
|
" si @0xfffd, #0xbeef\n"
|
||||||
" si @DIRQ, #0x0001\n");
|
" si @DIRQ, #0x0001\n");
|
||||||
|
|
||||||
// Let's try some messy extended instructions.
|
// Let's try some messy extended instructions.
|
||||||
//CHK(" MULMV'SN $AX0.L, $AX0.H, $ACC0 : @$AR2, $AC1.M\n");
|
//CHK(" MULMV'SN $AX0.L, $AX0.H, $ACC0 : @$AR2, $AC1.M\n");
|
||||||
|
|
||||||
//" ADDAXL'MV $ACC1, $AX1.L : $AX1.H, $AC1.M\n");
|
//" ADDAXL'MV $ACC1, $AX1.L : $AX1.H, $AC1.M\n");
|
||||||
// Let's get brutal. We generate random code bytes and make sure that they can
|
// Let's get brutal. We generate random code bytes and make sure that they can
|
||||||
// be roundtripped. We don't expect it to always succeed but it'll be sure to generate
|
// be roundtripped. We don't expect it to always succeed but it'll be sure to generate
|
||||||
|
|
||||||
// interesting test cases.
|
// interesting test cases.
|
||||||
/*
|
/*
|
||||||
std::vector<u16> hermes;
|
std::vector<u16> hermes;
|
||||||
if (!LoadBinary("testdata/hermes.bin", &hermes))
|
if (!LoadBinary("testdata/hermes.bin", &hermes))
|
||||||
PanicAlert("Failed to load hermes rom");
|
PanicAlert("Failed to load hermes rom");
|
||||||
RoundTrip(hermes);
|
RoundTrip(hermes);
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
std::vector<u16> code;
|
std::vector<u16> code;
|
||||||
std::string text_orig;
|
std::string text_orig;
|
||||||
File::ReadFileToString(false, "testdata/dsp_test.S", &text_orig);
|
File::ReadFileToString(false, "testdata/dsp_test.S", &text_orig);
|
||||||
if (!Assemble(text_orig.c_str(), &code))
|
if (!Assemble(text_orig.c_str(), &code))
|
||||||
{
|
{
|
||||||
printf("SuperTrip: First assembly failed\n");
|
printf("SuperTrip: First assembly failed\n");
|
||||||
return;
|
return;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
std::vector<u16> code;
|
std::vector<u16> code;
|
||||||
code.clear();
|
code.clear();
|
||||||
for (int i = 0; i < sizeof(dsp_test)/4; i++)
|
for (int i = 0; i < sizeof(dsp_test)/4; i++)
|
||||||
{
|
{
|
||||||
code.push_back(dsp_test[i] >> 16);
|
code.push_back(dsp_test[i] >> 16);
|
||||||
code.push_back(dsp_test[i] & 0xFFFF);
|
code.push_back(dsp_test[i] & 0xFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveBinary(code, "dsp_test2.bin");
|
SaveBinary(code, "dsp_test2.bin");
|
||||||
RoundTrip(code);
|
RoundTrip(code);
|
||||||
}*/
|
}*/
|
||||||
//if (Compare(code, hermes))
|
//if (Compare(code, hermes))
|
||||||
// printf("Successs\n");
|
// printf("Successs\n");
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
std::vector<u16> code;
|
std::vector<u16> code;
|
||||||
std::string text;
|
std::string text;
|
||||||
LoadBinary("testdata/dsp_test.bin", &code);
|
LoadBinary("testdata/dsp_test.bin", &code);
|
||||||
Disassemble(code, true, &text);
|
Disassemble(code, true, &text);
|
||||||
Assemble(text.c_str(), &code);
|
Assemble(text.c_str(), &code);
|
||||||
Disassemble(code, true, &text);
|
Disassemble(code, true, &text);
|
||||||
printf("%s", text.c_str());
|
printf("%s", text.c_str());
|
||||||
}*/
|
}*/
|
||||||
/*
|
/*
|
||||||
puts("Insane Random Code Test\n");
|
puts("Insane Random Code Test\n");
|
||||||
std::vector<u16> rand_code;
|
std::vector<u16> rand_code;
|
||||||
GenRandomCode(30, &rand_code);
|
GenRandomCode(30, &rand_code);
|
||||||
std::string rand_code_text;
|
std::string rand_code_text;
|
||||||
Disassemble(rand_code, true, &rand_code_text);
|
Disassemble(rand_code, true, &rand_code_text);
|
||||||
printf("%s", rand_code_text.c_str());
|
printf("%s", rand_code_text.c_str());
|
||||||
RoundTrip(rand_code);
|
RoundTrip(rand_code);
|
||||||
|
|
||||||
|
|
||||||
if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))
|
if (File::ReadFileToString(true, "C:/devkitPro/examples/wii/asndlib/dsptest/dsp_test.ds", &dsp_test))
|
||||||
SuperTrip(dsp_test.c_str());
|
SuperTrip(dsp_test.c_str());
|
||||||
|
|
||||||
//.File::ReadFileToString(true, "C:/devkitPro/trunk/libogc/libasnd/dsp_mixer/dsp_mixer.s", &dsp_test);
|
//.File::ReadFileToString(true, "C:/devkitPro/trunk/libogc/libasnd/dsp_mixer/dsp_mixer.s", &dsp_test);
|
||||||
// This is CLOSE to working. Sorry about the local path btw. This is preliminary code.
|
// This is CLOSE to working. Sorry about the local path btw. This is preliminary code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::string dsp_test;
|
std::string dsp_test;
|
||||||
if (File::ReadFileToString(true, "Testdata/dsp_test.s", dsp_test))
|
if (File::ReadFileToString(true, "Testdata/dsp_test.s", dsp_test))
|
||||||
fail = fail || !SuperTrip(dsp_test.c_str());
|
fail = fail || !SuperTrip(dsp_test.c_str());
|
||||||
if (!fail)
|
if (!fail)
|
||||||
printf("All passed!\n");
|
printf("All passed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Usage:
|
// Usage:
|
||||||
// Run internal tests:
|
// Run internal tests:
|
||||||
// dsptool test
|
// dsptool test
|
||||||
// Disassemble a file:
|
// Disassemble a file:
|
||||||
// dsptool -d -o asdf.txt asdf.bin
|
// dsptool -d -o asdf.txt asdf.bin
|
||||||
// Disassemble a file, output to standard output:
|
// Disassemble a file, output to standard output:
|
||||||
// dsptool -d asdf.bin
|
// dsptool -d asdf.bin
|
||||||
// Assemble a file:
|
// Assemble a file:
|
||||||
// dsptool -o asdf.bin asdf.txt
|
// dsptool -o asdf.bin asdf.txt
|
||||||
// Assemble a file, output header:
|
// Assemble a file, output header:
|
||||||
// dsptool -h asdf.h asdf.txt
|
// dsptool -h asdf.h asdf.txt
|
||||||
|
|
||||||
// So far, all this binary can do is test partially that itself works correctly.
|
// So far, all this binary can do is test partially that itself works correctly.
|
||||||
int main(int argc, const char *argv[])
|
int main(int argc, const char *argv[])
|
||||||
{
|
{
|
||||||
if(argc == 1 || (argc == 2 && (!strcmp(argv[1], "--help") || (!strcmp(argv[1], "-?")))))
|
if(argc == 1 || (argc == 2 && (!strcmp(argv[1], "--help") || (!strcmp(argv[1], "-?")))))
|
||||||
{
|
{
|
||||||
printf("USAGE: DSPTool [-?] [--help] [-d] [-m] [-o <FILE>] [-h <FILE>] <DSP ASSEMBLER FILE>\n");
|
printf("USAGE: DSPTool [-?] [--help] [-d] [-m] [-o <FILE>] [-h <FILE>] <DSP ASSEMBLER FILE>\n");
|
||||||
printf("-? / --help: Prints this message\n");
|
printf("-? / --help: Prints this message\n");
|
||||||
printf("-d: Disassemble\n");
|
printf("-d: Disassemble\n");
|
||||||
printf("-m: Input file contains a list of files (Header assembly only)\n");
|
printf("-m: Input file contains a list of files (Header assembly only)\n");
|
||||||
printf("-s: Print the final size in bytes (only)\n");
|
printf("-s: Print the final size in bytes (only)\n");
|
||||||
printf("-o <OUTPUT FILE>: Results from stdout redirected to a file\n");
|
printf("-o <OUTPUT FILE>: Results from stdout redirected to a file\n");
|
||||||
printf("-h <HEADER FILE>: Output assembly results to a header\n");
|
printf("-h <HEADER FILE>: Output assembly results to a header\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 2 && !strcmp(argv[1], "test"))
|
if (argc == 2 && !strcmp(argv[1], "test"))
|
||||||
{
|
{
|
||||||
RunAsmTests();
|
RunAsmTests();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string input_name;
|
std::string input_name;
|
||||||
std::string output_header_name;
|
std::string output_header_name;
|
||||||
std::string output_name;
|
std::string output_name;
|
||||||
|
|
||||||
bool disassemble = false, compare = false, multiple = false, outputSize = false;
|
bool disassemble = false, compare = false, multiple = false, outputSize = false;
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
{
|
{
|
||||||
if (!strcmp(argv[i], "-d"))
|
if (!strcmp(argv[i], "-d"))
|
||||||
disassemble = true;
|
disassemble = true;
|
||||||
else if (!strcmp(argv[i], "-o"))
|
else if (!strcmp(argv[i], "-o"))
|
||||||
output_name = argv[++i];
|
output_name = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-h"))
|
else if (!strcmp(argv[i], "-h"))
|
||||||
output_header_name = argv[++i];
|
output_header_name = argv[++i];
|
||||||
else if (!strcmp(argv[i], "-c"))
|
else if (!strcmp(argv[i], "-c"))
|
||||||
compare = true;
|
compare = true;
|
||||||
else if (!strcmp(argv[i], "-s"))
|
else if (!strcmp(argv[i], "-s"))
|
||||||
outputSize = true;
|
outputSize = true;
|
||||||
else if (!strcmp(argv[i], "-m"))
|
else if (!strcmp(argv[i], "-m"))
|
||||||
multiple = true;
|
multiple = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!input_name.empty())
|
if (!input_name.empty())
|
||||||
{
|
{
|
||||||
printf("ERROR: Can only take one input file.\n");
|
printf("ERROR: Can only take one input file.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
input_name = argv[i];
|
input_name = argv[i];
|
||||||
if (!File::Exists(input_name.c_str()))
|
if (!File::Exists(input_name.c_str()))
|
||||||
{
|
{
|
||||||
printf("ERROR: Input path does not exist.\n");
|
printf("ERROR: Input path does not exist.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(multiple && (compare || disassemble || !output_name.empty() ||
|
if(multiple && (compare || disassemble || !output_name.empty() ||
|
||||||
input_name.empty())) {
|
input_name.empty())) {
|
||||||
printf("ERROR: Multiple files can only be used with assembly "
|
printf("ERROR: Multiple files can only be used with assembly "
|
||||||
"and must compile a header file.\n");
|
"and must compile a header file.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compare)
|
if (compare)
|
||||||
{
|
{
|
||||||
// Two binary inputs, let's diff.
|
// Two binary inputs, let's diff.
|
||||||
std::string binary_code;
|
std::string binary_code;
|
||||||
std::vector<u16> code1, code2;
|
std::vector<u16> code1, code2;
|
||||||
File::ReadFileToString(false, input_name.c_str(), binary_code);
|
File::ReadFileToString(false, input_name.c_str(), binary_code);
|
||||||
BinaryStringBEToCode(binary_code, code1);
|
BinaryStringBEToCode(binary_code, code1);
|
||||||
File::ReadFileToString(false, output_name.c_str(), binary_code);
|
File::ReadFileToString(false, output_name.c_str(), binary_code);
|
||||||
BinaryStringBEToCode(binary_code, code2);
|
BinaryStringBEToCode(binary_code, code2);
|
||||||
Compare(code1, code2);
|
Compare(code1, code2);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disassemble)
|
if (disassemble)
|
||||||
{
|
{
|
||||||
if (input_name.empty())
|
if (input_name.empty())
|
||||||
{
|
{
|
||||||
printf("Disassemble: Must specify input.\n");
|
printf("Disassemble: Must specify input.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
std::string binary_code;
|
std::string binary_code;
|
||||||
std::vector<u16> code;
|
std::vector<u16> code;
|
||||||
File::ReadFileToString(false, input_name.c_str(), binary_code);
|
File::ReadFileToString(false, input_name.c_str(), binary_code);
|
||||||
BinaryStringBEToCode(binary_code, code);
|
BinaryStringBEToCode(binary_code, code);
|
||||||
std::string text;
|
std::string text;
|
||||||
Disassemble(code, true, text);
|
Disassemble(code, true, text);
|
||||||
if (!output_name.empty())
|
if (!output_name.empty())
|
||||||
File::WriteStringToFile(true, text, output_name.c_str());
|
File::WriteStringToFile(true, text, output_name.c_str());
|
||||||
else
|
else
|
||||||
printf("%s", text.c_str());
|
printf("%s", text.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (input_name.empty())
|
if (input_name.empty())
|
||||||
{
|
{
|
||||||
printf("Assemble: Must specify input.\n");
|
printf("Assemble: Must specify input.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
std::string source;
|
std::string source;
|
||||||
if (File::ReadFileToString(true, input_name.c_str(), source))
|
if (File::ReadFileToString(true, input_name.c_str(), source))
|
||||||
{
|
{
|
||||||
if(multiple)
|
if(multiple)
|
||||||
{
|
{
|
||||||
// When specifying a list of files we must compile a header
|
// When specifying a list of files we must compile a header
|
||||||
// (we can't assemble multiple files to one binary)
|
// (we can't assemble multiple files to one binary)
|
||||||
// since we checked it before, we assume output_header_name isn't empty
|
// since we checked it before, we assume output_header_name isn't empty
|
||||||
int lines;
|
int lines;
|
||||||
std::vector<u16> *codes;
|
std::vector<u16> *codes;
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
std::string header, currentSource;
|
std::string header, currentSource;
|
||||||
size_t lastPos = 0, pos = 0;
|
size_t lastPos = 0, pos = 0;
|
||||||
|
|
||||||
source.append("\n");
|
source.append("\n");
|
||||||
|
|
||||||
while((pos = source.find('\n', lastPos)) != std::string::npos)
|
while((pos = source.find('\n', lastPos)) != std::string::npos)
|
||||||
{
|
{
|
||||||
std::string temp = source.substr(lastPos, pos - lastPos);
|
std::string temp = source.substr(lastPos, pos - lastPos);
|
||||||
if(!temp.empty())
|
if(!temp.empty())
|
||||||
files.push_back(temp);
|
files.push_back(temp);
|
||||||
lastPos = pos + 1;
|
lastPos = pos + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lines = (int)files.size();
|
lines = (int)files.size();
|
||||||
|
|
||||||
if(lines == 0)
|
if(lines == 0)
|
||||||
{
|
{
|
||||||
printf("ERROR: Must specify at least one file\n");
|
printf("ERROR: Must specify at least one file\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
codes = new std::vector<u16>[lines];
|
codes = new std::vector<u16>[lines];
|
||||||
|
|
||||||
for(int i = 0; i < lines; i++)
|
for(int i = 0; i < lines; i++)
|
||||||
{
|
{
|
||||||
if (!File::ReadFileToString(true, files[i].c_str(), currentSource))
|
if (!File::ReadFileToString(true, files[i].c_str(), currentSource))
|
||||||
{
|
{
|
||||||
printf("ERROR reading %s, skipping...\n", files[i].c_str());
|
printf("ERROR reading %s, skipping...\n", files[i].c_str());
|
||||||
lines--;
|
lines--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(!Assemble(currentSource.c_str(), codes[i]))
|
if(!Assemble(currentSource.c_str(), codes[i]))
|
||||||
{
|
{
|
||||||
printf("Assemble: Assembly of %s failed due to errors\n",
|
printf("Assemble: Assembly of %s failed due to errors\n",
|
||||||
files[i].c_str());
|
files[i].c_str());
|
||||||
lines--;
|
lines--;
|
||||||
}
|
}
|
||||||
if(outputSize)
|
if(outputSize)
|
||||||
printf("%s: %d\n", files[i].c_str(), codes[i].size());
|
printf("%s: %d\n", files[i].c_str(), codes[i].size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CodesToHeader(codes, &files, lines, output_header_name.c_str(), header);
|
CodesToHeader(codes, &files, lines, output_header_name.c_str(), header);
|
||||||
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
|
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
|
||||||
|
|
||||||
delete[] codes;
|
delete[] codes;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector<u16> code;
|
std::vector<u16> code;
|
||||||
|
|
||||||
if(!Assemble(source.c_str(), code)) {
|
if(!Assemble(source.c_str(), code)) {
|
||||||
printf("Assemble: Assembly failed due to errors\n");
|
printf("Assemble: Assembly failed due to errors\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(outputSize)
|
if(outputSize)
|
||||||
printf("%s: %d\n", input_name.c_str(), code.size());
|
printf("%s: %d\n", input_name.c_str(), code.size());
|
||||||
|
|
||||||
if (!output_name.empty())
|
if (!output_name.empty())
|
||||||
{
|
{
|
||||||
std::string binary_code;
|
std::string binary_code;
|
||||||
CodeToBinaryStringBE(code, binary_code);
|
CodeToBinaryStringBE(code, binary_code);
|
||||||
File::WriteStringToFile(false, binary_code, output_name.c_str());
|
File::WriteStringToFile(false, binary_code, output_name.c_str());
|
||||||
}
|
}
|
||||||
if (!output_header_name.empty())
|
if (!output_header_name.empty())
|
||||||
{
|
{
|
||||||
std::string header;
|
std::string header;
|
||||||
CodeToHeader(code, input_name, output_header_name.c_str(), header);
|
CodeToHeader(code, input_name, output_header_name.c_str(), header);
|
||||||
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
|
File::WriteStringToFile(true, header, (output_header_name + ".h").c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
source.clear();
|
source.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!outputSize)
|
if(!outputSize)
|
||||||
printf("Assembly completed successfully!\n");
|
printf("Assembly completed successfully!\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,42 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Config.h" // Local
|
#include "Config.h" // Local
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "DSPHandler.h"
|
#include "DSPHandler.h"
|
||||||
#include "HLEMixer.h"
|
#include "HLEMixer.h"
|
||||||
|
|
||||||
void HLEMixer::MixUCode(short *samples, int numSamples) {
|
void HLEMixer::MixUCode(short *samples, int numSamples) {
|
||||||
// if this was called directly from the HLE, and not by timeout
|
// if this was called directly from the HLE, and not by timeout
|
||||||
if (g_Config.m_EnableHLEAudio && IsHLEReady()) {
|
if (g_Config.m_EnableHLEAudio && IsHLEReady()) {
|
||||||
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
|
IUCode* pUCode = CDSPHandler::GetInstance().GetUCode();
|
||||||
if (pUCode != NULL)
|
if (pUCode != NULL)
|
||||||
pUCode->MixAdd(samples, numSamples);
|
pUCode->MixAdd(samples, numSamples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HLEMixer::Premix(short *samples, int numSamples) {
|
void HLEMixer::Premix(short *samples, int numSamples) {
|
||||||
|
|
||||||
// first get the DTK Music
|
// first get the DTK Music
|
||||||
// if (g_Config.m_EnableDTKMusic) {
|
// if (g_Config.m_EnableDTKMusic) {
|
||||||
// g_dspInitialize.pGetAudioStreaming(samples, numSamples);
|
// g_dspInitialize.pGetAudioStreaming(samples, numSamples);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
MixUCode(samples, numSamples);
|
MixUCode(samples, numSamples);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,95 +1,95 @@
|
||||||
// Copyright (C) 2003-2008 Dolphin Project.
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "UCode_Zelda_ADPCM.h"
|
#include "UCode_Zelda_ADPCM.h"
|
||||||
|
|
||||||
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type)
|
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type)
|
||||||
{
|
{
|
||||||
short nibbles[16];
|
short nibbles[16];
|
||||||
short hist = *histp;
|
short hist = *histp;
|
||||||
short hist2 = *hist2p;
|
short hist2 = *hist2p;
|
||||||
|
|
||||||
const char *src = input;
|
const char *src = input;
|
||||||
char *dst = (char*)out;
|
char *dst = (char*)out;
|
||||||
|
|
||||||
// First 2 nibbles are ADPCM scale etc.
|
// First 2 nibbles are ADPCM scale etc.
|
||||||
short delta = 1 << (((*src) >> 4) & 0xf);
|
short delta = 1 << (((*src) >> 4) & 0xf);
|
||||||
short idx = (*src) & 0xf;
|
short idx = (*src) & 0xf;
|
||||||
src++;
|
src++;
|
||||||
|
|
||||||
if (type == 9)
|
if (type == 9)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 16; i = i + 2) {
|
for (int i = 0; i < 16; i = i + 2) {
|
||||||
int j = (*src & 255) >> 4;
|
int j = (*src & 255) >> 4;
|
||||||
nibbles[i] = j;
|
nibbles[i] = j;
|
||||||
j = *src & 255 & 15;
|
j = *src & 255 & 15;
|
||||||
nibbles[i+1] = j;
|
nibbles[i+1] = j;
|
||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 16; i = i + 1) {
|
for (int i = 0; i < 16; i = i + 1) {
|
||||||
if (nibbles[i] >= 8)
|
if (nibbles[i] >= 8)
|
||||||
nibbles[i] = nibbles[i] - 16;
|
nibbles[i] = nibbles[i] - 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// untested !!! i havnt seen such a sample yet :)
|
// untested !!! i havnt seen such a sample yet :)
|
||||||
for (int i = 0; i < 16; i += 4)
|
for (int i = 0; i < 16; i += 4)
|
||||||
{
|
{
|
||||||
int j = (*src >> 0) & 0x02;
|
int j = (*src >> 0) & 0x02;
|
||||||
nibbles[i] = j;
|
nibbles[i] = j;
|
||||||
|
|
||||||
j = (*src >> 2) & 0x02;
|
j = (*src >> 2) & 0x02;
|
||||||
nibbles[i+1] = j;
|
nibbles[i+1] = j;
|
||||||
|
|
||||||
j = (*src >> 4) & 0x02;
|
j = (*src >> 4) & 0x02;
|
||||||
nibbles[i+2] = j;
|
nibbles[i+2] = j;
|
||||||
|
|
||||||
j = (*src >> 6) & 0x02;
|
j = (*src >> 6) & 0x02;
|
||||||
nibbles[i+3] = j;
|
nibbles[i+3] = j;
|
||||||
|
|
||||||
src++;
|
src++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
if (nibbles[i] >= 2)
|
if (nibbles[i] >= 2)
|
||||||
nibbles[i] = nibbles[i] - 4;
|
nibbles[i] = nibbles[i] - 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
int sample = (delta * nibbles[i]) << 11;
|
int sample = (delta * nibbles[i]) << 11;
|
||||||
sample += ((long)hist * coef[idx * 2]) + ((long)hist2 * coef[idx * 2 + 1]);
|
sample += ((long)hist * coef[idx * 2]) + ((long)hist2 * coef[idx * 2 + 1]);
|
||||||
sample = sample >> 11;
|
sample = sample >> 11;
|
||||||
if (sample > 32767) {
|
if (sample > 32767) {
|
||||||
sample = 32767;
|
sample = 32767;
|
||||||
}
|
}
|
||||||
if (sample < -32768) {
|
if (sample < -32768) {
|
||||||
sample = -32768;
|
sample = -32768;
|
||||||
}
|
}
|
||||||
*(short*)dst = (short)sample;
|
*(short*)dst = (short)sample;
|
||||||
dst = dst + 2;
|
dst = dst + 2;
|
||||||
hist2 = hist;
|
hist2 = hist;
|
||||||
hist = (short)sample;
|
hist = (short)sample;
|
||||||
}
|
}
|
||||||
*histp = hist;
|
*histp = hist;
|
||||||
*hist2p = hist2;
|
*hist2p = hist2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
// Copyright (C) 2003-2008 Dolphin Project.
|
// Copyright (C) 2003-2008 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type);
|
void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type);
|
||||||
|
|
|
@ -1,106 +1,106 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "../Globals.h"
|
#include "../Globals.h"
|
||||||
#include "UCodes.h"
|
#include "UCodes.h"
|
||||||
#include "UCode_Zelda.h"
|
#include "UCode_Zelda.h"
|
||||||
#include "UCode_Zelda_ADPCM.h"
|
#include "UCode_Zelda_ADPCM.h"
|
||||||
|
|
||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
#include "Mixer.h"
|
#include "Mixer.h"
|
||||||
|
|
||||||
void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
void CUCode_Zelda::RenderSynth_Waveform(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||||
{
|
{
|
||||||
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||||
u32 _ratio = (PB.RatioInt << 16);
|
u32 _ratio = (PB.RatioInt << 16);
|
||||||
s64 ratio = (_ratio * ratioFactor) * 16;
|
s64 ratio = (_ratio * ratioFactor) * 16;
|
||||||
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
|
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
|
||||||
TrueSamplePosition += PB.CurSampleFrac;
|
TrueSamplePosition += PB.CurSampleFrac;
|
||||||
|
|
||||||
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
|
int mask = PB.Format ? 3 : 1, shift = PB.Format ? 2 : 1;
|
||||||
|
|
||||||
u32 pos[2] = {0, 0};
|
u32 pos[2] = {0, 0};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (PB.KeyOff != 0)
|
if (PB.KeyOff != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PB.NeedsReset)
|
if (PB.NeedsReset)
|
||||||
{
|
{
|
||||||
PB.RemLength = PB.Length - PB.RestartPos;
|
PB.RemLength = PB.Length - PB.RestartPos;
|
||||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||||
PB.ReachedEnd = 0;
|
PB.ReachedEnd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_lRestart:
|
_lRestart:
|
||||||
if (PB.ReachedEnd)
|
if (PB.ReachedEnd)
|
||||||
{
|
{
|
||||||
PB.ReachedEnd = 0;
|
PB.ReachedEnd = 0;
|
||||||
|
|
||||||
if (PB.RepeatMode == 0)
|
if (PB.RepeatMode == 0)
|
||||||
{
|
{
|
||||||
PB.KeyOff = 1;
|
PB.KeyOff = 1;
|
||||||
PB.RemLength = 0;
|
PB.RemLength = 0;
|
||||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PB.RestartPos = PB.LoopStartPos;
|
PB.RestartPos = PB.LoopStartPos;
|
||||||
PB.RemLength = PB.Length - PB.RestartPos;
|
PB.RemLength = PB.Length - PB.RestartPos;
|
||||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||||
pos[1] = 0; pos[0] = 0;
|
pos[1] = 0; pos[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while(i < _Size)
|
while(i < _Size)
|
||||||
{
|
{
|
||||||
s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000;
|
s16 sample = ((pos[1] & mask) == mask) ? 0xc000 : 0x4000;
|
||||||
|
|
||||||
TrueSamplePosition += (ratio >> 16);
|
TrueSamplePosition += (ratio >> 16);
|
||||||
|
|
||||||
_Buffer[i++] = (s32)sample;
|
_Buffer[i++] = (s32)sample;
|
||||||
|
|
||||||
(*(u64*)&pos) += ratio;
|
(*(u64*)&pos) += ratio;
|
||||||
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
|
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
|
||||||
{
|
{
|
||||||
PB.ReachedEnd = 1;
|
PB.ReachedEnd = 1;
|
||||||
goto _lRestart;
|
goto _lRestart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PB.RemLength < pos[1])
|
if (PB.RemLength < pos[1])
|
||||||
{
|
{
|
||||||
PB.RemLength = 0;
|
PB.RemLength = 0;
|
||||||
PB.ReachedEnd = 1;
|
PB.ReachedEnd = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PB.RemLength -= pos[1];
|
PB.RemLength -= pos[1];
|
||||||
|
|
||||||
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CUCode_Zelda::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
void CUCode_Zelda::RenderSynth_Constant(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||||
{
|
{
|
||||||
// TODO: Header, footer and cases this synth actually happens
|
// TODO: Header, footer and cases this synth actually happens
|
||||||
for (int i = 0; i < _Size; i++)
|
for (int i = 0; i < _Size; i++)
|
||||||
_Buffer[i++] = (s32)PB.RatioInt;
|
_Buffer[i++] = (s32)PB.RatioInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,466 +1,466 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "../Globals.h"
|
#include "../Globals.h"
|
||||||
#include "UCodes.h"
|
#include "UCodes.h"
|
||||||
#include "UCode_Zelda.h"
|
#include "UCode_Zelda.h"
|
||||||
#include "UCode_Zelda_ADPCM.h"
|
#include "UCode_Zelda_ADPCM.h"
|
||||||
|
|
||||||
#include "../main.h"
|
#include "../main.h"
|
||||||
#include "Mixer.h"
|
#include "Mixer.h"
|
||||||
|
|
||||||
void CUCode_Zelda::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB)
|
void CUCode_Zelda::ReadVoicePB(u32 _Addr, ZeldaVoicePB& PB)
|
||||||
{
|
{
|
||||||
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
|
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
|
||||||
|
|
||||||
// Perform byteswap
|
// Perform byteswap
|
||||||
for (int i = 0; i < (0x180 / 2); i++)
|
for (int i = 0; i < (0x180 / 2); i++)
|
||||||
((u16*)&PB)[i] = Common::swap16(memory[i]);
|
((u16*)&PB)[i] = Common::swap16(memory[i]);
|
||||||
|
|
||||||
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
|
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
|
||||||
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
|
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
|
||||||
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
|
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
|
||||||
PB.LoopStartPos = (PB.LoopStartPos << 16) | (PB.LoopStartPos >> 16);
|
PB.LoopStartPos = (PB.LoopStartPos << 16) | (PB.LoopStartPos >> 16);
|
||||||
PB.Length = (PB.Length << 16) | (PB.Length >> 16);
|
PB.Length = (PB.Length << 16) | (PB.Length >> 16);
|
||||||
PB.StartAddr = (PB.StartAddr << 16) | (PB.StartAddr >> 16);
|
PB.StartAddr = (PB.StartAddr << 16) | (PB.StartAddr >> 16);
|
||||||
PB.UnkAddr = (PB.UnkAddr << 16) | (PB.UnkAddr >> 16);
|
PB.UnkAddr = (PB.UnkAddr << 16) | (PB.UnkAddr >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUCode_Zelda::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB)
|
void CUCode_Zelda::WritebackVoicePB(u32 _Addr, ZeldaVoicePB& PB)
|
||||||
{
|
{
|
||||||
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
|
u16 *memory = (u16*)g_dspInitialize.pGetMemoryPointer(_Addr);
|
||||||
|
|
||||||
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
|
PB.RestartPos = (PB.RestartPos << 16) | (PB.RestartPos >> 16);
|
||||||
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
|
PB.CurAddr = (PB.CurAddr << 16) | (PB.CurAddr >> 16);
|
||||||
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
|
PB.RemLength = (PB.RemLength << 16) | (PB.RemLength >> 16);
|
||||||
|
|
||||||
// Perform byteswap
|
// Perform byteswap
|
||||||
// Only the first 0x100 bytes are written back
|
// Only the first 0x100 bytes are written back
|
||||||
for (int i = 0; i < (0x100 / 2); i++)
|
for (int i = 0; i < (0x100 / 2); i++)
|
||||||
memory[i] = Common::swap16(((u16*)&PB)[i]);
|
memory[i] = Common::swap16(((u16*)&PB)[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUCode_Zelda::RenderVoice_PCM16(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
void CUCode_Zelda::RenderVoice_PCM16(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||||
{
|
{
|
||||||
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||||
u32 _ratio = (((PB.RatioInt * 80) + PB.CurSampleFrac) << 4) & 0xFFFF0000;
|
u32 _ratio = (((PB.RatioInt * 80) + PB.CurSampleFrac) << 4) & 0xFFFF0000;
|
||||||
u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor);
|
u64 ratio = (u64)(((_ratio / 80) << 16) * ratioFactor);
|
||||||
|
|
||||||
u32 pos[2] = {0, 0};
|
u32 pos[2] = {0, 0};
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
if (PB.KeyOff != 0)
|
if (PB.KeyOff != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (PB.NeedsReset)
|
if (PB.NeedsReset)
|
||||||
{
|
{
|
||||||
PB.RemLength = PB.Length - PB.RestartPos;
|
PB.RemLength = PB.Length - PB.RestartPos;
|
||||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||||
PB.ReachedEnd = 0;
|
PB.ReachedEnd = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_lRestart:
|
_lRestart:
|
||||||
if (PB.ReachedEnd)
|
if (PB.ReachedEnd)
|
||||||
{
|
{
|
||||||
PB.ReachedEnd = 0;
|
PB.ReachedEnd = 0;
|
||||||
|
|
||||||
if (PB.RepeatMode == 0)
|
if (PB.RepeatMode == 0)
|
||||||
{
|
{
|
||||||
PB.KeyOff = 1;
|
PB.KeyOff = 1;
|
||||||
PB.RemLength = 0;
|
PB.RemLength = 0;
|
||||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1) + PB.Length;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PB.RestartPos = PB.LoopStartPos;
|
PB.RestartPos = PB.LoopStartPos;
|
||||||
PB.RemLength = PB.Length - PB.RestartPos;
|
PB.RemLength = PB.Length - PB.RestartPos;
|
||||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||||
pos[1] = 0; pos[0] = 0;
|
pos[1] = 0; pos[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 *source;
|
s16 *source;
|
||||||
if (m_CRC == 0xD643001F)
|
if (m_CRC == 0xD643001F)
|
||||||
source = (s16*)(g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr) + PB.CurAddr);
|
source = (s16*)(g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr) + PB.CurAddr);
|
||||||
else
|
else
|
||||||
source = (s16*)(g_dspInitialize.pGetARAMPointer() + PB.CurAddr);
|
source = (s16*)(g_dspInitialize.pGetARAMPointer() + PB.CurAddr);
|
||||||
|
|
||||||
for (; i < _Size;)
|
for (; i < _Size;)
|
||||||
{
|
{
|
||||||
s16 sample = Common::swap16(source[pos[1]]);
|
s16 sample = Common::swap16(source[pos[1]]);
|
||||||
|
|
||||||
_Buffer[i++] = (s32)sample;
|
_Buffer[i++] = (s32)sample;
|
||||||
|
|
||||||
(*(u64*)&pos) += ratio;
|
(*(u64*)&pos) += ratio;
|
||||||
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
|
if ((pos[1] + ((PB.CurAddr - PB.StartAddr) >> 1)) >= PB.Length)
|
||||||
{
|
{
|
||||||
PB.ReachedEnd = 1;
|
PB.ReachedEnd = 1;
|
||||||
goto _lRestart;
|
goto _lRestart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PB.RemLength < pos[1])
|
if (PB.RemLength < pos[1])
|
||||||
{
|
{
|
||||||
PB.RemLength = 0;
|
PB.RemLength = 0;
|
||||||
PB.ReachedEnd = 1;
|
PB.ReachedEnd = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
PB.RemLength -= pos[1];
|
PB.RemLength -= pos[1];
|
||||||
|
|
||||||
PB.CurAddr += pos[1] << 1;
|
PB.CurAddr += pos[1] << 1;
|
||||||
// There should be a position fraction as well.
|
// There should be a position fraction as well.
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
void CUCode_Zelda::RenderVoice_AFC(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||||
{
|
{
|
||||||
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||||
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
|
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
|
||||||
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
|
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
|
||||||
|
|
||||||
// initialize "decoder" if the sample is played the first time
|
// initialize "decoder" if the sample is played the first time
|
||||||
if (PB.NeedsReset != 0)
|
if (PB.NeedsReset != 0)
|
||||||
{
|
{
|
||||||
// This is 0717_ReadOutPBStuff
|
// This is 0717_ReadOutPBStuff
|
||||||
|
|
||||||
// increment 4fb
|
// increment 4fb
|
||||||
|
|
||||||
// zelda:
|
// zelda:
|
||||||
// perhaps init or "has played before"
|
// perhaps init or "has played before"
|
||||||
PB.CurBlock = 0x00;
|
PB.CurBlock = 0x00;
|
||||||
PB.YN2 = 0x00; // history1
|
PB.YN2 = 0x00; // history1
|
||||||
PB.YN1 = 0x00; // history2
|
PB.YN1 = 0x00; // history2
|
||||||
|
|
||||||
// Length in samples.
|
// Length in samples.
|
||||||
PB.RemLength = PB.Length;
|
PB.RemLength = PB.Length;
|
||||||
|
|
||||||
// Copy ARAM addr from r to rw area.
|
// Copy ARAM addr from r to rw area.
|
||||||
PB.CurAddr = PB.StartAddr;
|
PB.CurAddr = PB.StartAddr;
|
||||||
PB.ReachedEnd = 0;
|
PB.ReachedEnd = 0;
|
||||||
PB.CurSampleFrac = 0;
|
PB.CurSampleFrac = 0;
|
||||||
// Looking at Zelda Four Swords
|
// Looking at Zelda Four Swords
|
||||||
// WARN_LOG(DSPHLE, "PB -----: %04x", PB.Unk03);
|
// WARN_LOG(DSPHLE, "PB -----: %04x", PB.Unk03);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0
|
// WARN_LOG(DSPHLE, "PB Unk03: %04x", PB.Unk03); 0
|
||||||
// WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0
|
// WARN_LOG(DSPHLE, "PB Unk07: %04x", PB.Unk07[0]); 0
|
||||||
|
|
||||||
/// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78);
|
/// WARN_LOG(DSPHLE, "PB Unk78: %04x", PB.Unk78);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79);
|
// WARN_LOG(DSPHLE, "PB Unk79: %04x", PB.Unk79);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31);
|
// WARN_LOG(DSPHLE, "PB Unk31: %04x", PB.Unk31);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk36: %04x", PB.Unk36[0]);
|
// WARN_LOG(DSPHLE, "PB Unk36: %04x", PB.Unk36[0]);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk37: %04x", PB.Unk36[1]);
|
// WARN_LOG(DSPHLE, "PB Unk37: %04x", PB.Unk36[1]);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk3c: %04x", PB.Unk3C[0]);
|
// WARN_LOG(DSPHLE, "PB Unk3c: %04x", PB.Unk3C[0]);
|
||||||
// WARN_LOG(DSPHLE, "PB Unk3d: %04x", PB.Unk3C[1]);
|
// WARN_LOG(DSPHLE, "PB Unk3d: %04x", PB.Unk3C[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PB.KeyOff != 0) // 0747 early out... i dunno if this can happen because we filter it above
|
if (PB.KeyOff != 0) // 0747 early out... i dunno if this can happen because we filter it above
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// round upwards how many samples we need to copy, 0759
|
// round upwards how many samples we need to copy, 0759
|
||||||
// u32 frac = NumberOfSamples & 0xF;
|
// u32 frac = NumberOfSamples & 0xF;
|
||||||
// NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction
|
// NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction
|
||||||
|
|
||||||
u8 *source;
|
u8 *source;
|
||||||
u32 ram_mask = 1024 * 1024 * 16 - 1;
|
u32 ram_mask = 1024 * 1024 * 16 - 1;
|
||||||
if (m_CRC == 0xD643001F) {
|
if (m_CRC == 0xD643001F) {
|
||||||
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
|
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
|
||||||
ram_mask = 1024 * 1024 * 64 - 1;
|
ram_mask = 1024 * 1024 * 64 - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
source = g_dspInitialize.pGetARAMPointer();
|
source = g_dspInitialize.pGetARAMPointer();
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
if (PB.ReachedEnd)
|
if (PB.ReachedEnd)
|
||||||
{
|
{
|
||||||
PB.ReachedEnd = 0;
|
PB.ReachedEnd = 0;
|
||||||
|
|
||||||
// HACK: Looping doesn't work.
|
// HACK: Looping doesn't work.
|
||||||
if (true || PB.RepeatMode == 0)
|
if (true || PB.RepeatMode == 0)
|
||||||
{
|
{
|
||||||
PB.KeyOff = 1;
|
PB.KeyOff = 1;
|
||||||
PB.RemLength = 0;
|
PB.RemLength = 0;
|
||||||
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
|
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This needs adjustment. It's not right for AFC, was just copied from PCM16.
|
// This needs adjustment. It's not right for AFC, was just copied from PCM16.
|
||||||
// We should also probably reinitialize YN1 and YN2 with something - but with what?
|
// We should also probably reinitialize YN1 and YN2 with something - but with what?
|
||||||
PB.RestartPos = PB.LoopStartPos;
|
PB.RestartPos = PB.LoopStartPos;
|
||||||
PB.RemLength = PB.Length - PB.RestartPos;
|
PB.RemLength = PB.Length - PB.RestartPos;
|
||||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||||
// pos[1] = 0; pos[0] = 0;
|
// pos[1] = 0; pos[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
short outbuf[16] = {0};
|
short outbuf[16] = {0};
|
||||||
|
|
||||||
u16 prev_yn1 = PB.YN1;
|
u16 prev_yn1 = PB.YN1;
|
||||||
u16 prev_yn2 = PB.YN2;
|
u16 prev_yn2 = PB.YN2;
|
||||||
u32 prev_addr = PB.CurAddr;
|
u32 prev_addr = PB.CurAddr;
|
||||||
|
|
||||||
// Prefill the decode buffer.
|
// Prefill the decode buffer.
|
||||||
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
||||||
PB.CurAddr += 9;
|
PB.CurAddr += 9;
|
||||||
|
|
||||||
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
|
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
|
||||||
TrueSamplePosition += PB.CurSampleFrac;
|
TrueSamplePosition += PB.CurSampleFrac;
|
||||||
s64 delta = ratio >> 16; // 0x100000000ULL;
|
s64 delta = ratio >> 16; // 0x100000000ULL;
|
||||||
int sampleCount = 0;
|
int sampleCount = 0;
|
||||||
while (sampleCount < _Size)
|
while (sampleCount < _Size)
|
||||||
{
|
{
|
||||||
int SamplePosition = TrueSamplePosition >> 16;
|
int SamplePosition = TrueSamplePosition >> 16;
|
||||||
_Buffer[sampleCount] = outbuf[SamplePosition & 15];
|
_Buffer[sampleCount] = outbuf[SamplePosition & 15];
|
||||||
|
|
||||||
sampleCount++;
|
sampleCount++;
|
||||||
TrueSamplePosition += delta;
|
TrueSamplePosition += delta;
|
||||||
|
|
||||||
int TargetPosition = TrueSamplePosition >> 16;
|
int TargetPosition = TrueSamplePosition >> 16;
|
||||||
|
|
||||||
// Decode forwards...
|
// Decode forwards...
|
||||||
while (SamplePosition < TargetPosition)
|
while (SamplePosition < TargetPosition)
|
||||||
{
|
{
|
||||||
SamplePosition++;
|
SamplePosition++;
|
||||||
PB.RemLength--;
|
PB.RemLength--;
|
||||||
if (PB.RemLength == 0)
|
if (PB.RemLength == 0)
|
||||||
{
|
{
|
||||||
PB.ReachedEnd = 1;
|
PB.ReachedEnd = 1;
|
||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need new samples!
|
// Need new samples!
|
||||||
if ((SamplePosition & 15) == 0) {
|
if ((SamplePosition & 15) == 0) {
|
||||||
prev_yn1 = PB.YN1;
|
prev_yn1 = PB.YN1;
|
||||||
prev_yn2 = PB.YN2;
|
prev_yn2 = PB.YN2;
|
||||||
prev_addr = PB.CurAddr;
|
prev_addr = PB.CurAddr;
|
||||||
|
|
||||||
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
||||||
PB.CurAddr += 9;
|
PB.CurAddr += 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we should back off to the previous addr/yn1/yn2, since we didn't consume the full last block.
|
// Here we should back off to the previous addr/yn1/yn2, since we didn't consume the full last block.
|
||||||
// We'll have to re-decode it the next time around.
|
// We'll have to re-decode it the next time around.
|
||||||
// if (SamplePosition & 15) {
|
// if (SamplePosition & 15) {
|
||||||
PB.YN2 = prev_yn2;
|
PB.YN2 = prev_yn2;
|
||||||
PB.YN1 = prev_yn1;
|
PB.YN1 = prev_yn1;
|
||||||
PB.CurAddr = prev_addr;
|
PB.CurAddr = prev_addr;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
PB.NeedsReset = 0;
|
PB.NeedsReset = 0;
|
||||||
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
||||||
// write back
|
// write back
|
||||||
// NumberOfSamples = (NumberOfSamples << 4) | frac; // missing fraction
|
// NumberOfSamples = (NumberOfSamples << 4) | frac; // missing fraction
|
||||||
|
|
||||||
// i think pTest[0x3a] and pTest[0x3b] got an update after you have decoded some samples...
|
// i think pTest[0x3a] and pTest[0x3b] got an update after you have decoded some samples...
|
||||||
// just decrement them with the number of samples you have played
|
// just decrement them with the number of samples you have played
|
||||||
// and increase the ARAM Offset in pTest[0x38], pTest[0x39]
|
// and increase the ARAM Offset in pTest[0x38], pTest[0x39]
|
||||||
|
|
||||||
// end of block (Zelda 03b2)
|
// end of block (Zelda 03b2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Researching what's actually inside the mysterious 0x21 case
|
// Researching what's actually inside the mysterious 0x21 case
|
||||||
void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
void CUCode_Zelda::RenderVoice_Raw(ZeldaVoicePB &PB, s32* _Buffer, int _Size)
|
||||||
{
|
{
|
||||||
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
float ratioFactor = 32000.0f / (float)soundStream->GetMixer()->GetSampleRate();
|
||||||
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
|
u32 _ratio = (PB.RatioInt << 16);// + PB.RatioFrac;
|
||||||
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
|
s64 ratio = (_ratio * ratioFactor) * 16; // (s64)(((_ratio / 80) << 16) * ratioFactor);
|
||||||
|
|
||||||
if (PB.NeedsReset != 0)
|
if (PB.NeedsReset != 0)
|
||||||
{
|
{
|
||||||
PB.CurBlock = 0x00;
|
PB.CurBlock = 0x00;
|
||||||
|
|
||||||
// Length in samples.
|
// Length in samples.
|
||||||
PB.RemLength = PB.Length;
|
PB.RemLength = PB.Length;
|
||||||
|
|
||||||
// Copy ARAM addr from r to rw area.
|
// Copy ARAM addr from r to rw area.
|
||||||
PB.CurAddr = PB.StartAddr;
|
PB.CurAddr = PB.StartAddr;
|
||||||
PB.ReachedEnd = 0;
|
PB.ReachedEnd = 0;
|
||||||
PB.CurSampleFrac = 0;
|
PB.CurSampleFrac = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PB.KeyOff != 0)
|
if (PB.KeyOff != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u8 *source;
|
u8 *source;
|
||||||
u32 ram_mask = 1024 * 1024 * 16 - 1;
|
u32 ram_mask = 1024 * 1024 * 16 - 1;
|
||||||
if (m_CRC == 0xD643001F) {
|
if (m_CRC == 0xD643001F) {
|
||||||
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
|
source = g_dspInitialize.pGetMemoryPointer(m_DMABaseAddr);
|
||||||
ram_mask = 1024 * 1024 * 64 - 1;
|
ram_mask = 1024 * 1024 * 64 - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
source = g_dspInitialize.pGetARAMPointer();
|
source = g_dspInitialize.pGetARAMPointer();
|
||||||
|
|
||||||
//restart:
|
//restart:
|
||||||
if (PB.ReachedEnd)
|
if (PB.ReachedEnd)
|
||||||
{
|
{
|
||||||
PB.ReachedEnd = 0;
|
PB.ReachedEnd = 0;
|
||||||
|
|
||||||
// HACK: Looping doesn't work.
|
// HACK: Looping doesn't work.
|
||||||
if (true || PB.RepeatMode == 0)
|
if (true || PB.RepeatMode == 0)
|
||||||
{
|
{
|
||||||
PB.KeyOff = 1;
|
PB.KeyOff = 1;
|
||||||
PB.RemLength = 0;
|
PB.RemLength = 0;
|
||||||
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
|
PB.CurAddr = PB.StartAddr + PB.RestartPos + PB.Length;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// This needs adjustment. It's not right for AFC, was just copied from PCM16.
|
// This needs adjustment. It's not right for AFC, was just copied from PCM16.
|
||||||
// We should also probably reinitialize YN1 and YN2 with something - but with what?
|
// We should also probably reinitialize YN1 and YN2 with something - but with what?
|
||||||
PB.RestartPos = PB.LoopStartPos;
|
PB.RestartPos = PB.LoopStartPos;
|
||||||
PB.RemLength = PB.Length - PB.RestartPos;
|
PB.RemLength = PB.Length - PB.RestartPos;
|
||||||
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
PB.CurAddr = PB.StartAddr + (PB.RestartPos << 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
u32 prev_addr = PB.CurAddr;
|
u32 prev_addr = PB.CurAddr;
|
||||||
|
|
||||||
// Prefill the decode buffer.
|
// Prefill the decode buffer.
|
||||||
//AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
//AFCdecodebuffer(m_AFCCoefTable, (char*)(source + (PB.CurAddr & ram_mask)), outbuf, (short*)&PB.YN2, (short*)&PB.YN1, PB.Format);
|
||||||
const char *src = (char *)(source + (PB.CurAddr & ram_mask));
|
const char *src = (char *)(source + (PB.CurAddr & ram_mask));
|
||||||
PB.CurAddr += 9;
|
PB.CurAddr += 9;
|
||||||
|
|
||||||
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
|
s64 TrueSamplePosition = (s64)(PB.Length - PB.RemLength) << 16;
|
||||||
TrueSamplePosition += PB.CurSampleFrac;
|
TrueSamplePosition += PB.CurSampleFrac;
|
||||||
s64 delta = ratio >> 16; // 0x100000000ULL;
|
s64 delta = ratio >> 16; // 0x100000000ULL;
|
||||||
int sampleCount = 0, realSample = 0;
|
int sampleCount = 0, realSample = 0;
|
||||||
while (sampleCount < _Size)
|
while (sampleCount < _Size)
|
||||||
{
|
{
|
||||||
_Buffer[sampleCount] = src[realSample] | (src[realSample + 1] << 8) | (src[realSample + 2] << 16)
|
_Buffer[sampleCount] = src[realSample] | (src[realSample + 1] << 8) | (src[realSample + 2] << 16)
|
||||||
| (src[realSample + 3] << 24);
|
| (src[realSample + 3] << 24);
|
||||||
|
|
||||||
//WARN_LOG(DSPHLE, "The sample: %02x", src[sampleCount]);
|
//WARN_LOG(DSPHLE, "The sample: %02x", src[sampleCount]);
|
||||||
|
|
||||||
sampleCount++;
|
sampleCount++;
|
||||||
realSample += 4;
|
realSample += 4;
|
||||||
TrueSamplePosition += delta;
|
TrueSamplePosition += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
PB.NeedsReset = 0;
|
PB.NeedsReset = 0;
|
||||||
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
PB.CurSampleFrac = TrueSamplePosition & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
|
void CUCode_Zelda::RenderAddVoice(ZeldaVoicePB &PB, s32* _LeftBuffer, s32* _RightBuffer, int _Size)
|
||||||
{
|
{
|
||||||
//static u16 lastLeft = 0x1FF, lastRight = 0x1FF;
|
//static u16 lastLeft = 0x1FF, lastRight = 0x1FF;
|
||||||
memset(m_TempBuffer, 0, _Size * sizeof(s32));
|
memset(m_TempBuffer, 0, _Size * sizeof(s32));
|
||||||
|
|
||||||
if (PB.IsBlank)
|
if (PB.IsBlank)
|
||||||
{
|
{
|
||||||
s32 sample = (s32)(s16)PB.FixedSample;
|
s32 sample = (s32)(s16)PB.FixedSample;
|
||||||
for (int i = 0; i < _Size; i++)
|
for (int i = 0; i < _Size; i++)
|
||||||
m_TempBuffer[i] = sample;
|
m_TempBuffer[i] = sample;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// XK: Use this to disable music (GREAT for testing)
|
// XK: Use this to disable music (GREAT for testing)
|
||||||
//if(PB.SoundType == 0x0d00) {
|
//if(PB.SoundType == 0x0d00) {
|
||||||
// PB.NeedsReset = 0;
|
// PB.NeedsReset = 0;
|
||||||
// return;
|
// return;
|
||||||
//}
|
//}
|
||||||
//WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x",
|
//WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x",
|
||||||
// PB.Format, PB.SoundType, PB.Unk29, PB.Unk2a);
|
// PB.Format, PB.SoundType, PB.Unk29, PB.Unk2a);
|
||||||
/*WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x %04x %04x %04x %04x %04x %04x",
|
/*WARN_LOG(DSPHLE, "Fmt %04x, %04x: %04x %04x %04x %04x %04x %04x %04x %04x",
|
||||||
PB.Format, PB.SoundType,
|
PB.Format, PB.SoundType,
|
||||||
PB.volumeLeft1, PB.volumeLeft2, PB.volumeRight1, PB.volumeRight2,
|
PB.volumeLeft1, PB.volumeLeft2, PB.volumeRight1, PB.volumeRight2,
|
||||||
PB.volumeUnknown1_1, PB.volumeUnknown1_2, PB.volumeUnknown2_1,
|
PB.volumeUnknown1_1, PB.volumeUnknown1_2, PB.volumeUnknown2_1,
|
||||||
PB.volumeUnknown2_2);*/
|
PB.volumeUnknown2_2);*/
|
||||||
|
|
||||||
switch (PB.Format)
|
switch (PB.Format)
|
||||||
{
|
{
|
||||||
// Synthesized sounds
|
// Synthesized sounds
|
||||||
case 0x0000: // Example: Magic meter filling up in ZWW
|
case 0x0000: // Example: Magic meter filling up in ZWW
|
||||||
case 0x0001: // Example: "Denied" sound when trying to pull out a sword
|
case 0x0001: // Example: "Denied" sound when trying to pull out a sword
|
||||||
// indoors in ZWW
|
// indoors in ZWW
|
||||||
RenderSynth_Waveform(PB, m_TempBuffer, _Size);
|
RenderSynth_Waveform(PB, m_TempBuffer, _Size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0006:
|
case 0x0006:
|
||||||
WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)");
|
WARN_LOG(DSPHLE, "Synthesizing 0x0006 (constant sound)");
|
||||||
RenderSynth_Constant(PB, m_TempBuffer, _Size);
|
RenderSynth_Constant(PB, m_TempBuffer, _Size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// These are more "synth" formats - square wave, saw wave etc.
|
// These are more "synth" formats - square wave, saw wave etc.
|
||||||
case 0x0002:
|
case 0x0002:
|
||||||
WARN_LOG(DSPHLE, "Synthesizing 0x0002");
|
WARN_LOG(DSPHLE, "Synthesizing 0x0002");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
// AFC formats
|
// AFC formats
|
||||||
case 0x0005: // AFC with extra low bitrate (32:5 compression). Not yet seen.
|
case 0x0005: // AFC with extra low bitrate (32:5 compression). Not yet seen.
|
||||||
WARN_LOG(DSPHLE, "5 byte AFC - does it work?");
|
WARN_LOG(DSPHLE, "5 byte AFC - does it work?");
|
||||||
case 0x0009: // AFC with normal bitrate (32:9 compression).
|
case 0x0009: // AFC with normal bitrate (32:9 compression).
|
||||||
|
|
||||||
|
|
||||||
RenderVoice_AFC(PB, m_TempBuffer, _Size);
|
RenderVoice_AFC(PB, m_TempBuffer, _Size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0010: // PCM16 - normal PCM 16-bit audio.
|
case 0x0010: // PCM16 - normal PCM 16-bit audio.
|
||||||
RenderVoice_PCM16(PB, m_TempBuffer, _Size);
|
RenderVoice_PCM16(PB, m_TempBuffer, _Size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case 0x0008: // Likely PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD.
|
case 0x0008: // Likely PCM8 - normal PCM 8-bit audio. Used in Mario Kart DD.
|
||||||
case 0x0020:
|
case 0x0020:
|
||||||
case 0x0021: // Probably raw sound. Important for Zelda WW. Really need to implement - missing it causes hangs.
|
case 0x0021: // Probably raw sound. Important for Zelda WW. Really need to implement - missing it causes hangs.
|
||||||
WARN_LOG(DSPHLE, "Unimplemented MixAddVoice format in zelda %04x", PB.Format);
|
WARN_LOG(DSPHLE, "Unimplemented MixAddVoice format in zelda %04x", PB.Format);
|
||||||
|
|
||||||
// This is what 0x20 and 0x21 do on end of voice
|
// This is what 0x20 and 0x21 do on end of voice
|
||||||
PB.RemLength = 0;
|
PB.RemLength = 0;
|
||||||
PB.KeyOff = 1;
|
PB.KeyOff = 1;
|
||||||
|
|
||||||
// Caution: Use at your own risk. Sounds awful :)
|
// Caution: Use at your own risk. Sounds awful :)
|
||||||
//RenderVoice_Raw(PB, m_TempBuffer, _Size);
|
//RenderVoice_Raw(PB, m_TempBuffer, _Size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// TODO: Implement general decoder here
|
// TODO: Implement general decoder here
|
||||||
ERROR_LOG(DSPHLE, "Unknown MixAddVoice format in zelda %04x", PB.Format);
|
ERROR_LOG(DSPHLE, "Unknown MixAddVoice format in zelda %04x", PB.Format);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Necessary for SMG, not for Zelda. Weird.
|
// Necessary for SMG, not for Zelda. Weird.
|
||||||
PB.NeedsReset = 0;
|
PB.NeedsReset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < _Size; i++)
|
for (int i = 0; i < _Size; i++)
|
||||||
{
|
{
|
||||||
/*if(PB.volumeLeft2)
|
/*if(PB.volumeLeft2)
|
||||||
lastLeft = PB.volumeLeft2;
|
lastLeft = PB.volumeLeft2;
|
||||||
if(PB.volumeRight2)
|
if(PB.volumeRight2)
|
||||||
lastRight = PB.volumeRight2;*/
|
lastRight = PB.volumeRight2;*/
|
||||||
|
|
||||||
// TODO: Some noises in Zelda WW (birds, etc) have a volume of 0
|
// TODO: Some noises in Zelda WW (birds, etc) have a volume of 0
|
||||||
// Really not sure about the masking here, but it seems to kill off some overly loud
|
// Really not sure about the masking here, but it seems to kill off some overly loud
|
||||||
// sounds in Zelda TP. Needs investigation.
|
// sounds in Zelda TP. Needs investigation.
|
||||||
s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
|
s32 left = _LeftBuffer[i] + (m_TempBuffer[i] * (float)(
|
||||||
(PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005);
|
(PB.volumeLeft1 & 0x1FFF) + (PB.volumeLeft2 & 0x1FFF)) * 0.00005);
|
||||||
s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
|
s32 right = _RightBuffer[i] + (m_TempBuffer[i] * (float)(
|
||||||
(PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005);
|
(PB.volumeRight1 & 0x1FFF) + (PB.volumeRight2 & 0x1FFF)) * 0.00005);
|
||||||
|
|
||||||
if (left < -32768) left = -32768;
|
if (left < -32768) left = -32768;
|
||||||
if (left > 32767) left = 32767;
|
if (left > 32767) left = 32767;
|
||||||
_LeftBuffer[i] = left; //(s32)(((float)left * (float)PB.volumeLeft) / 1000.f);
|
_LeftBuffer[i] = left; //(s32)(((float)left * (float)PB.volumeLeft) / 1000.f);
|
||||||
|
|
||||||
if (right < -32768) right = -32768;
|
if (right < -32768) right = -32768;
|
||||||
if (right > 32767) right = 32767;
|
if (right > 32767) right = 32767;
|
||||||
_RightBuffer[i] = right; //(s32)(((float)right * (float)PB.volumeRight) / 1000.0f);
|
_RightBuffer[i] = right; //(s32)(((float)right * (float)PB.volumeRight) / 1000.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,179 +1,179 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "DSPDebugInterface.h"
|
#include "DSPDebugInterface.h"
|
||||||
|
|
||||||
#include "DSPCore.h"
|
#include "DSPCore.h"
|
||||||
#include "disassemble.h"
|
#include "disassemble.h"
|
||||||
|
|
||||||
#include "DSPSymbols.h"
|
#include "DSPSymbols.h"
|
||||||
#include "DSPMemoryMap.h"
|
#include "DSPMemoryMap.h"
|
||||||
|
|
||||||
void DSPDebugInterface::disasm(unsigned int address, char *dest, int max_size)
|
void DSPDebugInterface::disasm(unsigned int address, char *dest, int max_size)
|
||||||
{
|
{
|
||||||
// we'll treat addresses as line numbers.
|
// we'll treat addresses as line numbers.
|
||||||
strncpy(dest, DSPSymbols::GetLineText(address), max_size);
|
strncpy(dest, DSPSymbols::GetLineText(address), max_size);
|
||||||
dest[max_size-1] = 0;
|
dest[max_size-1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::getRawMemoryString(int memory, unsigned int address, char *dest, int max_size)
|
void DSPDebugInterface::getRawMemoryString(int memory, unsigned int address, char *dest, int max_size)
|
||||||
{
|
{
|
||||||
switch (memory) {
|
switch (memory) {
|
||||||
case 0: // IMEM
|
case 0: // IMEM
|
||||||
switch (address >> 12) {
|
switch (address >> 12) {
|
||||||
case 0:
|
case 0:
|
||||||
case 0x8:
|
case 0x8:
|
||||||
sprintf(dest, "%04x", dsp_imem_read(address));
|
sprintf(dest, "%04x", dsp_imem_read(address));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(dest, "----");
|
sprintf(dest, "----");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: // DMEM
|
case 1: // DMEM
|
||||||
switch (address >> 12) {
|
switch (address >> 12) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
sprintf(dest, "%04x", dsp_dmem_read(address));
|
sprintf(dest, "%04x", dsp_dmem_read(address));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(dest, "----");
|
sprintf(dest, "----");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DSPDebugInterface::readMemory(unsigned int address)
|
unsigned int DSPDebugInterface::readMemory(unsigned int address)
|
||||||
{
|
{
|
||||||
return 0; //Memory::ReadUnchecked_U32(address);
|
return 0; //Memory::ReadUnchecked_U32(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DSPDebugInterface::readInstruction(unsigned int address)
|
unsigned int DSPDebugInterface::readInstruction(unsigned int address)
|
||||||
{
|
{
|
||||||
return 0; //Memory::Read_Instruction(address);
|
return 0; //Memory::Read_Instruction(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPDebugInterface::isAlive()
|
bool DSPDebugInterface::isAlive()
|
||||||
{
|
{
|
||||||
return true; //Core::GetState() != Core::CORE_UNINITIALIZED;
|
return true; //Core::GetState() != Core::CORE_UNINITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPDebugInterface::isBreakpoint(unsigned int address)
|
bool DSPDebugInterface::isBreakpoint(unsigned int address)
|
||||||
{
|
{
|
||||||
int real_addr = DSPSymbols::Line2Addr(address);
|
int real_addr = DSPSymbols::Line2Addr(address);
|
||||||
if (real_addr >= 0)
|
if (real_addr >= 0)
|
||||||
return dsp_breakpoints.IsAddressBreakPoint(real_addr);
|
return dsp_breakpoints.IsAddressBreakPoint(real_addr);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::setBreakpoint(unsigned int address)
|
void DSPDebugInterface::setBreakpoint(unsigned int address)
|
||||||
{
|
{
|
||||||
int real_addr = DSPSymbols::Line2Addr(address);
|
int real_addr = DSPSymbols::Line2Addr(address);
|
||||||
if (real_addr >= 0) {
|
if (real_addr >= 0) {
|
||||||
if (dsp_breakpoints.Add(real_addr))
|
if (dsp_breakpoints.Add(real_addr))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::clearBreakpoint(unsigned int address)
|
void DSPDebugInterface::clearBreakpoint(unsigned int address)
|
||||||
{
|
{
|
||||||
int real_addr = DSPSymbols::Line2Addr(address);
|
int real_addr = DSPSymbols::Line2Addr(address);
|
||||||
if (real_addr >= 0) {
|
if (real_addr >= 0) {
|
||||||
if (dsp_breakpoints.Remove(real_addr))
|
if (dsp_breakpoints.Remove(real_addr))
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::clearAllBreakpoints() {
|
void DSPDebugInterface::clearAllBreakpoints() {
|
||||||
dsp_breakpoints.Clear();
|
dsp_breakpoints.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::toggleBreakpoint(unsigned int address)
|
void DSPDebugInterface::toggleBreakpoint(unsigned int address)
|
||||||
{
|
{
|
||||||
int real_addr = DSPSymbols::Line2Addr(address);
|
int real_addr = DSPSymbols::Line2Addr(address);
|
||||||
if (real_addr >= 0) {
|
if (real_addr >= 0) {
|
||||||
if (dsp_breakpoints.IsAddressBreakPoint(real_addr))
|
if (dsp_breakpoints.IsAddressBreakPoint(real_addr))
|
||||||
dsp_breakpoints.Remove(real_addr);
|
dsp_breakpoints.Remove(real_addr);
|
||||||
else
|
else
|
||||||
dsp_breakpoints.Add(real_addr);
|
dsp_breakpoints.Add(real_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::insertBLR(unsigned int address)
|
void DSPDebugInterface::insertBLR(unsigned int address)
|
||||||
{
|
{
|
||||||
PanicAlert("insertBLR functionality not supported in DSP module.");
|
PanicAlert("insertBLR functionality not supported in DSP module.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// =======================================================
|
// =======================================================
|
||||||
// Separate the blocks with colors.
|
// Separate the blocks with colors.
|
||||||
// -------------
|
// -------------
|
||||||
int DSPDebugInterface::getColor(unsigned int address)
|
int DSPDebugInterface::getColor(unsigned int address)
|
||||||
{
|
{
|
||||||
static const int colors[6] =
|
static const int colors[6] =
|
||||||
{
|
{
|
||||||
0xd0FFFF, // light cyan
|
0xd0FFFF, // light cyan
|
||||||
0xFFd0d0, // light red
|
0xFFd0d0, // light red
|
||||||
0xd8d8FF, // light blue
|
0xd8d8FF, // light blue
|
||||||
0xFFd0FF, // light purple
|
0xFFd0FF, // light purple
|
||||||
0xd0FFd0, // light green
|
0xd0FFd0, // light green
|
||||||
0xFFFFd0, // light yellow
|
0xFFFFd0, // light yellow
|
||||||
};
|
};
|
||||||
|
|
||||||
// Scan backwards so we don't miss it. Hm, actually, let's not - it looks pretty good.
|
// Scan backwards so we don't miss it. Hm, actually, let's not - it looks pretty good.
|
||||||
int addr = -1;
|
int addr = -1;
|
||||||
for (int i = 0; i < 1; i++)
|
for (int i = 0; i < 1; i++)
|
||||||
{
|
{
|
||||||
addr = DSPSymbols::Line2Addr(address - i);
|
addr = DSPSymbols::Line2Addr(address - i);
|
||||||
if (addr >= 0)
|
if (addr >= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (addr == -1)
|
if (addr == -1)
|
||||||
return 0xFFFFFF;
|
return 0xFFFFFF;
|
||||||
|
|
||||||
Symbol *symbol = DSPSymbols::g_dsp_symbol_db.GetSymbolFromAddr(addr);
|
Symbol *symbol = DSPSymbols::g_dsp_symbol_db.GetSymbolFromAddr(addr);
|
||||||
if (!symbol)
|
if (!symbol)
|
||||||
return 0xFFFFFF;
|
return 0xFFFFFF;
|
||||||
if (symbol->type != Symbol::SYMBOL_FUNCTION)
|
if (symbol->type != Symbol::SYMBOL_FUNCTION)
|
||||||
return 0xEEEEFF;
|
return 0xEEEEFF;
|
||||||
return colors[symbol->index % 6];
|
return colors[symbol->index % 6];
|
||||||
}
|
}
|
||||||
// =============
|
// =============
|
||||||
|
|
||||||
|
|
||||||
std::string DSPDebugInterface::getDescription(unsigned int address)
|
std::string DSPDebugInterface::getDescription(unsigned int address)
|
||||||
{
|
{
|
||||||
return ""; // g_symbolDB.GetDescription(address);
|
return ""; // g_symbolDB.GetDescription(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DSPDebugInterface::getPC()
|
unsigned int DSPDebugInterface::getPC()
|
||||||
{
|
{
|
||||||
return DSPSymbols::Addr2Line(g_dsp.pc);
|
return DSPSymbols::Addr2Line(g_dsp.pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::setPC(unsigned int address)
|
void DSPDebugInterface::setPC(unsigned int address)
|
||||||
{
|
{
|
||||||
int new_pc = DSPSymbols::Line2Addr(address);
|
int new_pc = DSPSymbols::Line2Addr(address);
|
||||||
if (new_pc > 0)
|
if (new_pc > 0)
|
||||||
g_dsp.pc = new_pc;
|
g_dsp.pc = new_pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebugInterface::runToBreakpoint()
|
void DSPDebugInterface::runToBreakpoint()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
#ifndef _DSPDEBUGINTERFACE_H
|
#ifndef _DSPDEBUGINTERFACE_H
|
||||||
#define _DSPDEBUGINTERFACE_H
|
#define _DSPDEBUGINTERFACE_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "DebugInterface.h"
|
#include "DebugInterface.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
class DSPDebugInterface : public DebugInterface
|
class DSPDebugInterface : public DebugInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DSPDebugInterface(){}
|
DSPDebugInterface(){}
|
||||||
virtual void disasm(unsigned int address, char *dest, int max_size);
|
virtual void disasm(unsigned int address, char *dest, int max_size);
|
||||||
virtual void getRawMemoryString(int memory, unsigned int address, char *dest, int max_size);
|
virtual void getRawMemoryString(int memory, unsigned int address, char *dest, int max_size);
|
||||||
virtual int getInstructionSize(int instruction) {return 1;}
|
virtual int getInstructionSize(int instruction) {return 1;}
|
||||||
virtual bool isAlive();
|
virtual bool isAlive();
|
||||||
virtual bool isBreakpoint(unsigned int address);
|
virtual bool isBreakpoint(unsigned int address);
|
||||||
virtual void setBreakpoint(unsigned int address);
|
virtual void setBreakpoint(unsigned int address);
|
||||||
virtual void clearBreakpoint(unsigned int address);
|
virtual void clearBreakpoint(unsigned int address);
|
||||||
virtual void clearAllBreakpoints();
|
virtual void clearAllBreakpoints();
|
||||||
virtual void toggleBreakpoint(unsigned int address);
|
virtual void toggleBreakpoint(unsigned int address);
|
||||||
virtual unsigned int readMemory(unsigned int address);
|
virtual unsigned int readMemory(unsigned int address);
|
||||||
virtual unsigned int readInstruction(unsigned int address);
|
virtual unsigned int readInstruction(unsigned int address);
|
||||||
virtual unsigned int getPC();
|
virtual unsigned int getPC();
|
||||||
virtual void setPC(unsigned int address);
|
virtual void setPC(unsigned int address);
|
||||||
virtual void step() {}
|
virtual void step() {}
|
||||||
virtual void runToBreakpoint();
|
virtual void runToBreakpoint();
|
||||||
virtual void insertBLR(unsigned int address);
|
virtual void insertBLR(unsigned int address);
|
||||||
virtual int getColor(unsigned int address);
|
virtual int getColor(unsigned int address);
|
||||||
virtual std::string getDescription(unsigned int address);
|
virtual std::string getDescription(unsigned int address);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _DSPDEBUGINTERFACE_H
|
#endif // _DSPDEBUGINTERFACE_H
|
||||||
|
|
|
@ -1,115 +1,115 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "DSPHost.h"
|
#include "DSPHost.h"
|
||||||
#include "DSPSymbols.h"
|
#include "DSPSymbols.h"
|
||||||
#include "Tools.h"
|
#include "Tools.h"
|
||||||
#include "pluginspecs_dsp.h"
|
#include "pluginspecs_dsp.h"
|
||||||
|
|
||||||
extern DSPInitialize g_dspInitialize;
|
extern DSPInitialize g_dspInitialize;
|
||||||
|
|
||||||
#if defined(HAVE_WX) && HAVE_WX
|
#if defined(HAVE_WX) && HAVE_WX
|
||||||
|
|
||||||
#include "DSPConfigDlgLLE.h"
|
#include "DSPConfigDlgLLE.h"
|
||||||
#include "Debugger/Debugger.h" // For the DSPDebuggerLLE class
|
#include "Debugger/Debugger.h" // For the DSPDebuggerLLE class
|
||||||
extern DSPDebuggerLLE* m_DebuggerFrame;
|
extern DSPDebuggerLLE* m_DebuggerFrame;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The user of the DSPCore library must supply a few functions so that the
|
// The user of the DSPCore library must supply a few functions so that the
|
||||||
// emulation core can access the environment it runs in. If the emulation
|
// emulation core can access the environment it runs in. If the emulation
|
||||||
// core isn't used, for example in an asm/disasm tool, then most of these
|
// core isn't used, for example in an asm/disasm tool, then most of these
|
||||||
// can be stubbed out.
|
// can be stubbed out.
|
||||||
|
|
||||||
u8 DSPHost_ReadHostMemory(u32 addr)
|
u8 DSPHost_ReadHostMemory(u32 addr)
|
||||||
{
|
{
|
||||||
return g_dspInitialize.pARAM_Read_U8(addr);
|
return g_dspInitialize.pARAM_Read_U8(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPHost_WriteHostMemory(u8 value, u32 addr)
|
void DSPHost_WriteHostMemory(u8 value, u32 addr)
|
||||||
{
|
{
|
||||||
g_dspInitialize.pARAM_Write_U8(value, addr);
|
g_dspInitialize.pARAM_Write_U8(value, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPHost_OnThread()
|
bool DSPHost_OnThread()
|
||||||
{
|
{
|
||||||
return g_dspInitialize.bOnThread;
|
return g_dspInitialize.bOnThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPHost_Running()
|
bool DSPHost_Running()
|
||||||
{
|
{
|
||||||
return !(*g_dspInitialize.pEmulatorState);
|
return !(*g_dspInitialize.pEmulatorState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPHost_InterruptRequest()
|
void DSPHost_InterruptRequest()
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_EXP
|
#ifdef DEBUG_EXP
|
||||||
NOTICE_LOG(DSPLLE, "Firing an interrupt on the PPC ASAP");
|
NOTICE_LOG(DSPLLE, "Firing an interrupt on the PPC ASAP");
|
||||||
#endif
|
#endif
|
||||||
// Fire an interrupt on the PPC ASAP.
|
// Fire an interrupt on the PPC ASAP.
|
||||||
g_dspInitialize.pGenerateDSPInterrupt();
|
g_dspInitialize.pGenerateDSPInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
|
u32 DSPHost_CodeLoaded(const u8 *ptr, int size)
|
||||||
{
|
{
|
||||||
u32 crc = GenerateCRC(ptr, size);
|
u32 crc = GenerateCRC(ptr, size);
|
||||||
DumpDSPCode(ptr, size, crc);
|
DumpDSPCode(ptr, size, crc);
|
||||||
|
|
||||||
// this crc is comparable with the HLE plugin
|
// this crc is comparable with the HLE plugin
|
||||||
u32 ector_crc = 0;
|
u32 ector_crc = 0;
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
ector_crc ^= ptr[i];
|
ector_crc ^= ptr[i];
|
||||||
//let's rol
|
//let's rol
|
||||||
ector_crc = (ector_crc << 3) | (ector_crc >> 29);
|
ector_crc = (ector_crc << 3) | (ector_crc >> 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
DSPSymbols::Clear();
|
DSPSymbols::Clear();
|
||||||
|
|
||||||
// Auto load text file - if none just disassemble.
|
// Auto load text file - if none just disassemble.
|
||||||
|
|
||||||
// TODO: Don't hardcode for Zelda.
|
// TODO: Don't hardcode for Zelda.
|
||||||
NOTICE_LOG(DSPLLE, "CRC: %08x", ector_crc);
|
NOTICE_LOG(DSPLLE, "CRC: %08x", ector_crc);
|
||||||
|
|
||||||
DSPSymbols::Clear();
|
DSPSymbols::Clear();
|
||||||
bool success = false;
|
bool success = false;
|
||||||
switch (ector_crc)
|
switch (ector_crc)
|
||||||
{
|
{
|
||||||
case 0x86840740: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Zelda.txt"); break;
|
case 0x86840740: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Zelda.txt"); break;
|
||||||
case 0x42f64ac4: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Luigi.txt"); break;
|
case 0x42f64ac4: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_Luigi.txt"); break;
|
||||||
case 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX1.txt"); break;
|
case 0x4e8a8b21: success = DSPSymbols::ReadAnnotatedAssembly("../../docs/DSP/DSP_UC_AX1.txt"); break;
|
||||||
default: success = false; break;
|
default: success = false; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
DSPSymbols::AutoDisassembly(0x0, 0x1000);
|
DSPSymbols::AutoDisassembly(0x0, 0x1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always add the ROM.
|
// Always add the ROM.
|
||||||
DSPSymbols::AutoDisassembly(0x8000, 0x9000);
|
DSPSymbols::AutoDisassembly(0x8000, 0x9000);
|
||||||
|
|
||||||
if (m_DebuggerFrame)
|
if (m_DebuggerFrame)
|
||||||
m_DebuggerFrame->Refresh();
|
m_DebuggerFrame->Refresh();
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPHost_UpdateDebugger()
|
void DSPHost_UpdateDebugger()
|
||||||
{
|
{
|
||||||
if (m_DebuggerFrame)
|
if (m_DebuggerFrame)
|
||||||
m_DebuggerFrame->Refresh();
|
m_DebuggerFrame->Refresh();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,287 +1,287 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include <iostream> // I hope this doesn't break anything
|
#include <iostream> // I hope this doesn't break anything
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
|
|
||||||
#include "DSPCore.h"
|
#include "DSPCore.h"
|
||||||
#include "DSPSymbols.h"
|
#include "DSPSymbols.h"
|
||||||
#include "disassemble.h"
|
#include "disassemble.h"
|
||||||
|
|
||||||
namespace DSPSymbols {
|
namespace DSPSymbols {
|
||||||
|
|
||||||
DSPSymbolDB g_dsp_symbol_db;
|
DSPSymbolDB g_dsp_symbol_db;
|
||||||
|
|
||||||
std::map<u16, int> addr_to_line;
|
std::map<u16, int> addr_to_line;
|
||||||
std::map<int, u16> line_to_addr;
|
std::map<int, u16> line_to_addr;
|
||||||
std::map<int, const char *> line_to_symbol;
|
std::map<int, const char *> line_to_symbol;
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
int line_counter = 0;
|
int line_counter = 0;
|
||||||
|
|
||||||
int Addr2Line(u16 address) // -1 for not found
|
int Addr2Line(u16 address) // -1 for not found
|
||||||
{
|
{
|
||||||
std::map<u16, int>::iterator iter = addr_to_line.find(address);
|
std::map<u16, int>::iterator iter = addr_to_line.find(address);
|
||||||
if (iter != addr_to_line.end())
|
if (iter != addr_to_line.end())
|
||||||
return iter->second;
|
return iter->second;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Line2Addr(int line) // -1 for not found
|
int Line2Addr(int line) // -1 for not found
|
||||||
{
|
{
|
||||||
std::map<int, u16>::iterator iter = line_to_addr.find(line);
|
std::map<int, u16>::iterator iter = line_to_addr.find(line);
|
||||||
if (iter != line_to_addr.end())
|
if (iter != line_to_addr.end())
|
||||||
return iter->second;
|
return iter->second;
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *GetLineText(int line)
|
const char *GetLineText(int line)
|
||||||
{
|
{
|
||||||
if (line > 0 && line < (int)lines.size())
|
if (line > 0 && line < (int)lines.size())
|
||||||
{
|
{
|
||||||
return lines[line].c_str();
|
return lines[line].c_str();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return "----";
|
return "----";
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *DSPSymbolDB::GetSymbolFromAddr(u32 addr)
|
Symbol *DSPSymbolDB::GetSymbolFromAddr(u32 addr)
|
||||||
{
|
{
|
||||||
XFuncMap::iterator it = functions.find(addr);
|
XFuncMap::iterator it = functions.find(addr);
|
||||||
if (it != functions.end())
|
if (it != functions.end())
|
||||||
return &it->second;
|
return &it->second;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||||
{
|
{
|
||||||
if (addr >= iter->second.address && addr < iter->second.address + iter->second.size)
|
if (addr >= iter->second.address && addr < iter->second.address + iter->second.size)
|
||||||
return &iter->second;
|
return &iter->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// lower case only
|
// lower case only
|
||||||
bool IsHexDigit(char c) {
|
bool IsHexDigit(char c) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '0':
|
case '0':
|
||||||
case '1':
|
case '1':
|
||||||
case '2':
|
case '2':
|
||||||
case '3':
|
case '3':
|
||||||
case '4':
|
case '4':
|
||||||
case '5':
|
case '5':
|
||||||
case '6':
|
case '6':
|
||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'c':
|
case 'c':
|
||||||
case 'd':
|
case 'd':
|
||||||
case 'e':
|
case 'e':
|
||||||
case 'f':
|
case 'f':
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsAlpha(char c) {
|
bool IsAlpha(char c) {
|
||||||
return (c >= 'A' && c <= 'Z') ||
|
return (c >= 'A' && c <= 'Z') ||
|
||||||
(c >= 'a' && c <= 'z');
|
(c >= 'a' && c <= 'z');
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisasssembleRange(u16 start, u16 end)
|
void DisasssembleRange(u16 start, u16 end)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadAnnotatedAssembly(const char *filename)
|
bool ReadAnnotatedAssembly(const char *filename)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(filename, "r");
|
FILE *f = fopen(filename, "r");
|
||||||
if (!f) {
|
if (!f) {
|
||||||
ERROR_LOG(DSPLLE, "Bah! ReadAnnotatedAssembly couldn't find the file %s", filename);
|
ERROR_LOG(DSPLLE, "Bah! ReadAnnotatedAssembly couldn't find the file %s", filename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char line[512];
|
char line[512];
|
||||||
|
|
||||||
int last_addr = 0;
|
int last_addr = 0;
|
||||||
|
|
||||||
lines.reserve(3000);
|
lines.reserve(3000);
|
||||||
|
|
||||||
// Symbol generation
|
// Symbol generation
|
||||||
int brace_count = 0;
|
int brace_count = 0;
|
||||||
bool symbol_in_progress = false;
|
bool symbol_in_progress = false;
|
||||||
|
|
||||||
int symbol_count = 0;
|
int symbol_count = 0;
|
||||||
Symbol current_symbol;
|
Symbol current_symbol;
|
||||||
|
|
||||||
while (fgets(line, 512, f))
|
while (fgets(line, 512, f))
|
||||||
{
|
{
|
||||||
// Scan string for the first 4-digit hex string.
|
// Scan string for the first 4-digit hex string.
|
||||||
size_t len = strlen(line);
|
size_t len = strlen(line);
|
||||||
int first_hex = -1;
|
int first_hex = -1;
|
||||||
bool hex_found = false;
|
bool hex_found = false;
|
||||||
for (unsigned int i = 0; i < strlen(line); i++)
|
for (unsigned int i = 0; i < strlen(line); i++)
|
||||||
{
|
{
|
||||||
const char c = line[i];
|
const char c = line[i];
|
||||||
if (IsHexDigit(c))
|
if (IsHexDigit(c))
|
||||||
{
|
{
|
||||||
if (first_hex == -1)
|
if (first_hex == -1)
|
||||||
{
|
{
|
||||||
first_hex = i;
|
first_hex = i;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Remove hex notation
|
// Remove hex notation
|
||||||
if (i == first_hex + 3 &&
|
if (i == first_hex + 3 &&
|
||||||
(first_hex == 0 || line[first_hex - 1] != 'x') &&
|
(first_hex == 0 || line[first_hex - 1] != 'x') &&
|
||||||
(i >= len - 1 || line[i + 1] == ' '))
|
(i >= len - 1 || line[i + 1] == ' '))
|
||||||
{
|
{
|
||||||
hex_found = true;
|
hex_found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (i - first_hex < 3)
|
if (i - first_hex < 3)
|
||||||
{
|
{
|
||||||
first_hex = -1;
|
first_hex = -1;
|
||||||
}
|
}
|
||||||
if (IsAlpha(c))
|
if (IsAlpha(c))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan for function starts
|
// Scan for function starts
|
||||||
if (!memcmp(line, "void", 4)) {
|
if (!memcmp(line, "void", 4)) {
|
||||||
char temp[256];
|
char temp[256];
|
||||||
for (int i = 6; i < len; i++) {
|
for (int i = 6; i < len; i++) {
|
||||||
if (line[i] == '(') {
|
if (line[i] == '(') {
|
||||||
// Yep, got one.
|
// Yep, got one.
|
||||||
memcpy(temp, line + 5, i - 5);
|
memcpy(temp, line + 5, i - 5);
|
||||||
temp[i - 5] = 0;
|
temp[i - 5] = 0;
|
||||||
|
|
||||||
// Mark symbol so the next hex sets the address
|
// Mark symbol so the next hex sets the address
|
||||||
current_symbol.name = temp;
|
current_symbol.name = temp;
|
||||||
current_symbol.address = 0xFFFF;
|
current_symbol.address = 0xFFFF;
|
||||||
current_symbol.index = symbol_count++;
|
current_symbol.index = symbol_count++;
|
||||||
symbol_in_progress = true;
|
symbol_in_progress = true;
|
||||||
|
|
||||||
// Reset brace count.
|
// Reset brace count.
|
||||||
brace_count = 0;
|
brace_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan for braces
|
// Scan for braces
|
||||||
for (int i = 0; i < (int)len; i++) {
|
for (int i = 0; i < (int)len; i++) {
|
||||||
if (line[i] == '{')
|
if (line[i] == '{')
|
||||||
brace_count++;
|
brace_count++;
|
||||||
if (line[i] == '}')
|
if (line[i] == '}')
|
||||||
{
|
{
|
||||||
brace_count--;
|
brace_count--;
|
||||||
if (brace_count == 0 && symbol_in_progress) {
|
if (brace_count == 0 && symbol_in_progress) {
|
||||||
// Commit this symbol.
|
// Commit this symbol.
|
||||||
current_symbol.size = last_addr - current_symbol.address + 1;
|
current_symbol.size = last_addr - current_symbol.address + 1;
|
||||||
g_dsp_symbol_db.AddCompleteSymbol(current_symbol);
|
g_dsp_symbol_db.AddCompleteSymbol(current_symbol);
|
||||||
current_symbol.address = 0xFFFF;
|
current_symbol.address = 0xFFFF;
|
||||||
symbol_in_progress = false;
|
symbol_in_progress = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hex_found)
|
if (hex_found)
|
||||||
{
|
{
|
||||||
int hex = 0;
|
int hex = 0;
|
||||||
sscanf(line + first_hex, "%04x", &hex);
|
sscanf(line + first_hex, "%04x", &hex);
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
if (hex > last_addr + 3 || hex < last_addr - 3) {
|
if (hex > last_addr + 3 || hex < last_addr - 3) {
|
||||||
static int errors = 0;
|
static int errors = 0;
|
||||||
ERROR_LOG(DSPLLE, "Got Insane Hex Digit %04x (%04x) from %s", hex, last_addr, line);
|
ERROR_LOG(DSPLLE, "Got Insane Hex Digit %04x (%04x) from %s", hex, last_addr, line);
|
||||||
errors++;
|
errors++;
|
||||||
if (errors > 10)
|
if (errors > 10)
|
||||||
{
|
{
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if (line_counter >= 200 && line_counter <= 220)
|
// if (line_counter >= 200 && line_counter <= 220)
|
||||||
// NOTICE_LOG(DSPLLE, "Got Hex Digit %04x from %s, line %i", hex, line, line_counter);
|
// NOTICE_LOG(DSPLLE, "Got Hex Digit %04x from %s, line %i", hex, line, line_counter);
|
||||||
if (symbol_in_progress && current_symbol.address == 0xFFFF)
|
if (symbol_in_progress && current_symbol.address == 0xFFFF)
|
||||||
current_symbol.address = hex;
|
current_symbol.address = hex;
|
||||||
|
|
||||||
line_to_addr[line_counter] = hex;
|
line_to_addr[line_counter] = hex;
|
||||||
addr_to_line[hex] = line_counter;
|
addr_to_line[hex] = line_counter;
|
||||||
last_addr = hex;
|
last_addr = hex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lines.push_back(TabsToSpaces(4, line));
|
lines.push_back(TabsToSpaces(4, line));
|
||||||
line_counter++;
|
line_counter++;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoDisassembly(u16 start_addr, u16 end_addr)
|
void AutoDisassembly(u16 start_addr, u16 end_addr)
|
||||||
{
|
{
|
||||||
AssemblerSettings settings;
|
AssemblerSettings settings;
|
||||||
settings.show_pc = true;
|
settings.show_pc = true;
|
||||||
settings.show_hex = true;
|
settings.show_hex = true;
|
||||||
DSPDisassembler disasm(settings);
|
DSPDisassembler disasm(settings);
|
||||||
|
|
||||||
u16 addr = start_addr;
|
u16 addr = start_addr;
|
||||||
const u16 *ptr = (start_addr >> 15) ? g_dsp.irom : g_dsp.iram;
|
const u16 *ptr = (start_addr >> 15) ? g_dsp.irom : g_dsp.iram;
|
||||||
while (addr < end_addr)
|
while (addr < end_addr)
|
||||||
{
|
{
|
||||||
line_to_addr[line_counter] = addr;
|
line_to_addr[line_counter] = addr;
|
||||||
addr_to_line[addr] = line_counter;
|
addr_to_line[addr] = line_counter;
|
||||||
|
|
||||||
std::string buf;
|
std::string buf;
|
||||||
if (!disasm.DisOpcode(ptr, 0, 2, &addr, buf))
|
if (!disasm.DisOpcode(ptr, 0, 2, &addr, buf))
|
||||||
{
|
{
|
||||||
ERROR_LOG(DSPLLE, "disasm failed at %04x", addr);
|
ERROR_LOG(DSPLLE, "disasm failed at %04x", addr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTICE_LOG(DSPLLE, "added %04x %i %s", addr, line_counter, buf.c_str());
|
//NOTICE_LOG(DSPLLE, "added %04x %i %s", addr, line_counter, buf.c_str());
|
||||||
lines.push_back(buf);
|
lines.push_back(buf);
|
||||||
line_counter++;
|
line_counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
addr_to_line.clear();
|
addr_to_line.clear();
|
||||||
line_to_addr.clear();
|
line_to_addr.clear();
|
||||||
lines.clear();
|
lines.clear();
|
||||||
line_counter = 0;
|
line_counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace DSPSymbols
|
} // namespace DSPSymbols
|
||||||
|
|
|
@ -1,54 +1,54 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DSPSYMBOLS_H
|
#ifndef _DSPSYMBOLS_H
|
||||||
#define _DSPSYMBOLS_H
|
#define _DSPSYMBOLS_H
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "SymbolDB.h"
|
#include "SymbolDB.h"
|
||||||
#include "AudioCommon.h"
|
#include "AudioCommon.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
namespace DSPSymbols {
|
namespace DSPSymbols {
|
||||||
|
|
||||||
class DSPSymbolDB : public SymbolDB
|
class DSPSymbolDB : public SymbolDB
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DSPSymbolDB() {}
|
DSPSymbolDB() {}
|
||||||
~DSPSymbolDB() {}
|
~DSPSymbolDB() {}
|
||||||
|
|
||||||
Symbol *GetSymbolFromAddr(u32 addr);
|
Symbol *GetSymbolFromAddr(u32 addr);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern DSPSymbolDB g_dsp_symbol_db;
|
extern DSPSymbolDB g_dsp_symbol_db;
|
||||||
|
|
||||||
bool ReadAnnotatedAssembly(const char *filename);
|
bool ReadAnnotatedAssembly(const char *filename);
|
||||||
void AutoDisassembly(u16 start_addr, u16 end_addr);
|
void AutoDisassembly(u16 start_addr, u16 end_addr);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
int Addr2Line(u16 address);
|
int Addr2Line(u16 address);
|
||||||
int Line2Addr(int line); // -1 for not found
|
int Line2Addr(int line); // -1 for not found
|
||||||
|
|
||||||
const char *GetLineText(int line);
|
const char *GetLineText(int line);
|
||||||
|
|
||||||
} // namespace DSPSymbols
|
} // namespace DSPSymbols
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,228 +1,228 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Common.h" // Common
|
#include "Common.h" // Common
|
||||||
#include <iostream> // System
|
#include <iostream> // System
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "Debugger.h"
|
#include "Debugger.h"
|
||||||
#include "DSPRegisterView.h"
|
#include "DSPRegisterView.h"
|
||||||
#include "CodeView.h"
|
#include "CodeView.h"
|
||||||
#include "../DSPSymbols.h"
|
#include "../DSPSymbols.h"
|
||||||
|
|
||||||
// Event table and class
|
// Event table and class
|
||||||
BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxFrame)
|
BEGIN_EVENT_TABLE(DSPDebuggerLLE, wxFrame)
|
||||||
EVT_CLOSE(DSPDebuggerLLE::OnClose)
|
EVT_CLOSE(DSPDebuggerLLE::OnClose)
|
||||||
|
|
||||||
EVT_MENU_RANGE(ID_RUNTOOL, ID_STEPTOOL, DSPDebuggerLLE::OnChangeState)
|
EVT_MENU_RANGE(ID_RUNTOOL, ID_STEPTOOL, DSPDebuggerLLE::OnChangeState)
|
||||||
EVT_MENU(ID_SHOWPCTOOL, DSPDebuggerLLE::OnShowPC)
|
EVT_MENU(ID_SHOWPCTOOL, DSPDebuggerLLE::OnShowPC)
|
||||||
EVT_TEXT(ID_ADDRBOX, DSPDebuggerLLE::OnAddrBoxChange)
|
EVT_TEXT(ID_ADDRBOX, DSPDebuggerLLE::OnAddrBoxChange)
|
||||||
EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange)
|
EVT_LISTBOX(ID_SYMBOLLIST, DSPDebuggerLLE::OnSymbolListChange)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
DSPDebuggerLLE::DSPDebuggerLLE(wxWindow *parent, wxWindowID id, const wxString &title,
|
DSPDebuggerLLE::DSPDebuggerLLE(wxWindow *parent, wxWindowID id, const wxString &title,
|
||||||
const wxPoint &position, const wxSize& size, long style)
|
const wxPoint &position, const wxSize& size, long style)
|
||||||
: wxFrame(parent, id, title, position, size, style)
|
: wxFrame(parent, id, title, position, size, style)
|
||||||
, m_CachedStepCounter(-1)
|
, m_CachedStepCounter(-1)
|
||||||
{
|
{
|
||||||
CreateGUIControls();
|
CreateGUIControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
DSPDebuggerLLE::~DSPDebuggerLLE()
|
DSPDebuggerLLE::~DSPDebuggerLLE()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::CreateGUIControls()
|
void DSPDebuggerLLE::CreateGUIControls()
|
||||||
{
|
{
|
||||||
// Basic settings
|
// Basic settings
|
||||||
SetSize(700, 800);
|
SetSize(700, 800);
|
||||||
this->SetSizeHints(700, 800);
|
this->SetSizeHints(700, 800);
|
||||||
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
|
this->SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
|
||||||
|
|
||||||
m_Toolbar = CreateToolBar(wxTB_NODIVIDER|wxTB_NOICONS|wxTB_HORZ_TEXT|wxTB_DOCKABLE, ID_TOOLBAR);
|
m_Toolbar = CreateToolBar(wxTB_NODIVIDER|wxTB_NOICONS|wxTB_HORZ_TEXT|wxTB_DOCKABLE, ID_TOOLBAR);
|
||||||
m_Toolbar->AddTool(ID_RUNTOOL, wxT("Run"), wxNullBitmap, wxEmptyString, wxITEM_NORMAL);
|
m_Toolbar->AddTool(ID_RUNTOOL, wxT("Run"), wxNullBitmap, wxEmptyString, wxITEM_NORMAL);
|
||||||
m_Toolbar->AddTool(ID_STEPTOOL, wxT("Step"), wxNullBitmap, wxT("Step Code "), wxITEM_NORMAL);
|
m_Toolbar->AddTool(ID_STEPTOOL, wxT("Step"), wxNullBitmap, wxT("Step Code "), wxITEM_NORMAL);
|
||||||
m_Toolbar->AddTool(ID_SHOWPCTOOL, wxT("Show Pc"), wxNullBitmap, wxT("Show where PC is"), wxITEM_NORMAL);
|
m_Toolbar->AddTool(ID_SHOWPCTOOL, wxT("Show Pc"), wxNullBitmap, wxT("Show where PC is"), wxITEM_NORMAL);
|
||||||
m_Toolbar->AddTool(ID_JUMPTOTOOL, wxT("Jump"), wxNullBitmap, wxT("Jump to a specific Address"), wxITEM_NORMAL);
|
m_Toolbar->AddTool(ID_JUMPTOTOOL, wxT("Jump"), wxNullBitmap, wxT("Jump to a specific Address"), wxITEM_NORMAL);
|
||||||
m_Toolbar->AddSeparator();
|
m_Toolbar->AddSeparator();
|
||||||
|
|
||||||
m_Toolbar->AddControl(new wxTextCtrl(m_Toolbar, ID_ADDRBOX, _T("")));
|
m_Toolbar->AddControl(new wxTextCtrl(m_Toolbar, ID_ADDRBOX, _T("")));
|
||||||
|
|
||||||
m_Toolbar->Realize();
|
m_Toolbar->Realize();
|
||||||
|
|
||||||
wxBoxSizer* sMain = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* sMain = new wxBoxSizer(wxHORIZONTAL);
|
||||||
wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
|
||||||
sizerLeft->Add(m_SymbolList = new wxListBox(this, ID_SYMBOLLIST, wxDefaultPosition, wxSize(140, 100), 0, NULL, wxLB_SORT),
|
sizerLeft->Add(m_SymbolList = new wxListBox(this, ID_SYMBOLLIST, wxDefaultPosition, wxSize(140, 100), 0, NULL, wxLB_SORT),
|
||||||
1, wxEXPAND);
|
1, wxEXPAND);
|
||||||
|
|
||||||
m_CodeView = new CCodeView(&debug_interface, &DSPSymbols::g_dsp_symbol_db, this, ID_CODEVIEW);
|
m_CodeView = new CCodeView(&debug_interface, &DSPSymbols::g_dsp_symbol_db, this, ID_CODEVIEW);
|
||||||
m_CodeView->SetPlain();
|
m_CodeView->SetPlain();
|
||||||
|
|
||||||
sMain->Add(sizerLeft, 0, wxEXPAND, 0);
|
sMain->Add(sizerLeft, 0, wxEXPAND, 0);
|
||||||
|
|
||||||
sMain->Add(m_CodeView, 4, wxEXPAND, 0);
|
sMain->Add(m_CodeView, 4, wxEXPAND, 0);
|
||||||
|
|
||||||
wxStaticLine* m_staticline = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
|
wxStaticLine* m_staticline = new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL);
|
||||||
sMain->Add(m_staticline, 0, wxEXPAND|wxALL, 0);
|
sMain->Add(m_staticline, 0, wxEXPAND|wxALL, 0);
|
||||||
|
|
||||||
m_Regs = new DSPRegisterView(this, ID_DSP_REGS);
|
m_Regs = new DSPRegisterView(this, ID_DSP_REGS);
|
||||||
sMain->Add(m_Regs, 0, wxEXPAND|wxALL, 5);
|
sMain->Add(m_Regs, 0, wxEXPAND|wxALL, 5);
|
||||||
|
|
||||||
this->SetSizer(sMain);
|
this->SetSizer(sMain);
|
||||||
this->Layout();
|
this->Layout();
|
||||||
|
|
||||||
UpdateState();
|
UpdateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::OnClose(wxCloseEvent& event)
|
void DSPDebuggerLLE::OnClose(wxCloseEvent& event)
|
||||||
{
|
{
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
|
void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
switch (event.GetId())
|
switch (event.GetId())
|
||||||
{
|
{
|
||||||
case ID_RUNTOOL:
|
case ID_RUNTOOL:
|
||||||
if (DSPCore_GetState() == DSPCORE_RUNNING)
|
if (DSPCore_GetState() == DSPCORE_RUNNING)
|
||||||
DSPCore_SetState(DSPCORE_STEPPING);
|
DSPCore_SetState(DSPCORE_STEPPING);
|
||||||
else
|
else
|
||||||
DSPCore_SetState(DSPCORE_RUNNING);
|
DSPCore_SetState(DSPCORE_RUNNING);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ID_STEPTOOL:
|
case ID_STEPTOOL:
|
||||||
if (DSPCore_GetState() == DSPCORE_STEPPING)
|
if (DSPCore_GetState() == DSPCORE_STEPPING)
|
||||||
DSPCore_Step();
|
DSPCore_Step();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ID_SHOWPCTOOL:
|
case ID_SHOWPCTOOL:
|
||||||
FocusOnPC();
|
FocusOnPC();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateState();
|
UpdateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::OnShowPC(wxCommandEvent& event)
|
void DSPDebuggerLLE::OnShowPC(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
Refresh();
|
Refresh();
|
||||||
FocusOnPC();
|
FocusOnPC();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::Refresh()
|
void DSPDebuggerLLE::Refresh()
|
||||||
{
|
{
|
||||||
UpdateSymbolMap();
|
UpdateSymbolMap();
|
||||||
UpdateDisAsmListView();
|
UpdateDisAsmListView();
|
||||||
UpdateRegisterFlags();
|
UpdateRegisterFlags();
|
||||||
UpdateState();
|
UpdateState();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::FocusOnPC()
|
void DSPDebuggerLLE::FocusOnPC()
|
||||||
{
|
{
|
||||||
JumpToAddress(g_dsp.pc);
|
JumpToAddress(g_dsp.pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::UpdateState()
|
void DSPDebuggerLLE::UpdateState()
|
||||||
{
|
{
|
||||||
if (DSPCore_GetState() == DSPCORE_RUNNING) {
|
if (DSPCore_GetState() == DSPCORE_RUNNING) {
|
||||||
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Pause"));
|
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Pause"));
|
||||||
m_Toolbar->FindById(ID_STEPTOOL)->Enable(false);
|
m_Toolbar->FindById(ID_STEPTOOL)->Enable(false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Run"));
|
m_Toolbar->FindById(ID_RUNTOOL)->SetLabel(wxT("Run"));
|
||||||
m_Toolbar->FindById(ID_STEPTOOL)->Enable(true);
|
m_Toolbar->FindById(ID_STEPTOOL)->Enable(true);
|
||||||
}
|
}
|
||||||
m_Toolbar->Realize();
|
m_Toolbar->Realize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::UpdateDisAsmListView()
|
void DSPDebuggerLLE::UpdateDisAsmListView()
|
||||||
{
|
{
|
||||||
if (m_CachedStepCounter == g_dsp.step_counter)
|
if (m_CachedStepCounter == g_dsp.step_counter)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// show PC
|
// show PC
|
||||||
FocusOnPC();
|
FocusOnPC();
|
||||||
m_CachedStepCounter = g_dsp.step_counter;
|
m_CachedStepCounter = g_dsp.step_counter;
|
||||||
m_Regs->Update();
|
m_Regs->Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::UpdateSymbolMap()
|
void DSPDebuggerLLE::UpdateSymbolMap()
|
||||||
{
|
{
|
||||||
if (g_dsp.dram == NULL)
|
if (g_dsp.dram == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_SymbolList->Freeze(); // HyperIris: wx style fast filling
|
m_SymbolList->Freeze(); // HyperIris: wx style fast filling
|
||||||
m_SymbolList->Clear();
|
m_SymbolList->Clear();
|
||||||
for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator();
|
for (SymbolDB::XFuncMap::iterator iter = DSPSymbols::g_dsp_symbol_db.GetIterator();
|
||||||
iter != DSPSymbols::g_dsp_symbol_db.End(); iter++)
|
iter != DSPSymbols::g_dsp_symbol_db.End(); iter++)
|
||||||
{
|
{
|
||||||
int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str()));
|
int idx = m_SymbolList->Append(wxString::FromAscii(iter->second.name.c_str()));
|
||||||
m_SymbolList->SetClientData(idx, (void*)&iter->second);
|
m_SymbolList->SetClientData(idx, (void*)&iter->second);
|
||||||
}
|
}
|
||||||
m_SymbolList->Thaw();
|
m_SymbolList->Thaw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::OnSymbolListChange(wxCommandEvent& event)
|
void DSPDebuggerLLE::OnSymbolListChange(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
int index = m_SymbolList->GetSelection();
|
int index = m_SymbolList->GetSelection();
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
Symbol* pSymbol = static_cast<Symbol *>(m_SymbolList->GetClientData(index));
|
Symbol* pSymbol = static_cast<Symbol *>(m_SymbolList->GetClientData(index));
|
||||||
if (pSymbol != NULL)
|
if (pSymbol != NULL)
|
||||||
{
|
{
|
||||||
if (pSymbol->type == Symbol::SYMBOL_FUNCTION)
|
if (pSymbol->type == Symbol::SYMBOL_FUNCTION)
|
||||||
{
|
{
|
||||||
JumpToAddress(pSymbol->address);
|
JumpToAddress(pSymbol->address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::UpdateRegisterFlags()
|
void DSPDebuggerLLE::UpdateRegisterFlags()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event)
|
void DSPDebuggerLLE::OnAddrBoxChange(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(ID_ADDRBOX);
|
wxTextCtrl* pAddrCtrl = (wxTextCtrl*)GetToolBar()->FindControl(ID_ADDRBOX);
|
||||||
wxString txt = pAddrCtrl->GetValue();
|
wxString txt = pAddrCtrl->GetValue();
|
||||||
|
|
||||||
std::string text(txt.mb_str());
|
std::string text(txt.mb_str());
|
||||||
text = StripSpaces(text);
|
text = StripSpaces(text);
|
||||||
if (text.size())
|
if (text.size())
|
||||||
{
|
{
|
||||||
u32 addr;
|
u32 addr;
|
||||||
sscanf(text.c_str(), "%04x", &addr);
|
sscanf(text.c_str(), "%04x", &addr);
|
||||||
if (JumpToAddress(addr))
|
if (JumpToAddress(addr))
|
||||||
pAddrCtrl->SetBackgroundColour(*wxWHITE);
|
pAddrCtrl->SetBackgroundColour(*wxWHITE);
|
||||||
else
|
else
|
||||||
pAddrCtrl->SetBackgroundColour(*wxRED);
|
pAddrCtrl->SetBackgroundColour(*wxRED);
|
||||||
}
|
}
|
||||||
event.Skip(1);
|
event.Skip(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSPDebuggerLLE::JumpToAddress(u16 addr)
|
bool DSPDebuggerLLE::JumpToAddress(u16 addr)
|
||||||
{
|
{
|
||||||
int new_line = DSPSymbols::Addr2Line(addr);
|
int new_line = DSPSymbols::Addr2Line(addr);
|
||||||
if (new_line >= 0) {
|
if (new_line >= 0) {
|
||||||
m_CodeView->Center(new_line);
|
m_CodeView->Center(new_line);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,126 +1,126 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _DSP_DEBUGGER_LLE_H
|
#ifndef _DSP_DEBUGGER_LLE_H
|
||||||
#define _DSP_DEBUGGER_LLE_H
|
#define _DSP_DEBUGGER_LLE_H
|
||||||
|
|
||||||
// general things
|
// general things
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#include <wx/frame.h>
|
#include <wx/frame.h>
|
||||||
#include <wx/button.h>
|
#include <wx/button.h>
|
||||||
#include <wx/stattext.h>
|
#include <wx/stattext.h>
|
||||||
#include <wx/statbox.h>
|
#include <wx/statbox.h>
|
||||||
#include <wx/sizer.h>
|
#include <wx/sizer.h>
|
||||||
#include <wx/listctrl.h>
|
#include <wx/listctrl.h>
|
||||||
#include <wx/statline.h>
|
#include <wx/statline.h>
|
||||||
|
|
||||||
#include "disassemble.h"
|
#include "disassemble.h"
|
||||||
#include "DSPInterpreter.h"
|
#include "DSPInterpreter.h"
|
||||||
#include "DSPMemoryMap.h"
|
#include "DSPMemoryMap.h"
|
||||||
#include "../DSPDebugInterface.h"
|
#include "../DSPDebugInterface.h"
|
||||||
|
|
||||||
class DSPRegisterView;
|
class DSPRegisterView;
|
||||||
class CCodeView;
|
class CCodeView;
|
||||||
|
|
||||||
class DSPDebuggerLLE : public wxFrame
|
class DSPDebuggerLLE : public wxFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DSPDebuggerLLE(wxWindow *parent,
|
DSPDebuggerLLE(wxWindow *parent,
|
||||||
wxWindowID id = wxID_ANY,
|
wxWindowID id = wxID_ANY,
|
||||||
const wxString &title = wxT("DSP LLE Debugger"),
|
const wxString &title = wxT("DSP LLE Debugger"),
|
||||||
const wxPoint& pos = wxDefaultPosition,
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
const wxSize& size = wxDefaultSize,
|
const wxSize& size = wxDefaultSize,
|
||||||
long style = wxDEFAULT_FRAME_STYLE);
|
long style = wxDEFAULT_FRAME_STYLE);
|
||||||
|
|
||||||
virtual ~DSPDebuggerLLE();
|
virtual ~DSPDebuggerLLE();
|
||||||
|
|
||||||
void Refresh();
|
void Refresh();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
// Toolbar
|
// Toolbar
|
||||||
ID_TOOLBAR = 1000,
|
ID_TOOLBAR = 1000,
|
||||||
ID_RUNTOOL,
|
ID_RUNTOOL,
|
||||||
ID_STEPTOOL,
|
ID_STEPTOOL,
|
||||||
ID_SHOWPCTOOL,
|
ID_SHOWPCTOOL,
|
||||||
ID_ADDRBOX,
|
ID_ADDRBOX,
|
||||||
ID_JUMPTOTOOL,
|
ID_JUMPTOTOOL,
|
||||||
ID_DISASMDUMPTOOL,
|
ID_DISASMDUMPTOOL,
|
||||||
ID_CHECK_ASSERTINT,
|
ID_CHECK_ASSERTINT,
|
||||||
ID_CHECK_HALT,
|
ID_CHECK_HALT,
|
||||||
ID_CHECK_INIT,
|
ID_CHECK_INIT,
|
||||||
ID_SYMBOLLIST,
|
ID_SYMBOLLIST,
|
||||||
|
|
||||||
// Code view
|
// Code view
|
||||||
ID_CODEVIEW,
|
ID_CODEVIEW,
|
||||||
|
|
||||||
// Register View
|
// Register View
|
||||||
ID_DSP_REGS,
|
ID_DSP_REGS,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Disasm listctrl columns
|
// Disasm listctrl columns
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
COLUMN_BP,
|
COLUMN_BP,
|
||||||
COLUMN_FUNCTION,
|
COLUMN_FUNCTION,
|
||||||
COLUMN_ADDRESS,
|
COLUMN_ADDRESS,
|
||||||
COLUMN_MNEMONIC,
|
COLUMN_MNEMONIC,
|
||||||
COLUMN_OPCODE,
|
COLUMN_OPCODE,
|
||||||
COLUMN_EXT,
|
COLUMN_EXT,
|
||||||
COLUMN_PARAM,
|
COLUMN_PARAM,
|
||||||
};
|
};
|
||||||
|
|
||||||
DSPDebugInterface debug_interface;
|
DSPDebugInterface debug_interface;
|
||||||
u64 m_CachedStepCounter;
|
u64 m_CachedStepCounter;
|
||||||
|
|
||||||
// GUI updaters
|
// GUI updaters
|
||||||
void UpdateDisAsmListView();
|
void UpdateDisAsmListView();
|
||||||
void UpdateRegisterFlags();
|
void UpdateRegisterFlags();
|
||||||
void UpdateSymbolMap();
|
void UpdateSymbolMap();
|
||||||
void UpdateState();
|
void UpdateState();
|
||||||
|
|
||||||
// GUI items
|
// GUI items
|
||||||
wxToolBar* m_Toolbar;
|
wxToolBar* m_Toolbar;
|
||||||
CCodeView* m_CodeView;
|
CCodeView* m_CodeView;
|
||||||
DSPRegisterView* m_Regs;
|
DSPRegisterView* m_Regs;
|
||||||
wxListBox* m_SymbolList;
|
wxListBox* m_SymbolList;
|
||||||
|
|
||||||
void OnClose(wxCloseEvent& event);
|
void OnClose(wxCloseEvent& event);
|
||||||
void OnChangeState(wxCommandEvent& event);
|
void OnChangeState(wxCommandEvent& event);
|
||||||
void OnShowPC(wxCommandEvent& event);
|
void OnShowPC(wxCommandEvent& event);
|
||||||
void OnRightClick(wxListEvent& event);
|
void OnRightClick(wxListEvent& event);
|
||||||
void OnDoubleClick(wxListEvent& event);
|
void OnDoubleClick(wxListEvent& event);
|
||||||
void OnAddrBoxChange(wxCommandEvent& event);
|
void OnAddrBoxChange(wxCommandEvent& event);
|
||||||
void OnSymbolListChange(wxCommandEvent& event);
|
void OnSymbolListChange(wxCommandEvent& event);
|
||||||
|
|
||||||
bool JumpToAddress(u16 addr);
|
bool JumpToAddress(u16 addr);
|
||||||
|
|
||||||
void CreateGUIControls();
|
void CreateGUIControls();
|
||||||
void FocusOnPC();
|
void FocusOnPC();
|
||||||
void UnselectAll();
|
void UnselectAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_DSP_DEBUGGER_LLE_H
|
#endif //_DSP_DEBUGGER_LLE_H
|
||||||
|
|
|
@ -1,336 +1,336 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "BPFunctions.h"
|
#include "BPFunctions.h"
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "TextureCache.h"
|
#include "TextureCache.h"
|
||||||
#include "VertexManager.h"
|
#include "VertexManager.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
|
|
||||||
bool textureChanged[8];
|
bool textureChanged[8];
|
||||||
|
|
||||||
const bool renderFog = false;
|
const bool renderFog = false;
|
||||||
|
|
||||||
using namespace D3D;
|
using namespace D3D;
|
||||||
|
|
||||||
// State translation lookup tables
|
// State translation lookup tables
|
||||||
static const D3DBLEND d3dSrcFactors[8] =
|
static const D3DBLEND d3dSrcFactors[8] =
|
||||||
{
|
{
|
||||||
D3DBLEND_ZERO,
|
D3DBLEND_ZERO,
|
||||||
D3DBLEND_ONE,
|
D3DBLEND_ONE,
|
||||||
D3DBLEND_DESTCOLOR,
|
D3DBLEND_DESTCOLOR,
|
||||||
D3DBLEND_INVDESTCOLOR,
|
D3DBLEND_INVDESTCOLOR,
|
||||||
D3DBLEND_SRCALPHA,
|
D3DBLEND_SRCALPHA,
|
||||||
D3DBLEND_INVSRCALPHA,
|
D3DBLEND_INVSRCALPHA,
|
||||||
D3DBLEND_DESTALPHA,
|
D3DBLEND_DESTALPHA,
|
||||||
D3DBLEND_INVDESTALPHA
|
D3DBLEND_INVDESTALPHA
|
||||||
};
|
};
|
||||||
|
|
||||||
static const D3DBLEND d3dDestFactors[8] =
|
static const D3DBLEND d3dDestFactors[8] =
|
||||||
{
|
{
|
||||||
D3DBLEND_ZERO,
|
D3DBLEND_ZERO,
|
||||||
D3DBLEND_ONE,
|
D3DBLEND_ONE,
|
||||||
D3DBLEND_SRCCOLOR,
|
D3DBLEND_SRCCOLOR,
|
||||||
D3DBLEND_INVSRCCOLOR,
|
D3DBLEND_INVSRCCOLOR,
|
||||||
D3DBLEND_SRCALPHA,
|
D3DBLEND_SRCALPHA,
|
||||||
D3DBLEND_INVSRCALPHA,
|
D3DBLEND_INVSRCALPHA,
|
||||||
D3DBLEND_DESTALPHA,
|
D3DBLEND_DESTALPHA,
|
||||||
D3DBLEND_INVDESTALPHA
|
D3DBLEND_INVDESTALPHA
|
||||||
};
|
};
|
||||||
|
|
||||||
static const D3DCULL d3dCullModes[4] =
|
static const D3DCULL d3dCullModes[4] =
|
||||||
{
|
{
|
||||||
D3DCULL_NONE,
|
D3DCULL_NONE,
|
||||||
D3DCULL_CCW,
|
D3DCULL_CCW,
|
||||||
D3DCULL_CW,
|
D3DCULL_CW,
|
||||||
D3DCULL_CCW
|
D3DCULL_CCW
|
||||||
};
|
};
|
||||||
|
|
||||||
static const D3DCMPFUNC d3dCmpFuncs[8] =
|
static const D3DCMPFUNC d3dCmpFuncs[8] =
|
||||||
{
|
{
|
||||||
D3DCMP_NEVER,
|
D3DCMP_NEVER,
|
||||||
D3DCMP_LESS,
|
D3DCMP_LESS,
|
||||||
D3DCMP_EQUAL,
|
D3DCMP_EQUAL,
|
||||||
D3DCMP_LESSEQUAL,
|
D3DCMP_LESSEQUAL,
|
||||||
D3DCMP_GREATER,
|
D3DCMP_GREATER,
|
||||||
D3DCMP_NOTEQUAL,
|
D3DCMP_NOTEQUAL,
|
||||||
D3DCMP_GREATEREQUAL,
|
D3DCMP_GREATEREQUAL,
|
||||||
D3DCMP_ALWAYS
|
D3DCMP_ALWAYS
|
||||||
};
|
};
|
||||||
|
|
||||||
static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
|
static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] =
|
||||||
{
|
{
|
||||||
D3DTEXF_NONE,
|
D3DTEXF_NONE,
|
||||||
D3DTEXF_POINT,
|
D3DTEXF_POINT,
|
||||||
D3DTEXF_ANISOTROPIC,
|
D3DTEXF_ANISOTROPIC,
|
||||||
D3DTEXF_LINEAR, //reserved
|
D3DTEXF_LINEAR, //reserved
|
||||||
};
|
};
|
||||||
|
|
||||||
static const D3DTEXTUREADDRESS d3dClamps[4] =
|
static const D3DTEXTUREADDRESS d3dClamps[4] =
|
||||||
{
|
{
|
||||||
D3DTADDRESS_CLAMP,
|
D3DTADDRESS_CLAMP,
|
||||||
D3DTADDRESS_WRAP,
|
D3DTADDRESS_WRAP,
|
||||||
D3DTADDRESS_MIRROR,
|
D3DTADDRESS_MIRROR,
|
||||||
D3DTADDRESS_WRAP //reserved
|
D3DTADDRESS_WRAP //reserved
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace BPFunctions
|
namespace BPFunctions
|
||||||
{
|
{
|
||||||
|
|
||||||
void FlushPipeline()
|
void FlushPipeline()
|
||||||
{
|
{
|
||||||
VertexManager::Flush();
|
VertexManager::Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetGenerationMode(const Bypass &bp)
|
void SetGenerationMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
// dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
|
// dev->SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
|
||||||
Renderer::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
|
Renderer::SetRenderState(D3DRS_CULLMODE, d3dCullModes[bpmem.genMode.cullmode]);
|
||||||
|
|
||||||
if (bpmem.genMode.cullmode == 3)
|
if (bpmem.genMode.cullmode == 3)
|
||||||
{
|
{
|
||||||
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||||
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DWORD write = 0;
|
DWORD write = 0;
|
||||||
if (bpmem.blendmode.alphaupdate)
|
if (bpmem.blendmode.alphaupdate)
|
||||||
write = D3DCOLORWRITEENABLE_ALPHA;
|
write = D3DCOLORWRITEENABLE_ALPHA;
|
||||||
if (bpmem.blendmode.colorupdate)
|
if (bpmem.blendmode.colorupdate)
|
||||||
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
|
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
|
||||||
|
|
||||||
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
// dev->SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
||||||
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetScissor(const Bypass &bp)
|
void SetScissor(const Bypass &bp)
|
||||||
{
|
{
|
||||||
Renderer::SetScissorRect();
|
Renderer::SetScissorRect();
|
||||||
}
|
}
|
||||||
void SetLineWidth(const Bypass &bp)
|
void SetLineWidth(const Bypass &bp)
|
||||||
{
|
{
|
||||||
// We can't change line width in D3D unless we use ID3DXLine
|
// We can't change line width in D3D unless we use ID3DXLine
|
||||||
float psize = float(bpmem.lineptwidth.pointsize) * 6.0f;
|
float psize = float(bpmem.lineptwidth.pointsize) * 6.0f;
|
||||||
Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize));
|
Renderer::SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psize));
|
||||||
}
|
}
|
||||||
void SetDepthMode(const Bypass &bp)
|
void SetDepthMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
if (bpmem.zmode.testenable)
|
if (bpmem.zmode.testenable)
|
||||||
{
|
{
|
||||||
// dev->SetRenderState(D3DRS_ZENABLE, TRUE);
|
// dev->SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||||
// dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
|
// dev->SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
|
||||||
// dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]);
|
// dev->SetRenderState(D3DRS_ZFUNC,d3dCmpFuncs[bpmem.zmode.func]);
|
||||||
|
|
||||||
Renderer::SetRenderState(D3DRS_ZENABLE, TRUE);
|
Renderer::SetRenderState(D3DRS_ZENABLE, TRUE);
|
||||||
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
|
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, bpmem.zmode.updateenable);
|
||||||
Renderer::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func]);
|
Renderer::SetRenderState(D3DRS_ZFUNC, d3dCmpFuncs[bpmem.zmode.func]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if the test is disabled write is disabled too
|
// if the test is disabled write is disabled too
|
||||||
// dev->SetRenderState(D3DRS_ZENABLE, FALSE);
|
// dev->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||||
// dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
// dev->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||||
|
|
||||||
Renderer::SetRenderState(D3DRS_ZENABLE, FALSE);
|
Renderer::SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||||
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
Renderer::SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!bpmem.zmode.updateenable)
|
//if (!bpmem.zmode.updateenable)
|
||||||
// Renderer::SetRenderMode(Renderer::RM_Normal);
|
// Renderer::SetRenderMode(Renderer::RM_Normal);
|
||||||
|
|
||||||
}
|
}
|
||||||
void SetBlendMode(const Bypass &bp)
|
void SetBlendMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
if (bp.changes & 1)
|
if (bp.changes & 1)
|
||||||
Renderer::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable);
|
Renderer::SetRenderState(D3DRS_ALPHABLENDENABLE, bpmem.blendmode.blendenable);
|
||||||
|
|
||||||
D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor];
|
D3DBLEND src = d3dSrcFactors[bpmem.blendmode.srcfactor];
|
||||||
D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor];
|
D3DBLEND dst = d3dDestFactors[bpmem.blendmode.dstfactor];
|
||||||
|
|
||||||
if (bp.changes & 0x700)
|
if (bp.changes & 0x700)
|
||||||
Renderer::SetRenderState(D3DRS_SRCBLEND, src);
|
Renderer::SetRenderState(D3DRS_SRCBLEND, src);
|
||||||
|
|
||||||
if (bp.changes & 0xE0) {
|
if (bp.changes & 0xE0) {
|
||||||
if (!bpmem.blendmode.subtract)
|
if (!bpmem.blendmode.subtract)
|
||||||
{
|
{
|
||||||
Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
|
Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (bp.changes & 0x800)
|
if (bp.changes & 0x800)
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.subtract)
|
if (bpmem.blendmode.subtract)
|
||||||
{
|
{
|
||||||
Renderer::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
Renderer::SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||||
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
Renderer::SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Renderer::SetRenderState(D3DRS_SRCBLEND, src);
|
Renderer::SetRenderState(D3DRS_SRCBLEND, src);
|
||||||
Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
|
Renderer::SetRenderState(D3DRS_DESTBLEND, dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::SetRenderState(D3DRS_BLENDOP, bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD);
|
Renderer::SetRenderState(D3DRS_BLENDOP, bpmem.blendmode.subtract ? D3DBLENDOP_SUBTRACT : D3DBLENDOP_ADD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SetDitherMode(const Bypass &bp)
|
void SetDitherMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
Renderer::SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither);
|
Renderer::SetRenderState(D3DRS_DITHERENABLE,bpmem.blendmode.dither);
|
||||||
}
|
}
|
||||||
void SetLogicOpMode(const Bypass &bp)
|
void SetLogicOpMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
// Logic op blending. D3D can't do this but can fake some modes.
|
// Logic op blending. D3D can't do this but can fake some modes.
|
||||||
}
|
}
|
||||||
void SetColorMask(const Bypass &bp)
|
void SetColorMask(const Bypass &bp)
|
||||||
{
|
{
|
||||||
DWORD write = 0;
|
DWORD write = 0;
|
||||||
if (bpmem.blendmode.alphaupdate)
|
if (bpmem.blendmode.alphaupdate)
|
||||||
write = D3DCOLORWRITEENABLE_ALPHA;
|
write = D3DCOLORWRITEENABLE_ALPHA;
|
||||||
if (bpmem.blendmode.colorupdate)
|
if (bpmem.blendmode.colorupdate)
|
||||||
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
|
write |= D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
|
||||||
|
|
||||||
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
Renderer::SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
||||||
}
|
}
|
||||||
float GetRendererTargetScaleX()
|
float GetRendererTargetScaleX()
|
||||||
{
|
{
|
||||||
return Renderer::GetXScale();
|
return Renderer::GetXScale();
|
||||||
}
|
}
|
||||||
float GetRendererTargetScaleY()
|
float GetRendererTargetScaleY()
|
||||||
{
|
{
|
||||||
return Renderer::GetYScale();
|
return Renderer::GetYScale();
|
||||||
}
|
}
|
||||||
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf)
|
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf)
|
||||||
{
|
{
|
||||||
RECT rec = { rc.left, rc.top, rc.right, rc.bottom };
|
RECT rec = { rc.left, rc.top, rc.right, rc.bottom };
|
||||||
TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest<<5, &rec);
|
TextureCache::CopyEFBToRenderTarget(bpmem.copyTexDest<<5, &rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight)
|
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight)
|
||||||
{
|
{
|
||||||
Renderer::SwapBuffers();
|
Renderer::SwapBuffers();
|
||||||
PRIM_LOG("Renderer::SwapBuffers()");
|
PRIM_LOG("Renderer::SwapBuffers()");
|
||||||
g_VideoInitialize.pCopiedToXFB();
|
g_VideoInitialize.pCopiedToXFB();
|
||||||
}
|
}
|
||||||
void ClearScreen(const Bypass &bp, const TRectangle &multirc)
|
void ClearScreen(const Bypass &bp, const TRectangle &multirc)
|
||||||
{
|
{
|
||||||
// it seems that the GC is able to alpha blend on color-fill
|
// it seems that the GC is able to alpha blend on color-fill
|
||||||
// we cant do that so if alpha is != 255 we skip it
|
// we cant do that so if alpha is != 255 we skip it
|
||||||
|
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
|
|
||||||
// Since clear operations use the source rectangle, we have to do
|
// Since clear operations use the source rectangle, we have to do
|
||||||
// regular renders
|
// regular renders
|
||||||
DWORD clearflags = 0;
|
DWORD clearflags = 0;
|
||||||
D3DCOLOR col = 0;
|
D3DCOLOR col = 0;
|
||||||
float clearZ = 0;
|
float clearZ = 0;
|
||||||
|
|
||||||
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
|
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
|
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
|
||||||
col = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
|
col = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
|
||||||
// clearflags |= D3DCLEAR_TARGET; set to break animal crossing :p
|
// clearflags |= D3DCLEAR_TARGET; set to break animal crossing :p
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear z-buffer
|
// clear z-buffer
|
||||||
if (bpmem.zmode.updateenable)
|
if (bpmem.zmode.updateenable)
|
||||||
{
|
{
|
||||||
clearZ = (float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF);
|
clearZ = (float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF);
|
||||||
if (clearZ > 1.0f) clearZ = 1.0f;
|
if (clearZ > 1.0f) clearZ = 1.0f;
|
||||||
if (clearZ < 0.0f) clearZ = 0.0f;
|
if (clearZ < 0.0f) clearZ = 0.0f;
|
||||||
clearflags |= D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
|
clearflags |= D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D::dev->Clear(0, NULL, clearflags, col, clearZ, 0);
|
D3D::dev->Clear(0, NULL, clearflags, col, clearZ, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestoreRenderState(const Bypass &bp)
|
void RestoreRenderState(const Bypass &bp)
|
||||||
{
|
{
|
||||||
//Renderer::SetRenderMode(Renderer::RM_Normal);
|
//Renderer::SetRenderMode(Renderer::RM_Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetConfig(const int &type)
|
bool GetConfig(const int &type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CONFIG_ISWII:
|
case CONFIG_ISWII:
|
||||||
return g_VideoInitialize.bWii;
|
return g_VideoInitialize.bWii;
|
||||||
case CONFIG_DISABLEFOG:
|
case CONFIG_DISABLEFOG:
|
||||||
return false;
|
return false;
|
||||||
case CONFIG_SHOWEFBREGIONS:
|
case CONFIG_SHOWEFBREGIONS:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
PanicAlert("GetConfig Error: Unknown Config Type!");
|
PanicAlert("GetConfig Error: Unknown Config Type!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u8 *GetPointer(const u32 &address)
|
u8 *GetPointer(const u32 &address)
|
||||||
{
|
{
|
||||||
return g_VideoInitialize.pGetMemoryPointer(address);
|
return g_VideoInitialize.pGetMemoryPointer(address);
|
||||||
}
|
}
|
||||||
void SetSamplerState(const Bypass &bp)
|
void SetSamplerState(const Bypass &bp)
|
||||||
{
|
{
|
||||||
FourTexUnits &tex = bpmem.tex[(bp.address & 0xE0) == 0xA0];
|
FourTexUnits &tex = bpmem.tex[(bp.address & 0xE0) == 0xA0];
|
||||||
int stage = (bp.address & 3);//(addr>>4)&2;
|
int stage = (bp.address & 3);//(addr>>4)&2;
|
||||||
TexMode0 &tm0 = tex.texMode0[stage];
|
TexMode0 &tm0 = tex.texMode0[stage];
|
||||||
|
|
||||||
D3DTEXTUREFILTERTYPE min, mag, mip;
|
D3DTEXTUREFILTERTYPE min, mag, mip;
|
||||||
if (g_Config.bForceFiltering)
|
if (g_Config.bForceFiltering)
|
||||||
{
|
{
|
||||||
min = mag = mip = D3DTEXF_LINEAR;
|
min = mag = mip = D3DTEXF_LINEAR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||||
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT;
|
||||||
mip = d3dMipFilters[tm0.min_filter & 3];
|
mip = d3dMipFilters[tm0.min_filter & 3];
|
||||||
}
|
}
|
||||||
if ((bp.address & 0xE0) == 0xA0)
|
if ((bp.address & 0xE0) == 0xA0)
|
||||||
stage += 4;
|
stage += 4;
|
||||||
|
|
||||||
if (g_Config.bForceMaxAniso)
|
if (g_Config.bForceMaxAniso)
|
||||||
{
|
{
|
||||||
mag = D3DTEXF_ANISOTROPIC;
|
mag = D3DTEXF_ANISOTROPIC;
|
||||||
mip = D3DTEXF_ANISOTROPIC;
|
mip = D3DTEXF_ANISOTROPIC;
|
||||||
min = D3DTEXF_ANISOTROPIC;
|
min = D3DTEXF_ANISOTROPIC;
|
||||||
}
|
}
|
||||||
dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min);
|
dev->SetSamplerState(stage, D3DSAMP_MINFILTER, min);
|
||||||
dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag);
|
dev->SetSamplerState(stage, D3DSAMP_MAGFILTER, mag);
|
||||||
dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip);
|
dev->SetSamplerState(stage, D3DSAMP_MIPFILTER, mip);
|
||||||
|
|
||||||
dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 16);
|
dev->SetSamplerState(stage, D3DSAMP_MAXANISOTROPY, 16);
|
||||||
dev->SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
|
dev->SetSamplerState(stage, D3DSAMP_ADDRESSU, d3dClamps[tm0.wrap_s]);
|
||||||
dev->SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
|
dev->SetSamplerState(stage, D3DSAMP_ADDRESSV, d3dClamps[tm0.wrap_t]);
|
||||||
//wip
|
//wip
|
||||||
//dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f);
|
//dev->SetSamplerState(stage,D3DSAMP_MIPMAPLODBIAS,tm0.lod_bias/4.0f);
|
||||||
//char temp[256];
|
//char temp[256];
|
||||||
//sprintf(temp,"lod %f",tm0.lod_bias/4.0f);
|
//sprintf(temp,"lod %f",tm0.lod_bias/4.0f);
|
||||||
//g_VideoInitialize.pLog(temp);
|
//g_VideoInitialize.pLog(temp);
|
||||||
}
|
}
|
||||||
void SetInterlacingMode(const Bypass &bp)
|
void SetInterlacingMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
};
|
};
|
|
@ -1,212 +1,212 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "BPFunctions.h"
|
#include "BPFunctions.h"
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "Profiler.h"
|
#include "Profiler.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "VertexManager.h"
|
#include "VertexManager.h"
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
#include "TextureMngr.h"
|
#include "TextureMngr.h"
|
||||||
#include "TextureConverter.h"
|
#include "TextureConverter.h"
|
||||||
#include "VertexShaderManager.h"
|
#include "VertexShaderManager.h"
|
||||||
#include "XFB.h"
|
#include "XFB.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
namespace BPFunctions
|
namespace BPFunctions
|
||||||
{
|
{
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
// State translation lookup tables
|
// State translation lookup tables
|
||||||
// Reference: Yet Another Gamecube Documentation
|
// Reference: Yet Another Gamecube Documentation
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
|
|
||||||
static const GLenum glCmpFuncs[8] = {
|
static const GLenum glCmpFuncs[8] = {
|
||||||
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
|
GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL, GL_GEQUAL, GL_ALWAYS
|
||||||
};
|
};
|
||||||
|
|
||||||
static const GLenum glLogicOpCodes[16] = {
|
static const GLenum glLogicOpCodes[16] = {
|
||||||
GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP, GL_XOR,
|
GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_AND_INVERTED, GL_NOOP, GL_XOR,
|
||||||
GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET
|
GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET
|
||||||
};
|
};
|
||||||
|
|
||||||
void FlushPipeline()
|
void FlushPipeline()
|
||||||
{
|
{
|
||||||
VertexManager::Flush();
|
VertexManager::Flush();
|
||||||
}
|
}
|
||||||
void SetGenerationMode(const Bypass &bp)
|
void SetGenerationMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
// none, ccw, cw, ccw
|
// none, ccw, cw, ccw
|
||||||
if (bpmem.genMode.cullmode > 0)
|
if (bpmem.genMode.cullmode > 0)
|
||||||
{
|
{
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW);
|
glFrontFace(bpmem.genMode.cullmode == 2 ? GL_CCW : GL_CW);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SetScissor(const Bypass &bp)
|
void SetScissor(const Bypass &bp)
|
||||||
{
|
{
|
||||||
if (!Renderer::SetScissorRect())
|
if (!Renderer::SetScissorRect())
|
||||||
if (bp.address == BPMEM_SCISSORBR)
|
if (bp.address == BPMEM_SCISSORBR)
|
||||||
ERROR_LOG(VIDEO, "bad scissor!");
|
ERROR_LOG(VIDEO, "bad scissor!");
|
||||||
}
|
}
|
||||||
void SetLineWidth(const Bypass &bp)
|
void SetLineWidth(const Bypass &bp)
|
||||||
{
|
{
|
||||||
float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f;
|
float fratio = xfregs.rawViewport[0] != 0 ? ((float)Renderer::GetTargetWidth() / EFB_WIDTH) : 1.0f;
|
||||||
if (bpmem.lineptwidth.linesize > 0)
|
if (bpmem.lineptwidth.linesize > 0)
|
||||||
glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths
|
glLineWidth((float)bpmem.lineptwidth.linesize * fratio / 6.0f); // scale by ratio of widths
|
||||||
if (bpmem.lineptwidth.pointsize > 0)
|
if (bpmem.lineptwidth.pointsize > 0)
|
||||||
glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f);
|
glPointSize((float)bpmem.lineptwidth.pointsize * fratio / 6.0f);
|
||||||
}
|
}
|
||||||
void SetDepthMode(const Bypass &bp)
|
void SetDepthMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
if (bpmem.zmode.testenable)
|
if (bpmem.zmode.testenable)
|
||||||
{
|
{
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glDepthMask(bpmem.zmode.updateenable ? GL_TRUE : GL_FALSE);
|
glDepthMask(bpmem.zmode.updateenable ? GL_TRUE : GL_FALSE);
|
||||||
glDepthFunc(glCmpFuncs[bpmem.zmode.func]);
|
glDepthFunc(glCmpFuncs[bpmem.zmode.func]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if the test is disabled write is disabled too
|
// if the test is disabled write is disabled too
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDepthMask(GL_FALSE);
|
glDepthMask(GL_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void SetBlendMode(const Bypass &bp)
|
void SetBlendMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
Renderer::SetBlendMode(false);
|
Renderer::SetBlendMode(false);
|
||||||
}
|
}
|
||||||
void SetDitherMode(const Bypass &bp)
|
void SetDitherMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.dither)
|
if (bpmem.blendmode.dither)
|
||||||
glEnable(GL_DITHER);
|
glEnable(GL_DITHER);
|
||||||
else
|
else
|
||||||
glDisable(GL_DITHER);
|
glDisable(GL_DITHER);
|
||||||
}
|
}
|
||||||
void SetLogicOpMode(const Bypass &bp)
|
void SetLogicOpMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
if (bpmem.blendmode.logicopenable)
|
if (bpmem.blendmode.logicopenable)
|
||||||
{
|
{
|
||||||
glEnable(GL_COLOR_LOGIC_OP);
|
glEnable(GL_COLOR_LOGIC_OP);
|
||||||
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
|
glLogicOp(glLogicOpCodes[bpmem.blendmode.logicmode]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
glDisable(GL_COLOR_LOGIC_OP);
|
glDisable(GL_COLOR_LOGIC_OP);
|
||||||
}
|
}
|
||||||
void SetColorMask(const Bypass &bp)
|
void SetColorMask(const Bypass &bp)
|
||||||
{
|
{
|
||||||
Renderer::SetColorMask();
|
Renderer::SetColorMask();
|
||||||
}
|
}
|
||||||
float GetRendererTargetScaleX()
|
float GetRendererTargetScaleX()
|
||||||
{
|
{
|
||||||
return Renderer::GetTargetScaleX();
|
return Renderer::GetTargetScaleX();
|
||||||
}
|
}
|
||||||
float GetRendererTargetScaleY()
|
float GetRendererTargetScaleY()
|
||||||
{
|
{
|
||||||
return Renderer::GetTargetScaleY();
|
return Renderer::GetTargetScaleY();
|
||||||
}
|
}
|
||||||
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf)
|
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©fmt, const bool &scaleByHalf)
|
||||||
{
|
{
|
||||||
// bpmem.zcontrol.pixel_format to PIXELFMT_Z24 is when the game wants to copy from ZBuffer (Zbuffer uses 24-bit Format)
|
// bpmem.zcontrol.pixel_format to PIXELFMT_Z24 is when the game wants to copy from ZBuffer (Zbuffer uses 24-bit Format)
|
||||||
if (!g_Config.bEFBCopyDisable)
|
if (!g_Config.bEFBCopyDisable)
|
||||||
if (g_Config.bCopyEFBToRAM) // To RAM
|
if (g_Config.bCopyEFBToRAM) // To RAM
|
||||||
TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
|
TextureConverter::EncodeToRam(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
|
||||||
else // To OGL Texture
|
else // To OGL Texture
|
||||||
TextureMngr::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
|
TextureMngr::CopyRenderTargetToTexture(address, fromZBuffer, isIntensityFmt, copyfmt, scaleByHalf, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight)
|
void RenderToXFB(const Bypass &bp, const TRectangle &multirc, const float &yScale, const float &xfbLines, u32 xfbAddr, const u32 &dstWidth, const u32 &dstHeight)
|
||||||
{
|
{
|
||||||
Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, multirc);
|
Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, multirc);
|
||||||
}
|
}
|
||||||
void ClearScreen(const Bypass &bp, const TRectangle &multirc)
|
void ClearScreen(const Bypass &bp, const TRectangle &multirc)
|
||||||
{
|
{
|
||||||
// Update the view port for clearing the picture
|
// Update the view port for clearing the picture
|
||||||
glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
|
glViewport(0, 0, Renderer::GetTargetWidth(), Renderer::GetTargetHeight());
|
||||||
|
|
||||||
// Always set the scissor in case it was set by the game and has not been reset
|
// Always set the scissor in case it was set by the game and has not been reset
|
||||||
glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom),
|
glScissor(multirc.left, (Renderer::GetTargetHeight() - multirc.bottom),
|
||||||
(multirc.right - multirc.left), (multirc.bottom - multirc.top));
|
(multirc.right - multirc.left), (multirc.bottom - multirc.top));
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
|
|
||||||
VertexShaderManager::SetViewportChanged();
|
VertexShaderManager::SetViewportChanged();
|
||||||
|
|
||||||
// Since clear operations use the source rectangle, we have to do
|
// Since clear operations use the source rectangle, we have to do
|
||||||
// regular renders (glClear clears the entire buffer)
|
// regular renders (glClear clears the entire buffer)
|
||||||
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate || bpmem.zmode.updateenable)
|
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate || bpmem.zmode.updateenable)
|
||||||
{
|
{
|
||||||
GLbitfield bits = 0;
|
GLbitfield bits = 0;
|
||||||
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
|
if (bpmem.blendmode.colorupdate || bpmem.blendmode.alphaupdate)
|
||||||
{
|
{
|
||||||
u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
|
u32 clearColor = (bpmem.clearcolorAR << 16) | bpmem.clearcolorGB;
|
||||||
|
|
||||||
// Alpha may or may not be present depending on the EFB pixel format.
|
// Alpha may or may not be present depending on the EFB pixel format.
|
||||||
GLclampf clearAlpha = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) ?
|
GLclampf clearAlpha = (bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24) ?
|
||||||
((clearColor>>24) & 0xff)*(1/255.0f) : 1.0f;
|
((clearColor>>24) & 0xff)*(1/255.0f) : 1.0f;
|
||||||
|
|
||||||
glClearColor(((clearColor>>16) & 0xff)*(1/255.0f),
|
glClearColor(((clearColor>>16) & 0xff)*(1/255.0f),
|
||||||
((clearColor>>8 ) & 0xff)*(1/255.0f),
|
((clearColor>>8 ) & 0xff)*(1/255.0f),
|
||||||
((clearColor>>0 ) & 0xff)*(1/255.0f),
|
((clearColor>>0 ) & 0xff)*(1/255.0f),
|
||||||
clearAlpha);
|
clearAlpha);
|
||||||
bits |= GL_COLOR_BUFFER_BIT;
|
bits |= GL_COLOR_BUFFER_BIT;
|
||||||
}
|
}
|
||||||
if (bpmem.zmode.updateenable)
|
if (bpmem.zmode.updateenable)
|
||||||
{
|
{
|
||||||
glClearDepth((float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF));
|
glClearDepth((float)(bpmem.clearZValue & 0xFFFFFF) / float(0xFFFFFF));
|
||||||
bits |= GL_DEPTH_BUFFER_BIT;
|
bits |= GL_DEPTH_BUFFER_BIT;
|
||||||
}
|
}
|
||||||
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
||||||
glClear(bits);
|
glClear(bits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestoreRenderState(const Bypass &bp)
|
void RestoreRenderState(const Bypass &bp)
|
||||||
{
|
{
|
||||||
Renderer::RestoreGLState();
|
Renderer::RestoreGLState();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetConfig(const int &type)
|
bool GetConfig(const int &type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CONFIG_ISWII:
|
case CONFIG_ISWII:
|
||||||
return g_VideoInitialize.bWii;
|
return g_VideoInitialize.bWii;
|
||||||
case CONFIG_DISABLEFOG:
|
case CONFIG_DISABLEFOG:
|
||||||
return g_Config.bDisableFog;
|
return g_Config.bDisableFog;
|
||||||
case CONFIG_SHOWEFBREGIONS:
|
case CONFIG_SHOWEFBREGIONS:
|
||||||
return g_Config.bShowEFBCopyRegions;
|
return g_Config.bShowEFBCopyRegions;
|
||||||
default:
|
default:
|
||||||
PanicAlert("GetConfig Error: Unknown Config Type!");
|
PanicAlert("GetConfig Error: Unknown Config Type!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
u8 *GetPointer(const u32 &address)
|
u8 *GetPointer(const u32 &address)
|
||||||
{
|
{
|
||||||
return g_VideoInitialize.pGetMemoryPointer(address);
|
return g_VideoInitialize.pGetMemoryPointer(address);
|
||||||
}
|
}
|
||||||
void SetSamplerState(const Bypass &bp)
|
void SetSamplerState(const Bypass &bp)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
void SetInterlacingMode(const Bypass &bp)
|
void SetInterlacingMode(const Bypass &bp)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,451 +1,451 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "FramebufferManager.h"
|
#include "FramebufferManager.h"
|
||||||
|
|
||||||
#include "TextureConverter.h"
|
#include "TextureConverter.h"
|
||||||
#include "XFB.h"
|
#include "XFB.h"
|
||||||
|
|
||||||
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
|
extern bool s_bHaveFramebufferBlit; // comes from Render.cpp
|
||||||
|
|
||||||
void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
|
void FramebufferManager::Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples)
|
||||||
{
|
{
|
||||||
m_targetWidth = targetWidth;
|
m_targetWidth = targetWidth;
|
||||||
m_targetHeight = targetHeight;
|
m_targetHeight = targetHeight;
|
||||||
m_msaaSamples = msaaSamples;
|
m_msaaSamples = msaaSamples;
|
||||||
m_msaaCoverageSamples = msaaCoverageSamples;
|
m_msaaCoverageSamples = msaaCoverageSamples;
|
||||||
|
|
||||||
// The EFB can be set to different pixel formats by the game through the
|
// The EFB can be set to different pixel formats by the game through the
|
||||||
// BPMEM_ZCOMPARE register (which should probably have a different name).
|
// BPMEM_ZCOMPARE register (which should probably have a different name).
|
||||||
// They are:
|
// They are:
|
||||||
// - 24-bit RGB (8-bit components) with 24-bit Z
|
// - 24-bit RGB (8-bit components) with 24-bit Z
|
||||||
// - 24-bit RGBA (6-bit components) with 24-bit Z
|
// - 24-bit RGBA (6-bit components) with 24-bit Z
|
||||||
// - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z
|
// - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z
|
||||||
// We only use one EFB format here: 32-bit ARGB with 24-bit Z.
|
// We only use one EFB format here: 32-bit ARGB with 24-bit Z.
|
||||||
// Multisampling depends on user settings.
|
// Multisampling depends on user settings.
|
||||||
// The distinction becomes important for certain operations, i.e. the
|
// The distinction becomes important for certain operations, i.e. the
|
||||||
// alpha channel should be ignored if the EFB does not have one.
|
// alpha channel should be ignored if the EFB does not have one.
|
||||||
|
|
||||||
// Create EFB target.
|
// Create EFB target.
|
||||||
|
|
||||||
glGenFramebuffersEXT(1, &m_efbFramebuffer);
|
glGenFramebuffersEXT(1, &m_efbFramebuffer);
|
||||||
|
|
||||||
if (m_msaaSamples <= 1)
|
if (m_msaaSamples <= 1)
|
||||||
{
|
{
|
||||||
// EFB targets will be textures in non-MSAA mode.
|
// EFB targets will be textures in non-MSAA mode.
|
||||||
|
|
||||||
GLuint glObj[2];
|
GLuint glObj[2];
|
||||||
glGenTextures(2, glObj);
|
glGenTextures(2, glObj);
|
||||||
m_efbColor = glObj[0];
|
m_efbColor = glObj[0];
|
||||||
m_efbDepth = glObj[1];
|
m_efbDepth = glObj[1];
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbColor);
|
||||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_efbDepth);
|
||||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
|
|
||||||
// Bind target textures to the EFB framebuffer.
|
// Bind target textures to the EFB framebuffer.
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0);
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbColor, 0);
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_efbDepth, 0);
|
||||||
|
|
||||||
GL_REPORT_FBO_ERROR();
|
GL_REPORT_FBO_ERROR();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// EFB targets will be renderbuffers in MSAA mode (required by OpenGL).
|
// EFB targets will be renderbuffers in MSAA mode (required by OpenGL).
|
||||||
// Resolve targets will be created to transfer EFB to RAM textures.
|
// Resolve targets will be created to transfer EFB to RAM textures.
|
||||||
// XFB framebuffer will be created to transfer EFB to XFB texture.
|
// XFB framebuffer will be created to transfer EFB to XFB texture.
|
||||||
|
|
||||||
// Create EFB target renderbuffers.
|
// Create EFB target renderbuffers.
|
||||||
|
|
||||||
GLuint glObj[2];
|
GLuint glObj[2];
|
||||||
glGenRenderbuffersEXT(2, glObj);
|
glGenRenderbuffersEXT(2, glObj);
|
||||||
m_efbColor = glObj[0];
|
m_efbColor = glObj[0];
|
||||||
m_efbDepth = glObj[1];
|
m_efbDepth = glObj[1];
|
||||||
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbColor);
|
||||||
if (m_msaaCoverageSamples)
|
if (m_msaaCoverageSamples)
|
||||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||||
else
|
else
|
||||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight);
|
||||||
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_efbDepth);
|
||||||
if (m_msaaCoverageSamples)
|
if (m_msaaCoverageSamples)
|
||||||
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
|
glRenderbufferStorageMultisampleCoverageNV(GL_RENDERBUFFER_EXT, m_msaaCoverageSamples, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
|
||||||
else
|
else
|
||||||
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
|
glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, m_msaaSamples, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight);
|
||||||
|
|
||||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
|
||||||
|
|
||||||
// Bind target renderbuffers to EFB framebuffer.
|
// Bind target renderbuffers to EFB framebuffer.
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
|
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor);
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_efbColor);
|
||||||
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth);
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_efbDepth);
|
||||||
|
|
||||||
GL_REPORT_FBO_ERROR();
|
GL_REPORT_FBO_ERROR();
|
||||||
|
|
||||||
// Create resolved targets for transferring multisampled EFB to texture.
|
// Create resolved targets for transferring multisampled EFB to texture.
|
||||||
|
|
||||||
glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
|
glGenFramebuffersEXT(1, &m_resolvedFramebuffer);
|
||||||
|
|
||||||
glGenTextures(2, glObj);
|
glGenTextures(2, glObj);
|
||||||
m_resolvedColorTexture = glObj[0];
|
m_resolvedColorTexture = glObj[0];
|
||||||
m_resolvedDepthTexture = glObj[1];
|
m_resolvedDepthTexture = glObj[1];
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture);
|
||||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, m_targetWidth, m_targetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture);
|
||||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
|
|
||||||
// Bind resolved textures to resolved framebuffer.
|
// Bind resolved textures to resolved framebuffer.
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
||||||
|
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0);
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedColorTexture, 0);
|
||||||
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, m_resolvedDepthTexture, 0);
|
||||||
|
|
||||||
GL_REPORT_FBO_ERROR();
|
GL_REPORT_FBO_ERROR();
|
||||||
|
|
||||||
// Return to EFB framebuffer.
|
// Return to EFB framebuffer.
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create XFB framebuffer; targets will be created elsewhere.
|
// Create XFB framebuffer; targets will be created elsewhere.
|
||||||
|
|
||||||
glGenFramebuffersEXT(1, &m_xfbFramebuffer);
|
glGenFramebuffersEXT(1, &m_xfbFramebuffer);
|
||||||
|
|
||||||
// EFB framebuffer is currently bound.
|
// EFB framebuffer is currently bound.
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::Shutdown()
|
void FramebufferManager::Shutdown()
|
||||||
{
|
{
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||||
|
|
||||||
GLuint glObj[3];
|
GLuint glObj[3];
|
||||||
|
|
||||||
// Note: OpenGL deletion functions silently ignore parameters of "0".
|
// Note: OpenGL deletion functions silently ignore parameters of "0".
|
||||||
|
|
||||||
glObj[0] = m_efbFramebuffer;
|
glObj[0] = m_efbFramebuffer;
|
||||||
glObj[1] = m_resolvedFramebuffer;
|
glObj[1] = m_resolvedFramebuffer;
|
||||||
glObj[2] = m_xfbFramebuffer;
|
glObj[2] = m_xfbFramebuffer;
|
||||||
glDeleteFramebuffersEXT(3, glObj);
|
glDeleteFramebuffersEXT(3, glObj);
|
||||||
m_efbFramebuffer = 0;
|
m_efbFramebuffer = 0;
|
||||||
m_xfbFramebuffer = 0;
|
m_xfbFramebuffer = 0;
|
||||||
|
|
||||||
glObj[0] = m_resolvedColorTexture;
|
glObj[0] = m_resolvedColorTexture;
|
||||||
glObj[1] = m_resolvedDepthTexture;
|
glObj[1] = m_resolvedDepthTexture;
|
||||||
glObj[2] = m_realXFBSource.texture;
|
glObj[2] = m_realXFBSource.texture;
|
||||||
glDeleteTextures(3, glObj);
|
glDeleteTextures(3, glObj);
|
||||||
m_resolvedColorTexture = 0;
|
m_resolvedColorTexture = 0;
|
||||||
m_resolvedDepthTexture = 0;
|
m_resolvedDepthTexture = 0;
|
||||||
m_realXFBSource.texture = 0;
|
m_realXFBSource.texture = 0;
|
||||||
|
|
||||||
glObj[0] = m_efbColor;
|
glObj[0] = m_efbColor;
|
||||||
glObj[1] = m_efbDepth;
|
glObj[1] = m_efbDepth;
|
||||||
if (m_msaaSamples <= 1)
|
if (m_msaaSamples <= 1)
|
||||||
glDeleteTextures(2, glObj);
|
glDeleteTextures(2, glObj);
|
||||||
else
|
else
|
||||||
glDeleteRenderbuffersEXT(2, glObj);
|
glDeleteRenderbuffersEXT(2, glObj);
|
||||||
m_efbColor = 0;
|
m_efbColor = 0;
|
||||||
m_efbDepth = 0;
|
m_efbDepth = 0;
|
||||||
|
|
||||||
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
for (VirtualXFBListType::iterator it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
||||||
{
|
{
|
||||||
glDeleteTextures(1, &it->xfbSource.texture);
|
glDeleteTextures(1, &it->xfbSource.texture);
|
||||||
}
|
}
|
||||||
m_virtualXFBList.clear();
|
m_virtualXFBList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
|
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
if (g_Config.bUseXFB)
|
if (g_Config.bUseXFB)
|
||||||
copyToRealXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
|
copyToRealXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
|
||||||
else
|
else
|
||||||
copyToVirtualXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
|
copyToVirtualXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFBSource* FramebufferManager::GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
|
const XFBSource* FramebufferManager::GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
|
||||||
{
|
{
|
||||||
if (g_Config.bUseXFB)
|
if (g_Config.bUseXFB)
|
||||||
return getRealXFBSource(xfbAddr, srcWidth, srcHeight);
|
return getRealXFBSource(xfbAddr, srcWidth, srcHeight);
|
||||||
else
|
else
|
||||||
return getVirtualXFBSource(xfbAddr, srcWidth, srcHeight);
|
return getVirtualXFBSource(xfbAddr, srcWidth, srcHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint FramebufferManager::GetEFBColorTexture(const TRectangle& sourceRc) const
|
GLuint FramebufferManager::GetEFBColorTexture(const TRectangle& sourceRc) const
|
||||||
{
|
{
|
||||||
if (m_msaaSamples <= 1)
|
if (m_msaaSamples <= 1)
|
||||||
{
|
{
|
||||||
return m_efbColor;
|
return m_efbColor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
|
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
|
||||||
// required.
|
// required.
|
||||||
|
|
||||||
// Flip source rectangle upside-down for OpenGL.
|
// Flip source rectangle upside-down for OpenGL.
|
||||||
TRectangle glRect;
|
TRectangle glRect;
|
||||||
sourceRc.FlipYPosition(m_targetHeight, &glRect);
|
sourceRc.FlipYPosition(m_targetHeight, &glRect);
|
||||||
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
|
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
|
||||||
|
|
||||||
// Resolve.
|
// Resolve.
|
||||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
||||||
glBlitFramebufferEXT(
|
glBlitFramebufferEXT(
|
||||||
glRect.left, glRect.top, glRect.right, glRect.bottom,
|
glRect.left, glRect.top, glRect.right, glRect.bottom,
|
||||||
glRect.left, glRect.top, glRect.right, glRect.bottom,
|
glRect.left, glRect.top, glRect.right, glRect.bottom,
|
||||||
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
||||||
);
|
);
|
||||||
|
|
||||||
// Return to EFB.
|
// Return to EFB.
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
|
|
||||||
return m_resolvedColorTexture;
|
return m_resolvedColorTexture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint FramebufferManager::GetEFBDepthTexture(const TRectangle& sourceRc) const
|
GLuint FramebufferManager::GetEFBDepthTexture(const TRectangle& sourceRc) const
|
||||||
{
|
{
|
||||||
if (m_msaaSamples <= 1)
|
if (m_msaaSamples <= 1)
|
||||||
{
|
{
|
||||||
return m_efbDepth;
|
return m_efbDepth;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
|
// Transfer the EFB to a resolved texture. EXT_framebuffer_blit is
|
||||||
// required.
|
// required.
|
||||||
|
|
||||||
// Flip source rectangle upside-down for OpenGL.
|
// Flip source rectangle upside-down for OpenGL.
|
||||||
TRectangle glRect;
|
TRectangle glRect;
|
||||||
sourceRc.FlipYPosition(m_targetHeight, &glRect);
|
sourceRc.FlipYPosition(m_targetHeight, &glRect);
|
||||||
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
|
glRect.Clamp(0, 0, m_targetWidth, m_targetHeight);
|
||||||
|
|
||||||
// Resolve.
|
// Resolve.
|
||||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_resolvedFramebuffer);
|
||||||
glBlitFramebufferEXT(
|
glBlitFramebufferEXT(
|
||||||
glRect.left, glRect.top, glRect.right, glRect.bottom,
|
glRect.left, glRect.top, glRect.right, glRect.bottom,
|
||||||
glRect.left, glRect.top, glRect.right, glRect.bottom,
|
glRect.left, glRect.top, glRect.right, glRect.bottom,
|
||||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST
|
GL_DEPTH_BUFFER_BIT, GL_NEAREST
|
||||||
);
|
);
|
||||||
|
|
||||||
// Return to EFB.
|
// Return to EFB.
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
|
|
||||||
return m_resolvedDepthTexture;
|
return m_resolvedDepthTexture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FramebufferManager::VirtualXFBListType::iterator
|
FramebufferManager::VirtualXFBListType::iterator
|
||||||
FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
||||||
{
|
{
|
||||||
u32 srcLower = xfbAddr;
|
u32 srcLower = xfbAddr;
|
||||||
u32 srcUpper = xfbAddr + 2 * width * height;
|
u32 srcUpper = xfbAddr + 2 * width * height;
|
||||||
|
|
||||||
VirtualXFBListType::iterator it;
|
VirtualXFBListType::iterator it;
|
||||||
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
for (it = m_virtualXFBList.begin(); it != m_virtualXFBList.end(); ++it)
|
||||||
{
|
{
|
||||||
u32 dstLower = it->xfbAddr;
|
u32 dstLower = it->xfbAddr;
|
||||||
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
u32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight;
|
||||||
|
|
||||||
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
if (addrRangesOverlap(srcLower, srcUpper, dstLower, dstUpper))
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// That address is not in the Virtual XFB list.
|
// That address is not in the Virtual XFB list.
|
||||||
return m_virtualXFBList.end();
|
return m_virtualXFBList.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
|
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
u8* pXFB = Memory_GetPtr(xfbAddr);
|
u8* pXFB = Memory_GetPtr(xfbAddr);
|
||||||
if (!pXFB)
|
if (!pXFB)
|
||||||
{
|
{
|
||||||
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
|
WARN_LOG(VIDEO, "Tried to copy to invalid XFB address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
XFB_Write(pXFB, sourceRc, dstWidth, dstHeight);
|
XFB_Write(pXFB, sourceRc, dstWidth, dstHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
|
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
|
||||||
{
|
{
|
||||||
GLuint xfbTexture;
|
GLuint xfbTexture;
|
||||||
|
|
||||||
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, dstWidth, dstHeight);
|
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, dstWidth, dstHeight);
|
||||||
|
|
||||||
if (it != m_virtualXFBList.end())
|
if (it != m_virtualXFBList.end())
|
||||||
{
|
{
|
||||||
// Overwrite an existing Virtual XFB.
|
// Overwrite an existing Virtual XFB.
|
||||||
|
|
||||||
it->xfbAddr = xfbAddr;
|
it->xfbAddr = xfbAddr;
|
||||||
it->xfbWidth = dstWidth;
|
it->xfbWidth = dstWidth;
|
||||||
it->xfbHeight = dstHeight;
|
it->xfbHeight = dstHeight;
|
||||||
|
|
||||||
it->xfbSource.texWidth = m_targetWidth;
|
it->xfbSource.texWidth = m_targetWidth;
|
||||||
it->xfbSource.texHeight = m_targetHeight;
|
it->xfbSource.texHeight = m_targetHeight;
|
||||||
it->xfbSource.sourceRc = sourceRc;
|
it->xfbSource.sourceRc = sourceRc;
|
||||||
|
|
||||||
xfbTexture = it->xfbSource.texture;
|
xfbTexture = it->xfbSource.texture;
|
||||||
|
|
||||||
// Move this Virtual XFB to the front of the list.
|
// Move this Virtual XFB to the front of the list.
|
||||||
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
|
m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, it);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create a new Virtual XFB and place it at the front of the list.
|
// Create a new Virtual XFB and place it at the front of the list.
|
||||||
|
|
||||||
glGenTextures(1, &xfbTexture);
|
glGenTextures(1, &xfbTexture);
|
||||||
|
|
||||||
#if 0 // XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
|
#if 0 // XXX: Some video drivers don't handle glCopyTexImage2D correctly, so use EXT_framebuffer_blit whenever possible.
|
||||||
if (m_msaaSamples > 1)
|
if (m_msaaSamples > 1)
|
||||||
#else
|
#else
|
||||||
if (s_bHaveFramebufferBlit)
|
if (s_bHaveFramebufferBlit)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// In MSAA mode, allocate the texture image here. In non-MSAA mode,
|
// In MSAA mode, allocate the texture image here. In non-MSAA mode,
|
||||||
// the image will be allocated by glCopyTexImage2D (later).
|
// the image will be allocated by glCopyTexImage2D (later).
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
|
||||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, m_targetWidth, m_targetHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, m_targetWidth, m_targetHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualXFB newVirt;
|
VirtualXFB newVirt;
|
||||||
|
|
||||||
newVirt.xfbAddr = xfbAddr;
|
newVirt.xfbAddr = xfbAddr;
|
||||||
newVirt.xfbWidth = dstWidth;
|
newVirt.xfbWidth = dstWidth;
|
||||||
newVirt.xfbHeight = dstHeight;
|
newVirt.xfbHeight = dstHeight;
|
||||||
|
|
||||||
newVirt.xfbSource.texture = xfbTexture;
|
newVirt.xfbSource.texture = xfbTexture;
|
||||||
newVirt.xfbSource.texWidth = m_targetWidth;
|
newVirt.xfbSource.texWidth = m_targetWidth;
|
||||||
newVirt.xfbSource.texHeight = m_targetHeight;
|
newVirt.xfbSource.texHeight = m_targetHeight;
|
||||||
newVirt.xfbSource.sourceRc = sourceRc;
|
newVirt.xfbSource.sourceRc = sourceRc;
|
||||||
|
|
||||||
// Add the new Virtual XFB to the list
|
// Add the new Virtual XFB to the list
|
||||||
|
|
||||||
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
if (m_virtualXFBList.size() >= MAX_VIRTUAL_XFB)
|
||||||
{
|
{
|
||||||
// List overflowed; delete the oldest.
|
// List overflowed; delete the oldest.
|
||||||
glDeleteTextures(1, &m_virtualXFBList.back().xfbSource.texture);
|
glDeleteTextures(1, &m_virtualXFBList.back().xfbSource.texture);
|
||||||
m_virtualXFBList.pop_back();
|
m_virtualXFBList.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_virtualXFBList.push_front(newVirt);
|
m_virtualXFBList.push_front(newVirt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy EFB to XFB texture
|
// Copy EFB to XFB texture
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (m_msaaSamples <= 1)
|
if (m_msaaSamples <= 1)
|
||||||
#else
|
#else
|
||||||
if (!s_bHaveFramebufferBlit)
|
if (!s_bHaveFramebufferBlit)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// Just copy the EFB directly.
|
// Just copy the EFB directly.
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, xfbTexture);
|
||||||
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, m_targetWidth, m_targetHeight, 0);
|
glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, 0, 0, m_targetWidth, m_targetHeight, 0);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// OpenGL cannot copy directly from a multisampled framebuffer, so use
|
// OpenGL cannot copy directly from a multisampled framebuffer, so use
|
||||||
// EXT_framebuffer_blit.
|
// EXT_framebuffer_blit.
|
||||||
|
|
||||||
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_xfbFramebuffer);
|
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_xfbFramebuffer);
|
||||||
|
|
||||||
// Bind texture.
|
// Bind texture.
|
||||||
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbTexture, 0);
|
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, xfbTexture, 0);
|
||||||
GL_REPORT_FBO_ERROR();
|
GL_REPORT_FBO_ERROR();
|
||||||
|
|
||||||
glBlitFramebufferEXT(
|
glBlitFramebufferEXT(
|
||||||
0, 0, m_targetWidth, m_targetHeight,
|
0, 0, m_targetWidth, m_targetHeight,
|
||||||
0, 0, m_targetWidth, m_targetHeight,
|
0, 0, m_targetWidth, m_targetHeight,
|
||||||
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
||||||
);
|
);
|
||||||
|
|
||||||
// Unbind texture.
|
// Unbind texture.
|
||||||
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
|
||||||
|
|
||||||
// Return to EFB.
|
// Return to EFB.
|
||||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_efbFramebuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
|
const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
|
||||||
{
|
{
|
||||||
m_realXFBSource.texWidth = XFB_WIDTH;
|
m_realXFBSource.texWidth = XFB_WIDTH;
|
||||||
m_realXFBSource.texHeight = XFB_HEIGHT;
|
m_realXFBSource.texHeight = XFB_HEIGHT;
|
||||||
|
|
||||||
m_realXFBSource.sourceRc.left = 0;
|
m_realXFBSource.sourceRc.left = 0;
|
||||||
m_realXFBSource.sourceRc.top = 0;
|
m_realXFBSource.sourceRc.top = 0;
|
||||||
m_realXFBSource.sourceRc.right = srcWidth;
|
m_realXFBSource.sourceRc.right = srcWidth;
|
||||||
m_realXFBSource.sourceRc.bottom = srcHeight;
|
m_realXFBSource.sourceRc.bottom = srcHeight;
|
||||||
|
|
||||||
if (!m_realXFBSource.texture)
|
if (!m_realXFBSource.texture)
|
||||||
{
|
{
|
||||||
glGenTextures(1, &m_realXFBSource.texture);
|
glGenTextures(1, &m_realXFBSource.texture);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_realXFBSource.texture);
|
||||||
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, XFB_WIDTH, XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, XFB_WIDTH, XFB_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode YUYV data from GameCube RAM
|
// Decode YUYV data from GameCube RAM
|
||||||
TextureConverter::DecodeToTexture(xfbAddr, srcWidth, srcHeight, m_realXFBSource.texture);
|
TextureConverter::DecodeToTexture(xfbAddr, srcWidth, srcHeight, m_realXFBSource.texture);
|
||||||
|
|
||||||
return &m_realXFBSource;
|
return &m_realXFBSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
|
const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
|
||||||
{
|
{
|
||||||
if (m_virtualXFBList.size() == 0)
|
if (m_virtualXFBList.size() == 0)
|
||||||
{
|
{
|
||||||
// No Virtual XFBs available.
|
// No Virtual XFBs available.
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, srcWidth, srcHeight);
|
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, srcWidth, srcHeight);
|
||||||
if (it == m_virtualXFBList.end())
|
if (it == m_virtualXFBList.end())
|
||||||
{
|
{
|
||||||
// Virtual XFB is not in the list, so return the most recently rendered
|
// Virtual XFB is not in the list, so return the most recently rendered
|
||||||
// one.
|
// one.
|
||||||
it = m_virtualXFBList.begin();
|
it = m_virtualXFBList.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
return &it->xfbSource;
|
return &it->xfbSource;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,152 +1,152 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _FRAMEBUFFERMANAGER_H_
|
#ifndef _FRAMEBUFFERMANAGER_H_
|
||||||
#define _FRAMEBUFFERMANAGER_H_
|
#define _FRAMEBUFFERMANAGER_H_
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include "GLUtil.h"
|
#include "GLUtil.h"
|
||||||
|
|
||||||
// On the GameCube, the game sends a request for the graphics processor to
|
// On the GameCube, the game sends a request for the graphics processor to
|
||||||
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
// transfer its internal EFB (Embedded Framebuffer) to an area in GameCube RAM
|
||||||
// called the XFB (External Framebuffer). The size and location of the XFB is
|
// called the XFB (External Framebuffer). The size and location of the XFB is
|
||||||
// decided at the time of the copy, and the format is always YUYV. The video
|
// decided at the time of the copy, and the format is always YUYV. The video
|
||||||
// interface is given a pointer to the XFB, which will be decoded and
|
// interface is given a pointer to the XFB, which will be decoded and
|
||||||
// displayed on the TV.
|
// displayed on the TV.
|
||||||
//
|
//
|
||||||
// There are two ways for Dolphin to emulate this:
|
// There are two ways for Dolphin to emulate this:
|
||||||
//
|
//
|
||||||
// Real XFB mode:
|
// Real XFB mode:
|
||||||
//
|
//
|
||||||
// Dolphin will behave like the GameCube and encode the EFB to
|
// Dolphin will behave like the GameCube and encode the EFB to
|
||||||
// a portion of GameCube RAM. The emulated video interface will decode the data
|
// a portion of GameCube RAM. The emulated video interface will decode the data
|
||||||
// for output to the screen.
|
// for output to the screen.
|
||||||
//
|
//
|
||||||
// Advantages: Behaves exactly like the GameCube.
|
// Advantages: Behaves exactly like the GameCube.
|
||||||
// Disadvantages: Resolution will be limited.
|
// Disadvantages: Resolution will be limited.
|
||||||
//
|
//
|
||||||
// Virtual XFB mode:
|
// Virtual XFB mode:
|
||||||
//
|
//
|
||||||
// When a request is made to copy the EFB to an XFB, Dolphin
|
// When a request is made to copy the EFB to an XFB, Dolphin
|
||||||
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
// will remember the RAM location and size of the XFB in a Virtual XFB list.
|
||||||
// The video interface will look up the XFB in the list and use the enhanced
|
// The video interface will look up the XFB in the list and use the enhanced
|
||||||
// data stored there, if available.
|
// data stored there, if available.
|
||||||
//
|
//
|
||||||
// Advantages: Enables high resolution graphics, better than real hardware.
|
// Advantages: Enables high resolution graphics, better than real hardware.
|
||||||
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
// Disadvantages: If the GameCube CPU writes directly to the XFB (which is
|
||||||
// possible but uncommon), the Virtual XFB will not capture this information.
|
// possible but uncommon), the Virtual XFB will not capture this information.
|
||||||
|
|
||||||
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
// There may be multiple XFBs in GameCube RAM. This is the maximum number to
|
||||||
// virtualize.
|
// virtualize.
|
||||||
const int MAX_VIRTUAL_XFB = 4;
|
const int MAX_VIRTUAL_XFB = 4;
|
||||||
|
|
||||||
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
|
||||||
{
|
{
|
||||||
return (
|
return (
|
||||||
(aLower >= bLower && aLower < bUpper) ||
|
(aLower >= bLower && aLower < bUpper) ||
|
||||||
(aUpper >= bLower && aUpper < bUpper) ||
|
(aUpper >= bLower && aUpper < bUpper) ||
|
||||||
(bLower >= aLower && bLower < aUpper) ||
|
(bLower >= aLower && bLower < aUpper) ||
|
||||||
(bUpper >= aLower && bUpper < aUpper)
|
(bUpper >= aLower && bUpper < aUpper)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct XFBSource
|
struct XFBSource
|
||||||
{
|
{
|
||||||
XFBSource() :
|
XFBSource() :
|
||||||
texture(0)
|
texture(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
int texWidth;
|
int texWidth;
|
||||||
int texHeight;
|
int texHeight;
|
||||||
|
|
||||||
TRectangle sourceRc;
|
TRectangle sourceRc;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FramebufferManager
|
class FramebufferManager
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
FramebufferManager() :
|
FramebufferManager() :
|
||||||
m_efbFramebuffer(0),
|
m_efbFramebuffer(0),
|
||||||
m_efbColor(0),
|
m_efbColor(0),
|
||||||
m_efbDepth(0),
|
m_efbDepth(0),
|
||||||
m_resolvedFramebuffer(0),
|
m_resolvedFramebuffer(0),
|
||||||
m_resolvedColorTexture(0),
|
m_resolvedColorTexture(0),
|
||||||
m_resolvedDepthTexture(0),
|
m_resolvedDepthTexture(0),
|
||||||
m_xfbFramebuffer(0)
|
m_xfbFramebuffer(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
|
void Init(int targetWidth, int targetHeight, int msaaSamples, int msaaCoverageSamples);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
// sourceRc is in GL target coordinates, not GameCube EFB coordinates!
|
// sourceRc is in GL target coordinates, not GameCube EFB coordinates!
|
||||||
// TODO: Clean that up.
|
// TODO: Clean that up.
|
||||||
void CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
|
void CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
|
||||||
|
|
||||||
const XFBSource* GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
|
const XFBSource* GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
|
||||||
|
|
||||||
// To get the EFB in texture form, these functions may have to transfer
|
// To get the EFB in texture form, these functions may have to transfer
|
||||||
// the EFB to a resolved texture first.
|
// the EFB to a resolved texture first.
|
||||||
GLuint GetEFBColorTexture(const TRectangle& sourceRc) const;
|
GLuint GetEFBColorTexture(const TRectangle& sourceRc) const;
|
||||||
GLuint GetEFBDepthTexture(const TRectangle& sourceRc) const;
|
GLuint GetEFBDepthTexture(const TRectangle& sourceRc) const;
|
||||||
|
|
||||||
GLuint GetEFBFramebuffer() const { return m_efbFramebuffer; }
|
GLuint GetEFBFramebuffer() const { return m_efbFramebuffer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct VirtualXFB
|
struct VirtualXFB
|
||||||
{
|
{
|
||||||
// Address and size in GameCube RAM
|
// Address and size in GameCube RAM
|
||||||
u32 xfbAddr;
|
u32 xfbAddr;
|
||||||
u32 xfbWidth;
|
u32 xfbWidth;
|
||||||
u32 xfbHeight;
|
u32 xfbHeight;
|
||||||
|
|
||||||
XFBSource xfbSource;
|
XFBSource xfbSource;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<VirtualXFB> VirtualXFBListType;
|
typedef std::list<VirtualXFB> VirtualXFBListType;
|
||||||
|
|
||||||
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
|
||||||
|
|
||||||
void copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
|
void copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
|
||||||
void copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
|
void copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
|
||||||
const XFBSource* getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
|
const XFBSource* getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
|
||||||
const XFBSource* getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
|
const XFBSource* getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
|
||||||
|
|
||||||
int m_targetWidth;
|
int m_targetWidth;
|
||||||
int m_targetHeight;
|
int m_targetHeight;
|
||||||
int m_msaaSamples;
|
int m_msaaSamples;
|
||||||
int m_msaaCoverageSamples;
|
int m_msaaCoverageSamples;
|
||||||
|
|
||||||
GLuint m_efbFramebuffer;
|
GLuint m_efbFramebuffer;
|
||||||
GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
GLuint m_efbColor; // Renderbuffer in MSAA mode; Texture otherwise
|
||||||
GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
GLuint m_efbDepth; // Renderbuffer in MSAA mode; Texture otherwise
|
||||||
|
|
||||||
// Only used in MSAA mode.
|
// Only used in MSAA mode.
|
||||||
GLuint m_resolvedFramebuffer;
|
GLuint m_resolvedFramebuffer;
|
||||||
GLuint m_resolvedColorTexture;
|
GLuint m_resolvedColorTexture;
|
||||||
GLuint m_resolvedDepthTexture;
|
GLuint m_resolvedDepthTexture;
|
||||||
|
|
||||||
GLuint m_xfbFramebuffer; // Only used in MSAA mode
|
GLuint m_xfbFramebuffer; // Only used in MSAA mode
|
||||||
XFBSource m_realXFBSource; // Only used in Real XFB mode
|
XFBSource m_realXFBSource; // Only used in Real XFB mode
|
||||||
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
VirtualXFBListType m_virtualXFBList; // Only used in Virtual XFB mode
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,89 +1,89 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "VideoCommon.h"
|
#include "VideoCommon.h"
|
||||||
#include "FileUtil.h"
|
#include "FileUtil.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "GLUtil.h"
|
#include "GLUtil.h"
|
||||||
#include "PostProcessing.h"
|
#include "PostProcessing.h"
|
||||||
#include "PixelShaderCache.h"
|
#include "PixelShaderCache.h"
|
||||||
|
|
||||||
namespace PostProcessing
|
namespace PostProcessing
|
||||||
{
|
{
|
||||||
|
|
||||||
static std::string s_currentShader;
|
static std::string s_currentShader;
|
||||||
static FRAGMENTSHADER s_shader;
|
static FRAGMENTSHADER s_shader;
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
s_currentShader = "";
|
s_currentShader = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
{
|
{
|
||||||
s_shader.Destroy();
|
s_shader.Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReloadShader()
|
void ReloadShader()
|
||||||
{
|
{
|
||||||
s_currentShader = "";
|
s_currentShader = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ApplyShader()
|
bool ApplyShader()
|
||||||
{
|
{
|
||||||
if (s_currentShader != "User/Shaders/" + g_Config.sPostProcessingShader + ".txt")
|
if (s_currentShader != "User/Shaders/" + g_Config.sPostProcessingShader + ".txt")
|
||||||
{
|
{
|
||||||
// Set immediately to prevent endless recompiles on failure.
|
// Set immediately to prevent endless recompiles on failure.
|
||||||
if (!g_Config.sPostProcessingShader.empty())
|
if (!g_Config.sPostProcessingShader.empty())
|
||||||
s_currentShader = "User/Shaders/" + g_Config.sPostProcessingShader + ".txt";
|
s_currentShader = "User/Shaders/" + g_Config.sPostProcessingShader + ".txt";
|
||||||
else
|
else
|
||||||
s_currentShader.clear();
|
s_currentShader.clear();
|
||||||
|
|
||||||
s_shader.Destroy();
|
s_shader.Destroy();
|
||||||
|
|
||||||
if (!s_currentShader.empty())
|
if (!s_currentShader.empty())
|
||||||
{
|
{
|
||||||
std::string code;
|
std::string code;
|
||||||
if (File::ReadFileToString(true, s_currentShader.c_str(), code))
|
if (File::ReadFileToString(true, s_currentShader.c_str(), code))
|
||||||
{
|
{
|
||||||
if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
|
if (!PixelShaderCache::CompilePixelShader(s_shader, code.c_str()))
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
|
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
|
ERROR_LOG(VIDEO, "Failed to load post-processing shader %s - does not exist?", s_currentShader.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s_shader.glprogid != 0)
|
if (s_shader.glprogid != 0)
|
||||||
{
|
{
|
||||||
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_shader.glprogid);
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, s_shader.glprogid);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
glDisable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
|
glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _POSTPROCESSING_H_
|
#ifndef _POSTPROCESSING_H_
|
||||||
#define _POSTPROCESSING_H_
|
#define _POSTPROCESSING_H_
|
||||||
|
|
||||||
#include "VideoCommon.h"
|
#include "VideoCommon.h"
|
||||||
#include "GLUtil.h"
|
#include "GLUtil.h"
|
||||||
|
|
||||||
namespace PostProcessing
|
namespace PostProcessing
|
||||||
{
|
{
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void ReloadShader();
|
void ReloadShader();
|
||||||
// Returns false if no shader was applied.
|
// Returns false if no shader was applied.
|
||||||
bool ApplyShader();
|
bool ApplyShader();
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif // _POSTPROCESSING_H_
|
#endif // _POSTPROCESSING_H_
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,108 +1,108 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <wiiuse/wpad.h>
|
#include <wiiuse/wpad.h>
|
||||||
|
|
||||||
// Pull in the assembly functions.
|
// Pull in the assembly functions.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void TestFRES1(u32 *fpscr, float *result, float *result2);
|
void TestFRES1(u32 *fpscr, float *result, float *result2);
|
||||||
};
|
};
|
||||||
|
|
||||||
int doreload=0, dooff=0;
|
int doreload=0, dooff=0;
|
||||||
void reload() { doreload=1; }
|
void reload() { doreload=1; }
|
||||||
void shutdown() { dooff=1; }
|
void shutdown() { dooff=1; }
|
||||||
|
|
||||||
|
|
||||||
void Compare(const char *a, const char *b) {
|
void Compare(const char *a, const char *b) {
|
||||||
if (!strcmp(a, b)) {
|
if (!strcmp(a, b)) {
|
||||||
printf("SUCCESS - %s\n", a);
|
printf("SUCCESS - %s\n", a);
|
||||||
} else {
|
} else {
|
||||||
printf("FAIL - %s != \n"
|
printf("FAIL - %s != \n"
|
||||||
" %s\n", a, b);
|
" %s\n", a, b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDivision() {
|
void TestDivision() {
|
||||||
double a, b, c, d, e;
|
double a, b, c, d, e;
|
||||||
a = 1.0;
|
a = 1.0;
|
||||||
b = 0.0;
|
b = 0.0;
|
||||||
c = a / b;
|
c = a / b;
|
||||||
d = b / a;
|
d = b / a;
|
||||||
e = sqrt(-1);
|
e = sqrt(-1);
|
||||||
char temp[100];
|
char temp[100];
|
||||||
sprintf(temp, "%1.1f %1.1f %1.1f %1.1f %1.1f", a, b, c, d, e);
|
sprintf(temp, "%1.1f %1.1f %1.1f %1.1f %1.1f", a, b, c, d, e);
|
||||||
Compare(temp, "1.0 0.0 inf 0.0 nan");
|
Compare(temp, "1.0 0.0 inf 0.0 nan");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestFres() {
|
void TestFres() {
|
||||||
u32 fpscr[2];
|
u32 fpscr[2];
|
||||||
float out, out2;
|
float out, out2;
|
||||||
TestFRES1(fpscr, &out, &out2);
|
TestFRES1(fpscr, &out, &out2);
|
||||||
char temp[100];
|
char temp[100];
|
||||||
sprintf(temp, "%08x %1.1f %1.1f", fpscr[1], out, out2);
|
sprintf(temp, "%08x %1.1f %1.1f", fpscr[1], out, out2);
|
||||||
Compare(temp, "86002004 inf 0.0");
|
Compare(temp, "86002004 inf 0.0");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestNormalize() {
|
void TestNormalize() {
|
||||||
//float a[3] = {2,2,2};
|
//float a[3] = {2,2,2};
|
||||||
//d_guVecNormalize(a);
|
//d_guVecNormalize(a);
|
||||||
//printf("%f %f %f\n", a[0], a[1], a[2]);
|
//printf("%f %f %f\n", a[0], a[1], a[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
void *xfb[2];
|
void *xfb[2];
|
||||||
int fbi = 0;
|
int fbi = 0;
|
||||||
GXRModeObj *rmode = NULL;
|
GXRModeObj *rmode = NULL;
|
||||||
|
|
||||||
VIDEO_Init();
|
VIDEO_Init();
|
||||||
PAD_Init();
|
PAD_Init();
|
||||||
WPAD_Init();
|
WPAD_Init();
|
||||||
|
|
||||||
rmode = VIDEO_GetPreferredMode(NULL);
|
rmode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
|
||||||
// double buffering, prevents flickering (is it needed for LCD TV? i don't have one to test)
|
// double buffering, prevents flickering (is it needed for LCD TV? i don't have one to test)
|
||||||
xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
xfb[0] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
||||||
xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
xfb[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
||||||
|
|
||||||
VIDEO_Configure(rmode);
|
VIDEO_Configure(rmode);
|
||||||
VIDEO_SetNextFramebuffer(xfb[0]);
|
VIDEO_SetNextFramebuffer(xfb[0]);
|
||||||
VIDEO_SetBlack(FALSE);
|
VIDEO_SetBlack(FALSE);
|
||||||
VIDEO_Flush();
|
VIDEO_Flush();
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
if (rmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
|
|
||||||
SYS_SetResetCallback(reload);
|
SYS_SetResetCallback(reload);
|
||||||
SYS_SetPowerCallback(shutdown);
|
SYS_SetPowerCallback(shutdown);
|
||||||
|
|
||||||
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
|
WPAD_SetDataFormat(0, WPAD_FMT_BTNS_ACC_IR);
|
||||||
WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
|
WPAD_SetVRes(0, rmode->fbWidth, rmode->xfbHeight);
|
||||||
|
|
||||||
CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
CON_Init(xfb[fbi],0,0,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
||||||
|
|
||||||
printf(" ");
|
printf(" ");
|
||||||
printf("Tests\n\n");
|
printf("Tests\n\n");
|
||||||
|
|
||||||
TestDivision();
|
TestDivision();
|
||||||
TestFres();
|
TestFres();
|
||||||
|
|
||||||
while (!doreload && !dooff) {
|
while (!doreload && !dooff) {
|
||||||
WPAD_ScanPads();
|
WPAD_ScanPads();
|
||||||
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
|
if (WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME)
|
||||||
exit(0);
|
exit(0);
|
||||||
|
|
||||||
VIDEO_SetNextFramebuffer(xfb[fbi]);
|
VIDEO_SetNextFramebuffer(xfb[fbi]);
|
||||||
VIDEO_Flush();
|
VIDEO_Flush();
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
}
|
}
|
||||||
if(doreload) return 0;
|
if(doreload) return 0;
|
||||||
if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0);
|
if(dooff) SYS_ResetSystem(SYS_SHUTDOWN,0,0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,37 +61,37 @@ int main()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialise()
|
void Initialise()
|
||||||
{
|
{
|
||||||
// Initialise the video system
|
// Initialise the video system
|
||||||
VIDEO_Init();
|
VIDEO_Init();
|
||||||
|
|
||||||
// This function initialises the attached controllers
|
// This function initialises the attached controllers
|
||||||
PAD_Init();
|
PAD_Init();
|
||||||
|
|
||||||
// Obtain the preferred video mode from the system
|
// Obtain the preferred video mode from the system
|
||||||
// This will correspond to the settings in the Wii menu
|
// This will correspond to the settings in the Wii menu
|
||||||
rmode = VIDEO_GetPreferredMode(NULL);
|
rmode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
|
||||||
// Allocate memory for the display in the uncached region
|
// Allocate memory for the display in the uncached region
|
||||||
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
||||||
|
|
||||||
// Initialise the console, required for printf
|
// Initialise the console, required for printf
|
||||||
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
||||||
|
|
||||||
// Set up the video registers with the chosen mode
|
// Set up the video registers with the chosen mode
|
||||||
VIDEO_Configure(rmode);
|
VIDEO_Configure(rmode);
|
||||||
|
|
||||||
// Tell the video hardware where our display memory is
|
// Tell the video hardware where our display memory is
|
||||||
VIDEO_SetNextFramebuffer(xfb);
|
VIDEO_SetNextFramebuffer(xfb);
|
||||||
|
|
||||||
// Make the display visible
|
// Make the display visible
|
||||||
VIDEO_SetBlack(FALSE);
|
VIDEO_SetBlack(FALSE);
|
||||||
|
|
||||||
// Flush the video register changes to the hardware
|
// Flush the video register changes to the hardware
|
||||||
VIDEO_Flush();
|
VIDEO_Flush();
|
||||||
|
|
||||||
// Wait for Video setup to complete
|
// Wait for Video setup to complete
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +1,72 @@
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
static void *xfb = NULL;
|
static void *xfb = NULL;
|
||||||
|
|
||||||
u32 first_frame = 1;
|
u32 first_frame = 1;
|
||||||
GXRModeObj *rmode;
|
GXRModeObj *rmode;
|
||||||
|
|
||||||
void Initialise();
|
void Initialise();
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Initialise();
|
Initialise();
|
||||||
|
|
||||||
time_t gc_time;
|
time_t gc_time;
|
||||||
gc_time = time(NULL);
|
gc_time = time(NULL);
|
||||||
|
|
||||||
srand(gc_time);
|
srand(gc_time);
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
gc_time = time(NULL);
|
gc_time = time(NULL);
|
||||||
std::cout<<"\x1b[10;0HGC RTC time is"<<ctime(&gc_time);
|
std::cout<<"\x1b[10;0HGC RTC time is"<<ctime(&gc_time);
|
||||||
|
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialise()
|
void Initialise()
|
||||||
{
|
{
|
||||||
// Initialise the video system
|
// Initialise the video system
|
||||||
VIDEO_Init();
|
VIDEO_Init();
|
||||||
|
|
||||||
// This function initialises the attached controllers
|
// This function initialises the attached controllers
|
||||||
PAD_Init();
|
PAD_Init();
|
||||||
|
|
||||||
// Obtain the preferred video mode from the system
|
// Obtain the preferred video mode from the system
|
||||||
// This will correspond to the settings in the Wii menu
|
// This will correspond to the settings in the Wii menu
|
||||||
rmode = VIDEO_GetPreferredMode(NULL);
|
rmode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
|
||||||
// Allocate memory for the display in the uncached region
|
// Allocate memory for the display in the uncached region
|
||||||
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
||||||
|
|
||||||
// Initialise the console, required for printf
|
// Initialise the console, required for printf
|
||||||
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
||||||
|
|
||||||
// Set up the video registers with the chosen mode
|
// Set up the video registers with the chosen mode
|
||||||
VIDEO_Configure(rmode);
|
VIDEO_Configure(rmode);
|
||||||
|
|
||||||
// Tell the video hardware where our display memory is
|
// Tell the video hardware where our display memory is
|
||||||
VIDEO_SetNextFramebuffer(xfb);
|
VIDEO_SetNextFramebuffer(xfb);
|
||||||
|
|
||||||
// Make the display visible
|
// Make the display visible
|
||||||
VIDEO_SetBlack(FALSE);
|
VIDEO_SetBlack(FALSE);
|
||||||
|
|
||||||
// Flush the video register changes to the hardware
|
// Flush the video register changes to the hardware
|
||||||
VIDEO_Flush();
|
VIDEO_Flush();
|
||||||
|
|
||||||
// Wait for Video setup to complete
|
// Wait for Video setup to complete
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +1,72 @@
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ogcsys.h>
|
#include <ogcsys.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
static void *xfb = NULL;
|
static void *xfb = NULL;
|
||||||
|
|
||||||
u32 first_frame = 1;
|
u32 first_frame = 1;
|
||||||
GXRModeObj *rmode;
|
GXRModeObj *rmode;
|
||||||
|
|
||||||
void Initialise();
|
void Initialise();
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
Initialise();
|
Initialise();
|
||||||
|
|
||||||
time_t wii_time;
|
time_t wii_time;
|
||||||
wii_time = time(NULL);
|
wii_time = time(NULL);
|
||||||
|
|
||||||
srand(wii_time);
|
srand(wii_time);
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
wii_time = time(NULL);
|
wii_time = time(NULL);
|
||||||
std::cout<<"\x1b[10;0HWii RTC time is"<<ctime(&wii_time);
|
std::cout<<"\x1b[10;0HWii RTC time is"<<ctime(&wii_time);
|
||||||
|
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialise()
|
void Initialise()
|
||||||
{
|
{
|
||||||
// Initialise the video system
|
// Initialise the video system
|
||||||
VIDEO_Init();
|
VIDEO_Init();
|
||||||
|
|
||||||
// This function initialises the attached controllers
|
// This function initialises the attached controllers
|
||||||
PAD_Init();
|
PAD_Init();
|
||||||
|
|
||||||
// Obtain the preferred video mode from the system
|
// Obtain the preferred video mode from the system
|
||||||
// This will correspond to the settings in the Wii menu
|
// This will correspond to the settings in the Wii menu
|
||||||
rmode = VIDEO_GetPreferredMode(NULL);
|
rmode = VIDEO_GetPreferredMode(NULL);
|
||||||
|
|
||||||
// Allocate memory for the display in the uncached region
|
// Allocate memory for the display in the uncached region
|
||||||
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode));
|
||||||
|
|
||||||
// Initialise the console, required for printf
|
// Initialise the console, required for printf
|
||||||
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ);
|
||||||
|
|
||||||
// Set up the video registers with the chosen mode
|
// Set up the video registers with the chosen mode
|
||||||
VIDEO_Configure(rmode);
|
VIDEO_Configure(rmode);
|
||||||
|
|
||||||
// Tell the video hardware where our display memory is
|
// Tell the video hardware where our display memory is
|
||||||
VIDEO_SetNextFramebuffer(xfb);
|
VIDEO_SetNextFramebuffer(xfb);
|
||||||
|
|
||||||
// Make the display visible
|
// Make the display visible
|
||||||
VIDEO_SetBlack(FALSE);
|
VIDEO_SetBlack(FALSE);
|
||||||
|
|
||||||
// Flush the video register changes to the hardware
|
// Flush the video register changes to the hardware
|
||||||
VIDEO_Flush();
|
VIDEO_Flush();
|
||||||
|
|
||||||
// Wait for Video setup to complete
|
// Wait for Video setup to complete
|
||||||
VIDEO_WaitVSync();
|
VIDEO_WaitVSync();
|
||||||
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,142 +1,142 @@
|
||||||
// Copyright (C) 2003-2009 Dolphin Project.
|
// Copyright (C) 2003-2009 Dolphin Project.
|
||||||
|
|
||||||
// This program is free software: you can redistribute it and/or modify
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// it under the terms of the GNU General Public License as published by
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation, version 2.0.
|
// the Free Software Foundation, version 2.0.
|
||||||
|
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License 2.0 for more details.
|
// GNU General Public License 2.0 for more details.
|
||||||
|
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "StringUtil.h"
|
#include "StringUtil.h"
|
||||||
#include "MathUtil.h"
|
#include "MathUtil.h"
|
||||||
#include "PowerPC/PowerPC.h"
|
#include "PowerPC/PowerPC.h"
|
||||||
#include "HW/SI_DeviceGCController.h"
|
#include "HW/SI_DeviceGCController.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
int fail_count = 0;
|
int fail_count = 0;
|
||||||
|
|
||||||
#define EXPECT_TRUE(a) \
|
#define EXPECT_TRUE(a) \
|
||||||
if (!a) { \
|
if (!a) { \
|
||||||
cout << "FAIL (" __FUNCTION__ "): " << #a << " is false" << endl; \
|
cout << "FAIL (" __FUNCTION__ "): " << #a << " is false" << endl; \
|
||||||
cout << "Value: " << a << endl << "Expected: true" << endl; \
|
cout << "Value: " << a << endl << "Expected: true" << endl; \
|
||||||
fail_count++; \
|
fail_count++; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXPECT_FALSE(a) \
|
#define EXPECT_FALSE(a) \
|
||||||
if (a) { \
|
if (a) { \
|
||||||
cout << "FAIL (" __FUNCTION__ "): " << #a << " is true" << endl; \
|
cout << "FAIL (" __FUNCTION__ "): " << #a << " is true" << endl; \
|
||||||
cout << "Value: " << a << endl << "Expected: false" << endl; \
|
cout << "Value: " << a << endl << "Expected: false" << endl; \
|
||||||
fail_count++; \
|
fail_count++; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXPECT_EQ(a, b) \
|
#define EXPECT_EQ(a, b) \
|
||||||
if ((a) != (b)) { \
|
if ((a) != (b)) { \
|
||||||
cout << "FAIL (" __FUNCTION__ "): " << #a << " is not equal to " << #b << endl; \
|
cout << "FAIL (" __FUNCTION__ "): " << #a << " is not equal to " << #b << endl; \
|
||||||
cout << "Actual: " << a << endl << "Expected: " << b << endl; \
|
cout << "Actual: " << a << endl << "Expected: " << b << endl; \
|
||||||
fail_count++; \
|
fail_count++; \
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreTests()
|
void CoreTests()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MathTests()
|
void MathTests()
|
||||||
{
|
{
|
||||||
// Tests that our fp classifier is correct.
|
// Tests that our fp classifier is correct.
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(1.0), MathUtil::PPC_FPCLASS_PN);
|
EXPECT_EQ(MathUtil::ClassifyDouble(1.0), MathUtil::PPC_FPCLASS_PN);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(-1.0), MathUtil::PPC_FPCLASS_NN);
|
EXPECT_EQ(MathUtil::ClassifyDouble(-1.0), MathUtil::PPC_FPCLASS_NN);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(1235223.0), MathUtil::PPC_FPCLASS_PN);
|
EXPECT_EQ(MathUtil::ClassifyDouble(1235223.0), MathUtil::PPC_FPCLASS_PN);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(-1263221.0), MathUtil::PPC_FPCLASS_NN);
|
EXPECT_EQ(MathUtil::ClassifyDouble(-1263221.0), MathUtil::PPC_FPCLASS_NN);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(1.0E-308), MathUtil::PPC_FPCLASS_PD);
|
EXPECT_EQ(MathUtil::ClassifyDouble(1.0E-308), MathUtil::PPC_FPCLASS_PD);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(-1.0E-308), MathUtil::PPC_FPCLASS_ND);
|
EXPECT_EQ(MathUtil::ClassifyDouble(-1.0E-308), MathUtil::PPC_FPCLASS_ND);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(0.0), MathUtil::PPC_FPCLASS_PZ);
|
EXPECT_EQ(MathUtil::ClassifyDouble(0.0), MathUtil::PPC_FPCLASS_PZ);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(-0.0), MathUtil::PPC_FPCLASS_NZ);
|
EXPECT_EQ(MathUtil::ClassifyDouble(-0.0), MathUtil::PPC_FPCLASS_NZ);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(HUGE_VAL), MathUtil::PPC_FPCLASS_PINF); // weird #define for infinity
|
EXPECT_EQ(MathUtil::ClassifyDouble(HUGE_VAL), MathUtil::PPC_FPCLASS_PINF); // weird #define for infinity
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(-HUGE_VAL), MathUtil::PPC_FPCLASS_NINF);
|
EXPECT_EQ(MathUtil::ClassifyDouble(-HUGE_VAL), MathUtil::PPC_FPCLASS_NINF);
|
||||||
EXPECT_EQ(MathUtil::ClassifyDouble(sqrt(-1.0)), MathUtil::PPC_FPCLASS_QNAN);
|
EXPECT_EQ(MathUtil::ClassifyDouble(sqrt(-1.0)), MathUtil::PPC_FPCLASS_QNAN);
|
||||||
|
|
||||||
// Float version
|
// Float version
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(1.0f), MathUtil::PPC_FPCLASS_PN);
|
EXPECT_EQ(MathUtil::ClassifyFloat(1.0f), MathUtil::PPC_FPCLASS_PN);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(-1.0f), MathUtil::PPC_FPCLASS_NN);
|
EXPECT_EQ(MathUtil::ClassifyFloat(-1.0f), MathUtil::PPC_FPCLASS_NN);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(1235223.0f), MathUtil::PPC_FPCLASS_PN);
|
EXPECT_EQ(MathUtil::ClassifyFloat(1235223.0f), MathUtil::PPC_FPCLASS_PN);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(-1263221.0f), MathUtil::PPC_FPCLASS_NN);
|
EXPECT_EQ(MathUtil::ClassifyFloat(-1263221.0f), MathUtil::PPC_FPCLASS_NN);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(1.0E-43f), MathUtil::PPC_FPCLASS_PD);
|
EXPECT_EQ(MathUtil::ClassifyFloat(1.0E-43f), MathUtil::PPC_FPCLASS_PD);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(-1.0E-43f), MathUtil::PPC_FPCLASS_ND);
|
EXPECT_EQ(MathUtil::ClassifyFloat(-1.0E-43f), MathUtil::PPC_FPCLASS_ND);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(0.0f), MathUtil::PPC_FPCLASS_PZ);
|
EXPECT_EQ(MathUtil::ClassifyFloat(0.0f), MathUtil::PPC_FPCLASS_PZ);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(-0.0f), MathUtil::PPC_FPCLASS_NZ);
|
EXPECT_EQ(MathUtil::ClassifyFloat(-0.0f), MathUtil::PPC_FPCLASS_NZ);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat((float)HUGE_VAL), MathUtil::PPC_FPCLASS_PINF); // weird #define for infinity
|
EXPECT_EQ(MathUtil::ClassifyFloat((float)HUGE_VAL), MathUtil::PPC_FPCLASS_PINF); // weird #define for infinity
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat((float)-HUGE_VAL), MathUtil::PPC_FPCLASS_NINF);
|
EXPECT_EQ(MathUtil::ClassifyFloat((float)-HUGE_VAL), MathUtil::PPC_FPCLASS_NINF);
|
||||||
EXPECT_EQ(MathUtil::ClassifyFloat(sqrtf(-1.0f)), MathUtil::PPC_FPCLASS_QNAN);
|
EXPECT_EQ(MathUtil::ClassifyFloat(sqrtf(-1.0f)), MathUtil::PPC_FPCLASS_QNAN);
|
||||||
|
|
||||||
EXPECT_FALSE(MathUtil::IsNAN(1.0));
|
EXPECT_FALSE(MathUtil::IsNAN(1.0));
|
||||||
EXPECT_TRUE(MathUtil::IsNAN(sqrt(-1.0)));
|
EXPECT_TRUE(MathUtil::IsNAN(sqrt(-1.0)));
|
||||||
EXPECT_FALSE(MathUtil::IsSNAN(sqrt(-1.0)));
|
EXPECT_FALSE(MathUtil::IsSNAN(sqrt(-1.0)));
|
||||||
|
|
||||||
// EXPECT_TRUE(MathUtil::IsQNAN(sqrt(-1.0))); // Hmm...
|
// EXPECT_TRUE(MathUtil::IsQNAN(sqrt(-1.0))); // Hmm...
|
||||||
EXPECT_EQ(pow2(2.0), 4.0);
|
EXPECT_EQ(pow2(2.0), 4.0);
|
||||||
EXPECT_EQ(pow2(-2.0), 4.0);
|
EXPECT_EQ(pow2(-2.0), 4.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringTests()
|
void StringTests()
|
||||||
{
|
{
|
||||||
EXPECT_EQ(StripSpaces(" abc "), "abc");
|
EXPECT_EQ(StripSpaces(" abc "), "abc");
|
||||||
EXPECT_EQ(StripNewline(" abc \n"), " abc ");
|
EXPECT_EQ(StripNewline(" abc \n"), " abc ");
|
||||||
EXPECT_EQ(StripNewline(" abc \n "), " abc \n ");
|
EXPECT_EQ(StripNewline(" abc \n "), " abc \n ");
|
||||||
EXPECT_EQ(StripQuotes("\"abc\""), "abc");
|
EXPECT_EQ(StripQuotes("\"abc\""), "abc");
|
||||||
EXPECT_EQ(StripQuotes("\"abc\" "), "\"abc\" ");
|
EXPECT_EQ(StripQuotes("\"abc\" "), "\"abc\" ");
|
||||||
EXPECT_EQ(TabsToSpaces(4, "a\tb"), "a b");
|
EXPECT_EQ(TabsToSpaces(4, "a\tb"), "a b");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, _TCHAR* argv[])
|
int main(int argc, _TCHAR* argv[])
|
||||||
{
|
{
|
||||||
CoreTests();
|
CoreTests();
|
||||||
MathTests();
|
MathTests();
|
||||||
StringTests();
|
StringTests();
|
||||||
if (fail_count == 0)
|
if (fail_count == 0)
|
||||||
{
|
{
|
||||||
printf("All tests passed.\n");
|
printf("All tests passed.\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Pretend that we are a host so we can link to core.... urgh.
|
// Pretend that we are a host so we can link to core.... urgh.
|
||||||
//==============================================================
|
//==============================================================
|
||||||
void Host_UpdateMainFrame(){}
|
void Host_UpdateMainFrame(){}
|
||||||
void Host_UpdateDisasmDialog(){}
|
void Host_UpdateDisasmDialog(){}
|
||||||
void Host_UpdateLogDisplay(){}
|
void Host_UpdateLogDisplay(){}
|
||||||
void Host_UpdateMemoryView(){}
|
void Host_UpdateMemoryView(){}
|
||||||
void Host_NotifyMapLoaded(){}
|
void Host_NotifyMapLoaded(){}
|
||||||
void Host_UpdateBreakPointView(){}
|
void Host_UpdateBreakPointView(){}
|
||||||
void Host_SetDebugMode(bool enable){}
|
void Host_SetDebugMode(bool enable){}
|
||||||
|
|
||||||
void Host_SetWaitCursor(bool enable){}
|
void Host_SetWaitCursor(bool enable){}
|
||||||
|
|
||||||
void Host_UpdateStatusBar(const char* _pText, int Filed = 0){}
|
void Host_UpdateStatusBar(const char* _pText, int Filed = 0){}
|
||||||
#ifdef SETUP_TIMER_WAITING
|
#ifdef SETUP_TIMER_WAITING
|
||||||
void Host_UpdateGUI(){}
|
void Host_UpdateGUI(){}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Host_SysMessage(const char *fmt, ...){}
|
void Host_SysMessage(const char *fmt, ...){}
|
||||||
void Host_SetWiiMoteConnectionState(int _State){}
|
void Host_SetWiiMoteConnectionState(int _State){}
|
||||||
|
|
||||||
void Host_UpdateLeds(int bits){}
|
void Host_UpdateLeds(int bits){}
|
||||||
void Host_UpdateSpeakerStatus(int index, int bits){}
|
void Host_UpdateSpeakerStatus(int index, int bits){}
|
||||||
void Host_UpdateStatus(){}
|
void Host_UpdateStatus(){}
|
||||||
|
|
||||||
int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
|
int CSIDevice_GCController::GetNetInput(u8 numPAD, SPADStatus PadStatus, u32 *PADStatus)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue