]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/blitter.cpp
QnD fix to prevent bad VIs from happening
[virtualjaguar] / src / blitter.cpp
index 432b53c296278b615486ed54c557578220b746c6..a08db2ebe270f8908f28aa1b4b78fce86a3df042 100644 (file)
@@ -1,7 +1,7 @@
 //
 // Blitter core
 //
-// by cal2
+// by Cal2
 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
 // Cleanups/fixes by James L. Hammons
 //
@@ -41,14 +41,14 @@ bool specialLog = false;
 #define INTENSITYINC   ((UINT32)0x70)
 #define ZINC                   ((UINT32)0x74)
 #define COLLISIONCTRL  ((UINT32)0x78)
-#define PHRASEINT3             ((UINT32)0x7C)
-#define PHRASEINT2             ((UINT32)0x80)
-#define PHRASEINT1             ((UINT32)0x84)
-#define PHRASEINT0             ((UINT32)0x88)
-#define PHRASEZ3               ((UINT32)0x8C)
-#define PHRASEZ2               ((UINT32)0x90)
-#define PHRASEZ1               ((UINT32)0x94)
-#define PHRASEZ0               ((UINT32)0x98)
+#define PHRASEINT0             ((UINT32)0x7C)
+#define PHRASEINT1             ((UINT32)0x80)
+#define PHRASEINT2             ((UINT32)0x84)
+#define PHRASEINT3             ((UINT32)0x88)
+#define PHRASEZ0               ((UINT32)0x8C)
+#define PHRASEZ1               ((UINT32)0x90)
+#define PHRASEZ2               ((UINT32)0x94)
+#define PHRASEZ3               ((UINT32)0x98)
 
 // Blitter command bits
 
@@ -244,7 +244,7 @@ static uint8 blitter_ram[0x100];
 // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to
 // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place
 // being shifted to the right 3 places).
-static uint32 blitter_scanline_width[48] = 
+/*static uint32 blitter_scanline_width[48] = 
 {             
      0,    0,    0,    0,                                      // Note: This would really translate to 1, 1, 1, 1
      2,    0,    0,    0,
@@ -258,7 +258,7 @@ static uint32 blitter_scanline_width[48] =
    512,  640,  768,  896,
   1024, 1280, 1536, 1792,
   2048, 2560, 3072, 3584
-};
+};//*/
 
 //static uint8 * tom_ram_8;
 //static uint8 * paletteRam;
@@ -340,6 +340,8 @@ if (specialLog)
 {
        WriteLog("  A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
 }
+               uint32 a1_start = a1_x, a2_start = a2_x;
+
                inner_loop = n_pixels;
                while (inner_loop--)
                {
@@ -442,9 +444,10 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd:
 //                                             if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
                                                        inhibit = 1;
                                        }
+
 // This is DEFINITELY WRONG
-                                       if (a1_phrase_mode || a2_phrase_mode)
-                                               inhibit = !inhibit;
+//                                     if (a1_phrase_mode || a2_phrase_mode)
+//                                             inhibit = !inhibit;
                                }
 
                                if (CLIPA1)
@@ -456,6 +459,15 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd:
                                // compute the write data and store
                                if (!inhibit)
                                {                       
+// Houston, we have a problem...
+// Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's
+// a conflict! E.g.:
+//Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008]
+// CMD -> src:  dst: DSTEN  misc:  a1ctl:  mode: GOURD  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
+//  A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+//  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+//        A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700
+
                                        if (PATDSEL)
                                        {
                                                // use pattern data for write data
@@ -480,6 +492,7 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd:
                                                if (LFU_A)       writedata |= srcdata  & dstdata;
                                        }
 
+//Although, this looks like it's OK... (even if it is shitty!)
                                        if (GOURD) 
                                                writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
 
@@ -593,8 +606,10 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd:
 //                                             if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
                                                        inhibit = 1;
                                        }
-                                       if (a1_phrase_mode || a2_phrase_mode)
-                                               inhibit =! inhibit;
+
+// This is DEFINITELY WRONG
+//                                     if (a1_phrase_mode || a2_phrase_mode)
+//                                             inhibit = !inhibit;
                                }
                                
                                if (CLIPA1)
@@ -667,6 +682,7 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd:
 }//*/
                                        // write to the destination
                                        WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
+
                                        if (DSTWRZ)
                                                WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
                                }
@@ -684,19 +700,74 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd:
                        if (GOURD || SRCSHADE)
                        {
                                gd_i[colour_index] += gd_ia;
+//Hmm, this doesn't seem to do anything...
+//But it is correct according to the JTRM...!
+if ((int32)gd_i[colour_index] < 0)
+       gd_i[colour_index] = 0;
+if (gd_i[colour_index] > 0x00FFFFFF)
+       gd_i[colour_index] = 0x00FFFFFF;//*/
+
                                gd_c[colour_index] += gd_ca;
+if ((int32)gd_c[colour_index] < 0)
+       gd_c[colour_index] = 0;
+if (gd_c[colour_index] > 0x000000FF)
+       gd_c[colour_index] = 0x000000FF;//*/
                        }
+
                        if (GOURD || SRCSHADE || GOURZ)
                        {
                                if (a1_phrase_mode)
+//This screws things up WORSE (for the BIOS opening screen)
+//                             if (a1_phrase_mode || a2_phrase_mode)
                                        colour_index = (colour_index + 1) & 0x03;
                        }
                }
 
+               //New: Phrase mode taken into account! :-p
+               if (a1_phrase_mode)
+               {
+                       // Bump the pointer to the next phrase boundary
+                       // Even though it works, this is crappy... Clean it up!
+                       uint32 size = 64 / a1_psize;
+
+                       // Crappy kludge... ('aligning' source to destination)
+                       if (a2_phrase_mode && DSTA2)
+                       {
+                               uint32 extra = (a2_start >> 16) % size;
+                               a1_x += extra << 16;
+                       }
+
+                       uint32 newx = (a1_x >> 16) / size;
+                       uint32 newxrem = (a1_x >> 16) % size;
+                       a1_x &= 0x0000FFFF;
+                       a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
+               }
+
+               if (a2_phrase_mode)
+               {
+                       // Bump the pointer to the next phrase boundary
+                       // Even though it works, this is crappy... Clean it up!
+                       uint32 size = 64 / a2_psize;
+
+                       // Crappy kludge... ('aligning' source to destination)
+                       // Prolly should do this for A1 channel as well...
+                       if (a1_phrase_mode && !DSTA2)
+                       {
+                               uint32 extra = (a1_start >> 16) % size;
+                               a2_x += extra << 16;
+                       }
+
+                       uint32 newx = (a2_x >> 16) / size;
+                       uint32 newxrem = (a2_x >> 16) % size;
+                       a2_x &= 0x0000FFFF;
+                       a2_x |= (((newx + (newxrem == 0 ? 0 : 1) /*+ extra*/) * size) & 0xFFFF) << 16;
+               }
+
+               //Not entirely: This still mucks things up... !!! FIX !!!
                a1_x += a1_step_x;
                a1_y += a1_step_y;
                a2_x += a2_step_x;
-               a2_y += a2_step_y;
+               a2_y += a2_step_y;//*/
 
 /*             if (a2_phrase_mode)
                {
@@ -730,13 +801,10 @@ void blitter_blit(uint32 cmd)
        op = (cmd >> 21) & 0x0F;
        ctrl = (cmd >> 25) & 0x3F;
 
-       a1_addr = REG(A1_BASE);
-//Just for testing Trevor McFur...
-//if (a1_addr == 0x130CB0) specialLog = true;
-//extern bool suppressOutput;
-//if (a1_addr == 0x130CB0) suppressOutput = false;
-//End testing
-       a2_addr = REG(A2_BASE);
+       // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
+       // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
+       a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
+       a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
 
        a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
        a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
@@ -755,9 +823,12 @@ void blitter_blit(uint32 cmd)
        a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
 //But it seems to fuck up T2K! !!! FIX !!!
+//Could it be sign extended??? Doesn't seem to be so according to JTRM
 //     a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
 
 //     a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
+// According to JTRM, this must give a *whole number* of phrases in the current
+// pixel size (this means the lookup above is WRONG)... !!! FIX !!!
        UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
        a1_width = ((0x04 | m) << e) >> 2;//*/
 
@@ -768,6 +839,8 @@ void blitter_blit(uint32 cmd)
 //     a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
 
 //     a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
+// According to JTRM, this must give a *whole number* of phrases in the current
+// pixel size (this means the lookup above is WRONG)... !!! FIX !!!
        m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
        a2_width = ((0x04 | m) << e) >> 2;//*/
        a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
@@ -811,6 +884,20 @@ void blitter_blit(uint32 cmd)
                a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
                break;
        }
+
+
+//Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801]
+//  A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD
+//  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD
+//if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// &&
+//     UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
+//Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it...
+//if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801)
+//        A1 x/y: 14368/7, A2 x/y: 150/36
+//This is it... The problem...
+//if ((a1_x >> 16) == 14368) // 14368 = $3820
+//     return; //Lesse what we got...
+
        if (XSIGNSUB_A1)
                a1_xadd = -a1_xadd;
 
@@ -837,13 +924,14 @@ void blitter_blit(uint32 cmd)
                break;
 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
        case XADDINC:
-WriteLog("BLIT: Asked to used invalid bit combo for A2...\n");
+WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
                // add the contents of the increment register
                // since there is no register for a2 we just add 1
 //Let's do nothing, since it's not listed as a valid bit combo...
 //             a2_xadd = 1 << 16;
                break;
        }
+
        if (XSIGNSUB_A2)
                a2_xadd = -a2_xadd;
 
@@ -879,45 +967,61 @@ WriteLog("BLIT: Asked to used invalid bit combo for A2...\n");
        a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
        a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
 
-       // zbuffering
+       // Z-buffering
        if (GOURZ)
        {
-               zadd = JaguarReadLong(0xF02274, BLITTER);
+//             zadd = JaguarReadLong(0xF02274, BLITTER);
+               zadd = REG(ZINC);
 
-               for(int v=0; v<4; v++) 
-                       z_i[v] = (int32)JaguarReadLong(0xF0228C + (v << 2), BLITTER);
+               for(int v=0; v<4; v++)
+//                     z_i[v] = (int32)JaguarReadLong(0xF0228C + (v << 2), BLITTER);
+                       z_i[v] = REG(PHRASEZ0 + v*4);
        }
+
+       // Gouraud shading
        if (GOURD || GOURZ || SRCSHADE)
        {
-               // gouraud shading
-               gouraud_add = JaguarReadLong(0xF02270, BLITTER);
-               
-               gd_c[0] = JaguarReadByte(0xF02268, BLITTER);
+/*             gd_c[0] = JaguarReadByte(0xF02268, BLITTER);
                gd_i[0] = JaguarReadByte(0xF02269, BLITTER);
                gd_i[0] <<= 16;
-               gd_i[0] |= JaguarReadWord(0xF02240, BLITTER);
+               gd_i[0] |= JaguarReadWord(0xF02240, BLITTER);//*/
+               gd_c[0] = blitter_ram[PATTERNDATA + 0];
+               gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
+                       | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
 
-               gd_c[1] = JaguarReadByte(0xF0226A, BLITTER);
+/*             gd_c[1] = JaguarReadByte(0xF0226A, BLITTER);
                gd_i[1] = JaguarReadByte(0xF0226B, BLITTER);
                gd_i[1] <<= 16;
-               gd_i[1] |= JaguarReadWord(0xF02242, BLITTER);
+               gd_i[1] |= JaguarReadWord(0xF02242, BLITTER);//*/
+               gd_c[1] = blitter_ram[PATTERNDATA + 2];
+               gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
+                       | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
 
-               gd_c[2] = JaguarReadByte(0xF0226C, BLITTER);
+/*             gd_c[2] = JaguarReadByte(0xF0226C, BLITTER);
                gd_i[2] = JaguarReadByte(0xF0226D, BLITTER);
                gd_i[2] <<= 16;
-               gd_i[2] |= JaguarReadWord(0xF02244, BLITTER);
+               gd_i[2] |= JaguarReadWord(0xF02244, BLITTER);//*/
+               gd_c[2] = blitter_ram[PATTERNDATA + 4];
+               gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
+                       | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
 
-               gd_c[3] = JaguarReadByte(0xF0226E, BLITTER);
+/*             gd_c[3] = JaguarReadByte(0xF0226E, BLITTER);
                gd_i[3] = JaguarReadByte(0xF0226F, BLITTER);
                gd_i[3] <<= 16; 
-               gd_i[3] |= JaguarReadWord(0xF02246, BLITTER);
+               gd_i[3] |= JaguarReadWord(0xF02246, BLITTER);//*/
+               gd_c[3] = blitter_ram[PATTERNDATA + 6];
+               gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
+                       | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
 
-               gd_ia = gouraud_add & 0xFFFFFF;
-               if (gd_ia & 0x800000)
+//             gouraud_add = JaguarReadLong(0xF02270, BLITTER);
+               gouraud_add = REG(INTENSITYINC);
+               
+               gd_ia = gouraud_add & 0x00FFFFFF;
+               if (gd_ia & 0x00800000)
                        gd_ia = 0xFF000000 | gd_ia;
 
-               gd_ca = (gouraud_add>>24) & 0xFF;
-               if (gd_ca & 0x80)
+               gd_ca = (gouraud_add >> 24) & 0xFF;
+               if (gd_ca & 0x00000080)
                        gd_ca = 0xFFFFFF00 | gd_ca;
        }
 
@@ -933,70 +1037,6 @@ WriteLog("BLIT: Asked to used invalid bit combo for A2...\n");
 
                if (a2_step_x < 0)
                        a2_step_x = (-n_pixels) * 65536;;
-       }
-       else
-       // fix for wolfenstein 3d
-       if (jaguar_mainRom_crc32==0x3966698f)
-       {
-               if (n_pixels==24)
-               {
-                       if ((a1_step_x / 65536)==-28)
-                       {
-                               a1_step_x=-24*65536; // au lieu de -28
-                               a2_step_x=  0*65536; // au lieu de -8
-                       }
-               }
-       } 
-       else
-       // fix for Tempest 2000
-       if (jaguar_mainRom_crc32==0x32816d44)
-       {
-
-               if ((n_lines!=1)&&((n_pixels==288)||(n_pixels==384)))
-               {
-                       WriteLog("Blit!\n");
-                       WriteLog("  cmd      = 0x%.8x\n",cmd);
-                       WriteLog("  a1_base  = %08X\n", a1_addr);
-                       WriteLog("  a1_pitch = %d\n", a1_pitch);
-                       WriteLog("  a1_psize = %d\n", a1_psize);
-                       WriteLog("  a1_width = %d\n", a1_width);
-                       WriteLog("  a1_xadd  = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
-                       WriteLog("  a1_yadd  = %f\n", (float)a1_yadd / 65536.0);
-                       WriteLog("  a1_xstep = %f\n", (float)a1_step_x / 65536.0);
-                       WriteLog("  a1_ystep = %f\n", (float)a1_step_y / 65536.0);
-                       WriteLog("  a1_x     = %f\n", (float)a1_x / 65536.0);
-                       WriteLog("  a1_y     = %f\n", (float)a1_y / 65536.0);
-                       WriteLog("  a1_zoffs = %i\n",a1_zoffs);
-
-                       WriteLog("  a2_base  = %08X\n", a2_addr);
-                       WriteLog("  a2_pitch = %d\n", a2_pitch);
-                       WriteLog("  a2_psize = %d\n", a2_psize);
-                       WriteLog("  a2_width = %d\n", a2_width);
-                       WriteLog("  a2_xadd  = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
-                       WriteLog("  a2_yadd  = %f\n", (float)a2_yadd / 65536.0);
-                       WriteLog("  a2_xstep = %f\n", (float)a2_step_x / 65536.0);
-                       WriteLog("  a2_ystep = %f\n", (float)a2_step_y / 65536.0);
-                       WriteLog("  a2_x     = %f\n", (float)a2_x / 65536.0);
-                       WriteLog("  a2_y     = %f\n", (float)a2_y / 65536.0);
-                       WriteLog("  a2_mask_x= 0x%.4x\n",a2_mask_x);
-                       WriteLog("  a2_mask_y= 0x%.4x\n",a2_mask_y);
-                       WriteLog("  a2_zoffs = %i\n",a2_zoffs);
-
-                       WriteLog("  count    = %d x %d\n", n_pixels, n_lines);
-
-                       WriteLog("  command  = %08X\n", cmd);
-                       WriteLog("  dsten    = %i\n",DSTEN);
-                       WriteLog("  srcen    = %i\n",SRCEN);
-                       WriteLog("  patdsel  = %i\n",PATDSEL);
-                       WriteLog("  color    = 0x%.8x\n",REG(PATTERNDATA));
-                       WriteLog("  dcompen  = %i\n",DCOMPEN);
-                       WriteLog("  bcompen  = %i\n",BCOMPEN);
-                       WriteLog("  cmpdst   = %i\n",CMPDST);
-                       WriteLog("  GOURZ    = %i\n",GOURZ);
-                       WriteLog("  GOURD    = %i\n",GOURD);
-                       WriteLog("  SRCSHADE = %i\n",SRCSHADE);
-                       WriteLog("  DSTDATA  = 0x%.8x%.8x\n",REG(DSTDATA),REG(DSTDATA+4));
-               }       
        }//*/
 
 #ifdef LOG_BLITS
@@ -1046,17 +1086,116 @@ WriteLog("BLIT: Asked to used invalid bit combo for A2...\n");
        }       
 #endif
 
+//NOTE: Pitch is ignored!
+
+//This *might* be the altimeter blits (they are)...
+//On captured screen, x-pos for black (inner) is 259, for pink is 257
+//Black is short by 3, pink is short by 1...
+/*
+Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
+ CMD -> src:  dst:  misc:  a1ctl: UPDA1  mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
+  A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 262/124, A2 x/y: 128/0
+Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
+ CMD -> src:  dst:  misc:  a1ctl: UPDA1  mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
+  A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 264/117, A2 x/y: 407/0
+
+Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
+ CMD -> src:  dst:  misc:  a1ctl: UPDA1  mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
+  A1 step values: -10 (X), 1 (Y)
+  A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 262/132, A2 x/y: 129/0
+Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
+ CMD -> src:  dst:  misc:  a1ctl: UPDA1  mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
+  A1 step values: -8 (X), 1 (Y)
+  A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 264/128, A2 x/y: 336/0
+
+  264v       vCursor ends up here...
+     xxxxx...`
+     111122223333
+
+262v         vCursor ends up here...
+   xxxxxxxxx.'
+ 1111222233334444
+
+Fixed! Now for more:
+
+; This looks like the ship icon in the upper left corner...
+
+Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
+ CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
+  A1 step values: -12 (X), 1 (Y)
+  A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 20/24, A2 x/y: 5780/0
+
+Also fixed!
+
+More (not sure this is a blitter problem as much as it's a GPU problem):
+All but the "M" are trashed...
+This does *NOT* look like a blitter problem, as it's rendering properly...
+Actually, if you look at the A1 step values, there IS a discrepancy!
+
+; D
+
+Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
+ CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
+  A1 step values: -14 (X), 1 (Y)
+  A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 134/144, A2 x/y: 2516/0
+;129,146: +5,-2
+
+; E
+
+Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
+ CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
+  A1 step values: -13 (X), 1 (Y)
+  A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 147/144, A2 x/y: 2660/0
+
+; M
+
+Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
+ CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
+  A1 step values: -12 (X), 1 (Y)
+  A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 160/144, A2 x/y: 3764/0
+
+; O
+
+Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
+ CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
+  A1 step values: -15 (X), 1 (Y)
+  A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 173/144, A2 x/y: 4052/0
+
+*/
 extern int blit_start_log;
-extern int op_start_log;
+//extern int op_start_log;
 if (blit_start_log)
 {
        char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
        char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
        char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
                "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
-       uint32 src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
-               a1ctl = (cmd >> 8) & 0x07, mode = (cmd >> 11) & 0x07, ity = (cmd >> 14) & 0x0F,
-               zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F;
+       uint32 /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
+               a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F,
+               zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/;
        UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
        uint32 p1 = a1f & 0x07, p2 = a2f & 0x07,
                d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
@@ -1078,14 +1217,15 @@ if (blit_start_log)
        WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
        WriteLog("ctrl: %s%s%s%s%s%s\n", (cmd & 0x02000000 ? "CMPDST " : ""), (cmd & 0x04000000 ? "BCOMPEN " : ""), (cmd & 0x08000000 ? "DCOMPEN " : ""), (cmd & 0x10000000 ? "BKGWREN " : ""), (cmd & 0x20000000 ? "BUSHI " : ""), (cmd & 0x40000000 ? "SRCSHADE" : ""));
 
+       if (UPDA1)
+               WriteLog("  A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16);
+
        if (UPDA2)
-       {
                WriteLog("  A2 step values: %d (X), %d (Y) [mask (%sused): %08X - %08X/%08X]\n", a2_step_x >> 16, a2_step_y >> 16, (a2f & 0x8000 ? "" : "un"), REG(A2_MASK), a2_mask_x, a2_mask_y);
-       }
 
        WriteLog("  A1 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p1, bppStr[d1], zo1, iw1, w1, ctrlStr[ac1&0x03], (ac1&0x04 ? "YADD1" : "YADD0"), (ac1&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac1&0x10 ? "YSIGNSUB" : "YSIGNADD"));
        WriteLog("  A2 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p2, bppStr[d2], zo2, iw2, w2, ctrlStr[ac2&0x03], (ac2&0x04 ? "YADD1" : "YADD0"), (ac2&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac2&0x10 ? "YSIGNSUB" : "YSIGNADD"));
-       WriteLog("        A1 x/y: %d/%d, A2 x/y: %d/%d\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16);
+       WriteLog("        A1 x/y: %d/%d, A2 x/y: %d/%d Pattern: %08X%08X\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16, REG(PATTERNDATA), REG(PATTERNDATA + 4));
 //     blit_start_log = 0;
 //     op_start_log = 1;
 }
@@ -1136,14 +1276,23 @@ uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
        if (offset == (0x38 + 3))
                return 0x01;    // always idle
 
+//Attempted fix for AvP:
+       if (offset >= 0x04 && offset <= 0x07)
+//             return (offset > 0x05 ? blitter_ram[PIXLINECOUNTER + offset - 0x04] : 0x00);
+//             return 0x00;    // WO register! What does it expect to see here???
+//This is it. I wonder if it just ignores the lower three bits?
+               return blitter_ram[A1_PIXEL + offset - 0x04];
+
        return blitter_ram[offset];
 }
 
+//Crappy!
 uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
 {
        return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
 }
 
+//Crappy!
 uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
 {
        return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
@@ -1156,32 +1305,53 @@ void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
        offset &= 0xFF;
 
 //     if ((offset >= 0x7C) && (offset <= 0x9B))
-       if ((offset >= 0x7C) && (offset <= 0x8B))
+       // This handles writes to INTENSITY0-3 by also writing them to their proper places in
+       // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
+       if ((offset >= 0x7C) && (offset <= 0x9B))//8B))
        {
                switch (offset)
                {
+               // INTENSITY registers 0-3
                case 0x7C: break;
-               case 0x7D: blitter_ram[0x69] = data; break;
-               case 0x7E: blitter_ram[0x40] = data; break;
-               case 0x7F: blitter_ram[0x41] = data; break;
+               case 0x7D: blitter_ram[PATTERNDATA + 1] = data; break;
+               case 0x7E: blitter_ram[SRCDATA + 0] = data; break;
+               case 0x7F: blitter_ram[SRCDATA + 1] = data; break;
 
                case 0x80: break;
-               case 0x81: blitter_ram[0x6B] = data; break;
-               case 0x82: blitter_ram[0x42] = data; break;
-               case 0x83: blitter_ram[0x43] = data; break;
+               case 0x81: blitter_ram[PATTERNDATA + 3] = data; break;
+               case 0x82: blitter_ram[SRCDATA + 2] = data; break;
+               case 0x83: blitter_ram[SRCDATA + 3] = data; break;
                
                case 0x84: break;
-               case 0x85: blitter_ram[0x6D] = data; break;
-               case 0x86: blitter_ram[0x44] = data; break;
-               case 0x87: blitter_ram[0x45] = data; break;
+               case 0x85: blitter_ram[PATTERNDATA + 5] = data; break;
+               case 0x86: blitter_ram[SRCDATA + 4] = data; break;
+               case 0x87: blitter_ram[SRCDATA + 5] = data; break;
                
                case 0x88: break;
-               case 0x89: blitter_ram[0x6F] = data; break;
-//Mistyped?
-//             case 0x9A: blitter_ram[0x46] = data; break;
-//             case 0x9B: blitter_ram[0x47] = data; break;
-               case 0x8A: blitter_ram[0x46] = data; break;
-               case 0x8B: blitter_ram[0x47] = data; break;
+               case 0x89: blitter_ram[PATTERNDATA + 7] = data; break;
+               case 0x8A: blitter_ram[SRCDATA + 6] = data; break;
+               case 0x8B: blitter_ram[SRCDATA + 7] = data; break;
+
+               // Z registers 0-3
+               case 0x8C: blitter_ram[SRCZINT + 0] = data; break;
+               case 0x8D: blitter_ram[SRCZINT + 1] = data; break;
+               case 0x8E: blitter_ram[SRCZFRAC + 0] = data; break;
+               case 0x8F: blitter_ram[SRCZFRAC + 1] = data; break;
+
+               case 0x90: blitter_ram[SRCZINT + 2] = data; break;
+               case 0x91: blitter_ram[SRCZINT + 3] = data; break;
+               case 0x92: blitter_ram[SRCZFRAC + 2] = data; break;
+               case 0x93: blitter_ram[SRCZFRAC + 3] = data; break;
+               
+               case 0x94: blitter_ram[SRCZINT + 4] = data; break;
+               case 0x95: blitter_ram[SRCZINT + 5] = data; break;
+               case 0x96: blitter_ram[SRCZFRAC + 4] = data; break;
+               case 0x97: blitter_ram[SRCZFRAC + 5] = data; break;
+               
+               case 0x98: blitter_ram[SRCZINT + 6] = data; break;
+               case 0x99: blitter_ram[SRCZINT + 7] = data; break;
+               case 0x9A: blitter_ram[SRCZFRAC + 6] = data; break;
+               case 0x9B: blitter_ram[SRCZFRAC + 7] = data; break;
                }
        }
 
@@ -1190,21 +1360,51 @@ void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
 
 void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
 {
+//#if 1
+/*     if (offset & 0xFF == A1_PIXEL && data == 14368)
+       {
+               WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
+extern bool doGPUDis;
+doGPUDis = true;
+       }
+       if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368)
+       {
+               WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
+extern bool doGPUDis;
+doGPUDis = true;
+       }//*/
+//#endif
+
        BlitterWriteByte(offset+0, (data>>8) & 0xFF, who);
        BlitterWriteByte(offset+1, data & 0xFF, who);
 
        if ((offset & 0xFF) == 0x3A)
        // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
        // But then again, according to the Jaguar docs, this is correct...!
+{
+/*extern int blit_start_log;
+extern bool doGPUDis;
+if (blit_start_log)
+{
+       WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
+       doGPUDis = true;
+}//*/
                blitter_blit(GET32(blitter_ram, 0x38));
-// Testing purposes only!
-//This does the clipping correctly, but not the Gouraud shading...
-//             blitter2_exec(GET32(blitter_ram, 0x38));
+}
 }
 //F02278,9,A,B
 
 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
 {
+//#if 1
+/*     if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368)
+       {
+               WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
+extern bool doGPUDis;
+doGPUDis = true;
+       }//*/
+//#endif
+
        BlitterWriteWord(offset, data >> 16, who);
        BlitterWriteWord(offset+2, data & 0xFFFF, who);
 }