Do ARAM DMA less often, and in larger chunks. hopefully it adds some speed, but probably only a tiny amount.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4865 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
59e7c19380
commit
4927e5607e
|
@ -82,8 +82,8 @@ union UARAMCount
|
|||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
unsigned count : 31;
|
||||
unsigned dir : 1;
|
||||
u32 count : 31;
|
||||
u32 dir : 1; // 0: MRAM -> ARAM 1: ARAM -> MRAM
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -94,21 +94,21 @@ union UDSPControl
|
|||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
unsigned DSPReset : 1; // Write 1 to reset and waits for 0
|
||||
unsigned DSPAssertInt : 1;
|
||||
unsigned DSPHalt : 1;
|
||||
u16 DSPReset : 1; // Write 1 to reset and waits for 0
|
||||
u16 DSPAssertInt : 1;
|
||||
u16 DSPHalt : 1;
|
||||
|
||||
unsigned AID : 1;
|
||||
unsigned AID_mask : 1;
|
||||
unsigned ARAM : 1;
|
||||
unsigned ARAM_mask : 1;
|
||||
unsigned DSP : 1;
|
||||
unsigned DSP_mask : 1;
|
||||
u16 AID : 1;
|
||||
u16 AID_mask : 1;
|
||||
u16 ARAM : 1;
|
||||
u16 ARAM_mask : 1;
|
||||
u16 DSP : 1;
|
||||
u16 DSP_mask : 1;
|
||||
|
||||
unsigned ARAM_DMAState : 1; // DSPGetDMAStatus() uses this flag
|
||||
unsigned unk3 : 1;
|
||||
unsigned DSPInit : 1; // DSPInit() writes to this flag (1 as long as dsp PC is in IROM?)
|
||||
unsigned pad : 4;
|
||||
u16 ARAM_DMAState : 1; // DSPGetDMAStatus() uses this flag
|
||||
u16 unk3 : 1;
|
||||
u16 DSPInit : 1; // DSPInit() writes to this flag (1 as long as dsp PC is in IROM?)
|
||||
u16 pad : 4;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -128,8 +128,8 @@ union UAudioDMAControl
|
|||
u16 Hex;
|
||||
struct
|
||||
{
|
||||
unsigned NumBlocks : 15;
|
||||
unsigned Enable : 1;
|
||||
u16 NumBlocks : 15;
|
||||
u16 Enable : 1;
|
||||
};
|
||||
|
||||
UAudioDMAControl(u16 _Hex = 0) : Hex(_Hex)
|
||||
|
@ -153,21 +153,18 @@ struct AudioDMA
|
|||
}
|
||||
};
|
||||
|
||||
// ARDMA
|
||||
struct ARDMA
|
||||
// ARAM_DMA
|
||||
struct ARAM_DMA
|
||||
{
|
||||
u32 MMAddr;
|
||||
u32 ARAddr;
|
||||
UARAMCount Cnt;
|
||||
bool CntValid[2];
|
||||
|
||||
ARDMA()
|
||||
ARAM_DMA()
|
||||
{
|
||||
MMAddr = 0;
|
||||
ARAddr = 0;
|
||||
Cnt.Hex = 0;
|
||||
CntValid[0] = false;
|
||||
CntValid[1] = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -192,7 +189,7 @@ struct ARAMInfo
|
|||
static ARAMInfo g_ARAM;
|
||||
static DSPState g_dspState;
|
||||
static AudioDMA g_audioDMA;
|
||||
static ARDMA g_arDMA;
|
||||
static ARAM_DMA g_arDMA;
|
||||
static u16 g_AR_SIZE;
|
||||
static u16 g_AR_MODE;
|
||||
static u16 g_AR_REFRESH;
|
||||
|
@ -214,7 +211,7 @@ void DoState(PointerWrap &p)
|
|||
|
||||
|
||||
void UpdateInterrupts();
|
||||
void Update_ARAM_DMA();
|
||||
void Do_ARAM_DMA();
|
||||
void WriteARAM(u8 _iValue, u32 _iAddress);
|
||||
bool Update_DSP_ReadRegister();
|
||||
void Update_DSP_WriteRegister();
|
||||
|
@ -433,16 +430,13 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
case AR_DMA_ARADDR_L:
|
||||
g_arDMA.ARAddr = (g_arDMA.ARAddr & 0xFFFF0000) | (_Value); break;
|
||||
|
||||
case AR_DMA_CNT_H:
|
||||
case AR_DMA_CNT_H:
|
||||
g_arDMA.Cnt.Hex = (g_arDMA.Cnt.Hex & 0xFFFF) | (_Value<<16);
|
||||
g_arDMA.CntValid[0] = true;
|
||||
Update_ARAM_DMA();
|
||||
break;
|
||||
|
||||
case AR_DMA_CNT_L:
|
||||
g_arDMA.Cnt.Hex = (g_arDMA.Cnt.Hex & 0xFFFF0000) | (_Value);
|
||||
g_arDMA.CntValid[1] = true;
|
||||
Update_ARAM_DMA();
|
||||
case AR_DMA_CNT_L:
|
||||
g_arDMA.Cnt.Hex = (g_arDMA.Cnt.Hex & 0xFFFF0000) | (_Value);
|
||||
Do_ARAM_DMA();
|
||||
break;
|
||||
|
||||
// Audio DMA_REGS 0x5030+
|
||||
|
@ -472,39 +466,6 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
}
|
||||
}
|
||||
|
||||
// This happens at 4 khz, since 32 bytes at 4khz = 4 bytes at 32 khz (16bit stereo pcm)
|
||||
void UpdateAudioDMA()
|
||||
{
|
||||
if (g_audioDMA.AudioDMAControl.Enable && g_audioDMA.BlocksLeft)
|
||||
{
|
||||
// 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.
|
||||
|
||||
// AyuanX: let's do it in a bundle to speed up
|
||||
if (g_audioDMA.BlocksLeft == g_audioDMA.AudioDMAControl.NumBlocks)
|
||||
dsp_plugin->DSP_SendAIBuffer(g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks * 8);
|
||||
|
||||
// g_audioDMA.ReadAddress += 32;
|
||||
g_audioDMA.BlocksLeft--;
|
||||
|
||||
if (g_audioDMA.BlocksLeft == 0)
|
||||
{
|
||||
GenerateDSPInterrupt(DSP::INT_AID);
|
||||
// g_audioDMA.ReadAddress = g_audioDMA.SourceAddress;
|
||||
g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks;
|
||||
// DEBUG_LOG(DSPLLE, "ADMA read addresses: %08x", g_audioDMA.ReadAddress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send silence. Yeah, it's a bit of a waste to sample rate convert
|
||||
// silence. or hm. Maybe we shouldn't do this :)
|
||||
// dsp->DSP_SendAIBuffer(0, AudioInterface::GetDSPSampleRate());
|
||||
}
|
||||
}
|
||||
|
||||
void Read32(u32& _uReturnValue, const u32 _iAddress)
|
||||
{
|
||||
INFO_LOG(DSPINTERFACE, "DSPInterface(r32) 0x%08x", _iAddress);
|
||||
|
@ -547,9 +508,8 @@ void Write32(const u32 _iValue, const u32 _iAddress)
|
|||
break;
|
||||
|
||||
case AR_DMA_CNT_H:
|
||||
g_arDMA.Cnt.Hex = _iValue;
|
||||
g_arDMA.CntValid[0] = g_arDMA.CntValid[1] = true;
|
||||
Update_ARAM_DMA();
|
||||
g_arDMA.Cnt.Hex = _iValue;
|
||||
Do_ARAM_DMA();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -593,52 +553,74 @@ void GenerateDSPInterruptFromPlugin(DSPInterruptType type, bool _bSet)
|
|||
0, et_GenerateDSPInterrupt, type | (_bSet<<16));
|
||||
}
|
||||
|
||||
void Update_ARAM_DMA()
|
||||
// This happens at 4 khz, since 32 bytes at 4khz = 4 bytes at 32 khz (16bit stereo pcm)
|
||||
void UpdateAudioDMA()
|
||||
{
|
||||
// check if the count reg is valid
|
||||
if (!g_arDMA.CntValid[0] || !g_arDMA.CntValid[1])
|
||||
return;
|
||||
g_arDMA.CntValid[0] = g_arDMA.CntValid[1] = false;
|
||||
|
||||
INFO_LOG(DSPINTERFACE, "ARAM DMA triggered");
|
||||
|
||||
//TODO: speedup
|
||||
if (g_arDMA.Cnt.dir)
|
||||
if (g_audioDMA.AudioDMAControl.Enable && g_audioDMA.BlocksLeft)
|
||||
{
|
||||
//read from ARAM
|
||||
INFO_LOG(DSPINTERFACE, "DMA copy %08x bytes from ARAM %08x to Mem: %08x",g_arDMA.Cnt.count, g_arDMA.ARAddr, g_arDMA.MMAddr);
|
||||
u32 iMemAddress = g_arDMA.MMAddr;
|
||||
u32 iARAMAddress = g_arDMA.ARAddr;
|
||||
|
||||
// TODO(??): sanity check instead of writing bogus data?
|
||||
for (u32 i = 0; i < g_arDMA.Cnt.count; i++)
|
||||
{
|
||||
u32 tmp = (iARAMAddress < g_ARAM.size) ? g_ARAM.ptr[iARAMAddress] : 0x05050505;
|
||||
Memory::Write_U8(tmp, iMemAddress);
|
||||
// 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.
|
||||
|
||||
iMemAddress++;
|
||||
iARAMAddress++;
|
||||
// AyuanX: let's do it in a bundle to speed up
|
||||
if (g_audioDMA.BlocksLeft == g_audioDMA.AudioDMAControl.NumBlocks)
|
||||
dsp_plugin->DSP_SendAIBuffer(g_audioDMA.SourceAddress, g_audioDMA.AudioDMAControl.NumBlocks * 8);
|
||||
|
||||
// g_audioDMA.ReadAddress += 32;
|
||||
g_audioDMA.BlocksLeft--;
|
||||
|
||||
if (g_audioDMA.BlocksLeft == 0)
|
||||
{
|
||||
GenerateDSPInterrupt(DSP::INT_AID);
|
||||
// g_audioDMA.ReadAddress = g_audioDMA.SourceAddress;
|
||||
g_audioDMA.BlocksLeft = g_audioDMA.AudioDMAControl.NumBlocks;
|
||||
// DEBUG_LOG(DSPLLE, "ADMA read addresses: %08x", g_audioDMA.ReadAddress);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 iMemAddress = g_arDMA.MMAddr;
|
||||
u32 iARAMAddress = g_arDMA.ARAddr;
|
||||
// Send silence. Yeah, it's a bit of a waste to sample rate convert
|
||||
// silence. or hm. Maybe we shouldn't do this :)
|
||||
// dsp->DSP_SendAIBuffer(0, AudioInterface::GetDSPSampleRate());
|
||||
}
|
||||
}
|
||||
|
||||
//write to g_ARAM
|
||||
INFO_LOG(DSPINTERFACE, "DMA copy %08x bytes from Mem %08x to ARAM %08x (sound data loaded)",
|
||||
g_arDMA.Cnt.count, g_arDMA.MMAddr, g_arDMA.ARAddr);
|
||||
for (u32 i = 0; i < g_arDMA.Cnt.count; i++)
|
||||
void Do_ARAM_DMA()
|
||||
{
|
||||
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
|
||||
if (g_arDMA.Cnt.dir)
|
||||
{
|
||||
// ARAM -> MRAM
|
||||
INFO_LOG(DSPINTERFACE, "DMA %08x bytes from ARAM %08x to MRAM %08x",
|
||||
g_arDMA.Cnt.count, g_arDMA.ARAddr, g_arDMA.MMAddr);
|
||||
|
||||
while (g_arDMA.Cnt.count)
|
||||
{
|
||||
if (iARAMAddress < g_ARAM.size)
|
||||
g_ARAM.ptr[iARAMAddress] = Memory::Read_U8(iMemAddress);
|
||||
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr], g_arDMA.MMAddr);
|
||||
g_arDMA.MMAddr += 8;
|
||||
g_arDMA.ARAddr += 8;
|
||||
g_arDMA.Cnt.count -= 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// MRAM -> ARAM
|
||||
INFO_LOG(DSPINTERFACE, "DMA %08x bytes from MRAM %08x to ARAM %08x",
|
||||
g_arDMA.Cnt.count, g_arDMA.MMAddr, g_arDMA.ARAddr);
|
||||
|
||||
iMemAddress++;
|
||||
iARAMAddress++;
|
||||
while (g_arDMA.Cnt.count)
|
||||
{
|
||||
if (g_arDMA.ARAddr < g_ARAM.size)
|
||||
{
|
||||
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
|
||||
g_arDMA.MMAddr += 8;
|
||||
g_arDMA.ARAddr += 8;
|
||||
}
|
||||
g_arDMA.Cnt.count -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
g_arDMA.Cnt.count = 0;
|
||||
GenerateDSPInterrupt(INT_ARAM);
|
||||
}
|
||||
|
||||
|
|
|
@ -443,7 +443,7 @@ void Write_U64(const u64 _Data, const u32 _Address)
|
|||
|
||||
WriteToHardware<u64>(_Address, _Data, _Address + 4, FLAG_WRITE);
|
||||
}
|
||||
void Write_U64_Swap(const u32 _Data, const u32 _Address) {
|
||||
void Write_U64_Swap(const u64 _Data, const u32 _Address) {
|
||||
Write_U64(Common::swap64(_Data), _Address);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue