From ba6e8bfd4b707aab042e47bc3e2a14f70be01075 Mon Sep 17 00:00:00 2001
From: notaz <notasas@gmail.com>
Date: Wed, 28 Aug 2013 03:07:33 +0300
Subject: [PATCH] cd: clean up dmna handling, stuff

---
 pico/cd/mcd.c    | 17 +++++++++--
 pico/cd/memory.c | 73 +++++++++++++++++++++++++-----------------------
 pico/pico_int.h  |  2 +-
 3 files changed, 54 insertions(+), 38 deletions(-)

diff --git a/pico/cd/mcd.c b/pico/cd/mcd.c
index 539d157e..82ae1bc6 100644
--- a/pico/cd/mcd.c
+++ b/pico/cd/mcd.c
@@ -252,15 +252,18 @@ int pcd_sync_s68k(unsigned int m68k_target, int m68k_poll_sync)
   #undef now
 }
 
+#define pcd_run_cpus_normal pcd_run_cpus
+//#define pcd_run_cpus_lockstep pcd_run_cpus
+
 static void SekSyncM68k(void);
 
-static void pcd_run_cpus(int m68k_cycles)
+static inline void pcd_run_cpus_normal(int m68k_cycles)
 {
   SekCycleAim += m68k_cycles;
   if (Pico_mcd->m.m68k_poll_cnt >= 16 && !SekShouldInterrupt()) {
     int s68k_left = pcd_sync_s68k(SekCycleAim, 1);
     if (s68k_left <= 0) {
-      elprintf(EL_CDPOLL, "m68k poll [%02x] %d @%06x",
+      elprintf(EL_CDPOLL, "m68k poll [%02x] x%d @%06x",
         Pico_mcd->m.m68k_poll_a, Pico_mcd->m.m68k_poll_cnt, SekPc);
       SekCycleCnt = SekCycleAim;
       return;
@@ -271,6 +274,16 @@ static void pcd_run_cpus(int m68k_cycles)
   SekSyncM68k();
 }
 
+static inline void pcd_run_cpus_lockstep(int m68k_cycles)
+{
+  unsigned int target = SekCycleAim + m68k_cycles;
+  do {
+    SekCycleAim += 8;
+    SekSyncM68k();
+    pcd_sync_s68k(SekCycleAim, 0);
+  } while (CYCLES_GT(target, SekCycleAim));
+}
+
 #define PICO_CD
 #define CPUS_RUN(m68k_cycles) \
   pcd_run_cpus(m68k_cycles)
diff --git a/pico/cd/memory.c b/pico/cd/memory.c
index 82e6d6dd..f8ffaeb0 100644
--- a/pico/cd/memory.c
+++ b/pico/cd/memory.c
@@ -184,24 +184,24 @@ void m68k_reg_write8(u32 a, u32 d)
     case 3:
       dold = Pico_mcd->s68k_regs[3];
       elprintf(EL_CDREG3, "m68k_regs w3: %02x @%06x", (u8)d, SekPc);
-      //if ((Pico_mcd->s68k_regs[3]&4) != (d&4)) dprintf("m68k: ram mode %i mbit", (d&4) ? 1 : 2);
-      //if ((Pico_mcd->s68k_regs[3]&2) != (d&2)) dprintf("m68k: %s", (d&4) ? ((d&2) ? "word swap req" : "noop?") :
-      //                                             ((d&2) ? "word ram to s68k" : "word ram to m68k"));
-      if (dold & 4) {   // 1M mode
-        d ^= 2;         // writing 0 to DMNA actually sets it, 1 does nothing
-      } else {
-        if ((d ^ dold) & d & 2) { // DMNA is being set
-          dold &= ~1;   // return word RAM to s68k
-          /* Silpheed hack: bset(w3), r3, btst, bne, r3 */
-          SekEndRun(20+16+10+12+16);
-        }
-      }
-      d = (d & 0xc2) | (dold & 0x1f);
       if ((d ^ dold) & 0xc0) {
         elprintf(EL_CDREGS, "m68k: prg bank: %i -> %i",
           (Pico_mcd->s68k_regs[a]>>6), ((d>>6)&3));
         remap_prg_window(d);
       }
+
+      // 2M mode state is tracked regardless of current mode
+      if (d & 2) {
+        Pico_mcd->m.dmna_ret_2m |= 2;
+        Pico_mcd->m.dmna_ret_2m &= ~1;
+      }
+      if (dold & 4) { // 1M mode
+        d ^= 2;       // 0 sets DMNA, 1 does nothing
+        d = (d & 0xc2) | (dold & 0x1f);
+      }
+      else
+        d = (d & 0xc0) | (dold & 0x1c) | Pico_mcd->m.dmna_ret_2m;
+
       goto write_comm;
     case 6:
       Pico_mcd->bios[0x72 + 1] = d; // simple hint vector changer
@@ -343,35 +343,34 @@ void s68k_reg_write8(u32 a, u32 d)
       elprintf(EL_CDREG3, "s68k_regs w3: %02x @%06x", (u8)d, SekPcS68k);
       d &= 0x1d;
       d |= dold & 0xc2;
+
+      // 2M mode state
+      if (d & 1) {
+        Pico_mcd->m.dmna_ret_2m |= 1;
+        Pico_mcd->m.dmna_ret_2m &= ~2; // DMNA clears
+      }
+
       if (d & 4)
       {
-        if ((d ^ dold) & 0x1d) {
-          d &= ~2; // in case of mode or bank change we clear DMNA (m68k req) bit
-          remap_word_ram(d);
-        }
         if (!(dold & 4)) {
           elprintf(EL_CDREG3, "wram mode 2M->1M");
           wram_2M_to_1M(Pico_mcd->word_ram2M);
         }
+
+        if ((d ^ dold) & 0x1d)
+          remap_word_ram(d);
+
+        if ((d ^ dold) & 0x05)
+          d &= ~2; // clear DMNA - swap complete
       }
       else
       {
         if (dold & 4) {
           elprintf(EL_CDREG3, "wram mode 1M->2M");
-          if (!(d&1)) { // it didn't set the ret bit, which means it doesn't want to give WRAM to m68k
-            d &= ~3;
-            d |= (dold&1) ? 2 : 1; // then give it to the one which had bank0 in 1M mode
-          }
           wram_1M_to_2M(Pico_mcd->word_ram2M);
           remap_word_ram(d);
         }
-        // s68k can only set RET, writing 0 has no effect
-        else if ((dold ^ d) & d & 1) {   // RET being set
-          SekEndRunS68k(20+16+10+12+16); // see DMNA case
-        } else
-          d |= dold & 1;
-        if (d & 1)
-          d &= ~2;                       // DMNA clears
+        d = (d & ~3) | Pico_mcd->m.dmna_ret_2m;
       }
       goto write_comm;
     }
@@ -806,20 +805,22 @@ static u32 PicoReadS68k8_pr(u32 a)
   // regs
   if ((a & 0xfe00) == 0x8000) {
     a &= 0x1ff;
-    elprintf(EL_CDREGS, "s68k_regs r8: [%02x] @ %06x", a, SekPcS68k);
     if (a >= 0x0e && a < 0x30) {
       d = Pico_mcd->s68k_regs[a];
       s68k_poll_detect(a, d);
-      elprintf(EL_CDREGS, "ret = %02x", (u8)d);
-      return d;
+      goto regs_done;
     }
     else if (a >= 0x58 && a < 0x68)
          d = gfx_cd_read(a & ~1);
     else d = s68k_reg_read16(a & ~1);
     if (!(a & 1))
       d >>= 8;
-    elprintf(EL_CDREGS, "ret = %02x", (u8)d);
-    return d & 0xff;
+
+regs_done:
+    d &= 0xff;
+    elprintf(EL_CDREGS, "s68k_regs r8: [%02x] %02x @ %06x",
+      a, d, SekPcS68k);
+    return d;
   }
 
   // PCM
@@ -847,11 +848,12 @@ static u32 PicoReadS68k16_pr(u32 a)
   // regs
   if ((a & 0xfe00) == 0x8000) {
     a &= 0x1fe;
-    elprintf(EL_CDREGS, "s68k_regs r16: [%02x] @ %06x", a, SekPcS68k);
     if (0x58 <= a && a < 0x68)
          d = gfx_cd_read(a);
     else d = s68k_reg_read16(a);
-    elprintf(EL_CDREGS, "ret = %04x", d);
+
+    elprintf(EL_CDREGS, "s68k_regs r16: [%02x] %04x @ %06x",
+      a, d, SekPcS68k);
     return d;
   }
 
@@ -1024,6 +1026,7 @@ void pcd_state_loaded_mem(void)
     wram_2M_to_1M(Pico_mcd->word_ram2M);
   remap_word_ram(r3);
   remap_prg_window(r3);
+  Pico_mcd->m.dmna_ret_2m &= 3;
 
   // restore hint vector
   *(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector;
diff --git a/pico/pico_int.h b/pico/pico_int.h
index be56abd0..2053ac60 100644
--- a/pico/pico_int.h
+++ b/pico/pico_int.h
@@ -395,7 +395,7 @@ struct mcd_misc
 	unsigned short s68k_poll_cnt;
 	unsigned int   s68k_poll_clk;
 	unsigned char  bcram_reg;	// 18: battery-backed RAM cart register
-	unsigned char  pad2;
+	unsigned char  dmna_ret_2m;
 	unsigned short pad3;
 	int pad4[9];
 };
-- 
2.39.5