32x: handle FEN quirk
authornotaz <notasas@gmail.com>
Sat, 10 Aug 2013 22:32:19 +0000 (01:32 +0300)
committernotaz <notasas@gmail.com>
Sat, 10 Aug 2013 22:32:19 +0000 (01:32 +0300)
Metal Head relies on it?

pico/32x/32x.c
pico/32x/memory.c
pico/pico_int.h

index dd4d0ed..0a72ddb 100644 (file)
@@ -155,7 +155,7 @@ void PicoPower32x(void)
   memset(&Pico32x, 0, sizeof(Pico32x));
 
   Pico32x.regs[0] = P32XS_REN|P32XS_nRES; // verified
-  Pico32x.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_HBLK|P32XV_PEN;
+  Pico32x.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_PEN;
   Pico32x.sh2_regs[0] = P32XS2_ADEN;
 }
 
@@ -322,8 +322,8 @@ static inline void run_sh2(SH2 *sh2, int m68k_cycles)
   pevt_log_sh2_o(sh2, EVT_RUN_START);
   sh2->state |= SH2_STATE_RUN;
   cycles = C_M68K_TO_SH2(*sh2, m68k_cycles);
-  elprintf(EL_32X, "%csh2 +run %u %d",
-    sh2->is_slave?'s':'m', sh2->m68krcycles_done, cycles);
+  elprintf(EL_32X, "%csh2 +run %u %d @%08x",
+    sh2->is_slave?'s':'m', sh2->m68krcycles_done, cycles, sh2->pc);
 
   done = sh2_execute(sh2, cycles);
 
index 11b0462..0e19d69 100644 (file)
@@ -93,12 +93,12 @@ void p32x_m68k_poll_event(u32 flags)
   m68k_poll.addr = m68k_poll.cnt = 0;
 }
 
-static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags)
+static void sh2_poll_detect(SH2 *sh2, u32 a, u32 flags, int maxcnt)
 {
   int cycles_left = sh2_cycles_left(sh2);
 
   if (a == sh2->poll_addr && sh2->poll_cycles - cycles_left <= 10) {
-    if (sh2->poll_cnt++ > 3) {
+    if (sh2->poll_cnt++ > maxcnt) {
       if (!(sh2->state & flags))
         elprintf(EL_32X, "%csh2 state: %02x->%02x", sh2->is_slave?'s':'m',
           sh2->state, sh2->state | flags);
@@ -321,6 +321,8 @@ static void p32x_reg_write16(u32 a, u32 d)
         if (Pico32x.dmac0_fifo_ptr == DMAC_FIFO_LEN)
           r[6 / 2] |= P32XS_FULL;
       }
+      else
+        elprintf(EL_32X|EL_ANOMALY, "DREQ FIFO overflow!");
       break;
   }
 
@@ -363,9 +365,22 @@ static void p32x_reg_write16(u32 a, u32 d)
 // VDP regs
 static u32 p32x_vdp_read16(u32 a)
 {
+  u32 d;
   a &= 0x0e;
 
-  return Pico32x.vdp_regs[a / 2];
+  d = Pico32x.vdp_regs[a / 2];
+  if (a == 0x0a) {
+    // tested: FEN seems to be randomly pulsing on hcnt 0x80-0xf0,
+    // most often at 0xb1-0xb5, even during vblank,
+    // what's the deal with that?
+    // we'll just fake it along with hblank for now
+    Pico32x.vdp_fbcr_fake++;
+    if (Pico32x.vdp_fbcr_fake & 4)
+      d |= P32XV_HBLK;
+    if ((Pico32x.vdp_fbcr_fake & 7) == 0)
+      d |= P32XV_nFEN;
+  }
+  return d;
 }
 
 static void p32x_vdp_write8(u32 a, u32 d)
@@ -442,7 +457,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
       return (r[0] & P32XS_FM) | Pico32x.sh2_regs[0]
         | Pico32x.sh2irq_mask[sh2->is_slave];
     case 0x04: // H count (often as comm too)
-      sh2_poll_detect(sh2, a, SH2_STATE_CPOLL);
+      sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3);
       sh2s_sync_on_read(sh2);
       return Pico32x.sh2_regs[4 / 2];
     case 0x10: // DREQ len
@@ -458,7 +473,7 @@ static u32 p32x_sh2reg_read16(u32 a, SH2 *sh2)
     if (Pico32x.comm_dirty_68k & comreg)
       Pico32x.comm_dirty_68k &= ~comreg;
     else
-      sh2_poll_detect(sh2, a, SH2_STATE_CPOLL);
+      sh2_poll_detect(sh2, a, SH2_STATE_CPOLL, 3);
     sh2s_sync_on_read(sh2);
     return r[a / 2];
   }
@@ -917,7 +932,7 @@ static u32 sh2_read8_cs0(u32 a, SH2 *sh2)
 
   if ((a & 0x3ff00) == 0x4100) {
     d = p32x_vdp_read16(a);
-    sh2_poll_detect(sh2, a, SH2_STATE_VPOLL);
+    sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
     goto out_16to8;
   }
 
@@ -971,7 +986,7 @@ static u32 sh2_read16_cs0(u32 a, SH2 *sh2)
 
   if ((a & 0x3ff00) == 0x4100) {
     d = p32x_vdp_read16(a);
-    sh2_poll_detect(sh2, a, SH2_STATE_VPOLL);
+    sh2_poll_detect(sh2, a, SH2_STATE_VPOLL, 7);
     goto out;
   }
 
index 34b2881..53c6f4e 100644 (file)
@@ -512,7 +512,8 @@ struct Pico32x
   unsigned int sh2irqs;          // common irqs\r
   unsigned short dmac_fifo[DMAC_FIFO_LEN];\r
   unsigned int dmac0_fifo_ptr;\r
-  unsigned int pad;\r
+  unsigned short vdp_fbcr_fake;\r
+  unsigned short pad;\r
   unsigned char comm_dirty_68k;\r
   unsigned char comm_dirty_sh2;\r
   unsigned char pwm_irq_cnt;\r