]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/blitter.cpp
Fix for bad branch handling in OP.
[virtualjaguar] / src / blitter.cpp
index aa5e46fefb7afa7d94580844524c60e0ae31ca32..776bc8c7165e9081142207ae8f2a504f8f36b433 100644 (file)
-#define GEN_CODE
-//#define LOG_BLITS
-//#define USE_GENERIC_BLITTER
+//
+// Blitter core
+//
+// by James Hammons
+// (C) 2010 Underground Software
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -----------------------------------------------------------
+// JLH  01/16/2010  Created this log ;-)
+//
+
+//
+// I owe a debt of gratitude to Curt Vendel and to John Mathieson--to Curt
+// for supplying the Oberon ASIC nets and to John for making them available
+// to Curt. ;-) Without that excellent documentation which shows *exactly*
+// what's going on inside the TOM chip, we'd all still be guessing as to how
+// the wily blitter and other pieces of the Jaguar puzzle actually work.
+// Now how about those JERRY ASIC nets gentlemen...? [We have those now!] ;-)
+//
+
+#include "blitter.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 #include "jaguar.h"
+#include "log.h"
+//#include "memory.h"
+#include "settings.h"
+
+// Various conditional compilation goodies...
+
+#define LOG_BLITS
+
+#define USE_ORIGINAL_BLITTER
+//#define USE_MIDSUMMER_BLITTER
+#define USE_MIDSUMMER_BLITTER_MKII
+
+#ifdef USE_ORIGINAL_BLITTER
+#ifdef USE_MIDSUMMER_BLITTER_MKII
+#define USE_BOTH_BLITTERS
+#endif
+#endif
+
+
+// External global variables
 
-#define null 0
 extern int jaguar_active_memory_dumps;
 
-#define REG(A)         blitter_reg_read(A)
-#define WREG(A,D)      blitter_reg_write(A,D)
+// Local global variables
 
 int start_logging = 0;
-
-static uint8 blitter_ram[0x100];
-
-#define A1_BASE                        ((UINT32)0x00)
-#define A1_FLAGS               ((UINT32)0x04)
-#define A1_CLIP                        ((UINT32)0x08)  // height and width values for clipping
-#define A1_PIXEL               ((UINT32)0x0c)  // integer part of the pixel (Y.i and X.i)
-#define A1_STEP                        ((UINT32)0x10)  // integer part of the step
-#define A1_FSTEP               ((UINT32)0x14)  // fractionnal part of the step
-#define A1_FPIXEL              ((UINT32)0x18)  // fractionnal part of the pixel (Y.f and X.f)
-#define A1_INC                 ((UINT32)0x1C)  // integer part of the increment
-#define A1_FINC                        ((UINT32)0x20)  // fractionnal part of the increment
-#define A2_BASE                        ((UINT32)0x24)
-#define A2_FLAGS               ((UINT32)0x28)
-#define A2_MASK                        ((UINT32)0x2c)  // modulo values for x and y (M.y  and M.x)
-#define A2_PIXEL               ((UINT32)0x30)  // integer part of the pixel (no fractionnal part for A2)
-#define A2_STEP                        ((UINT32)0x34)  // integer part of the step (no fractionnal part for A2)
-#define COMMAND                        ((UINT32)0x38)
-#define PIXLINECOUNTER ((UINT32)0x3C)
-#define SRCDATA                        ((UINT32)0x40)
-#define DSTDATA                        ((UINT32)0x48)
-#define DSTZ                   ((UINT32)0x50)
-#define SRCZINT                        ((UINT32)0x58)
-#define SRCZFRAC               ((UINT32)0x60)
-#define PATTERNDATA            ((UINT32)0x68)
-#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 SRCEN                  (cmd&0x00000001)
-#define SRCENZ                 (cmd&0x00000002)
-#define SRCENX                 (cmd&0x00000004)
-#define DSTEN                  (cmd&0x00000008)
-#define DSTENZ                 (cmd&0x00000010)
-#define DSTWRZ                 (cmd&0x00000020)
-#define CLIPA1                 (cmd&0x00000040)
-#define DSTA2                  (cmd&0x00000800)
-
-#define Z_OP_INF               (cmd&0x00040000)
-#define Z_OP_EQU               (cmd&0x00080000)
-#define Z_OP_SUP               (cmd&0x00100000)
-
-#define CMPDST                 (cmd&0x02000000)
-#define BCOMPEN                        (cmd&0x04000000)
-#define DCOMPEN                        (cmd&0x08000000)
-
-#define LFU_NAN                        (cmd&0x00200000)
-#define LFU_NA                 (cmd&0x00400000)
-#define LFU_AN                 (cmd&0x00800000)
-#define LFU_A                  (cmd&0x01000000)
-
-#define PATDSEL                        (cmd&0x00010000)
-#define INTADD                 (cmd&0x00020000)
-#define TOPBEN                 (cmd&0x00004000)
-#define TOPNEN                 (cmd&0x00008000)
-#define BKGWREN                        (cmd&0x10000000)
-#define GOURD                  (cmd&0x00001000)
-#define GOURZ                  (cmd&0x00002000)
-#define SRCSHADE               (cmd&0x40000000)
+uint8_t blitter_working = 0;
+bool startConciseBlitLogging = false;
+bool logBlit = false;
+
+// Blitter register RAM (most of it is hidden from the user)
+
+static uint8_t blitter_ram[0x100];
+
+// Other crapola
+
+bool specialLog = false;
+extern int effect_start;
+extern int blit_start_log;
+void BlitterMidsummer(uint32_t cmd);
+void BlitterMidsummer2(void);
+
+#define REG(A) (((uint32_t)blitter_ram[(A)] << 24) | ((uint32_t)blitter_ram[(A)+1] << 16) \
+                               | ((uint32_t)blitter_ram[(A)+2] << 8) | (uint32_t)blitter_ram[(A)+3])
+#define WREG(A,D)      (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
+                                       blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
+
+// Blitter registers (offsets from F02200)
+
+#define A1_BASE                        ((uint32_t)0x00)
+#define A1_FLAGS               ((uint32_t)0x04)
+#define A1_CLIP                        ((uint32_t)0x08)        // Height and width values for clipping
+#define A1_PIXEL               ((uint32_t)0x0C)        // Integer part of the pixel (Y.i and X.i)
+#define A1_STEP                        ((uint32_t)0x10)        // Integer part of the step
+#define A1_FSTEP               ((uint32_t)0x14)        // Fractional part of the step
+#define A1_FPIXEL              ((uint32_t)0x18)        // Fractional part of the pixel (Y.f and X.f)
+#define A1_INC                 ((uint32_t)0x1C)        // Integer part of the increment
+#define A1_FINC                        ((uint32_t)0x20)        // Fractional part of the increment
+#define A2_BASE                        ((uint32_t)0x24)
+#define A2_FLAGS               ((uint32_t)0x28)
+#define A2_MASK                        ((uint32_t)0x2C)        // Modulo values for x and y (M.y  and M.x)
+#define A2_PIXEL               ((uint32_t)0x30)        // Integer part of the pixel (no fractional part for A2)
+#define A2_STEP                        ((uint32_t)0x34)        // Integer part of the step (no fractional part for A2)
+#define COMMAND                        ((uint32_t)0x38)
+#define PIXLINECOUNTER ((uint32_t)0x3C)        // Inner & outer loop values
+#define SRCDATA                        ((uint32_t)0x40)
+#define DSTDATA                        ((uint32_t)0x48)
+#define DSTZ                   ((uint32_t)0x50)
+#define SRCZINT                        ((uint32_t)0x58)
+#define SRCZFRAC               ((uint32_t)0x60)
+#define PATTERNDATA            ((uint32_t)0x68)
+#define INTENSITYINC   ((uint32_t)0x70)
+#define ZINC                   ((uint32_t)0x74)
+#define COLLISIONCTRL  ((uint32_t)0x78)
+#define PHRASEINT0             ((uint32_t)0x7C)
+#define PHRASEINT1             ((uint32_t)0x80)
+#define PHRASEINT2             ((uint32_t)0x84)
+#define PHRASEINT3             ((uint32_t)0x88)
+#define PHRASEZ0               ((uint32_t)0x8C)
+#define PHRASEZ1               ((uint32_t)0x90)
+#define PHRASEZ2               ((uint32_t)0x94)
+#define PHRASEZ3               ((uint32_t)0x98)
+
+// Blitter command bits
+
+#define SRCEN                  (cmd & 0x00000001)
+#define SRCENZ                 (cmd & 0x00000002)
+#define SRCENX                 (cmd & 0x00000004)
+#define DSTEN                  (cmd & 0x00000008)
+#define DSTENZ                 (cmd & 0x00000010)
+#define DSTWRZ                 (cmd & 0x00000020)
+#define CLIPA1                 (cmd & 0x00000040)
+
+#define UPDA1F                 (cmd & 0x00000100)
+#define UPDA1                  (cmd & 0x00000200)
+#define UPDA2                  (cmd & 0x00000400)
+
+#define DSTA2                  (cmd & 0x00000800)
+
+#define Z_OP_INF               (cmd & 0x00040000)
+#define Z_OP_EQU               (cmd & 0x00080000)
+#define Z_OP_SUP               (cmd & 0x00100000)
+
+#define LFU_NAN                        (cmd & 0x00200000)
+#define LFU_NA                 (cmd & 0x00400000)
+#define LFU_AN                 (cmd & 0x00800000)
+#define LFU_A                  (cmd & 0x01000000)
+
+#define CMPDST                 (cmd & 0x02000000)
+#define BCOMPEN                        (cmd & 0x04000000)
+#define DCOMPEN                        (cmd & 0x08000000)
+
+#define PATDSEL                        (cmd & 0x00010000)
+#define ADDDSEL                        (cmd & 0x00020000)
+#define TOPBEN                 (cmd & 0x00004000)
+#define TOPNEN                 (cmd & 0x00008000)
+#define BKGWREN                        (cmd & 0x10000000)
+#define GOURD                  (cmd & 0x00001000)
+#define GOURZ                  (cmd & 0x00002000)
+#define SRCSHADE               (cmd & 0x40000000)
 
 
 #define XADDPHR         0
@@ -85,41 +153,53 @@ static uint8 blitter_ram[0x100];
 #define XADD0   2
 #define XADDINC         3
 
-#define XSIGNSUB_A1            (REG(A1_FLAGS)&0x80000)
-#define XSIGNSUB_A2            (REG(A2_FLAGS)&0x80000)
+#define XSIGNSUB_A1            (REG(A1_FLAGS)&0x080000)
+#define XSIGNSUB_A2            (REG(A2_FLAGS)&0x080000)
 
 #define YSIGNSUB_A1            (REG(A1_FLAGS)&0x100000)
 #define YSIGNSUB_A2            (REG(A2_FLAGS)&0x100000)
 
-#define YADD1_A1               (REG(A1_FLAGS)&0x40000)
-#define YADD1_A2               (REG(A2_FLAGS)&0x40000)
+#define YADD1_A1               (REG(A1_FLAGS)&0x040000)
+#define YADD1_A2               (REG(A2_FLAGS)&0x040000)
+
+/*******************************************************************************
+********************** STUFF CUT BELOW THIS LINE! ******************************
+*******************************************************************************/
+#ifdef USE_ORIGINAL_BLITTER                                                                            // We're ditching this crap for now...
 
+//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 PIXEL_OFFSET_1(a)     (((((uint32_t)a##_y >> 16) * a##_width / 8) + (((uint32_t)a##_x >> 19) & ~7)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 19) & 7))
+#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 PIXEL_OFFSET_2(a)     (((((uint32_t)a##_y >> 16) * a##_width / 4) + (((uint32_t)a##_x >> 18) & ~7)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 18) & 7))
+#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 PIXEL_OFFSET_4(a)     (((((uint32_t)a##_y >> 16) * (a##_width/2)) + (((uint32_t)a##_x >> 17) & ~7)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 17) & 7))
+#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 PIXEL_OFFSET_8(a)     (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 7))
+#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 PIXEL_OFFSET_16(a)    (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 3))
+#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 PIXEL_OFFSET_32(a)    (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 1))
+#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) (\
@@ -132,35 +212,36 @@ static uint8 blitter_ram[0x100];
 
 // 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)     {  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); 
+#define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d);
 
 // 1 bpp r data read
-#define READ_RDATA_1(r,a,p)  ((p) ?  ((REG(r+(((UINT32)a##_x>>19)&4)))>>(((UINT32)a##_x>>16)&0x1f))&   0x1 : (REG(r) &    0x1))
+#define READ_RDATA_1(r,a,p)  ((p) ?  ((REG(r+(((uint32_t)a##_x >> 19) & 0x04))) >> (((uint32_t)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001))
 
 // 2 bpp r data read
-#define READ_RDATA_2(r,a,p)  ((p) ?  ((REG(r+(((UINT32)a##_x>>18)&4)))>>(((UINT32)a##_x>>15)&0x3e))&   0x3 : (REG(r) &    0x3))
+#define READ_RDATA_2(r,a,p)  ((p) ?  ((REG(r+(((uint32_t)a##_x >> 18) & 0x04))) >> (((uint32_t)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003))
 
 // 4 bpp r data read
-#define READ_RDATA_4(r,a,p)  ((p) ?  ((REG(r+(((UINT32)a##_x>>17)&4)))>>(((UINT32)a##_x>>14)&0x28))&   0xf : (REG(r) &    0xf))
+#define READ_RDATA_4(r,a,p)  ((p) ?  ((REG(r+(((uint32_t)a##_x >> 17) & 0x04))) >> (((uint32_t)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F))
 
 // 8 bpp r data read
-#define READ_RDATA_8(r,a,p)  ((p) ?  ((REG(r+(((UINT32)a##_x>>16)&4)))>>(((UINT32)a##_x>>13)&0x18))&  0xff : (REG(r) &   0xff))
+#define READ_RDATA_8(r,a,p)  ((p) ?  ((REG(r+(((uint32_t)a##_x >> 16) & 0x04))) >> (((uint32_t)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF))
 
 // 16 bpp r data read
-#define READ_RDATA_16(r,a,p)  ((p) ? ((REG(r+(((UINT32)a##_x>>15)&4)))>>(((UINT32)a##_x>>12)&0x10))&0xffff : (REG(r) & 0xffff))
+#define READ_RDATA_16(r,a,p)  ((p) ? ((REG(r+(((uint32_t)a##_x >> 15) & 0x04))) >> (((uint32_t)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF))
 
 // 32 bpp r data read
-#define READ_RDATA_32(r,a,p)  ((p) ? REG(r+(((UINT32)a##_x>>14)&4)) : REG(r))
-
+#define READ_RDATA_32(r,a,p)  ((p) ? REG(r+(((uint32_t)a##_x >> 14) & 0x04)) : REG(r))
 
 // register data read
 #define READ_RDATA(r,a,f,p) (\
@@ -172,672 +253,443 @@ static uint8 blitter_ram[0x100];
         (((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)     {  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)            { 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) {\
        switch ((f>>3)&0x07) { \
        case 0: WRITE_PIXEL_1(a,d);  break;  \
        case 1: WRITE_PIXEL_2(a,d);  break;  \
-       case 2: WRITE_PIXEL_4(a,d); break;  \
+       case 2: WRITE_PIXEL_4(a,d);  break;  \
        case 3: WRITE_PIXEL_8(a,d);  break;  \
        case 4: WRITE_PIXEL_16(a,d); break;  \
        case 5: WRITE_PIXEL_32(a,d); break;  \
-       }} \
-
-
+       }}
 
 // Width in Pixels of a Scanline
-static uint32 blitter_scanline_width[48] = 
-{             
-     0,     0,     0,      0,      2,      0,      0,      0,      4,
-     0,     6,     0,      8,     10,     12,     14,     16,     20,
-    24,    28,    32,     40,     48,     56,     64,     80,     96,
-   112,   128,   160,    192,    224,    256,    320,    384,    448,
-   512,   640,   768,    896,   1024,   1280,   1536,   1792,   2048,
-  2560,  3072,  3584
-};
-
-static uint8 * tom_ram_8;
-static uint8 * paletteRam;
-static uint8 src;
-static uint8 dst;
-static uint8 misc;
-static uint8 a1ctl;
-static uint8 mode;
-static uint8 ity;
-static uint8 zop;
-static uint8 op;
-static uint8 ctrl;
-static uint32 a1_addr;
-static uint32 a2_addr;
-static int32 a1_zoffs;
-static int32 a2_zoffs;
-static uint32 xadd_a1_control;
-static uint32 xadd_a2_control;
-static int32 a1_pitch;
-static int32 a2_pitch;
-static uint32 n_pixels;
-static uint32 n_lines;
-static int32 a1_x;
-static int32 a1_y;
-static int32 a1_width;
-static int32 a2_x;
-static int32 a2_y;
-static int32 a2_width;
-static int32 a2_mask_x;
-static int32 a2_mask_y;
-static int32 a1_xadd;
-static int32 a1_yadd;
-static int32 a2_xadd;
-static int32 a2_yadd;
-static uint8 a1_phrase_mode;
-static uint8 a2_phrase_mode;
-static int32 a1_step_x=0;
-static int32 a1_step_y=0;
-static int32 a2_step_x=0;
-static int32 a2_step_y=0;
-static uint32 outer_loop;
-static uint32 inner_loop;
-static uint32 a2_psize;
-static uint32 a1_psize;
-static uint32 gouraud_add;
-static uint32 gouraud_data;
-static uint16 gint[4];
-static uint16 gfrac[4];
-static uint8  gcolour[4];
-static int       gd_i[4];
-static int    gd_c[4];
-static int    gd_ia,gd_ca;
-static int    colour_index = 0;
-static int32  zadd;
-static uint32  z_i[4];
-
-static uint8 blitter_code_cache[4096];
-static uint8 * blitter_ptr;
-uint8 blitter_working = 0;
-
-typedef void (blitter_fn)(void);
-
-typedef struct s_blitter_cache
-{
-       uint32 hashcode;
-       uint8  *code;
-       uint32 ready;
-       uint8   used;
-       struct s_blitter_cache *next;
-       struct s_blitter_cache *prev;
-} s_blitter_code_cache;
-
-s_blitter_cache *blitter_cache[256];
-
-uint8 blitter_cache_init=0;
-static uint8 BPP_LUT[8]={1,2,4,8,16,32,0,0};
-
-FILE *blitters_code_fp;
-FILE *blitters_code_init_fp;
-
-//////////////////////////////////////////////////////////////////////////////
-// build C code for the specified blitter
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_gen_c_code(FILE *fp, uint32 cmd,uint32 hashcode)
-{
-       static uint8 inhibit_modified=0;
-
-       fprintf(fp,"#ifndef blitter_code_0x%.8x\n",hashcode);
-       fprintf(fp,"#define blitter_code_0x%.8x\n",hashcode);
-
-       fprintf(fp,"void blitter_0x%.8x(void)\n",hashcode);
-       fprintf(fp,"{\n");
-       fprintf(fp,"\twhile (outer_loop--)\n");
-       fprintf(fp,"\t{\n");
-       fprintf(fp,"\t\tinner_loop=n_pixels;\n");
-       fprintf(fp,"\t\twhile (inner_loop--)\n");
-       fprintf(fp,"\t\t{\n");
-       fprintf(fp,"\t\t\tuint32 srcdata   = 0;\n");
-       fprintf(fp,"\t\t\tuint32 srczdata  = 0;\n");
-       fprintf(fp,"\t\t\tuint32 dstdata   = 0;\n");
-       fprintf(fp,"\t\t\tuint32 dstzdata  = 0;\n");
-       fprintf(fp,"\t\t\tuint32 writedata = 0;\n");
-       fprintf(fp,"\t\t\tuint32 inhibit   = 0;\n");
-       
-       char *src;
-       char *dst;
-       uint32 src_flags;
-       uint32 dst_flags;
-
-       if (!DSTA2)
-       {
-               src="a2";
-               dst="a1";
-               src_flags=A2_FLAGS;
-               dst_flags=A1_FLAGS;
-       }
-       else
-       {
-               src="a1";
-               dst="a2";
-               src_flags=A1_FLAGS;
-               dst_flags=A2_FLAGS;
-       }
-
-       // load src data and Z
-       if (SRCEN)
-       {
-               fprintf(fp,"\t\t\tsrcdata = READ_PIXEL_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src);
-               if (SRCENZ)
-                       fprintf(fp,"\t\t\tsrczdata = READ_ZDATA_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src);
-               else 
-               if (cmd & 0x001c020)
-                       fprintf(fp,"\t\t\tsrczdata = READ_RDATA_%i(SRCZINT, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(src_flags))>>3)&0x07)],src,src);
-       }
-       else
-       {
-               fprintf(fp,"\t\t\tsrcdata = READ_RDATA_%i(SRCDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src);
-               if (cmd & 0x001c020)
-                       fprintf(fp,"\t\t\tsrczdata = READ_RDATA_%i(SRCZINT, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src);
-       }
-
-       // load dst data and Z 
-       if (DSTEN)
-       {
-               fprintf(fp,"\t\t\tdstdata = READ_PIXEL_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
-               if (DSTENZ)
-                       fprintf(fp,"\t\t\tdstzdata = READ_ZDATA_%i(%s);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
-               else
-                       fprintf(fp,"\t\t\tdstzdata = READ_RDATA_%i(DSTZ, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
-       }
-       else
-       {
-               fprintf(fp,"\t\t\tdstdata = READ_RDATA_%i(DSTDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
-
-               if (DSTENZ)
-                       fprintf(fp,"\t\t\tdstzdata = READ_RDATA_%i(DSTZ, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
-       }
-
-       // a1 clipping
-       if ((cmd & 0x00000040)&&(!DSTA2))
-
-       {
-               fprintf(fp,"\t\t\tif (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7fff) || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7fff))       inhibit = 1;\n");
-                inhibit_modified=1;
-       }
-       if(GOURZ) 
-       {
-               fprintf(fp,"\t\t\tsrczdata=z_i[colour_index]>>16;\n");
-       }
-       // apply z comparator
-       if (Z_OP_INF) { fprintf(fp,"\t\t\tif (srczdata <  dstzdata)     inhibit = 1;\n"); inhibit_modified=1;}
-       if (Z_OP_EQU) { fprintf(fp,"\t\t\tif (srczdata == dstzdata)     inhibit = 1;\n"); inhibit_modified=1;}
-       if (Z_OP_SUP) { fprintf(fp,"\t\t\tif (srczdata >  dstzdata)     inhibit = 1;\n"); inhibit_modified=1;}
-
-       // apply data comparator
-       if (DCOMPEN)
-       {
-               if (!CMPDST)
-               {
-                       // compare source pixel with pattern pixel
-                       fprintf(fp,"\t\t\tif (srcdata == READ_RDATA_%i(PATTERNDATA, %s,%s_phrase_mode)) inhibit=1;\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],src,src);
-                       inhibit_modified=1;
-               }
-               else
-               {
-                       // compare destination pixel with pattern pixel
-                       fprintf(fp,"\t\t\tif (dstdata == READ_RDATA_%i(PATTERNDATA, %s,%s_phrase_mode)) inhibit=1;\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
-                       inhibit_modified=1;
-               }
-       }
-       
-       // compute the write data and store
-               if (inhibit_modified) fprintf(fp,"\t\t\tif (!inhibit)\n\t\t\t{\n");
-               if (PATDSEL)
-               {
-                       // use pattern data for write data
-                       fprintf(fp,"\t\t\t\twritedata= READ_RDATA_%i(PATTERNDATA, %s, %s_phrase_mode);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst,dst);
-               }
-               else 
-               if (INTADD)
-               {
-                       // intensity addition
-                       fprintf(fp,"\t\t\t\twritedata = (srcdata & 0xff) + (dstdata & 0xff);\n");
-                       if (!(TOPBEN))
-                               fprintf(fp,"\t\t\t\tif (writedata > 0xff) writedata = 0xff;\n");
-
-                       fprintf(fp,"\t\t\t\twritedata |= (srcdata & 0xf00) + (dstdata & 0xf00);\n");
-                       if (!(TOPNEN)) fprintf(fp,"\t\t\t\tif (writedata > 0xfff) writedata = 0xfff;\n");
-                       fprintf(fp,"\t\t\t\twritedata |= (srcdata & 0xf000) + (dstdata & 0xf000);\n");
-               }
-               else
-               {
-                       if (LFU_NAN) fprintf(fp,"\t\t\t\twritedata |= ~srcdata & ~dstdata;\n");
-                       if (LFU_NA)  fprintf(fp,"\t\t\t\twritedata |= ~srcdata & dstdata;\n");
-                       if (LFU_AN)  fprintf(fp,"\t\t\t\twritedata |= srcdata  & ~dstdata;\n");
-                       if (LFU_A)       fprintf(fp,"\t\t\t\twritedata |= srcdata  & dstdata;\n");
-               }
-               if(GOURD) 
-               {
-                       fprintf(fp,"\t\t\t\twritedata = ((gd_c[colour_index])<<8)|(gd_i[colour_index]>>16);\n");
-               }
-               if(SRCSHADE) 
-               {
-                       fprintf(fp,"\t\t\t\t{\n");
-                       fprintf(fp,"\t\t\t\tint intensity = srcdata & 0xFF;\n");
-                       fprintf(fp,"\t\t\t\tint ia = gd_ia >> 16;\n");
-                       fprintf(fp,"\t\t\t\tif(ia & 0x80)\n");
-                       fprintf(fp,"\t\t\t\t    ia = 0xFFFFFF00 | ia;\n");
-                       fprintf(fp,"\t\t\t\tintensity += ia;\n");
-                       fprintf(fp,"\t\t\t\tif(intensity < 0)\n");
-                       fprintf(fp,"\t\t\t\t    intensity = 0;\n");
-                       fprintf(fp,"\t\t\t\tif(intensity > 0xFF)\n");
-                       fprintf(fp,"\t\t\t\t    intensity = 0xFF;\n");
-                       fprintf(fp,"\t\t\t\twritedata = (srcdata & 0xFF00) | intensity;\n");
-                       fprintf(fp,"\t\t\t\t}\n");
-               }
-       if (inhibit_modified)  
-       {
-               fprintf(fp,"\t\t\t} else { srczdata=dstzdata; writedata=dstdata; }\n");
-       }
-
-       if ((DSTA2?a2_phrase_mode:a1_phrase_mode) || BKGWREN)
-       {
-               // write to the destination
-               fprintf(fp,"\t\t\tWRITE_PIXEL_%i(%s, writedata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
-               if (DSTWRZ) fprintf(fp,"\t\t\tWRITE_ZDATA_%i(%s, srczdata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
-       }
-       else
-       {
-               if (inhibit_modified) fprintf(fp,"\t\t\tif (!inhibit)\n\t\t\t{\n");
-               // write to the destination
-               fprintf(fp,"\t\t\t\tWRITE_PIXEL_%i(%s, writedata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
-               if (DSTWRZ) fprintf(fp,"\t\t\t\tWRITE_ZDATA_%i(%s, srczdata);\n",BPP_LUT[(((REG(dst_flags))>>3)&0x07)],dst);
-               if (inhibit_modified) fprintf(fp,"\t\t\t}\n");
-       }
-       // update x and y
-       fprintf(fp,"\t\t\ta1_x += a1_xadd;\n");
-       fprintf(fp,"\t\t\ta1_y += a1_yadd;\n");
-       fprintf(fp,"\t\t\ta2_x = (a2_x + a2_xadd) & a2_mask_x;\n");
-       fprintf(fp,"\t\t\ta2_y = (a2_y + a2_yadd) & a2_mask_y;\n");
-       if (GOURZ)
-       {
-               fprintf(fp,"\t\t\tz_i[colour_index]+=zadd;\n");
-       }
-       if ((GOURD)||(SRCSHADE))
-       {
-               fprintf(fp,"\t\t\tgd_i[colour_index] += gd_ia;\n");
-               fprintf(fp,"\t\t\tgd_c[colour_index] += gd_ca;\n");
-       }
-       if ((GOURD)||(SRCSHADE)||(GOURZ))
-       {
-               if (a1_phrase_mode)
-               fprintf(fp,"\t\t\t colour_index=(colour_index+1)&0x3;\n");
-       }
-       fprintf(fp,"\t\t}\n");
-
-       fprintf(fp,"\t\ta1_x+=a1_step_x;\n");
-       fprintf(fp,"\t\ta1_y+=a1_step_y;\n");
-       fprintf(fp,"\t\ta2_x+=a2_step_x;\n");
-       fprintf(fp,"\t\ta2_y+=a2_step_y;\n");
-       fprintf(fp,"\t}\n");
-       
-       // write values back to registers 
-       fprintf(fp,"\tWREG(A1_PIXEL,  (a1_y & 0xffff0000) | ((a1_x >> 16) & 0xffff));\n");
-       fprintf(fp,"\tWREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xffff));\n");
-       fprintf(fp,"\tWREG(A2_PIXEL,  (a2_y & 0xffff0000) | ((a2_x >> 16) & 0xffff));\n");
-       fprintf(fp,"}\n");
-       fprintf(fp,"#endif\n");
-}
-
-//////////////////////////////////////////////////////////////////////////////
-// Generate a start of function in x86 assembly
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_gen_start_of_function(void)
+// This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
+// of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
+// the exponent. Valid values for the exponent range from 0 to 11 (decimal). It's easiest to think of it
+// 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_t blitter_scanline_width[48] =
 {
-       *blitter_ptr++=0x55;    // push ebp
-       *blitter_ptr++=0x8b;    // mov  ebp,esp
-       *blitter_ptr++=0xec;
-}
-//////////////////////////////////////////////////////////////////////////////
-// Generate a end of function in x86 assembly
-//////////////////////////////////////////////////////////////////////////////
-//
+     0,    0,    0,    0,                                      // Note: This would really translate to 1, 1, 1, 1
+     2,    0,    0,    0,
+     4,    0,    6,    0,
+     8,   10,   12,   14,
+    16,   20,   24,   28,
+    32,   40,   48,   56,
+    64,   80,   96,  112,
+   128,  160,  192,  224,
+   256,  320,  384,  448,
+   512,  640,  768,  896,
+  1024, 1280, 1536, 1792,
+  2048, 2560, 3072, 3584
+};//*/
+
+//static uint8_t * tom_ram_8;
+//static uint8_t * paletteRam;
+static uint8_t src;
+static uint8_t dst;
+static uint8_t misc;
+static uint8_t a1ctl;
+static uint8_t mode;
+static uint8_t ity;
+static uint8_t zop;
+static uint8_t op;
+static uint8_t ctrl;
+static uint32_t a1_addr;
+static uint32_t a2_addr;
+static int32_t a1_zoffs;
+static int32_t a2_zoffs;
+static uint32_t xadd_a1_control;
+static uint32_t xadd_a2_control;
+static int32_t a1_pitch;
+static int32_t a2_pitch;
+static uint32_t n_pixels;
+static uint32_t n_lines;
+static int32_t a1_x;
+static int32_t a1_y;
+static int32_t a1_width;
+static int32_t a2_x;
+static int32_t a2_y;
+static int32_t a2_width;
+static int32_t a2_mask_x;
+static int32_t a2_mask_y;
+static int32_t a1_xadd;
+static int32_t a1_yadd;
+static int32_t a2_xadd;
+static int32_t a2_yadd;
+static uint8_t a1_phrase_mode;
+static uint8_t a2_phrase_mode;
+static int32_t a1_step_x = 0;
+static int32_t a1_step_y = 0;
+static int32_t a2_step_x = 0;
+static int32_t a2_step_y = 0;
+static uint32_t outer_loop;
+static uint32_t inner_loop;
+static uint32_t a2_psize;
+static uint32_t a1_psize;
+static uint32_t gouraud_add;
+//static uint32_t gouraud_data;
+//static uint16_t gint[4];
+//static uint16_t gfrac[4];
+//static uint8_t  gcolour[4];
+static int gd_i[4];
+static int gd_c[4];
+static int gd_ia, gd_ca;
+static int colour_index = 0;
+static int32_t zadd;
+static uint32_t z_i[4];
+
+static int32_t a1_clip_x, a1_clip_y;
+
+// In the spirit of "get it right first, *then* optimize" I've taken the liberty
+// of removing all the unnecessary code caching. If it turns out to be a good way
+// to optimize the blitter, then we may revisit it in the future...
+
 //
+// Generic blit handler
 //
-//////////////////////////////////////////////////////////////////////////////
-void blitter_gen_end_of_function(void)
+void blitter_generic(uint32_t cmd)
 {
-       *blitter_ptr++=0x8B;    // mov         esp,ebp
-       *blitter_ptr++=0xE5;
-       *blitter_ptr++=0x5D;    // pop         ebp
-       *blitter_ptr++=0xC3;    // ret
-}
-//////////////////////////////////////////////////////////////////////////////
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-#define HASHCODE_BIT(C,B) if (C) hashcode|=(1<<B);
-#define HASHCODE_BIT_TEST(B) (hashcode&(1<<B))
-
-uint32 blitter_calc_hashcode(uint32 cmd)
-{
-       uint32 hashcode=0x00000000;
-
-       // source and destination bit depth
-       hashcode|=((REG(A1_FLAGS)>>3)&0x07)<<0;
-       hashcode|=((REG(A2_FLAGS)>>3)&0x07)<<3;
-
-       HASHCODE_BIT(DSTA2,                                     6);
-       HASHCODE_BIT(SRCEN,                                     7);
-       HASHCODE_BIT(SRCENZ,                            8);
-       HASHCODE_BIT(DSTEN,                                     9);
-       HASHCODE_BIT(DSTENZ,                            10);
-       HASHCODE_BIT(Z_OP_INF,                          11);
-       HASHCODE_BIT(Z_OP_EQU,                          12);
-       HASHCODE_BIT(Z_OP_SUP,                          13);
-       HASHCODE_BIT(DCOMPEN,                           14);
-       HASHCODE_BIT(CMPDST,                            15);
-       HASHCODE_BIT(PATDSEL,                           16);
-       HASHCODE_BIT(INTADD,                            17);
-       HASHCODE_BIT(TOPBEN,                            18);
-       HASHCODE_BIT(TOPNEN,                            19);
-       HASHCODE_BIT(LFU_NAN,                           20);
-       HASHCODE_BIT(LFU_NA,                            21);
-       HASHCODE_BIT(LFU_AN,                            22);
-       HASHCODE_BIT(LFU_A,                                     23);
-       HASHCODE_BIT(BKGWREN,                           24);
-       HASHCODE_BIT(DSTWRZ,                            25);
-       HASHCODE_BIT((cmd & 0x001c020),         26); // extra data read/write
-       HASHCODE_BIT((cmd & 0x00000040),        27); // source clipping
-       HASHCODE_BIT(a1_phrase_mode,            28); 
-       HASHCODE_BIT(a2_phrase_mode,            29); 
-
-
-       return(hashcode);
-}
-//////////////////////////////////////////////////////////////////////////////
-// Build the blitter code for the current blitter operation in the cache
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_build_cached_code(uint32 cmd, uint32 cache_index)
+/*
+Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
+ CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
+  A1 step values: -2 (X), 1 (Y)
+  A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
+*/
+//if (effect_start)
+//     specialLog = true;
+/*if (cmd == 0x1401060C && blit_start_log)
+       specialLog = true;//*/
+//Testing only!
+//uint32_t logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
+       uint32_t srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
+       uint32_t bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07));
+
+if (specialLog)
 {
+       WriteLog("About to do n x m blit (BM width is ? pixels)...\n");
+       WriteLog("A1_STEP_X/Y = %08X/%08X, A2_STEP_X/Y = %08X/%08X\n", a1_step_x, a1_step_y, a2_step_x, a2_step_y);
 }
-//////////////////////////////////////////////////////////////////////////////
-// Check if the blitter code for the current blitter operation is cached
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-struct s_blitter_cache * blitter_in_cache(uint32 cmd)
-{
-       uint32 i;
-       uint32 hashcode=blitter_calc_hashcode(cmd);
-#ifdef LOG_BLITS
-       fprintf(log_get(),"blitter: hashcode= 0x%.8x\n",hashcode);
-#endif
-       struct s_blitter_cache *blitter_list=blitter_cache[hashcode>>24];
-       
-       i=0;
-       while (blitter_list->next)
+/*     if (BCOMPEN)
        {
-               blitter_list=blitter_list->next;
-
-               if (blitter_list->hashcode==hashcode)
-                       return(blitter_list);
-       }
-#ifdef GEN_CODE
-       blitter_list->next=(struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache));
-       blitter_list->next->prev=blitter_list;
-       blitter_list->next->next=null;
-       blitter_list=blitter_list->next;
-
-       blitter_list->code=(uint8*)malloc(4096);
-       blitter_list->hashcode=hashcode;
-       blitter_list->ready=0;
-       blitter_gen_c_code(blitters_code_fp,cmd,hashcode);
-       fprintf(blitters_code_init_fp,"\tblitter_add(0x%.8x,(uint8*)&blitter_0x%.8x);\n",hashcode,hashcode);
-#else
-       //fprintf(log_get(),"warning: using generic blitter for blitter 0x%.8x\n",hashcode);
-#endif
-       return(null);
-}
-#ifndef USE_GENERIC_BLITTER
-#include "include/blit_c.h"
-#endif
-//////////////////////////////////////////////////////////////////////////////
-// Execute the cached blitter code for the current blitter operation
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-uint32 blitter_execute_cached_code(struct s_blitter_cache *blitter)
-{
-       if ((blitter==null)||(blitter->ready==0))
-               return 0;
-
-       blitter_fn *fn=(blitter_fn*)blitter->code;
-       blitter->used=1;
-       (*fn)();
-
-       return(1);
-}
-//////////////////////////////////////////////////////////////////////////////
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_add(uint32 hashcode, uint8 *code)
-{
-       struct s_blitter_cache *blitter_list=blitter_cache[(hashcode>>24)];
-
-//     fprintf(log_get(),"adding blitter for hashcode 0x%.8x\n",hashcode);
+               if (DSTA2)
+                       a1_xadd = 0;
+               else
+                       a2_xadd = 0;
+       }//*/
 
-       while (blitter_list->next)
+       while (outer_loop--)
        {
-               blitter_list=blitter_list->next;
-
-               if (blitter_list->hashcode==hashcode)
-                       return;
-       }
-       blitter_list->next=(struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache));
-       blitter_list->next->prev=blitter_list;
-       blitter_list->next->next=null;
-       blitter_list=blitter_list->next;
-
-       blitter_list->code=code;
-       blitter_list->hashcode=hashcode;
-       blitter_list->ready=1;
-       blitter_list->used=0;
-}
-//////////////////////////////////////////////////////////////////////////////
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_list(void)
+if (specialLog)
 {
-/*
-       fprintf(log_get(),"Used blitters list:\n");
-
-       for (int i=0;i<256;i++)
-       {
-               struct s_blitter_cache *blitter_list=blitter_cache[i];
+       WriteLog("  A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
+}
+               uint32_t a1_start = a1_x, a2_start = a2_x, bitPos = 0;
 
-               while (blitter_list->next)
+               //Kludge for Hover Strike...
+               //I wonder if this kludge is in conjunction with the SRCENX down below...
+               // This isn't so much a kludge but the way things work in BCOMPEN mode...!
+               if (BCOMPEN && SRCENX)
                {
-                       blitter_list=blitter_list->next;
-                       if (blitter_list->used)
-                               fprintf(log_get(),"\t0%.8x\n",blitter_list->hashcode);
+                       if (n_pixels < bppSrc)
+                               bitPos = bppSrc - n_pixels;
                }
-       }
-*/
-}
-//////////////////////////////////////////////////////////////////////////////
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_generic(uint32 cmd)
-{
-       uint32 srcdata   = 0;
-       uint32  srczdata  = 0;
-       uint32 dstdata   = 0;
-       uint32  dstzdata  = 0;
-       uint32 writedata = 0;
-       uint32 inhibit   = 0;
-       while (outer_loop--)
-       {
-               inner_loop=n_pixels;
+
+               inner_loop = n_pixels;
                while (inner_loop--)
                {
-                       srcdata   = 0;
-                       srczdata  = 0;
-                       dstdata   = 0;
-                       dstzdata  = 0;
-                       writedata = 0;
-                       inhibit   = 0;
-
-                       if (!DSTA2)
+if (specialLog)
+{
+       WriteLog("    A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
+}
+                       srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
+
+                       if (!DSTA2)                                                     // Data movement: A1 <- A2
                        {
                                // load src data and Z
-                               if (SRCEN)
+//                             if (SRCEN)
+                               if (SRCEN || SRCENX)    // Not sure if this is correct... (seems to be...!)
                                {
                                        srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
+
                                        if (SRCENZ)
-                                       {
                                                srczdata = READ_ZDATA(a2, REG(A2_FLAGS));
-                                       }
-                                       else 
-                                       if (cmd & 0x001c020)
-                                       {
+                                       else if (cmd & 0x0001C020)      // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
                                                srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
-                                       }
                                }
-                               else
+                               else    // Use SRCDATA register...
                                {
                                        srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
-                                       if (cmd & 0x001c020)
-                                       {
+
+                                       if (cmd & 0x0001C020)           // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
                                                srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
-                                       }
                                }
 
-                               // load dst data and Z 
+                               // load dst data and Z
                                if (DSTEN)
                                {
                                        dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
+
                                        if (DSTENZ)
-                                       {
                                                dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
-                                       }
                                        else
-                                       {
                                                dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
-                                       }
                                }
                                else
                                {
                                        dstdata = READ_RDATA(DSTDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
-               
+
                                        if (DSTENZ)
-                                       {
                                                dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
-                                       }
                                }
 
-                               // a1 clipping
+/*This wasn't working...                               // a1 clipping
                                if (cmd & 0x00000040)
                                {
-                                       if ( 
-                                                a1_x < 0 || 
-                                                a1_y < 0 ||
-                                            (a1_x >> 16) >= (REG(A1_CLIP) & 0x7fff) ||
-                                                (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7fff)
-                                               )
+                                       if (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7FFF)
+                                               || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7FFF))
                                                inhibit = 1;
-                               }
+                               }//*/
 
-                               if(GOURZ) 
-                                       srczdata=z_i[colour_index]>>16;
+                               if (GOURZ)
+                                       srczdata = z_i[colour_index] >> 16;
 
                                // apply z comparator
-                               if (Z_OP_INF) if (srczdata <  dstzdata) inhibit = 1;
-                               if (Z_OP_EQU) if (srczdata == dstzdata) inhibit = 1;
-                               if (Z_OP_SUP) if (srczdata >  dstzdata) inhibit = 1;
-                               
+                               if (Z_OP_INF && srczdata <  dstzdata)   inhibit = 1;
+                               if (Z_OP_EQU && srczdata == dstzdata)   inhibit = 1;
+                               if (Z_OP_SUP && srczdata >  dstzdata)   inhibit = 1;
+
                                // apply data comparator
-                               if (DCOMPEN|BCOMPEN)
+// Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
+// Does BCOMPEN only work in 1 bpp mode???
+//   No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!!
+//   This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside
+//   an 8BPP space.
+                               if (DCOMPEN | BCOMPEN)
                                {
+//Temp, for testing Hover Strike
+//Doesn't seem to do it... Why?
+//What needs to happen here is twofold. First, the address generator in the outer loop has
+//to honor the BPP when calculating the start address (which it kinda does already). Second,
+//it has to step bit by bit when using BCOMPEN. How to do this???
+       if (BCOMPEN)
+//small problem with this approach: it's not accurate... We need a proper address to begin with
+//and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!!
+//[DONE]
+       {
+               uint32_t pixShift = (~bitPos) & (bppSrc - 1);
+               srcdata = (srcdata >> pixShift) & 0x01;
+
+               bitPos++;
+//             if (bitPos % bppSrc == 0)
+//                     a2_x += 0x00010000;
+       }
+/*
+Interesting (Hover Strike--large letter):
+
+Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
+ CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
+  A1 step values: -2 (X), 1 (Y)
+  A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
+
+Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
+ CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
+  A1 step values: -8 (X), 1 (Y)
+  A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000
+
+Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
+ CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
+  A1 step values: -1 (X), 1 (Y)
+  A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 118/12, A2 x/y: 70/0 Pattern: 000000F300000000
+
+Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
+ CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
+  A1 step values: -8 (X), 1 (Y)
+  A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 119/12, A2 x/y: 71/0 Pattern: 000000F300000000
+
+Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
+ CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
+  A1 step values: -1 (X), 1 (Y)
+  A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 127/12, A2 x/y: 66/0 Pattern: 000000F300000000
+
+Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
+ CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
+  A1 step values: -8 (X), 1 (Y)
+  A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000
+*/
+
+
                                        if (!CMPDST)
                                        {
+//WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit);
                                                // compare source pixel with pattern pixel
-                                               if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
-                                                       inhibit=1;
+/*
+Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: 05810001]
+ CMD -> src: SRCEN  dst:  misc:  a1ctl:  mode:  ity: PATDSEL z-op:  op: LFU_REPLACE ctrl: BCOMPEN
+  A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 1bpp, z-off: 0, width: 16 (10), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
+        x/y: 0/20
+...
+*/
+// AvP is still wrong, could be cuz it's doing A1 -> A2...
+
+// Src is the 1bpp bitmap... DST is the PATTERN!!!
+// This seems to solve at least ONE of the problems with MC3D...
+// Why should this be inverted???
+// Bcuz it is. This is supposed to be used only for a bit -> pixel expansion...
+/*                                             if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
+//                                             if (srcdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
+                                                       inhibit = 1;//*/
+/*                                             uint32_t A2bpp = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
+                                               if (A2bpp == 1 || A2bpp == 16 || A2bpp == 8)
+                                                       inhibit = (srcdata == 0 ? 1: 0);
+//                                                     inhibit = !srcdata;
+                                               else
+                                                       WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
+// What it boils down to is this:
+
+                                               if (srcdata == 0)
+                                                       inhibit = 1;//*/
                                        }
                                        else
                                        {
                                                // compare destination pixel with pattern pixel
                                                if (dstdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
-                                                       inhibit=1;
+//                                             if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_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)
+                               {
+                                       inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
+                                               && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
                                }
-                               
+
                                // 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
-                                               writedata= READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
+                                               writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
                                        }
-                                       else 
-                                       if (INTADD)
+                                       else if (ADDDSEL)
                                        {
+/*if (blit_start_log)
+       WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/
+
                                                // intensity addition
-                                               writedata = (srcdata & 0xff) + (dstdata & 0xff);
-                                               if (!(TOPBEN) && writedata > 0xff)
-                                                       writedata = 0xff;
-                                               writedata |= (srcdata & 0xf00) + (dstdata & 0xf00);
-                                               if (!(TOPNEN) && writedata > 0xfff)
-                                                       writedata = 0xfff;
-                                               writedata |= (srcdata & 0xf000) + (dstdata & 0xf000);
+//Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!!
+/*                                             writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
+                                               if (!(TOPBEN) && writedata > 0xFF)
+//                                                     writedata = 0xFF;
+                                                       writedata &= 0xFF;
+                                               writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
+                                               if (!(TOPNEN) && writedata > 0xFFF)
+//                                                     writedata = 0xFFF;
+                                                       writedata &= 0xFFF;
+                                               writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/
+//notneeded--writedata &= 0xFFFF;
+/*if (blit_start_log)
+       WriteLog("writedata: %08X\n", writedata);//*/
+/*
+Hover Strike ADDDSEL blit:
+
+Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208]
+ CMD -> src:  dst: DSTEN  misc:  a1ctl: UPDA1  mode:  ity: ADDDSEL z-op:  op: LFU_CLEAR ctrl:
+  A1 step values: -320 (X), 1 (Y)
+  A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD
+*/
+                                               writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
+
+                                               if (!TOPBEN)
+                                               {
+//This is correct now, but slow...
+                                                       int16_t s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000),
+                                                               d = dstdata & 0xFF;
+                                                       int16_t sum = s + d;
+
+                                                       if (sum < 0)
+                                                               writedata = 0x00;
+                                                       else if (sum > 0xFF)
+                                                               writedata = 0xFF;
+                                                       else
+                                                               writedata = (uint32_t)sum;
+                                               }
+
+//This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!!
+                                               writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
+
+                                               if (!TOPNEN && writedata > 0xFFF)
+                                               {
+                                                       writedata &= 0xFFF;
+                                               }
+
+                                               writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
                                        }
                                        else
                                        {
@@ -846,129 +698,156 @@ void blitter_generic(uint32 cmd)
                                                if (LFU_AN)  writedata |= srcdata  & ~dstdata;
                                                if (LFU_A)       writedata |= srcdata  & dstdata;
                                        }
-                                       if(GOURD) 
-                                               writedata = ((gd_c[colour_index])<<8)|(gd_i[colour_index]>>16);
 
-                                       if(SRCSHADE) 
+//Although, this looks like it's OK... (even if it is shitty!)
+//According to JTRM, this is part of the four things the blitter does with the write data (the other
+//three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL
+//(see above blit example)...
+                                       if (GOURD)
+                                               writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
+
+                                       if (SRCSHADE)
                                        {
                                                int intensity = srcdata & 0xFF;
                                                int ia = gd_ia >> 16;
-                                               if(ia & 0x80)
+                                               if (ia & 0x80)
                                                        ia = 0xFFFFFF00 | ia;
                                                intensity += ia;
-                                               if(intensity < 0)
+                                               if (intensity < 0)
                                                        intensity = 0;
-                                               if(intensity > 0xFF)
+                                               if (intensity > 0xFF)
                                                        intensity = 0xFF;
                                                writedata = (srcdata & 0xFF00) | intensity;
                                        }
                                }
                                else
                                {
-                                       writedata=dstdata;
-                                       srczdata=dstzdata;
+                                       writedata = dstdata;
+                                       srczdata = dstzdata;
                                }
+
+//Tried 2nd below for Hover Strike: No dice.
                                if (/*a1_phrase_mode || */BKGWREN || !inhibit)
+//                             if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit)
                                {
+/*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
+{
+       uint32_t offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
+// (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 1))
+       if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
+               WriteLog("32bpp pixel write: A1 Phrase mode --> ");
+}//*/
                                        // write to the destination
                                        WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
-                                       if (DSTWRZ) WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
+                                       if (DSTWRZ)
+                                               WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
                                }
                        }
-                       else
+                       else    // if (DSTA2)                                                   // Data movement: A1 -> A2
                        {
                                // load src data and Z
                                if (SRCEN)
                                {
                                        srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
                                        if (SRCENZ)
-                                       {
                                                srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
-                                       }
-                                       else 
-                                       if (cmd & 0x001c020)
-                                       {
+                                       else if (cmd & 0x0001C020)      // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
                                                srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
-                                       }
                                }
                                else
                                {
                                        srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
-                                       if (cmd & 0x001c020)
-                                       {
+                                       if (cmd & 0x001C020)    // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
                                                srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
-                                       }
                                }
 
-                               // load dst data and Z 
+                               // load dst data and Z
                                if (DSTEN)
                                {
                                        dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
                                        if (DSTENZ)
-                                       {
                                                dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
-                                       }
                                        else
-                                       {
                                                dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
-                                       }
                                }
                                else
                                {
                                        dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
-               
                                        if (DSTENZ)
-                                       {
                                                dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
-                                       }
                                }
 
-                               if(GOURZ) 
-                                       srczdata=z_i[colour_index]>>16;
+                               if (GOURZ)
+                                       srczdata = z_i[colour_index] >> 16;
 
                                // apply z comparator
-                               if (Z_OP_INF) if (srczdata < dstzdata)  inhibit = 1;
-                               if (Z_OP_EQU) if (srczdata == dstzdata) inhibit = 1;
-                               if (Z_OP_SUP) if (srczdata > dstzdata)  inhibit = 1;
-                               
+                               if (Z_OP_INF && srczdata < dstzdata)    inhibit = 1;
+                               if (Z_OP_EQU && srczdata == dstzdata)   inhibit = 1;
+                               if (Z_OP_SUP && srczdata > dstzdata)    inhibit = 1;
+
                                // apply data comparator
-                               if (DCOMPEN|BCOMPEN)
+//NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
+                               if (DCOMPEN | BCOMPEN)
                                {
                                        if (!CMPDST)
                                        {
                                                // compare source pixel with pattern pixel
-                                               if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
-                                                       inhibit=1;
+// AvP: Numbers are correct, but sprites are not!
+//This doesn't seem to be a problem... But could still be wrong...
+/*                                             if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
+//                                             if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
+                                                       inhibit = 1;//*/
+// This is probably not 100% correct... It works in the 1bpp case
+// (in A1 <- A2 mode, that is...)
+// AvP: This is causing blocks to be written instead of bit patterns...
+// Works now...
+// NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
+/*                                             uint32_t A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
+                                               if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
+                                                       inhibit = (srcdata == 0 ? 1: 0);
+                                               else
+                                                       WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
+// What it boils down to is this:
+                                               if (srcdata == 0)
+                                                       inhibit = 1;//*/
                                        }
                                        else
                                        {
                                                // compare destination pixel with pattern pixel
                                                if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
-                                                       inhibit=1;
+//                                             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)
+                               {
+                                       inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
+                                               && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
                                }
-                               
+
                                // compute the write data and store
                                if (!inhibit)
-                               {                       
+                               {
                                        if (PATDSEL)
                                        {
                                                // use pattern data for write data
-                                               writedata= READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
+                                               writedata = READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
                                        }
-                                       else 
-                                       if (INTADD)
+                                       else if (ADDDSEL)
                                        {
                                                // intensity addition
-                                               writedata = (srcdata & 0xff) + (dstdata & 0xff);
-                                               if (!(TOPBEN) && writedata > 0xff)
-                                                       writedata = 0xff;
-                                               writedata |= (srcdata & 0xf00) + (dstdata & 0xf00);
-                                               if (!(TOPNEN) && writedata > 0xfff)
-                                                       writedata = 0xfff;
-                                               writedata |= (srcdata & 0xf000) + (dstdata & 0xf000);
+                                               writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
+                                               if (!(TOPBEN) && writedata > 0xFF)
+                                                       writedata = 0xFF;
+                                               writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
+                                               if (!(TOPNEN) && writedata > 0xFFF)
+                                                       writedata = 0xFFF;
+                                               writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
                                        }
                                        else
                                        {
@@ -981,543 +860,5374 @@ void blitter_generic(uint32 cmd)
                                                if (LFU_A)
                                                        writedata |= srcdata & dstdata;
                                        }
-                                       if(GOURD) 
-                                               writedata = ((gd_c[colour_index])<<8)|(gd_i[colour_index]>>16);
 
-                                       if(SRCSHADE) 
+                                       if (GOURD)
+                                               writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
+
+                                       if (SRCSHADE)
                                        {
                                                int intensity = srcdata & 0xFF;
                                                int ia = gd_ia >> 16;
-                                               if(ia & 0x80)
+                                               if (ia & 0x80)
                                                        ia = 0xFFFFFF00 | ia;
                                                intensity += ia;
-                                               if(intensity < 0)
+                                               if (intensity < 0)
                                                        intensity = 0;
-                                               if(intensity > 0xFF)
+                                               if (intensity > 0xFF)
                                                        intensity = 0xFF;
                                                writedata = (srcdata & 0xFF00) | intensity;
                                        }
                                }
                                else
                                {
-                                       writedata=dstdata;
-                                       srczdata=dstzdata;
+                                       writedata = dstdata;
+                                       srczdata = dstzdata;
                                }
 
                                if (/*a2_phrase_mode || */BKGWREN || !inhibit)
                                {
+/*if (logGo)
+{
+       uint32_t offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
+// (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 1))
+       WriteLog("[%08X:%04X] ", offset, writedata);
+}//*/
                                        // write to the destination
                                        WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
+
                                        if (DSTWRZ)
                                                WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
                                }
                        }
-                       // update x and y
-                       a1_x += a1_xadd;
-                       a1_y += a1_yadd;
-                       a2_x = (a2_x + a2_xadd) & a2_mask_x;
-                       a2_y = (a2_y + a2_yadd) & a2_mask_y;
+
+                       // Update x and y (inner loop)
+//Now it does! But crappy, crappy, crappy! !!! FIX !!! [DONE]
+//This is less than ideal, but it works...
+                       if (!BCOMPEN)
+                       {//*/
+                               a1_x += a1_xadd, a1_y += a1_yadd;
+                               a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
+                       }
+                       else
+                       {
+                               a1_y += a1_yadd, a2_y = (a2_y + a2_yadd) & a2_mask_y;
+                               if (!DSTA2)
+                               {
+                                       a1_x += a1_xadd;
+                                       if (bitPos % bppSrc == 0)
+                                               a2_x = (a2_x + a2_xadd) & a2_mask_x;
+                               }
+                               else
+                               {
+                                       a2_x = (a2_x + a2_xadd) & a2_mask_x;
+                                       if (bitPos % bppSrc == 0)
+                                               a1_x += a1_xadd;
+                               }
+                       }//*/
 
                        if (GOURZ)
-                               z_i[colour_index]+=zadd;
+                               z_i[colour_index] += zadd;
 
-                       if ((GOURD)||(SRCSHADE))
+                       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_t)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_t)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 (GOURD || SRCSHADE || GOURZ)
                        {
-                               if(a1_phrase_mode)
-                                       colour_index=(colour_index+1)&0x3;
+                               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;
                        }
                }
 
-               a1_x+=a1_step_x;
-               a1_y+=a1_step_y;
-               a2_x+=a2_step_x;
-               a2_y+=a2_step_y;
+/*
+Here's the problem... The phrase mode code!
+Blit! (00100000 -> 00148000) count: 327 x 267, A1/2_FLAGS: 00004420/00004420 [cmd: 41802E01]
+ CMD -> src: SRCEN  dst:  misc:  a1ctl: UPDA1 UPDA2 mode: DSTA2 GOURZ ity:  z-op:  op: LFU_REPLACE ctrl: SRCSHADE
+  A1 step values: -327 (X), 1 (Y)
+  A2 step values: -327 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
+  A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
+        A1 x/y: 28/58, A2 x/y: 28/58 Pattern: 00EA7BEA77EA77EA SRCDATA: 7BFF7BFF7BFF7BFF
+
+Below fixes it, but then borks:
+; 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
+
+Lesse, with pre-add we'd have:
+
+     oooooooooooo
+00001111222233334444555566667777
+  ^  ^starts here...
+  |             ^ends here.
+  |rolls back to here. Hmm.
 
-/*             if (a2_phrase_mode)
-               {
-                       a1_x+=(64/a1_psize)*a1_xadd;
-               }       
-               if (a2_phrase_mode)
+*/
+//NOTE: The way to fix the CD BIOS is to uncomment below and comment the stuff after
+//      the phrase mode mucking around. But it fucks up everything else...
+//#define SCREWY_CD_DEPENDENT
+#ifdef SCREWY_CD_DEPENDENT
+               a1_x += a1_step_x;
+               a1_y += a1_step_y;
+               a2_x += a2_step_x;
+               a2_y += a2_step_y;//*/
+#endif
+
+               //New: Phrase mode taken into account! :-p
+/*             if (a1_phrase_mode)                     // v1
                {
-                       for (int nb=0;nb<(64/a2_psize)+1;nb++)
-                               a2_x = (a2_x + a2_xadd) & a2_mask_x;
-               }
-*/     }
-       
-       // write values back to registers 
-       WREG(A1_PIXEL,  (a1_y & 0xffff0000) | ((a1_x >> 16) & 0xffff));
-       WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xffff));
-       WREG(A2_PIXEL,  (a2_y & 0xffff0000) | ((a2_x >> 16) & 0xffff));
-}
-//////////////////////////////////////////////////////////////////////////////
-//
-//////////////////////////////////////////////////////////////////////////////
-//
-//
-//
-//////////////////////////////////////////////////////////////////////////////
-void blitter_blit(uint32 cmd)
-{
-       colour_index = 0;
-       src=(cmd&0x07);
-       dst=(cmd>>3)&0x07;
-       misc=(cmd>>6)&0x03;
-       a1ctl=(cmd>>8)&0x7;
-       mode=(cmd>>11)&0x07;
-       ity=(cmd>>14)&0x0f;
-       zop=(cmd>>18)&0x07;
-       op=(cmd>>21)&0x0f;
-       ctrl=(cmd>>25)&0x3f;
-
-       a1_addr=REG(A1_BASE);
-       a2_addr=REG(A2_BASE);
+                       // Bump the pointer to the next phrase boundary
+                       // Even though it works, this is crappy... Clean it up!
+                       uint32_t size = 64 / a1_psize;
 
-       a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
-       a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
-       
-       xadd_a1_control=(REG(A1_FLAGS)>>16)&0x03;
-       xadd_a2_control=(REG(A2_FLAGS)>>16)&0x03;
-       a1_pitch = (REG(A1_FLAGS) & 3) ^ ((REG(A1_FLAGS) & 2) >> 1);
-       a2_pitch = (REG(A2_FLAGS) & 3) ^ ((REG(A2_FLAGS) & 2) >> 1);
-
-       n_pixels=(REG(PIXLINECOUNTER)&0xffff);
-       n_lines=((REG(PIXLINECOUNTER)>>16)&0xffff);
-
-       a1_x=(REG(A1_PIXEL)<<16)|(REG(A1_FPIXEL)&0xffff);
-       a1_y=(REG(A1_PIXEL)&0xffff0000)|(REG(A1_FPIXEL)>>16);
-       a1_width=blitter_scanline_width[((REG(A1_FLAGS)&0x00007E00)>>9)];
-
-       a2_x=(REG(A2_PIXEL)&0x0000ffff)<<16;
-       a2_y=(REG(A2_PIXEL)&0xffff0000);
-       a2_width=blitter_scanline_width[((REG(A2_FLAGS)&0x00007E00)>>9)];
-       a2_mask_x=0xffff|((REG(A2_MASK)&0x0000ffff)<<16);
-       a2_mask_y=((REG(A2_MASK)&0xffff0000)|0xffff);
-       
-       // 
-       if (!((REG(A2_FLAGS))&0x8000))
-       {
-               a2_mask_x=0xffffffff; // must be 16.16
-               a2_mask_y=0xffffffff; // must be 16.16
-       }
-       
-       a1_phrase_mode=0;
+                       // Crappy kludge... ('aligning' source to destination)
+                       if (a2_phrase_mode && DSTA2)
+                       {
+                               uint32_t extra = (a2_start >> 16) % size;
+                               a1_x += extra << 16;
+                       }
 
-       // determine a1_yadd
-       if (YADD1_A1)
-               a1_yadd = 1 << 16;
-       else
-               a1_yadd = 0;
+                       uint32_t newx = (a1_x >> 16) / size;
+                       uint32_t newxrem = (a1_x >> 16) % size;
+                       a1_x &= 0x0000FFFF;
+                       a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
+               }//*/
+               if (a1_phrase_mode)                     // v2
+               {
+                       // Bump the pointer to the next phrase boundary
+                       // Even though it works, this is crappy... Clean it up!
+                       uint32_t size = 64 / a1_psize;
 
-       if (YSIGNSUB_A1)
-               a1_yadd=-a1_yadd;
+                       // Crappy kludge... ('aligning' source to destination)
+                       if (a2_phrase_mode && DSTA2)
+                       {
+                               uint32_t extra = (a2_start >> 16) % size;
+                               a1_x += extra << 16;
+                       }
 
-       // determine a1_xadd
+                       uint32_t pixelSize = (size - 1) << 16;
+                       a1_x = (a1_x + pixelSize) & ~pixelSize;
+               }
+
+/*             if (a2_phrase_mode)                     // v1
+               {
+                       // Bump the pointer to the next phrase boundary
+                       // Even though it works, this is crappy... Clean it up!
+                       uint32_t size = 64 / a2_psize;
+
+                       // Crappy kludge... ('aligning' source to destination)
+                       // Prolly should do this for A1 channel as well... [DONE]
+                       if (a1_phrase_mode && !DSTA2)
+                       {
+                               uint32_t extra = (a1_start >> 16) % size;
+                               a2_x += extra << 16;
+                       }
+
+                       uint32_t newx = (a2_x >> 16) / size;
+                       uint32_t newxrem = (a2_x >> 16) % size;
+                       a2_x &= 0x0000FFFF;
+                       a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
+               }//*/
+               if (a2_phrase_mode)                     // v1
+               {
+                       // Bump the pointer to the next phrase boundary
+                       // Even though it works, this is crappy... Clean it up!
+                       uint32_t size = 64 / a2_psize;
+
+                       // Crappy kludge... ('aligning' source to destination)
+                       // Prolly should do this for A1 channel as well... [DONE]
+                       if (a1_phrase_mode && !DSTA2)
+                       {
+                               uint32_t extra = (a1_start >> 16) % size;
+                               a2_x += extra << 16;
+                       }
+
+                       uint32_t pixelSize = (size - 1) << 16;
+                       a2_x = (a2_x + pixelSize) & ~pixelSize;
+               }
+
+               //Not entirely: This still mucks things up... !!! FIX !!!
+               //Should this go before or after the phrase mode mucking around?
+#ifndef SCREWY_CD_DEPENDENT
+               a1_x += a1_step_x;
+               a1_y += a1_step_y;
+               a2_x += a2_step_x;
+               a2_y += a2_step_y;//*/
+#endif
+       }
+
+       // write values back to registers
+       WREG(A1_PIXEL,  (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
+       WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
+       WREG(A2_PIXEL,  (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
+specialLog = false;
+}
+
+void blitter_blit(uint32_t cmd)
+{
+//Apparently this is doing *something*, just not sure exactly what...
+/*if (cmd == 0x41802E01)
+{
+       WriteLog("BLIT: Found our blit. Was: %08X ", cmd);
+       cmd = 0x01800E01;
+       WriteLog("Is: %08X\n", cmd);
+}//*/
+
+       uint32_t pitchValue[4] = { 0, 1, 3, 2 };
+       colour_index = 0;
+       src = cmd & 0x07;
+       dst = (cmd >> 3) & 0x07;
+       misc = (cmd >> 6) & 0x03;
+       a1ctl = (cmd >> 8) & 0x7;
+       mode = (cmd >> 11) & 0x07;
+       ity = (cmd >> 14) & 0x0F;
+       zop = (cmd >> 18) & 0x07;
+       op = (cmd >> 21) & 0x0F;
+       ctrl = (cmd >> 25) & 0x3F;
+
+       // 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;
+
+       xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
+       xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
+
+       a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
+       a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
+
+       n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
+       n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
+
+       a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
+       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;
+//Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
+//     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_t m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
+       a1_width = ((0x04 | m) << e) >> 2;//*/
+
+       a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
+       a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
+//According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
+//But it seems to fuck up T2K! !!! FIX !!!
+//     a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
+//Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
+//     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;
+       a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
+
+       // Check for "use mask" flag
+       if (!(REG(A2_FLAGS) & 0x8000))
+       {
+               a2_mask_x = 0xFFFFFFFF; // must be 16.16
+               a2_mask_y = 0xFFFFFFFF; // must be 16.16
+       }
+
+       a1_phrase_mode = 0;
+
+       // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
+       a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
+
+       if (YSIGNSUB_A1)
+               a1_yadd = -a1_yadd;
+
+       // determine a1_xadd
        switch (xadd_a1_control)
        {
        case XADDPHR:
-                               // add phrase offset to X and truncate
-                               a1_xadd = 1 << 16;
-
-                               a1_phrase_mode=1;
-                               break;
+// This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
+               // add phrase offset to X and truncate
+               a1_xadd = 1 << 16;
+               a1_phrase_mode = 1;
+               break;
        case XADDPIX:
-                               // add pixelsize (1) to X
-                               a1_xadd = 1 << 16;
-                               break;
-       case XADD0:     
-                               // add zero (for those nice vertical lines)
-                               a1_xadd = 0;
-                               break;
+               // add pixelsize (1) to X
+               a1_xadd = 1 << 16;
+               break;
+       case XADD0:
+               // add zero (for those nice vertical lines)
+               a1_xadd = 0;
+               break;
        case XADDINC:
-                               // add the contents of the increment register
-                               a1_xadd = (REG(A1_INC) << 16)            | (REG(A1_FINC) & 0xffff);
-                               a1_yadd = (REG(A1_INC) & 0xffff0000) | (REG(A1_FINC) >> 16);
-                               break;
+               // add the contents of the increment register
+               a1_xadd = (REG(A1_INC) << 16)            | (REG(A1_FINC) & 0x0000FFFF);
+               a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
+               break;
        }
-       if (XSIGNSUB_A1)
-               a1_xadd=-a1_xadd;
 
-       // determine a2_yadd
-       if ((YADD1_A2)||(YADD1_A1))
-               a2_yadd = 1 << 16;
-       else
-               a2_yadd = 0;
+
+//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_t 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;
 
        if (YSIGNSUB_A2)
-               a2_yadd=-a2_yadd;
+               a2_yadd = -a2_yadd;
 
-       a2_phrase_mode=0;
+       a2_phrase_mode = 0;
 
        // determine a2_xadd
        switch (xadd_a2_control)
        {
        case XADDPHR:
-                               // add phrase offset to X and truncate
-                               a2_xadd = 1 << 16;
-
-                               a2_phrase_mode=1;
-                               break;
+               // add phrase offset to X and truncate
+               a2_xadd = 1 << 16;
+               a2_phrase_mode = 1;
+               break;
        case XADDPIX:
-                               // add pixelsize (1) to X
-                               a2_xadd = 1 << 16;
-                               break;
-       case XADD0:     
-                               // add zero (for those nice vertical lines)
-                               a2_xadd = 0;
-                               break;
+               // add pixelsize (1) to X
+               a2_xadd = 1 << 16;
+               break;
+       case XADD0:
+               // add zero (for those nice vertical lines)
+               a2_xadd = 0;
+               break;
+//This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
        case XADDINC:
-                               // add the contents of the increment register
-                               // since there is no register for a2 we just add 1
-                               a2_xadd = 1 << 16;
-                               break;
+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;
+               a2_xadd = -a2_xadd;
 
-       // modify outer loop steps based on command 
-       a1_step_x=0;
-       a1_step_y=0;
-       a2_step_x=0;
-       a2_step_y=0;
+       // Modify outer loop steps based on blitter command
 
-       if (cmd & 0x00000100)
-       {
-               a1_step_x = (REG(A1_FSTEP)&0xffff);
-               a1_step_y = (REG(A1_FSTEP)>>16);
-       }
-       if (cmd & 0x00000200)
-       {
-               a1_step_x += ((REG(A1_STEP)&0x0000ffff)<<16);
-               a1_step_y += ((REG(A1_STEP)&0xffff0000));
-       }
-       if (cmd & 0x00000400)
-       {
-               a2_step_x = (REG(A2_STEP)&0x0000ffff)<<16;
-               a2_step_y = (REG(A2_STEP)&0xffff0000);
-       }
+       a1_step_x = 0;
+       a1_step_y = 0;
+       a2_step_x = 0;
+       a2_step_y = 0;
+
+       if (UPDA1F)
+               a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
+               a1_step_y = (REG(A1_FSTEP) >> 16);
+
+       if (UPDA1)
+               a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
+               a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
+
+       if (UPDA2)
+               a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
+               a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
 
+       outer_loop = n_lines;
 
-       outer_loop=n_lines;
+       // Clipping...
 
+       if (CLIPA1)
+               a1_clip_x = REG(A1_CLIP) & 0x7FFF,
+               a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
 
-       a2_psize=1 << ((REG(A2_FLAGS) >> 3) & 7);
-       a1_psize=1 << ((REG(A1_FLAGS) >> 3) & 7);
+// This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX]
+// Err, this is pixel size... (and it's OK)
+       a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
+       a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
 
-       // zbuffering
+       // Z-buffering
        if (GOURZ)
        {
-               zadd=jaguar_long_read(0xF02274);
+               zadd = REG(ZINC);
 
-               for(int v=0;v<4;v++) 
-                       z_i[v]=(int32)jaguar_long_read(0xF0228C+(v<<2));
+               for(int v=0; v<4; v++)
+                       z_i[v] = REG(PHRASEZ0 + v*4);
        }
-       if ((GOURD)||(GOURZ)||(SRCSHADE))
+
+       // Gouraud shading
+       if (GOURD || GOURZ || SRCSHADE)
        {
-               // gouraud shading
-               gouraud_add = jaguar_long_read(0xF02270);
-
-               
-               gd_c[0] = jaguar_byte_read(0xF02268);
-               gd_i[0] = jaguar_byte_read(0xF02269);
-               gd_i[0]<<=16;
-               gd_i[0]|=jaguar_word_read(0xF02240);
-
-               gd_c[1] = jaguar_byte_read(0xF0226A);
-               gd_i[1] = jaguar_byte_read(0xF0226b);
-               gd_i[1]<<=16;
-               gd_i[1]|=jaguar_word_read(0xF02242);
-
-               gd_c[2] = jaguar_byte_read(0xF0226C);
-               gd_i[2] = jaguar_byte_read(0xF0226d);
-               gd_i[2]<<=16;
-               gd_i[2]|=jaguar_word_read(0xF02244);
-
-               gd_c[3] = jaguar_byte_read(0xF0226E);
-               gd_i[3] = jaguar_byte_read(0xF0226f);
-               gd_i[3]<<=16; 
-               gd_i[3]|=jaguar_word_read(0xF02246);
-
-               gd_ia = gouraud_add & 0xFFFFFF;
-               if(gd_ia & 0x800000)
+               gd_c[0] = blitter_ram[PATTERNDATA + 6];
+               gd_i[0] = ((uint32_t)blitter_ram[PATTERNDATA + 7] << 16)
+                       | ((uint32_t)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
+
+               gd_c[1] = blitter_ram[PATTERNDATA + 4];
+               gd_i[1] = ((uint32_t)blitter_ram[PATTERNDATA + 5] << 16)
+                       | ((uint32_t)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
+
+               gd_c[2] = blitter_ram[PATTERNDATA + 2];
+               gd_i[2] = ((uint32_t)blitter_ram[PATTERNDATA + 3] << 16)
+                       | ((uint32_t)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
+
+               gd_c[3] = blitter_ram[PATTERNDATA + 0];
+               gd_i[3] = ((uint32_t)blitter_ram[PATTERNDATA + 1] << 16)
+                       | ((uint32_t)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
+
+               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;
        }
 
-       // fix for zoop! and syndicate
-       if ((jaguar_mainRom_crc32==0x501be17c)||
-               (jaguar_mainRom_crc32==0x70895c51)||
-               (jaguar_mainRom_crc32==0x0f1f1497)||
-               (jaguar_mainRom_crc32==0xfc8f0dcd)
-          )
-       {
-               if (a1_step_x<0)
-                       a1_step_x=(-n_pixels)*65536;
-
-               if (a2_step_x<0)
-                       a2_step_x=(-n_pixels)*65536;;
-       }
-       else
-       // fix for wolfenstein 3d
-       if (jaguar_mainRom_crc32==0x3966698f)
+       // Bit comparitor fixing...
+/*     if (BCOMPEN)
        {
-               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)
+               // Determine the data flow direction...
+               if (!DSTA2)
+                       a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07));
+               else
+                       ;//add this later
+       }//*/
+/*     if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!!
        {
-/*
-               if ((n_lines!=1)&&((n_pixels==288)||(n_pixels==384)))
-               {
-                       fprintf(log_get(),"Blit!\n");
-                       fprintf(log_get(),"  cmd      = 0x%.8x\n",cmd);
-                       fprintf(log_get(),"  a1_base  = %08X\n", a1_addr);
-                       fprintf(log_get(),"  a1_pitch = %d\n", a1_pitch);
-                       fprintf(log_get(),"  a1_psize = %d\n", a1_psize);
-                       fprintf(log_get(),"  a1_width = %d\n", a1_width);
-                       fprintf(log_get(),"  a1_xadd  = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
-                       fprintf(log_get(),"  a1_yadd  = %f\n", (float)a1_yadd / 65536.0);
-                       fprintf(log_get(),"  a1_xstep = %f\n", (float)a1_step_x / 65536.0);
-                       fprintf(log_get(),"  a1_ystep = %f\n", (float)a1_step_y / 65536.0);
-                       fprintf(log_get(),"  a1_x     = %f\n", (float)a1_x / 65536.0);
-                       fprintf(log_get(),"  a1_y     = %f\n", (float)a1_y / 65536.0);
-                       fprintf(log_get(),"  a1_zoffs = %i\n",a1_zoffs);
-
-                       fprintf(log_get(),"  a2_base  = %08X\n", a2_addr);
-                       fprintf(log_get(),"  a2_pitch = %d\n", a2_pitch);
-                       fprintf(log_get(),"  a2_psize = %d\n", a2_psize);
-                       fprintf(log_get(),"  a2_width = %d\n", a2_width);
-                       fprintf(log_get(),"  a2_xadd  = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
-                       fprintf(log_get(),"  a2_yadd  = %f\n", (float)a2_yadd / 65536.0);
-                       fprintf(log_get(),"  a2_xstep = %f\n", (float)a2_step_x / 65536.0);
-                       fprintf(log_get(),"  a2_ystep = %f\n", (float)a2_step_y / 65536.0);
-                       fprintf(log_get(),"  a2_x     = %f\n", (float)a2_x / 65536.0);
-                       fprintf(log_get(),"  a2_y     = %f\n", (float)a2_y / 65536.0);
-                       fprintf(log_get(),"  a2_mask_x= 0x%.4x\n",a2_mask_x);
-                       fprintf(log_get(),"  a2_mask_y= 0x%.4x\n",a2_mask_y);
-                       fprintf(log_get(),"  a2_zoffs = %i\n",a2_zoffs);
-
-                       fprintf(log_get(),"  count    = %d x %d\n", n_pixels, n_lines);
-
-                       fprintf(log_get(),"  command  = %08X\n", cmd);
-                       fprintf(log_get(),"  dsten    = %i\n",DSTEN);
-                       fprintf(log_get(),"  srcen    = %i\n",SRCEN);
-                       fprintf(log_get(),"  patdsel  = %i\n",PATDSEL);
-                       fprintf(log_get(),"  color    = 0x%.8x\n",REG(PATTERNDATA));
-                       fprintf(log_get(),"  dcompen  = %i\n",DCOMPEN);
-                       fprintf(log_get(),"  bcompen  = %i\n",BCOMPEN);
-                       fprintf(log_get(),"  cmpdst   = %i\n",CMPDST);
-                       fprintf(log_get(),"  GOURZ    = %i\n",GOURZ);
-                       fprintf(log_get(),"  GOURD    = %i\n",GOURD);
-                       fprintf(log_get(),"  SRCSHADE = %i\n",SRCSHADE);
-                       fprintf(log_get(),"  DSTDATA  = 0x%.8x%.8x\n",REG(DSTDATA),REG(DSTDATA+4));
-               }       
-*/     }
+               // Determine the data flow direction...
+               if (!DSTA2)
+                       a2_x <<= 3;
+       }//*/
 
 #ifdef LOG_BLITS
-//     if (start_logging)
+       if (start_logging)
        {
-               fprintf(log_get(),"Blit!\n");
-               fprintf(log_get(),"  cmd      = 0x%.8x\n",cmd);
-               fprintf(log_get(),"  a1_base  = %08X\n", a1_addr);
-               fprintf(log_get(),"  a1_pitch = %d\n", a1_pitch);
-               fprintf(log_get(),"  a1_psize = %d\n", a1_psize);
-               fprintf(log_get(),"  a1_width = %d\n", a1_width);
-               fprintf(log_get(),"  a1_xadd  = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
-               fprintf(log_get(),"  a1_yadd  = %f\n", (float)a1_yadd / 65536.0);
-               fprintf(log_get(),"  a1_xstep = %f\n", (float)a1_step_x / 65536.0);
-               fprintf(log_get(),"  a1_ystep = %f\n", (float)a1_step_y / 65536.0);
-               fprintf(log_get(),"  a1_x     = %f\n", (float)a1_x / 65536.0);
-               fprintf(log_get(),"  a1_y     = %f\n", (float)a1_y / 65536.0);
-               fprintf(log_get(),"  a1_zoffs = %i\n",a1_zoffs);
-
-               fprintf(log_get(),"  a2_base  = %08X\n", a2_addr);
-               fprintf(log_get(),"  a2_pitch = %d\n", a2_pitch);
-               fprintf(log_get(),"  a2_psize = %d\n", a2_psize);
-               fprintf(log_get(),"  a2_width = %d\n", a2_width);
-               fprintf(log_get(),"  a2_xadd  = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
-               fprintf(log_get(),"  a2_yadd  = %f\n", (float)a2_yadd / 65536.0);
-               fprintf(log_get(),"  a2_xstep = %f\n", (float)a2_step_x / 65536.0);
-               fprintf(log_get(),"  a2_ystep = %f\n", (float)a2_step_y / 65536.0);
-               fprintf(log_get(),"  a2_x     = %f\n", (float)a2_x / 65536.0);
-               fprintf(log_get(),"  a2_y     = %f\n", (float)a2_y / 65536.0);
-               fprintf(log_get(),"  a2_mask_x= 0x%.4x\n",a2_mask_x);
-               fprintf(log_get(),"  a2_mask_y= 0x%.4x\n",a2_mask_y);
-               fprintf(log_get(),"  a2_zoffs = %i\n",a2_zoffs);
-
-               fprintf(log_get(),"  count    = %d x %d\n", n_pixels, n_lines);
-
-               fprintf(log_get(),"  command  = %08X\n", cmd);
-               fprintf(log_get(),"  dsten    = %i\n",DSTEN);
-               fprintf(log_get(),"  srcen    = %i\n",SRCEN);
-               fprintf(log_get(),"  patdsel  = %i\n",PATDSEL);
-               fprintf(log_get(),"  color    = 0x%.8x\n",REG(PATTERNDATA));
-               fprintf(log_get(),"  dcompen  = %i\n",DCOMPEN);
-               fprintf(log_get(),"  bcompen  = %i\n",BCOMPEN);
-               fprintf(log_get(),"  cmpdst   = %i\n",CMPDST);
-               fprintf(log_get(),"  GOURZ   = %i\n",GOURZ);
-               fprintf(log_get(),"  GOURD   = %i\n",GOURD);
-               fprintf(log_get(),"  SRCSHADE= %i\n",SRCSHADE);
-       }       
+               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);
+       }
 #endif
 
+//NOTE: Pitch is ignored!
 
-       blitter_working=1;
-#ifndef USE_GENERIC_BLITTER
-       if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
-#endif
-               blitter_generic(cmd);
-       blitter_working=0;
+//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 op_start_log;
+if (blit_start_log)
+{
+       const char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
+       const char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
+       const 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_t /*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_t a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
+       uint32_t p1 = a1f & 0x07, p2 = a2f & 0x07,
+               d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
+               zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
+               w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
+               ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
+       uint32_t iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
+       uint32_t iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
+       WriteLog("Blit! (%08X %s %08X) count: %d x %d, A1/2_FLAGS: %08X/%08X [cmd: %08X]\n", a1_addr, (mode&0x01 ? "->" : "<-"), a2_addr, n_pixels, n_lines, a1f, a2f, cmd);
+//     WriteLog(" CMD -> src: %d, dst: %d, misc: %d, a1ctl: %d, mode: %d, ity: %1X, z-op: %d, op: %1X, ctrl: %02X\n", src, dst, misc, a1ctl, mode, ity, zop, op, ctrl);
+
+       WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
+       WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
+       WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
+       WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
+       WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "GOURZ" : ""));
+       WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : ""));
+       WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
+       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 Pattern: %08X%08X SRCDATA: %08X%08X\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16, REG(PATTERNDATA), REG(PATTERNDATA + 4), REG(SRCDATA), REG(SRCDATA + 4));
+//     blit_start_log = 0;
+//     op_start_log = 1;
 }
 
-uint32 blitter_reg_read(uint32 offset)
+       blitter_working = 1;
+//#ifndef USE_GENERIC_BLITTER
+//     if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
+//#endif
+       blitter_generic(cmd);
+
+/*if (blit_start_log)
 {
-       uint32 data = blitter_ram[offset];
-       data <<= 8;
-       data |= blitter_ram[offset+1];
-       data <<= 8;
-       data |= blitter_ram[offset+2];
-       data <<= 8;
-       data |= blitter_ram[offset+3];
-       return data;
+       if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
+       {
+               WriteLog("\nBytes at 004D58:\n");
+               for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
+                       WriteLog("%02X ", JaguarReadByte(i));
+               WriteLog("\nBytes at F03000:\n");
+               for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
+                       WriteLog("%02X ", JaguarReadByte(i));
+               WriteLog("\n\n");
+       }
+}//*/
+
+       blitter_working = 0;
 }
+#endif                                                                                 // of the #if 0 near the top...
+/*******************************************************************************
+********************** STUFF CUT ABOVE THIS LINE! ******************************
+*******************************************************************************/
+
 
-void blitter_reg_write(uint32 offset, uint32 data)
+void BlitterInit(void)
 {
-       blitter_ram[offset+0] = (data>>24) & 0xFF;
-       blitter_ram[offset+1] = (data>>16) & 0xFF;
-       blitter_ram[offset+2] = (data>>8) & 0xFF;
-       blitter_ram[offset+3] = data & 0xFF;
+       BlitterReset();
 }
 
-uint32 blitter_long_read(uint32 offset)
+
+void BlitterReset(void)
 {
-       return (blitter_word_read(offset) << 16) | blitter_word_read(offset+2);
+       memset(blitter_ram, 0x00, 0xA0);
 }
 
-void blitter_long_write(uint32 offset, uint32 data)
+
+void BlitterDone(void)
 {
-       blitter_word_write(offset, data >> 16);
-       blitter_word_write(offset+2, data & 0xFFFF);
+       WriteLog("BLIT: Done.\n");
 }
 
-void blitter_init(void)
+
+uint8_t BlitterReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
 {
-       if (!blitter_cache_init)
-       {
-               for (int i=0;i<256;i++)
-               {
-                       blitter_cache[i]=(struct s_blitter_cache *)malloc(sizeof(struct s_blitter_cache));
-                       blitter_cache[i]->next=null;
-                       blitter_cache[i]->prev=null;
-               }
-               blitter_cache_init=1;
-       }
-#ifndef USE_GENERIC_BLITTER
-       #include "include/blit_i.h"
-#endif
+       offset &= 0xFF;
 
-       blitter_reset();
-#ifdef GEN_CODE
-       blitters_code_fp=fopen("include/blit_c.h","awrt");
-       blitters_code_init_fp=fopen("include/blit_i.h","awrt");
-#endif
+       // status register
+//This isn't cycle accurate--how to fix? !!! FIX !!!
+//Probably have to do some multi-threaded implementation or at least a reentrant safe implementation...
+//Real hardware returns $00000805, just like the JTRM says.
+       if (offset == (0x38 + 0))
+               return 0x00;
+       if (offset == (0x38 + 1))
+               return 0x00;
+       if (offset == (0x38 + 2))
+               return 0x08;
+       if (offset == (0x38 + 3))
+               return 0x05;    // always idle/never stopped (collision detection ignored!)
+
+// CHECK HERE ONCE THIS FIX HAS BEEN TESTED: [X]
+//Fix for AvP:
+       if (offset >= 0x04 && offset <= 0x07)
+//This is it. I wonder if it just ignores the lower three bits?
+//No, this is a documented Jaguar I bug. It also bites the read at $F02230 as well...
+               return blitter_ram[offset + 0x08];              // A1_PIXEL ($F0220C) read at $F02204
+
+       if (offset >= 0x2C && offset <= 0x2F)
+               return blitter_ram[offset + 0x04];              // A2_PIXEL ($F02230) read at $F0222C
+
+       return blitter_ram[offset];
 }
 
-void blitter_reset(void)
+
+//Crappy!
+uint16_t BlitterReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
 {
-       memset(blitter_ram, 0x00, 0xA0);
+       return ((uint16_t)BlitterReadByte(offset, who) << 8) | (uint16_t)BlitterReadByte(offset+1, who);
 }
 
-void blitter_done(void)
+
+//Crappy!
+uint32_t BlitterReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
 {
-       blitter_list();
-#ifdef GEN_CODE
-       fclose(blitters_code_fp);
-       fclose(blitters_code_init_fp);
-#endif
+       return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
 }
 
-void blitter_byte_write(uint32 offset, uint8 data)
+
+void BlitterWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
 {
+/*if (offset & 0xFF == 0x7B)
+       WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
        offset &= 0xFF;
+/*if ((offset >= PATTERNDATA) && (offset < PATTERNDATA + 8))
+{
+       printf("--> %s wrote %02X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - PATTERNDATA);
+       fflush(stdout);
+}//*/
 
+       // 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))
        {
                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 + 7] = data; break;
+               case 0x7E: blitter_ram[SRCDATA + 6] = data; break;
+               case 0x7F: blitter_ram[SRCDATA + 7] = 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 + 5] = data; break;
+               case 0x82: blitter_ram[SRCDATA + 4] = data; break;
+               case 0x83: blitter_ram[SRCDATA + 5] = 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 0x88: break;
-               case 0x89: blitter_ram[0x6F] = data; break;
-               case 0x9A: blitter_ram[0x46] = data; break;
-               case 0x9B: blitter_ram[0x47] = data; break;
+               case 0x85: blitter_ram[PATTERNDATA + 3] = data; break;
+               case 0x86: blitter_ram[SRCDATA + 2] = data; break;
+               case 0x87: blitter_ram[SRCDATA + 3] = data; break;
 
+               case 0x88: break;
+               case 0x89: blitter_ram[PATTERNDATA + 1] = data; break;
+               case 0x8A: blitter_ram[SRCDATA + 0] = data; break;
+               case 0x8B: blitter_ram[SRCDATA + 1] = data; break;
+
+
+               // Z registers 0-3
+               case 0x8C: blitter_ram[SRCZINT + 6] = data; break;
+               case 0x8D: blitter_ram[SRCZINT + 7] = data; break;
+               case 0x8E: blitter_ram[SRCZFRAC + 6] = data; break;
+               case 0x8F: blitter_ram[SRCZFRAC + 7] = data; break;
+
+               case 0x90: blitter_ram[SRCZINT + 4] = data; break;
+               case 0x91: blitter_ram[SRCZINT + 5] = data; break;
+               case 0x92: blitter_ram[SRCZFRAC + 4] = data; break;
+               case 0x93: blitter_ram[SRCZFRAC + 5] = data; break;
+
+               case 0x94: blitter_ram[SRCZINT + 2] = data; break;
+               case 0x95: blitter_ram[SRCZINT + 3] = data; break;
+               case 0x96: blitter_ram[SRCZFRAC + 2] = data; break;
+               case 0x97: blitter_ram[SRCZFRAC + 3] = data; break;
+
+               case 0x98: blitter_ram[SRCZINT + 0] = data; break;
+               case 0x99: blitter_ram[SRCZINT + 1] = data; break;
+               case 0x9A: blitter_ram[SRCZFRAC + 0] = data; break;
+               case 0x9B: blitter_ram[SRCZFRAC + 1] = data; break;
                }
        }
 
-       blitter_ram[offset] = data;
+       // It looks weird, but this is how the 64 bit registers are actually handled...!
+
+       else if ((offset >= SRCDATA + 0) && (offset <= SRCDATA + 3)
+               || (offset >= DSTDATA + 0) && (offset <= DSTDATA + 3)
+               || (offset >= DSTZ + 0) && (offset <= DSTZ + 3)
+               || (offset >= SRCZINT + 0) && (offset <= SRCZINT + 3)
+               || (offset >= SRCZFRAC + 0) && (offset <= SRCZFRAC + 3)
+               || (offset >= PATTERNDATA + 0) && (offset <= PATTERNDATA + 3))
+       {
+               blitter_ram[offset + 4] = data;
+       }
+       else if ((offset >= SRCDATA + 4) && (offset <= SRCDATA + 7)
+               || (offset >= DSTDATA + 4) && (offset <= DSTDATA + 7)
+               || (offset >= DSTZ + 4) && (offset <= DSTZ + 7)
+               || (offset >= SRCZINT + 4) && (offset <= SRCZINT + 7)
+               || (offset >= SRCZFRAC + 4) && (offset <= SRCZFRAC + 7)
+               || (offset >= PATTERNDATA + 4) && (offset <= PATTERNDATA + 7))
+       {
+               blitter_ram[offset - 4] = data;
+       }
+       else
+               blitter_ram[offset] = data;
 }
 
-void blitter_word_write(uint32 offset, uint16 data)
+
+void BlitterWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
 {
-       blitter_byte_write(offset+0, (data>>8) & 0xFF);
-       blitter_byte_write(offset+1, data & 0xFF);
+/*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
+{
+       printf("----> %s wrote %04X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
+       fflush(stdout);
+}*/
+//#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, 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;
+}//*/
+#ifndef USE_BOTH_BLITTERS
+#ifdef USE_ORIGINAL_BLITTER
+               blitter_blit(GET32(blitter_ram, 0x38));
+#endif
+#ifdef USE_MIDSUMMER_BLITTER
+               BlitterMidsummer(GET32(blitter_ram, 0x38));
+#endif
+#ifdef USE_MIDSUMMER_BLITTER_MKII
+               BlitterMidsummer2();
+#endif
+#else
        {
-               uint32 cmd = blitter_ram[0x38];
-               cmd <<= 8;
-               cmd |= blitter_ram[0x39];
-               cmd <<= 8;
-               cmd |= blitter_ram[0x3A];
-               cmd <<= 8;
-               cmd |= blitter_ram[0x3B];
-
-               blitter_blit(cmd);
+               if (vjs.useFastBlitter)
+                       blitter_blit(GET32(blitter_ram, 0x38));
+               else
+                       BlitterMidsummer2();
        }
+#endif
 }
+//F02278,9,A,B
 
-uint8 blitter_byte_read(uint32 offset)
+
+void BlitterWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
 {
-       offset &= 0xFF;
+/*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
+{
+       printf("------> %s wrote %08X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
+       fflush(stdout);
+}//*/
+//#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 + 0, data >> 16, who);
+       BlitterWriteWord(offset + 2, data & 0xFFFF, who);
+}
 
-       // status register
-       if (offset == (0x38+3))
-               return 0x01;    // always idle
 
-       return blitter_ram[offset];
+void LogBlit(void)
+{
+       const 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_t cmd = GET32(blitter_ram, 0x38);
+       uint32_t m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
+       uint32_t a1_width = ((0x04 | m) << e) >> 2;
+       m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
+       uint32_t a2_width = ((0x04 | m) << e) >> 2;
+
+       WriteLog("Blit!\n");
+       WriteLog("  COMMAND  = %08X\n", cmd);
+       WriteLog("  a1_base  = %08X\n", REG(A1_BASE));
+       WriteLog("  a1_flags = %08X (%c %c %c %c%c . %c%c%c%c%c%c %c%c%c %c%c%c . %c%c)\n", REG(A1_FLAGS),
+               (REG(A1_FLAGS) & 0x100000 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x080000 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x040000 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x020000 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x010000 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x004000 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x002000 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x001000 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000800 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000400 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000200 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000100 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000080 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000040 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000020 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000010 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000008 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000002 ? '1' : '0'),
+               (REG(A1_FLAGS) & 0x000001 ? '1' : '0'));
+       WriteLog("             pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
+               REG(A1_FLAGS) & 0x00003, (REG(A1_FLAGS) & 0x00038) >> 3,
+               (REG(A1_FLAGS) & 0x001C0) >> 6,  a1_width, (REG(A1_FLAGS) & 0x30000) >> 16);
+       WriteLog("  a1_clip  = %u, %u (%08X)\n", GET16(blitter_ram, A1_CLIP + 2), GET16(blitter_ram, A1_CLIP + 0), GET32(blitter_ram, A1_CLIP));
+       WriteLog("  a1_pixel = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A1_PIXEL + 2), (int16_t)GET16(blitter_ram, A1_PIXEL + 0), GET32(blitter_ram, A1_PIXEL));
+       WriteLog("  a1_step  = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A1_STEP + 2), (int16_t)GET16(blitter_ram, A1_STEP + 0), GET32(blitter_ram, A1_STEP));
+       WriteLog("  a1_fstep = %u, %u (%08X)\n", GET16(blitter_ram, A1_FSTEP + 2), GET16(blitter_ram, A1_FSTEP + 0), GET32(blitter_ram, A1_FSTEP));
+       WriteLog("  a1_fpixel= %u, %u (%08X)\n", GET16(blitter_ram, A1_FPIXEL + 2), GET16(blitter_ram, A1_FPIXEL + 0), GET32(blitter_ram, A1_FPIXEL));
+       WriteLog("  a1_inc   = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A1_INC + 2), (int16_t)GET16(blitter_ram, A1_INC + 0), GET32(blitter_ram, A1_INC));
+       WriteLog("  a1_finc  = %u, %u (%08X)\n", GET16(blitter_ram, A1_FINC + 2), GET16(blitter_ram, A1_FINC + 0), GET32(blitter_ram, A1_FINC));
+
+       WriteLog("  a2_base  = %08X\n", REG(A2_BASE));
+       WriteLog("  a2_flags = %08X (%c %c %c %c%c %c %c%c%c%c%c%c %c%c%c %c%c%c . %c%c)\n", REG(A2_FLAGS),
+               (REG(A2_FLAGS) & 0x100000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x080000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x040000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x020000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x010000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x008000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x004000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x002000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x001000 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000800 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000400 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000200 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000100 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000080 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000040 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000020 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000010 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000008 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000002 ? '1' : '0'),
+               (REG(A2_FLAGS) & 0x000001 ? '1' : '0'));
+       WriteLog("             pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
+               REG(A2_FLAGS) & 0x00003, (REG(A2_FLAGS) & 0x00038) >> 3,
+               (REG(A2_FLAGS) & 0x001C0) >> 6,  a2_width, (REG(A2_FLAGS) & 0x30000) >> 16);
+       WriteLog("  a2_mask  = %u, %u (%08X)\n", GET16(blitter_ram, A2_MASK + 2), GET16(blitter_ram, A2_MASK + 0), GET32(blitter_ram, A2_MASK));
+       WriteLog("  a2_pixel = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A2_PIXEL + 2), (int16_t)GET16(blitter_ram, A2_PIXEL + 0), GET32(blitter_ram, A2_PIXEL));
+       WriteLog("  a2_step  = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A2_STEP + 2), (int16_t)GET16(blitter_ram, A2_STEP + 0), GET32(blitter_ram, A2_STEP));
+
+       WriteLog("  count    = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
+
+       WriteLog("  SRCEN    = %s\n", (SRCEN ? "1" : "0"));
+       WriteLog("  SRCENZ   = %s\n", (SRCENZ ? "1" : "0"));
+       WriteLog("  SRCENX   = %s\n", (SRCENX ? "1" : "0"));
+       WriteLog("  DSTEN    = %s\n", (DSTEN ? "1" : "0"));
+       WriteLog("  DSTENZ   = %s\n", (DSTENZ ? "1" : "0"));
+       WriteLog("  DSTWRZ   = %s\n", (DSTWRZ ? "1" : "0"));
+       WriteLog("  CLIPA1   = %s\n", (CLIPA1 ? "1" : "0"));
+       WriteLog("  UPDA1F   = %s\n", (UPDA1F ? "1" : "0"));
+       WriteLog("  UPDA1    = %s\n", (UPDA1 ? "1" : "0"));
+       WriteLog("  UPDA2    = %s\n", (UPDA2 ? "1" : "0"));
+       WriteLog("  DSTA2    = %s\n", (DSTA2 ? "1" : "0"));
+       WriteLog("  ZOP      = %s %s %s\n", (Z_OP_INF ? "<" : ""), (Z_OP_EQU ? "=" : ""), (Z_OP_SUP ? ">" : ""));
+       WriteLog("+-LFUFUNC  = %s\n", opStr[(cmd >> 21) & 0x0F]);
+       WriteLog("| PATDSEL  = %s (PD=%08X%08X)\n", (PATDSEL ? "1" : "0"), REG(PATTERNDATA), REG(PATTERNDATA + 4));
+       WriteLog("+-ADDDSEL  = %s\n", (ADDDSEL ? "1" : "0"));
+       WriteLog("  CMPDST   = %s\n", (CMPDST ? "1" : "0"));
+       WriteLog("  BCOMPEN  = %s\n", (BCOMPEN ? "1" : "0"));
+       WriteLog("  DCOMPEN  = %s\n", (DCOMPEN ? "1" : "0"));
+       WriteLog("  TOPBEN   = %s\n", (TOPBEN ? "1" : "0"));
+       WriteLog("  TOPNEN   = %s\n", (TOPNEN ? "1" : "0"));
+       WriteLog("  BKGWREN  = %s\n", (BKGWREN ? "1" : "0"));
+       WriteLog("  GOURD    = %s (II=%08X, SD=%08X%08X)\n", (GOURD ? "1" : "0"), REG(INTENSITYINC), REG(SRCDATA), REG(SRCDATA + 4));
+       WriteLog("  GOURZ    = %s (ZI=%08X, ZD=%08X%08X, SZ1=%08X%08X, SZ2=%08X%08X)\n", (GOURZ ? "1" : "0"), REG(ZINC), REG(DSTZ), REG(DSTZ + 4),
+               REG(SRCZINT), REG(SRCZINT + 4), REG(SRCZFRAC), REG(SRCZFRAC + 4));
+       WriteLog("  SRCSHADE = %s\n", (SRCSHADE ? "1" : "0"));
 }
 
-uint16 blitter_word_read(uint32 offset)
+
+#ifdef USE_MIDSUMMER_BLITTER
+//
+// Here's an attempt to write a blitter that conforms to the Midsummer specs--since
+// it's supposedly backwards compatible, it should work well...
+//
+//#define LOG_BLITTER_MEMORY_ACCESSES
+
+#define DATINIT (false)
+#define TXTEXT  (false)
+#define POLYGON (false)
+
+void BlitterMidsummer(uint32_t cmd)
 {
-       return (blitter_byte_read(offset) << 8) | blitter_byte_read(offset+1);
-}
+#ifdef LOG_BLITS
+       LogBlit();
+#endif
+uint32_t outer_loop, inner_loop, a1_addr, a2_addr;
+int32_t a1_x, a1_y, a2_x, a2_y, a1_width, a2_width;
+uint8_t a1_phrase_mode, a2_phrase_mode;
+
+       a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
+       a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
+       a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
+       a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
+       uint32_t m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
+       a1_width = ((0x04 | m) << e) >> 2;//*/
+       a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
+       a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
+       m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
+       a2_width = ((0x04 | m) << e) >> 2;//*/
+
+       a1_phrase_mode = a2_phrase_mode = 0;
+
+       if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
+               a1_phrase_mode = 1;
+
+       if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
+               a2_phrase_mode = 1;
+
+#define INNER0  (inner_loop == 0)
+#define OUTER0  (outer_loop == 0)
+
+// $01800005 has SRCENX, may have to investigate further...
+// $00011008 has GOURD & DSTEN.
+// $41802F41 has SRCSHADE, CLIPA1
+/*bool logBlit = false;
+if (cmd != 0x00010200 && cmd != 0x01800001 && cmd != 0x01800005
+       && cmd != 0x00011008 && cmd !=0x41802F41)
+{
+       logBlit = true;
+       LogBlit();
+}//*/
+
+       uint64_t srcData = GET64(blitter_ram, SRCDATA), srcXtraData,
+               dstData = GET64(blitter_ram, DSTDATA), writeData;
+       uint32_t srcAddr, dstAddr;
+       uint8_t bitCount, a1PixelSize, a2PixelSize;
+
+       // JTRM says phrase mode only works for 8BPP or higher, so let's try this...
+       uint32_t phraseOffset[8] = { 8, 8, 8, 8, 4, 2, 0, 0 };
+       uint8_t pixelShift[8] = { 3, 2, 1, 0, 1, 2, 0, 0 };
+
+       a1PixelSize = (blitter_ram[A1_FLAGS + 3] >> 3) & 0x07;
+       a2PixelSize = (blitter_ram[A2_FLAGS + 3] >> 3) & 0x07;
+
+       outer_loop = GET16(blitter_ram, PIXLINECOUNTER + 0);
+
+       if (outer_loop == 0)
+               outer_loop = 0x10000;
+
+       // We just list the states here and jump from state to state in order to
+       // keep things somewhat clear. Optimization/cleanups later.
+
+//idle:                                                        // Blitter is idle, and will not perform any bus activity
+/*
+idle         Blitter is off the bus, and no activity takes place.
+if GO    if DATINIT goto init_if
+         else       goto inner
+*/
+       if (DATINIT)
+               goto init_if;
+       else
+               goto inner;
+
+/*
+inner        Inner loop is active, read and write cycles are performed
+*/
+inner:                                                 // Run inner loop state machine (asserts step from its idle state)
+       inner_loop = GET16(blitter_ram, PIXLINECOUNTER + 2);
+
+       if (inner_loop == 0)
+               inner_loop = 0x10000;
+
+/*
+------------------------------
+idle:                        Inactive, blitter is idle or passing round outer loop
+idle       Another state in the outer loop is active. No bus transfers are performed.
+if STEP
+    if SRCENX goto sreadx
+    else if TXTEXT goto txtread
+    else if SRCEN goto sread
+    else if DSTEN goto dread
+    else if DSTENZ goto dzread
+    else goto dwrite
+*/
+    if (SRCENX)
+               goto sreadx;
+    else if (TXTEXT)
+               goto txtread;
+    else if (SRCEN)
+               goto sread;
+    else if (DSTEN)
+               goto dread;
+    else if (DSTENZ)
+               goto dzread;
+    else
+               goto dwrite;
+
+/*
+sreadx     Extra source data read at the start of an inner loop pass.
+if STEP
+    if SRCENZ goto szreadx
+    else if TXTEXT goto txtread
+    else if SRCEN goto sread
+    else if DSTEN goto dread
+    else if DSTENZ goto dzread
+    else goto dwrite
+*/
+sreadx:                                                        // Extra source data read
+       if (SRCENZ)
+               goto szreadx;
+       else if (TXTEXT)
+               goto txtread;
+       else if (SRCEN)
+               goto sread;
+       else if (DSTEN)
+               goto dread;
+       else if (DSTENZ)
+               goto dzread;
+       else
+               goto dwrite;
+
+/*
+szreadx    Extra source Z read as the start of an inner loop pass.
+if STEP
+    if TXTEXT goto txtread
+    else goto sread
+*/
+szreadx:                                               // Extra source Z read
+       if (TXTEXT)
+               goto txtread;
+       else
+               goto sread;
+
+/*
+txtread    Read texture data from external memory. This state is only used for external texture.
+           TEXTEXT is the condition TEXTMODE=1.
+if STEP
+    if SRCEN goto sread
+    else if DSTEN goto dread
+    else if DSTENZ goto dzread
+    else goto dwrite
+*/
+txtread:                                               // Read external texture data
+       if (SRCEN)
+               goto sread;
+       else if (DSTEN)
+               goto dread;
+       else if (DSTENZ)
+               goto dzread;
+       else
+               goto dwrite;
+
+/*
+sread      Source data read.
+if STEP
+    if SRCENZ goto szread
+    else if DSTEN goto dread
+    else if DSTENZ goto dzread
+    else goto dwrite
+*/
+sread:                                                 // Source data read
+//The JTRM doesn't really specify the internal structure of the source data read, but I would
+//imagine that if it's in phrase mode that it starts by reading the phrase that the window is
+//pointing at. Likewise, the pixel (if in BPP 1, 2 & 4, chopped) otherwise. It probably still
+//transfers an entire phrase even in pixel mode.
+//Odd thought: Does it expand, e.g., 1 BPP pixels into 32 BPP internally? Hmm...
+//No.
+/*
+       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;
+       xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
+       xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
+       a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
+       a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
+       n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
+       n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
+       a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
+       a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
+       a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
+       a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
+       a1_phrase_mode = 0;
+       a2_phrase_mode = 0;
+       a1_width = ((0x04 | m) << e) >> 2;
+       a2_width = ((0x04 | m) << e) >> 2;
+
+       // write values back to registers
+       WREG(A1_PIXEL,  (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
+       WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
+       WREG(A2_PIXEL,  (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
+*/
+       // Calculate the address to be read...
+
+//Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
+//Also, need to fix various differing BPP modes here, since offset won't be correct except
+//for 8BPP. !!! FIX !!!
+       srcAddr = (DSTA2 ? a1_addr : a2_addr);
+
+/*     if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
+       {
+               srcAddr += (((DSTA2 ? a1_x : a2_x) >> 16)
+                       + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width)));
+       }
+       else*/
+       {
+//             uint32_t pixAddr = ((DSTA2 ? a1_x : a2_x) >> 16)
+//                     + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
+               int32_t pixAddr = (int16_t)((DSTA2 ? a1_x : a2_x) >> 16)
+                       + ((int16_t)((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
+
+               if ((DSTA2 ? a1PixelSize : a2PixelSize) < 3)
+                       pixAddr >>= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
+               else if ((DSTA2 ? a1PixelSize : a2PixelSize) > 3)
+                       pixAddr <<= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
+
+               srcAddr += pixAddr;
+       }
+
+       // And read it!
+
+       if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
+       {
+               srcData = ((uint64_t)JaguarReadLong(srcAddr, BLITTER) << 32)
+                       | (uint64_t)JaguarReadLong(srcAddr + 4, BLITTER);
+       }
+       else
+       {
+//1,2,&4BPP are wrong here... !!! FIX !!!
+               if ((DSTA2 ? a1PixelSize : a2PixelSize) == 0)           // 1 BPP
+                       srcData = JaguarReadByte(srcAddr, BLITTER);
+               if ((DSTA2 ? a1PixelSize : a2PixelSize) == 1)           // 2 BPP
+                       srcData = JaguarReadByte(srcAddr, BLITTER);
+               if ((DSTA2 ? a1PixelSize : a2PixelSize) == 2)           // 4 BPP
+                       srcData = JaguarReadByte(srcAddr, BLITTER);
+               if ((DSTA2 ? a1PixelSize : a2PixelSize) == 3)           // 8 BPP
+                       srcData = JaguarReadByte(srcAddr, BLITTER);
+               if ((DSTA2 ? a1PixelSize : a2PixelSize) == 4)           // 16 BPP
+                       srcData = JaguarReadWord(srcAddr, BLITTER);
+               if ((DSTA2 ? a1PixelSize : a2PixelSize) == 5)           // 32 BPP
+                       srcData = JaguarReadLong(srcAddr, BLITTER);
+       }
+
+#ifdef LOG_BLITTER_MEMORY_ACCESSES
+if (logBlit)
+       WriteLog("BLITTER: srcAddr=%08X,   srcData=%08X %08X\n", srcAddr, (uint32_t)(srcData >> 32), (uint32_t)(srcData & 0xFFFFFFFF));
+#endif
+
+       if (SRCENZ)
+               goto szread;
+       else if (DSTEN)
+               goto dread;
+       else if (DSTENZ)
+               goto dzread;
+       else
+               goto dwrite;
+
+szread:                                                        // Source Z read
+/*
+szread     Source Z read.
+if STEP
+    if DSTEN goto dread
+    else if DSTENZ goto dzread
+    else goto dwrite
+*/
+       if (DSTEN)
+               goto dread;
+       else if (DSTENZ)
+               goto dzread;
+       else
+               goto dwrite;
+
+dread:                                                 // Destination data read
+/*
+dread      Destination data read.
+if STEP
+    if DSTENZ goto dzread
+    else goto dwrite
+*/
+       // Calculate the destination address to be read...
+
+//Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
+//Also, need to fix various differing BPP modes here, since offset won't be correct except
+//for 8BPP. !!! FIX !!!
+       dstAddr = (DSTA2 ? a2_addr : a1_addr);
+
+       {
+//     uint32_t pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
+//             + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
+       int32_t pixAddr = (int16_t)((DSTA2 ? a2_x : a1_x) >> 16)
+               + ((int16_t)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
+
+       if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
+               pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
+       else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
+               pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
+
+       dstAddr += pixAddr;
+       }
+
+       // And read it!
+
+       if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
+       {
+               dstData = ((uint64_t)JaguarReadLong(srcAddr, BLITTER) << 32)
+                       | (uint64_t)JaguarReadLong(srcAddr + 4, BLITTER);
+       }
+       else
+       {
+//1,2,&4BPP are wrong here... !!! FIX !!!
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0)           // 1 BPP
+                       dstData = JaguarReadByte(dstAddr, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1)           // 2 BPP
+                       dstData = JaguarReadByte(dstAddr, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2)           // 4 BPP
+                       dstData = JaguarReadByte(dstAddr, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3)           // 8 BPP
+                       dstData = JaguarReadByte(dstAddr, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4)           // 16 BPP
+                       dstData = JaguarReadWord(dstAddr, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5)           // 32 BPP
+                       dstData = JaguarReadLong(dstAddr, BLITTER);
+       }
+
+#ifdef LOG_BLITTER_MEMORY_ACCESSES
+if (logBlit)
+       WriteLog("BLITTER (dread): dstAddr=%08X,   dstData=%08X %08X\n", dstAddr, (uint32_t)(dstData >> 32), (uint32_t)(dstData & 0xFFFFFFFF));
+#endif
+
+       if (DSTENZ)
+               goto dzread;
+       else
+               goto dwrite;
+
+dzread:                                                        // Destination Z read
+/*
+dzread     Destination Z read.
+if STEP goto dwrite
+*/
+       goto dwrite;
+
+dwrite:                                                        // Destination data write
+/*
+dwrite     Destination write. Every pass round the inner loop must go through this state..
+if STEP
+    if DSTWRZ goto dzwrite
+    else if INNER0 goto idle
+    else if TXTEXT goto txtread
+    else if SRCEN goto sread
+    else if DSTEN goto dread
+    else if DSTENZ goto dzread
+    else goto dwrite
+*/
+/*
+Blit!
+  a1_base  = 00100000
+  a1_pitch = 0
+  a1_psize = 16
+  a1_width = 320
+  a1_xadd  = 1.000000 (phrase=0)
+  a1_yadd  = 0.000000
+  a1_x     = 159.000000
+  a1_y     = 1.000000
+  a1_zoffs = 0
+  a2_base  = 000095D0
+  a2_pitch = 0
+  a2_psize = 16
+  a2_width = 256
+  a2_xadd  = 1.000000 (phrase=1)
+  a2_yadd  = 0.000000
+  a2_x     = 2.000000
+  a2_y     = 0.000000
+  a2_mask_x= 0xFFFFFFFF
+  a2_mask_y= 0xFFFFFFFF
+  a2_zoffs = 0
+  count    = 2 x 1
+  COMMAND  = 00011008
+  SRCEN    = 0
+  DSTEN    = 1
+  UPDA1F   = 0
+  UPDA1    = 0
+  UPDA2    = 0
+  DSTA2    = 0
+--LFUFUNC  = LFU_CLEAR
+| PATDSEL  = 1 (PD=77C7 7700 7700 7700)
+--ADDDSEL  = 0
+  GOURD    = 1 (II=00FC 1A00, SD=FF00 0000 0000 0000)
+*/
+
+//Still need to do CLIPA1 and SRCSHADE and GOURD and GOURZ...
+
+       // Check clipping...
+
+       if (CLIPA1)
+       {
+               uint16_t x = a1_x >> 16, y = a1_y >> 16;
+
+               if (x >= GET16(blitter_ram, A1_CLIP + 2) || y >= GET16(blitter_ram, A1_CLIP))
+                       goto inhibitWrite;
+       }
+
+       // Figure out what gets written...
+
+       if (PATDSEL)
+       {
+               writeData = GET64(blitter_ram, PATTERNDATA);
+//GOURD works properly only in 16BPP mode...
+//SRCDATA holds the intensity fractions...
+//Does GOURD get calc'ed here or somewhere else???
+//Temporary testing kludge...
+//if (GOURD)
+//   writeData >>= 48;
+//     writeData = 0xFF88;
+//OK, it's not writing an entire strip of pixels... Why?
+//bad incrementing, that's why!
+       }
+       else if (ADDDSEL)
+       {
+               // Apparently this only works with 16-bit pixels. Not sure if it works in phrase mode either.
+//Also, take TOPBEN & TOPNEN into account here as well...
+               writeData = srcData + dstData;
+       }
+       else    // LFUFUNC is the default...
+       {
+               writeData = 0;
+
+               if (LFU_NAN)
+                       writeData |= ~srcData & ~dstData;
+               if (LFU_NA)
+                       writeData |= ~srcData & dstData;
+               if (LFU_AN)
+                       writeData |= srcData & ~dstData;
+               if (LFU_A)
+                       writeData |= srcData & dstData;
+       }
+
+       // Calculate the address to be written...
+
+       dstAddr = (DSTA2 ? a2_addr : a1_addr);
+
+/*     if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
+       {
+//both of these calculate the wrong address because they don't take into account
+//pixel sizes...
+               dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
+                       + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
+       }
+       else*/
+       {
+/*             dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
+                       + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));*/
+//             uint32_t pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
+//                     + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
+               int32_t pixAddr = (int16_t)((DSTA2 ? a2_x : a1_x) >> 16)
+                       + ((int16_t)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
+
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
+                       pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
+               else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
+                       pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
+
+               dstAddr += pixAddr;
+       }
+
+       // And write it!
+
+       if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
+       {
+               JaguarWriteLong(dstAddr, writeData >> 32, BLITTER);
+               JaguarWriteLong(dstAddr + 4, writeData & 0xFFFFFFFF, BLITTER);
+       }
+       else
+       {
+//1,2,&4BPP are wrong here... !!! FIX !!!
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0)           // 1 BPP
+                       JaguarWriteByte(dstAddr, writeData, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1)           // 2 BPP
+                       JaguarWriteByte(dstAddr, writeData, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2)           // 4 BPP
+                       JaguarWriteByte(dstAddr, writeData, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3)           // 8 BPP
+                       JaguarWriteByte(dstAddr, writeData, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4)           // 16 BPP
+                       JaguarWriteWord(dstAddr, writeData, BLITTER);
+               if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5)           // 32 BPP
+                       JaguarWriteLong(dstAddr, writeData, BLITTER);
+       }
+
+#ifdef LOG_BLITTER_MEMORY_ACCESSES
+if (logBlit)
+       WriteLog("BLITTER: dstAddr=%08X, writeData=%08X %08X\n", dstAddr, (uint32_t)(writeData >> 32), (uint32_t)(writeData & 0xFFFFFFFF));
+#endif
+
+inhibitWrite://Should this go here? or on the other side of the X/Y incrementing?
+//Seems OK here... for now.
+
+// Do funky X/Y incrementation here as well... !!! FIX !!!
+
+       // Handle A1 channel stepping
+
+       if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
+               a1_x += phraseOffset[a1PixelSize] << 16;
+       else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 1)
+               a1_x += (blitter_ram[A1_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
+/*     else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 2)
+               a1_x += 0 << 16;                              */
+       else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 3)
+       {
+//Always add the FINC here??? That was the problem with the BIOS screen... So perhaps.
+               a1_x += GET16(blitter_ram, A1_FINC + 2);
+               a1_y += GET16(blitter_ram, A1_FINC + 0);
+
+               a1_x += GET16(blitter_ram, A1_INC + 2) << 16;
+               a1_y += GET16(blitter_ram, A1_INC + 0) << 16;
+       }
+
+       if ((blitter_ram[A1_FLAGS + 1] & 0x04) && (blitter_ram[A1_FLAGS + 1] & 0x03 != 3))
+               a1_y += (blitter_ram[A1_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
+
+       // Handle A2 channel stepping
+
+       if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
+               a2_x += phraseOffset[a2PixelSize] << 16;
+       else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 1)
+               a2_x += (blitter_ram[A2_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
+/*     else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 2)
+               a2_x += 0 << 16;                              */
+
+       if (blitter_ram[A2_FLAGS + 1] & 0x04)
+               a2_y += (blitter_ram[A2_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
+
+//Need to fix this so that it subtracts (saturating, of course) the correct number of pixels
+//in phrase mode... !!! FIX !!! [DONE]
+//Need to fix this so that it counts down the correct item. Does it count the
+//source or the destination phrase mode???
+//It shouldn't matter, because we *should* end up processing the same amount
+//the same number of pixels... Not sure though.
+       if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
+       {
+               if (inner_loop < phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize])
+                       inner_loop = 0;
+               else
+                       inner_loop -= phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize];
+       }
+       else
+               inner_loop--;
+
+
+       if (DSTWRZ)
+               goto dzwrite;
+       else if (INNER0)
+               goto indone;
+       else if (TXTEXT)
+               goto txtread;
+       else if (SRCEN)
+               goto sread;
+       else if (DSTEN)
+               goto dread;
+       else if (DSTENZ)
+               goto dzread;
+       else
+               goto dwrite;
+
+dzwrite:                                               // Destination Z write
+/*
+dzwrite    Destination Z write.
+if STEP
+    if INNER0 goto idle
+    else if TXTEXT goto txtread
+    else if SRCEN goto sread
+    else if DSTEN goto dread
+    else if DSTENZ goto dzread
+    else goto dwrite
+*/
+       if (INNER0)
+               goto indone;
+       else if (TXTEXT)
+               goto txtread;
+       else if (SRCEN)
+               goto sread;
+       else if (DSTEN)
+               goto dread;
+       else if (DSTENZ)
+               goto dzread;
+       else
+               goto dwrite;
+
+/*
+------------------------------
+if INDONE if OUTER0 goto idle
+else if UPDA1F        goto a1fupdate
+else if UPDA1         goto a1update
+else if GOURZ.POLYGON goto zfupdate
+else if UPDA2         goto a2update
+else if DATINIT       goto init_if
+else restart inner
+*/
+indone:
+       outer_loop--;
+
+
+       if (OUTER0)
+               goto blitter_done;
+       else if (UPDA1F)
+               goto a1fupdate;
+       else if (UPDA1)
+               goto a1update;
+//kill this, for now...
+//     else if (GOURZ.POLYGON)
+//             goto zfupdate;
+       else if (UPDA2)
+               goto a2update;
+       else if (DATINIT)
+               goto init_if;
+       else
+               goto inner;
+
+a1fupdate:                                             // Update A1 pointer fractions and more (see below)
+/*
+a1fupdate    A1 step fraction is added to A1 pointer fraction
+             POLYGON true: A1 step delta X and Y fraction parts are added to the A1
+                        step X and Y fraction parts (the value prior to this add is used for
+                        the step to pointer add).
+             POLYGON true: inner count step fraction is added to the inner count
+                        fraction part
+             POLYGON.GOURD true: the I fraction step is added to the computed
+                        intensity fraction parts +
+             POLYGON.GOURD true: the I fraction step delta is added to the I
+                        fraction step
+goto a1update
+*/
+/*
+#define A1_PIXEL               ((uint32_t)0x0C)        // Integer part of the pixel (Y.i and X.i)
+#define A1_STEP                        ((uint32_t)0x10)        // Integer part of the step
+#define A1_FSTEP               ((uint32_t)0x14)        // Fractional part of the step
+#define A1_FPIXEL              ((uint32_t)0x18)        // Fractional part of the pixel (Y.f and X.f)
+*/
+
+// This is all kinda murky. All we have are the Midsummer docs to give us any guidance,
+// and it's incomplete or filled with errors (like above). Aarrrgggghhhhh!
+
+//This isn't right. Is it? I don't think the fractional parts are signed...
+//     a1_x += (int32_t)((int16_t)GET16(blitter_ram, A1_FSTEP + 2));
+//     a1_y += (int32_t)((int16_t)GET16(blitter_ram, A1_FSTEP + 0));
+       a1_x += GET16(blitter_ram, A1_FSTEP + 2);
+       a1_y += GET16(blitter_ram, A1_FSTEP + 0);
+
+       goto a1update;
+
+a1update:                                              // Update A1 pointer integers
+/*
+a1update     A1 step is added to A1 pointer, with carry from the fractional add
+             POLYGON true: A1 step delta X and Y integer parts are added to the A1
+                        step X and Y integer parts, with carry from the corresponding
+                        fractional part add (again, the value prior to this add is used for
+                        the step to pointer add).
+             POLYGON true: inner count step is added to the inner count, with carry
+             POLYGON.GOURD true: the I step is added to the computed intensities,
+                        with carry +
+             POLYGON.GOURD true: the I step delta is added to the I step, with
+                        carry the texture X and Y step delta values are added to the X and Y
+                        step values.
+if GOURZ.POLYGON goto zfupdate
+else if UPDA2 goto a2update
+else if DATINIT goto init_if
+else restart inner
+*/
+       a1_x += (int32_t)(GET16(blitter_ram, A1_STEP + 2) << 16);
+       a1_y += (int32_t)(GET16(blitter_ram, A1_STEP + 0) << 16);
+
+
+//kill this, for now...
+//     if (GOURZ.POLYGON)
+       if (false)
+               goto zfupdate;
+       else if (UPDA2)
+               goto a2update;
+       else if (DATINIT)
+               goto init_if;
+       else
+               goto inner;
+
+zfupdate:                                              // Update computed Z step fractions
+/*
+zfupdate     the Z fraction step is added to the computed Z fraction parts +
+             the Z fraction step delta is added to the Z fraction step
+goto zupdate
+*/
+       goto zupdate;
+
+zupdate:                                               // Update computed Z step integers
+/*
+zupdate      the Z step is added to the computed Zs, with carry +
+             the Z step delta is added to the Z step, with carry
+if UPDA2 goto a2update
+else if DATINIT goto init_if
+else restart inner
+*/
+       if (UPDA2)
+               goto a2update;
+       else if (DATINIT)
+               goto init_if;
+       else
+               goto inner;
+
+a2update:                                              // Update A2 pointer
+/*
+a2update     A2 step is added to the A2 pointer
+if DATINIT goto init_if
+else restart inner
+*/
+       a2_x += (int32_t)(GET16(blitter_ram, A2_STEP + 2) << 16);
+       a2_y += (int32_t)(GET16(blitter_ram, A2_STEP + 0) << 16);
+
+
+       if (DATINIT)
+               goto init_if;
+       else
+               goto inner;
+
+init_if:                                               // Initialise intensity fractions and texture X
+/*
+init_if      Initialise the fractional part of the computed intensity fields, from
+             the increment and step registers. The texture X integer and fractional
+                        parts can also be initialised.
+goto     init_ii
+*/
+       goto init_ii;
+
+init_ii:                                               // Initialise intensity integers and texture Y
+/*
+init_ii      Initialise the integer part of the computed intensity, and texture Y
+             integer and fractional parts
+if GOURZ goto init_zf
+else     goto inner
+*/
+       if (GOURZ)
+               goto init_zf;
+       else
+           goto inner;
+
+init_zf:                                               // Initialise Z fractions
+/*
+init_zf      Initialise the fractional part of the computed Z fields.
+goto init_zi
+*/
+       goto init_zi;
+
+init_zi:                                               // Initialise Z integers
+/*
+init_zi      Initialise the integer part of the computed Z fields.
+goto inner
+*/
+       goto inner;
+
+
+/*
+The outer loop state machine fires off the inner loop, and controls the updating
+process between passes through the inner loop.
+
++ -- these functions are irrelevant if the DATINIT function is enabled, which it
+     will normally be.
+
+All these states will complete in one clock cycle, with the exception of the idle
+state, which means the blitter is quiescent; and the inner state, which takes as
+long as is required to complete one strip of pixels. It is therefore possible for
+the blitter to spend a maximum of nine clock cycles of inactivity between passes
+through the inner loop.
+*/
+
+blitter_done:
+       {}
+}
+#endif
+
+
+//
+// Here's attempt #2--taken from the Oberon chip specs!
+//
+
+#ifdef USE_MIDSUMMER_BLITTER_MKII
+
+void ADDRGEN(uint32_t &, uint32_t &, bool, bool,
+       uint16_t, uint16_t, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
+       uint16_t, uint16_t, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t);
+void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
+       uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
+       uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
+       uint32_t zinc, uint32_t zstep);
+void ADD16SAT(uint16_t &r, uint8_t &co, uint16_t a, uint16_t b, uint8_t cin, bool sat, bool eightbit, bool hicinh);
+void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y,
+       int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y,
+       int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst,
+       bool adda_yconst, bool addareg, bool suba_x, bool suba_y);
+void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y,
+       int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y);
+void DATAMUX(int16_t &data_x, int16_t &data_y, uint32_t gpu_din, int16_t addq_x, int16_t addq_y, bool addqsel);
+void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
+       uint16_t adda_x, uint16_t adda_y, uint16_t addb_x, uint16_t addb_y, uint8_t modx, bool suba_x, bool suba_y);
+void DATA(uint64_t &wdata, uint8_t &dcomp, uint8_t &zcomp, bool &nowrite,
+       bool big_pix, bool cmpdst, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, bool daddq_sel, uint8_t data_sel,
+       uint8_t dbinh, uint8_t dend, uint8_t dstart, uint64_t dstd, uint32_t iinc, uint8_t lfu_func, uint64_t &patd, bool patdadd,
+       bool phrase_mode, uint64_t srcd, bool srcdread, bool srczread, bool srcz2add, uint8_t zmode,
+       bool bcompen, bool bkgwren, bool dcompen, uint8_t icount, uint8_t pixsize,
+       uint64_t &srcz, uint64_t dstz, uint32_t zinc);
+void COMP_CTRL(uint8_t &dbinh, bool &nowrite,
+       bool bcompen, bool big_pix, bool bkgwren, uint8_t dcomp, bool dcompen, uint8_t icount,
+       uint8_t pixsize, bool phrase_mode, uint8_t srcd, uint8_t zcomp);
+#define VERBOSE_BLITTER_LOGGING
+
+void BlitterMidsummer2(void)
+{
+#ifdef LOG_BLITS
+       LogBlit();
+#endif
+       if (startConciseBlitLogging)
+               LogBlit();
+
+       // Here's what the specs say the state machine does. Note that this can probably be
+       // greatly simplified (also, it's different from what John has in his Oberon docs):
+//Will remove stuff that isn't in Jaguar I once fully described (stuff like texture won't
+//be described here at all)...
+
+       uint32_t cmd = GET32(blitter_ram, COMMAND);
+
+#if 0
+logBlit = false;
+if (
+       cmd != 0x00010200 &&    // PATDSEL
+       cmd != 0x01800001               // SRCEN LFUFUNC=C
+       && cmd != 0x01800005
+//Boot ROM ATARI letters:
+       && cmd != 0x00011008    // DSTEN GOURD PATDSEL
+//Boot ROM spinning cube:
+       && cmd != 0x41802F41    // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
+//T2K intro screen:
+       && cmd != 0x01800E01    // SRCEN UPDA1 UPDA2 DSTA2 LFUFUNC=C
+//T2K TEMPEST letters:
+       && cmd != 0x09800741    // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 LFUFUNC=C DCOMPEN
+//Static letters on Cybermorph intro screen:
+       && cmd != 0x09800609    // SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
+//Static pic on title screen:
+       && cmd != 0x01800601    // SRCEN UPDA1 UPDA2 LFUFUNC=C
+//Turning letters on Cybermorph intro screen:
+//     && cmd != 0x09800F41    // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
+       && cmd != 0x00113078    // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
+       && cmd != 0x09900F39    // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
+       && cmd != 0x09800209    // SRCEN DSTEN UPDA1 LFUFUNC=C DCOMPEN
+       && cmd != 0x00011200    // UPDA1 GOURD PATDSEL
+//Start of Hover Strike (clearing screen):
+       && cmd != 0x00010000    // PATDSEL
+//Hover Strike text:
+       && cmd != 0x1401060C    // SRCENX DSTEN UPDA1 UPDA2 PATDSEL BCOMPEN BKGWREN
+//Hover Strike 3D stuff
+       && cmd != 0x01902839    // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
+//Hover Strike darkening on intro to play (briefing) screen
+       && cmd != 0x00020208    // DSTEN UPDA1 ADDDSEL
+//Trevor McFur stuff:
+       && cmd != 0x05810601    // SRCEN UPDA1 UPDA2 PATDSEL BCOMPEN
+       && cmd != 0x01800201    // SRCEN UPDA1 LFUFUNC=C
+//T2K:
+       && cmd != 0x00011000    // GOURD PATDSEL
+       && cmd != 0x00011040    // CLIP_A1 GOURD PATDSEL
+//Checkered flag:
+       && cmd != 0x01800000    // LFUFUNC=C
+       && cmd != 0x01800401    //
+       && cmd != 0x01800040    //
+       && cmd != 0x00020008    //
+//     && cmd != 0x09800F41    // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
+       )
+       logBlit = true;//*/
+#else
+logBlit = true;
+#endif
+if (blit_start_log == 0)       // Wait for the signal...
+       logBlit = false;//*/
+//temp, for testing...
+/*if (cmd != 0x49820609)
+       logBlit = false;//*/
+
+/*
+Some T2K unique blits:
+logBlit = F, cmd = 00010200 *
+logBlit = F, cmd = 00011000
+logBlit = F, cmd = 00011040
+logBlit = F, cmd = 01800005 *
+logBlit = F, cmd = 09800741 *
+
+Hover Strike mission selection screen:
+Blit! (CMD = 01902839) // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
+
+Checkered Flag blits in the screw up zone:
+Blit! (CMD = 01800001) // SRCEN LFUFUNC=C
+Blit! (CMD = 01800000) // LFUFUNC=C
+Blit! (CMD = 00010000) // PATDSEL
+
+Wolfenstein 3D in the fuckup zone:
+Blit! (CMD = 01800000) // LFUFUNC=C
+*/
+
+//printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
+//fflush(stdout);
+//logBlit = true;
+
+/*
+Blit! (CMD = 00011040)
+Flags: CLIP_A1 GOURD PATDSEL
+  count = 18 x 1
+  a1_base = 00100000, a2_base = 0081F6A8
+  a1_x = 00A7, a1_y = 0014, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0001, a2_y = 0000
+  a1_step_x = FE80, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFF8, a2_step_y = 0001
+  a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
+  a1_win_x = 0180, a1_win_y = 0118, a2_mask_x = 0000, a2_mask_y = 0000
+  a2_mask=F a1add=+phr/+0 a2add=+phr/+0
+  a1_pixsize = 4, a2_pixsize = 4
+*/
+//Testing T2K...
+/*logBlit = false;
+if (cmd == 0x00011040
+       && (GET16(blitter_ram, A1_PIXEL + 2) == 0x00A7) && (GET16(blitter_ram, A1_PIXEL + 0) == 0x0014)
+       && (GET16(blitter_ram, A2_PIXEL + 2) == 0x0001) && (GET16(blitter_ram, A2_PIXEL + 0) == 0x0000)
+       && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 18))
+       logBlit = true;*/
+
+       // Line states passed in via the command register
+
+       bool srcen = (SRCEN), srcenx = (SRCENX), srcenz = (SRCENZ),
+               dsten = (DSTEN), dstenz = (DSTENZ), dstwrz = (DSTWRZ), clip_a1 = (CLIPA1),
+               upda1 = (UPDA1), upda1f = (UPDA1F), upda2 = (UPDA2), dsta2 = (DSTA2),
+               gourd = (GOURD), gourz = (GOURZ), topben = (TOPBEN), topnen = (TOPNEN),
+               patdsel = (PATDSEL), adddsel = (ADDDSEL), cmpdst = (CMPDST), bcompen = (BCOMPEN),
+               dcompen = (DCOMPEN), bkgwren = (BKGWREN), srcshade = (SRCSHADE);
+
+       uint8_t zmode = (cmd & 0x01C0000) >> 18, lfufunc = (cmd & 0x1E00000) >> 21;
+//Missing: BUSHI
+//Where to find various lines:
+// clip_a1  -> inner
+// gourd    -> dcontrol, inner, outer, state
+// gourz    -> dcontrol, inner, outer, state
+// cmpdst   -> blit, data, datacomp, state
+// bcompen  -> acontrol, inner, mcontrol, state
+// dcompen  -> inner, state
+// bkgwren  -> inner, state
+// srcshade -> dcontrol, inner, state
+// adddsel  -> dcontrol
+//NOTE: ADDDSEL takes precedence over PATDSEL, PATDSEL over LFU_FUNC
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       char zfs[512], lfus[512];
+       zfs[0] = lfus[0] = 0;
+       if (dstwrz || dstenz || gourz)
+               sprintf(zfs, " ZMODE=%X", zmode);
+       if (!(patdsel || adddsel))
+               sprintf(lfus, " LFUFUNC=%X", lfufunc);
+       WriteLog("\nBlit! (CMD = %08X)\nFlags:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", cmd,
+               (srcen ? " SRCEN" : ""), (srcenx ? " SRCENX" : ""), (srcenz ? " SRCENZ" : ""),
+               (dsten ? " DSTEN" : ""), (dstenz ? " DSTENZ" : ""), (dstwrz ? " DSTWRZ" : ""),
+               (clip_a1 ? " CLIP_A1" : ""), (upda1 ? " UPDA1" : ""), (upda1f ? " UPDA1F" : ""),
+               (upda2 ? " UPDA2" : ""), (dsta2 ? " DSTA2" : ""), (gourd ? " GOURD" : ""),
+               (gourz ? " GOURZ" : ""), (topben ? " TOPBEN" : ""), (topnen ? " TOPNEN" : ""),
+               (patdsel ? " PATDSEL" : ""), (adddsel ? " ADDDSEL" : ""), zfs, lfus, (cmpdst ? " CMPDST" : ""),
+               (bcompen ? " BCOMPEN" : ""), (dcompen ? " DCOMPEN" : ""), (bkgwren ? " BKGWREN" : ""),
+               (srcshade ? " SRCSHADE" : ""));
+       WriteLog("  count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
+}
+#endif
+
+       // Lines that don't exist in Jaguar I (and will never be asserted)
+
+       bool polygon = false, datinit = false, a1_stepld = false, a2_stepld = false, ext_int = false;
+       bool istepadd = false, istepfadd = false, finneradd = false, inneradd = false;
+       bool zstepfadd = false, zstepadd = false;
+
+       // Various state lines (initial state--basically the reset state of the FDSYNCs)
+
+       bool go = true, idle = true, inner = false, a1fupdate = false, a1update = false,
+               zfupdate = false, zupdate = false, a2update = false, init_if = false, init_ii = false,
+               init_zf = false, init_zi = false;
+
+       bool outer0 = false, indone = false;
+
+       bool idlei, inneri, a1fupdatei, a1updatei, zfupdatei, zupdatei, a2updatei, init_ifi, init_iii,
+               init_zfi, init_zii;
+
+       bool notgzandp = !(gourz && polygon);
+
+       // Various registers set up by user
+
+       uint16_t ocount = GET16(blitter_ram, PIXLINECOUNTER);
+       uint8_t a1_pitch = blitter_ram[A1_FLAGS + 3] & 0x03;
+       uint8_t a2_pitch = blitter_ram[A2_FLAGS + 3] & 0x03;
+       uint8_t a1_pixsize = (blitter_ram[A1_FLAGS + 3] & 0x38) >> 3;
+       uint8_t a2_pixsize = (blitter_ram[A2_FLAGS + 3] & 0x38) >> 3;
+       uint8_t a1_zoffset = (GET16(blitter_ram, A1_FLAGS + 2) >> 6) & 0x07;
+       uint8_t a2_zoffset = (GET16(blitter_ram, A2_FLAGS + 2) >> 6) & 0x07;
+       uint8_t a1_width = (blitter_ram[A1_FLAGS + 2] >> 1) & 0x3F;
+       uint8_t a2_width = (blitter_ram[A2_FLAGS + 2] >> 1) & 0x3F;
+       bool a2_mask = blitter_ram[A2_FLAGS + 2] & 0x80;
+       uint8_t a1addx = blitter_ram[A1_FLAGS + 1] & 0x03, a2addx = blitter_ram[A2_FLAGS + 1] & 0x03;
+       bool a1addy = blitter_ram[A1_FLAGS + 1] & 0x04, a2addy = blitter_ram[A2_FLAGS + 1] & 0x04;
+       bool a1xsign = blitter_ram[A1_FLAGS + 1] & 0x08, a2xsign = blitter_ram[A2_FLAGS + 1] & 0x08;
+       bool a1ysign = blitter_ram[A1_FLAGS + 1] & 0x10, a2ysign = blitter_ram[A2_FLAGS + 1] & 0x10;
+       uint32_t a1_base = GET32(blitter_ram, A1_BASE) & 0xFFFFFFF8;    // Phrase aligned by ignoring bottom 3 bits
+       uint32_t a2_base = GET32(blitter_ram, A2_BASE) & 0xFFFFFFF8;
+
+       uint16_t a1_win_x = GET16(blitter_ram, A1_CLIP + 2) & 0x7FFF;
+       uint16_t a1_win_y = GET16(blitter_ram, A1_CLIP + 0) & 0x7FFF;
+       int16_t a1_x = (int16_t)GET16(blitter_ram, A1_PIXEL + 2);
+       int16_t a1_y = (int16_t)GET16(blitter_ram, A1_PIXEL + 0);
+       int16_t a1_step_x = (int16_t)GET16(blitter_ram, A1_STEP + 2);
+       int16_t a1_step_y = (int16_t)GET16(blitter_ram, A1_STEP + 0);
+       uint16_t a1_stepf_x = GET16(blitter_ram, A1_FSTEP + 2);
+       uint16_t a1_stepf_y = GET16(blitter_ram, A1_FSTEP + 0);
+       uint16_t a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
+       uint16_t a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
+       int16_t a1_inc_x = (int16_t)GET16(blitter_ram, A1_INC + 2);
+       int16_t a1_inc_y = (int16_t)GET16(blitter_ram, A1_INC + 0);
+       uint16_t a1_incf_x = GET16(blitter_ram, A1_FINC + 2);
+       uint16_t a1_incf_y = GET16(blitter_ram, A1_FINC + 0);
+
+       int16_t a2_x = (int16_t)GET16(blitter_ram, A2_PIXEL + 2);
+       int16_t a2_y = (int16_t)GET16(blitter_ram, A2_PIXEL + 0);
+       uint16_t a2_mask_x = GET16(blitter_ram, A2_MASK + 2);
+       uint16_t a2_mask_y = GET16(blitter_ram, A2_MASK + 0);
+       int16_t a2_step_x = (int16_t)GET16(blitter_ram, A2_STEP + 2);
+       int16_t a2_step_y = (int16_t)GET16(blitter_ram, A2_STEP + 0);
+
+       uint64_t srcd1 = GET64(blitter_ram, SRCDATA);
+       uint64_t srcd2 = 0;
+       uint64_t dstd = GET64(blitter_ram, DSTDATA);
+       uint64_t patd = GET64(blitter_ram, PATTERNDATA);
+       uint32_t iinc = GET32(blitter_ram, INTENSITYINC);
+       uint64_t srcz1 = GET64(blitter_ram, SRCZINT);
+       uint64_t srcz2 = GET64(blitter_ram, SRCZFRAC);
+       uint64_t dstz = GET64(blitter_ram, DSTZ);
+       uint32_t zinc = GET32(blitter_ram, ZINC);
+       uint32_t collision = GET32(blitter_ram, COLLISIONCTRL);// 0=RESUME, 1=ABORT, 2=STOPEN
+
+       uint8_t pixsize = (dsta2 ? a2_pixsize : a1_pixsize);    // From ACONTROL
+
+//Testing Trevor McFur--I *think* it's the circle on the lower RHS of the screen...
+/*logBlit = false;
+if (cmd == 0x05810601 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 96)
+       && (GET16(blitter_ram, PIXLINECOUNTER + 0) == 72))
+       logBlit = true;//*/
+//Testing...
+//if (cmd == 0x1401060C) patd = 0xFFFFFFFFFFFFFFFFLL;
+//if (cmd == 0x1401060C) patd = 0x00000000000000FFLL;
+//If it's still not working (bcompen-patd) then see who's writing what to patd and where...
+//Still not OK. Check to see who's writing what to where in patd!
+//It looks like M68K is writing to the top half of patd... Hmm...
+/*
+----> M68K wrote 0000 to byte 15737344 of PATTERNDATA...
+--> M68K wrote 00 to byte 0 of PATTERNDATA...
+--> M68K wrote 00 to byte 1 of PATTERNDATA...
+----> M68K wrote 00FF to byte 15737346 of PATTERNDATA...
+--> M68K wrote 00 to byte 2 of PATTERNDATA...
+--> M68K wrote FF to byte 3 of PATTERNDATA...
+logBlit = F, cmd = 1401060C
+
+Wren0 := ND6 (wren\[0], gpua\[5], gpua\[6..8], bliten, gpu_memw);
+Wren1 := ND6 (wren\[1], gpua[5], gpua\[6..8], bliten, gpu_memw);
+Wren2 := ND6 (wren\[2], gpua\[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
+Wren3 := ND6 (wren\[3], gpua[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
+
+--> 0 000x xx00
+Dec0  := D38GH (a1baseld, a1flagld, a1winld, a1ptrld, a1stepld, a1stepfld, a1fracld, a1incld, gpua[2..4], wren\[0]);
+--> 0 001x xx00
+Dec1  := D38GH (a1incfld, a2baseld, a2flagld, a2maskld, a2ptrldg, a2stepld, cmdldt, countldt, gpua[2..4], wren\[1]);
+--> 0 010x xx00
+Dec2  := D38GH (srcd1ldg[0..1], dstdldg[0..1], dstzldg[0..1], srcz1ldg[0..1], gpua[2..4], wren\[2]);
+--> 0 011x xx00
+Dec3  := D38GH (srcz2ld[0..1], patdld[0..1], iincld, zincld, stopld, intld[0], gpua[2..4], wren\[3]);
+
+wren[3] is asserted when gpu address bus = 0 011x xx00
+patdld[0] -> 0 0110 1000 -> $F02268 (lo 32 bits)
+patdld[1] -> 0 0110 1100 -> $F0226C (hi 32 bits)
+
+So... It's reversed! The data organization of the patd register is [low 32][high 32]! !!! FIX !!! [DONE]
+And fix all the other 64 bit registers [DONE]
+*/
+/*if (cmd == 0x1401060C)
+{
+       printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
+       fflush(stdout);
+}*/
+/*logBlit = false;
+if ((cmd == 0x00010200) && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 9))
+       logBlit = true;
+
+; Pink altimeter bar
+
+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 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/132, A2 x/y: 129/0
+;x-coord is 257 in pic, so add 5
+;20 for ship, 33 for #... Let's see if we can find 'em!
+
+; Black altimeter bar
+
+Blit! (00110000 <- 000BF010) count: 5 x 29, 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 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/126, A2 x/y: 336/0
+
+Here's the pink bar--note that it's phrase mode without dread, so how does this work???
+Not sure, but I *think* that somehow it MUXes the data at the write site in on the left or right side
+of the write data when masked in phrase mode. I'll have to do some tracing to see if this is the mechanism
+it uses or not...
+
+Blit! (CMD = 00010200)
+Flags: UPDA1 PATDSEL
+  count = 9 x 11
+  a1_base = 00110010, a2_base = 000BD7E0
+  a1_x = 0106, a1_y = 0090, a1_frac_x = 0000, a1_frac_y = 8000, a2_x = 025A, a2_y = 0000
+  a1_step_x = FFF6, a1_step_y = 0001, a1_stepf_x = 5E00, a1_stepf_y = D100, a2_step_x = FFF7, a2_step_y = 0001
+  a1_inc_x = 0001, a1_inc_y = FFFF, a1_incf_x = 0000, a1_incf_y = E000
+  a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
+  a2_mask=F a1add=+phr/+0 a2add=+1/+0
+  a1_pixsize = 4, a2_pixsize = 4
+   srcd=BAC673AC2C92E578  dstd=0000000000000000 patd=74C074C074C074C0 iinc=0002E398
+  srcz1=7E127E12000088DA srcz2=DBE06DF000000000 dstz=0000000000000000 zinc=FFFE4840, coll=0
+  Phrase mode is ON
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+  Entering DWRITE state...
+     Dest write address/pix address: 0016A830/0 [dstart=20 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F] [7400000074C074C0] (icount=0007, inc=2)
+  Entering A1_ADD state [a1_x=0106, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0016A850/0 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F] [74C074C074C074C0] (icount=0003, inc=4)
+  Entering A1_ADD state [a1_x=0108, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0016A870/0 [dstart=0 dend=30 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F] [74C074C074C00000] (icount=FFFF, inc=4)
+  Entering A1_ADD state [a1_x=010C, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering IDLE_INNER state...
+  Leaving INNER state... (ocount=000A)
+  [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering A1UPDATE state... (272/144 -> 262/145)
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+*/
+
+       // Bugs in Jaguar I
+
+       a2addy = a1addy;                                                        // A2 channel Y add bit is tied to A1's
+
+//if (logBlit && (ocount > 20)) logBlit = false;
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       WriteLog("  a1_base = %08X, a2_base = %08X\n", a1_base, a2_base);
+       WriteLog("  a1_x = %04X, a1_y = %04X, a1_frac_x = %04X, a1_frac_y = %04X, a2_x = %04X, a2_y = %04X\n", (uint16_t)a1_x, (uint16_t)a1_y, a1_frac_x, a1_frac_y, (uint16_t)a2_x, (uint16_t)a2_y);
+       WriteLog("  a1_step_x = %04X, a1_step_y = %04X, a1_stepf_x = %04X, a1_stepf_y = %04X, a2_step_x = %04X, a2_step_y = %04X\n", (uint16_t)a1_step_x, (uint16_t)a1_step_y, a1_stepf_x, a1_stepf_y, (uint16_t)a2_step_x, (uint16_t)a2_step_y);
+       WriteLog("  a1_inc_x = %04X, a1_inc_y = %04X, a1_incf_x = %04X, a1_incf_y = %04X\n", (uint16_t)a1_inc_x, (uint16_t)a1_inc_y, a1_incf_x, a1_incf_y);
+       WriteLog("  a1_win_x = %04X, a1_win_y = %04X, a2_mask_x = %04X, a2_mask_y = %04X\n", a1_win_x, a1_win_y, a2_mask_x, a2_mask_y);
+       char x_add_str[4][4] = { "phr", "1", "0", "inc" };
+       WriteLog("  a2_mask=%s a1add=%s%s/%s%s a2add=%s%s/%s%s\n", (a2_mask ? "T" : "F"), (a1xsign ? "-" : "+"), x_add_str[a1addx],
+               (a1ysign ? "-" : "+"), (a1addy ? "1" : "0"), (a2xsign ? "-" : "+"), x_add_str[a2addx],
+               (a2ysign ? "-" : "+"), (a2addy ? "1" : "0"));
+       WriteLog("  a1_pixsize = %u, a2_pixsize = %u\n", a1_pixsize, a2_pixsize);
+       WriteLog("   srcd=%08X%08X  dstd=%08X%08X patd=%08X%08X iinc=%08X\n",
+               (uint32_t)(srcd1 >> 32), (uint32_t)(srcd1 & 0xFFFFFFFF),
+               (uint32_t)(dstd >> 32), (uint32_t)(dstd & 0xFFFFFFFF),
+               (uint32_t)(patd >> 32), (uint32_t)(patd & 0xFFFFFFFF), iinc);
+       WriteLog("  srcz1=%08X%08X srcz2=%08X%08X dstz=%08X%08X zinc=%08X, coll=%X\n",
+               (uint32_t)(srcz1 >> 32), (uint32_t)(srcz1 & 0xFFFFFFFF),
+               (uint32_t)(srcz2 >> 32), (uint32_t)(srcz2 & 0xFFFFFFFF),
+               (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF), zinc, collision);
+}
+#endif
+
+       // Various state lines set up by user
+
+       bool phrase_mode = ((!dsta2 && a1addx == 0) || (dsta2 && a2addx == 0) ? true : false);  // From ACONTROL
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Phrase mode is %s\n", (phrase_mode ? "ON" : "off"));
+#endif
+//logBlit = false;
+
+       // Stopgap vars to simulate various lines
+
+       uint16_t a1FracCInX = 0, a1FracCInY = 0;
+
+       while (true)
+       {
+               // IDLE
+
+               if ((idle && !go) || (inner && outer0 && indone))
+               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering IDLE state...\n");
+#endif
+                       idlei = true;
+
+//Instead of a return, let's try breaking out of the loop...
+break;
+//                     return;
+               }
+               else
+                       idlei = false;
+
+               // INNER LOOP ACTIVE
+/*
+  Entering DWRITE state... (icount=0000, inc=4)
+  Entering IDLE_INNER state...
+  Leaving INNER state... (ocount=00EF)
+  [in=T a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+Now:
+  [in=F a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+*/
+
+               if ((idle && go && !datinit)
+                       || (inner && !indone)
+                       || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && !datinit)
+                       || (a1update && !upda2 && notgzandp && !datinit)
+                       || (zupdate && !upda2 && !datinit)
+                       || (a2update && !datinit)
+                       || (init_ii && !gourz)
+                       || (init_zi))
+               {
+                       inneri = true;
+               }
+               else
+                       inneri = false;
+
+               // A1 FRACTION UPDATE
+
+               if (inner && indone && !outer0 && upda1f)
+               {
+                       a1fupdatei = true;
+               }
+               else
+                       a1fupdatei = false;
+
+               // A1 POINTER UPDATE
+
+               if ((a1fupdate)
+                       || (inner && indone && !outer0 && !upda1f && upda1))
+               {
+                       a1updatei = true;
+               }
+               else
+                       a1updatei = false;
+
+               // Z FRACTION UPDATE
+
+               if ((a1update && gourz && polygon)
+                       || (inner && indone && !outer0 && !upda1f && !upda1 && gourz && polygon))
+               {
+                       zfupdatei = true;
+               }
+               else
+                       zfupdatei = false;
+
+               // Z INTEGER UPDATE
+
+               if (zfupdate)
+               {
+                       zupdatei = true;
+               }
+               else
+                       zupdatei = false;
+
+               // A2 POINTER UPDATE
+
+               if ((a1update && upda2 && notgzandp)
+                       || (zupdate && upda2)
+                       || (inner && indone && !outer0 && !upda1f && notgzandp && !upda1 && upda2))
+               {
+                       a2updatei = true;
+               }
+               else
+                       a2updatei = false;
+
+               // INITIALIZE INTENSITY FRACTION
+
+               if ((zupdate && !upda2 && datinit)
+                       || (a1update && !upda2 && datinit && notgzandp)
+                       || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && datinit)
+                       || (a2update && datinit)
+                       || (idle && go && datinit))
+               {
+                       init_ifi = true;
+               }
+               else
+                       init_ifi = false;
+
+               // INITIALIZE INTENSITY INTEGER
+
+               if (init_if)
+               {
+                       init_iii = true;
+               }
+               else
+                       init_iii = false;
+
+               // INITIALIZE Z FRACTION
+
+               if (init_ii && gourz)
+               {
+                       init_zfi = true;
+               }
+               else
+                       init_zfi = false;
+
+               // INITIALIZE Z INTEGER
+
+               if (init_zf)
+               {
+                       init_zii = true;
+               }
+               else
+                       init_zii = false;
+
+// Here we move the fooi into their foo counterparts in order to simulate the moving
+// of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
+
+               idle = idlei;
+               inner = inneri;
+               a1fupdate = a1fupdatei;
+               a1update = a1updatei;
+               zfupdate = zfupdatei;           // *
+               zupdate = zupdatei;                     // *
+               a2update = a2updatei;
+               init_if = init_ifi;                     // *
+               init_ii = init_iii;                     // *
+               init_zf = init_zfi;                     // *
+               init_zi = init_zii;                     // *
+// * denotes states that will never assert for Jaguar I
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  [in=%c a1f=%c a1=%c zf=%c z=%c a2=%c iif=%c iii=%c izf=%c izi=%c]\n",
+               (inner ? 'T' : 'F'), (a1fupdate ? 'T' : 'F'), (a1update ? 'T' : 'F'),
+               (zfupdate ? 'T' : 'F'), (zupdate ? 'T' : 'F'), (a2update ? 'T' : 'F'),
+               (init_if ? 'T' : 'F'), (init_ii ? 'T' : 'F'), (init_zf ? 'T' : 'F'),
+               (init_zi ? 'T' : 'F'));
+#endif
+
+// Now, depending on how we want to handle things, we could either put the implementation
+// of the various pieces up above, or handle them down below here.
+
+// Let's try postprocessing for now...
+
+               if (inner)
+               {
+                       indone = false;
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering INNER state...\n");
+#endif
+                       uint16_t icount = GET16(blitter_ram, PIXLINECOUNTER + 2);
+                       bool idle_inner = true, step = true, sreadx = false, szreadx = false, sread = false,
+                               szread = false, dread = false, dzread = false, dwrite = false, dzwrite = false;
+                       bool inner0 = false;
+                       bool idle_inneri, sreadxi, szreadxi, sreadi, szreadi, dreadi, dzreadi, dwritei, dzwritei;
+
+                       // State lines that will never assert in Jaguar I
+
+                       bool textext = false, txtread = false;
+
+//other stuff
+uint8_t srcshift = 0;
+bool sshftld = true; // D flipflop (D -> Q): instart -> sshftld
+//NOTE: sshftld probably is only asserted at the beginning of the inner loop. !!! FIX !!!
+/*
+Blit! (CMD = 01800005)
+Flags: SRCEN SRCENX LFUFUNC=C
+  count = 626 x 1
+  a1_base = 00037290, a2_base = 000095D0
+  a1_x = 0000, a1_y = 0000, a2_x = 0002, a2_y = 0000
+  a1_pixsize = 4, a2_pixsize = 4
+  srcd=0000000000000000, dstd=0000000000000000, patd=0000000000000000
+  Phrase mode is ON
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+  Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
+    Source extra read address/pix address: 000095D4/0 [0000001C00540038]
+  Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
+    Source read address/pix address: 000095D8/0 [0054003800009814]
+  Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
+  Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
+    Source read address/pix address: 000095E0/0 [00009968000377C7]
+  Entering A2_ADD state [a2_x=0008, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00037298/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026A, inc=4)
+  Entering A1_ADD state [a1_x=0004, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+*/
+
+//                     while (!idle_inner)
+                       while (true)
+                       {
+                               // IDLE
+
+                               if ((idle_inner && !step)
+                                       || (dzwrite && step && inner0)
+                                       || (dwrite && step && !dstwrz && inner0))
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering IDLE_INNER state...\n");
+#endif
+                                       idle_inneri = true;
+break;
+                               }
+                               else
+                                       idle_inneri = false;
+
+                               // EXTRA SOURCE DATA READ
+
+                               if ((idle_inner && step && srcenx)
+                                       || (sreadx && !step))
+                               {
+                                       sreadxi = true;
+                               }
+                               else
+                                       sreadxi = false;
+
+                               // EXTRA SOURCE ZED READ
+
+                               if ((sreadx && step && srcenz)
+                                       || (szreadx && !step))
+                               {
+                                       szreadxi = true;
+                               }
+                               else
+                                       szreadxi = false;
+
+                               // TEXTURE DATA READ (not implemented because not in Jaguar I)
+
+                               // SOURCE DATA READ
+
+                               if ((szreadx && step && !textext)
+                                       || (sreadx && step && !srcenz && srcen)
+                                       || (idle_inner && step && !srcenx && !textext && srcen)
+                                       || (dzwrite && step && !inner0 && !textext && srcen)
+                                       || (dwrite && step && !dstwrz && !inner0 && !textext && srcen)
+                                       || (txtread && step && srcen)
+                                       || (sread && !step))
+                               {
+                                       sreadi = true;
+                               }
+                               else
+                                       sreadi = false;
+
+                               // SOURCE ZED READ
+
+                               if ((sread && step && srcenz)
+                                       || (szread && !step))
+                               {
+                                       szreadi = true;
+                               }
+                               else
+                                       szreadi = false;
+
+                               // DESTINATION DATA READ
+
+                               if ((szread && step && dsten)
+                                       || (sread && step && !srcenz && dsten)
+                                       || (sreadx && step && !srcenz && !textext && !srcen && dsten)
+                                       || (idle_inner && step && !srcenx && !textext && !srcen && dsten)
+                                       || (dzwrite && step && !inner0 && !textext && !srcen && dsten)
+                                       || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && dsten)
+                                       || (txtread && step && !srcen && dsten)
+                                       || (dread && !step))
+                               {
+                                       dreadi = true;
+                               }
+                               else
+                                       dreadi = false;
+
+                               // DESTINATION ZED READ
+
+                               if ((dread && step && dstenz)
+                                       || (szread && step && !dsten && dstenz)
+                                       || (sread && step && !srcenz && !dsten && dstenz)
+                                       || (sreadx && step && !srcenz && !textext && !srcen && !dsten && dstenz)
+                                       || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && dstenz)
+                                       || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && dstenz)
+                                       || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && dstenz)
+                                       || (txtread && step && !srcen && !dsten && dstenz)
+                                       || (dzread && !step))
+                               {
+                                       dzreadi = true;
+                               }
+                               else
+                                       dzreadi = false;
+
+                               // DESTINATION DATA WRITE
+
+                               if ((dzread && step)
+                                       || (dread && step && !dstenz)
+                                       || (szread && step && !dsten && !dstenz)
+                                       || (sread && step && !srcenz && !dsten && !dstenz)
+                                       || (txtread && step && !srcen && !dsten && !dstenz)
+                                       || (sreadx && step && !srcenz && !textext && !srcen && !dsten && !dstenz)
+                                       || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && !dstenz)
+                                       || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && !dstenz)
+                                       || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && !dstenz)
+                                       || (dwrite && !step))
+                               {
+                                       dwritei = true;
+                               }
+                               else
+                                       dwritei = false;
+
+                               // DESTINATION ZED WRITE
+
+                               if ((dzwrite && !step)
+                                       || (dwrite && step && dstwrz))
+                               {
+                                       dzwritei = true;
+                               }
+                               else
+                                       dzwritei = false;
+
+//Kludge: A QnD way to make sure that sshftld is asserted only for the first
+//        cycle of the inner loop...
+sshftld = idle_inner;
+
+// Here we move the fooi into their foo counterparts in order to simulate the moving
+// of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
+
+                               idle_inner = idle_inneri;
+                               sreadx = sreadxi;
+                               szreadx = szreadxi;
+                               sread = sreadi;
+                               szread = szreadi;
+                               dread = dreadi;
+                               dzread = dzreadi;
+                               dwrite = dwritei;
+                               dzwrite = dzwritei;
+
+// Here's a few more decodes--not sure if they're supposed to go here or not...
+
+                               bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
+
+                               bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
+
+                               bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
+                               bool gendst = dreadi || dzreadi || dwritei || dzwritei;
+                               bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
+
+                               bool zaddr = szreadx || szread || dzread || dzwrite;
+
+// Some stuff from MCONTROL.NET--not sure if this is the correct use of this decode or not...
+/*Fontread\    := OND1 (fontread\, sread[1], sreadx[1], bcompen);
+Fontread       := INV1 (fontread, fontread\);
+Justt          := NAN3 (justt, fontread\, phrase_mode, tactive\);
+Justify                := TS (justify, justt, busen);*/
+bool fontread = (sread || sreadx) && bcompen;
+bool justify = !(!fontread && phrase_mode /*&& tactive*/);
+
+/* Generate inner loop update enables */
+/*
+A1_addi                := MX2 (a1_addi, dsta_addi, srca_addi, dsta2);
+A2_addi                := MX2 (a2_addi, srca_addi, dsta_addi, dsta2);
+A1_add         := FD1 (a1_add, a1_add\, a1_addi, clk);
+A2_add         := FD1 (a2_add, a2_add\, a2_addi, clk);
+A2_addb                := BUF1 (a2_addb, a2_add);
+*/
+                               bool a1_add = (dsta2 ? srca_addi : dsta_addi);
+                               bool a2_add = (dsta2 ? dsta_addi : srca_addi);
+
+/* Address adder input A register selection
+000    A1 step integer part
+001    A1 step fraction part
+010    A1 increment integer part
+011    A1 increment fraction part
+100    A2 step
+
+bit 2 = a2update
+bit 1 = /a2update . (a1_add . a1addx[0..1])
+bit 0 = /a2update . ( a1fupdate
+                                   + a1_add . atick[0] . a1addx[0..1])
+The /a2update term on bits 0 and 1 is redundant.
+Now look-ahead based
+*/
+                               uint8_t addasel = (a1fupdate || (a1_add && a1addx == 3) ? 0x01 : 0x00);
+                               addasel |= (a1_add && a1addx == 3 ? 0x02 : 0x00);
+                               addasel |= (a2update ? 0x04 : 0x00);
+/* Address adder input A X constant selection
+adda_xconst[0..2] generate a power of 2 in the range 1-64 or all
+zeroes when they are all 1
+Remember - these are pixels, so to add one phrase the pixel size
+has to be taken into account to get the appropriate value.
+for A1
+               if a1addx[0..1] are 00 set 6 - pixel size
+               if a1addx[0..1] are 01 set the value 000
+               if a1addx[0..1] are 10 set the value 111
+similarly for A2
+JLH: Also, 11 will likewise set the value to 111
+*/
+                               uint8_t a1_xconst = 6 - a1_pixsize, a2_xconst = 6 - a2_pixsize;
+
+                               if (a1addx == 1)
+                                   a1_xconst = 0;
+                               else if (a1addx & 0x02)
+                                   a1_xconst = 7;
+
+                               if (a2addx == 1)
+                                   a2_xconst = 0;
+                               else if (a2addx & 0x02)
+                                   a2_xconst = 7;
+
+                               uint8_t adda_xconst = (a2_add ? a2_xconst : a1_xconst);
+/* Address adder input A Y constant selection
+22 June 94 - This was erroneous, because only the a1addy bit was reflected here.
+Therefore, the selection has to be controlled by a bug fix bit.
+JLH: Bug fix bit in Jaguar II--not in Jaguar I!
+*/
+                               bool adda_yconst = a1addy;
+/* Address adder input A register versus constant selection
+given by         a1_add . a1addx[0..1]
+                               + a1update
+                               + a1fupdate
+                               + a2_add . a2addx[0..1]
+                               + a2update
+*/
+                               bool addareg = ((a1_add && a1addx == 3) || a1update || a1fupdate
+                                       || (a2_add && a2addx == 3) || a2update ? true : false);
+/* The adders can be put into subtract mode in add pixel size
+mode when the corresponding flags are set */
+                               bool suba_x = ((a1_add && a1xsign && a1addx == 1) || (a2_add && a2xsign && a2addx == 1) ? true : false);
+                               bool suba_y = ((a1_add && a1addy && a1ysign) || (a2_add && a2addy && a2ysign) ? true : false);
+/* Address adder input B selection
+00     A1 pointer
+01     A2 pointer
+10     A1 fraction
+11     Zero
+
+Bit 1 =   a1fupdate
+               + (a1_add . atick[0] . a1addx[0..1])
+               + a1fupdate . a1_stepld
+               + a1update . a1_stepld
+               + a2update . a2_stepld
+Bit 0 =   a2update + a2_add
+               + a1fupdate . a1_stepld
+               + a1update . a1_stepld
+               + a2update . a2_stepld
+*/
+                               uint8_t addbsel = (a2update || a2_add || (a1fupdate && a1_stepld)
+                                   || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x01 : 0x00);
+                               addbsel |= (a1fupdate || (a1_add && a1addx == 3) || (a1fupdate && a1_stepld)
+                                   || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x02 : 0x00);
+
+/* The modulo bits are used to align X onto a phrase boundary when
+it is being updated by one phrase
+000    no mask
+001    mask bit 0
+010    mask bits 1-0
+..
+110    mask bits 5-0
+
+Masking is enabled for a1 when a1addx[0..1] is 00, and the value
+is 6 - the pixel size (again!)
+*/
+                               uint8_t maska1 = (a1_add && a1addx == 0 ? 6 - a1_pixsize : 0);
+                               uint8_t maska2 = (a2_add && a2addx == 0 ? 6 - a2_pixsize : 0);
+                               uint8_t modx = (a2_add ? maska2 : maska1);
+/* Generate load strobes for the increment updates */
+
+/*A1pldt               := NAN2 (a1pldt, atick[1], a1_add);
+A1ptrldi       := NAN2 (a1ptrldi, a1update\, a1pldt);
+
+A1fldt         := NAN4 (a1fldt, atick[0], a1_add, a1addx[0..1]);
+A1fracldi      := NAN2 (a1fracldi, a1fupdate\, a1fldt);
+
+A2pldt         := NAN2 (a2pldt, atick[1], a2_add);
+A2ptrldi       := NAN2 (a2ptrldi, a2update\, a2pldt);*/
+                               bool a1fracldi = a1fupdate || (a1_add && a1addx == 3);
+
+// Some more from DCONTROL...
+// atick[] just MAY be important here! We're assuming it's true and dropping the term...
+// That will probably screw up some of the lower terms that seem to rely on the timing of it...
+#warning srcdreadd is not properly initialized!
+bool srcdreadd = false;                                                // Set in INNER.NET
+//Shadeadd\    := NAN2H (shadeadd\, dwrite, srcshade);
+//Shadeadd     := INV2 (shadeadd, shadeadd\);
+bool shadeadd = dwrite && srcshade;
+/* Data adder control, input A selection
+000   Destination data
+001   Initialiser pixel value
+100   Source data      - computed intensity fraction
+101   Pattern data     - computed intensity
+110   Source zed 1     - computed zed
+111   Source zed 2     - computed zed fraction
+
+Bit 0 =   dwrite  . gourd . atick[1]
+       + dzwrite . gourz . atick[0]
+       + istepadd
+       + zstepfadd
+       + init_if + init_ii + init_zf + init_zi
+Bit 1 =   dzwrite . gourz . (atick[0] + atick[1])
+       + zstepadd
+       + zstepfadd
+Bit 2 =   (gourd + gourz) . /(init_if + init_ii + init_zf + init_zi)
+       + dwrite  . srcshade
+*/
+uint8_t daddasel = ((dwrite && gourd) || (dzwrite && gourz) || istepadd || zstepfadd
+       || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
+daddasel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
+daddasel |= (((gourd || gourz) && !(init_if || init_ii || init_zf || init_zi))
+       || (dwrite && srcshade) ? 0x04 : 0x00);
+/* Data adder control, input B selection
+0000   Source data
+0001   Data initialiser increment
+0100   Bottom 16 bits of I increment repeated four times
+0101   Top 16 bits of I increment repeated four times
+0110   Bottom 16 bits of Z increment repeated four times
+0111   Top 16 bits of Z increment repeated four times
+1100   Bottom 16 bits of I step repeated four times
+1101   Top 16 bits of I step repeated four times
+1110   Bottom 16 bits of Z step repeated four times
+1111   Top 16 bits of Z step repeated four times
+
+Bit 0 =   dwrite  . gourd . atick[1]
+       + dzwrite . gourz . atick[1]
+       + dwrite  . srcshade
+       + istepadd
+       + zstepadd
+       + init_if + init_ii + init_zf + init_zi
+Bit 1 =   dzwrite . gourz . (atick[0] + atick[1])
+       + zstepadd
+       + zstepfadd
+Bit 2 =   dwrite  . gourd . (atick[0] + atick[1])
+       + dzwrite . gourz . (atick[0] + atick[1])
+       + dwrite  . srcshade
+       + istepadd + istepfadd + zstepadd + zstepfadd
+Bit 3 =   istepadd + istepfadd + zstepadd + zstepfadd
+*/
+uint8_t daddbsel = ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
+       || istepadd || zstepadd || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
+daddbsel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
+daddbsel |= ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
+       || istepadd || istepfadd || zstepadd || zstepfadd ? 0x04 : 0x00);
+daddbsel |= (istepadd && istepfadd && zstepadd && zstepfadd ? 0x08 : 0x00);
+/* Data adder mode control
+000    16-bit normal add
+001    16-bit saturating add with carry
+010    8-bit saturating add with carry, carry into top byte is
+       inhibited (YCrCb)
+011    8-bit saturating add with carry, carry into top byte and
+       between top nybbles is inhibited (CRY)
+100    16-bit normal add with carry
+101    16-bit saturating add
+110    8-bit saturating add, carry into top byte is inhibited
+111    8-bit saturating add, carry into top byte and between top
+       nybbles is inhibited
+
+The first five are used for Gouraud calculations, the latter three
+for adding source and destination data
+
+Bit 0 =   dzwrite . gourz . atick[1]
+       + dwrite  . gourd . atick[1] . /topnen . /topben . /ext_int
+       + dwrite  . gourd . atick[1] .  topnen .  topben . /ext_int
+       + zstepadd
+       + istepadd . /topnen . /topben . /ext_int
+       + istepadd .  topnen .  topben . /ext_int
+       + /gourd . /gourz . /topnen . /topben
+       + /gourd . /gourz .  topnen .  topben
+       + shadeadd . /topnen . /topben
+       + shadeadd .  topnen .  topben
+       + init_ii . /topnen . /topben . /ext_int
+       + init_ii .  topnen .  topben . /ext_int
+       + init_zi
+
+Bit 1 =   dwrite . gourd . atick[1] . /topben . /ext_int
+       + istepadd . /topben . /ext_int
+       + /gourd . /gourz .  /topben
+       + shadeadd .  /topben
+       + init_ii .  /topben . /ext_int
+
+Bit 2 =   /gourd . /gourz
+       + shadeadd
+       + dwrite  . gourd . atick[1] . ext_int
+       + istepadd . ext_int
+       + init_ii . ext_int
+*/
+uint8_t daddmode = ((dzwrite && gourz) || (dwrite && gourd && !topnen && !topben && !ext_int)
+       || (dwrite && gourd && topnen && topben && !ext_int) || zstepadd
+       || (istepadd && !topnen && !topben && !ext_int)
+       || (istepadd && topnen && topben && !ext_int) || (!gourd && !gourz && !topnen && !topben)
+       || (!gourd && !gourz && topnen && topben) || (shadeadd && !topnen && !topben)
+       || (shadeadd && topnen && topben) || (init_ii && !topnen && !topben && !ext_int)
+       || (init_ii && topnen && topben && !ext_int) || init_zi ? 0x01 : 0x00);
+daddmode |= ((dwrite && gourd && !topben && !ext_int) || (istepadd && !topben && !ext_int)
+       || (!gourd && !gourz && !topben) || (shadeadd && !topben)
+       || (init_ii && !topben && !ext_int) ? 0x02 : 0x00);
+daddmode |= ((!gourd && !gourz) || shadeadd || (dwrite && gourd && ext_int)
+       || (istepadd && ext_int) || (init_ii && ext_int) ? 0x04 : 0x00);
+/* Data add load controls
+Pattern fraction (dest data) is loaded on
+         dwrite . gourd . atick[0]
+       + istepfadd . /datinit
+       + init_if
+Pattern data is loaded on
+         dwrite . gourd . atick[1]
+       + istepadd . /datinit . /datinit
+       + init_ii
+Source z1 is loaded on
+         dzwrite . gourz . atick[1]
+       + zstepadd . /datinit . /datinit
+       + init_zi
+Source z2 is loaded on
+         dzwrite . gourz . atick[0]
+       + zstepfadd
+       + init_zf
+Texture map shaded data is loaded on
+       srcdreadd . srcshade
+*/
+bool patfadd = (dwrite && gourd) || (istepfadd && !datinit) || init_if;
+bool patdadd = (dwrite && gourd) || (istepadd && !datinit) || init_ii;
+bool srcz1add = (dzwrite && gourz) || (zstepadd && !datinit) || init_zi;
+bool srcz2add = (dzwrite && gourz) || zstepfadd || init_zf;
+bool srcshadd = srcdreadd && srcshade;
+bool daddq_sel = patfadd || patdadd || srcz1add || srcz2add || srcshadd;
+/* Select write data
+This has to be controlled from stage 1 of the pipe-line, delayed
+by one tick, as the write occurs in the cycle after the ack.
+
+00     pattern data
+01     lfu data
+10     adder output
+11     source zed
+
+Bit 0 =  /patdsel . /adddsel
+       + dzwrite1d
+Bit 1 =   adddsel
+       + dzwrite1d
+*/
+uint8_t data_sel = ((!patdsel && !adddsel) || dzwrite ? 0x01 : 0x00)
+       | (adddsel || dzwrite ? 0x02 : 0x00);
+
+uint32_t address, pixAddr;
+ADDRGEN(address, pixAddr, gena2i, zaddr,
+       a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
+       a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
+
+//Here's my guess as to how the addresses get truncated to phrase boundaries in phrase mode...
+if (!justify)
+       address &= 0xFFFFF8;
+
+/* Generate source alignment shift
+   -------------------------------
+The source alignment shift for data move is the difference between
+the source and destination X pointers, multiplied by the pixel
+size.  Only the low six bits of the pointers are of interest, as
+pixel sizes are always a power of 2 and window rows are always
+phrase aligned.
+
+When not in phrase mode, the top 3 bits of the shift value are
+set to zero (2/26).
+
+Source shifting is also used to extract bits for bit-to-byte
+expansion in phrase mode.  This involves only the bottom three
+bits of the shift value, and is based on the offset within the
+phrase of the destination X pointer, in pixels.
+
+Source shifting is disabled when srcen is not set.
+*/
+uint8_t dstxp = (dsta2 ? a2_x : a1_x) & 0x3F;
+uint8_t srcxp = (dsta2 ? a1_x : a2_x) & 0x3F;
+uint8_t shftv = ((dstxp - srcxp) << pixsize) & 0x3F;
+/* The phrase mode alignment count is given by the phrase offset
+of the first pixel, for bit to byte expansion */
+uint8_t pobb = 0;
+
+if (pixsize == 3)
+       pobb = dstxp & 0x07;
+if (pixsize == 4)
+       pobb = dstxp & 0x03;
+if (pixsize == 5)
+       pobb = dstxp & 0x01;
+
+bool pobbsel = phrase_mode && bcompen;
+uint8_t loshd = (pobbsel ? pobb : shftv) & 0x07;
+uint8_t shfti = (srcen || pobbsel ? (sshftld ? loshd : srcshift & 0x07) : 0);
+/* Enable for high bits is srcen . phrase_mode */
+shfti |= (srcen && phrase_mode ? (sshftld ? shftv & 0x38 : srcshift & 0x38) : 0);
+srcshift = shfti;
+
+                               if (sreadx)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering SREADX state...");
+#endif
+//uint32_t srcAddr, pixAddr;
+//ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
+//     a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
+//     a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
+                                       srcd2 = srcd1;
+                                       srcd1 = ((uint64_t)JaguarReadLong(address + 0, BLITTER) << 32)
+                                               | (uint64_t)JaguarReadLong(address + 4, BLITTER);
+//Kludge to take pixel size into account...
+//Hmm. If we're not in phrase mode, this is most likely NOT going to be used...
+//Actually, it would be--because of BCOMPEN expansion, for example...
+if (!phrase_mode)
+{
+       if (bcompen)
+               srcd1 >>= 56;
+       else
+       {
+               if (pixsize == 5)
+                       srcd1 >>= 32;
+               else if (pixsize == 4)
+                       srcd1 >>= 48;
+               else
+                       srcd1 >>= 56;
+       }
+}//*/
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("    Source extra read address/pix address: %08X/%1X [%08X%08X]\n",
+               address, pixAddr, (uint32_t)(srcd1 >> 32), (uint32_t)(srcd1 & 0xFFFFFFFF));
+#endif
+                               }
+
+                               if (szreadx)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering SZREADX state...");
+#endif
+                                       srcz2 = srcz1;
+                                       srcz1 = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog(" Src Z extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
+               (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF));
+#endif
+                               }
+
+                               if (sread)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering SREAD state...");
+#endif
+//uint32_t srcAddr, pixAddr;
+//ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
+//     a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
+//     a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
+srcd2 = srcd1;
+srcd1 = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
+//Kludge to take pixel size into account...
+if (!phrase_mode)
+{
+       if (bcompen)
+               srcd1 >>= 56;
+       else
+       {
+               if (pixsize == 5)
+                       srcd1 >>= 32;
+               else if (pixsize == 4)
+                       srcd1 >>= 48;
+               else
+                       srcd1 >>= 56;
+       }
+}
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("     Source read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
+       (uint32_t)(srcd1 >> 32), (uint32_t)(srcd1 & 0xFFFFFFFF));
+//fflush(stdout);
+}
+#endif
+                               }
+
+                               if (szread)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("  Entering SZREAD state...");
+//fflush(stdout);
+}
+#endif
+                                       srcz2 = srcz1;
+                                       srcz1 = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
+//Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
+if (!phrase_mode && pixsize == 4)
+       srcz1 >>= 48;
+
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       WriteLog("     Src Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
+               (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF));
+}
+#endif
+                               }
+
+                               if (dread)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering DREAD state...");
+#endif
+//uint32_t dstAddr, pixAddr;
+//ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
+//     a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
+//     a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
+dstd = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
+//Kludge to take pixel size into account...
+if (!phrase_mode)
+{
+       if (pixsize == 5)
+               dstd >>= 32;
+       else if (pixsize == 4)
+               dstd >>= 48;
+       else
+               dstd >>= 56;
+}
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("       Dest read address/pix address: %08X/%1X [%08X%08X]\n", address,
+               pixAddr, (uint32_t)(dstd >> 32), (uint32_t)(dstd & 0xFFFFFFFF));
+#endif
+                               }
+
+                               if (dzread)
+                               {
+// Is Z always 64 bit read? Or sometimes 16 bit (dependent on phrase_mode)?
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering DZREAD state...");
+#endif
+                                       dstz = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
+//Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
+if (!phrase_mode && pixsize == 4)
+       dstz >>= 48;
+
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("    Dest Z read address/pix address: %08X/%1X [%08X%08X]\n", address,
+               pixAddr, (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF));
+#endif
+                               }
+
+// These vars should probably go further up in the code... !!! FIX !!!
+// We can't preassign these unless they're static...
+//uint64_t srcz = 0;                   // These are assigned to shut up stupid compiler warnings--dwrite is ALWAYS asserted
+//bool winhibit = false;
+uint64_t srcz;
+bool winhibit;
+//NOTE: SRCSHADE requires GOURZ to be set to work properly--another Jaguar I bug
+                               if (dwrite)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("  Entering DWRITE state...");
+#endif
+//Counter is done on the dwrite state...! (We'll do it first, since it affects dstart/dend calculations.)
+//Here's the voodoo for figuring the correct amount of pixels in phrase mode (or not):
+                                       int8_t inct = -((dsta2 ? a2_x : a1_x) & 0x07);  // From INNER_CNT
+                                       uint8_t inc = 0;
+                                       inc = (!phrase_mode || (phrase_mode && (inct & 0x01)) ? 0x01 : 0x00);
+                                       inc |= (phrase_mode && (((pixsize == 3 || pixsize == 4) && (inct & 0x02)) || pixsize == 5 && !(inct & 0x01)) ? 0x02 : 0x00);
+                                       inc |= (phrase_mode && ((pixsize == 3 && (inct & 0x04)) || (pixsize == 4 && !(inct & 0x03))) ? 0x04 : 0x00);
+                                       inc |= (phrase_mode && pixsize == 3 && !(inct & 0x07) ? 0x08 : 0x00);
+
+                                       uint16_t oldicount = icount;    // Save icount to detect underflow...
+                                       icount -= inc;
+
+                                       if (icount == 0 || ((icount & 0x8000) && !(oldicount & 0x8000)))
+                                               inner0 = true;
+// X/Y stepping is also done here, I think...No. It's done when a1_add or a2_add is asserted...
+
+//*********************************************************************************
+//Start & end write mask computations...
+//*********************************************************************************
+
+uint8_t dstart = 0;
+
+if (pixsize == 3)
+       dstart = (dstxp & 0x07) << 3;
+if (pixsize == 4)
+       dstart = (dstxp & 0x03) << 4;
+if (pixsize == 5)
+       dstart = (dstxp & 0x01) << 5;
+
+dstart = (phrase_mode ? dstart : pixAddr & 0x07);
+
+//This is the other Jaguar I bug... Normally, should ALWAYS select a1_x here.
+uint16_t dstxwr = (dsta2 ? a2_x : a1_x) & 0x7FFE;
+uint16_t pseq = dstxwr ^ (a1_win_x & 0x7FFE);
+pseq = (pixsize == 5 ? pseq : pseq & 0x7FFC);
+pseq = ((pixsize & 0x06) == 4 ? pseq : pseq & 0x7FF8);
+bool penden = clip_a1 && (pseq == 0);
+uint8_t window_mask = 0;
+
+if (pixsize == 3)
+       window_mask = (a1_win_x & 0x07) << 3;
+if (pixsize == 4)
+       window_mask = (a1_win_x & 0x03) << 4;
+if (pixsize == 5)
+       window_mask = (a1_win_x & 0x01) << 5;
+
+window_mask = (penden ? window_mask : 0);
+
+/*
+  Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
+    Source extra read address/pix address: 000095D0/0 [000004E40000001C]
+  Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=20]
+    Source read address/pix address: 000095D8/0 [0054003800009814]
+  Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=20][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000001C00000000] (icount=026E, inc=4)
+  Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+
+(icount=026E, inc=4)
+icount & 0x03 = 0x02
+         << 4 = 0x20
+
+window_mask = 0x1000
+
+Therefore, it chooses the inner_mask over the window_mask every time! Argh!
+This is because we did this wrong:
+Innerm[3-5]    := AN2 (inner_mask[3-5], imb[3-5], inner0);
+NOTE! This doesn't fix the problem because inner0 is asserted too late to help here. !!! FIX !!! [Should be DONE]
+*/
+
+/* The mask to be used if within one phrase of the end of the inner
+loop, similarly */
+uint8_t inner_mask = 0;
+
+if (pixsize == 3)
+       inner_mask = (icount & 0x07) << 3;
+if (pixsize == 4)
+       inner_mask = (icount & 0x03) << 4;
+if (pixsize == 5)
+       inner_mask = (icount & 0x01) << 5;
+if (!inner0)
+       inner_mask = 0;
+/* The actual mask used should be the lesser of the window masks and
+the inner mask, where is all cases 000 means 1000. */
+window_mask = (window_mask == 0 ? 0x40 : window_mask);
+inner_mask = (inner_mask == 0 ? 0x40 : inner_mask);
+uint8_t emask = (window_mask > inner_mask ? inner_mask : window_mask);
+/* The mask to be used for the pixel size, to which must be added
+the bit offset */
+uint8_t pma = pixAddr + (1 << pixsize);
+/* Select the mask */
+uint8_t dend = (phrase_mode ? emask : pma);
+
+/* The cycle width in phrase mode is normally one phrase.  However,
+at the start and end it may be narrower.  The start and end masks
+are used to generate this.  The width is given by:
+
+       8 - start mask - (8 - end mask)
+=      end mask - start mask
+
+This is only used for writes in phrase mode.
+Start and end from the address level of the pipeline are used.
+*/
+uint8_t pwidth = (((dend | dstart) & 0x07) == 0 ? 0x08 : (dend - dstart) & 0x07);
+
+//uint32_t dstAddr, pixAddr;
+//ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
+//     a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
+//     a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("     Dest write address/pix address: %08X/%1X", address, pixAddr);
+#endif
+
+//More testing... This is almost certainly wrong, but how else does this work???
+//Seems to kinda work... But still, this doesn't seem to make any sense!
+if (phrase_mode && !dsten)
+       dstd = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
+
+//Testing only... for now...
+//This is wrong because the write data is a combination of srcd and dstd--either run
+//thru the LFU or in PATDSEL or ADDDSEL mode. [DONE now, thru DATA module]
+// Precedence is ADDDSEL > PATDSEL > LFU.
+//Also, doesn't take into account the start & end masks, or the phrase width...
+//Now it does!
+
+// srcd2 = xxxx xxxx 0123 4567, srcd = 8901 2345 xxxx xxxx, srcshift = $20 (32)
+uint64_t srcd = (srcd2 << (64 - srcshift)) | (srcd1 >> srcshift);
+//bleh, ugly ugly ugly
+if (srcshift == 0)
+       srcd = srcd1;
+
+//NOTE: This only works with pixel sizes less than 8BPP...
+//DOUBLE NOTE: Still need to do regression testing to ensure that this doesn't break other stuff... !!! CHECK !!!
+if (!phrase_mode && srcshift != 0)
+       srcd = ((srcd2 & 0xFF) << (8 - srcshift)) | ((srcd1 & 0xFF) >> srcshift);
+
+//Z DATA() stuff done here... And it has to be done before any Z shifting...
+//Note that we need to have phrase mode start/end support here... (Not since we moved it from dzwrite...!)
+/*
+Here are a couple of Cybermorph blits with Z:
+$00113078      // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
+$09900F39      // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
+
+We're having the same phrase mode overwrite problem we had with the pixels... !!! FIX !!!
+Odd. It's equating 0 with 0... Even though ZMODE is $04 (less than)!
+*/
+if (gourz)
+{
+/*
+void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
+       uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
+       uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
+       uint32_t zinc, uint32_t zstep)
+*/
+       uint16_t addq[4];
+       uint8_t initcin[4] = { 0, 0, 0, 0 };
+       ADDARRAY(addq, 7/*daddasel*/, 6/*daddbsel*/, 0/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
+       srcz2 = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
+       ADDARRAY(addq, 6/*daddasel*/, 7/*daddbsel*/, 1/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
+       srcz1 = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
+
+#if 0//def VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("\n[srcz1=%08X%08X, srcz2=%08X%08X, zinc=%08X",
+               (uint32_t)(srcz1 >> 32), (uint32_t)(srcz1 & 0xFFFFFFFF),
+               (uint32_t)(srcz2 >> 32), (uint32_t)(srcz2 & 0xFFFFFFFF), zinc);
+#endif
+}
+
+uint8_t zSrcShift = srcshift & 0x30;
+srcz = (srcz2 << (64 - zSrcShift)) | (srcz1 >> zSrcShift);
+//bleh, ugly ugly ugly
+if (zSrcShift == 0)
+       srcz = srcz1;
+
+#if 0//def VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog(" srcz=%08X%08X]\n", (uint32_t)(srcz >> 32), (uint32_t)(srcz & 0xFFFFFFFF));
+#endif
+
+//When in SRCSHADE mode, it adds the IINC to the read source (from LFU???)
+//According to following line, it gets LFU mode. But does it feed the source into the LFU
+//after the add?
+//Dest write address/pix address: 0014E83E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003F, inc=1)
+//Let's try this:
+if (srcshade)
+{
+//NOTE: This is basically doubling the work done by DATA--since this is what
+//      ADDARRAY is loaded with when srschshade is enabled... !!! FIX !!!
+//      Also note that it doesn't work properly unless GOURZ is set--there's the clue!
+       uint16_t addq[4];
+       uint8_t initcin[4] = { 0, 0, 0, 0 };
+       ADDARRAY(addq, 4/*daddasel*/, 5/*daddbsel*/, 7/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
+       srcd = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
+}
+//Seems to work... Not 100% sure tho.
+//end try this
+
+//Temporary kludge, to see if the fractional pattern does anything...
+//This works, BTW
+//But it seems to mess up in Cybermorph... the shading should be smooth but it isn't...
+//Seems the carry out is lost again... !!! FIX !!! [DONE--see below]
+if (patfadd)
+{
+       uint16_t addq[4];
+       uint8_t initcin[4] = { 0, 0, 0, 0 };
+       ADDARRAY(addq, 4/*daddasel*/, 4/*daddbsel*/, 0/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
+       srcd1 = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
+}
+
+//Note that we still don't take atick[0] & [1] into account here, so this will skip half of the data needed... !!! FIX !!!
+//Not yet enumerated: dbinh, srcdread, srczread
+//Also, should do srcshift on the z value in phrase mode... !!! FIX !!! [DONE]
+//As well as add a srcz variable we can set external to this state... !!! FIX !!! [DONE]
+
+uint64_t wdata;
+uint8_t dcomp, zcomp;
+DATA(wdata, dcomp, zcomp, winhibit,
+       true, cmpdst, daddasel, daddbsel, daddmode, daddq_sel, data_sel, 0/*dbinh*/,
+       dend, dstart, dstd, iinc, lfufunc, patd, patdadd,
+       phrase_mode, srcd, false/*srcdread*/, false/*srczread*/, srcz2add, zmode,
+       bcompen, bkgwren, dcompen, icount & 0x07, pixsize,
+       srcz, dstz, zinc);
+/*
+Seems that the phrase mode writes with DCOMPEN and DSTEN are corrupting inside of DATA: !!! FIX !!!
+It's fairly random as well. 7CFE -> 7DFE, 7FCA -> 78CA, 7FA4 -> 78A4, 7F88 -> 8F88
+It could be related to an uninitialized variable, like the zmode bug...
+[DONE]
+It was a bug in the dech38el data--it returned $FF for ungated instead of $00...
+
+Blit! (CMD = 09800609)
+Flags: SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
+  count = 10 x 12
+  a1_base = 00110000, a2_base = 0010B2A8
+  a1_x = 004B, a1_y = 00D8, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0704, a2_y = 0000
+  a1_step_x = FFF3, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFFC, a2_step_y = 0000
+  a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
+  a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
+  a2_mask=F a1add=+phr/+0 a2add=+phr/+0
+  a1_pixsize = 4, a2_pixsize = 4
+   srcd=0000000000000000  dstd=0000000000000000 patd=0000000000000000 iinc=00000000
+  srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
+  Phrase mode is ON
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+  Entering SREAD state...    Source read address/pix address: 0010C0B0/0 [0000000078047804]
+  Entering A2_ADD state [a2_x=0704, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DREAD state...
+      Dest read address/pix address: 00197240/0 [0000000000000028]
+  Entering DWRITE state...
+     Dest write address/pix address: 00197240/0 [dstart=30 dend=40 pwidth=8 srcshift=30][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000028] (icount=0009, inc=1)
+  Entering A1_ADD state [a1_x=004B, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 0010C0B8/0 [7804780478047804]
+  Entering A2_ADD state [a2_x=0708, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DREAD state...
+      Dest read address/pix address: 00197260/0 [0028000000200008]
+  Entering DWRITE state...
+     Dest write address/pix address: 00197260/0 [dstart=0 dend=40 pwidth=8 srcshift=30][daas=0 dabs=0 dam=7 ds=1 daq=F] [0028780478047804] (icount=0005, inc=4)
+  Entering A1_ADD state [a1_x=004C, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 0010C0C0/0 [0000000000000000]
+  Entering A2_ADD state [a2_x=070C, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DREAD state...
+      Dest read address/pix address: 00197280/0 [0008001800180018]
+  Entering DWRITE state...
+     Dest write address/pix address: 00197280/0 [dstart=0 dend=40 pwidth=8 srcshift=30][daas=0 dabs=0 dam=7 ds=1 daq=F] [7804780478040018] (icount=0001, inc=4)
+  Entering A1_ADD state [a1_x=0050, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 0010C0C8/0 [000078047BFE7BFE]
+  Entering A2_ADD state [a2_x=0710, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering DREAD state...
+      Dest read address/pix address: 001972A0/0 [0008002000000000]
+  Entering DWRITE state...
+     Dest write address/pix address: 001972A0/0 [dstart=0 dend=10 pwidth=8 srcshift=30][daas=0 dabs=0 dam=7 ds=1 daq=F] [0008002000000000] (icount=FFFD, inc=4)
+  Entering A1_ADD state [a1_x=0054, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering IDLE_INNER state...
+*/
+
+//Why isn't this taken care of in DATA? Because, DATA is modifying its local copy instead of the one used here.
+//!!! FIX !!! [DONE]
+//if (patdadd)
+//     patd = wdata;
+
+//if (patfadd)
+//     srcd1 = wdata;
+
+/*
+DEF ADDRCOMP (
+       a1_outside      // A1 pointer is outside window bounds
+       :OUT;
+INT16/ a1_x
+INT16/ a1_y
+INT15/ a1_win_x
+INT15/ a1_win_y
+       :IN);
+BEGIN
+
+// The address is outside if negative, or if greater than or equal
+// to the window size
+
+A1_xcomp       := MAG_15 (a1xgr, a1xeq, a1xlt, a1_x{0..14}, a1_win_x{0..14});
+A1_ycomp       := MAG_15 (a1ygr, a1yeq, a1ylt, a1_y{0..14}, a1_win_y{0..14});
+A1_outside     := OR6 (a1_outside, a1_x{15}, a1xgr, a1xeq, a1_y{15}, a1ygr, a1yeq);
+*/
+//NOTE: There seems to be an off-by-one bug here in the clip_a1 section... !!! FIX !!!
+//      Actually, seems to be related to phrase mode writes...
+//      Or is it? Could be related to non-15-bit compares as above?
+if (clip_a1 && ((a1_x & 0x8000) || (a1_y & 0x8000) || (a1_x >= a1_win_x) || (a1_y >= a1_win_y)))
+       winhibit = true;
+
+if (!winhibit)
+{
+       if (phrase_mode)
+       {
+               JaguarWriteLong(address + 0, wdata >> 32, BLITTER);
+               JaguarWriteLong(address + 4, wdata & 0xFFFFFFFF, BLITTER);
+       }
+       else
+       {
+               if (pixsize == 5)
+                       JaguarWriteLong(address, wdata & 0xFFFFFFFF, BLITTER);
+               else if (pixsize == 4)
+                       JaguarWriteWord(address, wdata & 0x0000FFFF, BLITTER);
+               else
+                       JaguarWriteByte(address, wdata & 0x000000FF, BLITTER);
+       }
+}
+
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       WriteLog(" [%08X%08X]%s", (uint32_t)(wdata >> 32), (uint32_t)(wdata & 0xFFFFFFFF), (winhibit ? "[X]" : ""));
+       WriteLog(" (icount=%04X, inc=%u)\n", icount, (uint16_t)inc);
+       WriteLog("    [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
+       WriteLog("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
+}
+#endif
+                               }
+
+                               if (dzwrite)
+                               {
+// OK, here's the big insight: When NOT in GOURZ mode, srcz1 & 2 function EXACTLY the same way that
+// srcd1 & 2 work--there's an implicit shift from srcz1 to srcz2 whenever srcz1 is read.
+// OTHERWISE, srcz1 is the integer for the computed Z and srcz2 is the fractional part.
+// Writes to srcz1 & 2 follow the same pattern as the other 64-bit registers--low 32 at the low address,
+// high 32 at the high address (little endian!).
+// NOTE: GOURZ is still not properly supported. Check patd/patf handling...
+//       Phrase mode start/end masks are not properly supported either...
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       WriteLog("  Entering DZWRITE state...");
+       WriteLog("  Dest Z write address/pix address: %08X/%1X [%08X%08X]\n", address,
+               pixAddr, (uint32_t)(srcz >> 32), (uint32_t)(srcz & 0xFFFFFFFF));
+}
+#endif
+//This is not correct... !!! FIX !!!
+//Should be OK now... We'll see...
+//Nope. Having the same starstep write problems in phrase mode as we had with pixels... !!! FIX !!!
+//This is not causing the problem in Hover Strike... :-/
+//The problem was with the SREADX not shifting. Still problems with Z comparisons & other text in pregame screen...
+if (!winhibit)
+{
+       if (phrase_mode)
+       {
+               JaguarWriteLong(address + 0, srcz >> 32, BLITTER);
+               JaguarWriteLong(address + 4, srcz & 0xFFFFFFFF, BLITTER);
+       }
+       else
+       {
+               if (pixsize == 4)
+                       JaguarWriteWord(address, srcz & 0x0000FFFF, BLITTER);
+       }
+}//*/
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+//     printf(" [%08X%08X]\n", (uint32_t)(srcz >> 32), (uint32_t)(srcz & 0xFFFFFFFF));
+//     fflush(stdout);
+//printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
+       WriteLog("    [dstart=? dend=? pwidth=? srcshift=%X]", srcshift);
+       WriteLog("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+                               }
+
+/*
+This is because the address generator was using only 15 bits of the X when it should have
+used 16!
+
+There's a slight problem here: The X pointer isn't wrapping like it should when it hits
+the edge of the window... Notice how the X isn't reset at the edge of the window:
+
+Blit! (CMD = 00010000)
+Flags: PATDSEL
+  count = 160 x 261
+  a1_base = 000E8008, a2_base = 0001FA68
+  a1_x = 0000, a1_y = 0000, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0000, a2_y = 0000
+  a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
+  a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
+  a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
+  a2_mask=F a1add=+phr/+0 a2add=+phr/+0
+  a1_pixsize = 5, a2_pixsize = 5
+   srcd=7717771777177717  dstd=0000000000000000 patd=7730773077307730 iinc=00000000
+  srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
+  Phrase mode is ON
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+  Entering DWRITE state...     Dest write address/pix address: 000E8008/0 [7730773077307730] (icount=009E, inc=2)
+ srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
+[srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
+    [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
+  Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
+  Entering DWRITE state...     Dest write address/pix address: 000E8018/0 [7730773077307730] (icount=009C, inc=2)
+ srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
+[srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
+    [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
+  Entering A1_ADD state [a1_x=0002, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
+
+...
+
+  Entering A1_ADD state [a1_x=009C, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
+  Entering DWRITE state...     Dest write address/pix address: 000E84F8/0 [7730773077307730] (icount=0000, inc=2)
+ srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
+[srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
+    [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
+  Entering A1_ADD state [a1_x=009E, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
+  Entering IDLE_INNER state...
+
+  Leaving INNER state... (ocount=0104)
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+
+  Entering INNER state...
+  Entering DWRITE state...     Dest write address/pix address: 000E8508/0 [7730773077307730] (icount=009E, inc=2)
+ srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
+[srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
+    [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
+  Entering A1_ADD state [a1_x=00A0, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
+  Entering DWRITE state...     Dest write address/pix address: 000E8518/0 [7730773077307730] (icount=009C, inc=2)
+ srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
+[srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
+    [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
+  Entering A1_ADD state [a1_x=00A2, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
+
+*/
+
+                               if (a1_add)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+//printf("  Entering A1_ADD state [addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
+WriteLog("  Entering A1_ADD state [a1_x=%04X, a1_y=%04X, addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", a1_x, a1_y, addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
+//fflush(stdout);
+}
+#endif
+int16_t adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
+ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
+       a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
+ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
+ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
+
+#if 0//def VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("  [adda_x=%d, adda_y=%d, addb_x=%d, addb_y=%d, addq_x=%d, addq_y=%d]\n", adda_x, adda_y, addb_x, addb_y, addq_x, addq_y);
+//fflush(stdout);
+}
+#endif
+//Now, write to what???
+//a2ptrld comes from a2ptrldi...
+//I believe it's addbsel that determines the writeback...
+// This is where atick[0] & [1] come in, in determining which part (fractional, integer)
+// gets written to...
+//a1_x = addq_x;
+//a1_y = addq_y;
+//Kludge, to get A1 channel increment working...
+if (a1addx == 3)
+{
+       a1_frac_x = addq_x, a1_frac_y = addq_y;
+
+addasel = 2, addbsel = 0, a1fracldi = false;
+ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
+       a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
+ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
+ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
+
+       a1_x = addq_x, a1_y = addq_y;
+}
+else
+       a1_x = addq_x, a1_y = addq_y;
+                               }
+
+                               if (a2_add)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+//printf("  Entering A2_ADD state [addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
+WriteLog("  Entering A2_ADD state [a2_x=%04X, a2_y=%04X, addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", a2_x, a2_y, addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
+//fflush(stdout);
+}
+#endif
+//void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y,
+//     int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y,
+//     int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst,
+//     bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
+//void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y,
+//     int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y)
+//void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
+//     int16_t adda_x, int16_t adda_y, int16_t addb_x, int16_t addb_y, uint8_t modx, bool suba_x, bool suba_y)
+//void DATAMUX(int16_t &data_x, int16_t &data_y, uint32_t gpu_din, int16_t addq_x, int16_t addq_y, bool addqsel)
+int16_t adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
+ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
+       a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
+ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
+ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
+
+#if 0//def VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("  [adda_x=%d, adda_y=%d, addb_x=%d, addb_y=%d, addq_x=%d, addq_y=%d]\n", adda_x, adda_y, addb_x, addb_y, addq_x, addq_y);
+//fflush(stdout);
+}
+#endif
+//Now, write to what???
+//a2ptrld comes from a2ptrldi...
+//I believe it's addbsel that determines the writeback...
+a2_x = addq_x;
+a2_y = addq_y;
+                               }
+                       }
+/*
+Flags: SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
+  count = 64 x 55
+  a1_base = 0015B000, a2_base = 0014B000
+  a1_x = 0000, a1_y = 0000, a1_frac_x = 8000, a1_frac_y = 8000, a2_x = 001F, a2_y = 0038
+  a1_step_x = FFFFFFC0, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 2AAA, a2_step_x = FFFFFFC0, a2_step_y = 0001
+  a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
+  a1_win_x = 0040, a1_win_y = 0040, a2_mask_x = 0000, a2_mask_y = 0000
+  a2_mask=F a1add=+inc/+0 a2add=+1/+0
+  a1_pixsize = 4, a2_pixsize = 4
+   srcd=FF00FF00FF00FF00  dstd=0000000000000000 patd=0000000000000000 iinc=00000000
+  srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, col=0
+  Phrase mode is off
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+  Entering SREAD state...    Source read address/pix address: 0015B000/0 [6505650565056505]
+  Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0014E83E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003F, inc=1)
+  Entering A2_ADD state [a2_x=001F, a2_y=0038, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 0015B000/0 [6505650565056505]
+  Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0014E942/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003E, inc=1)
+  Entering A2_ADD state [a2_x=0021, a2_y=0039, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 0015B000/0 [6505650565056505]
+  Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0014EA46/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003D, inc=1)
+  Entering A2_ADD state [a2_x=0023, a2_y=003A, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 0015B000/0 [6505650565056505]
+  Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0014EB4A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003C, inc=1)
+  Entering A2_ADD state [a2_x=0025, a2_y=003B, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  ...
+  Entering SREAD state...    Source read address/pix address: 0015B000/0 [6505650565056505]
+  Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0015283A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=0000, inc=1)
+  Entering A2_ADD state [a2_x=009D, a2_y=0077, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering IDLE_INNER state...
+  Leaving INNER state... (ocount=0036)
+  [in=F a1f=T a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering A1FUPDATE state...
+  [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering A1UPDATE state... (-32768/-32768 -> 32704/-32767)
+  [in=F a1f=F a1=F zf=F z=F a2=T iif=F iii=F izf=F izi=F]
+  Entering A2UPDATE state... (159/120 -> 95/121)
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+*/
+
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("  Leaving INNER state...");
+//fflush(stdout);
+}
+#endif
+                       indone = true;
+// The outer counter is updated here as well on the clock cycle...
+
+/* the inner loop is started whenever another state is about to
+cause the inner state to go active */
+//Instart              := ND7 (instart, innert[0], innert[2..7]);
+
+//Actually, it's done only when inner gets asserted without the 2nd line of conditions
+//(inner AND !indone)
+//fixed now...
+//Since we don't get here until the inner loop is finished (indone = true) we can get
+//away with doing it here...!
+                       ocount--;
+
+                       if (ocount == 0)
+                               outer0 = true;
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog(" (ocount=%04X)\n", ocount);
+//fflush(stdout);
+}
+#endif
+               }
+
+               if (a1fupdate)
+               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("  Entering A1FUPDATE state...\n");
+//fflush(stdout);
+}
+#endif
+                       uint32_t a1_frac_xt = (uint32_t)a1_frac_x + (uint32_t)a1_stepf_x;
+                       uint32_t a1_frac_yt = (uint32_t)a1_frac_y + (uint32_t)a1_stepf_y;
+                       a1FracCInX = a1_frac_xt >> 16;
+                       a1FracCInY = a1_frac_yt >> 16;
+                       a1_frac_x = (uint16_t)(a1_frac_xt & 0xFFFF);
+                       a1_frac_y = (uint16_t)(a1_frac_yt & 0xFFFF);
+               }
+
+               if (a1update)
+               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("  Entering A1UPDATE state... (%d/%d -> ", a1_x, a1_y);
+//fflush(stdout);
+}
+#endif
+                       a1_x += a1_step_x + a1FracCInX;
+                       a1_y += a1_step_y + a1FracCInY;
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("%d/%d)\n", a1_x, a1_y);
+//fflush(stdout);
+}
+#endif
+               }
+
+               if (a2update)
+               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("  Entering A2UPDATE state... (%d/%d -> ", a2_x, a2_y);
+//fflush(stdout);
+}
+#endif
+                       a2_x += a2_step_x;
+                       a2_y += a2_step_y;
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("%d/%d)\n", a2_x, a2_y);
+//fflush(stdout);
+}
+#endif
+               }
+       }
+
+// We never get here! !!! FIX !!!
+
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       WriteLog("Done!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
+               GET16(blitter_ram, A1_PIXEL + 2),
+               GET16(blitter_ram, A1_PIXEL + 0),
+               GET16(blitter_ram, A1_FPIXEL + 2),
+               GET16(blitter_ram, A1_FPIXEL + 0),
+               GET16(blitter_ram, A2_PIXEL + 2),
+               GET16(blitter_ram, A2_PIXEL + 0));
+//     fflush(stdout);
+}
+#endif
+
+       // Write values back to registers (in real blitter, these are continuously updated)
+       SET16(blitter_ram, A1_PIXEL + 2, a1_x);
+       SET16(blitter_ram, A1_PIXEL + 0, a1_y);
+       SET16(blitter_ram, A1_FPIXEL + 2, a1_frac_x);
+       SET16(blitter_ram, A1_FPIXEL + 0, a1_frac_y);
+       SET16(blitter_ram, A2_PIXEL + 2, a2_x);
+       SET16(blitter_ram, A2_PIXEL + 0, a2_y);
+
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       WriteLog("Writeback!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
+               GET16(blitter_ram, A1_PIXEL + 2),
+               GET16(blitter_ram, A1_PIXEL + 0),
+               GET16(blitter_ram, A1_FPIXEL + 2),
+               GET16(blitter_ram, A1_FPIXEL + 0),
+               GET16(blitter_ram, A2_PIXEL + 2),
+               GET16(blitter_ram, A2_PIXEL + 0));
+//     fflush(stdout);
+}
+#endif
+}
+
+
+/*
+       int16_t a1_x = (int16_t)GET16(blitter_ram, A1_PIXEL + 2);
+       int16_t a1_y = (int16_t)GET16(blitter_ram, A1_PIXEL + 0);
+       uint16_t a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
+       uint16_t a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
+       int16_t a2_x = (int16_t)GET16(blitter_ram, A2_PIXEL + 2);
+       int16_t a2_y = (int16_t)GET16(blitter_ram, A2_PIXEL + 0);
+
+Seems that the ending a1_x should be written between blits, but it doesn't seem to be...
+
+Blit! (CMD = 01800000)
+Flags: LFUFUNC=C
+  count = 28672 x 1
+  a1_base = 00050000, a2_base = 00070000
+  a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
+  a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
+  a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
+  a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
+  a2_mask=F a1add=+phr/+0 a2add=+phr/+0
+  a1_pixsize = 4, a2_pixsize = 3
+   srcd=DEDEDEDEDEDEDEDE  dstd=0000000000000000 patd=0000000000000000 iinc=00000000
+  srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
+  Phrase mode is ON
+
+Blit! (CMD = 01800000)
+Flags: LFUFUNC=C
+  count = 28672 x 1
+  a1_base = 00050000, a2_base = 00070000
+  a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
+  a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
+  a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
+  a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
+  a2_mask=F a1add=+phr/+0 a2add=+phr/+0
+  a1_pixsize = 4, a2_pixsize = 3
+   srcd=D6D6D6D6D6D6D6D6  dstd=0000000000000000 patd=0000000000000000 iinc=00000000
+  srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
+  Phrase mode is ON
+*/
+
+
+
+// Various pieces of the blitter puzzle are teased out here...
+
+
+
+/*
+DEF ADDRGEN (
+INT24/ address         // byte address
+               pixa[0..2]      // bit part of address, un-pipe-lined
+               :OUT;
+INT16/ a1_x
+INT16/ a1_y
+INT21/ a1_base
+               a1_pitch[0..1]
+               a1_pixsize[0..2]
+               a1_width[0..5]
+               a1_zoffset[0..1]
+INT16/ a2_x
+INT16/ a2_y
+INT21/ a2_base
+               a2_pitch[0..1]
+               a2_pixsize[0..2]
+               a2_width[0..5]
+               a2_zoffset[0..1]
+               apipe           // load address pipe-line latch
+               clk                     // co-processor clock
+               gena2           // generate A2 as opposed to A1
+               zaddr           // generate Z address
+               :IN);
+*/
+
+void ADDRGEN(uint32_t &address, uint32_t &pixa, bool gena2, bool zaddr,
+       uint16_t a1_x, uint16_t a1_y, uint32_t a1_base, uint8_t a1_pitch, uint8_t a1_pixsize, uint8_t a1_width, uint8_t a1_zoffset,
+       uint16_t a2_x, uint16_t a2_y, uint32_t a2_base, uint8_t a2_pitch, uint8_t a2_pixsize, uint8_t a2_width, uint8_t a2_zoffset)
+{
+//     uint16_t x = (gena2 ? a2_x : a1_x) & 0x7FFF;
+       uint16_t x = (gena2 ? a2_x : a1_x) & 0xFFFF;    // Actually uses all 16 bits to generate address...!
+       uint16_t y = (gena2 ? a2_y : a1_y) & 0x0FFF;
+       uint8_t width = (gena2 ? a2_width : a1_width);
+       uint8_t pixsize = (gena2 ? a2_pixsize : a1_pixsize);
+       uint8_t pitch = (gena2 ? a2_pitch : a1_pitch);
+       uint32_t base = (gena2 ? a2_base : a1_base) >> 3;//Only upper 21 bits are passed around the bus? Seems like it...
+       uint8_t zoffset = (gena2 ? a2_zoffset : a1_zoffset);
+
+       uint32_t ytm = ((uint32_t)y << 2) + (width & 0x02 ? (uint32_t)y << 1 : 0) + (width & 0x01 ? (uint32_t)y : 0);
+
+       uint32_t ya = (ytm << (width >> 2)) >> 2;
+
+       uint32_t pa = ya + x;
+
+       /*uint32*/ pixa = pa << pixsize;
+
+       uint8_t pt = ((pitch & 0x01) && !(pitch & 0x02) ? 0x01 : 0x00)
+               | (!(pitch & 0x01) && (pitch & 0x02) ? 0x02 : 0x00);
+//     uint32_t phradr = pixa << pt;
+       uint32_t phradr = (pixa >> 6) << pt;
+       uint32_t shup = (pitch == 0x03 ? (pixa >> 6) : 0);
+
+       uint8_t za = (zaddr ? zoffset : 0) & 0x03;
+//     uint32_t addr = za + (phradr & 0x07) + (shup << 1) + base;
+       uint32_t addr = za + phradr + (shup << 1) + base;
+       /*uint32*/ address = ((pixa & 0x38) >> 3) | ((addr & 0x1FFFFF) << 3);
+#if 0//def VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+WriteLog("    [gena2=%s, x=%04X, y=%04X, w=%1X, pxsz=%1X, ptch=%1X, b=%08X, zoff=%1X]\n", (gena2 ? "T" : "F"), x, y, width, pixsize, pitch, base, zoffset);
+WriteLog("    [ytm=%X, ya=%X, pa=%X, pixa=%X, pt=%X, phradr=%X, shup=%X, za=%X, addr=%X, address=%X]\n", ytm, ya, pa, pixa, pt, phradr, shup, za, addr, address);
+//fflush(stdout);
+}
+#endif
+       pixa &= 0x07;
+/*
+  Entering INNER state...
+    [gena2=T, x=0002, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
+    [ytm=0, ya=0, pa=2, pixa=20, pt=0, phradr=0, shup=0, za=0, addr=12BA, address=95D4]
+  Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
+    Source extra read address/pix address: 000095D4/0 [0000001C00540038]
+  Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+    [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
+    [ytm=0, ya=0, pa=4, pixa=40, pt=0, phradr=1, shup=0, za=0, addr=12BB, address=95D8]
+  Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
+    Source read address/pix address: 000095D8/0 [0054003800009814]
+  Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+    [gena2=F, x=0000, y=0000, w=20, pxsz=4, ptch=0, b=00006E52, zoff=0]
+    [ytm=0, ya=0, pa=0, pixa=0, pt=0, phradr=0, shup=0, za=0, addr=6E52, address=37290]
+  Entering DWRITE state...
+     Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
+  Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+    [gena2=T, x=0008, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
+    [ytm=0, ya=0, pa=8, pixa=80, pt=0, phradr=2, shup=0, za=0, addr=12BC, address=95E0]
+*/
+/*
+Obviously wrong:
+  Entering SREAD state...
+    [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
+    [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10AC, address=8560]
+    Source read address/pix address: 00008560/0 [8C27981B327E00F0]
+
+2nd pass (still wrong):
+  Entering SREAD state...
+    [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
+    [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10EC, address=8760]
+    Source read address/pix address: 00008760/0 [00E06DC04581880C]
+
+Correct!:
+  Entering SREAD state...
+    [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
+    [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=1, shup=0, za=0, addr=10AD, address=8568]
+    Source read address/pix address: 00008568/0 [6267981A327C00F0]
+
+OK, now we're back into incorrect (or is it?):
+  Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
+    Source extra read address/pix address: 000095D4/0 [0000 001C 0054 0038]
+  Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+  Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
+    Source read address/pix address: 000095D8/0 [0054 0038 0000 9814]
+  Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
+I think this may be correct...!
+*/
+}
+
+/*
+// source and destination address update conditions
+
+Sraat0         := AN2 (sraat[0], sreadxi, srcenz\);
+Sraat1         := AN2 (sraat[1], sreadi, srcenz\);
+Srca_addi      := OR4 (srca_addi, szreadxi, szreadi, sraat[0..1]);
+Srca_add       := FD1Q (srca_add, srca_addi, clk);
+
+Dstaat         := AN2 (dstaat, dwritei, dstwrz\);
+Dsta_addi      := OR2 (dsta_addi, dzwritei, dstaat);
+// Dsta_add    := FD1Q (dsta_add, dsta_addi, clk);
+
+// source and destination address generate conditions
+
+Gensrc         := OR4 (gensrc, sreadxi, szreadxi, sreadi, szreadi);
+Gendst         := OR4 (gendst, dreadi, dzreadi, dwritei, dzwritei);
+Dsta2\         := INV1 (dsta2\, dsta2);
+Gena2t0                := NAN2 (gena2t[0], gensrc, dsta2\);
+Gena2t1                := NAN2 (gena2t[1], gendst, dsta2);
+Gena2i         := NAN2 (gena2i, gena2t[0..1]);
+Gena2          := FD1QU (gena2, gena2i, clk);
+
+Zaddr          := OR4 (zaddr, szreadx, szread, dzread, dzwrite);
+*/
+
+/*void foo(void)
+{
+       // Basically, the above translates to:
+       bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
+
+       bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
+
+       bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
+       bool gendst = dreadi || szreadi || dwritei || dzwritei;
+       bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
+
+       bool zaddr = szreadx || szread || dzread || dzwrite;
+}*/
+
+/*
+// source data reads
+
+Srcdpset\      := NAN2 (srcdpset\, readreq, sread);
+Srcdpt1        := NAN2 (srcdpt[1], srcdpend, srcdack\);
+Srcdpt2                := NAN2 (srcdpt[2], srcdpset\, srcdpt[1]);
+Srcdpend       := FD2Q (srcdpend, srcdpt[2], clk, reset\);
+
+Srcdxpset\     := NAN2 (srcdxpset\, readreq, sreadx);
+Srcdxpt1       := NAN2 (srcdxpt[1], srcdxpend, srcdxack\);
+Srcdxpt2       := NAN2 (srcdxpt[2], srcdxpset\, srcdxpt[1]);
+Srcdxpend      := FD2Q (srcdxpend, srcdxpt[2], clk, reset\);
+
+Sdpend         := OR2 (sdpend, srcdxpend, srcdpend);
+Srcdreadt      := AN2 (srcdreadt, sdpend, read_ack);
+
+//2/9/92 - enhancement?
+//Load srcdread on the next tick as well to modify it in srcshade
+
+Srcdreadd      := FD1Q (srcdreadd, srcdreadt, clk);
+Srcdread       := AOR1 (srcdread, srcshade, srcdreadd, srcdreadt);
+
+// source zed reads
+
+Srczpset\      := NAN2 (srczpset\, readreq, szread);
+Srczpt1        := NAN2 (srczpt[1], srczpend, srczack\);
+Srczpt2                := NAN2 (srczpt[2], srczpset\, srczpt[1]);
+Srczpend       := FD2Q (srczpend, srczpt[2], clk, reset\);
+
+Srczxpset\     := NAN2 (srczxpset\, readreq, szreadx);
+Srczxpt1       := NAN2 (srczxpt[1], srczxpend, srczxack\);
+Srczxpt2       := NAN2 (srczxpt[2], srczxpset\, srczxpt[1]);
+Srczxpend      := FD2Q (srczxpend, srczxpt[2], clk, reset\);
+
+Szpend         := OR2 (szpend, srczpend, srczxpend);
+Srczread       := AN2 (srczread, szpend, read_ack);
+
+// destination data reads
+
+Dstdpset\      := NAN2 (dstdpset\, readreq, dread);
+Dstdpt0        := NAN2 (dstdpt[0], dstdpend, dstdack\);
+Dstdpt1                := NAN2 (dstdpt[1], dstdpset\, dstdpt[0]);
+Dstdpend       := FD2Q (dstdpend, dstdpt[1], clk, reset\);
+Dstdread       := AN2 (dstdread, dstdpend, read_ack);
+
+// destination zed reads
+
+Dstzpset\      := NAN2 (dstzpset\, readreq, dzread);
+Dstzpt0        := NAN2 (dstzpt[0], dstzpend, dstzack\);
+Dstzpt1                := NAN2 (dstzpt[1], dstzpset\, dstzpt[0]);
+Dstzpend       := FD2Q (dstzpend, dstzpt[1], clk, reset\);
+Dstzread       := AN2 (dstzread, dstzpend, read_ack);
+*/
+
+/*void foo2(void)
+{
+       // Basically, the above translates to:
+       bool srcdpend = (readreq && sread) || (srcdpend && !srcdack);
+       bool srcdxpend = (readreq && sreadx) || (srcdxpend && !srcdxack);
+       bool sdpend = srcxpend || srcdpend;
+       bool srcdread = ((sdpend && read_ack) && srcshade) || (sdpend && read_ack);//the latter term is lookahead
+
+}*/
+
+
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+// Here's an important bit: The source data adder logic. Need to track down the inputs!!! //
+////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////
+
+/*
+DEF ADDARRAY (
+INT16/  addq[0..3]
+        :OUT;
+        clk
+        daddasel[0..2]  // data adder input A selection
+        daddbsel[0..3]
+        daddmode[0..2]
+INT32/  dstd[0..1]
+INT32/  iinc
+        initcin[0..3]   // carry into the adders from the initializers
+        initinc[0..63]  // the initialisation increment
+        initpix[0..15]  // Data initialiser pixel value
+INT32/  istep
+INT32/  patd[0..1]
+INT32/  srcdlo
+INT32/  srcdhi
+INT32/  srcz1[0..1]
+INT32/  srcz2[0..1]
+        reset\
+INT32/  zinc
+INT32/  zstep
+        :IN);
+*/
+void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
+       uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
+       uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
+       uint32_t zinc, uint32_t zstep)
+{
+       uint32_t initpix2 = ((uint32_t)initpix << 16) | initpix;
+       uint32_t addalo[8], addahi[8];
+       addalo[0] = dstd & 0xFFFFFFFF;
+       addalo[1] = initpix2;
+       addalo[2] = 0;
+       addalo[3] = 0;
+       addalo[4] = srcd & 0xFFFFFFFF;
+       addalo[5] = patd & 0xFFFFFFFF;
+       addalo[6] = srcz1 & 0xFFFFFFFF;
+       addalo[7] = srcz2 & 0xFFFFFFFF;
+       addahi[0] = dstd >> 32;
+       addahi[1] = initpix2;
+       addahi[2] = 0;
+       addahi[3] = 0;
+       addahi[4] = srcd >> 32;
+       addahi[5] = patd >> 32;
+       addahi[6] = srcz1 >> 32;
+       addahi[7] = srcz2 >> 32;
+       uint16_t adda[4];
+       adda[0] = addalo[daddasel] & 0xFFFF;
+       adda[1] = addalo[daddasel] >> 16;
+       adda[2] = addahi[daddasel] & 0xFFFF;
+       adda[3] = addahi[daddasel] >> 16;
+
+       uint16_t wordmux[8];
+       wordmux[0] = iinc & 0xFFFF;
+       wordmux[1] = iinc >> 16;
+       wordmux[2] = zinc & 0xFFFF;
+       wordmux[3] = zinc >> 16;;
+       wordmux[4] = istep & 0xFFFF;
+       wordmux[5] = istep >> 16;;
+       wordmux[6] = zstep & 0xFFFF;
+       wordmux[7] = zstep >> 16;;
+       uint16_t word = wordmux[((daddbsel & 0x08) >> 1) | (daddbsel & 0x03)];
+       uint16_t addb[4];
+       bool dbsel2 = daddbsel & 0x04;
+       bool iincsel = (daddbsel & 0x01) && !(daddbsel & 0x04);
+
+       if (!dbsel2 && !iincsel)
+               addb[0] = srcd & 0xFFFF,
+               addb[1] = (srcd >> 16) & 0xFFFF,
+               addb[2] = (srcd >> 32) & 0xFFFF,
+               addb[3] = (srcd >> 48) & 0xFFFF;
+       else if (dbsel2 && !iincsel)
+               addb[0] = addb[1] = addb[2] = addb[3] = word;
+       else if (!dbsel2 && iincsel)
+               addb[0] = initinc & 0xFFFF,
+               addb[1] = (initinc >> 16) & 0xFFFF,
+               addb[2] = (initinc >> 32) & 0xFFFF,
+               addb[3] = (initinc >> 48) & 0xFFFF;
+       else
+               addb[0] = addb[1] = addb[2] = addb[3] = 0;
+
+       uint8_t cinsel = (daddmode >= 1 && daddmode <= 4 ? 1 : 0);
+
+static uint8_t co[4];//These are preserved between calls...
+       uint8_t cin[4];
+
+       for(int i=0; i<4; i++)
+               cin[i] = initcin[i] | (co[i] & cinsel);
+
+       bool eightbit = daddmode & 0x02;
+       bool sat = daddmode & 0x03;
+       bool hicinh = ((daddmode & 0x03) == 0x03);
+
+//Note that the carry out is saved between calls to this function...
+       for(int i=0; i<4; i++)
+               ADD16SAT(addq[i], co[i], adda[i], addb[i], cin[i], sat, eightbit, hicinh);
+}
+
+
+/*
+DEF ADD16SAT (
+INT16/  r               // result
+        co              // carry out
+        :IO;
+INT16/  a
+INT16/  b
+        cin
+        sat
+        eightbit
+        hicinh
+        :IN);
+*/
+void ADD16SAT(uint16_t &r, uint8_t &co, uint16_t a, uint16_t b, uint8_t cin, bool sat, bool eightbit, bool hicinh)
+{
+/*if (logBlit)
+{
+       printf("--> [sat=%s 8b=%s hicinh=%s] %04X + %04X (+ %u) = ", (sat ? "T" : "F"), (eightbit ? "T" : "F"), (hicinh ? "T" : "F"), a, b, cin);
+       fflush(stdout);
+}*/
+       uint8_t carry[4];
+       uint32_t qt = (a & 0xFF) + (b & 0xFF) + cin;
+       carry[0] = (qt & 0x0100 ? 1 : 0);
+       uint16_t q = qt & 0x00FF;
+       carry[1] = (carry[0] && !eightbit ? carry[0] : 0);
+       qt = (a & 0x0F00) + (b & 0x0F00) + (carry[1] << 8);
+       carry[2] = (qt & 0x1000 ? 1 : 0);
+       q |= qt & 0x0F00;
+       carry[3] = (carry[2] && !hicinh ? carry[2] : 0);
+       qt = (a & 0xF000) + (b & 0xF000) + (carry[3] << 12);
+       co = (qt & 0x10000 ? 1 : 0);
+       q |= qt & 0xF000;
+
+       uint8_t btop = (eightbit ? (b & 0x0080) >> 7 : (b & 0x8000) >> 15);
+       uint8_t ctop = (eightbit ? carry[0] : co);
+
+       bool saturate = sat && (btop ^ ctop);
+       bool hisaturate = saturate && !eightbit;
+/*if (logBlit)
+{
+       printf("bt=%u ct=%u s=%u hs=%u] ", btop, ctop, saturate, hisaturate);
+       fflush(stdout);
+}*/
+
+       r = (saturate ? (ctop ? 0x00FF : 0x0000) : q & 0x00FF);
+       r |= (hisaturate ? (ctop ? 0xFF00 : 0x0000) : q & 0xFF00);
+/*if (logBlit)
+{
+       printf("%04X (co=%u)\n", r, co);
+       fflush(stdout);
+}*/
+}
+
+
+/**  ADDAMUX - Address adder input A selection  *******************
+
+This module generates the data loaded into the address adder input A.  This is
+the update value, and can be one of four registers :  A1 step, A2 step, A1
+increment and A1 fraction.  It can complement these values to perform
+subtraction, and it can generate constants to increment / decrement the window
+pointers.
+
+addasel[0..2] select the register to add
+
+000    A1 step integer part
+001    A1 step fraction part
+010    A1 increment integer part
+011    A1 increment fraction part
+100    A2 step
+
+adda_xconst[0..2] generate a power of 2 in the range 1-64 or all zeroes when
+they are all 1.
+
+addareg selects register value to be added as opposed to constant
+value.
+
+suba_x, suba_y complement the X and Y values
+
+*/
+
+/*
+DEF ADDAMUX (
+INT16/ adda_x
+INT16/ adda_y
+       :OUT;
+       addasel[0..2]
+INT16/ a1_step_x
+INT16/ a1_step_y
+INT16/ a1_stepf_x
+INT16/ a1_stepf_y
+INT16/ a2_step_x
+INT16/ a2_step_y
+INT16/ a1_inc_x
+INT16/ a1_inc_y
+INT16/ a1_incf_x
+INT16/ a1_incf_y
+       adda_xconst[0..2]
+       adda_yconst
+       addareg
+       suba_x
+       suba_y :IN);
+*/
+void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y,
+       int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y,
+       int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst,
+       bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
+{
+
+/*INT16/       addac_x, addac_y, addar_x, addar_y, addart_x, addart_y,
+INT16/ addas_x, addas_y, suba_x16, suba_y16
+:LOCAL;
+BEGIN
+
+Zero           := TIE0 (zero);*/
+
+/* Multiplex the register terms */
+
+/*Addaselb[0-2]        := BUF8 (addaselb[0-2], addasel[0-2]);
+Addart_x       := MX4 (addart_x, a1_step_x, a1_stepf_x, a1_inc_x, a1_incf_x, addaselb[0..1]);
+Addar_x                := MX2 (addar_x, addart_x, a2_step_x, addaselb[2]);
+Addart_y       := MX4 (addart_y, a1_step_y, a1_stepf_y, a1_inc_y, a1_incf_y, addaselb[0..1]);
+Addar_y                := MX2 (addar_y, addart_y, a2_step_y, addaselb[2]);*/
+
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       int16_t xterm[4], yterm[4];
+       xterm[0] = a1_step_x, xterm[1] = a1_stepf_x, xterm[2] = a1_inc_x, xterm[3] = a1_incf_x;
+       yterm[0] = a1_step_y, yterm[1] = a1_stepf_y, yterm[2] = a1_inc_y, yterm[3] = a1_incf_y;
+       int16_t addar_x = (addasel & 0x04 ? a2_step_x : xterm[addasel & 0x03]);
+       int16_t addar_y = (addasel & 0x04 ? a2_step_y : yterm[addasel & 0x03]);
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* Generate a constant value - this is a power of 2 in the range
+0-64, or zero.  The control bits are adda_xconst[0..2], when they
+are all 1  the result is 0.
+Constants for Y can only be 0 or 1 */
+
+/*Addac_xlo    := D38H (addac_x[0..6], unused[0], adda_xconst[0..2]);
+Unused[0]      := DUMMY (unused[0]);
+
+Addac_x                := JOIN (addac_x, addac_x[0..6], zero, zero, zero, zero, zero, zero, zero, zero, zero);
+Addac_y                := JOIN (addac_y, adda_yconst, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero,
+                       zero, zero, zero, zero, zero);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       int16_t addac_x = (adda_xconst == 0x07 ? 0 : 1 << adda_xconst);
+       int16_t addac_y = (adda_yconst ? 0x01 : 0);
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* Select between constant value and register value */
+
+/*Addas_x              := MX2 (addas_x, addac_x, addar_x, addareg);
+Addas_y                := MX2 (addas_y, addac_y, addar_y, addareg);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       int16_t addas_x = (addareg ? addar_x : addac_x);
+       int16_t addas_y = (addareg ? addar_y : addac_y);
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* Complement these values (complement flag gives adder carry in)*/
+
+/*Suba_x16     := JOIN (suba_x16, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x,
+                       suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x);
+Suba_y16       := JOIN (suba_y16, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y,
+                       suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y);
+Adda_x         := EO (adda_x, suba_x16, addas_x);
+Adda_y         := EO (adda_y, suba_y16, addas_y);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       adda_x = addas_x ^ (suba_x ? 0xFFFF : 0x0000);
+       adda_y = addas_y ^ (suba_y ? 0xFFFF : 0x0000);
+//////////////////////////////////////////////////////////////////////////////////////
+
+//END;
+}
+
+
+/**  ADDBMUX - Address adder input B selection  *******************
+
+This module selects the register to be updated by the address
+adder.  This can be one of three registers, the A1 and A2
+pointers, or the A1 fractional part. It can also be zero, so that the step
+registers load directly into the pointers.
+*/
+
+/*DEF ADDBMUX (
+INT16/ addb_x
+INT16/ addb_y
+       :OUT;
+       addbsel[0..1]
+INT16/ a1_x
+INT16/ a1_y
+INT16/ a2_x
+INT16/ a2_y
+INT16/ a1_frac_x
+INT16/ a1_frac_y
+       :IN);
+INT16/ zero16 :LOCAL;
+BEGIN*/
+void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y,
+       int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y)
+{
+
+/*Zero         := TIE0 (zero);
+Zero16         := JOIN (zero16, zero, zero, zero, zero, zero, zero, zero,
+                       zero, zero, zero, zero, zero, zero, zero, zero, zero);
+Addbselb[0-1]  := BUF8 (addbselb[0-1], addbsel[0-1]);
+Addb_x         := MX4 (addb_x, a1_x, a2_x, a1_frac_x, zero16, addbselb[0..1]);
+Addb_y         := MX4 (addb_y, a1_y, a2_y, a1_frac_y, zero16, addbselb[0..1]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       int16_t xterm[4], yterm[4];
+       xterm[0] = a1_x, xterm[1] = a2_x, xterm[2] = a1_frac_x, xterm[3] = 0;
+       yterm[0] = a1_y, yterm[1] = a2_y, yterm[2] = a1_frac_y, yterm[3] = 0;
+       addb_x = xterm[addbsel & 0x03];
+       addb_y = yterm[addbsel & 0x03];
+//////////////////////////////////////////////////////////////////////////////////////
+
+//END;
+}
+
+
+/**  DATAMUX - Address local data bus selection  ******************
+
+Select between the adder output and the input data bus
+*/
+
+/*DEF DATAMUX (
+INT16/ data_x
+INT16/ data_y
+       :OUT;
+INT32/ gpu_din
+INT16/ addq_x
+INT16/ addq_y
+       addqsel
+       :IN);
+
+INT16/ gpu_lo, gpu_hi
+:LOCAL;
+BEGIN*/
+void DATAMUX(int16_t &data_x, int16_t &data_y, uint32_t gpu_din, int16_t addq_x, int16_t addq_y, bool addqsel)
+{
+/*Gpu_lo               := JOIN (gpu_lo, gpu_din{0..15});
+Gpu_hi         := JOIN (gpu_hi, gpu_din{16..31});
+
+Addqselb       := BUF8 (addqselb, addqsel);
+Data_x         := MX2 (data_x, gpu_lo, addq_x, addqselb);
+Data_y         := MX2 (data_y, gpu_hi, addq_y, addqselb);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       data_x = (addqsel ? addq_x : (int16_t)(gpu_din & 0xFFFF));
+       data_y = (addqsel ? addq_y : (int16_t)(gpu_din >> 16));
+//////////////////////////////////////////////////////////////////////////////////////
+
+//END;
+}
+
+
+/******************************************************************
+addradd
+29/11/90
+
+Blitter Address Adder
+---------------------
+The blitter address adder is a pair of sixteen bit adders, one
+each for X and Y.  The multiplexing of the input terms is
+performed elsewhere, but this adder can also perform modulo
+arithmetic to align X-addresses onto phrase boundaries.
+
+modx[0..2] take values
+000    no mask
+001    mask bit 0
+010    mask bits 1-0
+..
+110    mask bits 5-0
+
+******************************************************************/
+
+/*IMPORT duplo, tosh;
+
+DEF ADDRADD (
+INT16/ addq_x
+INT16/ addq_y
+               :OUT;
+               a1fracldi               // propagate address adder carry
+INT16/ adda_x
+INT16/ adda_y
+INT16/ addb_x
+INT16/ addb_y
+               clk[0]                  // co-processor clock
+               modx[0..2]
+               suba_x
+               suba_y
+               :IN);
+
+BEGIN
+
+Zero           := TIE0 (zero);*/
+void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
+       uint16_t adda_x, uint16_t adda_y, uint16_t addb_x, uint16_t addb_y, uint8_t modx, bool suba_x, bool suba_y)
+{
+
+/* Perform the addition */
+
+/*Adder_x              := ADD16 (addqt_x[0..15], co_x, adda_x{0..15}, addb_x{0..15}, ci_x);
+Adder_y                := ADD16 (addq_y[0..15], co_y, adda_y{0..15}, addb_y{0..15}, ci_y);*/
+
+/* latch carry and propagate if required */
+
+/*Cxt0         := AN2 (cxt[0], co_x, a1fracldi);
+Cxt1           := FD1Q (cxt[1], cxt[0], clk[0]);
+Ci_x           := EO (ci_x, cxt[1], suba_x);
+
+yt0                    := AN2 (cyt[0], co_y, a1fracldi);
+Cyt1           := FD1Q (cyt[1], cyt[0], clk[0]);
+Ci_y           := EO (ci_y, cyt[1], suba_y);*/
+
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+//I'm sure the following will generate a bunch of warnings, but will have to do for now.
+       static uint16_t co_x = 0, co_y = 0;     // Carry out has to propogate between function calls...
+       uint16_t ci_x = co_x ^ (suba_x ? 1 : 0);
+       uint16_t ci_y = co_y ^ (suba_y ? 1 : 0);
+       uint32_t addqt_x = adda_x + addb_x + ci_x;
+       uint32_t addqt_y = adda_y + addb_y + ci_y;
+       co_x = ((addqt_x & 0x10000) && a1fracldi ? 1 : 0);
+       co_y = ((addqt_y & 0x10000) && a1fracldi ? 1 : 0);
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* Mask low bits of X to 0 if required */
+
+/*Masksel              := D38H (unused[0], masksel[0..4], maskbit[5], unused[1], modx[0..2]);
+
+Maskbit[0-4]   := OR2 (maskbit[0-4], masksel[0-4], maskbit[1-5]);
+
+Mask[0-5]      := MX2 (addq_x[0-5], addqt_x[0-5], zero, maskbit[0-5]);
+
+Addq_x         := JOIN (addq_x, addq_x[0..5], addqt_x[6..15]);
+Addq_y         := JOIN (addq_y, addq_y[0..15]);*/
+
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       int16_t mask[8] = { 0xFFFF, 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, 0xFFE0, 0xFFC0, 0x0000 };
+       addq_x = addqt_x & mask[modx];
+       addq_y = addqt_y & 0xFFFF;
+//////////////////////////////////////////////////////////////////////////////////////
+
+//Unused[0-1]  := DUMMY (unused[0-1]);
+
+//END;
+}
+
+
+/*
+DEF DATA (
+               wdata[0..63]    // co-processor write data bus
+               :BUS;
+               dcomp[0..7]             // data byte equal flags
+               srcd[0..7]              // bits to use for bit to byte expansion
+               zcomp[0..3]             // output from Z comparators
+               :OUT;
+               a1_x[0..1]              // low two bits of A1 X pointer
+               big_pix                 // pixel organisation is big-endian
+               blitter_active  // blitter is active
+               clk                             // co-processor clock
+               cmpdst                  // compare dest rather than source
+               colorld                 // load the pattern color fields
+               daddasel[0..2]  // data adder input A selection
+               daddbsel[0..3]  // data adder input B selection
+               daddmode[0..2]  // data adder mode
+               daddq_sel               // select adder output vs. GPU data
+               data[0..63]             // co-processor read data bus
+               data_ena                // enable write data
+               data_sel[0..1]  // select data to write
+               dbinh\[0..7]    // byte oriented changed data inhibits
+               dend[0..5]              // end of changed write data zone
+               dpipe[0..1]             // load computed data pipe-line latch
+               dstart[0..5]    // start of changed write data zone
+               dstdld[0..1]    // dest data load (two halves)
+               dstzld[0..1]    // dest zed load (two halves)
+               ext_int                 // enable extended precision intensity calculations
+INT32/ gpu_din                 // GPU data bus
+               iincld                  // I increment load
+               iincldx                 // alternate I increment load
+               init_if                 // initialise I fraction phase
+               init_ii                 // initialise I integer phase
+               init_zf                 // initialise Z fraction phase
+               intld[0..3]             // computed intensities load
+               istepadd                // intensity step integer add
+               istepfadd               // intensity step fraction add
+               istepld                 // I step load
+               istepdld                // I step delta load
+               lfu_func[0..3]  // LFU function code
+               patdadd                 // pattern data gouraud add
+               patdld[0..1]    // pattern data load (two halves)
+               pdsel[0..1]             // select pattern data type
+               phrase_mode             // phrase write mode
+               reload                  // transfer contents of double buffers
+               reset\                  // system reset
+               srcd1ld[0..1]   // source register 1 load (two halves)
+               srcdread                // source data read load enable
+               srczread                // source zed read load enable
+               srcshift[0..5]  // source alignment shift
+               srcz1ld[0..1]   // source zed 1 load (two halves)
+               srcz2add                // zed fraction gouraud add
+               srcz2ld[0..1]   // source zed 2 load (two halves)
+               textrgb                 // texture mapping in RGB mode
+               txtd[0..63]             // data from the texture unit
+               zedld[0..3]             // computed zeds load
+               zincld                  // Z increment load
+               zmode[0..2]             // Z comparator mode
+               zpipe[0..1]             // load computed zed pipe-line latch
+               zstepadd                // zed step integer add
+               zstepfadd               // zed step fraction add
+               zstepld                 // Z step load
+               zstepdld                // Z step delta load
+               :IN);
+*/
+
+void DATA(uint64_t &wdata, uint8_t &dcomp, uint8_t &zcomp, bool &nowrite,
+       bool big_pix, bool cmpdst, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, bool daddq_sel, uint8_t data_sel,
+       uint8_t dbinh, uint8_t dend, uint8_t dstart, uint64_t dstd, uint32_t iinc, uint8_t lfu_func, uint64_t &patd, bool patdadd,
+       bool phrase_mode, uint64_t srcd, bool srcdread, bool srczread, bool srcz2add, uint8_t zmode,
+       bool bcompen, bool bkgwren, bool dcompen, uint8_t icount, uint8_t pixsize,
+       uint64_t &srcz, uint64_t dstz, uint32_t zinc)
+{
+/*
+  Stuff we absolutely *need* to have passed in/out:
+IN:
+  patdadd, dstd, srcd, patd, daddasel, daddbsel, daddmode, iinc, srcz1, srcz2, big_pix, phrase_mode, cmpdst
+OUT:
+  changed patd (wdata I guess...) (Nope. We pass it back directly now...)
+*/
+
+// Source data registers
+
+/*Data_src     := DATA_SRC (srcdlo, srcdhi, srcz[0..1], srczo[0..1], srczp[0..1], srcz1[0..1], srcz2[0..1], big_pix,
+                       clk, gpu_din, intld[0..3], local_data0, local_data1, srcd1ld[0..1], srcdread, srczread, srcshift[0..5],
+                       srcz1ld[0..1], srcz2add, srcz2ld[0..1], zedld[0..3], zpipe[0..1]);
+Srcd[0-7]      := JOIN (srcd[0-7], srcdlo{0-7});
+Srcd[8-31]     := JOIN (srcd[8-31], srcdlo{8-31});
+Srcd[32-63]    := JOIN (srcd[32-63], srcdhi{0-31});*/
+
+// Destination data registers
+
+/*Data_dst     := DATA_DST (dstd[0..63], dstz[0..1], clk, dstdld[0..1], dstzld[0..1], load_data[0..1]);
+Dstdlo         := JOIN (dstdlo, dstd[0..31]);
+Dstdhi         := JOIN (dstdhi, dstd[32..63]);*/
+
+// Pattern and Color data registers
+
+// Looks like this is simply another register file for the pattern data registers. No adding or anything funky
+// going on. Note that patd & patdv will output the same info.
+// Patdldl/h (patdld[0..1]) can select the local_data bus to overwrite the current pattern data...
+// Actually, it can be either patdld OR patdadd...!
+/*Data_pat     := DATA_PAT (colord[0..15], int0dp[8..10], int1dp[8..10], int2dp[8..10], int3dp[8..10], mixsel[0..2],
+                       patd[0..63], patdv[0..1], clk, colorld, dpipe[0], ext_int, gpu_din, intld[0..3], local_data0, local_data1,
+                       patdadd, patdld[0..1], reload, reset\);
+Patdlo         := JOIN (patdlo, patd[0..31]);
+Patdhi         := JOIN (patdhi, patd[32..63]);*/
+
+// Multiplying data Mixer (NOT IN JAGUAR I)
+
+/*Datamix              := DATAMIX (patdo[0..1], clk, colord[0..15], dpipe[1], dstd[0..63], int0dp[8..10], int1dp[8..10],
+                       int2dp[8..10], int3dp[8..10], mixsel[0..2], patd[0..63], pdsel[0..1], srcd[0..63], textrgb, txtd[0..63]);*/
+
+// Logic function unit
+
+/*Lfu          := LFU (lfu[0..1], srcdlo, srcdhi, dstdlo, dstdhi, lfu_func[0..3]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       uint64_t funcmask[2] = { 0, 0xFFFFFFFFFFFFFFFFLL };
+       uint64_t func0 = funcmask[lfu_func & 0x01];
+       uint64_t func1 = funcmask[(lfu_func >> 1) & 0x01];
+       uint64_t func2 = funcmask[(lfu_func >> 2) & 0x01];
+       uint64_t func3 = funcmask[(lfu_func >> 3) & 0x01];
+       uint64_t lfu = (~srcd & ~dstd & func0) | (~srcd & dstd & func1) | (srcd & ~dstd & func2) | (srcd & dstd & func3);
+//////////////////////////////////////////////////////////////////////////////////////
+
+// Increment and Step Registers
+
+// Does it do anything without the step add lines? Check it!
+// No. This is pretty much just a register file without the Jaguar II lines...
+/*Inc_step     := INC_STEP (iinc, istep[0..31], zinc, zstep[0..31], clk, ext_int, gpu_din, iincld, iincldx, istepadd,
+                       istepfadd, istepld, istepdld, reload, reset\, zincld, zstepadd, zstepfadd, zstepld, zstepdld);
+Istep          := JOIN (istep, istep[0..31]);
+Zstep          := JOIN (zstep, zstep[0..31]);*/
+
+// Pixel data comparator
+
+/*Datacomp     := DATACOMP (dcomp[0..7], cmpdst, dstdlo, dstdhi, patdlo, patdhi, srcdlo, srcdhi);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       dcomp = 0;
+       uint64_t cmpd = patd ^ (cmpdst ? dstd : srcd);
+
+       if ((cmpd & 0x00000000000000FFLL) == 0)
+               dcomp |= 0x01;
+       if ((cmpd & 0x000000000000FF00LL) == 0)
+               dcomp |= 0x02;
+       if ((cmpd & 0x0000000000FF0000LL) == 0)
+               dcomp |= 0x04;
+       if ((cmpd & 0x00000000FF000000LL) == 0)
+               dcomp |= 0x08;
+       if ((cmpd & 0x000000FF00000000LL) == 0)
+               dcomp |= 0x10;
+       if ((cmpd & 0x0000FF0000000000LL) == 0)
+               dcomp |= 0x20;
+       if ((cmpd & 0x00FF000000000000LL) == 0)
+               dcomp |= 0x40;
+       if ((cmpd & 0xFF00000000000000LL) == 0)
+               dcomp |= 0x80;
+//////////////////////////////////////////////////////////////////////////////////////
+
+// Zed comparator for Z-buffer operations
+
+/*Zedcomp              := ZEDCOMP (zcomp[0..3], srczp[0..1], dstz[0..1], zmode[0..2]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+//srczp is srcz pipelined, also it goes through a source shift as well...
+/*The shift is basically like so (each piece is 16 bits long):
+
+       0         1         2         3         4          5         6
+       srcz1lolo srcz1lohi srcz1hilo srcz1hihi srcrz2lolo srcz2lohi srcz2hilo
+
+with srcshift bits 4 & 5 selecting the start position
+*/
+//So... basically what we have here is:
+       zcomp = 0;
+
+       if ((((srcz & 0x000000000000FFFFLL) < (dstz & 0x000000000000FFFFLL)) && (zmode & 0x01))
+               || (((srcz & 0x000000000000FFFFLL) == (dstz & 0x000000000000FFFFLL)) && (zmode & 0x02))
+               || (((srcz & 0x000000000000FFFFLL) > (dstz & 0x000000000000FFFFLL)) && (zmode & 0x04)))
+               zcomp |= 0x01;
+
+       if ((((srcz & 0x00000000FFFF0000LL) < (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x01))
+               || (((srcz & 0x00000000FFFF0000LL) == (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x02))
+               || (((srcz & 0x00000000FFFF0000LL) > (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x04)))
+               zcomp |= 0x02;
+
+       if ((((srcz & 0x0000FFFF00000000LL) < (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x01))
+               || (((srcz & 0x0000FFFF00000000LL) == (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x02))
+               || (((srcz & 0x0000FFFF00000000LL) > (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x04)))
+               zcomp |= 0x04;
+
+       if ((((srcz & 0xFFFF000000000000LL) < (dstz & 0xFFFF000000000000LL)) && (zmode & 0x01))
+               || (((srcz & 0xFFFF000000000000LL) == (dstz & 0xFFFF000000000000LL)) && (zmode & 0x02))
+               || (((srcz & 0xFFFF000000000000LL) > (dstz & 0xFFFF000000000000LL)) && (zmode & 0x04)))
+               zcomp |= 0x08;
+
+//TEMP, TO TEST IF ZCOMP IS THE CULPRIT...
+//Nope, this is NOT the problem...
+//zcomp=0;
+// We'll do the comparison/bit/byte inhibits here, since that's they way it happens
+// in the real thing (dcomp goes out to COMP_CTRL and back into DATA through dbinh)...
+#if 1
+       uint8_t dbinht;
+//     bool nowrite;
+       COMP_CTRL(dbinht, nowrite,
+               bcompen, true/*big_pix*/, bkgwren, dcomp, dcompen, icount, pixsize, phrase_mode, srcd & 0xFF, zcomp);
+       dbinh = dbinht;
+//     dbinh = 0x00;
+#endif
+
+#if 1
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+       WriteLog("\n[dcomp=%02X zcomp=%02X dbinh=%02X]\n", dcomp, zcomp, dbinh);
+#endif
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+// 22 Mar 94
+// The data initializer - allows all four initial values to be computed from one (NOT IN JAGUAR I)
+
+/*Datinit              := DATINIT (initcin[0..3], initinc[0..63], initpix[0..15], a1_x[0..1], big_pix, clk, iinc, init_if, init_ii,
+                       init_zf, istep[0..31], zinc, zstep[0..31]);*/
+
+// Adder array for Z and intensity increments
+
+/*Addarray     := ADDARRAY (addq[0..3], clk, daddasel[0..2], daddbsel[0..3], daddmode[0..2], dstdlo, dstdhi, iinc,
+                       initcin[0..3], initinc[0..63], initpix[0..15], istep, patdv[0..1], srcdlo, srcdhi, srcz1[0..1],
+                       srcz2[0..1], reset\, zinc, zstep);*/
+/*void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
+       uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
+       uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
+       uint32_t zinc, uint32_t zstep)*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       uint16_t addq[4];
+       uint8_t initcin[4] = { 0, 0, 0, 0 };
+       ADDARRAY(addq, daddasel, daddbsel, daddmode, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
+
+       //This is normally done asynchronously above (thru local_data) when in patdadd mode...
+//And now it's passed back to the caller to be persistent between calls...!
+//But it's causing some serious fuck-ups in T2K now... !!! FIX !!! [DONE--???]
+//Weird! It doesn't anymore...!
+       if (patdadd)
+               patd = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
+//////////////////////////////////////////////////////////////////////////////////////
+
+// Local data bus multiplexer
+
+/*Local_mux    := LOCAL_MUX (local_data[0..1], load_data[0..1],
+       addq[0..3], gpu_din, data[0..63], blitter_active, daddq_sel);
+Local_data0    := JOIN (local_data0, local_data[0]);
+Local_data1    := JOIN (local_data1, local_data[1]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////
+
+// Data output multiplexer and tri-state drive
+
+/*Data_mux     := DATA_MUX (wdata[0..63], addq[0..3], big_pix, dstdlo, dstdhi, dstz[0..1], data_sel[0..1], data_ena,
+                       dstart[0..5], dend[0..5], dbinh\[0..7], lfu[0..1], patdo[0..1], phrase_mode, srczo[0..1]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+// NOTE: patdo comes from DATAMIX and can be considered the same as patd for Jaguar I
+
+//////////////////////////////////////////////////////////////////////////////////////
+//}
+
+/*DEF DATA_MUX (
+               wdata[0..63]    // co-processor rwrite data bus
+               :BUS;
+INT16/ addq[0..3]
+               big_pix                 // Pixel organisation is big-endian
+INT32/ dstdlo
+INT32/ dstdhi
+INT32/ dstzlo
+INT32/ dstzhi
+               data_sel[0..1]  // source of write data
+               data_ena                // enable write data onto read/write bus
+               dstart[0..5]    // start of changed write data
+               dend[0..5]              // end of changed write data
+               dbinh\[0..7]    // byte oriented changed data inhibits
+INT32/ lfu[0..1]
+INT32/ patd[0..1]
+               phrase_mode             // phrase write mode
+INT32/ srczlo
+INT32/ srczhi
+               :IN);*/
+
+/*INT32/       addql[0..1], ddatlo, ddathi zero32
+:LOCAL;
+BEGIN
+
+Phrase_mode\   := INV1 (phrase_mode\, phrase_mode);
+Zero           := TIE0 (zero);
+Zero32         := JOIN (zero32, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero);*/
+
+/* Generate a changed data mask */
+
+/*Edis         := OR6 (edis\, dend[0..5]);
+Ecoarse                := DECL38E (e_coarse\[0..7], dend[3..5], edis\);
+E_coarse[0]    := INV1 (e_coarse[0], e_coarse\[0]);
+Efine          := DECL38E (unused[0], e_fine\[1..7], dend[0..2], e_coarse[0]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       uint8_t decl38e[2][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
+               { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } };
+       uint8_t dech38[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+       uint8_t dech38el[2][8] = { { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
+               { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
+
+                       int en = (dend & 0x3F ? 1 : 0);
+       uint8_t e_coarse = decl38e[en][(dend & 0x38) >> 3];             // Actually, this is e_coarse inverted...
+       uint8_t e_fine = decl38e[(e_coarse & 0x01) ^ 0x01][dend & 0x07];
+       e_fine &= 0xFE;
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Scoarse              := DECH38 (s_coarse[0..7], dstart[3..5]);
+Sfen\          := INV1 (sfen\, s_coarse[0]);
+Sfine          := DECH38EL (s_fine[0..7], dstart[0..2], sfen\);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       uint8_t s_coarse = dech38[(dstart & 0x38) >> 3];
+       uint8_t s_fine = dech38el[(s_coarse & 0x01) ^ 0x01][dstart & 0x07];
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Maskt[0]     := BUF1 (maskt[0], s_fine[0]);
+Maskt[1-7]     := OAN1P (maskt[1-7], maskt[0-6], s_fine[1-7], e_fine\[1-7]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       uint16_t maskt = s_fine & 0x0001;
+       maskt |= (((maskt & 0x0001) || (s_fine & 0x02)) && (e_fine & 0x02) ? 0x0002 : 0x0000);
+       maskt |= (((maskt & 0x0002) || (s_fine & 0x04)) && (e_fine & 0x04) ? 0x0004 : 0x0000);
+       maskt |= (((maskt & 0x0004) || (s_fine & 0x08)) && (e_fine & 0x08) ? 0x0008 : 0x0000);
+       maskt |= (((maskt & 0x0008) || (s_fine & 0x10)) && (e_fine & 0x10) ? 0x0010 : 0x0000);
+       maskt |= (((maskt & 0x0010) || (s_fine & 0x20)) && (e_fine & 0x20) ? 0x0020 : 0x0000);
+       maskt |= (((maskt & 0x0020) || (s_fine & 0x40)) && (e_fine & 0x40) ? 0x0040 : 0x0000);
+       maskt |= (((maskt & 0x0040) || (s_fine & 0x80)) && (e_fine & 0x80) ? 0x0080 : 0x0000);
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* Produce a look-ahead on the ripple carry:
+masktla = s_coarse[0] . /e_coarse[0] */
+/*Masktla              := AN2 (masktla, s_coarse[0], e_coarse\[0]);
+Maskt[8]       := OAN1P (maskt[8], masktla, s_coarse[1], e_coarse\[1]);
+Maskt[9-14]    := OAN1P (maskt[9-14], maskt[8-13], s_coarse[2-7], e_coarse\[2-7]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       maskt |= (((s_coarse & e_coarse & 0x01) || (s_coarse & 0x02)) && (e_coarse & 0x02) ? 0x0100 : 0x0000);
+       maskt |= (((maskt & 0x0100) || (s_coarse & 0x04)) && (e_coarse & 0x04) ? 0x0200 : 0x0000);
+       maskt |= (((maskt & 0x0200) || (s_coarse & 0x08)) && (e_coarse & 0x08) ? 0x0400 : 0x0000);
+       maskt |= (((maskt & 0x0400) || (s_coarse & 0x10)) && (e_coarse & 0x10) ? 0x0800 : 0x0000);
+       maskt |= (((maskt & 0x0800) || (s_coarse & 0x20)) && (e_coarse & 0x20) ? 0x1000 : 0x0000);
+       maskt |= (((maskt & 0x1000) || (s_coarse & 0x40)) && (e_coarse & 0x40) ? 0x2000 : 0x0000);
+       maskt |= (((maskt & 0x2000) || (s_coarse & 0x80)) && (e_coarse & 0x80) ? 0x4000 : 0x0000);
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* The bit terms are mirrored for big-endian pixels outside phrase
+mode.  The byte terms are mirrored for big-endian pixels in phrase
+mode.  */
+
+/*Mirror_bit   := AN2M (mir_bit, phrase_mode\, big_pix);
+Mirror_byte    := AN2H (mir_byte, phrase_mode, big_pix);
+
+Masktb[14]     := BUF1 (masktb[14], maskt[14]);
+Masku[0]       := MX4 (masku[0],  maskt[0],  maskt[7],  maskt[14],  zero, mir_bit, mir_byte);
+Masku[1]       := MX4 (masku[1],  maskt[1],  maskt[6],  maskt[14],  zero, mir_bit, mir_byte);
+Masku[2]       := MX4 (masku[2],  maskt[2],  maskt[5],  maskt[14],  zero, mir_bit, mir_byte);
+Masku[3]       := MX4 (masku[3],  maskt[3],  maskt[4],  masktb[14], zero, mir_bit, mir_byte);
+Masku[4]       := MX4 (masku[4],  maskt[4],  maskt[3],  masktb[14], zero, mir_bit, mir_byte);
+Masku[5]       := MX4 (masku[5],  maskt[5],  maskt[2],  masktb[14], zero, mir_bit, mir_byte);
+Masku[6]       := MX4 (masku[6],  maskt[6],  maskt[1],  masktb[14], zero, mir_bit, mir_byte);
+Masku[7]       := MX4 (masku[7],  maskt[7],  maskt[0],  masktb[14], zero, mir_bit, mir_byte);
+Masku[8]       := MX2 (masku[8],  maskt[8],  maskt[13], mir_byte);
+Masku[9]       := MX2 (masku[9],  maskt[9],  maskt[12], mir_byte);
+Masku[10]      := MX2 (masku[10], maskt[10], maskt[11], mir_byte);
+Masku[11]      := MX2 (masku[11], maskt[11], maskt[10], mir_byte);
+Masku[12]      := MX2 (masku[12], maskt[12], maskt[9],  mir_byte);
+Masku[13]      := MX2 (masku[13], maskt[13], maskt[8],  mir_byte);
+Masku[14]      := MX2 (masku[14], maskt[14], maskt[0],  mir_byte);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       bool mir_bit = true/*big_pix*/ && !phrase_mode;
+       bool mir_byte = true/*big_pix*/ && phrase_mode;
+       uint16_t masku = maskt;
+
+       if (mir_bit)
+       {
+               masku &= 0xFF00;
+               masku |= (maskt >> 7) & 0x0001;
+               masku |= (maskt >> 5) & 0x0002;
+               masku |= (maskt >> 3) & 0x0004;
+               masku |= (maskt >> 1) & 0x0008;
+               masku |= (maskt << 1) & 0x0010;
+               masku |= (maskt << 3) & 0x0020;
+               masku |= (maskt << 5) & 0x0040;
+               masku |= (maskt << 7) & 0x0080;
+       }
+
+       if (mir_byte)
+       {
+               masku = 0;
+               masku |= (maskt >> 14) & 0x0001;
+               masku |= (maskt >> 13) & 0x0002;
+               masku |= (maskt >> 12) & 0x0004;
+               masku |= (maskt >> 11) & 0x0008;
+               masku |= (maskt >> 10) & 0x0010;
+               masku |= (maskt >> 9)  & 0x0020;
+               masku |= (maskt >> 8)  & 0x0040;
+               masku |= (maskt >> 7)  & 0x0080;
+
+               masku |= (maskt >> 5) & 0x0100;
+               masku |= (maskt >> 3) & 0x0200;
+               masku |= (maskt >> 1) & 0x0400;
+               masku |= (maskt << 1) & 0x0800;
+               masku |= (maskt << 3) & 0x1000;
+               masku |= (maskt << 5) & 0x2000;
+               masku |= (maskt << 7) & 0x4000;
+       }
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* The maskt terms define the area for changed data, but the byte
+inhibit terms can override these */
+
+/*Mask[0-7]    := AN2 (mask[0-7], masku[0-7], dbinh\[0]);
+Mask[8-14]     := AN2H (mask[8-14], masku[8-14], dbinh\[1-7]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       uint16_t mask = masku & (!(dbinh & 0x01) ? 0xFFFF : 0xFF00);
+       mask &= ~(((uint16_t)dbinh & 0x00FE) << 7);
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Addql[0]     := JOIN (addql[0], addq[0..1]);
+Addql[1]       := JOIN (addql[1], addq[2..3]);
+
+Dsel0b[0-1]    := BUF8 (dsel0b[0-1], data_sel[0]);
+Dsel1b[0-1]    := BUF8 (dsel1b[0-1], data_sel[1]);
+Ddatlo         := MX4 (ddatlo, patd[0], lfu[0], addql[0], zero32, dsel0b[0], dsel1b[0]);
+Ddathi         := MX4 (ddathi, patd[1], lfu[1], addql[1], zero32, dsel0b[1], dsel1b[1]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       uint64_t dmux[4];
+       dmux[0] = patd;
+       dmux[1] = lfu;
+       dmux[2] = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
+       dmux[3] = 0;
+       uint64_t ddat = dmux[data_sel];
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Zed_sel              := AN2 (zed_sel, data_sel[0..1]);
+Zed_selb[0-1]  := BUF8 (zed_selb[0-1], zed_sel);
+
+Dat[0-7]       := MX4 (dat[0-7],   dstdlo{0-7},   ddatlo{0-7},   dstzlo{0-7},   srczlo{0-7},   mask[0-7], zed_selb[0]);
+Dat[8-15]      := MX4 (dat[8-15],  dstdlo{8-15},  ddatlo{8-15},  dstzlo{8-15},  srczlo{8-15},  mask[8],   zed_selb[0]);
+Dat[16-23]     := MX4 (dat[16-23], dstdlo{16-23}, ddatlo{16-23}, dstzlo{16-23}, srczlo{16-23}, mask[9],   zed_selb[0]);
+Dat[24-31]     := MX4 (dat[24-31], dstdlo{24-31}, ddatlo{24-31}, dstzlo{24-31}, srczlo{24-31}, mask[10],  zed_selb[0]);
+Dat[32-39]     := MX4 (dat[32-39], dstdhi{0-7},   ddathi{0-7},   dstzhi{0-7},   srczhi{0-7},   mask[11],  zed_selb[1]);
+Dat[40-47]     := MX4 (dat[40-47], dstdhi{8-15},  ddathi{8-15},  dstzhi{8-15},  srczhi{8-15},  mask[12],  zed_selb[1]);
+Dat[48-55]     := MX4 (dat[48-55], dstdhi{16-23}, ddathi{16-23}, dstzhi{16-23}, srczhi{16-23}, mask[13],  zed_selb[1]);
+Dat[56-63]     := MX4 (dat[56-63], dstdhi{24-31}, ddathi{24-31}, dstzhi{24-31}, srczhi{24-31}, mask[14],  zed_selb[1]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       wdata = ((ddat & mask) | (dstd & ~mask)) & 0x00000000000000FFLL;
+       wdata |= (mask & 0x0100 ? ddat : dstd) & 0x000000000000FF00LL;
+       wdata |= (mask & 0x0200 ? ddat : dstd) & 0x0000000000FF0000LL;
+       wdata |= (mask & 0x0400 ? ddat : dstd) & 0x00000000FF000000LL;
+       wdata |= (mask & 0x0800 ? ddat : dstd) & 0x000000FF00000000LL;
+       wdata |= (mask & 0x1000 ? ddat : dstd) & 0x0000FF0000000000LL;
+       wdata |= (mask & 0x2000 ? ddat : dstd) & 0x00FF000000000000LL;
+       wdata |= (mask & 0x4000 ? ddat : dstd) & 0xFF00000000000000LL;
+/*if (logBlit)
+{
+       printf("\n[ddat=%08X%08X dstd=%08X%08X wdata=%08X%08X mask=%04X]\n",
+               (uint32_t)(ddat >> 32), (uint32_t)(ddat & 0xFFFFFFFF),
+               (uint32_t)(dstd >> 32), (uint32_t)(dstd & 0xFFFFFFFF),
+               (uint32_t)(wdata >> 32), (uint32_t)(wdata & 0xFFFFFFFF), mask);
+       fflush(stdout);
+}//*/
+//This is a crappy way of handling this, but it should work for now...
+       uint64_t zwdata;
+       zwdata = ((srcz & mask) | (dstz & ~mask)) & 0x00000000000000FFLL;
+       zwdata |= (mask & 0x0100 ? srcz : dstz) & 0x000000000000FF00LL;
+       zwdata |= (mask & 0x0200 ? srcz : dstz) & 0x0000000000FF0000LL;
+       zwdata |= (mask & 0x0400 ? srcz : dstz) & 0x00000000FF000000LL;
+       zwdata |= (mask & 0x0800 ? srcz : dstz) & 0x000000FF00000000LL;
+       zwdata |= (mask & 0x1000 ? srcz : dstz) & 0x0000FF0000000000LL;
+       zwdata |= (mask & 0x2000 ? srcz : dstz) & 0x00FF000000000000LL;
+       zwdata |= (mask & 0x4000 ? srcz : dstz) & 0xFF00000000000000LL;
+if (logBlit)
+{
+       WriteLog("\n[srcz=%08X%08X dstz=%08X%08X zwdata=%08X%08X mask=%04X]\n",
+               (uint32_t)(srcz >> 32), (uint32_t)(srcz & 0xFFFFFFFF),
+               (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF),
+               (uint32_t)(zwdata >> 32), (uint32_t)(zwdata & 0xFFFFFFFF), mask);
+//     fflush(stdout);
+}//*/
+       srcz = zwdata;
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Data_enab[0-1]       := BUF8 (data_enab[0-1], data_ena);
+Datadrv[0-31]  := TS (wdata[0-31],  dat[0-31],  data_enab[0]);
+Datadrv[32-63] := TS (wdata[32-63], dat[32-63], data_enab[1]);
+
+Unused[0]      := DUMMY (unused[0]);
+
+END;*/
+}
+
+
+/**  COMP_CTRL - Comparator output control logic  *****************
+
+This block is responsible for taking the comparator outputs and
+using them as appropriate to inhibit writes.  Two methods are
+supported for inhibiting write data:
+
+-      suppression of the inner loop controlled write operation
+-      a set of eight byte inhibit lines to write back dest data
+
+The first technique is used in pixel oriented modes, the second in
+phrase mode, but the phrase mode form is only applicable to eight
+and sixteen bit pixel modes.
+
+Writes can be suppressed by data being equal, by the Z comparator
+conditions being met, or by the bit to pixel expansion scheme.
+
+Pipe-lining issues: the data derived comparator outputs are stable
+until the next data read, well after the affected write from this
+operation.  However, the inner counter bits can count immediately
+before the ack for the last write.  Therefore, it is necessary to
+delay bcompbit select terms by one inner loop pipe-line stage,
+when generating the select for the data control - the output is
+delayed one further tick to give it write data timing (2/34).
+
+There is also a problem with computed data - the new values are
+calculated before the write associated with the old value has been
+performed.  The is taken care of within the zed comparator by
+pipe-lining the comparator inputs where appropriate.
+*/
+
+//#define LOG_COMP_CTRL
+/*DEF COMP_CTRL (
+       dbinh\[0..7]    // destination byte inhibit lines
+       nowrite         // suppress inner loop write operation
+       :OUT;
+       bcompen         // bit selector inhibit enable
+       big_pix         // pixels are big-endian
+       bkgwren         // enable dest data write in pix inhibit
+       clk             // co-processor clock
+       dcomp[0..7]     // output of data byte comparators
+       dcompen         // data comparator inhibit enable
+       icount[0..2]    // low bits of inner count
+       pixsize[0..2]   // destination pixel size
+       phrase_mode     // phrase write mode
+       srcd[0..7]      // bits to use for bit to byte expansion
+       step_inner      // inner loop advance
+       zcomp[0..3]     // output of word zed comparators
+       :IN);*/
+void COMP_CTRL(uint8_t &dbinh, bool &nowrite,
+       bool bcompen, bool big_pix, bool bkgwren, uint8_t dcomp, bool dcompen, uint8_t icount,
+       uint8_t pixsize, bool phrase_mode, uint8_t srcd, uint8_t zcomp)
+{
+//BEGIN
+
+/*Bkgwren\     := INV1 (bkgwren\, bkgwren);
+Phrase_mode\   := INV1 (phrase_mode\, phrase_mode);
+Pixsize\[0-2]  := INV2 (pixsize\[0-2], pixsize[0-2]);*/
+
+/* The bit comparator bits are derived from the source data, which
+will have been suitably aligned for phrase mode.  The contents of
+the inner counter are used to select which bit to use.
+
+When not in phrase mode the inner count value is used to select
+one bit.  It is assumed that the count has already occurred, so,
+7 selects bit 0, etc.  In big-endian pixel mode, this turns round,
+so that a count of 7 selects bit 7.
+
+In phrase mode, the eight bits are used directly, and this mode is
+only applicable to 8-bit pixel mode (2/34) */
+
+/*Bcompselt[0-2]       := EO (bcompselt[0-2], icount[0-2], big_pix);
+Bcompbit       := MX8 (bcompbit, srcd[7], srcd[6], srcd[5],
+                       srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompselt[0..2]);
+Bcompbit\      := INV1 (bcompbit\, bcompbit);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("\n     [bcompen=%s dcompen=%s phrase_mode=%s bkgwren=%s dcomp=%02X zcomp=%02X]", (bcompen ? "T" : "F"), (dcompen ? "T" : "F"), (phrase_mode ? "T" : "F"), (bkgwren ? "T" : "F"), dcomp, zcomp);
+       WriteLog("\n     ");
+//     fflush(stdout);
+}
+#endif
+       uint8_t bcompselt = (big_pix ? ~icount : icount) & 0x07;
+       uint8_t bitmask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+       bool bcompbit = srcd & bitmask[bcompselt];
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* pipe-line the count */
+/*Bcompsel[0-2]        := FDSYNC (bcompsel[0-2], bcompselt[0-2], step_inner, clk);
+Bcompbt                := MX8 (bcompbitpt, srcd[7], srcd[6], srcd[5],
+                       srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompsel[0..2]);
+Bcompbitp      := FD1Q (bcompbitp, bcompbitpt, clk);
+Bcompbitp\     := INV1 (bcompbitp\, bcompbitp);*/
+
+/* For pixel mode, generate the write inhibit signal for all modes
+on bit inhibit, for 8 and 16 bit modes on comparator inhibit, and
+for 16 bit mode on Z inhibit
+
+Nowrite = bcompen . /bcompbit . /phrase_mode
+       + dcompen . dcomp[0] . /phrase_mode . pixsize = 011
+       + dcompen . dcomp[0..1] . /phrase_mode . pixsize = 100
+       + zcomp[0] . /phrase_mode . pixsize = 100
+*/
+
+/*Nowt0                := NAN3 (nowt[0], bcompen, bcompbit\, phrase_mode\);
+Nowt1          := ND6  (nowt[1], dcompen, dcomp[0], phrase_mode\, pixsize\[2], pixsize[0..1]);
+Nowt2          := ND7  (nowt[2], dcompen, dcomp[0..1], phrase_mode\, pixsize[2], pixsize\[0..1]);
+Nowt3          := NAN5 (nowt[3], zcomp[0], phrase_mode\, pixsize[2], pixsize\[0..1]);
+Nowt4          := NAN4 (nowt[4], nowt[0..3]);
+Nowrite                := AN2  (nowrite, nowt[4], bkgwren\);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       nowrite = ((bcompen && !bcompbit && !phrase_mode)
+               || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
+               || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
+               || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4)))
+               && !bkgwren;
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Winht                := NAN3 (winht, bcompen, bcompbitp\, phrase_mode\);
+Winhibit       := NAN4 (winhibit, winht, nowt[1..3]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+//This is the same as above, but with bcompbit delayed one tick and called 'winhibit'
+//Small difference: Besides the pipeline effect, it's also not using !bkgwren...
+//     bool winhibit = (bcompen && !
+       bool winhibit = (bcompen && !bcompbit && !phrase_mode)
+               || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
+               || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
+               || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4));
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[nw=%s wi=%s]", (nowrite ? "T" : "F"), (winhibit ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+/* For phrase mode, generate the byte inhibit signals for eight bit
+mode 011, or sixteen bit mode 100
+dbinh\[0] =  pixsize[2] . zcomp[0]
+        +  pixsize[2] . dcomp[0] . dcomp[1] . dcompen
+        + /pixsize[2] . dcomp[0] . dcompen
+        + /srcd[0] . bcompen
+
+Inhibits 0-3 are also used when not in phrase mode to write back
+destination data.
+*/
+
+/*Srcd\[0-7]   := INV1 (srcd\[0-7], srcd[0-7]);
+
+Di0t0          := NAN2H (di0t[0], pixsize[2], zcomp[0]);
+Di0t1          := NAN4H (di0t[1], pixsize[2], dcomp[0..1], dcompen);
+Di0t2          := NAN2 (di0t[2], srcd\[0], bcompen);
+Di0t3          := NAN3 (di0t[3], pixsize\[2], dcomp[0], dcompen);
+Di0t4          := NAN4 (di0t[4], di0t[0..3]);
+Dbinh[0]       := ANR1P (dbinh\[0], di0t[4], phrase_mode, winhibit);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       dbinh = 0;
+       bool di0t0_1 = ((pixsize & 0x04) && (zcomp & 0x01))
+               || ((pixsize & 0x04) && (dcomp & 0x01) && (dcomp & 0x02) && dcompen);
+       bool di0t4 = di0t0_1
+               || (!(srcd & 0x01) && bcompen)
+               || (!(pixsize & 0x04) && (dcomp & 0x01) && dcompen);
+       dbinh |= (!((di0t4 && phrase_mode) || winhibit) ? 0x01 : 0x00);
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[di0t0_1=%s di0t4=%s]", (di0t0_1 ? "T" : "F"), (di0t4 ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Di1t0                := NAN3 (di1t[0], pixsize\[2], dcomp[1], dcompen);
+Di1t1          := NAN2 (di1t[1], srcd\[1], bcompen);
+Di1t2          := NAN4 (di1t[2], di0t[0..1], di1t[0..1]);
+Dbinh[1]       := ANR1 (dbinh\[1], di1t[2], phrase_mode, winhibit);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       bool di1t2 = di0t0_1
+               || (!(srcd & 0x02) && bcompen)
+               || (!(pixsize & 0x04) && (dcomp & 0x02) && dcompen);
+       dbinh |= (!((di1t2 && phrase_mode) || winhibit) ? 0x02 : 0x00);
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[di1t2=%s]", (di1t2 ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Di2t0                := NAN2H (di2t[0], pixsize[2], zcomp[1]);
+Di2t1          := NAN4H (di2t[1], pixsize[2], dcomp[2..3], dcompen);
+Di2t2          := NAN2 (di2t[2], srcd\[2], bcompen);
+Di2t3          := NAN3 (di2t[3], pixsize\[2], dcomp[2], dcompen);
+Di2t4          := NAN4 (di2t[4], di2t[0..3]);
+Dbinh[2]       := ANR1 (dbinh\[2], di2t[4], phrase_mode, winhibit);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+//[bcompen=F dcompen=T phrase_mode=T bkgwren=F][nw=F wi=F]
+//[di0t0_1=F di0t4=F][di1t2=F][di2t0_1=T di2t4=T][di3t2=T][di4t0_1=F di2t4=F][di5t2=F][di6t0_1=F di6t4=F][di7t2=F]
+//[dcomp=$00 dbinh=$0C][7804780400007804] (icount=0005, inc=4)
+       bool di2t0_1 = ((pixsize & 0x04) && (zcomp & 0x02))
+               || ((pixsize & 0x04) && (dcomp & 0x04) && (dcomp & 0x08) && dcompen);
+       bool di2t4 = di2t0_1
+               || (!(srcd & 0x04) && bcompen)
+               || (!(pixsize & 0x04) && (dcomp & 0x04) && dcompen);
+       dbinh |= (!((di2t4 && phrase_mode) || winhibit) ? 0x04 : 0x00);
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[di2t0_1=%s di2t4=%s]", (di2t0_1 ? "T" : "F"), (di2t4 ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Di3t0                := NAN3 (di3t[0], pixsize\[2], dcomp[3], dcompen);
+Di3t1          := NAN2 (di3t[1], srcd\[3], bcompen);
+Di3t2          := NAN4 (di3t[2], di2t[0..1], di3t[0..1]);
+Dbinh[3]       := ANR1 (dbinh\[3], di3t[2], phrase_mode, winhibit);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       bool di3t2 = di2t0_1
+               || (!(srcd & 0x08) && bcompen)
+               || (!(pixsize & 0x04) && (dcomp & 0x08) && dcompen);
+       dbinh |= (!((di3t2 && phrase_mode) || winhibit) ? 0x08 : 0x00);
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[di3t2=%s]", (di3t2 ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Di4t0                := NAN2H (di4t[0], pixsize[2], zcomp[2]);
+Di4t1          := NAN4H (di4t[1], pixsize[2], dcomp[4..5], dcompen);
+Di4t2          := NAN2 (di4t[2], srcd\[4], bcompen);
+Di4t3          := NAN3 (di4t[3], pixsize\[2], dcomp[4], dcompen);
+Di4t4          := NAN4 (di4t[4], di4t[0..3]);
+Dbinh[4]       := NAN2 (dbinh\[4], di4t[4], phrase_mode);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       bool di4t0_1 = ((pixsize & 0x04) && (zcomp & 0x04))
+               || ((pixsize & 0x04) && (dcomp & 0x10) && (dcomp & 0x20) && dcompen);
+       bool di4t4 = di4t0_1
+               || (!(srcd & 0x10) && bcompen)
+               || (!(pixsize & 0x04) && (dcomp & 0x10) && dcompen);
+       dbinh |= (!(di4t4 && phrase_mode) ? 0x10 : 0x00);
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[di4t0_1=%s di2t4=%s]", (di4t0_1 ? "T" : "F"), (di4t4 ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Di5t0                := NAN3 (di5t[0], pixsize\[2], dcomp[5], dcompen);
+Di5t1          := NAN2 (di5t[1], srcd\[5], bcompen);
+Di5t2          := NAN4 (di5t[2], di4t[0..1], di5t[0..1]);
+Dbinh[5]       := NAN2 (dbinh\[5], di5t[2], phrase_mode);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       bool di5t2 = di4t0_1
+               || (!(srcd & 0x20) && bcompen)
+               || (!(pixsize & 0x04) && (dcomp & 0x20) && dcompen);
+       dbinh |= (!(di5t2 && phrase_mode) ? 0x20 : 0x00);
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[di5t2=%s]", (di5t2 ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Di6t0                := NAN2H (di6t[0], pixsize[2], zcomp[3]);
+Di6t1          := NAN4H (di6t[1], pixsize[2], dcomp[6..7], dcompen);
+Di6t2          := NAN2 (di6t[2], srcd\[6], bcompen);
+Di6t3          := NAN3 (di6t[3], pixsize\[2], dcomp[6], dcompen);
+Di6t4          := NAN4 (di6t[4], di6t[0..3]);
+Dbinh[6]       := NAN2 (dbinh\[6], di6t[4], phrase_mode);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       bool di6t0_1 = ((pixsize & 0x04) && (zcomp & 0x08))
+               || ((pixsize & 0x04) && (dcomp & 0x40) && (dcomp & 0x80) && dcompen);
+       bool di6t4 = di6t0_1
+               || (!(srcd & 0x40) && bcompen)
+               || (!(pixsize & 0x04) && (dcomp & 0x40) && dcompen);
+       dbinh |= (!(di6t4 && phrase_mode) ? 0x40 : 0x00);
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[di6t0_1=%s di6t4=%s]", (di6t0_1 ? "T" : "F"), (di6t4 ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*Di7t0                := NAN3 (di7t[0], pixsize\[2], dcomp[7], dcompen);
+Di7t1          := NAN2 (di7t[1], srcd\[7], bcompen);
+Di7t2          := NAN4 (di7t[2], di6t[0..1], di7t[0..1]);
+Dbinh[7]       := NAN2 (dbinh\[7], di7t[2], phrase_mode);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       bool di7t2 = di6t0_1
+               || (!(srcd & 0x80) && bcompen)
+               || (!(pixsize & 0x04) && (dcomp & 0x80) && dcompen);
+       dbinh |= (!(di7t2 && phrase_mode) ? 0x80 : 0x00);
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[di7t2=%s]", (di7t2 ? "T" : "F"));
+//     fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+//END;
+//kludge
+dbinh = ~dbinh;
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       WriteLog("[dcomp=$%02X dbinh=$%02X]\n    ", dcomp, dbinh);
+//     fflush(stdout);
+}
+#endif
+}
+
+
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////
+
+// !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
+// !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
+// !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
+
+#endif
+