]> Shamusworld >> Repos - virtualjaguar/blob - blitter.cpp
857c8d2392deef322ae98555c4a2f2b646b0fc59
[virtualjaguar] / 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 // This is DEFINITELY WRONG
446                                         if (a1_phrase_mode || a2_phrase_mode)
447                                                 inhibit = !inhibit;
448                                 }
449
450                                 if (CLIPA1)
451                                 {
452                                         inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
453                                                 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
454                                 }
455
456                                 // compute the write data and store
457                                 if (!inhibit)
458                                 {                       
459                                         if (PATDSEL)
460                                         {
461                                                 // use pattern data for write data
462                                                 writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
463                                         }
464                                         else if (INTADD)
465                                         {
466                                                 // intensity addition
467                                                 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
468                                                 if (!(TOPBEN) && writedata > 0xFF)
469                                                         writedata = 0xFF;
470                                                 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
471                                                 if (!(TOPNEN) && writedata > 0xFFF)
472                                                         writedata = 0xFFF;
473                                                 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
474                                         }
475                                         else
476                                         {
477                                                 if (LFU_NAN) writedata |= ~srcdata & ~dstdata;
478                                                 if (LFU_NA)  writedata |= ~srcdata & dstdata;
479                                                 if (LFU_AN)  writedata |= srcdata  & ~dstdata;
480                                                 if (LFU_A)       writedata |= srcdata  & dstdata;
481                                         }
482
483                                         if (GOURD) 
484                                                 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
485
486                                         if (SRCSHADE) 
487                                         {
488                                                 int intensity = srcdata & 0xFF;
489                                                 int ia = gd_ia >> 16;
490                                                 if (ia & 0x80)
491                                                         ia = 0xFFFFFF00 | ia;
492                                                 intensity += ia;
493                                                 if (intensity < 0)
494                                                         intensity = 0;
495                                                 if (intensity > 0xFF)
496                                                         intensity = 0xFF;
497                                                 writedata = (srcdata & 0xFF00) | intensity;
498                                         }
499                                 }
500                                 else
501                                 {
502                                         writedata = dstdata;
503                                         srczdata = dstzdata;
504                                 }
505
506                                 if (/*a1_phrase_mode || */BKGWREN || !inhibit)
507                                 {
508 /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
509 {
510         uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
511 // (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
512         if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
513                 WriteLog("32bpp pixel write: A1 Phrase mode --> ");
514 }//*/
515                                         // write to the destination
516                                         WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
517                                         if (DSTWRZ)
518                                                 WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
519                                 }
520                         }
521                         else    // if (DSTA2)
522                         {
523                                 // load src data and Z
524                                 if (SRCEN)
525                                 {
526                                         srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
527                                         if (SRCENZ)
528                                                 srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
529                                         else if (cmd & 0x0001C020)
530                                                 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
531                                 }
532                                 else
533                                 {
534                                         srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
535                                         if (cmd & 0x001C020)
536                                                 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
537                                 }
538
539                                 // load dst data and Z 
540                                 if (DSTEN)
541                                 {
542                                         dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
543                                         if (DSTENZ)
544                                                 dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
545                                         else
546                                                 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
547                                 }
548                                 else
549                                 {
550                                         dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
551                                         if (DSTENZ)
552                                                 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
553                                 }
554
555                                 if (GOURZ) 
556                                         srczdata = z_i[colour_index] >> 16;
557
558                                 // apply z comparator
559                                 if (Z_OP_INF) if (srczdata < dstzdata)  inhibit = 1;
560                                 if (Z_OP_EQU) if (srczdata == dstzdata) inhibit = 1;
561                                 if (Z_OP_SUP) if (srczdata > dstzdata)  inhibit = 1;
562                                 
563                                 // apply data comparator
564 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
565                                 if (DCOMPEN | BCOMPEN)
566                                 {
567                                         if (!CMPDST)
568                                         {
569                                                 // compare source pixel with pattern pixel
570 // AvP: Numbers are correct, but sprites are not!
571 //This doesn't seem to be a problem... But could still be wrong...
572 /*                                              if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
573 //                                              if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
574                                                         inhibit = 1;//*/
575 // This is probably not 100% correct... It works in the 1bpp case
576 // (in A1 <- A2 mode, that is...)
577 // AvP: This is causing blocks to be written instead of bit patterns...
578 // Works now...
579 // NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
580 /*                                              uint32 A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
581                                                 if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
582                                                         inhibit = (srcdata == 0 ? 1: 0);
583                                                 else
584                                                         WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
585 // What it boils down to is this:
586                                                 if (srcdata == 0)
587                                                         inhibit = 1;//*/
588                                         }
589                                         else
590                                         {
591                                                 // compare destination pixel with pattern pixel
592                                                 if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
593 //                                              if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
594                                                         inhibit = 1;
595                                         }
596                                         if (a1_phrase_mode || a2_phrase_mode)
597                                                 inhibit =! inhibit;
598                                 }
599                                 
600                                 if (CLIPA1)
601                                 {
602                                         inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
603                                                 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
604                                 }
605
606                                 // compute the write data and store
607                                 if (!inhibit)
608                                 {                       
609                                         if (PATDSEL)
610                                         {
611                                                 // use pattern data for write data
612                                                 writedata= READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
613                                         }
614                                         else if (INTADD)
615                                         {
616                                                 // intensity addition
617                                                 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
618                                                 if (!(TOPBEN) && writedata > 0xFF)
619                                                         writedata = 0xFF;
620                                                 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
621                                                 if (!(TOPNEN) && writedata > 0xFFF)
622                                                         writedata = 0xFFF;
623                                                 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
624                                         }
625                                         else
626                                         {
627                                                 if (LFU_NAN)
628                                                         writedata |= ~srcdata & ~dstdata;
629                                                 if (LFU_NA)
630                                                         writedata |= ~srcdata & dstdata;
631                                                 if (LFU_AN)
632                                                         writedata |= srcdata & ~dstdata;
633                                                 if (LFU_A)
634                                                         writedata |= srcdata & dstdata;
635                                         }
636
637                                         if (GOURD) 
638                                                 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
639
640                                         if (SRCSHADE) 
641                                         {
642                                                 int intensity = srcdata & 0xFF;
643                                                 int ia = gd_ia >> 16;
644                                                 if (ia & 0x80)
645                                                         ia = 0xFFFFFF00 | ia;
646                                                 intensity += ia;
647                                                 if (intensity < 0)
648                                                         intensity = 0;
649                                                 if (intensity > 0xFF)
650                                                         intensity = 0xFF;
651                                                 writedata = (srcdata & 0xFF00) | intensity;
652                                         }
653                                 }
654                                 else
655                                 {
656                                         writedata = dstdata;
657                                         srczdata = dstzdata;
658                                 }
659
660                                 if (/*a2_phrase_mode || */BKGWREN || !inhibit)
661                                 {
662 /*if (logGo)
663 {
664         uint32 offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
665 // (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
666         WriteLog("[%08X:%04X] ", offset, writedata);
667 }//*/
668                                         // write to the destination
669                                         WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
670                                         if (DSTWRZ)
671                                                 WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
672                                 }
673                         }
674
675                         // update x and y
676                         a1_x += a1_xadd;
677                         a1_y += a1_yadd;
678                         a2_x = (a2_x + a2_xadd) & a2_mask_x;
679                         a2_y = (a2_y + a2_yadd) & a2_mask_y;
680
681                         if (GOURZ)
682                                 z_i[colour_index] += zadd;
683
684                         if (GOURD || SRCSHADE)
685                         {
686                                 gd_i[colour_index] += gd_ia;
687                                 gd_c[colour_index] += gd_ca;
688                         }
689                         if (GOURD || SRCSHADE || GOURZ)
690                         {
691                                 if (a1_phrase_mode)
692                                         colour_index = (colour_index + 1) & 0x03;
693                         }
694                 }
695
696                 a1_x += a1_step_x;
697                 a1_y += a1_step_y;
698                 a2_x += a2_step_x;
699                 a2_y += a2_step_y;
700
701 /*              if (a2_phrase_mode)
702                 {
703                         a1_x+=(64/a1_psize)*a1_xadd;
704                 }       
705                 if (a2_phrase_mode)
706                 {
707                         for (int nb=0;nb<(64/a2_psize)+1;nb++)
708                                 a2_x = (a2_x + a2_xadd) & a2_mask_x;
709                 }
710 */      }
711         
712         // write values back to registers 
713         WREG(A1_PIXEL,  (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
714         WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
715         WREG(A2_PIXEL,  (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
716 specialLog = false;
717 }
718
719 void blitter_blit(uint32 cmd)
720 {
721         uint32 pitchValue[4] = { 0, 1, 3, 2 };
722         colour_index = 0;
723         src = cmd & 0x07;
724         dst = (cmd >> 3) & 0x07;
725         misc = (cmd >> 6) & 0x03;
726         a1ctl = (cmd >> 8) & 0x7;
727         mode = (cmd >> 11) & 0x07;
728         ity = (cmd >> 14) & 0x0F;
729         zop = (cmd >> 18) & 0x07;
730         op = (cmd >> 21) & 0x0F;
731         ctrl = (cmd >> 25) & 0x3F;
732
733         // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
734         // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
735         a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
736         a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
737
738         a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
739         a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
740         
741         xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
742         xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
743 //      a1_pitch = (REG(A1_FLAGS) & 3) ^ ((REG(A1_FLAGS) & 2) >> 1);
744 //      a2_pitch = (REG(A2_FLAGS) & 3) ^ ((REG(A2_FLAGS) & 2) >> 1);
745         a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
746         a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
747
748         n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
749         n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
750
751         a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
752         a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
753 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
754 //But it seems to fuck up T2K! !!! FIX !!!
755 //Could it be sign extended??? Doesn't seem to be so according to JTRM
756 //      a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
757
758 //      a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
759 // According to JTRM, this must give a *whole number* of phrases in the current
760 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
761         UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
762         a1_width = ((0x04 | m) << e) >> 2;//*/
763
764         a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
765         a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
766 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
767 //But it seems to fuck up T2K! !!! FIX !!!
768 //      a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
769
770 //      a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
771 // According to JTRM, this must give a *whole number* of phrases in the current
772 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
773         m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
774         a2_width = ((0x04 | m) << e) >> 2;//*/
775         a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
776         a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
777
778         // Check for "use mask" flag
779         if (!(REG(A2_FLAGS) & 0x8000))
780         {
781                 a2_mask_x = 0xFFFFFFFF; // must be 16.16
782                 a2_mask_y = 0xFFFFFFFF; // must be 16.16
783         }
784
785         a1_phrase_mode = 0;
786
787         // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
788         a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
789
790         if (YSIGNSUB_A1)
791                 a1_yadd = -a1_yadd;
792
793         // determine a1_xadd
794         switch (xadd_a1_control)
795         {
796         case XADDPHR:
797 // This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
798                 // add phrase offset to X and truncate
799                 a1_xadd = 1 << 16;
800                 a1_phrase_mode = 1;
801                 break;
802         case XADDPIX:
803                 // add pixelsize (1) to X
804                 a1_xadd = 1 << 16;
805                 break;
806         case XADD0:     
807                 // add zero (for those nice vertical lines)
808                 a1_xadd = 0;
809                 break;
810         case XADDINC:
811                 // add the contents of the increment register
812                 a1_xadd = (REG(A1_INC) << 16)            | (REG(A1_FINC) & 0xFFFF);
813                 a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
814                 break;
815         }
816         if (XSIGNSUB_A1)
817                 a1_xadd = -a1_xadd;
818
819         if (YSIGNSUB_A2)
820                 a2_yadd = -a2_yadd;
821
822         a2_phrase_mode = 0;
823
824         // determine a2_xadd
825         switch (xadd_a2_control)
826         {
827         case XADDPHR:
828                 // add phrase offset to X and truncate
829                 a2_xadd = 1 << 16;
830                 a2_phrase_mode = 1;
831                 break;
832         case XADDPIX:
833                 // add pixelsize (1) to X
834                 a2_xadd = 1 << 16;
835                 break;
836         case XADD0:     
837                 // add zero (for those nice vertical lines)
838                 a2_xadd = 0;
839                 break;
840 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
841         case XADDINC:
842 WriteLog("BLIT: Asked to used invalid bit combo for A2...\n");
843                 // add the contents of the increment register
844                 // since there is no register for a2 we just add 1
845 //Let's do nothing, since it's not listed as a valid bit combo...
846 //              a2_xadd = 1 << 16;
847                 break;
848         }
849         if (XSIGNSUB_A2)
850                 a2_xadd = -a2_xadd;
851
852         // Modify outer loop steps based on blitter command
853
854         a1_step_x = 0;
855         a1_step_y = 0;
856         a2_step_x = 0;
857         a2_step_y = 0;
858
859         if (UPDA1F)
860                 a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
861                 a1_step_y = (REG(A1_FSTEP) >> 16);
862
863         if (UPDA1)
864                 a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
865                 a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
866
867         if (UPDA2)
868                 a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
869                 a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
870
871         outer_loop = n_lines;
872
873         // Clipping...
874
875         if (CLIPA1)
876                 a1_clip_x = REG(A1_CLIP) & 0x7FFF,
877                 a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
878
879 // This phrase sizing is incorrect as well... !!! FIX !!!
880 // Err, this is pixel size... (and it's OK)
881         a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
882         a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
883
884         // zbuffering
885         if (GOURZ)
886         {
887                 zadd = JaguarReadLong(0xF02274, BLITTER);
888
889                 for(int v=0; v<4; v++) 
890                         z_i[v] = (int32)JaguarReadLong(0xF0228C + (v << 2), BLITTER);
891         }
892         if (GOURD || GOURZ || SRCSHADE)
893         {
894                 // gouraud shading
895                 gouraud_add = JaguarReadLong(0xF02270, BLITTER);
896                 
897                 gd_c[0] = JaguarReadByte(0xF02268, BLITTER);
898                 gd_i[0] = JaguarReadByte(0xF02269, BLITTER);
899                 gd_i[0] <<= 16;
900                 gd_i[0] |= JaguarReadWord(0xF02240, BLITTER);
901
902                 gd_c[1] = JaguarReadByte(0xF0226A, BLITTER);
903                 gd_i[1] = JaguarReadByte(0xF0226B, BLITTER);
904                 gd_i[1] <<= 16;
905                 gd_i[1] |= JaguarReadWord(0xF02242, BLITTER);
906
907                 gd_c[2] = JaguarReadByte(0xF0226C, BLITTER);
908                 gd_i[2] = JaguarReadByte(0xF0226D, BLITTER);
909                 gd_i[2] <<= 16;
910                 gd_i[2] |= JaguarReadWord(0xF02244, BLITTER);
911
912                 gd_c[3] = JaguarReadByte(0xF0226E, BLITTER);
913                 gd_i[3] = JaguarReadByte(0xF0226F, BLITTER);
914                 gd_i[3] <<= 16; 
915                 gd_i[3] |= JaguarReadWord(0xF02246, BLITTER);
916
917                 gd_ia = gouraud_add & 0xFFFFFF;
918                 if (gd_ia & 0x800000)
919                         gd_ia = 0xFF000000 | gd_ia;
920
921                 gd_ca = (gouraud_add>>24) & 0xFF;
922                 if (gd_ca & 0x80)
923                         gd_ca = 0xFFFFFF00 | gd_ca;
924         }
925
926         // fix for zoop! and syndicate
927 /*      if ((jaguar_mainRom_crc32==0x501be17c)||
928                 (jaguar_mainRom_crc32==0x70895c51)||
929                 (jaguar_mainRom_crc32==0x0f1f1497)||
930                 (jaguar_mainRom_crc32==0xfc8f0dcd)
931            )
932         {
933                 if (a1_step_x < 0)
934                         a1_step_x = (-n_pixels) * 65536;
935
936                 if (a2_step_x < 0)
937                         a2_step_x = (-n_pixels) * 65536;;
938         }
939         else
940         // fix for wolfenstein 3d
941         if (jaguar_mainRom_crc32==0x3966698f)
942         {
943                 if (n_pixels==24)
944                 {
945                         if ((a1_step_x / 65536)==-28)
946                         {
947                                 a1_step_x=-24*65536; // au lieu de -28
948                                 a2_step_x=  0*65536; // au lieu de -8
949                         }
950                 }
951         } 
952         else
953         // fix for Tempest 2000
954         if (jaguar_mainRom_crc32==0x32816d44)
955         {
956
957                 if ((n_lines!=1)&&((n_pixels==288)||(n_pixels==384)))
958                 {
959                         WriteLog("Blit!\n");
960                         WriteLog("  cmd      = 0x%.8x\n",cmd);
961                         WriteLog("  a1_base  = %08X\n", a1_addr);
962                         WriteLog("  a1_pitch = %d\n", a1_pitch);
963                         WriteLog("  a1_psize = %d\n", a1_psize);
964                         WriteLog("  a1_width = %d\n", a1_width);
965                         WriteLog("  a1_xadd  = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
966                         WriteLog("  a1_yadd  = %f\n", (float)a1_yadd / 65536.0);
967                         WriteLog("  a1_xstep = %f\n", (float)a1_step_x / 65536.0);
968                         WriteLog("  a1_ystep = %f\n", (float)a1_step_y / 65536.0);
969                         WriteLog("  a1_x     = %f\n", (float)a1_x / 65536.0);
970                         WriteLog("  a1_y     = %f\n", (float)a1_y / 65536.0);
971                         WriteLog("  a1_zoffs = %i\n",a1_zoffs);
972
973                         WriteLog("  a2_base  = %08X\n", a2_addr);
974                         WriteLog("  a2_pitch = %d\n", a2_pitch);
975                         WriteLog("  a2_psize = %d\n", a2_psize);
976                         WriteLog("  a2_width = %d\n", a2_width);
977                         WriteLog("  a2_xadd  = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
978                         WriteLog("  a2_yadd  = %f\n", (float)a2_yadd / 65536.0);
979                         WriteLog("  a2_xstep = %f\n", (float)a2_step_x / 65536.0);
980                         WriteLog("  a2_ystep = %f\n", (float)a2_step_y / 65536.0);
981                         WriteLog("  a2_x     = %f\n", (float)a2_x / 65536.0);
982                         WriteLog("  a2_y     = %f\n", (float)a2_y / 65536.0);
983                         WriteLog("  a2_mask_x= 0x%.4x\n",a2_mask_x);
984                         WriteLog("  a2_mask_y= 0x%.4x\n",a2_mask_y);
985                         WriteLog("  a2_zoffs = %i\n",a2_zoffs);
986
987                         WriteLog("  count    = %d x %d\n", n_pixels, n_lines);
988
989                         WriteLog("  command  = %08X\n", cmd);
990                         WriteLog("  dsten    = %i\n",DSTEN);
991                         WriteLog("  srcen    = %i\n",SRCEN);
992                         WriteLog("  patdsel  = %i\n",PATDSEL);
993                         WriteLog("  color    = 0x%.8x\n",REG(PATTERNDATA));
994                         WriteLog("  dcompen  = %i\n",DCOMPEN);
995                         WriteLog("  bcompen  = %i\n",BCOMPEN);
996                         WriteLog("  cmpdst   = %i\n",CMPDST);
997                         WriteLog("  GOURZ    = %i\n",GOURZ);
998                         WriteLog("  GOURD    = %i\n",GOURD);
999                         WriteLog("  SRCSHADE = %i\n",SRCSHADE);
1000                         WriteLog("  DSTDATA  = 0x%.8x%.8x\n",REG(DSTDATA),REG(DSTDATA+4));
1001                 }       
1002         }//*/
1003
1004 #ifdef LOG_BLITS
1005         if (start_logging)
1006         {
1007                 WriteLog("Blit!\n");
1008                 WriteLog("  cmd      = 0x%.8x\n",cmd);
1009                 WriteLog("  a1_base  = %08X\n", a1_addr);
1010                 WriteLog("  a1_pitch = %d\n", a1_pitch);
1011                 WriteLog("  a1_psize = %d\n", a1_psize);
1012                 WriteLog("  a1_width = %d\n", a1_width);
1013                 WriteLog("  a1_xadd  = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1014                 WriteLog("  a1_yadd  = %f\n", (float)a1_yadd / 65536.0);
1015                 WriteLog("  a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1016                 WriteLog("  a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1017                 WriteLog("  a1_x     = %f\n", (float)a1_x / 65536.0);
1018                 WriteLog("  a1_y     = %f\n", (float)a1_y / 65536.0);
1019                 WriteLog("  a1_zoffs = %i\n",a1_zoffs);
1020
1021                 WriteLog("  a2_base  = %08X\n", a2_addr);
1022                 WriteLog("  a2_pitch = %d\n", a2_pitch);
1023                 WriteLog("  a2_psize = %d\n", a2_psize);
1024                 WriteLog("  a2_width = %d\n", a2_width);
1025                 WriteLog("  a2_xadd  = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1026                 WriteLog("  a2_yadd  = %f\n", (float)a2_yadd / 65536.0);
1027                 WriteLog("  a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1028                 WriteLog("  a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1029                 WriteLog("  a2_x     = %f\n", (float)a2_x / 65536.0);
1030                 WriteLog("  a2_y     = %f\n", (float)a2_y / 65536.0);
1031                 WriteLog("  a2_mask_x= 0x%.4x\n",a2_mask_x);
1032                 WriteLog("  a2_mask_y= 0x%.4x\n",a2_mask_y);
1033                 WriteLog("  a2_zoffs = %i\n",a2_zoffs);
1034
1035                 WriteLog("  count    = %d x %d\n", n_pixels, n_lines);
1036
1037                 WriteLog("  command  = %08X\n", cmd);
1038                 WriteLog("  dsten    = %i\n",DSTEN);
1039                 WriteLog("  srcen    = %i\n",SRCEN);
1040                 WriteLog("  patdsel  = %i\n",PATDSEL);
1041                 WriteLog("  color    = 0x%.8x\n",REG(PATTERNDATA));
1042                 WriteLog("  dcompen  = %i\n",DCOMPEN);
1043                 WriteLog("  bcompen  = %i\n",BCOMPEN);
1044                 WriteLog("  cmpdst   = %i\n",CMPDST);
1045                 WriteLog("  GOURZ   = %i\n",GOURZ);
1046                 WriteLog("  GOURD   = %i\n",GOURD);
1047                 WriteLog("  SRCSHADE= %i\n",SRCSHADE);
1048         }       
1049 #endif
1050
1051 extern int blit_start_log;
1052 extern int op_start_log;
1053 if (blit_start_log)
1054 {
1055         char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
1056         char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
1057         char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1058                 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1059         uint32 src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
1060                 a1ctl = (cmd >> 8) & 0x07, mode = (cmd >> 11) & 0x07, ity = (cmd >> 14) & 0x0F,
1061                 zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F;
1062         UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1063         uint32 p1 = a1f & 0x07, p2 = a2f & 0x07,
1064                 d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
1065                 zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
1066                 w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
1067                 ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
1068         UINT32 iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
1069         UINT32 iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
1070         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);
1071 //      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);
1072
1073         WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
1074         WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
1075         WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
1076         WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
1077         WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "ZBUFF" : ""));
1078         WriteLog("ity: %s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""));
1079         WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
1080         WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
1081         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" : ""));
1082
1083         if (UPDA2)
1084         {
1085                 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);
1086         }
1087
1088         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"));
1089         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"));
1090         WriteLog("        A1 x/y: %d/%d, A2 x/y: %d/%d\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16);
1091 //      blit_start_log = 0;
1092 //      op_start_log = 1;
1093 }
1094
1095         blitter_working = 1;
1096 //#ifndef USE_GENERIC_BLITTER
1097 //      if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
1098 //#endif
1099         blitter_generic(cmd);
1100
1101 /*if (blit_start_log)
1102 {
1103         if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
1104         {
1105                 WriteLog("\nBytes at 004D58:\n");
1106                 for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
1107                         WriteLog("%02X ", JaguarReadByte(i));
1108                 WriteLog("\nBytes at F03000:\n");
1109                 for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
1110                         WriteLog("%02X ", JaguarReadByte(i));
1111                 WriteLog("\n\n");
1112         }
1113 }//*/
1114
1115         blitter_working = 0;
1116 }
1117
1118 void blitter_init(void)
1119 {
1120         blitter_reset();
1121 }
1122
1123 void blitter_reset(void)
1124 {
1125         memset(blitter_ram, 0x00, 0xA0);
1126 }
1127
1128 void blitter_done(void)
1129 {
1130         WriteLog("BLIT: Done.\n");
1131 }
1132
1133 uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1134 {
1135         offset &= 0xFF;
1136
1137         // status register
1138         if (offset == (0x38 + 3))
1139                 return 0x01;    // always idle
1140
1141         return blitter_ram[offset];
1142 }
1143
1144 uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1145 {
1146         return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
1147 }
1148
1149 uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1150 {
1151         return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
1152 }
1153
1154 void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1155 {
1156 /*if (offset & 0xFF == 0x7B)
1157         WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
1158         offset &= 0xFF;
1159
1160 //      if ((offset >= 0x7C) && (offset <= 0x9B))
1161         if ((offset >= 0x7C) && (offset <= 0x8B))
1162         {
1163                 switch (offset)
1164                 {
1165                 case 0x7C: break;
1166                 case 0x7D: blitter_ram[0x69] = data; break;
1167                 case 0x7E: blitter_ram[0x40] = data; break;
1168                 case 0x7F: blitter_ram[0x41] = data; break;
1169
1170                 case 0x80: break;
1171                 case 0x81: blitter_ram[0x6B] = data; break;
1172                 case 0x82: blitter_ram[0x42] = data; break;
1173                 case 0x83: blitter_ram[0x43] = data; break;
1174                 
1175                 case 0x84: break;
1176                 case 0x85: blitter_ram[0x6D] = data; break;
1177                 case 0x86: blitter_ram[0x44] = data; break;
1178                 case 0x87: blitter_ram[0x45] = data; break;
1179                 
1180                 case 0x88: break;
1181                 case 0x89: blitter_ram[0x6F] = data; break;
1182 //Mistyped?
1183 //              case 0x9A: blitter_ram[0x46] = data; break;
1184 //              case 0x9B: blitter_ram[0x47] = data; break;
1185                 case 0x8A: blitter_ram[0x46] = data; break;
1186                 case 0x8B: blitter_ram[0x47] = data; break;
1187                 }
1188         }
1189
1190         blitter_ram[offset] = data;
1191 }
1192
1193 void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1194 {
1195         BlitterWriteByte(offset+0, (data>>8) & 0xFF, who);
1196         BlitterWriteByte(offset+1, data & 0xFF, who);
1197
1198         if ((offset & 0xFF) == 0x3A)
1199         // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
1200         // But then again, according to the Jaguar docs, this is correct...!
1201                 blitter_blit(GET32(blitter_ram, 0x38));
1202 // Testing purposes only!
1203 //This does the clipping correctly, but not the Gouraud shading...
1204 //              blitter2_exec(GET32(blitter_ram, 0x38));
1205 }
1206 //F02278,9,A,B
1207
1208 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1209 {
1210         BlitterWriteWord(offset, data >> 16, who);
1211         BlitterWriteWord(offset+2, data & 0xFFFF, who);
1212 }