Browse Source

PicoVideoRead optimization

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@511 be3aeb3a-fb24-0410-a615-afba39da0efa
notaz 16 years ago
parent
commit
9761a7d0d4
10 changed files with 89 additions and 63 deletions
  1. 3 3
      Pico/Memory.c
  2. 1 7
      Pico/Memory.s
  3. 3 1
      Pico/Memory_amips.s
  4. 2 1
      Pico/Pico.c
  5. 1 2
      Pico/Pico/Memory.c
  6. 21 9
      Pico/PicoFrameHints.c
  7. 3 1
      Pico/PicoInt.h
  8. 51 28
      Pico/VideoPort.c
  9. 2 4
      Pico/cd/Memory.c
  10. 2 7
      Pico/cd/Memory.s

+ 3 - 3
Pico/Memory.c

@@ -344,9 +344,9 @@ PICO_INTERNAL_ASM u32 PicoRead8(u32 a)
   log_io(a, 8, 0);
   if ((a&0xff4000)==0xa00000) { d=z80Read8(a); goto end; } // Z80 Ram
 
-  if ((a&0xe700e0)==0xc00000) // VDP
-       d=PicoVideoRead(a);
-  else d=OtherRead16(a&~1, 8);
+  if ((a&0xe700e0)==0xc00000) { d=PicoVideoRead8(a); goto end; } // VDP
+  
+  d=OtherRead16(a&~1, 8);
   if ((a&1)==0) d>>=8;
 
 end:

+ 1 - 7
Pico/Memory.s

@@ -415,13 +415,7 @@ m_read8_vdp:
     tst     r0, #0x70000
     tsteq   r0, #0x000e0
     bxne    lr              @ invalid read
-    stmfd   sp!,{r0,lr}
-    bic     r0, r0, #1
-    bl      PicoVideoRead
-    ldmfd   sp!,{r1,lr}
-    tst     r1, #1
-    moveq   r0, r0, lsr #8
-    bx      lr
+    b       PicoVideoRead8
 
 m_read8_ram:
     ldr     r1, =Pico

+ 3 - 1
Pico/Memory_amips.s

@@ -469,7 +469,9 @@ m_read8_vdp:
     andi    $t1, $a0, 0xe0
     or      $t0, $t1
     bnez    $t0, m_read_null # invalid address
-    m_read8_call16 PicoVideoRead
+    nop
+    j       PicoVideoRead8
+    nop
 
 m_read8_ram:
     lui     $t0, %hi(Pico)

+ 2 - 1
Pico/Pico.c

@@ -218,7 +218,8 @@ PICO_INTERNAL int CheckDMA(void)
   if(Pico.video.reg[12] & 1) dma_op |= 4; // 40 cell mode?
   if(!(Pico.video.status&8)&&(Pico.video.reg[1]&0x40)) dma_op|=8; // active display?
   xfers_can = dma_timings[dma_op];
-  if(xfers <= xfers_can) {
+  if(xfers <= xfers_can)
+  {
     if(dma_op&2) Pico.video.status&=~2; // dma no longer busy
     else {
       burn = xfers * dma_bsycles[dma_op] >> 8; // have to be approximate because can't afford division..

+ 1 - 2
Pico/Pico/Memory.c

@@ -22,8 +22,7 @@ static u32 PicoReadPico8(u32 a)
   a&=0xffffff;
 
   if ((a&0xfffff0)==0xc00000) { // VDP
-    d=PicoVideoRead(a);
-    if ((a&1)==0) d>>=8;
+    d=PicoVideoRead8(a);
     goto end;
   }
 

+ 21 - 9
Pico/PicoFrameHints.c

@@ -35,10 +35,10 @@
 static int PicoFrameHints(void)
 {
   struct PicoVideo *pv=&Pico.video;
-  int lines, y, lines_vis = 224, line_sample, skip;
+  int lines, y, lines_vis = 224, line_sample, skip, vcnt_wrap;
   int hint; // Hint counter
 
-  Pico.m.scanline = 0;
+  pv->v_counter = Pico.m.scanline = 0;
 
   if ((PicoOpt&POPT_ALT_RENDERER) && !PicoSkipFrame && (pv->reg[1]&0x40)) { // fast rend., display enabled
     // draw a frame just after vblank in alternative render mode
@@ -53,7 +53,7 @@ static int PicoFrameHints(void)
 
   if (Pico.m.pal) {
     line_sample = 68;
-    if(pv->reg[1]&8) lines_vis = 240;
+    if (pv->reg[1]&8) lines_vis = 240;
   } else {
     line_sample = 93;
   }
@@ -75,7 +75,12 @@ static int PicoFrameHints(void)
 
   for (y = 0; y < lines_vis; y++)
   {
-    Pico.m.scanline = y;
+    pv->v_counter = Pico.m.scanline = y;
+    if ((pv->reg[12]&6) == 6) { // interlace mode 2
+      pv->v_counter <<= 1;
+      pv->v_counter |= pv->v_counter >> 8;
+      pv->v_counter &= 0xff;
+    }
 
     // VDP FIFO
     pv->lwrite_cnt -= 12;
@@ -138,6 +143,11 @@ static int PicoFrameHints(void)
 #endif
   }
 
+  // V-int line (224 or 240)
+  Pico.m.scanline = y;
+  pv->v_counter = 0xe0; // bad for 240 mode
+  if ((pv->reg[12]&6) == 6) pv->v_counter = 0xc1;
+
   if (!skip)
   {
     if (DrawScanline < y)
@@ -147,9 +157,6 @@ static int PicoFrameHints(void)
 #endif
   }
 
-  // V-int line (224 or 240)
-  Pico.m.scanline = y;
-
   // VDP FIFO
   pv->lwrite_cnt=0;
   Pico.video.status|=0x200;
@@ -168,7 +175,6 @@ static int PicoFrameHints(void)
     if (pv->reg[0]&0x10) SekInterrupt(4);
   }
 
-  // V-Interrupt:
   pv->status|=0x08; // go into vblank
   pv->pending_ints|=0x20;
 
@@ -212,10 +218,16 @@ static int PicoFrameHints(void)
 
   // PAL line count might actually be 313 according to Steve Snake, but that would complicate things.
   lines = Pico.m.pal ? 312 : 262;
+  vcnt_wrap = Pico.m.pal ? 0x103 : 0xEB; // based on Gens
 
   for (y++; y < lines; y++)
   {
-    Pico.m.scanline = y;
+    pv->v_counter = Pico.m.scanline = y;
+    if (y >= vcnt_wrap)
+      pv->v_counter -= Pico.m.pal ? 56 : 6;
+    if ((pv->reg[12]&6) == 6)
+      pv->v_counter = (pv->v_counter << 1) | 1;
+    pv->v_counter &= 0xff;
 
     PAD_DELAY
 #ifdef PICO_CD

+ 3 - 1
Pico/PicoInt.h

@@ -237,7 +237,8 @@ struct PicoVideo
   int status;                 // Status bits
   unsigned char pending_ints; // pending interrupts: ??VH????
   signed char lwrite_cnt;     // VDP write count during active display line
-  unsigned char pad[0x12];
+  unsigned short v_counter;   // V-counter
+  unsigned char pad[0x10];
 };
 
 struct PicoMisc
@@ -504,6 +505,7 @@ void ym2612_unpack_state(void);
 // VideoPort.c
 PICO_INTERNAL_ASM void PicoVideoWrite(unsigned int a,unsigned short d);
 PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a);
+PICO_INTERNAL_ASM unsigned int PicoVideoRead8(unsigned int a);
 extern int (*PicoDmaHook)(unsigned int source, int len, unsigned short **srcp, unsigned short **limitp);
 
 // Misc.c

+ 51 - 28
Pico/VideoPort.c

@@ -449,24 +449,19 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
 {
   a&=0x1c;
 
-  if (a==0x00) // data port
-  {
-    return VideoRead();
-  }
-
   if (a==0x04) // control port
   {
     struct PicoVideo *pv=&Pico.video;
     unsigned int d;
     d=pv->status;
-    if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast)
-    if (!(pv->reg[1]&0x40))        d|=0x0008; // set V-Blank if display is disabled
+    //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast)
     if (SekCyclesLeft < 84+4)      d|=0x0004; // H-Blank (Sonic3 vs)
 
-    d|=(pv->pending_ints&0x20)<<2; // V-int pending?
+    d |= ((pv->reg[1]&0x40)^0x40) >> 3;  // set V-Blank if display is disabled
+    d |= (pv->pending_ints&0x20)<<2;     // V-int pending?
     if (d&0x100) pv->status&=~0x100; // FIFO no longer full
 
-    pv->pending=0; // ctrl port reads clear write-pending flag (Charles MacDonald)
+    pv->pending = 0; // ctrl port reads clear write-pending flag (Charles MacDonald)
 
     elprintf(EL_SR, "SR read: %04x @ %06x", d, SekPc);
     return d;
@@ -489,32 +484,60 @@ PICO_INTERNAL_ASM unsigned int PicoVideoRead(unsigned int a)
   // check: Sonic 3D Blast bonus, Cannon Fodder, Chase HQ II, 3 Ninjas kick back, Road Rash 3, Skitchin', Wheel of Fortune
   if ((a&0x1c)==0x08)
   {
-    unsigned int hc, d;
+    unsigned int d;
     int lineCycles;
     
     lineCycles = (488-SekCyclesLeft)&0x1ff;
-    d = Pico.m.scanline; // V-Counter
-
     if (Pico.video.reg[12]&1)
-         hc=hcounts_40[lineCycles];
-    else hc=hcounts_32[lineCycles];
+         d = hcounts_40[lineCycles];
+    else d = hcounts_32[lineCycles];
 
-    if (Pico.m.pal) {
-      if (d >= 0x103) d-=56; // based on Gens
-    } else {
-      if (d >= 0xEB)  d-=6;
-    }
+    elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", d, Pico.video.v_counter, SekCyclesDone(), SekPc);
+    return d | (Pico.video.v_counter << 8);
+  }
 
-    if ((Pico.video.reg[12]&6) == 6) {
-      // interlace mode 2 (Combat Cars (UE) [!])
-      d <<= 1;
-      if (d&0xf00) d|= 1;
-    }
+  if (a==0x00) // data port
+  {
+    return VideoRead();
+  }
 
-    elprintf(EL_HVCNT, "hv: %02x %02x (%i) @ %06x", hc, d, SekCyclesDone(), SekPc);
-    d&=0xff; d<<=8;
-    d|=hc;
-    return d;
+  return 0;
+}
+
+unsigned int PicoVideoRead8(unsigned int a)
+{
+  unsigned int d;
+  a&=0x1d;
+
+  switch (a)
+  {
+    case 0: return VideoRead() >> 8;
+    case 1: return VideoRead() & 0xff;
+    case 4: // control port/status reg
+      d = Pico.video.status >> 8;
+      if (d&1) Pico.video.status&=~0x100; // FIFO no longer full
+      Pico.video.pending = 0;
+      elprintf(EL_SR, "SR read (h): %02x @ %06x", d, SekPc);
+      return d;
+    case 5:
+      d = Pico.video.status & 0xff;
+      //if (PicoOpt&POPT_ALT_RENDERER) d|=0x0020; // sprite collision (Shadow of the Beast)
+      d |= ((Pico.video.reg[1]&0x40)^0x40) >> 3;  // set V-Blank if display is disabled
+      d |= (Pico.video.pending_ints&0x20)<<2;     // V-int pending?
+      if (SekCyclesLeft < 84+4) d |= 4;    // H-Blank
+      Pico.video.pending = 0;
+      elprintf(EL_SR, "SR read (l): %02x @ %06x", d, SekPc);
+      return d;
+    case 8: // hv counter
+      elprintf(EL_HVCNT, "vcounter: %02x (%i) @ %06x", Pico.video.v_counter, SekCyclesDone(), SekPc);
+      return Pico.video.v_counter;
+    case 9:
+      d = (488-SekCyclesLeft)&0x1ff;
+      if (Pico.video.reg[12]&1)
+           d = hcounts_40[d];
+      else d = hcounts_32[d];
+      elprintf(EL_HVCNT, "hcounter: %02x (%i) @ %06x", d, SekCyclesDone(), SekPc);
+      return d;
   }
 
   return 0;

+ 2 - 4
Pico/cd/Memory.c

@@ -501,10 +501,8 @@ u32 PicoReadM68k8(u32 a)
     case 0xd0>>1: case 0xd2>>1: case 0xd4>>1: case 0xd6>>1:
     case 0xd8>>1: case 0xda>>1: case 0xdc>>1: case 0xde>>1:
       // VDP
-      if ((a&0xe700e0)==0xc00000) {
-        d=PicoVideoRead(a);
-        if ((a&1)==0) d>>=8;
-      }
+      if ((a&0xe700e0)==0xc00000)
+        d=PicoVideoRead8(a);
       break;
     case 0xe0>>1: case 0xe2>>1: case 0xe4>>1: case 0xe6>>1:
     case 0xe8>>1: case 0xea>>1: case 0xec>>1: case 0xee>>1:

+ 2 - 7
Pico/cd/Memory.s

@@ -126,6 +126,7 @@ m_s68k_decode_write_table:
 .extern z80Read8
 .extern OtherRead16
 .extern PicoVideoRead
+.extern PicoVideoRead8
 .extern Read_CDC_Host
 .extern m68k_reg_write8
 .extern OtherWrite16
@@ -611,13 +612,7 @@ m_m68k_read8_vdp:
     tst     r0, #0x70000
     tsteq   r0, #0x000e0
     bxne    lr              @ invalid read
-    stmfd   sp!,{r0,lr}
-    bic     r0, r0, #1
-    bl      PicoVideoRead               @ TODO: implement it in asm
-    ldmfd   sp!,{r1,lr}
-    tst     r1, #1
-    moveq   r0, r0, lsr #8
-    bx      lr
+    b       PicoVideoRead8
 
 
 m_m68k_read8_ram: