mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2025-01-13 11:49:06 +01:00
[Core/CD] improved accuracy of CDC DMA processing (verified on real hardware, cf. Krikzz's mcd-verificator)
This commit is contained in:
parent
16589b558f
commit
da8e4e547a
@ -24,7 +24,8 @@ Genesis Plus GX 1.7.5 (xx/xx/xxxx) (Eke-Eke)
|
|||||||
* improved Timer interrupt timings and CDD interrupt accuracy (fixes audio stutters during Popful Mail FMV)
|
* improved Timer interrupt timings and CDD interrupt accuracy (fixes audio stutters during Popful Mail FMV)
|
||||||
* improved CDC emulation (fixes random freezes during Jeopardy & ESPN Sunday Night NFL intro)
|
* improved CDC emulation (fixes random freezes during Jeopardy & ESPN Sunday Night NFL intro)
|
||||||
* 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 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 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 |
307
core/cd_hw/cdc.c
307
core/cd_hw/cdc.c
@ -62,8 +62,11 @@
|
|||||||
/* STAT3 register bitmask */
|
/* STAT3 register bitmask */
|
||||||
#define BIT_VALST 0x80
|
#define BIT_VALST 0x80
|
||||||
|
|
||||||
/* TODO: figure exact DMA transfer rate */
|
/* DMA transfer rate */
|
||||||
#define DMA_BYTES_PER_LINE 512
|
/* min. 4 x SUB-CPU cycles (i.e 16 x SCD cycles) per byte (cf https://github.com/MiSTer-devel/MegaCD_MiSTer/tree/master/docs/mcd%20logs) */
|
||||||
|
/* additional delays caused by SUB-CPU access & periodic refresh (all RAM), GPU operation (Word-RAM only) or PCM playback (PCM RAM only) */
|
||||||
|
/* are not emulated */
|
||||||
|
#define DMA_CYCLES_PER_BYTE 16
|
||||||
|
|
||||||
void cdc_init(void)
|
void cdc_init(void)
|
||||||
{
|
{
|
||||||
@ -105,11 +108,11 @@ void cdc_reset(void)
|
|||||||
cdc.head[1][2] = 0x00;
|
cdc.head[1][2] = 0x00;
|
||||||
cdc.head[1][3] = 0x00;
|
cdc.head[1][3] = 0x00;
|
||||||
|
|
||||||
/* reset CDC cycle counter */
|
/* reset CDC DMA cycle counter */
|
||||||
cdc.cycles = 0;
|
cdc.cycles = 0;
|
||||||
|
|
||||||
/* DMA transfer disabled */
|
/* disable CDC DMA */
|
||||||
cdc.dma_w = 0;
|
cdc.dma_w = cdc.halted_dma_w = 0;
|
||||||
|
|
||||||
/* clear any pending IRQ */
|
/* clear any pending IRQ */
|
||||||
if (scd.pending & (1 << 5))
|
if (scd.pending & (1 << 5))
|
||||||
@ -147,12 +150,19 @@ int cdc_context_save(uint8 *state)
|
|||||||
{
|
{
|
||||||
tmp8 = 5;
|
tmp8 = 5;
|
||||||
}
|
}
|
||||||
|
else if (cdc.halted_dma_w == prg_ram_dma_w)
|
||||||
|
{
|
||||||
|
tmp8 = 6;
|
||||||
|
}
|
||||||
|
else if (cdc.halted_dma_w == word_ram_2M_dma_w)
|
||||||
|
{
|
||||||
|
tmp8 = 7;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tmp8 = 0;
|
tmp8 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
save_param(&cdc.ifstat, sizeof(cdc.ifstat));
|
save_param(&cdc.ifstat, sizeof(cdc.ifstat));
|
||||||
save_param(&cdc.ifctrl, sizeof(cdc.ifctrl));
|
save_param(&cdc.ifctrl, sizeof(cdc.ifctrl));
|
||||||
save_param(&cdc.dbc, sizeof(cdc.dbc));
|
save_param(&cdc.dbc, sizeof(cdc.dbc));
|
||||||
@ -194,31 +204,181 @@ int cdc_context_load(uint8 *state)
|
|||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
cdc.dma_w = pcm_ram_dma_w;
|
cdc.dma_w = pcm_ram_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
cdc.dma_w = prg_ram_dma_w;
|
cdc.dma_w = prg_ram_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
cdc.dma_w = word_ram_0_dma_w;
|
cdc.dma_w = word_ram_0_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
cdc.dma_w = word_ram_1_dma_w;
|
cdc.dma_w = word_ram_1_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
cdc.dma_w = word_ram_2M_dma_w;
|
cdc.dma_w = word_ram_2M_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
cdc.dma_w = 0;
|
||||||
|
cdc.halted_dma_w = prg_ram_dma_w;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
cdc.dma_w = 0;
|
||||||
|
cdc.halted_dma_w = word_ram_2M_dma_w;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cdc.dma_w = 0;
|
cdc.dma_w = 0;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bufferptr;
|
return bufferptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cdc_dma_update(void)
|
void cdc_dma_init(void)
|
||||||
{
|
{
|
||||||
|
/* no effect if data transfer is not started */
|
||||||
|
if (cdc.ifstat & BIT_DTEN)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* disable DMA by default */
|
||||||
|
cdc.dma_w = cdc.halted_dma_w = 0;
|
||||||
|
|
||||||
|
/* check data transfer destination */
|
||||||
|
switch (scd.regs[0x04>>1].byte.h & 0x07)
|
||||||
|
{
|
||||||
|
case 2: /* MAIN-CPU host read */
|
||||||
|
case 3: /* SUB-CPU host read */
|
||||||
|
{
|
||||||
|
/* read 16-bit word from CDC RAM buffer (big-endian format) into gate-array register $08 */
|
||||||
|
/* Note: on real-hardware, 16-bit word is not immediately available, cf. https://github.com/MiSTer-devel/MegaCD_MiSTer/blob/master/docs/mcd%20logs/dma_sub_read.jpg for transfer timings */
|
||||||
|
scd.regs[0x08>>1].w = READ_WORD(cdc.ram, cdc.dac.w & 0x3ffe);
|
||||||
|
#ifdef LOG_CDC
|
||||||
|
error("CDC host read 0x%04x -> 0x%04x (dbc=0x%x) (%X)\n", cdc.dac.w, scd.regs[0x08>>1].w, cdc.dbc.w, s68k.pc);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* set DSR bit (gate-array register $04) */
|
||||||
|
scd.regs[0x04>>1].byte.h |= 0x40;
|
||||||
|
|
||||||
|
/* increment data address counter */
|
||||||
|
cdc.dac.w += 2;
|
||||||
|
|
||||||
|
/* decrement data byte counter */
|
||||||
|
cdc.dbc.w -= 2;
|
||||||
|
|
||||||
|
/* end of transfer ? */
|
||||||
|
if ((int16)cdc.dbc.w < 0)
|
||||||
|
{
|
||||||
|
/* reset data byte counter (DBCH bits 4-7 should also be set to 1) */
|
||||||
|
cdc.dbc.w = 0xffff;
|
||||||
|
|
||||||
|
/* clear !DTEN and !DTBSY */
|
||||||
|
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
|
||||||
|
|
||||||
|
/* pending Data Transfer End interrupt */
|
||||||
|
cdc.ifstat &= ~BIT_DTEI;
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
/* update IRQ level */
|
||||||
|
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set EDT bit (gate-array register $04) */
|
||||||
|
scd.regs[0x04>>1].byte.h |= 0x80;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 4: /* PCM RAM DMA */
|
||||||
|
{
|
||||||
|
cdc.dma_w = pcm_ram_dma_w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 5: /* PRG-RAM DMA */
|
||||||
|
{
|
||||||
|
/* check if MAIN-CPU has access to PRG-RAM */
|
||||||
|
if (scd.regs[0x00].byte.l & 0x02)
|
||||||
|
{
|
||||||
|
/* halt DMA to PRG-RAM */
|
||||||
|
cdc.halted_dma_w = prg_ram_dma_w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* enable DMA to PRG-RAM */
|
||||||
|
cdc.dma_w = prg_ram_dma_w;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 7: /* Word-RAM DMA */
|
||||||
|
{
|
||||||
|
/* check memory mode */
|
||||||
|
if (scd.regs[0x02 >> 1].byte.l & 0x04)
|
||||||
|
{
|
||||||
|
/* 1M mode */
|
||||||
|
if (scd.regs[0x02 >> 1].byte.l & 0x01)
|
||||||
|
{
|
||||||
|
/* Word-RAM bank 0 is assigned to SUB-CPU */
|
||||||
|
cdc.dma_w = word_ram_0_dma_w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Word-RAM bank 1 is assigned to SUB-CPU */
|
||||||
|
cdc.dma_w = word_ram_1_dma_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* check if MAIN-CPU has access to 2M Word-RAM */
|
||||||
|
if (scd.regs[0x02 >> 1].byte.l & 0x01)
|
||||||
|
{
|
||||||
|
/* halt DMA to 2M Word-RAM */
|
||||||
|
cdc.halted_dma_w = word_ram_2M_dma_w;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* enable DMA to 2M Word-RAM */
|
||||||
|
cdc.dma_w = word_ram_2M_dma_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: /* invalid */
|
||||||
|
{
|
||||||
|
#ifdef LOG_CDC
|
||||||
|
error("invalid CDC transfer destination (%d)\n", scd.regs[0x04>>1].byte.h & 0x07);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* always process blocks of 8 bytes */
|
||||||
|
dma_bytes = (dma_bytes / 8) * 8;
|
||||||
|
|
||||||
/* end of DMA transfer ? */
|
/* end of DMA transfer ? */
|
||||||
if (cdc.dbc.w < DMA_BYTES_PER_LINE)
|
if (cdc.dbc.w < dma_bytes)
|
||||||
{
|
{
|
||||||
/* transfer remaining bytes using DMA */
|
/* transfer remaining bytes using DMA */
|
||||||
cdc.dma_w(cdc.dbc.w + 1);
|
cdc.dma_w(cdc.dbc.w + 1);
|
||||||
@ -252,8 +412,8 @@ void cdc_dma_update(void)
|
|||||||
/* SUB-CPU idle on register $04 polling ? */
|
/* SUB-CPU idle on register $04 polling ? */
|
||||||
if (s68k.stopped & (1<<0x04))
|
if (s68k.stopped & (1<<0x04))
|
||||||
{
|
{
|
||||||
/* sync SUB-CPU with CDC */
|
/* sync SUB-CPU with CDC DMA */
|
||||||
s68k.cycles = scd.cycles;
|
s68k.cycles = cdc.cycles;
|
||||||
|
|
||||||
/* restart SUB-CPU */
|
/* restart SUB-CPU */
|
||||||
s68k.stopped = 0;
|
s68k.stopped = 0;
|
||||||
@ -262,16 +422,19 @@ void cdc_dma_update(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* disable DMA transfer */
|
/* disable DMA */
|
||||||
cdc.dma_w = 0;
|
cdc.dma_w = cdc.halted_dma_w = 0;
|
||||||
}
|
}
|
||||||
else
|
else if (dma_bytes > 0)
|
||||||
{
|
{
|
||||||
/* transfer limited amount of bytes using DMA */
|
/* transfer limited amount of bytes using DMA */
|
||||||
cdc.dma_w(DMA_BYTES_PER_LINE);
|
cdc.dma_w(dma_bytes);
|
||||||
|
|
||||||
/* decrement data byte counter */
|
/* decrement data byte counter */
|
||||||
cdc.dbc.w -= DMA_BYTES_PER_LINE;
|
cdc.dbc.w -= dma_bytes;
|
||||||
|
|
||||||
|
/* update DMA cycle counter */
|
||||||
|
cdc.cycles += dma_bytes * DMA_CYCLES_PER_BYTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,6 +566,9 @@ void cdc_reg_w(unsigned char data)
|
|||||||
{
|
{
|
||||||
/* clear !DTBSY and !DTEN */
|
/* clear !DTBSY and !DTEN */
|
||||||
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
|
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
|
||||||
|
|
||||||
|
/* disable DMA */
|
||||||
|
cdc.dma_w = cdc.halted_dma_w = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdc.ifctrl = data;
|
cdc.ifctrl = data;
|
||||||
@ -436,110 +602,11 @@ void cdc_reg_w(unsigned char data)
|
|||||||
/* clear EDT & DSR bits (gate-array register $04) */
|
/* clear EDT & DSR bits (gate-array register $04) */
|
||||||
scd.regs[0x04>>1].byte.h &= 0x07;
|
scd.regs[0x04>>1].byte.h &= 0x07;
|
||||||
|
|
||||||
/* setup data transfer destination */
|
/* initialize data transfer destination */
|
||||||
switch (scd.regs[0x04>>1].byte.h & 0x07)
|
cdc_dma_init();
|
||||||
{
|
|
||||||
case 2: /* MAIN-CPU host read */
|
|
||||||
case 3: /* SUB-CPU host read */
|
|
||||||
{
|
|
||||||
/* read 16-bit word from CDC RAM buffer (big-endian format) into gate-array register $08 */
|
|
||||||
/* Note: on real-hardware, 16-bit word is not immediately available, cf. https://github.com/MiSTer-devel/MegaCD_MiSTer/blob/master/docs/mcd%20logs/dma_sub_read.jpg for transfer timings */
|
|
||||||
scd.regs[0x08>>1].w = READ_WORD(cdc.ram, cdc.dac.w & 0x3ffe);
|
|
||||||
#ifdef LOG_CDC
|
|
||||||
error("CDC host read 0x%04x -> 0x%04x (dbc=0x%x) (%X)\n", cdc.dac.w, scd.regs[0x08>>1].w, cdc.dbc.w, s68k.pc);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* set DSR bit (gate-array register $04) */
|
/* initialize DMA cycle counter */
|
||||||
scd.regs[0x04>>1].byte.h |= 0x40;
|
cdc.cycles = s68k.cycles;
|
||||||
|
|
||||||
/* increment data address counter */
|
|
||||||
cdc.dac.w += 2;
|
|
||||||
|
|
||||||
/* decrement data byte counter */
|
|
||||||
cdc.dbc.w -= 2;
|
|
||||||
|
|
||||||
/* end of transfer ? */
|
|
||||||
if ((int16)cdc.dbc.w < 0)
|
|
||||||
{
|
|
||||||
/* reset data byte counter (DBCH bits 4-7 should also be set to 1) */
|
|
||||||
cdc.dbc.w = 0xffff;
|
|
||||||
|
|
||||||
/* clear !DTEN and !DTBSY */
|
|
||||||
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
|
|
||||||
|
|
||||||
/* pending Data Transfer End interrupt */
|
|
||||||
cdc.ifstat &= ~BIT_DTEI;
|
|
||||||
|
|
||||||
/* 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)
|
|
||||||
{
|
|
||||||
/* update IRQ level */
|
|
||||||
s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set EDT bit (gate-array register $04) */
|
|
||||||
scd.regs[0x04>>1].byte.h |= 0x80;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 4: /* PCM RAM DMA */
|
|
||||||
{
|
|
||||||
cdc.dma_w = pcm_ram_dma_w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 5: /* PRG-RAM DMA */
|
|
||||||
{
|
|
||||||
cdc.dma_w = prg_ram_dma_w;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 7: /* WORD-RAM DMA */
|
|
||||||
{
|
|
||||||
/* check memory mode */
|
|
||||||
if (scd.regs[0x02 >> 1].byte.l & 0x04)
|
|
||||||
{
|
|
||||||
/* 1M mode */
|
|
||||||
if (scd.regs[0x02 >> 1].byte.l & 0x01)
|
|
||||||
{
|
|
||||||
/* Word-RAM bank 0 is assigned to SUB-CPU */
|
|
||||||
cdc.dma_w = word_ram_0_dma_w;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Word-RAM bank 1 is assigned to SUB-CPU */
|
|
||||||
cdc.dma_w = word_ram_1_dma_w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 2M mode */
|
|
||||||
if (scd.regs[0x02 >> 1].byte.l & 0x02)
|
|
||||||
{
|
|
||||||
/* only process DMA if Word-RAM is assigned to SUB-CPU */
|
|
||||||
cdc.dma_w = word_ram_2M_dma_w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: /* invalid */
|
|
||||||
{
|
|
||||||
#ifdef LOG_CDC
|
|
||||||
error("invalid CDC transfer destination (%d)\n", scd.regs[0x04>>1].byte.h & 0x07);
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -623,7 +690,7 @@ void cdc_reg_w(unsigned char data)
|
|||||||
cdc_reset();
|
cdc_reset();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* unemulated registers*/
|
default: /* unemulated registers */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,7 +824,7 @@ unsigned char cdc_reg_r(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LOG_CDC
|
#ifdef LOG_CDC
|
||||||
error("CDC register %d read 0x%02X (%X)\n", scd.regs[0x04>>1].byte.l, data, s68k.pc);
|
error("CDC register %d read 0x%02X (%X)\n", scd.regs[0x04>>1].byte.l, data, s68k.pc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* increment address register (except when register #0 is selected) */
|
/* increment address register (except when register #0 is selected) */
|
||||||
|
@ -55,8 +55,9 @@ typedef struct
|
|||||||
uint8 ctrl[2];
|
uint8 ctrl[2];
|
||||||
uint8 head[2][4];
|
uint8 head[2][4];
|
||||||
uint8 stat[4];
|
uint8 stat[4];
|
||||||
int cycles;
|
unsigned int cycles;
|
||||||
void (*dma_w)(unsigned int length); /* DMA transfer callback */
|
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 ram[0x4000 + 2352]; /* 16K external RAM (with one block overhead to handle buffer overrun) */
|
||||||
uint8 ar_mask;
|
uint8 ar_mask;
|
||||||
} cdc_t;
|
} cdc_t;
|
||||||
@ -66,7 +67,8 @@ extern void cdc_init(void);
|
|||||||
extern void cdc_reset(void);
|
extern void cdc_reset(void);
|
||||||
extern int cdc_context_save(uint8 *state);
|
extern int cdc_context_save(uint8 *state);
|
||||||
extern int cdc_context_load(uint8 *state);
|
extern int cdc_context_load(uint8 *state);
|
||||||
extern void cdc_dma_update(void);
|
extern void cdc_dma_init(void);
|
||||||
|
extern void cdc_dma_update(unsigned int cycles);
|
||||||
extern void cdc_decoder_update(uint32 header);
|
extern void cdc_decoder_update(uint32 header);
|
||||||
extern void cdc_reg_w(unsigned char data);
|
extern void cdc_reg_w(unsigned char data);
|
||||||
extern unsigned char cdc_reg_r(void);
|
extern unsigned char cdc_reg_r(void);
|
||||||
|
@ -1003,6 +1003,17 @@ static void scd_write_byte(unsigned int address, unsigned int data)
|
|||||||
gfx_update(s68k.cycles);
|
gfx_update(s68k.cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if CDC DMA to 2M Word-RAM is running */
|
||||||
|
if (cdc.dma_w == word_ram_2M_dma_w)
|
||||||
|
{
|
||||||
|
/* synchronize CDC DMA with SUB-CPU */
|
||||||
|
cdc_dma_update(s68k.cycles);
|
||||||
|
|
||||||
|
/* halt CDC DMA to 2M Word-RAM */
|
||||||
|
cdc.dma_w = 0;
|
||||||
|
cdc.halted_dma_w = word_ram_2M_dma_w;
|
||||||
|
}
|
||||||
|
|
||||||
/* Word-RAM is returned to MAIN-CPU */
|
/* Word-RAM is returned to MAIN-CPU */
|
||||||
scd.dmna = 0;
|
scd.dmna = 0;
|
||||||
|
|
||||||
@ -1038,6 +1049,24 @@ static void scd_write_byte(unsigned int address, unsigned int data)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 0x04: /* CDC mode */
|
||||||
|
{
|
||||||
|
scd.regs[0x04 >> 1].byte.h = data & 0x07;
|
||||||
|
|
||||||
|
/* synchronize CDC DMA (if running) with SUB-CPU */
|
||||||
|
if (cdc.dma_w)
|
||||||
|
{
|
||||||
|
cdc_dma_update(s68k.cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reinitialize CDC data transfer destination (verified on real hardware, cf. Krikzz's mcd-verificator) */
|
||||||
|
cdc_dma_init();
|
||||||
|
|
||||||
|
/* reset CDC DMA address (verified on real hardware, cf. Krikzz's mcd-verificator) */
|
||||||
|
scd.regs[0x0a >> 1].w = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case 0x05: /* CDC register address */
|
case 0x05: /* CDC register address */
|
||||||
{
|
{
|
||||||
scd.regs[0x04 >> 1].byte.l = data & cdc.ar_mask;
|
scd.regs[0x04 >> 1].byte.l = data & cdc.ar_mask;
|
||||||
@ -1312,6 +1341,17 @@ static void scd_write_word(unsigned int address, unsigned int data)
|
|||||||
gfx_update(s68k.cycles);
|
gfx_update(s68k.cycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if CDC DMA to 2M Word-RAM is running */
|
||||||
|
if (cdc.dma_w == word_ram_2M_dma_w)
|
||||||
|
{
|
||||||
|
/* synchronize CDC DMA with SUB-CPU */
|
||||||
|
cdc_dma_update(s68k.cycles);
|
||||||
|
|
||||||
|
/* halt CDC DMA to 2M Word-RAM */
|
||||||
|
cdc.dma_w = 0;
|
||||||
|
cdc.halted_dma_w = word_ram_2M_dma_w;
|
||||||
|
}
|
||||||
|
|
||||||
/* Word-RAM is returned to MAIN-CPU */
|
/* Word-RAM is returned to MAIN-CPU */
|
||||||
scd.dmna = 0;
|
scd.dmna = 0;
|
||||||
|
|
||||||
@ -1350,6 +1390,18 @@ static void scd_write_word(unsigned int address, unsigned int data)
|
|||||||
case 0x04: /* CDC mode & register address */
|
case 0x04: /* CDC mode & register address */
|
||||||
{
|
{
|
||||||
scd.regs[0x04 >> 1].w = data & (0x0700 | cdc.ar_mask);
|
scd.regs[0x04 >> 1].w = data & (0x0700 | cdc.ar_mask);
|
||||||
|
|
||||||
|
/* synchronize CDC DMA (if running) with SUB-CPU */
|
||||||
|
if (cdc.dma_w)
|
||||||
|
{
|
||||||
|
cdc_dma_update(s68k.cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reinitialize CDC data transfer destination (verified on real hardware, cf. Krikzz's mcd-verificator) */
|
||||||
|
cdc_dma_init();
|
||||||
|
|
||||||
|
/* reset CDC DMA address (verified on real hardware, cf. Krikzz's mcd-verificator) */
|
||||||
|
scd.regs[0x0a >> 1].w = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1833,16 +1885,6 @@ void scd_update(unsigned int cycles)
|
|||||||
int s68k_run_cycles;
|
int s68k_run_cycles;
|
||||||
int s68k_end_cycles = scd.cycles + SCYCLES_PER_LINE;
|
int s68k_end_cycles = scd.cycles + SCYCLES_PER_LINE;
|
||||||
|
|
||||||
/* update CDC DMA transfer */
|
|
||||||
if (cdc.dma_w)
|
|
||||||
{
|
|
||||||
/* check if Word-RAM is returned to SUB-CPU in 2M mode */
|
|
||||||
if ((cdc.dma_w != word_ram_2M_dma_w) || scd.dmna)
|
|
||||||
{
|
|
||||||
cdc_dma_update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* run both CPU in sync until end of line */
|
/* run both CPU in sync until end of line */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@ -1918,10 +1960,15 @@ void scd_update(unsigned int cycles)
|
|||||||
}
|
}
|
||||||
while ((m68k.cycles < cycles) || (s68k.cycles < s68k_end_cycles));
|
while ((m68k.cycles < cycles) || (s68k.cycles < s68k_end_cycles));
|
||||||
|
|
||||||
/* GFX processing */
|
/* update CDC DMA processing (if running) */
|
||||||
|
if (cdc.dma_w)
|
||||||
|
{
|
||||||
|
cdc_dma_update(scd.cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update GFX processing (if started) */
|
||||||
if (scd.regs[0x58>>1].byte.h & 0x80)
|
if (scd.regs[0x58>>1].byte.h & 0x80)
|
||||||
{
|
{
|
||||||
/* update graphics operation if running */
|
|
||||||
gfx_update(scd.cycles);
|
gfx_update(scd.cycles);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
103
core/mem68k.c
103
core/mem68k.c
@ -756,6 +756,17 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
|
|||||||
m68k.memory_map[base].write16 = m68k.memory_map[base+1].write16 = NULL;
|
m68k.memory_map[base].write16 = m68k.memory_map[base+1].write16 = NULL;
|
||||||
zbank_memory_map[base].read = zbank_memory_map[base+1].read = NULL;
|
zbank_memory_map[base].read = zbank_memory_map[base+1].read = NULL;
|
||||||
zbank_memory_map[base].write = zbank_memory_map[base+1].write = NULL;
|
zbank_memory_map[base].write = zbank_memory_map[base+1].write = NULL;
|
||||||
|
|
||||||
|
/* check if CDC DMA to PRG-RAM is running */
|
||||||
|
if (cdc.dma_w == prg_ram_dma_w)
|
||||||
|
{
|
||||||
|
/* synchronize CDC DMA with MAIN-CPU */
|
||||||
|
cdc_dma_update((m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE);
|
||||||
|
|
||||||
|
/* halt CDC DMA to PRG-RAM */
|
||||||
|
cdc.dma_w = 0;
|
||||||
|
cdc.halted_dma_w = prg_ram_dma_w;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -765,6 +776,23 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
|
|||||||
m68k.memory_map[base].write16 = m68k.memory_map[base+1].write16 = m68k_unused_16_w;
|
m68k.memory_map[base].write16 = m68k.memory_map[base+1].write16 = m68k_unused_16_w;
|
||||||
zbank_memory_map[base].read = zbank_memory_map[base+1].read = zbank_unused_r;
|
zbank_memory_map[base].read = zbank_memory_map[base+1].read = zbank_unused_r;
|
||||||
zbank_memory_map[base].write = zbank_memory_map[base+1].write = zbank_unused_w;
|
zbank_memory_map[base].write = zbank_memory_map[base+1].write = zbank_unused_w;
|
||||||
|
|
||||||
|
/* check if CDC DMA to PRG-RAM is halted */
|
||||||
|
if (cdc.halted_dma_w == prg_ram_dma_w)
|
||||||
|
{
|
||||||
|
/* relative SUB-CPU cycle counter */
|
||||||
|
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
|
/* enable CDC DMA to PRG-RAM */
|
||||||
|
cdc.dma_w = prg_ram_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
|
|
||||||
|
/* synchronize CDC DMA with MAIN-CPU (only if not already ahead) */
|
||||||
|
if (cdc.cycles < cycles)
|
||||||
|
{
|
||||||
|
cdc.cycles = cycles;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -840,7 +868,7 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
|
|||||||
/* check if SUB-CPU is waiting for Word-RAM access */
|
/* check if SUB-CPU is waiting for Word-RAM access */
|
||||||
if (s68k.stopped & 0x04)
|
if (s68k.stopped & 0x04)
|
||||||
{
|
{
|
||||||
/* sync SUB-CPU with MAIN-CPU */
|
/* synchronize SUB-CPU with MAIN-CPU */
|
||||||
s68k.cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
s68k.cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
/* restart SUB-CPU */
|
/* restart SUB-CPU */
|
||||||
@ -850,18 +878,36 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if graphics operation is running */
|
/* check if graphics operation is started */
|
||||||
if (scd.regs[0x58>>1].byte.h & 0x80)
|
if (scd.regs[0x58>>1].byte.h & 0x80)
|
||||||
{
|
{
|
||||||
/* relative SUB-CPU cycle counter */
|
/* relative SUB-CPU cycle counter */
|
||||||
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
/* synchronize GFX processing with SUB-CPU (only if not already ahead) */
|
/* synchronize GFX processing with MAIN-CPU (only if not already ahead) */
|
||||||
if (gfx.cycles < cycles)
|
if (gfx.cycles < cycles)
|
||||||
{
|
{
|
||||||
gfx.cycles = cycles;
|
gfx.cycles = cycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if CDC DMA to 2M Word-RAM is halted */
|
||||||
|
if (cdc.halted_dma_w == word_ram_2M_dma_w)
|
||||||
|
{
|
||||||
|
/* relative SUB-CPU cycle counter */
|
||||||
|
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
|
/* enable CDC DMA to 2M Word-RAM */
|
||||||
|
cdc.dma_w = word_ram_2M_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
|
|
||||||
|
/* synchronize CDC DMA with MAIN-CPU (only if not already ahead) */
|
||||||
|
if (cdc.cycles < cycles)
|
||||||
|
{
|
||||||
|
cdc.cycles = cycles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1039,6 +1085,17 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
|
|||||||
m68k.memory_map[base].write16 = m68k.memory_map[base+1].write16 = NULL;
|
m68k.memory_map[base].write16 = m68k.memory_map[base+1].write16 = NULL;
|
||||||
zbank_memory_map[base].read = zbank_memory_map[base+1].read = NULL;
|
zbank_memory_map[base].read = zbank_memory_map[base+1].read = NULL;
|
||||||
zbank_memory_map[base].write = zbank_memory_map[base+1].write = NULL;
|
zbank_memory_map[base].write = zbank_memory_map[base+1].write = NULL;
|
||||||
|
|
||||||
|
/* check if CDC DMA to PRG-RAM is running */
|
||||||
|
if (cdc.dma_w == prg_ram_dma_w)
|
||||||
|
{
|
||||||
|
/* synchronize CDC DMA with MAIN-CPU */
|
||||||
|
cdc_dma_update((m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE);
|
||||||
|
|
||||||
|
/* halt CDC DMA to PRG-RAM */
|
||||||
|
cdc.dma_w = 0;
|
||||||
|
cdc.halted_dma_w = prg_ram_dma_w;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1048,6 +1105,23 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
|
|||||||
m68k.memory_map[base].write16 = m68k.memory_map[base+1].write16 = m68k_unused_16_w;
|
m68k.memory_map[base].write16 = m68k.memory_map[base+1].write16 = m68k_unused_16_w;
|
||||||
zbank_memory_map[base].read = zbank_memory_map[base+1].read = zbank_unused_r;
|
zbank_memory_map[base].read = zbank_memory_map[base+1].read = zbank_unused_r;
|
||||||
zbank_memory_map[base].write = zbank_memory_map[base+1].write = zbank_unused_w;
|
zbank_memory_map[base].write = zbank_memory_map[base+1].write = zbank_unused_w;
|
||||||
|
|
||||||
|
/* check if CDC DMA to PRG-RAM is halted */
|
||||||
|
if (cdc.halted_dma_w == prg_ram_dma_w)
|
||||||
|
{
|
||||||
|
/* relative SUB-CPU cycle counter */
|
||||||
|
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
|
/* enable CDC DMA to PRG-RAM */
|
||||||
|
cdc.dma_w = prg_ram_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
|
|
||||||
|
/* synchronize CDC DMA with MAIN-CPU (only if not already ahead) */
|
||||||
|
if (cdc.cycles < cycles)
|
||||||
|
{
|
||||||
|
cdc.cycles = cycles;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1133,7 +1207,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
|
|||||||
/* check if SUB-CPU is waiting for Word-RAM access */
|
/* check if SUB-CPU is waiting for Word-RAM access */
|
||||||
if (s68k.stopped & 0x04)
|
if (s68k.stopped & 0x04)
|
||||||
{
|
{
|
||||||
/* sync SUB-CPU with MAIN-CPU */
|
/* synchronize SUB-CPU with MAIN-CPU */
|
||||||
s68k.cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
s68k.cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
/* restart SUB-CPU */
|
/* restart SUB-CPU */
|
||||||
@ -1143,18 +1217,35 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if graphics operation is running */
|
/* check if graphics operation is started */
|
||||||
if (scd.regs[0x58>>1].byte.h & 0x80)
|
if (scd.regs[0x58>>1].byte.h & 0x80)
|
||||||
{
|
{
|
||||||
/* relative SUB-CPU cycle counter */
|
/* relative SUB-CPU cycle counter */
|
||||||
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
/* synchronize GFX processing with SUB-CPU (only if not already ahead) */
|
/* synchronize GFX processing with MAIN-CPU (only if not already ahead) */
|
||||||
if (gfx.cycles < cycles)
|
if (gfx.cycles < cycles)
|
||||||
{
|
{
|
||||||
gfx.cycles = cycles;
|
gfx.cycles = cycles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if CDC DMA to 2M Word-RAM is halted */
|
||||||
|
if (cdc.halted_dma_w == word_ram_2M_dma_w)
|
||||||
|
{
|
||||||
|
/* relative SUB-CPU cycle counter */
|
||||||
|
unsigned int cycles = (m68k.cycles * SCYCLES_PER_LINE) / MCYCLES_PER_LINE;
|
||||||
|
|
||||||
|
/* enable CDC DMA to 2M Word-RAM */
|
||||||
|
cdc.dma_w = word_ram_2M_dma_w;
|
||||||
|
cdc.halted_dma_w = 0;
|
||||||
|
|
||||||
|
/* synchronize CDC DMA with MAIN-CPU (only if not already ahead) */
|
||||||
|
if (cdc.cycles < cycles)
|
||||||
|
{
|
||||||
|
cdc.cycles = cycles;
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user