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