#undef old_load
}
-static void do_dma(enum dma_type type, int words_in)
+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];
+ int dma_addr = (Pico_mcd->s68k_regs[0x0a] << 8) | Pico_mcd->s68k_regs[0x0b];
int src_addr = cdc.dac & 0x3ffe;
int dst_addr = dma_addr;
- int words = words_in;
+ int bytes = bytes_in;
+ int words = bytes_in >> 1;
int dst_limit = 0;
uint8 *dst;
int len;
elprintf(EL_CD, "dma %d %04x->%04x %x",
- type, cdc.dac, dst_addr, words_in);
+ type, cdc.dac, dst_addr, bytes_in);
switch (type)
{
case pcm_ram_dma_w:
dst_addr = (dst_addr << 2) & 0xffc;
- if (dst_addr + words * 2 > 0x1000) {
+ if (dst_addr + bytes > 0x1000) {
elprintf(EL_ANOMALY, "pcm dma oflow: %x %x", dst_addr, words);
- words = (0x1000 - dst_addr) / 2;
+ bytes = 0x1000 - dst_addr;
}
dst = Pico_mcd->pcm_ram_b[Pico_mcd->pcm.bank];
dst = dst + dst_addr;
- while (words > 0)
+ while (bytes > 0)
{
- if (src_addr + words * 2 > 0x4000) {
+ if (src_addr + bytes > 0x4000) {
len = 0x4000 - src_addr;
memcpy(dst, cdc.ram + src_addr, len);
dst += len;
src_addr = 0;
- words -= len / 2;
+ bytes -= len;
continue;
}
- memcpy(dst, cdc.ram + src_addr, words * 2);
+ memcpy(dst, cdc.ram + src_addr, bytes);
break;
}
goto update_dma;
case prg_ram_dma_w:
dst_addr <<= 3;
- dst = Pico_mcd->prg_ram + dst_addr;
+ dst = Pico_mcd->prg_ram + dst_addr;
dst_limit = 0x80000;
break;
case word_ram_0_dma_w:
dst_addr = (dst_addr << 3) & 0x1fffe;
- dst = Pico_mcd->word_ram1M[0] + dst_addr;
+ dst = Pico_mcd->word_ram1M[0] + dst_addr;
dst_limit = 0x20000;
break;
case word_ram_1_dma_w:
dst_addr = (dst_addr << 3) & 0x1fffe;
- dst = Pico_mcd->word_ram1M[1] + dst_addr;
+ dst = Pico_mcd->word_ram1M[1] + dst_addr;
dst_limit = 0x20000;
break;
case word_ram_2M_dma_w:
dst_addr = (dst_addr << 3) & 0x3fffe;
- dst = Pico_mcd->word_ram2M + dst_addr;
+ dst = Pico_mcd->word_ram2M + dst_addr;
dst_limit = 0x40000;
break;
break;
}
+ bytes_in &= ~1; // Todo leftover byte?
+
update_dma:
/* update DMA addresses */
- cdc.dac += words_in * 2;
+ cdc.dac += bytes_in;
if (type == pcm_ram_dma_w)
- dma_addr += words_in >> 1;
+ dma_addr += bytes_in >> 2;
else
- dma_addr += words_in >> 2;
+ dma_addr += bytes_in >> 3;
Pico_mcd->s68k_regs[0x0a] = dma_addr >> 8;
Pico_mcd->s68k_regs[0x0b] = dma_addr;
{
/* transfer remaining words using 16-bit DMA */
//cdc.dma_w((cdc.dbc + 1) >> 1);
- do_dma(cdc.dma_w, (cdc.dbc + 1) >> 1);
+ do_dma(cdc.dma_w, cdc.dbc + 1);
/* reset data byte counter (DBCH bits 4-7 should be set to 1) */
cdc.dbc = 0xf000;
/* clear !DTEN and !DTBSY */
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
- /* pending Data Transfer End interrupt */
- cdc.ifstat &= ~BIT_DTEI;
+ /* clear DSR bit & set EDT bit (SCD register $04) */
+ Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0x80;
- /* Data Transfer End interrupt enabled ? */
- if (cdc.ifctrl & BIT_DTEIEN)
- {
- /* level 5 interrupt enabled ? */
- if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5)
+ if (cdc.ifstat & BIT_DTEI) {
+ /* pending Data Transfer End interrupt */
+ cdc.ifstat &= ~BIT_DTEI;
+
+ /* Data Transfer End interrupt enabled ? */
+ if (cdc.ifctrl & BIT_DTEIEN)
{
- /* update IRQ level */
- elprintf(EL_INTS, "cdc DTE irq 5");
- pcd_irq_s68k(5, 1);
+ /* level 5 interrupt enabled ? */
+ if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5)
+ {
+ /* update IRQ level */
+ elprintf(EL_INTS, "cdc DTE irq 5");
+ pcd_irq_s68k(5, 1);
+ }
}
}
- /* clear DSR bit & set EDT bit (SCD register $04) */
- Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0x80;
-
/* disable DMA transfer */
cdc.dma_w = 0;
}
#ifdef LOG_CDC
elprintf(EL_STATUS, "CDC register %X write 0x%04x", Pico_mcd->s68k_regs[0x04+1] & 0x0F, data);
#endif
- switch (Pico_mcd->s68k_regs[0x04+1] & 0x0F)
+ switch (Pico_mcd->s68k_regs[0x04+1] & 0x1F)
{
+ case 0x00:
+ break;
+
case 0x01: /* IFCTRL */
{
/* pending interrupts ? */
case 0x03: /* DBCH */
cdc.dbc &= 0x00ff;
- cdc.dbc |= data << 8;
+ cdc.dbc |= (data & 0x0f) << 8;
Pico_mcd->s68k_regs[0x04+1] = 0x04;
break;
/* set CRCOK bit only if decoding is enabled */
cdc.stat[0] = data & BIT_DECEN;
+ /* reset DECI if decoder turned off */
+ if (!cdc.stat[0])
+ cdc.ifstat |= BIT_DECI;
+
/* update decoding mode */
if (data & BIT_AUTORQ)
{
case 0x0f: /* RESET */
cdc_reset();
+ Pico_mcd->s68k_regs[0x04+1] = 0x10;
break;
default: /* by default, SBOUT is not used */
+ Pico_mcd->s68k_regs[0x04+1] = (Pico_mcd->s68k_regs[0x04+1] + 1) & 0x1f;
break;
}
}
unsigned char cdc_reg_r(void)
{
- switch (Pico_mcd->s68k_regs[0x04+1] & 0x0F)
+ switch (Pico_mcd->s68k_regs[0x04+1] & 0x01F)
{
+ case 0x00:
+ return 0xff;
+
case 0x01: /* IFSTAT */
Pico_mcd->s68k_regs[0x04+1] = 0x02;
return cdc.ifstat;
}
#endif
- Pico_mcd->s68k_regs[0x04+1] = 0x00;
+ Pico_mcd->s68k_regs[0x04+1] = 0x10;
return data;
}
default: /* by default, COMIN is always empty */
+ Pico_mcd->s68k_regs[0x04+1] = (Pico_mcd->s68k_regs[0x04+1] + 1) & 0x1f;
return 0xff;
}
}
/* clear !DTEN and !DTBSY */
cdc.ifstat |= (BIT_DTBSY | BIT_DTEN);
- /* pending Data Transfer End interrupt */
- cdc.ifstat &= ~BIT_DTEI;
+ /* clear DSR bit & set EDT bit (SCD register $04) */
+ Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0x80;
+ } else if ((int16)cdc.dbc <= 2) {
+ if (cdc.ifstat & BIT_DTEI) {
+ /* pending Data Transfer End interrupt */
+ cdc.ifstat &= ~BIT_DTEI;
- /* Data Transfer End interrupt enabled ? */
- if (cdc.ifctrl & BIT_DTEIEN)
- {
- /* level 5 interrupt enabled ? */
- if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5)
+ /* Data Transfer End interrupt enabled ? */
+ if (cdc.ifctrl & BIT_DTEIEN)
{
- /* update IRQ level */
- elprintf(EL_INTS, "cdc DTE irq 5");
- pcd_irq_s68k(5, 1);
+ /* level 5 interrupt enabled ? */
+ if (Pico_mcd->s68k_regs[0x32+1] & PCDS_IEN5)
+ {
+ /* update IRQ level */
+ elprintf(EL_INTS, "cdc DTE irq 5");
+ pcd_irq_s68k(5, 1);
+ }
}
}
-
- /* clear DSR bit & set EDT bit (SCD register $04) */
- Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0x80;
+ /* set DSR and EDT bit (SCD register $04) */
+ Pico_mcd->s68k_regs[0x04+0] = (Pico_mcd->s68k_regs[0x04+0] & 0x07) | 0xc0;
}
return data;
\r
switch (a) {\r
case 0:\r
- // here IFL2 is always 0, just like in Gens\r
- d = ((Pico_mcd->s68k_regs[0x33] << 13) & 0x8000)\r
- | Pico_mcd->m.busreq;\r
+ pcd_sync_s68k(SekCyclesDone(), 0);\r
+ d = ((Pico_mcd->s68k_regs[0x33] & PCDS_IEN2) << 13) |\r
+ (Pico_mcd->m.state_flags & PCD_ST_S68K_IFL2) | Pico_mcd->m.busreq;\r
goto end;\r
case 2:\r
m68k_comm_check(a);\r
switch (a) {\r
case 0:\r
d &= 1;\r
+ Pico_mcd->m.state_flags &= ~PCD_ST_S68K_IFL2;\r
+ if (d) Pico_mcd->m.state_flags |= PCD_ST_S68K_IFL2;\r
if (d && (Pico_mcd->s68k_regs[0x33] & PCDS_IEN2)) {\r
elprintf(EL_INTS, "m68k: s68k irq 2");\r
pcd_sync_s68k(SekCyclesDone(), 0);\r
if (!(d & 1))\r
Pico_mcd->m.state_flags |= PCD_ST_S68K_RST;\r
else if (d == 1 && (Pico_mcd->m.state_flags & PCD_ST_S68K_RST)) {\r
- Pico_mcd->m.state_flags &= ~PCD_ST_S68K_RST;\r
+ Pico_mcd->m.state_flags &= ~(PCD_ST_S68K_RST|PCD_ST_S68K_POLL|PCD_ST_S68K_SLEEP);\r
elprintf(EL_CDREGS, "m68k: resetting s68k");\r
SekResetS68k();\r
}\r
elprintf(EL_CDREGS, "m68k: prg wp=%02x", d);\r
goto write_comm;\r
case 3:\r
- dold = Pico_mcd->s68k_regs[3];\r
elprintf(EL_CDREG3, "m68k_regs w3: %02x @%06x", (u8)d, SekPc);\r
+ dold = Pico_mcd->s68k_regs[3];\r
if ((d ^ dold) & 0xc0) {\r
elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i",\r
(Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
d = (d & 0xc0) | (dold & 0x1c) | Pico_mcd->m.dmna_ret_2m;\r
if ((dold ^ d) & 0x1f)\r
remap_word_ram(d);\r
-\r
goto write_comm;\r
case 6:\r
Pico_mcd->bios[MEM_BE2(0x72)] = d; // simple hint vector changer\r
elprintf(EL_CDREGS, "hint vector set to %04x%04x",\r
((u16 *)Pico_mcd->bios)[0x70/2], ((u16 *)Pico_mcd->bios)[0x72/2]);\r
return;\r
+ case 8:\r
+ (void) cdc_host_r(); // acts same as reading\r
+ return;\r
case 0x0f:\r
a = 0x0e;\r
case 0x0e:\r
elprintf(EL_CDPOLL, "s68k poll detected @%06x, a=%02x",\r
SekPcS68k, a);\r
} else if (cnt > 2)\r
- SekEndRunS68k(80);\r
+ SekEndRunS68k(240);\r
}\r
}\r
Pico_mcd->m.s68k_poll_a = a;\r
\r
switch (a) {\r
case 0:\r
- return ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state\r
+ d = ((Pico_mcd->s68k_regs[0]&3)<<8) | 1; // ver = 0, not in reset state\r
+ goto end;\r
case 2:\r
d = (Pico_mcd->s68k_regs[2]<<8) | (Pico_mcd->s68k_regs[3]&0x1f);\r
elprintf(EL_CDREG3, "s68k_regs r3: %02x @%06x", (u8)d, SekPcS68k);\r
- return s68k_poll_detect(a, d);\r
+ s68k_poll_detect(a, d);\r
+ goto end;\r
+ case 4:\r
+ d = (Pico_mcd->s68k_regs[4]<<8) | (Pico_mcd->s68k_regs[5]&0x1f);\r
+ goto end;\r
case 6:\r
- return cdc_reg_r();\r
+ d = cdc_reg_r();\r
+ goto end;\r
case 8:\r
- return cdc_host_r();\r
+ d = cdc_host_r();\r
+ goto end;\r
case 0xC:\r
d = SekCyclesDoneS68k() - Pico_mcd->m.stopwatch_base_c;\r
d /= 384;\r
d &= 0x0fff;\r
elprintf(EL_CDREGS, "s68k stopwatch timer read (%04x)", d);\r
- return d;\r
+ goto end;\r
case 0x30:\r
- elprintf(EL_CDREGS, "s68k int3 timer read (%02x)", Pico_mcd->s68k_regs[31]);\r
- return Pico_mcd->s68k_regs[31];\r
+ elprintf(EL_CDREGS, "s68k int3 timer read (%02x)", Pico_mcd->s68k_regs[0x31]);\r
+ d = Pico_mcd->s68k_regs[0x31];\r
+ goto end;\r
case 0x34: // fader\r
- return 0; // no busy bit\r
+ d = 0; // no busy bit\r
+ goto end;\r
case 0x50: // font data (check: Lunar 2, Silpheed)\r
READ_FONT_DATA(0x00100000);\r
- return d;\r
+ goto end;\r
case 0x52:\r
READ_FONT_DATA(0x00010000);\r
- return d;\r
+ goto end;\r
case 0x54:\r
READ_FONT_DATA(0x10000000);\r
- return d;\r
+ goto end;\r
case 0x56:\r
READ_FONT_DATA(0x01000000);\r
- return d;\r
+ goto end;\r
}\r
\r
d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
if (a >= 0x0e && a < 0x30)\r
return s68k_poll_detect(a, d);\r
\r
+end:\r
return d;\r
}\r
\r
if (!(d & 1))\r
pcd_soft_reset();\r
return;\r
- case 2:\r
- return; // only m68k can change WP\r
+ case 2: a++; // byte access only, ignores LDS/UDS\r
case 3: {\r
int dold = Pico_mcd->s68k_regs[3];\r
elprintf(EL_CDREG3, "s68k_regs w3: %02x @%06x", (u8)d, SekPcS68k);\r
}\r
case 4:\r
elprintf(EL_CDREGS, "s68k CDC dest: %x", d&7);\r
- Pico_mcd->s68k_regs[4] = (Pico_mcd->s68k_regs[4]&0xC0) | (d&7); // CDC mode\r
+ Pico_mcd->s68k_regs[a] = (d&7); // CDC mode\r
+ Pico_mcd->s68k_regs[0xa] = Pico_mcd->s68k_regs[0xb] = 0; // resets DMA\r
return;\r
case 5:\r
- //dprintf("s68k CDC reg addr: %x", d&0xf);\r
- break;\r
+ //dprintf("s68k CDC reg addr: %x", d&0x1f);\r
+ Pico_mcd->s68k_regs[a] = (d&0x1f);\r
+ return;\r
case 7:\r
cdc_reg_w(d & 0xff);\r
return;\r
case 0xa:\r
+ case 0xb:\r
+ // word access only. 68k sets both bus halves to value d.\r
elprintf(EL_CDREGS, "s68k set CDC dma addr");\r
- break;\r
+ Pico_mcd->s68k_regs[0xa] = Pico_mcd->s68k_regs[0xb] = d;\r
+ return;\r
case 0xc:\r
case 0xd: // 384 cycle stopwatch timer\r
elprintf(EL_CDREGS|EL_CD, "s68k clear stopwatch (%x)", d);\r
// does this also reset internal 384 cycle counter?\r
Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k();\r
return;\r
- case 0x0e:\r
- a = 0x0f;\r
+ case 0x0e: a++;\r
case 0x0f:\r
goto write_comm;\r
+ case 0x30: a++;\r
case 0x31: // 384 cycle int3 timer\r
d &= 0xff;\r
elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d);\r
Pico_mcd->s68k_regs[a] = (u8) d;\r
- if (d) // d or d+1??\r
- pcd_event_schedule_s68k(PCD_EVENT_TIMER3, d * 384);\r
+ if (d) // XXX: d or d+1? mcd-verificator results suggest d+1\r
+ pcd_event_schedule_s68k(PCD_EVENT_TIMER3, (d+1) * 384);\r
else\r
pcd_event_schedule(0, PCD_EVENT_TIMER3, 0);\r
break;\r
pcd_irq_s68k(4, 1);\r
}\r
}\r
+ if ((d ^ Pico_mcd->s68k_regs[0x33]) & ~d & PCDS_IEN2)\r
+ pcd_irq_s68k(2, 0);\r
break;\r
case 0x34: // fader\r
Pico_mcd->s68k_regs[a] = (u8) d & 0x7f;\r
s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], s[8], s[9]);\r
}\r
return;\r
+ case 0x4c: a++;\r
+ break;\r
case 0x58:\r
return;\r
}\r
goto write_comm;\r
\r
switch (a) {\r
+ case 0x02:\r
case 0x0e:\r
- // special case, 2 byte writes would be handled differently\r
- // TODO: verify\r
- d = (u8)d | (r[0xe] << 8);\r
- goto write_comm;\r
+ case 0x30:\r
+ case 0x4c:\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
+ case 0x0a: // DMA address\r
+ r[0xa] = d >> 8;\r
+ r[0xb] = d;\r
+ return;\r
case 0x58: // stamp data size\r
r[0x59] = d & 7;\r
return;\r
static u32 PicoReadM68k8_ramc(u32 a)\r
{\r
u32 d = 0;\r
- if (a == 0x400001) {\r
+ if ((a & 0xf00001) == 0x400001) {\r
if (Pico.sv.data != NULL)\r
d = 3; // 64k cart\r
return d;\r
}\r
\r
- if ((a & 0xfe0000) == 0x600000) {\r
+ if ((a & 0xf00001) == 0x600001) {\r
if (Pico.sv.data != NULL)\r
d = Pico.sv.data[((a >> 1) & 0xffff) + 0x2000];\r
return d;\r
}\r
\r
- if (a == 0x7fffff)\r
+ if ((a & 0xf00001) == 0x700001)\r
return Pico_mcd->m.bcram_reg;\r
\r
elprintf(EL_UIO, "m68k unmapped r8 [%06x] @%06x", a, SekPc);\r
\r
static void PicoWriteM68k8_ramc(u32 a, u32 d)\r
{\r
- if ((a & 0xfe0000) == 0x600000) {\r
+ if ((a & 0xf00001) == 0x600001) {\r
if (Pico.sv.data != NULL && (Pico_mcd->m.bcram_reg & 1)) {\r
- Pico.sv.data[((a>>1) & 0xffff) + 0x2000] = d;\r
+ Pico.sv.data[((a >> 1) & 0xffff) + 0x2000] = d;\r
Pico.sv.changed = 1;\r
}\r
return;\r
}\r
\r
- if (a == 0x7fffff) {\r
+ if ((a & 0xf00001) == 0x700001) {\r
Pico_mcd->m.bcram_reg = d;\r
return;\r
}\r
u32 d;\r
elprintf(EL_ANOMALY, "FIXME: s68k_bram r16: [%06x] @%06x", a, SekPcS68k);\r
a = (a >> 1) & 0x1fff;\r
- d = Pico_mcd->bram[a++];\r
- d|= Pico_mcd->bram[a++] << 8; // probably wrong, TODO: verify\r
+ d = Pico_mcd->bram[a];\r
return d;\r
}\r
\r
static void PicoWriteS68k8_bram(u32 a, u32 d)\r
{\r
- Pico_mcd->bram[(a >> 1) & 0x1fff] = d;\r
- Pico.sv.changed = 1;\r
+ if (a & 1) {\r
+ Pico_mcd->bram[(a >> 1) & 0x1fff] = d;\r
+ Pico.sv.changed = 1;\r
+ }\r
}\r
\r
static void PicoWriteS68k16_bram(u32 a, u32 d)\r
elprintf(EL_ANOMALY, "s68k_bram w16: [%06x] %04x @%06x", a, d, SekPcS68k);\r
a = (a >> 1) & 0x1fff;\r
Pico_mcd->bram[a++] = d;\r
- Pico_mcd->bram[a++] = d >> 8; // TODO: verify..\r
Pico.sv.changed = 1;\r
}\r
\r
// is reassigned to it (e.g. Mega Race).\r
// since DTACK isn't on the expansion port, main cpu accesses are not blocked.\r
// XXX is data read/written if main is accessing Word_RAM while not owning it?\r
-static u32 m68k_wordram_sub_read8(u32 a)\r
-{\r
- return 0xff;\r
-// return Pico_mcd->word_ram2M[MEM_BE2(a) & 0x3ffff];\r
-}\r
-\r
-static u32 m68k_wordram_sub_read16(u32 a)\r
-{\r
- return 0xffff;\r
-// return ((u16 *)Pico_mcd->word_ram2M)[(a >> 1) & 0x1ffff];\r
-}\r
-\r
-static void m68k_wordram_sub_write8(u32 a, u32 d)\r
-{\r
-// Pico_mcd->word_ram2M[MEM_BE2(a) & 0x3ffff] = d;\r
-}\r
-\r
-static void m68k_wordram_sub_write16(u32 a, u32 d)\r
-{\r
-// ((u16 *)Pico_mcd->word_ram2M)[(a >> 1) & 0x1ffff] = d;\r
-}\r
-\r
static u32 s68k_wordram_main_read8(u32 a)\r
{\r
Pico_mcd->m.state_flags |= PCD_ST_S68K_SLEEP;\r
} else {\r
Pico_mcd->m.state_flags &= ~PCD_ST_S68K_SLEEP;\r
cpu68k_map_all_ram(0x080000, 0x0bffff, bank, 1);\r
- cpu68k_map_all_funcs(0x200000, 0x23ffff,\r
- m68k_wordram_sub_read8, m68k_wordram_sub_read16,\r
- m68k_wordram_sub_write8, m68k_wordram_sub_write16, 0);\r
+ m68k_map_unmap(0x200000, 0x23ffff);\r
}\r
// TODO: handle 0x0c0000\r
}\r
cpu68k_map_set(s68k_write16_map, 0xff0000, 0xffffff, PicoWriteS68k16_pr, 1);\r
\r
// RAMs\r
+ remap_prg_window(2,1);\r
remap_word_ram(1);\r
\r
#ifdef EMU_C68K\r