git-svn-id: http://svn.purei.org/purei/trunk@408 b36208d7-6611-0410-8bec-b1987f11c4a2

This commit is contained in:
jpd002 2008-11-06 23:48:40 +00:00
parent 66fb9f25e1
commit 4ede26cb6a
20 changed files with 1005 additions and 1457 deletions

View File

@ -4,13 +4,11 @@
#include "Log.h"
using namespace std;
using namespace Iop;
#define LOG_NAME ("spu")
#define MAX_GENERAL_REG_NAME (64)
#define SAMPLE_RATE (44100)
//#define SAMPLE_RATE (48000)
static const char* g_channelRegisterName[8] =
{
"VOL_LEFT",
@ -91,37 +89,10 @@ static const char* g_generalRegisterName[MAX_GENERAL_REG_NAME] =
"IN_COEF_R"
};
CSpu::CSpu(uint8* ram, uint32 ramSize) :
m_ram(ram),
m_ramSize(ramSize)
CSpu::CSpu(CSpuBase& base) :
m_base(base)
{
Reset();
//Init log table for ADSR
memset(m_adsrLogTable, 0, sizeof(m_adsrLogTable));
uint32 value = 3;
uint32 columnIncrement = 1;
uint32 column = 0;
for(unsigned int i = 32; i < 160; i++)
{
if(value < 0x3FFFFFFF)
{
value += columnIncrement;
column++;
if(column == 5)
{
column = 1;
columnIncrement *= 2;
}
}
else
{
value = 0x3FFFFFFF;
}
m_adsrLogTable[i] = value;
}
}
CSpu::~CSpu()
@ -133,247 +104,7 @@ void CSpu::Reset()
{
m_status0 = 0;
m_status1 = 0;
m_bufferAddr = 0;
m_channelOn.f = 0;
m_channelReverb.f = 0;
m_reverbTicks = 0;
m_ctrl = 0;
m_bufferAddr = 0;
m_reverbCurrAddr = 0;
m_reverbWorkAddr = 0;
m_baseSamplingRate = 44100;
memset(m_channel, 0, sizeof(m_channel));
memset(m_reverb, 0, sizeof(m_reverb));
for(unsigned int i = 0; i < MAX_CHANNEL; i++)
{
m_reader[i].Reset();
}
}
void CSpu::SetBaseSamplingRate(uint32 samplingRate)
{
m_baseSamplingRate = samplingRate;
}
uint32 CSpu::GetChannelOn() const
{
return m_channelOn.f;
}
uint32 CSpu::GetChannelReverb() const
{
return m_channelReverb.f;
}
CSpu::CHANNEL& CSpu::GetChannel(unsigned int channelNumber)
{
return m_channel[channelNumber];
}
uint32 CSpu::GetTransferAddress() const
{
return m_bufferAddr;
}
void CSpu::SetTransferAddress(uint32 value)
{
m_bufferAddr = value & (m_ramSize - 1);
}
void CSpu::Render(int16* samples, unsigned int sampleCount, unsigned int sampleRate)
{
struct SampleMixer
{
void operator() (int32 inputSample, const CHANNEL_VOLUME& volume, int16* output) const
{
if(!volume.mode.mode)
{
inputSample = (inputSample * static_cast<int32>(volume.volume.volume)) / 0x3FFF;
}
int32 resultSample = inputSample + static_cast<int32>(*output);
resultSample = max<int32>(resultSample, SHRT_MIN);
resultSample = min<int32>(resultSample, SHRT_MAX);
*output = static_cast<int16>(resultSample);
}
};
assert((sampleCount & 0x01) == 0);
//ticks are 44100Hz ticks
unsigned int ticks = sampleCount / 2;
memset(samples, 0, sizeof(int16) * sampleCount);
// int16* bufferTemp = reinterpret_cast<int16*>(_alloca(sizeof(int16) * ticks));
for(unsigned int j = 0; j < ticks; j++)
{
int16 reverbSample[2] = { 0, 0 };
//Update channels
for(unsigned int i = 0; i < 24; i++)
{
CHANNEL& channel(m_channel[i]);
if(channel.status == STOPPED) continue;
CSampleReader& reader(m_reader[i]);
if(channel.status == KEY_ON)
{
reader.SetParams(m_ram + (channel.address * 8), m_ram + (channel.repeat * 8));
channel.status = ATTACK;
channel.adsrVolume = 0;
}
else
{
// uint8* repeat = reader.GetRepeat();
// channel.repeat = (repeat - m_ram) / 8;
}
int16 readSample = 0;
reader.SetPitch(m_baseSamplingRate, channel.pitch);
reader.GetSamples(&readSample, 1, sampleRate);
channel.current = (reader.GetCurrent() - m_ram);
//Mix samples
UpdateAdsr(channel);
int32 inputSample = static_cast<int32>(readSample);
//Mix adsrVolume
{
int64 result = (static_cast<int64>(inputSample) * static_cast<int64>(channel.adsrVolume)) / static_cast<int64>(MAX_ADSR_VOLUME);
inputSample = static_cast<int32>(result);
}
SampleMixer()(inputSample, channel.volumeLeft, samples + 0);
SampleMixer()(inputSample, channel.volumeRight, samples + 1);
//Mix in reverb if enabled for this channel
if(m_channelReverb.f & (1 << i))
{
SampleMixer()(inputSample, channel.volumeLeft, reverbSample + 0);
SampleMixer()(inputSample, channel.volumeRight, reverbSample + 1);
}
}
//Update reverb
{
//Feed samples to FIR filter
if(m_reverbTicks & 1)
{
if(m_ctrl & 0x80)
{
//IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
//IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
//IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
//IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
float input_sample_l = static_cast<float>(reverbSample[0]) * 0.5f;
float input_sample_r = static_cast<float>(reverbSample[1]) * 0.5f;
float irr_coef = GetReverbCoef(IIR_COEF);
float in_coef_l = GetReverbCoef(IN_COEF_L);
float in_coef_r = GetReverbCoef(IN_COEF_R);
float iir_input_a0 = GetReverbSample(GetReverbOffset(ACC_SRC_A0)) * irr_coef + input_sample_l * in_coef_l;
float iir_input_a1 = GetReverbSample(GetReverbOffset(ACC_SRC_A1)) * irr_coef + input_sample_r * in_coef_r;
float iir_input_b0 = GetReverbSample(GetReverbOffset(ACC_SRC_B0)) * irr_coef + input_sample_l * in_coef_l;
float iir_input_b1 = GetReverbSample(GetReverbOffset(ACC_SRC_B1)) * irr_coef + input_sample_r * in_coef_r;
//IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
//IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
//IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
//IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
float iir_alpha = GetReverbCoef(IIR_ALPHA);
float iir_a0 = iir_input_a0 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_A0)) * (1.0f - iir_alpha);
float iir_a1 = iir_input_a1 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_A1)) * (1.0f - iir_alpha);
float iir_b0 = iir_input_b0 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_B0)) * (1.0f - iir_alpha);
float iir_b1 = iir_input_b1 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_B1)) * (1.0f - iir_alpha);
//buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
//buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
//buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
//buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
SetReverbSample(GetReverbOffset(IIR_DEST_A0) + 2, iir_a0);
SetReverbSample(GetReverbOffset(IIR_DEST_A1) + 2, iir_a1);
SetReverbSample(GetReverbOffset(IIR_DEST_B0) + 2, iir_b0);
SetReverbSample(GetReverbOffset(IIR_DEST_B1) + 2, iir_b1);
//ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
// buffer[ACC_SRC_B0] * ACC_COEF_B +
// buffer[ACC_SRC_C0] * ACC_COEF_C +
// buffer[ACC_SRC_D0] * ACC_COEF_D;
//ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
// buffer[ACC_SRC_B1] * ACC_COEF_B +
// buffer[ACC_SRC_C1] * ACC_COEF_C +
// buffer[ACC_SRC_D1] * ACC_COEF_D;
float acc_coef_a = GetReverbCoef(ACC_COEF_A);
float acc_coef_b = GetReverbCoef(ACC_COEF_B);
float acc_coef_c = GetReverbCoef(ACC_COEF_C);
float acc_coef_d = GetReverbCoef(ACC_COEF_D);
float acc0 =
GetReverbSample(GetReverbOffset(ACC_SRC_A0)) * acc_coef_a +
GetReverbSample(GetReverbOffset(ACC_SRC_B0)) * acc_coef_b +
GetReverbSample(GetReverbOffset(ACC_SRC_C0)) * acc_coef_c +
GetReverbSample(GetReverbOffset(ACC_SRC_D0)) * acc_coef_d;
float acc1 =
GetReverbSample(GetReverbOffset(ACC_SRC_A1)) * acc_coef_a +
GetReverbSample(GetReverbOffset(ACC_SRC_B1)) * acc_coef_b +
GetReverbSample(GetReverbOffset(ACC_SRC_C1)) * acc_coef_c +
GetReverbSample(GetReverbOffset(ACC_SRC_D1)) * acc_coef_d;
//FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
//FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
//FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
//FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
float fb_a0 = GetReverbSample(GetReverbOffset(MIX_DEST_A0) - GetReverbOffset(FB_SRC_A));
float fb_a1 = GetReverbSample(GetReverbOffset(MIX_DEST_A1) - GetReverbOffset(FB_SRC_A));
float fb_b0 = GetReverbSample(GetReverbOffset(MIX_DEST_B0) - GetReverbOffset(FB_SRC_B));
float fb_b1 = GetReverbSample(GetReverbOffset(MIX_DEST_B1) - GetReverbOffset(FB_SRC_B));
//buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
//buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
//buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
//buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
float fb_alpha = GetReverbCoef(FB_ALPHA);
float fb_x = GetReverbCoef(FB_X);
SetReverbSample(GetReverbOffset(MIX_DEST_A0), acc0 - fb_a0 * fb_alpha);
SetReverbSample(GetReverbOffset(MIX_DEST_A1), acc1 - fb_a1 * fb_alpha);
SetReverbSample(GetReverbOffset(MIX_DEST_B0), (fb_alpha * acc0) - fb_a0 * -fb_alpha - fb_b0 * fb_x);
SetReverbSample(GetReverbOffset(MIX_DEST_B1), (fb_alpha * acc1) - fb_a1 * -fb_alpha - fb_b1 * fb_x);
}
m_reverbCurrAddr += 2;
if(m_reverbCurrAddr >= m_ramSize)
{
m_reverbCurrAddr = m_reverbWorkAddr;
}
}
if(m_reverbWorkAddr != 0)
{
float sampleL = 0.333f * (GetReverbSample(GetReverbOffset(MIX_DEST_A0)) + GetReverbSample(GetReverbOffset(MIX_DEST_B0)));
float sampleR = 0.333f * (GetReverbSample(GetReverbOffset(MIX_DEST_A1)) + GetReverbSample(GetReverbOffset(MIX_DEST_B1)));
{
int16* output = samples + 0;
int32 resultSample = static_cast<int32>(sampleL) + static_cast<int32>(*output);
resultSample = max<int32>(resultSample, SHRT_MIN);
resultSample = min<int32>(resultSample, SHRT_MAX);
*output = static_cast<int16>(resultSample);
}
{
int16* output = samples + 1;
int32 resultSample = static_cast<int32>(sampleR) + static_cast<int32>(*output);
resultSample = max<int32>(resultSample, SHRT_MIN);
resultSample = min<int32>(resultSample, SHRT_MAX);
*output = static_cast<int16>(resultSample);
}
}
m_reverbTicks++;
}
samples += 2;
}
}
uint16 CSpu::ReadRegister(uint32 address)
@ -392,24 +123,25 @@ uint16 CSpu::ReadRegister(uint32 address)
return m_status0;
break;
case REVERB_0:
return m_channelReverb.h0;
return m_base.GetChannelReverb().h0;
break;
case REVERB_1:
return m_channelReverb.h1;
return m_base.GetChannelReverb().h1;
break;
case BUFFER_ADDR:
return static_cast<int16>(m_bufferAddr / 8);
return static_cast<int16>(m_base.GetTransferAddress() / 8);
break;
}
}
else
{
unsigned int channel = (address - SPU_BEGIN) / 0x10;
unsigned int channelId = (address - SPU_BEGIN) / 0x10;
unsigned int registerId = address & 0x0F;
CSpuBase::CHANNEL& channel(m_base.GetChannel(channelId));
switch(registerId)
{
case CH_ADSR_VOLUME:
return static_cast<uint16>(m_channel[channel].adsrVolume >> 16);
return static_cast<uint16>(channel.adsrVolume >> 16);
break;
}
}
@ -424,7 +156,7 @@ void CSpu::WriteRegister(uint32 address, uint16 value)
if(address >= REVERB_START && address < REVERB_END)
{
uint32 registerId = (address - REVERB_START) / 2;
m_reverb[registerId] = value;
m_base.SetReverbParam(registerId, value);
}
else if(address >= SPU_GENERAL_BASE)
{
@ -437,126 +169,74 @@ void CSpu::WriteRegister(uint32 address, uint16 value)
m_status0 = value;
break;
case SPU_DATA:
assert((m_bufferAddr + 1) < m_ramSize);
*reinterpret_cast<uint16*>(&m_ram[m_bufferAddr]) = value;
m_bufferAddr += 2;
m_base.WriteWord(value);
break;
case VOICE_ON_0:
SendKeyOn(value);
m_base.SendKeyOn(value);
break;
case VOICE_ON_1:
SendKeyOn(value << 16);
m_base.SendKeyOn(value << 16);
break;
case VOICE_OFF_0:
SendKeyOff(value);
m_base.SendKeyOff(value);
break;
case VOICE_OFF_1:
SendKeyOff(value << 16);
m_base.SendKeyOff(value << 16);
break;
case CHANNEL_ON_0:
m_channelOn.h0 = value;
m_base.SetChannelOnLo(value);
break;
case CHANNEL_ON_1:
m_channelOn.h1 = value;
m_base.SetChannelOnHi(value);
break;
case REVERB_0:
m_channelReverb.h0 = value;
m_base.SetChannelReverbLo(value);
break;
case REVERB_1:
m_channelReverb.h1 = value;
m_base.SetChannelReverbHi(value);
break;
case REVERB_WORK:
m_reverbWorkAddr = value * 8;
m_reverbCurrAddr = m_reverbWorkAddr;
m_base.SetReverbWorkAddressStart(value * 8);
m_base.SetReverbCurrentAddress(value * 8);
break;
case BUFFER_ADDR:
m_bufferAddr = value * 8;
m_base.SetTransferAddress(value * 8);
break;
}
}
else
{
unsigned int channel = (address - SPU_BEGIN) / 0x10;
unsigned int channelId = (address - SPU_BEGIN) / 0x10;
unsigned int registerId = address & 0x0F;
CSpuBase::CHANNEL& channel(m_base.GetChannel(channelId));
switch(registerId)
{
case CH_VOL_LEFT:
m_channel[channel].volumeLeft <<= value;
channel.volumeLeft <<= value;
break;
case CH_VOL_RIGHT:
m_channel[channel].volumeRight <<= value;
channel.volumeRight <<= value;
break;
case CH_PITCH:
m_channel[channel].pitch = value;
channel.pitch = value;
break;
case CH_ADDRESS:
m_channel[channel].address = value;
m_channel[channel].current = value * 8;
channel.address = value * 8;
channel.current = value * 8;
break;
case CH_ADSR_LEVEL:
m_channel[channel].adsrLevel <<= value;
channel.adsrLevel <<= value;
break;
case CH_ADSR_RATE:
m_channel[channel].adsrRate <<= value;
channel.adsrRate <<= value;
break;
case CH_REPEAT:
m_channel[channel].repeat = value;
channel.repeat = value;
break;
}
}
}
uint32 CSpu::ReceiveDma(uint8* buffer, uint32 blockSize, uint32 blockAmount)
{
#ifdef _DEBUG
CLog::GetInstance().Print(LOG_NAME, "Receiving DMA transfer to 0x%0.8X. Size = 0x%0.8X bytes.\r\n",
m_bufferAddr, blockSize * blockAmount);
#endif
unsigned int blocksTransfered = 0;
for(unsigned int i = 0; i < blockAmount; i++)
{
uint32 copySize = min<uint32>(m_ramSize - m_bufferAddr, blockSize);
memcpy(m_ram + m_bufferAddr, buffer, copySize);
m_bufferAddr += blockSize;
m_bufferAddr &= m_ramSize - 1;
buffer += blockSize;
blocksTransfered++;
}
return blocksTransfered;
}
void CSpu::SendKeyOn(uint32 channels)
{
for(unsigned int i = 0; i < MAX_CHANNEL; i++)
{
CHANNEL& channel = m_channel[i];
if(channels & (1 << i))
{
channel.status = KEY_ON;
}
}
}
void CSpu::SendKeyOff(uint32 channels)
{
for(unsigned int i = 0; i < MAX_CHANNEL; i++)
{
CHANNEL& channel = m_channel[i];
if(channels & (1 << i))
{
if(channel.status == STOPPED) continue;
if(channel.status == KEY_ON)
{
channel.status = STOPPED;
}
else
{
channel.status = RELEASE;
}
}
}
}
void CSpu::DisassembleRead(uint32 address)
{
if(address >= SPU_GENERAL_BASE)
@ -621,335 +301,3 @@ void CSpu::DisassembleWrite(uint32 address, uint16 value)
}
}
}
uint32 CSpu::GetAdsrDelta(unsigned int index) const
{
return m_adsrLogTable[index + 32];
}
float CSpu::GetReverbSample(uint32 address) const
{
uint32 absoluteAddress = m_reverbCurrAddr + address;
while(absoluteAddress >= m_ramSize)
{
absoluteAddress -= m_ramSize;
absoluteAddress += m_reverbWorkAddr;
}
return static_cast<float>(*reinterpret_cast<int16*>(m_ram + absoluteAddress));
}
void CSpu::SetReverbSample(uint32 address, float value)
{
uint32 absoluteAddress = m_reverbCurrAddr + address;
while(absoluteAddress >= m_ramSize)
{
absoluteAddress -= m_ramSize;
absoluteAddress += m_reverbWorkAddr;
}
assert(absoluteAddress < m_ramSize);
value = max<float>(value, SHRT_MIN);
value = min<float>(value, SHRT_MAX);
int16 intValue = static_cast<int16>(value);
*reinterpret_cast<int16*>(m_ram + absoluteAddress) = intValue;
}
uint32 CSpu::GetReverbOffset(unsigned int registerId) const
{
uint16 value = m_reverb[registerId];
return value * 8;
}
float CSpu::GetReverbCoef(unsigned int registerId) const
{
int16 value = m_reverb[registerId];
return static_cast<float>(value) / static_cast<float>(0x8000);
}
void CSpu::UpdateAdsr(CHANNEL& channel)
{
static unsigned int logIndex[8] = { 0, 4, 6, 8, 9, 10, 11, 12 };
int64 currentAdsrLevel = channel.adsrVolume;
if(channel.status == ATTACK)
{
if(channel.adsrLevel.attackMode == 0)
{
//Linear mode
currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x10);
}
else
{
if(currentAdsrLevel < 0x60000000)
{
currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x10);
}
else
{
currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x18);
}
}
//Terminasion condition
if(currentAdsrLevel >= MAX_ADSR_VOLUME)
{
channel.status = DECAY;
}
}
else if(channel.status == DECAY)
{
unsigned int decayType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrLevel.decayRate ^ 0x1F)) - 0x18 + logIndex[decayType]);
//Terminasion condition
if(((currentAdsrLevel >> 27) & 0xF) <= channel.adsrLevel.sustainLevel)
{
channel.status = SUSTAIN;
}
}
else if(channel.status == SUSTAIN)
{
if(channel.adsrRate.sustainDirection == 0)
{
//Increment
if(channel.adsrRate.sustainMode == 0)
{
currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x10);
}
else
{
if(currentAdsrLevel < 0x60000000)
{
currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x10);
}
else
{
currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x18);
}
}
}
else
{
//Decrement
if(channel.adsrRate.sustainMode == 0)
{
//Linear
currentAdsrLevel -= GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x0F);
}
else
{
unsigned int sustainType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
currentAdsrLevel -= GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x1B + logIndex[sustainType]);
}
}
}
else if(channel.status == RELEASE)
{
if(channel.adsrRate.releaseMode == 0)
{
//Linear
currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrRate.releaseRate ^ 0x1F)) - 0x0C);
}
else
{
unsigned int releaseType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrRate.releaseRate ^ 0x1F)) - 0x18 + logIndex[releaseType]);
}
if(currentAdsrLevel <= 0)
{
channel.status = STOPPED;
}
}
currentAdsrLevel = min<int64>(currentAdsrLevel, MAX_ADSR_VOLUME);
currentAdsrLevel = max<int64>(currentAdsrLevel, 0);
channel.adsrVolume = static_cast<uint32>(currentAdsrLevel);
}
///////////////////////////////////////////////////////
// CSampleReader
///////////////////////////////////////////////////////
CSpu::CSampleReader::CSampleReader() :
m_nextSample(NULL)
{
Reset();
}
CSpu::CSampleReader::~CSampleReader()
{
}
void CSpu::CSampleReader::Reset()
{
m_sourceSamplingRate = 0;
m_nextSample = NULL;
m_repeat = NULL;
memset(m_buffer, 0, sizeof(m_buffer));
m_pitch = 0;
m_currentTime = 0;
m_dstTime = 0;
m_s1 = 0;
m_s2 = 0;
m_done = false;
m_nextValid = false;
}
void CSpu::CSampleReader::SetParams(uint8* address, uint8* repeat)
{
m_currentTime = 0;
m_dstTime = 0;
m_nextSample = address;
m_repeat = repeat;
m_s1 = 0;
m_s2 = 0;
m_nextValid = false;
m_done = false;
AdvanceBuffer();
}
void CSpu::CSampleReader::SetPitch(uint32 baseSamplingRate, uint16 pitch)
{
m_sourceSamplingRate = baseSamplingRate * pitch / 4096;
}
void CSpu::CSampleReader::GetSamples(int16* samples, unsigned int sampleCount, unsigned int destSamplingRate)
{
assert(m_nextSample != NULL);
double dstTimeDelta = 1.0 / static_cast<double>(destSamplingRate);
for(unsigned int i = 0; i < sampleCount; i++)
{
samples[i] = GetSample(m_dstTime);
m_dstTime += dstTimeDelta;
}
}
int16 CSpu::CSampleReader::GetSample(double time)
{
time -= m_currentTime;
double sample = time * static_cast<double>(GetSamplingRate());
double sampleInt = 0;
double alpha = modf(sample, &sampleInt);
unsigned int sampleIndex = static_cast<int>(sampleInt);
int16 currentSample = m_buffer[sampleIndex];
int16 nextSample = m_buffer[sampleIndex + 1];
double resultSample =
(static_cast<double>(currentSample) * (1 - alpha)) + (static_cast<double>(nextSample) * alpha);
if(sampleIndex >= BUFFER_SAMPLES)
{
AdvanceBuffer();
}
return static_cast<int16>(resultSample);
}
void CSpu::CSampleReader::AdvanceBuffer()
{
if(m_nextValid)
{
memmove(m_buffer, m_buffer + BUFFER_SAMPLES, sizeof(int16) * BUFFER_SAMPLES);
UnpackSamples(m_buffer + BUFFER_SAMPLES);
m_currentTime += GetBufferStep();
}
else
{
assert(m_currentTime == 0);
UnpackSamples(m_buffer);
UnpackSamples(m_buffer + BUFFER_SAMPLES);
m_nextValid = true;
}
}
void CSpu::CSampleReader::UnpackSamples(int16* dst)
{
double workBuffer[28];
//Read header
uint8 shiftFactor = m_nextSample[0] & 0xF;
uint8 predictNumber = m_nextSample[0] >> 4;
uint8 flags = m_nextSample[1];
assert(predictNumber < 5);
if(m_done)
{
memset(m_buffer, 0, sizeof(int16) * BUFFER_SAMPLES);
return;
}
//Get intermediate values
{
unsigned int workBufferPtr = 0;
for(unsigned int i = 2; i < 16; i++)
{
uint8 sampleByte = m_nextSample[i];
int16 firstSample = ((sampleByte & 0x0F) << 12);
int16 secondSample = ((sampleByte & 0xF0) << 8);
firstSample >>= shiftFactor;
secondSample >>= shiftFactor;
workBuffer[workBufferPtr++] = firstSample;
workBuffer[workBufferPtr++] = secondSample;
}
}
//Generate PCM samples
{
double predictorTable[5][2] =
{
{ 0.0, 0.0 },
{ 60.0 / 64.0, 0.0 },
{ 115.0 / 64.0, -52.0 / 64.0 },
{ 98.0 / 64.0, -55.0 / 64.0 },
{ 122.0 / 64.0, -60.0 / 64.0 },
};
for(unsigned int i = 0; i < 28; i++)
{
workBuffer[i] = workBuffer[i] +
m_s1 * predictorTable[predictNumber][0] +
m_s2 * predictorTable[predictNumber][1];
m_s2 = m_s1;
m_s1 = workBuffer[i];
dst[i] = static_cast<int16>(workBuffer[i] + 0.5);
}
}
if(flags & 0x04)
{
m_repeat = m_nextSample;
}
m_nextSample += 0x10;
if(flags & 0x01)
{
if(flags == 0x03)
{
m_nextSample = m_repeat;
}
else
{
m_done = true;
}
}
}
uint8* CSpu::CSampleReader::GetRepeat() const
{
return m_repeat;
}
uint8* CSpu::CSampleReader::GetCurrent() const
{
return m_nextSample;
}
double CSpu::CSampleReader::GetSamplingRate() const
{
return m_sourceSamplingRate;
}
double CSpu::CSampleReader::GetBufferStep() const
{
return static_cast<double>(BUFFER_SAMPLES) / static_cast<double>(GetSamplingRate());
}
double CSpu::CSampleReader::GetNextTime() const
{
return m_currentTime + GetBufferStep();
}

View File

@ -1,313 +1,115 @@
#ifndef _SPU_H_
#define _SPU_H_
#ifndef _IOP_SPU_H_
#define _IOP_SPU_H_
#include "Types.h"
#include "BasicUnions.h"
#include "convertible.h"
#include <boost/static_assert.hpp>
#include "Iop_SpuBase.h"
class CSpu
namespace Iop
{
public:
struct ADSR_LEVEL : public convertible<uint16>
{
unsigned int sustainLevel : 4;
unsigned int decayRate : 4;
unsigned int attackRate : 7;
unsigned int attackMode : 1;
};
BOOST_STATIC_ASSERT(sizeof(ADSR_LEVEL) >= sizeof(uint16));
struct ADSR_RATE : public convertible<uint16>
{
unsigned int releaseRate : 5;
unsigned int releaseMode : 1;
unsigned int sustainRate : 7;
unsigned int reserved0 : 1;
unsigned int sustainDirection : 1;
unsigned int sustainMode : 1;
};
BOOST_STATIC_ASSERT(sizeof(ADSR_RATE) >= sizeof(uint16));
struct CHANNEL_VOLUME : public convertible<uint16>
{
union
{
struct
{
unsigned int unused0 : 15;
unsigned int mode : 1;
} mode;
struct
{
unsigned int volume : 14;
unsigned int phase : 1;
unsigned int mode : 1;
} volume;
struct
{
unsigned int volume : 7;
unsigned int unused0 : 5;
unsigned int phase : 1;
unsigned int decrease : 1;
unsigned int slope : 1;
unsigned int mode : 1;
} sweep;
};
};
BOOST_STATIC_ASSERT(sizeof(CHANNEL_VOLUME) >= sizeof(uint16));
struct CHANNEL
{
CHANNEL_VOLUME volumeLeft;
CHANNEL_VOLUME volumeRight;
uint16 pitch;
uint32 address;
ADSR_LEVEL adsrLevel;
ADSR_RATE adsrRate;
uint32 adsrVolume;
uint32 repeat;
uint16 status;
uint32 current;
};
CSpu(uint8*, uint32);
virtual ~CSpu();
void Reset();
void SetBaseSamplingRate(uint32);
uint16 ReadRegister(uint32);
void WriteRegister(uint32, uint16);
uint32 GetTransferAddress() const;
void SetTransferAddress(uint32);
uint32 GetChannelOn() const;
uint32 GetChannelReverb() const;
CHANNEL& GetChannel(unsigned int);
void SendKeyOn(uint32);
void SendKeyOff(uint32);
uint32 ReceiveDma(uint8*, uint32, uint32);
void Render(int16*, unsigned int, unsigned int);
enum
{
SPU_BEGIN = 0x1F801C00,
SPU_END = 0x1F801DFF
};
enum
{
MAX_CHANNEL = 24
};
enum
{
CH0_BASE = 0x1F801C00,
CH1_BASE = 0x1F801C10,
CH2_BASE = 0x1F801C20,
CH3_BASE = 0x1F801C30,
CH4_BASE = 0x1F801C40,
CH5_BASE = 0x1F801C50,
CH6_BASE = 0x1F801C60,
CH7_BASE = 0x1F801C70,
CH8_BASE = 0x1F801C80,
CH9_BASE = 0x1F801C90,
CH10_BASE = 0x1F801CA0,
CH11_BASE = 0x1F801CB0,
CH12_BASE = 0x1F801CC0,
CH13_BASE = 0x1F801CD0,
CH14_BASE = 0x1F801CE0,
CH15_BASE = 0x1F801CF0,
CH16_BASE = 0x1F801D00,
CH17_BASE = 0x1F801D10,
CH18_BASE = 0x1F801D20,
CH19_BASE = 0x1F801D30,
CH20_BASE = 0x1F801D40,
CH21_BASE = 0x1F801D50,
CH22_BASE = 0x1F801D60,
CH23_BASE = 0x1F801D70,
};
enum
{
CH_VOL_LEFT = 0x00,
CH_VOL_RIGHT = 0x02,
CH_PITCH = 0x04,
CH_ADDRESS = 0x06,
CH_ADSR_LEVEL = 0x08,
CH_ADSR_RATE = 0x0A,
CH_ADSR_VOLUME = 0x0C,
CH_REPEAT = 0x0E
};
enum
{
SPU_GENERAL_BASE = 0x1F801D80,
};
enum
{
MAIN_VOL_LEFT = 0x1F801D80,
MAIN_VOL_RIGHT = 0x1F801D82,
REVERB_LEFT = 0x1F801D84,
REVERB_RIGHT = 0x1F801D86,
VOICE_ON_0 = 0x1F801D88,
VOICE_ON_1 = 0x1F801D8A,
VOICE_OFF_0 = 0x1F801D8C,
VOICE_OFF_1 = 0x1F801D8E,
FM_0 = 0x1F801D90,
FM_1 = 0x1F801D92,
NOISE_0 = 0x1F801D94,
NOISE_1 = 0x1F801D96,
REVERB_0 = 0x1F801D98,
REVERB_1 = 0x1F801D9A,
CHANNEL_ON_0 = 0x1F801D9C,
CHANNEL_ON_1 = 0x1F801D9E,
REVERB_WORK = 0x1F801DA2,
IRQ_ADDR = 0x1F801DA4,
BUFFER_ADDR = 0x1F801DA6,
SPU_DATA = 0x1F801DA8,
SPU_CTRL0 = 0x1F801DAA,
SPU_STATUS0 = 0x1F801DAC,
SPU_STATUS1 = 0x1F801DAE,
CD_VOL_LEFT = 0x1F801DB0,
CD_VOL_RIGHT = 0x1F801DB2,
EXT_VOL_LEFT = 0x1F801DB4,
EXT_VOL_RIGHT = 0x1F801DB6,
REVERB_START = 0x1F801DC0,
REVERB_END = 0x1F801E00,
};
enum
{
FB_SRC_A,
FB_SRC_B,
IIR_ALPHA,
ACC_COEF_A,
ACC_COEF_B,
ACC_COEF_C,
ACC_COEF_D,
IIR_COEF,
FB_ALPHA,
FB_X,
IIR_DEST_A0,
IIR_DEST_A1,
ACC_SRC_A0,
ACC_SRC_A1,
ACC_SRC_B0,
ACC_SRC_B1,
IIR_SRC_A0,
IIR_SRC_A1,
IIR_DEST_B0,
IIR_DEST_B1,
ACC_SRC_C0,
ACC_SRC_C1,
ACC_SRC_D0,
ACC_SRC_D1,
IIR_SRC_B1,
IIR_SRC_B0,
MIX_DEST_A0,
MIX_DEST_A1,
MIX_DEST_B0,
MIX_DEST_B1,
IN_COEF_L,
IN_COEF_R
};
enum
{
REVERB_REG_COUNT = (REVERB_END - REVERB_START) / 2,
};
enum CHANNEL_STATUS
{
STOPPED = 0,
KEY_ON = 1,
ATTACK,
DECAY,
SUSTAIN,
RELEASE,
};
private:
class CSampleReader
class CSpu
{
public:
CSampleReader();
virtual ~CSampleReader();
CSpu(CSpuBase&);
virtual ~CSpu();
void Reset();
void Reset();
void SetParams(uint8*, uint8*);
void SetPitch(uint32, uint16);
void GetSamples(int16*, unsigned int, unsigned int);
uint8* GetRepeat() const;
uint8* GetCurrent() const;
uint16 ReadRegister(uint32);
void WriteRegister(uint32, uint16);
private:
enum
{
BUFFER_SAMPLES = 28,
SPU_BEGIN = 0x1F801C00,
SPU_END = 0x1F801DFF
};
void UnpackSamples(int16*);
void AdvanceBuffer();
int16 GetSample(double);
double GetNextTime() const;
double GetBufferStep() const;
double GetSamplingRate() const;
enum
{
CH0_BASE = 0x1F801C00,
CH1_BASE = 0x1F801C10,
CH2_BASE = 0x1F801C20,
CH3_BASE = 0x1F801C30,
CH4_BASE = 0x1F801C40,
CH5_BASE = 0x1F801C50,
CH6_BASE = 0x1F801C60,
CH7_BASE = 0x1F801C70,
CH8_BASE = 0x1F801C80,
CH9_BASE = 0x1F801C90,
CH10_BASE = 0x1F801CA0,
CH11_BASE = 0x1F801CB0,
CH12_BASE = 0x1F801CC0,
CH13_BASE = 0x1F801CD0,
CH14_BASE = 0x1F801CE0,
CH15_BASE = 0x1F801CF0,
CH16_BASE = 0x1F801D00,
CH17_BASE = 0x1F801D10,
CH18_BASE = 0x1F801D20,
CH19_BASE = 0x1F801D30,
CH20_BASE = 0x1F801D40,
CH21_BASE = 0x1F801D50,
CH22_BASE = 0x1F801D60,
CH23_BASE = 0x1F801D70,
};
unsigned int m_sourceSamplingRate;
uint8* m_nextSample;
uint8* m_repeat;
int16 m_buffer[BUFFER_SAMPLES * 2];
uint16 m_pitch;
double m_currentTime;
double m_dstTime;
double m_s1;
double m_s2;
bool m_done;
bool m_nextValid;
enum
{
CH_VOL_LEFT = 0x00,
CH_VOL_RIGHT = 0x02,
CH_PITCH = 0x04,
CH_ADDRESS = 0x06,
CH_ADSR_LEVEL = 0x08,
CH_ADSR_RATE = 0x0A,
CH_ADSR_VOLUME = 0x0C,
CH_REPEAT = 0x0E
};
enum
{
SPU_GENERAL_BASE = 0x1F801D80,
};
enum
{
MAIN_VOL_LEFT = 0x1F801D80,
MAIN_VOL_RIGHT = 0x1F801D82,
REVERB_LEFT = 0x1F801D84,
REVERB_RIGHT = 0x1F801D86,
VOICE_ON_0 = 0x1F801D88,
VOICE_ON_1 = 0x1F801D8A,
VOICE_OFF_0 = 0x1F801D8C,
VOICE_OFF_1 = 0x1F801D8E,
FM_0 = 0x1F801D90,
FM_1 = 0x1F801D92,
NOISE_0 = 0x1F801D94,
NOISE_1 = 0x1F801D96,
REVERB_0 = 0x1F801D98,
REVERB_1 = 0x1F801D9A,
CHANNEL_ON_0 = 0x1F801D9C,
CHANNEL_ON_1 = 0x1F801D9E,
REVERB_WORK = 0x1F801DA2,
IRQ_ADDR = 0x1F801DA4,
BUFFER_ADDR = 0x1F801DA6,
SPU_DATA = 0x1F801DA8,
SPU_CTRL0 = 0x1F801DAA,
SPU_STATUS0 = 0x1F801DAC,
SPU_STATUS1 = 0x1F801DAE,
CD_VOL_LEFT = 0x1F801DB0,
CD_VOL_RIGHT = 0x1F801DB2,
EXT_VOL_LEFT = 0x1F801DB4,
EXT_VOL_RIGHT = 0x1F801DB6,
REVERB_START = 0x1F801DC0,
REVERB_END = 0x1F801E00,
};
private:
void DisassembleRead(uint32);
void DisassembleWrite(uint32, uint16);
CSpuBase& m_base;
uint16 m_ctrl;
uint16 m_status0;
uint16 m_status1;
};
enum
{
MAX_ADSR_VOLUME = 0x7FFFFFFF,
};
void DisassembleRead(uint32);
void DisassembleWrite(uint32, uint16);
void UpdateAdsr(CHANNEL&);
uint32 GetAdsrDelta(unsigned int) const;
float GetReverbSample(uint32) const;
void SetReverbSample(uint32, float);
uint32 GetReverbOffset(unsigned int) const;
float GetReverbCoef(unsigned int) const;
uint32 m_baseSamplingRate;
uint32 m_bufferAddr;
uint16 m_ctrl;
uint16 m_status0;
uint16 m_status1;
UNION32_16 m_channelOn;
UNION32_16 m_channelReverb;
uint32 m_reverbWorkAddr;
uint32 m_reverbCurrAddr;
int m_reverbTicks;
uint16 m_reverb[REVERB_REG_COUNT];
uint8* m_ram;
uint32 m_ramSize;
CHANNEL m_channel[MAX_CHANNEL];
CSampleReader m_reader[MAX_CHANNEL];
uint32 m_adsrLogTable[160];
};
}
#endif

696
Source/iop/Iop_SpuBase.cpp Normal file
View File

@ -0,0 +1,696 @@
#include <cassert>
#include "Log.h"
#include "Iop_SpuBase.h"
using namespace Iop;
using namespace std;
#define INIT_SAMPLE_RATE (44100)
#define LOG_NAME ("iop_spubase")
CSpuBase::CSpuBase(uint8* ram, uint32 ramSize) :
m_ram(ram),
m_ramSize(ramSize)
{
Reset();
//Init log table for ADSR
memset(m_adsrLogTable, 0, sizeof(m_adsrLogTable));
uint32 value = 3;
uint32 columnIncrement = 1;
uint32 column = 0;
for(unsigned int i = 32; i < 160; i++)
{
if(value < 0x3FFFFFFF)
{
value += columnIncrement;
column++;
if(column == 5)
{
column = 1;
columnIncrement *= 2;
}
}
else
{
value = 0x3FFFFFFF;
}
m_adsrLogTable[i] = value;
}
}
CSpuBase::~CSpuBase()
{
}
void CSpuBase::Reset()
{
m_channelOn.f = 0;
m_channelReverb.f = 0;
m_reverbTicks = 0;
m_bufferAddr = 0;
m_reverbCurrAddr = 0;
m_reverbWorkAddrStart = 0;
m_reverbWorkAddrEnd = 0x7FFFF;
m_baseSamplingRate = 44100;
memset(m_channel, 0, sizeof(m_channel));
memset(m_reverb, 0, sizeof(m_reverb));
}
void CSpuBase::SetBaseSamplingRate(uint32 samplingRate)
{
m_baseSamplingRate = samplingRate;
}
uint32 CSpuBase::GetTransferAddress() const
{
return m_bufferAddr;
}
void CSpuBase::SetTransferAddress(uint32 value)
{
m_bufferAddr = value & (m_ramSize - 1);
}
UNION32_16 CSpuBase::GetChannelOn() const
{
return m_channelOn;
}
UNION32_16 CSpuBase::GetChannelReverb() const
{
return m_channelReverb;
}
CSpuBase::CHANNEL& CSpuBase::GetChannel(unsigned int channelNumber)
{
assert(channelNumber < MAX_CHANNEL);
return m_channel[channelNumber];
}
void CSpuBase::SendKeyOn(uint32 channels)
{
for(unsigned int i = 0; i < MAX_CHANNEL; i++)
{
CHANNEL& channel = m_channel[i];
if(channels & (1 << i))
{
channel.status = KEY_ON;
}
}
}
void CSpuBase::SendKeyOff(uint32 channels)
{
for(unsigned int i = 0; i < MAX_CHANNEL; i++)
{
CHANNEL& channel = m_channel[i];
if(channels & (1 << i))
{
if(channel.status == STOPPED) continue;
if(channel.status == KEY_ON)
{
channel.status = STOPPED;
}
else
{
channel.status = RELEASE;
}
}
}
}
void CSpuBase::SetReverbWorkAddressStart(uint32 address)
{
m_reverbWorkAddrStart = address;
}
void CSpuBase::SetReverbWorkAddressEnd(uint32 address)
{
assert((address & 0xFFFF) == 0xFFFF);
m_reverbWorkAddrEnd = address;
}
void CSpuBase::SetReverbCurrentAddress(uint32 address)
{
m_reverbCurrAddr = address;
}
uint32 CSpuBase::ReceiveDma(uint8* buffer, uint32 blockSize, uint32 blockAmount)
{
#ifdef _DEBUG
CLog::GetInstance().Print(LOG_NAME, "Receiving DMA transfer to 0x%0.8X. Size = 0x%0.8X bytes.\r\n",
m_bufferAddr, blockSize * blockAmount);
#endif
unsigned int blocksTransfered = 0;
for(unsigned int i = 0; i < blockAmount; i++)
{
uint32 copySize = min<uint32>(m_ramSize - m_bufferAddr, blockSize);
memcpy(m_ram + m_bufferAddr, buffer, copySize);
m_bufferAddr += blockSize;
m_bufferAddr &= m_ramSize - 1;
buffer += blockSize;
blocksTransfered++;
}
return blocksTransfered;
}
void CSpuBase::WriteWord(uint16 value)
{
assert((m_bufferAddr + 1) < m_ramSize);
*reinterpret_cast<uint16*>(&m_ram[m_bufferAddr]) = value;
m_bufferAddr += 2;
}
/*
void CSpu::Render(int16* samples, unsigned int sampleCount, unsigned int sampleRate)
{
struct SampleMixer
{
void operator() (int32 inputSample, const CHANNEL_VOLUME& volume, int16* output) const
{
if(!volume.mode.mode)
{
inputSample = (inputSample * static_cast<int32>(volume.volume.volume)) / 0x3FFF;
}
int32 resultSample = inputSample + static_cast<int32>(*output);
resultSample = max<int32>(resultSample, SHRT_MIN);
resultSample = min<int32>(resultSample, SHRT_MAX);
*output = static_cast<int16>(resultSample);
}
};
assert((sampleCount & 0x01) == 0);
//ticks are 44100Hz ticks
unsigned int ticks = sampleCount / 2;
memset(samples, 0, sizeof(int16) * sampleCount);
// int16* bufferTemp = reinterpret_cast<int16*>(_alloca(sizeof(int16) * ticks));
for(unsigned int j = 0; j < ticks; j++)
{
int16 reverbSample[2] = { 0, 0 };
//Update channels
for(unsigned int i = 0; i < 24; i++)
{
CHANNEL& channel(m_channel[i]);
if(channel.status == STOPPED) continue;
CSampleReader& reader(m_reader[i]);
if(channel.status == KEY_ON)
{
reader.SetParams(m_ram + (channel.address * 8), m_ram + (channel.repeat * 8));
channel.status = ATTACK;
channel.adsrVolume = 0;
}
else
{
// uint8* repeat = reader.GetRepeat();
// channel.repeat = (repeat - m_ram) / 8;
}
int16 readSample = 0;
reader.SetPitch(m_baseSamplingRate, channel.pitch);
reader.GetSamples(&readSample, 1, sampleRate);
channel.current = (reader.GetCurrent() - m_ram);
//Mix samples
UpdateAdsr(channel);
int32 inputSample = static_cast<int32>(readSample);
//Mix adsrVolume
{
int64 result = (static_cast<int64>(inputSample) * static_cast<int64>(channel.adsrVolume)) / static_cast<int64>(MAX_ADSR_VOLUME);
inputSample = static_cast<int32>(result);
}
SampleMixer()(inputSample, channel.volumeLeft, samples + 0);
SampleMixer()(inputSample, channel.volumeRight, samples + 1);
//Mix in reverb if enabled for this channel
if(m_channelReverb.f & (1 << i))
{
SampleMixer()(inputSample, channel.volumeLeft, reverbSample + 0);
SampleMixer()(inputSample, channel.volumeRight, reverbSample + 1);
}
}
//Update reverb
{
//Feed samples to FIR filter
if(m_reverbTicks & 1)
{
if(m_ctrl & 0x80)
{
//IIR_INPUT_A0 = buffer[IIR_SRC_A0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
//IIR_INPUT_A1 = buffer[IIR_SRC_A1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
//IIR_INPUT_B0 = buffer[IIR_SRC_B0] * IIR_COEF + INPUT_SAMPLE_L * IN_COEF_L;
//IIR_INPUT_B1 = buffer[IIR_SRC_B1] * IIR_COEF + INPUT_SAMPLE_R * IN_COEF_R;
float input_sample_l = static_cast<float>(reverbSample[0]) * 0.5f;
float input_sample_r = static_cast<float>(reverbSample[1]) * 0.5f;
float irr_coef = GetReverbCoef(IIR_COEF);
float in_coef_l = GetReverbCoef(IN_COEF_L);
float in_coef_r = GetReverbCoef(IN_COEF_R);
float iir_input_a0 = GetReverbSample(GetReverbOffset(ACC_SRC_A0)) * irr_coef + input_sample_l * in_coef_l;
float iir_input_a1 = GetReverbSample(GetReverbOffset(ACC_SRC_A1)) * irr_coef + input_sample_r * in_coef_r;
float iir_input_b0 = GetReverbSample(GetReverbOffset(ACC_SRC_B0)) * irr_coef + input_sample_l * in_coef_l;
float iir_input_b1 = GetReverbSample(GetReverbOffset(ACC_SRC_B1)) * irr_coef + input_sample_r * in_coef_r;
//IIR_A0 = IIR_INPUT_A0 * IIR_ALPHA + buffer[IIR_DEST_A0] * (1.0 - IIR_ALPHA);
//IIR_A1 = IIR_INPUT_A1 * IIR_ALPHA + buffer[IIR_DEST_A1] * (1.0 - IIR_ALPHA);
//IIR_B0 = IIR_INPUT_B0 * IIR_ALPHA + buffer[IIR_DEST_B0] * (1.0 - IIR_ALPHA);
//IIR_B1 = IIR_INPUT_B1 * IIR_ALPHA + buffer[IIR_DEST_B1] * (1.0 - IIR_ALPHA);
float iir_alpha = GetReverbCoef(IIR_ALPHA);
float iir_a0 = iir_input_a0 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_A0)) * (1.0f - iir_alpha);
float iir_a1 = iir_input_a1 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_A1)) * (1.0f - iir_alpha);
float iir_b0 = iir_input_b0 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_B0)) * (1.0f - iir_alpha);
float iir_b1 = iir_input_b1 * iir_alpha + GetReverbSample(GetReverbOffset(IIR_DEST_B1)) * (1.0f - iir_alpha);
//buffer[IIR_DEST_A0 + 1sample] = IIR_A0;
//buffer[IIR_DEST_A1 + 1sample] = IIR_A1;
//buffer[IIR_DEST_B0 + 1sample] = IIR_B0;
//buffer[IIR_DEST_B1 + 1sample] = IIR_B1;
SetReverbSample(GetReverbOffset(IIR_DEST_A0) + 2, iir_a0);
SetReverbSample(GetReverbOffset(IIR_DEST_A1) + 2, iir_a1);
SetReverbSample(GetReverbOffset(IIR_DEST_B0) + 2, iir_b0);
SetReverbSample(GetReverbOffset(IIR_DEST_B1) + 2, iir_b1);
//ACC0 = buffer[ACC_SRC_A0] * ACC_COEF_A +
// buffer[ACC_SRC_B0] * ACC_COEF_B +
// buffer[ACC_SRC_C0] * ACC_COEF_C +
// buffer[ACC_SRC_D0] * ACC_COEF_D;
//ACC1 = buffer[ACC_SRC_A1] * ACC_COEF_A +
// buffer[ACC_SRC_B1] * ACC_COEF_B +
// buffer[ACC_SRC_C1] * ACC_COEF_C +
// buffer[ACC_SRC_D1] * ACC_COEF_D;
float acc_coef_a = GetReverbCoef(ACC_COEF_A);
float acc_coef_b = GetReverbCoef(ACC_COEF_B);
float acc_coef_c = GetReverbCoef(ACC_COEF_C);
float acc_coef_d = GetReverbCoef(ACC_COEF_D);
float acc0 =
GetReverbSample(GetReverbOffset(ACC_SRC_A0)) * acc_coef_a +
GetReverbSample(GetReverbOffset(ACC_SRC_B0)) * acc_coef_b +
GetReverbSample(GetReverbOffset(ACC_SRC_C0)) * acc_coef_c +
GetReverbSample(GetReverbOffset(ACC_SRC_D0)) * acc_coef_d;
float acc1 =
GetReverbSample(GetReverbOffset(ACC_SRC_A1)) * acc_coef_a +
GetReverbSample(GetReverbOffset(ACC_SRC_B1)) * acc_coef_b +
GetReverbSample(GetReverbOffset(ACC_SRC_C1)) * acc_coef_c +
GetReverbSample(GetReverbOffset(ACC_SRC_D1)) * acc_coef_d;
//FB_A0 = buffer[MIX_DEST_A0 - FB_SRC_A];
//FB_A1 = buffer[MIX_DEST_A1 - FB_SRC_A];
//FB_B0 = buffer[MIX_DEST_B0 - FB_SRC_B];
//FB_B1 = buffer[MIX_DEST_B1 - FB_SRC_B];
float fb_a0 = GetReverbSample(GetReverbOffset(MIX_DEST_A0) - GetReverbOffset(FB_SRC_A));
float fb_a1 = GetReverbSample(GetReverbOffset(MIX_DEST_A1) - GetReverbOffset(FB_SRC_A));
float fb_b0 = GetReverbSample(GetReverbOffset(MIX_DEST_B0) - GetReverbOffset(FB_SRC_B));
float fb_b1 = GetReverbSample(GetReverbOffset(MIX_DEST_B1) - GetReverbOffset(FB_SRC_B));
//buffer[MIX_DEST_A0] = ACC0 - FB_A0 * FB_ALPHA;
//buffer[MIX_DEST_A1] = ACC1 - FB_A1 * FB_ALPHA;
//buffer[MIX_DEST_B0] = (FB_ALPHA * ACC0) - FB_A0 * (FB_ALPHA^0x8000) - FB_B0 * FB_X;
//buffer[MIX_DEST_B1] = (FB_ALPHA * ACC1) - FB_A1 * (FB_ALPHA^0x8000) - FB_B1 * FB_X;
float fb_alpha = GetReverbCoef(FB_ALPHA);
float fb_x = GetReverbCoef(FB_X);
SetReverbSample(GetReverbOffset(MIX_DEST_A0), acc0 - fb_a0 * fb_alpha);
SetReverbSample(GetReverbOffset(MIX_DEST_A1), acc1 - fb_a1 * fb_alpha);
SetReverbSample(GetReverbOffset(MIX_DEST_B0), (fb_alpha * acc0) - fb_a0 * -fb_alpha - fb_b0 * fb_x);
SetReverbSample(GetReverbOffset(MIX_DEST_B1), (fb_alpha * acc1) - fb_a1 * -fb_alpha - fb_b1 * fb_x);
}
m_reverbCurrAddr += 2;
if(m_reverbCurrAddr >= m_ramSize)
{
m_reverbCurrAddr = m_reverbWorkAddr;
}
}
if(m_reverbWorkAddr != 0)
{
float sampleL = 0.333f * (GetReverbSample(GetReverbOffset(MIX_DEST_A0)) + GetReverbSample(GetReverbOffset(MIX_DEST_B0)));
float sampleR = 0.333f * (GetReverbSample(GetReverbOffset(MIX_DEST_A1)) + GetReverbSample(GetReverbOffset(MIX_DEST_B1)));
{
int16* output = samples + 0;
int32 resultSample = static_cast<int32>(sampleL) + static_cast<int32>(*output);
resultSample = max<int32>(resultSample, SHRT_MIN);
resultSample = min<int32>(resultSample, SHRT_MAX);
*output = static_cast<int16>(resultSample);
}
{
int16* output = samples + 1;
int32 resultSample = static_cast<int32>(sampleR) + static_cast<int32>(*output);
resultSample = max<int32>(resultSample, SHRT_MIN);
resultSample = min<int32>(resultSample, SHRT_MAX);
*output = static_cast<int16>(resultSample);
}
}
m_reverbTicks++;
}
samples += 2;
}
}
uint32 CSpu::GetAdsrDelta(unsigned int index) const
{
return m_adsrLogTable[index + 32];
}
float CSpu::GetReverbSample(uint32 address) const
{
uint32 absoluteAddress = m_reverbCurrAddr + address;
while(absoluteAddress >= m_ramSize)
{
absoluteAddress -= m_ramSize;
absoluteAddress += m_reverbWorkAddr;
}
return static_cast<float>(*reinterpret_cast<int16*>(m_ram + absoluteAddress));
}
void CSpu::SetReverbSample(uint32 address, float value)
{
uint32 absoluteAddress = m_reverbCurrAddr + address;
while(absoluteAddress >= m_ramSize)
{
absoluteAddress -= m_ramSize;
absoluteAddress += m_reverbWorkAddr;
}
assert(absoluteAddress < m_ramSize);
value = max<float>(value, SHRT_MIN);
value = min<float>(value, SHRT_MAX);
int16 intValue = static_cast<int16>(value);
*reinterpret_cast<int16*>(m_ram + absoluteAddress) = intValue;
}
uint32 CSpu::GetReverbOffset(unsigned int registerId) const
{
uint16 value = m_reverb[registerId];
return value * 8;
}
float CSpu::GetReverbCoef(unsigned int registerId) const
{
int16 value = m_reverb[registerId];
return static_cast<float>(value) / static_cast<float>(0x8000);
}
void CSpu::UpdateAdsr(CHANNEL& channel)
{
static unsigned int logIndex[8] = { 0, 4, 6, 8, 9, 10, 11, 12 };
int64 currentAdsrLevel = channel.adsrVolume;
if(channel.status == ATTACK)
{
if(channel.adsrLevel.attackMode == 0)
{
//Linear mode
currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x10);
}
else
{
if(currentAdsrLevel < 0x60000000)
{
currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x10);
}
else
{
currentAdsrLevel += GetAdsrDelta((channel.adsrLevel.attackRate ^ 0x7F) - 0x18);
}
}
//Terminasion condition
if(currentAdsrLevel >= MAX_ADSR_VOLUME)
{
channel.status = DECAY;
}
}
else if(channel.status == DECAY)
{
unsigned int decayType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrLevel.decayRate ^ 0x1F)) - 0x18 + logIndex[decayType]);
//Terminasion condition
if(((currentAdsrLevel >> 27) & 0xF) <= channel.adsrLevel.sustainLevel)
{
channel.status = SUSTAIN;
}
}
else if(channel.status == SUSTAIN)
{
if(channel.adsrRate.sustainDirection == 0)
{
//Increment
if(channel.adsrRate.sustainMode == 0)
{
currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x10);
}
else
{
if(currentAdsrLevel < 0x60000000)
{
currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x10);
}
else
{
currentAdsrLevel += GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x18);
}
}
}
else
{
//Decrement
if(channel.adsrRate.sustainMode == 0)
{
//Linear
currentAdsrLevel -= GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x0F);
}
else
{
unsigned int sustainType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
currentAdsrLevel -= GetAdsrDelta((channel.adsrRate.sustainRate ^ 0x7F) - 0x1B + logIndex[sustainType]);
}
}
}
else if(channel.status == RELEASE)
{
if(channel.adsrRate.releaseMode == 0)
{
//Linear
currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrRate.releaseRate ^ 0x1F)) - 0x0C);
}
else
{
unsigned int releaseType = (static_cast<uint32>(currentAdsrLevel) >> 28) & 0x7;
currentAdsrLevel -= GetAdsrDelta((4 * (channel.adsrRate.releaseRate ^ 0x1F)) - 0x18 + logIndex[releaseType]);
}
if(currentAdsrLevel <= 0)
{
channel.status = STOPPED;
}
}
currentAdsrLevel = min<int64>(currentAdsrLevel, MAX_ADSR_VOLUME);
currentAdsrLevel = max<int64>(currentAdsrLevel, 0);
channel.adsrVolume = static_cast<uint32>(currentAdsrLevel);
}
///////////////////////////////////////////////////////
// CSampleReader
///////////////////////////////////////////////////////
CSpu::CSampleReader::CSampleReader() :
m_nextSample(NULL)
{
Reset();
}
CSpu::CSampleReader::~CSampleReader()
{
}
void CSpu::CSampleReader::Reset()
{
m_sourceSamplingRate = 0;
m_nextSample = NULL;
m_repeat = NULL;
memset(m_buffer, 0, sizeof(m_buffer));
m_pitch = 0;
m_currentTime = 0;
m_dstTime = 0;
m_s1 = 0;
m_s2 = 0;
m_done = false;
m_nextValid = false;
}
void CSpu::CSampleReader::SetParams(uint8* address, uint8* repeat)
{
m_currentTime = 0;
m_dstTime = 0;
m_nextSample = address;
m_repeat = repeat;
m_s1 = 0;
m_s2 = 0;
m_nextValid = false;
m_done = false;
AdvanceBuffer();
}
void CSpu::CSampleReader::SetPitch(uint32 baseSamplingRate, uint16 pitch)
{
m_sourceSamplingRate = baseSamplingRate * pitch / 4096;
}
void CSpu::CSampleReader::GetSamples(int16* samples, unsigned int sampleCount, unsigned int destSamplingRate)
{
assert(m_nextSample != NULL);
double dstTimeDelta = 1.0 / static_cast<double>(destSamplingRate);
for(unsigned int i = 0; i < sampleCount; i++)
{
samples[i] = GetSample(m_dstTime);
m_dstTime += dstTimeDelta;
}
}
int16 CSpu::CSampleReader::GetSample(double time)
{
time -= m_currentTime;
double sample = time * static_cast<double>(GetSamplingRate());
double sampleInt = 0;
double alpha = modf(sample, &sampleInt);
unsigned int sampleIndex = static_cast<int>(sampleInt);
int16 currentSample = m_buffer[sampleIndex];
int16 nextSample = m_buffer[sampleIndex + 1];
double resultSample =
(static_cast<double>(currentSample) * (1 - alpha)) + (static_cast<double>(nextSample) * alpha);
if(sampleIndex >= BUFFER_SAMPLES)
{
AdvanceBuffer();
}
return static_cast<int16>(resultSample);
}
void CSpu::CSampleReader::AdvanceBuffer()
{
if(m_nextValid)
{
memmove(m_buffer, m_buffer + BUFFER_SAMPLES, sizeof(int16) * BUFFER_SAMPLES);
UnpackSamples(m_buffer + BUFFER_SAMPLES);
m_currentTime += GetBufferStep();
}
else
{
assert(m_currentTime == 0);
UnpackSamples(m_buffer);
UnpackSamples(m_buffer + BUFFER_SAMPLES);
m_nextValid = true;
}
}
void CSpu::CSampleReader::UnpackSamples(int16* dst)
{
double workBuffer[28];
//Read header
uint8 shiftFactor = m_nextSample[0] & 0xF;
uint8 predictNumber = m_nextSample[0] >> 4;
uint8 flags = m_nextSample[1];
assert(predictNumber < 5);
if(m_done)
{
memset(m_buffer, 0, sizeof(int16) * BUFFER_SAMPLES);
return;
}
//Get intermediate values
{
unsigned int workBufferPtr = 0;
for(unsigned int i = 2; i < 16; i++)
{
uint8 sampleByte = m_nextSample[i];
int16 firstSample = ((sampleByte & 0x0F) << 12);
int16 secondSample = ((sampleByte & 0xF0) << 8);
firstSample >>= shiftFactor;
secondSample >>= shiftFactor;
workBuffer[workBufferPtr++] = firstSample;
workBuffer[workBufferPtr++] = secondSample;
}
}
//Generate PCM samples
{
double predictorTable[5][2] =
{
{ 0.0, 0.0 },
{ 60.0 / 64.0, 0.0 },
{ 115.0 / 64.0, -52.0 / 64.0 },
{ 98.0 / 64.0, -55.0 / 64.0 },
{ 122.0 / 64.0, -60.0 / 64.0 },
};
for(unsigned int i = 0; i < 28; i++)
{
workBuffer[i] = workBuffer[i] +
m_s1 * predictorTable[predictNumber][0] +
m_s2 * predictorTable[predictNumber][1];
m_s2 = m_s1;
m_s1 = workBuffer[i];
dst[i] = static_cast<int16>(workBuffer[i] + 0.5);
}
}
if(flags & 0x04)
{
m_repeat = m_nextSample;
}
m_nextSample += 0x10;
if(flags & 0x01)
{
if(flags == 0x03)
{
m_nextSample = m_repeat;
}
else
{
m_done = true;
}
}
}
uint8* CSpu::CSampleReader::GetRepeat() const
{
return m_repeat;
}
uint8* CSpu::CSampleReader::GetCurrent() const
{
return m_nextSample;
}
double CSpu::CSampleReader::GetSamplingRate() const
{
return m_sourceSamplingRate;
}
double CSpu::CSampleReader::GetBufferStep() const
{
return static_cast<double>(BUFFER_SAMPLES) / static_cast<double>(GetSamplingRate());
}
double CSpu::CSampleReader::GetNextTime() const
{
return m_currentTime + GetBufferStep();
}
*/

View File

@ -136,13 +136,28 @@ namespace Iop
uint32 GetTransferAddress() const;
void SetTransferAddress(uint32);
uint32 GetChannelOn() const;
uint32 GetChannelReverb() const;
void SetReverbParam(unsigned int, uint16);
void SetReverbWorkAddressStart(uint32);
void SetReverbWorkAddressEnd(uint32);
void SetReverbCurrentAddress(uint32);
UNION32_16 GetChannelOn() const;
void SetChannelOn(uint16, uint16);
void SetChannelOnLo(uint16);
void SetChannelOnHi(uint16);
UNION32_16 GetChannelReverb() const;
void SetChannelReverb(uint16, uint16);
void SetChannelReverbLo(uint16);
void SetChannelReverbHi(uint16);
CHANNEL& GetChannel(unsigned int);
void SendKeyOn(uint32);
void SendKeyOff(uint32);
void WriteWord(uint16);
uint32 ReceiveDma(uint8*, uint32, uint32);
void Render(int16*, unsigned int, unsigned int);
@ -153,14 +168,21 @@ namespace Iop
MAX_ADSR_VOLUME = 0x7FFFFFFF,
};
uint8* m_ram;
void UpdateAdsr(CHANNEL&);
uint32 GetAdsrDelta(unsigned int) const;
float GetReverbSample(uint32) const;
void SetReverbSample(uint32, float);
uint32 GetReverbOffset(unsigned int) const;
float GetReverbCoef(unsigned int) const;
uint8* m_ram;
uint32 m_ramSize;
uint32 m_baseSamplingRate;
uint32 m_bufferAddr;
UNION32_16 m_channelOn;
UNION32_16 m_channelReverb;
uint32 m_reverbWorkStartAddr;
uint32 m_reverbWorkEndAddr;
uint32 m_reverbWorkAddrStart;
uint32 m_reverbWorkAddrEnd;
uint32 m_reverbCurrAddr;
int m_reverbTicks;
uint16 m_reverb[REVERB_REG_COUNT];
@ -170,3 +192,44 @@ namespace Iop
}
#endif
/*
class CSampleReader
{
public:
CSampleReader();
virtual ~CSampleReader();
void Reset();
void SetParams(uint8*, uint8*);
void SetPitch(uint32, uint16);
void GetSamples(int16*, unsigned int, unsigned int);
uint8* GetRepeat() const;
uint8* GetCurrent() const;
private:
enum
{
BUFFER_SAMPLES = 28,
};
void UnpackSamples(int16*);
void AdvanceBuffer();
int16 GetSample(double);
double GetNextTime() const;
double GetBufferStep() const;
double GetSamplingRate() const;
unsigned int m_sourceSamplingRate;
uint8* m_nextSample;
uint8* m_repeat;
int16 m_buffer[BUFFER_SAMPLES * 2];
uint16 m_pitch;
double m_currentTime;
double m_dstTime;
double m_s1;
double m_s2;
bool m_done;
bool m_nextValid;
};
*/

View File

@ -1,144 +0,0 @@
#include <cassert>
#include "Log.h"
#include "Iop_SpuBase.h"
using namespace Iop;
using namespace std;
#define LOG_NAME ("iop_spubase")
CSpuBase::CSpuBase(uint8* ram, uint32 ramSize) :
m_ram(ram),
m_ramSize(ramSize)
{
Reset();
//Init log table for ADSR
memset(m_adsrLogTable, 0, sizeof(m_adsrLogTable));
uint32 value = 3;
uint32 columnIncrement = 1;
uint32 column = 0;
for(unsigned int i = 32; i < 160; i++)
{
if(value < 0x3FFFFFFF)
{
value += columnIncrement;
column++;
if(column == 5)
{
column = 1;
columnIncrement *= 2;
}
}
else
{
value = 0x3FFFFFFF;
}
m_adsrLogTable[i] = value;
}
}
CSpuBase::~CSpuBase()
{
}
void CSpuBase::Reset()
{
m_channelOn.f = 0;
m_channelReverb.f = 0;
m_reverbTicks = 0;
m_bufferAddr = 0;
m_reverbCurrAddr = 0;
m_reverbWorkStartAddr = 0;
m_reverbWorkEndAddr = 0;
m_baseSamplingRate = 44100;
memset(m_channel, 0, sizeof(m_channel));
memset(m_reverb, 0, sizeof(m_reverb));
}
void CSpuBase::SetBaseSamplingRate(uint32 samplingRate)
{
m_baseSamplingRate = samplingRate;
}
uint32 CSpuBase::GetTransferAddress() const
{
return m_bufferAddr;
}
void CSpuBase::SetTransferAddress(uint32 value)
{
m_bufferAddr = value & (m_ramSize - 1);
}
uint32 CSpuBase::GetChannelOn() const
{
return m_channelOn.f;
}
uint32 CSpuBase::GetChannelReverb() const
{
return m_channelReverb.f;
}
CSpuBase::CHANNEL& CSpuBase::GetChannel(unsigned int channelNumber)
{
assert(channelNumber < MAX_CHANNEL);
return m_channel[channelNumber];
}
void CSpuBase::SendKeyOn(uint32 channels)
{
for(unsigned int i = 0; i < MAX_CHANNEL; i++)
{
CHANNEL& channel = m_channel[i];
if(channels & (1 << i))
{
channel.status = KEY_ON;
}
}
}
void CSpuBase::SendKeyOff(uint32 channels)
{
for(unsigned int i = 0; i < MAX_CHANNEL; i++)
{
CHANNEL& channel = m_channel[i];
if(channels & (1 << i))
{
if(channel.status == STOPPED) continue;
if(channel.status == KEY_ON)
{
channel.status = STOPPED;
}
else
{
channel.status = RELEASE;
}
}
}
}
uint32 CSpuBase::ReceiveDma(uint8* buffer, uint32 blockSize, uint32 blockAmount)
{
#ifdef _DEBUG
CLog::GetInstance().Print(LOG_NAME, "Receiving DMA transfer to 0x%0.8X. Size = 0x%0.8X bytes.\r\n",
m_bufferAddr, blockSize * blockAmount);
#endif
unsigned int blocksTransfered = 0;
for(unsigned int i = 0; i < blockAmount; i++)
{
uint32 copySize = min<uint32>(m_ramSize - m_bufferAddr, blockSize);
memcpy(m_ram + m_bufferAddr, buffer, copySize);
m_bufferAddr += blockSize;
m_bufferAddr &= m_ramSize - 1;
buffer += blockSize;
blocksTransfered++;
}
return blocksTransfered;
}

View File

@ -13,10 +13,9 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, char*, int)
#ifdef DEBUGGER_INCLUDED
{
virtualMachine.Reset();
// CPsfLoader::LoadPsf(virtualMachine, "C:\\Media\\PSX\\C-SotN_psf\\Master Librarian.minipsf");
// CPsfLoader::LoadPsf2(virtualMachine, "D:\\Media\\PS2\\FF4\\ff4-02.psf2");
CPsfLoader::LoadPsf(virtualMachine, "C:\\Downloads\\vp-psf\\vp-114.minipsf");
// CPsfLoader::LoadPsf(virtualMachine, "C:\\Media\\PS2\\FFXI_psf2\\FFXI_psf2\\104 Ronfaure.psf2");
// CPsfLoader::LoadPsf(virtualMachine, "C:\\Media\\PS2\\FF4\\ff4-01.psf2");
CPsfLoader::LoadPsf(virtualMachine, "C:\\Media\\PS2\\FF10_psf\\102 In Zanarkand.minipsf2");
CMiniDebugger debugger(virtualMachine, virtualMachine.GetDebugInfo());
debugger.Show(SW_SHOW);
debugger.Run();

View File

@ -39,7 +39,7 @@ m_accel(CreateAccelerators())
SetTimer(m_hWnd, 0, 1000, NULL);
m_regView = new CSpuRegView(m_hWnd, &GetClientRect(), m_virtualMachine.GetSpu());
m_regView = new CSpuRegView(m_hWnd, &GetClientRect(), m_virtualMachine.GetSpuCore(0));
m_regView->Show(SW_SHOW);
UpdateUi();

View File

@ -28,9 +28,10 @@ m_spuRam(new uint8[SPURAMSIZE]),
m_dmac(m_ram, m_intc),
m_counters(CLOCK_FREQ, m_intc),
m_thread(bind(&CPsfVm::ThreadProc, this)),
m_spu2(PS2::CSpu2::REGS_BEGIN),
m_spuCore0(m_spuRam, SPURAMSIZE),
m_spuCore1(m_spuRam, SPURAMSIZE)
m_spuCore1(m_spuRam, SPURAMSIZE),
m_spu(m_spuCore0),
m_spu2(m_spuCore0, m_spuCore1)
{
//Read memory map
m_cpu.m_pMemoryMap->InsertReadMap((0 * RAMSIZE), (0 * RAMSIZE) + RAMSIZE - 1, m_ram, 0x01);
@ -62,11 +63,8 @@ m_spuCore1(m_spuRam, SPURAMSIZE)
m_cpu.m_Comments.Unserialize("rawr.comments");
#endif
m_dmac.SetReceiveFunction(4, bind(&CSpu::ReceiveDma, &m_spuCore0, _1, _2, _3));
m_dmac.SetReceiveFunction(8, bind(&CSpu::ReceiveDma, &m_spuCore1, _1, _2, _3));
m_spu2.GetCore(0)->SetSpu(&m_spuCore0);
m_spu2.GetCore(1)->SetSpu(&m_spuCore1);
m_dmac.SetReceiveFunction(4, bind(&CSpuBase::ReceiveDma, &m_spuCore0, _1, _2, _3));
m_dmac.SetReceiveFunction(8, bind(&CSpuBase::ReceiveDma, &m_spuCore1, _1, _2, _3));
}
CPsfVm::~CPsfVm()
@ -94,7 +92,7 @@ void CPsfVm::Reset()
m_cpu.Reset();
m_spuCore0.Reset();
m_spuCore1.Reset();
m_spu2.Reset();
// m_spu2.Reset();
m_counters.Reset();
m_dmac.Reset();
m_intc.Reset();
@ -103,14 +101,14 @@ void CPsfVm::Reset()
uint32 CPsfVm::ReadIoRegister(uint32 address)
{
if(address >= CSpu::SPU_BEGIN && address <= CSpu::SPU_END)
{
return m_spuCore0.ReadRegister(address);
}
else if(address == 0x1F801814)
if(address == 0x1F801814)
{
return 0x14802000;
}
else if(address >= CSpu::SPU_BEGIN && address <= CSpu::SPU_END)
{
return m_spu.ReadRegister(address);
}
else if(address >= CDmac::DMAC_ZONE1_START && address <= CDmac::DMAC_ZONE1_END)
{
return m_dmac.ReadRegister(address);
@ -127,7 +125,7 @@ uint32 CPsfVm::ReadIoRegister(uint32 address)
{
return m_counters.ReadRegister(address);
}
else if(address >= PS2::CSpu2::REGS_BEGIN && address <= PS2::CSpu2::REGS_END)
else if(address >= CSpu2::REGS_BEGIN && address <= CSpu2::REGS_END)
{
return m_spu2.ReadRegister(address);
}
@ -140,14 +138,14 @@ uint32 CPsfVm::ReadIoRegister(uint32 address)
uint32 CPsfVm::WriteIoRegister(uint32 address, uint32 value)
{
if(address >= CSpu::SPU_BEGIN && address <= CSpu::SPU_END)
{
m_spuCore0.WriteRegister(address, static_cast<uint16>(value));
}
else if(address >= CDmac::DMAC_ZONE1_START && address <= CDmac::DMAC_ZONE1_END)
if(address >= CDmac::DMAC_ZONE1_START && address <= CDmac::DMAC_ZONE1_END)
{
m_dmac.WriteRegister(address, value);
}
else if(address >= CSpu::SPU_BEGIN && address <= CSpu::SPU_END)
{
m_spu.WriteRegister(address, static_cast<uint16>(value));
}
else if(address >= CDmac::DMAC_ZONE2_START && address <= CDmac::DMAC_ZONE2_END)
{
m_dmac.WriteRegister(address, value);
@ -160,7 +158,7 @@ uint32 CPsfVm::WriteIoRegister(uint32 address, uint32 value)
{
m_counters.WriteRegister(address, value);
}
else if(address >= PS2::CSpu2::REGS_BEGIN && address <= PS2::CSpu2::REGS_END)
else if(address >= CSpu2::REGS_BEGIN && address <= CSpu2::REGS_END)
{
return m_spu2.WriteRegister(address, value);
}
@ -207,9 +205,16 @@ CMIPS& CPsfVm::GetCpu()
return m_cpu;
}
CSpu& CPsfVm::GetSpu()
CSpuBase& CPsfVm::GetSpuCore(unsigned int coreId)
{
return m_spuCore0;
if(coreId == 0)
{
return m_spuCore0;
}
else
{
return m_spuCore1;
}
}
uint8* CPsfVm::GetRam()
@ -347,7 +352,7 @@ void CPsfVm::ThreadProc()
}
}
m_spuHandler.Update(m_spuCore0);
//m_spuHandler.Update(m_spuCore0);
spuUpdateCounter += spuUpdateTicks;
}
}

View File

@ -5,6 +5,7 @@
#include "MIPS.h"
#include "Bios.h"
#include "SH_OpenAL.h"
#include "iop/Iop_SpuBase.h"
#include "iop/Iop_Spu.h"
#include "iop/Iop_Dmac.h"
#include "iop/Iop_Intc.h"
@ -42,7 +43,7 @@ public:
void Step();
CMIPS& GetCpu();
CSpu& GetSpu();
Iop::CSpuBase& GetSpuCore(unsigned int);
uint8* GetRam();
void SetBios(CBios*);
@ -77,10 +78,11 @@ private:
Iop::CIntc m_intc;
Iop::CRootCounters m_counters;
Iop::CDmac m_dmac;
CSpu m_spuCore0;
CSpu m_spuCore1;
PS2::CSpu2 m_spu2;
CMIPS m_cpu;
Iop::CSpuBase m_spuCore0;
Iop::CSpuBase m_spuCore1;
Iop::CSpu m_spu;
Iop::CSpu2 m_spu2;
CMIPS m_cpu;
CMipsExecutor m_executor;
CBios* m_bios;
CSH_OpenAL m_spuHandler;

View File

@ -6,6 +6,7 @@
//#define LOGGING
using namespace boost;
using namespace Iop;
ALCint g_attrList[] =
{
@ -52,7 +53,7 @@ bool CSH_OpenAL::HasFreeBuffers()
return m_availableBuffers.size() != 0;
}
void CSH_OpenAL::Update(CSpu& spu)
void CSH_OpenAL::Update(CSpuBase& spu)
{
// const unsigned int minBufferLength = 16;
// unsigned int bufferLength = minBufferLength;

View File

@ -3,7 +3,7 @@
#include <deque>
#include <time.h>
#include "iop/Iop_Spu.h"
#include "iop/Iop_SpuBase.h"
#include "openal/Device.h"
#include "openal/Context.h"
#include "openal/Source.h"
@ -16,7 +16,7 @@ public:
virtual ~CSH_OpenAL();
void Reset();
void Update(CSpu&);
void Update(Iop::CSpuBase&);
bool HasFreeBuffers();
private:

View File

@ -1,8 +1,9 @@
#include "SpuRegView.h"
using namespace std;
using namespace Iop;
CSpuRegView::CSpuRegView(HWND parent, RECT* rect, CSpu& spu) :
CSpuRegView::CSpuRegView(HWND parent, RECT* rect, CSpuBase& spu) :
CRegViewPage(parent, rect),
m_spu(spu)
{
@ -17,44 +18,43 @@ CSpuRegView::~CSpuRegView()
void CSpuRegView::Render()
{
string text;
char channelStatus[CSpu::MAX_CHANNEL + 1];
char channelStatus[CSpuBase::MAX_CHANNEL + 1];
//Header
text += " VLEFT VRIGH PITCH ADDRE ADSRL ADSRR ADSRV REPEA \r\n";
text += "\r\n";
//Channel detail
for(unsigned int i = 0; i < CSpu::MAX_CHANNEL; i++)
for(unsigned int i = 0; i < CSpuBase::MAX_CHANNEL; i++)
{
CSpu::CHANNEL& channel(m_spu.GetChannel(i));
uint32 address = CSpu::CH0_BASE + (i * 0x10);
CSpuBase::CHANNEL& channel(m_spu.GetChannel(i));
char temp[256];
sprintf(temp, "CH%0.2i %0.4X %0.4X %0.4X %0.6X %0.4X %0.4X %0.4X %0.6X\r\n",
i,
channel.volumeLeft,
channel.volumeRight,
channel.pitch,
channel.address * 8,
channel.address,
channel.adsrLevel,
channel.adsrRate,
channel.adsrVolume >> 16,
channel.repeat * 8);
channel.repeat);
text += temp;
char status = '0';
switch(channel.status)
{
case CSpu::ATTACK:
case CSpu::KEY_ON:
case CSpuBase::ATTACK:
case CSpuBase::KEY_ON:
status = 'A';
break;
case CSpu::DECAY:
case CSpuBase::DECAY:
status = 'D';
break;
case CSpu::SUSTAIN:
case CSpuBase::SUSTAIN:
status = 'S';
break;
case CSpu::RELEASE:
case CSpuBase::RELEASE:
status = 'R';
break;
}
@ -62,7 +62,7 @@ void CSpuRegView::Render()
channelStatus[i] = status;
}
channelStatus[CSpu::MAX_CHANNEL] = 0;
channelStatus[CSpuBase::MAX_CHANNEL] = 0;
text += "\r\n";
{
@ -72,14 +72,14 @@ void CSpuRegView::Render()
}
{
char revbStat[CSpu::MAX_CHANNEL + 1];
char revbStat[CSpuBase::MAX_CHANNEL + 1];
char temp[256];
uint32 stat = m_spu.GetChannelReverb();
for(unsigned int i = 0; i < CSpu::MAX_CHANNEL; i++)
uint32 stat = m_spu.GetChannelReverb().f;
for(unsigned int i = 0; i < CSpuBase::MAX_CHANNEL; i++)
{
revbStat[i] = (stat & (1 << i)) ? '1' : '0';
}
revbStat[CSpu::MAX_CHANNEL] = 0;
revbStat[CSpuBase::MAX_CHANNEL] = 0;
sprintf(temp, "CH_REVB: %s\r\n", revbStat);
text += temp;

View File

@ -2,18 +2,18 @@
#define _SPUREGVIEW_H_
#include "win32ui/RegViewPage.h"
#include "iop/Iop_Spu.h"
#include "iop/Iop_SpuBase.h"
class CSpuRegView : public CRegViewPage
{
public:
CSpuRegView(HWND, RECT*, CSpu&);
CSpuRegView(HWND, RECT*, Iop::CSpuBase&);
virtual ~CSpuRegView();
void Render();
private:
CSpu& m_spu;
Iop::CSpuBase& m_spu;
};
#endif

View File

@ -4,8 +4,8 @@
#define LOG_NAME ("spu2")
using namespace PS2;
using namespace PS2::Spu2;
using namespace Iop;
using namespace Iop::Spu2;
using namespace std;
using namespace std::tr1;
using namespace std::tr1::placeholders;
@ -132,77 +132,12 @@ using namespace Framework;
#define SD_DMA_DIR_IOP2SPU 1
*/
//Global stuff
enum
{
SD_VP_REG_BASE_0 = 0x1F900000,
SD_VP_REG_BASE_1 = 0x1F900400,
SD_S_REG_BASE_0 = 0x1F900180,
SD_S_REG_BASE_1 = 0x1F900580,
SD_A_REG_BASE_0 = 0x1F9001A0,
SD_A_REG_BASE_1 = 0x1F9005A0,
SD_P_REG_BASE_0 = 0x1F900760,
SD_P_REG_BASE_1 = 0x1F900760 + 40,
SD_C_SPDIF_OUT = 0x1F9007C0,
SD_C_IRQINFO = 0x1F9007C2,
SD_C_SPDIF_MODE = 0x1F9007C6,
SD_C_SPDIF_MEDIA = 0x1F9007C8,
};
//SD_S_REG
enum
{
SD_S_PMON_HI = 0x00,
SD_S_PMON_LO = 0x02,
SD_S_NON_HI = 0x04,
SD_S_NON_LO = 0x06,
SD_S_VMIXL_HI = 0x08,
SD_S_VMIXL_LO = 0x0A,
SD_S_VMIXEL_HI = 0x0C,
SD_S_VMIXEL_LO = 0x0E,
SD_S_VMIXR_HI = 0x10,
SD_S_VMIXR_LO = 0x12,
SD_S_VMIXER_HI = 0x14,
SD_S_VMIXER_LO = 0x16,
SD_P_MMIX = 0x18,
SD_CORE_ATTR = 0x1A,
SD_CORE_IRQA = 0x1C,
};
//SD_A_REG
enum
{
SD_A_KON_HI = 0x00,
SD_A_KON_LO = 0x02,
SD_A_KOFF_HI = 0x04,
SD_A_KOFF_LO = 0x06,
SD_A_TSA_HI = 0x08,
SD_A_TSA_LO = 0x0A,
SD_A_STD = 0x0C,
};
//SD_P_REG
enum
{
SD_P_MVOLL = 0x00,
SD_P_MVOLR = 0x02,
SD_P_EVOLL = 0x04,
SD_P_EVOLR = 0x06,
SD_P_AVOLL = 0x08,
SD_P_AVOLR = 0x0A,
SD_P_BVOLL = 0x0C,
SD_P_BVOLR = 0x0E,
SD_P_MVOLXL = 0x10,
SD_P_MVOLXR = 0x12,
};
CSpu2::CSpu2(uint32 baseAddress) :
m_baseAddress(baseAddress)
CSpu2::CSpu2(CSpuBase& spuBase0, CSpuBase& spuBase1)
{
for(unsigned int i = 0; i < CORE_NUM; i++)
{
m_core[i] = new CCore(i);
CSpuBase& base(i == 0 ? spuBase0 : spuBase1);
m_core[i] = new CCore(i, base);
}
m_readDispatchInfo.global = bind(&CSpu2::ReadRegisterImpl, this, _1, _2);
@ -246,7 +181,7 @@ uint32 CSpu2::WriteRegister(uint32 address, uint32 value)
uint32 CSpu2::ProcessRegisterAccess(const REGISTER_DISPATCH_INFO& dispatchInfo, uint32 address, uint32 value)
{
uint32 tmpAddress = address - m_baseAddress;
uint32 tmpAddress = address - REGS_BEGIN;
if(tmpAddress < 0x760)
{
unsigned int coreId = (tmpAddress & 0x400) ? 1 : 0;

View File

@ -5,12 +5,12 @@
#include <functional>
#include "Spu2_Core.h"
namespace PS2
namespace Iop
{
class CSpu2 : boost::noncopyable
{
public:
CSpu2(uint32);
CSpu2(CSpuBase&, CSpuBase&);
virtual ~CSpu2();
uint32 ReadRegister(uint32);
@ -47,7 +47,6 @@ namespace PS2
REGISTER_DISPATCH_INFO m_readDispatchInfo;
REGISTER_DISPATCH_INFO m_writeDispatchInfo;
uint32 m_baseAddress;
Spu2::CCore* m_core[CORE_NUM];
};
}

View File

@ -1,21 +0,0 @@
#include "Spu2_Channel.h"
using namespace PS2;
using namespace PS2::Spu2;
CChannel::CChannel()
{
volLeft = 0;
volRight = 0;
pitch = 0;
adsr1 = 0;
adsr2 = 0;
envx = 0;
volxLeft = 0;
volxRight = 0;
}
CChannel::~CChannel()
{
}

View File

@ -1,28 +0,0 @@
#ifndef _PS2_SPU2_CHANNEL_H_
#define _PS2_SPU2_CHANNEL_H_
#include "Types.h"
namespace PS2
{
namespace Spu2
{
class CChannel
{
public:
CChannel();
virtual ~CChannel();
uint16 volLeft;
uint16 volRight;
uint16 pitch;
uint16 adsr1;
uint16 adsr2;
uint16 envx;
uint16 volxLeft;
uint16 volxRight;
};
}
}
#endif

View File

@ -6,16 +6,16 @@
#define LOG_NAME_PREFIX ("spu2_core_")
#define SPU_BASE_SAMPLING_RATE (48000)
using namespace PS2::Spu2;
using namespace Iop;
using namespace Iop::Spu2;
using namespace std;
using namespace std::tr1;
using namespace Framework;
using namespace boost;
CCore::CCore(unsigned int coreId) :
CCore::CCore(unsigned int coreId, CSpuBase& spuBase) :
m_coreId(coreId),
m_spuBase(NULL)
//m_ram(new uint8[RAMSIZE])
m_spuBase(spuBase)
{
m_logName = LOG_NAME_PREFIX + lexical_cast<string>(m_coreId);
@ -30,32 +30,16 @@ m_spuBase(NULL)
CCore::~CCore()
{
// delete [] m_ram;
}
void CCore::Reset()
{
if(m_spuBase)
{
m_spuBase->Reset();
}
// memset(m_ram, 0, RAMSIZE);
// m_transferAddress.f = 0;
m_tempReverb = 0;
m_tempReverbA = 0;
m_coreAttr = 0;
}
void CCore::SetSpu(CSpu* spu)
{
m_spuBase = spu;
}
//CSpu& CCore::GetSpu()
//{
// return m_spuBase;
//}
uint32 CCore::ReadRegister(uint32 address, uint32 value)
{
return ProcessRegisterAccess(m_readDispatch, address, value);
@ -66,26 +50,6 @@ uint32 CCore::WriteRegister(uint32 address, uint32 value)
return ProcessRegisterAccess(m_writeDispatch, address, value);
}
uint32 CCore::ReceiveDma(uint8* buffer, uint32 blockSize, uint32 blockAmount)
{
/*
assert((blockSize & 1) == 0);
unsigned int blocksTransfered = 0;
uint32 dstAddress = m_transferAddress.f << 1;
for(unsigned int i = 0; i < blockAmount; i++)
{
uint32 copySize = min<uint32>(RAMSIZE - dstAddress, blockSize);
memcpy(m_ram + dstAddress, buffer, copySize);
dstAddress += blockSize;
dstAddress &= RAMSIZE - 1;
buffer += blockSize;
blocksTransfered++;
}
m_transferAddress.f = dstAddress >> 1;
*/
return m_spuBase->ReceiveDma(buffer, blockSize, blockAmount);
}
uint32 CCore::ProcessRegisterAccess(const REGISTER_DISPATCH_INFO& dispatchInfo, uint32 address, uint32 value)
{
if(address < S_REG_BASE)
@ -125,11 +89,10 @@ uint32 CCore::ReadRegisterCore(unsigned int channelId, uint32 address, uint32 va
result = m_coreAttr;
break;
case A_TSA_HI:
if(m_spuBase)
{
uint32 transferAddress = m_spuBase->GetTransferAddress();
uint32 transferAddress = m_spuBase.GetTransferAddress();
result = (transferAddress >> (16 + 1));
}
}
break;
case A_ESA_LO:
result = (m_tempReverb & 0xFFFF);
@ -147,62 +110,38 @@ uint32 CCore::WriteRegisterCore(unsigned int channelId, uint32 address, uint32 v
switch(address)
{
case CORE_ATTR:
if(m_spuBase)
{
m_spuBase->SetBaseSamplingRate(SPU_BASE_SAMPLING_RATE);
}
m_spuBase.SetBaseSamplingRate(SPU_BASE_SAMPLING_RATE);
m_coreAttr = static_cast<uint16>(value);
break;
case A_STD:
{
// uint32 address = m_transferAddress.f << 1;
// address &= RAMSIZE - 1;
// *reinterpret_cast<uint16*>(m_ram + address) = static_cast<uint16>(value);
// m_transferAddress.f++;
}
m_spuBase.WriteWord(static_cast<uint16>(value));
break;
case A_KON_HI:
if(m_spuBase)
{
m_spuBase->SendKeyOn(value);
}
m_spuBase.SendKeyOn(value);
break;
case A_KON_LO:
if(m_spuBase)
{
m_spuBase->SendKeyOn(value << 16);
}
m_spuBase.SendKeyOn(value << 16);
break;
case A_KOFF_HI:
if(m_spuBase)
{
m_spuBase->SendKeyOff(value);
}
m_spuBase.SendKeyOff(value);
break;
case A_KOFF_LO:
if(m_spuBase)
{
m_spuBase->SendKeyOff(value << 16);
}
m_spuBase.SendKeyOff(value << 16);
break;
case A_TSA_HI:
if(m_spuBase)
{
uint32 transferAddress = m_spuBase->GetTransferAddress();
uint32 transferAddress = m_spuBase.GetTransferAddress();
transferAddress &= 0xFFFF << 1;
transferAddress |= value << (1 + 16);
// transferAddress &= RAMSIZE - 1;
m_spuBase->SetTransferAddress(transferAddress);
m_spuBase.SetTransferAddress(transferAddress);
}
break;
case A_TSA_LO:
if(m_spuBase)
{
uint32 transferAddress = m_spuBase->GetTransferAddress();
uint32 transferAddress = m_spuBase.GetTransferAddress();
transferAddress &= 0xFFFF << (1 + 16);
transferAddress |= value << 1;
// transferAddress &= RAMSIZE - 1;
m_spuBase->SetTransferAddress(transferAddress);
m_spuBase.SetTransferAddress(transferAddress);
}
break;
case A_ESA_HI:
@ -226,9 +165,8 @@ uint32 CCore::ReadRegisterChannel(unsigned int channelId, uint32 address, uint32
{
return 0;
}
if(!m_spuBase) return 0;
uint32 result = 0;
CSpu::CHANNEL& channel(m_spuBase->GetChannel(channelId));
CSpuBase::CHANNEL& channel(m_spuBase.GetChannel(channelId));
switch(address)
{
case VP_ENVX:
@ -253,8 +191,7 @@ uint32 CCore::WriteRegisterChannel(unsigned int channelId, uint32 address, uint3
return 0;
}
LogChannelWrite(channelId, address, value);
if(!m_spuBase) return 0;
CSpu::CHANNEL& channel(m_spuBase->GetChannel(channelId));
CSpuBase::CHANNEL& channel(m_spuBase.GetChannel(channelId));
switch(address)
{
case VP_VOLL:
@ -283,71 +220,41 @@ uint32 CCore::WriteRegisterChannel(unsigned int channelId, uint32 address, uint3
break;
case VA_SSA_HI:
{
uint32 address = channel.address * 8;
uint32 address = channel.address;
address &= 0xFFFF << 1;
address |= value << (1 + 16);
assert((address & 0x7) == 0);
channel.address = address / 8;
channel.address = address;
}
break;
case VA_SSA_LO:
{
uint32 address = channel.address * 8;
uint32 address = channel.address;
address &= 0xFFFF << (1 + 16);
address |= value << 1;
assert((address & 0x7) == 0);
channel.address = address / 8;
channel.address = address;
}
break;
case VA_LSAX_HI:
{
uint32 address = channel.repeat * 8;
uint32 address = channel.repeat;
address &= 0xFFFF << 1;
address |= value << (1 + 16);
assert((address & 0x7) == 0);
channel.repeat = address / 8;
channel.repeat = address;
}
break;
case VA_LSAX_LO:
{
uint32 address = channel.repeat * 8;
uint32 address = channel.repeat;
address &= 0xFFFF << (1 + 16);
address |= value << 1;
assert((address & 0x7) == 0);
channel.repeat = address / 8;
channel.repeat = address;
}
break;
}
/*
CChannel& channel(m_channel[channelId]);
switch(address)
{
case VP_VOLL:
channel.volLeft = static_cast<uint16>(value);
break;
case VP_VOLR:
channel.volRight = static_cast<uint16>(value);
break;
case VP_PITCH:
channel.pitch = static_cast<uint16>(value);
break;
case VP_ADSR1:
channel.adsr1 = static_cast<uint16>(value);
break;
case VP_ADSR2:
channel.adsr2 = static_cast<uint16>(value);
break;
case VP_ENVX:
channel.envx = static_cast<uint16>(value);
break;
case VP_VOLXL:
channel.volxLeft = static_cast<uint16>(value);
break;
case VP_VOLXR:
channel.volxRight = static_cast<uint16>(value);
break;
}
*/
return 0;
}

View File

@ -6,27 +6,22 @@
#include <boost/utility.hpp>
#include "Types.h"
#include "../BasicUnions.h"
#include "iop/Iop_Spu.h"
#include "Spu2_Channel.h"
#include "iop/Iop_SpuBase.h"
namespace PS2
namespace Iop
{
namespace Spu2
{
class CCore : public boost::noncopyable
{
public:
CCore(unsigned int);
CCore(unsigned int, CSpuBase&);
virtual ~CCore();
void Reset();
uint32 ReadRegister(uint32, uint32);
uint32 WriteRegister(uint32, uint32);
uint32 ReceiveDma(uint8*, uint32, uint32);
void SetSpu(CSpu*);
// CSpu& GetSpu();
enum REGISTERS
{
@ -96,13 +91,10 @@ namespace PS2
REGISTER_DISPATCH_INFO m_readDispatch;
REGISTER_DISPATCH_INFO m_writeDispatch;
// uint8* m_ram;
// CChannel m_channel[MAX_CHANNEL];
unsigned int m_coreId;
uint16 m_coreAttr;
// UNION32_16 m_transferAddress;
std::string m_logName;
CSpu* m_spuBase;
CSpuBase& m_spuBase;
uint32 m_tempReverb;
uint32 m_tempReverbA;
};

View File

@ -237,14 +237,6 @@
RelativePath=".\Source\FunctionsView.h"
>
</File>
<File
RelativePath=".\Source\Iop_SpuBase.cpp"
>
</File>
<File
RelativePath=".\Source\Iop_SpuBase.h"
>
</File>
<File
RelativePath=".\Source\Main.cpp"
>
@ -356,14 +348,6 @@
RelativePath=".\Source\ps2\Spu2.h"
>
</File>
<File
RelativePath=".\Source\ps2\Spu2_Channel.cpp"
>
</File>
<File
RelativePath=".\Source\ps2\Spu2_Channel.h"
>
</File>
<File
RelativePath=".\Source\ps2\Spu2_Core.cpp"
>
@ -760,6 +744,14 @@
RelativePath="..\..\Source\iop\Iop_Spu.h"
>
</File>
<File
RelativePath="..\..\Source\iop\Iop_SpuBase.cpp"
>
</File>
<File
RelativePath="..\..\Source\iop\Iop_SpuBase.h"
>
</File>
<File
RelativePath="..\..\Source\iop\Iop_Stdio.cpp"
>