]> Shamusworld >> Repos - virtualjaguar/blob - src/blitter.cpp
Initial blitter fixes (to be cleaned up)
[virtualjaguar] / src / blitter.cpp
1 //
2 // Blitter core
3 //
4 // by Cal2
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups/fixes by James L. Hammons
7 //
8 bool specialLog = false;
9 extern int effect_start;
10 extern int blit_start_log;
11
12 #include "jaguar.h"
13
14 #define REG(A)  (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
15                                 | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
16 #define WREG(A,D)       (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
17                                         blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
18
19 // Blitter registers (offsets from F02200)
20
21 #define A1_BASE                 ((UINT32)0x00)
22 #define A1_FLAGS                ((UINT32)0x04)
23 #define A1_CLIP                 ((UINT32)0x08)  // Height and width values for clipping
24 #define A1_PIXEL                ((UINT32)0x0C)  // Integer part of the pixel (Y.i and X.i)
25 #define A1_STEP                 ((UINT32)0x10)  // Integer part of the step
26 #define A1_FSTEP                ((UINT32)0x14)  // Fractionnal part of the step
27 #define A1_FPIXEL               ((UINT32)0x18)  // Fractionnal part of the pixel (Y.f and X.f)
28 #define A1_INC                  ((UINT32)0x1C)  // Integer part of the increment
29 #define A1_FINC                 ((UINT32)0x20)  // Fractional part of the increment
30 #define A2_BASE                 ((UINT32)0x24)
31 #define A2_FLAGS                ((UINT32)0x28)
32 #define A2_MASK                 ((UINT32)0x2C)  // Modulo values for x and y (M.y  and M.x)
33 #define A2_PIXEL                ((UINT32)0x30)  // Integer part of the pixel (no fractional part for A2)
34 #define A2_STEP                 ((UINT32)0x34)  // Integer part of the step (no fractional part for A2)
35 #define COMMAND                 ((UINT32)0x38)
36 #define PIXLINECOUNTER  ((UINT32)0x3C)
37 #define SRCDATA                 ((UINT32)0x40)
38 #define DSTDATA                 ((UINT32)0x48)
39 #define DSTZ                    ((UINT32)0x50)
40 #define SRCZINT                 ((UINT32)0x58)
41 #define SRCZFRAC                ((UINT32)0x60)
42 #define PATTERNDATA             ((UINT32)0x68)
43 #define INTENSITYINC    ((UINT32)0x70)
44 #define ZINC                    ((UINT32)0x74)
45 #define COLLISIONCTRL   ((UINT32)0x78)
46 #define PHRASEINT0              ((UINT32)0x7C)
47 #define PHRASEINT1              ((UINT32)0x80)
48 #define PHRASEINT2              ((UINT32)0x84)
49 #define PHRASEINT3              ((UINT32)0x88)
50 #define PHRASEZ0                ((UINT32)0x8C)
51 #define PHRASEZ1                ((UINT32)0x90)
52 #define PHRASEZ2                ((UINT32)0x94)
53 #define PHRASEZ3                ((UINT32)0x98)
54
55 // Blitter command bits
56
57 #define SRCEN                   (cmd & 0x00000001)
58 #define SRCENZ                  (cmd & 0x00000002)
59 #define SRCENX                  (cmd & 0x00000004)
60 #define DSTEN                   (cmd & 0x00000008)
61 #define DSTENZ                  (cmd & 0x00000010)
62 #define DSTWRZ                  (cmd & 0x00000020)
63 #define CLIPA1                  (cmd & 0x00000040)
64
65 #define UPDA1F                  (cmd & 0x00000100)
66 #define UPDA1                   (cmd & 0x00000200)
67 #define UPDA2                   (cmd & 0x00000400)
68
69 #define DSTA2                   (cmd & 0x00000800)
70
71 #define Z_OP_INF                (cmd & 0x00040000)
72 #define Z_OP_EQU                (cmd & 0x00080000)
73 #define Z_OP_SUP                (cmd & 0x00100000)
74
75 #define LFU_NAN                 (cmd & 0x00200000)
76 #define LFU_NA                  (cmd & 0x00400000)
77 #define LFU_AN                  (cmd & 0x00800000)
78 #define LFU_A                   (cmd & 0x01000000)
79
80 #define CMPDST                  (cmd & 0x02000000)
81 #define BCOMPEN                 (cmd & 0x04000000)
82 #define DCOMPEN                 (cmd & 0x08000000)
83
84 #define PATDSEL                 (cmd & 0x00010000)
85 #define ADDDSEL                 (cmd & 0x00020000)
86 #define TOPBEN                  (cmd & 0x00004000)
87 #define TOPNEN                  (cmd & 0x00008000)
88 #define BKGWREN                 (cmd & 0x10000000)
89 #define GOURD                   (cmd & 0x00001000)
90 #define GOURZ                   (cmd & 0x00002000)
91 #define SRCSHADE                (cmd & 0x40000000)
92
93
94 #define XADDPHR  0
95 #define XADDPIX  1
96 #define XADD0    2
97 #define XADDINC  3
98
99 #define XSIGNSUB_A1             (REG(A1_FLAGS)&0x080000)
100 #define XSIGNSUB_A2             (REG(A2_FLAGS)&0x080000)
101
102 #define YSIGNSUB_A1             (REG(A1_FLAGS)&0x100000)
103 #define YSIGNSUB_A2             (REG(A2_FLAGS)&0x100000)
104
105 #define YADD1_A1                (REG(A1_FLAGS)&0x040000)
106 #define YADD1_A2                (REG(A2_FLAGS)&0x040000)
107
108 //Put 'em back, once we fix the problem!!! [KO]
109 // 1 bpp pixel read
110 #define PIXEL_SHIFT_1(a)      (((~a##_x) >> 16) & 7)
111 #define PIXEL_OFFSET_1(a)     (((((UINT32)a##_y >> 16) * a##_width / 8) + (((UINT32)a##_x >> 19) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 19) & 7))
112 #define READ_PIXEL_1(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
113 //#define READ_PIXEL_1(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
114
115 // 2 bpp pixel read
116 #define PIXEL_SHIFT_2(a)      (((~a##_x) >> 15) & 6)
117 #define PIXEL_OFFSET_2(a)     (((((UINT32)a##_y >> 16) * a##_width / 4) + (((UINT32)a##_x >> 18) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 18) & 7))
118 #define READ_PIXEL_2(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03)
119 //#define READ_PIXEL_2(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
120
121 // 4 bpp pixel read
122 #define PIXEL_SHIFT_4(a)      (((~a##_x) >> 14) & 4)
123 #define PIXEL_OFFSET_4(a)     (((((UINT32)a##_y >> 16) * (a##_width/2)) + (((UINT32)a##_x >> 17) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 17) & 7))
124 #define READ_PIXEL_4(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f)
125 //#define READ_PIXEL_4(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
126
127 // 8 bpp pixel read
128 #define PIXEL_OFFSET_8(a)     (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 7))
129 #define READ_PIXEL_8(a)       (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER))
130 //#define READ_PIXEL_8(a)       (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a)))
131
132 // 16 bpp pixel read
133 #define PIXEL_OFFSET_16(a)    (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 3))
134 #define READ_PIXEL_16(a)       (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER))
135 //#define READ_PIXEL_16(a)       (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
136
137 // 32 bpp pixel read
138 #define PIXEL_OFFSET_32(a)    (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
139 #define READ_PIXEL_32(a)      (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER))
140 //#define READ_PIXEL_32(a)      (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
141
142 // pixel read
143 #define READ_PIXEL(a,f) (\
144          (((f>>3)&0x07) == 0) ? (READ_PIXEL_1(a)) : \
145          (((f>>3)&0x07) == 1) ? (READ_PIXEL_2(a)) : \
146          (((f>>3)&0x07) == 2) ? (READ_PIXEL_4(a)) : \
147          (((f>>3)&0x07) == 3) ? (READ_PIXEL_8(a)) : \
148          (((f>>3)&0x07) == 4) ? (READ_PIXEL_16(a)) : \
149          (((f>>3)&0x07) == 5) ? (READ_PIXEL_32(a)) : 0)
150
151 // 16 bpp z data read
152 #define ZDATA_OFFSET_16(a)     (PIXEL_OFFSET_16(a) + a##_zoffs * 4)
153 #define READ_ZDATA_16(a)       (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER))
154 //#define READ_ZDATA_16(a)       (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
155
156 // z data read
157 #define READ_ZDATA(a,f) (READ_ZDATA_16(a))
158
159 // 16 bpp z data write
160 #define WRITE_ZDATA_16(a,d)     {  JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); }
161 //#define WRITE_ZDATA_16(a,d)     {  JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); }
162
163 // z data write
164 #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d); 
165
166 // 1 bpp r data read
167 #define READ_RDATA_1(r,a,p)  ((p) ?  ((REG(r+(((UINT32)a##_x >> 19) & 0x04))) >> (((UINT32)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001))
168
169 // 2 bpp r data read
170 #define READ_RDATA_2(r,a,p)  ((p) ?  ((REG(r+(((UINT32)a##_x >> 18) & 0x04))) >> (((UINT32)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003))
171
172 // 4 bpp r data read
173 #define READ_RDATA_4(r,a,p)  ((p) ?  ((REG(r+(((UINT32)a##_x >> 17) & 0x04))) >> (((UINT32)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F))
174
175 // 8 bpp r data read
176 #define READ_RDATA_8(r,a,p)  ((p) ?  ((REG(r+(((UINT32)a##_x >> 16) & 0x04))) >> (((UINT32)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF))
177
178 // 16 bpp r data read
179 #define READ_RDATA_16(r,a,p)  ((p) ? ((REG(r+(((UINT32)a##_x >> 15) & 0x04))) >> (((UINT32)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF))
180
181 // 32 bpp r data read
182 #define READ_RDATA_32(r,a,p)  ((p) ? REG(r+(((UINT32)a##_x >> 14) & 0x04)) : REG(r))
183
184 // register data read
185 #define READ_RDATA(r,a,f,p) (\
186          (((f>>3)&0x07) == 0) ? (READ_RDATA_1(r,a,p)) : \
187          (((f>>3)&0x07) == 1) ? (READ_RDATA_2(r,a,p)) : \
188          (((f>>3)&0x07) == 2) ? (READ_RDATA_4(r,a,p)) : \
189          (((f>>3)&0x07) == 3) ? (READ_RDATA_8(r,a,p)) : \
190          (((f>>3)&0x07) == 4) ? (READ_RDATA_16(r,a,p)) : \
191          (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0)
192
193 // 1 bpp pixel write
194 #define WRITE_PIXEL_1(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_1(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER)&(~(0x01 << PIXEL_SHIFT_1(a))))|(d<<PIXEL_SHIFT_1(a)), BLITTER); }
195 //#define WRITE_PIXEL_1(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_1(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a))&(~(0x01 << PIXEL_SHIFT_1(a))))|(d<<PIXEL_SHIFT_1(a))); }
196
197 // 2 bpp pixel write
198 #define WRITE_PIXEL_2(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_2(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER)&(~(0x03 << PIXEL_SHIFT_2(a))))|(d<<PIXEL_SHIFT_2(a)), BLITTER); }
199 //#define WRITE_PIXEL_2(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_2(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a))&(~(0x03 << PIXEL_SHIFT_2(a))))|(d<<PIXEL_SHIFT_2(a))); }
200
201 // 4 bpp pixel write
202 #define WRITE_PIXEL_4(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_4(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER)&(~(0x0f << PIXEL_SHIFT_4(a))))|(d<<PIXEL_SHIFT_4(a)), BLITTER); }
203 //#define WRITE_PIXEL_4(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_4(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a))&(~(0x0f << PIXEL_SHIFT_4(a))))|(d<<PIXEL_SHIFT_4(a))); }
204
205 // 8 bpp pixel write
206 #define WRITE_PIXEL_8(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d, BLITTER); }
207 //#define WRITE_PIXEL_8(a,d)       { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d); }
208
209 // 16 bpp pixel write
210 //#define WRITE_PIXEL_16(a,d)     {  JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
211 #define WRITE_PIXEL_16(a,d)     {  JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), d, BLITTER); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); }
212 //#define WRITE_PIXEL_16(a,d)     {  JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), d); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); }
213
214 // 32 bpp pixel write
215 #define WRITE_PIXEL_32(a,d)             { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); } 
216 //#define WRITE_PIXEL_32(a,d)           { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); } 
217
218 // pixel write
219 #define WRITE_PIXEL(a,f,d) {\
220         switch ((f>>3)&0x07) { \
221         case 0: WRITE_PIXEL_1(a,d);  break;  \
222         case 1: WRITE_PIXEL_2(a,d);  break;  \
223         case 2: WRITE_PIXEL_4(a,d);  break;  \
224         case 3: WRITE_PIXEL_8(a,d);  break;  \
225         case 4: WRITE_PIXEL_16(a,d); break;  \
226         case 5: WRITE_PIXEL_32(a,d); break;  \
227         }}
228
229 // External global variables
230
231 extern int jaguar_active_memory_dumps;
232
233 // Local global variables
234
235 int start_logging = 0;
236 uint8 blitter_working = 0;
237
238 // Blitter register RAM (most of it is hidden from the user)
239
240 static uint8 blitter_ram[0x100];
241
242 // Width in Pixels of a Scanline
243 // This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
244 // of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
245 // the exponent. Valid values for the exponent range from 0 to 11 (decimal). It's easiest to think of it
246 // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to
247 // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place
248 // being shifted to the right 3 places).
249 /*static uint32 blitter_scanline_width[48] = 
250 {             
251      0,    0,    0,    0,                                       // Note: This would really translate to 1, 1, 1, 1
252      2,    0,    0,    0,
253      4,    0,    6,    0,
254      8,   10,   12,   14,
255     16,   20,   24,   28,
256     32,   40,   48,   56,
257     64,   80,   96,  112,
258    128,  160,  192,  224,
259    256,  320,  384,  448,
260    512,  640,  768,  896,
261   1024, 1280, 1536, 1792,
262   2048, 2560, 3072, 3584
263 };//*/
264
265 //static uint8 * tom_ram_8;
266 //static uint8 * paletteRam;
267 static uint8 src;
268 static uint8 dst;
269 static uint8 misc;
270 static uint8 a1ctl;
271 static uint8 mode;
272 static uint8 ity;
273 static uint8 zop;
274 static uint8 op;
275 static uint8 ctrl;
276 static uint32 a1_addr;
277 static uint32 a2_addr;
278 static int32 a1_zoffs;
279 static int32 a2_zoffs;
280 static uint32 xadd_a1_control;
281 static uint32 xadd_a2_control;
282 static int32 a1_pitch;
283 static int32 a2_pitch;
284 static uint32 n_pixels;
285 static uint32 n_lines;
286 static int32 a1_x;
287 static int32 a1_y;
288 static int32 a1_width;
289 static int32 a2_x;
290 static int32 a2_y;
291 static int32 a2_width;
292 static int32 a2_mask_x;
293 static int32 a2_mask_y;
294 static int32 a1_xadd;
295 static int32 a1_yadd;
296 static int32 a2_xadd;
297 static int32 a2_yadd;
298 static uint8 a1_phrase_mode;
299 static uint8 a2_phrase_mode;
300 static int32 a1_step_x = 0;
301 static int32 a1_step_y = 0;
302 static int32 a2_step_x = 0;
303 static int32 a2_step_y = 0;
304 static uint32 outer_loop;
305 static uint32 inner_loop;
306 static uint32 a2_psize;
307 static uint32 a1_psize;
308 static uint32 gouraud_add;
309 //static uint32 gouraud_data;
310 //static uint16 gint[4];
311 //static uint16 gfrac[4];
312 //static uint8  gcolour[4];
313 static int gd_i[4];
314 static int gd_c[4];
315 static int gd_ia, gd_ca;
316 static int colour_index = 0;
317 static int32 zadd;
318 static uint32 z_i[4];
319
320 static int32 a1_clip_x, a1_clip_y;
321
322 // In the spirit of "get it right first, *then* optimize" I've taken the liberty
323 // of removing all the unnecessary code caching. If it turns out to be a good way
324 // to optimize the blitter, then we may revisit it in the future...
325
326 //
327 // Generic blit handler
328 //
329 void blitter_generic(uint32 cmd)
330 {
331 /*
332 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
333  CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN 
334   A1 step values: -2 (X), 1 (Y)
335   A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
336   A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
337   A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
338         A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
339 */
340 //if (effect_start)
341 //      specialLog = true;
342 /*if (cmd == 0x1401060C && blit_start_log)
343         specialLog = true;//*/
344 //Testing only!
345 //uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
346         uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
347
348 if (specialLog)
349 {
350         WriteLog("About to do n x m blit (BM width is ? pixels)...\n");
351         WriteLog("A1_STEP_X/Y = %08X/%08X, A2_STEP_X/Y = %08X/%08X\n", a1_step_x, a1_step_y, a2_step_x, a2_step_y);
352 }
353         while (outer_loop--)
354         {
355 if (specialLog)
356 {
357         WriteLog("  A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
358 }
359                 uint32 a1_start = a1_x, a2_start = a2_x, bitPos = 0;
360 //Kludge for Hover Strike...
361 //I wonder if this kludge is in conjunction with the SRCENX down below...
362 if (BCOMPEN && SRCENX)
363 {
364         if (n_pixels < 8)
365                 bitPos = 8 - n_pixels;
366 }
367
368                 inner_loop = n_pixels;
369                 while (inner_loop--)
370                 {
371 if (specialLog)
372 {
373         WriteLog("    A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
374 }
375                         srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
376 //Kludge...
377 //Doesn't work...
378 srcdata = 0xFFFFFFFF;
379
380                         if (!DSTA2)                                                     // Data movement: A1 <- A2
381                         {
382                                 // load src data and Z
383 //                              if (SRCEN)
384                                 if (SRCEN || SRCENX)    // Not sure if this is correct...
385                                 {
386                                         srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
387                                         if (SRCENZ)
388                                                 srczdata = READ_ZDATA(a2, REG(A2_FLAGS));
389                                         else if (cmd & 0x0001C020)      // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
390                                                 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
391                                 }
392                                 else    // Use SRCDATA register...
393                                 {
394                                         srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
395                                         if (cmd & 0x0001C020)   // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
396                                                 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
397                                 }
398
399                                 // load dst data and Z 
400                                 if (DSTEN)
401                                 {
402                                         dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
403                                         if (DSTENZ)
404                                                 dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
405                                         else
406                                                 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
407                                 }
408                                 else
409                                 {
410                                         dstdata = READ_RDATA(DSTDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
411                                         if (DSTENZ)
412                                                 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
413                                 }
414
415 /*This wasn't working...                                // a1 clipping
416                                 if (cmd & 0x00000040)
417                                 {
418                                         if (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7FFF)
419                                                 || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7FFF))
420                                                 inhibit = 1;
421                                 }//*/
422
423                                 if (GOURZ) 
424                                         srczdata = z_i[colour_index] >> 16;
425
426                                 // apply z comparator
427                                 if (Z_OP_INF) if (srczdata <  dstzdata) inhibit = 1;
428                                 if (Z_OP_EQU) if (srczdata == dstzdata) inhibit = 1;
429                                 if (Z_OP_SUP) if (srczdata >  dstzdata) inhibit = 1;
430                                 
431                                 // apply data comparator
432 // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
433 // Does BCOMPEN only work in 1 bpp mode???
434 //   No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!!
435 //   This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside
436 //   an 8BPP space.
437                                 if (DCOMPEN | BCOMPEN)
438                                 {
439 //Temp, for testing Hover Strike
440 //Doesn't seem to do it... Why?
441 //What needs to happen here is twofold. First, the address generator in the outer loop has
442 //to honor the BPP when calculating the start address (which it kinda does already). Second,
443 //it has to step bit by bit when using BCOMPEN. How to do this???
444         if (BCOMPEN)
445 //              srcdata = READ_RDATA_1(SRCDATA, a2, a2_phrase_mode);
446 //              srcdata = READ_PIXEL_1(a2);
447 //              srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
448 /*
449 #define PIXEL_SHIFT_1(a)      (((~a##_x) >> 16) & 0x07)
450 #define PIXEL_OFFSET_1(a)     (((((UINT32)a##_y >> 16) * a##_width / 8) + (((UINT32)a##_x >> 19) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 19) & 7))
451 #define READ_PIXEL_1(a)       ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
452
453 #define PIXEL_SHIFT_1(a)
454         (((~a2_x) >> 16) & 0x07)
455 #define PIXEL_OFFSET_1(a)
456         (((((UINT32)a2_y >> 16) * a2_width / 8) + (((UINT32)a2_x >> 19) & ~7)) * (1 + a2_pitch) + (((UINT32)a2_x >> 19) & 7))
457 #define READ_PIXEL_1(a)
458         ((JaguarReadByte(a2_addr+PIXEL_OFFSET_1(a2), BLITTER) >> PIXEL_SHIFT_1(a2)) & 0x01)
459 */
460 //small problem with this approach: it's not accurate... We need a proper address to begin with
461 //and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!!
462         {
463 //              uint32 pixShift = ((~(a2_x * 8)) >> 16) & 0x07;
464 //              uint32 pixShift = (~(a2_x >> 13)) & 0x07;
465                 uint32 pixShift = (~bitPos) & 0x07;             // 8BPP only...!
466 //              uint32 pixOffset = (((((UINT32)a2_y >> 16) * a2_width / 8) + (((UINT32)(a2_x * 8) >> 19) & ~0x07)) * (1 + a2_pitch) + (((UINT32)(a2_x * 8) >> 19) & 0x07));
467 //              uint32 pixOffset = (((((UINT32)a2_y >> 16) * a2_width) + (((UINT32)(a2_x * 8) >> 19) & ~0x07)) * (1 + a2_pitch) + (((UINT32)(a2_x * 8) >> 19) & 0x07));
468 //              uint32 pixOffset = (((((UINT32)a2_y >> 16) * a2_width) + (((UINT32)a2_x >> 16) & ~0x07)) * (1 + a2_pitch)) + (((UINT32)a2_x >> 16) & 0x07);
469 //              srcdata = (JaguarReadByte(a2_addr+pixOffset, BLITTER) >> pixShift) & 0x01;
470                 srcdata = (srcdata >> pixShift) & 0x01;
471
472                 bitPos++;
473         }
474 /*
475 Interesting (Hover Strike--large letter):
476
477 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
478  CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN 
479   A1 step values: -2 (X), 1 (Y)
480   A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
481   A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
482   A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
483         A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
484
485 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
486  CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN 
487   A1 step values: -8 (X), 1 (Y)
488   A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
489   A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
490   A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
491         A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000
492
493 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
494  CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN 
495   A1 step values: -1 (X), 1 (Y)
496   A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
497   A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
498   A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
499         A1 x/y: 118/12, A2 x/y: 70/0 Pattern: 000000F300000000
500
501 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
502  CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN 
503   A1 step values: -8 (X), 1 (Y)
504   A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
505   A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
506   A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
507         A1 x/y: 119/12, A2 x/y: 71/0 Pattern: 000000F300000000
508
509 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
510  CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN 
511   A1 step values: -1 (X), 1 (Y)
512   A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
513   A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
514   A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
515         A1 x/y: 127/12, A2 x/y: 66/0 Pattern: 000000F300000000
516
517 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
518  CMD -> src: SRCENX dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: BCOMPEN BKGWREN 
519   A1 step values: -8 (X), 1 (Y)
520   A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
521   A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
522   A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
523         A1 x/y: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000
524 */
525
526
527                                         if (!CMPDST)
528                                         {
529 //WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit);
530                                                 // compare source pixel with pattern pixel
531 /*
532 Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: 05810001]
533  CMD -> src: SRCEN  dst:  misc:  a1ctl:  mode:  ity: PATDSEL z-op:  op: LFU_REPLACE ctrl: BCOMPEN 
534   A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
535   A2 -> pitch: 1 phrases, depth: 1bpp, z-off: 0, width: 16 (10), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
536         x/y: 0/20
537 ...
538 */
539 // AvP is still wrong, could be cuz it's doing A1 -> A2...
540
541 // Src is the 1bpp bitmap... DST is the PATTERN!!!
542 // This seems to solve at least ONE of the problems with MC3D...
543 // Why should this be inverted???
544 // Bcuz it is. This is supposed to be used only for a bit -> pixel expansion...
545 /*                                              if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
546 //                                              if (srcdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
547                                                         inhibit = 1;//*/
548 /*                                              uint32 A2bpp = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
549                                                 if (A2bpp == 1 || A2bpp == 16 || A2bpp == 8)
550                                                         inhibit = (srcdata == 0 ? 1: 0);
551 //                                                      inhibit = !srcdata;
552                                                 else
553                                                         WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
554 // What it boils down to is this:
555
556                                                 if (srcdata == 0)
557                                                         inhibit = 1;//*/
558                                         }
559                                         else
560                                         {
561                                                 // compare destination pixel with pattern pixel
562                                                 if (dstdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
563 //                                              if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
564                                                         inhibit = 1;
565                                         }
566
567 // This is DEFINITELY WRONG
568 //                                      if (a1_phrase_mode || a2_phrase_mode)
569 //                                              inhibit = !inhibit;
570                                 }
571
572                                 if (CLIPA1)
573                                 {
574                                         inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
575                                                 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
576                                 }
577
578                                 // compute the write data and store
579                                 if (!inhibit)
580                                 {                       
581 // Houston, we have a problem...
582 // Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's
583 // a conflict! E.g.:
584 //Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008]
585 // CMD -> src:  dst: DSTEN  misc:  a1ctl:  mode: GOURD  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
586 //  A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
587 //  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
588 //        A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700
589
590                                         if (PATDSEL)
591                                         {
592                                                 // use pattern data for write data
593                                                 writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
594                                         }
595                                         else if (ADDDSEL)
596                                         {
597 /*if (blit_start_log)
598         WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/
599
600                                                 // intensity addition
601 //Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!!
602 /*                                              writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
603                                                 if (!(TOPBEN) && writedata > 0xFF)
604 //                                                      writedata = 0xFF;
605                                                         writedata &= 0xFF;
606                                                 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
607                                                 if (!(TOPNEN) && writedata > 0xFFF)
608 //                                                      writedata = 0xFFF;
609                                                         writedata &= 0xFFF;
610                                                 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/
611 //notneeded--writedata &= 0xFFFF;
612 /*if (blit_start_log)
613         WriteLog("writedata: %08X\n", writedata);//*/
614 /*
615 Hover Strike ADDDSEL blit:
616
617 Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208]
618  CMD -> src:  dst: DSTEN  misc:  a1ctl: UPDA1  mode:  ity: ADDDSEL z-op:  op: LFU_CLEAR ctrl: 
619   A1 step values: -320 (X), 1 (Y)
620   A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
621   A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
622         A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD
623 */
624                                                 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
625
626                                                 if (!TOPBEN)
627                                                 {
628 //This is correct now, but slow...
629                                                         int16 s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000),
630                                                                 d = dstdata & 0xFF;
631                                                         int16 sum = s + d;
632
633                                                         if (sum < 0)
634                                                                 writedata = 0x00;
635                                                         else if (sum > 0xFF)
636                                                                 writedata = 0xFF;
637                                                         else
638                                                                 writedata = (uint32)sum;
639                                                 }
640
641 //This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!!
642                                                 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
643
644                                                 if (!TOPNEN && writedata > 0xFFF)
645                                                 {
646                                                         writedata &= 0xFFF;
647                                                 }
648
649                                                 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
650                                         }
651                                         else
652                                         {
653                                                 if (LFU_NAN) writedata |= ~srcdata & ~dstdata;
654                                                 if (LFU_NA)  writedata |= ~srcdata & dstdata;
655                                                 if (LFU_AN)  writedata |= srcdata  & ~dstdata;
656                                                 if (LFU_A)       writedata |= srcdata  & dstdata;
657                                         }
658
659 //Although, this looks like it's OK... (even if it is shitty!)
660 //According to JTRM, this is part of the four things the blitter does with the write data (the other
661 //three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL
662 //(see above blit example)...
663                                         if (GOURD) 
664                                                 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
665
666                                         if (SRCSHADE) 
667                                         {
668                                                 int intensity = srcdata & 0xFF;
669                                                 int ia = gd_ia >> 16;
670                                                 if (ia & 0x80)
671                                                         ia = 0xFFFFFF00 | ia;
672                                                 intensity += ia;
673                                                 if (intensity < 0)
674                                                         intensity = 0;
675                                                 if (intensity > 0xFF)
676                                                         intensity = 0xFF;
677                                                 writedata = (srcdata & 0xFF00) | intensity;
678                                         }
679                                 }
680                                 else
681                                 {
682                                         writedata = dstdata;
683                                         srczdata = dstzdata;
684                                 }
685
686 //Tried 2nd below for Hover Strike: No dice.
687                                 if (/*a1_phrase_mode || */BKGWREN || !inhibit)
688 //                              if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit)
689                                 {
690 /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
691 {
692         uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
693 // (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
694         if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
695                 WriteLog("32bpp pixel write: A1 Phrase mode --> ");
696 }//*/
697                                         // write to the destination
698                                         WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
699                                         if (DSTWRZ)
700                                                 WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
701                                 }
702                         }
703                         else    // if (DSTA2)
704                         {
705                                 // load src data and Z
706                                 if (SRCEN)
707                                 {
708                                         srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
709                                         if (SRCENZ)
710                                                 srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
711                                         else if (cmd & 0x0001C020)      // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
712                                                 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
713                                 }
714                                 else
715                                 {
716                                         srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
717                                         if (cmd & 0x001C020)    // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
718                                                 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
719                                 }
720
721                                 // load dst data and Z 
722                                 if (DSTEN)
723                                 {
724                                         dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
725                                         if (DSTENZ)
726                                                 dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
727                                         else
728                                                 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
729                                 }
730                                 else
731                                 {
732                                         dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
733                                         if (DSTENZ)
734                                                 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
735                                 }
736
737                                 if (GOURZ) 
738                                         srczdata = z_i[colour_index] >> 16;
739
740                                 // apply z comparator
741                                 if (Z_OP_INF) if (srczdata < dstzdata)  inhibit = 1;
742                                 if (Z_OP_EQU) if (srczdata == dstzdata) inhibit = 1;
743                                 if (Z_OP_SUP) if (srczdata > dstzdata)  inhibit = 1;
744                                 
745                                 // apply data comparator
746 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
747                                 if (DCOMPEN | BCOMPEN)
748                                 {
749                                         if (!CMPDST)
750                                         {
751                                                 // compare source pixel with pattern pixel
752 // AvP: Numbers are correct, but sprites are not!
753 //This doesn't seem to be a problem... But could still be wrong...
754 /*                                              if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
755 //                                              if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
756                                                         inhibit = 1;//*/
757 // This is probably not 100% correct... It works in the 1bpp case
758 // (in A1 <- A2 mode, that is...)
759 // AvP: This is causing blocks to be written instead of bit patterns...
760 // Works now...
761 // NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
762 /*                                              uint32 A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
763                                                 if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
764                                                         inhibit = (srcdata == 0 ? 1: 0);
765                                                 else
766                                                         WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
767 // What it boils down to is this:
768                                                 if (srcdata == 0)
769                                                         inhibit = 1;//*/
770                                         }
771                                         else
772                                         {
773                                                 // compare destination pixel with pattern pixel
774                                                 if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
775 //                                              if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
776                                                         inhibit = 1;
777                                         }
778
779 // This is DEFINITELY WRONG
780 //                                      if (a1_phrase_mode || a2_phrase_mode)
781 //                                              inhibit = !inhibit;
782                                 }
783                                 
784                                 if (CLIPA1)
785                                 {
786                                         inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
787                                                 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
788                                 }
789
790                                 // compute the write data and store
791                                 if (!inhibit)
792                                 {                       
793                                         if (PATDSEL)
794                                         {
795                                                 // use pattern data for write data
796                                                 writedata= READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
797                                         }
798                                         else if (ADDDSEL)
799                                         {
800                                                 // intensity addition
801                                                 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
802                                                 if (!(TOPBEN) && writedata > 0xFF)
803                                                         writedata = 0xFF;
804                                                 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
805                                                 if (!(TOPNEN) && writedata > 0xFFF)
806                                                         writedata = 0xFFF;
807                                                 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
808                                         }
809                                         else
810                                         {
811                                                 if (LFU_NAN)
812                                                         writedata |= ~srcdata & ~dstdata;
813                                                 if (LFU_NA)
814                                                         writedata |= ~srcdata & dstdata;
815                                                 if (LFU_AN)
816                                                         writedata |= srcdata & ~dstdata;
817                                                 if (LFU_A)
818                                                         writedata |= srcdata & dstdata;
819                                         }
820
821                                         if (GOURD) 
822                                                 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
823
824                                         if (SRCSHADE) 
825                                         {
826                                                 int intensity = srcdata & 0xFF;
827                                                 int ia = gd_ia >> 16;
828                                                 if (ia & 0x80)
829                                                         ia = 0xFFFFFF00 | ia;
830                                                 intensity += ia;
831                                                 if (intensity < 0)
832                                                         intensity = 0;
833                                                 if (intensity > 0xFF)
834                                                         intensity = 0xFF;
835                                                 writedata = (srcdata & 0xFF00) | intensity;
836                                         }
837                                 }
838                                 else
839                                 {
840                                         writedata = dstdata;
841                                         srczdata = dstzdata;
842                                 }
843
844                                 if (/*a2_phrase_mode || */BKGWREN || !inhibit)
845                                 {
846 /*if (logGo)
847 {
848         uint32 offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
849 // (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
850         WriteLog("[%08X:%04X] ", offset, writedata);
851 }//*/
852                                         // write to the destination
853                                         WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
854
855                                         if (DSTWRZ)
856                                                 WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
857                                 }
858                         }
859
860                         // update x and y (inner loop)
861 //kludge to test shiatsu...
862 //nope, no wok.
863 //Now it does! But crappy, crappy, crappy! !!! FIX !!!
864 if (!BCOMPEN)
865 {
866                         a1_x += a1_xadd, a1_y += a1_yadd;
867                         a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
868 }
869 else
870 {
871         a1_x += a1_xadd, a1_y += a1_yadd;
872         a2_x = (a2_x + (a2_xadd / 8)) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
873 }//*/
874
875                         if (GOURZ)
876                                 z_i[colour_index] += zadd;
877
878                         if (GOURD || SRCSHADE)
879                         {
880                                 gd_i[colour_index] += gd_ia;
881 //Hmm, this doesn't seem to do anything...
882 //But it is correct according to the JTRM...!
883 if ((int32)gd_i[colour_index] < 0)
884         gd_i[colour_index] = 0;
885 if (gd_i[colour_index] > 0x00FFFFFF)
886         gd_i[colour_index] = 0x00FFFFFF;//*/
887
888                                 gd_c[colour_index] += gd_ca;
889 if ((int32)gd_c[colour_index] < 0)
890         gd_c[colour_index] = 0;
891 if (gd_c[colour_index] > 0x000000FF)
892         gd_c[colour_index] = 0x000000FF;//*/
893                         }
894
895                         if (GOURD || SRCSHADE || GOURZ)
896                         {
897                                 if (a1_phrase_mode)
898 //This screws things up WORSE (for the BIOS opening screen)
899 //                              if (a1_phrase_mode || a2_phrase_mode)
900                                         colour_index = (colour_index + 1) & 0x03;
901                         }
902                 }
903
904 //more kludge to test shiatsu...
905 //nope, no wok.
906 //Now it does! But crappy, crappy, crappy! !!! FIX !!!
907 if (BCOMPEN)
908 {
909         if (a2_x & 0xFFFF)
910                 a2_x = (a2_x & 0xFFFF0000) + 0x00010000;
911 }//*/
912 /*if (BCOMPEN && !DSTA2)//kludge for Hover Strike... !!! FIX !!!
913 {
914         a2_x -= n_pixels << 16;
915         a2_x += ((n_pixels << 16) / 8) & 0XFFFF0000;
916         a2_x += (n_pixels % 8 == 0 ? 0 : 1 << 16);
917 }//*/
918
919                 //New: Phrase mode taken into account! :-p
920                 if (a1_phrase_mode)
921                 {
922                         // Bump the pointer to the next phrase boundary
923                         // Even though it works, this is crappy... Clean it up!
924                         uint32 size = 64 / a1_psize;
925
926                         // Crappy kludge... ('aligning' source to destination)
927                         if (a2_phrase_mode && DSTA2)
928                         {
929                                 uint32 extra = (a2_start >> 16) % size;
930                                 a1_x += extra << 16;
931                         }
932
933                         uint32 newx = (a1_x >> 16) / size;
934                         uint32 newxrem = (a1_x >> 16) % size;
935                         a1_x &= 0x0000FFFF;
936                         a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
937                 }
938
939                 if (a2_phrase_mode)
940                 {
941                         // Bump the pointer to the next phrase boundary
942                         // Even though it works, this is crappy... Clean it up!
943                         uint32 size = 64 / a2_psize;
944
945                         // Crappy kludge... ('aligning' source to destination)
946                         // Prolly should do this for A1 channel as well... [DONE]
947                         if (a1_phrase_mode && !DSTA2)
948                         {
949                                 uint32 extra = (a1_start >> 16) % size;
950                                 a2_x += extra << 16;
951                         }
952
953                         uint32 newx = (a2_x >> 16) / size;
954                         uint32 newxrem = (a2_x >> 16) % size;
955                         a2_x &= 0x0000FFFF;
956                         a2_x |= (((newx + (newxrem == 0 ? 0 : 1) /*+ extra*/) * size) & 0xFFFF) << 16;
957                 }
958
959                 //Not entirely: This still mucks things up... !!! FIX !!!
960                 //Should this go before or after the phrase mode mucking around?
961                 a1_x += a1_step_x;
962                 a1_y += a1_step_y;
963                 a2_x += a2_step_x;
964                 a2_y += a2_step_y;//*/
965         }
966         
967         // write values back to registers 
968         WREG(A1_PIXEL,  (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
969         WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
970         WREG(A2_PIXEL,  (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
971 specialLog = false;
972 }
973
974 void blitter_blit(uint32 cmd)
975 {
976         uint32 pitchValue[4] = { 0, 1, 3, 2 };
977         colour_index = 0;
978         src = cmd & 0x07;
979         dst = (cmd >> 3) & 0x07;
980         misc = (cmd >> 6) & 0x03;
981         a1ctl = (cmd >> 8) & 0x7;
982         mode = (cmd >> 11) & 0x07;
983         ity = (cmd >> 14) & 0x0F;
984         zop = (cmd >> 18) & 0x07;
985         op = (cmd >> 21) & 0x0F;
986         ctrl = (cmd >> 25) & 0x3F;
987
988         // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
989         // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
990         a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
991         a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
992
993         a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
994         a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
995         
996         xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
997         xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
998 //      a1_pitch = (REG(A1_FLAGS) & 3) ^ ((REG(A1_FLAGS) & 2) >> 1);
999 //      a2_pitch = (REG(A2_FLAGS) & 3) ^ ((REG(A2_FLAGS) & 2) >> 1);
1000         a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
1001         a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
1002
1003         n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
1004         n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
1005
1006         a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1007         a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1008 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1009 //But it seems to fuck up T2K! !!! FIX !!!
1010 //Could it be sign extended??? Doesn't seem to be so according to JTRM
1011 //      a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
1012 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1013 //      a1_y &= 0x0FFFFFFF;
1014
1015 //      a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
1016 // According to JTRM, this must give a *whole number* of phrases in the current
1017 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1018         UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1019         a1_width = ((0x04 | m) << e) >> 2;//*/
1020
1021         a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1022         a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1023 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1024 //But it seems to fuck up T2K! !!! FIX !!!
1025 //      a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
1026 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1027 //      a2_y &= 0x0FFFFFFF;
1028
1029 //      a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
1030 // According to JTRM, this must give a *whole number* of phrases in the current
1031 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1032         m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1033         a2_width = ((0x04 | m) << e) >> 2;//*/
1034         a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
1035         a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
1036
1037         // Check for "use mask" flag
1038         if (!(REG(A2_FLAGS) & 0x8000))
1039         {
1040                 a2_mask_x = 0xFFFFFFFF; // must be 16.16
1041                 a2_mask_y = 0xFFFFFFFF; // must be 16.16
1042         }
1043
1044         a1_phrase_mode = 0;
1045
1046         // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
1047         a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
1048
1049         if (YSIGNSUB_A1)
1050                 a1_yadd = -a1_yadd;
1051
1052         // determine a1_xadd
1053         switch (xadd_a1_control)
1054         {
1055         case XADDPHR:
1056 // This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
1057                 // add phrase offset to X and truncate
1058                 a1_xadd = 1 << 16;
1059                 a1_phrase_mode = 1;
1060                 break;
1061         case XADDPIX:
1062                 // add pixelsize (1) to X
1063                 a1_xadd = 1 << 16;
1064                 break;
1065         case XADD0:     
1066                 // add zero (for those nice vertical lines)
1067                 a1_xadd = 0;
1068                 break;
1069         case XADDINC:
1070                 // add the contents of the increment register
1071                 a1_xadd = (REG(A1_INC) << 16)            | (REG(A1_FINC) & 0x0000FFFF);
1072                 a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
1073                 break;
1074         }
1075
1076
1077 //Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801]
1078 //  A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD
1079 //  A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD
1080 //if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// &&
1081 //      UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1082 //Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it...
1083 //if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801)
1084 //        A1 x/y: 14368/7, A2 x/y: 150/36
1085 //This is it... The problem...
1086 //if ((a1_x >> 16) == 14368) // 14368 = $3820
1087 //      return; //Lesse what we got...
1088
1089         if (XSIGNSUB_A1)
1090                 a1_xadd = -a1_xadd;
1091
1092         if (YSIGNSUB_A2)
1093                 a2_yadd = -a2_yadd;
1094
1095         a2_phrase_mode = 0;
1096
1097         // determine a2_xadd
1098         switch (xadd_a2_control)
1099         {
1100         case XADDPHR:
1101                 // add phrase offset to X and truncate
1102                 a2_xadd = 1 << 16;
1103                 a2_phrase_mode = 1;
1104                 break;
1105         case XADDPIX:
1106                 // add pixelsize (1) to X
1107                 a2_xadd = 1 << 16;
1108                 break;
1109         case XADD0:     
1110                 // add zero (for those nice vertical lines)
1111                 a2_xadd = 0;
1112                 break;
1113 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
1114         case XADDINC:
1115 WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
1116                 // add the contents of the increment register
1117                 // since there is no register for a2 we just add 1
1118 //Let's do nothing, since it's not listed as a valid bit combo...
1119 //              a2_xadd = 1 << 16;
1120                 break;
1121         }
1122
1123         if (XSIGNSUB_A2)
1124                 a2_xadd = -a2_xadd;
1125
1126         // Modify outer loop steps based on blitter command
1127
1128         a1_step_x = 0;
1129         a1_step_y = 0;
1130         a2_step_x = 0;
1131         a2_step_y = 0;
1132
1133         if (UPDA1F)
1134                 a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
1135                 a1_step_y = (REG(A1_FSTEP) >> 16);
1136
1137         if (UPDA1)
1138                 a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
1139                 a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
1140
1141         if (UPDA2)
1142                 a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
1143                 a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
1144
1145         outer_loop = n_lines;
1146
1147         // Clipping...
1148
1149         if (CLIPA1)
1150                 a1_clip_x = REG(A1_CLIP) & 0x7FFF,
1151                 a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
1152
1153 // This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX]
1154 // Err, this is pixel size... (and it's OK)
1155         a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
1156         a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
1157
1158         // Z-buffering
1159         if (GOURZ)
1160         {
1161                 zadd = REG(ZINC);
1162
1163                 for(int v=0; v<4; v++)
1164                         z_i[v] = REG(PHRASEZ0 + v*4);
1165         }
1166
1167         // Gouraud shading
1168         if (GOURD || GOURZ || SRCSHADE)
1169         {
1170                 gd_c[0] = blitter_ram[PATTERNDATA + 0];
1171                 gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
1172                         | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
1173
1174                 gd_c[1] = blitter_ram[PATTERNDATA + 2];
1175                 gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
1176                         | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
1177
1178                 gd_c[2] = blitter_ram[PATTERNDATA + 4];
1179                 gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
1180                         | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
1181
1182                 gd_c[3] = blitter_ram[PATTERNDATA + 6];
1183                 gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
1184                         | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
1185
1186                 gouraud_add = REG(INTENSITYINC);
1187                 
1188                 gd_ia = gouraud_add & 0x00FFFFFF;
1189                 if (gd_ia & 0x00800000)
1190                         gd_ia = 0xFF000000 | gd_ia;
1191
1192                 gd_ca = (gouraud_add >> 24) & 0xFF;
1193                 if (gd_ca & 0x00000080)
1194                         gd_ca = 0xFFFFFF00 | gd_ca;
1195         }
1196
1197         // Bit comparitor fixing...
1198 /*      if (BCOMPEN)
1199         {
1200                 // Determine the data flow direction...
1201                 if (!DSTA2)
1202                         a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07));
1203                 else
1204                         ;//add this later
1205         }//*/
1206 /*      if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!!
1207         {
1208                 // Determine the data flow direction...
1209                 if (!DSTA2)
1210                         a2_x <<= 3;
1211         }//*/
1212
1213 #ifdef LOG_BLITS
1214         if (start_logging)
1215         {
1216                 WriteLog("Blit!\n");
1217                 WriteLog("  cmd      = 0x%.8x\n",cmd);
1218                 WriteLog("  a1_base  = %08X\n", a1_addr);
1219                 WriteLog("  a1_pitch = %d\n", a1_pitch);
1220                 WriteLog("  a1_psize = %d\n", a1_psize);
1221                 WriteLog("  a1_width = %d\n", a1_width);
1222                 WriteLog("  a1_xadd  = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1223                 WriteLog("  a1_yadd  = %f\n", (float)a1_yadd / 65536.0);
1224                 WriteLog("  a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1225                 WriteLog("  a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1226                 WriteLog("  a1_x     = %f\n", (float)a1_x / 65536.0);
1227                 WriteLog("  a1_y     = %f\n", (float)a1_y / 65536.0);
1228                 WriteLog("  a1_zoffs = %i\n",a1_zoffs);
1229
1230                 WriteLog("  a2_base  = %08X\n", a2_addr);
1231                 WriteLog("  a2_pitch = %d\n", a2_pitch);
1232                 WriteLog("  a2_psize = %d\n", a2_psize);
1233                 WriteLog("  a2_width = %d\n", a2_width);
1234                 WriteLog("  a2_xadd  = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1235                 WriteLog("  a2_yadd  = %f\n", (float)a2_yadd / 65536.0);
1236                 WriteLog("  a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1237                 WriteLog("  a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1238                 WriteLog("  a2_x     = %f\n", (float)a2_x / 65536.0);
1239                 WriteLog("  a2_y     = %f\n", (float)a2_y / 65536.0);
1240                 WriteLog("  a2_mask_x= 0x%.4x\n",a2_mask_x);
1241                 WriteLog("  a2_mask_y= 0x%.4x\n",a2_mask_y);
1242                 WriteLog("  a2_zoffs = %i\n",a2_zoffs);
1243
1244                 WriteLog("  count    = %d x %d\n", n_pixels, n_lines);
1245
1246                 WriteLog("  command  = %08X\n", cmd);
1247                 WriteLog("  dsten    = %i\n",DSTEN);
1248                 WriteLog("  srcen    = %i\n",SRCEN);
1249                 WriteLog("  patdsel  = %i\n",PATDSEL);
1250                 WriteLog("  color    = 0x%.8x\n",REG(PATTERNDATA));
1251                 WriteLog("  dcompen  = %i\n",DCOMPEN);
1252                 WriteLog("  bcompen  = %i\n",BCOMPEN);
1253                 WriteLog("  cmpdst   = %i\n",CMPDST);
1254                 WriteLog("  GOURZ   = %i\n",GOURZ);
1255                 WriteLog("  GOURD   = %i\n",GOURD);
1256                 WriteLog("  SRCSHADE= %i\n",SRCSHADE);
1257         }       
1258 #endif
1259
1260 //NOTE: Pitch is ignored!
1261
1262 //This *might* be the altimeter blits (they are)...
1263 //On captured screen, x-pos for black (inner) is 259, for pink is 257
1264 //Black is short by 3, pink is short by 1...
1265 /*
1266 Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1267  CMD -> src:  dst:  misc:  a1ctl: UPDA1  mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
1268   A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1269   A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1270         A1 x/y: 262/124, A2 x/y: 128/0
1271 Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1272  CMD -> src:  dst:  misc:  a1ctl: UPDA1  mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
1273   A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1274   A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1275         A1 x/y: 264/117, A2 x/y: 407/0
1276
1277 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1278  CMD -> src:  dst:  misc:  a1ctl: UPDA1  mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
1279   A1 step values: -10 (X), 1 (Y)
1280   A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1281   A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1282         A1 x/y: 262/132, A2 x/y: 129/0
1283 Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1284  CMD -> src:  dst:  misc:  a1ctl: UPDA1  mode:  ity: PATDSEL z-op:  op: LFU_CLEAR ctrl: 
1285   A1 step values: -8 (X), 1 (Y)
1286   A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1287   A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1288         A1 x/y: 264/128, A2 x/y: 336/0
1289
1290   264v       vCursor ends up here...
1291      xxxxx...`
1292      111122223333
1293
1294 262v         vCursor ends up here...
1295    xxxxxxxxx.'
1296  1111222233334444
1297
1298 Fixed! Now for more:
1299
1300 ; This looks like the ship icon in the upper left corner...
1301
1302 Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1303  CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
1304   A1 step values: -12 (X), 1 (Y)
1305   A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1306   A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1307   A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1308         A1 x/y: 20/24, A2 x/y: 5780/0
1309
1310 Also fixed!
1311
1312 More (not sure this is a blitter problem as much as it's a GPU problem):
1313 All but the "M" are trashed...
1314 This does *NOT* look like a blitter problem, as it's rendering properly...
1315 Actually, if you look at the A1 step values, there IS a discrepancy!
1316
1317 ; D
1318
1319 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1320  CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
1321   A1 step values: -14 (X), 1 (Y)
1322   A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1323   A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1324   A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1325         A1 x/y: 134/144, A2 x/y: 2516/0
1326 ;129,146: +5,-2
1327
1328 ; E
1329
1330 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1331  CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
1332   A1 step values: -13 (X), 1 (Y)
1333   A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1334   A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1335   A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1336         A1 x/y: 147/144, A2 x/y: 2660/0
1337
1338 ; M
1339
1340 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1341  CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
1342   A1 step values: -12 (X), 1 (Y)
1343   A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1344   A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1345   A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1346         A1 x/y: 160/144, A2 x/y: 3764/0
1347
1348 ; O
1349
1350 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1351  CMD -> src: SRCEN  dst: DSTEN  misc:  a1ctl: UPDA1 UPDA2 mode:  ity:  z-op:  op: LFU_REPLACE ctrl: DCOMPEN 
1352   A1 step values: -15 (X), 1 (Y)
1353   A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1354   A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1355   A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1356         A1 x/y: 173/144, A2 x/y: 4052/0
1357
1358 */
1359 //extern int op_start_log;
1360 if (blit_start_log)
1361 {
1362         char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
1363         char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
1364         char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1365                 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1366         uint32 /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
1367                 a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F,
1368                 zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/;
1369         UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1370         uint32 p1 = a1f & 0x07, p2 = a2f & 0x07,
1371                 d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
1372                 zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
1373                 w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
1374                 ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
1375         UINT32 iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
1376         UINT32 iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
1377         WriteLog("Blit! (%08X %s %08X) count: %d x %d, A1/2_FLAGS: %08X/%08X [cmd: %08X]\n", a1_addr, (mode&0x01 ? "->" : "<-"), a2_addr, n_pixels, n_lines, a1f, a2f, cmd);
1378 //      WriteLog(" CMD -> src: %d, dst: %d, misc: %d, a1ctl: %d, mode: %d, ity: %1X, z-op: %d, op: %1X, ctrl: %02X\n", src, dst, misc, a1ctl, mode, ity, zop, op, ctrl);
1379
1380         WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
1381         WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
1382         WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
1383         WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
1384         WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "ZBUFF" : ""));
1385         WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : ""));
1386         WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
1387         WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
1388         WriteLog("ctrl: %s%s%s%s%s%s\n", (cmd & 0x02000000 ? "CMPDST " : ""), (cmd & 0x04000000 ? "BCOMPEN " : ""), (cmd & 0x08000000 ? "DCOMPEN " : ""), (cmd & 0x10000000 ? "BKGWREN " : ""), (cmd & 0x20000000 ? "BUSHI " : ""), (cmd & 0x40000000 ? "SRCSHADE" : ""));
1389
1390         if (UPDA1)
1391                 WriteLog("  A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16);
1392
1393         if (UPDA2)
1394                 WriteLog("  A2 step values: %d (X), %d (Y) [mask (%sused): %08X - %08X/%08X]\n", a2_step_x >> 16, a2_step_y >> 16, (a2f & 0x8000 ? "" : "un"), REG(A2_MASK), a2_mask_x, a2_mask_y);
1395
1396         WriteLog("  A1 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p1, bppStr[d1], zo1, iw1, w1, ctrlStr[ac1&0x03], (ac1&0x04 ? "YADD1" : "YADD0"), (ac1&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac1&0x10 ? "YSIGNSUB" : "YSIGNADD"));
1397         WriteLog("  A2 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p2, bppStr[d2], zo2, iw2, w2, ctrlStr[ac2&0x03], (ac2&0x04 ? "YADD1" : "YADD0"), (ac2&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac2&0x10 ? "YSIGNSUB" : "YSIGNADD"));
1398         WriteLog("        A1 x/y: %d/%d, A2 x/y: %d/%d Pattern: %08X%08X SRCDATA: %08X%08X\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16, REG(PATTERNDATA), REG(PATTERNDATA + 4), REG(SRCDATA), REG(SRCDATA + 4));
1399 //      blit_start_log = 0;
1400 //      op_start_log = 1;
1401 }
1402
1403         blitter_working = 1;
1404 //#ifndef USE_GENERIC_BLITTER
1405 //      if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
1406 //#endif
1407         blitter_generic(cmd);
1408
1409 /*if (blit_start_log)
1410 {
1411         if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
1412         {
1413                 WriteLog("\nBytes at 004D58:\n");
1414                 for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
1415                         WriteLog("%02X ", JaguarReadByte(i));
1416                 WriteLog("\nBytes at F03000:\n");
1417                 for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
1418                         WriteLog("%02X ", JaguarReadByte(i));
1419                 WriteLog("\n\n");
1420         }
1421 }//*/
1422
1423         blitter_working = 0;
1424 }
1425
1426 void blitter_init(void)
1427 {
1428         blitter_reset();
1429 }
1430
1431 void blitter_reset(void)
1432 {
1433         memset(blitter_ram, 0x00, 0xA0);
1434 }
1435
1436 void blitter_done(void)
1437 {
1438         WriteLog("BLIT: Done.\n");
1439 }
1440
1441 uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1442 {
1443         offset &= 0xFF;
1444
1445         // status register
1446 //This isn't cycle accurate--how to fix? !!! FIX !!!
1447         if (offset == (0x38 + 3))
1448                 return 0x01;    // always idle
1449
1450 //Attempted fix for AvP:
1451         if (offset >= 0x04 && offset <= 0x07)
1452 //              return (offset > 0x05 ? blitter_ram[PIXLINECOUNTER + offset - 0x04] : 0x00);
1453 //              return 0x00;    // WO register! What does it expect to see here???
1454 //This is it. I wonder if it just ignores the lower three bits?
1455                 return blitter_ram[A1_PIXEL + offset - 0x04];
1456
1457         return blitter_ram[offset];
1458 }
1459
1460 //Crappy!
1461 uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1462 {
1463         return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
1464 }
1465
1466 //Crappy!
1467 uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1468 {
1469         return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
1470 }
1471
1472 void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1473 {
1474 /*if (offset & 0xFF == 0x7B)
1475         WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
1476         offset &= 0xFF;
1477
1478 //      if ((offset >= 0x7C) && (offset <= 0x9B))
1479         // This handles writes to INTENSITY0-3 by also writing them to their proper places in
1480         // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
1481         if ((offset >= 0x7C) && (offset <= 0x9B))//8B))
1482         {
1483                 switch (offset)
1484                 {
1485                 // INTENSITY registers 0-3
1486                 case 0x7C: break;
1487                 case 0x7D: blitter_ram[PATTERNDATA + 1] = data; break;
1488                 case 0x7E: blitter_ram[SRCDATA + 0] = data; break;
1489                 case 0x7F: blitter_ram[SRCDATA + 1] = data; break;
1490
1491                 case 0x80: break;
1492                 case 0x81: blitter_ram[PATTERNDATA + 3] = data; break;
1493                 case 0x82: blitter_ram[SRCDATA + 2] = data; break;
1494                 case 0x83: blitter_ram[SRCDATA + 3] = data; break;
1495                 
1496                 case 0x84: break;
1497                 case 0x85: blitter_ram[PATTERNDATA + 5] = data; break;
1498                 case 0x86: blitter_ram[SRCDATA + 4] = data; break;
1499                 case 0x87: blitter_ram[SRCDATA + 5] = data; break;
1500                 
1501                 case 0x88: break;
1502                 case 0x89: blitter_ram[PATTERNDATA + 7] = data; break;
1503                 case 0x8A: blitter_ram[SRCDATA + 6] = data; break;
1504                 case 0x8B: blitter_ram[SRCDATA + 7] = data; break;
1505
1506                 // Z registers 0-3
1507                 case 0x8C: blitter_ram[SRCZINT + 0] = data; break;
1508                 case 0x8D: blitter_ram[SRCZINT + 1] = data; break;
1509                 case 0x8E: blitter_ram[SRCZFRAC + 0] = data; break;
1510                 case 0x8F: blitter_ram[SRCZFRAC + 1] = data; break;
1511
1512                 case 0x90: blitter_ram[SRCZINT + 2] = data; break;
1513                 case 0x91: blitter_ram[SRCZINT + 3] = data; break;
1514                 case 0x92: blitter_ram[SRCZFRAC + 2] = data; break;
1515                 case 0x93: blitter_ram[SRCZFRAC + 3] = data; break;
1516                 
1517                 case 0x94: blitter_ram[SRCZINT + 4] = data; break;
1518                 case 0x95: blitter_ram[SRCZINT + 5] = data; break;
1519                 case 0x96: blitter_ram[SRCZFRAC + 4] = data; break;
1520                 case 0x97: blitter_ram[SRCZFRAC + 5] = data; break;
1521                 
1522                 case 0x98: blitter_ram[SRCZINT + 6] = data; break;
1523                 case 0x99: blitter_ram[SRCZINT + 7] = data; break;
1524                 case 0x9A: blitter_ram[SRCZFRAC + 6] = data; break;
1525                 case 0x9B: blitter_ram[SRCZFRAC + 7] = data; break;
1526                 }
1527         }
1528
1529         blitter_ram[offset] = data;
1530 }
1531
1532 void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1533 {
1534 //#if 1
1535 /*      if (offset & 0xFF == A1_PIXEL && data == 14368)
1536         {
1537                 WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1538 extern bool doGPUDis;
1539 doGPUDis = true;
1540         }
1541         if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368)
1542         {
1543                 WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1544 extern bool doGPUDis;
1545 doGPUDis = true;
1546         }//*/
1547 //#endif
1548
1549         BlitterWriteByte(offset+0, (data>>8) & 0xFF, who);
1550         BlitterWriteByte(offset+1, data & 0xFF, who);
1551
1552         if ((offset & 0xFF) == 0x3A)
1553         // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
1554         // But then again, according to the Jaguar docs, this is correct...!
1555 {
1556 /*extern int blit_start_log;
1557 extern bool doGPUDis;
1558 if (blit_start_log)
1559 {
1560         WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
1561         doGPUDis = true;
1562 }//*/
1563                 blitter_blit(GET32(blitter_ram, 0x38));
1564 }
1565 }
1566 //F02278,9,A,B
1567
1568 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1569 {
1570 //#if 1
1571 /*      if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368)
1572         {
1573                 WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1574 extern bool doGPUDis;
1575 doGPUDis = true;
1576         }//*/
1577 //#endif
1578
1579         BlitterWriteWord(offset, data >> 16, who);
1580         BlitterWriteWord(offset+2, data & 0xFFFF, who);
1581 }