cd sync improvements
authornotaz <notasas@gmail.com>
Mon, 26 Aug 2013 00:46:27 +0000 (03:46 +0300)
committernotaz <notasas@gmail.com>
Tue, 27 Aug 2013 22:51:29 +0000 (01:51 +0300)
pico/cd/memory.c
pico/cd/memory_arm.s
pico/cd/pico.c
pico/debug.c
pico/pico_int.h

index 2c6eadc..743568e 100644 (file)
@@ -73,6 +73,26 @@ static void remap_word_ram(int r3);
 #define POLL_CYCLES 124\r
 unsigned int s68k_poll_adclk, s68k_poll_cnt;\r
 \r
+void m68k_comm_check(u32 a)\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
+  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
+  }\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
+}\r
+\r
 #ifndef _ASM_CD_MEMORY_C\r
 static u32 m68k_reg_read16(u32 a)\r
 {\r
@@ -84,6 +104,7 @@ 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
@@ -110,6 +131,7 @@ 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
   }\r
@@ -130,6 +152,8 @@ void m68k_reg_write8(u32 a, u32 d)
   u32 dold;\r
   a &= 0x3f;\r
 \r
+  Pico_mcd->m.m68k_poll_a = 0;\r
+\r
   switch (a) {\r
     case 0:\r
       d &= 1;\r
@@ -137,18 +161,24 @@ void m68k_reg_write8(u32 a, u32 d)
       return;\r
     case 1:\r
       d &= 3;\r
-      if (!(d&1)) Pico_mcd->m.state_flags |= 1; // reset pending, needed to be sure we fetch the right vectors on reset\r
-      if ( (Pico_mcd->m.busreq&1) != (d&1)) elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1));\r
-      if ( (Pico_mcd->m.busreq&2) != (d&2)) elprintf(EL_INTSW, "m68k: s68k brq %i", (d&2)>>1);\r
-      if ((Pico_mcd->m.state_flags&1) && (d&3)==1) {\r
-        SekResetS68k(); // S68k comes out of RESET or BRQ state\r
-        Pico_mcd->m.state_flags&=~1;\r
-        elprintf(EL_CDREGS, "m68k: resetting s68k, cycles=%i", SekCyclesLeft);\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
+\r
+      if ((Pico_mcd->m.busreq ^ d) & 1) {\r
+        elprintf(EL_INTSW, "m68k: s68k reset %i", !(d&1));\r
+        if (!(d & 1))\r
+          d |= 2; // verified: reset also gives bus\r
+        else {\r
+          elprintf(EL_CDREGS, "m68k: resetting s68k");\r
+          SekResetS68k();\r
+        }\r
       }\r
-      if (!(d & 1))\r
-        d |= 2; // verified: reset also gives bus\r
-      if ((d ^ Pico_mcd->m.busreq) & 2)\r
+      if ((Pico_mcd->m.busreq ^ d) & 2) {\r
+        elprintf(EL_INTSW, "m68k: s68k brq %i", d >> 1);\r
         remap_prg_window();\r
+      }\r
       Pico_mcd->m.busreq = d;\r
       return;\r
     case 2:\r
@@ -193,8 +223,10 @@ void m68k_reg_write8(u32 a, u32 d)
     case 0xf:\r
       d = (d << 1) | ((d >> 7) & 1); // rol8 1 (special case)\r
     case 0xe:\r
-      //dprintf("m68k: comm flag: %02x", d);\r
-      Pico_mcd->s68k_regs[0xe] = d;\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
@@ -374,8 +406,8 @@ void s68k_reg_write8(u32 a, u32 d)
       Pico_mcd->m.stopwatch_base_c = SekCyclesDoneS68k();\r
       return;\r
     case 0xe:\r
-      Pico_mcd->s68k_regs[0xf] = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair\r
-      return;\r
+      d = (d>>1) | (d<<7); // ror8 1, Gens note: Dragons lair\r
+      break;\r
     case 0x31: // 384 cycle int3 timer\r
       d &= 0xff;\r
       elprintf(EL_CDREGS|EL_CD, "s68k set int3 timer: %02x", d);\r
@@ -418,6 +450,9 @@ void s68k_reg_write8(u32 a, u32 d)
     return;\r
   }\r
 \r
+  if (a < 0x30)\r
+    Pico_mcd->m.m68k_comm_dirty |= (1 << a/2);\r
+\r
   Pico_mcd->s68k_regs[a] = (u8) d;\r
 }\r
 \r
index b9bbaec..598bcd7 100644 (file)
@@ -216,6 +216,9 @@ m_m68k_read8_r0d:
     mov     r0, r0, lsr #16
     bx      lr
 m_m68k_read8_hi:
+    push    {r0,r1,lr}
+    bl      m68k_comm_check
+    pop     {r0,r1,lr}
     cmp     r0, #0x30
     movge   r0, #0
     bxeq    lr
index 0b6b943..eabd2ea 100644 (file)
@@ -45,7 +45,7 @@ PICO_INTERNAL int PicoResetMCD(void)
   memset(&Pico_mcd->m, 0, sizeof(Pico_mcd->m));
 
   memset(Pico_mcd->bios + 0x70, 0xff, 4); // reset hint vector (simplest way to implement reg6)
-  Pico_mcd->m.state_flags |= 1; // s68k reset pending
+  Pico_mcd->m.state_flags = 0;
   Pico_mcd->s68k_regs[3] = 1; // 2M word RAM mode with m68k access after reset
 
   Reset_CD();
@@ -219,7 +219,7 @@ static void pcd_run_events(unsigned int until)
       oldest, event_time_next);
 }
 
-static void pcd_sync_s68k(unsigned int m68k_target)
+void pcd_sync_s68k(unsigned int m68k_target)
 {
   #define now SekCycleCntS68k
   unsigned int s68k_target =
index 26b6393..959331f 100644 (file)
@@ -45,9 +45,6 @@ char *PDebugMain(void)
   sprintf(dstrp, "pend int: v:%i, h:%i, vdp status: %04x\n", bit(pv->pending_ints,5), bit(pv->pending_ints,4), pv->status); MVP;
   sprintf(dstrp, "pal: %i, hw: %02x, frame#: %i, cycles: %i\n", Pico.m.pal, Pico.m.hardware, Pico.m.frame_count, SekCyclesDone()); MVP;
   sprintf(dstrp, "M68k: PC: %06x, SR: %04x, irql: %i\n", SekPc, SekSr, SekIrqLevel); MVP;
-#if defined(EMU_C68K)
-  sprintf(dstrp - 1, ", st_flg: %x\n", PicoCpuCM68k.state_flags); MVP;
-#endif
   for (r = 0; r < 8; r++) {
     sprintf(dstrp, "d%i=%08x, a%i=%08x\n", r, SekDar(r), r, SekDar(r+8)); MVP;
   }
index ef49295..c23705b 100644 (file)
@@ -132,7 +132,11 @@ extern unsigned int SekCycleAim;
 \r
 // burn cycles while not in SekRun() and while in\r
 #define SekCyclesBurn(c)    SekCycleCnt += c\r
-#define SekCyclesBurnRun(c) SekCyclesLeft -= c\r
+#define SekCyclesBurnRun(c) { \\r
+  SekCyclesLeft -= c; \\r
+  if (SekCyclesLeft < 0) \\r
+    SekCyclesLeft = 0; \\r
+}\r
 \r
 // note: sometimes may extend timeslice to delay an irq\r
 #define SekEndRun(after) { \\r
@@ -383,9 +387,12 @@ struct mcd_misc
        unsigned short hint_vector;\r
        unsigned char  busreq;\r
        unsigned char  s68k_pend_ints;\r
-       unsigned int   state_flags;     // 04: emu state: reset_pending\r
+       unsigned int   state_flags;     // 04\r
        unsigned int   stopwatch_base_c;\r
-       unsigned int   pad[3];\r
+       unsigned int   m68k_comm_dirty;\r
+       unsigned short m68k_poll_a;\r
+       unsigned short m68k_poll_cnt;\r
+       unsigned int   pad;\r
        unsigned char  bcram_reg;       // 18: battery-backed RAM cart register\r
        unsigned char  pad2;\r
        unsigned short pad3;\r
@@ -624,6 +631,7 @@ extern unsigned int pcd_event_times[PCD_EVENT_COUNT];
 void pcd_event_schedule(unsigned int now, enum pcd_event event, int after);\r
 void pcd_event_schedule_s68k(enum pcd_event event, int after);\r
 unsigned int pcd_cycles_m68k_to_s68k(unsigned int c);\r
+void pcd_sync_s68k(unsigned int m68k_target);\r
 void pcd_state_loaded(void);\r
 \r
 // pico/pico.c\r