Should fix crashes caused by aram dma reading off the end of our aram size.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4958 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Shawn Hoffman 2010-01-25 15:38:58 +00:00
parent e3730a2440
commit cdb829edd5
1 changed files with 59 additions and 49 deletions

View File

@ -60,9 +60,9 @@ enum
DSP_MAIL_FROM_DSP_LO = 0x5006, DSP_MAIL_FROM_DSP_LO = 0x5006,
DSP_CONTROL = 0x500A, DSP_CONTROL = 0x500A,
DSP_INTERRUPT_CONTROL = 0x5010, DSP_INTERRUPT_CONTROL = 0x5010,
AR_SIZE = 0x5012, // These names are a good guess at best AR_INFO = 0x5012, // These names are a good guess at best
AR_MODE = 0x5016, // AR_MODE = 0x5016, //
AR_REFRESH = 0x501a, // AR_REFRESH = 0x501a,
AR_DMA_MMADDR_H = 0x5020, AR_DMA_MMADDR_H = 0x5020,
AR_DMA_MMADDR_L = 0x5022, AR_DMA_MMADDR_L = 0x5022,
AR_DMA_ARADDR_H = 0x5024, AR_DMA_ARADDR_H = 0x5024,
@ -94,20 +94,23 @@ union UDSPControl
u16 Hex; u16 Hex;
struct struct
{ {
// DSP Control
u16 DSPReset : 1; // Write 1 to reset and waits for 0 u16 DSPReset : 1; // Write 1 to reset and waits for 0
u16 DSPAssertInt : 1; u16 DSPAssertInt : 1;
u16 DSPHalt : 1; u16 DSPHalt : 1;
// Interrupt for DMA to the AI/speakers
u16 AID : 1; u16 AID : 1;
u16 AID_mask : 1; u16 AID_mask : 1;
// ARAM DMA interrupt
u16 ARAM : 1; u16 ARAM : 1;
u16 ARAM_mask : 1; u16 ARAM_mask : 1;
// DSP DMA interrupt
u16 DSP : 1; u16 DSP : 1;
u16 DSP_mask : 1; u16 DSP_mask : 1;
// Other ???
u16 ARAM_DMAState : 1; // DSPGetDMAStatus() uses this flag u16 DMAState : 1; // DSPGetDMAStatus() uses this flag. __ARWaitForDMA() uses it too...maybe it's just general DMA flag
u16 unk3 : 1; u16 unk3 : 1;
u16 DSPInit : 1; // DSPInit() writes to this flag (1 as long as dsp PC is in IROM?) u16 DSPInit : 1; // DSPInit() writes to this flag
u16 pad : 4; u16 pad : 4;
}; };
}; };
@ -190,7 +193,21 @@ static ARAMInfo g_ARAM;
static DSPState g_dspState; static DSPState g_dspState;
static AudioDMA g_audioDMA; static AudioDMA g_audioDMA;
static ARAM_DMA g_arDMA; static ARAM_DMA g_arDMA;
static u16 g_AR_SIZE;
union ARAM_Info
{
u16 Hex;
struct
{
u16 size : 6;
u16 unk : 1;
u16 : 9;
};
};
static ARAM_Info g_ARAM_Info;
// Contains bitfields for some stuff we don't care about (and nothing ever reads):
// CAS latency/burst length/addressing mode/write mode
// We care about the LSB tho. It indicates that the ARAM controller has finished initializing
static u16 g_AR_MODE; static u16 g_AR_MODE;
static u16 g_AR_REFRESH; static u16 g_AR_REFRESH;
@ -204,7 +221,7 @@ void DoState(PointerWrap &p)
p.Do(g_dspState); p.Do(g_dspState);
p.Do(g_audioDMA); p.Do(g_audioDMA);
p.Do(g_arDMA); p.Do(g_arDMA);
p.Do(g_AR_SIZE); p.Do(g_ARAM_Info);
p.Do(g_AR_MODE); p.Do(g_AR_MODE);
p.Do(g_AR_REFRESH); p.Do(g_AR_REFRESH);
} }
@ -249,9 +266,9 @@ void Init()
g_dspState.DSPControl.Hex = 0; g_dspState.DSPControl.Hex = 0;
g_dspState.DSPControl.DSPHalt = 1; g_dspState.DSPControl.DSPHalt = 1;
g_AR_SIZE = 0; g_ARAM_Info.Hex = 0;
g_AR_MODE = 1; // Means that aram controller has finished initializing the mem g_AR_MODE = 1; // ARAM Controller has init'd
g_AR_REFRESH = 0; g_AR_REFRESH = 156; // 156MHz
et_GenerateDSPInterrupt = CoreTiming::RegisterEvent("DSPint", GenerateDSPInterrupt_Wrapper); et_GenerateDSPInterrupt = CoreTiming::RegisterEvent("DSPint", GenerateDSPInterrupt_Wrapper);
} }
@ -269,7 +286,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
{ {
switch (_iAddress & 0xFFFF) switch (_iAddress & 0xFFFF)
{ {
// AI_REGS 0x5000+ // DSP
case DSP_MAIL_TO_DSP_HI: case DSP_MAIL_TO_DSP_HI:
_uReturnValue = dsp_plugin->DSP_ReadMailboxHigh(true); _uReturnValue = dsp_plugin->DSP_ReadMailboxHigh(true);
break; break;
@ -291,9 +308,10 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
(dsp_plugin->DSP_ReadControlRegister() & DSP_CONTROL_MASK); (dsp_plugin->DSP_ReadControlRegister() & DSP_CONTROL_MASK);
break; break;
// AR_REGS 0x501x+ // ARAM
case AR_SIZE: case AR_INFO:
_uReturnValue = g_AR_SIZE; PanicAlert("read %x %x", g_ARAM_Info.Hex,PowerPC::ppcState.pc);
_uReturnValue = g_ARAM_Info.Hex;
break; break;
case AR_MODE: case AR_MODE:
@ -311,7 +329,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
case AR_DMA_CNT_H: _uReturnValue = g_arDMA.Cnt.Hex >> 16; return; case AR_DMA_CNT_H: _uReturnValue = g_arDMA.Cnt.Hex >> 16; return;
case AR_DMA_CNT_L: _uReturnValue = g_arDMA.Cnt.Hex & 0xFFFF; return; case AR_DMA_CNT_L: _uReturnValue = g_arDMA.Cnt.Hex & 0xFFFF; return;
// DMA_REGS 0x5030+ // AI
case AUDIO_DMA_BLOCKS_LEFT: case AUDIO_DMA_BLOCKS_LEFT:
_uReturnValue = g_audioDMA.BlocksLeft; _uReturnValue = g_audioDMA.BlocksLeft;
break; break;
@ -345,7 +363,7 @@ void Write16(const u16 _Value, const u32 _Address)
switch (_Address & 0xFFFF) switch (_Address & 0xFFFF)
{ {
// DSP Regs 0x5000+ // DSP
case DSP_MAIL_TO_DSP_HI: case DSP_MAIL_TO_DSP_HI:
dsp_plugin->DSP_WriteMailboxHigh(true, _Value); dsp_plugin->DSP_WriteMailboxHigh(true, _Value);
break; break;
@ -386,7 +404,7 @@ void Write16(const u16 _Value, const u32 _Address)
if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0; if (tmpControl.DSP) g_dspState.DSPControl.DSP = 0;
// g_ARAM // g_ARAM
g_dspState.DSPControl.ARAM_DMAState = 0; // keep g_ARAM DMA State zero g_dspState.DSPControl.DMAState = 0; // keep g_ARAM DMA State zero
// unknown // unknown
g_dspState.DSPControl.unk3 = tmpControl.unk3; g_dspState.DSPControl.unk3 = tmpControl.unk3;
@ -400,16 +418,15 @@ void Write16(const u16 _Value, const u32 _Address)
} }
break; break;
// AR_REGS 0x501x+ // ARAM
// DMA back and forth between ARAM and RAM // DMA back and forth between ARAM and RAM
case AR_SIZE: case AR_INFO:
g_AR_SIZE = _Value; PanicAlert("write %x %x", _Value,PowerPC::ppcState.pc);
// __OSInitAudioSystem sets to 0x43 g_ARAM_Info.Hex = _Value;
// __OSInitAudioSystem sets to 0x43 -> expects 16bit adressing and mapping to dsp iram?
// __OSCheckSize sets = 0x20 | 3 (keeps upper bits) // __OSCheckSize sets = 0x20 | 3 (keeps upper bits)
// 0x23 -> Zelda standard mode (standard ARAM access ??) // 0x23 -> Zelda standard mode (standard ARAM access ??)
// 0x63 -> ARCheckSize Mode (access AR-registers ??) or no exception ?? // 0x63 -> ARCheckSize Mode (access AR-registers ??) or no exception ??
// probably bitfield for: CAS latency/burst length/addressing mode/write mode
// In any case, the aram driver should set it up :}
break; break;
case AR_MODE: case AR_MODE:
@ -436,16 +453,10 @@ void Write16(const u16 _Value, const u32 _Address)
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);
if (g_arDMA.Cnt.count % 8)
{
PanicAlert("DSPINTERFACE: ARAM DMA count: %08x not aligned to 8 bytes!", g_arDMA.Cnt.Hex);
ERROR_LOG(DSPINTERFACE, "ARAM DMA count: %08x not aligned to 8 bytes!", g_arDMA.Cnt.Hex);
}
else
Do_ARAM_DMA(); Do_ARAM_DMA();
break; break;
// Audio DMA_REGS 0x5030+ // AI
// This is the DMA that goes straight out the speaker. // This is the DMA that goes straight out the speaker.
case AUDIO_DMA_START_HI: case AUDIO_DMA_START_HI:
g_audioDMA.SourceAddress = (g_audioDMA.SourceAddress & 0xFFFF) | (_Value<<16); g_audioDMA.SourceAddress = (g_audioDMA.SourceAddress & 0xFFFF) | (_Value<<16);
@ -477,6 +488,7 @@ void Read32(u32& _uReturnValue, const u32 _iAddress)
INFO_LOG(DSPINTERFACE, "DSPInterface(r32) 0x%08x", _iAddress); INFO_LOG(DSPINTERFACE, "DSPInterface(r32) 0x%08x", _iAddress);
switch (_iAddress & 0xFFFF) switch (_iAddress & 0xFFFF)
{ {
// DSP
case DSP_MAIL_TO_DSP_HI: case DSP_MAIL_TO_DSP_HI:
_uReturnValue = (dsp_plugin->DSP_ReadMailboxHigh(true) << 16) | dsp_plugin->DSP_ReadMailboxLow(true); _uReturnValue = (dsp_plugin->DSP_ReadMailboxHigh(true) << 16) | dsp_plugin->DSP_ReadMailboxLow(true);
break; break;
@ -494,17 +506,18 @@ void Write32(const u32 _iValue, const u32 _iAddress)
switch (_iAddress & 0xFFFF) switch (_iAddress & 0xFFFF)
{ {
// DSP
case DSP_MAIL_TO_DSP_HI: case DSP_MAIL_TO_DSP_HI:
dsp_plugin->DSP_WriteMailboxHigh(true, _iValue >> 16); dsp_plugin->DSP_WriteMailboxHigh(true, _iValue >> 16);
dsp_plugin->DSP_WriteMailboxLow(true, (u16)_iValue); dsp_plugin->DSP_WriteMailboxLow(true, (u16)_iValue);
break; break;
// AI
case AUDIO_DMA_START_HI: case AUDIO_DMA_START_HI:
g_audioDMA.SourceAddress = _iValue; g_audioDMA.SourceAddress = _iValue;
break; break;
// AR_REGS - i dont know why they are accessed 32 bit too ... // ARAM
// Answer: simply because they can be
case AR_DMA_MMADDR_H: case AR_DMA_MMADDR_H:
g_arDMA.MMAddr = _iValue; g_arDMA.MMAddr = _iValue;
break; break;
@ -515,12 +528,6 @@ void Write32(const u32 _iValue, const u32 _iAddress)
case AR_DMA_CNT_H: case AR_DMA_CNT_H:
g_arDMA.Cnt.Hex = _iValue; g_arDMA.Cnt.Hex = _iValue;
if (g_arDMA.Cnt.count % 8)
{
PanicAlert("DSPINTERFACE: ARAM DMA count: %08x not aligned to 8 bytes!", g_arDMA.Cnt.Hex);
ERROR_LOG(DSPINTERFACE, "ARAM DMA count: %08x not aligned to 8 bytes!", g_arDMA.Cnt.Hex);
}
else
Do_ARAM_DMA(); Do_ARAM_DMA();
break; break;
@ -608,10 +615,13 @@ void Do_ARAM_DMA()
g_arDMA.Cnt.count, g_arDMA.ARAddr, g_arDMA.MMAddr); g_arDMA.Cnt.count, g_arDMA.ARAddr, g_arDMA.MMAddr);
while (g_arDMA.Cnt.count) while (g_arDMA.Cnt.count)
{
if (g_arDMA.ARAddr < g_ARAM.size)
{ {
Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr], g_arDMA.MMAddr); Memory::Write_U64_Swap(*(u64*)&g_ARAM.ptr[g_arDMA.ARAddr], g_arDMA.MMAddr);
g_arDMA.MMAddr += 8; g_arDMA.MMAddr += 8;
g_arDMA.ARAddr += 8; g_arDMA.ARAddr += 8;
}
g_arDMA.Cnt.count -= 8; g_arDMA.Cnt.count -= 8;
} }
} }