work on 'vblank on line start' problem, var changes, mask defines
[picodrive.git] / Pico / VideoPort.c
index cceab7c..55514ed 100644 (file)
@@ -13,7 +13,6 @@
 extern const unsigned char  hcounts_32[];\r
 extern const unsigned char  hcounts_40[];\r
 extern const unsigned short vcounts[];\r
-extern int rendstatus;\r
 \r
 #ifndef UTYPES_DEFINED\r
 typedef unsigned char  u8;\r
@@ -37,7 +36,7 @@ static void VideoWrite(u16 d)
   {\r
     case 1: if(a&1) d=(u16)((d<<8)|(d>>8)); // If address is odd, bytes are swapped (which game needs this?)\r
             Pico.vram [(a>>1)&0x7fff]=d;\r
-            rendstatus|=0x10; break;\r
+            rendstatus |= PDRAW_DIRTY_SPRITES; break;\r
     case 3: Pico.m.dirtyPal = 1;\r
             Pico.cram [(a>>1)&0x003f]=d; break; // wraps (Desert Strike)\r
     case 5: Pico.vsram[(a>>1)&0x003f]=d; break;\r
@@ -93,9 +92,9 @@ static void DmaSlow(int len)
     Pico.video.type, source, a, len, inc, (Pico.video.status&8)||!(Pico.video.reg[1]&0x40),\r
     SekCyclesDone(), SekPc);\r
 \r
-  if(Pico.m.scanline != -1) {\r
+  if (Pico.m.scanline != -1) {\r
     Pico.m.dma_xfers += len;\r
-    if ((PicoMCD&1) && (PicoOpt & 0x2000)) SekCyclesBurn(CheckDMA());\r
+    if ((PicoAHW & PAHW_MCD) && (PicoOpt & POPT_EN_MCD_PSYNC)) SekCyclesBurn(CheckDMA());\r
     else SekSetCyclesLeftNoMCD(SekCyclesLeftNoMCD - CheckDMA());\r
   } else {\r
     // be approximate in non-accurate mode\r
@@ -105,7 +104,9 @@ static void DmaSlow(int len)
   if ((source&0xe00000)==0xe00000) { // Ram\r
     pd=(u16 *)(Pico.ram+(source&0xfffe));\r
     pdend=(u16 *)(Pico.ram+0x10000);\r
-  } else if (PicoMCD & 1) {\r
+  }\r
+  else if (PicoAHW & PAHW_MCD)\r
+  {\r
     elprintf(EL_VDPDMA, "DmaSlow CD, r3=%02x", Pico_mcd->s68k_regs[3]);\r
     if(source<0x20000) { // Bios area\r
       pd=(u16 *)(Pico_mcd->bios+(source&~1));\r
@@ -133,7 +134,9 @@ static void DmaSlow(int len)
       elprintf(EL_VDPDMA|EL_ANOMALY, "DmaSlow[%i] %06x->%04x: FIXME: unsupported src", Pico.video.type, source, a);\r
       return;\r
     }\r
-  } else {\r
+  }\r
+  else\r
+  {\r
     // if we have DmaHook, let it handle ROM because of possible DMA delay\r
     if (PicoDmaHook && PicoDmaHook(source, len, &pd, &pdend));\r
     else if (source<Pico.romsize) { // Rom\r
@@ -175,7 +178,7 @@ static void DmaSlow(int len)
           //if(pd >= pdend) pd-=0x8000; // should be good for RAM, bad for ROM\r
         }\r
       }\r
-      rendstatus|=0x10;\r
+      rendstatus |= PDRAW_DIRTY_SPRITES;\r
       break;\r
 \r
     case 3: // cram\r
@@ -244,7 +247,7 @@ static void DmaCopy(int len)
   }\r
   // remember addr\r
   Pico.video.addr=a;\r
-  rendstatus|=0x10;\r
+  rendstatus |= PDRAW_DIRTY_SPRITES;\r
 }\r
 \r
 // check: Contra, Megaman\r
@@ -284,7 +287,7 @@ static void DmaFill(int data)
   // update length\r
   Pico.video.reg[0x13] = Pico.video.reg[0x14] = 0; // Dino Dini's Soccer (E) (by Haze)\r
 \r
-  rendstatus|=0x10;\r
+  rendstatus |= PDRAW_DIRTY_SPRITES;\r
 }\r
 \r
 static void CommandDma(void)\r
@@ -341,7 +344,7 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
     else\r
     {\r
       // preliminary FIFO emulation for Chaos Engine, The (E)\r
-      if(!(pvid->status&8) && (pvid->reg[1]&0x40) && Pico.m.scanline!=-1 && !(PicoOpt&0x10000)) // active display, accurate mode?\r
+      if(!(pvid->status&8) && (pvid->reg[1]&0x40) && Pico.m.scanline!=-1 && !(PicoOpt&POPT_DIS_VDP_FIFO)) // active display, accurate mode?\r
       {\r
         pvid->status&=~0x200; // FIFO no longer empty\r
         pvid->lwrite_cnt++;\r
@@ -366,45 +369,63 @@ PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d)
       pvid->command|=d;\r
       pvid->pending=0;\r
       CommandChange();\r
-    } else {\r
-      if((d&0xc000)==0x8000)\r
+    }\r
+    else\r
+    {\r
+      if ((d&0xc000)==0x8000)\r
       {\r
         // Register write:\r
         int num=(d>>8)&0x1f;\r
         int dold=pvid->reg[num];\r
+        pvid->type=0; // register writes clear command (else no Sega logo in Golden Axe II)\r
         if (num > 0x0a && !(pvid->reg[1]&4)) {\r
           elprintf(EL_ANOMALY, "%02x written to reg %02x in SMS mode @ %06x", d, num, SekPc);\r
+          return;\r
         } else\r
-         pvid->reg[num]=(unsigned char)d;\r
-        if (num==00) elprintf(EL_INTSW, "hint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x10)>>4,\r
-                        (d&0x10)>>4, SekCyclesDone(), (pvid->pending_ints&0x10)>>4, SekPc);\r
-        if (num==01) elprintf(EL_INTSW, "vint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x20)>>5,\r
-                        (d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc);\r
-        if      (num ==   5 && (d^dold)) rendstatus|=1;\r
-        // renderers should update their palettes if sh/hi mode is changed\r
-        else if (num == 0xc && ((d^dold)&8)) Pico.m.dirtyPal = 2;\r
+          pvid->reg[num]=(unsigned char)d;\r
+\r
+        switch (num)\r
+        {\r
+          case 0x00:\r
+            elprintf(EL_INTSW, "hint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x10)>>4,\r
+                    (d&0x10)>>4, SekCyclesDone(), (pvid->pending_ints&0x10)>>4, SekPc);\r
+            goto update_irq;\r
+          case 0x01:\r
+            elprintf(EL_INTSW, "vint_onoff: %i->%i [%i] pend=%i @ %06x", (dold&0x20)>>5,\r
+                    (d&0x20)>>5, SekCyclesDone(), (pvid->pending_ints&0x20)>>5, SekPc);\r
+            if (!(d&0x40) && SekCyclesLeft > 420) { /*elprintf(EL_ANOMALY, "aa %i", SekCyclesLeft);*/ rendstatus |= PDRAW_EARLY_BLANK; }\r
+            goto update_irq;\r
+          case 0x05:\r
+            if (d^dold) rendstatus |= PDRAW_SPRITES_MOVED;\r
+            break;\r
+          case 0x0c:\r
+            // renderers should update their palettes if sh/hi mode is changed\r
+            if ((d^dold)&8) Pico.m.dirtyPal = 2;\r
+            break;\r
+        }\r
+        return;\r
+\r
+update_irq:\r
 #ifndef EMU_CORE_DEBUG\r
         // update IRQ level (Lemmings, Wiz 'n' Liz intro, ... )\r
         // may break if done improperly:\r
         // International Superstar Soccer Deluxe (crash), Street Racer (logos), Burning Force (gfx),\r
         // Fatal Rewind (crash), Sesame Street Counting Cafe\r
-        else if (num < 2)\r
+        if (!SekShouldInterrupt) // hack\r
         {\r
-          if (!SekShouldInterrupt) // hack\r
-          {\r
-            int lines, pints, irq=0;\r
-            lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10);\r
-            pints = (pvid->pending_ints&lines);\r
-                 if(pints & 0x20) irq = 6;\r
-            else if(pints & 0x10) irq = 4;\r
-            SekInterrupt(irq); // update line\r
-\r
-            if (irq && Pico.m.scanline!=-1) SekEndRun(24); // make it delayed\r
-          }\r
+          int lines, pints, irq=0;\r
+          lines = (pvid->reg[1] & 0x20) | (pvid->reg[0] & 0x10);\r
+          pints = (pvid->pending_ints&lines);\r
+               if(pints & 0x20) irq = 6;\r
+          else if(pints & 0x10) irq = 4;\r
+          SekInterrupt(irq); // update line\r
+\r
+          if (irq && Pico.m.scanline!=-1) SekEndRun(24); // make it delayed\r
         }\r
 #endif\r
-        pvid->type=0; // register writes clear command (else no Sega logo in Golden Axe II)\r
-      } else {\r
+      }\r
+      else\r
+      {\r
         // High word of command:\r
         pvid->command&=0x0000ffff;\r
         pvid->command|=d<<16;\r
@@ -431,9 +452,9 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
   {\r
     struct PicoVideo *pv=&Pico.video;\r
     d=pv->status;\r
-    if (PicoOpt&0x10)         d|=0x0020; // sprite collision (Shadow of the Beast)\r
-    if (!(pv->reg[1]&0x40))   d|=0x0008; // set V-Blank if display is disabled\r
-    if (SekCyclesLeft < 84+4) d|=0x0004; // H-Blank (Sonic3 vs)\r
+    if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast)\r
+    if (!(pv->reg[1]&0x40))        d|=0x0008; // set V-Blank if display is disabled\r
+    if (SekCyclesLeft < 84+4)      d|=0x0004; // H-Blank (Sonic3 vs)\r
 \r
     d|=(pv->pending_ints&0x20)<<2; // V-int pending?\r
     if (d&0x100) pv->status&=~0x100; // FIFO no longer full\r