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