diff --git a/HISTORY.txt b/HISTORY.txt index 5764ed9..8aa1b47 100644 --- a/HISTORY.txt +++ b/HISTORY.txt @@ -24,6 +24,7 @@ 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 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 CDC transfer to Main-CPU & Sub-CPU (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") diff --git a/builds/genesis_plus_gx_libretro.dll b/builds/genesis_plus_gx_libretro.dll index 9353c14..fb244e9 100644 Binary files a/builds/genesis_plus_gx_libretro.dll and b/builds/genesis_plus_gx_libretro.dll differ diff --git a/builds/genplus_cube.dol b/builds/genplus_cube.dol index aa3bbf2..4c04085 100644 Binary files a/builds/genplus_cube.dol and b/builds/genplus_cube.dol differ diff --git a/builds/genplus_wii.dol b/builds/genplus_wii.dol index f1873e9..f0b0f35 100644 Binary files a/builds/genplus_wii.dol and b/builds/genplus_wii.dol differ diff --git a/core/cd_hw/cdc.c b/core/cd_hw/cdc.c index bc217a2..1679a16 100644 --- a/core/cd_hw/cdc.c +++ b/core/cd_hw/cdc.c @@ -433,7 +433,7 @@ void cdc_reg_w(unsigned char data) /* set !DTBSY and !DTEN */ cdc.ifstat &= ~(BIT_DTBSY | BIT_DTEN); - /* clear EDT & DSR bits (SCD register $04) */ + /* clear EDT & DSR bits (gate-array register $04) */ scd.regs[0x04>>1].byte.h &= 0x07; /* setup data transfer destination */ @@ -442,8 +442,52 @@ void cdc_reg_w(unsigned char data) case 2: /* MAIN-CPU host read */ case 3: /* SUB-CPU host read */ { - /* set DSR bit (SCD register $04) */ + /* 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; } @@ -727,57 +771,64 @@ unsigned char cdc_reg_r(void) unsigned short cdc_host_r(void) { - /* check if data is available */ + /* read CDC buffered data (gate-array register $08) */ + uint16 data = scd.regs[0x08>>1].w; + + /* check if host data transfer is enabled */ if (scd.regs[0x04>>1].byte.h & 0x40) { - /* read 16-bit word from CDC RAM buffer (big-endian format) */ - uint16 data = 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, data, cdc.dbc.w, s68k.pc); -#endif - - /* 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) + /* check if EDT bit (gate-array register $04) is set (host data transfer is finished) */ + if (scd.regs[0x04>>1].byte.h & 0x80) { - /* reset data byte counter (DBCH bits 4-7 should be set to 1) */ - cdc.dbc.w = 0xf000; - - /* 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); - } - } - - /* clear DSR bit & set EDT bit (SCD register $04) */ - scd.regs[0x04>>1].byte.h = (scd.regs[0x04>>1].byte.h & 0x07) | 0x80; + /* clear DSR bit (gate-array register $04) */ + scd.regs[0x04>>1].byte.h &= ~0x40; } + else + { + /* read next 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 - return data; + /* 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; + } + } } -#ifdef LOG_CDC - error("error reading CDC host (data transfer disabled)\n"); -#endif - return 0xffff; + return data; }