Added preliminary support for ARAM memory map mode "4".
Fixes issue 3410.
This commit is contained in:
parent
2540fe0606
commit
1b15cd0b60
|
@ -354,7 +354,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
|||
|
||||
// AI
|
||||
case AUDIO_DMA_BLOCKS_LEFT:
|
||||
_uReturnValue = g_audioDMA.BlocksLeft - 1; // AUDIO_DMA_BLOCKS_LEFT is zero based
|
||||
_uReturnValue = g_audioDMA.BlocksLeft > 0 ? g_audioDMA.BlocksLeft - 1 : 0; // AUDIO_DMA_BLOCKS_LEFT is zero based
|
||||
break;
|
||||
|
||||
case AUDIO_DMA_START_LO:
|
||||
|
@ -435,7 +435,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
if (tmpControl.ARAM) g_dspState.DSPControl.ARAM = 0;
|
||||
if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0;
|
||||
|
||||
// g_ARAM
|
||||
// g_ARAM (line below should be commented out to emulate the DMA wait time)
|
||||
g_dspState.DSPControl.DMAState = 0; // keep g_ARAM DMA State zero
|
||||
|
||||
// unknown
|
||||
|
@ -453,14 +453,30 @@ void Write16(const u16 _Value, const u32 _Address)
|
|||
// ARAM
|
||||
// DMA back and forth between ARAM and RAM
|
||||
case AR_INFO:
|
||||
//PanicAlert("write %x %x", _Value,PowerPC::ppcState.pc);
|
||||
//PanicAlert("AR_INFO %x PC: %x", _Value, PowerPC::ppcState.pc);
|
||||
ERROR_LOG(DSPINTERFACE, "AR_INFO %x PC: %x", _Value, PowerPC::ppcState.pc);
|
||||
g_ARAM_Info.Hex = _Value;
|
||||
|
||||
// 0x43
|
||||
// Monster Hunter Tri, DKCR
|
||||
|
||||
// 0x43, 0x63:
|
||||
// Rebel Strike, Clone Wars, WWE DOR2, Mario Golf
|
||||
|
||||
// 0x43, 0x64, 0x63
|
||||
// Transworld Surf, Smashing Drive, SSBM, Cel Damage
|
||||
|
||||
// __OSInitAudioSystem sets to 0x43 -> expects 16bit adressing and mapping to dsp iram?
|
||||
// __OSCheckSize sets = 0x20 | 3 (keeps upper bits)
|
||||
// 0x23 -> Zelda standard mode (standard ARAM access ??)
|
||||
// 0x43 -> Set by __OSInitAudioSystem
|
||||
// 0x58 -> Transworld Surf, Cel Damage, SSBM
|
||||
// 0x60 -> Transworld Surf, Cel Damage, SSBM
|
||||
// 0x63 -> ARCheckSize Mode (access AR-registers ??) or no exception ??
|
||||
// 0x64 -> Transworld Surf, Cel Damage, SSBM
|
||||
|
||||
// 0x00 -> Switch to external ARAM
|
||||
// 0x04 -> Switch to internal ARAM
|
||||
break;
|
||||
|
||||
case AR_MODE:
|
||||
|
@ -621,7 +637,7 @@ void GenerateDSPInterrupt(DSPInterruptType type, bool _bSet)
|
|||
switch (type)
|
||||
{
|
||||
case INT_DSP: g_dspState.DSPControl.DSP = _bSet ? 1 : 0; break;
|
||||
case INT_ARAM: g_dspState.DSPControl.ARAM = _bSet ? 1 : 0; break;
|
||||
case INT_ARAM: g_dspState.DSPControl.ARAM = _bSet ? 1 : 0; if (_bSet) g_dspState.DSPControl.DMAState = 0; break;
|
||||
case INT_AID: g_dspState.DSPControl.AID = _bSet ? 1 : 0; break;
|
||||
}
|
||||
|
||||
|
@ -683,6 +699,9 @@ void Do_ARAM_DMA()
|
|||
// seems like a good estimate
|
||||
CoreTiming::ScheduleEvent_Threadsafe(g_arDMA.Cnt.count >> 1, et_GenerateDSPInterrupt, INT_ARAM | (1<<16));
|
||||
|
||||
// Uncomment the line below to emulate the DMA wait time.
|
||||
//g_dspState.DSPControl.DMAState = 1;
|
||||
|
||||
// Real hardware DMAs in 32byte chunks, but we can get by with 8byte chunks
|
||||
if (g_arDMA.Cnt.dir)
|
||||
{
|
||||
|
@ -694,15 +713,20 @@ void Do_ARAM_DMA()
|
|||
g_arDMA.ARAddr &= 0x3ffffff;
|
||||
g_arDMA.MMAddr &= 0x3ffffff;
|
||||
|
||||
// Transworld Surf (GTVE70) needs this
|
||||
if (g_arDMA.ARAddr > g_ARAM.size)
|
||||
g_arDMA.ARAddr -= g_ARAM.size;
|
||||
|
||||
if (g_arDMA.ARAddr < g_ARAM.size)
|
||||
{
|
||||
while (g_arDMA.Cnt.count)
|
||||
{
|
||||
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & ARAM_MASK], g_arDMA.MMAddr);
|
||||
if ((g_ARAM_Info.Hex & 0xf) == 3)
|
||||
{
|
||||
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask], g_arDMA.MMAddr);
|
||||
}
|
||||
else if ((g_ARAM_Info.Hex & 0xf) == 4)
|
||||
{
|
||||
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask], g_arDMA.MMAddr);
|
||||
}
|
||||
else
|
||||
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask], g_arDMA.MMAddr);
|
||||
g_arDMA.MMAddr += 8;
|
||||
g_arDMA.ARAddr += 8;
|
||||
g_arDMA.Cnt.count -= 8;
|
||||
|
@ -710,7 +734,7 @@ void Do_ARAM_DMA()
|
|||
}
|
||||
else
|
||||
{
|
||||
// Returns zeroes on out of bounds reads (verified on real HW)
|
||||
// Assuming no external ARAM installed; returns zeroes on out of bounds reads (verified on real HW)
|
||||
while (g_arDMA.Cnt.count)
|
||||
{
|
||||
Memory::Write_U64(0, g_arDMA.MMAddr);
|
||||
|
@ -730,15 +754,25 @@ void Do_ARAM_DMA()
|
|||
g_arDMA.ARAddr &= 0x3ffffff;
|
||||
g_arDMA.MMAddr &= 0x3ffffff;
|
||||
|
||||
// Transworld Surf (GTVE70) needs this
|
||||
if (g_arDMA.ARAddr > g_ARAM.size)
|
||||
g_arDMA.ARAddr -= g_ARAM.size;
|
||||
|
||||
if (g_arDMA.ARAddr < g_ARAM.size)
|
||||
{
|
||||
while (g_arDMA.Cnt.count)
|
||||
{
|
||||
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & ARAM_MASK] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
|
||||
if ((g_ARAM_Info.Hex & 0xf) == 3)
|
||||
{
|
||||
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
|
||||
}
|
||||
else if ((g_ARAM_Info.Hex & 0xf) == 4)
|
||||
{
|
||||
if (g_arDMA.ARAddr < 0x400000)
|
||||
{
|
||||
*(u64*)&g_ARAM.ptr[(g_arDMA.ARAddr + 0x400000) & g_ARAM.mask] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
|
||||
}
|
||||
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
|
||||
}
|
||||
else
|
||||
*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr & g_ARAM.mask] = Common::swap64(Memory::Read_U64(g_arDMA.MMAddr));
|
||||
|
||||
g_arDMA.MMAddr += 8;
|
||||
g_arDMA.ARAddr += 8;
|
||||
g_arDMA.Cnt.count -= 8;
|
||||
|
@ -746,7 +780,7 @@ void Do_ARAM_DMA()
|
|||
}
|
||||
else
|
||||
{
|
||||
// Writes nothing to ARAM when out of bounds (verified on real HW)
|
||||
// Assuming no external ARAM installed; writes nothing to ARAM when out of bounds (verified on real HW)
|
||||
g_arDMA.MMAddr += g_arDMA.Cnt.count;
|
||||
g_arDMA.ARAddr += g_arDMA.Cnt.count;
|
||||
g_arDMA.Cnt.count = 0;
|
||||
|
|
|
@ -504,7 +504,7 @@ void CheckExternalExceptions()
|
|||
// clear MSR as specified
|
||||
//MSR &= ~0x04EF36; // 0x04FF36 also clears ME (only for machine check exception)
|
||||
// set to exception type entry point
|
||||
//NPC = 0x80000x00;
|
||||
//NPC = 0x00000x00;
|
||||
|
||||
// EXTERNAL INTERRUPT
|
||||
if (MSR & 0x0008000) //hacky...the exception shouldn't be generated if EE isn't set...
|
||||
|
|
Loading…
Reference in New Issue