cd sync improvements, part2
[picodrive.git] / pico / cd / memory.c
index 743568e..82e6d6d 100644 (file)
@@ -65,32 +65,23 @@ void PicoWriteS68k16_dec_m1b1(u32 a, u32 d);
 void PicoWriteS68k16_dec_m2b1(u32 a, u32 d);\r
 #endif\r
 \r
-static void remap_prg_window(void);\r
+static void remap_prg_window(int r3);\r
 static void remap_word_ram(int r3);\r
 \r
 // poller detection\r
 #define POLL_LIMIT 16\r
 #define POLL_CYCLES 124\r
-unsigned int s68k_poll_adclk, s68k_poll_cnt;\r
 \r
-void m68k_comm_check(u32 a)\r
+u32 m68k_comm_check(u32 a, u32 d)\r
 {\r
-  pcd_sync_s68k(SekCyclesDone());\r
-  /*if (Pico_mcd->m.m68k_comm_dirty & (1 << a/2)) {\r
-    Pico_mcd->m.m68k_comm_dirty &= ~(1 << a/2);\r
-    Pico_mcd->m.m68k_poll_a = Pico_mcd->m.m68k_poll_cnt = 0;\r
-    return;\r
-  }\r
+  pcd_sync_s68k(SekCyclesDone(), 0);\r
   if (a != Pico_mcd->m.m68k_poll_a) {\r
     Pico_mcd->m.m68k_poll_a = a;\r
     Pico_mcd->m.m68k_poll_cnt = 0;\r
-    return;\r
+    return d;\r
   }\r
-  if (++Pico_mcd->m.m68k_poll_cnt > 5)\r
-    SekCyclesBurnRun(122);\r
-\r
-  elprintf(EL_CDPOLL, "m68k poll [%02x] %d %u", a,\r
-    Pico_mcd->m.m68k_poll_cnt, SekCyclesDone());*/\r
+  Pico_mcd->m.m68k_poll_cnt++;\r
+  return d;\r
 }\r
 \r
 #ifndef _ASM_CD_MEMORY_C\r
@@ -104,10 +95,9 @@ static u32 m68k_reg_read16(u32 a)
       d = ((Pico_mcd->s68k_regs[0x33]<<13)&0x8000) | Pico_mcd->m.busreq; // here IFL2 is always 0, just like in Gens\r
       goto end;\r
     case 2:\r
-      m68k_comm_check(a);\r
       d = (Pico_mcd->s68k_regs[a]<<8) | (Pico_mcd->s68k_regs[a+1]&0xc7);\r
       elprintf(EL_CDREG3, "m68k_regs r3: %02x @%06x", (u8)d, SekPc);\r
-      goto end;\r
+      goto end_comm;\r
     case 4:\r
       d = Pico_mcd->s68k_regs[4]<<8;\r
       goto end;\r
@@ -131,16 +121,17 @@ static u32 m68k_reg_read16(u32 a)
 \r
   if (a < 0x30) {\r
     // comm flag/cmd/status (0xE-0x2F)\r
-    m68k_comm_check(a);\r
     d = (Pico_mcd->s68k_regs[a]<<8) | Pico_mcd->s68k_regs[a+1];\r
-    goto end;\r
+    goto end_comm;\r
   }\r
 \r
   elprintf(EL_UIO, "m68k_regs FIXME invalid read @ %02x", a);\r
 \r
 end:\r
-\r
   return d;\r
+\r
+end_comm:\r
+  return m68k_comm_check(a, d);\r
 }\r
 #endif\r
 \r
@@ -152,19 +143,24 @@ void m68k_reg_write8(u32 a, u32 d)
   u32 dold;\r
   a &= 0x3f;\r
 \r
-  Pico_mcd->m.m68k_poll_a = 0;\r
+  Pico_mcd->m.m68k_poll_a =\r
+  Pico_mcd->m.m68k_poll_cnt = 0;\r
 \r
   switch (a) {\r
     case 0:\r
       d &= 1;\r
-      if ((d&1) && (Pico_mcd->s68k_regs[0x33]&(1<<2))) { elprintf(EL_INTS, "m68k: s68k irq 2"); SekInterruptS68k(2); }\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
+        SekInterruptS68k(2);\r
+      }\r
       return;\r
     case 1:\r
       d &= 3;\r
           elprintf(EL_CDREGS, "d m.busreq %u %u", d, Pico_mcd->m.busreq);\r
       if (d == Pico_mcd->m.busreq)\r
         return;\r
-      pcd_sync_s68k(SekCyclesDone());\r
+      pcd_sync_s68k(SekCyclesDone(), 0);\r
 \r
       if ((Pico_mcd->m.busreq ^ d) & 1) {\r
         elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1));\r
@@ -177,7 +173,7 @@ void m68k_reg_write8(u32 a, u32 d)
       }\r
       if ((Pico_mcd->m.busreq ^ d) & 2) {\r
         elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1);\r
-        remap_prg_window();\r
+        remap_prg_window(Pico_mcd->s68k_regs[3]);\r
       }\r
       Pico_mcd->m.busreq = d;\r
       return;\r
@@ -194,24 +190,19 @@ void m68k_reg_write8(u32 a, u32 d)
       if (dold & 4) {   // 1M mode\r
         d ^= 2;         // writing 0 to DMNA actually sets it, 1 does nothing\r
       } else {\r
-       if ((d ^ dold) & d & 2) { // DMNA is being set\r
+        if ((d ^ dold) & d & 2) { // DMNA is being set\r
           dold &= ~1;   // return word RAM to s68k\r
           /* Silpheed hack: bset(w3), r3, btst, bne, r3 */\r
           SekEndRun(20+16+10+12+16);\r
         }\r
       }\r
-      Pico_mcd->s68k_regs[3] = (d & 0xc2) | (dold & 0x1f);\r
+      d = (d & 0xc2) | (dold & 0x1f);\r
       if ((d ^ dold) & 0xc0) {\r
-        elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i", (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
-        remap_prg_window();\r
-      }\r
-#ifdef USE_POLL_DETECT\r
-      if ((s68k_poll_adclk&0xfe) == 2 && s68k_poll_cnt > POLL_LIMIT) {\r
-        SekSetStopS68k(0); s68k_poll_adclk = 0;\r
-        elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
+        elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i",\r
+          (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));\r
+        remap_prg_window(d);\r
       }\r
-#endif\r
-      return;\r
+      goto write_comm;\r
     case 6:\r
       Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer\r
       return;\r
@@ -220,34 +211,30 @@ void m68k_reg_write8(u32 a, u32 d)
       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 0xf:\r
+    case 0x0f:\r
       d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case)\r
-    case 0xe:\r
-      if (d != Pico_mcd->s68k_regs[0xe]) {\r
-        pcd_sync_s68k(SekCyclesDone());\r
-        Pico_mcd->s68k_regs[0xe] = d;\r
-      }\r
-#ifdef USE_POLL_DETECT\r
-      if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) {\r
-        SekSetStopS68k(0); s68k_poll_adclk = 0;\r
-        elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
-      }\r
-#endif\r
-      return;\r
+      a = 0x0e;\r
+    case 0x0e:\r
+      goto write_comm;\r
   }\r
 \r
-  if ((a&0xf0) == 0x10) {\r
-      Pico_mcd->s68k_regs[a] = d;\r
-#ifdef USE_POLL_DETECT\r
-      if ((a&0xfe) == (s68k_poll_adclk&0xfe) && s68k_poll_cnt > POLL_LIMIT) {\r
-        SekSetStopS68k(0); s68k_poll_adclk = 0;\r
-        elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
-      }\r
-#endif\r
-      return;\r
-  }\r
+  if ((a&0xf0) == 0x10)\r
+    goto write_comm;\r
 \r
   elprintf(EL_UIO, "m68k FIXME: invalid write? [%02x] %02x", a, d);\r
+  return;\r
+\r
+write_comm:\r
+  if (d == Pico_mcd->s68k_regs[a])\r
+    return;\r
+\r
+  Pico_mcd->s68k_regs[a] = d;\r
+  pcd_sync_s68k(SekCyclesDone(), 0);\r
+  if (Pico_mcd->m.s68k_poll_a == a && Pico_mcd->m.s68k_poll_cnt > POLL_LIMIT) {\r
+    SekSetStopS68k(0);\r
+    Pico_mcd->m.s68k_poll_a = 0;\r
+    elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
+  }\r
 }\r
 \r
 #ifndef _ASM_CD_MEMORY_C\r
@@ -256,24 +243,26 @@ static
 u32 s68k_poll_detect(u32 a, u32 d)\r
 {\r
 #ifdef USE_POLL_DETECT\r
-  // needed mostly for Cyclone, which doesn't always check it's cycle counter\r
-  if (SekIsStoppedS68k()) return d;\r
-  // polling detection\r
-  if (a == (s68k_poll_adclk&0xff)) {\r
-    unsigned int clkdiff = SekCyclesDoneS68k() - (s68k_poll_adclk>>8);\r
+  u32 cycles, cnt = 0;\r
+  if (SekIsStoppedS68k())\r
+    return d;\r
+\r
+  cycles = SekCyclesDoneS68k();\r
+  if (a == Pico_mcd->m.s68k_poll_a) {\r
+    u32 clkdiff = cycles - Pico_mcd->m.s68k_poll_clk;\r
     if (clkdiff <= POLL_CYCLES) {\r
-      s68k_poll_cnt++;\r
-      //printf("-- diff: %u, cnt = %i\n", clkdiff, s68k_poll_cnt);\r
-      if (s68k_poll_cnt > POLL_LIMIT) {\r
+      cnt = Pico_mcd->m.s68k_poll_cnt + 1;\r
+      //printf("-- diff: %u, cnt = %i\n", clkdiff, cnt);\r
+      if (Pico_mcd->m.s68k_poll_cnt > POLL_LIMIT) {\r
         SekSetStopS68k(1);\r
-        elprintf(EL_CDPOLL, "s68k poll detected @ %06x, a=%02x", SekPcS68k, a);\r
+        elprintf(EL_CDPOLL, "s68k poll detected @ %06x, a=%02x",\r
+          SekPcS68k, a);\r
       }\r
-      s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a;\r
-      return d;\r
     }\r
   }\r
-  s68k_poll_adclk = (SekCyclesDoneS68k() << 8) | a;\r
-  s68k_poll_cnt = 0;\r
+  Pico_mcd->m.s68k_poll_a = a;\r
+  Pico_mcd->m.s68k_poll_clk = cycles;\r
+  Pico_mcd->m.s68k_poll_cnt = cnt;\r
 #endif\r
   return d;\r
 }\r
@@ -384,7 +373,7 @@ void s68k_reg_write8(u32 a, u32 d)
         if (d & 1)\r
           d &= ~2;                       // DMNA clears\r
       }\r
-      break;\r
+      goto write_comm;\r
     }\r
     case 4:\r
       elprintf(EL_CDREGS, "s68k CDC dest: %x", d&7);\r
@@ -405,9 +394,12 @@ void s68k_reg_write8(u32 a, u32 d)
       // does this also reset internal 384 cycle counter?\r
       Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k();\r
       return;\r
-    case 0xe:\r
+    case 0x0e:\r
+      d &= 0xff;\r
       d = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair\r
-      break;\r
+      a = 0x0f;\r
+    case 0x0f:\r
+      goto write_comm;\r
     case 0x31: // 384 cycle int3 timer\r
       d &= 0xff;\r
       elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d);\r
@@ -444,16 +436,23 @@ void s68k_reg_write8(u32 a, u32 d)
       return;\r
   }\r
 \r
+  if ((a&0x1f0) == 0x20)\r
+    goto write_comm;\r
+\r
   if ((a&0x1f0) == 0x10 || (a >= 0x38 && a < 0x42))\r
   {\r
     elprintf(EL_UIO, "s68k FIXME: invalid write @ %02x?", a);\r
     return;\r
   }\r
 \r
-  if (a < 0x30)\r
-    Pico_mcd->m.m68k_comm_dirty |= (1 << a/2);\r
+  Pico_mcd->s68k_regs[a] = (u8) d;\r
+  return;\r
 \r
+write_comm:\r
   Pico_mcd->s68k_regs[a] = (u8) d;\r
+  if (Pico_mcd->m.m68k_poll_cnt)\r
+    SekEndRunS68k(0);\r
+  Pico_mcd->m.m68k_poll_cnt = 0;\r
 }\r
 \r
 // -----------------------------------------------------------------\r
@@ -611,20 +610,10 @@ static void PicoWriteM68k16_io(u32 a, u32 d)
 {\r
   if ((a & 0xff00) == 0x2000) { // a12000 - a120ff\r
     elprintf(EL_CDREGS, "m68k_regs w16: [%02x] %04x @%06x", a&0x3f, d, SekPc);\r
-/* TODO FIXME?\r
-    if (a == 0xe) { // special case, 2 byte writes would be handled differently\r
-      Pico_mcd->s68k_regs[0xe] = d >> 8;\r
-#ifdef USE_POLL_DETECT\r
-      if ((s68k_poll_adclk&0xfe) == 0xe && s68k_poll_cnt > POLL_LIMIT) {\r
-        SekSetStopS68k(0); s68k_poll_adclk = 0;\r
-        elprintf(EL_CDPOLL, "s68k poll release, a=%02x", a);\r
-      }\r
-#endif\r
-      return;\r
-    }\r
-*/\r
+\r
     m68k_reg_write8(a,     d >> 8);\r
-    m68k_reg_write8(a + 1, d & 0xff);\r
+    if ((a & 0x3e) != 0x0e) // special case\r
+      m68k_reg_write8(a + 1, d & 0xff);\r
     return;\r
   }\r
 \r
@@ -965,11 +954,11 @@ static const void *s68k_dec_write16[2][4] = {
 \r
 // -----------------------------------------------------------------\r
 \r
-static void remap_prg_window(void)\r
+static void remap_prg_window(int r3)\r
 {\r
   // PRG RAM\r
   if (Pico_mcd->m.busreq & 2) {\r
-    void *bank = Pico_mcd->prg_ram_b[Pico_mcd->s68k_regs[3] >> 6];\r
+    void *bank = Pico_mcd->prg_ram_b[r3 >> 6];\r
     cpu68k_map_all_ram(0x020000, 0x03ffff, bank, 0);\r
   }\r
   else {\r
@@ -1034,7 +1023,7 @@ void pcd_state_loaded_mem(void)
   if (r3 & 4) // 1M mode?\r
     wram_2M_to_1M(Pico_mcd->word_ram2M);\r
   remap_word_ram(r3);\r
-  remap_prg_window();\r
+  remap_prg_window(r3);\r
 \r
   // restore hint vector\r
   *(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector;\r
@@ -1144,9 +1133,6 @@ PICO_INTERNAL void PicoMemSetupCD(void)
 #ifdef EMU_M68K\r
   m68k_mem_setup_cd();\r
 #endif\r
-\r
-  // m68k_poll_addr = m68k_poll_cnt = 0;\r
-  s68k_poll_adclk = s68k_poll_cnt = 0;\r
 }\r
 \r
 \r