Audio system update - HLE plugin submitted, homebrew has sound, and also Mario movies!! (this was very unexpected). This also acts as a frame limiter. Might provide an option to turn it off in the future.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@227 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2008-08-16 21:58:07 +00:00
parent dcd5ffeb7a
commit aa3fee8c60
57 changed files with 4438 additions and 104 deletions

View File

@ -53,14 +53,14 @@ union AICR
AICR(u32 _hex) { hex = _hex;}
struct
{
unsigned PSTAT : 1; // sample counter/playback enable
unsigned AFR : 1; // 0=32khz 1=48khz
unsigned AIINTMSK : 1; // 0=interrupt masked 1=interrupt enabled
unsigned AIINT : 1; // audio interrupt status
unsigned AIINTVLD : 1; // This bit controls whether AIINT is affected by the AIIT register
// matching AISLRCNT. Once set, AIINT will hold
unsigned SCRESET : 1; // write to reset counter
unsigned DSPFR : 1; // DSP Frequency (0=32khz 1=48khz)
unsigned PSTAT : 1; // sample counter/playback enable
unsigned AFR : 1; // 0=32khz 1=48khz
unsigned AIINTMSK : 1; // 0=interrupt masked 1=interrupt enabled
unsigned AIINT : 1; // audio interrupt status
unsigned AIINTVLD : 1; // This bit controls whether AIINT is affected by the AIIT register
// matching AISLRCNT. Once set, AIINT will hold
unsigned SCRESET : 1; // write to reset counter
unsigned DSPFR : 1; // DSP Frequency (0=32khz 1=48khz)
unsigned :25;
};
u32 hex;
@ -96,6 +96,7 @@ void ReadStreamBlock(short* _pPCM);
static u64 g_LastCPUTime = 0;
static int g_SampleRate = 32000;
static int g_DSPSampleRate = 32000;
static u64 g_CPUCyclesPerSample = 0xFFFFFFFFFFFULL;
void Init()
@ -116,6 +117,7 @@ void Read32(u32& _rReturnValue, const u32 _Address)
case AI_CONTROL_REGISTER: //0x6C00
LOG(AUDIO_INTERFACE, "AudioInterface(R) 0x%08x", _Address);
_rReturnValue = g_AudioRegister.m_Control.hex;
return;
// Sample Rate (AIGetDSPSampleRate)
@ -164,7 +166,10 @@ void Write32(const u32 _Value, const u32 _Address)
g_AudioRegister.m_Control.AFR = tmpAICtrl.AFR;
}
g_SampleRate = g_AudioRegister.m_Control.AFR ? 48000 : 32000;
g_SampleRate = tmpAICtrl.AFR ? 32000 : 48000;
g_DSPSampleRate = tmpAICtrl.DSPFR ? 32000 : 48000;
// PanicAlert("Sample rate %i %i", g_Aui, g_SampleRate);
g_CPUCyclesPerSample = SystemTimers::GetTicksPerSecond() / g_SampleRate;
// Streaming counter
@ -195,6 +200,8 @@ void Write32(const u32 _Value, const u32 _Address)
g_LastCPUTime = CoreTiming::GetTicks();
}
g_AudioRegister.m_Control = tmpAICtrl;
UpdateInterrupts();
}
break;
@ -316,11 +323,16 @@ void IncreaseSampleCount(const u32 _iAmount)
}
}
u32 GetRate()
u32 GetAISampleRate()
{
return g_SampleRate;
}
u32 GetDSPSampleRate()
{
return g_DSPSampleRate;
}
void Update()
{
// update timer

View File

@ -42,7 +42,8 @@ void HWCALL Read32(u32& _uReturnValue, const u32 _iAddress);
void HWCALL Write32(const u32 _iValue, const u32 _iAddress);
// Get the Audio Rate (48000 or 32000)
u32 GetRate();
u32 GetAISampleRate();
u32 GetDSPSampleRate();
} // end of namespace AudioInterface

View File

@ -179,11 +179,6 @@ void WriteARAM(u8 _iValue, u32 _iAddress);
bool Update_DSP_ReadRegister();
void Update_DSP_WriteRegister();
int GetDSPSampleRate()
{
return 32000; // TODO - can also be 48000
}
void Init()
{
g_ARAM = (u8 *)AllocateMemoryPages(ARAM_SIZE);
@ -414,7 +409,7 @@ void Write16(const u16 _Value, const u32 _Address)
g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks;
g_audioDMA.ReadAddress = g_audioDMA.SourceAddress;
GenerateDSPInterrupt(DSP::INT_AID);
LOG(DSP, "AID DMA started - source address %08x, length %i blocks", g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks);
LOG(DSPINTERFACE, "AID DMA started - source address %08x, length %i blocks", g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks);
}
break;
}
@ -432,8 +427,12 @@ void Write16(const u16 _Value, const u32 _Address)
void UpdateAudioDMA()
{
if (g_audioDMA.AudioDMAControl.Enabled && g_audioDMA.BlocksLeft) {
// TODO : Read audio at g_audioDMA.ReadAddress in RAM and push onto an external audio fifo in the emulator,
// to be mixed with the disc streaming output. If that audio queue fills up, we have to delay the emulator.
// Read audio at g_audioDMA.ReadAddress in RAM and push onto an external audio fifo in the emulator,
// to be mixed with the disc streaming output. If that audio queue fills up, we delay the emulator.
// TO RESTORE OLD BEHAVIOUR, COMMENT OUT THIS LINE
PluginDSP::DSP_SendAIBuffer(g_audioDMA.ReadAddress, AudioInterface::GetDSPSampleRate());
g_audioDMA.ReadAddress += 32;
g_audioDMA.BlocksLeft--;
if (!g_audioDMA.BlocksLeft) {
@ -444,6 +443,10 @@ void UpdateAudioDMA()
g_audioDMA.ReadAddress = g_audioDMA.SourceAddress;
GenerateDSPInterrupt(DSP::INT_AID);
}
} else {
// Send silence. Yeah, it's a bit of a waste to sample rate convert silence.
// or hm. Maybe we shouldn't do this :)
// PluginDSP::DSP_SendAIBuffer(0, AudioInterface::GetDSPSampleRate());
}
}

View File

@ -50,7 +50,6 @@ u8 ReadARAM(const u32 _uAddress);
u8* GetARAMPtr();
void UpdateAudioDMA();
int GetDSPSampleRate();
}// end of namespace DSP

View File

@ -92,15 +92,14 @@ void AICallback(u64 userdata, int cyclesLate)
void DSPCallback(u64 userdata, int cyclesLate)
{
// Poke the DSP, make it do stuff. This should eventually be replaced with dsp->RunCycles(1000) or whatever,
// ~1/6th as many cycles as the period PPC-side.
PluginDSP::DSP_Update();
PluginDSP::DSP_Update(DSP_PERIOD / 6);
CoreTiming::ScheduleEvent(DSP_PERIOD-cyclesLate, &DSPCallback, "DSPCallback");
}
void AudioFifoCallback(u64 userdata, int cyclesLate)
{
int period = CPU_CORE_CLOCK / (DSP::GetDSPSampleRate() * 4 / 32);
int period = CPU_CORE_CLOCK / (AudioInterface::GetDSPSampleRate() * 4 / 32);
DSP::UpdateAudioDMA(); // Push audio to speakers.
CoreTiming::ScheduleEvent(period - cyclesLate, &AudioFifoCallback, "AudioFifoCallback");
@ -140,7 +139,7 @@ void DecrementerSet()
u32 decValue = PowerPC::ppcState.spr[SPR_DEC];
fakeDec = decValue*TIMER_RATIO;
CoreTiming::RemoveEvent(DecrementerCallback);
CoreTiming::ScheduleEvent(decValue*TIMER_RATIO, DecrementerCallback, "DecCallback");
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, DecrementerCallback, "DecCallback");
}
void AdvanceCallback(int cyclesExecuted)

View File

@ -31,8 +31,8 @@ typedef void (__cdecl* TDSP_WriteMailBox)(BOOL _CPUMailbox, unsigned short);
typedef unsigned short (__cdecl* TDSP_ReadMailBox)(BOOL _CPUMailbox);
typedef unsigned short (__cdecl* TDSP_ReadControlRegister)();
typedef unsigned short (__cdecl* TDSP_WriteControlRegister)(unsigned short);
typedef void (__cdecl* TDSP_Update)();
typedef void (__cdecl* TDSP_SendAIBuffer)(unsigned int _Address, unsigned int _Size);
typedef void (__cdecl* TDSP_Update)(int cycles);
typedef void (__cdecl* TDSP_SendAIBuffer)(unsigned int address, int sample_rate);
//! Function Pointer
TGetDllInfo g_GetDllInfo = 0;
@ -217,16 +217,16 @@ unsigned short DSP_ReadControlRegister()
// __________________________________________________________________________________________________
//
void DSP_Update()
void DSP_Update(int cycles)
{
g_DSP_Update();
g_DSP_Update(cycles);
}
// __________________________________________________________________________________________________
//
void DSP_SendAIBuffer(unsigned int _Address, unsigned int _Size)
void DSP_SendAIBuffer(unsigned int address, int sample_rate)
{
g_DSP_SendAIBuffer(_Address, _Size);
g_DSP_SendAIBuffer(address, sample_rate);
}
}

View File

@ -42,8 +42,8 @@ void DSP_WriteMailboxHigh(bool _CPUMailbox, unsigned short _Value);
void DSP_WriteMailboxLow(bool _CPUMailbox, unsigned short _Value);
unsigned short DSP_WriteControlRegister(unsigned short _Flags);
unsigned short DSP_ReadControlRegister();
void DSP_Update();
void DSP_SendAIBuffer(unsigned int _Address, unsigned int _Size);
void DSP_Update(int cycles);
void DSP_SendAIBuffer(unsigned int address, int sample_rate);
} // end of namespace PluginDSP

View File

@ -353,7 +353,8 @@ namespace Jit64
const u8* DoJit(u32 emaddress, JitBlock &b)
{
_assert_msg_(DYNA_REC, emaddress != 0, "ERROR - Trying to compile at 0. LR=%08x",LR);
if (emaddress == 0)
PanicAlert("ERROR : Trying to compile at 0. LR=%08x", LR);
u32 size;
js.isLastInstruction = false;

View File

@ -87,12 +87,14 @@ namespace Jit64
if (inst.LK)
AND(32, M(&CR), Imm32(~(0xFF000000)));
#endif
//if (destination == js.compilerPC)
//{
if (destination == js.compilerPC)
{
//PanicAlert("Idle loop detected at %08x", destination);
// CALL(ProtectFunction(&CoreTiming::Idle, 0));
// JMP(Asm::testExceptions, true);
//}
// make idle loops go faster
js.downcountAmount += 8;
}
WriteExit(destination, 0);
}
else {

View File

@ -99,9 +99,6 @@ u32 PPCAnalyst::EvaluateBranchTarget(UGeckoInstruction instr, u32 pc)
u32 PPCAnalyst::AnalyzeFunction(u32 startAddr, SFunction &func)
{
//if (startAddr <0x80000008 || startAddr>0x80000000+Memory::RAM_MASK)
// return 0;
func.name = StringFromFormat("zzz_%08x ??", startAddr);
func.calls.clear();
func.callers.clear();

View File

@ -262,9 +262,8 @@ inline void decodebytesARGB8pass1(u32 *dst, u16 *src, int numpixels)
for (int x = 0; x < numpixels; x++)
{
int val = Common::swap16(src[x]);
int a=val&0xFF;
val>>=8;
int a = val & 0xFF;
val >>= 8;
*dst++ = (a<<16) | (val<<24);
}
}
@ -274,9 +273,8 @@ inline void decodebytesARGB8pass2(u32 *dst, u16 *src, int numpixels)
for (int x = 0; x < numpixels; x++)
{
int val = Common::swap16(src[x]);
int a=val&0xFF;
val>>=8;
int a = val & 0xFF;
val >>= 8;
*dst++ |= (val<<8) | (a<<0);
}
}
@ -419,9 +417,9 @@ PC_TexFormat TexDecoder_Decode(u8 *dst, u8 *src, int width, int height, int texf
for (int x = 0; x < width; x += 4)
{
for (int iy = 0; iy < 4; iy++, src += 8)
decodebytesARGB8pass1((u32*)dst+(y+iy)*width+x, (u16*)src, 4);
decodebytesARGB8pass1((u32*)dst + (y+iy)*width + x, (u16*)src, 4);
for (int iy = 0; iy < 4; iy++, src += 8)
decodebytesARGB8pass2((u32*)dst+(y+iy)*width+x, (u16*)src, 4);
decodebytesARGB8pass2((u32*)dst + (y+iy)*width + x, (u16*)src, 4);
}
}
return PC_TEX_FMT_BGRA32;