//void (*dma_w)(unsigned int words);
int dma_w;
uint8 ram[0x4000 + 2352]; /* 16K external RAM (with one block overhead to handle buffer overrun) */
-} cdc_t;
+} cdc_t;
static cdc_t cdc;
cdc.head[1][3] = 0x00;
/* reset CDC cycle counter */
- cdc.cycles = 0;
+ cdc.cycles = SekCyclesDoneS68k();
/* DMA transfer disabled */
cdc.dma_w = 0;
#undef old_load
}
+static int check_decoder_irq_pending(void)
+{
+ /* As per mcd-verificator, DECI is active for a phase of 49:72 per sector */
+ /* 12500000/75 * 49/(49+72) = ~67500, but it sometimes fails with that */
+ if (CYCLES_GE(SekCyclesDoneS68k(), cdc.cycles + 67250))
+ cdc.ifstat |= BIT_DECI;
+
+ return !(cdc.ifstat & BIT_DECI) && (cdc.ifctrl & BIT_DECIEN);
+}
+
static void do_dma(enum dma_type type, int bytes_in)
{
int dma_addr = (Pico_mcd->s68k_regs[0x0a] << 8) | Pico_mcd->s68k_regs[0x0b];
cdc.ifstat &= ~BIT_DTEI;
/* Data Transfer End interrupt enabled ? */
- if (cdc.ifctrl & BIT_DTEIEN)
+ if (!check_decoder_irq_pending() && (cdc.ifctrl & BIT_DTEIEN))
{
/* level 5 interrupt enabled ? */
if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5)
/* pending decoder interrupt */
cdc.ifstat &= ~BIT_DECI;
+ cdc.cycles = SekCyclesDoneS68k();
/* decoder interrupt enabled ? */
- if (cdc.ifctrl & BIT_DECIEN)
+ if (((cdc.ifstat & BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN)) && (cdc.ifctrl & BIT_DECIEN))
{
/* level 5 interrupt enabled ? */
if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5)
return 1;
}
}
-
+
/* keep decoding same data block if Buffer Write is disabled */
return 0;
}
case 0x01: /* IFCTRL */
{
/* pending interrupts ? */
+ check_decoder_irq_pending();
if (((data & BIT_DTEIEN) && !(cdc.ifstat & BIT_DTEI)) ||
((data & BIT_DECIEN) && !(cdc.ifstat & BIT_DECI)))
{
/* clear DBCH bits 4-7 */
cdc.dbc &= 0x0fff;
-#if 0
/* no pending decoder interrupt ? */
- if ((cdc.ifstat | BIT_DECI) || !(cdc.ifctrl & BIT_DECIEN))
+ if (!check_decoder_irq_pending())
{
/* clear pending level 5 interrupt */
pcd_irq_s68k(5, 0);
}
-#endif
+
Pico_mcd->s68k_regs[0x04+1] = 0x08;
break;
}
case 0x0a: /* CTRL0 */
{
/* reset DECI if decoder turned off */
- if (!(data & BIT_DECEN))
+ if (!(data & BIT_DECEN)) {
cdc.ifstat |= BIT_DECI;
+ if ((cdc.ifstat & BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN))
+ {
+ /* clear pending level 5 interrupt */
+ pcd_irq_s68k(5, 0);
+ }
+ }
+
/* update decoding mode */
if (data & BIT_AUTORQ)
{
/* set MODE bit according to CTRL1 register & clear FORM bit */
cdc.stat[2] = cdc.ctrl[1] & BIT_MODRQ;
}
- else
+ else
{
/* set MODE & FORM bits according to CTRL1 register */
cdc.stat[2] = cdc.ctrl[1] & (BIT_MODRQ | BIT_FORMRQ);
/* set MODE bit according to CTRL1 register & clear FORM bit */
cdc.stat[2] = data & BIT_MODRQ;
}
- else
+ else
{
/* set MODE & FORM bits according to CTRL1 register */
cdc.stat[2] = data & (BIT_MODRQ | BIT_FORMRQ);
cdc.pt |= data;
Pico_mcd->s68k_regs[0x04+1] = 0x0d;
break;
-
+
case 0x0d: /* PTH */
cdc.pt &= 0x00ff;
cdc.pt |= data << 8;
case 0x01: /* IFSTAT */
Pico_mcd->s68k_regs[0x04+1] = 0x02;
+ check_decoder_irq_pending();
return cdc.ifstat;
case 0x02: /* DBCL */
/* 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))
+ if ((cdc.ifstat & BIT_DTEI) || !(cdc.ifctrl & BIT_DTEIEN))
{
/* clear pending level 5 interrupt */
pcd_irq_s68k(5, 0);
}
-#endif
Pico_mcd->s68k_regs[0x04+1] = 0x10;
return data;
}
}
-unsigned short cdc_host_r(void)
+unsigned short cdc_host_r(int sub)
{
+ int dir = Pico_mcd->s68k_regs[0x04+0] & 0x07;
+
+ /* sync sub cpu if DSR bit not there (yet?) on main cpu */
+ if (!(Pico_mcd->s68k_regs[0x04+0] & 0x40))
+ if (!sub) pcd_sync_s68k(SekCyclesDone()+8, 0); /* HACK, mcd-verificator */
+
/* check if data is available */
if (!(cdc.ifstat & BIT_DTEN))
{
#ifdef LOG_CDC
error("CDC host read 0x%04x -> 0x%04x (dbc=0x%x) (%X)\n", cdc.dac, data, cdc.dbc, s68k.pc);
#endif
-
+
+ /* only the configured cpu access advances the DMA */
+ if ((sub && dir != 3) || (!sub && dir != 2))
+ return data;
+
/* increment data address counter */
cdc.dac += 2;
cdc.ifstat &= ~BIT_DTEI;
/* Data Transfer End interrupt enabled ? */
- if (cdc.ifctrl & BIT_DTEIEN)
+ if (!check_decoder_irq_pending() && (cdc.ifctrl & BIT_DTEIEN))
{
/* level 5 interrupt enabled ? */
if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5)
error("LBA = %d (track n°%d)(latency=%d)\n", cdd.lba, cdd.index, cdd.latency);
#endif
+ /* update decoder, depending on track type */
+ if (cdd.status == CD_PLAY && !is_audio(cdd.index))
+ {
+ /* DATA sector header (CD-ROM Mode 1) */
+ uint8 header[4];
+ uint32 msf = cdd.lba + 150;
+ header[0] = lut_BCD_8[(msf / 75) / 60];
+ header[1] = lut_BCD_8[(msf / 75) % 60];
+ header[2] = lut_BCD_8[(msf % 75)];
+ header[3] = 0x01;
+
+ /* data track sector read is controlled by CDC */
+ cdc_decoder_update(header);
+ }
+ else
+ {
+ uint8 header[4] = { 0, };
+
+ /* audio blocks are still sent to CDC as well as CD DAC/Fader */
+ cdc_decoder_update(header);
+ }
+
/* drive latency */
if (cdd.latency > 0)
{
return;
}
- /* track type */
- if (!is_audio(cdd.index))
+ /* check against audio track start index */
+ if (is_audio(cdd.index) && cdd.lba >= cdd.toc.tracks[cdd.index].start)
{
- /* DATA sector header (CD-ROM Mode 1) */
- uint8 header[4];
- uint32 msf = cdd.lba + 150;
- header[0] = lut_BCD_8[(msf / 75) / 60];
- header[1] = lut_BCD_8[(msf / 75) % 60];
- header[2] = lut_BCD_8[(msf % 75)];
- header[3] = 0x01;
-
- /* data track sector read is controlled by CDC */
- cdc_decoder_update(header);
- }
- else
- {
- uint8 header[4] = { 0, };
-
- /* check against audio track start index */
- if (cdd.lba >= cdd.toc.tracks[cdd.index].start)
- {
- /* audio track playing */
- Pico_mcd->s68k_regs[0x36+0] = 0x00;
- }
-
- /* audio blocks are still sent to CDC as well as CD DAC/Fader */
- cdc_decoder_update(header);
+ /* audio track playing */
+ Pico_mcd->s68k_regs[0x36+0] = 0x00;
}
/* next block is automatically read */
(Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
(Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
- /* if drive is currently reading, another block or 2 are decoded before the seek starts */
- if (cdd.status == CD_PLAY && !(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) {
+ /* return track index in RS2-RS3 */
+ set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
+ set_reg16(0x3a, 0x0000);
+ set_reg16(0x3c, 0x0000);
+ set_reg16(0x3e, 0x0000);
+ set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
+
+ /* seek delayed by max 2 blocks before the seek starts */
+ if (!(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) {
Pico_mcd->m.state_flags |= PCD_ST_CDD_CMD;
return;
}
/* update status */
cdd.status = CD_PLAY;
- /* return track index in RS2-RS3 */
- set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
- set_reg16(0x3a, 0x0000);
- set_reg16(0x3c, 0x0000);
- set_reg16(0x3e, 0x0000);
- set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
return;
}
(Pico_mcd->s68k_regs[0x46+0] * 10 + Pico_mcd->s68k_regs[0x46+1])) * 75 +
(Pico_mcd->s68k_regs[0x48+0] * 10 + Pico_mcd->s68k_regs[0x48+1]) - 150;
- /* if drive is currently reading, another block or 2 are decoded before the seek starts */
- if (cdd.status == CD_PLAY && !(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) {
+ /* unknown RS1-RS8 values (returning 0xF in RS1 invalidates track infos in RS2-RS8 and fixes Final Fight CD intro when seek time is emulated) */
+ set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
+ set_reg16(0x3a, 0x0000);
+ set_reg16(0x3c, 0x0000);
+ set_reg16(0x3e, 0x0000);
+ set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
+
+ /* seek delayed by max 2 blocks before the seek starts */
+ if (!(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) {
Pico_mcd->m.state_flags |= PCD_ST_CDD_CMD;
return;
}
/* update status */
cdd.status = CD_READY;
- /* unknown RS1-RS8 values (returning 0xF in RS1 invalidates track infos in RS2-RS8 and fixes Final Fight CD intro when seek time is emulated) */
- set_reg16(0x38, (CD_SEEK << 8) | 0x0f);
- set_reg16(0x3a, 0x0000);
- set_reg16(0x3c, 0x0000);
- set_reg16(0x3e, 0x0000);
- set_reg16(0x40, ~(CD_SEEK + 0xf) & 0x0f);
return;
}
case 0x06: /* Pause */
{
- /* if drive is currently reading, another block or 2 are decoded before the seek starts */
- if (cdd.status == CD_PLAY && !(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) {
+ /* update status (RS1-RS8 unchanged) */
+ cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
+
+ /* seek delayed by max 2 blocks before the seek starts */
+ if (!(Pico_mcd->m.state_flags & PCD_ST_CDD_CMD)) {
Pico_mcd->m.state_flags |= PCD_ST_CDD_CMD;
return;
}
/* no audio track playing */
Pico_mcd->s68k_regs[0x36+0] = 0x01;
- /* update status (RS1-RS8 unchanged) */
- cdd.status = Pico_mcd->s68k_regs[0x38+0] = CD_READY;
break;
}
Pico_mcd->m.state_flags = PCD_ST_S68K_RST;
Pico_mcd->m.busreq = 2; // busreq on, s68k in reset
Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode, m68k access
- if (Pico.romsize <= 0x20000) // hack to detect BIOS, no GA HINT vector for MSU
+ if (Pico.romsize == 0x20000) // hack to detect BIOS, no GA HINT vector for MSU
memset(Pico.rom + 0x70, 0xff, 4);
}
{
/* reset CDD command wait flag */
Pico_mcd->s68k_regs[0x4b] = 0xf0;
+ }
- if ((Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) && (Pico_mcd->s68k_regs[0x37] & 4)) {
- elprintf(EL_INTS|EL_CD, "s68k: cdd irq 4");
- pcd_irq_s68k(4, 1);
- }
+ if ((Pico_mcd->s68k_regs[0x33] & PCDS_IEN4) && (Pico_mcd->s68k_regs[0x37] & 4)) {
+ elprintf(EL_INTS|EL_CD, "s68k: cdd irq 4");
+ pcd_irq_s68k(4, 1);
}
pcd_event_schedule(now, PCD_EVENT_CDC, 12500000/75);
void pcd_run_cpus_normal(int m68k_cycles)
{
- // TODO this is suspicious. ~1 cycle refresh delay every 256 cycles?
- SekAimM68k(m68k_cycles, 0x42); // Fhey area
+ SekAimM68k(m68k_cycles, 0x108);
while (CYCLES_GT(Pico.t.m68c_aim, Pico.t.m68c_cnt)) {
if (SekShouldInterrupt()) {
\r
// poller detection\r
#define POLL_LIMIT 16\r
-#define POLL_CYCLES 64\r
+#define POLL_CYCLES 52\r
\r
void m68k_comm_check(u32 a)\r
{\r
elprintf(EL_CDREG3, "m68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
goto end;\r
case 4:\r
+ pcd_sync_s68k(SekCyclesDone(), 0);\r
d = Pico_mcd->s68k_regs[4]<<8;\r
goto end;\r
case 6:\r
d = *(u16 *)(Pico.rom + 0x72);\r
goto end;\r
case 8:\r
- d = cdc_host_r();\r
+ d = cdc_host_r(0);\r
goto end;\r
case 0xa:\r
elprintf(EL_UIO, "m68k FIXME: reserved read");\r
goto end;\r
case 0xc: // 384 cycle stopwatch timer\r
+ pcd_sync_s68k(SekCyclesDone(), 0);\r
d = pcd_stopwatch_read(0);\r
elprintf(EL_CDREGS, "m68k stopwatch timer read (%04x)", d);\r
goto end;\r
((u16 *)Pico.rom)[0x70/2], ((u16 *)Pico.rom)[0x72/2]);\r
return;\r
case 8:\r
- (void) cdc_host_r(); // acts same as reading\r
+ (void) cdc_host_r(0); // acts same as reading\r
return;\r
case 0x0f:\r
a = 0x0e;\r
d = cdc_reg_r();\r
goto end;\r
case 8:\r
- d = cdc_host_r();\r
+ d = cdc_host_r(1);\r
goto end;\r
case 0xc:\r
d = pcd_stopwatch_read(1);\r
// these are only byte registers, LDS/UDS ignored\r
return s68k_reg_write8(a + 1, d);\r
case 0x08:\r
- return (void) cdc_host_r(); // acts same as reading\r
+ return (void) cdc_host_r(1); // acts same as reading\r
case 0x0a: // DMA address\r
r[0xa] = d >> 8;\r
r[0xb] = d;\r
Pico_mcd = plat_mmap(0x05000000, sizeof(mcd_state), 0, 0);\r
memset(Pico_mcd, 0, sizeof(mcd_state));\r
}\r
- pcd_base_address = (Pico.romsize > 0x20000 ? 0x400000 : 0x000000);\r
+ pcd_base_address = (Pico.romsize != 0x20000 ? 0x400000 : 0x000000);\r
\r
// setup default main68k map\r
PicoMemSetup();\r
\r
// main68k map (BIOS or MSU mapped by PicoMemSetup()):\r
- if (Pico.romsize > 0x20000) {\r
+ if (pcd_base_address != 0) {\r
// MSU cartridge. Fake BIOS detection\r
cpu68k_map_set(m68k_read8_map, 0x400000, 0x41ffff, PicoReadM68k8_bios, 1);\r
cpu68k_map_set(m68k_read16_map, 0x400000, 0x41ffff, PicoReadM68k16_bios, 1);\r
int cdc_decoder_update(unsigned char header[4]);\r
void cdc_reg_w(unsigned char data);\r
unsigned char cdc_reg_r(void);\r
-unsigned short cdc_host_r(void);\r
+unsigned short cdc_host_r(int sub);\r
\r
// cd/cdd.c\r
void cdd_reset(void);\r