mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
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:
@ -1,88 +1,88 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "AudioCommon.h"
|
||||
#include "Mixer.h"
|
||||
#include "DSoundStream.h"
|
||||
#include "AOSoundStream.h"
|
||||
#include "NullSoundStream.h"
|
||||
#include "OpenALStream.h"
|
||||
|
||||
namespace AudioCommon
|
||||
{
|
||||
SoundStream *InitSoundStream(CMixer *mixer)
|
||||
{
|
||||
if (!mixer)
|
||||
mixer = new CMixer();
|
||||
|
||||
std::string backend = ac_Config.sBackend;
|
||||
if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd);
|
||||
if (backend == BACKEND_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
|
||||
if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
|
||||
if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
|
||||
|
||||
if (soundStream != NULL) {
|
||||
ac_Config.Update();
|
||||
if (soundStream->Start()) {
|
||||
// Start the sound recording
|
||||
/*
|
||||
if (ac_Config.record) {
|
||||
soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
|
||||
}
|
||||
*/
|
||||
|
||||
return soundStream;
|
||||
}
|
||||
PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str());
|
||||
}
|
||||
|
||||
PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
|
||||
|
||||
delete soundStream;
|
||||
soundStream = new NullSound(mixer);
|
||||
soundStream->Start();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ShutdownSoundStream()
|
||||
{
|
||||
NOTICE_LOG(DSPHLE, "Shutting down sound stream");
|
||||
|
||||
if (soundStream)
|
||||
{
|
||||
soundStream->Stop();
|
||||
soundStream->StopLogAudio();
|
||||
delete soundStream;
|
||||
soundStream = NULL;
|
||||
}
|
||||
|
||||
INFO_LOG(DSPHLE, "Done shutting down sound stream");
|
||||
}
|
||||
|
||||
std::vector<std::string> GetSoundBackends()
|
||||
{
|
||||
std::vector<std::string> backends;
|
||||
|
||||
if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
|
||||
if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
|
||||
if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
|
||||
if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
|
||||
|
||||
return backends;
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "AudioCommon.h"
|
||||
#include "Mixer.h"
|
||||
#include "DSoundStream.h"
|
||||
#include "AOSoundStream.h"
|
||||
#include "NullSoundStream.h"
|
||||
#include "OpenALStream.h"
|
||||
|
||||
namespace AudioCommon
|
||||
{
|
||||
SoundStream *InitSoundStream(CMixer *mixer)
|
||||
{
|
||||
if (!mixer)
|
||||
mixer = new CMixer();
|
||||
|
||||
std::string backend = ac_Config.sBackend;
|
||||
if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) soundStream = new DSound(mixer, g_dspInitialize.hWnd);
|
||||
if (backend == BACKEND_AOSOUND && AOSound::isValid()) soundStream = new AOSound(mixer);
|
||||
if (backend == BACKEND_OPENAL && OpenALStream::isValid()) soundStream = new OpenALStream(mixer);
|
||||
if (backend == BACKEND_NULL && NullSound::isValid()) soundStream = new NullSound(mixer);
|
||||
|
||||
if (soundStream != NULL) {
|
||||
ac_Config.Update();
|
||||
if (soundStream->Start()) {
|
||||
// Start the sound recording
|
||||
/*
|
||||
if (ac_Config.record) {
|
||||
soundStream->StartLogAudio(FULL_DUMP_DIR g_Config.recordFile);
|
||||
}
|
||||
*/
|
||||
|
||||
return soundStream;
|
||||
}
|
||||
PanicAlert("Could not initialize backend %s, falling back to NULL", backend.c_str());
|
||||
}
|
||||
|
||||
PanicAlert("Sound backend %s is not valid, falling back to NULL", backend.c_str());
|
||||
|
||||
delete soundStream;
|
||||
soundStream = new NullSound(mixer);
|
||||
soundStream->Start();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ShutdownSoundStream()
|
||||
{
|
||||
NOTICE_LOG(DSPHLE, "Shutting down sound stream");
|
||||
|
||||
if (soundStream)
|
||||
{
|
||||
soundStream->Stop();
|
||||
soundStream->StopLogAudio();
|
||||
delete soundStream;
|
||||
soundStream = NULL;
|
||||
}
|
||||
|
||||
INFO_LOG(DSPHLE, "Done shutting down sound stream");
|
||||
}
|
||||
|
||||
std::vector<std::string> GetSoundBackends()
|
||||
{
|
||||
std::vector<std::string> backends;
|
||||
|
||||
if (DSound::isValid()) backends.push_back(BACKEND_DIRECTSOUND);
|
||||
if (AOSound::isValid()) backends.push_back(BACKEND_AOSOUND);
|
||||
if (OpenALStream::isValid()) backends.push_back(BACKEND_OPENAL);
|
||||
if (NullSound::isValid()) backends.push_back(BACKEND_NULL);
|
||||
|
||||
return backends;
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +1,40 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _AUDIO_COMMON_H_
|
||||
#define _AUDIO_COMMON_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "AudioCommonConfig.h"
|
||||
#include "../../../PluginSpecs/pluginspecs_dsp.h"
|
||||
#include "SoundStream.h"
|
||||
|
||||
|
||||
class CMixer;
|
||||
|
||||
extern DSPInitialize g_dspInitialize;
|
||||
extern SoundStream *soundStream;
|
||||
extern AudioCommonConfig ac_Config;
|
||||
|
||||
namespace AudioCommon
|
||||
{
|
||||
SoundStream *InitSoundStream(CMixer *mixer = NULL);
|
||||
void ShutdownSoundStream();
|
||||
std::vector<std::string> GetSoundBackends();
|
||||
}
|
||||
|
||||
#endif // _AUDIO_COMMON_H_
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _AUDIO_COMMON_H_
|
||||
#define _AUDIO_COMMON_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "AudioCommonConfig.h"
|
||||
#include "../../../PluginSpecs/pluginspecs_dsp.h"
|
||||
#include "SoundStream.h"
|
||||
|
||||
|
||||
class CMixer;
|
||||
|
||||
extern DSPInitialize g_dspInitialize;
|
||||
extern SoundStream *soundStream;
|
||||
extern AudioCommonConfig ac_Config;
|
||||
|
||||
namespace AudioCommon
|
||||
{
|
||||
SoundStream *InitSoundStream(CMixer *mixer = NULL);
|
||||
void ShutdownSoundStream();
|
||||
std::vector<std::string> GetSoundBackends();
|
||||
}
|
||||
|
||||
#endif // _AUDIO_COMMON_H_
|
||||
|
@ -1,52 +1,52 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "AudioCommon.h"
|
||||
AudioCommonConfig ac_Config;
|
||||
|
||||
// Load from given file
|
||||
void AudioCommonConfig::Load(IniFile &file) {
|
||||
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
|
||||
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
|
||||
file.Get("Config", "Volume", &m_Volume, 75);
|
||||
#ifdef _WIN32
|
||||
file.Get("Config", "Backend", &sBackend, "DSound");
|
||||
#elif defined(__APPLE__)
|
||||
std::string temp;
|
||||
file.Get("Config", "Backend", &temp, "AOSound");
|
||||
strncpy(sBackend, temp.c_str(), 128);
|
||||
#else
|
||||
file.Get("Config", "Backend", &sBackend, "AOSound");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set the values for the file
|
||||
void AudioCommonConfig::Set(IniFile &file) {
|
||||
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
|
||||
file.Set("Config", "EnableThrottle", m_EnableThrottle);
|
||||
file.Set("Config", "Backend", sBackend);
|
||||
file.Set("Config", "Volume", m_Volume);
|
||||
}
|
||||
|
||||
// Update according to the values (stream/mixer)
|
||||
void AudioCommonConfig::Update() {
|
||||
if (soundStream) {
|
||||
soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
|
||||
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
|
||||
soundStream->SetVolume(m_Volume);
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "AudioCommon.h"
|
||||
AudioCommonConfig ac_Config;
|
||||
|
||||
// Load from given file
|
||||
void AudioCommonConfig::Load(IniFile &file) {
|
||||
file.Get("Config", "EnableDTKMusic", &m_EnableDTKMusic, true);
|
||||
file.Get("Config", "EnableThrottle", &m_EnableThrottle, true);
|
||||
file.Get("Config", "Volume", &m_Volume, 75);
|
||||
#ifdef _WIN32
|
||||
file.Get("Config", "Backend", &sBackend, "DSound");
|
||||
#elif defined(__APPLE__)
|
||||
std::string temp;
|
||||
file.Get("Config", "Backend", &temp, "AOSound");
|
||||
strncpy(sBackend, temp.c_str(), 128);
|
||||
#else
|
||||
file.Get("Config", "Backend", &sBackend, "AOSound");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set the values for the file
|
||||
void AudioCommonConfig::Set(IniFile &file) {
|
||||
file.Set("Config", "EnableDTKMusic", m_EnableDTKMusic);
|
||||
file.Set("Config", "EnableThrottle", m_EnableThrottle);
|
||||
file.Set("Config", "Backend", sBackend);
|
||||
file.Set("Config", "Volume", m_Volume);
|
||||
}
|
||||
|
||||
// Update according to the values (stream/mixer)
|
||||
void AudioCommonConfig::Update() {
|
||||
if (soundStream) {
|
||||
soundStream->GetMixer()->SetThrottle(m_EnableThrottle);
|
||||
soundStream->GetMixer()->SetDTKMusic(m_EnableDTKMusic);
|
||||
soundStream->SetVolume(m_Volume);
|
||||
}
|
||||
}
|
||||
|
@ -1,50 +1,50 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _AUDIO_COMMON_CONFIG_H_
|
||||
#define _AUDIO_COMMON_CONFIG_H_
|
||||
|
||||
#include <string>
|
||||
#include "IniFile.h"
|
||||
|
||||
// Backend Types
|
||||
#define BACKEND_DIRECTSOUND "DSound"
|
||||
#define BACKEND_AOSOUND "AOSound"
|
||||
#define BACKEND_OPENAL "OpenAL"
|
||||
#define BACKEND_NULL "NullSound"
|
||||
struct AudioCommonConfig
|
||||
{
|
||||
bool m_EnableDTKMusic;
|
||||
bool m_EnableThrottle;
|
||||
int m_Volume;
|
||||
#ifdef __APPLE__
|
||||
char sBackend[128];
|
||||
#else
|
||||
std::string sBackend;
|
||||
#endif
|
||||
|
||||
// Load from given file
|
||||
void Load(IniFile &file);
|
||||
|
||||
// Set the values for the file
|
||||
void Set(IniFile &file);
|
||||
|
||||
// Update according to the values (stream/mixer)
|
||||
void Update();
|
||||
};
|
||||
|
||||
#endif //AUDIO_COMMON_CONFIG
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _AUDIO_COMMON_CONFIG_H_
|
||||
#define _AUDIO_COMMON_CONFIG_H_
|
||||
|
||||
#include <string>
|
||||
#include "IniFile.h"
|
||||
|
||||
// Backend Types
|
||||
#define BACKEND_DIRECTSOUND "DSound"
|
||||
#define BACKEND_AOSOUND "AOSound"
|
||||
#define BACKEND_OPENAL "OpenAL"
|
||||
#define BACKEND_NULL "NullSound"
|
||||
struct AudioCommonConfig
|
||||
{
|
||||
bool m_EnableDTKMusic;
|
||||
bool m_EnableThrottle;
|
||||
int m_Volume;
|
||||
#ifdef __APPLE__
|
||||
char sBackend[128];
|
||||
#else
|
||||
std::string sBackend;
|
||||
#endif
|
||||
|
||||
// Load from given file
|
||||
void Load(IniFile &file);
|
||||
|
||||
// Set the values for the file
|
||||
void Set(IniFile &file);
|
||||
|
||||
// Update according to the values (stream/mixer)
|
||||
void Update();
|
||||
};
|
||||
|
||||
#endif //AUDIO_COMMON_CONFIG
|
||||
|
@ -1,170 +1,170 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "aldlist.h"
|
||||
#include "OpenALStream.h"
|
||||
|
||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||
|
||||
#define AUDIO_NUMBUFFERS (4)
|
||||
//#define AUDIO_SERVICE_UPDATE_PERIOD (20)
|
||||
|
||||
bool OpenALStream::Start()
|
||||
{
|
||||
ALDeviceList *pDeviceList = NULL;
|
||||
ALCcontext *pContext = NULL;
|
||||
ALCdevice *pDevice = NULL;
|
||||
bool bReturn = false;
|
||||
|
||||
pDeviceList = new ALDeviceList();
|
||||
if ((pDeviceList) && (pDeviceList->GetNumDevices()))
|
||||
{
|
||||
pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
|
||||
if (pDevice)
|
||||
{
|
||||
pContext = alcCreateContext(pDevice, NULL);
|
||||
if (pContext)
|
||||
{
|
||||
alcMakeContextCurrent(pContext);
|
||||
thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
|
||||
bReturn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
alcCloseDevice(pDevice);
|
||||
PanicAlert("OpenAL: can't create context for device %s", pDevice);
|
||||
}
|
||||
} else {
|
||||
PanicAlert("OpenAL: can't open device %s", pDevice);
|
||||
}
|
||||
|
||||
|
||||
delete pDeviceList;
|
||||
} else {
|
||||
PanicAlert("OpenAL: can't find sound devices");
|
||||
}
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
void OpenALStream::Stop()
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *pDevice;
|
||||
|
||||
soundCriticalSection.Enter();
|
||||
threadData = 1;
|
||||
// kick the thread if it's waiting
|
||||
soundSyncEvent.Set();
|
||||
soundCriticalSection.Leave();
|
||||
delete thread;
|
||||
|
||||
pContext = alcGetCurrentContext();
|
||||
pDevice = alcGetContextsDevice(pContext);
|
||||
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(pContext);
|
||||
alcCloseDevice(pDevice);
|
||||
|
||||
soundSyncEvent.Shutdown();
|
||||
thread = NULL;
|
||||
}
|
||||
|
||||
void OpenALStream::Update()
|
||||
{
|
||||
//if (m_mixer->GetDataSize()) //here need debug
|
||||
{
|
||||
soundSyncEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
THREAD_RETURN OpenALStream::ThreadFunc(void* args)
|
||||
{
|
||||
(reinterpret_cast<OpenALStream *>(args))->SoundLoop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenALStream::SoundLoop()
|
||||
{
|
||||
ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
|
||||
ALuint uiSource = 0;
|
||||
ALenum err;
|
||||
u32 ulFrequency = m_mixer->GetSampleRate();
|
||||
// Generate some AL Buffers for streaming
|
||||
alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
|
||||
// Generate a Source to playback the Buffers
|
||||
alGenSources(1, &uiSource);
|
||||
|
||||
memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
|
||||
//*
|
||||
for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
|
||||
{
|
||||
// pay load fake data
|
||||
alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
|
||||
alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
|
||||
}
|
||||
//*/
|
||||
alSourcePlay(uiSource);
|
||||
err = alGetError();
|
||||
|
||||
while (!threadData)
|
||||
{
|
||||
soundCriticalSection.Enter();
|
||||
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
|
||||
/*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
|
||||
soundCriticalSection.Leave();
|
||||
|
||||
//if (numBytesRender) //here need debug
|
||||
{
|
||||
ALint iBuffersProcessed = 0;
|
||||
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
|
||||
|
||||
if (iBuffersProcessed)
|
||||
{
|
||||
// Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
|
||||
ALuint uiTempBuffer = 0;
|
||||
alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
|
||||
/*
|
||||
soundCriticalSection.Enter();
|
||||
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
|
||||
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
|
||||
soundCriticalSection.Leave();
|
||||
|
||||
unsigned long ulBytesWritten = 0;
|
||||
*/
|
||||
//if (numBytesRender)
|
||||
{
|
||||
alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
|
||||
}
|
||||
alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (!threadData)
|
||||
soundSyncEvent.Wait();
|
||||
}
|
||||
alSourceStop(uiSource);
|
||||
alSourcei(uiSource, AL_BUFFER, 0);
|
||||
|
||||
// Clean up buffers and sources
|
||||
alDeleteSources(1, &uiSource);
|
||||
alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
|
||||
|
||||
}
|
||||
|
||||
#endif //HAVE_OPENAL
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "aldlist.h"
|
||||
#include "OpenALStream.h"
|
||||
|
||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||
|
||||
#define AUDIO_NUMBUFFERS (4)
|
||||
//#define AUDIO_SERVICE_UPDATE_PERIOD (20)
|
||||
|
||||
bool OpenALStream::Start()
|
||||
{
|
||||
ALDeviceList *pDeviceList = NULL;
|
||||
ALCcontext *pContext = NULL;
|
||||
ALCdevice *pDevice = NULL;
|
||||
bool bReturn = false;
|
||||
|
||||
pDeviceList = new ALDeviceList();
|
||||
if ((pDeviceList) && (pDeviceList->GetNumDevices()))
|
||||
{
|
||||
pDevice = alcOpenDevice((const ALCchar *)pDeviceList->GetDeviceName(pDeviceList->GetDefaultDevice()));
|
||||
if (pDevice)
|
||||
{
|
||||
pContext = alcCreateContext(pDevice, NULL);
|
||||
if (pContext)
|
||||
{
|
||||
alcMakeContextCurrent(pContext);
|
||||
thread = new Common::Thread(OpenALStream::ThreadFunc, (void *)this);
|
||||
bReturn = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
alcCloseDevice(pDevice);
|
||||
PanicAlert("OpenAL: can't create context for device %s", pDevice);
|
||||
}
|
||||
} else {
|
||||
PanicAlert("OpenAL: can't open device %s", pDevice);
|
||||
}
|
||||
|
||||
|
||||
delete pDeviceList;
|
||||
} else {
|
||||
PanicAlert("OpenAL: can't find sound devices");
|
||||
}
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
void OpenALStream::Stop()
|
||||
{
|
||||
ALCcontext *pContext;
|
||||
ALCdevice *pDevice;
|
||||
|
||||
soundCriticalSection.Enter();
|
||||
threadData = 1;
|
||||
// kick the thread if it's waiting
|
||||
soundSyncEvent.Set();
|
||||
soundCriticalSection.Leave();
|
||||
delete thread;
|
||||
|
||||
pContext = alcGetCurrentContext();
|
||||
pDevice = alcGetContextsDevice(pContext);
|
||||
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(pContext);
|
||||
alcCloseDevice(pDevice);
|
||||
|
||||
soundSyncEvent.Shutdown();
|
||||
thread = NULL;
|
||||
}
|
||||
|
||||
void OpenALStream::Update()
|
||||
{
|
||||
//if (m_mixer->GetDataSize()) //here need debug
|
||||
{
|
||||
soundSyncEvent.Set();
|
||||
}
|
||||
}
|
||||
|
||||
THREAD_RETURN OpenALStream::ThreadFunc(void* args)
|
||||
{
|
||||
(reinterpret_cast<OpenALStream *>(args))->SoundLoop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenALStream::SoundLoop()
|
||||
{
|
||||
ALuint uiBuffers[AUDIO_NUMBUFFERS] = {0};
|
||||
ALuint uiSource = 0;
|
||||
ALenum err;
|
||||
u32 ulFrequency = m_mixer->GetSampleRate();
|
||||
// Generate some AL Buffers for streaming
|
||||
alGenBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
|
||||
// Generate a Source to playback the Buffers
|
||||
alGenSources(1, &uiSource);
|
||||
|
||||
memset(realtimeBuffer, 0, OAL_BUFFER_SIZE * sizeof(short));
|
||||
//*
|
||||
for (int iLoop = 0; iLoop < AUDIO_NUMBUFFERS; iLoop++)
|
||||
{
|
||||
// pay load fake data
|
||||
alBufferData(uiBuffers[iLoop], AL_FORMAT_STEREO16, realtimeBuffer, 1024, ulFrequency);
|
||||
alSourceQueueBuffers(uiSource, 1, &uiBuffers[iLoop]);
|
||||
}
|
||||
//*/
|
||||
alSourcePlay(uiSource);
|
||||
err = alGetError();
|
||||
|
||||
while (!threadData)
|
||||
{
|
||||
soundCriticalSection.Enter();
|
||||
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
|
||||
/*int numBytesRender =*/ m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
|
||||
soundCriticalSection.Leave();
|
||||
|
||||
//if (numBytesRender) //here need debug
|
||||
{
|
||||
ALint iBuffersProcessed = 0;
|
||||
alGetSourcei(uiSource, AL_BUFFERS_PROCESSED, &iBuffersProcessed);
|
||||
|
||||
if (iBuffersProcessed)
|
||||
{
|
||||
// Remove the Buffer from the Queue. (uiBuffer contains the Buffer ID for the unqueued Buffer)
|
||||
ALuint uiTempBuffer = 0;
|
||||
alSourceUnqueueBuffers(uiSource, 1, &uiTempBuffer);
|
||||
/*
|
||||
soundCriticalSection.Enter();
|
||||
int numBytesToRender = 32768; //ya, this is a hack, we need real data count
|
||||
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
|
||||
soundCriticalSection.Leave();
|
||||
|
||||
unsigned long ulBytesWritten = 0;
|
||||
*/
|
||||
//if (numBytesRender)
|
||||
{
|
||||
alBufferData(uiTempBuffer, AL_FORMAT_STEREO16, realtimeBuffer, numBytesToRender, ulFrequency);
|
||||
}
|
||||
alSourceQueueBuffers(uiSource, 1, &uiTempBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (!threadData)
|
||||
soundSyncEvent.Wait();
|
||||
}
|
||||
alSourceStop(uiSource);
|
||||
alSourcei(uiSource, AL_BUFFER, 0);
|
||||
|
||||
// Clean up buffers and sources
|
||||
alDeleteSources(1, &uiSource);
|
||||
alDeleteBuffers(AUDIO_NUMBUFFERS, (ALuint *)uiBuffers);
|
||||
|
||||
}
|
||||
|
||||
#endif //HAVE_OPENAL
|
||||
|
||||
|
@ -1,74 +1,74 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _OPENALSTREAM_H_
|
||||
#define _OPENALSTREAM_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "SoundStream.h"
|
||||
#include "Thread.h"
|
||||
|
||||
|
||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||
#ifdef _WIN32
|
||||
#include "../../../../Externals/OpenAL/include/al.h"
|
||||
#include "../../../../Externals/OpenAL/include/alc.h"
|
||||
#elif defined(__APPLE__)
|
||||
#include "openal/al.h"
|
||||
#include "openal/alc.h"
|
||||
#else
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#endif // WIN32
|
||||
// public use
|
||||
#define SFX_MAX_SOURCE 1
|
||||
#define OAL_BUFFER_SIZE 1024*1024
|
||||
#endif
|
||||
|
||||
|
||||
class OpenALStream: public SoundStream
|
||||
{
|
||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||
public:
|
||||
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
|
||||
virtual ~OpenALStream() {};
|
||||
|
||||
virtual bool Start();
|
||||
virtual void SoundLoop();
|
||||
virtual void Stop();
|
||||
static bool isValid() { return true; }
|
||||
virtual bool usesMixer() const { return true; }
|
||||
virtual void Update();
|
||||
|
||||
static THREAD_RETURN ThreadFunc(void* args);
|
||||
|
||||
private:
|
||||
Common::Thread *thread;
|
||||
Common::CriticalSection soundCriticalSection;
|
||||
Common::Event soundSyncEvent;
|
||||
|
||||
short realtimeBuffer[OAL_BUFFER_SIZE];
|
||||
#else
|
||||
public:
|
||||
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
|
||||
#endif // HAVE_OPENAL
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // OPENALSTREAM
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _OPENALSTREAM_H_
|
||||
#define _OPENALSTREAM_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include "SoundStream.h"
|
||||
#include "Thread.h"
|
||||
|
||||
|
||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||
#ifdef _WIN32
|
||||
#include "../../../../Externals/OpenAL/include/al.h"
|
||||
#include "../../../../Externals/OpenAL/include/alc.h"
|
||||
#elif defined(__APPLE__)
|
||||
#include "openal/al.h"
|
||||
#include "openal/alc.h"
|
||||
#else
|
||||
#include "AL/al.h"
|
||||
#include "AL/alc.h"
|
||||
#endif // WIN32
|
||||
// public use
|
||||
#define SFX_MAX_SOURCE 1
|
||||
#define OAL_BUFFER_SIZE 1024*1024
|
||||
#endif
|
||||
|
||||
|
||||
class OpenALStream: public SoundStream
|
||||
{
|
||||
#if defined HAVE_OPENAL && HAVE_OPENAL
|
||||
public:
|
||||
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {};
|
||||
virtual ~OpenALStream() {};
|
||||
|
||||
virtual bool Start();
|
||||
virtual void SoundLoop();
|
||||
virtual void Stop();
|
||||
static bool isValid() { return true; }
|
||||
virtual bool usesMixer() const { return true; }
|
||||
virtual void Update();
|
||||
|
||||
static THREAD_RETURN ThreadFunc(void* args);
|
||||
|
||||
private:
|
||||
Common::Thread *thread;
|
||||
Common::CriticalSection soundCriticalSection;
|
||||
Common::Event soundSyncEvent;
|
||||
|
||||
short realtimeBuffer[OAL_BUFFER_SIZE];
|
||||
#else
|
||||
public:
|
||||
OpenALStream(CMixer *mixer, void *hWnd = NULL): SoundStream(mixer) {}
|
||||
#endif // HAVE_OPENAL
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // OPENALSTREAM
|
||||
|
@ -1,341 +1,341 @@
|
||||
/*
|
||||
* Copyright (c) 2006, Creative Labs Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||||
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
|
||||
* promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "aldlist.h"
|
||||
#include "../../../../Externals/OpenAL/include/al.h"
|
||||
#include "../../../../Externals/OpenAL/include/alc.h"
|
||||
|
||||
|
||||
/*
|
||||
* Init call
|
||||
*/
|
||||
ALDeviceList::ALDeviceList()
|
||||
{
|
||||
ALDEVICEINFO ALDeviceInfo;
|
||||
char *devices;
|
||||
s32 index;
|
||||
const char *defaultDeviceName = NULL;
|
||||
const char *actualDeviceName = NULL;
|
||||
|
||||
// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
|
||||
vDeviceInfo.empty();
|
||||
vDeviceInfo.reserve(10);
|
||||
|
||||
defaultDeviceIndex = 0;
|
||||
|
||||
// grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
|
||||
//if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
|
||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
|
||||
{
|
||||
devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
index = 0;
|
||||
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
|
||||
while (devices != NULL && strlen(devices) > 0)
|
||||
{
|
||||
if (strcmp(defaultDeviceName, devices) == 0)
|
||||
{
|
||||
defaultDeviceIndex = index;
|
||||
}
|
||||
ALCdevice *device = alcOpenDevice(devices);
|
||||
if (device)
|
||||
{
|
||||
ALCcontext *context = alcCreateContext(device, NULL);
|
||||
if (context)
|
||||
{
|
||||
alcMakeContextCurrent(context);
|
||||
// if new actual device name isn't already in the list, then add it...
|
||||
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||
bool bNewName = true;
|
||||
for (s32 i = 0; i < GetNumDevices(); i++)
|
||||
{
|
||||
if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
|
||||
{
|
||||
bNewName = false;
|
||||
}
|
||||
}
|
||||
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
|
||||
{
|
||||
ALDeviceInfo.bSelected = true;
|
||||
ALDeviceInfo.strDeviceName = actualDeviceName;
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
|
||||
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
|
||||
|
||||
ALDeviceInfo.pvstrExtensions = new vector<string>;
|
||||
|
||||
// Check for ALC Extensions
|
||||
if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
|
||||
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
|
||||
|
||||
// Check for AL Extensions
|
||||
if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
|
||||
|
||||
if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
|
||||
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
|
||||
|
||||
if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
|
||||
if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
|
||||
if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
|
||||
if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
|
||||
|
||||
if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
|
||||
|
||||
// Get Source Count
|
||||
ALDeviceInfo.uiSourceCount = GetMaxNumSources();
|
||||
|
||||
vDeviceInfo.push_back(ALDeviceInfo);
|
||||
}
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(context);
|
||||
}
|
||||
alcCloseDevice(device);
|
||||
}
|
||||
devices += strlen(devices) + 1;
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
ResetFilters();
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit call
|
||||
*/
|
||||
ALDeviceList::~ALDeviceList()
|
||||
{
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
if (vDeviceInfo[i].pvstrExtensions) {
|
||||
vDeviceInfo[i].pvstrExtensions->empty();
|
||||
delete vDeviceInfo[i].pvstrExtensions;
|
||||
}
|
||||
}
|
||||
|
||||
vDeviceInfo.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of devices in the complete device list
|
||||
*/
|
||||
s32 ALDeviceList::GetNumDevices()
|
||||
{
|
||||
return (s32)vDeviceInfo.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the device name at an index in the complete device list
|
||||
*/
|
||||
char * ALDeviceList::GetDeviceName(s32 index)
|
||||
{
|
||||
if (index < GetNumDevices())
|
||||
return (char *)vDeviceInfo[index].strDeviceName.c_str();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the major and minor version numbers for a device at a specified index in the complete list
|
||||
*/
|
||||
void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
|
||||
{
|
||||
if (index < GetNumDevices()) {
|
||||
if (major)
|
||||
*major = vDeviceInfo[index].iMajorVersion;
|
||||
if (minor)
|
||||
*minor = vDeviceInfo[index].iMinorVersion;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the maximum number of Sources that can be generate on the given device
|
||||
*/
|
||||
u32 ALDeviceList::GetMaxNumSources(s32 index)
|
||||
{
|
||||
if (index < GetNumDevices())
|
||||
return vDeviceInfo[index].uiSourceCount;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the extension is supported on the given device
|
||||
*/
|
||||
bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
|
||||
{
|
||||
bool bReturn = false;
|
||||
|
||||
if (index < GetNumDevices()) {
|
||||
for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
|
||||
if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
|
||||
bReturn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the index of the default device in the complete device list
|
||||
*/
|
||||
s32 ALDeviceList::GetDefaultDevice()
|
||||
{
|
||||
return defaultDeviceIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects devices which don't have the specified minimum version
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
|
||||
{
|
||||
s32 dMajor = 0, dMinor = 0;
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
GetDeviceVersion(i, &dMajor, &dMinor);
|
||||
if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
|
||||
vDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects devices which don't have the specified maximum version
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
|
||||
{
|
||||
s32 dMajor = 0, dMinor = 0;
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
GetDeviceVersion(i, &dMajor, &dMinor);
|
||||
if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
|
||||
vDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects device which don't support the given extension name
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesExtension(char *szExtName)
|
||||
{
|
||||
bool bFound;
|
||||
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
bFound = false;
|
||||
for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
|
||||
if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bFound)
|
||||
vDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Resets all filtering, such that all devices are in the list
|
||||
*/
|
||||
void ALDeviceList::ResetFilters()
|
||||
{
|
||||
for (s32 i = 0; i < GetNumDevices(); i++) {
|
||||
vDeviceInfo[i].bSelected = true;
|
||||
}
|
||||
filterIndex = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets index of first filtered device
|
||||
*/
|
||||
s32 ALDeviceList::GetFirstFilteredDevice()
|
||||
{
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < GetNumDevices(); i++) {
|
||||
if (vDeviceInfo[i].bSelected == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
filterIndex = i + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets index of next filtered device
|
||||
*/
|
||||
s32 ALDeviceList::GetNextFilteredDevice()
|
||||
{
|
||||
s32 i;
|
||||
|
||||
for (i = filterIndex; i < GetNumDevices(); i++) {
|
||||
if (vDeviceInfo[i].bSelected == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
filterIndex = i + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function to detemine max number of Sources that can be generated
|
||||
*/
|
||||
u32 ALDeviceList::GetMaxNumSources()
|
||||
{
|
||||
ALuint uiSources[256];
|
||||
u32 iSourceCount = 0;
|
||||
|
||||
// Clear AL Error Code
|
||||
alGetError();
|
||||
|
||||
// Generate up to 256 Sources, checking for any errors
|
||||
for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
|
||||
{
|
||||
alGenSources(1, &uiSources[iSourceCount]);
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
break;
|
||||
}
|
||||
|
||||
// Release the Sources
|
||||
alDeleteSources(iSourceCount, uiSources);
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
for (u32 i = 0; i < 256; i++)
|
||||
{
|
||||
alDeleteSources(1, &uiSources[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return iSourceCount;
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2006, Creative Labs Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
|
||||
* that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||||
* and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Creative Labs Inc. nor the names of its contributors may be used to endorse or
|
||||
* promote products derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "aldlist.h"
|
||||
#include "../../../../Externals/OpenAL/include/al.h"
|
||||
#include "../../../../Externals/OpenAL/include/alc.h"
|
||||
|
||||
|
||||
/*
|
||||
* Init call
|
||||
*/
|
||||
ALDeviceList::ALDeviceList()
|
||||
{
|
||||
ALDEVICEINFO ALDeviceInfo;
|
||||
char *devices;
|
||||
s32 index;
|
||||
const char *defaultDeviceName = NULL;
|
||||
const char *actualDeviceName = NULL;
|
||||
|
||||
// DeviceInfo vector stores, for each enumerated device, it's device name, selection status, spec version #, and extension support
|
||||
vDeviceInfo.empty();
|
||||
vDeviceInfo.reserve(10);
|
||||
|
||||
defaultDeviceIndex = 0;
|
||||
|
||||
// grab function pointers for 1.0-API functions, and if successful proceed to enumerate all devices
|
||||
//if (LoadOAL10Library(NULL, &ALFunction) == TRUE) {
|
||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT"))
|
||||
{
|
||||
devices = (char *)alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||
defaultDeviceName = (char *)alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER);
|
||||
index = 0;
|
||||
// go through device list (each device terminated with a single NULL, list terminated with double NULL)
|
||||
while (devices != NULL && strlen(devices) > 0)
|
||||
{
|
||||
if (strcmp(defaultDeviceName, devices) == 0)
|
||||
{
|
||||
defaultDeviceIndex = index;
|
||||
}
|
||||
ALCdevice *device = alcOpenDevice(devices);
|
||||
if (device)
|
||||
{
|
||||
ALCcontext *context = alcCreateContext(device, NULL);
|
||||
if (context)
|
||||
{
|
||||
alcMakeContextCurrent(context);
|
||||
// if new actual device name isn't already in the list, then add it...
|
||||
actualDeviceName = alcGetString(device, ALC_DEVICE_SPECIFIER);
|
||||
bool bNewName = true;
|
||||
for (s32 i = 0; i < GetNumDevices(); i++)
|
||||
{
|
||||
if (strcmp(GetDeviceName(i), actualDeviceName) == 0)
|
||||
{
|
||||
bNewName = false;
|
||||
}
|
||||
}
|
||||
if ((bNewName) && (actualDeviceName != NULL) && (strlen(actualDeviceName) > 0))
|
||||
{
|
||||
ALDeviceInfo.bSelected = true;
|
||||
ALDeviceInfo.strDeviceName = actualDeviceName;
|
||||
alcGetIntegerv(device, ALC_MAJOR_VERSION, sizeof(s32), &ALDeviceInfo.iMajorVersion);
|
||||
alcGetIntegerv(device, ALC_MINOR_VERSION, sizeof(s32), &ALDeviceInfo.iMinorVersion);
|
||||
|
||||
ALDeviceInfo.pvstrExtensions = new vector<string>;
|
||||
|
||||
// Check for ALC Extensions
|
||||
if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_CAPTURE");
|
||||
if (alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("ALC_EXT_EFX");
|
||||
|
||||
// Check for AL Extensions
|
||||
if (alIsExtensionPresent("AL_EXT_OFFSET") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_OFFSET");
|
||||
|
||||
if (alIsExtensionPresent("AL_EXT_LINEAR_DISTANCE") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_LINEAR_DISTANCE");
|
||||
if (alIsExtensionPresent("AL_EXT_EXPONENT_DISTANCE") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("AL_EXT_EXPONENT_DISTANCE");
|
||||
|
||||
if (alIsExtensionPresent("EAX2.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX2.0");
|
||||
if (alIsExtensionPresent("EAX3.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX3.0");
|
||||
if (alIsExtensionPresent("EAX4.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX4.0");
|
||||
if (alIsExtensionPresent("EAX5.0") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX5.0");
|
||||
|
||||
if (alIsExtensionPresent("EAX-RAM") == AL_TRUE)
|
||||
ALDeviceInfo.pvstrExtensions->push_back("EAX-RAM");
|
||||
|
||||
// Get Source Count
|
||||
ALDeviceInfo.uiSourceCount = GetMaxNumSources();
|
||||
|
||||
vDeviceInfo.push_back(ALDeviceInfo);
|
||||
}
|
||||
alcMakeContextCurrent(NULL);
|
||||
alcDestroyContext(context);
|
||||
}
|
||||
alcCloseDevice(device);
|
||||
}
|
||||
devices += strlen(devices) + 1;
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
ResetFilters();
|
||||
}
|
||||
|
||||
/*
|
||||
* Exit call
|
||||
*/
|
||||
ALDeviceList::~ALDeviceList()
|
||||
{
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
if (vDeviceInfo[i].pvstrExtensions) {
|
||||
vDeviceInfo[i].pvstrExtensions->empty();
|
||||
delete vDeviceInfo[i].pvstrExtensions;
|
||||
}
|
||||
}
|
||||
|
||||
vDeviceInfo.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the number of devices in the complete device list
|
||||
*/
|
||||
s32 ALDeviceList::GetNumDevices()
|
||||
{
|
||||
return (s32)vDeviceInfo.size();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the device name at an index in the complete device list
|
||||
*/
|
||||
char * ALDeviceList::GetDeviceName(s32 index)
|
||||
{
|
||||
if (index < GetNumDevices())
|
||||
return (char *)vDeviceInfo[index].strDeviceName.c_str();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the major and minor version numbers for a device at a specified index in the complete list
|
||||
*/
|
||||
void ALDeviceList::GetDeviceVersion(s32 index, s32 *major, s32 *minor)
|
||||
{
|
||||
if (index < GetNumDevices()) {
|
||||
if (major)
|
||||
*major = vDeviceInfo[index].iMajorVersion;
|
||||
if (minor)
|
||||
*minor = vDeviceInfo[index].iMinorVersion;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the maximum number of Sources that can be generate on the given device
|
||||
*/
|
||||
u32 ALDeviceList::GetMaxNumSources(s32 index)
|
||||
{
|
||||
if (index < GetNumDevices())
|
||||
return vDeviceInfo[index].uiSourceCount;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks if the extension is supported on the given device
|
||||
*/
|
||||
bool ALDeviceList::IsExtensionSupported(s32 index, char *szExtName)
|
||||
{
|
||||
bool bReturn = false;
|
||||
|
||||
if (index < GetNumDevices()) {
|
||||
for (u32 i = 0; i < vDeviceInfo[index].pvstrExtensions->size(); i++) {
|
||||
if (!strcasecmp(vDeviceInfo[index].pvstrExtensions->at(i).c_str(), szExtName)) {
|
||||
bReturn = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bReturn;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the index of the default device in the complete device list
|
||||
*/
|
||||
s32 ALDeviceList::GetDefaultDevice()
|
||||
{
|
||||
return defaultDeviceIndex;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects devices which don't have the specified minimum version
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesMinVer(s32 major, s32 minor)
|
||||
{
|
||||
s32 dMajor = 0, dMinor = 0;
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
GetDeviceVersion(i, &dMajor, &dMinor);
|
||||
if ((dMajor < major) || ((dMajor == major) && (dMinor < minor))) {
|
||||
vDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects devices which don't have the specified maximum version
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesMaxVer(s32 major, s32 minor)
|
||||
{
|
||||
s32 dMajor = 0, dMinor = 0;
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
GetDeviceVersion(i, &dMajor, &dMinor);
|
||||
if ((dMajor > major) || ((dMajor == major) && (dMinor > minor))) {
|
||||
vDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Deselects device which don't support the given extension name
|
||||
*/
|
||||
void ALDeviceList::FilterDevicesExtension(char *szExtName)
|
||||
{
|
||||
bool bFound;
|
||||
|
||||
for (u32 i = 0; i < vDeviceInfo.size(); i++) {
|
||||
bFound = false;
|
||||
for (u32 j = 0; j < vDeviceInfo[i].pvstrExtensions->size(); j++) {
|
||||
if (!strcasecmp(vDeviceInfo[i].pvstrExtensions->at(j).c_str(), szExtName)) {
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bFound)
|
||||
vDeviceInfo[i].bSelected = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Resets all filtering, such that all devices are in the list
|
||||
*/
|
||||
void ALDeviceList::ResetFilters()
|
||||
{
|
||||
for (s32 i = 0; i < GetNumDevices(); i++) {
|
||||
vDeviceInfo[i].bSelected = true;
|
||||
}
|
||||
filterIndex = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets index of first filtered device
|
||||
*/
|
||||
s32 ALDeviceList::GetFirstFilteredDevice()
|
||||
{
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < GetNumDevices(); i++) {
|
||||
if (vDeviceInfo[i].bSelected == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
filterIndex = i + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets index of next filtered device
|
||||
*/
|
||||
s32 ALDeviceList::GetNextFilteredDevice()
|
||||
{
|
||||
s32 i;
|
||||
|
||||
for (i = filterIndex; i < GetNumDevices(); i++) {
|
||||
if (vDeviceInfo[i].bSelected == true) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
filterIndex = i + 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal function to detemine max number of Sources that can be generated
|
||||
*/
|
||||
u32 ALDeviceList::GetMaxNumSources()
|
||||
{
|
||||
ALuint uiSources[256];
|
||||
u32 iSourceCount = 0;
|
||||
|
||||
// Clear AL Error Code
|
||||
alGetError();
|
||||
|
||||
// Generate up to 256 Sources, checking for any errors
|
||||
for (iSourceCount = 0; iSourceCount < 256; iSourceCount++)
|
||||
{
|
||||
alGenSources(1, &uiSources[iSourceCount]);
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
break;
|
||||
}
|
||||
|
||||
// Release the Sources
|
||||
alDeleteSources(iSourceCount, uiSources);
|
||||
if (alGetError() != AL_NO_ERROR)
|
||||
{
|
||||
for (u32 i = 0; i < 256; i++)
|
||||
{
|
||||
alDeleteSources(1, &uiSources[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return iSourceCount;
|
||||
}
|
||||
|
@ -1,51 +1,51 @@
|
||||
#ifndef ALDEVICELIST_H
|
||||
#define ALDEVICELIST_H
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable: 4786) //disable warning "identifier was truncated to
|
||||
//'255' characters in the browser information"
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
string strDeviceName;
|
||||
s32 iMajorVersion;
|
||||
s32 iMinorVersion;
|
||||
u32 uiSourceCount;
|
||||
vector<string> *pvstrExtensions;
|
||||
bool bSelected;
|
||||
} ALDEVICEINFO, *LPALDEVICEINFO;
|
||||
|
||||
class ALDeviceList
|
||||
{
|
||||
private:
|
||||
vector<ALDEVICEINFO> vDeviceInfo;
|
||||
s32 defaultDeviceIndex;
|
||||
s32 filterIndex;
|
||||
|
||||
public:
|
||||
ALDeviceList ();
|
||||
~ALDeviceList ();
|
||||
s32 GetNumDevices();
|
||||
char *GetDeviceName(s32 index);
|
||||
void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
|
||||
u32 GetMaxNumSources(s32 index);
|
||||
bool IsExtensionSupported(s32 index, char *szExtName);
|
||||
s32 GetDefaultDevice();
|
||||
void FilterDevicesMinVer(s32 major, s32 minor);
|
||||
void FilterDevicesMaxVer(s32 major, s32 minor);
|
||||
void FilterDevicesExtension(char *szExtName);
|
||||
void ResetFilters();
|
||||
s32 GetFirstFilteredDevice();
|
||||
s32 GetNextFilteredDevice();
|
||||
|
||||
private:
|
||||
u32 GetMaxNumSources();
|
||||
};
|
||||
|
||||
#endif // ALDEVICELIST_H
|
||||
#ifndef ALDEVICELIST_H
|
||||
#define ALDEVICELIST_H
|
||||
|
||||
#include "CommonTypes.h"
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable: 4786) //disable warning "identifier was truncated to
|
||||
//'255' characters in the browser information"
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
string strDeviceName;
|
||||
s32 iMajorVersion;
|
||||
s32 iMinorVersion;
|
||||
u32 uiSourceCount;
|
||||
vector<string> *pvstrExtensions;
|
||||
bool bSelected;
|
||||
} ALDEVICEINFO, *LPALDEVICEINFO;
|
||||
|
||||
class ALDeviceList
|
||||
{
|
||||
private:
|
||||
vector<ALDEVICEINFO> vDeviceInfo;
|
||||
s32 defaultDeviceIndex;
|
||||
s32 filterIndex;
|
||||
|
||||
public:
|
||||
ALDeviceList ();
|
||||
~ALDeviceList ();
|
||||
s32 GetNumDevices();
|
||||
char *GetDeviceName(s32 index);
|
||||
void GetDeviceVersion(s32 index, s32 *major, s32 *minor);
|
||||
u32 GetMaxNumSources(s32 index);
|
||||
bool IsExtensionSupported(s32 index, char *szExtName);
|
||||
s32 GetDefaultDevice();
|
||||
void FilterDevicesMinVer(s32 major, s32 minor);
|
||||
void FilterDevicesMaxVer(s32 major, s32 minor);
|
||||
void FilterDevicesExtension(char *szExtName);
|
||||
void ResetFilters();
|
||||
s32 GetFirstFilteredDevice();
|
||||
s32 GetNextFilteredDevice();
|
||||
|
||||
private:
|
||||
u32 GetMaxNumSources();
|
||||
};
|
||||
|
||||
#endif // ALDEVICELIST_H
|
||||
|
@ -1,59 +1,59 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "SymbolDB.h"
|
||||
|
||||
|
||||
void SymbolDB::List()
|
||||
{
|
||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||
{
|
||||
DEBUG_LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
|
||||
}
|
||||
INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
|
||||
}
|
||||
|
||||
void SymbolDB::Clear(const char *prefix)
|
||||
{
|
||||
// TODO: honor prefix
|
||||
functions.clear();
|
||||
checksumToFunction.clear();
|
||||
}
|
||||
|
||||
void SymbolDB::Index()
|
||||
{
|
||||
int i = 0;
|
||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||
{
|
||||
iter->second.index = i++;
|
||||
}
|
||||
}
|
||||
|
||||
Symbol *SymbolDB::GetSymbolFromName(const char *name)
|
||||
{
|
||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||
{
|
||||
if (!strcmp(iter->second.name.c_str(), name))
|
||||
return &iter->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
|
||||
{
|
||||
functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "SymbolDB.h"
|
||||
|
||||
|
||||
void SymbolDB::List()
|
||||
{
|
||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||
{
|
||||
DEBUG_LOG(HLE,"%s @ %08x: %i bytes (hash %08x) : %i calls", iter->second.name.c_str(), iter->second.address, iter->second.size, iter->second.hash,iter->second.numCalls);
|
||||
}
|
||||
INFO_LOG(HLE,"%i functions known in this program above.", functions.size());
|
||||
}
|
||||
|
||||
void SymbolDB::Clear(const char *prefix)
|
||||
{
|
||||
// TODO: honor prefix
|
||||
functions.clear();
|
||||
checksumToFunction.clear();
|
||||
}
|
||||
|
||||
void SymbolDB::Index()
|
||||
{
|
||||
int i = 0;
|
||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||
{
|
||||
iter->second.index = i++;
|
||||
}
|
||||
}
|
||||
|
||||
Symbol *SymbolDB::GetSymbolFromName(const char *name)
|
||||
{
|
||||
for (XFuncMap::iterator iter = functions.begin(); iter != functions.end(); iter++)
|
||||
{
|
||||
if (!strcmp(iter->second.name.c_str(), name))
|
||||
return &iter->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SymbolDB::AddCompleteSymbol(const Symbol &symbol)
|
||||
{
|
||||
functions.insert(std::pair<u32, Symbol>(symbol.address, symbol));
|
||||
}
|
||||
|
@ -1,122 +1,122 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
// This file contains a generic symbol map implementation. For CPU-specific
|
||||
// magic, derive and extend.
|
||||
|
||||
#ifndef _SYMBOL_DB_H
|
||||
#define _SYMBOL_DB_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
struct SCall
|
||||
{
|
||||
SCall(u32 a, u32 b) :
|
||||
function(a),
|
||||
callAddress(b)
|
||||
{}
|
||||
u32 function;
|
||||
u32 callAddress;
|
||||
};
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
enum {
|
||||
SYMBOL_FUNCTION = 0,
|
||||
SYMBOL_DATA = 1,
|
||||
};
|
||||
|
||||
Symbol() :
|
||||
hash(0),
|
||||
address(0),
|
||||
flags(0),
|
||||
size(0),
|
||||
numCalls(0),
|
||||
type(SYMBOL_FUNCTION),
|
||||
analyzed(0)
|
||||
{}
|
||||
|
||||
std::string name;
|
||||
std::vector<SCall> callers; //addresses of functions that call this function
|
||||
std::vector<SCall> calls; //addresses of functions that are called by this function
|
||||
u32 hash; //use for HLE function finding
|
||||
u32 address;
|
||||
u32 flags;
|
||||
int size;
|
||||
int numCalls;
|
||||
int type;
|
||||
int index; // only used for coloring the disasm view
|
||||
int analyzed;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FFLAG_TIMERINSTRUCTIONS=(1<<0),
|
||||
FFLAG_LEAF=(1<<1),
|
||||
FFLAG_ONLYCALLSNICELEAFS=(1<<2),
|
||||
FFLAG_EVIL=(1<<3),
|
||||
FFLAG_RFI=(1<<4),
|
||||
FFLAG_STRAIGHT=(1<<5)
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SymbolDB
|
||||
{
|
||||
public:
|
||||
typedef std::map<u32, Symbol> XFuncMap;
|
||||
typedef std::map<u32, Symbol*> XFuncPtrMap;
|
||||
|
||||
protected:
|
||||
XFuncMap functions;
|
||||
XFuncPtrMap checksumToFunction;
|
||||
|
||||
public:
|
||||
SymbolDB() {}
|
||||
virtual ~SymbolDB() {}
|
||||
virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
|
||||
virtual Symbol *AddFunction(u32 startAddr) { return 0;}
|
||||
|
||||
void AddCompleteSymbol(const Symbol &symbol);
|
||||
|
||||
Symbol *GetSymbolFromName(const char *name);
|
||||
Symbol *GetSymbolFromHash(u32 hash) {
|
||||
XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
|
||||
if (iter != checksumToFunction.end())
|
||||
return iter->second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const XFuncMap &Symbols() const {return functions;}
|
||||
XFuncMap &AccessSymbols() {return functions;}
|
||||
|
||||
// deprecated
|
||||
XFuncMap::iterator GetIterator() { return functions.begin(); }
|
||||
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
|
||||
XFuncMap::iterator End() { return functions.end(); }
|
||||
|
||||
void Clear(const char *prefix = "");
|
||||
void List();
|
||||
void Index();
|
||||
};
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
// This file contains a generic symbol map implementation. For CPU-specific
|
||||
// magic, derive and extend.
|
||||
|
||||
#ifndef _SYMBOL_DB_H
|
||||
#define _SYMBOL_DB_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
struct SCall
|
||||
{
|
||||
SCall(u32 a, u32 b) :
|
||||
function(a),
|
||||
callAddress(b)
|
||||
{}
|
||||
u32 function;
|
||||
u32 callAddress;
|
||||
};
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
enum {
|
||||
SYMBOL_FUNCTION = 0,
|
||||
SYMBOL_DATA = 1,
|
||||
};
|
||||
|
||||
Symbol() :
|
||||
hash(0),
|
||||
address(0),
|
||||
flags(0),
|
||||
size(0),
|
||||
numCalls(0),
|
||||
type(SYMBOL_FUNCTION),
|
||||
analyzed(0)
|
||||
{}
|
||||
|
||||
std::string name;
|
||||
std::vector<SCall> callers; //addresses of functions that call this function
|
||||
std::vector<SCall> calls; //addresses of functions that are called by this function
|
||||
u32 hash; //use for HLE function finding
|
||||
u32 address;
|
||||
u32 flags;
|
||||
int size;
|
||||
int numCalls;
|
||||
int type;
|
||||
int index; // only used for coloring the disasm view
|
||||
int analyzed;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FFLAG_TIMERINSTRUCTIONS=(1<<0),
|
||||
FFLAG_LEAF=(1<<1),
|
||||
FFLAG_ONLYCALLSNICELEAFS=(1<<2),
|
||||
FFLAG_EVIL=(1<<3),
|
||||
FFLAG_RFI=(1<<4),
|
||||
FFLAG_STRAIGHT=(1<<5)
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SymbolDB
|
||||
{
|
||||
public:
|
||||
typedef std::map<u32, Symbol> XFuncMap;
|
||||
typedef std::map<u32, Symbol*> XFuncPtrMap;
|
||||
|
||||
protected:
|
||||
XFuncMap functions;
|
||||
XFuncPtrMap checksumToFunction;
|
||||
|
||||
public:
|
||||
SymbolDB() {}
|
||||
virtual ~SymbolDB() {}
|
||||
virtual Symbol *GetSymbolFromAddr(u32 addr) { return 0; }
|
||||
virtual Symbol *AddFunction(u32 startAddr) { return 0;}
|
||||
|
||||
void AddCompleteSymbol(const Symbol &symbol);
|
||||
|
||||
Symbol *GetSymbolFromName(const char *name);
|
||||
Symbol *GetSymbolFromHash(u32 hash) {
|
||||
XFuncPtrMap::iterator iter = checksumToFunction.find(hash);
|
||||
if (iter != checksumToFunction.end())
|
||||
return iter->second;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const XFuncMap &Symbols() const {return functions;}
|
||||
XFuncMap &AccessSymbols() {return functions;}
|
||||
|
||||
// deprecated
|
||||
XFuncMap::iterator GetIterator() { return functions.begin(); }
|
||||
XFuncMap::const_iterator GetConstIterator() { return functions.begin(); }
|
||||
XFuncMap::iterator End() { return functions.end(); }
|
||||
|
||||
void Clear(const char *prefix = "");
|
||||
void List();
|
||||
void Index();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,24 +1,24 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||
//Add support for apple keycodes
|
||||
};
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||
//Add support for apple keycodes
|
||||
};
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||
//Add support for apple keycodes
|
||||
};
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||
//Add support for apple keycodes
|
||||
};
|
||||
|
@ -1,25 +1,25 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||
//Add support for Linux keycodes
|
||||
};
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||
//Add support for Linux keycodes
|
||||
};
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||
//Add support for Linux keycodes
|
||||
};
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||
//Add support for Linux keycodes
|
||||
};
|
||||
|
||||
|
@ -1,192 +1,192 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2A, // Backspace
|
||||
0x2B, // Tab
|
||||
0x00, 0x00,
|
||||
0x00, // Clear
|
||||
0x28, // Return
|
||||
0x00, 0x00,
|
||||
0x00, // Shift
|
||||
0x00, // Control
|
||||
0x00, // ALT
|
||||
0x48, // Pause
|
||||
0x39, // Capital
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, // Escape
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x2C, // Space
|
||||
0x4B, // Prior
|
||||
0x4E, // Next
|
||||
0x4D, // End
|
||||
0x4A, // Home
|
||||
0x50, // Left
|
||||
0x52, // Up
|
||||
0x4F, // Right
|
||||
0x51, // Down
|
||||
0x00, 0x00, 0x00,
|
||||
0x46, // Print screen
|
||||
0x49, // Insert
|
||||
0x4C, // Delete
|
||||
0x00,
|
||||
// 0 -> 9
|
||||
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||
0x25, 0x26,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
// A -> Z
|
||||
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
||||
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
|
||||
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
|
||||
0x1C, 0x1D,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
// Numpad 0 -> 9
|
||||
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61,
|
||||
0x55, // Multiply
|
||||
0x57, // Add
|
||||
0x00, // Separator
|
||||
0x56, // Substract
|
||||
0x63, // Decimal
|
||||
0x54, // Divide
|
||||
// F1 -> F12
|
||||
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
|
||||
0x42, 0x43, 0x44, 0x45,
|
||||
// F13 -> F24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x53, // Numlock
|
||||
0x47, // Scroll lock
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Modifier keys
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x33, // ';'
|
||||
0x2E, // Plus
|
||||
0x36, // Comma
|
||||
0x2D, // Minus
|
||||
0x37, // Period
|
||||
0x38, // '/'
|
||||
0x35, // '~'
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x2F, // '['
|
||||
0x32, // '\'
|
||||
0x30, // ']'
|
||||
0x34, // '''
|
||||
0x00, //
|
||||
0x00, // Nothing interesting past this point.
|
||||
|
||||
};
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2A, // Backspace
|
||||
0x2B, // Tab
|
||||
0x00, 0x00,
|
||||
0x00, // Clear
|
||||
0x28, // Return
|
||||
0x00, 0x00,
|
||||
0x00, // Shift
|
||||
0x00, // Control
|
||||
0x00, // ALT
|
||||
0x48, // Pause
|
||||
0x39, // Capital
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, // Escape
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x2C, // Space
|
||||
0x4B, // Prior
|
||||
0x4E, // Next
|
||||
0x4D, // End
|
||||
0x4A, // Home
|
||||
0x50, // Left
|
||||
0x52, // Up
|
||||
0x4F, // Right
|
||||
0x51, // Down
|
||||
0x00, 0x00, 0x00,
|
||||
0x46, // Print screen
|
||||
0x49, // Insert
|
||||
0x4C, // Delete
|
||||
0x00,
|
||||
// 0 -> 9
|
||||
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||
0x25, 0x26,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
// A -> Z
|
||||
0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
||||
0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
|
||||
0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
|
||||
0x1C, 0x1A,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
// Numpad 0 -> 9
|
||||
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61,
|
||||
0x55, // Multiply
|
||||
0x57, // Add
|
||||
0x00, // Separator
|
||||
0x56, // Substract
|
||||
0x63, // Decimal
|
||||
0x54, // Divide
|
||||
// F1 -> F12
|
||||
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
|
||||
0x42, 0x43, 0x44, 0x45,
|
||||
// F13 -> F24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x53, // Numlock
|
||||
0x47, // Scroll lock
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Modifier keys
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x30, // '$'
|
||||
0x2E, // Plus
|
||||
0x10, // Comma
|
||||
0x00, // Minus
|
||||
0x36, // Period
|
||||
0x37, // '/'
|
||||
0x34, // '<27>'
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x2D, // ')'
|
||||
0x32, // '\'
|
||||
0x2F, // '^'
|
||||
0x00, // '<27>'
|
||||
0x38, // '!'
|
||||
0x00, // Nothing interesting past this point.
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesQWERTY[256] = {
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2A, // Backspace
|
||||
0x2B, // Tab
|
||||
0x00, 0x00,
|
||||
0x00, // Clear
|
||||
0x28, // Return
|
||||
0x00, 0x00,
|
||||
0x00, // Shift
|
||||
0x00, // Control
|
||||
0x00, // ALT
|
||||
0x48, // Pause
|
||||
0x39, // Capital
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, // Escape
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x2C, // Space
|
||||
0x4B, // Prior
|
||||
0x4E, // Next
|
||||
0x4D, // End
|
||||
0x4A, // Home
|
||||
0x50, // Left
|
||||
0x52, // Up
|
||||
0x4F, // Right
|
||||
0x51, // Down
|
||||
0x00, 0x00, 0x00,
|
||||
0x46, // Print screen
|
||||
0x49, // Insert
|
||||
0x4C, // Delete
|
||||
0x00,
|
||||
// 0 -> 9
|
||||
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||
0x25, 0x26,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
// A -> Z
|
||||
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
||||
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13,
|
||||
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B,
|
||||
0x1C, 0x1D,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
// Numpad 0 -> 9
|
||||
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61,
|
||||
0x55, // Multiply
|
||||
0x57, // Add
|
||||
0x00, // Separator
|
||||
0x56, // Substract
|
||||
0x63, // Decimal
|
||||
0x54, // Divide
|
||||
// F1 -> F12
|
||||
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
|
||||
0x42, 0x43, 0x44, 0x45,
|
||||
// F13 -> F24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x53, // Numlock
|
||||
0x47, // Scroll lock
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Modifier keys
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x33, // ';'
|
||||
0x2E, // Plus
|
||||
0x36, // Comma
|
||||
0x2D, // Minus
|
||||
0x37, // Period
|
||||
0x38, // '/'
|
||||
0x35, // '~'
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x2F, // '['
|
||||
0x32, // '\'
|
||||
0x30, // ']'
|
||||
0x34, // '''
|
||||
0x00, //
|
||||
0x00, // Nothing interesting past this point.
|
||||
|
||||
};
|
||||
|
||||
u8 CWII_IPC_HLE_Device_usb_kbd::m_KeyCodesAZERTY[256] = {
|
||||
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2A, // Backspace
|
||||
0x2B, // Tab
|
||||
0x00, 0x00,
|
||||
0x00, // Clear
|
||||
0x28, // Return
|
||||
0x00, 0x00,
|
||||
0x00, // Shift
|
||||
0x00, // Control
|
||||
0x00, // ALT
|
||||
0x48, // Pause
|
||||
0x39, // Capital
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x29, // Escape
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x2C, // Space
|
||||
0x4B, // Prior
|
||||
0x4E, // Next
|
||||
0x4D, // End
|
||||
0x4A, // Home
|
||||
0x50, // Left
|
||||
0x52, // Up
|
||||
0x4F, // Right
|
||||
0x51, // Down
|
||||
0x00, 0x00, 0x00,
|
||||
0x46, // Print screen
|
||||
0x49, // Insert
|
||||
0x4C, // Delete
|
||||
0x00,
|
||||
// 0 -> 9
|
||||
0x27, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||
0x25, 0x26,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
// A -> Z
|
||||
0x14, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
||||
0x0C, 0x0D, 0x0E, 0x0F, 0x33, 0x11, 0x12, 0x13,
|
||||
0x04, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1D, 0x1B,
|
||||
0x1C, 0x1A,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
// Numpad 0 -> 9
|
||||
0x62, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
|
||||
0x60, 0x61,
|
||||
0x55, // Multiply
|
||||
0x57, // Add
|
||||
0x00, // Separator
|
||||
0x56, // Substract
|
||||
0x63, // Decimal
|
||||
0x54, // Divide
|
||||
// F1 -> F12
|
||||
0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41,
|
||||
0x42, 0x43, 0x44, 0x45,
|
||||
// F13 -> F24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x53, // Numlock
|
||||
0x47, // Scroll lock
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
// Modifier keys
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x30, // '$'
|
||||
0x2E, // Plus
|
||||
0x10, // Comma
|
||||
0x00, // Minus
|
||||
0x36, // Period
|
||||
0x37, // '/'
|
||||
0x34, // '<27>'
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x2D, // ')'
|
||||
0x32, // '\'
|
||||
0x2F, // '^'
|
||||
0x00, // '<27>'
|
||||
0x38, // '!'
|
||||
0x00, // Nothing interesting past this point.
|
||||
|
||||
};
|
@ -1,133 +1,133 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "DSPAnalyzer.h"
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPTables.h"
|
||||
#include "DSPMemoryMap.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
// Holds data about all instructions in RAM.
|
||||
u8 code_flags[ISPACE];
|
||||
|
||||
// Good candidates for idle skipping is mail wait loops. If we're time slicing
|
||||
// between the main CPU and the DSP, if the DSP runs into one of these, it might
|
||||
// as well give up its time slice immediately, after executing once.
|
||||
|
||||
// Max signature length is 6. A 0 in a signature is ignored.
|
||||
#define NUM_IDLE_SIGS 5
|
||||
#define MAX_IDLE_SIG_SIZE 6
|
||||
|
||||
// 0xFFFF means ignore.
|
||||
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
||||
{
|
||||
// From AX:
|
||||
{ 0x26fc, // LRS $30, @DMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x27fc, // LRS $31, @DMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x26fe, // LRS $30, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
{ 0x27fe, // LRS $31, @CMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
|
||||
// From Zelda:
|
||||
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x05cf
|
||||
0 }
|
||||
};
|
||||
|
||||
void Reset()
|
||||
{
|
||||
memset(code_flags, 0, sizeof(code_flags));
|
||||
}
|
||||
|
||||
void AnalyzeRange(int start_addr, int end_addr)
|
||||
{
|
||||
// First we run an extremely simplified version of a disassembler to find
|
||||
// where all instructions start.
|
||||
|
||||
// This may not be 100% accurate in case of jump tables!
|
||||
// It could get desynced, which would be bad. We'll see if that's an issue.
|
||||
int addr = start_addr;
|
||||
while (addr < end_addr)
|
||||
{
|
||||
UDSPInstruction inst = dsp_imem_read(addr);
|
||||
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
|
||||
if (!opcode)
|
||||
{
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
code_flags[addr] |= CODE_START_OF_INST;
|
||||
addr += opcode->size;
|
||||
|
||||
// Look for loops.
|
||||
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
|
||||
// BLOOP, BLOOPI
|
||||
u16 loop_end = dsp_imem_read(addr + 1);
|
||||
code_flags[loop_end] |= CODE_LOOP_END;
|
||||
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
|
||||
// LOOP, LOOPI
|
||||
code_flags[addr + 1] |= CODE_LOOP_END;
|
||||
}
|
||||
}
|
||||
|
||||
// Next, we'll scan for potential idle skips.
|
||||
for (int s = 0; s < NUM_IDLE_SIGS; s++)
|
||||
{
|
||||
for (int addr = start_addr; addr < end_addr; addr++)
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
|
||||
{
|
||||
if (idle_skip_sigs[s][i] == 0)
|
||||
found = true;
|
||||
if (idle_skip_sigs[s][i] == 0xFFFF)
|
||||
continue;
|
||||
if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
|
||||
break;
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
|
||||
code_flags[addr] |= CODE_IDLE_SKIP;
|
||||
// TODO: actually use this flag somewhere.
|
||||
}
|
||||
}
|
||||
}
|
||||
NOTICE_LOG(DSPLLE, "Finished analysis.");
|
||||
}
|
||||
|
||||
void Analyze()
|
||||
{
|
||||
Reset();
|
||||
AnalyzeRange(0x0000, 0x1000); // IRAM
|
||||
AnalyzeRange(0x8000, 0x9000); // IROM
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "DSPAnalyzer.h"
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPTables.h"
|
||||
#include "DSPMemoryMap.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
// Holds data about all instructions in RAM.
|
||||
u8 code_flags[ISPACE];
|
||||
|
||||
// Good candidates for idle skipping is mail wait loops. If we're time slicing
|
||||
// between the main CPU and the DSP, if the DSP runs into one of these, it might
|
||||
// as well give up its time slice immediately, after executing once.
|
||||
|
||||
// Max signature length is 6. A 0 in a signature is ignored.
|
||||
#define NUM_IDLE_SIGS 5
|
||||
#define MAX_IDLE_SIG_SIZE 6
|
||||
|
||||
// 0xFFFF means ignore.
|
||||
const u16 idle_skip_sigs[NUM_IDLE_SIGS][MAX_IDLE_SIG_SIZE + 1] =
|
||||
{
|
||||
// From AX:
|
||||
{ 0x26fc, // LRS $30, @DMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x27fc, // LRS $31, @DMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029d, 0xFFFF, // JLZ 0x027a
|
||||
0, 0 }, // RET
|
||||
{ 0x26fe, // LRS $30, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $30, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
{ 0x27fe, // LRS $31, @CMBH
|
||||
0x03c0, 0x8000, // ANDCF $31, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x0280
|
||||
0, 0 }, // RET
|
||||
|
||||
// From Zelda:
|
||||
{ 0x00de, 0xFFFE, // LR $AC0.M, @CMBH
|
||||
0x02c0, 0x8000, // ANDCF $AC0.M, #0x8000
|
||||
0x029c, 0xFFFF, // JLNZ 0x05cf
|
||||
0 }
|
||||
};
|
||||
|
||||
void Reset()
|
||||
{
|
||||
memset(code_flags, 0, sizeof(code_flags));
|
||||
}
|
||||
|
||||
void AnalyzeRange(int start_addr, int end_addr)
|
||||
{
|
||||
// First we run an extremely simplified version of a disassembler to find
|
||||
// where all instructions start.
|
||||
|
||||
// This may not be 100% accurate in case of jump tables!
|
||||
// It could get desynced, which would be bad. We'll see if that's an issue.
|
||||
int addr = start_addr;
|
||||
while (addr < end_addr)
|
||||
{
|
||||
UDSPInstruction inst = dsp_imem_read(addr);
|
||||
const DSPOPCTemplate *opcode = GetOpTemplate(inst);
|
||||
if (!opcode)
|
||||
{
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
code_flags[addr] |= CODE_START_OF_INST;
|
||||
addr += opcode->size;
|
||||
|
||||
// Look for loops.
|
||||
if ((inst.hex & 0xffe0) == 0x0060 || (inst.hex & 0xff00) == 0x1100) {
|
||||
// BLOOP, BLOOPI
|
||||
u16 loop_end = dsp_imem_read(addr + 1);
|
||||
code_flags[loop_end] |= CODE_LOOP_END;
|
||||
} else if ((inst.hex & 0xffe0) == 0x0040 || (inst.hex & 0xff00) == 0x1000) {
|
||||
// LOOP, LOOPI
|
||||
code_flags[addr + 1] |= CODE_LOOP_END;
|
||||
}
|
||||
}
|
||||
|
||||
// Next, we'll scan for potential idle skips.
|
||||
for (int s = 0; s < NUM_IDLE_SIGS; s++)
|
||||
{
|
||||
for (int addr = start_addr; addr < end_addr; addr++)
|
||||
{
|
||||
bool found = false;
|
||||
for (int i = 0; i < MAX_IDLE_SIG_SIZE + 1; i++)
|
||||
{
|
||||
if (idle_skip_sigs[s][i] == 0)
|
||||
found = true;
|
||||
if (idle_skip_sigs[s][i] == 0xFFFF)
|
||||
continue;
|
||||
if (idle_skip_sigs[s][i] != dsp_imem_read(addr + i))
|
||||
break;
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
NOTICE_LOG(DSPLLE, "Idle skip location found at %02x", addr);
|
||||
code_flags[addr] |= CODE_IDLE_SKIP;
|
||||
// TODO: actually use this flag somewhere.
|
||||
}
|
||||
}
|
||||
}
|
||||
NOTICE_LOG(DSPLLE, "Finished analysis.");
|
||||
}
|
||||
|
||||
void Analyze()
|
||||
{
|
||||
Reset();
|
||||
AnalyzeRange(0x0000, 0x1000); // IRAM
|
||||
AnalyzeRange(0x8000, 0x9000); // IROM
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1,49 +1,49 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Basic code analysis.
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
#define ISPACE 65536
|
||||
|
||||
// Useful things to detect:
|
||||
// * Loop endpoints - so that we can avoid checking for loops every cycle.
|
||||
|
||||
enum
|
||||
{
|
||||
CODE_START_OF_INST = 1,
|
||||
CODE_IDLE_SKIP = 2,
|
||||
CODE_LOOP_END = 4,
|
||||
};
|
||||
|
||||
// Easy to query array covering the whole of instruction memory.
|
||||
// Just index by address.
|
||||
// This one will be helpful for debuggers and jits.
|
||||
extern u8 code_flags[ISPACE];
|
||||
|
||||
// This one should be called every time IRAM changes - which is basically
|
||||
// every time that a new ucode gets uploaded, and never else. At that point,
|
||||
// we can do as much static analysis as we want - but we should always throw
|
||||
// all old analysis away. Luckily the entire address space is only 64K code
|
||||
// words and the actual code space 8K instructions in total, so we can do
|
||||
// some pretty expensive analysis if necessary.
|
||||
void Analyze();
|
||||
|
||||
} // namespace
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Basic code analysis.
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
namespace DSPAnalyzer {
|
||||
|
||||
#define ISPACE 65536
|
||||
|
||||
// Useful things to detect:
|
||||
// * Loop endpoints - so that we can avoid checking for loops every cycle.
|
||||
|
||||
enum
|
||||
{
|
||||
CODE_START_OF_INST = 1,
|
||||
CODE_IDLE_SKIP = 2,
|
||||
CODE_LOOP_END = 4,
|
||||
};
|
||||
|
||||
// Easy to query array covering the whole of instruction memory.
|
||||
// Just index by address.
|
||||
// This one will be helpful for debuggers and jits.
|
||||
extern u8 code_flags[ISPACE];
|
||||
|
||||
// This one should be called every time IRAM changes - which is basically
|
||||
// every time that a new ucode gets uploaded, and never else. At that point,
|
||||
// we can do as much static analysis as we want - but we should always throw
|
||||
// all old analysis away. Luckily the entire address space is only 64K code
|
||||
// words and the actual code space 8K instructions in total, so we can do
|
||||
// some pretty expensive analysis if necessary.
|
||||
void Analyze();
|
||||
|
||||
} // namespace
|
||||
|
@ -1,19 +1,19 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "DSPBreakpoints.h"
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "DSPBreakpoints.h"
|
||||
|
||||
|
@ -1,63 +1,63 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSP_BREAKPOINTS
|
||||
#define _DSP_BREAKPOINTS
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// super fast breakpoints for a limited range.
|
||||
// To be used interchangably with the BreakPoints class.
|
||||
class DSPBreakpoints
|
||||
{
|
||||
public:
|
||||
DSPBreakpoints() {Clear();}
|
||||
// is address breakpoint
|
||||
bool IsAddressBreakPoint(u32 addr) {
|
||||
return b[addr] != 0;
|
||||
}
|
||||
|
||||
// AddBreakPoint
|
||||
bool Add(u32 addr, bool temp=false) {
|
||||
bool was_one = b[addr] != 0;
|
||||
if (!was_one) {
|
||||
b[addr] = temp ? 2 : 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Remove Breakpoint
|
||||
bool Remove(u32 addr) {
|
||||
bool was_one = b[addr] != 0;
|
||||
b[addr] = 0;
|
||||
return was_one;
|
||||
}
|
||||
void Clear() {
|
||||
for (int i = 0; i < 65536; i++)
|
||||
b[i] = 0;
|
||||
}
|
||||
|
||||
void DeleteByAddress(u32 addr) {
|
||||
b[addr] = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
u8 b[65536];
|
||||
};
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSP_BREAKPOINTS
|
||||
#define _DSP_BREAKPOINTS
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// super fast breakpoints for a limited range.
|
||||
// To be used interchangably with the BreakPoints class.
|
||||
class DSPBreakpoints
|
||||
{
|
||||
public:
|
||||
DSPBreakpoints() {Clear();}
|
||||
// is address breakpoint
|
||||
bool IsAddressBreakPoint(u32 addr) {
|
||||
return b[addr] != 0;
|
||||
}
|
||||
|
||||
// AddBreakPoint
|
||||
bool Add(u32 addr, bool temp=false) {
|
||||
bool was_one = b[addr] != 0;
|
||||
if (!was_one) {
|
||||
b[addr] = temp ? 2 : 1;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Remove Breakpoint
|
||||
bool Remove(u32 addr) {
|
||||
bool was_one = b[addr] != 0;
|
||||
b[addr] = 0;
|
||||
return was_one;
|
||||
}
|
||||
void Clear() {
|
||||
for (int i = 0; i < 65536; i++)
|
||||
b[i] = 0;
|
||||
}
|
||||
|
||||
void DeleteByAddress(u32 addr) {
|
||||
b[addr] = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
u8 b[65536];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,235 +1,235 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "StringUtil.h"
|
||||
#include "DSPCodeUtil.h"
|
||||
#include "assemble.h"
|
||||
#include "disassemble.h"
|
||||
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> &code)
|
||||
{
|
||||
AssemblerSettings settings;
|
||||
settings.pc = 0;
|
||||
// settings.decode_registers = false;
|
||||
// settings.decode_names = false;
|
||||
settings.print_tabs = false;
|
||||
settings.ext_separator = '\'';
|
||||
|
||||
// TODO: fix the terrible api of the assembler.
|
||||
DSPAssembler assembler(settings);
|
||||
if (!assembler.Assemble(text, code)) {
|
||||
std::cerr << assembler.GetErrorString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
|
||||
{
|
||||
if (code.empty())
|
||||
return false;
|
||||
|
||||
AssemblerSettings settings;
|
||||
|
||||
// These two prevent roundtripping.
|
||||
settings.show_hex = false;
|
||||
settings.show_pc = line_numbers;
|
||||
settings.ext_separator = '\'';
|
||||
settings.decode_names = false;
|
||||
settings.decode_registers = true;
|
||||
|
||||
DSPDisassembler disasm(settings);
|
||||
bool success = disasm.Disassemble(0, code, 0x0000, text);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
|
||||
{
|
||||
if (code1.size() != code2.size())
|
||||
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
|
||||
u32 count_equal = 0;
|
||||
const int min_size = (int)std::min(code1.size(), code2.size());
|
||||
|
||||
AssemblerSettings settings;
|
||||
DSPDisassembler disassembler(settings);
|
||||
for (int i = 0; i < min_size; i++)
|
||||
{
|
||||
if (code1[i] == code2[i])
|
||||
count_equal++;
|
||||
else
|
||||
{
|
||||
std::string line1, line2;
|
||||
u16 pc = i;
|
||||
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
|
||||
pc = i;
|
||||
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
|
||||
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
|
||||
}
|
||||
}
|
||||
if (code2.size() != code1.size())
|
||||
{
|
||||
printf("Extra code words:\n");
|
||||
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
|
||||
for (int i = min_size; i < (int)longest.size(); i++)
|
||||
{
|
||||
u16 pc = i;
|
||||
std::string line;
|
||||
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
|
||||
printf("!! %s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
|
||||
return code1.size() == code2.size() && code1.size() == count_equal;
|
||||
}
|
||||
|
||||
void GenRandomCode(int size, std::vector<u16> &code)
|
||||
{
|
||||
code.resize(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
code[i] = rand() ^ (rand() << 8);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||
const char *name, std::string &header)
|
||||
{
|
||||
std::vector<u16> code_copy = code;
|
||||
// Add some nops at the end to align the size a bit.
|
||||
while (code_copy.size() & 7)
|
||||
code_copy.push_back(0);
|
||||
char buffer[1024];
|
||||
header.clear();
|
||||
header.reserve(code.size() * 4);
|
||||
header.append("#define NUM_UCODES 1\n\n");
|
||||
std::string filename;
|
||||
SplitPath(_filename, NULL, &filename, NULL);
|
||||
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
|
||||
header.append("#ifndef _MSCVER\n");
|
||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
|
||||
header.append("#else\n");
|
||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||
header.append("#endif\n\n");
|
||||
|
||||
header.append("\t{\n\t\t");
|
||||
for (u32 j = 0; j < code.size(); j++)
|
||||
{
|
||||
if (j && ((j & 15) == 0))
|
||||
header.append("\n\t\t");
|
||||
sprintf(buffer, "0x%04x, ", code[j]);
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("\n\t},\n");
|
||||
|
||||
header.append("};\n");
|
||||
}
|
||||
|
||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
|
||||
int numCodes, const char *name, std::string &header)
|
||||
{
|
||||
char buffer[1024];
|
||||
int reserveSize = 0;
|
||||
for(int i = 0; i < numCodes; i++)
|
||||
reserveSize += (int)codes[i].size();
|
||||
|
||||
|
||||
header.clear();
|
||||
header.reserve(reserveSize * 4);
|
||||
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
|
||||
header.append(buffer);
|
||||
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
|
||||
for (int i = 0; i < numCodes; i++)
|
||||
{
|
||||
std::string filename;
|
||||
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
|
||||
filename = filenames->at(i);
|
||||
sprintf(buffer, "\t\"%s\",\n", filename.c_str());
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("};\n\n");
|
||||
header.append("#ifndef _MSCVER\n");
|
||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
|
||||
header.append("#else\n");
|
||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||
header.append("#endif\n\n");
|
||||
|
||||
for(int i = 0; i < numCodes; i++) {
|
||||
if(codes[i].size() == 0)
|
||||
continue;
|
||||
|
||||
std::vector<u16> code_copy = codes[i];
|
||||
// Add some nops at the end to align the size a bit.
|
||||
while (code_copy.size() & 7)
|
||||
code_copy.push_back(0);
|
||||
|
||||
header.append("\t{\n\t\t");
|
||||
for (u32 j = 0; j < codes[i].size(); j++)
|
||||
{
|
||||
if (j && ((j & 15) == 0))
|
||||
header.append("\n\t\t");
|
||||
sprintf(buffer, "0x%04x, ", codes[i][j]);
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("\n\t},\n");
|
||||
}
|
||||
header.append("};\n");
|
||||
}
|
||||
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
|
||||
{
|
||||
str.resize(code.size() * 2);
|
||||
for (int i = 0; i < (int)code.size(); i++)
|
||||
{
|
||||
str[i * 2 + 0] = code[i] >> 8;
|
||||
str[i * 2 + 1] = code[i] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
|
||||
{
|
||||
code.resize(str.size() / 2);
|
||||
for (int i = 0; i < (int)code.size(); i++)
|
||||
{
|
||||
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadBinary(const char *filename, std::vector<u16> &code)
|
||||
{
|
||||
std::string buffer;
|
||||
if (!File::ReadFileToString(false, filename, buffer))
|
||||
return false;
|
||||
|
||||
BinaryStringBEToCode(buffer, code);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename)
|
||||
{
|
||||
std::string buffer;
|
||||
CodeToBinaryStringBE(code, buffer);
|
||||
if (!File::WriteStringToFile(false, buffer, filename))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
#include "FileUtil.h"
|
||||
#include "StringUtil.h"
|
||||
#include "DSPCodeUtil.h"
|
||||
#include "assemble.h"
|
||||
#include "disassemble.h"
|
||||
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> &code)
|
||||
{
|
||||
AssemblerSettings settings;
|
||||
settings.pc = 0;
|
||||
// settings.decode_registers = false;
|
||||
// settings.decode_names = false;
|
||||
settings.print_tabs = false;
|
||||
settings.ext_separator = '\'';
|
||||
|
||||
// TODO: fix the terrible api of the assembler.
|
||||
DSPAssembler assembler(settings);
|
||||
if (!assembler.Assemble(text, code)) {
|
||||
std::cerr << assembler.GetErrorString() << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text)
|
||||
{
|
||||
if (code.empty())
|
||||
return false;
|
||||
|
||||
AssemblerSettings settings;
|
||||
|
||||
// These two prevent roundtripping.
|
||||
settings.show_hex = false;
|
||||
settings.show_pc = line_numbers;
|
||||
settings.ext_separator = '\'';
|
||||
settings.decode_names = false;
|
||||
settings.decode_registers = true;
|
||||
|
||||
DSPDisassembler disasm(settings);
|
||||
bool success = disasm.Disassemble(0, code, 0x0000, text);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2)
|
||||
{
|
||||
if (code1.size() != code2.size())
|
||||
printf("Size difference! 1=%i 2=%i\n", (int)code1.size(), (int)code2.size());
|
||||
u32 count_equal = 0;
|
||||
const int min_size = (int)std::min(code1.size(), code2.size());
|
||||
|
||||
AssemblerSettings settings;
|
||||
DSPDisassembler disassembler(settings);
|
||||
for (int i = 0; i < min_size; i++)
|
||||
{
|
||||
if (code1[i] == code2[i])
|
||||
count_equal++;
|
||||
else
|
||||
{
|
||||
std::string line1, line2;
|
||||
u16 pc = i;
|
||||
disassembler.DisOpcode(&code1[0], 0x0000, 2, &pc, line1);
|
||||
pc = i;
|
||||
disassembler.DisOpcode(&code2[0], 0x0000, 2, &pc, line2);
|
||||
printf("!! %04x : %04x vs %04x - %s vs %s\n", i, code1[i], code2[i], line1.c_str(), line2.c_str());
|
||||
}
|
||||
}
|
||||
if (code2.size() != code1.size())
|
||||
{
|
||||
printf("Extra code words:\n");
|
||||
const std::vector<u16> &longest = code1.size() > code2.size() ? code1 : code2;
|
||||
for (int i = min_size; i < (int)longest.size(); i++)
|
||||
{
|
||||
u16 pc = i;
|
||||
std::string line;
|
||||
disassembler.DisOpcode(&longest[0], 0x0000, 2, &pc, line);
|
||||
printf("!! %s\n", line.c_str());
|
||||
}
|
||||
}
|
||||
printf("Equal instruction words: %i / %i\n", count_equal, min_size);
|
||||
return code1.size() == code2.size() && code1.size() == count_equal;
|
||||
}
|
||||
|
||||
void GenRandomCode(int size, std::vector<u16> &code)
|
||||
{
|
||||
code.resize(size);
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
code[i] = rand() ^ (rand() << 8);
|
||||
}
|
||||
}
|
||||
|
||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||
const char *name, std::string &header)
|
||||
{
|
||||
std::vector<u16> code_copy = code;
|
||||
// Add some nops at the end to align the size a bit.
|
||||
while (code_copy.size() & 7)
|
||||
code_copy.push_back(0);
|
||||
char buffer[1024];
|
||||
header.clear();
|
||||
header.reserve(code.size() * 4);
|
||||
header.append("#define NUM_UCODES 1\n\n");
|
||||
std::string filename;
|
||||
SplitPath(_filename, NULL, &filename, NULL);
|
||||
header.append(StringFromFormat("const char* UCODE_NAMES[NUM_UCODES] = {\"%s\"};\n\n", filename.c_str()));
|
||||
header.append("#ifndef _MSCVER\n");
|
||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n");
|
||||
header.append("#else\n");
|
||||
header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||
header.append("#endif\n\n");
|
||||
|
||||
header.append("\t{\n\t\t");
|
||||
for (u32 j = 0; j < code.size(); j++)
|
||||
{
|
||||
if (j && ((j & 15) == 0))
|
||||
header.append("\n\t\t");
|
||||
sprintf(buffer, "0x%04x, ", code[j]);
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("\n\t},\n");
|
||||
|
||||
header.append("};\n");
|
||||
}
|
||||
|
||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string>* filenames,
|
||||
int numCodes, const char *name, std::string &header)
|
||||
{
|
||||
char buffer[1024];
|
||||
int reserveSize = 0;
|
||||
for(int i = 0; i < numCodes; i++)
|
||||
reserveSize += (int)codes[i].size();
|
||||
|
||||
|
||||
header.clear();
|
||||
header.reserve(reserveSize * 4);
|
||||
sprintf(buffer, "#define NUM_UCODES %d\n\n", numCodes);
|
||||
header.append(buffer);
|
||||
header.append("const char* UCODE_NAMES[NUM_UCODES] = {\n");
|
||||
for (int i = 0; i < numCodes; i++)
|
||||
{
|
||||
std::string filename;
|
||||
if (! SplitPath(filenames->at(i), NULL, &filename, NULL))
|
||||
filename = filenames->at(i);
|
||||
sprintf(buffer, "\t\"%s\",\n", filename.c_str());
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("};\n\n");
|
||||
header.append("#ifndef _MSCVER\n");
|
||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] = {\n");
|
||||
header.append("#else\n");
|
||||
header.append("const unsigned short dsp_ucode[NUM_UCODES][0x1000] __attribute__ ((aligned (64))) = {\n");
|
||||
header.append("#endif\n\n");
|
||||
|
||||
for(int i = 0; i < numCodes; i++) {
|
||||
if(codes[i].size() == 0)
|
||||
continue;
|
||||
|
||||
std::vector<u16> code_copy = codes[i];
|
||||
// Add some nops at the end to align the size a bit.
|
||||
while (code_copy.size() & 7)
|
||||
code_copy.push_back(0);
|
||||
|
||||
header.append("\t{\n\t\t");
|
||||
for (u32 j = 0; j < codes[i].size(); j++)
|
||||
{
|
||||
if (j && ((j & 15) == 0))
|
||||
header.append("\n\t\t");
|
||||
sprintf(buffer, "0x%04x, ", codes[i][j]);
|
||||
header.append(buffer);
|
||||
}
|
||||
header.append("\n\t},\n");
|
||||
}
|
||||
header.append("};\n");
|
||||
}
|
||||
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str)
|
||||
{
|
||||
str.resize(code.size() * 2);
|
||||
for (int i = 0; i < (int)code.size(); i++)
|
||||
{
|
||||
str[i * 2 + 0] = code[i] >> 8;
|
||||
str[i * 2 + 1] = code[i] & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code)
|
||||
{
|
||||
code.resize(str.size() / 2);
|
||||
for (int i = 0; i < (int)code.size(); i++)
|
||||
{
|
||||
code[i] = ((u16)(u8)str[i * 2 + 0] << 8) | ((u16)(u8)str[i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
bool LoadBinary(const char *filename, std::vector<u16> &code)
|
||||
{
|
||||
std::string buffer;
|
||||
if (!File::ReadFileToString(false, filename, buffer))
|
||||
return false;
|
||||
|
||||
BinaryStringBEToCode(buffer, code);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename)
|
||||
{
|
||||
std::string buffer;
|
||||
CodeToBinaryStringBE(code, buffer);
|
||||
if (!File::WriteStringToFile(false, buffer, filename))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1,43 +1,43 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPCODEUTIL_H
|
||||
#define _DSPCODEUTIL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> &code);
|
||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
|
||||
void GenRandomCode(int size, std::vector<u16> &code);
|
||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||
const char *name, std::string &header);
|
||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
|
||||
int numCodes, const char *name, std::string &header);
|
||||
|
||||
// Big-endian, for writing straight to file using File::WriteStringToFile.
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
|
||||
|
||||
// Load code (big endian binary).
|
||||
bool LoadBinary(const char *filename, std::vector<u16> &code);
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename);
|
||||
|
||||
#endif // _DSPCODEUTIL_H
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPCODEUTIL_H
|
||||
#define _DSPCODEUTIL_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
bool Assemble(const char *text, std::vector<u16> &code);
|
||||
bool Disassemble(const std::vector<u16> &code, bool line_numbers, std::string &text);
|
||||
bool Compare(const std::vector<u16> &code1, const std::vector<u16> &code2);
|
||||
void GenRandomCode(int size, std::vector<u16> &code);
|
||||
void CodeToHeader(const std::vector<u16> &code, std::string _filename,
|
||||
const char *name, std::string &header);
|
||||
void CodesToHeader(const std::vector<u16> *codes, const std::vector<std::string> *filenames,
|
||||
int numCodes, const char *name, std::string &header);
|
||||
|
||||
// Big-endian, for writing straight to file using File::WriteStringToFile.
|
||||
void CodeToBinaryStringBE(const std::vector<u16> &code, std::string &str);
|
||||
void BinaryStringBEToCode(const std::string &str, std::vector<u16> &code);
|
||||
|
||||
// Load code (big endian binary).
|
||||
bool LoadBinary(const char *filename, std::vector<u16> &code);
|
||||
bool SaveBinary(const std::vector<u16> &code, const char *filename);
|
||||
|
||||
#endif // _DSPCODEUTIL_H
|
||||
|
@ -1,256 +1,256 @@
|
||||
/*====================================================================
|
||||
|
||||
filename: gdsp_interpreter.cpp
|
||||
project: GCemu
|
||||
created: 2004-6-18
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie & Tratax
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Thread.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPHost.h"
|
||||
#include "DSPAnalyzer.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#include "DSPHWInterface.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
SDSP g_dsp;
|
||||
DSPBreakpoints dsp_breakpoints;
|
||||
DSPCoreState core_state = DSPCORE_RUNNING;
|
||||
Common::Event step_event;
|
||||
|
||||
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
|
||||
{
|
||||
FILE *pFile = fopen(fname, "rb");
|
||||
const size_t size_in_bytes = size_in_words * sizeof(u16);
|
||||
if (pFile)
|
||||
{
|
||||
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
|
||||
if (read_bytes != size_in_bytes)
|
||||
{
|
||||
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
fclose(pFile);
|
||||
|
||||
// Byteswap the rom.
|
||||
for (int i = 0; i < DSP_IROM_SIZE; i++)
|
||||
rom[i] = Common::swap16(rom[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Always keep ROMs write protected.
|
||||
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
|
||||
{
|
||||
g_dsp.step_counter = 0;
|
||||
|
||||
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
|
||||
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
|
||||
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
|
||||
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
|
||||
|
||||
// Fill roms with zeros.
|
||||
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
|
||||
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
|
||||
|
||||
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
|
||||
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
|
||||
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
g_dsp.r[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
g_dsp.reg_stack_ptr[i] = 0;
|
||||
for (int j = 0; j < DSP_STACK_DEPTH; j++)
|
||||
{
|
||||
g_dsp.reg_stack[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill IRAM with HALT opcodes.
|
||||
for (int i = 0; i < DSP_IRAM_SIZE; i++)
|
||||
{
|
||||
g_dsp.iram[i] = 0x0021; // HALT opcode
|
||||
}
|
||||
|
||||
// Just zero out DRAM.
|
||||
for (int i = 0; i < DSP_DRAM_SIZE; i++)
|
||||
{
|
||||
g_dsp.dram[i] = 0;
|
||||
}
|
||||
|
||||
// Copied from a real console after the custom UCode has been loaded.
|
||||
// These are the indexing wrapping registers.
|
||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||
|
||||
g_dsp.cr = 0x804;
|
||||
gdsp_ifx_init();
|
||||
|
||||
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
|
||||
// in new ucodes.
|
||||
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
|
||||
DSPAnalyzer::Analyze();
|
||||
|
||||
step_event.Init();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSPCore_Shutdown()
|
||||
{
|
||||
step_event.Shutdown();
|
||||
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
|
||||
}
|
||||
|
||||
void DSPCore_Reset()
|
||||
{
|
||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
|
||||
g_dsp.pc = DSP_RESET_VECTOR;
|
||||
g_dsp.exception_in_progress_hack = false;
|
||||
|
||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||
|
||||
}
|
||||
|
||||
void DSPCore_SetException(u8 level)
|
||||
{
|
||||
g_dsp.exceptions |= 1 << level;
|
||||
}
|
||||
|
||||
void DSPCore_CheckExternalInterrupt()
|
||||
{
|
||||
// check if there is an external interrupt
|
||||
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
|
||||
{
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "trying External interupt fired");
|
||||
#endif
|
||||
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
|
||||
{
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "External interupt fired");
|
||||
#endif
|
||||
// level 7 is the interrupt exception
|
||||
DSPCore_SetException(EXP_INT);
|
||||
|
||||
g_dsp.cr &= ~CR_EXTERNAL_INT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSPCore_CheckExceptions()
|
||||
{
|
||||
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
|
||||
#endif
|
||||
// check exceptions
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// Seems 7 must pass or zelda dies
|
||||
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
|
||||
if (g_dsp.exceptions & (1 << i)) {
|
||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
|
||||
|
||||
g_dsp.pc = i * 2;
|
||||
g_dsp.exceptions &= ~(1 << i);
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "exception %d fired");
|
||||
#endif
|
||||
g_dsp.exception_in_progress_hack = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delegate to JIT (when it is written) or interpreter as appropriate.
|
||||
// Handle state changes and stepping.
|
||||
int DSPCore_RunCycles(int cycles)
|
||||
{
|
||||
while (cycles > 0) {
|
||||
reswitch:
|
||||
switch (core_state)
|
||||
{
|
||||
case DSPCORE_RUNNING:
|
||||
#if 1 // Set to 0 to disable breakpoints, for a speed boost.
|
||||
cycles = DSPInterpreter::RunCyclesDebug(cycles);
|
||||
#else
|
||||
cycles = DSPInterpreter::RunCycles(cycles);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DSPCORE_STEPPING:
|
||||
step_event.Wait();
|
||||
if (core_state != DSPCORE_STEPPING)
|
||||
goto reswitch;
|
||||
|
||||
DSPInterpreter::Step();
|
||||
cycles--;
|
||||
|
||||
DSPHost_UpdateDebugger();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cycles;
|
||||
}
|
||||
|
||||
void DSPCore_SetState(DSPCoreState new_state)
|
||||
{
|
||||
core_state = new_state;
|
||||
// kick the event, in case we are waiting
|
||||
if (new_state == DSPCORE_RUNNING)
|
||||
step_event.Set();
|
||||
// Sleep(10);
|
||||
DSPHost_UpdateDebugger();
|
||||
}
|
||||
|
||||
DSPCoreState DSPCore_GetState()
|
||||
{
|
||||
return core_state;
|
||||
}
|
||||
|
||||
void DSPCore_Step()
|
||||
{
|
||||
if (core_state == DSPCORE_STEPPING)
|
||||
step_event.Set();
|
||||
}
|
||||
/*====================================================================
|
||||
|
||||
filename: gdsp_interpreter.cpp
|
||||
project: GCemu
|
||||
created: 2004-6-18
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie & Tratax
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Thread.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPHost.h"
|
||||
#include "DSPAnalyzer.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#include "DSPHWInterface.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
SDSP g_dsp;
|
||||
DSPBreakpoints dsp_breakpoints;
|
||||
DSPCoreState core_state = DSPCORE_RUNNING;
|
||||
Common::Event step_event;
|
||||
|
||||
static bool LoadRom(const char *fname, int size_in_words, u16 *rom)
|
||||
{
|
||||
FILE *pFile = fopen(fname, "rb");
|
||||
const size_t size_in_bytes = size_in_words * sizeof(u16);
|
||||
if (pFile)
|
||||
{
|
||||
size_t read_bytes = fread(rom, 1, size_in_bytes, pFile);
|
||||
if (read_bytes != size_in_bytes)
|
||||
{
|
||||
PanicAlert("ROM %s too short : %i/%i", fname, (int)read_bytes, (int)size_in_bytes);
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
fclose(pFile);
|
||||
|
||||
// Byteswap the rom.
|
||||
for (int i = 0; i < DSP_IROM_SIZE; i++)
|
||||
rom[i] = Common::swap16(rom[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
// Always keep ROMs write protected.
|
||||
WriteProtectMemory(g_dsp.irom, size_in_bytes, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename)
|
||||
{
|
||||
g_dsp.step_counter = 0;
|
||||
|
||||
g_dsp.irom = (u16*)AllocateMemoryPages(DSP_IROM_BYTE_SIZE);
|
||||
g_dsp.iram = (u16*)AllocateMemoryPages(DSP_IRAM_BYTE_SIZE);
|
||||
g_dsp.dram = (u16*)AllocateMemoryPages(DSP_DRAM_BYTE_SIZE);
|
||||
g_dsp.coef = (u16*)AllocateMemoryPages(DSP_COEF_BYTE_SIZE);
|
||||
|
||||
// Fill roms with zeros.
|
||||
memset(g_dsp.irom, 0, DSP_IROM_BYTE_SIZE);
|
||||
memset(g_dsp.coef, 0, DSP_COEF_BYTE_SIZE);
|
||||
|
||||
// Try to load real ROM contents. Failing this, only homebrew will work correctly with the DSP.
|
||||
LoadRom(irom_filename, DSP_IROM_SIZE, g_dsp.irom);
|
||||
LoadRom(coef_filename, DSP_COEF_SIZE, g_dsp.coef);
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
g_dsp.r[i] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
g_dsp.reg_stack_ptr[i] = 0;
|
||||
for (int j = 0; j < DSP_STACK_DEPTH; j++)
|
||||
{
|
||||
g_dsp.reg_stack[i][j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill IRAM with HALT opcodes.
|
||||
for (int i = 0; i < DSP_IRAM_SIZE; i++)
|
||||
{
|
||||
g_dsp.iram[i] = 0x0021; // HALT opcode
|
||||
}
|
||||
|
||||
// Just zero out DRAM.
|
||||
for (int i = 0; i < DSP_DRAM_SIZE; i++)
|
||||
{
|
||||
g_dsp.dram[i] = 0;
|
||||
}
|
||||
|
||||
// Copied from a real console after the custom UCode has been loaded.
|
||||
// These are the indexing wrapping registers.
|
||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||
|
||||
g_dsp.cr = 0x804;
|
||||
gdsp_ifx_init();
|
||||
|
||||
// Mostly keep IRAM write protected. We unprotect only when DMA-ing
|
||||
// in new ucodes.
|
||||
WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false);
|
||||
DSPAnalyzer::Analyze();
|
||||
|
||||
step_event.Init();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DSPCore_Shutdown()
|
||||
{
|
||||
step_event.Shutdown();
|
||||
FreeMemoryPages(g_dsp.irom, DSP_IROM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.iram, DSP_IRAM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.dram, DSP_DRAM_BYTE_SIZE);
|
||||
FreeMemoryPages(g_dsp.coef, DSP_COEF_BYTE_SIZE);
|
||||
}
|
||||
|
||||
void DSPCore_Reset()
|
||||
{
|
||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "reset while exception");
|
||||
g_dsp.pc = DSP_RESET_VECTOR;
|
||||
g_dsp.exception_in_progress_hack = false;
|
||||
|
||||
g_dsp.r[DSP_REG_WR0] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR1] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR2] = 0xffff;
|
||||
g_dsp.r[DSP_REG_WR3] = 0xffff;
|
||||
|
||||
}
|
||||
|
||||
void DSPCore_SetException(u8 level)
|
||||
{
|
||||
g_dsp.exceptions |= 1 << level;
|
||||
}
|
||||
|
||||
void DSPCore_CheckExternalInterrupt()
|
||||
{
|
||||
// check if there is an external interrupt
|
||||
if (g_dsp.cr & CR_EXTERNAL_INT && !g_dsp.exception_in_progress_hack)
|
||||
{
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "trying External interupt fired");
|
||||
#endif
|
||||
if (dsp_SR_is_flag_set(SR_EXT_INT_ENABLE))
|
||||
{
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "External interupt fired");
|
||||
#endif
|
||||
// level 7 is the interrupt exception
|
||||
DSPCore_SetException(EXP_INT);
|
||||
|
||||
g_dsp.cr &= ~CR_EXTERNAL_INT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DSPCore_CheckExceptions()
|
||||
{
|
||||
if (g_dsp.exceptions != 0 && !g_dsp.exception_in_progress_hack) {
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "trying exception %d fired", g_dsp.exceptions);
|
||||
#endif
|
||||
// check exceptions
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// Seems 7 must pass or zelda dies
|
||||
if (dsp_SR_is_flag_set(SR_INT_ENABLE) || i == EXP_INT) {
|
||||
if (g_dsp.exceptions & (1 << i)) {
|
||||
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
dsp_reg_store_stack(DSP_STACK_D, g_dsp.r[DSP_REG_SR]);
|
||||
|
||||
g_dsp.pc = i * 2;
|
||||
g_dsp.exceptions &= ~(1 << i);
|
||||
#ifdef DEBUG_EXP
|
||||
NOTICE_LOG(DSPLLE, "exception %d fired");
|
||||
#endif
|
||||
g_dsp.exception_in_progress_hack = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delegate to JIT (when it is written) or interpreter as appropriate.
|
||||
// Handle state changes and stepping.
|
||||
int DSPCore_RunCycles(int cycles)
|
||||
{
|
||||
while (cycles > 0) {
|
||||
reswitch:
|
||||
switch (core_state)
|
||||
{
|
||||
case DSPCORE_RUNNING:
|
||||
#if 1 // Set to 0 to disable breakpoints, for a speed boost.
|
||||
cycles = DSPInterpreter::RunCyclesDebug(cycles);
|
||||
#else
|
||||
cycles = DSPInterpreter::RunCycles(cycles);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case DSPCORE_STEPPING:
|
||||
step_event.Wait();
|
||||
if (core_state != DSPCORE_STEPPING)
|
||||
goto reswitch;
|
||||
|
||||
DSPInterpreter::Step();
|
||||
cycles--;
|
||||
|
||||
DSPHost_UpdateDebugger();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cycles;
|
||||
}
|
||||
|
||||
void DSPCore_SetState(DSPCoreState new_state)
|
||||
{
|
||||
core_state = new_state;
|
||||
// kick the event, in case we are waiting
|
||||
if (new_state == DSPCORE_RUNNING)
|
||||
step_event.Set();
|
||||
// Sleep(10);
|
||||
DSPHost_UpdateDebugger();
|
||||
}
|
||||
|
||||
DSPCoreState DSPCore_GetState()
|
||||
{
|
||||
return core_state;
|
||||
}
|
||||
|
||||
void DSPCore_Step()
|
||||
{
|
||||
if (core_state == DSPCORE_STEPPING)
|
||||
step_event.Set();
|
||||
}
|
||||
|
@ -1,240 +1,240 @@
|
||||
/*====================================================================
|
||||
|
||||
filename: DSPCore.h
|
||||
project: GCemu
|
||||
created: 2004-6-18
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie & Tratax
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#ifndef _DSPCORE_H
|
||||
#define _DSPCORE_H
|
||||
|
||||
#include "DSPBreakpoints.h"
|
||||
|
||||
#define DSP_IRAM_BYTE_SIZE 0x2000
|
||||
#define DSP_IRAM_SIZE 0x1000
|
||||
#define DSP_IRAM_MASK 0x0fff
|
||||
|
||||
#define DSP_IROM_BYTE_SIZE 0x2000
|
||||
#define DSP_IROM_SIZE 0x1000
|
||||
#define DSP_IROM_MASK 0x0fff
|
||||
|
||||
#define DSP_DRAM_BYTE_SIZE 0x2000
|
||||
#define DSP_DRAM_SIZE 0x1000
|
||||
#define DSP_DRAM_MASK 0x0fff
|
||||
|
||||
#define DSP_COEF_BYTE_SIZE 0x2000
|
||||
#define DSP_COEF_SIZE 0x1000
|
||||
#define DSP_COEF_MASK 0x0fff
|
||||
|
||||
#define DSP_RESET_VECTOR 0x8000
|
||||
|
||||
#define DSP_STACK_DEPTH 0x20
|
||||
#define DSP_STACK_MASK 0x1f
|
||||
|
||||
#define DSP_CR_IMEM 2
|
||||
#define DSP_CR_DMEM 0
|
||||
#define DSP_CR_TO_CPU 1
|
||||
#define DSP_CR_FROM_CPU 0
|
||||
|
||||
|
||||
// Register table taken from libasnd
|
||||
#define DSP_REG_AR0 0x00 // address registers
|
||||
#define DSP_REG_AR1 0x01
|
||||
#define DSP_REG_AR2 0x02
|
||||
#define DSP_REG_AR3 0x03
|
||||
|
||||
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
|
||||
#define DSP_REG_IX1 0x05
|
||||
#define DSP_REG_IX2 0x06
|
||||
#define DSP_REG_IX3 0x07
|
||||
|
||||
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
|
||||
#define DSP_REG_WR1 0x09
|
||||
#define DSP_REG_WR2 0x0a
|
||||
#define DSP_REG_WR3 0x0b
|
||||
|
||||
#define DSP_REG_ST0 0x0c // stacks.
|
||||
#define DSP_REG_ST1 0x0d
|
||||
#define DSP_REG_ST2 0x0e
|
||||
#define DSP_REG_ST3 0x0f
|
||||
|
||||
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
|
||||
#define DSP_REG_SR 0x13
|
||||
|
||||
#define DSP_REG_PRODL 0x14 // product.
|
||||
#define DSP_REG_PRODM 0x15
|
||||
#define DSP_REG_PRODH 0x16
|
||||
#define DSP_REG_PRODM2 0x17
|
||||
|
||||
#define DSP_REG_AXL0 0x18
|
||||
#define DSP_REG_AXL1 0x19
|
||||
#define DSP_REG_AXH0 0x1a
|
||||
#define DSP_REG_AXH1 0x1b
|
||||
|
||||
#define DSP_REG_ACC0 0x1c // accumulator (global)
|
||||
#define DSP_REG_ACC1 0x1d
|
||||
|
||||
#define DSP_REG_ACL0 0x1c // Low accumulator
|
||||
#define DSP_REG_ACL1 0x1d
|
||||
#define DSP_REG_ACM0 0x1e // Mid accumulator
|
||||
#define DSP_REG_ACM1 0x1f
|
||||
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
|
||||
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
|
||||
|
||||
// Hardware registers address
|
||||
|
||||
#define DSP_COEF_A1_0 0xa0
|
||||
|
||||
#define DSP_DSMAH 0xce
|
||||
#define DSP_DSMAL 0xcf
|
||||
#define DSP_DSCR 0xc9 // DSP DMA Control Reg
|
||||
#define DSP_DSPA 0xcd // DSP DMA Block Length
|
||||
#define DSP_DSBL 0xcb // DSP DMA DMEM Address
|
||||
#define DSP_DSMAH 0xce // DSP DMA Mem Address H
|
||||
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
|
||||
|
||||
#define DSP_FORMAT 0xd1
|
||||
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
|
||||
#define DSP_ACSAH 0xd4
|
||||
#define DSP_ACSAL 0xd5
|
||||
#define DSP_ACEAH 0xd6
|
||||
#define DSP_ACEAL 0xd7
|
||||
#define DSP_ACCAH 0xd8
|
||||
#define DSP_ACCAL 0xd9
|
||||
#define DSP_PRED_SCALE 0xda
|
||||
#define DSP_YN1 0xdb
|
||||
#define DSP_YN2 0xdc
|
||||
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
|
||||
#define DSP_GAIN 0xde
|
||||
|
||||
#define DSP_DIRQ 0xfb // DSP Irq Rest
|
||||
#define DSP_DMBH 0xfc // DSP Mailbox H
|
||||
#define DSP_DMBL 0xfd // DSP Mailbox L
|
||||
#define DSP_CMBH 0xfe // CPU Mailbox H
|
||||
#define DSP_CMBL 0xff // CPU Mailbox L
|
||||
|
||||
#define DMA_TO_DSP 0
|
||||
#define DMA_TO_CPU 1
|
||||
|
||||
// Stacks
|
||||
#define DSP_STACK_C 0
|
||||
#define DSP_STACK_D 1
|
||||
|
||||
// cr (Not g_dsp.r[CR]) bits
|
||||
// See HW/DSP.cpp.
|
||||
#define CR_HALT 0x0004
|
||||
#define CR_EXTERNAL_INT 0x0002
|
||||
|
||||
|
||||
// SR bits
|
||||
#define SR_CARRY 0x0001
|
||||
#define SR_2 0x0002 // overflow???
|
||||
#define SR_ARITH_ZERO 0x0004
|
||||
#define SR_SIGN 0x0008
|
||||
#define SR_10 0x0010 // seem to be set by tst
|
||||
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
|
||||
#define SR_LOGIC_ZERO 0x0040
|
||||
#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
|
||||
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
|
||||
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
|
||||
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
|
||||
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
|
||||
|
||||
// This should be the bits affected by CMP. Does not include logic zero.
|
||||
#define SR_CMP_MASK 0x3f
|
||||
|
||||
// exceptions vector
|
||||
#define EXP_RESET 0 // 0x0000
|
||||
#define EXP_STOVF 1 // 0x0002 stack under/over flow
|
||||
#define EXP_4 2 // 0x0004
|
||||
#define EXP_6 3 // 0x0006
|
||||
#define EXP_8 4 // 0x0008
|
||||
#define EXP_ACCOV 5 // 0x000a accelerator address overflow
|
||||
#define EXP_c 6 // 0x000c
|
||||
#define EXP_INT 7 // 0x000e external int? (mail?)
|
||||
|
||||
struct SDSP
|
||||
{
|
||||
u16 r[32];
|
||||
u16 pc;
|
||||
#if PROFILE
|
||||
u16 err_pc;
|
||||
#endif
|
||||
|
||||
// This is NOT the same cr as r[DSP_REG_CR].
|
||||
// This register is shared with the main emulation, see DSP.cpp
|
||||
// The plugin has control over 0x0C07 of this reg.
|
||||
// Bits are defined in a struct in DSP.cpp.
|
||||
u16 cr;
|
||||
|
||||
u8 reg_stack_ptr[4];
|
||||
u8 exceptions; // pending exceptions?
|
||||
bool exception_in_progress_hack; // is this the same as "exception enabled"?
|
||||
|
||||
// Let's make stack depth 32 for now. The real DSP has different depths
|
||||
// for the different stacks, but it would be strange if any ucode relied on stack
|
||||
// overflows since on the DSP, when the stack overflows, you're screwed.
|
||||
u16 reg_stack[4][DSP_STACK_DEPTH];
|
||||
|
||||
// For debugging.
|
||||
u32 iram_crc;
|
||||
u64 step_counter;
|
||||
|
||||
// When state saving, all of the above can just be memcpy'd into the save state.
|
||||
// The below needs special handling.
|
||||
u16 *iram;
|
||||
u16 *dram;
|
||||
u16 *irom;
|
||||
u16 *coef;
|
||||
|
||||
// This one doesn't really belong here.
|
||||
u8 *cpu_ram;
|
||||
};
|
||||
|
||||
extern SDSP g_dsp;
|
||||
extern DSPBreakpoints dsp_breakpoints;
|
||||
|
||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
|
||||
|
||||
void DSPCore_Reset();
|
||||
void DSPCore_Shutdown(); // Frees all allocated memory.
|
||||
|
||||
void DSPCore_CheckExternalInterrupt();
|
||||
void DSPCore_CheckExceptions();
|
||||
|
||||
// sets a flag in the pending exception register.
|
||||
void DSPCore_SetException(u8 level);
|
||||
|
||||
enum DSPCoreState
|
||||
{
|
||||
DSPCORE_RUNNING = 0,
|
||||
DSPCORE_STEPPING = 1,
|
||||
};
|
||||
|
||||
int DSPCore_RunCycles(int cycles);
|
||||
|
||||
// These are meant to be called from the UI thread.
|
||||
void DSPCore_SetState(DSPCoreState new_state);
|
||||
DSPCoreState DSPCore_GetState();
|
||||
|
||||
void DSPCore_Step();
|
||||
|
||||
#endif // _DSPCORE_H
|
||||
/*====================================================================
|
||||
|
||||
filename: DSPCore.h
|
||||
project: GCemu
|
||||
created: 2004-6-18
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie & Tratax
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#ifndef _DSPCORE_H
|
||||
#define _DSPCORE_H
|
||||
|
||||
#include "DSPBreakpoints.h"
|
||||
|
||||
#define DSP_IRAM_BYTE_SIZE 0x2000
|
||||
#define DSP_IRAM_SIZE 0x1000
|
||||
#define DSP_IRAM_MASK 0x0fff
|
||||
|
||||
#define DSP_IROM_BYTE_SIZE 0x2000
|
||||
#define DSP_IROM_SIZE 0x1000
|
||||
#define DSP_IROM_MASK 0x0fff
|
||||
|
||||
#define DSP_DRAM_BYTE_SIZE 0x2000
|
||||
#define DSP_DRAM_SIZE 0x1000
|
||||
#define DSP_DRAM_MASK 0x0fff
|
||||
|
||||
#define DSP_COEF_BYTE_SIZE 0x2000
|
||||
#define DSP_COEF_SIZE 0x1000
|
||||
#define DSP_COEF_MASK 0x0fff
|
||||
|
||||
#define DSP_RESET_VECTOR 0x8000
|
||||
|
||||
#define DSP_STACK_DEPTH 0x20
|
||||
#define DSP_STACK_MASK 0x1f
|
||||
|
||||
#define DSP_CR_IMEM 2
|
||||
#define DSP_CR_DMEM 0
|
||||
#define DSP_CR_TO_CPU 1
|
||||
#define DSP_CR_FROM_CPU 0
|
||||
|
||||
|
||||
// Register table taken from libasnd
|
||||
#define DSP_REG_AR0 0x00 // address registers
|
||||
#define DSP_REG_AR1 0x01
|
||||
#define DSP_REG_AR2 0x02
|
||||
#define DSP_REG_AR3 0x03
|
||||
|
||||
#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments)
|
||||
#define DSP_REG_IX1 0x05
|
||||
#define DSP_REG_IX2 0x06
|
||||
#define DSP_REG_IX3 0x07
|
||||
|
||||
#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used.
|
||||
#define DSP_REG_WR1 0x09
|
||||
#define DSP_REG_WR2 0x0a
|
||||
#define DSP_REG_WR3 0x0b
|
||||
|
||||
#define DSP_REG_ST0 0x0c // stacks.
|
||||
#define DSP_REG_ST1 0x0d
|
||||
#define DSP_REG_ST2 0x0e
|
||||
#define DSP_REG_ST3 0x0f
|
||||
|
||||
#define DSP_REG_CR 0x12 // Seems to be the top 8 bits of LRS/SRS.
|
||||
#define DSP_REG_SR 0x13
|
||||
|
||||
#define DSP_REG_PRODL 0x14 // product.
|
||||
#define DSP_REG_PRODM 0x15
|
||||
#define DSP_REG_PRODH 0x16
|
||||
#define DSP_REG_PRODM2 0x17
|
||||
|
||||
#define DSP_REG_AXL0 0x18
|
||||
#define DSP_REG_AXL1 0x19
|
||||
#define DSP_REG_AXH0 0x1a
|
||||
#define DSP_REG_AXH1 0x1b
|
||||
|
||||
#define DSP_REG_ACC0 0x1c // accumulator (global)
|
||||
#define DSP_REG_ACC1 0x1d
|
||||
|
||||
#define DSP_REG_ACL0 0x1c // Low accumulator
|
||||
#define DSP_REG_ACL1 0x1d
|
||||
#define DSP_REG_ACM0 0x1e // Mid accumulator
|
||||
#define DSP_REG_ACM1 0x1f
|
||||
#define DSP_REG_ACH0 0x10 // Sign extended 8 bit register 0
|
||||
#define DSP_REG_ACH1 0x11 // Sign extended 8 bit register 1
|
||||
|
||||
// Hardware registers address
|
||||
|
||||
#define DSP_COEF_A1_0 0xa0
|
||||
|
||||
#define DSP_DSMAH 0xce
|
||||
#define DSP_DSMAL 0xcf
|
||||
#define DSP_DSCR 0xc9 // DSP DMA Control Reg
|
||||
#define DSP_DSPA 0xcd // DSP DMA Block Length
|
||||
#define DSP_DSBL 0xcb // DSP DMA DMEM Address
|
||||
#define DSP_DSMAH 0xce // DSP DMA Mem Address H
|
||||
#define DSP_DSMAL 0xcf // DSP DMA Mem Address L
|
||||
|
||||
#define DSP_FORMAT 0xd1
|
||||
#define DSP_ACDATA1 0xd3 // used only by Zelda ucodes
|
||||
#define DSP_ACSAH 0xd4
|
||||
#define DSP_ACSAL 0xd5
|
||||
#define DSP_ACEAH 0xd6
|
||||
#define DSP_ACEAL 0xd7
|
||||
#define DSP_ACCAH 0xd8
|
||||
#define DSP_ACCAL 0xd9
|
||||
#define DSP_PRED_SCALE 0xda
|
||||
#define DSP_YN1 0xdb
|
||||
#define DSP_YN2 0xdc
|
||||
#define DSP_ACCELERATOR 0xdd // ADPCM accelerator read. Used by AX.
|
||||
#define DSP_GAIN 0xde
|
||||
|
||||
#define DSP_DIRQ 0xfb // DSP Irq Rest
|
||||
#define DSP_DMBH 0xfc // DSP Mailbox H
|
||||
#define DSP_DMBL 0xfd // DSP Mailbox L
|
||||
#define DSP_CMBH 0xfe // CPU Mailbox H
|
||||
#define DSP_CMBL 0xff // CPU Mailbox L
|
||||
|
||||
#define DMA_TO_DSP 0
|
||||
#define DMA_TO_CPU 1
|
||||
|
||||
// Stacks
|
||||
#define DSP_STACK_C 0
|
||||
#define DSP_STACK_D 1
|
||||
|
||||
// cr (Not g_dsp.r[CR]) bits
|
||||
// See HW/DSP.cpp.
|
||||
#define CR_HALT 0x0004
|
||||
#define CR_EXTERNAL_INT 0x0002
|
||||
|
||||
|
||||
// SR bits
|
||||
#define SR_CARRY 0x0001
|
||||
#define SR_2 0x0002 // overflow???
|
||||
#define SR_ARITH_ZERO 0x0004
|
||||
#define SR_SIGN 0x0008
|
||||
#define SR_10 0x0010 // seem to be set by tst
|
||||
#define SR_TOP2BITS 0x0020 // this is an odd one. (set by tst)
|
||||
#define SR_LOGIC_ZERO 0x0040
|
||||
#define SR_INT_ENABLE 0x0200 // Not 100% sure but duddie says so. This should replace the hack, if so.
|
||||
#define SR_EXT_INT_ENABLE 0x0800 // Appears in zelda - seems to disable external interupts
|
||||
#define SR_MUL_MODIFY 0x2000 // 1 = normal. 0 = x2 (M0, M2)
|
||||
#define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums.
|
||||
#define SR_MUL_UNSIGNED 0x8000 // 0 = normal. 1 = unsigned (CLR15, SET15) If set, treats operands as unsigned. Tested with mulx only so far.
|
||||
|
||||
// This should be the bits affected by CMP. Does not include logic zero.
|
||||
#define SR_CMP_MASK 0x3f
|
||||
|
||||
// exceptions vector
|
||||
#define EXP_RESET 0 // 0x0000
|
||||
#define EXP_STOVF 1 // 0x0002 stack under/over flow
|
||||
#define EXP_4 2 // 0x0004
|
||||
#define EXP_6 3 // 0x0006
|
||||
#define EXP_8 4 // 0x0008
|
||||
#define EXP_ACCOV 5 // 0x000a accelerator address overflow
|
||||
#define EXP_c 6 // 0x000c
|
||||
#define EXP_INT 7 // 0x000e external int? (mail?)
|
||||
|
||||
struct SDSP
|
||||
{
|
||||
u16 r[32];
|
||||
u16 pc;
|
||||
#if PROFILE
|
||||
u16 err_pc;
|
||||
#endif
|
||||
|
||||
// This is NOT the same cr as r[DSP_REG_CR].
|
||||
// This register is shared with the main emulation, see DSP.cpp
|
||||
// The plugin has control over 0x0C07 of this reg.
|
||||
// Bits are defined in a struct in DSP.cpp.
|
||||
u16 cr;
|
||||
|
||||
u8 reg_stack_ptr[4];
|
||||
u8 exceptions; // pending exceptions?
|
||||
bool exception_in_progress_hack; // is this the same as "exception enabled"?
|
||||
|
||||
// Let's make stack depth 32 for now. The real DSP has different depths
|
||||
// for the different stacks, but it would be strange if any ucode relied on stack
|
||||
// overflows since on the DSP, when the stack overflows, you're screwed.
|
||||
u16 reg_stack[4][DSP_STACK_DEPTH];
|
||||
|
||||
// For debugging.
|
||||
u32 iram_crc;
|
||||
u64 step_counter;
|
||||
|
||||
// When state saving, all of the above can just be memcpy'd into the save state.
|
||||
// The below needs special handling.
|
||||
u16 *iram;
|
||||
u16 *dram;
|
||||
u16 *irom;
|
||||
u16 *coef;
|
||||
|
||||
// This one doesn't really belong here.
|
||||
u8 *cpu_ram;
|
||||
};
|
||||
|
||||
extern SDSP g_dsp;
|
||||
extern DSPBreakpoints dsp_breakpoints;
|
||||
|
||||
bool DSPCore_Init(const char *irom_filename, const char *coef_filename);
|
||||
|
||||
void DSPCore_Reset();
|
||||
void DSPCore_Shutdown(); // Frees all allocated memory.
|
||||
|
||||
void DSPCore_CheckExternalInterrupt();
|
||||
void DSPCore_CheckExceptions();
|
||||
|
||||
// sets a flag in the pending exception register.
|
||||
void DSPCore_SetException(u8 level);
|
||||
|
||||
enum DSPCoreState
|
||||
{
|
||||
DSPCORE_RUNNING = 0,
|
||||
DSPCORE_STEPPING = 1,
|
||||
};
|
||||
|
||||
int DSPCore_RunCycles(int cycles);
|
||||
|
||||
// These are meant to be called from the UI thread.
|
||||
void DSPCore_SetState(DSPCoreState new_state);
|
||||
DSPCoreState DSPCore_GetState();
|
||||
|
||||
void DSPCore_Step();
|
||||
|
||||
#endif // _DSPCORE_H
|
||||
|
@ -1,35 +1,35 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPHOST_H
|
||||
#define _DSPHOST_H
|
||||
|
||||
// The user of the DSPCore library must supply a few functions so that the
|
||||
// emulation core can access the environment it runs in. If the emulation
|
||||
// core isn't used, for example in an asm/disasm tool, then most of these
|
||||
// can be stubbed out.
|
||||
#define DEBUG_EXP 1
|
||||
|
||||
u8 DSPHost_ReadHostMemory(u32 addr);
|
||||
void DSPHost_WriteHostMemory(u8 value, u32 addr);
|
||||
bool DSPHost_OnThread();
|
||||
bool DSPHost_Running();
|
||||
void DSPHost_InterruptRequest();
|
||||
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
|
||||
void DSPHost_UpdateDebugger();
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPHOST_H
|
||||
#define _DSPHOST_H
|
||||
|
||||
// The user of the DSPCore library must supply a few functions so that the
|
||||
// emulation core can access the environment it runs in. If the emulation
|
||||
// core isn't used, for example in an asm/disasm tool, then most of these
|
||||
// can be stubbed out.
|
||||
#define DEBUG_EXP 1
|
||||
|
||||
u8 DSPHost_ReadHostMemory(u32 addr);
|
||||
void DSPHost_WriteHostMemory(u8 value, u32 addr);
|
||||
bool DSPHost_OnThread();
|
||||
bool DSPHost_Running();
|
||||
void DSPHost_InterruptRequest();
|
||||
u32 DSPHost_CodeLoaded(const u8 *ptr, int size);
|
||||
void DSPHost_UpdateDebugger();
|
||||
|
||||
#endif
|
||||
|
@ -1,140 +1,140 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
#include "DSPIntCCUtil.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void Update_SR_Register64(s64 _Value)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
if (_Value < 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
}
|
||||
|
||||
if (_Value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
}
|
||||
|
||||
// weird
|
||||
if ((_Value >> 62) == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_SR_Register16(s16 _Value)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
if (_Value < 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
}
|
||||
|
||||
if (_Value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
}
|
||||
|
||||
// weird
|
||||
if ((_Value >> 14) == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_SR_LZ(s64 value) {
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMultiplyModifier()
|
||||
{
|
||||
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
inline bool isCarry() {
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
|
||||
}
|
||||
inline bool isSign() {
|
||||
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
|
||||
}
|
||||
inline bool isZero() {
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
|
||||
}
|
||||
|
||||
//see gdsp_registers.h for flags
|
||||
bool CheckCondition(u8 _Condition)
|
||||
{
|
||||
switch (_Condition & 0xf)
|
||||
{
|
||||
case 0x0: //NS - NOT SIGN
|
||||
return !isSign();
|
||||
case 0x1: // S - SIGN
|
||||
return isSign();
|
||||
case 0x2: // G - GREATER
|
||||
return !isSign() && !isZero();
|
||||
case 0x3: // LE - LESS EQUAL
|
||||
return isSign() || isZero();
|
||||
case 0x4: // NZ - NOT ZERO
|
||||
return !isZero();
|
||||
case 0x5: // Z - ZERO
|
||||
return isZero();
|
||||
case 0x6: // L - LESS
|
||||
// Should be that once we set 0x01
|
||||
return !isCarry();
|
||||
// if (isSign())
|
||||
case 0x7: // GE - GREATER EQUAL
|
||||
// Should be that once we set 0x01
|
||||
return isCarry();
|
||||
// if (! isSign() || isZero())
|
||||
case 0xc: // LNZ - LOGIC NOT ZERO
|
||||
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
|
||||
case 0xd: // LZ - LOGIC ZERO
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
|
||||
|
||||
case 0xf: // Empty - always true.
|
||||
return true;
|
||||
default:
|
||||
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
|
||||
// HELPER FUNCTIONS
|
||||
|
||||
#include "DSPIntCCUtil.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void Update_SR_Register64(s64 _Value)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
if (_Value < 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
}
|
||||
|
||||
if (_Value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
}
|
||||
|
||||
// weird
|
||||
if ((_Value >> 62) == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_SR_Register16(s16 _Value)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_CMP_MASK;
|
||||
|
||||
if (_Value < 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_SIGN;
|
||||
}
|
||||
|
||||
if (_Value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_ARITH_ZERO;
|
||||
}
|
||||
|
||||
// weird
|
||||
if ((_Value >> 14) == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
void Update_SR_LZ(s64 value) {
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] |= SR_LOGIC_ZERO;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_LOGIC_ZERO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMultiplyModifier()
|
||||
{
|
||||
if (g_dsp.r[DSP_REG_SR] & SR_MUL_MODIFY)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
|
||||
inline bool isCarry() {
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_CARRY) ? true : false;
|
||||
}
|
||||
inline bool isSign() {
|
||||
return ((g_dsp.r[DSP_REG_SR] & SR_2) != (g_dsp.r[DSP_REG_SR] & SR_SIGN));
|
||||
}
|
||||
inline bool isZero() {
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_ARITH_ZERO) ? true : false;
|
||||
}
|
||||
|
||||
//see gdsp_registers.h for flags
|
||||
bool CheckCondition(u8 _Condition)
|
||||
{
|
||||
switch (_Condition & 0xf)
|
||||
{
|
||||
case 0x0: //NS - NOT SIGN
|
||||
return !isSign();
|
||||
case 0x1: // S - SIGN
|
||||
return isSign();
|
||||
case 0x2: // G - GREATER
|
||||
return !isSign() && !isZero();
|
||||
case 0x3: // LE - LESS EQUAL
|
||||
return isSign() || isZero();
|
||||
case 0x4: // NZ - NOT ZERO
|
||||
return !isZero();
|
||||
case 0x5: // Z - ZERO
|
||||
return isZero();
|
||||
case 0x6: // L - LESS
|
||||
// Should be that once we set 0x01
|
||||
return !isCarry();
|
||||
// if (isSign())
|
||||
case 0x7: // GE - GREATER EQUAL
|
||||
// Should be that once we set 0x01
|
||||
return isCarry();
|
||||
// if (! isSign() || isZero())
|
||||
case 0xc: // LNZ - LOGIC NOT ZERO
|
||||
return !(g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO);
|
||||
case 0xd: // LZ - LOGIC ZERO
|
||||
return (g_dsp.r[DSP_REG_SR] & SR_LOGIC_ZERO) != 0;
|
||||
|
||||
case 0xf: // Empty - always true.
|
||||
return true;
|
||||
default:
|
||||
ERROR_LOG(DSPLLE, "Unknown condition check: 0x%04x\n", _Condition & 0xf);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1,39 +1,39 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#ifndef _GDSP_CONDITION_CODES_H
|
||||
#define _GDSP_CONDITION_CODES_H
|
||||
|
||||
// Anything to do with SR and conditions goes here.
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
bool CheckCondition(u8 _Condition);
|
||||
|
||||
int GetMultiplyModifier();
|
||||
|
||||
void Update_SR_Register16(s16 _Value);
|
||||
void Update_SR_Register64(s64 _Value);
|
||||
void Update_SR_LZ(s64 value);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _GDSP_CONDITION_CODES_H
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#ifndef _GDSP_CONDITION_CODES_H
|
||||
#define _GDSP_CONDITION_CODES_H
|
||||
|
||||
// Anything to do with SR and conditions goes here.
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
bool CheckCondition(u8 _Condition);
|
||||
|
||||
int GetMultiplyModifier();
|
||||
|
||||
void Update_SR_Register16(s16 _Value);
|
||||
void Update_SR_Register64(s64 _Value);
|
||||
void Update_SR_LZ(s64 value);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _GDSP_CONDITION_CODES_H
|
||||
|
@ -1,171 +1,171 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPINTERPRETER_H
|
||||
#define _DSPINTERPRETER_H
|
||||
|
||||
#include "DSPTables.h"
|
||||
|
||||
#define DSP_REG_MASK 0x1f
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void Step();
|
||||
void Run();
|
||||
|
||||
// If these simply return the same number of cycles as was passed into them,
|
||||
// chances are that the DSP is halted.
|
||||
// The difference between them is that the debug one obeys breakpoints.
|
||||
int RunCycles(int cycles);
|
||||
int RunCyclesDebug(int cycles);
|
||||
|
||||
void Stop();
|
||||
|
||||
void WriteCR(u16 val);
|
||||
u16 ReadCR();
|
||||
|
||||
|
||||
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
|
||||
|
||||
// All the opcode functions.
|
||||
void unknown(const UDSPInstruction& opc);
|
||||
void call(const UDSPInstruction& opc);
|
||||
void callr(const UDSPInstruction& opc);
|
||||
void ifcc(const UDSPInstruction& opc);
|
||||
void jcc(const UDSPInstruction& opc);
|
||||
void jmprcc(const UDSPInstruction& opc);
|
||||
void ret(const UDSPInstruction& opc);
|
||||
void halt(const UDSPInstruction& opc);
|
||||
void loop(const UDSPInstruction& opc);
|
||||
void loopi(const UDSPInstruction& opc);
|
||||
void bloop(const UDSPInstruction& opc);
|
||||
void bloopi(const UDSPInstruction& opc);
|
||||
void mrr(const UDSPInstruction& opc);
|
||||
void lrr(const UDSPInstruction& opc);
|
||||
void lrrd(const UDSPInstruction& opc);
|
||||
void lrri(const UDSPInstruction& opc);
|
||||
void lrrn(const UDSPInstruction& opc);
|
||||
void srr(const UDSPInstruction& opc);
|
||||
void srrd(const UDSPInstruction& opc);
|
||||
void srri(const UDSPInstruction& opc);
|
||||
void srrn(const UDSPInstruction& opc);
|
||||
void lri(const UDSPInstruction& opc);
|
||||
void lris(const UDSPInstruction& opc);
|
||||
void lr(const UDSPInstruction& opc);
|
||||
void sr(const UDSPInstruction& opc);
|
||||
void si(const UDSPInstruction& opc);
|
||||
void tstaxh(const UDSPInstruction& opc);
|
||||
void clr(const UDSPInstruction& opc);
|
||||
void clrl(const UDSPInstruction& opc);
|
||||
void clrp(const UDSPInstruction& opc);
|
||||
void mulc(const UDSPInstruction& opc);
|
||||
void cmpar(const UDSPInstruction& opc);
|
||||
void cmp(const UDSPInstruction& opc);
|
||||
void tst(const UDSPInstruction& opc);
|
||||
void addaxl(const UDSPInstruction& opc);
|
||||
void addarn(const UDSPInstruction& opc);
|
||||
void mulcac(const UDSPInstruction& opc);
|
||||
void movr(const UDSPInstruction& opc);
|
||||
void movax(const UDSPInstruction& opc);
|
||||
void xorr(const UDSPInstruction& opc);
|
||||
void andr(const UDSPInstruction& opc);
|
||||
void andc(const UDSPInstruction& opc);
|
||||
void orr(const UDSPInstruction& opc);
|
||||
void orc(const UDSPInstruction& opc);
|
||||
void orf(const UDSPInstruction& opc);
|
||||
void add(const UDSPInstruction& opc);
|
||||
void addp(const UDSPInstruction& opc);
|
||||
void cmpis(const UDSPInstruction& opc);
|
||||
void addpaxz(const UDSPInstruction& opc);
|
||||
void movpz(const UDSPInstruction& opc);
|
||||
void decm(const UDSPInstruction& opc);
|
||||
void dec(const UDSPInstruction& opc);
|
||||
void inc(const UDSPInstruction& opc);
|
||||
void incm(const UDSPInstruction& opc);
|
||||
void neg(const UDSPInstruction& opc);
|
||||
void addax(const UDSPInstruction& opc);
|
||||
void addr(const UDSPInstruction& opc);
|
||||
void subr(const UDSPInstruction& opc);
|
||||
void subp(const UDSPInstruction& opc);
|
||||
void subax(const UDSPInstruction& opc);
|
||||
void addis(const UDSPInstruction& opc);
|
||||
void addi(const UDSPInstruction& opc);
|
||||
void lsl16(const UDSPInstruction& opc);
|
||||
void madd(const UDSPInstruction& opc);
|
||||
void msub(const UDSPInstruction& opc);
|
||||
void lsr16(const UDSPInstruction& opc);
|
||||
void asr16(const UDSPInstruction& opc);
|
||||
void lsl(const UDSPInstruction& opc);
|
||||
void lsr(const UDSPInstruction& opc);
|
||||
void asl(const UDSPInstruction& opc);
|
||||
void asr(const UDSPInstruction& opc);
|
||||
void lsrn(const UDSPInstruction& opc);
|
||||
void asrn(const UDSPInstruction& opc);
|
||||
void dar(const UDSPInstruction& opc);
|
||||
void iar(const UDSPInstruction& opc);
|
||||
void sbclr(const UDSPInstruction& opc);
|
||||
void sbset(const UDSPInstruction& opc);
|
||||
void mov(const UDSPInstruction& opc);
|
||||
void movp(const UDSPInstruction& opc);
|
||||
void mul(const UDSPInstruction& opc);
|
||||
void mulac(const UDSPInstruction& opc);
|
||||
void mulmv(const UDSPInstruction& opc);
|
||||
void mulmvz(const UDSPInstruction& opc);
|
||||
void mulx(const UDSPInstruction& opc);
|
||||
void mulxac(const UDSPInstruction& opc);
|
||||
void mulxmv(const UDSPInstruction& opc);
|
||||
void mulxmvz(const UDSPInstruction& opc);
|
||||
void mulcmvz(const UDSPInstruction& opc);
|
||||
void mulcmv(const UDSPInstruction& opc);
|
||||
void movnp(const UDSPInstruction& opc);
|
||||
void sub(const UDSPInstruction& opc);
|
||||
void maddx(const UDSPInstruction& opc);
|
||||
void msubx(const UDSPInstruction& opc);
|
||||
void maddc(const UDSPInstruction& opc);
|
||||
void msubc(const UDSPInstruction& opc);
|
||||
void srs(const UDSPInstruction& opc);
|
||||
void lrs(const UDSPInstruction& opc);
|
||||
void nx(const UDSPInstruction& opc);
|
||||
void cmpi(const UDSPInstruction& opc);
|
||||
void rti(const UDSPInstruction& opc);
|
||||
void ilrr(const UDSPInstruction& opc);
|
||||
void ilrrd(const UDSPInstruction& opc);
|
||||
void ilrri(const UDSPInstruction& opc);
|
||||
void ilrrn(const UDSPInstruction& opc);
|
||||
void andcf(const UDSPInstruction& opc);
|
||||
void andf(const UDSPInstruction& opc);
|
||||
void xori(const UDSPInstruction& opc);
|
||||
void andi(const UDSPInstruction& opc);
|
||||
void ori(const UDSPInstruction& opc);
|
||||
|
||||
// FIXME inside
|
||||
void srbith(const UDSPInstruction& opc);
|
||||
|
||||
// END OF FIXMEs
|
||||
|
||||
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
|
||||
void tstaxl(const UDSPInstruction& opc);
|
||||
// The mysterious a100
|
||||
|
||||
// END OF UNIMPLEMENTED
|
||||
|
||||
// Helpers
|
||||
inline void tsta(int reg);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _DSPINTERPRETER_H
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPINTERPRETER_H
|
||||
#define _DSPINTERPRETER_H
|
||||
|
||||
#include "DSPTables.h"
|
||||
|
||||
#define DSP_REG_MASK 0x1f
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void Step();
|
||||
void Run();
|
||||
|
||||
// If these simply return the same number of cycles as was passed into them,
|
||||
// chances are that the DSP is halted.
|
||||
// The difference between them is that the debug one obeys breakpoints.
|
||||
int RunCycles(int cycles);
|
||||
int RunCyclesDebug(int cycles);
|
||||
|
||||
void Stop();
|
||||
|
||||
void WriteCR(u16 val);
|
||||
u16 ReadCR();
|
||||
|
||||
|
||||
typedef void (*DSPInterpreterFunc)(const UDSPInstruction& opc);
|
||||
|
||||
// All the opcode functions.
|
||||
void unknown(const UDSPInstruction& opc);
|
||||
void call(const UDSPInstruction& opc);
|
||||
void callr(const UDSPInstruction& opc);
|
||||
void ifcc(const UDSPInstruction& opc);
|
||||
void jcc(const UDSPInstruction& opc);
|
||||
void jmprcc(const UDSPInstruction& opc);
|
||||
void ret(const UDSPInstruction& opc);
|
||||
void halt(const UDSPInstruction& opc);
|
||||
void loop(const UDSPInstruction& opc);
|
||||
void loopi(const UDSPInstruction& opc);
|
||||
void bloop(const UDSPInstruction& opc);
|
||||
void bloopi(const UDSPInstruction& opc);
|
||||
void mrr(const UDSPInstruction& opc);
|
||||
void lrr(const UDSPInstruction& opc);
|
||||
void lrrd(const UDSPInstruction& opc);
|
||||
void lrri(const UDSPInstruction& opc);
|
||||
void lrrn(const UDSPInstruction& opc);
|
||||
void srr(const UDSPInstruction& opc);
|
||||
void srrd(const UDSPInstruction& opc);
|
||||
void srri(const UDSPInstruction& opc);
|
||||
void srrn(const UDSPInstruction& opc);
|
||||
void lri(const UDSPInstruction& opc);
|
||||
void lris(const UDSPInstruction& opc);
|
||||
void lr(const UDSPInstruction& opc);
|
||||
void sr(const UDSPInstruction& opc);
|
||||
void si(const UDSPInstruction& opc);
|
||||
void tstaxh(const UDSPInstruction& opc);
|
||||
void clr(const UDSPInstruction& opc);
|
||||
void clrl(const UDSPInstruction& opc);
|
||||
void clrp(const UDSPInstruction& opc);
|
||||
void mulc(const UDSPInstruction& opc);
|
||||
void cmpar(const UDSPInstruction& opc);
|
||||
void cmp(const UDSPInstruction& opc);
|
||||
void tst(const UDSPInstruction& opc);
|
||||
void addaxl(const UDSPInstruction& opc);
|
||||
void addarn(const UDSPInstruction& opc);
|
||||
void mulcac(const UDSPInstruction& opc);
|
||||
void movr(const UDSPInstruction& opc);
|
||||
void movax(const UDSPInstruction& opc);
|
||||
void xorr(const UDSPInstruction& opc);
|
||||
void andr(const UDSPInstruction& opc);
|
||||
void andc(const UDSPInstruction& opc);
|
||||
void orr(const UDSPInstruction& opc);
|
||||
void orc(const UDSPInstruction& opc);
|
||||
void orf(const UDSPInstruction& opc);
|
||||
void add(const UDSPInstruction& opc);
|
||||
void addp(const UDSPInstruction& opc);
|
||||
void cmpis(const UDSPInstruction& opc);
|
||||
void addpaxz(const UDSPInstruction& opc);
|
||||
void movpz(const UDSPInstruction& opc);
|
||||
void decm(const UDSPInstruction& opc);
|
||||
void dec(const UDSPInstruction& opc);
|
||||
void inc(const UDSPInstruction& opc);
|
||||
void incm(const UDSPInstruction& opc);
|
||||
void neg(const UDSPInstruction& opc);
|
||||
void addax(const UDSPInstruction& opc);
|
||||
void addr(const UDSPInstruction& opc);
|
||||
void subr(const UDSPInstruction& opc);
|
||||
void subp(const UDSPInstruction& opc);
|
||||
void subax(const UDSPInstruction& opc);
|
||||
void addis(const UDSPInstruction& opc);
|
||||
void addi(const UDSPInstruction& opc);
|
||||
void lsl16(const UDSPInstruction& opc);
|
||||
void madd(const UDSPInstruction& opc);
|
||||
void msub(const UDSPInstruction& opc);
|
||||
void lsr16(const UDSPInstruction& opc);
|
||||
void asr16(const UDSPInstruction& opc);
|
||||
void lsl(const UDSPInstruction& opc);
|
||||
void lsr(const UDSPInstruction& opc);
|
||||
void asl(const UDSPInstruction& opc);
|
||||
void asr(const UDSPInstruction& opc);
|
||||
void lsrn(const UDSPInstruction& opc);
|
||||
void asrn(const UDSPInstruction& opc);
|
||||
void dar(const UDSPInstruction& opc);
|
||||
void iar(const UDSPInstruction& opc);
|
||||
void sbclr(const UDSPInstruction& opc);
|
||||
void sbset(const UDSPInstruction& opc);
|
||||
void mov(const UDSPInstruction& opc);
|
||||
void movp(const UDSPInstruction& opc);
|
||||
void mul(const UDSPInstruction& opc);
|
||||
void mulac(const UDSPInstruction& opc);
|
||||
void mulmv(const UDSPInstruction& opc);
|
||||
void mulmvz(const UDSPInstruction& opc);
|
||||
void mulx(const UDSPInstruction& opc);
|
||||
void mulxac(const UDSPInstruction& opc);
|
||||
void mulxmv(const UDSPInstruction& opc);
|
||||
void mulxmvz(const UDSPInstruction& opc);
|
||||
void mulcmvz(const UDSPInstruction& opc);
|
||||
void mulcmv(const UDSPInstruction& opc);
|
||||
void movnp(const UDSPInstruction& opc);
|
||||
void sub(const UDSPInstruction& opc);
|
||||
void maddx(const UDSPInstruction& opc);
|
||||
void msubx(const UDSPInstruction& opc);
|
||||
void maddc(const UDSPInstruction& opc);
|
||||
void msubc(const UDSPInstruction& opc);
|
||||
void srs(const UDSPInstruction& opc);
|
||||
void lrs(const UDSPInstruction& opc);
|
||||
void nx(const UDSPInstruction& opc);
|
||||
void cmpi(const UDSPInstruction& opc);
|
||||
void rti(const UDSPInstruction& opc);
|
||||
void ilrr(const UDSPInstruction& opc);
|
||||
void ilrrd(const UDSPInstruction& opc);
|
||||
void ilrri(const UDSPInstruction& opc);
|
||||
void ilrrn(const UDSPInstruction& opc);
|
||||
void andcf(const UDSPInstruction& opc);
|
||||
void andf(const UDSPInstruction& opc);
|
||||
void xori(const UDSPInstruction& opc);
|
||||
void andi(const UDSPInstruction& opc);
|
||||
void ori(const UDSPInstruction& opc);
|
||||
|
||||
// FIXME inside
|
||||
void srbith(const UDSPInstruction& opc);
|
||||
|
||||
// END OF FIXMEs
|
||||
|
||||
// TODO: PENDING IMPLEMENTATION / UNIMPLEMENTED
|
||||
void tstaxl(const UDSPInstruction& opc);
|
||||
// The mysterious a100
|
||||
|
||||
// END OF UNIMPLEMENTED
|
||||
|
||||
// Helpers
|
||||
inline void tsta(int reg);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _DSPINTERPRETER_H
|
||||
|
@ -1,22 +1,22 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "DSPJit.h"
|
||||
|
||||
namespace DSPJit {
|
||||
|
||||
};
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "DSPJit.h"
|
||||
|
||||
namespace DSPJit {
|
||||
|
||||
};
|
||||
|
@ -1,28 +1,28 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPJIT_H
|
||||
#define _DSPJIT_H
|
||||
|
||||
namespace DSPJit {
|
||||
|
||||
// TODO(XK): Fill
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _DSPJIT_H
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DSPJIT_H
|
||||
#define _DSPJIT_H
|
||||
|
||||
namespace DSPJit {
|
||||
|
||||
// TODO(XK): Fill
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // _DSPJIT_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,168 +1,168 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
|
||||
|
||||
#ifndef _DSPTABLES_H
|
||||
#define _DSPTABLES_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// The non-ADDR ones that end with _D are the opposite one - if the bit specify
|
||||
// ACC0, then ACC_D will be ACC1.
|
||||
|
||||
// The values of these are very important.
|
||||
// For the reg ones, the value >> 8 is the base register.
|
||||
// & 0x80 means it's a "D".
|
||||
|
||||
enum partype_t
|
||||
{
|
||||
P_NONE = 0x0000,
|
||||
P_VAL = 0x0001,
|
||||
P_IMM = 0x0002,
|
||||
P_MEM = 0x0003,
|
||||
P_STR = 0x0004,
|
||||
P_ADDR_I = 0x0005,
|
||||
P_ADDR_D = 0x0006,
|
||||
P_REG = 0x8000,
|
||||
P_REG04 = P_REG | 0x0400, // IX
|
||||
P_REG08 = P_REG | 0x0800,
|
||||
P_REG18 = P_REG | 0x1800,
|
||||
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
|
||||
P_REG19 = P_REG | 0x1900,
|
||||
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
|
||||
P_REG1A = P_REG | 0x1a80,
|
||||
P_REG1C = P_REG | 0x1c00,
|
||||
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
|
||||
P_ACC_D = P_REG | 0x1c80,
|
||||
P_ACCL = P_REG | 0x1c00, // used for low part of accum
|
||||
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
|
||||
// The following are not in gcdsptool
|
||||
P_ACCM_D = P_REG | 0x1e80,
|
||||
P_ACC = P_REG | 0x2000, // used for full accum.
|
||||
P_AX = P_REG | 0x2200,
|
||||
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
|
||||
P_REF = P_REG | 0x4000,
|
||||
P_PRG = P_REF | P_REG,
|
||||
|
||||
// The following seem like junk:
|
||||
// P_REG10 = P_REG | 0x1000,
|
||||
// P_AX_D = P_REG | 0x2280,
|
||||
};
|
||||
|
||||
#define P_EXT 0x80
|
||||
|
||||
#define OPTABLE_SIZE 65536
|
||||
|
||||
union UDSPInstruction
|
||||
{
|
||||
u16 hex;
|
||||
|
||||
UDSPInstruction(u16 _hex) { hex = _hex; }
|
||||
UDSPInstruction() { hex = 0; }
|
||||
|
||||
struct
|
||||
{
|
||||
signed shift : 6;
|
||||
unsigned negating : 1;
|
||||
unsigned arithmetic : 1;
|
||||
unsigned areg : 1;
|
||||
unsigned op : 7;
|
||||
};
|
||||
struct
|
||||
{
|
||||
unsigned ushift : 6;
|
||||
};
|
||||
|
||||
// TODO: Figure out more instruction structures (add structs here)
|
||||
};
|
||||
|
||||
typedef void (*dspInstFunc)(const UDSPInstruction&);
|
||||
|
||||
struct param2_t
|
||||
{
|
||||
partype_t type;
|
||||
u8 size;
|
||||
u8 loc;
|
||||
s8 lshift;
|
||||
u16 mask;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
u16 opcode;
|
||||
u16 opcode_mask;
|
||||
|
||||
dspInstFunc interpFunc;
|
||||
dspInstFunc jitFunc;
|
||||
|
||||
u8 size;
|
||||
u8 param_count;
|
||||
param2_t params[8];
|
||||
dspInstFunc prologue;
|
||||
dspInstFunc epilogue;
|
||||
} DSPOPCTemplate;
|
||||
|
||||
typedef DSPOPCTemplate opc_t;
|
||||
|
||||
// Opcodes
|
||||
extern const DSPOPCTemplate opcodes[];
|
||||
extern const int opcodes_size;
|
||||
extern const DSPOPCTemplate opcodes_ext[];
|
||||
extern const int opcodes_ext_size;
|
||||
extern u8 opSize[OPTABLE_SIZE];
|
||||
extern const DSPOPCTemplate cw;
|
||||
|
||||
extern dspInstFunc opTable[];
|
||||
extern dspInstFunc prologueTable[OPTABLE_SIZE];
|
||||
extern dspInstFunc epilogueTable[OPTABLE_SIZE];
|
||||
|
||||
// Predefined labels
|
||||
struct pdlabel_t
|
||||
{
|
||||
u16 addr;
|
||||
const char* name;
|
||||
const char* description;
|
||||
};
|
||||
|
||||
extern const pdlabel_t regnames[];
|
||||
extern const pdlabel_t pdlabels[];
|
||||
extern const u32 pdlabels_size;
|
||||
|
||||
const char *pdname(u16 val);
|
||||
const char *pdregname(int val);
|
||||
const char *pdregnamelong(int val);
|
||||
|
||||
void InitInstructionTable();
|
||||
|
||||
inline void ExecuteInstruction(const UDSPInstruction& inst)
|
||||
{
|
||||
// TODO: Move the prologuetable calls into the relevant instructions themselves.
|
||||
// Better not do things like this until things work correctly though.
|
||||
if (prologueTable[inst.hex])
|
||||
prologueTable[inst.hex](inst);
|
||||
opTable[inst.hex](inst);
|
||||
if (epilogueTable[inst.hex])
|
||||
epilogueTable[inst.hex](inst);
|
||||
}
|
||||
|
||||
// This one's pretty slow, try to use it only at init or seldomly.
|
||||
// returns NULL if no matching instruction.
|
||||
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
|
||||
|
||||
#endif // _DSPTABLES_H
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie (c) 2005 (duddie@walla.com)
|
||||
|
||||
#ifndef _DSPTABLES_H
|
||||
#define _DSPTABLES_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// The non-ADDR ones that end with _D are the opposite one - if the bit specify
|
||||
// ACC0, then ACC_D will be ACC1.
|
||||
|
||||
// The values of these are very important.
|
||||
// For the reg ones, the value >> 8 is the base register.
|
||||
// & 0x80 means it's a "D".
|
||||
|
||||
enum partype_t
|
||||
{
|
||||
P_NONE = 0x0000,
|
||||
P_VAL = 0x0001,
|
||||
P_IMM = 0x0002,
|
||||
P_MEM = 0x0003,
|
||||
P_STR = 0x0004,
|
||||
P_ADDR_I = 0x0005,
|
||||
P_ADDR_D = 0x0006,
|
||||
P_REG = 0x8000,
|
||||
P_REG04 = P_REG | 0x0400, // IX
|
||||
P_REG08 = P_REG | 0x0800,
|
||||
P_REG18 = P_REG | 0x1800,
|
||||
P_REGM18 = P_REG | 0x1810, // used in multiply instructions
|
||||
P_REG19 = P_REG | 0x1900,
|
||||
P_REGM19 = P_REG | 0x1910, // used in multiply instructions
|
||||
P_REG1A = P_REG | 0x1a80,
|
||||
P_REG1C = P_REG | 0x1c00,
|
||||
// P_ACC = P_REG | 0x1c10, // used for global accum (gcdsptool's value)
|
||||
P_ACC_D = P_REG | 0x1c80,
|
||||
P_ACCL = P_REG | 0x1c00, // used for low part of accum
|
||||
P_ACCM = P_REG | 0x1e00, // used for mid part of accum
|
||||
// The following are not in gcdsptool
|
||||
P_ACCM_D = P_REG | 0x1e80,
|
||||
P_ACC = P_REG | 0x2000, // used for full accum.
|
||||
P_AX = P_REG | 0x2200,
|
||||
P_REGS_MASK = 0x03f80, // gcdsptool's value = 0x01f80
|
||||
P_REF = P_REG | 0x4000,
|
||||
P_PRG = P_REF | P_REG,
|
||||
|
||||
// The following seem like junk:
|
||||
// P_REG10 = P_REG | 0x1000,
|
||||
// P_AX_D = P_REG | 0x2280,
|
||||
};
|
||||
|
||||
#define P_EXT 0x80
|
||||
|
||||
#define OPTABLE_SIZE 65536
|
||||
|
||||
union UDSPInstruction
|
||||
{
|
||||
u16 hex;
|
||||
|
||||
UDSPInstruction(u16 _hex) { hex = _hex; }
|
||||
UDSPInstruction() { hex = 0; }
|
||||
|
||||
struct
|
||||
{
|
||||
signed shift : 6;
|
||||
unsigned negating : 1;
|
||||
unsigned arithmetic : 1;
|
||||
unsigned areg : 1;
|
||||
unsigned op : 7;
|
||||
};
|
||||
struct
|
||||
{
|
||||
unsigned ushift : 6;
|
||||
};
|
||||
|
||||
// TODO: Figure out more instruction structures (add structs here)
|
||||
};
|
||||
|
||||
typedef void (*dspInstFunc)(const UDSPInstruction&);
|
||||
|
||||
struct param2_t
|
||||
{
|
||||
partype_t type;
|
||||
u8 size;
|
||||
u8 loc;
|
||||
s8 lshift;
|
||||
u16 mask;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
u16 opcode;
|
||||
u16 opcode_mask;
|
||||
|
||||
dspInstFunc interpFunc;
|
||||
dspInstFunc jitFunc;
|
||||
|
||||
u8 size;
|
||||
u8 param_count;
|
||||
param2_t params[8];
|
||||
dspInstFunc prologue;
|
||||
dspInstFunc epilogue;
|
||||
} DSPOPCTemplate;
|
||||
|
||||
typedef DSPOPCTemplate opc_t;
|
||||
|
||||
// Opcodes
|
||||
extern const DSPOPCTemplate opcodes[];
|
||||
extern const int opcodes_size;
|
||||
extern const DSPOPCTemplate opcodes_ext[];
|
||||
extern const int opcodes_ext_size;
|
||||
extern u8 opSize[OPTABLE_SIZE];
|
||||
extern const DSPOPCTemplate cw;
|
||||
|
||||
extern dspInstFunc opTable[];
|
||||
extern dspInstFunc prologueTable[OPTABLE_SIZE];
|
||||
extern dspInstFunc epilogueTable[OPTABLE_SIZE];
|
||||
|
||||
// Predefined labels
|
||||
struct pdlabel_t
|
||||
{
|
||||
u16 addr;
|
||||
const char* name;
|
||||
const char* description;
|
||||
};
|
||||
|
||||
extern const pdlabel_t regnames[];
|
||||
extern const pdlabel_t pdlabels[];
|
||||
extern const u32 pdlabels_size;
|
||||
|
||||
const char *pdname(u16 val);
|
||||
const char *pdregname(int val);
|
||||
const char *pdregnamelong(int val);
|
||||
|
||||
void InitInstructionTable();
|
||||
|
||||
inline void ExecuteInstruction(const UDSPInstruction& inst)
|
||||
{
|
||||
// TODO: Move the prologuetable calls into the relevant instructions themselves.
|
||||
// Better not do things like this until things work correctly though.
|
||||
if (prologueTable[inst.hex])
|
||||
prologueTable[inst.hex](inst);
|
||||
opTable[inst.hex](inst);
|
||||
if (epilogueTable[inst.hex])
|
||||
epilogueTable[inst.hex](inst);
|
||||
}
|
||||
|
||||
// This one's pretty slow, try to use it only at init or seldomly.
|
||||
// returns NULL if no matching instruction.
|
||||
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst);
|
||||
|
||||
#endif // _DSPTABLES_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,249 +1,249 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPMemoryMap.h"
|
||||
#include "DSPStacks.h"
|
||||
|
||||
#include "DSPIntCCUtil.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// Generic call implementation
|
||||
// CALLcc addressA
|
||||
// 0000 0010 1011 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to $st0. Set program counter to address
|
||||
// represented by value that follows this "call" instruction.
|
||||
void call(const UDSPInstruction& opc)
|
||||
{
|
||||
// must be outside the if.
|
||||
u16 dest = dsp_fetch_code();
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
g_dsp.pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic callr implementation
|
||||
// CALLRcc $R
|
||||
// 0001 0111 rrr1 cccc
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to call stack $st0. Set program counter to
|
||||
// register $R.
|
||||
void callr(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
u8 reg = (opc.hex >> 5) & 0x7;
|
||||
u16 addr = dsp_op_read_reg(reg);
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
g_dsp.pc = addr;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic if implementation
|
||||
// IFcc
|
||||
// 0000 0010 0111 cccc
|
||||
// Execute following opcode if the condition has been met.
|
||||
void ifcc(const UDSPInstruction& opc)
|
||||
{
|
||||
if (!CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
// skip the next opcode - we have to lookup its size.
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
// Generic jmp implementation
|
||||
// Jcc addressA
|
||||
// 0000 0010 1001 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Jump to addressA if condition cc has been met. Set program counter to
|
||||
// address represented by value that follows this "jmp" instruction.
|
||||
void jcc(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 dest = dsp_fetch_code();
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
g_dsp.pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic jmpr implementation
|
||||
// JMPcc $R
|
||||
// 0001 0111 rrr0 cccc
|
||||
// Jump to address; set program counter to a value from register $R.
|
||||
void jmprcc(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
u8 reg = (opc.hex >> 5) & 0x7;
|
||||
g_dsp.pc = dsp_op_read_reg(reg);
|
||||
}
|
||||
}
|
||||
|
||||
// Generic ret implementation
|
||||
// RETcc
|
||||
// 0000 0010 1101 cccc
|
||||
// Return from subroutine if condition cc has been met. Pops stored PC
|
||||
// from call stack $st0 and sets $pc to this location.
|
||||
void ret(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
}
|
||||
}
|
||||
|
||||
// RTI
|
||||
// 0000 0010 1111 1111
|
||||
// Return from exception. Pops stored status register $sr from data stack
|
||||
// $st1 and program counter PC from call stack $st0 and sets $pc to this
|
||||
// location.
|
||||
void rti(const UDSPInstruction& opc)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
|
||||
g_dsp.exception_in_progress_hack = false;
|
||||
}
|
||||
|
||||
// HALT
|
||||
// 0000 0000 0020 0001
|
||||
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
|
||||
void halt(const UDSPInstruction& opc)
|
||||
{
|
||||
g_dsp.cr |= 0x4;
|
||||
g_dsp.pc--;
|
||||
}
|
||||
|
||||
|
||||
// LOOP handling: Loop stack is used to control execution of repeated blocks of
|
||||
// instructions. Whenever there is value on stack $st2 and current PC is equal
|
||||
// value at $st2, then value at stack $st3 is decremented. If value is not zero
|
||||
// then PC is modified with calue from call stack $st0. Otherwise values from
|
||||
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
|
||||
// continues at next opcode.
|
||||
|
||||
|
||||
// LOOP $R
|
||||
// 0000 0000 010r rrrr
|
||||
// Repeatedly execute following opcode until counter specified by value
|
||||
// from register $R reaches zero. Each execution decrement counter. Register
|
||||
// $R remains unchanged. If register $R is set to zero at the beginning of loop
|
||||
// then looped instruction will not get executed.
|
||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||
// The looping hardware takes care of the rest.
|
||||
void loop(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x1f;
|
||||
u16 cnt = g_dsp.r[reg];
|
||||
u16 loop_pc = g_dsp.pc;
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
// LOOPI #I
|
||||
// 0001 0000 iiii iiii
|
||||
// Repeatedly execute following opcode until counter specified by
|
||||
// immediate value I reaches zero. Each execution decrement counter. If
|
||||
// immediate value I is set to zero at the beginning of loop then looped
|
||||
// instruction will not get executed.
|
||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||
// The looping hardware takes care of the rest.
|
||||
void loopi(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 cnt = opc.hex & 0xff;
|
||||
u16 loop_pc = g_dsp.pc;
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BLOOP $R, addrA
|
||||
// 0000 0000 011r rrrr
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Repeatedly execute block of code starting at following opcode until
|
||||
// counter specified by value from register $R reaches zero. Block ends at
|
||||
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
|
||||
// included in loop. Counter is pushed on loop stack $st3, end of block address
|
||||
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
|
||||
// Up to 4 nested loops is allowed.
|
||||
void bloop(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x1f;
|
||||
u16 cnt = g_dsp.r[reg];
|
||||
u16 loop_pc = dsp_fetch_code();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.pc = loop_pc;
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
// BLOOPI #I, addrA
|
||||
// 0001 0001 iiii iiii
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Repeatedly execute block of code starting at following opcode until
|
||||
// counter specified by immediate value I reaches zero. Block ends at specified
|
||||
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
|
||||
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
|
||||
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
|
||||
// nested loops is allowed.
|
||||
void bloopi(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 cnt = opc.hex & 0xff;
|
||||
u16 loop_pc = dsp_fetch_code();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.pc = loop_pc;
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
#include "DSPCore.h"
|
||||
#include "DSPMemoryMap.h"
|
||||
#include "DSPStacks.h"
|
||||
|
||||
#include "DSPIntCCUtil.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// Generic call implementation
|
||||
// CALLcc addressA
|
||||
// 0000 0010 1011 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to $st0. Set program counter to address
|
||||
// represented by value that follows this "call" instruction.
|
||||
void call(const UDSPInstruction& opc)
|
||||
{
|
||||
// must be outside the if.
|
||||
u16 dest = dsp_fetch_code();
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
g_dsp.pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic callr implementation
|
||||
// CALLRcc $R
|
||||
// 0001 0111 rrr1 cccc
|
||||
// Call function if condition cc has been met. Push program counter of
|
||||
// instruction following "call" to call stack $st0. Set program counter to
|
||||
// register $R.
|
||||
void callr(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
u8 reg = (opc.hex >> 5) & 0x7;
|
||||
u16 addr = dsp_op_read_reg(reg);
|
||||
dsp_reg_store_stack(DSP_STACK_C, g_dsp.pc);
|
||||
g_dsp.pc = addr;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic if implementation
|
||||
// IFcc
|
||||
// 0000 0010 0111 cccc
|
||||
// Execute following opcode if the condition has been met.
|
||||
void ifcc(const UDSPInstruction& opc)
|
||||
{
|
||||
if (!CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
// skip the next opcode - we have to lookup its size.
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
// Generic jmp implementation
|
||||
// Jcc addressA
|
||||
// 0000 0010 1001 cccc
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Jump to addressA if condition cc has been met. Set program counter to
|
||||
// address represented by value that follows this "jmp" instruction.
|
||||
void jcc(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 dest = dsp_fetch_code();
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
g_dsp.pc = dest;
|
||||
}
|
||||
}
|
||||
|
||||
// Generic jmpr implementation
|
||||
// JMPcc $R
|
||||
// 0001 0111 rrr0 cccc
|
||||
// Jump to address; set program counter to a value from register $R.
|
||||
void jmprcc(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
u8 reg = (opc.hex >> 5) & 0x7;
|
||||
g_dsp.pc = dsp_op_read_reg(reg);
|
||||
}
|
||||
}
|
||||
|
||||
// Generic ret implementation
|
||||
// RETcc
|
||||
// 0000 0010 1101 cccc
|
||||
// Return from subroutine if condition cc has been met. Pops stored PC
|
||||
// from call stack $st0 and sets $pc to this location.
|
||||
void ret(const UDSPInstruction& opc)
|
||||
{
|
||||
if (CheckCondition(opc.hex & 0xf))
|
||||
{
|
||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
}
|
||||
}
|
||||
|
||||
// RTI
|
||||
// 0000 0010 1111 1111
|
||||
// Return from exception. Pops stored status register $sr from data stack
|
||||
// $st1 and program counter PC from call stack $st0 and sets $pc to this
|
||||
// location.
|
||||
void rti(const UDSPInstruction& opc)
|
||||
{
|
||||
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
||||
g_dsp.pc = dsp_reg_load_stack(DSP_STACK_C);
|
||||
|
||||
g_dsp.exception_in_progress_hack = false;
|
||||
}
|
||||
|
||||
// HALT
|
||||
// 0000 0000 0020 0001
|
||||
// Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR.
|
||||
void halt(const UDSPInstruction& opc)
|
||||
{
|
||||
g_dsp.cr |= 0x4;
|
||||
g_dsp.pc--;
|
||||
}
|
||||
|
||||
|
||||
// LOOP handling: Loop stack is used to control execution of repeated blocks of
|
||||
// instructions. Whenever there is value on stack $st2 and current PC is equal
|
||||
// value at $st2, then value at stack $st3 is decremented. If value is not zero
|
||||
// then PC is modified with calue from call stack $st0. Otherwise values from
|
||||
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
|
||||
// continues at next opcode.
|
||||
|
||||
|
||||
// LOOP $R
|
||||
// 0000 0000 010r rrrr
|
||||
// Repeatedly execute following opcode until counter specified by value
|
||||
// from register $R reaches zero. Each execution decrement counter. Register
|
||||
// $R remains unchanged. If register $R is set to zero at the beginning of loop
|
||||
// then looped instruction will not get executed.
|
||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||
// The looping hardware takes care of the rest.
|
||||
void loop(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x1f;
|
||||
u16 cnt = g_dsp.r[reg];
|
||||
u16 loop_pc = g_dsp.pc;
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
// LOOPI #I
|
||||
// 0001 0000 iiii iiii
|
||||
// Repeatedly execute following opcode until counter specified by
|
||||
// immediate value I reaches zero. Each execution decrement counter. If
|
||||
// immediate value I is set to zero at the beginning of loop then looped
|
||||
// instruction will not get executed.
|
||||
// Actually, this instruction simply prepares the loop stacks for the above.
|
||||
// The looping hardware takes care of the rest.
|
||||
void loopi(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 cnt = opc.hex & 0xff;
|
||||
u16 loop_pc = g_dsp.pc;
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// BLOOP $R, addrA
|
||||
// 0000 0000 011r rrrr
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Repeatedly execute block of code starting at following opcode until
|
||||
// counter specified by value from register $R reaches zero. Block ends at
|
||||
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
|
||||
// included in loop. Counter is pushed on loop stack $st3, end of block address
|
||||
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
|
||||
// Up to 4 nested loops is allowed.
|
||||
void bloop(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x1f;
|
||||
u16 cnt = g_dsp.r[reg];
|
||||
u16 loop_pc = dsp_fetch_code();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.pc = loop_pc;
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
// BLOOPI #I, addrA
|
||||
// 0001 0001 iiii iiii
|
||||
// aaaa aaaa aaaa aaaa
|
||||
// Repeatedly execute block of code starting at following opcode until
|
||||
// counter specified by immediate value I reaches zero. Block ends at specified
|
||||
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
|
||||
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
|
||||
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
|
||||
// nested loops is allowed.
|
||||
void bloopi(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 cnt = opc.hex & 0xff;
|
||||
u16 loop_pc = dsp_fetch_code();
|
||||
|
||||
if (cnt)
|
||||
{
|
||||
dsp_reg_store_stack(0, g_dsp.pc);
|
||||
dsp_reg_store_stack(2, loop_pc);
|
||||
dsp_reg_store_stack(3, cnt);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_dsp.pc = loop_pc;
|
||||
g_dsp.pc += opSize[dsp_peek_code()];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1,266 +1,266 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
#include "DSPMemoryMap.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// SRS @M, $(0x18+S)
|
||||
// 0010 1sss mmmm mmmm
|
||||
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
|
||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||
// lower 8 bits are from the 8-bit immediate.
|
||||
// Note: pc+=2 in duddie's doc seems wrong
|
||||
void srs(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||
dsp_dmem_write(addr, g_dsp.r[reg]);
|
||||
}
|
||||
|
||||
// LRS $(0x18+D), @M
|
||||
// 0010 0ddd mmmm mmmm
|
||||
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
|
||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||
// lower 8 bits are from the 8-bit immediate.
|
||||
void lrs(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||
g_dsp.r[reg] = dsp_dmem_read(addr);
|
||||
}
|
||||
|
||||
// LR $D, @M
|
||||
// 0000 0000 110d dddd
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Move value from data memory pointed by address M to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_dmem_read(addr);
|
||||
dsp_op_write_reg(reg, val);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// SR @M, $S
|
||||
// 0000 0000 111s ssss
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Store value from register $S to a memory pointed by address M.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void sr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_op_read_reg(reg);
|
||||
dsp_dmem_write(addr, val);
|
||||
}
|
||||
|
||||
// SI @M, #I
|
||||
// 0001 0110 mmmm mmmm
|
||||
// iiii iiii iiii iiii
|
||||
// Store 16-bit immediate value I to a memory location pointed by address
|
||||
// M (M is 8-bit value sign extended).
|
||||
void si(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 addr = (s8)opc.hex;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_dmem_write(addr, imm);
|
||||
}
|
||||
|
||||
// LRR $D, @$S
|
||||
// 0001 1000 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
}
|
||||
|
||||
// LRRD $D, @$S
|
||||
// 0001 1000 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||
// Decrement register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_decrement_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRI $D, @$S
|
||||
// 0001 1001 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Increment register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_increment_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRN $D, @$S
|
||||
// 0001 1001 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Add indexing register $(0x4+S) to register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
|
||||
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
}
|
||||
|
||||
// SRR @$D, $S
|
||||
// 0001 1010 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
}
|
||||
|
||||
// SRRD @$D, $S
|
||||
// 0001 1010 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Decrement register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
dsp_decrement_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRI @$D, $S
|
||||
// 0001 1011 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Increment register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
dsp_increment_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRN @$D, $S
|
||||
// 0001 1011 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
|
||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
||||
}
|
||||
|
||||
// ILRR $acD.m, @$arS
|
||||
// 0000 001d 0001 00ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m.
|
||||
void ilrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
}
|
||||
|
||||
// ILRRD $acD.m, @$arS
|
||||
// 0000 001d 0001 01ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
|
||||
void ilrrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
dsp_decrement_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRI $acD.m, @$S
|
||||
// 0000 001d 0001 10ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
|
||||
void ilrri(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
dsp_increment_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRN $acD.m, @$arS
|
||||
// 0000 001d 0001 11ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Add corresponding indexing
|
||||
// register $ixS to addressing register $arS.
|
||||
void ilrrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
|
||||
dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
#include "DSPMemoryMap.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
// SRS @M, $(0x18+S)
|
||||
// 0010 1sss mmmm mmmm
|
||||
// Move value from register $(0x18+D) to data memory pointed by address CR[0-7] | M.
|
||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||
// lower 8 bits are from the 8-bit immediate.
|
||||
// Note: pc+=2 in duddie's doc seems wrong
|
||||
void srs(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||
dsp_dmem_write(addr, g_dsp.r[reg]);
|
||||
}
|
||||
|
||||
// LRS $(0x18+D), @M
|
||||
// 0010 0ddd mmmm mmmm
|
||||
// Move value from data memory pointed by address CR[0-7] | M to register $(0x18+D).
|
||||
// That is, the upper 8 bits of the address are the bottom 8 bits from CR, and the
|
||||
// lower 8 bits are from the 8-bit immediate.
|
||||
void lrs(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||
u16 addr = (g_dsp.r[DSP_REG_CR] << 8) | (opc.hex & 0xFF);
|
||||
g_dsp.r[reg] = dsp_dmem_read(addr);
|
||||
}
|
||||
|
||||
// LR $D, @M
|
||||
// 0000 0000 110d dddd
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Move value from data memory pointed by address M to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_dmem_read(addr);
|
||||
dsp_op_write_reg(reg, val);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// SR @M, $S
|
||||
// 0000 0000 111s ssss
|
||||
// mmmm mmmm mmmm mmmm
|
||||
// Store value from register $S to a memory pointed by address M.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void sr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 addr = dsp_fetch_code();
|
||||
u16 val = dsp_op_read_reg(reg);
|
||||
dsp_dmem_write(addr, val);
|
||||
}
|
||||
|
||||
// SI @M, #I
|
||||
// 0001 0110 mmmm mmmm
|
||||
// iiii iiii iiii iiii
|
||||
// Store 16-bit immediate value I to a memory location pointed by address
|
||||
// M (M is 8-bit value sign extended).
|
||||
void si(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 addr = (s8)opc.hex;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_dmem_write(addr, imm);
|
||||
}
|
||||
|
||||
// LRR $D, @$S
|
||||
// 0001 1000 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
}
|
||||
|
||||
// LRRD $D, @$S
|
||||
// 0001 1000 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S toregister $D.
|
||||
// Decrement register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_decrement_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRI $D, @$S
|
||||
// 0001 1001 0ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Increment register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
dsp_increment_addr_reg(sreg);
|
||||
}
|
||||
|
||||
// LRRN $D, @$S
|
||||
// 0001 1001 1ssd dddd
|
||||
// Move value from data memory pointed by addressing register $S to register $D.
|
||||
// Add indexing register $(0x4+S) to register $S.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lrrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = (opc.hex >> 5) & 0x3;
|
||||
u8 dreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_dmem_read(g_dsp.r[sreg]);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
// g_dsp.r[sreg] += g_dsp.r[DSP_REG_IX0 + sreg];
|
||||
dsp_increase_addr_reg(sreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
}
|
||||
|
||||
// SRR @$D, $S
|
||||
// 0001 1010 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
}
|
||||
|
||||
// SRRD @$D, $S
|
||||
// 0001 1010 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Decrement register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
dsp_decrement_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRI @$D, $S
|
||||
// 0001 1011 0dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Increment register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
dsp_increment_addr_reg(dreg);
|
||||
}
|
||||
|
||||
// SRRN @$D, $S
|
||||
// 0001 1011 1dds ssss
|
||||
// Store value from source register $S to a memory location pointed by
|
||||
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||
// FIXME: Perform additional operation depending on source register.
|
||||
void srrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = (opc.hex >> 5) & 0x3;
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||
// g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
|
||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + dreg]);
|
||||
}
|
||||
|
||||
// ILRR $acD.m, @$arS
|
||||
// 0000 001d 0001 00ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m.
|
||||
void ilrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
}
|
||||
|
||||
// ILRRD $acD.m, @$arS
|
||||
// 0000 001d 0001 01ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Decrement addressing register $arS.
|
||||
void ilrrd(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
dsp_decrement_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRI $acD.m, @$S
|
||||
// 0000 001d 0001 10ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Increment addressing register $arS.
|
||||
void ilrri(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
dsp_increment_addr_reg(reg);
|
||||
}
|
||||
|
||||
// ILRRN $acD.m, @$arS
|
||||
// 0000 001d 0001 11ss
|
||||
// Move value from instruction memory pointed by addressing register
|
||||
// $arS to mid accumulator register $acD.m. Add corresponding indexing
|
||||
// register $ixS to addressing register $arS.
|
||||
void ilrrn(const UDSPInstruction& opc)
|
||||
{
|
||||
u16 reg = opc.hex & 0x3;
|
||||
u16 dreg = DSP_REG_ACM0 + ((opc.hex >> 8) & 1);
|
||||
|
||||
g_dsp.r[dreg] = dsp_imem_read(g_dsp.r[reg]);
|
||||
|
||||
// g_dsp.r[reg] += g_dsp.r[DSP_REG_IX0 + reg];
|
||||
dsp_increase_addr_reg(reg, (s16)g_dsp.r[DSP_REG_IX0 + reg]);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -1,202 +1,202 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
#include "DSPCore.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void unknown(const UDSPInstruction& opc)
|
||||
{
|
||||
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
|
||||
}
|
||||
|
||||
// MRR $D, $S
|
||||
// 0001 11dd ddds ssss
|
||||
// Move value from register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void mrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
u8 dreg = (opc.hex >> 5) & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
}
|
||||
|
||||
// LRI $D, #I
|
||||
// 0000 0000 100d dddd
|
||||
// iiii iiii iiii iiii
|
||||
// Load immediate value I to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
|
||||
// DSPSpy discovery: This, and possibly other instructions that load a register,
|
||||
// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
|
||||
// to the whole accumulator! This does not happen in S16 mode.
|
||||
void lri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// LRIS $(0x18+D), #I
|
||||
// 0000 1ddd iiii iiii
|
||||
// Load immediate value I (8-bit sign extended) to accumulator register.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lris(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
|
||||
u16 imm = (s8)opc.hex;
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
|
||||
// TSTAXL $acR
|
||||
// 1000 r001 xxxx xxxx
|
||||
// r specifies one of the main accumulators.
|
||||
// Definitely not a test instruction - it changes the accums.
|
||||
// Not affected by m0/m2. Not affected by s16/s40.
|
||||
void tstaxl(const UDSPInstruction& opc)
|
||||
{
|
||||
// This is probably all wrong.
|
||||
//u8 reg = (opc.hex >> 8) & 0x1;
|
||||
//s16 val = dsp_get_ax_l(reg);
|
||||
//Update_SR_Register16(val);
|
||||
}
|
||||
|
||||
// ADDARN $arD, $ixS
|
||||
// 0000 0000 0001 ssdd
|
||||
// Adds indexing register $ixS to an addressing register $arD.
|
||||
void addarn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = opc.hex & 0x3;
|
||||
u8 sreg = (opc.hex >> 2) & 0x3;
|
||||
|
||||
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
|
||||
|
||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
|
||||
// It is critical for the Zelda ucode that this one wraps correctly.
|
||||
}
|
||||
|
||||
// NX
|
||||
// 1000 -000 xxxx xxxx
|
||||
// No operation, but can be extended with extended opcode.
|
||||
void nx(const UDSPInstruction& opc)
|
||||
{
|
||||
// This opcode is supposed to do nothing - it's used if you want to use
|
||||
// an opcode extension but not do anything. At least according to duddie.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// DAR $arD ?
|
||||
// 0000 0000 0000 01dd
|
||||
// Decrement address register $arD.
|
||||
void dar(const UDSPInstruction& opc)
|
||||
{
|
||||
dsp_decrement_addr_reg(opc.hex & 0x3);
|
||||
}
|
||||
|
||||
// IAR $arD ?
|
||||
// 0000 0000 0000 10dd
|
||||
// Increment address register $arD.
|
||||
void iar(const UDSPInstruction& opc)
|
||||
{
|
||||
dsp_increment_addr_reg(opc.hex & 0x3);
|
||||
}
|
||||
|
||||
// SBCLR #I
|
||||
// 0001 0011 0000 0iii
|
||||
// bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void sbclr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 bit = (opc.hex & 0xff) + 6;
|
||||
g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
// SBSET #I
|
||||
// 0001 0010 0000 0iii
|
||||
// Set bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void sbset(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 bit = (opc.hex & 0xff) + 6;
|
||||
g_dsp.r[DSP_REG_SR] |= (1 << bit);
|
||||
}
|
||||
|
||||
|
||||
// FIXME inside
|
||||
// This is a bunch of flag setters, flipping bits in SR. So far so good,
|
||||
// but it's harder to know exactly what effect they have.
|
||||
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
|
||||
//
|
||||
// SET16 changes something very important: see the LRI instruction above.
|
||||
// Hermes' demo sets the following defaults:
|
||||
// SET40
|
||||
// CLR15
|
||||
// M0
|
||||
void srbith(const UDSPInstruction& opc)
|
||||
{
|
||||
switch ((opc.hex >> 8) & 0xf)
|
||||
{
|
||||
// M0 seems to be the default. M2 is used in functions in Zelda
|
||||
// and then reset with M0 at the end. Like the other bits here, it's
|
||||
// done around loops with lots of multiplications.
|
||||
// I've confirmed with DSPSpy that they flip this bit.
|
||||
case 0xa: // M2
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
|
||||
break;
|
||||
case 0xb: // M0
|
||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
|
||||
break;
|
||||
|
||||
// If set, treat multiplicands as unsigned.
|
||||
// If clear, treat them as signed.
|
||||
case 0xc: // CLR15
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
|
||||
break;
|
||||
case 0xd: // SET15
|
||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
|
||||
break;
|
||||
|
||||
// Automatic 40-bit sign extension when loading ACx.M.
|
||||
// 40 seems to be the default.
|
||||
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
|
||||
case 0xe: // SET16 (really, clear SR's 0x4000)
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
case 0xf: // SET40 (really, set SR's 0x4000)
|
||||
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Additional copyrights go to Duddie and Tratax (c) 2004
|
||||
|
||||
|
||||
#include "DSPInterpreter.h"
|
||||
|
||||
#include "DSPCore.h"
|
||||
#include "DSPIntUtil.h"
|
||||
|
||||
namespace DSPInterpreter {
|
||||
|
||||
void unknown(const UDSPInstruction& opc)
|
||||
{
|
||||
//_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
|
||||
ERROR_LOG(DSPLLE, "LLE: Unrecognized opcode 0x%04x, pc 0x%04x", opc.hex, g_dsp.pc);
|
||||
}
|
||||
|
||||
// MRR $D, $S
|
||||
// 0001 11dd ddds ssss
|
||||
// Move value from register $S to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void mrr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 sreg = opc.hex & 0x1f;
|
||||
u8 dreg = (opc.hex >> 5) & 0x1f;
|
||||
|
||||
u16 val = dsp_op_read_reg(sreg);
|
||||
dsp_op_write_reg(dreg, val);
|
||||
}
|
||||
|
||||
// LRI $D, #I
|
||||
// 0000 0000 100d dddd
|
||||
// iiii iiii iiii iiii
|
||||
// Load immediate value I to register $D.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
|
||||
// DSPSpy discovery: This, and possibly other instructions that load a register,
|
||||
// has a different behaviour in S40 mode if loaded to AC0.M: The value gets sign extended
|
||||
// to the whole accumulator! This does not happen in S16 mode.
|
||||
void lri(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = opc.hex & DSP_REG_MASK;
|
||||
u16 imm = dsp_fetch_code();
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
// LRIS $(0x18+D), #I
|
||||
// 0000 1ddd iiii iiii
|
||||
// Load immediate value I (8-bit sign extended) to accumulator register.
|
||||
// FIXME: Perform additional operation depending on destination register.
|
||||
void lris(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
|
||||
u16 imm = (s8)opc.hex;
|
||||
dsp_op_write_reg(reg, imm);
|
||||
dsp_conditional_extend_accum(reg);
|
||||
}
|
||||
|
||||
|
||||
// TSTAXL $acR
|
||||
// 1000 r001 xxxx xxxx
|
||||
// r specifies one of the main accumulators.
|
||||
// Definitely not a test instruction - it changes the accums.
|
||||
// Not affected by m0/m2. Not affected by s16/s40.
|
||||
void tstaxl(const UDSPInstruction& opc)
|
||||
{
|
||||
// This is probably all wrong.
|
||||
//u8 reg = (opc.hex >> 8) & 0x1;
|
||||
//s16 val = dsp_get_ax_l(reg);
|
||||
//Update_SR_Register16(val);
|
||||
}
|
||||
|
||||
// ADDARN $arD, $ixS
|
||||
// 0000 0000 0001 ssdd
|
||||
// Adds indexing register $ixS to an addressing register $arD.
|
||||
void addarn(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 dreg = opc.hex & 0x3;
|
||||
u8 sreg = (opc.hex >> 2) & 0x3;
|
||||
|
||||
// g_dsp.r[dreg] += (s16)g_dsp.r[DSP_REG_IX0 + sreg];
|
||||
|
||||
dsp_increase_addr_reg(dreg, (s16)g_dsp.r[DSP_REG_IX0 + sreg]);
|
||||
|
||||
// It is critical for the Zelda ucode that this one wraps correctly.
|
||||
}
|
||||
|
||||
// NX
|
||||
// 1000 -000 xxxx xxxx
|
||||
// No operation, but can be extended with extended opcode.
|
||||
void nx(const UDSPInstruction& opc)
|
||||
{
|
||||
// This opcode is supposed to do nothing - it's used if you want to use
|
||||
// an opcode extension but not do anything. At least according to duddie.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
// DAR $arD ?
|
||||
// 0000 0000 0000 01dd
|
||||
// Decrement address register $arD.
|
||||
void dar(const UDSPInstruction& opc)
|
||||
{
|
||||
dsp_decrement_addr_reg(opc.hex & 0x3);
|
||||
}
|
||||
|
||||
// IAR $arD ?
|
||||
// 0000 0000 0000 10dd
|
||||
// Increment address register $arD.
|
||||
void iar(const UDSPInstruction& opc)
|
||||
{
|
||||
dsp_increment_addr_reg(opc.hex & 0x3);
|
||||
}
|
||||
|
||||
// SBCLR #I
|
||||
// 0001 0011 0000 0iii
|
||||
// bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void sbclr(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 bit = (opc.hex & 0xff) + 6;
|
||||
g_dsp.r[DSP_REG_SR] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
// SBSET #I
|
||||
// 0001 0010 0000 0iii
|
||||
// Set bit of status register $sr. Bit number is calculated by adding 6 to
|
||||
// immediate value I.
|
||||
void sbset(const UDSPInstruction& opc)
|
||||
{
|
||||
u8 bit = (opc.hex & 0xff) + 6;
|
||||
g_dsp.r[DSP_REG_SR] |= (1 << bit);
|
||||
}
|
||||
|
||||
|
||||
// FIXME inside
|
||||
// This is a bunch of flag setters, flipping bits in SR. So far so good,
|
||||
// but it's harder to know exactly what effect they have.
|
||||
// M0/M2 change the multiplier mode (it can multiply by 2 for free).
|
||||
//
|
||||
// SET16 changes something very important: see the LRI instruction above.
|
||||
// Hermes' demo sets the following defaults:
|
||||
// SET40
|
||||
// CLR15
|
||||
// M0
|
||||
void srbith(const UDSPInstruction& opc)
|
||||
{
|
||||
switch ((opc.hex >> 8) & 0xf)
|
||||
{
|
||||
// M0 seems to be the default. M2 is used in functions in Zelda
|
||||
// and then reset with M0 at the end. Like the other bits here, it's
|
||||
// done around loops with lots of multiplications.
|
||||
// I've confirmed with DSPSpy that they flip this bit.
|
||||
case 0xa: // M2
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_MODIFY;
|
||||
break;
|
||||
case 0xb: // M0
|
||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_MODIFY;
|
||||
break;
|
||||
|
||||
// If set, treat multiplicands as unsigned.
|
||||
// If clear, treat them as signed.
|
||||
case 0xc: // CLR15
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_MUL_UNSIGNED;
|
||||
break;
|
||||
case 0xd: // SET15
|
||||
g_dsp.r[DSP_REG_SR] |= SR_MUL_UNSIGNED;
|
||||
break;
|
||||
|
||||
// Automatic 40-bit sign extension when loading ACx.M.
|
||||
// 40 seems to be the default.
|
||||
// Confirmed these by using DSPSpy and copying the value of SR to R00 after setting.
|
||||
case 0xe: // SET16 (really, clear SR's 0x4000)
|
||||
g_dsp.r[DSP_REG_SR] &= ~SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
case 0xf: // SET40 (really, set SR's 0x4000)
|
||||
g_dsp.r[DSP_REG_SR] |= SR_40_MODE_BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,85 +1,85 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "LabelMap.h"
|
||||
#include "DSPTables.h"
|
||||
|
||||
LabelMap::LabelMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LabelMap::RegisterDefaults()
|
||||
{
|
||||
for (int i = 0; i < 0x24; i++)
|
||||
{
|
||||
if (regnames[i].name)
|
||||
RegisterLabel(regnames[i].name, regnames[i].addr);
|
||||
}
|
||||
for (int i = 0; i < (int)pdlabels_size; i++)
|
||||
{
|
||||
if (pdlabels[i].name)
|
||||
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
|
||||
{
|
||||
u16 old_value;
|
||||
if (GetLabelValue(label, &old_value) && old_value != lval)
|
||||
{
|
||||
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
|
||||
label.c_str(), lval, old_value);
|
||||
DeleteLabel(label);
|
||||
}
|
||||
labels.push_back(label_t(label, lval, type));
|
||||
}
|
||||
|
||||
void LabelMap::DeleteLabel(const std::string &label)
|
||||
{
|
||||
for (std::vector<label_t>::iterator iter = labels.begin();
|
||||
iter != labels.end(); ++iter)
|
||||
{
|
||||
if (!label.compare(iter->name))
|
||||
{
|
||||
labels.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
|
||||
{
|
||||
for (u32 i = 0; i < labels.size(); i++)
|
||||
{
|
||||
if (!label.compare(labels[i].name))
|
||||
{
|
||||
if (type & labels[i].type) {
|
||||
*value = labels[i].addr;
|
||||
return true;
|
||||
} else {
|
||||
printf("WARNING: Wrong label type requested. %s\n", label.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LabelMap::Clear()
|
||||
{
|
||||
labels.clear();
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "LabelMap.h"
|
||||
#include "DSPTables.h"
|
||||
|
||||
LabelMap::LabelMap()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LabelMap::RegisterDefaults()
|
||||
{
|
||||
for (int i = 0; i < 0x24; i++)
|
||||
{
|
||||
if (regnames[i].name)
|
||||
RegisterLabel(regnames[i].name, regnames[i].addr);
|
||||
}
|
||||
for (int i = 0; i < (int)pdlabels_size; i++)
|
||||
{
|
||||
if (pdlabels[i].name)
|
||||
RegisterLabel(pdlabels[i].name, pdlabels[i].addr);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelMap::RegisterLabel(const std::string &label, u16 lval, LabelType type)
|
||||
{
|
||||
u16 old_value;
|
||||
if (GetLabelValue(label, &old_value) && old_value != lval)
|
||||
{
|
||||
printf("WARNING: Redefined label %s to %04x - old value %04x\n",
|
||||
label.c_str(), lval, old_value);
|
||||
DeleteLabel(label);
|
||||
}
|
||||
labels.push_back(label_t(label, lval, type));
|
||||
}
|
||||
|
||||
void LabelMap::DeleteLabel(const std::string &label)
|
||||
{
|
||||
for (std::vector<label_t>::iterator iter = labels.begin();
|
||||
iter != labels.end(); ++iter)
|
||||
{
|
||||
if (!label.compare(iter->name))
|
||||
{
|
||||
labels.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LabelMap::GetLabelValue(const std::string &label, u16 *value, LabelType type) const
|
||||
{
|
||||
for (u32 i = 0; i < labels.size(); i++)
|
||||
{
|
||||
if (!label.compare(labels[i].name))
|
||||
{
|
||||
if (type & labels[i].type) {
|
||||
*value = labels[i].addr;
|
||||
return true;
|
||||
} else {
|
||||
printf("WARNING: Wrong label type requested. %s\n", label.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void LabelMap::Clear()
|
||||
{
|
||||
labels.clear();
|
||||
}
|
||||
|
@ -1,55 +1,55 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _LABELMAP_H
|
||||
#define _LABELMAP_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
enum LabelType
|
||||
{
|
||||
LABEL_IADDR = 1, // Jump addresses, etc
|
||||
LABEL_DADDR = 2, // Data addresses, etc
|
||||
LABEL_VALUE = 4,
|
||||
LABEL_ANY = 0xFF,
|
||||
};
|
||||
|
||||
class LabelMap
|
||||
{
|
||||
struct label_t
|
||||
{
|
||||
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
|
||||
std::string name;
|
||||
s32 addr;
|
||||
LabelType type;
|
||||
};
|
||||
std::vector<label_t> labels;
|
||||
|
||||
public:
|
||||
LabelMap();
|
||||
~LabelMap() { }
|
||||
void RegisterDefaults();
|
||||
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
|
||||
void DeleteLabel(const std::string &label);
|
||||
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
|
||||
void Clear();
|
||||
};
|
||||
|
||||
#endif // _LABELMAP_H
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _LABELMAP_H
|
||||
#define _LABELMAP_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
enum LabelType
|
||||
{
|
||||
LABEL_IADDR = 1, // Jump addresses, etc
|
||||
LABEL_DADDR = 2, // Data addresses, etc
|
||||
LABEL_VALUE = 4,
|
||||
LABEL_ANY = 0xFF,
|
||||
};
|
||||
|
||||
class LabelMap
|
||||
{
|
||||
struct label_t
|
||||
{
|
||||
label_t(const std::string &lbl, s32 address, LabelType ltype) : name(lbl), addr(address), type(ltype) {}
|
||||
std::string name;
|
||||
s32 addr;
|
||||
LabelType type;
|
||||
};
|
||||
std::vector<label_t> labels;
|
||||
|
||||
public:
|
||||
LabelMap();
|
||||
~LabelMap() { }
|
||||
void RegisterDefaults();
|
||||
void RegisterLabel(const std::string &label, u16 lval, LabelType type = LABEL_VALUE);
|
||||
void DeleteLabel(const std::string &label);
|
||||
bool GetLabelValue(const std::string &label, u16 *value, LabelType type = LABEL_ANY) const;
|
||||
void Clear();
|
||||
};
|
||||
|
||||
#endif // _LABELMAP_H
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,139 +1,139 @@
|
||||
/*====================================================================
|
||||
|
||||
project: GameCube DSP Tool (gcdsp)
|
||||
created: 2005.03.04
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#ifndef _DSP_ASSEMBLE_H
|
||||
#define _DSP_ASSEMBLE_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "disassemble.h"
|
||||
#include "DSPTables.h"
|
||||
#include "LabelMap.h"
|
||||
|
||||
enum err_t
|
||||
{
|
||||
ERR_OK = 0,
|
||||
ERR_UNKNOWN,
|
||||
ERR_UNKNOWN_OPCODE,
|
||||
ERR_NOT_ENOUGH_PARAMETERS,
|
||||
ERR_TOO_MANY_PARAMETERS,
|
||||
ERR_WRONG_PARAMETER,
|
||||
ERR_EXPECTED_PARAM_STR,
|
||||
ERR_EXPECTED_PARAM_VAL,
|
||||
ERR_EXPECTED_PARAM_REG,
|
||||
ERR_EXPECTED_PARAM_MEM,
|
||||
ERR_EXPECTED_PARAM_IMM,
|
||||
ERR_INCORRECT_BIN,
|
||||
ERR_INCORRECT_HEX,
|
||||
ERR_INCORRECT_DEC,
|
||||
ERR_LABEL_EXISTS,
|
||||
ERR_UNKNOWN_LABEL,
|
||||
ERR_NO_MATCHING_BRACKETS,
|
||||
ERR_EXT_CANT_EXTEND_OPCODE,
|
||||
ERR_EXT_PAR_NOT_EXT,
|
||||
ERR_WRONG_PARAMETER_ACC,
|
||||
ERR_WRONG_PARAMETER_MID_ACC,
|
||||
ERR_INVALID_REGISTER,
|
||||
ERR_OUT_RANGE_NUMBER
|
||||
};
|
||||
|
||||
|
||||
// Unless you want labels to carry over between files, you probably
|
||||
// want to create a new DSPAssembler for every file you assemble.
|
||||
class DSPAssembler
|
||||
{
|
||||
public:
|
||||
DSPAssembler(const AssemblerSettings &settings);
|
||||
~DSPAssembler();
|
||||
|
||||
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
|
||||
// one for each word of code, indicating the source assembler code line number it came from.
|
||||
|
||||
// If returns false, call GetErrorString to get some text to present to the user.
|
||||
bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
|
||||
|
||||
std::string GetErrorString() const { return last_error_str; }
|
||||
err_t GetError() const { return last_error; }
|
||||
|
||||
private:
|
||||
struct param_t
|
||||
{
|
||||
u32 val;
|
||||
partype_t type;
|
||||
char *str;
|
||||
};
|
||||
|
||||
enum segment_t
|
||||
{
|
||||
SEGMENT_CODE = 0,
|
||||
SEGMENT_DATA,
|
||||
SEGMENT_OVERLAY,
|
||||
SEGMENT_MAX
|
||||
};
|
||||
|
||||
// Utility functions
|
||||
s32 ParseValue(const char *str);
|
||||
u32 ParseExpression(const char *ptr);
|
||||
|
||||
u32 GetParams(char *parstr, param_t *par);
|
||||
|
||||
void InitPass(int pass);
|
||||
bool AssembleFile(const char *fname, int pass);
|
||||
|
||||
void ShowError(err_t err_code, const char *extra_info = NULL);
|
||||
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
|
||||
|
||||
char *FindBrackets(char *src, char *dst);
|
||||
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
|
||||
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
|
||||
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
|
||||
|
||||
char *gdg_buffer;
|
||||
|
||||
std::string include_dir;
|
||||
std::string cur_line;
|
||||
|
||||
u32 m_cur_addr;
|
||||
int m_totalSize;
|
||||
u8 m_cur_pass;
|
||||
|
||||
LabelMap labels;
|
||||
|
||||
u32 code_line;
|
||||
bool failed;
|
||||
std::string last_error_str;
|
||||
err_t last_error;
|
||||
|
||||
typedef std::map<std::string, std::string> AliasMap;
|
||||
AliasMap aliases;
|
||||
|
||||
segment_t cur_segment;
|
||||
u32 segment_addr[SEGMENT_MAX];
|
||||
int m_current_param;
|
||||
const AssemblerSettings settings_;
|
||||
};
|
||||
|
||||
#endif // _DSP_ASSEMBLE_H
|
||||
/*====================================================================
|
||||
|
||||
project: GameCube DSP Tool (gcdsp)
|
||||
created: 2005.03.04
|
||||
mail: duddie@walla.com
|
||||
|
||||
Copyright (c) 2005 Duddie
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
====================================================================*/
|
||||
|
||||
#ifndef _DSP_ASSEMBLE_H
|
||||
#define _DSP_ASSEMBLE_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "disassemble.h"
|
||||
#include "DSPTables.h"
|
||||
#include "LabelMap.h"
|
||||
|
||||
enum err_t
|
||||
{
|
||||
ERR_OK = 0,
|
||||
ERR_UNKNOWN,
|
||||
ERR_UNKNOWN_OPCODE,
|
||||
ERR_NOT_ENOUGH_PARAMETERS,
|
||||
ERR_TOO_MANY_PARAMETERS,
|
||||
ERR_WRONG_PARAMETER,
|
||||
ERR_EXPECTED_PARAM_STR,
|
||||
ERR_EXPECTED_PARAM_VAL,
|
||||
ERR_EXPECTED_PARAM_REG,
|
||||
ERR_EXPECTED_PARAM_MEM,
|
||||
ERR_EXPECTED_PARAM_IMM,
|
||||
ERR_INCORRECT_BIN,
|
||||
ERR_INCORRECT_HEX,
|
||||
ERR_INCORRECT_DEC,
|
||||
ERR_LABEL_EXISTS,
|
||||
ERR_UNKNOWN_LABEL,
|
||||
ERR_NO_MATCHING_BRACKETS,
|
||||
ERR_EXT_CANT_EXTEND_OPCODE,
|
||||
ERR_EXT_PAR_NOT_EXT,
|
||||
ERR_WRONG_PARAMETER_ACC,
|
||||
ERR_WRONG_PARAMETER_MID_ACC,
|
||||
ERR_INVALID_REGISTER,
|
||||
ERR_OUT_RANGE_NUMBER
|
||||
};
|
||||
|
||||
|
||||
// Unless you want labels to carry over between files, you probably
|
||||
// want to create a new DSPAssembler for every file you assemble.
|
||||
class DSPAssembler
|
||||
{
|
||||
public:
|
||||
DSPAssembler(const AssemblerSettings &settings);
|
||||
~DSPAssembler();
|
||||
|
||||
// line_numbers is optional (and not yet implemented). It'll receieve a list of ints,
|
||||
// one for each word of code, indicating the source assembler code line number it came from.
|
||||
|
||||
// If returns false, call GetErrorString to get some text to present to the user.
|
||||
bool Assemble(const char *text, std::vector<u16> &code, std::vector<int> *line_numbers = NULL);
|
||||
|
||||
std::string GetErrorString() const { return last_error_str; }
|
||||
err_t GetError() const { return last_error; }
|
||||
|
||||
private:
|
||||
struct param_t
|
||||
{
|
||||
u32 val;
|
||||
partype_t type;
|
||||
char *str;
|
||||
};
|
||||
|
||||
enum segment_t
|
||||
{
|
||||
SEGMENT_CODE = 0,
|
||||
SEGMENT_DATA,
|
||||
SEGMENT_OVERLAY,
|
||||
SEGMENT_MAX
|
||||
};
|
||||
|
||||
// Utility functions
|
||||
s32 ParseValue(const char *str);
|
||||
u32 ParseExpression(const char *ptr);
|
||||
|
||||
u32 GetParams(char *parstr, param_t *par);
|
||||
|
||||
void InitPass(int pass);
|
||||
bool AssembleFile(const char *fname, int pass);
|
||||
|
||||
void ShowError(err_t err_code, const char *extra_info = NULL);
|
||||
// void ShowWarning(err_t err_code, const char *extra_info = NULL);
|
||||
|
||||
char *FindBrackets(char *src, char *dst);
|
||||
const opc_t *FindOpcode(const char *opcode, u32 par_count, const opc_t * const opcod, int opcod_size);
|
||||
bool VerifyParams(const opc_t *opc, param_t *par, int count, bool ext = false);
|
||||
void BuildCode(const opc_t *opc, param_t *par, u32 par_count, u16 *outbuf);
|
||||
|
||||
char *gdg_buffer;
|
||||
|
||||
std::string include_dir;
|
||||
std::string cur_line;
|
||||
|
||||
u32 m_cur_addr;
|
||||
int m_totalSize;
|
||||
u8 m_cur_pass;
|
||||
|
||||
LabelMap labels;
|
||||
|
||||
u32 code_line;
|
||||
bool failed;
|
||||
std::string last_error_str;
|
||||
err_t last_error;
|
||||
|
||||
typedef std::map<std::string, std::string> AliasMap;
|
||||
AliasMap aliases;
|
||||
|
||||
segment_t cur_segment;
|
||||
u32 segment_addr[SEGMENT_MAX];
|
||||
int m_current_param;
|
||||
const AssemblerSettings settings_;
|
||||
};
|
||||
|
||||
#endif // _DSP_ASSEMBLE_H
|
||||
|
@ -1,23 +1,23 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "DebuggerUIUtil.h"
|
||||
|
||||
// The default font
|
||||
wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));
|
||||
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "DebuggerUIUtil.h"
|
||||
|
||||
// The default font
|
||||
wxFont DebuggerFont = wxFont(9, wxMODERN, wxNORMAL, wxNORMAL, false, wxT("monospace"));
|
||||
|
||||
|
@ -1,36 +1,36 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DEBUGGER_UI_UTIL_H
|
||||
#define _DEBUGGER_UI_UTIL_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#define wxUSE_XPM_IN_MSW 1
|
||||
#define USE_XPM_BITMAPS 1
|
||||
|
||||
// Defined in CodeWindow.cpp
|
||||
extern wxFont DebuggerFont;
|
||||
|
||||
// define this to use XPMs everywhere (by default, BMPs are used under Win)
|
||||
// BMPs use less space, but aren't compiled into the executable on other platforms
|
||||
|
||||
#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
|
||||
#error You need to enable XPM support to use XPM bitmaps with toolbar!
|
||||
#endif // USE_XPM_BITMAPS
|
||||
|
||||
#endif
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _DEBUGGER_UI_UTIL_H
|
||||
#define _DEBUGGER_UI_UTIL_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
#define wxUSE_XPM_IN_MSW 1
|
||||
#define USE_XPM_BITMAPS 1
|
||||
|
||||
// Defined in CodeWindow.cpp
|
||||
extern wxFont DebuggerFont;
|
||||
|
||||
// define this to use XPMs everywhere (by default, BMPs are used under Win)
|
||||
// BMPs use less space, but aren't compiled into the executable on other platforms
|
||||
|
||||
#if USE_XPM_BITMAPS && defined (__WXMSW__) && !wxUSE_XPM_IN_MSW
|
||||
#error You need to enable XPM support to use XPM bitmaps with toolbar!
|
||||
#endif // USE_XPM_BITMAPS
|
||||
|
||||
#endif
|
||||
|
@ -1,100 +1,100 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NAND_CONTENT_LOADER_H
|
||||
#define _NAND_CONTENT_LOADER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Blob.h"
|
||||
#include "Volume.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
struct SNANDContent
|
||||
{
|
||||
u32 m_ContentID;
|
||||
u16 m_Index;
|
||||
u16 m_Type;
|
||||
u32 m_Size;
|
||||
u8 m_SHA1Hash[20];
|
||||
u8 m_Header[36]; //all of the above
|
||||
|
||||
u8* m_pData;
|
||||
};
|
||||
|
||||
// pure virtual interface so just the NANDContentManager can create these files only
|
||||
class INANDContentLoader
|
||||
{
|
||||
public:
|
||||
|
||||
INANDContentLoader() {}
|
||||
|
||||
virtual ~INANDContentLoader() {}
|
||||
|
||||
virtual bool IsValid() const = 0;
|
||||
virtual u64 GetTitleID() const = 0;
|
||||
virtual u16 GetIosVersion() const = 0;
|
||||
virtual u32 GetBootIndex() const = 0;
|
||||
virtual size_t GetContentSize() const = 0;
|
||||
virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
|
||||
virtual const u8* GetTicketView() const = 0;
|
||||
virtual const u8* GetTmdHeader() const = 0;
|
||||
virtual const std::vector<SNANDContent>& GetContent() const = 0;
|
||||
virtual const u16 GetTitleVersion() const = 0;
|
||||
virtual const u16 GetNumEntries() const = 0;
|
||||
virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
|
||||
|
||||
enum
|
||||
{
|
||||
TICKET_VIEW_SIZE = 0x58,
|
||||
TMD_HEADER_SIZE = 0x1e4,
|
||||
CONTENT_HEADER_SIZE = 0x24
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// we open the NAND Content files to often... lets cache them
|
||||
class CNANDContentManager
|
||||
{
|
||||
public:
|
||||
|
||||
static CNANDContentManager& Access() { return m_Instance; }
|
||||
|
||||
const INANDContentLoader& GetNANDLoader(const std::string& _rName);
|
||||
|
||||
private:
|
||||
|
||||
CNANDContentManager() {};
|
||||
|
||||
~CNANDContentManager();
|
||||
|
||||
static CNANDContentManager m_Instance;
|
||||
|
||||
typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
|
||||
CNANDContentMap m_Map;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NAND_CONTENT_LOADER_H
|
||||
#define _NAND_CONTENT_LOADER_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Blob.h"
|
||||
#include "Volume.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
struct SNANDContent
|
||||
{
|
||||
u32 m_ContentID;
|
||||
u16 m_Index;
|
||||
u16 m_Type;
|
||||
u32 m_Size;
|
||||
u8 m_SHA1Hash[20];
|
||||
u8 m_Header[36]; //all of the above
|
||||
|
||||
u8* m_pData;
|
||||
};
|
||||
|
||||
// pure virtual interface so just the NANDContentManager can create these files only
|
||||
class INANDContentLoader
|
||||
{
|
||||
public:
|
||||
|
||||
INANDContentLoader() {}
|
||||
|
||||
virtual ~INANDContentLoader() {}
|
||||
|
||||
virtual bool IsValid() const = 0;
|
||||
virtual u64 GetTitleID() const = 0;
|
||||
virtual u16 GetIosVersion() const = 0;
|
||||
virtual u32 GetBootIndex() const = 0;
|
||||
virtual size_t GetContentSize() const = 0;
|
||||
virtual const SNANDContent* GetContentByIndex(int _Index) const = 0;
|
||||
virtual const u8* GetTicketView() const = 0;
|
||||
virtual const u8* GetTmdHeader() const = 0;
|
||||
virtual const std::vector<SNANDContent>& GetContent() const = 0;
|
||||
virtual const u16 GetTitleVersion() const = 0;
|
||||
virtual const u16 GetNumEntries() const = 0;
|
||||
virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
|
||||
|
||||
enum
|
||||
{
|
||||
TICKET_VIEW_SIZE = 0x58,
|
||||
TMD_HEADER_SIZE = 0x1e4,
|
||||
CONTENT_HEADER_SIZE = 0x24
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// we open the NAND Content files to often... lets cache them
|
||||
class CNANDContentManager
|
||||
{
|
||||
public:
|
||||
|
||||
static CNANDContentManager& Access() { return m_Instance; }
|
||||
|
||||
const INANDContentLoader& GetNANDLoader(const std::string& _rName);
|
||||
|
||||
private:
|
||||
|
||||
CNANDContentManager() {};
|
||||
|
||||
~CNANDContentManager();
|
||||
|
||||
static CNANDContentManager m_Instance;
|
||||
|
||||
typedef std::map<std::string, INANDContentLoader*> CNANDContentMap;
|
||||
CNANDContentMap m_Map;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,52 +1,52 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Volume.h"
|
||||
#include "Blob.h"
|
||||
#include "NANDContentLoader.h"
|
||||
|
||||
// --- this volume type is used for Wad files ---
|
||||
// Some of this code might look redundant with the CNANDContentLoader class, however,
|
||||
// We do not do any decryption here, we do raw read, so things are -Faster-
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
class CVolumeWAD : public IVolume
|
||||
{
|
||||
public:
|
||||
CVolumeWAD(IBlobReader* _pReader);
|
||||
~CVolumeWAD();
|
||||
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
|
||||
bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
|
||||
bool GetTitleID(u8* _pBuffer) const;
|
||||
std::string GetUniqueID() const;
|
||||
std::string GetMakerID() const;
|
||||
std::string GetName() const;
|
||||
u32 GetFSTSize() const { return 0; }
|
||||
std::string GetApploaderDate() const { return "0"; }
|
||||
ECountry GetCountry() const;
|
||||
u64 GetSize() const;
|
||||
|
||||
private:
|
||||
IBlobReader* m_pReader;
|
||||
u64 m_titleID;
|
||||
u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Volume.h"
|
||||
#include "Blob.h"
|
||||
#include "NANDContentLoader.h"
|
||||
|
||||
// --- this volume type is used for Wad files ---
|
||||
// Some of this code might look redundant with the CNANDContentLoader class, however,
|
||||
// We do not do any decryption here, we do raw read, so things are -Faster-
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
class CVolumeWAD : public IVolume
|
||||
{
|
||||
public:
|
||||
CVolumeWAD(IBlobReader* _pReader);
|
||||
~CVolumeWAD();
|
||||
bool Read(u64 _Offset, u64 _Length, u8* _pBuffer) const;
|
||||
bool RAWRead(u64 _Offset, u64 _Length, u8* _pBuffer) const { return false; }
|
||||
bool GetTitleID(u8* _pBuffer) const;
|
||||
std::string GetUniqueID() const;
|
||||
std::string GetMakerID() const;
|
||||
std::string GetName() const;
|
||||
u32 GetFSTSize() const { return 0; }
|
||||
std::string GetApploaderDate() const { return "0"; }
|
||||
ECountry GetCountry() const;
|
||||
u64 GetSize() const;
|
||||
|
||||
private:
|
||||
IBlobReader* m_pReader;
|
||||
u64 m_titleID;
|
||||
u32 OpeningBnrOffset, hdr_size, cert_size, tick_size, tmd_size, data_size;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -1,156 +1,156 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "NANDContentLoader.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include "MathUtil.h"
|
||||
#include "FileUtil.h"
|
||||
#include "Log.h"
|
||||
#include "WiiWad.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
class CBlobBigEndianReader
|
||||
{
|
||||
public:
|
||||
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
|
||||
|
||||
u32 Read32(u64 _Offset)
|
||||
{
|
||||
u32 Temp;
|
||||
m_rReader.Read(_Offset, 4, (u8*)&Temp);
|
||||
return(Common::swap32(Temp));
|
||||
}
|
||||
|
||||
private:
|
||||
DiscIO::IBlobReader& m_rReader;
|
||||
};
|
||||
|
||||
WiiWAD::WiiWAD(const std::string& _rName)
|
||||
{
|
||||
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
|
||||
if (pReader == NULL)
|
||||
{
|
||||
m_Valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_Valid = ParseWAD(*pReader);
|
||||
delete pReader;
|
||||
}
|
||||
|
||||
WiiWAD::~WiiWAD()
|
||||
{
|
||||
if (m_Valid)
|
||||
{
|
||||
delete m_pCertificateChain;
|
||||
delete m_pTicket;
|
||||
delete m_pTMD;
|
||||
delete m_pDataApp;
|
||||
delete m_pFooter;
|
||||
}
|
||||
}
|
||||
|
||||
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
|
||||
{
|
||||
if (_Size > 0)
|
||||
{
|
||||
u8* pTmpBuffer = new u8[_Size];
|
||||
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
|
||||
|
||||
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
|
||||
PanicAlert("WiiWAD: Could not read from file");
|
||||
}
|
||||
return pTmpBuffer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
|
||||
{
|
||||
CBlobBigEndianReader ReaderBig(_rReader);
|
||||
|
||||
// get header size
|
||||
u32 HeaderSize = ReaderBig.Read32(0);
|
||||
if (HeaderSize != 0x20)
|
||||
{
|
||||
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
|
||||
return false;
|
||||
}
|
||||
|
||||
// get header
|
||||
u8 Header[0x20];
|
||||
_rReader.Read(0, HeaderSize, Header);
|
||||
u32 HeaderType = ReaderBig.Read32(0x4);
|
||||
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
|
||||
return false;
|
||||
|
||||
m_CertificateChainSize = ReaderBig.Read32(0x8);
|
||||
u32 Reserved = ReaderBig.Read32(0xC);
|
||||
m_TicketSize = ReaderBig.Read32(0x10);
|
||||
m_TMDSize = ReaderBig.Read32(0x14);
|
||||
m_DataAppSize = ReaderBig.Read32(0x18);
|
||||
m_FooterSize = ReaderBig.Read32(0x1C);
|
||||
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
|
||||
|
||||
u32 Offset = 0x40;
|
||||
m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
|
||||
m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
|
||||
m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
|
||||
m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
|
||||
m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiiWAD::IsWiiWAD(const std::string& _rName)
|
||||
{
|
||||
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
|
||||
if (pReader == NULL)
|
||||
return false;
|
||||
|
||||
CBlobBigEndianReader Reader(*pReader);
|
||||
bool Result = false;
|
||||
|
||||
// check for wii wad
|
||||
if (Reader.Read32(0x00) == 0x20)
|
||||
{
|
||||
u32 WADTYpe = Reader.Read32(0x04);
|
||||
switch(WADTYpe)
|
||||
{
|
||||
case 0x49730000:
|
||||
case 0x69620000:
|
||||
Result = true;
|
||||
}
|
||||
}
|
||||
|
||||
delete pReader;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace end
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "NANDContentLoader.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include "MathUtil.h"
|
||||
#include "FileUtil.h"
|
||||
#include "Log.h"
|
||||
#include "WiiWad.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
class CBlobBigEndianReader
|
||||
{
|
||||
public:
|
||||
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
|
||||
|
||||
u32 Read32(u64 _Offset)
|
||||
{
|
||||
u32 Temp;
|
||||
m_rReader.Read(_Offset, 4, (u8*)&Temp);
|
||||
return(Common::swap32(Temp));
|
||||
}
|
||||
|
||||
private:
|
||||
DiscIO::IBlobReader& m_rReader;
|
||||
};
|
||||
|
||||
WiiWAD::WiiWAD(const std::string& _rName)
|
||||
{
|
||||
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
|
||||
if (pReader == NULL)
|
||||
{
|
||||
m_Valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
m_Valid = ParseWAD(*pReader);
|
||||
delete pReader;
|
||||
}
|
||||
|
||||
WiiWAD::~WiiWAD()
|
||||
{
|
||||
if (m_Valid)
|
||||
{
|
||||
delete m_pCertificateChain;
|
||||
delete m_pTicket;
|
||||
delete m_pTMD;
|
||||
delete m_pDataApp;
|
||||
delete m_pFooter;
|
||||
}
|
||||
}
|
||||
|
||||
u8* WiiWAD::CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
|
||||
{
|
||||
if (_Size > 0)
|
||||
{
|
||||
u8* pTmpBuffer = new u8[_Size];
|
||||
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
|
||||
|
||||
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
|
||||
{
|
||||
ERROR_LOG(DISCIO, "WiiWAD: Could not read from file");
|
||||
PanicAlert("WiiWAD: Could not read from file");
|
||||
}
|
||||
return pTmpBuffer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
|
||||
{
|
||||
CBlobBigEndianReader ReaderBig(_rReader);
|
||||
|
||||
// get header size
|
||||
u32 HeaderSize = ReaderBig.Read32(0);
|
||||
if (HeaderSize != 0x20)
|
||||
{
|
||||
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
|
||||
return false;
|
||||
}
|
||||
|
||||
// get header
|
||||
u8 Header[0x20];
|
||||
_rReader.Read(0, HeaderSize, Header);
|
||||
u32 HeaderType = ReaderBig.Read32(0x4);
|
||||
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
|
||||
return false;
|
||||
|
||||
m_CertificateChainSize = ReaderBig.Read32(0x8);
|
||||
u32 Reserved = ReaderBig.Read32(0xC);
|
||||
m_TicketSize = ReaderBig.Read32(0x10);
|
||||
m_TMDSize = ReaderBig.Read32(0x14);
|
||||
m_DataAppSize = ReaderBig.Read32(0x18);
|
||||
m_FooterSize = ReaderBig.Read32(0x1C);
|
||||
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
|
||||
|
||||
u32 Offset = 0x40;
|
||||
m_pCertificateChain = CreateWADEntry(_rReader, m_CertificateChainSize, Offset); Offset += ROUND_UP(m_CertificateChainSize, 0x40);
|
||||
m_pTicket = CreateWADEntry(_rReader, m_TicketSize, Offset); Offset += ROUND_UP(m_TicketSize, 0x40);
|
||||
m_pTMD = CreateWADEntry(_rReader, m_TMDSize, Offset); Offset += ROUND_UP(m_TMDSize, 0x40);
|
||||
m_pDataApp = CreateWADEntry(_rReader, m_DataAppSize, Offset); Offset += ROUND_UP(m_DataAppSize, 0x40);
|
||||
m_pFooter = CreateWADEntry(_rReader, m_FooterSize, Offset); Offset += ROUND_UP(m_FooterSize, 0x40);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WiiWAD::IsWiiWAD(const std::string& _rName)
|
||||
{
|
||||
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_rName.c_str());
|
||||
if (pReader == NULL)
|
||||
return false;
|
||||
|
||||
CBlobBigEndianReader Reader(*pReader);
|
||||
bool Result = false;
|
||||
|
||||
// check for wii wad
|
||||
if (Reader.Read32(0x00) == 0x20)
|
||||
{
|
||||
u32 WADTYpe = Reader.Read32(0x04);
|
||||
switch(WADTYpe)
|
||||
{
|
||||
case 0x49730000:
|
||||
case 0x69620000:
|
||||
Result = true;
|
||||
}
|
||||
}
|
||||
|
||||
delete pReader;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace end
|
||||
|
||||
|
@ -1,78 +1,78 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _WII_WAD_H
|
||||
#define _WII_WAD_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Blob.h"
|
||||
#include "Volume.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
class WiiWAD
|
||||
{
|
||||
public:
|
||||
|
||||
WiiWAD(const std::string& _rName);
|
||||
|
||||
~WiiWAD();
|
||||
|
||||
bool IsValid() const { return m_Valid; }
|
||||
u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
|
||||
u32 GetTicketSize() const { return m_TicketSize; }
|
||||
u32 GetTMDSize() const { return m_TMDSize; }
|
||||
u32 GetDataAppSize() const { return m_DataAppSize; }
|
||||
u32 GetFooterSize() const { return m_FooterSize; }
|
||||
|
||||
u8* GetCertificateChain() const { return m_pCertificateChain; }
|
||||
u8* GetTicket() const { return m_pTicket; }
|
||||
u8* GetTMD() const { return m_pTMD; }
|
||||
u8* GetDataApp() const { return m_pDataApp; }
|
||||
u8* GetFooter() const { return m_pFooter; }
|
||||
|
||||
static bool IsWiiWAD(const std::string& _rName);
|
||||
|
||||
private:
|
||||
|
||||
bool m_Valid;
|
||||
|
||||
u32 m_CertificateChainSize;
|
||||
u32 m_TicketSize;
|
||||
u32 m_TMDSize;
|
||||
u32 m_DataAppSize;
|
||||
u32 m_FooterSize;
|
||||
|
||||
u8* m_pCertificateChain;
|
||||
u8* m_pTicket;
|
||||
u8* m_pTMD;
|
||||
u8* m_pDataApp;
|
||||
u8* m_pFooter;
|
||||
|
||||
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
|
||||
bool ParseWAD(DiscIO::IBlobReader& _rReader);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _WII_WAD_H
|
||||
#define _WII_WAD_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Blob.h"
|
||||
#include "Volume.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
class WiiWAD
|
||||
{
|
||||
public:
|
||||
|
||||
WiiWAD(const std::string& _rName);
|
||||
|
||||
~WiiWAD();
|
||||
|
||||
bool IsValid() const { return m_Valid; }
|
||||
u32 GetCertificateChainSize() const { return m_CertificateChainSize; }
|
||||
u32 GetTicketSize() const { return m_TicketSize; }
|
||||
u32 GetTMDSize() const { return m_TMDSize; }
|
||||
u32 GetDataAppSize() const { return m_DataAppSize; }
|
||||
u32 GetFooterSize() const { return m_FooterSize; }
|
||||
|
||||
u8* GetCertificateChain() const { return m_pCertificateChain; }
|
||||
u8* GetTicket() const { return m_pTicket; }
|
||||
u8* GetTMD() const { return m_pTMD; }
|
||||
u8* GetDataApp() const { return m_pDataApp; }
|
||||
u8* GetFooter() const { return m_pFooter; }
|
||||
|
||||
static bool IsWiiWAD(const std::string& _rName);
|
||||
|
||||
private:
|
||||
|
||||
bool m_Valid;
|
||||
|
||||
u32 m_CertificateChainSize;
|
||||
u32 m_TicketSize;
|
||||
u32 m_TMDSize;
|
||||
u32 m_DataAppSize;
|
||||
u32 m_FooterSize;
|
||||
|
||||
u8* m_pCertificateChain;
|
||||
u8* m_pTicket;
|
||||
u8* m_pTMD;
|
||||
u8* m_pDataApp;
|
||||
u8* m_pFooter;
|
||||
|
||||
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
|
||||
bool ParseWAD(DiscIO::IBlobReader& _rReader);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,288 +1,288 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "NetWindow.h"
|
||||
|
||||
void ClientSide::OnClientData(unsigned char data)
|
||||
{
|
||||
unsigned char sent = 0;
|
||||
u32 buffer_size;
|
||||
size_t recv_size;
|
||||
char *buffer = NULL;
|
||||
|
||||
switch (data)
|
||||
{
|
||||
case 0x10: // Player joined server
|
||||
{
|
||||
// Read GameFound
|
||||
m_socket.Receive((char*)&sent, 1, recv_size);
|
||||
|
||||
// Read nickname
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
|
||||
|
||||
if (sent != 0x1F)
|
||||
for (int i = 0; i < 4; i++)
|
||||
Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
|
||||
|
||||
m_numplayers++;
|
||||
Event->SendEvent(HOST_NEWPLAYER);
|
||||
break;
|
||||
}
|
||||
case 0x11: // Player left server
|
||||
{
|
||||
// Read Nickname
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
|
||||
Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
|
||||
|
||||
m_numplayers--;
|
||||
Event->SendEvent(HOST_PLAYERLEFT);
|
||||
break;
|
||||
}
|
||||
case 0x15: // Ping Player
|
||||
{
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
m_socket.Send((const char*)&buffer_size, 4);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x20: // IP request
|
||||
{
|
||||
//buffer_size = m_addr.size();
|
||||
//m_socket.Send((const char*)&buffer_size, 4);
|
||||
m_socket.Send((const char*)&data, 1);
|
||||
m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x30: // Chat message received from server
|
||||
{
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
|
||||
if (recv_size > 1024)
|
||||
{
|
||||
//something wrong...
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
Event->AppendText(wxString::FromAscii(buffer));
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x35: // ChangeGame message received
|
||||
{
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
|
||||
m_selectedgame = std::string(buffer);
|
||||
Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
|
||||
|
||||
// Tell the server if the game's been found
|
||||
m_socket.Send((const char*)&data, 1);
|
||||
CheckGameFound();
|
||||
|
||||
Event->SendEvent(GUI_UPDATE);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x40: // Ready message received
|
||||
{
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
|
||||
if (recv_size > 1024)
|
||||
{
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
Event->AppendText(wxString::FromAscii(buffer));
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x50: // Everyone is Ready message received
|
||||
{
|
||||
// Load the game and start synching
|
||||
m_netptr->LoadGame();
|
||||
|
||||
break;
|
||||
}
|
||||
case 0xA1: // Received pad data from host in versus mode
|
||||
{
|
||||
if (m_data_received)
|
||||
wxThread::Sleep(10);
|
||||
|
||||
m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
|
||||
m_data_received = true;
|
||||
|
||||
#ifdef NET_DEBUG
|
||||
char sent[64];
|
||||
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
|
||||
Event->AppendText(wxString::FromAscii(sent));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void ServerSide::OnServerData(int sock, unsigned char data)
|
||||
{
|
||||
size_t recv_size;
|
||||
char *buffer = NULL;
|
||||
unsigned char sent;
|
||||
unsigned int four_bytes;
|
||||
|
||||
switch (data)
|
||||
{
|
||||
case 0x15: // Ping Request
|
||||
{
|
||||
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
|
||||
m_client[sock].socket.Send((const char*)&four_bytes, 4);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x20: // IP request response
|
||||
{
|
||||
buffer = new char[24];
|
||||
// Read IP Address
|
||||
m_client[sock].socket.Receive(buffer, 24, recv_size);
|
||||
|
||||
Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x30: // Chat message
|
||||
{
|
||||
buffer = new char[1024];
|
||||
|
||||
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
|
||||
m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
|
||||
|
||||
if (recv_size > 1024)
|
||||
{
|
||||
//something wrong...
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
sent = 0x30;
|
||||
// Send to all
|
||||
for (int i=0; i < m_numplayers ; i++)
|
||||
{
|
||||
if (i == sock)
|
||||
continue;
|
||||
|
||||
m_client[i].socket.Send((const char*)&sent, 1);
|
||||
|
||||
m_client[1].socket.Send((const char*)&four_bytes, 4);
|
||||
m_client[i].socket.Send(buffer, recv_size);
|
||||
}
|
||||
|
||||
Event->AppendText(wxString::FromAscii(buffer));
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x35: // Change game response received
|
||||
{
|
||||
// Receive isGameFound response (0x1F / 0x1A)
|
||||
m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
|
||||
|
||||
// If game is not found
|
||||
if (sent != 0x1F)
|
||||
{
|
||||
sent = 0x30;
|
||||
|
||||
wxString error_str = wxString::Format(
|
||||
wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
|
||||
four_bytes = (int)error_str.size();
|
||||
|
||||
for (int i=0; i < 2; i++)
|
||||
Event->AppendText(error_str);
|
||||
|
||||
// Send to all
|
||||
for (int i=0; i < m_numplayers ; i++)
|
||||
{
|
||||
if (i == sock)
|
||||
continue;
|
||||
m_client[i].socket.Send((const char*)&sent, 1);
|
||||
|
||||
m_client[i].socket.Send((const char*)&four_bytes, 4);
|
||||
m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x40: // Ready message received
|
||||
{
|
||||
std::string buffer_str;
|
||||
|
||||
m_client[sock].ready = !m_client[sock].ready;
|
||||
|
||||
if (m_client[sock].ready)
|
||||
buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
|
||||
else
|
||||
buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
|
||||
|
||||
four_bytes = (int)buffer_str.size();
|
||||
|
||||
// Send to all
|
||||
for (int i=0; i < m_numplayers ; i++)
|
||||
{
|
||||
m_client[i].socket.Send((const char*)&data, 1);
|
||||
|
||||
m_client[i].socket.Send((const char*)&four_bytes, 4);
|
||||
m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
|
||||
}
|
||||
|
||||
Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
|
||||
IsEveryoneReady();
|
||||
|
||||
break;
|
||||
}
|
||||
case 0xA1: // Received pad data from a client
|
||||
{
|
||||
if (m_data_received)
|
||||
wxThread::Sleep(10);
|
||||
|
||||
m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
|
||||
m_data_received = true;
|
||||
|
||||
#ifdef NET_DEBUG
|
||||
char sent[64];
|
||||
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
|
||||
Event->AppendText(wxString::FromAscii(sent));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "NetWindow.h"
|
||||
|
||||
void ClientSide::OnClientData(unsigned char data)
|
||||
{
|
||||
unsigned char sent = 0;
|
||||
u32 buffer_size;
|
||||
size_t recv_size;
|
||||
char *buffer = NULL;
|
||||
|
||||
switch (data)
|
||||
{
|
||||
case 0x10: // Player joined server
|
||||
{
|
||||
// Read GameFound
|
||||
m_socket.Receive((char*)&sent, 1, recv_size);
|
||||
|
||||
// Read nickname
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
Event->AppendText(wxString::Format(wxT("*Player : %s is now connected to Host...\n"), buffer));
|
||||
|
||||
if (sent != 0x1F)
|
||||
for (int i = 0; i < 4; i++)
|
||||
Event->AppendText(_("WARNING : Game Not Found on Client Side!\n"));
|
||||
|
||||
m_numplayers++;
|
||||
Event->SendEvent(HOST_NEWPLAYER);
|
||||
break;
|
||||
}
|
||||
case 0x11: // Player left server
|
||||
{
|
||||
// Read Nickname
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
|
||||
Event->AppendText(wxString::Format(wxT("*Player : %s left the game\n\n"), buffer));
|
||||
|
||||
m_numplayers--;
|
||||
Event->SendEvent(HOST_PLAYERLEFT);
|
||||
break;
|
||||
}
|
||||
case 0x15: // Ping Player
|
||||
{
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
m_socket.Send((const char*)&buffer_size, 4);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x20: // IP request
|
||||
{
|
||||
//buffer_size = m_addr.size();
|
||||
//m_socket.Send((const char*)&buffer_size, 4);
|
||||
m_socket.Send((const char*)&data, 1);
|
||||
m_socket.Send(m_addr.c_str(), m_addr.size() + 1);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x30: // Chat message received from server
|
||||
{
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
|
||||
if (recv_size > 1024)
|
||||
{
|
||||
//something wrong...
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
Event->AppendText(wxString::FromAscii(buffer));
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x35: // ChangeGame message received
|
||||
{
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
|
||||
m_selectedgame = std::string(buffer);
|
||||
Event->AppendText(wxString::Format(wxT("*Host changed Game to : %s\n"), buffer));
|
||||
|
||||
// Tell the server if the game's been found
|
||||
m_socket.Send((const char*)&data, 1);
|
||||
CheckGameFound();
|
||||
|
||||
Event->SendEvent(GUI_UPDATE);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x40: // Ready message received
|
||||
{
|
||||
m_socket.Receive((char*)&buffer_size, 4, recv_size);
|
||||
buffer = new char[buffer_size+1];
|
||||
m_socket.Receive(buffer, buffer_size+1, recv_size);
|
||||
|
||||
if (recv_size > 1024)
|
||||
{
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
Event->AppendText(wxString::FromAscii(buffer));
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x50: // Everyone is Ready message received
|
||||
{
|
||||
// Load the game and start synching
|
||||
m_netptr->LoadGame();
|
||||
|
||||
break;
|
||||
}
|
||||
case 0xA1: // Received pad data from host in versus mode
|
||||
{
|
||||
if (m_data_received)
|
||||
wxThread::Sleep(10);
|
||||
|
||||
m_socket.Receive((char*)m_netvalues[0], 8, recv_size);
|
||||
m_data_received = true;
|
||||
|
||||
#ifdef NET_DEBUG
|
||||
char sent[64];
|
||||
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[0][0], m_netvalues[0][1]);
|
||||
Event->AppendText(wxString::FromAscii(sent));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void ServerSide::OnServerData(int sock, unsigned char data)
|
||||
{
|
||||
size_t recv_size;
|
||||
char *buffer = NULL;
|
||||
unsigned char sent;
|
||||
unsigned int four_bytes;
|
||||
|
||||
switch (data)
|
||||
{
|
||||
case 0x15: // Ping Request
|
||||
{
|
||||
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
|
||||
m_client[sock].socket.Send((const char*)&four_bytes, 4);
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x20: // IP request response
|
||||
{
|
||||
buffer = new char[24];
|
||||
// Read IP Address
|
||||
m_client[sock].socket.Receive(buffer, 24, recv_size);
|
||||
|
||||
Event->AppendText(wxString::Format(wxT("> Your IP is : %s\n"), buffer));
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x30: // Chat message
|
||||
{
|
||||
buffer = new char[1024];
|
||||
|
||||
m_client[sock].socket.Receive((char*)&four_bytes, 4, recv_size);
|
||||
m_client[sock].socket.Receive((char*)buffer, four_bytes + 1, recv_size);
|
||||
|
||||
if (recv_size > 1024)
|
||||
{
|
||||
//something wrong...
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
sent = 0x30;
|
||||
// Send to all
|
||||
for (int i=0; i < m_numplayers ; i++)
|
||||
{
|
||||
if (i == sock)
|
||||
continue;
|
||||
|
||||
m_client[i].socket.Send((const char*)&sent, 1);
|
||||
|
||||
m_client[1].socket.Send((const char*)&four_bytes, 4);
|
||||
m_client[i].socket.Send(buffer, recv_size);
|
||||
}
|
||||
|
||||
Event->AppendText(wxString::FromAscii(buffer));
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x35: // Change game response received
|
||||
{
|
||||
// Receive isGameFound response (0x1F / 0x1A)
|
||||
m_client[sock].socket.Receive((char*)&sent, 1, recv_size);
|
||||
|
||||
// If game is not found
|
||||
if (sent != 0x1F)
|
||||
{
|
||||
sent = 0x30;
|
||||
|
||||
wxString error_str = wxString::Format(
|
||||
wxT("WARNING : Player %s does Not have this Game !\n"), m_client[sock].nick.c_str());
|
||||
four_bytes = (int)error_str.size();
|
||||
|
||||
for (int i=0; i < 2; i++)
|
||||
Event->AppendText(error_str);
|
||||
|
||||
// Send to all
|
||||
for (int i=0; i < m_numplayers ; i++)
|
||||
{
|
||||
if (i == sock)
|
||||
continue;
|
||||
m_client[i].socket.Send((const char*)&sent, 1);
|
||||
|
||||
m_client[i].socket.Send((const char*)&four_bytes, 4);
|
||||
m_client[i].socket.Send(error_str.mb_str(), four_bytes + 1);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x40: // Ready message received
|
||||
{
|
||||
std::string buffer_str;
|
||||
|
||||
m_client[sock].ready = !m_client[sock].ready;
|
||||
|
||||
if (m_client[sock].ready)
|
||||
buffer_str = ">> "+m_client[sock].nick+" is now ready !\n";
|
||||
else
|
||||
buffer_str = ">> "+m_client[sock].nick+" is now Unready !\n";
|
||||
|
||||
four_bytes = (int)buffer_str.size();
|
||||
|
||||
// Send to all
|
||||
for (int i=0; i < m_numplayers ; i++)
|
||||
{
|
||||
m_client[i].socket.Send((const char*)&data, 1);
|
||||
|
||||
m_client[i].socket.Send((const char*)&four_bytes, 4);
|
||||
m_client[i].socket.Send(buffer_str.c_str(), four_bytes+1);
|
||||
}
|
||||
|
||||
Event->AppendText(wxString::FromAscii(buffer_str.c_str()));
|
||||
IsEveryoneReady();
|
||||
|
||||
break;
|
||||
}
|
||||
case 0xA1: // Received pad data from a client
|
||||
{
|
||||
if (m_data_received)
|
||||
wxThread::Sleep(10);
|
||||
|
||||
m_client[sock].socket.Receive((char*)m_netvalues[sock], 8, recv_size);
|
||||
m_data_received = true;
|
||||
|
||||
#ifdef NET_DEBUG
|
||||
char sent[64];
|
||||
sprintf(sent, "Received Values: 0x%08x : 0x%08x \n", m_netvalues[sock][0], m_netvalues[sock][1]);
|
||||
Event->AppendText(wxString::FromAscii(sent));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,317 +1,317 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NETWINDOW_H_
|
||||
#define _NETWINDOW_H_
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
#include <string>
|
||||
#include <wx/wx.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/listbox.h>
|
||||
|
||||
#include <wx/thread.h>
|
||||
|
||||
#include "Globals.h"
|
||||
#include "BootManager.h"
|
||||
#include "Common.h"
|
||||
#include "Core.h"
|
||||
#include "pluginspecs_pad.h"
|
||||
#include "HW/SI.h"
|
||||
#include "HW/SI_Device.h"
|
||||
#include "HW/SI_DeviceGCController.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define NET_DEBUG
|
||||
#endif
|
||||
|
||||
// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay,
|
||||
// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
|
||||
// #define USE_TCP
|
||||
|
||||
class NetPlay;
|
||||
|
||||
struct Netpads {
|
||||
int nHi[128];
|
||||
int nLow[128];
|
||||
};
|
||||
|
||||
struct Clients {
|
||||
std::string nick;
|
||||
sf::SocketTCP socket;
|
||||
unsigned short port;
|
||||
sf::IPAddress address;
|
||||
bool ready;
|
||||
};
|
||||
|
||||
class NetEvent
|
||||
{
|
||||
public:
|
||||
NetEvent(NetPlay* netptr) { m_netptr = netptr; }
|
||||
~NetEvent() {};
|
||||
|
||||
void SendEvent(int EventType, std::string="NULL", int=NULL);
|
||||
void AppendText(const wxString text);
|
||||
|
||||
private:
|
||||
NetPlay *m_netptr;
|
||||
};
|
||||
|
||||
class ServerSide : public wxThread
|
||||
{
|
||||
public:
|
||||
ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
|
||||
~ServerSide() {};
|
||||
|
||||
virtual void *Entry();
|
||||
|
||||
void Write(int socknb, const char *data, size_t size, long *ping=NULL);
|
||||
void WriteUDP(int socknb, const char *data, size_t size);
|
||||
bool isNewPadData(u32 *netValues, bool current, int client=0);
|
||||
|
||||
private:
|
||||
bool SyncValues(unsigned char, sf::IPAddress);
|
||||
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
|
||||
char GetSocket(sf::SocketTCP Socket);
|
||||
void OnServerData(int sock, unsigned char data);
|
||||
void IsEveryoneReady();
|
||||
|
||||
NetPlay *m_netptr;
|
||||
NetEvent *Event;
|
||||
|
||||
u32 m_netvalues[3][3];
|
||||
bool m_data_received; // New Pad data received ?
|
||||
|
||||
unsigned char m_numplayers;
|
||||
int m_netmodel;
|
||||
std::string m_nick;
|
||||
|
||||
Clients m_client[3]; // Connected client objects
|
||||
sf::SelectorTCP m_selector;
|
||||
sf::SocketTCP m_socket; // Server 'listening' socket
|
||||
sf::SocketUDP m_socketUDP;
|
||||
|
||||
wxCriticalSection m_CriticalSection;
|
||||
};
|
||||
|
||||
class ClientSide : public wxThread
|
||||
{
|
||||
public:
|
||||
ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
|
||||
~ClientSide() {}
|
||||
|
||||
virtual void *Entry();
|
||||
|
||||
void Write(const char *data, size_t size, long *ping=NULL);
|
||||
void WriteUDP(const char *data, size_t size);
|
||||
bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
|
||||
|
||||
private:
|
||||
bool SyncValues();
|
||||
void CheckGameFound();
|
||||
void OnClientData(unsigned char data);
|
||||
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
|
||||
|
||||
NetPlay *m_netptr;
|
||||
NetEvent *Event;
|
||||
|
||||
u32 m_netvalues[3][3];
|
||||
bool m_data_received; // New Pad data received ?
|
||||
|
||||
unsigned char m_numplayers;
|
||||
int m_netmodel;
|
||||
std::string m_nick;
|
||||
std::string m_hostnick;
|
||||
std::string m_selectedgame;
|
||||
|
||||
sf::SelectorTCP m_selector;
|
||||
sf::SocketTCP m_socket; // Client I/O socket
|
||||
sf::SocketUDP m_socketUDP;
|
||||
unsigned short m_port;
|
||||
std::string m_addr; // Contains the server addr
|
||||
|
||||
wxCriticalSection m_CriticalSection;
|
||||
};
|
||||
|
||||
class NetPlay : public wxFrame
|
||||
{
|
||||
public:
|
||||
NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
|
||||
~NetPlay();
|
||||
|
||||
void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
|
||||
void AppendText(const wxString text) { m_Logging->AppendText(text); }
|
||||
|
||||
// Send and receive pads values
|
||||
bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
|
||||
void ChangeSelectedGame(std::string game);
|
||||
void IsGameFound(unsigned char*, std::string);
|
||||
std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
|
||||
|
||||
void LoadGame();
|
||||
|
||||
protected:
|
||||
// Protects our vars from being fuxored by threads
|
||||
wxCriticalSection m_critical;
|
||||
|
||||
// this draws the GUI, ya rly
|
||||
void DrawGUI();
|
||||
void DrawNetWindow();
|
||||
|
||||
// event handlers
|
||||
void OnGUIEvent(wxCommandEvent& event);
|
||||
void OnDisconnect(wxCommandEvent& event);
|
||||
void OnNetEvent(wxCommandEvent& event);
|
||||
void OnQuit(wxCloseEvent& event);
|
||||
|
||||
void OnJoin(wxCommandEvent& event);
|
||||
void OnHost(wxCommandEvent& event);
|
||||
|
||||
// Net play vars (used ingame)
|
||||
int m_frame;
|
||||
int m_lastframe;
|
||||
Common::Timer m_timer;
|
||||
int m_loopframe;
|
||||
int m_frameDelay;
|
||||
bool m_data_received;// True if first frame data received
|
||||
|
||||
// Basic vars
|
||||
std::string m_paths; // Game paths list
|
||||
std::string m_games; // Game names list
|
||||
|
||||
std::string m_selectedGame;// Selected game's string
|
||||
std::string m_hostaddr; // Used with OnGetIP to cache it
|
||||
bool m_ready, m_clients_ready;
|
||||
std::string m_nick;
|
||||
|
||||
int m_NetModel; // Using P2P model (0) or Server model (1)
|
||||
int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
|
||||
unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
|
||||
std::string m_address; // The address entered into connection box
|
||||
unsigned short m_port;
|
||||
|
||||
Netpads m_pads[4]; // this struct is used to save synced pad values
|
||||
IniFile ConfigIni;
|
||||
|
||||
// Sockets objects
|
||||
ServerSide *m_sock_server;
|
||||
ClientSide *m_sock_client;
|
||||
|
||||
// -----------
|
||||
// GUI objects
|
||||
// -----------
|
||||
wxNotebook *m_Notebook;
|
||||
wxPanel *m_Tab_Connect;
|
||||
wxPanel *m_Tab_Host;
|
||||
wxStaticText *m_SetNick_text;
|
||||
wxTextCtrl *m_SetNick;
|
||||
wxChoice *m_NetMode;
|
||||
|
||||
// Host tab :
|
||||
wxArrayString m_GameList_str;
|
||||
wxStaticText *m_GameList_text;
|
||||
wxListBox *m_GameList;
|
||||
wxStaticText *m_SetPort_text;
|
||||
wxTextCtrl *m_SetPort;
|
||||
wxButton *m_HostGame;
|
||||
|
||||
// Connect tab :
|
||||
wxTextCtrl *m_ConAddr;
|
||||
wxStaticText *m_ConAddr_text;
|
||||
wxButton *m_JoinGame;
|
||||
wxCheckBox *m_UseRandomPort;
|
||||
|
||||
// Connection window
|
||||
wxButton *m_Game_str;
|
||||
wxTextCtrl *m_Logging;
|
||||
wxTextCtrl *m_Chat;
|
||||
wxButton *m_Chat_ok;
|
||||
// Right part
|
||||
wxButton *m_wtfismyip;
|
||||
wxButton *m_ChangeGame;
|
||||
// Left Part
|
||||
wxButton *m_Disconnect;
|
||||
wxStaticText *m_ConInfo_text;
|
||||
wxButton *m_GetPing;
|
||||
wxCheckBox *m_Ready;
|
||||
wxCheckBox *m_RecordGame;
|
||||
|
||||
// wxWidgets event table
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
class GameListPopup : public wxDialog
|
||||
{
|
||||
public:
|
||||
GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
|
||||
~GameListPopup() {}
|
||||
protected:
|
||||
void OnButtons(wxCommandEvent& event);
|
||||
wxArrayString m_GameList_str;
|
||||
NetPlay* m_netParent;
|
||||
wxListBox *m_GameList;
|
||||
wxButton *m_Accept;
|
||||
wxButton *m_Cancel;
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ID_NOTEBOOK,
|
||||
ID_TAB_HOST,
|
||||
ID_TAB_CONN,
|
||||
ID_BUTTON_HOST,
|
||||
ID_BUTTON_JOIN,
|
||||
ID_NETMODE,
|
||||
ID_GAMELIST,
|
||||
ID_LOGGING_TXT,
|
||||
ID_CHAT,
|
||||
ID_SETNICK,
|
||||
ID_SETPORT,
|
||||
ID_CONNADDR,
|
||||
ID_CONNINFO_TXT,
|
||||
ID_USE_RANDOMPORT,
|
||||
ID_BUTTON_GETPING,
|
||||
ID_BUTTON_GETIP,
|
||||
ID_CHANGEGAME,
|
||||
ID_BUTTON_QUIT,
|
||||
ID_BUTTON_CHAT,
|
||||
ID_READY,
|
||||
ID_RECORD,
|
||||
|
||||
ID_SOCKET,
|
||||
ID_SERVER,
|
||||
|
||||
HOST_FULL = 200, // ...
|
||||
HOST_ERROR, // Sent on socket error
|
||||
HOST_DISCONNECTED,
|
||||
HOST_NEWPLAYER,
|
||||
HOST_PLAYERLEFT,
|
||||
CLIENTS_READY,
|
||||
CLIENTS_NOTREADY,
|
||||
GUI_UPDATE, // Refresh the shown selectedgame on GUI
|
||||
ADD_TEXT, // Add text to m_Logging (string)
|
||||
ADD_INFO, // Sent when updating net infos (string)
|
||||
NET_EVENT
|
||||
};
|
||||
|
||||
#endif // _NETWINDOW_H_
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _NETWINDOW_H_
|
||||
#define _NETWINDOW_H_
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
#include <string>
|
||||
#include <wx/wx.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/listbox.h>
|
||||
|
||||
#include <wx/thread.h>
|
||||
|
||||
#include "Globals.h"
|
||||
#include "BootManager.h"
|
||||
#include "Common.h"
|
||||
#include "Core.h"
|
||||
#include "pluginspecs_pad.h"
|
||||
#include "HW/SI.h"
|
||||
#include "HW/SI_Device.h"
|
||||
#include "HW/SI_DeviceGCController.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define NET_DEBUG
|
||||
#endif
|
||||
|
||||
// Use TCP instead of UDP to send pad data @ 60fps. Suitable and better for LAN netplay,
|
||||
// Unrealistic for Internet netplay, unless you have an uberfast connexion (<10ms ping)
|
||||
// #define USE_TCP
|
||||
|
||||
class NetPlay;
|
||||
|
||||
struct Netpads {
|
||||
int nHi[128];
|
||||
int nLow[128];
|
||||
};
|
||||
|
||||
struct Clients {
|
||||
std::string nick;
|
||||
sf::SocketTCP socket;
|
||||
unsigned short port;
|
||||
sf::IPAddress address;
|
||||
bool ready;
|
||||
};
|
||||
|
||||
class NetEvent
|
||||
{
|
||||
public:
|
||||
NetEvent(NetPlay* netptr) { m_netptr = netptr; }
|
||||
~NetEvent() {};
|
||||
|
||||
void SendEvent(int EventType, std::string="NULL", int=NULL);
|
||||
void AppendText(const wxString text);
|
||||
|
||||
private:
|
||||
NetPlay *m_netptr;
|
||||
};
|
||||
|
||||
class ServerSide : public wxThread
|
||||
{
|
||||
public:
|
||||
ServerSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, int netmodel, std::string nick);
|
||||
~ServerSide() {};
|
||||
|
||||
virtual void *Entry();
|
||||
|
||||
void Write(int socknb, const char *data, size_t size, long *ping=NULL);
|
||||
void WriteUDP(int socknb, const char *data, size_t size);
|
||||
bool isNewPadData(u32 *netValues, bool current, int client=0);
|
||||
|
||||
private:
|
||||
bool SyncValues(unsigned char, sf::IPAddress);
|
||||
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time = 0);
|
||||
char GetSocket(sf::SocketTCP Socket);
|
||||
void OnServerData(int sock, unsigned char data);
|
||||
void IsEveryoneReady();
|
||||
|
||||
NetPlay *m_netptr;
|
||||
NetEvent *Event;
|
||||
|
||||
u32 m_netvalues[3][3];
|
||||
bool m_data_received; // New Pad data received ?
|
||||
|
||||
unsigned char m_numplayers;
|
||||
int m_netmodel;
|
||||
std::string m_nick;
|
||||
|
||||
Clients m_client[3]; // Connected client objects
|
||||
sf::SelectorTCP m_selector;
|
||||
sf::SocketTCP m_socket; // Server 'listening' socket
|
||||
sf::SocketUDP m_socketUDP;
|
||||
|
||||
wxCriticalSection m_CriticalSection;
|
||||
};
|
||||
|
||||
class ClientSide : public wxThread
|
||||
{
|
||||
public:
|
||||
ClientSide(NetPlay* netptr, sf::SocketTCP, sf::SocketUDP, std::string addr, std::string nick);
|
||||
~ClientSide() {}
|
||||
|
||||
virtual void *Entry();
|
||||
|
||||
void Write(const char *data, size_t size, long *ping=NULL);
|
||||
void WriteUDP(const char *data, size_t size);
|
||||
bool isNewPadData(u32 *netValues, bool current, bool isVersus=true);
|
||||
|
||||
private:
|
||||
bool SyncValues();
|
||||
void CheckGameFound();
|
||||
void OnClientData(unsigned char data);
|
||||
bool RecvT(sf::SocketUDP Socket, char * Data, size_t Max, size_t& Recvd, float Time=0);
|
||||
|
||||
NetPlay *m_netptr;
|
||||
NetEvent *Event;
|
||||
|
||||
u32 m_netvalues[3][3];
|
||||
bool m_data_received; // New Pad data received ?
|
||||
|
||||
unsigned char m_numplayers;
|
||||
int m_netmodel;
|
||||
std::string m_nick;
|
||||
std::string m_hostnick;
|
||||
std::string m_selectedgame;
|
||||
|
||||
sf::SelectorTCP m_selector;
|
||||
sf::SocketTCP m_socket; // Client I/O socket
|
||||
sf::SocketUDP m_socketUDP;
|
||||
unsigned short m_port;
|
||||
std::string m_addr; // Contains the server addr
|
||||
|
||||
wxCriticalSection m_CriticalSection;
|
||||
};
|
||||
|
||||
class NetPlay : public wxFrame
|
||||
{
|
||||
public:
|
||||
NetPlay(wxWindow* parent, std::string GamePath = "", std::string GameName = "");
|
||||
~NetPlay();
|
||||
|
||||
void UpdateNetWindow(bool update_infos, wxString=wxT("NULL"));
|
||||
void AppendText(const wxString text) { m_Logging->AppendText(text); }
|
||||
|
||||
// Send and receive pads values
|
||||
bool GetNetPads(u8 pad_nb, SPADStatus, u32 *netvalues);
|
||||
void ChangeSelectedGame(std::string game);
|
||||
void IsGameFound(unsigned char*, std::string);
|
||||
std::string GetSelectedGame() { wxCriticalSectionLocker lock(m_critical); return m_selectedGame; }
|
||||
|
||||
void LoadGame();
|
||||
|
||||
protected:
|
||||
// Protects our vars from being fuxored by threads
|
||||
wxCriticalSection m_critical;
|
||||
|
||||
// this draws the GUI, ya rly
|
||||
void DrawGUI();
|
||||
void DrawNetWindow();
|
||||
|
||||
// event handlers
|
||||
void OnGUIEvent(wxCommandEvent& event);
|
||||
void OnDisconnect(wxCommandEvent& event);
|
||||
void OnNetEvent(wxCommandEvent& event);
|
||||
void OnQuit(wxCloseEvent& event);
|
||||
|
||||
void OnJoin(wxCommandEvent& event);
|
||||
void OnHost(wxCommandEvent& event);
|
||||
|
||||
// Net play vars (used ingame)
|
||||
int m_frame;
|
||||
int m_lastframe;
|
||||
Common::Timer m_timer;
|
||||
int m_loopframe;
|
||||
int m_frameDelay;
|
||||
bool m_data_received;// True if first frame data received
|
||||
|
||||
// Basic vars
|
||||
std::string m_paths; // Game paths list
|
||||
std::string m_games; // Game names list
|
||||
|
||||
std::string m_selectedGame;// Selected game's string
|
||||
std::string m_hostaddr; // Used with OnGetIP to cache it
|
||||
bool m_ready, m_clients_ready;
|
||||
std::string m_nick;
|
||||
|
||||
int m_NetModel; // Using P2P model (0) or Server model (1)
|
||||
int m_isHosting; // 0 = false ; 1 = true ; 2 = Not set
|
||||
unsigned char m_numClients; // starting from 0, 4 players max thus 3 clients
|
||||
std::string m_address; // The address entered into connection box
|
||||
unsigned short m_port;
|
||||
|
||||
Netpads m_pads[4]; // this struct is used to save synced pad values
|
||||
IniFile ConfigIni;
|
||||
|
||||
// Sockets objects
|
||||
ServerSide *m_sock_server;
|
||||
ClientSide *m_sock_client;
|
||||
|
||||
// -----------
|
||||
// GUI objects
|
||||
// -----------
|
||||
wxNotebook *m_Notebook;
|
||||
wxPanel *m_Tab_Connect;
|
||||
wxPanel *m_Tab_Host;
|
||||
wxStaticText *m_SetNick_text;
|
||||
wxTextCtrl *m_SetNick;
|
||||
wxChoice *m_NetMode;
|
||||
|
||||
// Host tab :
|
||||
wxArrayString m_GameList_str;
|
||||
wxStaticText *m_GameList_text;
|
||||
wxListBox *m_GameList;
|
||||
wxStaticText *m_SetPort_text;
|
||||
wxTextCtrl *m_SetPort;
|
||||
wxButton *m_HostGame;
|
||||
|
||||
// Connect tab :
|
||||
wxTextCtrl *m_ConAddr;
|
||||
wxStaticText *m_ConAddr_text;
|
||||
wxButton *m_JoinGame;
|
||||
wxCheckBox *m_UseRandomPort;
|
||||
|
||||
// Connection window
|
||||
wxButton *m_Game_str;
|
||||
wxTextCtrl *m_Logging;
|
||||
wxTextCtrl *m_Chat;
|
||||
wxButton *m_Chat_ok;
|
||||
// Right part
|
||||
wxButton *m_wtfismyip;
|
||||
wxButton *m_ChangeGame;
|
||||
// Left Part
|
||||
wxButton *m_Disconnect;
|
||||
wxStaticText *m_ConInfo_text;
|
||||
wxButton *m_GetPing;
|
||||
wxCheckBox *m_Ready;
|
||||
wxCheckBox *m_RecordGame;
|
||||
|
||||
// wxWidgets event table
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
class GameListPopup : public wxDialog
|
||||
{
|
||||
public:
|
||||
GameListPopup(NetPlay *net_ptr, wxArrayString GameNames);
|
||||
~GameListPopup() {}
|
||||
protected:
|
||||
void OnButtons(wxCommandEvent& event);
|
||||
wxArrayString m_GameList_str;
|
||||
NetPlay* m_netParent;
|
||||
wxListBox *m_GameList;
|
||||
wxButton *m_Accept;
|
||||
wxButton *m_Cancel;
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ID_NOTEBOOK,
|
||||
ID_TAB_HOST,
|
||||
ID_TAB_CONN,
|
||||
ID_BUTTON_HOST,
|
||||
ID_BUTTON_JOIN,
|
||||
ID_NETMODE,
|
||||
ID_GAMELIST,
|
||||
ID_LOGGING_TXT,
|
||||
ID_CHAT,
|
||||
ID_SETNICK,
|
||||
ID_SETPORT,
|
||||
ID_CONNADDR,
|
||||
ID_CONNINFO_TXT,
|
||||
ID_USE_RANDOMPORT,
|
||||
ID_BUTTON_GETPING,
|
||||
ID_BUTTON_GETIP,
|
||||
ID_CHANGEGAME,
|
||||
ID_BUTTON_QUIT,
|
||||
ID_BUTTON_CHAT,
|
||||
ID_READY,
|
||||
ID_RECORD,
|
||||
|
||||
ID_SOCKET,
|
||||
ID_SERVER,
|
||||
|
||||
HOST_FULL = 200, // ...
|
||||
HOST_ERROR, // Sent on socket error
|
||||
HOST_DISCONNECTED,
|
||||
HOST_NEWPLAYER,
|
||||
HOST_PLAYERLEFT,
|
||||
CLIENTS_READY,
|
||||
CLIENTS_NOTREADY,
|
||||
GUI_UPDATE, // Refresh the shown selectedgame on GUI
|
||||
ADD_TEXT, // Add text to m_Logging (string)
|
||||
ADD_INFO, // Sent when updating net infos (string)
|
||||
NET_EVENT
|
||||
};
|
||||
|
||||
#endif // _NETWINDOW_H_
|
||||
|
||||
|
@ -1,127 +1,127 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef __SUMMARIZE_H__
|
||||
#define __SUMMARIZE_H__
|
||||
|
||||
std::string Summarize_Plug()
|
||||
{
|
||||
return StringFromFormat(
|
||||
"Plugin Information\n\n"
|
||||
"Default GFX Plugin: %s\n"
|
||||
"Default DSP Plugin: %s\n"
|
||||
"Default PAD Plugin: %s\n"
|
||||
"Default WiiMote Plugin: %s\n\n"
|
||||
"Current GFX Plugin: %s\n"
|
||||
"Current DSP Plugin: %s\n"
|
||||
"Current PAD Plugin[0]: %s\n"
|
||||
"Current PAD Plugin[1]: %s\n"
|
||||
"Current PAD Plugin[2]: %s\n"
|
||||
"Current PAD Plugin[3]: %s\n"
|
||||
"Current WiiMote Plugin[0]: %s\n",
|
||||
SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
|
||||
SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
|
||||
SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
|
||||
SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
|
||||
Core::GetStartupParameter().m_strVideoPlugin.c_str(),
|
||||
Core::GetStartupParameter().m_strDSPPlugin.c_str(),
|
||||
Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
|
||||
Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
|
||||
Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
|
||||
Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
|
||||
Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
|
||||
);
|
||||
}
|
||||
|
||||
std::string Summarize_Settings()
|
||||
{
|
||||
return StringFromFormat(
|
||||
"Dolphin Settings\n\n"
|
||||
"Always HLE Bios: %s\n"
|
||||
"Use Dynarec: %s\n"
|
||||
"Use Dual Core: %s\n"
|
||||
"DSP Thread: %s\n"
|
||||
"Skip Idle: %s\n"
|
||||
"Lock Threads: %s\n"
|
||||
"Use Dual Core: %s\n"
|
||||
"Default GCM: %s\n"
|
||||
"DVD Root: %s\n"
|
||||
"Optimize Quantizers: %s\n"
|
||||
"Enable Cheats: %s\n"
|
||||
"Selected Language: %d\n"
|
||||
"Memcard A: %s\n"
|
||||
"Memcard B: %s\n"
|
||||
"Slot A: %d\n"
|
||||
"Slot B: %d\n"
|
||||
"Serial Port 1: %d\n"
|
||||
"Run Compare Server: %s\n"
|
||||
"Run Compare Client: %s\n"
|
||||
"TLB Hack: %s\n"
|
||||
"Frame Limit: %d\n"
|
||||
"[Wii]Widescreen: %s\n"
|
||||
"[Wii]Progressive Scan: %s\n",
|
||||
Core::GetStartupParameter().bHLEBios?"True":"False",
|
||||
Core::GetStartupParameter().bUseJIT?"True":"False",
|
||||
Core::GetStartupParameter().bUseDualCore?"True":"False",
|
||||
Core::GetStartupParameter().bDSPThread?"True":"False",
|
||||
Core::GetStartupParameter().bSkipIdle?"True":"False",
|
||||
Core::GetStartupParameter().bLockThreads?"True":"False",
|
||||
Core::GetStartupParameter().bUseDualCore?"True":"False",
|
||||
Core::GetStartupParameter().m_strDefaultGCM.c_str(),
|
||||
Core::GetStartupParameter().m_strDVDRoot.c_str(),
|
||||
Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
|
||||
Core::GetStartupParameter().bEnableCheats?"True":"False",
|
||||
Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
|
||||
SConfig::GetInstance().m_strMemoryCardA.c_str(),
|
||||
SConfig::GetInstance().m_strMemoryCardB.c_str(),
|
||||
SConfig::GetInstance().m_EXIDevice[0], //FIXME
|
||||
SConfig::GetInstance().m_EXIDevice[1], //FIXME
|
||||
SConfig::GetInstance().m_EXIDevice[2], //FIXME
|
||||
Core::GetStartupParameter().bRunCompareServer?"True":"False",
|
||||
Core::GetStartupParameter().bRunCompareClient?"True":"False",
|
||||
Core::GetStartupParameter().iTLBHack?"True":"False",
|
||||
SConfig::GetInstance().m_Framelimit*5,
|
||||
Core::GetStartupParameter().bWidescreen?"True":"False",
|
||||
Core::GetStartupParameter().bProgressiveScan?"True":"False"
|
||||
);
|
||||
}
|
||||
|
||||
std::string Summarize_CPU()
|
||||
{
|
||||
return StringFromFormat(
|
||||
"Processor Information: \n%s\n",
|
||||
cpu_info.Summarize().c_str()
|
||||
);
|
||||
}
|
||||
|
||||
std::string Summarize_Drives()
|
||||
{
|
||||
char ** drives = cdio_get_devices();
|
||||
std::string drive;
|
||||
for (int i = 0; drives[i] != NULL && i < 24; i++)
|
||||
{
|
||||
|
||||
drive += StringFromFormat(
|
||||
"CD/DVD Drive%d: %s\n",
|
||||
i+1,
|
||||
drives[i]
|
||||
);
|
||||
}
|
||||
return drive;
|
||||
}
|
||||
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef __SUMMARIZE_H__
|
||||
#define __SUMMARIZE_H__
|
||||
|
||||
std::string Summarize_Plug()
|
||||
{
|
||||
return StringFromFormat(
|
||||
"Plugin Information\n\n"
|
||||
"Default GFX Plugin: %s\n"
|
||||
"Default DSP Plugin: %s\n"
|
||||
"Default PAD Plugin: %s\n"
|
||||
"Default WiiMote Plugin: %s\n\n"
|
||||
"Current GFX Plugin: %s\n"
|
||||
"Current DSP Plugin: %s\n"
|
||||
"Current PAD Plugin[0]: %s\n"
|
||||
"Current PAD Plugin[1]: %s\n"
|
||||
"Current PAD Plugin[2]: %s\n"
|
||||
"Current PAD Plugin[3]: %s\n"
|
||||
"Current WiiMote Plugin[0]: %s\n",
|
||||
SConfig::GetInstance().m_DefaultGFXPlugin.c_str(),
|
||||
SConfig::GetInstance().m_DefaultDSPPlugin.c_str(),
|
||||
SConfig::GetInstance().m_DefaultPADPlugin.c_str(),
|
||||
SConfig::GetInstance().m_DefaultWiiMotePlugin.c_str(),
|
||||
Core::GetStartupParameter().m_strVideoPlugin.c_str(),
|
||||
Core::GetStartupParameter().m_strDSPPlugin.c_str(),
|
||||
Core::GetStartupParameter().m_strPadPlugin[0].c_str(),
|
||||
Core::GetStartupParameter().m_strPadPlugin[1].c_str(),
|
||||
Core::GetStartupParameter().m_strPadPlugin[2].c_str(),
|
||||
Core::GetStartupParameter().m_strPadPlugin[3].c_str(),
|
||||
Core::GetStartupParameter().m_strWiimotePlugin[0].c_str()
|
||||
);
|
||||
}
|
||||
|
||||
std::string Summarize_Settings()
|
||||
{
|
||||
return StringFromFormat(
|
||||
"Dolphin Settings\n\n"
|
||||
"Always HLE Bios: %s\n"
|
||||
"Use Dynarec: %s\n"
|
||||
"Use Dual Core: %s\n"
|
||||
"DSP Thread: %s\n"
|
||||
"Skip Idle: %s\n"
|
||||
"Lock Threads: %s\n"
|
||||
"Use Dual Core: %s\n"
|
||||
"Default GCM: %s\n"
|
||||
"DVD Root: %s\n"
|
||||
"Optimize Quantizers: %s\n"
|
||||
"Enable Cheats: %s\n"
|
||||
"Selected Language: %d\n"
|
||||
"Memcard A: %s\n"
|
||||
"Memcard B: %s\n"
|
||||
"Slot A: %d\n"
|
||||
"Slot B: %d\n"
|
||||
"Serial Port 1: %d\n"
|
||||
"Run Compare Server: %s\n"
|
||||
"Run Compare Client: %s\n"
|
||||
"TLB Hack: %s\n"
|
||||
"Frame Limit: %d\n"
|
||||
"[Wii]Widescreen: %s\n"
|
||||
"[Wii]Progressive Scan: %s\n",
|
||||
Core::GetStartupParameter().bHLEBios?"True":"False",
|
||||
Core::GetStartupParameter().bUseJIT?"True":"False",
|
||||
Core::GetStartupParameter().bUseDualCore?"True":"False",
|
||||
Core::GetStartupParameter().bDSPThread?"True":"False",
|
||||
Core::GetStartupParameter().bSkipIdle?"True":"False",
|
||||
Core::GetStartupParameter().bLockThreads?"True":"False",
|
||||
Core::GetStartupParameter().bUseDualCore?"True":"False",
|
||||
Core::GetStartupParameter().m_strDefaultGCM.c_str(),
|
||||
Core::GetStartupParameter().m_strDVDRoot.c_str(),
|
||||
Core::GetStartupParameter().bOptimizeQuantizers?"True":"False",
|
||||
Core::GetStartupParameter().bEnableCheats?"True":"False",
|
||||
Core::GetStartupParameter().SelectedLanguage, //FIXME show language based on index
|
||||
SConfig::GetInstance().m_strMemoryCardA.c_str(),
|
||||
SConfig::GetInstance().m_strMemoryCardB.c_str(),
|
||||
SConfig::GetInstance().m_EXIDevice[0], //FIXME
|
||||
SConfig::GetInstance().m_EXIDevice[1], //FIXME
|
||||
SConfig::GetInstance().m_EXIDevice[2], //FIXME
|
||||
Core::GetStartupParameter().bRunCompareServer?"True":"False",
|
||||
Core::GetStartupParameter().bRunCompareClient?"True":"False",
|
||||
Core::GetStartupParameter().iTLBHack?"True":"False",
|
||||
SConfig::GetInstance().m_Framelimit*5,
|
||||
Core::GetStartupParameter().bWidescreen?"True":"False",
|
||||
Core::GetStartupParameter().bProgressiveScan?"True":"False"
|
||||
);
|
||||
}
|
||||
|
||||
std::string Summarize_CPU()
|
||||
{
|
||||
return StringFromFormat(
|
||||
"Processor Information: \n%s\n",
|
||||
cpu_info.Summarize().c_str()
|
||||
);
|
||||
}
|
||||
|
||||
std::string Summarize_Drives()
|
||||
{
|
||||
char ** drives = cdio_get_devices();
|
||||
std::string drive;
|
||||
for (int i = 0; drives[i] != NULL && i < 24; i++)
|
||||
{
|
||||
|
||||
drive += StringFromFormat(
|
||||
"CD/DVD Drive%d: %s\n",
|
||||
i+1,
|
||||
drives[i]
|
||||
);
|
||||
}
|
||||
return drive;
|
||||
}
|
||||
|
||||
#endif //__SUMMARIZE_H__
|
@ -1,129 +1,129 @@
|
||||
/* XPM */
|
||||
static const char *Dolphin_xpm[] = {
|
||||
"32 32 94 2",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #1A496C",
|
||||
"@ c #091A27",
|
||||
"# c #3AA4F0",
|
||||
"$ c #3AA3EF",
|
||||
"% c #3CA1EA",
|
||||
"& c #1A4A6D",
|
||||
"* c #3AA2ED",
|
||||
"= c #F7FAFA",
|
||||
"- c #FFFFFF",
|
||||
"; c #FDFDFD",
|
||||
"> c #49A1E0",
|
||||
", c #3BA2EC",
|
||||
"' c #FBFDFC",
|
||||
") c #FEFFFD",
|
||||
"! c #4EA3E0",
|
||||
"~ c #3DA1E9",
|
||||
"{ c #D1E1EB",
|
||||
"] c #8ABBDE",
|
||||
"^ c #F2F6F7",
|
||||
"/ c #FAFBFC",
|
||||
"( c #CEDEEA",
|
||||
"_ c #E5EEF2",
|
||||
": c #BBD2E1",
|
||||
"< c #B3CFE5",
|
||||
"[ c #FFFFFE",
|
||||
"} c #FEFFFE",
|
||||
"| c #E8F0F3",
|
||||
"1 c #E4ECF1",
|
||||
"2 c #E5EDF0",
|
||||
"3 c #E9F0F3",
|
||||
"4 c #FEFEFE",
|
||||
"5 c #F9FBFB",
|
||||
"6 c #B0CCE0",
|
||||
"7 c #FEFEFF",
|
||||
"8 c #F9FAFB",
|
||||
"9 c #43A1E4",
|
||||
"0 c #EFF3F6",
|
||||
"a c #F0F5F7",
|
||||
"b c #97C1DE",
|
||||
"c c #FEFEFD",
|
||||
"d c #FDFDFC",
|
||||
"e c #97BEDB",
|
||||
"f c #FBFCFC",
|
||||
"g c #EDF3F6",
|
||||
"h c #6EADDA",
|
||||
"i c #F3F6F8",
|
||||
"j c #3BA1EA",
|
||||
"k c #6EADDB",
|
||||
"l c #F4F8F9",
|
||||
"m c #F1F6F7",
|
||||
"n c #3FA1E7",
|
||||
"o c #9BC1DD",
|
||||
"p c #FCFDFC",
|
||||
"q c #FBFDFB",
|
||||
"r c #B9D1E1",
|
||||
"s c #E0EBF2",
|
||||
"t c #D3E3EF",
|
||||
"u c #FFFEFE",
|
||||
"v c #F2F7F7",
|
||||
"w c #D5E4F0",
|
||||
"x c #F6F9F9",
|
||||
"y c #BDD5E5",
|
||||
"z c #EBF1F4",
|
||||
"A c #DEEAF2",
|
||||
"B c #AAC9DE",
|
||||
"C c #FEFFFF",
|
||||
"D c #EFF4F6",
|
||||
"E c #F8FAFB",
|
||||
"F c #A0C4E1",
|
||||
"G c #D6E5F0",
|
||||
"H c #FAFCFC",
|
||||
"I c #BDD5E7",
|
||||
"J c #EEF3F7",
|
||||
"K c #F3F7FA",
|
||||
"L c #C7D8E4",
|
||||
"M c #CDDEEC",
|
||||
"N c #DAE6ED",
|
||||
"O c #9AC2DF",
|
||||
"P c #E8EFF4",
|
||||
"Q c #ACCDE3",
|
||||
"R c #8DBBDC",
|
||||
"S c #D5E3EB",
|
||||
"T c #FDFFFE",
|
||||
"U c #FCFDFD",
|
||||
"V c #FEFDFD",
|
||||
"W c #F7F9FA",
|
||||
"X c #FDFEFD",
|
||||
"Y c #E7EFF4",
|
||||
"Z c #A4C7E0",
|
||||
"` c #F9FDFB",
|
||||
" . c #F6FBFC",
|
||||
".. c #B8D1E3",
|
||||
" . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
|
||||
". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
|
||||
". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
|
||||
"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
|
||||
". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
|
||||
". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
|
||||
". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
|
||||
". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
|
||||
". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
|
||||
". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
|
||||
". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
|
||||
". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
|
||||
". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
|
||||
". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
|
||||
". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
|
||||
". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
|
||||
". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
|
||||
". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
|
||||
". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
|
||||
". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
|
||||
". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
|
||||
". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
|
||||
". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
|
||||
". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
|
||||
". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
|
||||
". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
|
||||
". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
|
||||
". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
|
||||
" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
|
||||
" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
|
||||
" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
|
||||
" . . . . . . . . . . . . . . . . . . . . . . . . "};
|
||||
/* XPM */
|
||||
static const char *Dolphin_xpm[] = {
|
||||
"32 32 94 2",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #1A496C",
|
||||
"@ c #091A27",
|
||||
"# c #3AA4F0",
|
||||
"$ c #3AA3EF",
|
||||
"% c #3CA1EA",
|
||||
"& c #1A4A6D",
|
||||
"* c #3AA2ED",
|
||||
"= c #F7FAFA",
|
||||
"- c #FFFFFF",
|
||||
"; c #FDFDFD",
|
||||
"> c #49A1E0",
|
||||
", c #3BA2EC",
|
||||
"' c #FBFDFC",
|
||||
") c #FEFFFD",
|
||||
"! c #4EA3E0",
|
||||
"~ c #3DA1E9",
|
||||
"{ c #D1E1EB",
|
||||
"] c #8ABBDE",
|
||||
"^ c #F2F6F7",
|
||||
"/ c #FAFBFC",
|
||||
"( c #CEDEEA",
|
||||
"_ c #E5EEF2",
|
||||
": c #BBD2E1",
|
||||
"< c #B3CFE5",
|
||||
"[ c #FFFFFE",
|
||||
"} c #FEFFFE",
|
||||
"| c #E8F0F3",
|
||||
"1 c #E4ECF1",
|
||||
"2 c #E5EDF0",
|
||||
"3 c #E9F0F3",
|
||||
"4 c #FEFEFE",
|
||||
"5 c #F9FBFB",
|
||||
"6 c #B0CCE0",
|
||||
"7 c #FEFEFF",
|
||||
"8 c #F9FAFB",
|
||||
"9 c #43A1E4",
|
||||
"0 c #EFF3F6",
|
||||
"a c #F0F5F7",
|
||||
"b c #97C1DE",
|
||||
"c c #FEFEFD",
|
||||
"d c #FDFDFC",
|
||||
"e c #97BEDB",
|
||||
"f c #FBFCFC",
|
||||
"g c #EDF3F6",
|
||||
"h c #6EADDA",
|
||||
"i c #F3F6F8",
|
||||
"j c #3BA1EA",
|
||||
"k c #6EADDB",
|
||||
"l c #F4F8F9",
|
||||
"m c #F1F6F7",
|
||||
"n c #3FA1E7",
|
||||
"o c #9BC1DD",
|
||||
"p c #FCFDFC",
|
||||
"q c #FBFDFB",
|
||||
"r c #B9D1E1",
|
||||
"s c #E0EBF2",
|
||||
"t c #D3E3EF",
|
||||
"u c #FFFEFE",
|
||||
"v c #F2F7F7",
|
||||
"w c #D5E4F0",
|
||||
"x c #F6F9F9",
|
||||
"y c #BDD5E5",
|
||||
"z c #EBF1F4",
|
||||
"A c #DEEAF2",
|
||||
"B c #AAC9DE",
|
||||
"C c #FEFFFF",
|
||||
"D c #EFF4F6",
|
||||
"E c #F8FAFB",
|
||||
"F c #A0C4E1",
|
||||
"G c #D6E5F0",
|
||||
"H c #FAFCFC",
|
||||
"I c #BDD5E7",
|
||||
"J c #EEF3F7",
|
||||
"K c #F3F7FA",
|
||||
"L c #C7D8E4",
|
||||
"M c #CDDEEC",
|
||||
"N c #DAE6ED",
|
||||
"O c #9AC2DF",
|
||||
"P c #E8EFF4",
|
||||
"Q c #ACCDE3",
|
||||
"R c #8DBBDC",
|
||||
"S c #D5E3EB",
|
||||
"T c #FDFFFE",
|
||||
"U c #FCFDFD",
|
||||
"V c #FEFDFD",
|
||||
"W c #F7F9FA",
|
||||
"X c #FDFEFD",
|
||||
"Y c #E7EFF4",
|
||||
"Z c #A4C7E0",
|
||||
"` c #F9FDFB",
|
||||
" . c #F6FBFC",
|
||||
".. c #B8D1E3",
|
||||
" . . + . . . . . . . . . . . . . . . . . . . . . . . . ",
|
||||
". @ . . # # # # # # # # # # # # # # # # # # # # # # # # . . ",
|
||||
". . # # # # # # # # # # # # $ . . . . . % # # # # # # # # # . ",
|
||||
"& . # # # # # # # # # # # * . = - - - ; . > # # # # # # # # . ",
|
||||
". # # # # # # # # # # # , . ' ) - - - - ) . ! # # # # # # # # . ",
|
||||
". # # # # # # $ . . # $ . ; - - - - - - - - . ~ # # # # # # # . ",
|
||||
". # # # # . . . { ] . . ^ ) - - - - - - - - / . # # # # # # # . ",
|
||||
". # # # . ( _ . : < . . [ } - - - - - - - - [ . # # # # # # # . ",
|
||||
". # # # # . | 1 2 3 . . 4 - - - - - - - - - 5 . $ # # # # # # . ",
|
||||
". # # # # . 6 [ } 7 . . 4 - - - - - - - - - 8 . 9 # # # # # # . ",
|
||||
". # # # # . 0 } - - - - - - - - - - - - - - - 4 . # # # # # # . ",
|
||||
". # # # # . a ) - [ - - - - - - - - - - - - - ; . # # # # # # . ",
|
||||
". # # # # . b = c 4 - - - - - - - - - - - - d . ~ # # # # # # . ",
|
||||
". # # # # # . . . e f - - - - - - - - - - g . , # # # # # # # . ",
|
||||
". # # # # # # # # . h i - - - - - - - - ) . j # # # # # # # # . ",
|
||||
". # # # # # # # # # . k l - - - - - - - } m . n # # # # # # # . ",
|
||||
". # # # # # # # # # # . o } - - - - - - - - p . , # # # # # # . ",
|
||||
". # # # # # # # # # # $ . } - - - - - - - - 4 q . # # # # # # . ",
|
||||
". # # # # # # # # # # . r - - - - - - - - - } 4 s . # # # # # . ",
|
||||
". # # # # # # # # # # . t - - - - - - - - - u v . # # # # # # . ",
|
||||
". # # # # # # # # # # . w - - - - - - - - - x . # # # # # # # . ",
|
||||
". # # # # # # # # # # . y [ - - - - - - - - z . # # # # # # # . ",
|
||||
". # # # # # # # # # # $ . ) - - [ - - - - - A . # # # # # # # . ",
|
||||
". # # # # # # # # # # . B C - - [ D E - - - F . # # # # # # # . ",
|
||||
". # # # # # # # # # # . G - - - H . I - - J . # # # # # # # # . ",
|
||||
". # # # # # # # # # # . K - - - L . M - [ N . # # # # # # # # . ",
|
||||
". # # # # # # # # # . O - - - - . . P - - 5 Q . $ # # # # # # . ",
|
||||
". # # # # # # # # . R q - - - - . . i - - - 7 l . # # # # # # . ",
|
||||
" . # # # # # # # . S T [ [ U V . . 5 W ; - X Y . # # # # # . ",
|
||||
" . # # # # # # # . Z ` .... . ~ , . . . . . . # # # # # # . ",
|
||||
" . . # # # # # # . . . . # # # # # # # # # # # # # # . . ",
|
||||
" . . . . . . . . . . . . . . . . . . . . . . . . "};
|
||||
|
@ -1,83 +1,83 @@
|
||||
/* XPM */
|
||||
static const char *const Flag_Europe_xpm[] = {
|
||||
"96 32 48 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #0000FD",
|
||||
"@ c #0000FF",
|
||||
"# c #0808F7",
|
||||
"$ c #5C5CA3",
|
||||
"% c #1717E8",
|
||||
"& c #767680",
|
||||
"* c #EDED00",
|
||||
"= c #A5A54D",
|
||||
"- c #2E2EB9",
|
||||
"; c #96961A",
|
||||
"> c #4A4A8E",
|
||||
", c #0000FB",
|
||||
"' c #0000F4",
|
||||
") c #0808EC",
|
||||
"! c #5C5C9B",
|
||||
"~ c #1717DD",
|
||||
"{ c #0000EE",
|
||||
"] c #767677",
|
||||
"^ c #A5A547",
|
||||
"/ c #0000DD",
|
||||
"( c #2E2EA0",
|
||||
"_ c #969616",
|
||||
": c #4A4A7B",
|
||||
"< c #0000D2",
|
||||
"[ c #0000C6",
|
||||
"} c #0808BF",
|
||||
"| c #5C5C7E",
|
||||
"1 c #1717B4",
|
||||
"2 c #0000B9",
|
||||
"3 c #76765C",
|
||||
"4 c #A5A537",
|
||||
"5 c #0808B3",
|
||||
"6 c #5C5C76",
|
||||
"7 c #1717A8",
|
||||
"8 c #0000A9",
|
||||
"9 c #2E2E7A",
|
||||
"0 c #969611",
|
||||
"a c #4A4A5E",
|
||||
"b c #767654",
|
||||
"c c #A5A533",
|
||||
"d c #000097",
|
||||
"e c #2E2E6D",
|
||||
"f c #96960F",
|
||||
"g c #4A4A54",
|
||||
"h c #000081",
|
||||
"i c #000077",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".++++++++++++++++++++++++++++++. ",
|
||||
".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
|
||||
".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
|
||||
".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
|
||||
".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
|
||||
".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
|
||||
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
|
||||
".''''''')!~''''''''')!~''''''''. ",
|
||||
".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
|
||||
".///////(_://///////(_:////////. ",
|
||||
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
|
||||
".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
|
||||
".2222222223*4256723*42222222222. ",
|
||||
".88888888890a8b*c890a8888888888. ",
|
||||
".dddddddddddddefgdddddddddddddd. ",
|
||||
".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
|
||||
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
|
||||
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
/* XPM */
|
||||
static const char *const Flag_Europe_xpm[] = {
|
||||
"96 32 48 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #0000FD",
|
||||
"@ c #0000FF",
|
||||
"# c #0808F7",
|
||||
"$ c #5C5CA3",
|
||||
"% c #1717E8",
|
||||
"& c #767680",
|
||||
"* c #EDED00",
|
||||
"= c #A5A54D",
|
||||
"- c #2E2EB9",
|
||||
"; c #96961A",
|
||||
"> c #4A4A8E",
|
||||
", c #0000FB",
|
||||
"' c #0000F4",
|
||||
") c #0808EC",
|
||||
"! c #5C5C9B",
|
||||
"~ c #1717DD",
|
||||
"{ c #0000EE",
|
||||
"] c #767677",
|
||||
"^ c #A5A547",
|
||||
"/ c #0000DD",
|
||||
"( c #2E2EA0",
|
||||
"_ c #969616",
|
||||
": c #4A4A7B",
|
||||
"< c #0000D2",
|
||||
"[ c #0000C6",
|
||||
"} c #0808BF",
|
||||
"| c #5C5C7E",
|
||||
"1 c #1717B4",
|
||||
"2 c #0000B9",
|
||||
"3 c #76765C",
|
||||
"4 c #A5A537",
|
||||
"5 c #0808B3",
|
||||
"6 c #5C5C76",
|
||||
"7 c #1717A8",
|
||||
"8 c #0000A9",
|
||||
"9 c #2E2E7A",
|
||||
"0 c #969611",
|
||||
"a c #4A4A5E",
|
||||
"b c #767654",
|
||||
"c c #A5A533",
|
||||
"d c #000097",
|
||||
"e c #2E2E6D",
|
||||
"f c #96960F",
|
||||
"g c #4A4A54",
|
||||
"h c #000081",
|
||||
"i c #000077",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".++++++++++++++++++++++++++++++. ",
|
||||
".@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. ",
|
||||
".@@@@@@@@@@@@@#$%@@@@@@@@@@@@@@. ",
|
||||
".@@@@@@@@@#$%@&*=@#$%@@@@@@@@@@. ",
|
||||
".@@@@@@@@@&*=@-;>@&*=@@@@@@@@@@. ",
|
||||
".@@@@@@@@@-;>@@@@@-;>@@@@@@@@@@. ",
|
||||
".,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,. ",
|
||||
".''''''')!~''''''''')!~''''''''. ",
|
||||
".{{{{{{{]*^{{{{{{{{{]*^{{{{{{{{. ",
|
||||
".///////(_://///////(_:////////. ",
|
||||
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
|
||||
".[[[[[[[[[}|1[[[[[}|1[[[[[[[[[[. ",
|
||||
".2222222223*4256723*42222222222. ",
|
||||
".88888888890a8b*c890a8888888888. ",
|
||||
".dddddddddddddefgdddddddddddddd. ",
|
||||
".hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh. ",
|
||||
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
|
||||
".iiiiiiiiiiiiiiiiiiiiiiiiiiiiii. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
|
@ -1,80 +1,80 @@
|
||||
/* XPM */
|
||||
static const char *const Flag_France_xpm[] = {
|
||||
"96 32 45 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #0000FF",
|
||||
"@ c #FFFFFF",
|
||||
"# c #FF0000",
|
||||
"$ c #0000FC",
|
||||
"% c #0000F8",
|
||||
"& c #FCFCFC",
|
||||
"* c #FC0000",
|
||||
"= c #0000F2",
|
||||
"- c #F8F8F8",
|
||||
"; c #F80000",
|
||||
"> c #0000EC",
|
||||
", c #F2F2F2",
|
||||
"' c #F20000",
|
||||
") c #0000E3",
|
||||
"! c #ECECEC",
|
||||
"~ c #EC0000",
|
||||
"{ c #0000DB",
|
||||
"] c #E3E3E3",
|
||||
"^ c #E30000",
|
||||
"/ c #0000D2",
|
||||
"( c #DBDBDB",
|
||||
"_ c #DB0000",
|
||||
": c #0000C8",
|
||||
"< c #D2D2D2",
|
||||
"[ c #D20000",
|
||||
"} c #0000BD",
|
||||
"| c #C8C8C8",
|
||||
"1 c #C80000",
|
||||
"2 c #0000B1",
|
||||
"3 c #BDBDBD",
|
||||
"4 c #BD0000",
|
||||
"5 c #0000A3",
|
||||
"6 c #B1B1B1",
|
||||
"7 c #B10000",
|
||||
"8 c #000093",
|
||||
"9 c #A3A3A3",
|
||||
"0 c #A30000",
|
||||
"a c #000080",
|
||||
"b c #939393",
|
||||
"c c #930000",
|
||||
"d c #000077",
|
||||
"e c #808080",
|
||||
"f c #800000",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".++++++++++@@@@@@@@@@@#########. ",
|
||||
".++++++++++@@@@@@@@@@@#########. ",
|
||||
".++++++++++@@@@@@@@@@@#########. ",
|
||||
".++++++++++@@@@@@@@@@@#########. ",
|
||||
".$$$$$$$$$$@@@@@@@@@@@#########. ",
|
||||
".%%%%%%%%%%&&&&&&&&&&&*********. ",
|
||||
".==========-----------;;;;;;;;;. ",
|
||||
".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
|
||||
".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
|
||||
".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
|
||||
".//////////(((((((((((_________. ",
|
||||
".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
|
||||
".}}}}}}}}}}|||||||||||111111111. ",
|
||||
".222222222233333333333444444444. ",
|
||||
".555555555566666666666777777777. ",
|
||||
".888888888899999999999000000000. ",
|
||||
".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
|
||||
".ddddddddddeeeeeeeeeeefffffffff. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
/* XPM */
|
||||
static const char *const Flag_France_xpm[] = {
|
||||
"96 32 45 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #0000FF",
|
||||
"@ c #FFFFFF",
|
||||
"# c #FF0000",
|
||||
"$ c #0000FC",
|
||||
"% c #0000F8",
|
||||
"& c #FCFCFC",
|
||||
"* c #FC0000",
|
||||
"= c #0000F2",
|
||||
"- c #F8F8F8",
|
||||
"; c #F80000",
|
||||
"> c #0000EC",
|
||||
", c #F2F2F2",
|
||||
"' c #F20000",
|
||||
") c #0000E3",
|
||||
"! c #ECECEC",
|
||||
"~ c #EC0000",
|
||||
"{ c #0000DB",
|
||||
"] c #E3E3E3",
|
||||
"^ c #E30000",
|
||||
"/ c #0000D2",
|
||||
"( c #DBDBDB",
|
||||
"_ c #DB0000",
|
||||
": c #0000C8",
|
||||
"< c #D2D2D2",
|
||||
"[ c #D20000",
|
||||
"} c #0000BD",
|
||||
"| c #C8C8C8",
|
||||
"1 c #C80000",
|
||||
"2 c #0000B1",
|
||||
"3 c #BDBDBD",
|
||||
"4 c #BD0000",
|
||||
"5 c #0000A3",
|
||||
"6 c #B1B1B1",
|
||||
"7 c #B10000",
|
||||
"8 c #000093",
|
||||
"9 c #A3A3A3",
|
||||
"0 c #A30000",
|
||||
"a c #000080",
|
||||
"b c #939393",
|
||||
"c c #930000",
|
||||
"d c #000077",
|
||||
"e c #808080",
|
||||
"f c #800000",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".++++++++++@@@@@@@@@@@#########. ",
|
||||
".++++++++++@@@@@@@@@@@#########. ",
|
||||
".++++++++++@@@@@@@@@@@#########. ",
|
||||
".++++++++++@@@@@@@@@@@#########. ",
|
||||
".$$$$$$$$$$@@@@@@@@@@@#########. ",
|
||||
".%%%%%%%%%%&&&&&&&&&&&*********. ",
|
||||
".==========-----------;;;;;;;;;. ",
|
||||
".>>>>>>>>>>,,,,,,,,,,,'''''''''. ",
|
||||
".))))))))))!!!!!!!!!!!~~~~~~~~~. ",
|
||||
".{{{{{{{{{{]]]]]]]]]]]^^^^^^^^^. ",
|
||||
".//////////(((((((((((_________. ",
|
||||
".::::::::::<<<<<<<<<<<[[[[[[[[[. ",
|
||||
".}}}}}}}}}}|||||||||||111111111. ",
|
||||
".222222222233333333333444444444. ",
|
||||
".555555555566666666666777777777. ",
|
||||
".888888888899999999999000000000. ",
|
||||
".aaaaaaaaaabbbbbbbbbbbccccccccc. ",
|
||||
".ddddddddddeeeeeeeeeeefffffffff. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
|
@ -1,102 +1,102 @@
|
||||
/* XPM */
|
||||
static const char * const Flag_Japan_xpm[] = {
|
||||
"96 32 67 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #FFFFFF",
|
||||
"@ c #FECACA",
|
||||
"# c #FD8080",
|
||||
"$ c #FD6161",
|
||||
"% c #FD7676",
|
||||
"& c #FEB6B6",
|
||||
"* c #FEFEFE",
|
||||
"= c #FFEDED",
|
||||
"- c #FF4C4C",
|
||||
"; c #FF0000",
|
||||
"> c #FF2F2F",
|
||||
", c #FFD7D7",
|
||||
"' c #FEF5F5",
|
||||
") c #FE2E2E",
|
||||
"! c #FE1313",
|
||||
"~ c #FEDDDD",
|
||||
"{ c #F9F9F9",
|
||||
"] c #FC7777",
|
||||
"^ c #FD4545",
|
||||
"/ c #F4F4F4",
|
||||
"( c #F4F3F3",
|
||||
"_ c #FA1313",
|
||||
": c #FB0000",
|
||||
"< c #FA0000",
|
||||
"[ c #F4D4D4",
|
||||
"} c #EFEFEF",
|
||||
"| c #EFCFCF",
|
||||
"1 c #F10000",
|
||||
"2 c #EF9F9F",
|
||||
"3 c #E4E4E4",
|
||||
"4 c #E2BEBE",
|
||||
"5 c #DD0000",
|
||||
"6 c #E19090",
|
||||
"7 c #D9D9D9",
|
||||
"8 c #D8D0D0",
|
||||
"9 c #CA0404",
|
||||
"0 c #CA0000",
|
||||
"a c #D5A9A9",
|
||||
"b c #D0D0D0",
|
||||
"c c #BC4242",
|
||||
"d c #B40000",
|
||||
"e c #B71A1A",
|
||||
"f c #CFCFCF",
|
||||
"g c #C6C6C6",
|
||||
"h c #BEA7A7",
|
||||
"i c #990808",
|
||||
"j c #980000",
|
||||
"k c #B78787",
|
||||
"l c #BBBBBB",
|
||||
"m c #A88989",
|
||||
"n c #7B0B0B",
|
||||
"o c #770000",
|
||||
"p c #780202",
|
||||
"q c #9E6B6B",
|
||||
"r c #AEAEAE",
|
||||
"s c #A89C9C",
|
||||
"t c #8F4E4E",
|
||||
"u c #7F1B1B",
|
||||
"v c #7A0A0A",
|
||||
"w c #7D1515",
|
||||
"x c #8B4242",
|
||||
"y c #A48F8F",
|
||||
"z c #A0A0A0",
|
||||
"A c #8F8F8F",
|
||||
"B c #7C7C7C",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".++++++++++++++++++++++++++++++. ",
|
||||
".++++++++++++++++++++++++++++++. ",
|
||||
".++++++++++++++++++++++++++++++. ",
|
||||
".++++++++++++@#$%&*++++++++++++. ",
|
||||
".++++++++++=-;;;;;>,+++++++++++. ",
|
||||
".*********');;;;;;;!~**********. ",
|
||||
".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
|
||||
".////////(_:::::::::<[/////////. ",
|
||||
".}}}}}}}}|111111111112}}}}}}}}}. ",
|
||||
".333333334555555555556333333333. ",
|
||||
".77777777890000000000a777777777. ",
|
||||
".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
|
||||
".ggggggggghijjjjjjjjkgggggggggg. ",
|
||||
".llllllllllmnooooopqlllllllllll. ",
|
||||
".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
|
||||
".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
|
||||
".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
|
||||
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
/* XPM */
|
||||
static const char * const Flag_Japan_xpm[] = {
|
||||
"96 32 67 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #FFFFFF",
|
||||
"@ c #FECACA",
|
||||
"# c #FD8080",
|
||||
"$ c #FD6161",
|
||||
"% c #FD7676",
|
||||
"& c #FEB6B6",
|
||||
"* c #FEFEFE",
|
||||
"= c #FFEDED",
|
||||
"- c #FF4C4C",
|
||||
"; c #FF0000",
|
||||
"> c #FF2F2F",
|
||||
", c #FFD7D7",
|
||||
"' c #FEF5F5",
|
||||
") c #FE2E2E",
|
||||
"! c #FE1313",
|
||||
"~ c #FEDDDD",
|
||||
"{ c #F9F9F9",
|
||||
"] c #FC7777",
|
||||
"^ c #FD4545",
|
||||
"/ c #F4F4F4",
|
||||
"( c #F4F3F3",
|
||||
"_ c #FA1313",
|
||||
": c #FB0000",
|
||||
"< c #FA0000",
|
||||
"[ c #F4D4D4",
|
||||
"} c #EFEFEF",
|
||||
"| c #EFCFCF",
|
||||
"1 c #F10000",
|
||||
"2 c #EF9F9F",
|
||||
"3 c #E4E4E4",
|
||||
"4 c #E2BEBE",
|
||||
"5 c #DD0000",
|
||||
"6 c #E19090",
|
||||
"7 c #D9D9D9",
|
||||
"8 c #D8D0D0",
|
||||
"9 c #CA0404",
|
||||
"0 c #CA0000",
|
||||
"a c #D5A9A9",
|
||||
"b c #D0D0D0",
|
||||
"c c #BC4242",
|
||||
"d c #B40000",
|
||||
"e c #B71A1A",
|
||||
"f c #CFCFCF",
|
||||
"g c #C6C6C6",
|
||||
"h c #BEA7A7",
|
||||
"i c #990808",
|
||||
"j c #980000",
|
||||
"k c #B78787",
|
||||
"l c #BBBBBB",
|
||||
"m c #A88989",
|
||||
"n c #7B0B0B",
|
||||
"o c #770000",
|
||||
"p c #780202",
|
||||
"q c #9E6B6B",
|
||||
"r c #AEAEAE",
|
||||
"s c #A89C9C",
|
||||
"t c #8F4E4E",
|
||||
"u c #7F1B1B",
|
||||
"v c #7A0A0A",
|
||||
"w c #7D1515",
|
||||
"x c #8B4242",
|
||||
"y c #A48F8F",
|
||||
"z c #A0A0A0",
|
||||
"A c #8F8F8F",
|
||||
"B c #7C7C7C",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".++++++++++++++++++++++++++++++. ",
|
||||
".++++++++++++++++++++++++++++++. ",
|
||||
".++++++++++++++++++++++++++++++. ",
|
||||
".++++++++++++@#$%&*++++++++++++. ",
|
||||
".++++++++++=-;;;;;>,+++++++++++. ",
|
||||
".*********');;;;;;;!~**********. ",
|
||||
".{{{{{{{{{];;;;;;;;;^{{{{{{{{{{. ",
|
||||
".////////(_:::::::::<[/////////. ",
|
||||
".}}}}}}}}|111111111112}}}}}}}}}. ",
|
||||
".333333334555555555556333333333. ",
|
||||
".77777777890000000000a777777777. ",
|
||||
".bbbbbbbbbcdddddddddefbbbbbbbbb. ",
|
||||
".ggggggggghijjjjjjjjkgggggggggg. ",
|
||||
".llllllllllmnooooopqlllllllllll. ",
|
||||
".rrrrrrrrrrrstuvwxyrrrrrrrrrrrr. ",
|
||||
".zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz. ",
|
||||
".AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. ",
|
||||
".BBBBBBBBBBBBBBBBBBBBBBBBBBBBBB. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
|
@ -1,124 +1,124 @@
|
||||
/* XPM */
|
||||
static const char * Flag_Taiwan_xpm[] = {
|
||||
"96 32 89 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"# c #000099",
|
||||
"$ c #000098",
|
||||
"% c #03039A",
|
||||
"& c #000094",
|
||||
"' c #05059B",
|
||||
"( c #050095",
|
||||
") c #DC0014",
|
||||
"* c #FF0000",
|
||||
"+ c #FD0001",
|
||||
", c #04049B",
|
||||
"- c #000096",
|
||||
"! c #020299",
|
||||
"0 c #2424A7",
|
||||
"1 c #04049A",
|
||||
"2 c #000097",
|
||||
"3 c #000093",
|
||||
"4 c #6262BF",
|
||||
"5 c #2828A8",
|
||||
"6 c #6C6CC1",
|
||||
"7 c #3E3EB1",
|
||||
"8 c #3B3BB0",
|
||||
"9 c #00008F",
|
||||
": c #01019A",
|
||||
"; c #1919A3",
|
||||
"< c #4040B0",
|
||||
"= c #6363C0",
|
||||
"> c #D6D6EE",
|
||||
"? c #D9D9ED",
|
||||
"@ c #C5C5E7",
|
||||
"A c #3F3FB0",
|
||||
"B c #3D3DAF",
|
||||
"C c #020297",
|
||||
"D c #010199",
|
||||
"E c #5E5EBE",
|
||||
"F c #DFDFF2",
|
||||
"G c white",
|
||||
"H c #BFBFE5",
|
||||
"I c #2626A7",
|
||||
"J c #4242B0",
|
||||
"K c #7D7DCA",
|
||||
"L c #FAFAFD",
|
||||
"M c #FBFBFD",
|
||||
"N c #FCFCFD",
|
||||
"O c #FCFCFE",
|
||||
"P c #DADAF0",
|
||||
"Q c #6A6AC2",
|
||||
"R c #1B1BA3",
|
||||
"S c #000199",
|
||||
"T c #0E0E9B",
|
||||
"U c #5858BC",
|
||||
"V c #D3D3ED",
|
||||
"W c #2727A6",
|
||||
"X c #060699",
|
||||
"Y c #1212A0",
|
||||
"Z c #6464C0",
|
||||
"[ c #8080CC",
|
||||
"] c #F4F4FA",
|
||||
"^ c #F8F8FB",
|
||||
"_ c #7070C4",
|
||||
"` c #4949B5",
|
||||
"a c #000095",
|
||||
"b c #040499",
|
||||
"c c #000092",
|
||||
"d c #6767C2",
|
||||
"e c #8686CA",
|
||||
"f c #7070C5",
|
||||
"g c #2B2BA9",
|
||||
"h c #00009A",
|
||||
"i c #01049C",
|
||||
"j c #1619A4",
|
||||
"k c #393CB3",
|
||||
"l c #00029A",
|
||||
"m c #1619A5",
|
||||
"n c #020096",
|
||||
"o c #DB0014",
|
||||
"p c #FC0001",
|
||||
"q c #0A0092",
|
||||
"r c #060090",
|
||||
"s c #0B0092",
|
||||
"t c #0F008E",
|
||||
"u c #DD0013",
|
||||
"v c #FD0000",
|
||||
"w c #E5000F",
|
||||
"x c #E6010F",
|
||||
"y c #E60110",
|
||||
"z c #FB0002",
|
||||
"{ c #FE0000",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".#####$%#&'$$$##()*+***********. ",
|
||||
".###$$,-!0&1!$##()*+***********. ",
|
||||
".##$#23456789:$#()*+***********. ",
|
||||
".###2;<=>?@ABCD#()*+***********. ",
|
||||
".###$CEFGGGHI&D$()*+***********. ",
|
||||
".##D-JKLMNOPQR-S()*+***********. ",
|
||||
".###$TUGGNGVWX$#()*+***********. ",
|
||||
".###2YZ[]^P_`aD$()*+***********. ",
|
||||
".###$bcdEefg3D$#()*+***********. ",
|
||||
".hhhhhijiklm#hhhno*p***********. ",
|
||||
".qqqqqqrsrqrqqqqtu*v***********. ",
|
||||
".wwwwwwxwywxwwwwwz*{***********. ",
|
||||
".******************************. ",
|
||||
".{{{{{{{{{{{{{{{{{*{***********. ",
|
||||
".******************************. ",
|
||||
".******************************. ",
|
||||
".******************************. ",
|
||||
".******************************. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
/* XPM */
|
||||
static const char * Flag_Taiwan_xpm[] = {
|
||||
"96 32 89 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"# c #000099",
|
||||
"$ c #000098",
|
||||
"% c #03039A",
|
||||
"& c #000094",
|
||||
"' c #05059B",
|
||||
"( c #050095",
|
||||
") c #DC0014",
|
||||
"* c #FF0000",
|
||||
"+ c #FD0001",
|
||||
", c #04049B",
|
||||
"- c #000096",
|
||||
"! c #020299",
|
||||
"0 c #2424A7",
|
||||
"1 c #04049A",
|
||||
"2 c #000097",
|
||||
"3 c #000093",
|
||||
"4 c #6262BF",
|
||||
"5 c #2828A8",
|
||||
"6 c #6C6CC1",
|
||||
"7 c #3E3EB1",
|
||||
"8 c #3B3BB0",
|
||||
"9 c #00008F",
|
||||
": c #01019A",
|
||||
"; c #1919A3",
|
||||
"< c #4040B0",
|
||||
"= c #6363C0",
|
||||
"> c #D6D6EE",
|
||||
"? c #D9D9ED",
|
||||
"@ c #C5C5E7",
|
||||
"A c #3F3FB0",
|
||||
"B c #3D3DAF",
|
||||
"C c #020297",
|
||||
"D c #010199",
|
||||
"E c #5E5EBE",
|
||||
"F c #DFDFF2",
|
||||
"G c white",
|
||||
"H c #BFBFE5",
|
||||
"I c #2626A7",
|
||||
"J c #4242B0",
|
||||
"K c #7D7DCA",
|
||||
"L c #FAFAFD",
|
||||
"M c #FBFBFD",
|
||||
"N c #FCFCFD",
|
||||
"O c #FCFCFE",
|
||||
"P c #DADAF0",
|
||||
"Q c #6A6AC2",
|
||||
"R c #1B1BA3",
|
||||
"S c #000199",
|
||||
"T c #0E0E9B",
|
||||
"U c #5858BC",
|
||||
"V c #D3D3ED",
|
||||
"W c #2727A6",
|
||||
"X c #060699",
|
||||
"Y c #1212A0",
|
||||
"Z c #6464C0",
|
||||
"[ c #8080CC",
|
||||
"] c #F4F4FA",
|
||||
"^ c #F8F8FB",
|
||||
"_ c #7070C4",
|
||||
"` c #4949B5",
|
||||
"a c #000095",
|
||||
"b c #040499",
|
||||
"c c #000092",
|
||||
"d c #6767C2",
|
||||
"e c #8686CA",
|
||||
"f c #7070C5",
|
||||
"g c #2B2BA9",
|
||||
"h c #00009A",
|
||||
"i c #01049C",
|
||||
"j c #1619A4",
|
||||
"k c #393CB3",
|
||||
"l c #00029A",
|
||||
"m c #1619A5",
|
||||
"n c #020096",
|
||||
"o c #DB0014",
|
||||
"p c #FC0001",
|
||||
"q c #0A0092",
|
||||
"r c #060090",
|
||||
"s c #0B0092",
|
||||
"t c #0F008E",
|
||||
"u c #DD0013",
|
||||
"v c #FD0000",
|
||||
"w c #E5000F",
|
||||
"x c #E6010F",
|
||||
"y c #E60110",
|
||||
"z c #FB0002",
|
||||
"{ c #FE0000",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".#####$%#&'$$$##()*+***********. ",
|
||||
".###$$,-!0&1!$##()*+***********. ",
|
||||
".##$#23456789:$#()*+***********. ",
|
||||
".###2;<=>?@ABCD#()*+***********. ",
|
||||
".###$CEFGGGHI&D$()*+***********. ",
|
||||
".##D-JKLMNOPQR-S()*+***********. ",
|
||||
".###$TUGGNGVWX$#()*+***********. ",
|
||||
".###2YZ[]^P_`aD$()*+***********. ",
|
||||
".###$bcdEefg3D$#()*+***********. ",
|
||||
".hhhhhijiklm#hhhno*p***********. ",
|
||||
".qqqqqqrsrqrqqqqtu*v***********. ",
|
||||
".wwwwwwxwywxwwwwwz*{***********. ",
|
||||
".******************************. ",
|
||||
".{{{{{{{{{{{{{{{{{*{***********. ",
|
||||
".******************************. ",
|
||||
".******************************. ",
|
||||
".******************************. ",
|
||||
".******************************. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
@ -1,65 +1,65 @@
|
||||
/* XPM */
|
||||
static const char * Flag_USA_xpm[] = {
|
||||
"96 32 30 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #0000FF",
|
||||
"@ c #CE7070",
|
||||
"# c #B0BF99",
|
||||
"$ c #F1F1F1",
|
||||
"% c #FFFFFF",
|
||||
"& c #0000FD",
|
||||
"* c #CF8484",
|
||||
"= c #DA9090",
|
||||
"- c #0000F3",
|
||||
"; c #B0BF96",
|
||||
"> c #0000DF",
|
||||
", c #0000CB",
|
||||
"' c #B0BF8C",
|
||||
") c #D98E8E",
|
||||
"! c #0000B5",
|
||||
"~ c #CA6C6C",
|
||||
"{ c #000098",
|
||||
"] c #B0BF80",
|
||||
"^ c #000077",
|
||||
"/ c #C26464",
|
||||
"( c #DBDBDB",
|
||||
"_ c #C17676",
|
||||
": c #B55757",
|
||||
"< c #BBBBBB",
|
||||
"[ c #AC6161",
|
||||
"} c #A34545",
|
||||
"| c #8B8B8B",
|
||||
"1 c #8E4343",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".++++++++++++++@@@@@@@@@@@@@@@@. ",
|
||||
".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
|
||||
".&&&&&&&&&&&&&&*===============. ",
|
||||
".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
|
||||
".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
|
||||
".,',',',',',',,*))))))))))))))). ",
|
||||
".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
|
||||
".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
|
||||
".^^^^^^^^^^^^^^****************. ",
|
||||
".^^^^^^^^^^^^^^@///////////////. ",
|
||||
".((((((((((((((((((((((((((((((. ",
|
||||
".______________________________. ",
|
||||
".::::::::::::::::::::::::::::::. ",
|
||||
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
|
||||
".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
|
||||
".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
|
||||
".||||||||||||||||||||||||||||||. ",
|
||||
".111111111111111111111111111111. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
/* XPM */
|
||||
static const char * Flag_USA_xpm[] = {
|
||||
"96 32 30 1",
|
||||
" c None",
|
||||
". c #000000",
|
||||
"+ c #0000FF",
|
||||
"@ c #CE7070",
|
||||
"# c #B0BF99",
|
||||
"$ c #F1F1F1",
|
||||
"% c #FFFFFF",
|
||||
"& c #0000FD",
|
||||
"* c #CF8484",
|
||||
"= c #DA9090",
|
||||
"- c #0000F3",
|
||||
"; c #B0BF96",
|
||||
"> c #0000DF",
|
||||
", c #0000CB",
|
||||
"' c #B0BF8C",
|
||||
") c #D98E8E",
|
||||
"! c #0000B5",
|
||||
"~ c #CA6C6C",
|
||||
"{ c #000098",
|
||||
"] c #B0BF80",
|
||||
"^ c #000077",
|
||||
"/ c #C26464",
|
||||
"( c #DBDBDB",
|
||||
"_ c #C17676",
|
||||
": c #B55757",
|
||||
"< c #BBBBBB",
|
||||
"[ c #AC6161",
|
||||
"} c #A34545",
|
||||
"| c #8B8B8B",
|
||||
"1 c #8E4343",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"................................ ",
|
||||
".++++++++++++++@@@@@@@@@@@@@@@@. ",
|
||||
".+#+#+#+#+#+#++$%%%%%%%%%%%%%%%. ",
|
||||
".&&&&&&&&&&&&&&*===============. ",
|
||||
".-;-;-;-;-;-;--@@@@@@@@@@@@@@@@. ",
|
||||
".>>>>>>>>>>>>>>$%%%%%%%%%%%%%%%. ",
|
||||
".,',',',',',',,*))))))))))))))). ",
|
||||
".!!!!!!!!!!!!!!@~~~~~~~~~~~~~~~. ",
|
||||
".{]{]{]{]{]{]{{$$$$$$$$$$$$$$$$. ",
|
||||
".^^^^^^^^^^^^^^****************. ",
|
||||
".^^^^^^^^^^^^^^@///////////////. ",
|
||||
".((((((((((((((((((((((((((((((. ",
|
||||
".______________________________. ",
|
||||
".::::::::::::::::::::::::::::::. ",
|
||||
".<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<. ",
|
||||
".[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[. ",
|
||||
".}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}. ",
|
||||
".||||||||||||||||||||||||||||||. ",
|
||||
".111111111111111111111111111111. ",
|
||||
"................................ ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
|
@ -1,179 +1,179 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "AVIDump.h"
|
||||
#include "tchar.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vfw.h>
|
||||
#include <winerror.h>
|
||||
|
||||
#include "FileUtil.h"
|
||||
#include "CommonPaths.h"
|
||||
#include "Log.h"
|
||||
|
||||
static HWND m_emuWnd;
|
||||
static int m_width;
|
||||
static int m_height;
|
||||
static LONG m_byteBuffer;
|
||||
static LONG m_frameCount;
|
||||
static LONG m_totalBytes;
|
||||
static PAVIFILE m_file;
|
||||
static int m_fileCount;
|
||||
static PAVISTREAM m_stream;
|
||||
static PAVISTREAM m_streamCompressed;
|
||||
static AVISTREAMINFO m_header;
|
||||
static AVICOMPRESSOPTIONS m_options;
|
||||
static AVICOMPRESSOPTIONS *m_arrayOptions[1];
|
||||
static BITMAPINFOHEADER m_bitmap;
|
||||
|
||||
bool AVIDump::Start(HWND hWnd, int w, int h)
|
||||
{
|
||||
m_emuWnd = hWnd;
|
||||
m_fileCount = 0;
|
||||
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
|
||||
return CreateFile();
|
||||
}
|
||||
|
||||
bool AVIDump::CreateFile()
|
||||
{
|
||||
m_totalBytes = 0;
|
||||
m_frameCount = 0;
|
||||
char movie_file_name[255];
|
||||
sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
|
||||
// Create path
|
||||
File::CreateFullPath(movie_file_name);
|
||||
|
||||
// Ask to delete file
|
||||
if (File::Exists(movie_file_name))
|
||||
{
|
||||
if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
|
||||
File::Delete(movie_file_name);
|
||||
}
|
||||
|
||||
AVIFileInit();
|
||||
NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
|
||||
// TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
|
||||
HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
|
||||
if (FAILED(hr)) {
|
||||
if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format.");
|
||||
if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory.");
|
||||
if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file.");
|
||||
if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file.");
|
||||
if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
SetBitmapFormat();
|
||||
NOTICE_LOG(VIDEO, "Setting video format...");
|
||||
if (!SetVideoFormat()) {
|
||||
NOTICE_LOG(VIDEO, "Setting video format failed");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
if (!m_fileCount) {
|
||||
if (!SetCompressionOptions()) {
|
||||
NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
|
||||
NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
|
||||
NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AVIDump::CloseFile()
|
||||
{
|
||||
if (m_streamCompressed) {
|
||||
AVIStreamClose(m_streamCompressed);
|
||||
m_streamCompressed = NULL;
|
||||
}
|
||||
if (m_stream) {
|
||||
AVIStreamClose(m_stream);
|
||||
m_stream = NULL;
|
||||
}
|
||||
if (m_file) {
|
||||
AVIFileRelease(m_file);
|
||||
m_file = NULL;
|
||||
}
|
||||
AVIFileExit();
|
||||
}
|
||||
|
||||
void AVIDump::Stop()
|
||||
{
|
||||
CloseFile();
|
||||
m_fileCount = 0;
|
||||
NOTICE_LOG(VIDEO, "Stop");
|
||||
}
|
||||
|
||||
void AVIDump::AddFrame(char *data)
|
||||
{
|
||||
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
|
||||
m_totalBytes += m_byteBuffer;
|
||||
// Close the recording if the file is more than 2gb
|
||||
// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
|
||||
if (m_totalBytes >= 2000000000) {
|
||||
CloseFile();
|
||||
m_fileCount++;
|
||||
CreateFile();
|
||||
}
|
||||
}
|
||||
|
||||
void AVIDump::SetBitmapFormat()
|
||||
{
|
||||
memset(&m_bitmap, 0, sizeof(m_bitmap));
|
||||
m_bitmap.biSize = 0x28;
|
||||
m_bitmap.biPlanes = 1;
|
||||
m_bitmap.biBitCount = 24;
|
||||
m_bitmap.biWidth = m_width;
|
||||
m_bitmap.biHeight = m_height;
|
||||
m_bitmap.biSizeImage = 3 * m_width * m_height;
|
||||
}
|
||||
|
||||
bool AVIDump::SetCompressionOptions()
|
||||
{
|
||||
memset(&m_options, 0, sizeof(m_options));
|
||||
m_arrayOptions[0] = &m_options;
|
||||
|
||||
return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
|
||||
}
|
||||
|
||||
bool AVIDump::SetVideoFormat()
|
||||
{
|
||||
memset(&m_header, 0, sizeof(m_header));
|
||||
m_header.fccType = streamtypeVIDEO;
|
||||
m_header.dwScale = 1;
|
||||
// TODO: Decect FPS using NTSC/PAL
|
||||
m_header.dwRate = 60;
|
||||
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
|
||||
|
||||
return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "AVIDump.h"
|
||||
#include "tchar.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vfw.h>
|
||||
#include <winerror.h>
|
||||
|
||||
#include "FileUtil.h"
|
||||
#include "CommonPaths.h"
|
||||
#include "Log.h"
|
||||
|
||||
static HWND m_emuWnd;
|
||||
static int m_width;
|
||||
static int m_height;
|
||||
static LONG m_byteBuffer;
|
||||
static LONG m_frameCount;
|
||||
static LONG m_totalBytes;
|
||||
static PAVIFILE m_file;
|
||||
static int m_fileCount;
|
||||
static PAVISTREAM m_stream;
|
||||
static PAVISTREAM m_streamCompressed;
|
||||
static AVISTREAMINFO m_header;
|
||||
static AVICOMPRESSOPTIONS m_options;
|
||||
static AVICOMPRESSOPTIONS *m_arrayOptions[1];
|
||||
static BITMAPINFOHEADER m_bitmap;
|
||||
|
||||
bool AVIDump::Start(HWND hWnd, int w, int h)
|
||||
{
|
||||
m_emuWnd = hWnd;
|
||||
m_fileCount = 0;
|
||||
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
|
||||
return CreateFile();
|
||||
}
|
||||
|
||||
bool AVIDump::CreateFile()
|
||||
{
|
||||
m_totalBytes = 0;
|
||||
m_frameCount = 0;
|
||||
char movie_file_name[255];
|
||||
sprintf(movie_file_name, "%s/framedump%d.avi", FULL_FRAMES_DIR, m_fileCount);
|
||||
// Create path
|
||||
File::CreateFullPath(movie_file_name);
|
||||
|
||||
// Ask to delete file
|
||||
if (File::Exists(movie_file_name))
|
||||
{
|
||||
if (AskYesNo("Delete the existing file '%s'?", movie_file_name))
|
||||
File::Delete(movie_file_name);
|
||||
}
|
||||
|
||||
AVIFileInit();
|
||||
NOTICE_LOG(VIDEO, "Opening AVI file (%s) for dumping", movie_file_name);
|
||||
// TODO: Make this work with AVIFileOpenW without it throwing REGDB_E_CLASSNOTREG
|
||||
HRESULT hr = AVIFileOpenA(&m_file, movie_file_name, OF_WRITE | OF_CREATE, NULL);
|
||||
if (FAILED(hr)) {
|
||||
if (hr == AVIERR_BADFORMAT) NOTICE_LOG(VIDEO, "The file couldn't be read, indicating a corrupt file or an unrecognized format.");
|
||||
if (hr == AVIERR_MEMORY) NOTICE_LOG(VIDEO, "The file could not be opened because of insufficient memory.");
|
||||
if (hr == AVIERR_FILEREAD) NOTICE_LOG(VIDEO, "A disk error occurred while reading the file.");
|
||||
if (hr == AVIERR_FILEOPEN) NOTICE_LOG(VIDEO, "A disk error occurred while opening the file.");
|
||||
if (hr == REGDB_E_CLASSNOTREG) NOTICE_LOG(VIDEO, "AVI class not registered");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
SetBitmapFormat();
|
||||
NOTICE_LOG(VIDEO, "Setting video format...");
|
||||
if (!SetVideoFormat()) {
|
||||
NOTICE_LOG(VIDEO, "Setting video format failed");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
if (!m_fileCount) {
|
||||
if (!SetCompressionOptions()) {
|
||||
NOTICE_LOG(VIDEO, "SetCompressionOptions failed");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (FAILED(AVIMakeCompressedStream(&m_streamCompressed, m_stream, &m_options, NULL))) {
|
||||
NOTICE_LOG(VIDEO, "AVIMakeCompressedStream failed");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
if (FAILED(AVIStreamSetFormat(m_streamCompressed, 0, &m_bitmap, m_bitmap.biSize))) {
|
||||
NOTICE_LOG(VIDEO, "AVIStreamSetFormat failed");
|
||||
Stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AVIDump::CloseFile()
|
||||
{
|
||||
if (m_streamCompressed) {
|
||||
AVIStreamClose(m_streamCompressed);
|
||||
m_streamCompressed = NULL;
|
||||
}
|
||||
if (m_stream) {
|
||||
AVIStreamClose(m_stream);
|
||||
m_stream = NULL;
|
||||
}
|
||||
if (m_file) {
|
||||
AVIFileRelease(m_file);
|
||||
m_file = NULL;
|
||||
}
|
||||
AVIFileExit();
|
||||
}
|
||||
|
||||
void AVIDump::Stop()
|
||||
{
|
||||
CloseFile();
|
||||
m_fileCount = 0;
|
||||
NOTICE_LOG(VIDEO, "Stop");
|
||||
}
|
||||
|
||||
void AVIDump::AddFrame(char *data)
|
||||
{
|
||||
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
|
||||
m_totalBytes += m_byteBuffer;
|
||||
// Close the recording if the file is more than 2gb
|
||||
// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
|
||||
if (m_totalBytes >= 2000000000) {
|
||||
CloseFile();
|
||||
m_fileCount++;
|
||||
CreateFile();
|
||||
}
|
||||
}
|
||||
|
||||
void AVIDump::SetBitmapFormat()
|
||||
{
|
||||
memset(&m_bitmap, 0, sizeof(m_bitmap));
|
||||
m_bitmap.biSize = 0x28;
|
||||
m_bitmap.biPlanes = 1;
|
||||
m_bitmap.biBitCount = 24;
|
||||
m_bitmap.biWidth = m_width;
|
||||
m_bitmap.biHeight = m_height;
|
||||
m_bitmap.biSizeImage = 3 * m_width * m_height;
|
||||
}
|
||||
|
||||
bool AVIDump::SetCompressionOptions()
|
||||
{
|
||||
memset(&m_options, 0, sizeof(m_options));
|
||||
m_arrayOptions[0] = &m_options;
|
||||
|
||||
return (AVISaveOptions(m_emuWnd, 0, 1, &m_stream, m_arrayOptions) != 0);
|
||||
}
|
||||
|
||||
bool AVIDump::SetVideoFormat()
|
||||
{
|
||||
memset(&m_header, 0, sizeof(m_header));
|
||||
m_header.fccType = streamtypeVIDEO;
|
||||
m_header.dwScale = 1;
|
||||
// TODO: Decect FPS using NTSC/PAL
|
||||
m_header.dwRate = 60;
|
||||
m_header.dwSuggestedBufferSize = m_bitmap.biSizeImage;
|
||||
|
||||
return SUCCEEDED(AVIFileCreateStream(m_file, &m_stream, &m_header));
|
||||
}
|
||||
|
@ -1,60 +1,60 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
// ------------------------------------------
|
||||
// The plugins has to define these functions
|
||||
// ------------------------------------------
|
||||
|
||||
#ifndef _BPFUNCTIONS_H_
|
||||
#define _BPFUNCTIONS_H_
|
||||
|
||||
#include "BPMemory.h"
|
||||
#include "VideoCommon.h"
|
||||
|
||||
namespace BPFunctions
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
CONFIG_ISWII = 0,
|
||||
CONFIG_DISABLEFOG,
|
||||
CONFIG_SHOWEFBREGIONS
|
||||
};
|
||||
|
||||
void FlushPipeline();
|
||||
void SetGenerationMode(const Bypass &bp);
|
||||
void SetScissor(const Bypass &bp);
|
||||
void SetLineWidth(const Bypass &bp);
|
||||
void SetDepthMode(const Bypass &bp);
|
||||
void SetBlendMode(const Bypass &bp);
|
||||
void SetDitherMode(const Bypass &bp);
|
||||
void SetLogicOpMode(const Bypass &bp);
|
||||
void SetColorMask(const Bypass &bp);
|
||||
float GetRendererTargetScaleX();
|
||||
float GetRendererTargetScaleY();
|
||||
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©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 ClearScreen(const Bypass &bp, const TRectangle &multirc);
|
||||
void RestoreRenderState(const Bypass &bp);
|
||||
u8 *GetPointer(const u32 &address);
|
||||
bool GetConfig(const int &type);
|
||||
void SetSamplerState(const Bypass &bp);
|
||||
void SetInterlacingMode(const Bypass &bp);
|
||||
};
|
||||
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
// ------------------------------------------
|
||||
// The plugins has to define these functions
|
||||
// ------------------------------------------
|
||||
|
||||
#ifndef _BPFUNCTIONS_H_
|
||||
#define _BPFUNCTIONS_H_
|
||||
|
||||
#include "BPMemory.h"
|
||||
#include "VideoCommon.h"
|
||||
|
||||
namespace BPFunctions
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
CONFIG_ISWII = 0,
|
||||
CONFIG_DISABLEFOG,
|
||||
CONFIG_SHOWEFBREGIONS
|
||||
};
|
||||
|
||||
void FlushPipeline();
|
||||
void SetGenerationMode(const Bypass &bp);
|
||||
void SetScissor(const Bypass &bp);
|
||||
void SetLineWidth(const Bypass &bp);
|
||||
void SetDepthMode(const Bypass &bp);
|
||||
void SetBlendMode(const Bypass &bp);
|
||||
void SetDitherMode(const Bypass &bp);
|
||||
void SetLogicOpMode(const Bypass &bp);
|
||||
void SetColorMask(const Bypass &bp);
|
||||
float GetRendererTargetScaleX();
|
||||
float GetRendererTargetScaleY();
|
||||
void CopyEFB(const Bypass &bp, const TRectangle &rc, const u32 &address, const bool &fromZBuffer, const bool &isIntensityFmt, const u32 ©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 ClearScreen(const Bypass &bp, const TRectangle &multirc);
|
||||
void RestoreRenderState(const Bypass &bp);
|
||||
u8 *GetPointer(const u32 &address);
|
||||
bool GetConfig(const int &type);
|
||||
void SetSamplerState(const Bypass &bp);
|
||||
void SetInterlacingMode(const Bypass &bp);
|
||||
};
|
||||
|
||||
#endif // _BPFUNCTIONS_H_
|
File diff suppressed because it is too large
Load Diff
@ -1,27 +1,27 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _BPSTRUCTS_H_
|
||||
#define _BPSTRUCTS_H_
|
||||
|
||||
#include "BPMemory.h"
|
||||
|
||||
void BPInit();
|
||||
void LoadBPReg(u32 value0);
|
||||
void BPReload();
|
||||
|
||||
#endif // _BPSTRUCTS_H_
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _BPSTRUCTS_H_
|
||||
#define _BPSTRUCTS_H_
|
||||
|
||||
#include "BPMemory.h"
|
||||
|
||||
void BPInit();
|
||||
void LoadBPReg(u32 value0);
|
||||
void BPReload();
|
||||
|
||||
#endif // _BPSTRUCTS_H_
|
||||
|
@ -1,154 +1,154 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "HiresTextures.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include "SOIL.h"
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
#include "FileSearch.h"
|
||||
|
||||
namespace HiresTextures
|
||||
{
|
||||
|
||||
std::map<std::string, std::string> textureMap;
|
||||
|
||||
void Init(const char *gameCode)
|
||||
{
|
||||
static bool bCheckedDir;
|
||||
|
||||
CFileSearch::XStringVector Directories;
|
||||
//Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
|
||||
char szDir[MAX_PATH];
|
||||
sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
|
||||
Directories.push_back(std::string(szDir));
|
||||
|
||||
|
||||
for (u32 i = 0; i < Directories.size(); i++)
|
||||
{
|
||||
File::FSTEntry FST_Temp;
|
||||
File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
|
||||
for (u32 j = 0; j < FST_Temp.children.size(); j++)
|
||||
{
|
||||
if (FST_Temp.children.at(j).isDirectory)
|
||||
{
|
||||
bool duplicate = false;
|
||||
NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
|
||||
for (u32 k = 0; k < Directories.size(); k++)
|
||||
{
|
||||
NormalizeDirSep(&Directories.at(k));
|
||||
if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
|
||||
{
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!duplicate)
|
||||
Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFileSearch::XStringVector Extensions;
|
||||
Extensions.push_back("*.png");
|
||||
Extensions.push_back("*.bmp");
|
||||
Extensions.push_back("*.tga");
|
||||
Extensions.push_back("*.dds");
|
||||
Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
|
||||
|
||||
CFileSearch FileSearch(Extensions, Directories);
|
||||
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
|
||||
char code[MAX_PATH];
|
||||
sprintf(code, "%s_", gameCode);
|
||||
|
||||
if (rFilenames.size() > 0)
|
||||
{
|
||||
for (u32 i = 0; i < rFilenames.size(); i++)
|
||||
{
|
||||
std::string FileName;
|
||||
SplitPath(rFilenames[i], NULL, &FileName, NULL);
|
||||
|
||||
if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end())
|
||||
textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
textureMap.clear();
|
||||
}
|
||||
|
||||
PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
|
||||
{
|
||||
std::string key(fileName);
|
||||
|
||||
if(textureMap.find(key) == textureMap.end())
|
||||
return PC_TEX_FMT_NONE;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int channels;
|
||||
|
||||
u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
|
||||
|
||||
if (temp == NULL) {
|
||||
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
|
||||
SOIL_free_image_data(temp);
|
||||
return PC_TEX_FMT_NONE;
|
||||
}
|
||||
|
||||
if (width > 1024 || height > 1024) {
|
||||
ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 1024 pixels tall and wide", textureMap[key].c_str(), width, height);
|
||||
SOIL_free_image_data(temp);
|
||||
return PC_TEX_FMT_NONE;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
PC_TexFormat returnTex;
|
||||
|
||||
switch (texformat)
|
||||
{
|
||||
case GX_TF_I4:
|
||||
case GX_TF_I8:
|
||||
case GX_TF_IA4:
|
||||
case GX_TF_IA8:
|
||||
for (int i = 0; i < width * height * 4; i += 4)
|
||||
{
|
||||
// Rather than use a luminosity function, just use the most intense color for luminance
|
||||
data[offset++] = *std::max_element(temp+i, temp+i+3);
|
||||
data[offset++] = temp[i+3];
|
||||
}
|
||||
returnTex = PC_TEX_FMT_IA8;
|
||||
break;
|
||||
default:
|
||||
memcpy(data, temp, width*height*4);
|
||||
returnTex = PC_TEX_FMT_RGBA32;
|
||||
break;
|
||||
}
|
||||
|
||||
*pWidth = width;
|
||||
*pHeight = height;
|
||||
SOIL_free_image_data(temp);
|
||||
INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
|
||||
return returnTex;
|
||||
}
|
||||
|
||||
}
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "HiresTextures.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include "SOIL.h"
|
||||
#include "CommonPaths.h"
|
||||
#include "FileUtil.h"
|
||||
#include "FileSearch.h"
|
||||
|
||||
namespace HiresTextures
|
||||
{
|
||||
|
||||
std::map<std::string, std::string> textureMap;
|
||||
|
||||
void Init(const char *gameCode)
|
||||
{
|
||||
static bool bCheckedDir;
|
||||
|
||||
CFileSearch::XStringVector Directories;
|
||||
//Directories.push_back(std::string(FULL_HIRES_TEXTURES_DIR));
|
||||
char szDir[MAX_PATH];
|
||||
sprintf(szDir,"%s/%s",FULL_HIRES_TEXTURES_DIR,gameCode);
|
||||
Directories.push_back(std::string(szDir));
|
||||
|
||||
|
||||
for (u32 i = 0; i < Directories.size(); i++)
|
||||
{
|
||||
File::FSTEntry FST_Temp;
|
||||
File::ScanDirectoryTree(Directories.at(i).c_str(), FST_Temp);
|
||||
for (u32 j = 0; j < FST_Temp.children.size(); j++)
|
||||
{
|
||||
if (FST_Temp.children.at(j).isDirectory)
|
||||
{
|
||||
bool duplicate = false;
|
||||
NormalizeDirSep(&(FST_Temp.children.at(j).physicalName));
|
||||
for (u32 k = 0; k < Directories.size(); k++)
|
||||
{
|
||||
NormalizeDirSep(&Directories.at(k));
|
||||
if (strcmp(Directories.at(k).c_str(), FST_Temp.children.at(j).physicalName.c_str()) == 0)
|
||||
{
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!duplicate)
|
||||
Directories.push_back(FST_Temp.children.at(j).physicalName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CFileSearch::XStringVector Extensions;
|
||||
Extensions.push_back("*.png");
|
||||
Extensions.push_back("*.bmp");
|
||||
Extensions.push_back("*.tga");
|
||||
Extensions.push_back("*.dds");
|
||||
Extensions.push_back("*.jpg"); // Why not? Could be useful for large photo-like textures
|
||||
|
||||
CFileSearch FileSearch(Extensions, Directories);
|
||||
const CFileSearch::XStringVector& rFilenames = FileSearch.GetFileNames();
|
||||
char code[MAX_PATH];
|
||||
sprintf(code, "%s_", gameCode);
|
||||
|
||||
if (rFilenames.size() > 0)
|
||||
{
|
||||
for (u32 i = 0; i < rFilenames.size(); i++)
|
||||
{
|
||||
std::string FileName;
|
||||
SplitPath(rFilenames[i], NULL, &FileName, NULL);
|
||||
|
||||
if (FileName.substr(0, strlen(code)).compare(code) == 0 && textureMap.find(FileName) == textureMap.end())
|
||||
textureMap.insert(std::map<std::string, std::string>::value_type(FileName, rFilenames[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
textureMap.clear();
|
||||
}
|
||||
|
||||
PC_TexFormat GetHiresTex(const char *fileName, int *pWidth, int *pHeight, int texformat, u8 *data)
|
||||
{
|
||||
std::string key(fileName);
|
||||
|
||||
if(textureMap.find(key) == textureMap.end())
|
||||
return PC_TEX_FMT_NONE;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
int channels;
|
||||
|
||||
u8 *temp = SOIL_load_image(textureMap[key].c_str(), &width, &height, &channels, SOIL_LOAD_RGBA);
|
||||
|
||||
if (temp == NULL) {
|
||||
ERROR_LOG(VIDEO, "Custom texture %s failed to load", textureMap[key].c_str(), width, height);
|
||||
SOIL_free_image_data(temp);
|
||||
return PC_TEX_FMT_NONE;
|
||||
}
|
||||
|
||||
if (width > 1024 || height > 1024) {
|
||||
ERROR_LOG(VIDEO, "Custom texture %s is too large (%ix%i); textures can only be 1024 pixels tall and wide", textureMap[key].c_str(), width, height);
|
||||
SOIL_free_image_data(temp);
|
||||
return PC_TEX_FMT_NONE;
|
||||
}
|
||||
|
||||
int offset = 0;
|
||||
PC_TexFormat returnTex;
|
||||
|
||||
switch (texformat)
|
||||
{
|
||||
case GX_TF_I4:
|
||||
case GX_TF_I8:
|
||||
case GX_TF_IA4:
|
||||
case GX_TF_IA8:
|
||||
for (int i = 0; i < width * height * 4; i += 4)
|
||||
{
|
||||
// Rather than use a luminosity function, just use the most intense color for luminance
|
||||
data[offset++] = *std::max_element(temp+i, temp+i+3);
|
||||
data[offset++] = temp[i+3];
|
||||
}
|
||||
returnTex = PC_TEX_FMT_IA8;
|
||||
break;
|
||||
default:
|
||||
memcpy(data, temp, width*height*4);
|
||||
returnTex = PC_TEX_FMT_RGBA32;
|
||||
break;
|
||||
}
|
||||
|
||||
*pWidth = width;
|
||||
*pHeight = height;
|
||||
SOIL_free_image_data(temp);
|
||||
INFO_LOG(VIDEO, "loading custom texture from %s", textureMap[key].c_str());
|
||||
return returnTex;
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user