mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-26 03:01:50 +01:00
[Core/CD] improved accuracy of CDC interrupt processing (verified on real hardware, cf. Krikzz's mcd-verificator)
This commit is contained in:
parent
79bd0e7582
commit
90c9c730f0
@ -26,6 +26,7 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
|
||||
* improved accuracy of Main-CPU & Sub-CPU access to CDC registers (verified on real hardware, cf. Krikzz's mcd-verificator)
|
||||
* improved accuracy of CDC data transfer to Main-CPU & Sub-CPU (verified on real hardware, cf. Krikzz's mcd-verificator)
|
||||
* improved accuracy of CDC DMA processing (verified on real hardware, cf. Krikzz's mcd-verificator)
|
||||
* improved accuracy of CDC interrupt processing (verified on real hardware, cf. Krikzz's mcd-verificator)
|
||||
* improved emulation of mirrored memory areas
|
||||
* improved savestate format
|
||||
* improved Sub-CPU synchronization with Main-CPU (fixes "Soul Star")
|
||||
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 3.8 MiB After Width: | Height: | Size: 3.8 MiB |
Binary file not shown.
Before Width: | Height: | Size: 4.0 MiB After Width: | Height: | Size: 4.0 MiB |
108
core/cd_hw/cdc.c
108
core/cd_hw/cdc.c
@ -114,6 +114,9 @@ void cdc_reset(void)
|
||||
/* disable CDC DMA */
|
||||
cdc.dma_w = cdc.halted_dma_w = 0;
|
||||
|
||||
/* reset CDC IRQ state */
|
||||
cdc.irq = 0;
|
||||
|
||||
/* clear any pending IRQ */
|
||||
if (scd.pending & (1 << 5))
|
||||
{
|
||||
@ -236,6 +239,8 @@ int cdc_context_load(uint8 *state)
|
||||
break;
|
||||
}
|
||||
|
||||
cdc.irq = ~cdc.ifstat & cdc.ifctrl & (BIT_DTEIEN | BIT_DECIEN);
|
||||
|
||||
return bufferptr;
|
||||
}
|
||||
|
||||
@ -285,15 +290,18 @@ void cdc_dma_init(void)
|
||||
/* Data Transfer End interrupt enabled ? */
|
||||
if (cdc.ifctrl & BIT_DTEIEN)
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* level 5 interrupt enabled ? */
|
||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
||||
/* level 5 interrupt triggered only on CDC /INT falling edge with interrupt enabled on gate-array side */
|
||||
if (!cdc.irq && (scd.regs[0x32>>1].byte.l & 0x20))
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
}
|
||||
|
||||
/* update CDC IRQ state */
|
||||
cdc.irq |= BIT_DTEI;
|
||||
}
|
||||
|
||||
/* set EDT bit (gate-array register $04) */
|
||||
@ -395,15 +403,18 @@ void cdc_dma_update(unsigned int cycles)
|
||||
/* Data Transfer End interrupt enabled ? */
|
||||
if (cdc.ifctrl & BIT_DTEIEN)
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* level 5 interrupt enabled ? */
|
||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
||||
/* level 5 interrupt triggered only on CDC /INT falling edge with interrupt enabled on gate-array side*/
|
||||
if (!cdc.irq && (scd.regs[0x32>>1].byte.l & 0x20))
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
}
|
||||
|
||||
/* update CDC IRQ state */
|
||||
cdc.irq |= BIT_DTEI;
|
||||
}
|
||||
|
||||
/* clear DSR bit & set EDT bit (CD register $04) */
|
||||
@ -455,15 +466,19 @@ void cdc_decoder_update(uint32 header)
|
||||
/* decoder interrupt enabled ? */
|
||||
if (cdc.ifctrl & BIT_DECIEN)
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* level 5 interrupt enabled ? */
|
||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
||||
/* level 5 interrupt triggered only on CDC /INT falling edge with interrupt enabled on gate-array side */
|
||||
/* note: only check DTEI as DECI is cleared automatically between decoder interrupt triggering */
|
||||
if (!(cdc.irq & BIT_DTEI) && (scd.regs[0x32>>1].byte.l & 0x20))
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
}
|
||||
|
||||
/* update CDC IRQ state */
|
||||
cdc.irq |= BIT_DECI;
|
||||
}
|
||||
|
||||
/* buffer RAM write enabled ? */
|
||||
@ -538,25 +553,18 @@ void cdc_reg_w(unsigned char data)
|
||||
{
|
||||
case 0x01: /* IFCTRL */
|
||||
{
|
||||
/* pending interrupts ? */
|
||||
if (((data & BIT_DTEIEN) && !(cdc.ifstat & BIT_DTEI)) ||
|
||||
((data & BIT_DECIEN) && !(cdc.ifstat & BIT_DECI)))
|
||||
/* previous CDC IRQ state */
|
||||
uint8 prev_irq = cdc.irq;
|
||||
|
||||
/* update CDC IRQ state according to DTEIEN and DECIEN bits */
|
||||
cdc.irq = ~cdc.ifstat & data & (BIT_DTEIEN | BIT_DECIEN);
|
||||
|
||||
/* level 5 interrupt is triggered on CDC /INT falling edge if interrupt enabled on gate-array side */
|
||||
if (cdc.irq && !prev_irq && (scd.regs[0x32>>1].byte.l & 0x20))
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* level 5 interrupt enabled ? */
|
||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
||||
{
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
}
|
||||
}
|
||||
else if (scd.pending & (1 << 5))
|
||||
{
|
||||
/* clear pending level 5 interrupts */
|
||||
scd.pending &= ~(1 << 5);
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
}
|
||||
@ -617,17 +625,8 @@ void cdc_reg_w(unsigned char data)
|
||||
/* clear pending data transfer end interrupt */
|
||||
cdc.ifstat |= BIT_DTEI;
|
||||
|
||||
#if 0
|
||||
/* no pending decoder interrupt ? */
|
||||
if ((cdc.ifstat | BIT_DECI) || !(cdc.ifctrl & BIT_DECIEN))
|
||||
{
|
||||
/* clear pending level 5 interrupt */
|
||||
scd.pending &= ~(1 << 5);
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
}
|
||||
#endif
|
||||
/* update CDC IRQ state */
|
||||
cdc.irq &= ~BIT_DTEI;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -801,18 +800,8 @@ unsigned char cdc_reg_r(void)
|
||||
/* clear pending decoder interrupt */
|
||||
cdc.ifstat |= BIT_DECI;
|
||||
|
||||
#if 0
|
||||
/* no pending data transfer end interrupt */
|
||||
if ((cdc.ifstat | BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN))
|
||||
{
|
||||
/* clear pending level 5 interrupt */
|
||||
scd.pending &= ~(1 << 5);
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* update CDC IRQ state */
|
||||
cdc.irq &= ~BIT_DECI;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -880,15 +869,18 @@ unsigned short cdc_host_r(uint8 cpu_access)
|
||||
/* Data Transfer End interrupt enabled ? */
|
||||
if (cdc.ifctrl & BIT_DTEIEN)
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* level 5 interrupt enabled ? */
|
||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
||||
/* level 5 interrupt triggered only on CDC /INT falling edge with interrupt enabled on gate-array side */
|
||||
if (!cdc.irq && (scd.regs[0x32>>1].byte.l & 0x20))
|
||||
{
|
||||
/* pending level 5 interrupt */
|
||||
scd.pending |= (1 << 5);
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
}
|
||||
|
||||
/* update CDC IRQ state */
|
||||
cdc.irq |= BIT_DTEI;
|
||||
}
|
||||
|
||||
/* set EDT bit (gate-array register $04) */
|
||||
|
@ -60,6 +60,7 @@ typedef struct
|
||||
void (*halted_dma_w)(unsigned int length); /* halted DMA callback */
|
||||
uint8 ram[0x4000 + 2352]; /* 16K external RAM (with one block overhead to handle buffer overrun) */
|
||||
uint8 ar_mask;
|
||||
uint8 irq; /* invert of CDC /INT output */
|
||||
} cdc_t;
|
||||
|
||||
/* Function prototypes */
|
||||
|
@ -2343,24 +2343,18 @@ int scd_68k_irq_ack(int level)
|
||||
error("INT ack level %d (%X)\n", level, s68k.pc);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* level 5 interrupt is normally acknowledged by CDC */
|
||||
if (level != 5)
|
||||
#endif
|
||||
/* clear pending interrupt flag */
|
||||
scd.pending &= ~(1 << level);
|
||||
|
||||
/* level 2 interrupt acknowledge */
|
||||
if (level == 2)
|
||||
{
|
||||
/* clear pending interrupt flag */
|
||||
scd.pending &= ~(1 << level);
|
||||
|
||||
/* level 2 interrupt acknowledge */
|
||||
if (level == 2)
|
||||
{
|
||||
/* clear IFL2 flag */
|
||||
scd.regs[0x00].byte.h &= ~0x01;
|
||||
}
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
/* clear IFL2 flag */
|
||||
scd.regs[0x00].byte.h &= ~0x01;
|
||||
}
|
||||
|
||||
/* update IRQ level */
|
||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||
|
||||
return M68K_INT_ACK_AUTOVECTOR;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user