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