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