]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/blitter.cpp
Changes for 1.0.7 update
[virtualjaguar] / src / blitter.cpp
index 90a0b3a1555301f49379618be3e9f70775729648..9a03a2555413f040e3b5d467786a30d8de4bdbcb 100644 (file)
@@ -1,14 +1,13 @@
 //
 // Blitter core
 //
-// by cal2
+// by Cal2
 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
 // Cleanups/fixes by James L. Hammons
 //
 bool specialLog = false;
 
 #include "jaguar.h"
-#include "blitter2.h"                  // Testing purposes only!
 
 #define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
                                | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
@@ -104,32 +103,39 @@ bool specialLog = false;
 #define YADD1_A1               (REG(A1_FLAGS)&0x040000)
 #define YADD1_A2               (REG(A2_FLAGS)&0x040000)
 
+//Put 'em back, once we fix the problem!!! [KO]
 // 1 bpp pixel read
 #define PIXEL_SHIFT_1(a)      (((~a##_x) >> 16) & 7)
 #define PIXEL_OFFSET_1(a)     (((((UINT32)a##_y >> 16) * a##_width / 8) + (((UINT32)a##_x >> 19) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 19) & 7))
-#define READ_PIXEL_1(a)       ((jaguar_byte_read(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
+#define READ_PIXEL_1(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
+//#define READ_PIXEL_1(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
 
 // 2 bpp pixel read
 #define PIXEL_SHIFT_2(a)      (((~a##_x) >> 15) & 6)
 #define PIXEL_OFFSET_2(a)     (((((UINT32)a##_y >> 16) * a##_width / 4) + (((UINT32)a##_x >> 18) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 18) & 7))
-#define READ_PIXEL_2(a)       ((jaguar_byte_read(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
+#define READ_PIXEL_2(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03)
+//#define READ_PIXEL_2(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
 
 // 4 bpp pixel read
 #define PIXEL_SHIFT_4(a)      (((~a##_x) >> 14) & 4)
 #define PIXEL_OFFSET_4(a)     (((((UINT32)a##_y >> 16) * (a##_width/2)) + (((UINT32)a##_x >> 17) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 17) & 7))
-#define READ_PIXEL_4(a)       ((jaguar_byte_read(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
+#define READ_PIXEL_4(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f)
+//#define READ_PIXEL_4(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
 
 // 8 bpp pixel read
 #define PIXEL_OFFSET_8(a)     (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 7))
-#define READ_PIXEL_8(a)       (jaguar_byte_read(a##_addr+PIXEL_OFFSET_8(a)))
+#define READ_PIXEL_8(a)       (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER))
+//#define READ_PIXEL_8(a)       (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a)))
 
 // 16 bpp pixel read
 #define PIXEL_OFFSET_16(a)    (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 3))
-#define READ_PIXEL_16(a)       (jaguar_word_read(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
+#define READ_PIXEL_16(a)       (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER))
+//#define READ_PIXEL_16(a)       (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
 
 // 32 bpp pixel read
 #define PIXEL_OFFSET_32(a)    (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
-#define READ_PIXEL_32(a)      (jaguar_long_read(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
+#define READ_PIXEL_32(a)      (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER))
+//#define READ_PIXEL_32(a)      (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
 
 // pixel read
 #define READ_PIXEL(a,f) (\
@@ -142,14 +148,15 @@ bool specialLog = false;
 
 // 16 bpp z data read
 #define ZDATA_OFFSET_16(a)     (PIXEL_OFFSET_16(a) + a##_zoffs * 4)
-#define READ_ZDATA_16(a)       (jaguar_word_read(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
+#define READ_ZDATA_16(a)       (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER))
+//#define READ_ZDATA_16(a)       (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
 
 // z data read
 #define READ_ZDATA(a,f) (READ_ZDATA_16(a))
 
 // 16 bpp z data write
-#define WRITE_ZDATA_16(a,d)     {  jaguar_word_write(a##_addr+(ZDATA_OFFSET_16(a)<<1),d); }
-//#define WRITE_ZDATA_16(a,d)     {  jaguar_word_write(a##_addr+(ZDATA_OFFSET_16(a)<<1),d); WriteLog("16bpp z write --> "); }
+#define WRITE_ZDATA_16(a,d)     {  JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); }
+//#define WRITE_ZDATA_16(a,d)     {  JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); }
 
 // z data write
 #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d); 
@@ -182,24 +189,29 @@ bool specialLog = false;
         (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0)
 
 // 1 bpp pixel write
-#define WRITE_PIXEL_1(a,d)       { jaguar_byte_write(a##_addr+PIXEL_OFFSET_1(a),(jaguar_byte_read(a##_addr+PIXEL_OFFSET_1(a))&(~(0x01 << PIXEL_SHIFT_1(a))))|(d<<PIXEL_SHIFT_1(a))); }
+#define WRITE_PIXEL_1(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_1(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER)&(~(0x01 << PIXEL_SHIFT_1(a))))|(d<<PIXEL_SHIFT_1(a)), BLITTER); }
+//#define WRITE_PIXEL_1(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_1(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a))&(~(0x01 << PIXEL_SHIFT_1(a))))|(d<<PIXEL_SHIFT_1(a))); }
 
 // 2 bpp pixel write
-#define WRITE_PIXEL_2(a,d)       { jaguar_byte_write(a##_addr+PIXEL_OFFSET_2(a),(jaguar_byte_read(a##_addr+PIXEL_OFFSET_2(a))&(~(0x03 << PIXEL_SHIFT_2(a))))|(d<<PIXEL_SHIFT_2(a))); }
+#define WRITE_PIXEL_2(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_2(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER)&(~(0x03 << PIXEL_SHIFT_2(a))))|(d<<PIXEL_SHIFT_2(a)), BLITTER); }
+//#define WRITE_PIXEL_2(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_2(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a))&(~(0x03 << PIXEL_SHIFT_2(a))))|(d<<PIXEL_SHIFT_2(a))); }
 
 // 4 bpp pixel write
-#define WRITE_PIXEL_4(a,d)       { jaguar_byte_write(a##_addr+PIXEL_OFFSET_4(a),(jaguar_byte_read(a##_addr+PIXEL_OFFSET_4(a))&(~(0x0f << PIXEL_SHIFT_4(a))))|(d<<PIXEL_SHIFT_4(a))); }
+#define WRITE_PIXEL_4(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_4(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER)&(~(0x0f << PIXEL_SHIFT_4(a))))|(d<<PIXEL_SHIFT_4(a)), BLITTER); }
+//#define WRITE_PIXEL_4(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_4(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a))&(~(0x0f << PIXEL_SHIFT_4(a))))|(d<<PIXEL_SHIFT_4(a))); }
 
 // 8 bpp pixel write
-#define WRITE_PIXEL_8(a,d)       { jaguar_byte_write(a##_addr+PIXEL_OFFSET_8(a),d); }
+#define WRITE_PIXEL_8(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d, BLITTER); }
+//#define WRITE_PIXEL_8(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d); }
 
 // 16 bpp pixel write
-//#define WRITE_PIXEL_16(a,d)     {  jaguar_word_write(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
-#define WRITE_PIXEL_16(a,d)     {  jaguar_word_write(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); }
+//#define WRITE_PIXEL_16(a,d)     {  JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
+#define WRITE_PIXEL_16(a,d)     {  JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), d, BLITTER); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); }
+//#define WRITE_PIXEL_16(a,d)     {  JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), d); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); }
 
 // 32 bpp pixel write
-#define WRITE_PIXEL_32(a,d)            { jaguar_long_write(a##_addr+(PIXEL_OFFSET_32(a)<<2),d); } 
-//#define WRITE_PIXEL_32(a,d)          { jaguar_long_write(a##_addr+(PIXEL_OFFSET_32(a)<<2),d); WriteLog("32bpp pixel write --> "); }
+#define WRITE_PIXEL_32(a,d)            { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); } 
+//#define WRITE_PIXEL_32(a,d)          { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); } 
 
 // pixel write
 #define WRITE_PIXEL(a,f,d) {\
@@ -430,9 +442,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)
@@ -581,8 +594,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)
@@ -681,6 +696,28 @@ Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd:
                        }
                }
 
+               //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;
+                       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 / a1_psize;
+                       uint32 newx = (a2_x >> 16) / size;
+                       uint32 newxrem = (a2_x >> 16) % size;
+                       a2_x &= 0x0000FFFF;
+                       a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
+               }
+
                a1_x += a1_step_x;
                a1_y += a1_step_y;
                a2_x += a2_step_x;
@@ -718,13 +755,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;
@@ -743,9 +777,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;//*/
 
@@ -756,6 +793,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;
@@ -825,7 +864,7 @@ 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...
@@ -870,35 +909,35 @@ WriteLog("BLIT: Asked to used invalid bit combo for A2...\n");
        // zbuffering
        if (GOURZ)
        {
-               zadd = jaguar_long_read(0xF02274);
+               zadd = JaguarReadLong(0xF02274, BLITTER);
 
                for(int v=0; v<4; v++) 
-                       z_i[v] = (int32)jaguar_long_read(0xF0228C + (v << 2));
+                       z_i[v] = (int32)JaguarReadLong(0xF0228C + (v << 2), BLITTER);
        }
        if (GOURD || GOURZ || SRCSHADE)
        {
                // gouraud shading
-               gouraud_add = jaguar_long_read(0xF02270);
+               gouraud_add = JaguarReadLong(0xF02270, BLITTER);
                
-               gd_c[0] = jaguar_byte_read(0xF02268);
-               gd_i[0] = jaguar_byte_read(0xF02269);
+               gd_c[0] = JaguarReadByte(0xF02268, BLITTER);
+               gd_i[0] = JaguarReadByte(0xF02269, BLITTER);
                gd_i[0] <<= 16;
-               gd_i[0] |= jaguar_word_read(0xF02240);
+               gd_i[0] |= JaguarReadWord(0xF02240, BLITTER);
 
-               gd_c[1] = jaguar_byte_read(0xF0226A);
-               gd_i[1] = jaguar_byte_read(0xF0226B);
+               gd_c[1] = JaguarReadByte(0xF0226A, BLITTER);
+               gd_i[1] = JaguarReadByte(0xF0226B, BLITTER);
                gd_i[1] <<= 16;
-               gd_i[1] |= jaguar_word_read(0xF02242);
+               gd_i[1] |= JaguarReadWord(0xF02242, BLITTER);
 
-               gd_c[2] = jaguar_byte_read(0xF0226C);
-               gd_i[2] = jaguar_byte_read(0xF0226D);
+               gd_c[2] = JaguarReadByte(0xF0226C, BLITTER);
+               gd_i[2] = JaguarReadByte(0xF0226D, BLITTER);
                gd_i[2] <<= 16;
-               gd_i[2] |= jaguar_word_read(0xF02244);
+               gd_i[2] |= JaguarReadWord(0xF02244, BLITTER);
 
-               gd_c[3] = jaguar_byte_read(0xF0226E);
-               gd_i[3] = jaguar_byte_read(0xF0226F);
+               gd_c[3] = JaguarReadByte(0xF0226E, BLITTER);
+               gd_i[3] = JaguarReadByte(0xF0226F, BLITTER);
                gd_i[3] <<= 16; 
-               gd_i[3] |= jaguar_word_read(0xF02246);
+               gd_i[3] |= JaguarReadWord(0xF02246, BLITTER);
 
                gd_ia = gouraud_add & 0xFFFFFF;
                if (gd_ia & 0x800000)
@@ -1034,6 +1073,104 @@ 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...
+
+; 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;
 if (blit_start_log)
@@ -1066,10 +1203,11 @@ 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"));
@@ -1090,10 +1228,10 @@ if (blit_start_log)
        {
                WriteLog("\nBytes at 004D58:\n");
                for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
-                       WriteLog("%02X ", jaguar_byte_read(i));
+                       WriteLog("%02X ", JaguarReadByte(i));
                WriteLog("\nBytes at F03000:\n");
                for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
-                       WriteLog("%02X ", jaguar_byte_read(i));
+                       WriteLog("%02X ", JaguarReadByte(i));
                WriteLog("\n\n");
        }
 }//*/
@@ -1101,17 +1239,6 @@ if (blit_start_log)
        blitter_working = 0;
 }
 
-uint32 blitter_long_read(uint32 offset)
-{
-       return (blitter_word_read(offset) << 16) | blitter_word_read(offset+2);
-}
-
-void blitter_long_write(uint32 offset, uint32 data)
-{
-       blitter_word_write(offset, data >> 16);
-       blitter_word_write(offset+2, data & 0xFFFF);
-}
-
 void blitter_init(void)
 {
        blitter_reset();
@@ -1127,7 +1254,28 @@ void blitter_done(void)
        WriteLog("BLIT: Done.\n");
 }
 
-void blitter_byte_write(uint32 offset, uint8 data)
+uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
+{
+       offset &= 0xFF;
+
+       // status register
+       if (offset == (0x38 + 3))
+               return 0x01;    // always idle
+
+       return blitter_ram[offset];
+}
+
+uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
+{
+       return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
+}
+
+uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
+{
+       return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
+}
+
+void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
 {
 /*if (offset & 0xFF == 0x7B)
        WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
@@ -1166,10 +1314,10 @@ void blitter_byte_write(uint32 offset, uint8 data)
        blitter_ram[offset] = data;
 }
 
-void blitter_word_write(uint32 offset, uint16 data)
+void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
 {
-       blitter_byte_write(offset+0, (data>>8) & 0xFF);
-       blitter_byte_write(offset+1, data & 0xFF);
+       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!
@@ -1181,18 +1329,8 @@ void blitter_word_write(uint32 offset, uint16 data)
 }
 //F02278,9,A,B
 
-uint8 blitter_byte_read(uint32 offset)
-{
-       offset &= 0xFF;
-
-       // status register
-       if (offset == (0x38 + 3))
-               return 0x01;    // always idle
-
-       return blitter_ram[offset];
-}
-
-uint16 blitter_word_read(uint32 offset)
+void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
 {
-       return ((uint16)blitter_byte_read(offset) << 8) | (uint16)blitter_byte_read(offset+1);
+       BlitterWriteWord(offset, data >> 16, who);
+       BlitterWriteWord(offset+2, data & 0xFFFF, who);
 }