mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2025-01-13 19:59:07 +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 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 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 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 emulation of mirrored memory areas
|
||||||
* improved savestate format
|
* improved savestate format
|
||||||
* improved Sub-CPU synchronization with Main-CPU (fixes "Soul Star")
|
* 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 */
|
/* disable CDC DMA */
|
||||||
cdc.dma_w = cdc.halted_dma_w = 0;
|
cdc.dma_w = cdc.halted_dma_w = 0;
|
||||||
|
|
||||||
|
/* reset CDC IRQ state */
|
||||||
|
cdc.irq = 0;
|
||||||
|
|
||||||
/* clear any pending IRQ */
|
/* clear any pending IRQ */
|
||||||
if (scd.pending & (1 << 5))
|
if (scd.pending & (1 << 5))
|
||||||
{
|
{
|
||||||
@ -236,6 +239,8 @@ int cdc_context_load(uint8 *state)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cdc.irq = ~cdc.ifstat & cdc.ifctrl & (BIT_DTEIEN | BIT_DECIEN);
|
||||||
|
|
||||||
return bufferptr;
|
return bufferptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,15 +290,18 @@ void cdc_dma_init(void)
|
|||||||
/* Data Transfer End interrupt enabled ? */
|
/* Data Transfer End interrupt enabled ? */
|
||||||
if (cdc.ifctrl & BIT_DTEIEN)
|
if (cdc.ifctrl & BIT_DTEIEN)
|
||||||
{
|
{
|
||||||
/* pending level 5 interrupt */
|
/* level 5 interrupt triggered only on CDC /INT falling edge with interrupt enabled on gate-array side */
|
||||||
scd.pending |= (1 << 5);
|
if (!cdc.irq && (scd.regs[0x32>>1].byte.l & 0x20))
|
||||||
|
|
||||||
/* level 5 interrupt enabled ? */
|
|
||||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
|
||||||
{
|
{
|
||||||
|
/* pending level 5 interrupt */
|
||||||
|
scd.pending |= (1 << 5);
|
||||||
|
|
||||||
/* update IRQ level */
|
/* update IRQ level */
|
||||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
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) */
|
/* set EDT bit (gate-array register $04) */
|
||||||
@ -395,15 +403,18 @@ void cdc_dma_update(unsigned int cycles)
|
|||||||
/* Data Transfer End interrupt enabled ? */
|
/* Data Transfer End interrupt enabled ? */
|
||||||
if (cdc.ifctrl & BIT_DTEIEN)
|
if (cdc.ifctrl & BIT_DTEIEN)
|
||||||
{
|
{
|
||||||
/* pending level 5 interrupt */
|
/* level 5 interrupt triggered only on CDC /INT falling edge with interrupt enabled on gate-array side*/
|
||||||
scd.pending |= (1 << 5);
|
if (!cdc.irq && (scd.regs[0x32>>1].byte.l & 0x20))
|
||||||
|
|
||||||
/* level 5 interrupt enabled ? */
|
|
||||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
|
||||||
{
|
{
|
||||||
|
/* pending level 5 interrupt */
|
||||||
|
scd.pending |= (1 << 5);
|
||||||
|
|
||||||
/* update IRQ level */
|
/* update IRQ level */
|
||||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
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) */
|
/* clear DSR bit & set EDT bit (CD register $04) */
|
||||||
@ -455,15 +466,19 @@ void cdc_decoder_update(uint32 header)
|
|||||||
/* decoder interrupt enabled ? */
|
/* decoder interrupt enabled ? */
|
||||||
if (cdc.ifctrl & BIT_DECIEN)
|
if (cdc.ifctrl & BIT_DECIEN)
|
||||||
{
|
{
|
||||||
/* pending level 5 interrupt */
|
/* level 5 interrupt triggered only on CDC /INT falling edge with interrupt enabled on gate-array side */
|
||||||
scd.pending |= (1 << 5);
|
/* 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))
|
||||||
/* level 5 interrupt enabled ? */
|
|
||||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
|
||||||
{
|
{
|
||||||
|
/* pending level 5 interrupt */
|
||||||
|
scd.pending |= (1 << 5);
|
||||||
|
|
||||||
/* update IRQ level */
|
/* update IRQ level */
|
||||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update CDC IRQ state */
|
||||||
|
cdc.irq |= BIT_DECI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* buffer RAM write enabled ? */
|
/* buffer RAM write enabled ? */
|
||||||
@ -538,25 +553,18 @@ void cdc_reg_w(unsigned char data)
|
|||||||
{
|
{
|
||||||
case 0x01: /* IFCTRL */
|
case 0x01: /* IFCTRL */
|
||||||
{
|
{
|
||||||
/* pending interrupts ? */
|
/* previous CDC IRQ state */
|
||||||
if (((data & BIT_DTEIEN) && !(cdc.ifstat & BIT_DTEI)) ||
|
uint8 prev_irq = cdc.irq;
|
||||||
((data & BIT_DECIEN) && !(cdc.ifstat & BIT_DECI)))
|
|
||||||
|
/* 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 */
|
/* pending level 5 interrupt */
|
||||||
scd.pending |= (1 << 5);
|
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 */
|
/* update IRQ level */
|
||||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
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 */
|
/* clear pending data transfer end interrupt */
|
||||||
cdc.ifstat |= BIT_DTEI;
|
cdc.ifstat |= BIT_DTEI;
|
||||||
|
|
||||||
#if 0
|
/* update CDC IRQ state */
|
||||||
/* no pending decoder interrupt ? */
|
cdc.irq &= ~BIT_DTEI;
|
||||||
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
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,18 +800,8 @@ unsigned char cdc_reg_r(void)
|
|||||||
/* clear pending decoder interrupt */
|
/* clear pending decoder interrupt */
|
||||||
cdc.ifstat |= BIT_DECI;
|
cdc.ifstat |= BIT_DECI;
|
||||||
|
|
||||||
#if 0
|
/* update CDC IRQ state */
|
||||||
/* no pending data transfer end interrupt */
|
cdc.irq &= ~BIT_DECI;
|
||||||
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
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,15 +869,18 @@ unsigned short cdc_host_r(uint8 cpu_access)
|
|||||||
/* Data Transfer End interrupt enabled ? */
|
/* Data Transfer End interrupt enabled ? */
|
||||||
if (cdc.ifctrl & BIT_DTEIEN)
|
if (cdc.ifctrl & BIT_DTEIEN)
|
||||||
{
|
{
|
||||||
/* pending level 5 interrupt */
|
/* level 5 interrupt triggered only on CDC /INT falling edge with interrupt enabled on gate-array side */
|
||||||
scd.pending |= (1 << 5);
|
if (!cdc.irq && (scd.regs[0x32>>1].byte.l & 0x20))
|
||||||
|
|
||||||
/* level 5 interrupt enabled ? */
|
|
||||||
if (scd.regs[0x32>>1].byte.l & 0x20)
|
|
||||||
{
|
{
|
||||||
|
/* pending level 5 interrupt */
|
||||||
|
scd.pending |= (1 << 5);
|
||||||
|
|
||||||
/* update IRQ level */
|
/* update IRQ level */
|
||||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
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) */
|
/* set EDT bit (gate-array register $04) */
|
||||||
|
@ -60,6 +60,7 @@ typedef struct
|
|||||||
void (*halted_dma_w)(unsigned int length); /* halted DMA callback */
|
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 ram[0x4000 + 2352]; /* 16K external RAM (with one block overhead to handle buffer overrun) */
|
||||||
uint8 ar_mask;
|
uint8 ar_mask;
|
||||||
|
uint8 irq; /* invert of CDC /INT output */
|
||||||
} cdc_t;
|
} cdc_t;
|
||||||
|
|
||||||
/* Function prototypes */
|
/* Function prototypes */
|
||||||
|
@ -2343,24 +2343,18 @@ int scd_68k_irq_ack(int level)
|
|||||||
error("INT ack level %d (%X)\n", level, s68k.pc);
|
error("INT ack level %d (%X)\n", level, s68k.pc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
/* clear pending interrupt flag */
|
||||||
/* level 5 interrupt is normally acknowledged by CDC */
|
scd.pending &= ~(1 << level);
|
||||||
if (level != 5)
|
|
||||||
#endif
|
/* level 2 interrupt acknowledge */
|
||||||
|
if (level == 2)
|
||||||
{
|
{
|
||||||
/* clear pending interrupt flag */
|
/* clear IFL2 flag */
|
||||||
scd.pending &= ~(1 << level);
|
scd.regs[0x00].byte.h &= ~0x01;
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* update IRQ level */
|
||||||
|
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||||
|
|
||||||
return M68K_INT_ACK_AUTOVECTOR;
|
return M68K_INT_ACK_AUTOVECTOR;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user