mirror of https://github.com/PCSX2/pcsx2.git
parent
b7f5404062
commit
f07ca859e5
|
@ -146,7 +146,7 @@ void psxRcntInit()
|
|||
psxCounters[4].interrupt = 0x08000;
|
||||
psxCounters[5].interrupt = 0x10000;
|
||||
|
||||
psxCounters[6].rate = 768 * 12;
|
||||
psxCounters[6].rate = 768; // One SPU tick
|
||||
psxCounters[6].CycleT = psxCounters[6].rate;
|
||||
psxCounters[6].mode = 0x8;
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore)
|
|||
//Console.Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT);
|
||||
|
||||
psxCounters[6].sCycleT = psxRegs.cycle;
|
||||
psxCounters[6].CycleT = size * 3;
|
||||
psxCounters[6].CycleT = size * 2;
|
||||
|
||||
psxNextCounter -= (psxRegs.cycle - psxNextsCounter);
|
||||
psxNextsCounter = psxRegs.cycle;
|
||||
|
|
|
@ -146,6 +146,7 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz)
|
|||
{
|
||||
TSA = 0x2000 + (Index << 10);
|
||||
DMAICounter = size;
|
||||
LastClock = lClocks;
|
||||
}
|
||||
else if (size >= 512)
|
||||
{
|
||||
|
@ -169,13 +170,17 @@ void V_Core::StartADMAWrite(u16* pMem, u32 sz)
|
|||
#endif
|
||||
// Klonoa 2
|
||||
if (size == 512)
|
||||
{
|
||||
DMAICounter = size;
|
||||
LastClock = lClocks;
|
||||
}
|
||||
}
|
||||
|
||||
AdmaInProgress = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LastClock = lClocks;
|
||||
InputDataLeft = 0;
|
||||
DMAICounter = 1;
|
||||
}
|
||||
|
@ -271,7 +276,7 @@ void V_Core::PlainDMAWrite(u16* pMem, u32 size)
|
|||
// 0x2800? Hard to know for sure (almost no games depend on this)
|
||||
|
||||
memcpy(GetMemPtr(0), &pMem[buff1size], buff2end * 2);
|
||||
TDA = (buff2end + 1) & 0xfffff;
|
||||
TDA = (buff2end) & 0xfffff;
|
||||
|
||||
// Flag interrupt? If IRQA occurs between start and dest, flag it.
|
||||
// Important: Test both core IRQ settings for either DMA!
|
||||
|
@ -292,7 +297,7 @@ void V_Core::PlainDMAWrite(u16* pMem, u32 size)
|
|||
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA || Cores[i].IRQA <= TDA))
|
||||
{
|
||||
//ConLog("DMAwrite Core %d: IRQ Called (IRQ passed). IRQA = %x Cycles = %d\n", i, Cores[i].IRQA, Cycles );
|
||||
SetIrqCall(i);
|
||||
SetIrqCallDMA(i);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -307,7 +312,7 @@ void V_Core::PlainDMAWrite(u16* pMem, u32 size)
|
|||
// Buffer doesn't wrap/overflow!
|
||||
// Just set the TDA and check for an IRQ...
|
||||
|
||||
TDA = (buff1end + 1) & 0xfffff;
|
||||
TDA = (buff1end) & 0xfffff;
|
||||
|
||||
// Flag interrupt? If IRQA occurs between start and dest, flag it.
|
||||
// Important: Test both core IRQ settings for either DMA!
|
||||
|
@ -318,7 +323,7 @@ void V_Core::PlainDMAWrite(u16* pMem, u32 size)
|
|||
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA && Cores[i].IRQA <= TDA))
|
||||
{
|
||||
//ConLog("DMAwrite Core %d: IRQ Called (IRQ passed). IRQA = %x Cycles = %d\n", i, Cores[i].IRQA, Cycles );
|
||||
SetIrqCall(i);
|
||||
SetIrqCallDMA(i);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
@ -328,7 +333,7 @@ void V_Core::PlainDMAWrite(u16* pMem, u32 size)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
LastClock = lClocks;
|
||||
TSA = TDA;
|
||||
DMAICounter = size;
|
||||
TADR = MADR + (size << 1);
|
||||
|
@ -369,7 +374,7 @@ void V_Core::FinishDMAread()
|
|||
{
|
||||
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA || Cores[i].IRQA <= TDA))
|
||||
{
|
||||
SetIrqCall(i);
|
||||
SetIrqCallDMA(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -387,7 +392,7 @@ void V_Core::FinishDMAread()
|
|||
{
|
||||
if (Cores[i].IRQEnable && (Cores[i].IRQA > TSA && Cores[i].IRQA <= TDA))
|
||||
{
|
||||
SetIrqCall(i);
|
||||
SetIrqCallDMA(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -402,9 +407,10 @@ void V_Core::DoDMAread(u16* pMem, u32 size)
|
|||
DMARPtr = pMem;
|
||||
ReadSize = size;
|
||||
IsDMARead = true;
|
||||
|
||||
LastClock = lClocks;
|
||||
DMAICounter = size;
|
||||
Regs.STATX &= ~0x80;
|
||||
Regs.STATX |= 0x400;
|
||||
//Regs.ATTR |= 0x30;
|
||||
TADR = MADR + (size << 1);
|
||||
}
|
||||
|
@ -418,7 +424,7 @@ void V_Core::DoDMAwrite(u16* pMem, u32 size)
|
|||
Regs.STATX &= ~0x80;
|
||||
//Regs.ATTR |= 0x30;
|
||||
DMAICounter = 1;
|
||||
|
||||
LastClock = lClocks;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -449,11 +455,12 @@ void V_Core::DoDMAwrite(u16* pMem, u32 size)
|
|||
{
|
||||
if (MsgDMA())
|
||||
ConLog("* SPU2: DMA%c Transfer of %d bytes to %x (%02x %x %04x). IRQE = %d IRQA = %x \n",
|
||||
GetDmaIndexChar(), size << 1, TSA, DMABits, AutoDMACtrl, (~Regs.ATTR) & 0x7fff,
|
||||
Cores[0].IRQEnable, Cores[0].IRQA);
|
||||
GetDmaIndexChar(), size << 1, TSA, DMABits, AutoDMACtrl, Regs.ATTR & 0x7fff,
|
||||
Cores[Index].IRQEnable, Cores[Index].IRQA);
|
||||
|
||||
PlainDMAWrite(pMem, size);
|
||||
}
|
||||
Regs.STATX &= ~0x80;
|
||||
Regs.STATX |= 0x400;
|
||||
//Regs.ATTR |= 0x30;
|
||||
}
|
||||
|
|
|
@ -401,6 +401,7 @@ struct V_Core
|
|||
s8 NoiseClk; // Noise Clock
|
||||
u16 AutoDMACtrl; // AutoDMA Status
|
||||
s32 DMAICounter; // DMA Interrupt Counter
|
||||
u32 LastClock; // DMA Interrupt Clock Cycle Counter
|
||||
u32 InputDataLeft; // Input Buffer
|
||||
u32 InputPosRead;
|
||||
u32 InputPosWrite;
|
||||
|
@ -549,6 +550,7 @@ extern s16* _spu2mem;
|
|||
extern int PlayMode;
|
||||
|
||||
extern void SetIrqCall(int core);
|
||||
extern void SetIrqCallDMA(int core);
|
||||
extern void StartVoices(int core, u32 value);
|
||||
extern void StopVoices(int core, u32 value);
|
||||
extern void InitADSR();
|
||||
|
|
|
@ -133,14 +133,16 @@ void SPU2interruptDMA4()
|
|||
{
|
||||
FileLog("[%10d] SPU2 interruptDMA4\n", Cycles);
|
||||
Cores[0].Regs.STATX |= 0x80;
|
||||
//Cores[0].Regs.ATTR &= ~0x30;
|
||||
Cores[0].Regs.STATX &= ~0x400;
|
||||
Cores[0].Regs.ATTR &= ~0x30;
|
||||
}
|
||||
|
||||
void SPU2interruptDMA7()
|
||||
{
|
||||
FileLog("[%10d] SPU2 interruptDMA7\n", Cycles);
|
||||
Cores[1].Regs.STATX |= 0x80;
|
||||
//Cores[1].Regs.ATTR &= ~0x30;
|
||||
Cores[1].Regs.STATX &= ~0x400;
|
||||
Cores[1].Regs.ATTR &= ~0x30;
|
||||
}
|
||||
|
||||
void SPU2readDMA7Mem(u16* pMem, u32 size)
|
||||
|
|
|
@ -40,7 +40,8 @@ u32 Cycles;
|
|||
|
||||
int PlayMode;
|
||||
|
||||
bool has_to_call_irq = false;
|
||||
bool has_to_call_irq[2] = { false, false };
|
||||
bool has_to_call_irq_dma[2] = { false, false };
|
||||
|
||||
bool psxmode = false;
|
||||
|
||||
|
@ -48,10 +49,14 @@ void SetIrqCall(int core)
|
|||
{
|
||||
// reset by an irq disable/enable cycle, behaviour found by
|
||||
// test programs that bizarrely only fired one interrupt
|
||||
if (Spdif.Info & 4 << core)
|
||||
return;
|
||||
Spdif.Info |= 4 << core;
|
||||
has_to_call_irq = true;
|
||||
has_to_call_irq[core] = true;
|
||||
}
|
||||
|
||||
void SetIrqCallDMA(int core)
|
||||
{
|
||||
// reset by an irq disable/enable cycle, behaviour found by
|
||||
// test programs that bizarrely only fired one interrupt
|
||||
has_to_call_irq_dma[core] = true;
|
||||
}
|
||||
|
||||
__forceinline s16* GetMemPtr(u32 addr)
|
||||
|
@ -340,6 +345,7 @@ bool V_Voice::Start()
|
|||
ADSR.Phase = 1;
|
||||
SCurrent = 28;
|
||||
LoopMode = 0;
|
||||
SP = 0;
|
||||
LoopFlags = 0;
|
||||
NextA = StartA | 1;
|
||||
Prev1 = 0;
|
||||
|
@ -395,60 +401,93 @@ __forceinline void TimeUpdate(u32 cClocks)
|
|||
else
|
||||
TickInterval = 768; // Reset to default, in case the user hotswitched from async to something else.
|
||||
|
||||
//Update DMA4 interrupt delay counter
|
||||
if (Cores[0].DMAICounter > 0 && (cClocks - Cores[0].LastClock) > 0)
|
||||
{
|
||||
const u32 amt = std::min(cClocks - Cores[0].LastClock, (u32)Cores[0].DMAICounter);
|
||||
Cores[0].DMAICounter -= amt;
|
||||
Cores[0].LastClock = cClocks;
|
||||
Cores[0].MADR += amt * 2;
|
||||
if (Cores[0].DMAICounter <= 0)
|
||||
{
|
||||
if (Cores[0].IsDMARead)
|
||||
Cores[0].FinishDMAread();
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (has_to_call_irq_dma[i])
|
||||
{
|
||||
//ConLog("* SPU2: Irq Called (%04x) at cycle %d.\n", Spdif.Info, Cycles);
|
||||
has_to_call_irq_dma[i] = false;
|
||||
if (!(Spdif.Info & (4 << i)))
|
||||
{
|
||||
Spdif.Info |= (4 << i);
|
||||
if (!SPU2_dummy_callback)
|
||||
spu2Irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ConLog("counter set and callback!\n");
|
||||
Cores[0].DMAICounter = 0;
|
||||
if (!SPU2_dummy_callback)
|
||||
spu2DMA4Irq();
|
||||
else
|
||||
SPU2interruptDMA4();
|
||||
}
|
||||
}
|
||||
|
||||
//Update DMA7 interrupt delay counter
|
||||
if (Cores[1].DMAICounter > 0 && (cClocks - Cores[1].LastClock) > 0)
|
||||
{
|
||||
const u32 amt = std::min(cClocks - Cores[1].LastClock, (u32)Cores[1].DMAICounter);
|
||||
Cores[1].DMAICounter -= amt;
|
||||
Cores[1].LastClock = cClocks;
|
||||
Cores[1].MADR += amt * 2;
|
||||
if (Cores[1].DMAICounter <= 0)
|
||||
{
|
||||
if (Cores[1].IsDMARead)
|
||||
Cores[1].FinishDMAread();
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
if (has_to_call_irq_dma[i])
|
||||
{
|
||||
//ConLog("* SPU2: Irq Called (%04x) at cycle %d.\n", Spdif.Info, Cycles);
|
||||
has_to_call_irq_dma[i] = false;
|
||||
if (!(Spdif.Info & (4 << i)))
|
||||
{
|
||||
Spdif.Info |= (4 << i);
|
||||
if (!SPU2_dummy_callback)
|
||||
spu2Irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cores[1].DMAICounter = 0;
|
||||
//ConLog( "* SPU2 > DMA 7 Callback! %d\n", Cycles );
|
||||
if (!SPU2_dummy_callback)
|
||||
spu2DMA7Irq();
|
||||
else
|
||||
SPU2interruptDMA7();
|
||||
}
|
||||
}
|
||||
|
||||
//Update Mixing Progress
|
||||
while (dClocks >= TickInterval)
|
||||
{
|
||||
if (has_to_call_irq)
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
//ConLog("* SPU2: Irq Called (%04x) at cycle %d.\n", Spdif.Info, Cycles);
|
||||
has_to_call_irq = false;
|
||||
if (!SPU2_dummy_callback)
|
||||
spu2Irq();
|
||||
}
|
||||
|
||||
//Update DMA4 interrupt delay counter
|
||||
if (Cores[0].DMAICounter > 0)
|
||||
{
|
||||
Cores[0].DMAICounter -= TickInterval;
|
||||
if (Cores[0].DMAICounter <= 0)
|
||||
if (has_to_call_irq[i])
|
||||
{
|
||||
if (Cores[0].IsDMARead)
|
||||
Cores[0].FinishDMAread();
|
||||
|
||||
//ConLog("counter set and callback!\n");
|
||||
Cores[0].MADR = Cores[0].TADR;
|
||||
Cores[0].DMAICounter = 0;
|
||||
if (!SPU2_dummy_callback)
|
||||
spu2DMA4Irq();
|
||||
else
|
||||
SPU2interruptDMA4();
|
||||
}
|
||||
else
|
||||
{
|
||||
Cores[0].MADR += TickInterval << 1;
|
||||
}
|
||||
}
|
||||
|
||||
//Update DMA7 interrupt delay counter
|
||||
if (Cores[1].DMAICounter > 0)
|
||||
{
|
||||
Cores[1].DMAICounter -= TickInterval;
|
||||
if (Cores[1].DMAICounter <= 0)
|
||||
{
|
||||
if (Cores[1].IsDMARead)
|
||||
Cores[1].FinishDMAread();
|
||||
|
||||
Cores[1].MADR = Cores[1].TADR;
|
||||
Cores[1].DMAICounter = 0;
|
||||
//ConLog( "* SPU2 > DMA 7 Callback! %d\n", Cycles );
|
||||
if (!SPU2_dummy_callback)
|
||||
spu2DMA7Irq();
|
||||
else
|
||||
SPU2interruptDMA7();
|
||||
}
|
||||
else
|
||||
{
|
||||
Cores[1].MADR += TickInterval << 1;
|
||||
//ConLog("* SPU2: Irq Called (%04x) at cycle %d.\n", Spdif.Info, Cycles);
|
||||
has_to_call_irq[i] = false;
|
||||
if (!(Spdif.Info & (4 << i)))
|
||||
{
|
||||
Spdif.Info |= (4 << i);
|
||||
if (!SPU2_dummy_callback)
|
||||
spu2Irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue