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;
|
u32 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned count : 31;
|
u32 count : 31;
|
||||||
unsigned dir : 1;
|
u32 dir : 1; // 0: MRAM -> ARAM 1: ARAM -> MRAM
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -94,21 +94,21 @@ union UDSPControl
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned DSPReset : 1; // Write 1 to reset and waits for 0
|
u16 DSPReset : 1; // Write 1 to reset and waits for 0
|
||||||
unsigned DSPAssertInt : 1;
|
u16 DSPAssertInt : 1;
|
||||||
unsigned DSPHalt : 1;
|
u16 DSPHalt : 1;
|
||||||
|
|
||||||
unsigned AID : 1;
|
u16 AID : 1;
|
||||||
unsigned AID_mask : 1;
|
u16 AID_mask : 1;
|
||||||
unsigned ARAM : 1;
|
u16 ARAM : 1;
|
||||||
unsigned ARAM_mask : 1;
|
u16 ARAM_mask : 1;
|
||||||
unsigned DSP : 1;
|
u16 DSP : 1;
|
||||||
unsigned DSP_mask : 1;
|
u16 DSP_mask : 1;
|
||||||
|
|
||||||
unsigned ARAM_DMAState : 1; // DSPGetDMAStatus() uses this flag
|
u16 ARAM_DMAState : 1; // DSPGetDMAStatus() uses this flag
|
||||||
unsigned unk3 : 1;
|
u16 unk3 : 1;
|
||||||
unsigned DSPInit : 1; // DSPInit() writes to this flag (1 as long as dsp PC is in IROM?)
|
u16 DSPInit : 1; // DSPInit() writes to this flag (1 as long as dsp PC is in IROM?)
|
||||||
unsigned pad : 4;
|
u16 pad : 4;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -128,8 +128,8 @@ union UAudioDMAControl
|
||||||
u16 Hex;
|
u16 Hex;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned NumBlocks : 15;
|
u16 NumBlocks : 15;
|
||||||
unsigned Enable : 1;
|
u16 Enable : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
UAudioDMAControl(u16 _Hex = 0) : Hex(_Hex)
|
UAudioDMAControl(u16 _Hex = 0) : Hex(_Hex)
|
||||||
|
@ -153,21 +153,18 @@ struct AudioDMA
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ARDMA
|
// ARAM_DMA
|
||||||
struct ARDMA
|
struct ARAM_DMA
|
||||||
{
|
{
|
||||||
u32 MMAddr;
|
u32 MMAddr;
|
||||||
u32 ARAddr;
|
u32 ARAddr;
|
||||||
UARAMCount Cnt;
|
UARAMCount Cnt;
|
||||||
bool CntValid[2];
|
|
||||||
|
|
||||||
ARDMA()
|
ARAM_DMA()
|
||||||
{
|
{
|
||||||
MMAddr = 0;
|
MMAddr = 0;
|
||||||
ARAddr = 0;
|
ARAddr = 0;
|
||||||
Cnt.Hex = 0;
|
Cnt.Hex = 0;
|
||||||
CntValid[0] = false;
|
|
||||||
CntValid[1] = false;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -192,7 +189,7 @@ struct ARAMInfo
|
||||||
static ARAMInfo g_ARAM;
|
static ARAMInfo g_ARAM;
|
||||||
static DSPState g_dspState;
|
static DSPState g_dspState;
|
||||||
static AudioDMA g_audioDMA;
|
static AudioDMA g_audioDMA;
|
||||||
static ARDMA g_arDMA;
|
static ARAM_DMA g_arDMA;
|
||||||
static u16 g_AR_SIZE;
|
static u16 g_AR_SIZE;
|
||||||
static u16 g_AR_MODE;
|
static u16 g_AR_MODE;
|
||||||
static u16 g_AR_REFRESH;
|
static u16 g_AR_REFRESH;
|
||||||
|
@ -214,7 +211,7 @@ void DoState(PointerWrap &p)
|
||||||
|
|
||||||
|
|
||||||
void UpdateInterrupts();
|
void UpdateInterrupts();
|
||||||
void Update_ARAM_DMA();
|
void Do_ARAM_DMA();
|
||||||
void WriteARAM(u8 _iValue, u32 _iAddress);
|
void WriteARAM(u8 _iValue, u32 _iAddress);
|
||||||
bool Update_DSP_ReadRegister();
|
bool Update_DSP_ReadRegister();
|
||||||
void Update_DSP_WriteRegister();
|
void Update_DSP_WriteRegister();
|
||||||
|
@ -433,16 +430,13 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||||
case AR_DMA_ARADDR_L:
|
case AR_DMA_ARADDR_L:
|
||||||
g_arDMA.ARAddr = (g_arDMA.ARAddr & 0xFFFF0000) | (_Value); break;
|
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.Cnt.Hex = (g_arDMA.Cnt.Hex & 0xFFFF) | (_Value<<16);
|
||||||
g_arDMA.CntValid[0] = true;
|
|
||||||
Update_ARAM_DMA();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AR_DMA_CNT_L:
|
case AR_DMA_CNT_L:
|
||||||
g_arDMA.Cnt.Hex = (g_arDMA.Cnt.Hex & 0xFFFF0000) | (_Value);
|
g_arDMA.Cnt.Hex = (g_arDMA.Cnt.Hex & 0xFFFF0000) | (_Value);
|
||||||
g_arDMA.CntValid[1] = true;
|
Do_ARAM_DMA();
|
||||||
Update_ARAM_DMA();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Audio DMA_REGS 0x5030+
|
// 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)
|
void Read32(u32& _uReturnValue, const u32 _iAddress)
|
||||||
{
|
{
|
||||||
INFO_LOG(DSPINTERFACE, "DSPInterface(r32) 0x%08x", _iAddress);
|
INFO_LOG(DSPINTERFACE, "DSPInterface(r32) 0x%08x", _iAddress);
|
||||||
|
@ -547,9 +508,8 @@ void Write32(const u32 _iValue, const u32 _iAddress)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AR_DMA_CNT_H:
|
case AR_DMA_CNT_H:
|
||||||
g_arDMA.Cnt.Hex = _iValue;
|
g_arDMA.Cnt.Hex = _iValue;
|
||||||
g_arDMA.CntValid[0] = g_arDMA.CntValid[1] = true;
|
Do_ARAM_DMA();
|
||||||
Update_ARAM_DMA();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -593,52 +553,74 @@ void GenerateDSPInterruptFromPlugin(DSPInterruptType type, bool _bSet)
|
||||||
0, et_GenerateDSPInterrupt, type | (_bSet<<16));
|
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_audioDMA.AudioDMAControl.Enable && g_audioDMA.BlocksLeft)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
//read from ARAM
|
// Read audio at g_audioDMA.ReadAddress in RAM and push onto an
|
||||||
INFO_LOG(DSPINTERFACE, "DMA copy %08x bytes from ARAM %08x to Mem: %08x",g_arDMA.Cnt.count, g_arDMA.ARAddr, g_arDMA.MMAddr);
|
// external audio fifo in the emulator, to be mixed with the disc
|
||||||
u32 iMemAddress = g_arDMA.MMAddr;
|
// streaming output. If that audio queue fills up, we delay the
|
||||||
u32 iARAMAddress = g_arDMA.ARAddr;
|
// emulator.
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
iMemAddress++;
|
// AyuanX: let's do it in a bundle to speed up
|
||||||
iARAMAddress++;
|
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
|
else
|
||||||
{
|
{
|
||||||
u32 iMemAddress = g_arDMA.MMAddr;
|
// Send silence. Yeah, it's a bit of a waste to sample rate convert
|
||||||
u32 iARAMAddress = g_arDMA.ARAddr;
|
// silence. or hm. Maybe we shouldn't do this :)
|
||||||
|
// dsp->DSP_SendAIBuffer(0, AudioInterface::GetDSPSampleRate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//write to g_ARAM
|
void Do_ARAM_DMA()
|
||||||
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);
|
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
|
||||||
for (u32 i = 0; i < g_arDMA.Cnt.count; i++)
|
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)
|
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr], g_arDMA.MMAddr);
|
||||||
g_ARAM.ptr[iARAMAddress] = Memory::Read_U8(iMemAddress);
|
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++;
|
while (g_arDMA.Cnt.count)
|
||||||
iARAMAddress++;
|
{
|
||||||
|
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);
|
GenerateDSPInterrupt(INT_ARAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -443,7 +443,7 @@ void Write_U64(const u64 _Data, const u32 _Address)
|
||||||
|
|
||||||
WriteToHardware<u64>(_Address, _Data, _Address + 4, FLAG_WRITE);
|
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);
|
Write_U64(Common::swap64(_Data), _Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue