]> Shamusworld >> Repos - virtualjaguar/commitdiff
1st semi-stable iteration of the new blitter
authorShamus Hammons <jlhamm@acm.org>
Sat, 6 Aug 2005 03:24:25 +0000 (03:24 +0000)
committerShamus Hammons <jlhamm@acm.org>
Sat, 6 Aug 2005 03:24:25 +0000 (03:24 +0000)
src/blitter.cpp

index ce4f0d7a83f539bc337bef7171a54329334d9a95..5baf7a551a20d97425079e233317ef40ee16c697 100644 (file)
@@ -1,17 +1,44 @@
 //
 // Blitter core
 //
-// Originally by David Raingeard
-// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
-// Extensive cleanups/fixes by James L. Hammons
+// by James L. Hammons
 //
+// 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.
+//
+
+#include "jaguar.h"
+#include "blitter.h"
+
+// Various conditional compilation goodies...
+
+//#define USE_ORIGINAL_BLITTER
+//#define USE_MIDSUMMER_BLITTER
+#define USE_MIDSUMMER_BLITTER_MKII
+
+// External global variables
+
+extern int jaguar_active_memory_dumps;
+
+// Local global variables
+
+int start_logging = 0;
+uint8 blitter_working = 0;
+
+// Blitter register RAM (most of it is hidden from the user)
+
+static uint8 blitter_ram[0x100];
+
+// Other crapola
 
 bool specialLog = false;
 extern int effect_start;
 extern int blit_start_log;
-
-#include "jaguar.h"
-#include "blitter.h"
+void BlitterMidsummer(uint32 cmd);
+void BlitterMidsummer2(void);
 
 #define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
                                | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
@@ -25,8 +52,8 @@ extern int blit_start_log;
 #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_FSTEP               ((UINT32)0x14)  // Fractional part of the step
+#define A1_FPIXEL              ((UINT32)0x18)  // Fractional part of the pixel (Y.f and X.f)
 #define A1_INC                 ((UINT32)0x1C)  // Integer part of the increment
 #define A1_FINC                        ((UINT32)0x20)  // Fractional part of the increment
 #define A2_BASE                        ((UINT32)0x24)
@@ -35,7 +62,7 @@ extern int blit_start_log;
 #define A2_PIXEL               ((UINT32)0x30)  // Integer part of the pixel (no fractional part for A2)
 #define A2_STEP                        ((UINT32)0x34)  // Integer part of the step (no fractional part for A2)
 #define COMMAND                        ((UINT32)0x38)
-#define PIXLINECOUNTER ((UINT32)0x3C)
+#define PIXLINECOUNTER ((UINT32)0x3C)  // Inner & outer loop values
 #define SRCDATA                        ((UINT32)0x40)
 #define DSTDATA                        ((UINT32)0x48)
 #define DSTZ                   ((UINT32)0x50)
@@ -107,6 +134,11 @@ extern int blit_start_log;
 #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)
@@ -228,19 +260,6 @@ extern int blit_start_log;
        case 5: WRITE_PIXEL_32(a,d); break;  \
        }}
 
-// External global variables
-
-extern int jaguar_active_memory_dumps;
-
-// Local global variables
-
-int start_logging = 0;
-uint8 blitter_working = 0;
-
-// Blitter register RAM (most of it is hidden from the user)
-
-static uint8 blitter_ram[0x100];
-
 // Width in Pixels of a Scanline
 // 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
@@ -394,6 +413,7 @@ if (specialLog)
                                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 & 0x0001C020)      // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
@@ -402,6 +422,7 @@ if (specialLog)
                                else    // Use SRCDATA register...
                                {
                                        srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
+
                                        if (cmd & 0x0001C020)           // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
                                                srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
                                }
@@ -410,6 +431,7 @@ if (specialLog)
                                if (DSTEN)
                                {
                                        dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
+
                                        if (DSTENZ)
                                                dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
                                        else
@@ -418,6 +440,7 @@ if (specialLog)
                                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);
                                }
@@ -434,9 +457,9 @@ if (specialLog)
                                        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
 // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
@@ -730,9 +753,9 @@ Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cm
                                        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
 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
@@ -785,7 +808,7 @@ Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cm
                                        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 (ADDDSEL)
                                        {
@@ -935,10 +958,13 @@ Lesse, with pre-add we'd have:
 */
 //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
@@ -1015,10 +1041,12 @@ Lesse, with pre-add we'd have:
 
                //Not entirely: This still mucks things up... !!! FIX !!!
                //Should this go before or after the phrase mode mucking around?
-/*             a1_x += a1_step_x;
+#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 
@@ -1060,8 +1088,7 @@ void blitter_blit(uint32 cmd)
        
        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);
+
        a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
        a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
 
@@ -1232,21 +1259,21 @@ WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
        // Gouraud shading
        if (GOURD || GOURZ || SRCSHADE)
        {
-               gd_c[0] = blitter_ram[PATTERNDATA + 0];
-               gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
-                       | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
+               gd_c[0] = blitter_ram[PATTERNDATA + 6];
+               gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
+                       | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 1];
 
-               gd_c[1] = blitter_ram[PATTERNDATA + 2];
-               gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
-                       | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
+               gd_c[1] = blitter_ram[PATTERNDATA + 4];
+               gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
+                       | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 3];
 
-               gd_c[2] = blitter_ram[PATTERNDATA + 4];
-               gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
-                       | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
+               gd_c[2] = blitter_ram[PATTERNDATA + 2];
+               gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
+                       | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 5];
 
-               gd_c[3] = blitter_ram[PATTERNDATA + 6];
-               gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
-                       | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
+               gd_c[3] = blitter_ram[PATTERNDATA + 0];
+               gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
+                       | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 7];
 
                gouraud_add = REG(INTENSITYINC);
                
@@ -1487,6 +1514,10 @@ if (blit_start_log)
 
        blitter_working = 0;
 }
+#endif                                                                                 // of the #if 0 near the top...
+/*******************************************************************************
+********************** STUFF CUT ABOVE THIS LINE! ******************************
+*******************************************************************************/
 
 void blitter_init(void)
 {
@@ -1509,15 +1540,19 @@ uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
 
        // 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...
        if (offset == (0x38 + 3))
                return 0x01;    // always idle
 
-//Attempted fix for AvP:
+// CHECK HERE ONCE THIS FIX HAS BEEN TESTED: [ ]
+//Fix for AvP:
        if (offset >= 0x04 && offset <= 0x07)
-//             return (offset > 0x05 ? blitter_ram[PIXLINECOUNTER + offset - 0x04] : 0x00);
-//             return 0x00;    // WO register! What does it expect to see here???
 //This is it. I wonder if it just ignores the lower three bits?
-               return blitter_ram[A1_PIXEL + offset - 0x04];
+//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];
 }
@@ -1539,63 +1574,94 @@ void BlitterWriteByte(uint32 offset, uint8 data, uint32 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);
+}//*/
 
-//     if ((offset >= 0x7C) && (offset <= 0x9B))
        // This handles writes to INTENSITY0-3 by also writing them to their proper places in
        // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
-       if ((offset >= 0x7C) && (offset <= 0x9B))//8B))
+       if ((offset >= 0x7C) && (offset <= 0x9B))
        {
                switch (offset)
                {
                // INTENSITY registers 0-3
                case 0x7C: break;
-               case 0x7D: blitter_ram[PATTERNDATA + 1] = data; break;
-               case 0x7E: blitter_ram[SRCDATA + 0] = data; break;
-               case 0x7F: blitter_ram[SRCDATA + 1] = data; break;
+               case 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[PATTERNDATA + 3] = data; break;
-               case 0x82: blitter_ram[SRCDATA + 2] = data; break;
-               case 0x83: blitter_ram[SRCDATA + 3] = 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[PATTERNDATA + 5] = data; break;
-               case 0x86: blitter_ram[SRCDATA + 4] = data; break;
-               case 0x87: blitter_ram[SRCDATA + 5] = 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 + 7] = data; break;
-               case 0x8A: blitter_ram[SRCDATA + 6] = data; break;
-               case 0x8B: blitter_ram[SRCDATA + 7] = data; 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 + 0] = data; break;
-               case 0x8D: blitter_ram[SRCZINT + 1] = data; break;
-               case 0x8E: blitter_ram[SRCZFRAC + 0] = data; break;
-               case 0x8F: blitter_ram[SRCZFRAC + 1] = data; break;
-
-               case 0x90: blitter_ram[SRCZINT + 2] = data; break;
-               case 0x91: blitter_ram[SRCZINT + 3] = data; break;
-               case 0x92: blitter_ram[SRCZFRAC + 2] = data; break;
-               case 0x93: blitter_ram[SRCZFRAC + 3] = data; break;
+               case 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 + 4] = data; break;
-               case 0x95: blitter_ram[SRCZINT + 5] = data; break;
-               case 0x96: blitter_ram[SRCZFRAC + 4] = data; break;
-               case 0x97: blitter_ram[SRCZFRAC + 5] = data; break;
+               case 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 + 6] = data; break;
-               case 0x99: blitter_ram[SRCZINT + 7] = data; break;
-               case 0x9A: blitter_ram[SRCZFRAC + 6] = data; break;
-               case 0x9B: blitter_ram[SRCZFRAC + 7] = data; break;
+               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 BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
 {
+/*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)
        {
@@ -1611,13 +1677,12 @@ doGPUDis = true;
        }//*/
 //#endif
 
-       BlitterWriteByte(offset+0, (data>>8) & 0xFF, who);
-       BlitterWriteByte(offset+1, data & 0xFF, who);
+       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)
@@ -1625,13 +1690,25 @@ if (blit_start_log)
        WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
        doGPUDis = true;
 }//*/
+#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
 }
 //F02278,9,A,B
 
 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
 {
+/*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)
        {
@@ -1641,53 +1718,4114 @@ doGPUDis = true;
        }//*/
 //#endif
 
-       BlitterWriteWord(offset, data >> 16, who);
-       BlitterWriteWord(offset+2, data & 0xFFFF, who);
+       BlitterWriteWord(offset + 0, data >> 16, who);
+       BlitterWriteWord(offset + 2, data & 0xFFFF, who);
 }
 
 void LogBlit(void)
 {
+       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 cmd = GET32(blitter_ram, 0x38);
+       UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
+       UINT32 a1_width = ((0x04 | m) << e) >> 2;
+       m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
+       UINT32 a2_width = ((0x04 | m) << e) >> 2;
 
        WriteLog("Blit!\n");
-       WriteLog("  cmd      = %08X\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    = %s\n", (DSTEN ? "1" : "0"));
+       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)GET16(blitter_ram, A1_PIXEL + 2), (int16)GET16(blitter_ram, A1_PIXEL + 0), GET32(blitter_ram, A1_PIXEL));
+       WriteLog("  a1_step  = %d, %d (%08X)\n", (int16)GET16(blitter_ram, A1_STEP + 2), (int16)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)GET16(blitter_ram, A1_INC + 2), (int16)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)GET16(blitter_ram, A2_PIXEL + 2), (int16)GET16(blitter_ram, A2_PIXEL + 0), GET32(blitter_ram, A2_PIXEL));
+       WriteLog("  a2_step  = %d, %d (%08X)\n", (int16)GET16(blitter_ram, A2_STEP + 2), (int16)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("  PATDSEL  = %s\n", (PATDSEL ? "1" : "0"));
-       WriteLog("  COLOR    = %08X\n", REG(PATTERNDATA));
-       WriteLog("  DCOMPEN  = %s\n", (DCOMPEN ? "1" : "0"));
-       WriteLog("  BCOMPEN  = %s\n", (BCOMPEN ? "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("  GOURZ    = %s\n", (GOURZ ? "1" : "0"));
-       WriteLog("  GOURD    = %s\n", (GOURD ? "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"));
 }
+
+
+#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 cmd)
+{
+uint32 outer_loop, inner_loop, a1_addr, a2_addr;
+int32 a1_x, a1_y, a2_x, a2_y, a1_width, a2_width;
+uint8 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 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 srcData = GET64(blitter_ram, SRCDATA), srcXtraData,
+               dstData = GET64(blitter_ram, DSTDATA), writeData;
+       uint32 srcAddr, dstAddr;
+       uint8 bitCount, a1PixelSize, a2PixelSize;
+
+       // JTRM says phrase mode only works for 8BPP or higher, so let's try this...
+       uint32 phraseOffset[8] = { 8, 8, 8, 8, 4, 2, 0, 0 };
+       uint8 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 pixAddr = ((DSTA2 ? a1_x : a2_x) >> 16)
+//                     + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
+               int32 pixAddr = (int16)((DSTA2 ? a1_x : a2_x) >> 16)
+                       + ((int16)((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)JaguarReadLong(srcAddr, BLITTER) << 32)
+                       | (uint64)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)(srcData >> 32), (uint32)(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 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
+//             + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
+       int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
+               + ((int16)((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)JaguarReadLong(srcAddr, BLITTER) << 32)
+                       | (uint64)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)(dstData >> 32), (uint32)(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 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 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
+//                     + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
+               int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
+                       + ((int16)((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)(writeData >> 32), (uint32)(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)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)  // Fractional part of the step
+#define A1_FPIXEL              ((UINT32)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)((int16)GET16(blitter_ram, A1_FSTEP + 2));
+//     a1_y += (int32)((int16)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)(GET16(blitter_ram, A1_STEP + 2) << 16);
+       a1_y += (int32)(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)(GET16(blitter_ram, A2_STEP + 2) << 16);
+       a2_y += (int32)(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 a collection of various blits that aren't handled correctly yet...
+
+Spinning cube in Jaguar BIOS opening:
+
+  COMMAND  = 41802F41
+  a1_base  = 0015B000
+  a1_flags = 00033020 (0 0 0 11 . 011000 000 100 . 00)
+             pitch=0, pixSz=4, zOff=0, width=64, xCtrl=3
+  a1_clip  = 64, 64 (00400040)
+  a1_pixel = 0, 65534 (FFFE0000)
+  a1_step  = -64, -1 (FFFFFFC0)
+  a1_fstep = 0, 18161 (46F10000)
+  a1_fpixel= 32768, 42497 (A6018000)
+  a1_inc   = 1, 0 (00000001)
+  a1_finc  = 0, 1926 (07860000)
+  a2_base  = 0014B000
+  a2_flags = 00013820 (0 0 0 01 0 011100 000 100 . 00)
+             pitch=0, pixSz=4, zOff=0, width=128, xCtrl=1
+  a2_mask  = 0, 0 (00000000)
+  a2_pixel = 33, 55 (00370021)
+  a2_step  = -64, 1 (0001FFC0)
+  count    = 64 x 57
+  SRCEN    = 1
+  SRCENZ   = 0
+  SRCENX   = 0
+  DSTEN    = 0
+  DSTENZ   = 0
+  DSTWRZ   = 0
+  CLIPA1   = 1
+  UPDA1F   = 1
+  UPDA1    = 1
+  UPDA2    = 1
+  DSTA2    = 1
+  ZOP      =
+--LFUFUNC  = LFU_REPLACE
+| PATDSEL  = 0 (PD=0000000000000000)
+--ADDDSEL  = 0
+  CMPDST   = 0
+  BCOMPEN  = 0
+  DCOMPEN  = 0
+  TOPBEN   = 0
+  TOPNEN   = 0
+  BKGWREN  = 0
+  GOURD    = 0 (II=00FCDC80, SD=FF00FF00FF00FF00)
+  GOURZ    = 1 (ZI=00000000, ZD=0000000000000000, SZ1=0000000000000000, SZ2=0000000000000000)
+  SRCSHADE = 1
+
+*/
+
+#ifdef USE_MIDSUMMER_BLITTER_MKII
+// Here's attempt #2--taken from the Oberon chip specs!
+
+void ADDRGEN(uint32 &, uint32 &, bool, bool,
+       uint16, uint16, uint32, uint8, uint8, uint8, uint8,
+       uint16, uint16, uint32, uint8, uint8, uint8, uint8);
+void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
+       uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
+       uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
+       uint32 zinc, uint32 zstep);
+void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh);
+void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, 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, uint8 adda_xconst,
+       bool adda_yconst, bool addareg, bool suba_x, bool suba_y);
+void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
+       int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y);
+void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel);
+void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
+       uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y);
+void DATA (uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
+       bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
+       uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 patd, bool patdadd,
+       bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
+       bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize);
+void COMP_CTRL(uint8 &dbinh, bool &nowrite,
+       bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
+       uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp);
+#define VERBOSE_BLITTER_LOGGING
+bool logBlit = false;
+
+void BlitterMidsummer2(void)
+{
+       // 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 cmd = GET32(blitter_ram, COMMAND);
+
+// $01800005 has SRCENX, may have to investigate further...
+// $00011008 has GOURD & DSTEN.
+// $41802F41 has SRCSHADE, CLIPA1
+logBlit = false;
+/*if (
+       cmd != 0x00010200
+       && cmd != 0x01800001
+       && 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    // 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
+       )
+       logBlit = true;//*/
+
+//printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
+//fflush(stdout);
+
+       // 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 zmode = (cmd & 0x01C0000) >> 18, lfufunc = (cmd & 0x1E00000) >> 21;
+//Missing: ZMODE, LFUFUNC, 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);
+printf("\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" : ""));
+printf("  count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
+fflush(stdout);
+}
+#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 ocount = GET16(blitter_ram, PIXLINECOUNTER);
+       uint8 a1_pitch = blitter_ram[A1_FLAGS + 3] & 0x03;
+       uint8 a2_pitch = blitter_ram[A2_FLAGS + 3] & 0x03;
+       uint8 a1_pixsize = (blitter_ram[A1_FLAGS + 3] & 0x38) >> 3;
+       uint8 a2_pixsize = (blitter_ram[A2_FLAGS + 3] & 0x38) >> 3;
+       uint8 a1_zoffset = (GET16(blitter_ram, A1_FLAGS + 2) >> 6) & 0x07;
+       uint8 a2_zoffset = (GET16(blitter_ram, A2_FLAGS + 2) >> 6) & 0x07;
+       uint8 a1_width = (blitter_ram[A1_FLAGS + 2] >> 1) & 0x3F;
+       uint8 a2_width = (blitter_ram[A2_FLAGS + 2] >> 1) & 0x3F;
+       bool a2_mask = blitter_ram[A2_FLAGS + 2] & 0x80;
+       uint8 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 a1_base = GET32(blitter_ram, A1_BASE) & 0xFFFFFFF8;      // Phrase aligned by ignoring bottom 3 bits
+       uint32 a2_base = GET32(blitter_ram, A2_BASE) & 0xFFFFFFF8;
+
+       uint16 a1_win_x = GET16(blitter_ram, A1_CLIP + 2) & 0x7FFF;
+       uint16 a1_win_y = GET16(blitter_ram, A1_CLIP + 0) & 0x7FFF;
+       int16 a1_x = (int16)GET16(blitter_ram, A1_PIXEL + 2);
+       int16 a1_y = (int16)GET16(blitter_ram, A1_PIXEL + 0);
+       int16 a1_step_x = (int16)GET16(blitter_ram, A1_STEP + 2);
+       int16 a1_step_y = (int16)GET16(blitter_ram, A1_STEP + 0);
+       uint16 a1_stepf_x = GET16(blitter_ram, A1_FSTEP + 2);
+       uint16 a1_stepf_y = GET16(blitter_ram, A1_FSTEP + 0);
+       uint16 a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
+       uint16 a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
+       int16 a1_inc_x = (int16)GET16(blitter_ram, A1_INC + 2);
+       int16 a1_inc_y = (int16)GET16(blitter_ram, A1_INC + 0);
+       uint16 a1_incf_x = GET16(blitter_ram, A1_FINC + 2);
+       uint16 a1_incf_y = GET16(blitter_ram, A1_FINC + 0);
+
+       int16 a2_x = (int16)GET16(blitter_ram, A2_PIXEL + 2);
+       int16 a2_y = (int16)GET16(blitter_ram, A2_PIXEL + 0);
+       uint16 a2_mask_x = GET16(blitter_ram, A2_MASK + 2);
+       uint16 a2_mask_y = GET16(blitter_ram, A2_MASK + 0);
+       int16 a2_step_x = (int16)GET16(blitter_ram, A2_STEP + 2);
+       int16 a2_step_y = (int16)GET16(blitter_ram, A2_STEP + 0);
+
+       uint64 srcd1 = GET64(blitter_ram, SRCDATA);
+       uint64 srcd2 = 0;
+       uint64 dstd = GET64(blitter_ram, DSTDATA);
+       uint64 patd = GET64(blitter_ram, PATTERNDATA);
+       uint32 iinc = GET32(blitter_ram, INTENSITYINC);
+       uint64 srcz1 = GET64(blitter_ram, SRCZINT);
+       uint64 srcz2 = GET64(blitter_ram, SRCZFRAC);
+       uint64 dstz = GET64(blitter_ram, DSTZ);
+       uint32 zinc = GET32(blitter_ram, ZINC);
+       uint32 collision = GET32(blitter_ram, COLLISIONCTRL);// 0=RESUME, 1=ABORT, 2=STOPEN
+
+       uint8 pixsize = (dsta2 ? a2_pixsize : a1_pixsize);      // From ACONTROL
+
+//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);
+}
+       // 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)
+{
+printf("  a1_base = %08X, a2_base = %08X\n", a1_base, a2_base);
+printf("  a1_x = %04X, a1_y = %04X, a1_frac_x = %04X, a1_frac_y = %04X, a2_x = %04X, a2_y = %04X\n", (uint16)a1_x, (uint16)a1_y, a1_frac_x, a1_frac_y, (uint16)a2_x, (uint16)a2_y);
+printf("  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)a1_step_x, (uint16)a1_step_y, a1_stepf_x, a1_stepf_y, (uint16)a2_step_x, (uint16)a2_step_y);
+printf("  a1_inc_x = %04X, a1_inc_y = %04X, a1_incf_x = %04X, a1_incf_y = %04X\n", (uint16)a1_inc_x, (uint16)a1_inc_y, a1_incf_x, a1_incf_y);
+printf("  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" };
+printf("  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"));
+printf("  a1_pixsize = %u, a2_pixsize = %u\n", a1_pixsize, a2_pixsize);
+printf("   srcd=%08X%08X  dstd=%08X%08X patd=%08X%08X iinc=%08X\n",
+       (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF),
+       (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
+       (uint32)(patd >> 32), (uint32)(patd & 0xFFFFFFFF), iinc);
+printf("  srcz1=%08X%08X srcz2=%08X%08X dstz=%08X%08X zinc=%08X, coll=%X\n",
+       (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
+       (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF),
+       (uint32)(dstz >> 32), (uint32)(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)
+{
+printf("  Phrase mode is %s\n", (phrase_mode ? "ON" : "off"));
+fflush(stdout);
+}
+#endif
+
+       // Stopgap vars to simulate various lines
+
+       uint16 a1FracCInX = 0, a1FracCInY = 0;
+
+       while (true)
+       {
+               // IDLE
+       
+               if ((idle && !go) || (inner && outer0 && indone))
+               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  Entering IDLE state...\n");
+fflush(stdout);
+}
+#endif
+                       idlei = true;
+
+                       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)
+{
+printf("  [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'));
+fflush(stdout);
+}
+#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)
+{
+printf("  Entering INNER state...\n");
+fflush(stdout);
+}
+#endif
+                       uint16 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 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)
+{
+printf("  Entering IDLE_INNER state...\n");
+fflush(stdout);
+}
+#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 || szreadi || 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 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 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 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 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 maska1 = (a1_add && a1addx == 0 ? 6 - a1_pixsize : 0);
+                               uint8 maska2 = (a2_add && a2addx == 0 ? 6 - a2_pixsize : 0);
+                               uint8 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 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 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 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 data_sel = ((!patdsel && !adddsel) || dzwrite ? 0x01 : 0x00)
+       | (adddsel || dzwrite ? 0x02 : 0x00);
+
+uint32 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 dstxp = (dsta2 ? a2_x : a1_x) & 0x3F;
+uint8 srcxp = (dsta2 ? a1_x : a2_x) & 0x3F;
+uint8 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 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 loshd = (pobbsel ? pobb : shftv) & 0x07;
+uint8 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)
+{
+printf("  Entering SREADX state...");
+//printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
+fflush(stdout);
+}
+#endif
+//uint32 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)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
+//Kludge to take pixel size into account...
+if (!phrase_mode)
+{
+       if (pixsize == 5)
+               srcd1 >>= 32;
+       else if (pixsize == 4)
+               srcd1 >>= 48;
+       else
+               srcd1 >>= 56;
+}
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("    Source extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
+       (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
+fflush(stdout);
+}
+#endif
+                               }
+
+                               if (szreadx)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  Entering SZREADX state...\n");
+fflush(stdout);
+}
+#endif
+                               }
+
+                               if (sread)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  Entering SREAD state...");
+//printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
+fflush(stdout);
+}
+#endif
+//uint32 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)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
+//Kludge to take pixel size into account...
+if (!phrase_mode)
+{
+       if (pixsize == 5)
+               srcd1 >>= 32;
+       else if (pixsize == 4)
+               srcd1 >>= 48;
+       else
+               srcd1 >>= 56;
+}
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("    Source read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
+       (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
+fflush(stdout);
+}
+#endif
+                               }
+
+                               if (szread)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  Entering SZREADX state...\n");
+fflush(stdout);
+}
+#endif
+                               }
+
+                               if (dread)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  Entering DREAD state...\n");
+fflush(stdout);
+}
+#endif
+//uint32 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)JaguarReadLong(address, BLITTER) << 32) | (uint64)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)
+{
+printf("      Dest read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
+       (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF));
+fflush(stdout);
+}
+#endif
+                               }
+
+                               if (dzread)
+                               {
+// Is Z always 64 bit read? Or sometimes 16 bit (dependent on phrase_mode)?
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       printf("  Entering DZREAD state...");
+       fflush(stdout);
+}
+#endif
+                                       dstz = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+       printf("    Dest Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
+               (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
+       fflush(stdout);
+}
+#endif
+                               }
+
+//NOTE: SRCSHADE requires GOURZ to be set to work properly--another Jaguar I bug
+                               if (dwrite)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  Entering DWRITE state...\n");
+fflush(stdout);
+}
+#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 inct = -((dsta2 ? a2_x : a1_x) & 0x07);    // From INNER_CNT
+                                       uint8 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 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 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 dstxwr = (dsta2 ? a2_x : a1_x) & 0x7FFE;
+uint16 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 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 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 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 pma = pixAddr + (1 << pixsize);
+/* Select the mask */
+uint8 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 pwidth = (((dend | dstart) & 0x07) == 0 ? 0x08 : (dend - dstart) & 0x07);
+
+//uint32 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)
+{
+printf("     Dest write address/pix address: %08X/%1X", address, pixAddr);
+printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
+fflush(stdout);
+printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
+fflush(stdout);
+}
+#endif
+
+//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.
+// 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 srcd = (srcd2 << (64 - srcshift)) | (srcd1 >> srcshift);
+//bleh, ugly ugly ugly
+if (srcshift == 0)
+       srcd = srcd1;
+
+//Temporary kludge, to see if the fractional pattern does anything...
+//This works, BTW
+if (patfadd)
+{
+       uint16 addq[4];
+       uint8 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)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)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
+
+//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 addq[4];
+       uint8 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)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
+}
+//Seems to work... Not 100% sure tho.
+//end try this
+
+bool winhibit;// = false;
+uint64 wdata;
+uint8 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);
+//     bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize)
+
+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 !!!
+if (clip_a1 && ((a1_x & 0x8000) || (a1_y & 0x8000) || (a1_x >= a1_win_x) || (a1_y >= a1_win_y)))
+       winhibit = true;
+
+/*if (dcompen)
+{
+//This is currently not correct for phrase mode. !!! FIX !!!
+       if ((pixsize == 3 && (dcomp & 0x01))
+               || (pixsize == 4 && (dcomp & 0x03)))
+               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)
+{
+       printf(" [%08X%08X]", (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF));
+       fflush(stdout);
+}
+#endif
+}
+
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf(" (icount=%04X, inc=%u)\n", icount, (uint16)inc);
+fflush(stdout);
+}
+#endif
+                               }
+
+                               if (dzwrite)
+                               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  Entering DZWRITE state...\n");
+fflush(stdout);
+}
+#endif
+                               }
+
+                               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"));
+printf("  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 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)
+{
+printf("  [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"));
+printf("  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 &adda_x, int16 &adda_y, uint8 addasel, 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, uint8 adda_xconst,
+//     bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
+//void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
+//     int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
+//void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
+//     int16 adda_x, int16 adda_y, int16 addb_x, int16 addb_y, uint8 modx, bool suba_x, bool suba_y)
+//void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
+int16 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)
+{
+printf("  [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)
+{
+printf("  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)
+{
+printf(" (ocount=%04X)\n", ocount);
+fflush(stdout);
+}
+#endif
+               }
+
+               if (a1fupdate)
+               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  Entering A1FUPDATE state...\n");
+fflush(stdout);
+}
+#endif
+                       uint32 a1_frac_xt = (uint32)a1_frac_x + (uint32)a1_stepf_x;
+                       uint32 a1_frac_yt = (uint32)a1_frac_y + (uint32)a1_stepf_y;
+                       a1FracCInX = a1_frac_xt >> 16;
+                       a1FracCInY = a1_frac_yt >> 16;
+                       a1_frac_x = (uint16)(a1_frac_xt & 0xFFFF);
+                       a1_frac_y = (uint16)(a1_frac_yt & 0xFFFF);
+               }
+
+               if (a1update)
+               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  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)
+{
+printf("%d/%d)\n", a1_x, a1_y);
+fflush(stdout);
+}
+#endif
+               }
+               
+               if (a2update)
+               {
+#ifdef VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("  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)
+{
+printf("%d/%d)\n", a2_x, a2_y);
+fflush(stdout);
+}
+#endif
+               }
+       }
+
+       // Write values back to registers (in real blitter, these are continuously updated)
+       SET16(blitter_ram, A1_PIXEL + 0, a1_y);
+       SET16(blitter_ram, A1_PIXEL + 2, a1_x);
+       SET16(blitter_ram, A1_FPIXEL + 0, a1_frac_y);
+       SET16(blitter_ram, A1_FPIXEL + 2, a1_frac_x);
+       SET16(blitter_ram, A2_PIXEL + 0, a2_y);
+       SET16(blitter_ram, A2_PIXEL + 2, a2_x);
+}
+
+
+/*
+The latest that doesn't work properly:
+
+Blit! (CMD = 09800741)
+Flags: SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 LFUFUNC=C DCOMPEN
+  count = 15 x 18
+  a1_base = 00050000, a2_base = 0083F400
+  a1_x = 003D, a1_y = 00AD, a1_frac_x = 8000, a1_frac_y = 0000, a2_x = 0027, a2_y = 00A4
+  a1_step_x = FFF1, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFF1, 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=+inc/+0 a2add=+1/+0
+  a1_pixsize = 4, a2_pixsize = 4
+   srcd=0000000000000000  dstd=0000000000000000 patd=0000000000000000 iinc=00FFF000
+  srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, col=2
+  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: 00858E4E/0 [0000000000000000]
+  Entering A2_ADD state [a2_x=0027, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0007077A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=000E, inc=1)
+  Entering A1_ADD state [a1_x=003D, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E50/0 [0000000000000000]
+  Entering A2_ADD state [a2_x=0028, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0007077C/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=000D, inc=1)
+  Entering A1_ADD state [a1_x=003E, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E52/0 [0000000000000000]
+  Entering A2_ADD state [a2_x=0029, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0007077E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=000C, inc=1)
+  Entering A1_ADD state [a1_x=003F, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E54/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=002A, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070780/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=000B, inc=1)
+  Entering A1_ADD state [a1_x=0040, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E56/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=002B, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070782/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=000A, inc=1)
+  Entering A1_ADD state [a1_x=0041, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E58/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=002C, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070784/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0009, inc=1)
+  Entering A1_ADD state [a1_x=0042, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E5A/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=002D, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070786/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0008, inc=1)
+  Entering A1_ADD state [a1_x=0043, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E5C/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=002E, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070788/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0007, inc=1)
+  Entering A1_ADD state [a1_x=0044, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E5E/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=002F, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0007078A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0006, inc=1)
+  Entering A1_ADD state [a1_x=0045, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E60/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=0030, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0007078C/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0005, inc=1)
+  Entering A1_ADD state [a1_x=0046, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E62/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=0031, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 0007078E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0004, inc=1)
+  Entering A1_ADD state [a1_x=0047, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E64/0 [000000000000014A]
+  Entering A2_ADD state [a2_x=0032, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070790/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0003, inc=1)
+  Entering A1_ADD state [a1_x=0048, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E66/0 [0000000000000000]
+  Entering A2_ADD state [a2_x=0033, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070792/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=0002, inc=1)
+  Entering A1_ADD state [a1_x=0049, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E68/0 [0000000000000000]
+  Entering A2_ADD state [a2_x=0034, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070794/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=0001, inc=1)
+  Entering A1_ADD state [a1_x=004A, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering SREAD state...    Source read address/pix address: 00858E6A/0 [0000000000000000]
+  Entering A2_ADD state [a2_x=0035, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
+  Entering DWRITE state...
+     Dest write address/pix address: 00070796/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=0000, inc=1)
+  Entering A1_ADD state [a1_x=004B, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
+  Entering IDLE_INNER state...
+  Leaving INNER state... (ocount=0011)
+  [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... (76/173 -> 61/174)
+  [in=F a1f=F a1=F zf=F z=F a2=T iif=F iii=F izf=F izi=F]
+  Entering A2UPDATE state... (54/164 -> 39/165)
+  [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
+  Entering INNER state...
+*/
+
+
+// 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 &address, uint32 &pixa, bool gena2, bool zaddr,
+       uint16 a1_x, uint16 a1_y, uint32 a1_base, uint8 a1_pitch, uint8 a1_pixsize, uint8 a1_width, uint8 a1_zoffset,
+       uint16 a2_x, uint16 a2_y, uint32 a2_base, uint8 a2_pitch, uint8 a2_pixsize, uint8 a2_width, uint8 a2_zoffset)
+{
+       uint16 x = (gena2 ? a2_x : a1_x) & 0x7FFF;
+       uint16 y = (gena2 ? a2_y : a1_y) & 0x0FFF;
+       uint8 width = (gena2 ? a2_width : a1_width);
+       uint8 pixsize = (gena2 ? a2_pixsize : a1_pixsize);
+       uint8 pitch = (gena2 ? a2_pitch : a1_pitch);
+       uint32 base = (gena2 ? a2_base : a1_base) >> 3;//Only upper 21 bits are passed around the bus? Seems like it...
+       uint8 zoffset = (gena2 ? a2_zoffset : a1_zoffset);
+
+       uint32 ytm = ((uint32)y << 2) + (width & 0x02 ? (uint32)y << 1 : 0) + (width & 0x01 ? (uint32)y : 0);
+
+       uint32 ya = (ytm << (width >> 2)) >> 2;
+
+       uint32 pa = ya + x;
+
+       /*uint32*/ pixa = pa << pixsize;
+
+       uint8 pt = ((pitch & 0x01) && !(pitch & 0x02) ? 0x01 : 0x00)
+               | (!(pitch & 0x01) && (pitch & 0x02) ? 0x02 : 0x00);
+//     uint32 phradr = pixa << pt;
+       uint32 phradr = (pixa >> 6) << pt;
+       uint32 shup = (pitch == 0x03 ? (pixa >> 6) : 0);
+
+       uint8 za = (zaddr ? zoffset : 0) & 0x03;
+//     uint32 addr = za + (phradr & 0x07) + (shup << 1) + base;
+       uint32 addr = za + phradr + (shup << 1) + base;
+       /*uint32*/ address = ((pixa & 0x38) >> 3) | ((addr & 0x1FFFFF) << 3);
+#if 0//def VERBOSE_BLITTER_LOGGING
+if (logBlit)
+{
+printf("    [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);
+printf("    [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 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
+       uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
+       uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
+       uint32 zinc, uint32 zstep)
+{
+       uint32 initpix2 = ((uint32)initpix << 16) | initpix;
+       uint32 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 adda[4];
+       adda[0] = addalo[daddasel] & 0xFFFF;
+       adda[1] = addalo[daddasel] >> 16;
+       adda[2] = addahi[daddasel] & 0xFFFF;
+       adda[3] = addahi[daddasel] >> 16;
+
+       uint16 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 word = wordmux[((daddbsel & 0x08) >> 1) | (daddbsel & 0x03)];
+       uint16 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 cinsel = (daddmode >= 1 && daddmode <= 4 ? 1 : 0);
+
+static uint8 co[4];//These are preserved between calls...
+       uint8 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 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh)
+{
+       uint8 carry[4];
+       uint32 qt = (a & 0xFF) + (b & 0xFF) + cin;
+       carry[0] = (qt & 0x0100 ? 1 : 0);
+       uint16 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 btop = (eightbit ? (b & 0x0080) >> 7 : (b & 0x8000) >> 15);
+       uint8 ctop = (eightbit ? carry[0] : co);
+
+       bool saturate = sat && (btop ^ ctop);
+       bool hisaturate = saturate && !eightbit;
+
+       r = (saturate ? (ctop ? 0x00FF : 0x0000) : q & 0x00FF);
+       r |= (hisaturate ? (ctop ? 0xFF00 : 0x0000) : q & 0xFF00);
+}
+
+/**  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 &adda_x, int16 &adda_y, uint8 addasel, 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, uint8 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 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 addar_x = (addasel & 0x04 ? a2_step_x : xterm[addasel & 0x03]);
+       int16 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 addac_x = (adda_xconst == 0x07 ? 0 : 1 << adda_xconst);
+       int16 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 addas_x = (addareg ? addar_x : addac_x);
+       int16 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 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
+       int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 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 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 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 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)(gpu_din & 0xFFFF));
+       data_y = (addqsel ? addq_y : (int16)(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 &addq_x, int16 &addq_y, bool a1fracldi,
+       uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 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 co_x = 0, co_y = 0;       // Carry out has to propogate between function calls...
+       uint16 ci_x = co_x ^ (suba_x ? 1 : 0);
+       uint16 ci_y = co_y ^ (suba_y ? 1 : 0);
+       uint32 addqt_x = adda_x + addb_x + ci_x;
+       uint32 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 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 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
+       bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
+       uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 patd, bool patdadd,
+       bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
+       bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize)
+{
+/*
+  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...)
+*/
+
+// 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 funcmask[2] = { 0, 0xFFFFFFFFFFFFFFFFLL };
+       uint64 func0 = funcmask[lfu_func & 0x01];
+       uint64 func1 = funcmask[(lfu_func >> 1) & 0x01];
+       uint64 func2 = funcmask[(lfu_func >> 2) & 0x01];
+       uint64 func3 = funcmask[(lfu_func >> 3) & 0x01];
+       uint64 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 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;
+// 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 dbinht;
+//     bool nowrite;
+       COMP_CTRL(dbinht, nowrite,
+               bcompen, true/*big_pix*/, bkgwren, dcomp, dcompen, icount, pixsize, phrase_mode, srcd & 0xFF, 0);//zcomp);
+       dbinh = dbinht;
+//     dbinh = 0x00;
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+// Zed comparator for Z-buffer operations
+
+/*Zedcomp              := ZEDCOMP (zcomp[0..3], srczp[0..1], dstz[0..1], zmode[0..2]);*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+// 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 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
+       uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
+       uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
+       uint32 zinc, uint32 zstep)*/
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+       uint16 addq[4];
+       uint8 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...
+       if (patdadd)
+               patd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)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 decl38e[2][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
+               { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } };
+       uint8 dech38[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
+       uint8 dech38el[2][8] = { { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
+               { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF } };
+
+                       int en = (dend & 0x3F ? 1 : 0);
+       uint8 e_coarse = decl38e[en][(dend & 0x38) >> 3];               // Actually, this is e_coarse inverted...
+       uint8 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 s_coarse = dech38[(dstart & 0x38) >> 3];
+       uint8 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 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 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 mask = masku & (!(dbinh & 0x01) ? 0xFFFF : 0xFF00);
+       mask &= ~(((uint16)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 dmux[4];
+       dmux[0] = patd;
+       dmux[1] = lfu;
+       dmux[2] = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
+       dmux[3] = 0;
+       uint64 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;
+//////////////////////////////////////////////////////////////////////////////////////
+
+/*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 &dbinh, bool &nowrite,
+       bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
+       uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 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)
+{
+       printf("\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);
+       printf("\n     ");
+       fflush(stdout);
+}
+#endif
+       uint8 bcompselt = (big_pix ? ~icount : icount) & 0x07;
+       uint8 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)
+{
+       printf("[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)
+{
+       printf("[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)
+{
+       printf("[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)
+{
+       printf("[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)
+{
+       printf("[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)
+{
+       printf("[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)
+{
+       printf("[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)
+{
+       printf("[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)
+{
+       printf("[di7t2=%s]", (di7t2 ? "T" : "F"));
+       fflush(stdout);
+}
+#endif
+//////////////////////////////////////////////////////////////////////////////////////
+
+//END;
+//kludge
+dbinh = ~dbinh;
+#ifdef LOG_COMP_CTRL
+if (logBlit)
+{
+       printf("[dcomp=$%02X dbinh=$%02X]\n    ", dcomp, dbinh);
+       fflush(stdout);
+}
+#endif
+}
+
+
+////////////////////////////////////// C++ CODE //////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////
+
+#endif