rearrange globals
[picodrive.git] / pico / cd / gfx.c
index 00a5d49..e3434e1 100644 (file)
  *  POSSIBILITY OF SUCH DAMAGE.
  *
  ****************************************************************************************/
-#include "genplus_types.h"
+#include "../pico_int.h"
+#include "genplus_macros.h"
 
 typedef struct
 {
-  uint32 cycles;                    /* current cycles count for graphics operation */
-  uint32 cyclesPerLine;             /* current graphics operation timings */
+  //uint32 cycles;                    /* current cycles count for graphics operation */
+  //uint32 cyclesPerLine;             /* current graphics operation timings */
   uint32 dotMask;                   /* stamp map size mask */
   uint16 *tracePtr;                 /* trace vector pointer */
   uint16 *mapPtr;                   /* stamp map table base address */
@@ -48,13 +49,16 @@ typedef struct
   uint8 mapShift;                   /* stamp map table shift value (related to stamp map size) */
   uint16 bufferOffset;              /* image buffer column offset */
   uint32 bufferStart;               /* image buffer start index */
-  uint8 lut_prio[4][0x100][0x100];  /* WORD-RAM data writes priority lookup table */
+  uint32 y_step;                    /* pico: render line step */
+  uint8 lut_prio[4][0x10][0x10];    /* WORD-RAM data writes priority lookup table */
   uint8 lut_pixel[0x200];           /* Graphics operation dot offset lookup table */
   uint8 lut_cell[0x100];            /* Graphics operation stamp offset lookup table */
 } gfx_t;
 
 static gfx_t gfx;
 
+static void gfx_schedule(void);
+
 /***************************************************************/
 /*      Rotation / Scaling operation (2M Mode)                 */
 /***************************************************************/
@@ -62,22 +66,21 @@ static gfx_t gfx;
 void gfx_init(void)
 {
   int i, j;
-  uint16 offset;
   uint8 mask, row, col, temp;
 
   memset(&gfx, 0, sizeof(gfx));
 
   /* Initialize priority modes lookup table */
-  for (i=0; i<0x100; i++)
+  for (i = 0; i < 0x10; i++)
   {
-    for (j=0; j<0x100; j++)
+    for (j = 0; j < 0x10; j++)
     {
       /* normal */
       gfx.lut_prio[0][i][j] = j;
       /* underwrite */
-      gfx.lut_prio[1][i][j] = ((i & 0x0f) ? (i & 0x0f) : (j & 0x0f)) | ((i & 0xf0) ? (i & 0xf0) : (j & 0xf0));
+      gfx.lut_prio[1][i][j] = i ? i : j;
       /* overwrite */
-      gfx.lut_prio[2][i][j] = ((j & 0x0f) ? (j & 0x0f) : (i & 0x0f)) | ((j & 0xf0) ? (j & 0xf0) : (i & 0xf0));
+      gfx.lut_prio[2][i][j] = j ? j : i;
       /* invalid */
       gfx.lut_prio[3][i][j] = i;
     }
@@ -124,41 +127,37 @@ void gfx_init(void)
   }
 }
 
-void gfx_reset(void)
-{ 
-  /* Reset cycle counter */
-  gfx.cycles = 0;
-}
-
 int gfx_context_save(uint8 *state)
 {
   uint32 tmp32;
   int bufferptr = 0;
 
-  save_param(&gfx.cycles, sizeof(gfx.cycles));
-  save_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine));
+  //save_param(&gfx.cycles, sizeof(gfx.cycles));
+  //save_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine));
   save_param(&gfx.dotMask, sizeof(gfx.dotMask));
   save_param(&gfx.stampShift, sizeof(gfx.stampShift));
   save_param(&gfx.mapShift, sizeof(gfx.mapShift));
   save_param(&gfx.bufferOffset, sizeof(gfx.bufferOffset));
   save_param(&gfx.bufferStart, sizeof(gfx.bufferStart));
 
-  tmp32 = (uint8 *)(gfx.tracePtr) - scd.word_ram_2M;
+  tmp32 = (uint8 *)(gfx.tracePtr) - Pico_mcd->word_ram2M;
   save_param(&tmp32, 4);
 
-  tmp32 = (uint8 *)(gfx.mapPtr) - scd.word_ram_2M;
+  tmp32 = (uint8 *)(gfx.mapPtr) - Pico_mcd->word_ram2M;
   save_param(&tmp32, 4);
 
+  save_param(&gfx.y_step, sizeof(gfx.y_step));
+
   return bufferptr;
 }
 
-int gfx_context_load(uint8 *state)
+int gfx_context_load(const uint8 *state)
 {
   uint32 tmp32;
   int bufferptr = 0;
 
-  load_param(&gfx.cycles, sizeof(gfx.cycles));
-  load_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine));
+  //load_param(&gfx.cycles, sizeof(gfx.cycles));
+  //load_param(&gfx.cyclesPerLine, sizeof(gfx.cyclesPerLine));
   load_param(&gfx.dotMask, sizeof(gfx.dotMask));
   load_param(&gfx.stampShift, sizeof(gfx.stampShift));
   load_param(&gfx.mapShift, sizeof(gfx.mapShift));
@@ -166,19 +165,22 @@ int gfx_context_load(uint8 *state)
   load_param(&gfx.bufferStart, sizeof(gfx.bufferStart));
 
   load_param(&tmp32, 4);
-  gfx.tracePtr = (uint16 *)(scd.word_ram_2M + tmp32);
+  gfx.tracePtr = (uint16 *)(Pico_mcd->word_ram2M + tmp32);
 
   load_param(&tmp32, 4);
-  gfx.mapPtr = (uint16 *)(scd.word_ram_2M + tmp32);
+  gfx.mapPtr = (uint16 *)(Pico_mcd->word_ram2M + tmp32);
+
+  load_param(&gfx.y_step, sizeof(gfx.y_step));
 
   return bufferptr;
 }
 
-INLINE void gfx_render(uint32 bufferIndex, uint32 width)
+static void gfx_render(uint32 bufferIndex, uint32 width)
 {
   uint8 pixel_in, pixel_out;
   uint16 stamp_data;
   uint32 stamp_index;
+  uint32 priority;
 
   /* pixel map start position for current line (13.3 format converted to 13.11) */
   uint32 xpos = *gfx.tracePtr++ << 8;
@@ -188,11 +190,14 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
   uint32 xoffset = (int16) *gfx.tracePtr++;
   uint32 yoffset = (int16) *gfx.tracePtr++;
 
+  priority = (Pico_mcd->s68k_regs[2] << 8) | Pico_mcd->s68k_regs[3];
+  priority = (priority >> 3) & 0x03;
+
   /* process all dots */
   while (width--)
   {
     /* check if stamp map is repeated */
-    if (scd.regs[0x58>>1].byte.l & 0x01)
+    if (Pico_mcd->s68k_regs[0x58+1] & 0x01)
     {
       /* stamp map range */
       xpos &= gfx.dotMask;
@@ -235,7 +240,9 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
         /*       xx = cell column (0-3) = (xpos >> (11 + 3)) & 3 */
         /*        s = stamp size (0=16x16, 1=32x32)              */
         /*      hrr = HFLIP & ROTATION bits                      */
-        stamp_index |= gfx.lut_cell[stamp_data | ((scd.regs[0x58>>1].byte.l & 0x02) << 2 ) | ((ypos >> 8) & 0xc0) | ((xpos >> 10) & 0x30)] << 6;
+        stamp_index |= gfx.lut_cell[
+          stamp_data | ((Pico_mcd->s68k_regs[0x58+1] & 0x02) << 2 )
+          | ((ypos >> 8) & 0xc0) | ((xpos >> 10) & 0x30)] << 6;
             
         /* pixel  offset (0-63)                              */
         /* table entry = yyyxxxhrr (9 bits)                  */
@@ -245,7 +252,7 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
         stamp_index |= gfx.lut_pixel[stamp_data | ((xpos >> 8) & 0x38) | ((ypos >> 5) & 0x1c0)];
 
         /* read pixel pair (2 pixels/byte) */
-        pixel_out = READ_BYTE(scd.word_ram_2M, stamp_index >> 1);
+        pixel_out = READ_BYTE(Pico_mcd->word_ram2M, stamp_index >> 1);
 
         /* extract left or rigth pixel */
         if (stamp_index & 1)
@@ -265,23 +272,26 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
     }
 
     /* read out paired pixel data */
-    pixel_in = READ_BYTE(scd.word_ram_2M, bufferIndex >> 1);
+    pixel_in = READ_BYTE(Pico_mcd->word_ram2M, bufferIndex >> 1);
 
     /* update left or rigth pixel */
     if (bufferIndex & 1)
     {
+      /* priority mode write */
+      pixel_out = gfx.lut_prio[priority][pixel_in & 0x0f][pixel_out];
+
       pixel_out |= (pixel_in & 0xf0);
     }
     else
     {
+      /* priority mode write */
+      pixel_out = gfx.lut_prio[priority][pixel_in >> 4][pixel_out];
+
       pixel_out = (pixel_out << 4) | (pixel_in & 0x0f);
     }
 
-    /* priority mode write */
-    pixel_out = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][pixel_in][pixel_out];
-
     /* write data to image buffer */
-    WRITE_BYTE(scd.word_ram_2M, bufferIndex >> 1, pixel_out);
+    WRITE_BYTE(Pico_mcd->word_ram2M, bufferIndex >> 1, pixel_out);
 
     /* check current pixel position  */
     if ((bufferIndex & 7) != 7)
@@ -301,18 +311,19 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
   }
 }
 
-void gfx_start(unsigned int base, int cycles)
+void gfx_start(unsigned int base)
 {
   /* make sure 2M mode is enabled */
-  if (!(scd.regs[0x02>>1].byte.l & 0x04))
+  if (!(Pico_mcd->s68k_regs[3] & 0x04))
   {
-    uint32 mask;
+    uint32 mask = 0;
+    uint32 reg;
     
     /* trace vector pointer */
-    gfx.tracePtr = (uint16 *)(scd.word_ram_2M + ((base << 2) & 0x3fff8));
+    gfx.tracePtr = (uint16 *)(Pico_mcd->word_ram2M + ((base << 2) & 0x3fff8));
 
     /* stamps & stamp map size */
-    switch ((scd.regs[0x58>>1].byte.l >> 1) & 0x03)
+    switch ((Pico_mcd->s68k_regs[0x58+1] >> 1) & 0x03)
     {
       case 0:
         gfx.dotMask = 0x07ffff;   /* 256x256 dots/map  */
@@ -344,78 +355,97 @@ void gfx_start(unsigned int base, int cycles)
     }
 
     /* stamp map table base address */
-    gfx.mapPtr = (uint16 *)(scd.word_ram_2M + ((scd.regs[0x5a>>1].w << 2) & mask));
+    reg = (Pico_mcd->s68k_regs[0x5a] << 8) | Pico_mcd->s68k_regs[0x5b];
+    gfx.mapPtr = (uint16 *)(Pico_mcd->word_ram2M + ((reg << 2) & mask));
 
     /* image buffer column offset (64 pixels/cell, minus 7 pixels to restart at cell beginning) */
-    gfx.bufferOffset = (((scd.regs[0x5c>>1].byte.l & 0x1f) + 1) << 6) - 7;
+    gfx.bufferOffset = (((Pico_mcd->s68k_regs[0x5c+1] & 0x1f) + 1) << 6) - 7;
 
     /* image buffer start index in dot units (2 pixels/byte) */
-    gfx.bufferStart = (scd.regs[0x5e>>1].w << 3) & 0x7ffc0;
+    reg = (Pico_mcd->s68k_regs[0x5e] << 8) | Pico_mcd->s68k_regs[0x5f];
+    gfx.bufferStart = (reg << 3) & 0x7ffc0;
 
     /* add image buffer horizontal dot offset */
-    gfx.bufferStart += (scd.regs[0x60>>1].byte.l & 0x3f);
+    gfx.bufferStart += (Pico_mcd->s68k_regs[0x60+1] & 0x3f);
 
     /* reset GFX chip cycle counter */
-    gfx.cycles = cycles;
+    //gfx.cycles = cycles;
 
     /* update GFX chip timings (see AC3:Thunderhawk / Thunderstrike) */
-    gfx.cyclesPerLine = 4 * 5 * scd.regs[0x62>>1].w; 
+    //gfx.cyclesPerLine = 4 * 5 * scd.regs[0x62>>1].w;
 
     /* start graphics operation */
-    scd.regs[0x58>>1].byte.h = 0x80;
+    Pico_mcd->s68k_regs[0x58] = 0x80;
+
+    gfx_schedule();
   }
 }
 
-void gfx_update(int cycles)
+/* PicoDrive specific */
+#define UPDATE_CYCLES 20000
+
+static void gfx_schedule(void)
 {
-  /* synchronize GFX chip with SUB-CPU */
-  cycles -= gfx.cycles;
+  int w, h, cycles;
+  int y_step;
 
-  /* make sure SUB-CPU is ahead */
-  if (cycles > 0)
-  {
-    /* number of lines to process */
-    unsigned int lines = (cycles + gfx.cyclesPerLine - 1) / gfx.cyclesPerLine;
+  w = (Pico_mcd->s68k_regs[0x62] << 8) | Pico_mcd->s68k_regs[0x63];
+  h = (Pico_mcd->s68k_regs[0x64] << 8) | Pico_mcd->s68k_regs[0x65];
 
-    /* check against remaining lines */
-    if (lines < scd.regs[0x64>>1].byte.l)
-    {
-      /* update Vdot remaining size */
-      scd.regs[0x64>>1].byte.l -= lines;
+  cycles = 5 * w * h;
+  if (cycles > UPDATE_CYCLES)
+    y_step = (UPDATE_CYCLES + 5 * w - 1) / (5 * w);
+  else
+    y_step = h;
 
-      /* increment cycle counter */
-      gfx.cycles += lines * gfx.cyclesPerLine;
-    }
-    else
-    {
-      /* process remaining lines */
-      lines = scd.regs[0x64>>1].byte.l;
+  gfx.y_step = y_step;
+  pcd_event_schedule_s68k(PCD_EVENT_GFX, 5 * w * y_step);
+}
 
-      /* clear Vdot remaining size */
-      scd.regs[0x64>>1].byte.l = 0;
+void gfx_update(unsigned int cycles)
+{
+  int lines, lines_reg;
+  int w;
 
-      /* end of graphics operation */
-      scd.regs[0x58>>1].byte.h = 0;
-      /* level 1 interrupt enabled ? */
-      if (scd.regs[0x32>>1].byte.l & 0x02)
-      {
-        /* trigger level 1 interrupt */
-        scd.pending |= (1 << 1);
+  if (!(Pico_mcd->s68k_regs[0x58] & 0x80))
+    return;
 
-        /* update IRQ level */
-        s68k_update_irq((scd.pending & scd.regs[0x32>>1].byte.l) >> 1);
-      }
+  w = (Pico_mcd->s68k_regs[0x62] << 8) | Pico_mcd->s68k_regs[0x63];
+  lines = (Pico_mcd->s68k_regs[0x64] << 8) | Pico_mcd->s68k_regs[0x65];
+  lines_reg = lines - gfx.y_step;
+
+  if (lines_reg <= 0) {
+    Pico_mcd->s68k_regs[0x58] = 0;
+    Pico_mcd->s68k_regs[0x64] =
+    Pico_mcd->s68k_regs[0x65] = 0;
+
+    if (Pico_mcd->s68k_regs[0x33] & PCDS_IEN1) {
+      elprintf(EL_INTS|EL_CD, "s68k: gfx_cd irq 1");
+      SekInterruptS68k(1);
     }
+  }
+  else {
+    Pico_mcd->s68k_regs[0x64] = lines_reg >> 8;
+    Pico_mcd->s68k_regs[0x65] = lines_reg;
 
+    if (lines > gfx.y_step)
+      lines = gfx.y_step;
+
+    pcd_event_schedule(cycles, PCD_EVENT_GFX, 5 * w * lines);
+  }
+
+  if (PicoIn.opt & POPT_EN_MCD_GFX)
+  {
     /* render lines */
     while (lines--)
     {
       /* process dots to image buffer */
-      gfx_render(gfx.bufferStart, scd.regs[0x62>>1].w);
+      gfx_render(gfx.bufferStart, w);
 
       /* increment image buffer start index for next line (8 pixels/line) */
       gfx.bufferStart += 8;
     }
   }
 }
+
+// vim:shiftwidth=2:ts=2:expandtab