set svn:eol-style=native for Plugins/**.cpp

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1441 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
bushing
2008-12-08 05:25:12 +00:00
parent 9146b9b261
commit 901fe7c00f
142 changed files with 43834 additions and 43834 deletions

View File

@ -1,280 +1,280 @@
// 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 "stdafx.h"
#include <mmsystem.h>
#include <dsound.h>
#include "DSoundStream.h"
namespace DSound
{
#define BUFSIZE 32768
#define MAXWAIT 70 //ms
//THE ROCK SOLID SYNCED DSOUND ENGINE :)
//v<>ran kritiska sektion och v<>r syncevent-handle
CRITICAL_SECTION soundCriticalSection;
HANDLE soundSyncEvent;
HANDLE hThread;
StreamCallback callback;
//lite mojs
IDirectSound8* ds;
IDirectSoundBuffer* dsBuffer;
//tja.. beh<65>vs
int bufferSize; //i bytes
int totalRenderedBytes;
int sampleRate;
//med den h<>r synkar vi st<73>ngning..
//0=vi spelar ov<6F>sen, 1=st<73>ng tr<74>den NU! 2=japp,tr<74>den <20>r st<73>ngd s<> forts<74>tt
volatile int threadData;
//ser till s<> X kan delas med 32
inline int FIX32(int x)
{
return(x & (~127));
}
int DSound_GetSampleRate()
{
return(sampleRate);
}
//Dags att skapa v<>r directsound buffert
bool createBuffer()
{
PCMWAVEFORMAT pcmwf;
DSBUFFERDESC dsbdesc;
//ljudformatet
memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
pcmwf.wf.nChannels = 2;
pcmwf.wf.nSamplesPerSec = sampleRate;
pcmwf.wf.nBlockAlign = 4;
pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
pcmwf.wBitsPerSample = 16;
//buffer description
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //<2F>ndra f<>r att st<73>lla in bufferstorlek
dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf;
// nu skapar vi bufferj<72>veln
if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL)))
{
dsBuffer->SetCurrentPosition(0);
return(true);
}
else
{
// Failed.
dsBuffer = NULL;
return(false);
}
}
bool writeDataToBuffer(DWORD dwOffset, // Our own write cursor.
char* soundData, // Start of our data.
DWORD dwSoundBytes) // Size of block to copy.
{
void* ptr1, * ptr2;
DWORD numBytes1, numBytes2;
// Obtain memory address of write block. This will be in two parts if the block wraps around.
HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
dsBuffer->Restore();
hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
}
if (SUCCEEDED(hr))
{
memcpy(ptr1, soundData, numBytes1);
if (ptr2 != 0)
{
memcpy(ptr2, soundData + numBytes1, numBytes2);
}
// Release the data back to DirectSound.
dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2);
return(true);
} /*
else
{
char temp[8];
sprintf(temp,"%i\n",hr);
OutputDebugString(temp);
}*/
return(false);
}
inline int ModBufferSize(int x)
{
return((x + bufferSize) % bufferSize);
}
int currentPos;
int lastPos;
short realtimeBuffer[1024 * 1024];
DWORD WINAPI soundThread(void*)
{
currentPos = 0;
lastPos = 0;
//writeDataToBuffer(0,realtimeBuffer,bufferSize);
// dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0);
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
while (!threadData)
{
EnterCriticalSection(&soundCriticalSection);
dsBuffer->GetCurrentPosition((DWORD*)&currentPos, 0);
int numBytesToRender = FIX32(ModBufferSize(currentPos - lastPos));
//renderStuff(numBytesToRender/2);
//if (numBytesToRender>bufferSize/2) numBytesToRender=0;
if (numBytesToRender >= 256)
{
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2);
writeDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
currentPos = ModBufferSize(lastPos + numBytesToRender);
totalRenderedBytes += numBytesToRender;
lastPos = currentPos;
}
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(soundSyncEvent, MAXWAIT);
}
dsBuffer->Stop();
threadData = 2;
return(0); //hurra!
}
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
{
callback = _callback;
threadData = 0;
sampleRate = _sampleRate;
//no security attributes, automatic resetting, init state nonset, untitled
soundSyncEvent = CreateEvent(0, false, false, 0);
//vi initierar den...........
InitializeCriticalSection(&soundCriticalSection);
//vi vill ha access till DSOUND s<>...
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
{
return(false);
}
//samarbetsvillig? n<><6E> :)
ds->SetCooperativeLevel(window, DSSCL_NORMAL); //DSSCL_PRIORITY?
//s<>.. skapa buffern
if (!createBuffer())
{
return(false);
}
//rensa den.. ?
DWORD num1;
short* p1;
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
memset(p1, 0, num1);
dsBuffer->Unlock(p1, num1, 0, 0);
totalRenderedBytes = -bufferSize;
DWORD h;
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
return(true);
}
void DSound_UpdateSound()
{
SetEvent(soundSyncEvent);
}
void DSound_StopSound()
{
EnterCriticalSection(&soundCriticalSection);
threadData = 1;
//kick the thread if it's waiting
SetEvent(soundSyncEvent);
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
dsBuffer->Release();
ds->Release();
CloseHandle(soundSyncEvent);
}
int DSound_GetCurSample()
{
EnterCriticalSection(&soundCriticalSection);
int playCursor;
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
LeaveCriticalSection(&soundCriticalSection);
return(playCursor);
}
float DSound_GetTimer()
{
return((float)DSound_GetCurSample() * (1.0f / (4.0f * 44100.0f)));
}
}
// 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 "stdafx.h"
#include <mmsystem.h>
#include <dsound.h>
#include "DSoundStream.h"
namespace DSound
{
#define BUFSIZE 32768
#define MAXWAIT 70 //ms
//THE ROCK SOLID SYNCED DSOUND ENGINE :)
//v<>ran kritiska sektion och v<>r syncevent-handle
CRITICAL_SECTION soundCriticalSection;
HANDLE soundSyncEvent;
HANDLE hThread;
StreamCallback callback;
//lite mojs
IDirectSound8* ds;
IDirectSoundBuffer* dsBuffer;
//tja.. beh<65>vs
int bufferSize; //i bytes
int totalRenderedBytes;
int sampleRate;
//med den h<>r synkar vi st<73>ngning..
//0=vi spelar ov<6F>sen, 1=st<73>ng tr<74>den NU! 2=japp,tr<74>den <20>r st<73>ngd s<> forts<74>tt
volatile int threadData;
//ser till s<> X kan delas med 32
inline int FIX32(int x)
{
return(x & (~127));
}
int DSound_GetSampleRate()
{
return(sampleRate);
}
//Dags att skapa v<>r directsound buffert
bool createBuffer()
{
PCMWAVEFORMAT pcmwf;
DSBUFFERDESC dsbdesc;
//ljudformatet
memset(&pcmwf, 0, sizeof(PCMWAVEFORMAT));
memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
pcmwf.wf.nChannels = 2;
pcmwf.wf.nSamplesPerSec = sampleRate;
pcmwf.wf.nBlockAlign = 4;
pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec * pcmwf.wf.nBlockAlign;
pcmwf.wBitsPerSample = 16;
//buffer description
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STICKYFOCUS; //VIKTIGT //DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY;
dsbdesc.dwBufferBytes = bufferSize = BUFSIZE; //FIX32(pcmwf.wf.nAvgBytesPerSec); //<2F>ndra f<>r att st<73>lla in bufferstorlek
dsbdesc.lpwfxFormat = (WAVEFORMATEX*)&pcmwf;
// nu skapar vi bufferj<72>veln
if (SUCCEEDED(ds->CreateSoundBuffer(&dsbdesc, &dsBuffer, NULL)))
{
dsBuffer->SetCurrentPosition(0);
return(true);
}
else
{
// Failed.
dsBuffer = NULL;
return(false);
}
}
bool writeDataToBuffer(DWORD dwOffset, // Our own write cursor.
char* soundData, // Start of our data.
DWORD dwSoundBytes) // Size of block to copy.
{
void* ptr1, * ptr2;
DWORD numBytes1, numBytes2;
// Obtain memory address of write block. This will be in two parts if the block wraps around.
HRESULT hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
// If the buffer was lost, restore and retry lock.
if (DSERR_BUFFERLOST == hr)
{
dsBuffer->Restore();
hr = dsBuffer->Lock(dwOffset, dwSoundBytes, &ptr1, &numBytes1, &ptr2, &numBytes2, 0);
}
if (SUCCEEDED(hr))
{
memcpy(ptr1, soundData, numBytes1);
if (ptr2 != 0)
{
memcpy(ptr2, soundData + numBytes1, numBytes2);
}
// Release the data back to DirectSound.
dsBuffer->Unlock(ptr1, numBytes1, ptr2, numBytes2);
return(true);
} /*
else
{
char temp[8];
sprintf(temp,"%i\n",hr);
OutputDebugString(temp);
}*/
return(false);
}
inline int ModBufferSize(int x)
{
return((x + bufferSize) % bufferSize);
}
int currentPos;
int lastPos;
short realtimeBuffer[1024 * 1024];
DWORD WINAPI soundThread(void*)
{
currentPos = 0;
lastPos = 0;
//writeDataToBuffer(0,realtimeBuffer,bufferSize);
// dsBuffer->Lock(0, bufferSize, (void **)&p1, &num1, (void **)&p2, &num2, 0);
dsBuffer->Play(0, 0, DSBPLAY_LOOPING);
while (!threadData)
{
EnterCriticalSection(&soundCriticalSection);
dsBuffer->GetCurrentPosition((DWORD*)&currentPos, 0);
int numBytesToRender = FIX32(ModBufferSize(currentPos - lastPos));
//renderStuff(numBytesToRender/2);
//if (numBytesToRender>bufferSize/2) numBytesToRender=0;
if (numBytesToRender >= 256)
{
(*callback)(realtimeBuffer, numBytesToRender >> 2, 16, 44100, 2);
writeDataToBuffer(lastPos, (char*)realtimeBuffer, numBytesToRender);
currentPos = ModBufferSize(lastPos + numBytesToRender);
totalRenderedBytes += numBytesToRender;
lastPos = currentPos;
}
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(soundSyncEvent, MAXWAIT);
}
dsBuffer->Stop();
threadData = 2;
return(0); //hurra!
}
bool DSound_StartSound(HWND window, int _sampleRate, StreamCallback _callback)
{
callback = _callback;
threadData = 0;
sampleRate = _sampleRate;
//no security attributes, automatic resetting, init state nonset, untitled
soundSyncEvent = CreateEvent(0, false, false, 0);
//vi initierar den...........
InitializeCriticalSection(&soundCriticalSection);
//vi vill ha access till DSOUND s<>...
if (FAILED(DirectSoundCreate8(0, &ds, 0)))
{
return(false);
}
//samarbetsvillig? n<><6E> :)
ds->SetCooperativeLevel(window, DSSCL_NORMAL); //DSSCL_PRIORITY?
//s<>.. skapa buffern
if (!createBuffer())
{
return(false);
}
//rensa den.. ?
DWORD num1;
short* p1;
dsBuffer->Lock(0, bufferSize, (void* *)&p1, &num1, 0, 0, 0);
memset(p1, 0, num1);
dsBuffer->Unlock(p1, num1, 0, 0);
totalRenderedBytes = -bufferSize;
DWORD h;
hThread = CreateThread(0, 0, soundThread, 0, 0, &h);
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
return(true);
}
void DSound_UpdateSound()
{
SetEvent(soundSyncEvent);
}
void DSound_StopSound()
{
EnterCriticalSection(&soundCriticalSection);
threadData = 1;
//kick the thread if it's waiting
SetEvent(soundSyncEvent);
LeaveCriticalSection(&soundCriticalSection);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
dsBuffer->Release();
ds->Release();
CloseHandle(soundSyncEvent);
}
int DSound_GetCurSample()
{
EnterCriticalSection(&soundCriticalSection);
int playCursor;
dsBuffer->GetCurrentPosition((DWORD*)&playCursor, 0);
playCursor = ModBufferSize(playCursor - lastPos) + totalRenderedBytes;
LeaveCriticalSection(&soundCriticalSection);
return(playCursor);
}
float DSound_GetTimer()
{
return((float)DSound_GetCurSample() * (1.0f / (4.0f * 44100.0f)));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,133 +1,133 @@
// 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 <iostream> // I hope this doesn't break anything
#include <stdio.h>
#include <stdarg.h>
#include "Common.h" // for Common::swap
#include "Globals.h"
#include "gdsp_interpreter.h"
// =======================================================================================
// This is to verbose, it has to be turned on manually for now
// --------------
void DebugLog(const char* _fmt, ...)
{
#if defined(_DEBUG) || defined(DEBUGFAST)
char Msg[512];
va_list ap;
va_start( ap, _fmt );
vsprintf( Msg, _fmt, ap );
va_end( ap );
// Only show certain messages
std::string sMsg = Msg;
if(sMsg.find("Mail") != -1 || sMsg.find("AX") != -1)
// no match = -1
{
OutputDebugString(Msg);
g_dspInitialize.pLog(Msg,0);
}
#endif
}
// =============
void ErrorLog(const char* _fmt, ...)
{
char Msg[512];
va_list ap;
va_start(ap, _fmt);
vsprintf(Msg, _fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg,0);
#ifdef _WIN32
::MessageBox(NULL, Msg, "Error", MB_OK);
#endif
DSP_DebugBreak(); // NOTICE: we also break the emulation if this happens
}
// =======================================================================================
// For PB address detection
// --------------
u32 RAM_MASK = 0x1FFFFFF;
u16 Memory_Read_U16(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap16(*(u16*)&g_dsp.cpu_ram[_uAddress]);
}
u32 Memory_Read_U32(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap32(*(u32*)&g_dsp.cpu_ram[_uAddress]);
}
#if PROFILE
#define PROFILE_MAP_SIZE 0x10000
u64 g_profileMap[PROFILE_MAP_SIZE];
bool g_profile = false;
void ProfilerStart()
{
g_profile = true;
}
void ProfilerAddDelta(int _addr, int _delta)
{
if (g_profile)
{
g_profileMap[_addr] += _delta;
}
}
void ProfilerInit()
{
memset(g_profileMap, 0, sizeof(g_profileMap));
}
void ProfilerDump(uint64 count)
{
FILE* pFile = fopen("c:\\_\\DSP_Prof.txt", "wt");
if (pFile != NULL)
{
fprintf(pFile, "Number of DSP steps: %llu\n\n", count);
for (int i=0; i<PROFILE_MAP_SIZE;i++)
{
if (g_profileMap[i] > 0)
{
fprintf(pFile, "0x%04X: %llu\n", i, g_profileMap[i]);
}
}
fclose(pFile);
}
}
#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/
#include <iostream> // I hope this doesn't break anything
#include <stdio.h>
#include <stdarg.h>
#include "Common.h" // for Common::swap
#include "Globals.h"
#include "gdsp_interpreter.h"
// =======================================================================================
// This is to verbose, it has to be turned on manually for now
// --------------
void DebugLog(const char* _fmt, ...)
{
#if defined(_DEBUG) || defined(DEBUGFAST)
char Msg[512];
va_list ap;
va_start( ap, _fmt );
vsprintf( Msg, _fmt, ap );
va_end( ap );
// Only show certain messages
std::string sMsg = Msg;
if(sMsg.find("Mail") != -1 || sMsg.find("AX") != -1)
// no match = -1
{
OutputDebugString(Msg);
g_dspInitialize.pLog(Msg,0);
}
#endif
}
// =============
void ErrorLog(const char* _fmt, ...)
{
char Msg[512];
va_list ap;
va_start(ap, _fmt);
vsprintf(Msg, _fmt, ap);
va_end(ap);
g_dspInitialize.pLog(Msg,0);
#ifdef _WIN32
::MessageBox(NULL, Msg, "Error", MB_OK);
#endif
DSP_DebugBreak(); // NOTICE: we also break the emulation if this happens
}
// =======================================================================================
// For PB address detection
// --------------
u32 RAM_MASK = 0x1FFFFFF;
u16 Memory_Read_U16(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap16(*(u16*)&g_dsp.cpu_ram[_uAddress]);
}
u32 Memory_Read_U32(u32 _uAddress)
{
_uAddress &= RAM_MASK;
return Common::swap32(*(u32*)&g_dsp.cpu_ram[_uAddress]);
}
#if PROFILE
#define PROFILE_MAP_SIZE 0x10000
u64 g_profileMap[PROFILE_MAP_SIZE];
bool g_profile = false;
void ProfilerStart()
{
g_profile = true;
}
void ProfilerAddDelta(int _addr, int _delta)
{
if (g_profile)
{
g_profileMap[_addr] += _delta;
}
}
void ProfilerInit()
{
memset(g_profileMap, 0, sizeof(g_profileMap));
}
void ProfilerDump(uint64 count)
{
FILE* pFile = fopen("c:\\_\\DSP_Prof.txt", "wt");
if (pFile != NULL)
{
fprintf(pFile, "Number of DSP steps: %llu\n\n", count);
for (int i=0; i<PROFILE_MAP_SIZE;i++)
{
if (g_profileMap[i] > 0)
{
fprintf(pFile, "0x%04X: %llu\n", i, g_profileMap[i]);
}
}
fclose(pFile);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +1,37 @@
// 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/
#ifdef _WIN32
#include "stdafx.h"
#endif
#include "Globals.h"
#include "gdsp_interpreter.h"
#include "gdsp_memory.h"
#include "gdsp_opcodes_helper.h"
bool WriteDMEM(uint16 addr, uint16 val)
{
return dsp_dmem_write(addr, val);
}
uint16 ReadDMEM(uint16 addr)
{
return dsp_dmem_read(addr);
}
// 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/
#ifdef _WIN32
#include "stdafx.h"
#endif
#include "Globals.h"
#include "gdsp_interpreter.h"
#include "gdsp_memory.h"
#include "gdsp_opcodes_helper.h"
bool WriteDMEM(uint16 addr, uint16 val)
{
return dsp_dmem_write(addr, val);
}
uint16 ReadDMEM(uint16 addr)
{
return dsp_dmem_read(addr);
}

View File

@ -1,100 +1,100 @@
// 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 "../Globals.h"
#include "Common.h"
extern u32 m_addressPBs;
// =======================================================================================
// Get the parameter block location - Example SSBM: We get the addr 8049cf00, first we
// always get 0 and go to AXLIST_STUDIOADDR, then we end up at AXLIST_PBADDR.
// --------------
bool AXTask(u32& _uMail)
{
u32 uAddress = _uMail;
DebugLog("AXTask - ================================================================");
DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress);
bool bExecuteList = true;
while (bExecuteList)
{
// ---------------------------------------------------------------------------------------
// SSBM: We get the addr 8049cf00, first we always get 0
u16 iCommand = Memory_Read_U16(uAddress);
uAddress += 2;
// ---------------------------------------------------------------------------------------
switch (iCommand)
{
// ---------------------------------------------------------------------------------------
// ?
case 0: // AXLIST_STUDIOADDR: //00
{
uAddress += 4;
DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress);
}
break;
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
case 2: // AXLIST_PBADDR: // 02
{
m_addressPBs = Memory_Read_U32(uAddress);
uAddress += 4;
DebugLog("AXLIST PB address: %08x", m_addressPBs);
bExecuteList = false;
}
break;
// ---------------------------------------------------------------------------------------
case 7: // AXLIST_SBUFFER: // 7
{
// Hopefully this is where in main ram to write.
uAddress += 4;
DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress);
}
break;
default:
{
// ---------------------------------------------------------------------------------------
// Stop the execution of this TaskList
DebugLog("AXLIST default: %08x", uAddress);
bExecuteList = false;
// ---------------------------------------------------------------------------------------
}
break;
} // end of switch
}
DebugLog("AXTask - done, send resume");
DebugLog("AXTask - ================================================================");
// now resume
return true;
}
// =======================================================================================
// 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 "../Globals.h"
#include "Common.h"
extern u32 m_addressPBs;
// =======================================================================================
// Get the parameter block location - Example SSBM: We get the addr 8049cf00, first we
// always get 0 and go to AXLIST_STUDIOADDR, then we end up at AXLIST_PBADDR.
// --------------
bool AXTask(u32& _uMail)
{
u32 uAddress = _uMail;
DebugLog("AXTask - ================================================================");
DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress);
bool bExecuteList = true;
while (bExecuteList)
{
// ---------------------------------------------------------------------------------------
// SSBM: We get the addr 8049cf00, first we always get 0
u16 iCommand = Memory_Read_U16(uAddress);
uAddress += 2;
// ---------------------------------------------------------------------------------------
switch (iCommand)
{
// ---------------------------------------------------------------------------------------
// ?
case 0: // AXLIST_STUDIOADDR: //00
{
uAddress += 4;
DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress);
}
break;
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
case 2: // AXLIST_PBADDR: // 02
{
m_addressPBs = Memory_Read_U32(uAddress);
uAddress += 4;
DebugLog("AXLIST PB address: %08x", m_addressPBs);
bExecuteList = false;
}
break;
// ---------------------------------------------------------------------------------------
case 7: // AXLIST_SBUFFER: // 7
{
// Hopefully this is where in main ram to write.
uAddress += 4;
DebugLog("AXLIST AXLIST_SBUFFER: %08x", uAddress);
}
break;
default:
{
// ---------------------------------------------------------------------------------------
// Stop the execution of this TaskList
DebugLog("AXLIST default: %08x", uAddress);
bExecuteList = false;
// ---------------------------------------------------------------------------------------
}
break;
} // end of switch
}
DebugLog("AXTask - done, send resume");
DebugLog("AXTask - ================================================================");
// now resume
return true;
}
// =======================================================================================

View File

@ -1,197 +1,197 @@
// 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/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <string>
#include <stdio.h>
#include <windows.h>
// ---------------------------------------------------------------------------------------
// Defines and settings
// --------------
bool g_consoleEnable = true;
#define DEBUGG
//#define DEBUGG_FILEONLY
//#define DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Handles
// --------------
#ifdef DEBUGG
FILE* __fStdOut = NULL;
#endif
#ifndef DEBUGG_FILEONLY
HANDLE __hStdOut = NULL;
#endif
// ==============
// =======================================================================================
// Width and height is the size of console window, if you specify fname,
// the output will also be writton to this file. The file pointer is automatically closed
// when you close the app
// --------------
void startConsoleWin(int width, int height, char* fname)
{
#ifdef DEBUGG
#ifndef DEBUGG_FILEONLY
AllocConsole();
SetConsoleTitle(fname);
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD co = {width,height};
SetConsoleScreenBufferSize(__hStdOut, co);
SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
#endif
#ifndef DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
// Write to a file
if(fname)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = fname;
std::string FullFilename = (FileName + FileEnding);
__fStdOut = fopen(FullFilename.c_str(), "w");
}
// -----------------
#endif
#endif
}
void ClearScreen();
int wprintf(char *fmt, ...)
{
#ifdef DEBUGG
char s[6000]; // WARNING: mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 3000, fmt, argptr);
va_end(argptr);
DWORD cCharsWritten;
// ---------------------------------------------------------------------------------------
#ifndef DEBUGG_FILEONLY
if(__hStdOut)
{
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
}
#endif
#ifndef DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
if(__fStdOut)
fprintf(__fStdOut, s);
// ---------------------------------------------------------------------------------------
#endif
return(cnt);
#else
return 0;
#endif
}
// =======================================================================================
// Clear screen
// --------------
void ClearScreen()
{
if(g_consoleEnable)
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//HANDLE hConsole = __hStdOut;
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
}
// =======================================================================================
// Get console HWND to be able to use MoveWindow()
// --------------
HWND GetConsoleHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles.
HWND hwndFound; // This is what is returned to the caller.
char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated
// WindowTitle.
char pszOldWindowTitle[MY_BUFSIZE]; // Contains original
// WindowTitle.
// Fetch current window title.
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
// Format a "unique" NewWindowTitle.
wsprintf(pszNewWindowTitle,"%d/%d",
GetTickCount(),
GetCurrentProcessId());
// Change current window title.
SetConsoleTitle(pszNewWindowTitle);
// Ensure window title has been updated.
Sleep(40);
// Look for NewWindowTitle.
hwndFound = FindWindow(NULL, pszNewWindowTitle);
// Restore original window title.
SetConsoleTitle(pszOldWindowTitle);
return(hwndFound);
}
// 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/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <string>
#include <stdio.h>
#include <windows.h>
// ---------------------------------------------------------------------------------------
// Defines and settings
// --------------
bool g_consoleEnable = true;
#define DEBUGG
//#define DEBUGG_FILEONLY
//#define DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Handles
// --------------
#ifdef DEBUGG
FILE* __fStdOut = NULL;
#endif
#ifndef DEBUGG_FILEONLY
HANDLE __hStdOut = NULL;
#endif
// ==============
// =======================================================================================
// Width and height is the size of console window, if you specify fname,
// the output will also be writton to this file. The file pointer is automatically closed
// when you close the app
// --------------
void startConsoleWin(int width, int height, char* fname)
{
#ifdef DEBUGG
#ifndef DEBUGG_FILEONLY
AllocConsole();
SetConsoleTitle(fname);
__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD co = {width,height};
SetConsoleScreenBufferSize(__hStdOut, co);
SMALL_RECT coo = {0,0,(width - 1),70}; // top, left, right, bottom
SetConsoleWindowInfo(__hStdOut, TRUE, &coo);
#endif
#ifndef DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
// Write to a file
if(fname)
{
// Edit the log file name
std::string FileEnding = ".log";
std::string FileName = fname;
std::string FullFilename = (FileName + FileEnding);
__fStdOut = fopen(FullFilename.c_str(), "w");
}
// -----------------
#endif
#endif
}
void ClearScreen();
int wprintf(char *fmt, ...)
{
#ifdef DEBUGG
char s[6000]; // WARNING: mind this value
va_list argptr;
int cnt;
va_start(argptr, fmt);
cnt = vsnprintf(s, 3000, fmt, argptr);
va_end(argptr);
DWORD cCharsWritten;
// ---------------------------------------------------------------------------------------
#ifndef DEBUGG_FILEONLY
if(__hStdOut)
{
WriteConsole(__hStdOut, s, strlen(s), &cCharsWritten, NULL);
}
#endif
#ifndef DEBUGG_NOFILE
// ---------------------------------------------------------------------------------------
if(__fStdOut)
fprintf(__fStdOut, s);
// ---------------------------------------------------------------------------------------
#endif
return(cnt);
#else
return 0;
#endif
}
// =======================================================================================
// Clear screen
// --------------
void ClearScreen()
{
if(g_consoleEnable)
{
COORD coordScreen = { 0, 0 };
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
//HANDLE hConsole = __hStdOut;
GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize,
coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize,
coordScreen, &cCharsWritten);
SetConsoleCursorPosition(hConsole, coordScreen);
}
}
// =======================================================================================
// Get console HWND to be able to use MoveWindow()
// --------------
HWND GetConsoleHwnd(void)
{
#define MY_BUFSIZE 1024 // Buffer size for console window titles.
HWND hwndFound; // This is what is returned to the caller.
char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated
// WindowTitle.
char pszOldWindowTitle[MY_BUFSIZE]; // Contains original
// WindowTitle.
// Fetch current window title.
GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);
// Format a "unique" NewWindowTitle.
wsprintf(pszNewWindowTitle,"%d/%d",
GetTickCount(),
GetCurrentProcessId());
// Change current window title.
SetConsoleTitle(pszNewWindowTitle);
// Ensure window title has been updated.
Sleep(40);
// Look for NewWindowTitle.
hwndFound = FindWindow(NULL, pszNewWindowTitle);
// Restore original window title.
SetConsoleTitle(pszOldWindowTitle);
return(hwndFound);
}
#endif

View File

@ -1,380 +1,380 @@
// 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/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <iostream>
#include <vector>
#include <string> // So that we can test if std::string == abc
#include <windows.h>
#include "Common.h"
#include "UCode_AXStructs.h" // they are only in a virtual dir called UCodes AX
#include "Console.h" // For wprintf, ClearScreen
// ---------------------------------------------------------------------------------------
// Declarations
// --------------
#define NUMBER_OF_PBS 64 // Todo: move this to a logging class
// ---------------------------------------------------------------------------------------
// Externals
// --------------
extern u32 m_addressPBs;
float ratioFactor;
int globaliSize;
short globalpBuffer;
u32 gLastBlock;
// --------------
// ---------------------------------------------------------------------------------------
// Vectors and other stuff
// --------------
std::vector<u32> gloopPos(64);
std::vector<u32> gsampleEnd(64);
std::vector<u32> gsamplePos(64);
std::vector<u32> gratio(64);
std::vector<u32> gratiohi(64);
std::vector<u32> gratiolo(64);
std::vector<u32> gfrac(64);
std::vector<u32> gcoef(64);
// PBSampleRateConverter mixer
std::vector<u16> gvolume_left(64);
std::vector<u16> gvolume_right(64);
std::vector<u16> gmixer_control(64);
std::vector<u16> gcur_volume(64);
std::vector<u16> gcur_volume_delta(64);
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
// loop
std::vector<u16> gloop1(64);
std::vector<u16> gloop2(64);
std::vector<u16> gloop3(64);
std::vector<u16> gadloop1(64);
std::vector<u16> gadloop2(64);
std::vector<u16> gadloop3(64);
// updates
std::vector<u16> gupdates1(64);
std::vector<u16> gupdates2(64);
std::vector<u16> gupdates3(64);
std::vector<u16> gupdates4(64);
std::vector<u16> gupdates5(64);
std::vector<u32> gupdates_addr(64);
// other stuff
std::vector<u16> Jump(64); // this is 1 or 0
std::vector<int> musicLength(64);
std::vector< std::vector<int> > vector1(64, std::vector<int>(100,0));
std::vector<int> numberRunning(64);
int j = 0;
int k = 0;
__int64 l = 0;
int iupd = 0;
bool iupdonce = false;
std::vector<u16> viupd(15); // the length of the update frequency bar
int vectorLength = 15; // the length of the playback history bar and how long
// old blocks are shown
std::vector<u16> vector62(vectorLength);
std::vector<u16> vector63(vectorLength);
int ReadOutPBs(AXParamBlock * _pPBs, int _num);
// ===========
// =======================================================================================
// Main logging function
// --------------
void Logging()
{
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Control how often the screen is updated
j++;
l++;
if (j>1000000) // TODO: make the update frequency adjustable from the logging window
{
AXParamBlock PBs[NUMBER_OF_PBS];
int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS);
// =======================================================================================
// Vector1 is a vector1[64][100] vector
/*
Move all items back like this
1 to 2
2 3
3 ...
*/
// ----------------
for (int i = 0; i < 64; i++)
{
for (int j = 1; j < vectorLength; j++)
{
vector1.at(i).at(j-1) = vector1.at(i).at(j);
}
}
// =================
// ---------------------------------------------------------------------------------------
// Enter the latest value
for (int i = 0; i < numberOfPBs; i++)
{
vector1.at(i).at(vectorLength-1) = PBs[i].running;
}
// -----------------
// ---------------------------------------------------------------------------------------
// Count how many blocks we have running now
int jj = 0;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < vectorLength-1; j++)
{
if (vector1.at(i).at(j) == 1)
{
jj++;
}
numberRunning.at(i) = jj;
}
}
// --------------
// ---------------------------------------------------------------------------------------
// Write the first row
char buffer [1000] = "";
std::string sbuff;
//sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5
sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
// --------------
// ---------------------------------------------------------------------------------------
// Read out values for all blocks
for (int i = 0; i < numberOfPBs; i++)
{
if (numberRunning.at(i) > 0)
{
// =======================================================================================
// Write the playback bar
// -------------
for (int j = 0; j < vectorLength; j++)
{
if(vector1.at(i).at(j) == 0)
{
sbuff = sbuff + " ";
}
else
{
sprintf(buffer, "%c", 177);
sbuff = sbuff + buffer; strcpy(buffer, "");
}
}
// ==============
// ================================================================================================
int sampleJump;
int loopJump;
//if (PBs[i].running && PBs[i].adpcm_loop_info.yn1 && PBs[i].mixer.volume_left)
if (true)
{
// ---------------------------------------------------------------------------------------
// AXPB base
//int running = pb.running;
gcoef[i] = PBs[i].unknown1;
sampleJump = ((PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo) - gsamplePos[i];
loopJump = ((PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo) - gloopPos[i];
gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo;
gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo;
gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo;
// PBSampleRateConverter src
gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor);
gratiohi[i] = PBs[i].src.ratio_hi;
gratiolo[i] = PBs[i].src.ratio_lo;
gfrac[i] = PBs[i].src.cur_addr_frac;
// adpcm_loop_info
gadloop1[i] = PBs[i].adpcm.pred_scale;
gadloop2[i] = PBs[i].adpcm.yn1;
gadloop3[i] = PBs[i].adpcm.yn2;
gloop1[i] = PBs[i].adpcm_loop_info.pred_scale;
gloop2[i] = PBs[i].adpcm_loop_info.yn1;
gloop3[i] = PBs[i].adpcm_loop_info.yn2;
// updates
gupdates1[i] = PBs[i].updates.num_updates[0];
gupdates2[i] = PBs[i].updates.num_updates[1];
gupdates3[i] = PBs[i].updates.num_updates[2];
gupdates4[i] = PBs[i].updates.num_updates[3];
gupdates5[i] = PBs[i].updates.num_updates[4];
gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo;
gaudioFormat[i] = PBs[i].audio_addr.sample_format;
glooping[i] = PBs[i].audio_addr.looping;
gsrc_type[i] = PBs[i].src_type;
gis_stream[i] = PBs[i].is_stream;
// mixer
gvolume_left[i] = PBs[i].mixer.volume_left;
gvolume_right[i] = PBs[i].mixer.volume_right;
gmixer_control[i] = PBs[i].mixer_control;
gcur_volume[i] = PBs[i].vol_env.cur_volume;
gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta;
// other stuff
Jump[i] = (gfrac[i] >> 16); // This is 1 or 0
musicLength[i] = gsampleEnd[i] - gloopPos[i];
}
// ================================================================================================
// =======================================================================================
// PRESETS
// ---------------------------------------------------------------------------------------
/*
/" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] |
*/
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i %05i %04i %05i | %i[%03i %05i %05i] %i | %05i %05i[%i %05i] | %i %i %i %i %i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i], gcur_volume[i], gcur_volume_delta[i], gmixer_control[i],
glooping[i], gloop1[i], gloop2[i], gloop3[i], gis_stream[i],
gfrac[i], gratio[i], gratiohi[i], gratiolo[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i]
);
// =======================================================================================
// write a new line
sbuff = sbuff + buffer; strcpy(buffer, "");
sbuff = sbuff + "\n";
} // end of if (true)
} // end of big loop - for (int i = 0; i < numberOfPBs; i++)
// =======================================================================================
// Write global values
sprintf(buffer, "\nParameter blocks span from %08x | to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192);
sbuff = sbuff + buffer; strcpy(buffer, "");
// ==============
// =======================================================================================
// Show update frequency
// ---------------
sbuff = sbuff + "\n";
if(!iupdonce)
{
/*
for (int i = 0; i < 10; i++)
{
viupd.at(i) == 0;
}
*/
viupd.at(0) = 1;
viupd.at(1) = 1;
viupd.at(2) = 1;
iupdonce = true;
}
for (int i = 0; i < viupd.size(); i++) // 0, 1,..., 9
{
if (i < viupd.size()-1)
{
viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward
}
else
{
viupd.at(0) = viupd.at(viupd.size()-1);
}
// Correction
if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1)
{
viupd.at(0) = 0;
}
if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0)
{
viupd.at(0) = 1;
}
}
for (int i = 0; i < viupd.size(); i++)
{
if(viupd.at(i) == 0)
sbuff = sbuff + " ";
else
sbuff = sbuff + ".";
}
// ================
// =======================================================================================
// Print
// ---------------
ClearScreen();
wprintf("%s", sbuff.c_str());
sbuff.clear(); strcpy(buffer, "");
// ---------------
k=0;
j=0;
// ---------------
}
// ---------------------------------------------------------------------------------------
}
// =======================================================================================
// 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/
#ifdef _WIN32
// =======================================================================================
// Includes
// --------------
#include <iostream>
#include <vector>
#include <string> // So that we can test if std::string == abc
#include <windows.h>
#include "Common.h"
#include "UCode_AXStructs.h" // they are only in a virtual dir called UCodes AX
#include "Console.h" // For wprintf, ClearScreen
// ---------------------------------------------------------------------------------------
// Declarations
// --------------
#define NUMBER_OF_PBS 64 // Todo: move this to a logging class
// ---------------------------------------------------------------------------------------
// Externals
// --------------
extern u32 m_addressPBs;
float ratioFactor;
int globaliSize;
short globalpBuffer;
u32 gLastBlock;
// --------------
// ---------------------------------------------------------------------------------------
// Vectors and other stuff
// --------------
std::vector<u32> gloopPos(64);
std::vector<u32> gsampleEnd(64);
std::vector<u32> gsamplePos(64);
std::vector<u32> gratio(64);
std::vector<u32> gratiohi(64);
std::vector<u32> gratiolo(64);
std::vector<u32> gfrac(64);
std::vector<u32> gcoef(64);
// PBSampleRateConverter mixer
std::vector<u16> gvolume_left(64);
std::vector<u16> gvolume_right(64);
std::vector<u16> gmixer_control(64);
std::vector<u16> gcur_volume(64);
std::vector<u16> gcur_volume_delta(64);
std::vector<u16> gaudioFormat(64);
std::vector<u16> glooping(64);
std::vector<u16> gsrc_type(64);
std::vector<u16> gis_stream(64);
// loop
std::vector<u16> gloop1(64);
std::vector<u16> gloop2(64);
std::vector<u16> gloop3(64);
std::vector<u16> gadloop1(64);
std::vector<u16> gadloop2(64);
std::vector<u16> gadloop3(64);
// updates
std::vector<u16> gupdates1(64);
std::vector<u16> gupdates2(64);
std::vector<u16> gupdates3(64);
std::vector<u16> gupdates4(64);
std::vector<u16> gupdates5(64);
std::vector<u32> gupdates_addr(64);
// other stuff
std::vector<u16> Jump(64); // this is 1 or 0
std::vector<int> musicLength(64);
std::vector< std::vector<int> > vector1(64, std::vector<int>(100,0));
std::vector<int> numberRunning(64);
int j = 0;
int k = 0;
__int64 l = 0;
int iupd = 0;
bool iupdonce = false;
std::vector<u16> viupd(15); // the length of the update frequency bar
int vectorLength = 15; // the length of the playback history bar and how long
// old blocks are shown
std::vector<u16> vector62(vectorLength);
std::vector<u16> vector63(vectorLength);
int ReadOutPBs(AXParamBlock * _pPBs, int _num);
// ===========
// =======================================================================================
// Main logging function
// --------------
void Logging()
{
// ---------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------
// Control how often the screen is updated
j++;
l++;
if (j>1000000) // TODO: make the update frequency adjustable from the logging window
{
AXParamBlock PBs[NUMBER_OF_PBS];
int numberOfPBs = ReadOutPBs(PBs, NUMBER_OF_PBS);
// =======================================================================================
// Vector1 is a vector1[64][100] vector
/*
Move all items back like this
1 to 2
2 3
3 ...
*/
// ----------------
for (int i = 0; i < 64; i++)
{
for (int j = 1; j < vectorLength; j++)
{
vector1.at(i).at(j-1) = vector1.at(i).at(j);
}
}
// =================
// ---------------------------------------------------------------------------------------
// Enter the latest value
for (int i = 0; i < numberOfPBs; i++)
{
vector1.at(i).at(vectorLength-1) = PBs[i].running;
}
// -----------------
// ---------------------------------------------------------------------------------------
// Count how many blocks we have running now
int jj = 0;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < vectorLength-1; j++)
{
if (vector1.at(i).at(j) == 1)
{
jj++;
}
numberRunning.at(i) = jj;
}
}
// --------------
// ---------------------------------------------------------------------------------------
// Write the first row
char buffer [1000] = "";
std::string sbuff;
//sbuff = sbuff + " Nr | | frac ratio | old new \n"; // 5
sbuff = sbuff + " Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
// --------------
// ---------------------------------------------------------------------------------------
// Read out values for all blocks
for (int i = 0; i < numberOfPBs; i++)
{
if (numberRunning.at(i) > 0)
{
// =======================================================================================
// Write the playback bar
// -------------
for (int j = 0; j < vectorLength; j++)
{
if(vector1.at(i).at(j) == 0)
{
sbuff = sbuff + " ";
}
else
{
sprintf(buffer, "%c", 177);
sbuff = sbuff + buffer; strcpy(buffer, "");
}
}
// ==============
// ================================================================================================
int sampleJump;
int loopJump;
//if (PBs[i].running && PBs[i].adpcm_loop_info.yn1 && PBs[i].mixer.volume_left)
if (true)
{
// ---------------------------------------------------------------------------------------
// AXPB base
//int running = pb.running;
gcoef[i] = PBs[i].unknown1;
sampleJump = ((PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo) - gsamplePos[i];
loopJump = ((PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo) - gloopPos[i];
gloopPos[i] = (PBs[i].audio_addr.loop_addr_hi << 16) | PBs[i].audio_addr.loop_addr_lo;
gsampleEnd[i] = (PBs[i].audio_addr.end_addr_hi << 16) | PBs[i].audio_addr.end_addr_lo;
gsamplePos[i] = (PBs[i].audio_addr.cur_addr_hi << 16) | PBs[i].audio_addr.cur_addr_lo;
// PBSampleRateConverter src
gratio[i] = (u32)(((PBs[i].src.ratio_hi << 16) + PBs[i].src.ratio_lo) * ratioFactor);
gratiohi[i] = PBs[i].src.ratio_hi;
gratiolo[i] = PBs[i].src.ratio_lo;
gfrac[i] = PBs[i].src.cur_addr_frac;
// adpcm_loop_info
gadloop1[i] = PBs[i].adpcm.pred_scale;
gadloop2[i] = PBs[i].adpcm.yn1;
gadloop3[i] = PBs[i].adpcm.yn2;
gloop1[i] = PBs[i].adpcm_loop_info.pred_scale;
gloop2[i] = PBs[i].adpcm_loop_info.yn1;
gloop3[i] = PBs[i].adpcm_loop_info.yn2;
// updates
gupdates1[i] = PBs[i].updates.num_updates[0];
gupdates2[i] = PBs[i].updates.num_updates[1];
gupdates3[i] = PBs[i].updates.num_updates[2];
gupdates4[i] = PBs[i].updates.num_updates[3];
gupdates5[i] = PBs[i].updates.num_updates[4];
gupdates_addr[i] = (PBs[i].updates.data_hi << 16) | PBs[i].updates.data_lo;
gaudioFormat[i] = PBs[i].audio_addr.sample_format;
glooping[i] = PBs[i].audio_addr.looping;
gsrc_type[i] = PBs[i].src_type;
gis_stream[i] = PBs[i].is_stream;
// mixer
gvolume_left[i] = PBs[i].mixer.volume_left;
gvolume_right[i] = PBs[i].mixer.volume_right;
gmixer_control[i] = PBs[i].mixer_control;
gcur_volume[i] = PBs[i].vol_env.cur_volume;
gcur_volume_delta[i] = PBs[i].vol_env.cur_volume_delta;
// other stuff
Jump[i] = (gfrac[i] >> 16); // This is 1 or 0
musicLength[i] = gsampleEnd[i] - gloopPos[i];
}
// ================================================================================================
// =======================================================================================
// PRESETS
// ---------------------------------------------------------------------------------------
/*
/" Nr pos / end lpos | voll volr curv vold mix | isl[pre yn1 yn2] iss | frac ratio[hi lo] | 1 2 3 4 5\n";
"---------------|00 12341234/12341234 12341234 | 00000 00000 00000 0000 00000 | 0[000 00000 00000] 0 | 00000 00000[0 00000] |
*/
sprintf(buffer,"%c%i %08i/%08i %08i | %05i %05i %05i %04i %05i | %i[%03i %05i %05i] %i | %05i %05i[%i %05i] | %i %i %i %i %i",
223, i, gsamplePos[i], gsampleEnd[i], gloopPos[i],
gvolume_left[i], gvolume_right[i], gcur_volume[i], gcur_volume_delta[i], gmixer_control[i],
glooping[i], gloop1[i], gloop2[i], gloop3[i], gis_stream[i],
gfrac[i], gratio[i], gratiohi[i], gratiolo[i],
gupdates1[i], gupdates2[i], gupdates3[i], gupdates4[i], gupdates5[i]
);
// =======================================================================================
// write a new line
sbuff = sbuff + buffer; strcpy(buffer, "");
sbuff = sbuff + "\n";
} // end of if (true)
} // end of big loop - for (int i = 0; i < numberOfPBs; i++)
// =======================================================================================
// Write global values
sprintf(buffer, "\nParameter blocks span from %08x | to %08x | distance %i %i\n", m_addressPBs, gLastBlock, (gLastBlock-m_addressPBs), (gLastBlock-m_addressPBs) / 192);
sbuff = sbuff + buffer; strcpy(buffer, "");
// ==============
// =======================================================================================
// Show update frequency
// ---------------
sbuff = sbuff + "\n";
if(!iupdonce)
{
/*
for (int i = 0; i < 10; i++)
{
viupd.at(i) == 0;
}
*/
viupd.at(0) = 1;
viupd.at(1) = 1;
viupd.at(2) = 1;
iupdonce = true;
}
for (int i = 0; i < viupd.size(); i++) // 0, 1,..., 9
{
if (i < viupd.size()-1)
{
viupd.at(viupd.size()-i-1) = viupd.at(viupd.size()-i-2); // move all forward
}
else
{
viupd.at(0) = viupd.at(viupd.size()-1);
}
// Correction
if (viupd.at(viupd.size()-3) == 1 && viupd.at(viupd.size()-2) == 1 && viupd.at(viupd.size()-1) == 1)
{
viupd.at(0) = 0;
}
if(viupd.at(0) == 0 && viupd.at(1) == 1 && viupd.at(2) == 1 && viupd.at(3) == 0)
{
viupd.at(0) = 1;
}
}
for (int i = 0; i < viupd.size(); i++)
{
if(viupd.at(i) == 0)
sbuff = sbuff + " ";
else
sbuff = sbuff + ".";
}
// ================
// =======================================================================================
// Print
// ---------------
ClearScreen();
wprintf("%s", sbuff.c_str());
sbuff.clear(); strcpy(buffer, "");
// ---------------
k=0;
j=0;
// ---------------
}
// ---------------------------------------------------------------------------------------
}
// =======================================================================================
#endif

View File

@ -1,115 +1,115 @@
// 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/
// Turn on and off logging modes
// --------------
//#define LOG1 // writes selected parameters only and with more readable formatting
//#define LOG2 // writes all parameters
#include "Common.h"
#include "../Globals.h"
#include "CommonTypes.h" // Pluginspecs
#include "UCode_AXStructs.h" // For the AXParamBlock structure
#include "Console.h" // For wprintf, ClearScreen
u32 m_addressPBs = 0;
extern u32 gLastBlock;
#ifdef _WIN32
int m = 0;
int n = 0;
#ifdef LOG2
bool logall = true;
#else
bool logall = false;
#endif
int ReadOutPBs(AXParamBlock * _pPBs, int _num)
{
int count = 0;
u32 blockAddr = m_addressPBs;
u32 OldblockAddr = blockAddr;
u32 paraAddr = blockAddr;
// reading and 'halfword' swap
n++;
if (n > 20 && logall) {ClearScreen();}
for (int i = 0; i < _num; i++)
{
// ---------------------------------------------------------------------------------------
// Check if there is something here.
const short * pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
// -------------
if (pSrc != NULL) // only read non-blank blocks
{
// ---------------------------------------------------------------------------------------
// Create a shortcut that let us update struct members
short * pDest = (short *) & _pPBs[i];
if (n > 20 && logall) {wprintf("%c%i:", 223, i);} // logging
// --------------
// Here we update the PB. We do it by going through all 192 / 2 = 96 u16 values
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
paraAddr += 2;
if(pSrc != NULL)
{
if (pSrc[p] != 0 && n > 20 && logall)
{
wprintf("%i %04x | ", p, Common::swap16(pSrc[p]));
}
}
pDest[p] = Common::swap16(pSrc[p]);
}
if(n > 20 && logall) {wprintf("\n");} // logging
// --------------
// Here we update the block address to the starting point of the next PB
blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
// --------------
// save some values
count++;
gLastBlock = paraAddr; // blockAddr
// ============
}
else
{
break;
}
} // end of the big loop
if (n > 20) {n = 0;} // for logging
// return the number of readed PBs
return count;
}
// =======================================================================================
#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/
// Turn on and off logging modes
// --------------
//#define LOG1 // writes selected parameters only and with more readable formatting
//#define LOG2 // writes all parameters
#include "Common.h"
#include "../Globals.h"
#include "CommonTypes.h" // Pluginspecs
#include "UCode_AXStructs.h" // For the AXParamBlock structure
#include "Console.h" // For wprintf, ClearScreen
u32 m_addressPBs = 0;
extern u32 gLastBlock;
#ifdef _WIN32
int m = 0;
int n = 0;
#ifdef LOG2
bool logall = true;
#else
bool logall = false;
#endif
int ReadOutPBs(AXParamBlock * _pPBs, int _num)
{
int count = 0;
u32 blockAddr = m_addressPBs;
u32 OldblockAddr = blockAddr;
u32 paraAddr = blockAddr;
// reading and 'halfword' swap
n++;
if (n > 20 && logall) {ClearScreen();}
for (int i = 0; i < _num; i++)
{
// ---------------------------------------------------------------------------------------
// Check if there is something here.
const short * pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
// -------------
if (pSrc != NULL) // only read non-blank blocks
{
// ---------------------------------------------------------------------------------------
// Create a shortcut that let us update struct members
short * pDest = (short *) & _pPBs[i];
if (n > 20 && logall) {wprintf("%c%i:", 223, i);} // logging
// --------------
// Here we update the PB. We do it by going through all 192 / 2 = 96 u16 values
for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
paraAddr += 2;
if(pSrc != NULL)
{
if (pSrc[p] != 0 && n > 20 && logall)
{
wprintf("%i %04x | ", p, Common::swap16(pSrc[p]));
}
}
pDest[p] = Common::swap16(pSrc[p]);
}
if(n > 20 && logall) {wprintf("\n");} // logging
// --------------
// Here we update the block address to the starting point of the next PB
blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
// --------------
// save some values
count++;
gLastBlock = paraAddr; // blockAddr
// ============
}
else
{
break;
}
} // end of the big loop
if (n > 20) {n = 0;} // for logging
// return the number of readed PBs
return count;
}
// =======================================================================================
#endif

View File

@ -1,164 +1,164 @@
// 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 queue solution is temporary. I'll implement something more efficient later.
#include <queue>
#include "Thread.h"
#include "Mixer.h"
#include "FixedSizeQueue.h"
#ifdef _WIN32
#include "DSoundStream.h"
#else
#include <unistd.h>
#endif
namespace {
Common::CriticalSection push_sync;
// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so...
const int queue_minlength = 1024 * 4;
const int queue_maxlength = 1024 * 28;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
} // namespace
volatile bool mixer_HLEready = false;
volatile int queue_size = 0;
void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
{
// silence
memset(buffer, 0, numSamples * 2 * sizeof(short));
push_sync.Enter();
int count = 0;
while (queue_size > queue_minlength && count < numSamples * 2) {
int x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
queue_size-=2;
}
push_sync.Leave();
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
// static FILE *f;
// if (!f)
// f = fopen("d:\\hello.raw", "wb");
// fwrite(buffer, num_stereo_samples * 4, 1, f);
if (queue_size == 0)
{
queue_size = queue_minlength;
for (int i = 0; i < queue_minlength; i++)
sample_queue.push((s16)0);
}
static int PV1l=0,PV2l=0,PV3l=0,PV4l=0;
static int PV1r=0,PV2r=0,PV3r=0,PV4r=0;
static int acc=0;
#ifdef _WIN32
if (!GetAsyncKeyState(VK_TAB)) {
while (queue_size > queue_maxlength / 2) {
DSound::DSound_UpdateSound();
Sleep(0);
}
} else {
return;
}
#else
while (queue_size > queue_maxlength) {
sleep(0);
}
#endif
//convert into config option?
const int mode = 2;
push_sync.Enter();
while (num_stereo_samples)
{
acc += sample_rate;
while (num_stereo_samples && (acc >= 48000))
{
PV4l=PV3l;
PV3l=PV2l;
PV2l=PV1l;
PV1l=*(buffer++); //32bit processing
PV4r=PV3r;
PV3r=PV2r;
PV2r=PV1r;
PV1r=*(buffer++); //32bit processing
num_stereo_samples--;
acc-=48000;
}
// defaults to nearest
s32 DataL = PV1l;
s32 DataR = PV1r;
if (mode == 1) //linear
{
DataL = PV1l + ((PV2l - PV1l)*acc)/48000;
DataR = PV1r + ((PV2r - PV1r)*acc)/48000;
}
else if (mode == 2) //cubic
{
s32 a0l = PV1l - PV2l - PV4l + PV3l;
s32 a0r = PV1r - PV2r - PV4r + PV3r;
s32 a1l = PV4l - PV3l - a0l;
s32 a1r = PV4r - PV3r - a0r;
s32 a2l = PV1l - PV4l;
s32 a2r = PV1r - PV4r;
s32 a3l = PV2l;
s32 a3r = PV2r;
s32 t0l = ((a0l )*acc)/48000;
s32 t0r = ((a0r )*acc)/48000;
s32 t1l = ((t0l+a1l)*acc)/48000;
s32 t1r = ((t0r+a1r)*acc)/48000;
s32 t2l = ((t1l+a2l)*acc)/48000;
s32 t2r = ((t1r+a2r)*acc)/48000;
s32 t3l = ((t2l+a3l));
s32 t3r = ((t2r+a3r));
DataL = t3l;
DataR = t3r;
}
int l = DataL, r = DataR;
if (l < -32767) l = -32767;
if (r < -32767) r = -32767;
if (l > 32767) l = 32767;
if (r > 32767) r = 32767;
sample_queue.push(l);
sample_queue.push(r);
}
push_sync.Leave();
}
// 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 queue solution is temporary. I'll implement something more efficient later.
#include <queue>
#include "Thread.h"
#include "Mixer.h"
#include "FixedSizeQueue.h"
#ifdef _WIN32
#include "DSoundStream.h"
#else
#include <unistd.h>
#endif
namespace {
Common::CriticalSection push_sync;
// On real hardware, this fifo is much, much smaller. But timing is also tighter than under Windows, so...
const int queue_minlength = 1024 * 4;
const int queue_maxlength = 1024 * 28;
FixedSizeQueue<s16, queue_maxlength> sample_queue;
} // namespace
volatile bool mixer_HLEready = false;
volatile int queue_size = 0;
void Mixer(short *buffer, int numSamples, int bits, int rate, int channels)
{
// silence
memset(buffer, 0, numSamples * 2 * sizeof(short));
push_sync.Enter();
int count = 0;
while (queue_size > queue_minlength && count < numSamples * 2) {
int x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
x = buffer[count];
x += sample_queue.front();
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buffer[count++] = x;
sample_queue.pop();
queue_size-=2;
}
push_sync.Leave();
}
void Mixer_PushSamples(short *buffer, int num_stereo_samples, int sample_rate) {
// static FILE *f;
// if (!f)
// f = fopen("d:\\hello.raw", "wb");
// fwrite(buffer, num_stereo_samples * 4, 1, f);
if (queue_size == 0)
{
queue_size = queue_minlength;
for (int i = 0; i < queue_minlength; i++)
sample_queue.push((s16)0);
}
static int PV1l=0,PV2l=0,PV3l=0,PV4l=0;
static int PV1r=0,PV2r=0,PV3r=0,PV4r=0;
static int acc=0;
#ifdef _WIN32
if (!GetAsyncKeyState(VK_TAB)) {
while (queue_size > queue_maxlength / 2) {
DSound::DSound_UpdateSound();
Sleep(0);
}
} else {
return;
}
#else
while (queue_size > queue_maxlength) {
sleep(0);
}
#endif
//convert into config option?
const int mode = 2;
push_sync.Enter();
while (num_stereo_samples)
{
acc += sample_rate;
while (num_stereo_samples && (acc >= 48000))
{
PV4l=PV3l;
PV3l=PV2l;
PV2l=PV1l;
PV1l=*(buffer++); //32bit processing
PV4r=PV3r;
PV3r=PV2r;
PV2r=PV1r;
PV1r=*(buffer++); //32bit processing
num_stereo_samples--;
acc-=48000;
}
// defaults to nearest
s32 DataL = PV1l;
s32 DataR = PV1r;
if (mode == 1) //linear
{
DataL = PV1l + ((PV2l - PV1l)*acc)/48000;
DataR = PV1r + ((PV2r - PV1r)*acc)/48000;
}
else if (mode == 2) //cubic
{
s32 a0l = PV1l - PV2l - PV4l + PV3l;
s32 a0r = PV1r - PV2r - PV4r + PV3r;
s32 a1l = PV4l - PV3l - a0l;
s32 a1r = PV4r - PV3r - a0r;
s32 a2l = PV1l - PV4l;
s32 a2r = PV1r - PV4r;
s32 a3l = PV2l;
s32 a3r = PV2r;
s32 t0l = ((a0l )*acc)/48000;
s32 t0r = ((a0r )*acc)/48000;
s32 t1l = ((t0l+a1l)*acc)/48000;
s32 t1r = ((t0r+a1r)*acc)/48000;
s32 t2l = ((t1l+a2l)*acc)/48000;
s32 t2r = ((t1r+a2r)*acc)/48000;
s32 t3l = ((t2l+a3l));
s32 t3r = ((t2r+a3r));
DataL = t3l;
DataR = t3r;
}
int l = DataL, r = DataR;
if (l < -32767) l = -32767;
if (r < -32767) r = -32767;
if (l > 32767) l = 32767;
if (r > 32767) r = 32767;
sample_queue.push(l);
sample_queue.push(r);
}
push_sync.Leave();
}

View File

@ -1,274 +1,274 @@
// RegSettings.cpp
//
// Copyright (c) 2001 Magomed Abdurakhmanov
// maq@hotbox.ru, http://mickels.iwt.ru/en
//
//
//
// No warranties are given. Use at your own risk.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RegSettings.h"
//////////////////////////////////////////////////////////////////////
// CWindowSettings
#define S_WINDOW_PLACEMENT_VAL _T("WindowPlacement")
CWindowSettings::CWindowSettings()
{
m_WindowPlacement.length = sizeof(m_WindowPlacement);
m_WindowPlacement.flags = 0;
m_WindowPlacement.ptMinPosition.x = 0;
m_WindowPlacement.ptMinPosition.y = 0;
m_WindowPlacement.ptMaxPosition.x = 0;
m_WindowPlacement.ptMaxPosition.y = 0;
CRect rc;
SystemParametersInfo(SPI_GETWORKAREA, 0, rc, 0);
rc.DeflateRect(100, 100);
m_WindowPlacement.rcNormalPosition = rc;
m_WindowPlacement.showCmd = SW_SHOWNORMAL;
}
bool CWindowSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
DWORD dwType = NULL;
DWORD dwSize = sizeof(m_WindowPlacement);
err = RegQueryValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, &dwType,
(LPBYTE)&m_WindowPlacement, &dwSize);
}
return(err == ERROR_SUCCESS);
}
bool CWindowSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
err = RegSetValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, REG_BINARY,
(LPBYTE)&m_WindowPlacement, sizeof(m_WindowPlacement));
}
return(err == ERROR_SUCCESS);
}
void CWindowSettings::GetFrom(CWindow& Wnd)
{
ATLASSERT(Wnd.IsWindow());
Wnd.GetWindowPlacement(&m_WindowPlacement);
}
void CWindowSettings::ApplyTo(CWindow& Wnd, int nCmdShow /* = SW_SHOWNORMAL*/) const
{
ATLASSERT(Wnd.IsWindow());
Wnd.SetWindowPlacement(&m_WindowPlacement);
if (SW_SHOWNORMAL != nCmdShow)
{
Wnd.ShowWindow(nCmdShow);
}
else
if (m_WindowPlacement.showCmd == SW_MINIMIZE || m_WindowPlacement.showCmd == SW_SHOWMINIMIZED)
{
Wnd.ShowWindow(SW_SHOWNORMAL);
}
}
//////////////////////////////////////////////////////////////////////
// CReBarSettings
#define S_BAR_BANDCOUNT _T("BandCount")
#define S_BAR_ID_VAL _T("ID")
#define S_BAR_CX_VAL _T("CX")
#define S_BAR_BREAKLINE_VAL _T("BreakLine")
CReBarSettings::CReBarSettings()
{
m_pBands = NULL;
m_cbBandCount = 0;
}
CReBarSettings::~CReBarSettings()
{
if (m_pBands != NULL)
{
delete[] m_pBands;
m_pBands = NULL;
}
}
bool CReBarSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
if (m_pBands != NULL)
{
delete[] m_pBands;
m_pBands = NULL;
}
m_pBands = NULL;
m_cbBandCount = 0;
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
reg.QueryDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount);
if (m_cbBandCount > 0)
{
m_pBands = new BandInfo[m_cbBandCount];
}
for (DWORD i = 0; i < m_cbBandCount; i++)
{
CString s;
s.Format(_T("%s%i_"), szPrefix, i);
reg.QueryDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID);
reg.QueryDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx);
DWORD dw;
reg.QueryDWORDValue(s + S_BAR_BREAKLINE_VAL, dw);
m_pBands[i].BreakLine = dw != 0;
}
}
return(err == ERROR_SUCCESS);
}
bool CReBarSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
reg.SetDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount);
for (DWORD i = 0; i < m_cbBandCount; i++)
{
CString s;
s.Format(_T("%s%i_"), szPrefix, i);
reg.SetDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID);
reg.SetDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx);
DWORD dw = m_pBands[i].BreakLine;
reg.SetDWORDValue(s + S_BAR_BREAKLINE_VAL, dw);
}
}
return(err == ERROR_SUCCESS);
}
void CReBarSettings::GetFrom(CReBarCtrl& ReBar)
{
ATLASSERT(ReBar.IsWindow());
if (m_pBands != NULL)
{
delete[] m_pBands;
}
m_pBands = NULL;
m_cbBandCount = ReBar.GetBandCount();
if (m_cbBandCount > 0)
{
m_pBands = new BandInfo[m_cbBandCount];
}
for (UINT i = 0; i < m_cbBandCount; i++)
{
REBARBANDINFO rbi;
rbi.cbSize = sizeof(rbi);
rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE;
ReBar.GetBandInfo(i, &rbi);
m_pBands[i].ID = rbi.wID;
m_pBands[i].cx = rbi.cx;
m_pBands[i].BreakLine = (rbi.fStyle & RBBS_BREAK) != 0;
}
}
void CReBarSettings::ApplyTo(CReBarCtrl& ReBar) const
{
ATLASSERT(ReBar.IsWindow());
for (UINT i = 0; i < m_cbBandCount; i++)
{
ReBar.MoveBand(ReBar.IdToIndex(m_pBands[i].ID), i);
REBARBANDINFO rbi;
rbi.cbSize = sizeof(rbi);
rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE;
ReBar.GetBandInfo(i, &rbi);
rbi.cx = m_pBands[i].cx;
if (m_pBands[i].BreakLine)
{
rbi.fStyle |= RBBS_BREAK;
}
else
{
rbi.fStyle &= (~RBBS_BREAK);
}
ReBar.SetBandInfo(i, &rbi);
}
}
//////////////////////////////////////////////////////////////////////
// CSplitterSettings
#define S_SPLITTER_POS _T("SplitterPos")
bool CSplitterSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
reg.QueryDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos);
}
return(err == ERROR_SUCCESS);
}
bool CSplitterSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
reg.SetDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos);
}
return(err == ERROR_SUCCESS);
}
// RegSettings.cpp
//
// Copyright (c) 2001 Magomed Abdurakhmanov
// maq@hotbox.ru, http://mickels.iwt.ru/en
//
//
//
// No warranties are given. Use at your own risk.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RegSettings.h"
//////////////////////////////////////////////////////////////////////
// CWindowSettings
#define S_WINDOW_PLACEMENT_VAL _T("WindowPlacement")
CWindowSettings::CWindowSettings()
{
m_WindowPlacement.length = sizeof(m_WindowPlacement);
m_WindowPlacement.flags = 0;
m_WindowPlacement.ptMinPosition.x = 0;
m_WindowPlacement.ptMinPosition.y = 0;
m_WindowPlacement.ptMaxPosition.x = 0;
m_WindowPlacement.ptMaxPosition.y = 0;
CRect rc;
SystemParametersInfo(SPI_GETWORKAREA, 0, rc, 0);
rc.DeflateRect(100, 100);
m_WindowPlacement.rcNormalPosition = rc;
m_WindowPlacement.showCmd = SW_SHOWNORMAL;
}
bool CWindowSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
DWORD dwType = NULL;
DWORD dwSize = sizeof(m_WindowPlacement);
err = RegQueryValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, &dwType,
(LPBYTE)&m_WindowPlacement, &dwSize);
}
return(err == ERROR_SUCCESS);
}
bool CWindowSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
err = RegSetValueEx(reg.m_hKey, CString(szPrefix) + S_WINDOW_PLACEMENT_VAL, NULL, REG_BINARY,
(LPBYTE)&m_WindowPlacement, sizeof(m_WindowPlacement));
}
return(err == ERROR_SUCCESS);
}
void CWindowSettings::GetFrom(CWindow& Wnd)
{
ATLASSERT(Wnd.IsWindow());
Wnd.GetWindowPlacement(&m_WindowPlacement);
}
void CWindowSettings::ApplyTo(CWindow& Wnd, int nCmdShow /* = SW_SHOWNORMAL*/) const
{
ATLASSERT(Wnd.IsWindow());
Wnd.SetWindowPlacement(&m_WindowPlacement);
if (SW_SHOWNORMAL != nCmdShow)
{
Wnd.ShowWindow(nCmdShow);
}
else
if (m_WindowPlacement.showCmd == SW_MINIMIZE || m_WindowPlacement.showCmd == SW_SHOWMINIMIZED)
{
Wnd.ShowWindow(SW_SHOWNORMAL);
}
}
//////////////////////////////////////////////////////////////////////
// CReBarSettings
#define S_BAR_BANDCOUNT _T("BandCount")
#define S_BAR_ID_VAL _T("ID")
#define S_BAR_CX_VAL _T("CX")
#define S_BAR_BREAKLINE_VAL _T("BreakLine")
CReBarSettings::CReBarSettings()
{
m_pBands = NULL;
m_cbBandCount = 0;
}
CReBarSettings::~CReBarSettings()
{
if (m_pBands != NULL)
{
delete[] m_pBands;
m_pBands = NULL;
}
}
bool CReBarSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
if (m_pBands != NULL)
{
delete[] m_pBands;
m_pBands = NULL;
}
m_pBands = NULL;
m_cbBandCount = 0;
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
reg.QueryDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount);
if (m_cbBandCount > 0)
{
m_pBands = new BandInfo[m_cbBandCount];
}
for (DWORD i = 0; i < m_cbBandCount; i++)
{
CString s;
s.Format(_T("%s%i_"), szPrefix, i);
reg.QueryDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID);
reg.QueryDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx);
DWORD dw;
reg.QueryDWORDValue(s + S_BAR_BREAKLINE_VAL, dw);
m_pBands[i].BreakLine = dw != 0;
}
}
return(err == ERROR_SUCCESS);
}
bool CReBarSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
reg.SetDWORDValue(CString(szPrefix) + S_BAR_BANDCOUNT, m_cbBandCount);
for (DWORD i = 0; i < m_cbBandCount; i++)
{
CString s;
s.Format(_T("%s%i_"), szPrefix, i);
reg.SetDWORDValue(s + S_BAR_ID_VAL, m_pBands[i].ID);
reg.SetDWORDValue(s + S_BAR_CX_VAL, m_pBands[i].cx);
DWORD dw = m_pBands[i].BreakLine;
reg.SetDWORDValue(s + S_BAR_BREAKLINE_VAL, dw);
}
}
return(err == ERROR_SUCCESS);
}
void CReBarSettings::GetFrom(CReBarCtrl& ReBar)
{
ATLASSERT(ReBar.IsWindow());
if (m_pBands != NULL)
{
delete[] m_pBands;
}
m_pBands = NULL;
m_cbBandCount = ReBar.GetBandCount();
if (m_cbBandCount > 0)
{
m_pBands = new BandInfo[m_cbBandCount];
}
for (UINT i = 0; i < m_cbBandCount; i++)
{
REBARBANDINFO rbi;
rbi.cbSize = sizeof(rbi);
rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE;
ReBar.GetBandInfo(i, &rbi);
m_pBands[i].ID = rbi.wID;
m_pBands[i].cx = rbi.cx;
m_pBands[i].BreakLine = (rbi.fStyle & RBBS_BREAK) != 0;
}
}
void CReBarSettings::ApplyTo(CReBarCtrl& ReBar) const
{
ATLASSERT(ReBar.IsWindow());
for (UINT i = 0; i < m_cbBandCount; i++)
{
ReBar.MoveBand(ReBar.IdToIndex(m_pBands[i].ID), i);
REBARBANDINFO rbi;
rbi.cbSize = sizeof(rbi);
rbi.fMask = RBBIM_ID | RBBIM_SIZE | RBBIM_STYLE;
ReBar.GetBandInfo(i, &rbi);
rbi.cx = m_pBands[i].cx;
if (m_pBands[i].BreakLine)
{
rbi.fStyle |= RBBS_BREAK;
}
else
{
rbi.fStyle &= (~RBBS_BREAK);
}
ReBar.SetBandInfo(i, &rbi);
}
}
//////////////////////////////////////////////////////////////////////
// CSplitterSettings
#define S_SPLITTER_POS _T("SplitterPos")
bool CSplitterSettings::Load(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/)
{
CRegKey reg;
DWORD err = reg.Open(hkRootKey, szRegKey, KEY_READ);
if (err == ERROR_SUCCESS)
{
reg.QueryDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos);
}
return(err == ERROR_SUCCESS);
}
bool CSplitterSettings::Save(LPCTSTR szRegKey, LPCTSTR szPrefix, HKEY hkRootKey /* = HKEY_CURRENT_USER*/) const
{
CRegKey reg;
DWORD err = reg.Create(hkRootKey, szRegKey);
if (err == ERROR_SUCCESS)
{
reg.SetDWORDValue(CString(szPrefix) + S_SPLITTER_POS, m_dwPos);
}
return(err == ERROR_SUCCESS);
}

View File

@ -1,207 +1,207 @@
// 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 "../res/resource.h"
#include "RegisterDlg.h"
#include "disassemble.h"
#include "gdsp_interpreter.h"
#include "RegSettings.h"
CRegisterDlg::CRegisterDlg()
: m_CachedCounter(-1)
{}
BOOL CRegisterDlg::PreTranslateMessage(MSG* pMsg)
{
return(IsDialogMessage(pMsg));
}
BOOL CRegisterDlg::OnIdle()
{
return(FALSE);
}
LRESULT CRegisterDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowSettings ws;
if (ws.Load("Software\\Dolphin\\DSP", "Register"))
{
ws.ApplyTo(CWindow(m_hWnd), SW_SHOW);
}
m_RegisterListViewCtrl.m_hWnd = GetDlgItem(IDC_DISASM_LIST);
UIAddChildWindowContainer(m_hWnd);
m_RegisterListViewCtrl.AddColumn(_T("General"), 0);
m_RegisterListViewCtrl.AddColumn(_T(" "), 1);
m_RegisterListViewCtrl.AddColumn(_T("Special"), 2);
m_RegisterListViewCtrl.AddColumn(_T("0"), 3);
m_RegisterListViewCtrl.SetColumnWidth(0, 50);
m_RegisterListViewCtrl.SetColumnWidth(1, 100);
m_RegisterListViewCtrl.SetColumnWidth(2, 60);
m_RegisterListViewCtrl.SetColumnWidth(3, 100);
m_RegisterListViewCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_RegisterListViewCtrl.SetTextBkColor(GetSysColor(COLOR_3DLIGHT));
for (uint16 i = 0; i < 16; i++)
{
// 0-15
int Item = m_RegisterListViewCtrl.AddItem(0, 0, gd_dis_get_reg_name(i));
// 16-31
m_RegisterListViewCtrl.AddItem(Item, 2, gd_dis_get_reg_name(16 + i));
// just for easy sort
m_RegisterListViewCtrl.SetItemData(Item, i);
}
m_RegisterListViewCtrl.SortItems(CompareFunc, (LPARAM) this);
UpdateRegisterListView();
return(TRUE);
}
LRESULT CRegisterDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowSettings ws;
ws.GetFrom(CWindow(m_hWnd));
ws.Save("Software\\Dolphin\\DSP", "Register");
return(0);
}
void CRegisterDlg::UpdateRegisterListView()
{
if (m_CachedCounter == g_dsp.step_counter)
{
return;
}
m_CachedCounter = g_dsp.step_counter;
char Temp[256];
for (uint16 i = 0; i < 16; i++)
{
// 0-15
if (m_CachedRegs[i] != g_dsp.r[i])
{
m_CachedRegHasChanged[i] = true;
}
else
{
m_CachedRegHasChanged[i] = false;
}
m_CachedRegs[i] = g_dsp.r[i];
sprintf_s(Temp, 256, "0x%04x", g_dsp.r[i]);
m_RegisterListViewCtrl.SetItemText(i, 1, Temp);
// 16-31
if (m_CachedRegs[16 + i] != g_dsp.r[16 + i])
{
m_CachedRegHasChanged[16 + i] = true;
}
else
{
m_CachedRegHasChanged[16 + i] = false;
}
m_CachedRegs[16 + i] = g_dsp.r[16 + i];
sprintf_s(Temp, 256, "0x%04x", g_dsp.r[16 + i]);
m_RegisterListViewCtrl.SetItemText(i, 3, Temp);
}
}
int CALLBACK CRegisterDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
return(lParam1 > lParam2);
}
LRESULT CRegisterDlg::OnCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& _bHandled)
{
int result = CDRF_DODEFAULT;
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pnmh);
switch (pLVCD->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
result = CDRF_NOTIFYITEMDRAW;
break;
case CDDS_ITEMPREPAINT:
result = CDRF_NOTIFYSUBITEMDRAW;
break;
case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
{
pLVCD->nmcd.uItemState &= ~(CDIS_SELECTED | CDIS_FOCUS);
int Offset = static_cast<int>(m_RegisterListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec));
size_t Register = -1;
if (pLVCD->iSubItem == 1)
{
Register = Offset;
}
else if (pLVCD->iSubItem == 3)
{
Register = Offset + 16;
}
if (Register != -1)
{
if (m_CachedRegHasChanged[Register])
{
pLVCD->clrTextBk = RGB(0xFF, 192, 192);
}
else
{
pLVCD->clrTextBk = RGB(0xF0, 0xF0, 0xF0);
}
}
else
{
pLVCD->clrTextBk = RGB(192, 224, 192);
}
// uint16 CurrentAddress = static_cast<uint16>(m_DisAsmListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec));
}
break;
}
return(result);
}
// 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 "../res/resource.h"
#include "RegisterDlg.h"
#include "disassemble.h"
#include "gdsp_interpreter.h"
#include "RegSettings.h"
CRegisterDlg::CRegisterDlg()
: m_CachedCounter(-1)
{}
BOOL CRegisterDlg::PreTranslateMessage(MSG* pMsg)
{
return(IsDialogMessage(pMsg));
}
BOOL CRegisterDlg::OnIdle()
{
return(FALSE);
}
LRESULT CRegisterDlg::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowSettings ws;
if (ws.Load("Software\\Dolphin\\DSP", "Register"))
{
ws.ApplyTo(CWindow(m_hWnd), SW_SHOW);
}
m_RegisterListViewCtrl.m_hWnd = GetDlgItem(IDC_DISASM_LIST);
UIAddChildWindowContainer(m_hWnd);
m_RegisterListViewCtrl.AddColumn(_T("General"), 0);
m_RegisterListViewCtrl.AddColumn(_T(" "), 1);
m_RegisterListViewCtrl.AddColumn(_T("Special"), 2);
m_RegisterListViewCtrl.AddColumn(_T("0"), 3);
m_RegisterListViewCtrl.SetColumnWidth(0, 50);
m_RegisterListViewCtrl.SetColumnWidth(1, 100);
m_RegisterListViewCtrl.SetColumnWidth(2, 60);
m_RegisterListViewCtrl.SetColumnWidth(3, 100);
m_RegisterListViewCtrl.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
m_RegisterListViewCtrl.SetTextBkColor(GetSysColor(COLOR_3DLIGHT));
for (uint16 i = 0; i < 16; i++)
{
// 0-15
int Item = m_RegisterListViewCtrl.AddItem(0, 0, gd_dis_get_reg_name(i));
// 16-31
m_RegisterListViewCtrl.AddItem(Item, 2, gd_dis_get_reg_name(16 + i));
// just for easy sort
m_RegisterListViewCtrl.SetItemData(Item, i);
}
m_RegisterListViewCtrl.SortItems(CompareFunc, (LPARAM) this);
UpdateRegisterListView();
return(TRUE);
}
LRESULT CRegisterDlg::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CWindowSettings ws;
ws.GetFrom(CWindow(m_hWnd));
ws.Save("Software\\Dolphin\\DSP", "Register");
return(0);
}
void CRegisterDlg::UpdateRegisterListView()
{
if (m_CachedCounter == g_dsp.step_counter)
{
return;
}
m_CachedCounter = g_dsp.step_counter;
char Temp[256];
for (uint16 i = 0; i < 16; i++)
{
// 0-15
if (m_CachedRegs[i] != g_dsp.r[i])
{
m_CachedRegHasChanged[i] = true;
}
else
{
m_CachedRegHasChanged[i] = false;
}
m_CachedRegs[i] = g_dsp.r[i];
sprintf_s(Temp, 256, "0x%04x", g_dsp.r[i]);
m_RegisterListViewCtrl.SetItemText(i, 1, Temp);
// 16-31
if (m_CachedRegs[16 + i] != g_dsp.r[16 + i])
{
m_CachedRegHasChanged[16 + i] = true;
}
else
{
m_CachedRegHasChanged[16 + i] = false;
}
m_CachedRegs[16 + i] = g_dsp.r[16 + i];
sprintf_s(Temp, 256, "0x%04x", g_dsp.r[16 + i]);
m_RegisterListViewCtrl.SetItemText(i, 3, Temp);
}
}
int CALLBACK CRegisterDlg::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
return(lParam1 > lParam2);
}
LRESULT CRegisterDlg::OnCustomDraw(int /*idCtrl*/, LPNMHDR pnmh, BOOL& _bHandled)
{
int result = CDRF_DODEFAULT;
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pnmh);
switch (pLVCD->nmcd.dwDrawStage)
{
case CDDS_PREPAINT:
result = CDRF_NOTIFYITEMDRAW;
break;
case CDDS_ITEMPREPAINT:
result = CDRF_NOTIFYSUBITEMDRAW;
break;
case (CDDS_ITEMPREPAINT | CDDS_SUBITEM):
{
pLVCD->nmcd.uItemState &= ~(CDIS_SELECTED | CDIS_FOCUS);
int Offset = static_cast<int>(m_RegisterListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec));
size_t Register = -1;
if (pLVCD->iSubItem == 1)
{
Register = Offset;
}
else if (pLVCD->iSubItem == 3)
{
Register = Offset + 16;
}
if (Register != -1)
{
if (m_CachedRegHasChanged[Register])
{
pLVCD->clrTextBk = RGB(0xFF, 192, 192);
}
else
{
pLVCD->clrTextBk = RGB(0xF0, 0xF0, 0xF0);
}
}
else
{
pLVCD->clrTextBk = RGB(192, 224, 192);
}
// uint16 CurrentAddress = static_cast<uint16>(m_DisAsmListViewCtrl.GetItemData((int)pLVCD->nmcd.dwItemSpec));
}
break;
}
return(result);
}

View File

@ -1,93 +1,93 @@
// 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 <stdio.h>
#include <stdlib.h>
#include "Common.h"
#include "Globals.h"
#include "gdsp_interpreter.h"
bool DumpDSPCode(uint32 _Address, uint32 _Length, uint32 crc)
{
char szFilename[MAX_PATH];
sprintf(szFilename, "c:\\_\\DSP_UC_%08X.bin", crc);
FILE* pFile = fopen(szFilename, "wb");
if (pFile != NULL)
{
fwrite(g_dspInitialize.pGetMemoryPointer(_Address), _Length, 1, pFile);
fclose(pFile);
return(true);
}
else
{
PanicAlert("Cant open file (%s) to dump UCode!!", szFilename);
}
return(false);
}
uint32 GenerateCRC(const unsigned char* _pBuffer, int _pLength)
{
unsigned long CRC = 0xFFFFFFFF;
while (_pLength--)
{
unsigned long Temp = (unsigned long)((CRC & 0xFF) ^ *_pBuffer++);
for (int j = 0; j < 8; j++)
{
if (Temp & 0x1)
{
Temp = (Temp >> 1) ^ 0xEDB88320;
}
else
{
Temp >>= 1;
}
}
CRC = (CRC >> 8) ^ Temp;
}
return(CRC ^ 0xFFFFFFFF);
}
bool DumpCWCode(uint32 _Address, uint32 _Length)
{
FILE* pFile = fopen("d:\\DSP_UCode.bin", "wb");
if (pFile != NULL)
{
for (size_t i = _Address; i < _Address + _Length; i++)
{
uint16 val = Common::swap16(g_dsp.iram[i]);
fprintf(pFile, " cw 0x%04x \n", val);
}
fclose(pFile);
return(true);
}
return(false);
}
// 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 <stdio.h>
#include <stdlib.h>
#include "Common.h"
#include "Globals.h"
#include "gdsp_interpreter.h"
bool DumpDSPCode(uint32 _Address, uint32 _Length, uint32 crc)
{
char szFilename[MAX_PATH];
sprintf(szFilename, "c:\\_\\DSP_UC_%08X.bin", crc);
FILE* pFile = fopen(szFilename, "wb");
if (pFile != NULL)
{
fwrite(g_dspInitialize.pGetMemoryPointer(_Address), _Length, 1, pFile);
fclose(pFile);
return(true);
}
else
{
PanicAlert("Cant open file (%s) to dump UCode!!", szFilename);
}
return(false);
}
uint32 GenerateCRC(const unsigned char* _pBuffer, int _pLength)
{
unsigned long CRC = 0xFFFFFFFF;
while (_pLength--)
{
unsigned long Temp = (unsigned long)((CRC & 0xFF) ^ *_pBuffer++);
for (int j = 0; j < 8; j++)
{
if (Temp & 0x1)
{
Temp = (Temp >> 1) ^ 0xEDB88320;
}
else
{
Temp >>= 1;
}
}
CRC = (CRC >> 8) ^ Temp;
}
return(CRC ^ 0xFFFFFFFF);
}
bool DumpCWCode(uint32 _Address, uint32 _Length)
{
FILE* pFile = fopen("d:\\DSP_UCode.bin", "wb");
if (pFile != NULL)
{
for (size_t i = _Address; i < _Address + _Length; i++)
{
uint16 val = Common::swap16(g_dsp.iram[i]);
fprintf(pFile, " cw 0x%04x \n", val);
}
fclose(pFile);
return(true);
}
return(false);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,113 +1,113 @@
// 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 "Globals.h"
#include "gdsp_interface.h"
extern uint16 dsp_swap16(uint16 x);
// The hardware adpcm decoder :)
sint16 ADPCM_Step(uint32& _rSamplePos, uint32 _BaseAddress)
{
sint16* pCoefTable = (sint16*)&gdsp_ifx_regs[DSP_COEF_A1_0];
if (((_rSamplePos) & 15) == 0)
{
gdsp_ifx_regs[DSP_PRED_SCALE] = g_dspInitialize.pARAM_Read_U8((_rSamplePos & ~15) >> 1);
_rSamplePos += 2;
}
int scale = 1 << (gdsp_ifx_regs[DSP_PRED_SCALE] & 0xF);
int coef_idx = gdsp_ifx_regs[DSP_PRED_SCALE] >> 4;
sint32 coef1 = pCoefTable[coef_idx * 2 + 0];
sint32 coef2 = pCoefTable[coef_idx * 2 + 1];
int temp = (_rSamplePos & 1) ?
(g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) & 0xF) :
(g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) >> 4);
if (temp >= 8)
temp -= 16;
// 0x400 = 0.5 in 11-bit fixed point
int val = (scale * temp) + ((0x400 + coef1 * (sint16)gdsp_ifx_regs[DSP_YN1] + coef2 * (sint16)gdsp_ifx_regs[DSP_YN2]) >> 11);
// Clamp values.
if (val > 0x7FFF)
val = 0x7FFF;
else if (val < -0x7FFF)
val = -0x7FFF;
gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
gdsp_ifx_regs[DSP_YN1] = val;
_rSamplePos++;
// The advanced interpolation (linear, polyphase,...) is done by the UCode, so we don't
// need to bother with it here.
return val;
}
extern void gdsp_generate_exception(uint8 level);
uint16 dsp_read_aram()
{
// uint32 BaseAddress = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
uint32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
uint32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
uint16 val;
// lets the "hardware" decode
switch (gdsp_ifx_regs[DSP_FORMAT])
{
case 0x00:
val = ADPCM_Step(Address, EndAddress);
break;
case 0x0A:
val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1);
gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
gdsp_ifx_regs[DSP_YN1] = val;
Address += 2;
break;
default:
val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1);
Address += 2;
ErrorLog("Unknown DSP Format %i", gdsp_ifx_regs[DSP_FORMAT]);
break;
}
// check for loop
if (Address > EndAddress)
{
Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
gdsp_generate_exception(3);
gdsp_generate_exception(5);
// Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah,
// it seems likely that we should raise an exception to let the DSP program do that,
// at least if DSP_FORMAT == 0x0A.
}
gdsp_ifx_regs[DSP_ACCAH] = Address >> 16;
gdsp_ifx_regs[DSP_ACCAL] = Address & 0xffff;
return(val);
}
// 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 "Globals.h"
#include "gdsp_interface.h"
extern uint16 dsp_swap16(uint16 x);
// The hardware adpcm decoder :)
sint16 ADPCM_Step(uint32& _rSamplePos, uint32 _BaseAddress)
{
sint16* pCoefTable = (sint16*)&gdsp_ifx_regs[DSP_COEF_A1_0];
if (((_rSamplePos) & 15) == 0)
{
gdsp_ifx_regs[DSP_PRED_SCALE] = g_dspInitialize.pARAM_Read_U8((_rSamplePos & ~15) >> 1);
_rSamplePos += 2;
}
int scale = 1 << (gdsp_ifx_regs[DSP_PRED_SCALE] & 0xF);
int coef_idx = gdsp_ifx_regs[DSP_PRED_SCALE] >> 4;
sint32 coef1 = pCoefTable[coef_idx * 2 + 0];
sint32 coef2 = pCoefTable[coef_idx * 2 + 1];
int temp = (_rSamplePos & 1) ?
(g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) & 0xF) :
(g_dspInitialize.pARAM_Read_U8(_rSamplePos >> 1) >> 4);
if (temp >= 8)
temp -= 16;
// 0x400 = 0.5 in 11-bit fixed point
int val = (scale * temp) + ((0x400 + coef1 * (sint16)gdsp_ifx_regs[DSP_YN1] + coef2 * (sint16)gdsp_ifx_regs[DSP_YN2]) >> 11);
// Clamp values.
if (val > 0x7FFF)
val = 0x7FFF;
else if (val < -0x7FFF)
val = -0x7FFF;
gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
gdsp_ifx_regs[DSP_YN1] = val;
_rSamplePos++;
// The advanced interpolation (linear, polyphase,...) is done by the UCode, so we don't
// need to bother with it here.
return val;
}
extern void gdsp_generate_exception(uint8 level);
uint16 dsp_read_aram()
{
// uint32 BaseAddress = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
uint32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
uint32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
uint16 val;
// lets the "hardware" decode
switch (gdsp_ifx_regs[DSP_FORMAT])
{
case 0x00:
val = ADPCM_Step(Address, EndAddress);
break;
case 0x0A:
val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1);
gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
gdsp_ifx_regs[DSP_YN1] = val;
Address += 2;
break;
default:
val = (g_dspInitialize.pARAM_Read_U8(Address) << 8) | g_dspInitialize.pARAM_Read_U8(Address + 1);
Address += 2;
ErrorLog("Unknown DSP Format %i", gdsp_ifx_regs[DSP_FORMAT]);
break;
}
// check for loop
if (Address > EndAddress)
{
Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
gdsp_generate_exception(3);
gdsp_generate_exception(5);
// Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah,
// it seems likely that we should raise an exception to let the DSP program do that,
// at least if DSP_FORMAT == 0x0A.
}
gdsp_ifx_regs[DSP_ACCAH] = Address >> 16;
gdsp_ifx_regs[DSP_ACCAL] = Address & 0xffff;
return(val);
}

View File

@ -1,284 +1,284 @@
/*====================================================================
filename: opcodes.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.
====================================================================*/
//
//
// At the moment just ls and sl are using the prolog
// perhaps all actions on r03 must be in the prolog
//
#include "Globals.h"
#include "gdsp_opcodes_helper.h"
//
void dsp_op_ext_r_epi(uint16 _Opcode)
{
uint8 op = (_Opcode >> 2) & 0x3;
uint8 reg = _Opcode & 0x3;
switch (op)
{
case 0x00:
ErrorLog("dsp_op_ext_r_epi");
break;
case 0x01:
g_dsp.r[reg]--;
break;
case 0x02:
g_dsp.r[reg]++;
break;
case 0x03:
g_dsp.r[reg] += g_dsp.r[reg + 4];
break;
}
}
void dsp_op_ext_mv(uint16 _Opcode)
{
uint8 sreg = _Opcode & 0x3;
uint8 dreg = ((_Opcode >> 2) & 0x3);
g_dsp.r[dreg + 0x18] = g_dsp.r[sreg + 0x1c];
}
void dsp_op_ext_s(uint16 _Opcode)
{
uint8 dreg = _Opcode & 0x3;
uint8 sreg = ((_Opcode >> 3) & 0x3) + 0x1c;
dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]);
if (_Opcode & 0x04)
{
g_dsp.r[dreg] += g_dsp.r[dreg + 4];
}
else
{
g_dsp.r[dreg]++;
}
}
void dsp_op_ext_l(uint16 _Opcode)
{
uint8 sreg = _Opcode & 0x3;
uint8 dreg = ((_Opcode >> 3) & 0x7) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg] = val;
if (_Opcode & 0x04)
{
g_dsp.r[sreg] += g_dsp.r[sreg + 4];
}
else
{
g_dsp.r[sreg]++;
}
}
void dsp_op_ext_ls_pro(uint16 _Opcode)
{
uint8 areg = (_Opcode & 0x1) + 0x1e;
dsp_dmem_write(g_dsp.r[0x03], g_dsp.r[areg]);
if (_Opcode & 0x8)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
void dsp_op_ext_ls_epi(uint16 _Opcode)
{
uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[0x00]);
dsp_op_write_reg(dreg, val);
if (_Opcode & 0x4)
{
g_dsp.r[0x00] += g_dsp.r[0x04];
}
else
{
g_dsp.r[0x00]++;
}
}
void dsp_op_ext_sl_pro(uint16 _Opcode)
{
uint8 areg = (_Opcode & 0x1) + 0x1e;
dsp_dmem_write(g_dsp.r[0x00], g_dsp.r[areg]);
if (_Opcode & 0x4)
{
g_dsp.r[0x00] += g_dsp.r[0x04];
}
else
{
g_dsp.r[0x00]++;
}
}
void dsp_op_ext_sl_epi(uint16 _Opcode)
{
uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[0x03]);
dsp_op_write_reg(dreg, val);
if (_Opcode & 0x8)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
void dsp_op_ext_ld(uint16 _Opcode)
{
uint8 dreg1 = (((_Opcode >> 5) & 0x1) << 1) + 0x18;
uint8 dreg2 = (((_Opcode >> 4) & 0x1) << 1) + 0x19;
uint8 sreg = _Opcode & 0x3;
g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[0x03]);
if (_Opcode & 0x04)
{
g_dsp.r[sreg] += g_dsp.r[sreg + 0x04];
}
else
{
g_dsp.r[sreg]++;
}
if (_Opcode & 0x08)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
// ================================================================================
//
//
//
// ================================================================================
void dsp_op_ext_ops_pro(uint16 _Opcode)
{
if ((_Opcode & 0xFF) == 0){return;}
switch ((_Opcode >> 4) & 0xf)
{
case 0x00:
dsp_op_ext_r_epi(_Opcode);
break;
case 0x01:
dsp_op_ext_mv(_Opcode);
break;
case 0x02:
case 0x03:
dsp_op_ext_s(_Opcode);
break;
case 0x04:
case 0x05:
case 0x06:
case 0x07:
dsp_op_ext_l(_Opcode);
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (_Opcode & 0x2)
{
dsp_op_ext_sl_pro(_Opcode);
}
else
{
dsp_op_ext_ls_pro(_Opcode);
}
return;
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
dsp_op_ext_ld(_Opcode);
break;
}
}
void dsp_op_ext_ops_epi(uint16 _Opcode)
{
if ((_Opcode & 0xFF) == 0){return;}
switch ((_Opcode >> 4) & 0xf)
{
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (_Opcode & 0x2)
{
dsp_op_ext_sl_epi(_Opcode);
}
else
{
dsp_op_ext_ls_epi(_Opcode);
}
return;
}
}
/*====================================================================
filename: opcodes.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.
====================================================================*/
//
//
// At the moment just ls and sl are using the prolog
// perhaps all actions on r03 must be in the prolog
//
#include "Globals.h"
#include "gdsp_opcodes_helper.h"
//
void dsp_op_ext_r_epi(uint16 _Opcode)
{
uint8 op = (_Opcode >> 2) & 0x3;
uint8 reg = _Opcode & 0x3;
switch (op)
{
case 0x00:
ErrorLog("dsp_op_ext_r_epi");
break;
case 0x01:
g_dsp.r[reg]--;
break;
case 0x02:
g_dsp.r[reg]++;
break;
case 0x03:
g_dsp.r[reg] += g_dsp.r[reg + 4];
break;
}
}
void dsp_op_ext_mv(uint16 _Opcode)
{
uint8 sreg = _Opcode & 0x3;
uint8 dreg = ((_Opcode >> 2) & 0x3);
g_dsp.r[dreg + 0x18] = g_dsp.r[sreg + 0x1c];
}
void dsp_op_ext_s(uint16 _Opcode)
{
uint8 dreg = _Opcode & 0x3;
uint8 sreg = ((_Opcode >> 3) & 0x3) + 0x1c;
dsp_dmem_write(g_dsp.r[dreg], g_dsp.r[sreg]);
if (_Opcode & 0x04)
{
g_dsp.r[dreg] += g_dsp.r[dreg + 4];
}
else
{
g_dsp.r[dreg]++;
}
}
void dsp_op_ext_l(uint16 _Opcode)
{
uint8 sreg = _Opcode & 0x3;
uint8 dreg = ((_Opcode >> 3) & 0x7) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg] = val;
if (_Opcode & 0x04)
{
g_dsp.r[sreg] += g_dsp.r[sreg + 4];
}
else
{
g_dsp.r[sreg]++;
}
}
void dsp_op_ext_ls_pro(uint16 _Opcode)
{
uint8 areg = (_Opcode & 0x1) + 0x1e;
dsp_dmem_write(g_dsp.r[0x03], g_dsp.r[areg]);
if (_Opcode & 0x8)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
void dsp_op_ext_ls_epi(uint16 _Opcode)
{
uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[0x00]);
dsp_op_write_reg(dreg, val);
if (_Opcode & 0x4)
{
g_dsp.r[0x00] += g_dsp.r[0x04];
}
else
{
g_dsp.r[0x00]++;
}
}
void dsp_op_ext_sl_pro(uint16 _Opcode)
{
uint8 areg = (_Opcode & 0x1) + 0x1e;
dsp_dmem_write(g_dsp.r[0x00], g_dsp.r[areg]);
if (_Opcode & 0x4)
{
g_dsp.r[0x00] += g_dsp.r[0x04];
}
else
{
g_dsp.r[0x00]++;
}
}
void dsp_op_ext_sl_epi(uint16 _Opcode)
{
uint8 dreg = ((_Opcode >> 4) & 0x3) + 0x18;
uint16 val = dsp_dmem_read(g_dsp.r[0x03]);
dsp_op_write_reg(dreg, val);
if (_Opcode & 0x8)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
void dsp_op_ext_ld(uint16 _Opcode)
{
uint8 dreg1 = (((_Opcode >> 5) & 0x1) << 1) + 0x18;
uint8 dreg2 = (((_Opcode >> 4) & 0x1) << 1) + 0x19;
uint8 sreg = _Opcode & 0x3;
g_dsp.r[dreg1] = dsp_dmem_read(g_dsp.r[sreg]);
g_dsp.r[dreg2] = dsp_dmem_read(g_dsp.r[0x03]);
if (_Opcode & 0x04)
{
g_dsp.r[sreg] += g_dsp.r[sreg + 0x04];
}
else
{
g_dsp.r[sreg]++;
}
if (_Opcode & 0x08)
{
g_dsp.r[0x03] += g_dsp.r[0x07];
}
else
{
g_dsp.r[0x03]++;
}
}
// ================================================================================
//
//
//
// ================================================================================
void dsp_op_ext_ops_pro(uint16 _Opcode)
{
if ((_Opcode & 0xFF) == 0){return;}
switch ((_Opcode >> 4) & 0xf)
{
case 0x00:
dsp_op_ext_r_epi(_Opcode);
break;
case 0x01:
dsp_op_ext_mv(_Opcode);
break;
case 0x02:
case 0x03:
dsp_op_ext_s(_Opcode);
break;
case 0x04:
case 0x05:
case 0x06:
case 0x07:
dsp_op_ext_l(_Opcode);
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (_Opcode & 0x2)
{
dsp_op_ext_sl_pro(_Opcode);
}
else
{
dsp_op_ext_ls_pro(_Opcode);
}
return;
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
dsp_op_ext_ld(_Opcode);
break;
}
}
void dsp_op_ext_ops_epi(uint16 _Opcode)
{
if ((_Opcode & 0xFF) == 0){return;}
switch ((_Opcode >> 4) & 0xf)
{
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
if (_Opcode & 0x2)
{
dsp_op_ext_sl_epi(_Opcode);
}
else
{
dsp_op_ext_ls_epi(_Opcode);
}
return;
}
}

View File

@ -1,357 +1,357 @@
/*====================================================================
filename: gdsp_interface.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.
====================================================================*/
#include <stdlib.h>
#include "Globals.h"
#include "Thread.h"
#include "gdsp_aram.h"
#include "gdsp_interpreter.h"
#include "gdsp_interface.h"
#include "Tools.h"
#ifndef NULL
#define NULL 0
#endif
#ifndef _WIN32
#undef WITH_DSP_ON_THREAD
//TODO FIX
#endif
const char* reg_names[] =
{
// a0
"COEF_A1_0", "COEF_A2_0", "COEF_A1_1", "COEF_A2_1", "COEF_A1_2", "COEF_A2_2", "COEF_A1_3", "COEF_A2_3",
"COEF_A1_4", "COEF_A2_4", "COEF_A1_5", "COEF_A2_5", "COEF_A1_6", "COEF_A2_6", "COEF_A1_7", "COEF_A2_7",
// b0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
// c0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, "DSCR", NULL, "DSBL", NULL, "DSPA", "DSMAH", "DSMAL",
// d0
NULL, "SampleFormat", NULL, NULL, "ACSAH", "ACSAL", "ACEAH", "ACEAL",
"ACCAH", "ACCAL", "PRED_SCALE", "YN1", "YN2", "ARAM", "GAIN", NULL,
// e0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "AMDM",
// f0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, "DMBH", "DMBL", "CMBH", "CMBL",
};
void gdsp_dma();
#ifdef WITH_DSP_ON_THREAD
Common::CriticalSection g_CriticalSection;
#endif
static volatile uint16 gdsp_mbox[2][2];
uint16 gdsp_ifx_regs[256];
void gdsp_ifx_init()
{
int i;
for (i = 0; i < 256; i++)
{
gdsp_ifx_regs[i] = 0;
}
gdsp_mbox[0][0] = 0;
gdsp_mbox[0][1] = 0;
gdsp_mbox[1][0] = 0;
gdsp_mbox[1][1] = 0;
}
uint32 gdsp_mbox_peek(uint8 mbx)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
uint32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]);
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
return value;
}
void gdsp_mbox_write_h(uint8 mbx, uint16 val)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
gdsp_mbox[mbx][0] = val & 0x7fff;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
}
void gdsp_mbox_write_l(uint8 mbx, uint16 val)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
gdsp_mbox[mbx][1] = val;
gdsp_mbox[mbx][0] |= 0x8000;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
if (mbx == GDSP_MBOX_DSP)
{
DebugLog("- Write DSP Mail: 0x%08x (pc=0x%04x)\n", gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.err_pc);
}
}
uint16 gdsp_mbox_read_h(uint8 mbx)
{
return (gdsp_mbox[mbx][0]);
}
uint16 gdsp_mbox_read_l(uint8 mbx)
{
uint16 val;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
val = gdsp_mbox[mbx][1];
gdsp_mbox[mbx][0] &= ~0x8000;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
return(val);
}
void gdsp_ifx_write(uint16 addr, uint16 val)
{
addr &= 0xff;
switch (addr & 0xff)
{
case 0xfb: // DIRQ
if (val & 0x1)
{
g_dsp.irq_request();
}
break;
case 0xfc: // DMBH
gdsp_mbox_write_h(GDSP_MBOX_DSP, val);
break;
case 0xfd: // DMBL
gdsp_mbox_write_l(GDSP_MBOX_DSP, val);
break;
case 0xcb: // DSBL
gdsp_ifx_regs[addr] = val;
gdsp_dma();
gdsp_ifx_regs[DSP_DSCR] &= ~0x0004;
break;
case 0xcd:
case 0xce:
case 0xcf:
case 0xc9:
gdsp_ifx_regs[addr] = val;
break;
default:
/* if ((addr & 0xff) >= 0xa0 && reg_names[addr - 0xa0])
DebugLog("%04x MW %s (%04x)\n", g_dsp.pc, reg_names[addr - 0xa0], val);
else
DebugLog("%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);*/
gdsp_ifx_regs[addr] = val;
break;
}
}
uint16 gdsp_ifx_read(uint16 addr)
{
uint16 val;
addr &= 0xff;
switch (addr & 0xff)
{
case 0xfc: // DMBH
val = gdsp_mbox_read_h(GDSP_MBOX_DSP);
break;
case 0xfe: // CMBH
val = gdsp_mbox_read_h(GDSP_MBOX_CPU);
break;
case 0xff: // CMBL
val = gdsp_mbox_read_l(GDSP_MBOX_CPU);
break;
case 0xc9:
val = gdsp_ifx_regs[addr];
break;
case 0xdd:
val = dsp_read_aram();
break;
default:
val = gdsp_ifx_regs[addr];
/* if ((addr & 0xff) >= 0xc0 && reg_names[addr & 0x3f])
printf("%04x MR %s (%04x)\n", g_dsp.pc, reg_names[addr & 0x3f], val);
else
printf("%04x MR %04x (%04x)\n", g_dsp.pc, addr, val);*/
break;
}
return(val);
}
void gdsp_idma_in(uint16 dsp_addr, uint32 addr, uint32 size)
{
uint8* dst = ((uint8*)g_dsp.iram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff];
}
g_dsp.iram_crc = GenerateCRC(g_dsp.cpu_ram + (addr & 0x0fffffff), size);
DebugLog("*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)\n", addr, dsp_addr, g_dsp.iram_crc);
#if DUMP_DSP_IMEM
DumpDSPCode(addr, size, g_dsp.iram_crc );
#endif
}
void gdsp_idma_out(uint16 dsp_addr, uint32 addr, uint32 size)
{
ErrorLog("*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size);
}
void gdsp_ddma_in(uint16 dsp_addr, uint32 addr, uint32 size)
{
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
{
ErrorLog("*** ddma_in read from invalid addr (0x%08x)\n", addr);
return;
}
uint8* dst = ((uint8*)g_dsp.dram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF];
}
DebugLog("*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)\n", addr, dsp_addr / 2, size);
}
void gdsp_ddma_out(uint16 dsp_addr, uint32 addr, uint32 size)
{
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
{
ErrorLog("*** gdsp_ddma_out to invalid addr (0x%08x)\n", addr);
return;
}
uint8* src = ((uint8*)g_dsp.dram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF] = *(uint16*)&src[dsp_addr + i];
}
DebugLog("*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size);
}
#define DSP_CR_IMEM (2)
#define DSP_CR_DMEM (0)
#define DSP_CR_TO_CPU (1)
#define DSP_CR_FROM_CPU (0)
void gdsp_dma()
{
uint16 ctl;
uint32 addr;
uint16 dsp_addr;
uint16 len;
addr = (gdsp_ifx_regs[DSP_DSMAH] << 16) | gdsp_ifx_regs[DSP_DSMAL];
ctl = gdsp_ifx_regs[DSP_DSCR];
dsp_addr = gdsp_ifx_regs[DSP_DSPA] * 2;
len = gdsp_ifx_regs[DSP_DSBL];
if ((ctl > 3) || (len > 0x4000))
{
ErrorLog("DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x\n", g_dsp.pc, ctl, addr, dsp_addr, len);
exit(0);
}
switch (ctl & 0x3)
{
case (DSP_CR_DMEM | DSP_CR_TO_CPU):
gdsp_ddma_out(dsp_addr, addr, len);
break;
case (DSP_CR_DMEM | DSP_CR_FROM_CPU):
gdsp_ddma_in(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_TO_CPU):
gdsp_idma_out(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_FROM_CPU):
gdsp_idma_in(dsp_addr, addr, len);
break;
}
}
/*====================================================================
filename: gdsp_interface.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.
====================================================================*/
#include <stdlib.h>
#include "Globals.h"
#include "Thread.h"
#include "gdsp_aram.h"
#include "gdsp_interpreter.h"
#include "gdsp_interface.h"
#include "Tools.h"
#ifndef NULL
#define NULL 0
#endif
#ifndef _WIN32
#undef WITH_DSP_ON_THREAD
//TODO FIX
#endif
const char* reg_names[] =
{
// a0
"COEF_A1_0", "COEF_A2_0", "COEF_A1_1", "COEF_A2_1", "COEF_A1_2", "COEF_A2_2", "COEF_A1_3", "COEF_A2_3",
"COEF_A1_4", "COEF_A2_4", "COEF_A1_5", "COEF_A2_5", "COEF_A1_6", "COEF_A2_6", "COEF_A1_7", "COEF_A2_7",
// b0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
// c0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, "DSCR", NULL, "DSBL", NULL, "DSPA", "DSMAH", "DSMAL",
// d0
NULL, "SampleFormat", NULL, NULL, "ACSAH", "ACSAL", "ACEAH", "ACEAL",
"ACCAH", "ACCAL", "PRED_SCALE", "YN1", "YN2", "ARAM", "GAIN", NULL,
// e0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, "AMDM",
// f0
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, "DMBH", "DMBL", "CMBH", "CMBL",
};
void gdsp_dma();
#ifdef WITH_DSP_ON_THREAD
Common::CriticalSection g_CriticalSection;
#endif
static volatile uint16 gdsp_mbox[2][2];
uint16 gdsp_ifx_regs[256];
void gdsp_ifx_init()
{
int i;
for (i = 0; i < 256; i++)
{
gdsp_ifx_regs[i] = 0;
}
gdsp_mbox[0][0] = 0;
gdsp_mbox[0][1] = 0;
gdsp_mbox[1][0] = 0;
gdsp_mbox[1][1] = 0;
}
uint32 gdsp_mbox_peek(uint8 mbx)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
uint32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]);
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
return value;
}
void gdsp_mbox_write_h(uint8 mbx, uint16 val)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
gdsp_mbox[mbx][0] = val & 0x7fff;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
}
void gdsp_mbox_write_l(uint8 mbx, uint16 val)
{
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
gdsp_mbox[mbx][1] = val;
gdsp_mbox[mbx][0] |= 0x8000;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
if (mbx == GDSP_MBOX_DSP)
{
DebugLog("- Write DSP Mail: 0x%08x (pc=0x%04x)\n", gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.err_pc);
}
}
uint16 gdsp_mbox_read_h(uint8 mbx)
{
return (gdsp_mbox[mbx][0]);
}
uint16 gdsp_mbox_read_l(uint8 mbx)
{
uint16 val;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Enter();
#endif
val = gdsp_mbox[mbx][1];
gdsp_mbox[mbx][0] &= ~0x8000;
#if WITH_DSP_ON_THREAD
g_CriticalSection.Leave();
#endif
return(val);
}
void gdsp_ifx_write(uint16 addr, uint16 val)
{
addr &= 0xff;
switch (addr & 0xff)
{
case 0xfb: // DIRQ
if (val & 0x1)
{
g_dsp.irq_request();
}
break;
case 0xfc: // DMBH
gdsp_mbox_write_h(GDSP_MBOX_DSP, val);
break;
case 0xfd: // DMBL
gdsp_mbox_write_l(GDSP_MBOX_DSP, val);
break;
case 0xcb: // DSBL
gdsp_ifx_regs[addr] = val;
gdsp_dma();
gdsp_ifx_regs[DSP_DSCR] &= ~0x0004;
break;
case 0xcd:
case 0xce:
case 0xcf:
case 0xc9:
gdsp_ifx_regs[addr] = val;
break;
default:
/* if ((addr & 0xff) >= 0xa0 && reg_names[addr - 0xa0])
DebugLog("%04x MW %s (%04x)\n", g_dsp.pc, reg_names[addr - 0xa0], val);
else
DebugLog("%04x MW %04x (%04x)\n", g_dsp.pc, addr, val);*/
gdsp_ifx_regs[addr] = val;
break;
}
}
uint16 gdsp_ifx_read(uint16 addr)
{
uint16 val;
addr &= 0xff;
switch (addr & 0xff)
{
case 0xfc: // DMBH
val = gdsp_mbox_read_h(GDSP_MBOX_DSP);
break;
case 0xfe: // CMBH
val = gdsp_mbox_read_h(GDSP_MBOX_CPU);
break;
case 0xff: // CMBL
val = gdsp_mbox_read_l(GDSP_MBOX_CPU);
break;
case 0xc9:
val = gdsp_ifx_regs[addr];
break;
case 0xdd:
val = dsp_read_aram();
break;
default:
val = gdsp_ifx_regs[addr];
/* if ((addr & 0xff) >= 0xc0 && reg_names[addr & 0x3f])
printf("%04x MR %s (%04x)\n", g_dsp.pc, reg_names[addr & 0x3f], val);
else
printf("%04x MR %04x (%04x)\n", g_dsp.pc, addr, val);*/
break;
}
return(val);
}
void gdsp_idma_in(uint16 dsp_addr, uint32 addr, uint32 size)
{
uint8* dst = ((uint8*)g_dsp.iram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff];
}
g_dsp.iram_crc = GenerateCRC(g_dsp.cpu_ram + (addr & 0x0fffffff), size);
DebugLog("*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)\n", addr, dsp_addr, g_dsp.iram_crc);
#if DUMP_DSP_IMEM
DumpDSPCode(addr, size, g_dsp.iram_crc );
#endif
}
void gdsp_idma_out(uint16 dsp_addr, uint32 addr, uint32 size)
{
ErrorLog("*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size);
}
void gdsp_ddma_in(uint16 dsp_addr, uint32 addr, uint32 size)
{
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
{
ErrorLog("*** ddma_in read from invalid addr (0x%08x)\n", addr);
return;
}
uint8* dst = ((uint8*)g_dsp.dram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&dst[dsp_addr + i] = *(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF];
}
DebugLog("*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)\n", addr, dsp_addr / 2, size);
}
void gdsp_ddma_out(uint16 dsp_addr, uint32 addr, uint32 size)
{
if ((addr & 0x7FFFFFFF) > 0x01FFFFFF)
{
ErrorLog("*** gdsp_ddma_out to invalid addr (0x%08x)\n", addr);
return;
}
uint8* src = ((uint8*)g_dsp.dram);
for (uint32 i = 0; i < size; i += 2)
{
*(uint16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF] = *(uint16*)&src[dsp_addr + i];
}
DebugLog("*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size);
}
#define DSP_CR_IMEM (2)
#define DSP_CR_DMEM (0)
#define DSP_CR_TO_CPU (1)
#define DSP_CR_FROM_CPU (0)
void gdsp_dma()
{
uint16 ctl;
uint32 addr;
uint16 dsp_addr;
uint16 len;
addr = (gdsp_ifx_regs[DSP_DSMAH] << 16) | gdsp_ifx_regs[DSP_DSMAL];
ctl = gdsp_ifx_regs[DSP_DSCR];
dsp_addr = gdsp_ifx_regs[DSP_DSPA] * 2;
len = gdsp_ifx_regs[DSP_DSBL];
if ((ctl > 3) || (len > 0x4000))
{
ErrorLog("DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x\n", g_dsp.pc, ctl, addr, dsp_addr, len);
exit(0);
}
switch (ctl & 0x3)
{
case (DSP_CR_DMEM | DSP_CR_TO_CPU):
gdsp_ddma_out(dsp_addr, addr, len);
break;
case (DSP_CR_DMEM | DSP_CR_FROM_CPU):
gdsp_ddma_in(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_TO_CPU):
gdsp_idma_out(dsp_addr, addr, len);
break;
case (DSP_CR_IMEM | DSP_CR_FROM_CPU):
gdsp_idma_in(dsp_addr, addr, len);
break;
}
}

View File

@ -1,444 +1,444 @@
/*====================================================================
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 <stdio.h>
#include <stdlib.h>
#include "gdsp_interface.h"
#include "gdsp_opcodes_helper.h"
#include "Tools.h"
//-------------------------------------------------------------------------------
SDSP g_dsp;
uint16 SDSP::r[32];
uint16 SDSP::pc = 0;
uint16 SDSP::err_pc = 0;
uint16* SDSP::iram = 0;
uint16* SDSP::dram = 0;
uint16* SDSP::irom = 0;
uint16* SDSP::drom = 0;
uint16* SDSP::coef = 0;
uint8* SDSP::cpu_ram = 0;
uint16 SDSP::cr = 0;
uint8 SDSP::reg_stack_ptr[4];
// lets make stack depth to 32 for now
uint16 SDSP::reg_stack[4][DSP_STACK_DEPTH];
void (*SDSP::irq_request)() = NULL;
bool SDSP::exception_in_progress_hack = false;
// for debugger only
uint32 SDSP::iram_crc = 0;
uint64 SDSP::step_counter = 0;
//-------------------------------------------------------------------------------
static bool CR_HALT = true;
static bool CR_EXTERNAL_INT = false;
void UpdateCachedCR()
{
CR_HALT = (g_dsp.cr & 0x4) != 0;
CR_EXTERNAL_INT = (g_dsp.cr & 0x02) != 0;
}
//-------------------------------------------------------------------------------
void (*dsp_op[])(uint16 opc) =
{
dsp_op0, dsp_op1, dsp_op2, dsp_op3,
dsp_op4, dsp_op5, dsp_op6, dsp_op7,
dsp_op8, dsp_op9, dsp_opab, dsp_opab,
dsp_opcd, dsp_opcd, dsp_ope, dsp_opf,
};
void dbg_error(char* err_msg)
{
return;
}
void gdsp_init()
{
g_dsp.irom = (uint16*)malloc(DSP_IROM_SIZE * sizeof(uint16));
g_dsp.iram = (uint16*)malloc(DSP_IRAM_SIZE * sizeof(uint16));
g_dsp.drom = (uint16*)malloc(DSP_DROM_SIZE * sizeof(uint16));
g_dsp.dram = (uint16*)malloc(DSP_DRAM_SIZE * sizeof(uint16));
g_dsp.coef = (uint16*)malloc(DSP_COEF_SIZE * sizeof(uint16));
for (int i = 0; i < DSP_IRAM_SIZE; i++)
{
g_dsp.iram[i] = 0x0021; // HALT opcode
}
for (int i = 0; i < DSP_DRAM_SIZE; i++)
{
g_dsp.dram[i] = 0x0021; // HALT opcode
}
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;
}
}
// copied from a real console after the custom UCode has been loaded
g_dsp.r[0x08] = 0xffff;
g_dsp.r[0x09] = 0xffff;
g_dsp.r[0x0a] = 0xffff;
g_dsp.r[0x0b] = 0xffff;
g_dsp.cr = 0x804;
gdsp_ifx_init();
UpdateCachedCR();
}
void gdsp_reset()
{
// _assert_msg_(0, "gdsp_reset()");
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
g_dsp.pc = DSP_RESET_VECTOR;
g_dsp.exception_in_progress_hack = false;
}
uint8 gdsp_exceptions = 0;
void gdsp_generate_exception(uint8 level)
{
gdsp_exceptions |= 1 << level;
}
bool gdsp_load_rom(char* fname)
{
FILE* pFile = fopen(fname, "rb");
if (pFile)
{
fread(g_dsp.irom, 1, DSP_IRAM_SIZE, pFile);
fclose(pFile);
return(true);
}
return(false);
}
bool gdsp_load_coef(char* fname)
{
FILE* pFile = fopen(fname, "rb");
if (pFile)
{
fread(g_dsp.coef, 1, DSP_COEF_SIZE, pFile);
fclose(pFile);
return(true);
}
return(false);
}
void gdsp_write_cr(uint16 val)
{
// reset
if (val & 0x0001)
{
gdsp_reset();
}
val &= ~0x0001;
// update cr
g_dsp.cr = val;
UpdateCachedCR();
}
uint16 gdsp_read_cr()
{
if (g_dsp.pc & 0x8000)
{
g_dsp.cr |= 0x800;
}
else
{
g_dsp.cr &= ~0x800;
}
UpdateCachedCR();
return(g_dsp.cr);
}
// special loop step.. because exception in loop or loopi fails
// dunno how we have to fix it
// atm we execute this instructions directly inside the loop command
// so it cant be interrupted by an exception
void gdsp_loop_step()
{
g_dsp.err_pc = g_dsp.pc;
uint16 opc = dsp_fetch_code();
dsp_op[opc >> 12](opc);
}
u16 HLE_ROM_80E7_81F8();
void hacks();
void gdsp_step()
{
g_dsp.step_counter++;
if (g_dsp.pc == 0x80e7)
{
//g_dsp.pc = HLE_ROM_80E7_81F8();
}
g_dsp.err_pc = g_dsp.pc;
#if PROFILE
ProfilerAddDelta(g_dsp.err_pc, 1);
if (g_dsp.step_counter == 1)
{
ProfilerInit();
}
if ((g_dsp.step_counter & 0xFFFFF) == 0)
{
ProfilerDump(g_dsp.step_counter);
}
#endif
uint16 opc = dsp_fetch_code();
dsp_op[opc >> 12](opc);
uint16& rLoopCounter = g_dsp.r[DSP_REG_ST0 + 3];
if (rLoopCounter > 0)
{
const uint16& rCallAddress = g_dsp.r[DSP_REG_ST0 + 0];
const uint16& rLoopAddress = g_dsp.r[DSP_REG_ST0 + 2];
if (g_dsp.pc == (rLoopAddress + 1))
{
rLoopCounter--;
if (rLoopCounter > 0)
{
g_dsp.pc = rCallAddress;
}
else
{
// end of loop
dsp_reg_load_stack(0);
dsp_reg_load_stack(2);
dsp_reg_load_stack(3);
}
}
}
// check if there is an external interrupt
if (CR_EXTERNAL_INT)
{
if (dsp_SR_is_flag_set(FLAG_ENABLE_INTERUPT) && (g_dsp.exception_in_progress_hack == false))
{
// level 7 is the interrupt exception
gdsp_generate_exception(7);
g_dsp.cr &= ~0x0002;
UpdateCachedCR();
}
}
// check exceptions
if ((gdsp_exceptions > 0) && (!g_dsp.exception_in_progress_hack))
{
for (uint8 i=0; i<8; i++)
{
if (gdsp_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[R_SR]);
g_dsp.pc = i * 2;
gdsp_exceptions &= ~(1<<i);
g_dsp.exception_in_progress_hack = true;
break;
}
}
}
}
bool gdsp_running;
extern volatile uint32 dsp_running;
bool gdsp_run()
{
gdsp_running = true;
while (!CR_HALT)
{
gdsp_step();
}
gdsp_running = false;
return(true);
}
bool gdsp_runx(uint16 cnt)
{
gdsp_running = true;
while (!(g_dsp.cr & 0x4) && gdsp_running)
{
gdsp_step();
cnt--;
if (cnt == 0)
{
break;
}
}
gdsp_running = false;
return(true);
}
void gdsp_stop()
{
gdsp_running = false;
}
///////////////////////////////////////////////////////////////////////////////
//
// From fires for fires :)
//
//
#include "disassemble.h"
#include "WaveFile.h"
#include "Mixer.h"
uint16 r30 = 0, r31 = 0;
void PanicAlert(const char* text, ...);
extern WaveFileWriter g_wave_writer;
extern uint16 dsp_swap16(uint16 x);
void Hacks()
{
// if (g_wave_writer.GetAudioSize() > 1024*1024*1)
/* if (g_dsp.pc == 0x165)
{
PanicAlert("Opcode_06");
}
if (g_dsp.pc == 0x43b)
{
PanicAlert("Opcode_14");
}
if (g_dsp.pc == 0xb37)
{
PanicAlert("Opcode_08");
}*/
/* if (g_dsp.pc == 0x1bc)
{
r30 = g_dsp.r[30];
r31 = g_dsp.r[31];
}
else if (g_dsp.pc == 0x384)
{
// if ((r30 == 0x1bc) && (r31 == 0xaff))
{
//PanicAlert("%x, %x", r30, r31);
const int numSamples = 0x280;
static short Buffer[numSamples];
uint16 bufferAddr = 0x280; //dsp_dmem_read(0xe44);
for (int i=0; i<numSamples; i++)
{
Buffer[i] = dsp_dmem_read(bufferAddr+i);
}
g_wave_writer.AddStereoSamples(Buffer, numSamples/2); // 2 channels
if (g_wave_writer.GetAudioSize() > 1024*1024*2)
{
//PanicAlert("%x", bufferAddr);
g_wave_writer.Stop();
exit(1);
}
}
} */
if (g_dsp.pc == 0x468)
{
int numSamples = g_dsp.r[25] / 2;
uint16 bufferAddr = g_dsp.r[27];
// PanicAlert("%x %x", bufferAddr, numSamples);
short samples[1024];
for (int i=0; i<numSamples; i++)
{
samples[i] = dsp_dmem_read(bufferAddr+i);
}
Mixer_PushSamples(samples, numSamples / 2, 32000); //sample_rate);
g_wave_writer.AddStereoSamples(samples, numSamples/2); // 2 channels
if (g_wave_writer.GetAudioSize() > 1024*1024*2)
{
//PanicAlert("%x", bufferAddr);
g_wave_writer.Stop();
exit(1);
}
}
}
/*====================================================================
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 <stdio.h>
#include <stdlib.h>
#include "gdsp_interface.h"
#include "gdsp_opcodes_helper.h"
#include "Tools.h"
//-------------------------------------------------------------------------------
SDSP g_dsp;
uint16 SDSP::r[32];
uint16 SDSP::pc = 0;
uint16 SDSP::err_pc = 0;
uint16* SDSP::iram = 0;
uint16* SDSP::dram = 0;
uint16* SDSP::irom = 0;
uint16* SDSP::drom = 0;
uint16* SDSP::coef = 0;
uint8* SDSP::cpu_ram = 0;
uint16 SDSP::cr = 0;
uint8 SDSP::reg_stack_ptr[4];
// lets make stack depth to 32 for now
uint16 SDSP::reg_stack[4][DSP_STACK_DEPTH];
void (*SDSP::irq_request)() = NULL;
bool SDSP::exception_in_progress_hack = false;
// for debugger only
uint32 SDSP::iram_crc = 0;
uint64 SDSP::step_counter = 0;
//-------------------------------------------------------------------------------
static bool CR_HALT = true;
static bool CR_EXTERNAL_INT = false;
void UpdateCachedCR()
{
CR_HALT = (g_dsp.cr & 0x4) != 0;
CR_EXTERNAL_INT = (g_dsp.cr & 0x02) != 0;
}
//-------------------------------------------------------------------------------
void (*dsp_op[])(uint16 opc) =
{
dsp_op0, dsp_op1, dsp_op2, dsp_op3,
dsp_op4, dsp_op5, dsp_op6, dsp_op7,
dsp_op8, dsp_op9, dsp_opab, dsp_opab,
dsp_opcd, dsp_opcd, dsp_ope, dsp_opf,
};
void dbg_error(char* err_msg)
{
return;
}
void gdsp_init()
{
g_dsp.irom = (uint16*)malloc(DSP_IROM_SIZE * sizeof(uint16));
g_dsp.iram = (uint16*)malloc(DSP_IRAM_SIZE * sizeof(uint16));
g_dsp.drom = (uint16*)malloc(DSP_DROM_SIZE * sizeof(uint16));
g_dsp.dram = (uint16*)malloc(DSP_DRAM_SIZE * sizeof(uint16));
g_dsp.coef = (uint16*)malloc(DSP_COEF_SIZE * sizeof(uint16));
for (int i = 0; i < DSP_IRAM_SIZE; i++)
{
g_dsp.iram[i] = 0x0021; // HALT opcode
}
for (int i = 0; i < DSP_DRAM_SIZE; i++)
{
g_dsp.dram[i] = 0x0021; // HALT opcode
}
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;
}
}
// copied from a real console after the custom UCode has been loaded
g_dsp.r[0x08] = 0xffff;
g_dsp.r[0x09] = 0xffff;
g_dsp.r[0x0a] = 0xffff;
g_dsp.r[0x0b] = 0xffff;
g_dsp.cr = 0x804;
gdsp_ifx_init();
UpdateCachedCR();
}
void gdsp_reset()
{
// _assert_msg_(0, "gdsp_reset()");
_assert_msg_(MASTER_LOG, !g_dsp.exception_in_progress_hack, "assert while exception");
g_dsp.pc = DSP_RESET_VECTOR;
g_dsp.exception_in_progress_hack = false;
}
uint8 gdsp_exceptions = 0;
void gdsp_generate_exception(uint8 level)
{
gdsp_exceptions |= 1 << level;
}
bool gdsp_load_rom(char* fname)
{
FILE* pFile = fopen(fname, "rb");
if (pFile)
{
fread(g_dsp.irom, 1, DSP_IRAM_SIZE, pFile);
fclose(pFile);
return(true);
}
return(false);
}
bool gdsp_load_coef(char* fname)
{
FILE* pFile = fopen(fname, "rb");
if (pFile)
{
fread(g_dsp.coef, 1, DSP_COEF_SIZE, pFile);
fclose(pFile);
return(true);
}
return(false);
}
void gdsp_write_cr(uint16 val)
{
// reset
if (val & 0x0001)
{
gdsp_reset();
}
val &= ~0x0001;
// update cr
g_dsp.cr = val;
UpdateCachedCR();
}
uint16 gdsp_read_cr()
{
if (g_dsp.pc & 0x8000)
{
g_dsp.cr |= 0x800;
}
else
{
g_dsp.cr &= ~0x800;
}
UpdateCachedCR();
return(g_dsp.cr);
}
// special loop step.. because exception in loop or loopi fails
// dunno how we have to fix it
// atm we execute this instructions directly inside the loop command
// so it cant be interrupted by an exception
void gdsp_loop_step()
{
g_dsp.err_pc = g_dsp.pc;
uint16 opc = dsp_fetch_code();
dsp_op[opc >> 12](opc);
}
u16 HLE_ROM_80E7_81F8();
void hacks();
void gdsp_step()
{
g_dsp.step_counter++;
if (g_dsp.pc == 0x80e7)
{
//g_dsp.pc = HLE_ROM_80E7_81F8();
}
g_dsp.err_pc = g_dsp.pc;
#if PROFILE
ProfilerAddDelta(g_dsp.err_pc, 1);
if (g_dsp.step_counter == 1)
{
ProfilerInit();
}
if ((g_dsp.step_counter & 0xFFFFF) == 0)
{
ProfilerDump(g_dsp.step_counter);
}
#endif
uint16 opc = dsp_fetch_code();
dsp_op[opc >> 12](opc);
uint16& rLoopCounter = g_dsp.r[DSP_REG_ST0 + 3];
if (rLoopCounter > 0)
{
const uint16& rCallAddress = g_dsp.r[DSP_REG_ST0 + 0];
const uint16& rLoopAddress = g_dsp.r[DSP_REG_ST0 + 2];
if (g_dsp.pc == (rLoopAddress + 1))
{
rLoopCounter--;
if (rLoopCounter > 0)
{
g_dsp.pc = rCallAddress;
}
else
{
// end of loop
dsp_reg_load_stack(0);
dsp_reg_load_stack(2);
dsp_reg_load_stack(3);
}
}
}
// check if there is an external interrupt
if (CR_EXTERNAL_INT)
{
if (dsp_SR_is_flag_set(FLAG_ENABLE_INTERUPT) && (g_dsp.exception_in_progress_hack == false))
{
// level 7 is the interrupt exception
gdsp_generate_exception(7);
g_dsp.cr &= ~0x0002;
UpdateCachedCR();
}
}
// check exceptions
if ((gdsp_exceptions > 0) && (!g_dsp.exception_in_progress_hack))
{
for (uint8 i=0; i<8; i++)
{
if (gdsp_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[R_SR]);
g_dsp.pc = i * 2;
gdsp_exceptions &= ~(1<<i);
g_dsp.exception_in_progress_hack = true;
break;
}
}
}
}
bool gdsp_running;
extern volatile uint32 dsp_running;
bool gdsp_run()
{
gdsp_running = true;
while (!CR_HALT)
{
gdsp_step();
}
gdsp_running = false;
return(true);
}
bool gdsp_runx(uint16 cnt)
{
gdsp_running = true;
while (!(g_dsp.cr & 0x4) && gdsp_running)
{
gdsp_step();
cnt--;
if (cnt == 0)
{
break;
}
}
gdsp_running = false;
return(true);
}
void gdsp_stop()
{
gdsp_running = false;
}
///////////////////////////////////////////////////////////////////////////////
//
// From fires for fires :)
//
//
#include "disassemble.h"
#include "WaveFile.h"
#include "Mixer.h"
uint16 r30 = 0, r31 = 0;
void PanicAlert(const char* text, ...);
extern WaveFileWriter g_wave_writer;
extern uint16 dsp_swap16(uint16 x);
void Hacks()
{
// if (g_wave_writer.GetAudioSize() > 1024*1024*1)
/* if (g_dsp.pc == 0x165)
{
PanicAlert("Opcode_06");
}
if (g_dsp.pc == 0x43b)
{
PanicAlert("Opcode_14");
}
if (g_dsp.pc == 0xb37)
{
PanicAlert("Opcode_08");
}*/
/* if (g_dsp.pc == 0x1bc)
{
r30 = g_dsp.r[30];
r31 = g_dsp.r[31];
}
else if (g_dsp.pc == 0x384)
{
// if ((r30 == 0x1bc) && (r31 == 0xaff))
{
//PanicAlert("%x, %x", r30, r31);
const int numSamples = 0x280;
static short Buffer[numSamples];
uint16 bufferAddr = 0x280; //dsp_dmem_read(0xe44);
for (int i=0; i<numSamples; i++)
{
Buffer[i] = dsp_dmem_read(bufferAddr+i);
}
g_wave_writer.AddStereoSamples(Buffer, numSamples/2); // 2 channels
if (g_wave_writer.GetAudioSize() > 1024*1024*2)
{
//PanicAlert("%x", bufferAddr);
g_wave_writer.Stop();
exit(1);
}
}
} */
if (g_dsp.pc == 0x468)
{
int numSamples = g_dsp.r[25] / 2;
uint16 bufferAddr = g_dsp.r[27];
// PanicAlert("%x %x", bufferAddr, numSamples);
short samples[1024];
for (int i=0; i<numSamples; i++)
{
samples[i] = dsp_dmem_read(bufferAddr+i);
}
Mixer_PushSamples(samples, numSamples / 2, 32000); //sample_rate);
g_wave_writer.AddStereoSamples(samples, numSamples/2); // 2 channels
if (g_wave_writer.GetAudioSize() > 1024*1024*2)
{
//PanicAlert("%x", bufferAddr);
g_wave_writer.Stop();
exit(1);
}
}
}

View File

@ -1,156 +1,156 @@
/*====================================================================
filename: gdsp_memory.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 <stdio.h>
#include "Globals.h"
#include "gdsp_interpreter.h"
#include "gdsp_memory.h"
#include "gdsp_ifx.h"
uint16 dsp_swap16(uint16 x)
{
return((x >> 8) | (x << 8));
}
uint16* gdsp_get_iram(void)
{
return(g_dsp.iram);
}
uint16* gdsp_get_irom(void)
{
return(g_dsp.irom);
}
uint16* gdsp_get_dram(void)
{
return(g_dsp.dram);
}
uint16* gdsp_get_drom(void)
{
return(g_dsp.drom);
}
uint16 dsp_imem_read(uint16 addr)
{
uint16 opc;
if (g_dsp.pc & 0x8000)
{
opc = g_dsp.irom[addr & DSP_IROM_MASK];
}
else
{
opc = g_dsp.iram[addr & DSP_IRAM_MASK];
}
return(dsp_swap16(opc));
}
uint16 dsp_dmem_read(uint16 addr)
{
uint16 val;
switch (addr >> 12)
{
case 0x0: // 0xxx DRAM
val = g_dsp.dram[addr & DSP_DRAM_MASK];
val = dsp_swap16(val);
break;
case 0x8: // 8xxx DROM
DebugLog("someone reads from ROM\n");
val = g_dsp.drom[addr & DSP_DROM_MASK];
val = dsp_swap16(val);
break;
case 0x1: // 1xxx COEF
val = g_dsp.coef[addr & DSP_DROM_MASK];
val = dsp_swap16(val);
break;
case 0xf: // Fxxx HW regs
val = gdsp_ifx_read(addr);
break;
default: // error
// ErrorLog("%04x DSP ERROR: Read from UNKNOWN (%04x) memory\n", g_dsp.pc, addr);
val = 0;
break;
}
return(val);
}
bool dsp_dmem_write(uint16 addr, uint16 val)
{
switch (addr >> 12)
{
case 0x8: // 8xxx DROM
DebugLog("someone writes to ROM\n");
/* val = dsp_swap16(val);
g_dsp.drom[addr & DSP_DROM_MASK] = val;*/
break;
case 0xf: // Fxxx HW regs
gdsp_ifx_write(addr, val);
break;
case 0x0: // 0xxx DRAM
val = dsp_swap16(val);
g_dsp.dram[addr & DSP_DRAM_MASK] = val;
break;
default: // error
DebugLog("%04x DSP ERROR: Write to UNKNOWN (%04x) memory\n", g_dsp.pc, addr);
break;
}
return(true);
}
uint16 dsp_fetch_code(void)
{
uint16 opc = dsp_imem_read(g_dsp.pc);
g_dsp.pc++;
return(opc);
}
uint16 dsp_peek_code(void)
{
return(dsp_imem_read(g_dsp.pc));
}
/*====================================================================
filename: gdsp_memory.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 <stdio.h>
#include "Globals.h"
#include "gdsp_interpreter.h"
#include "gdsp_memory.h"
#include "gdsp_ifx.h"
uint16 dsp_swap16(uint16 x)
{
return((x >> 8) | (x << 8));
}
uint16* gdsp_get_iram(void)
{
return(g_dsp.iram);
}
uint16* gdsp_get_irom(void)
{
return(g_dsp.irom);
}
uint16* gdsp_get_dram(void)
{
return(g_dsp.dram);
}
uint16* gdsp_get_drom(void)
{
return(g_dsp.drom);
}
uint16 dsp_imem_read(uint16 addr)
{
uint16 opc;
if (g_dsp.pc & 0x8000)
{
opc = g_dsp.irom[addr & DSP_IROM_MASK];
}
else
{
opc = g_dsp.iram[addr & DSP_IRAM_MASK];
}
return(dsp_swap16(opc));
}
uint16 dsp_dmem_read(uint16 addr)
{
uint16 val;
switch (addr >> 12)
{
case 0x0: // 0xxx DRAM
val = g_dsp.dram[addr & DSP_DRAM_MASK];
val = dsp_swap16(val);
break;
case 0x8: // 8xxx DROM
DebugLog("someone reads from ROM\n");
val = g_dsp.drom[addr & DSP_DROM_MASK];
val = dsp_swap16(val);
break;
case 0x1: // 1xxx COEF
val = g_dsp.coef[addr & DSP_DROM_MASK];
val = dsp_swap16(val);
break;
case 0xf: // Fxxx HW regs
val = gdsp_ifx_read(addr);
break;
default: // error
// ErrorLog("%04x DSP ERROR: Read from UNKNOWN (%04x) memory\n", g_dsp.pc, addr);
val = 0;
break;
}
return(val);
}
bool dsp_dmem_write(uint16 addr, uint16 val)
{
switch (addr >> 12)
{
case 0x8: // 8xxx DROM
DebugLog("someone writes to ROM\n");
/* val = dsp_swap16(val);
g_dsp.drom[addr & DSP_DROM_MASK] = val;*/
break;
case 0xf: // Fxxx HW regs
gdsp_ifx_write(addr, val);
break;
case 0x0: // 0xxx DRAM
val = dsp_swap16(val);
g_dsp.dram[addr & DSP_DRAM_MASK] = val;
break;
default: // error
DebugLog("%04x DSP ERROR: Write to UNKNOWN (%04x) memory\n", g_dsp.pc, addr);
break;
}
return(true);
}
uint16 dsp_fetch_code(void)
{
uint16 opc = dsp_imem_read(g_dsp.pc);
g_dsp.pc++;
return(opc);
}
uint16 dsp_peek_code(void)
{
return(dsp_imem_read(g_dsp.pc));
}

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +1,62 @@
/*====================================================================
filename: gdsp_registers.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 "Globals.h"
#include "gdsp_registers.h"
#include "gdsp_interpreter.h"
void dsp_reg_stack_push(uint8 stack_reg)
{
g_dsp.reg_stack_ptr[stack_reg]++;
g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg];
}
void dsp_reg_stack_pop(uint8 stack_reg)
{
g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]];
g_dsp.reg_stack_ptr[stack_reg]--;
g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
}
void dsp_reg_store_stack(uint8 stack_reg, uint16 val)
{
dsp_reg_stack_push(stack_reg);
g_dsp.r[DSP_REG_ST0 + stack_reg] = val;
}
uint16 dsp_reg_load_stack(uint8 stack_reg)
{
uint16 val = g_dsp.r[DSP_REG_ST0 + stack_reg];
dsp_reg_stack_pop(stack_reg);
return(val);
}
/*====================================================================
filename: gdsp_registers.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 "Globals.h"
#include "gdsp_registers.h"
#include "gdsp_interpreter.h"
void dsp_reg_stack_push(uint8 stack_reg)
{
g_dsp.reg_stack_ptr[stack_reg]++;
g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]] = g_dsp.r[DSP_REG_ST0 + stack_reg];
}
void dsp_reg_stack_pop(uint8 stack_reg)
{
g_dsp.r[DSP_REG_ST0 + stack_reg] = g_dsp.reg_stack[stack_reg][g_dsp.reg_stack_ptr[stack_reg]];
g_dsp.reg_stack_ptr[stack_reg]--;
g_dsp.reg_stack_ptr[stack_reg] &= DSP_STACK_MASK;
}
void dsp_reg_store_stack(uint8 stack_reg, uint16 val)
{
dsp_reg_stack_push(stack_reg);
g_dsp.r[DSP_REG_ST0 + stack_reg] = val;
}
uint16 dsp_reg_load_stack(uint8 stack_reg)
{
uint16 val = g_dsp.r[DSP_REG_ST0 + stack_reg];
dsp_reg_stack_pop(stack_reg);
return(val);
}

View File

@ -1,432 +1,432 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "Globals.h"
#include "WaveFile.h"
#include "CommonTypes.h"
#include "Mixer.h"
#include "gdsp_interpreter.h"
#include "gdsp_interface.h"
#include "disassemble.h"
#ifdef _WIN32
#include "DisAsmDlg.h"
#include "DSoundStream.h"
#include "Logging/Console.h" // For wprintf, ClearScreen
#include "Logging/Logging.h" // For Logging
HINSTANCE g_hInstance = NULL;
HANDLE g_hDSPThread = NULL;
CRITICAL_SECTION g_CriticalSection;
CDisAsmDlg g_Dialog;
#else
#define WINAPI
#define LPVOID void*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "AOSoundStream.h"
pthread_t g_hDSPThread = NULL;
#endif
#include "ChunkFile.h"
// =======================================================================================
// Globals
// --------------
DSPInitialize g_dspInitialize;
#define GDSP_MBOX_CPU 0
#define GDSP_MBOX_DSP 1
uint32 g_LastDMAAddress = 0;
uint32 g_LastDMASize = 0;
extern u32 m_addressPBs;
bool AXTask(u32& _uMail);
bool bCanWork = false;
// Set this if you want to log audio. search for log_ai in this file to see the filename.
static bool log_ai = false;
WaveFileWriter g_wave_writer;
// ==============
#ifdef _WIN32
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
g_hInstance = hinstDLL;
return(TRUE);
}
#endif
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_DSP;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (DebugFast)");
#else
#ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin");
#else
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (Debug)");
#endif
#endif
}
void DllAbout(HWND _hParent)
{}
void DllConfig(HWND _hParent)
{}
void DSP_DoState(unsigned char **ptr, int mode) {
PointerWrap p(ptr, mode);
}
void DllDebugger(HWND _hParent, bool Show)
{
#ifdef _WIN32
#if defined (_DEBUG) || defined (DEBUGFAST)
g_Dialog.Create(NULL); //_hParent);
g_Dialog.ShowWindow(SW_SHOW);
MoveWindow(g_Dialog.m_hWnd, 450,0, 780,530, true);
// Open the console window
startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows
wprintf("DllDebugger > Console opened\n");
// TODO: Make this adjustable from the Debugging window
MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true);
#else
MessageBox(0, "Can't open debugging window in Release build of this plugin.", "DSP LLE", 0);
#endif
#endif
}
// =======================================================================================
// Regular thread
// --------------
#ifdef _WIN32
DWORD WINAPI dsp_thread(LPVOID lpParameter)
#else
void* dsp_thread(void* lpParameter)
#endif
{
while (1)
{
if (!gdsp_run())
{
ErrorLog("*** DSP: CRITICAL ERROR ***\n");
//return 0;
exit(0);
}
}
}
// ==============
// =======================================================================================
// Debug thread
// --------------
#ifdef _WIN32
DWORD WINAPI dsp_thread_debug(LPVOID lpParameter)
#else
void* dsp_thread_debug(void* lpParameter)
#endif
{
//if (g_hDSPThread)
//{
// return NULL; // enable this to disable the plugin
//}
#ifdef _WIN32
while (1)
{
Logging(); // logging
if (g_Dialog.CanDoStep())
{
gdsp_runx(1);
}
else
{
Sleep(100);
}
}
#endif
return NULL;
}
// ==============
void DSP_DebugBreak()
{
#ifdef _WIN32
#if defined(_DEBUG) || defined(DEBUGFAST)
g_Dialog.DebugBreak();
#endif
#endif
}
void dspi_req_dsp_irq()
{
g_dspInitialize.pGenerateDSPInterrupt();
}
void DSP_Initialize(DSPInitialize _dspInitialize)
{
bCanWork = true;
g_dspInitialize = _dspInitialize;
gdsp_init();
g_dsp.step_counter = 0;
g_dsp.cpu_ram = g_dspInitialize.pGetMemoryPointer(0);
g_dsp.irq_request = dspi_req_dsp_irq;
gdsp_reset();
if (!gdsp_load_rom((char *)DSP_ROM_FILE))
{
bCanWork = false;
PanicAlert("No DSP ROM");
ErrorLog("Cannot load DSP ROM\n");
}
if (!gdsp_load_coef((char *)DSP_COEF_FILE))
{
bCanWork = false;
PanicAlert("No DSP COEF");
ErrorLog("Cannot load DSP COEF\n");
}
if(!bCanWork)
return; // TODO: Don't let it work
// ---------------------------------------------------------------------------------------
// First create DSP_UCode.bin by setting "#define DUMP_DSP_IMEM 1" in Globals.h. Then
// make the disassembled file here.
// --------------
// Dump UCode to file...
FILE* t = fopen("C:\\_\\DSP_UC_09CD143F.txt", "wb");
if (t != NULL)
{
gd_globals_t gdg;
gd_dis_file(&gdg, (char *)"C:\\_\\DSP_UC_09CD143F.bin", t);
fclose(t);
}
// --------------
#ifdef _WIN32
#if defined(_DEBUG) || defined(DEBUGFAST)
g_hDSPThread = CreateThread(NULL, 0, dsp_thread_debug, 0, 0, NULL);
#else
g_hDSPThread = CreateThread(NULL, 0, dsp_thread, 0, 0, NULL);
#endif // DEBUG
#else
#if _DEBUG
pthread_create(&g_hDSPThread, NULL, dsp_thread_debug, (void *)NULL);
#else
pthread_create(&g_hDSPThread, NULL, dsp_thread, (void *)NULL);
#endif // DEBUG
#endif // WIN32
if (log_ai) {
g_wave_writer.Start("C:\\_\\ai_log.wav");
g_wave_writer.SetSkipSilence(false);
}
#ifdef _WIN32
InitializeCriticalSection(&g_CriticalSection);
DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer);
#else
AOSound::AOSound_StartSound(48000, Mixer);
#endif
}
void DSP_Shutdown(void)
{
if (log_ai)
g_wave_writer.Stop();
#ifdef _WIN32
if (g_hDSPThread != NULL)
{
TerminateThread(g_hDSPThread, 0);
}
#else
pthread_cancel(g_hDSPThread);
#endif
}
u16 DSP_WriteControlRegister(u16 _uFlag)
{
gdsp_write_cr(_uFlag);
return(gdsp_read_cr());
}
u16 DSP_ReadControlRegister()
{
return(gdsp_read_cr());
}
u16 DSP_ReadMailboxHigh(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return(gdsp_mbox_read_h(GDSP_MBOX_CPU));
}
else
{
return(gdsp_mbox_read_h(GDSP_MBOX_DSP));
}
}
u16 DSP_ReadMailboxLow(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return(gdsp_mbox_read_l(GDSP_MBOX_CPU));
}
else
{
return(gdsp_mbox_read_l(GDSP_MBOX_DSP));
}
}
void DSP_WriteMailboxHigh(bool _CPUMailbox, u16 _uHighMail)
{
if (_CPUMailbox)
{
if (gdsp_mbox_peek(GDSP_MBOX_CPU) & 0x80000000)
{
ErrorLog("Mailbox isnt empty ... strange");
}
#if PROFILE
if ((_uHighMail) == 0xBABE)
{
ProfilerStart();
}
#endif
gdsp_mbox_write_h(GDSP_MBOX_CPU, _uHighMail);
}
else
{
ErrorLog("CPU cant write to DSP mailbox");
}
}
void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail)
{
if (_CPUMailbox)
{
gdsp_mbox_write_l(GDSP_MBOX_CPU, _uLowMail);
u32 uAddress = gdsp_mbox_peek(GDSP_MBOX_CPU);
u16 errpc = g_dsp.err_pc;
DebugLog("Write CPU Mail: 0x%08x (pc=0x%04x)\n", uAddress, errpc);
// ---------------------------------------------------------------------------------------
// I couldn't find any better way to detect the AX mails so this had to do. Please feel free
// to change it.
// --------------
if ((errpc == 0x0054 || errpc == 0x0055) && m_addressPBs == 0)
{
DebugLog("AXTask ======== 0x%08x (pc=0x%04x)", uAddress, errpc);
AXTask(uAddress);
}
}
else
{
ErrorLog("CPU cant write to DSP mailbox");
}
}
void DSP_Update(int cycles)
{
if (g_hDSPThread)
{
return;
}
#ifdef _WIN32
if (g_Dialog.CanDoStep())
{
gdsp_runx(100); // cycles
}
#endif
}
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
short samples[16] = {0}; // interleaved stereo
if (address) {
for (int i = 0; i < 16; i++) {
samples[i] = Memory_Read_U16(address + i * 2);
}
if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8);
}
Mixer_PushSamples(samples, 32 / 4, sample_rate);
static int counter = 0;
counter++;
#ifdef _WIN32
if ((counter & 255) == 0)
DSound::DSound_UpdateSound();
#endif
}
void __Log(int, const char *fmt, ...)
{
//DebugLog(fmt);
}
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#include "Common.h"
#include "Globals.h"
#include "WaveFile.h"
#include "CommonTypes.h"
#include "Mixer.h"
#include "gdsp_interpreter.h"
#include "gdsp_interface.h"
#include "disassemble.h"
#ifdef _WIN32
#include "DisAsmDlg.h"
#include "DSoundStream.h"
#include "Logging/Console.h" // For wprintf, ClearScreen
#include "Logging/Logging.h" // For Logging
HINSTANCE g_hInstance = NULL;
HANDLE g_hDSPThread = NULL;
CRITICAL_SECTION g_CriticalSection;
CDisAsmDlg g_Dialog;
#else
#define WINAPI
#define LPVOID void*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "AOSoundStream.h"
pthread_t g_hDSPThread = NULL;
#endif
#include "ChunkFile.h"
// =======================================================================================
// Globals
// --------------
DSPInitialize g_dspInitialize;
#define GDSP_MBOX_CPU 0
#define GDSP_MBOX_DSP 1
uint32 g_LastDMAAddress = 0;
uint32 g_LastDMASize = 0;
extern u32 m_addressPBs;
bool AXTask(u32& _uMail);
bool bCanWork = false;
// Set this if you want to log audio. search for log_ai in this file to see the filename.
static bool log_ai = false;
WaveFileWriter g_wave_writer;
// ==============
#ifdef _WIN32
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD dwReason, // reason called
LPVOID lpvReserved) // reserved
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
g_hInstance = hinstDLL;
return(TRUE);
}
#endif
void GetDllInfo(PLUGIN_INFO* _PluginInfo)
{
_PluginInfo->Version = 0x0100;
_PluginInfo->Type = PLUGIN_TYPE_DSP;
#ifdef DEBUGFAST
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (DebugFast)");
#else
#ifndef _DEBUG
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin");
#else
sprintf(_PluginInfo->Name, "Dolphin DSP-LLE Plugin (Debug)");
#endif
#endif
}
void DllAbout(HWND _hParent)
{}
void DllConfig(HWND _hParent)
{}
void DSP_DoState(unsigned char **ptr, int mode) {
PointerWrap p(ptr, mode);
}
void DllDebugger(HWND _hParent, bool Show)
{
#ifdef _WIN32
#if defined (_DEBUG) || defined (DEBUGFAST)
g_Dialog.Create(NULL); //_hParent);
g_Dialog.ShowWindow(SW_SHOW);
MoveWindow(g_Dialog.m_hWnd, 450,0, 780,530, true);
// Open the console window
startConsoleWin(155, 100, "Sound Debugging"); // give room for 100 rows
wprintf("DllDebugger > Console opened\n");
// TODO: Make this adjustable from the Debugging window
MoveWindow(GetConsoleHwnd(), 0,400, 1280,500, true);
#else
MessageBox(0, "Can't open debugging window in Release build of this plugin.", "DSP LLE", 0);
#endif
#endif
}
// =======================================================================================
// Regular thread
// --------------
#ifdef _WIN32
DWORD WINAPI dsp_thread(LPVOID lpParameter)
#else
void* dsp_thread(void* lpParameter)
#endif
{
while (1)
{
if (!gdsp_run())
{
ErrorLog("*** DSP: CRITICAL ERROR ***\n");
//return 0;
exit(0);
}
}
}
// ==============
// =======================================================================================
// Debug thread
// --------------
#ifdef _WIN32
DWORD WINAPI dsp_thread_debug(LPVOID lpParameter)
#else
void* dsp_thread_debug(void* lpParameter)
#endif
{
//if (g_hDSPThread)
//{
// return NULL; // enable this to disable the plugin
//}
#ifdef _WIN32
while (1)
{
Logging(); // logging
if (g_Dialog.CanDoStep())
{
gdsp_runx(1);
}
else
{
Sleep(100);
}
}
#endif
return NULL;
}
// ==============
void DSP_DebugBreak()
{
#ifdef _WIN32
#if defined(_DEBUG) || defined(DEBUGFAST)
g_Dialog.DebugBreak();
#endif
#endif
}
void dspi_req_dsp_irq()
{
g_dspInitialize.pGenerateDSPInterrupt();
}
void DSP_Initialize(DSPInitialize _dspInitialize)
{
bCanWork = true;
g_dspInitialize = _dspInitialize;
gdsp_init();
g_dsp.step_counter = 0;
g_dsp.cpu_ram = g_dspInitialize.pGetMemoryPointer(0);
g_dsp.irq_request = dspi_req_dsp_irq;
gdsp_reset();
if (!gdsp_load_rom((char *)DSP_ROM_FILE))
{
bCanWork = false;
PanicAlert("No DSP ROM");
ErrorLog("Cannot load DSP ROM\n");
}
if (!gdsp_load_coef((char *)DSP_COEF_FILE))
{
bCanWork = false;
PanicAlert("No DSP COEF");
ErrorLog("Cannot load DSP COEF\n");
}
if(!bCanWork)
return; // TODO: Don't let it work
// ---------------------------------------------------------------------------------------
// First create DSP_UCode.bin by setting "#define DUMP_DSP_IMEM 1" in Globals.h. Then
// make the disassembled file here.
// --------------
// Dump UCode to file...
FILE* t = fopen("C:\\_\\DSP_UC_09CD143F.txt", "wb");
if (t != NULL)
{
gd_globals_t gdg;
gd_dis_file(&gdg, (char *)"C:\\_\\DSP_UC_09CD143F.bin", t);
fclose(t);
}
// --------------
#ifdef _WIN32
#if defined(_DEBUG) || defined(DEBUGFAST)
g_hDSPThread = CreateThread(NULL, 0, dsp_thread_debug, 0, 0, NULL);
#else
g_hDSPThread = CreateThread(NULL, 0, dsp_thread, 0, 0, NULL);
#endif // DEBUG
#else
#if _DEBUG
pthread_create(&g_hDSPThread, NULL, dsp_thread_debug, (void *)NULL);
#else
pthread_create(&g_hDSPThread, NULL, dsp_thread, (void *)NULL);
#endif // DEBUG
#endif // WIN32
if (log_ai) {
g_wave_writer.Start("C:\\_\\ai_log.wav");
g_wave_writer.SetSkipSilence(false);
}
#ifdef _WIN32
InitializeCriticalSection(&g_CriticalSection);
DSound::DSound_StartSound((HWND)g_dspInitialize.hWnd, 48000, Mixer);
#else
AOSound::AOSound_StartSound(48000, Mixer);
#endif
}
void DSP_Shutdown(void)
{
if (log_ai)
g_wave_writer.Stop();
#ifdef _WIN32
if (g_hDSPThread != NULL)
{
TerminateThread(g_hDSPThread, 0);
}
#else
pthread_cancel(g_hDSPThread);
#endif
}
u16 DSP_WriteControlRegister(u16 _uFlag)
{
gdsp_write_cr(_uFlag);
return(gdsp_read_cr());
}
u16 DSP_ReadControlRegister()
{
return(gdsp_read_cr());
}
u16 DSP_ReadMailboxHigh(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return(gdsp_mbox_read_h(GDSP_MBOX_CPU));
}
else
{
return(gdsp_mbox_read_h(GDSP_MBOX_DSP));
}
}
u16 DSP_ReadMailboxLow(bool _CPUMailbox)
{
if (_CPUMailbox)
{
return(gdsp_mbox_read_l(GDSP_MBOX_CPU));
}
else
{
return(gdsp_mbox_read_l(GDSP_MBOX_DSP));
}
}
void DSP_WriteMailboxHigh(bool _CPUMailbox, u16 _uHighMail)
{
if (_CPUMailbox)
{
if (gdsp_mbox_peek(GDSP_MBOX_CPU) & 0x80000000)
{
ErrorLog("Mailbox isnt empty ... strange");
}
#if PROFILE
if ((_uHighMail) == 0xBABE)
{
ProfilerStart();
}
#endif
gdsp_mbox_write_h(GDSP_MBOX_CPU, _uHighMail);
}
else
{
ErrorLog("CPU cant write to DSP mailbox");
}
}
void DSP_WriteMailboxLow(bool _CPUMailbox, u16 _uLowMail)
{
if (_CPUMailbox)
{
gdsp_mbox_write_l(GDSP_MBOX_CPU, _uLowMail);
u32 uAddress = gdsp_mbox_peek(GDSP_MBOX_CPU);
u16 errpc = g_dsp.err_pc;
DebugLog("Write CPU Mail: 0x%08x (pc=0x%04x)\n", uAddress, errpc);
// ---------------------------------------------------------------------------------------
// I couldn't find any better way to detect the AX mails so this had to do. Please feel free
// to change it.
// --------------
if ((errpc == 0x0054 || errpc == 0x0055) && m_addressPBs == 0)
{
DebugLog("AXTask ======== 0x%08x (pc=0x%04x)", uAddress, errpc);
AXTask(uAddress);
}
}
else
{
ErrorLog("CPU cant write to DSP mailbox");
}
}
void DSP_Update(int cycles)
{
if (g_hDSPThread)
{
return;
}
#ifdef _WIN32
if (g_Dialog.CanDoStep())
{
gdsp_runx(100); // cycles
}
#endif
}
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
short samples[16] = {0}; // interleaved stereo
if (address) {
for (int i = 0; i < 16; i++) {
samples[i] = Memory_Read_U16(address + i * 2);
}
if (log_ai)
g_wave_writer.AddStereoSamples(samples, 8);
}
Mixer_PushSamples(samples, 32 / 4, sample_rate);
static int counter = 0;
counter++;
#ifdef _WIN32
if ((counter & 255) == 0)
DSound::DSound_UpdateSound();
#endif
}
void __Log(int, const char *fmt, ...)
{
//DebugLog(fmt);
}

View File

@ -1,237 +1,237 @@
/*====================================================================
filename: opcodes.cpp
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.
====================================================================*/
#include "Globals.h"
#include "opcodes.h"
opc_t opcodes[] =
{
{"NOP", 0x0000, 0xffff, 1, 0, {},},
{"HALT", 0x0021, 0xffff, 1, 0, {},},
{"RET", 0x02df, 0xffff, 1, 0, {},},
{"RETEQ", 0x02d5, 0xffff, 1, 0, {},},
{"RETNZ", 0x02dd, 0xffff, 1, 0, {},},
{"RTI", 0x02ff, 0xffff, 1, 0, {},},
{"CALL", 0x02bf, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"CALLNE", 0x02b4, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"IF_0", 0x0270, 0xffff, 1, 0, {},},
{"IF_1", 0x0271, 0xffff, 1, 0, {},},
{"IF_2", 0x0272, 0xffff, 1, 0, {},},
{"IF_3", 0x0273, 0xffff, 1, 0, {},},
{"IF_E", 0x0274, 0xffff, 1, 0, {},},
{"IF_Q", 0x0275, 0xffff, 1, 0, {},},
{"IF_R", 0x027c, 0xffff, 1, 0, {},},
{"IF_Z", 0x027d, 0xffff, 1, 0, {},},
{"IF_P", 0x027f, 0xffff, 1, 0, {},},
{"JX0", 0x0290, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX1", 0x0291, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX2", 0x0292, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX3", 0x0293, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JNE", 0x0294, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JEQ", 0x0295, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JZR", 0x029c, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JNZ", 0x029d, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JMP", 0x029f, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"DAR", 0x0004, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"IAR", 0x0008, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"CALLR", 0x171f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},},
{"JMPR", 0x170f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},},
{"SBCLR", 0x1200, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},},
{"SBSET", 0x1300, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},},
{"LSL", 0x1400, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},},
{"LSR", 0x1440, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},},
{"ASL", 0x1480, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},},
{"ASR", 0x14c0, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},},
{"LRI", 0x0080, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}},},
{"LR", 0x00c0, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}},},
{"SR", 0x00e0, 0xffe0, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}},},
{"MRR", 0x1c00, 0xfc00, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}},},
{"SI", 0x1600, 0xff00, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}},},
{"LRS", 0x2000, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}},},
{"SRS", 0x2800, 0xf800, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}},},
{"LRIS", 0x0800, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"ADDIS", 0x0400, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"CMPIS", 0x0600, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"ANDI", 0x0240, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ANDF", 0x02c0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"XORI", 0x0220, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ANDCF", 0x02a0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ORI", 0x0260, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ORF", 0x02e0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ADDI", 0x0200, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64
{"CMPI", 0x0280, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64
{"ILRR", 0x0210, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},},
{"ILRRI", 0x0218, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},},
// load and store value pointed by indexing reg and increment; LRR/SRR variants
{"LRRI", 0x1900, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRRD", 0x1880, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRRN", 0x1980, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRR", 0x1800, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"SRRI", 0x1b00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRRD", 0x1a80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRRN", 0x1b80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRR", 0x1a00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"LOOPI", 0x1000, 0xff00, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}},},
{"BLOOPI", 0x1100, 0xff00, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_VAL, 2, 1, 0, 0xffff}},},
{"LOOP", 0x0040, 0xffe0, 1, 1, {{P_REG, 1, 0, 0, 0x001f}},},
{"BLOOP", 0x0060, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_VAL, 2, 1, 0, 0xffff}},},
// opcodes that can be extended
// extended opcodes, note size of opcode will be set to 0
{"NX", 0x8000, 0xffff, 1 | P_EXT, 0, {},},
{"S40", 0x8e00, 0xffff, 1 | P_EXT, 0, {},},
{"S16", 0x8f00, 0xffff, 1 | P_EXT, 0, {},},
{"M2", 0x8a00, 0xffff, 1 | P_EXT, 0, {},},
{"M0", 0x8b00, 0xffff, 1 | P_EXT, 0, {},},
{"CLR15", 0x8c00, 0xffff, 1 | P_EXT, 0, {},},
{"SET15", 0x8d00, 0xffff, 1 | P_EXT, 0, {},},
{"DECM", 0x7800, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"INCM", 0x7400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"DEC", 0x7a00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"INC", 0x7600, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"NEG", 0x7c00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"TST", 0xb100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"TSTAXH", 0x8600, 0xfeff, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}},},
{"CMP", 0x8200, 0xffff, 1 | P_EXT, 0, {},},
{"CMPAXH", 0xc100, 0xe7ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}},},
{"CLR", 0x8100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"CLRP", 0x8400, 0xffff, 1 | P_EXT, 0, {},},
{"MOV", 0x6c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"MOVAX", 0x6800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"MOVR", 0x6000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"MOVP", 0x6e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"MOVPZ", 0xfe00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ADDPAXZ", 0xf800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"ADDP", 0x4e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"LSL16", 0xf000, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"LSR16", 0xf400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ASR16", 0x9100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"XORR", 0x3000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ANDR", 0x3400, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ORR", 0x3800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ANDC", 0x3C00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ORC", 0x3E00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"MULX", 0xa000, 0xe7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}},},
{"MULXAC", 0xa400, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULXMV", 0xa600, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULXMVZ", 0xa200, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MUL", 0x9000, 0xf7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}},},
{"MULAC", 0x9400, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULMV", 0x9600, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULMVZ", 0x9200, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULC", 0xc000, 0xe7ff, 1 | P_EXT, 2, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}},},
{"MULCAC", 0xc400, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULCMV", 0xc600, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULCMVZ", 0xc200, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"ADDR", 0x4000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"ADDAX", 0x4800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"ADD", 0x4c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"ADDAXL", 0x7000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"SUBR", 0x5000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"SUBAX", 0x5800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"SUB", 0x5c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"MADD", 0xf200, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"MSUB", 0xf600, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"MADDX", 0xe000, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MSUBX", 0xe400, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MADDC", 0xe800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MSUBC", 0xec00, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
// assemble CW
{"CW", 0x0000, 0xffff, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},},
// unknown opcode for disassemble
{"CW", 0x0000, 0x0000, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},},
};
opc_t opcodes_ext[] =
{
{"L", 0x0040, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LN", 0x0044, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LS", 0x0080, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSN", 0x0084, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSM", 0x0088, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSNM", 0x008c, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"SL", 0x0082, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLN", 0x0086, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLM", 0x008a, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLNM", 0x008e, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"S", 0x0020, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},},
{"SN", 0x0024, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},},
{"LDX", 0x00c0, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXN", 0x00c4, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXM", 0x00c8, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXNM", 0x00cc, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LD", 0x00c0, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDN", 0x00c4, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDM", 0x00c8, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDNM", 0x00cc, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"MV", 0x0010, 0x00f0, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}},},
{"DR", 0x0004, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"IR", 0x0008, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"NR", 0x000c, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"XXX", 0x0000, 0x0000, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}},},
};
const uint32 opcodes_size = sizeof(opcodes) / sizeof(opc_t);
const uint32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(opc_t);
/*====================================================================
filename: opcodes.cpp
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.
====================================================================*/
#include "Globals.h"
#include "opcodes.h"
opc_t opcodes[] =
{
{"NOP", 0x0000, 0xffff, 1, 0, {},},
{"HALT", 0x0021, 0xffff, 1, 0, {},},
{"RET", 0x02df, 0xffff, 1, 0, {},},
{"RETEQ", 0x02d5, 0xffff, 1, 0, {},},
{"RETNZ", 0x02dd, 0xffff, 1, 0, {},},
{"RTI", 0x02ff, 0xffff, 1, 0, {},},
{"CALL", 0x02bf, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"CALLNE", 0x02b4, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"IF_0", 0x0270, 0xffff, 1, 0, {},},
{"IF_1", 0x0271, 0xffff, 1, 0, {},},
{"IF_2", 0x0272, 0xffff, 1, 0, {},},
{"IF_3", 0x0273, 0xffff, 1, 0, {},},
{"IF_E", 0x0274, 0xffff, 1, 0, {},},
{"IF_Q", 0x0275, 0xffff, 1, 0, {},},
{"IF_R", 0x027c, 0xffff, 1, 0, {},},
{"IF_Z", 0x027d, 0xffff, 1, 0, {},},
{"IF_P", 0x027f, 0xffff, 1, 0, {},},
{"JX0", 0x0290, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX1", 0x0291, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX2", 0x0292, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JX3", 0x0293, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JNE", 0x0294, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JEQ", 0x0295, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JZR", 0x029c, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JNZ", 0x029d, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"JMP", 0x029f, 0xffff, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}},},
{"DAR", 0x0004, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"IAR", 0x0008, 0xfffc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"CALLR", 0x171f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},},
{"JMPR", 0x170f, 0xff1f, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}},},
{"SBCLR", 0x1200, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},},
{"SBSET", 0x1300, 0xfff8, 1, 1, {{P_IMM, 1, 0, 0, 0x0007}},},
{"LSL", 0x1400, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},},
{"LSR", 0x1440, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x003f}},},
{"ASL", 0x1480, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},},
{"ASR", 0x14c0, 0xfec0, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x007f}},},
{"LRI", 0x0080, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_IMM, 2, 1, 0, 0xffff}},},
{"LR", 0x00c0, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_MEM, 2, 1, 0, 0xffff}},},
{"SR", 0x00e0, 0xffe0, 2, 2, {{P_MEM, 2, 1, 0, 0xffff}, {P_REG, 1, 0, 0, 0x001f}},},
{"MRR", 0x1c00, 0xfc00, 1, 2, {{P_REG, 1, 0, 5, 0x03e0}, {P_REG, 1, 0, 0, 0x001f}},},
{"SI", 0x1600, 0xff00, 2, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_IMM, 2, 1, 0, 0xffff}},},
{"LRS", 0x2000, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_MEM, 1, 0, 0, 0x00ff}},},
{"SRS", 0x2800, 0xf800, 1, 2, {{P_MEM, 1, 0, 0, 0x00ff}, {P_REG18, 1, 0, 8, 0x0700}},},
{"LRIS", 0x0800, 0xf800, 1, 2, {{P_REG18, 1, 0, 8, 0x0700}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"ADDIS", 0x0400, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"CMPIS", 0x0600, 0xfe00, 1, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 1, 0, 0, 0x00ff}},},
{"ANDI", 0x0240, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ANDF", 0x02c0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"XORI", 0x0220, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ANDCF", 0x02a0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ORI", 0x0260, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ORF", 0x02e0, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},},
{"ADDI", 0x0200, 0xfeff, 2, 2, {{P_ACC, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64
{"CMPI", 0x0280, 0xfeff, 2, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_IMM, 2, 1, 0, 0xffff}},}, // missing S64
{"ILRR", 0x0210, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},},
{"ILRRI", 0x0218, 0xfedc, 1, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_PRG, 1, 0, 0, 0x0003}},},
// load and store value pointed by indexing reg and increment; LRR/SRR variants
{"LRRI", 0x1900, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRRD", 0x1880, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRRN", 0x1980, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"LRR", 0x1800, 0xff80, 1, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_PRG, 1, 0, 5, 0x0060}},},
{"SRRI", 0x1b00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRRD", 0x1a80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRRN", 0x1b80, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"SRR", 0x1a00, 0xff80, 1, 2, {{P_PRG, 1, 0, 5, 0x0060}, {P_REG, 1, 0, 0, 0x001f}},},
{"LOOPI", 0x1000, 0xff00, 1, 1, {{P_IMM, 1, 0, 0, 0x00ff}},},
{"BLOOPI", 0x1100, 0xff00, 2, 2, {{P_IMM, 1, 0, 0, 0x00ff}, {P_VAL, 2, 1, 0, 0xffff}},},
{"LOOP", 0x0040, 0xffe0, 1, 1, {{P_REG, 1, 0, 0, 0x001f}},},
{"BLOOP", 0x0060, 0xffe0, 2, 2, {{P_REG, 1, 0, 0, 0x001f}, {P_VAL, 2, 1, 0, 0xffff}},},
// opcodes that can be extended
// extended opcodes, note size of opcode will be set to 0
{"NX", 0x8000, 0xffff, 1 | P_EXT, 0, {},},
{"S40", 0x8e00, 0xffff, 1 | P_EXT, 0, {},},
{"S16", 0x8f00, 0xffff, 1 | P_EXT, 0, {},},
{"M2", 0x8a00, 0xffff, 1 | P_EXT, 0, {},},
{"M0", 0x8b00, 0xffff, 1 | P_EXT, 0, {},},
{"CLR15", 0x8c00, 0xffff, 1 | P_EXT, 0, {},},
{"SET15", 0x8d00, 0xffff, 1 | P_EXT, 0, {},},
{"DECM", 0x7800, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"INCM", 0x7400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"DEC", 0x7a00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"INC", 0x7600, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"NEG", 0x7c00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"TST", 0xb100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"TSTAXH", 0x8600, 0xfeff, 1 | P_EXT, 1, {{P_REG1A, 1, 0, 8, 0x0100}},},
{"CMP", 0x8200, 0xffff, 1 | P_EXT, 0, {},},
{"CMPAXH", 0xc100, 0xe7ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 12, 0x1000}, {P_REG1A, 1, 0, 11, 0x0800}},},
{"CLR", 0x8100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"CLRP", 0x8400, 0xffff, 1 | P_EXT, 0, {},},
{"MOV", 0x6c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"MOVAX", 0x6800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"MOVR", 0x6000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"MOVP", 0x6e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"MOVPZ", 0xfe00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ADDPAXZ", 0xf800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"ADDP", 0x4e00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"LSL16", 0xf000, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"LSR16", 0xf400, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ASR16", 0x9100, 0xf7ff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 11, 0x0800}},},
{"XORR", 0x3000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ANDR", 0x3400, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ORR", 0x3800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 9, 0x0200}},},
{"ANDC", 0x3C00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"ORC", 0x3E00, 0xfeff, 1 | P_EXT, 1, {{P_ACCM, 1, 0, 8, 0x0100}},},
{"MULX", 0xa000, 0xe7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}},},
{"MULXAC", 0xa400, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULXMV", 0xa600, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULXMVZ", 0xa200, 0xe6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x1000}, {P_REG19, 1, 0, 10, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MUL", 0x9000, 0xf7ff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}},},
{"MULAC", 0x9400, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULMV", 0x9600, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULMVZ", 0x9200, 0xf6ff, 1 | P_EXT, 3, {{P_REG18, 1, 0, 11, 0x0800}, {P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULC", 0xc000, 0xe7ff, 1 | P_EXT, 2, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}},},
{"MULCAC", 0xc400, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULCMV", 0xc600, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"MULCMVZ", 0xc200, 0xe6ff, 1 | P_EXT, 3, {{P_REG1A, 1, 0, 11, 0x0800}, {P_ACCM, 1, 0, 12, 0x1000}, {P_ACCM, 1, 0, 8, 0x0100}},},
{"ADDR", 0x4000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"ADDAX", 0x4800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"ADD", 0x4c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"ADDAXL", 0x7000, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"SUBR", 0x5000, 0xf8ff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0600}},},
{"SUBAX", 0x5800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_REG18, 1, 0, 9, 0x0200}},},
{"SUB", 0x5c00, 0xfeff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 8, 0x0100}, {P_ACCM_D, 1, 0, 8, 0x0100}},},
{"MADD", 0xf200, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"MSUB", 0xf600, 0xfeff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0100}, {P_REG1A, 1, 0, 8, 0x0100}},},
{"MADDX", 0xe000, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MSUBX", 0xe400, 0xfcff, 1 | P_EXT, 2, {{P_REG18, 1, 0, 8, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MADDC", 0xe800, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
{"MSUBC", 0xec00, 0xfcff, 1 | P_EXT, 2, {{P_ACCM, 1, 0, 9, 0x0200}, {P_REG19, 1, 0, 7, 0x0100}},},
// assemble CW
{"CW", 0x0000, 0xffff, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},},
// unknown opcode for disassemble
{"CW", 0x0000, 0x0000, 1, 1, {{P_VAL, 2, 0, 0, 0xffff}},},
};
opc_t opcodes_ext[] =
{
{"L", 0x0040, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LN", 0x0044, 0x00c4, 1, 2, {{P_REG18, 1, 0, 3, 0x0038}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LS", 0x0080, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSN", 0x0084, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSM", 0x0088, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"LSNM", 0x008c, 0x00ce, 1, 2, {{P_REG18, 1, 0, 4, 0x0030}, {P_ACCM, 1, 0, 0, 0x0001}},},
{"SL", 0x0082, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLN", 0x0086, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLM", 0x008a, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"SLNM", 0x008e, 0x00ce, 1, 2, {{P_ACCM, 1, 0, 0, 0x0001}, {P_REG18, 1, 0, 4, 0x0030}},},
{"S", 0x0020, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},},
{"SN", 0x0024, 0x00e4, 1, 2, {{P_PRG, 1, 0, 0, 0x0003}, {P_REG1C, 1, 0, 3, 0x0018}},},
{"LDX", 0x00c0, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXN", 0x00c4, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXM", 0x00c8, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LDXNM", 0x00cc, 0x00cf, 1, 3, {{P_REG18, 1, 0, 4, 0x0010}, {P_REG1A, 1, 0, 4, 0x0010}, {P_PRG, 1, 0, 5, 0x0020}},},
{"LD", 0x00c0, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDN", 0x00c4, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDM", 0x00c8, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"LDNM", 0x00cc, 0x00cc, 1, 3, {{P_REG18, 1, 0, 4, 0x0020}, {P_REG19, 1, 0, 3, 0x0010}, {P_PRG, 1, 0, 0, 0x0003}},},
{"MV", 0x0010, 0x00f0, 1, 2, {{P_REG18, 1, 0, 2, 0x000c}, {P_REG1C, 1, 0, 0, 0x0003}},},
{"DR", 0x0004, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"IR", 0x0008, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"NR", 0x000c, 0x00fc, 1, 1, {{P_REG, 1, 0, 0, 0x0003}},},
{"XXX", 0x0000, 0x0000, 1, 1, {{P_VAL, 1, 0, 0, 0x00ff}},},
};
const uint32 opcodes_size = sizeof(opcodes) / sizeof(opc_t);
const uint32 opcodes_ext_size = sizeof(opcodes_ext) / sizeof(opc_t);

View File

@ -1,19 +1,19 @@
// 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 "stdafx.h"
// 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 "stdafx.h"