Skip to content

Commit

Permalink
Merge branch 'ekeeke:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
ds22x authored Feb 6, 2024
2 parents 59cdc56 + e8a6086 commit ecb956d
Show file tree
Hide file tree
Showing 11 changed files with 152 additions and 93 deletions.
2 changes: 2 additions & 0 deletions HISTORY.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ 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 decoder 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")
Expand Down
Binary file modified builds/genesis_plus_gx_libretro.dll
Binary file not shown.
Binary file modified builds/genplus_cube.dol
Binary file not shown.
Binary file modified builds/genplus_wii.dol
Binary file not shown.
170 changes: 108 additions & 62 deletions core/cd_hw/cdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,15 @@ void cdc_reset(void)
cdc.head[1][2] = 0x00;
cdc.head[1][3] = 0x00;

/* reset CDC DMA cycle counter */
cdc.cycles = 0;
/* reset CDC DMA & decoder cycle counters */
cdc.cycles[0] = cdc.cycles[1] = 0;

/* 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))
{
Expand Down Expand Up @@ -173,7 +176,6 @@ int cdc_context_save(uint8 *state)
save_param(&cdc.head, sizeof(cdc.head));
save_param(&cdc.stat, sizeof(cdc.stat));
save_param(&cdc.cycles, sizeof(cdc.cycles));
save_param(&cdc.dma_w, sizeof(cdc.dma_w));
save_param(&cdc.ram, sizeof(cdc.ram));
save_param(&tmp8, 1);

Expand All @@ -195,7 +197,6 @@ int cdc_context_load(uint8 *state)
load_param(&cdc.head, sizeof(cdc.head));
load_param(&cdc.stat, sizeof(cdc.stat));
load_param(&cdc.cycles, sizeof(cdc.cycles));
load_param(&cdc.dma_w, sizeof(cdc.dma_w));
load_param(&cdc.ram, sizeof(cdc.ram));

load_param(&tmp8, 1);
Expand Down Expand Up @@ -236,6 +237,8 @@ int cdc_context_load(uint8 *state)
break;
}

cdc.irq = ~cdc.ifstat & cdc.ifctrl & (BIT_DTEIEN | BIT_DECIEN);

return bufferptr;
}

Expand Down Expand Up @@ -285,15 +288,28 @@ void cdc_dma_init(void)
/* Data Transfer End interrupt enabled ? */
if (cdc.ifctrl & BIT_DTEIEN)
{
/* pending level 5 interrupt */
scd.pending |= (1 << 5);
/* check end of CDC decoder active period */
if ((cdc.irq & BIT_DECI) && (cdc.cycles[0] > cdc.cycles[1]))
{
/* clear pending decoder interrupt */
cdc.ifstat |= BIT_DECI;

/* level 5 interrupt enabled ? */
if (scd.regs[0x32>>1].byte.l & 0x20)
/* update CDC IRQ state */
cdc.irq &= ~BIT_DECI;
}

/* 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) */
Expand Down Expand Up @@ -372,7 +388,7 @@ void cdc_dma_init(void)
void cdc_dma_update(unsigned int cycles)
{
/* max number of bytes that can be transfered */
int dma_bytes = (cycles - cdc.cycles + DMA_CYCLES_PER_BYTE - 1) / DMA_CYCLES_PER_BYTE;
int dma_bytes = (cycles - cdc.cycles[0] + DMA_CYCLES_PER_BYTE - 1) / DMA_CYCLES_PER_BYTE;

/* always process blocks of 8 bytes */
dma_bytes = (dma_bytes / 8) * 8;
Expand All @@ -383,6 +399,9 @@ void cdc_dma_update(unsigned int cycles)
/* transfer remaining bytes using DMA */
cdc.dma_w(cdc.dbc.w + 1);

/* update DMA cycle counter */
cdc.cycles[0] += (cdc.dbc.w + 1) * DMA_CYCLES_PER_BYTE;

/* reset data byte counter (DBCH bits 4-7 should also be set to 1) */
cdc.dbc.w = 0xffff;

Expand All @@ -395,15 +414,28 @@ 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);
/* check end of CDC decoder active period */
if ((cdc.irq & BIT_DECI) && (cdc.cycles[0] > cdc.cycles[1]))
{
/* clear pending decoder interrupt */
cdc.ifstat |= BIT_DECI;

/* level 5 interrupt enabled ? */
if (scd.regs[0x32>>1].byte.l & 0x20)
/* update CDC IRQ state */
cdc.irq &= ~BIT_DECI;
}

/* 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) */
Expand All @@ -413,7 +445,7 @@ void cdc_dma_update(unsigned int cycles)
if (s68k.stopped & (1<<0x04))
{
/* sync SUB-CPU with CDC DMA */
s68k.cycles = cdc.cycles;
s68k.cycles = cdc.cycles[0];

/* restart SUB-CPU */
s68k.stopped = 0;
Expand All @@ -434,7 +466,7 @@ void cdc_dma_update(unsigned int cycles)
cdc.dbc.w -= dma_bytes;

/* update DMA cycle counter */
cdc.cycles += dma_bytes * DMA_CYCLES_PER_BYTE;
cdc.cycles[0] += dma_bytes * DMA_CYCLES_PER_BYTE;
}
}

Expand All @@ -452,18 +484,25 @@ void cdc_decoder_update(uint32 header)
/* pending decoder interrupt */
cdc.ifstat &= ~BIT_DECI;

/* update CDC decoder end cycle (value adjusted for MCD-verificator CDC FLAGS Tests #40 & #41) */
cdc.cycles[1] = s68k.cycles + 269000;

/* 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 ? */
Expand Down Expand Up @@ -538,24 +577,27 @@ 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;

/* check end of CDC decoder active period */
if (s68k.cycles > cdc.cycles[1])
{
/* pending level 5 interrupt */
scd.pending |= (1 << 5);
/* clear pending decoder interrupt */
cdc.ifstat |= BIT_DECI;

/* 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);
}
/* update previous CDC IRQ state */
prev_irq &= ~BIT_DECI;
}
else if (scd.pending & (1 << 5))

/* 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))
{
/* clear pending level 5 interrupts */
scd.pending &= ~(1 << 5);
/* pending level 5 interrupt */
scd.pending |= (1 << 5);

/* update IRQ level */
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
Expand Down Expand Up @@ -606,7 +648,7 @@ void cdc_reg_w(unsigned char data)
cdc_dma_init();

/* initialize DMA cycle counter */
cdc.cycles = s68k.cycles;
cdc.cycles[0] = s68k.cycles;
}

break;
Expand All @@ -617,17 +659,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;
}

Expand Down Expand Up @@ -709,6 +742,16 @@ unsigned char cdc_reg_r(void)
{
case 0x01: /* IFSTAT */
{
/* check end of CDC decoder active period */
if (s68k.cycles > cdc.cycles[1])
{
/* clear pending decoder interrupt */
cdc.ifstat |= BIT_DECI;

/* update CDC IRQ state */
cdc.irq &= ~BIT_DECI;
}

data = cdc.ifstat;
break;
}
Expand Down Expand Up @@ -801,18 +844,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;
}

Expand Down Expand Up @@ -880,15 +913,28 @@ 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);
/* check end of CDC decoder active period */
if ((cdc.irq & BIT_DECI) && (cdc.cycles[0] > cdc.cycles[1]))
{
/* clear pending decoder interrupt */
cdc.ifstat |= BIT_DECI;

/* update CDC IRQ state */
cdc.irq &= ~BIT_DECI;
}

/* 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) */
Expand Down
3 changes: 2 additions & 1 deletion core/cd_hw/cdc.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,12 @@ typedef struct
uint8 ctrl[2];
uint8 head[2][4];
uint8 stat[4];
unsigned int cycles;
int cycles[2];
void (*dma_w)(unsigned int length); /* active 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 ar_mask;
uint8 irq; /* invert of CDC /INT output */
} cdc_t;

/* Function prototypes */
Expand Down
9 changes: 7 additions & 2 deletions core/cd_hw/cdd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Genesis Plus
* CD drive processor & CD-DA fader
*
* Copyright (C) 2012-2023 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2024 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
Expand Down Expand Up @@ -1855,9 +1855,14 @@ void cdd_update(void)
scd.regs[0x36>>1].byte.h = 0x01;
}
}
else
{
/* CDC decoder is still running while disc is not being read (fixes MCD-verificator CDC Flags Test #30) */
cdc_decoder_update(0);
}

/* scanning disc */
else if (cdd.status == CD_SCAN)
if (cdd.status == CD_SCAN)
{
/* current track index */
int index = cdd.index;
Expand Down
2 changes: 1 addition & 1 deletion core/cd_hw/cdd.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Genesis Plus
* CD drive processor & CD-DA fader
*
* Copyright (C) 2012-2023 Eke-Eke (Genesis Plus GX)
* Copyright (C) 2012-2024 Eke-Eke (Genesis Plus GX)
*
* Redistribution and use of this code or any derivative works are permitted
* provided that the following conditions are met:
Expand Down
Loading

0 comments on commit ecb956d

Please sign in to comment.