4 // Originally by David Raingeard
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Extensive cleanups/fixes by James L. Hammons
9 bool specialLog = false;
10 extern int effect_start;
11 extern int blit_start_log;
16 #define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
17 | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
18 #define WREG(A,D) (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
19 blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
21 // Blitter registers (offsets from F02200)
23 #define A1_BASE ((UINT32)0x00)
24 #define A1_FLAGS ((UINT32)0x04)
25 #define A1_CLIP ((UINT32)0x08) // Height and width values for clipping
26 #define A1_PIXEL ((UINT32)0x0C) // Integer part of the pixel (Y.i and X.i)
27 #define A1_STEP ((UINT32)0x10) // Integer part of the step
28 #define A1_FSTEP ((UINT32)0x14) // Fractionnal part of the step
29 #define A1_FPIXEL ((UINT32)0x18) // Fractionnal part of the pixel (Y.f and X.f)
30 #define A1_INC ((UINT32)0x1C) // Integer part of the increment
31 #define A1_FINC ((UINT32)0x20) // Fractional part of the increment
32 #define A2_BASE ((UINT32)0x24)
33 #define A2_FLAGS ((UINT32)0x28)
34 #define A2_MASK ((UINT32)0x2C) // Modulo values for x and y (M.y and M.x)
35 #define A2_PIXEL ((UINT32)0x30) // Integer part of the pixel (no fractional part for A2)
36 #define A2_STEP ((UINT32)0x34) // Integer part of the step (no fractional part for A2)
37 #define COMMAND ((UINT32)0x38)
38 #define PIXLINECOUNTER ((UINT32)0x3C)
39 #define SRCDATA ((UINT32)0x40)
40 #define DSTDATA ((UINT32)0x48)
41 #define DSTZ ((UINT32)0x50)
42 #define SRCZINT ((UINT32)0x58)
43 #define SRCZFRAC ((UINT32)0x60)
44 #define PATTERNDATA ((UINT32)0x68)
45 #define INTENSITYINC ((UINT32)0x70)
46 #define ZINC ((UINT32)0x74)
47 #define COLLISIONCTRL ((UINT32)0x78)
48 #define PHRASEINT0 ((UINT32)0x7C)
49 #define PHRASEINT1 ((UINT32)0x80)
50 #define PHRASEINT2 ((UINT32)0x84)
51 #define PHRASEINT3 ((UINT32)0x88)
52 #define PHRASEZ0 ((UINT32)0x8C)
53 #define PHRASEZ1 ((UINT32)0x90)
54 #define PHRASEZ2 ((UINT32)0x94)
55 #define PHRASEZ3 ((UINT32)0x98)
57 // Blitter command bits
59 #define SRCEN (cmd & 0x00000001)
60 #define SRCENZ (cmd & 0x00000002)
61 #define SRCENX (cmd & 0x00000004)
62 #define DSTEN (cmd & 0x00000008)
63 #define DSTENZ (cmd & 0x00000010)
64 #define DSTWRZ (cmd & 0x00000020)
65 #define CLIPA1 (cmd & 0x00000040)
67 #define UPDA1F (cmd & 0x00000100)
68 #define UPDA1 (cmd & 0x00000200)
69 #define UPDA2 (cmd & 0x00000400)
71 #define DSTA2 (cmd & 0x00000800)
73 #define Z_OP_INF (cmd & 0x00040000)
74 #define Z_OP_EQU (cmd & 0x00080000)
75 #define Z_OP_SUP (cmd & 0x00100000)
77 #define LFU_NAN (cmd & 0x00200000)
78 #define LFU_NA (cmd & 0x00400000)
79 #define LFU_AN (cmd & 0x00800000)
80 #define LFU_A (cmd & 0x01000000)
82 #define CMPDST (cmd & 0x02000000)
83 #define BCOMPEN (cmd & 0x04000000)
84 #define DCOMPEN (cmd & 0x08000000)
86 #define PATDSEL (cmd & 0x00010000)
87 #define ADDDSEL (cmd & 0x00020000)
88 #define TOPBEN (cmd & 0x00004000)
89 #define TOPNEN (cmd & 0x00008000)
90 #define BKGWREN (cmd & 0x10000000)
91 #define GOURD (cmd & 0x00001000)
92 #define GOURZ (cmd & 0x00002000)
93 #define SRCSHADE (cmd & 0x40000000)
101 #define XSIGNSUB_A1 (REG(A1_FLAGS)&0x080000)
102 #define XSIGNSUB_A2 (REG(A2_FLAGS)&0x080000)
104 #define YSIGNSUB_A1 (REG(A1_FLAGS)&0x100000)
105 #define YSIGNSUB_A2 (REG(A2_FLAGS)&0x100000)
107 #define YADD1_A1 (REG(A1_FLAGS)&0x040000)
108 #define YADD1_A2 (REG(A2_FLAGS)&0x040000)
110 //Put 'em back, once we fix the problem!!! [KO]
112 #define PIXEL_SHIFT_1(a) (((~a##_x) >> 16) & 7)
113 #define PIXEL_OFFSET_1(a) (((((UINT32)a##_y >> 16) * a##_width / 8) + (((UINT32)a##_x >> 19) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 19) & 7))
114 #define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
115 //#define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
118 #define PIXEL_SHIFT_2(a) (((~a##_x) >> 15) & 6)
119 #define PIXEL_OFFSET_2(a) (((((UINT32)a##_y >> 16) * a##_width / 4) + (((UINT32)a##_x >> 18) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 18) & 7))
120 #define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03)
121 //#define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
124 #define PIXEL_SHIFT_4(a) (((~a##_x) >> 14) & 4)
125 #define PIXEL_OFFSET_4(a) (((((UINT32)a##_y >> 16) * (a##_width/2)) + (((UINT32)a##_x >> 17) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 17) & 7))
126 #define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f)
127 //#define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
130 #define PIXEL_OFFSET_8(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 7))
131 #define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER))
132 //#define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a)))
135 #define PIXEL_OFFSET_16(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 3))
136 #define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER))
137 //#define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
140 #define PIXEL_OFFSET_32(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
141 #define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER))
142 //#define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
145 #define READ_PIXEL(a,f) (\
146 (((f>>3)&0x07) == 0) ? (READ_PIXEL_1(a)) : \
147 (((f>>3)&0x07) == 1) ? (READ_PIXEL_2(a)) : \
148 (((f>>3)&0x07) == 2) ? (READ_PIXEL_4(a)) : \
149 (((f>>3)&0x07) == 3) ? (READ_PIXEL_8(a)) : \
150 (((f>>3)&0x07) == 4) ? (READ_PIXEL_16(a)) : \
151 (((f>>3)&0x07) == 5) ? (READ_PIXEL_32(a)) : 0)
153 // 16 bpp z data read
154 #define ZDATA_OFFSET_16(a) (PIXEL_OFFSET_16(a) + a##_zoffs * 4)
155 #define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER))
156 //#define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
159 #define READ_ZDATA(a,f) (READ_ZDATA_16(a))
161 // 16 bpp z data write
162 #define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); }
163 //#define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); }
166 #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d);
169 #define READ_RDATA_1(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 19) & 0x04))) >> (((UINT32)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001))
172 #define READ_RDATA_2(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 18) & 0x04))) >> (((UINT32)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003))
175 #define READ_RDATA_4(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 17) & 0x04))) >> (((UINT32)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F))
178 #define READ_RDATA_8(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 16) & 0x04))) >> (((UINT32)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF))
180 // 16 bpp r data read
181 #define READ_RDATA_16(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 15) & 0x04))) >> (((UINT32)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF))
183 // 32 bpp r data read
184 #define READ_RDATA_32(r,a,p) ((p) ? REG(r+(((UINT32)a##_x >> 14) & 0x04)) : REG(r))
186 // register data read
187 #define READ_RDATA(r,a,f,p) (\
188 (((f>>3)&0x07) == 0) ? (READ_RDATA_1(r,a,p)) : \
189 (((f>>3)&0x07) == 1) ? (READ_RDATA_2(r,a,p)) : \
190 (((f>>3)&0x07) == 2) ? (READ_RDATA_4(r,a,p)) : \
191 (((f>>3)&0x07) == 3) ? (READ_RDATA_8(r,a,p)) : \
192 (((f>>3)&0x07) == 4) ? (READ_RDATA_16(r,a,p)) : \
193 (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0)
196 #define WRITE_PIXEL_1(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_1(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER)&(~(0x01 << PIXEL_SHIFT_1(a))))|(d<<PIXEL_SHIFT_1(a)), BLITTER); }
197 //#define WRITE_PIXEL_1(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_1(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a))&(~(0x01 << PIXEL_SHIFT_1(a))))|(d<<PIXEL_SHIFT_1(a))); }
200 #define WRITE_PIXEL_2(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_2(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER)&(~(0x03 << PIXEL_SHIFT_2(a))))|(d<<PIXEL_SHIFT_2(a)), BLITTER); }
201 //#define WRITE_PIXEL_2(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_2(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a))&(~(0x03 << PIXEL_SHIFT_2(a))))|(d<<PIXEL_SHIFT_2(a))); }
204 #define WRITE_PIXEL_4(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_4(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER)&(~(0x0f << PIXEL_SHIFT_4(a))))|(d<<PIXEL_SHIFT_4(a)), BLITTER); }
205 //#define WRITE_PIXEL_4(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_4(a), (JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a))&(~(0x0f << PIXEL_SHIFT_4(a))))|(d<<PIXEL_SHIFT_4(a))); }
208 #define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d, BLITTER); }
209 //#define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d); }
211 // 16 bpp pixel write
212 //#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
213 #define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), d, BLITTER); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); }
214 //#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), d); if (specialLog) WriteLog("Pixel write address: %08X\n", a##_addr+(PIXEL_OFFSET_16(a)<<1)); }
216 // 32 bpp pixel write
217 #define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); }
218 //#define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); }
221 #define WRITE_PIXEL(a,f,d) {\
222 switch ((f>>3)&0x07) { \
223 case 0: WRITE_PIXEL_1(a,d); break; \
224 case 1: WRITE_PIXEL_2(a,d); break; \
225 case 2: WRITE_PIXEL_4(a,d); break; \
226 case 3: WRITE_PIXEL_8(a,d); break; \
227 case 4: WRITE_PIXEL_16(a,d); break; \
228 case 5: WRITE_PIXEL_32(a,d); break; \
231 // External global variables
233 extern int jaguar_active_memory_dumps;
235 // Local global variables
237 int start_logging = 0;
238 uint8 blitter_working = 0;
240 // Blitter register RAM (most of it is hidden from the user)
242 static uint8 blitter_ram[0x100];
244 // Width in Pixels of a Scanline
245 // This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
246 // of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
247 // the exponent. Valid values for the exponent range from 0 to 11 (decimal). It's easiest to think of it
248 // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to
249 // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place
250 // being shifted to the right 3 places).
251 /*static uint32 blitter_scanline_width[48] =
253 0, 0, 0, 0, // Note: This would really translate to 1, 1, 1, 1
263 1024, 1280, 1536, 1792,
264 2048, 2560, 3072, 3584
267 //static uint8 * tom_ram_8;
268 //static uint8 * paletteRam;
278 static uint32 a1_addr;
279 static uint32 a2_addr;
280 static int32 a1_zoffs;
281 static int32 a2_zoffs;
282 static uint32 xadd_a1_control;
283 static uint32 xadd_a2_control;
284 static int32 a1_pitch;
285 static int32 a2_pitch;
286 static uint32 n_pixels;
287 static uint32 n_lines;
290 static int32 a1_width;
293 static int32 a2_width;
294 static int32 a2_mask_x;
295 static int32 a2_mask_y;
296 static int32 a1_xadd;
297 static int32 a1_yadd;
298 static int32 a2_xadd;
299 static int32 a2_yadd;
300 static uint8 a1_phrase_mode;
301 static uint8 a2_phrase_mode;
302 static int32 a1_step_x = 0;
303 static int32 a1_step_y = 0;
304 static int32 a2_step_x = 0;
305 static int32 a2_step_y = 0;
306 static uint32 outer_loop;
307 static uint32 inner_loop;
308 static uint32 a2_psize;
309 static uint32 a1_psize;
310 static uint32 gouraud_add;
311 //static uint32 gouraud_data;
312 //static uint16 gint[4];
313 //static uint16 gfrac[4];
314 //static uint8 gcolour[4];
317 static int gd_ia, gd_ca;
318 static int colour_index = 0;
320 static uint32 z_i[4];
322 static int32 a1_clip_x, a1_clip_y;
324 // In the spirit of "get it right first, *then* optimize" I've taken the liberty
325 // of removing all the unnecessary code caching. If it turns out to be a good way
326 // to optimize the blitter, then we may revisit it in the future...
329 // Generic blit handler
331 void blitter_generic(uint32 cmd)
334 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
335 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
336 A1 step values: -2 (X), 1 (Y)
337 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
338 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
339 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
340 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
343 // specialLog = true;
344 /*if (cmd == 0x1401060C && blit_start_log)
345 specialLog = true;//*/
347 //uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
348 uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
349 uint32 bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07));
353 WriteLog("About to do n x m blit (BM width is ? pixels)...\n");
354 WriteLog("A1_STEP_X/Y = %08X/%08X, A2_STEP_X/Y = %08X/%08X\n", a1_step_x, a1_step_y, a2_step_x, a2_step_y);
368 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
370 uint32 a1_start = a1_x, a2_start = a2_x, bitPos = 0;
372 //Kludge for Hover Strike...
373 //I wonder if this kludge is in conjunction with the SRCENX down below...
374 // This isn't so much a kludge but the way things work in BCOMPEN mode...!
375 if (BCOMPEN && SRCENX)
377 if (n_pixels < bppSrc)
378 bitPos = bppSrc - n_pixels;
381 inner_loop = n_pixels;
386 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
388 srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
390 if (!DSTA2) // Data movement: A1 <- A2
392 // load src data and Z
394 if (SRCEN || SRCENX) // Not sure if this is correct... (seems to be...!)
396 srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
398 srczdata = READ_ZDATA(a2, REG(A2_FLAGS));
399 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
400 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
402 else // Use SRCDATA register...
404 srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
405 if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
406 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
409 // load dst data and Z
412 dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
414 dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
416 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
420 dstdata = READ_RDATA(DSTDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
422 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
425 /*This wasn't working... // a1 clipping
426 if (cmd & 0x00000040)
428 if (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7FFF)
429 || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7FFF))
434 srczdata = z_i[colour_index] >> 16;
436 // apply z comparator
437 if (Z_OP_INF) if (srczdata < dstzdata) inhibit = 1;
438 if (Z_OP_EQU) if (srczdata == dstzdata) inhibit = 1;
439 if (Z_OP_SUP) if (srczdata > dstzdata) inhibit = 1;
441 // apply data comparator
442 // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
443 // Does BCOMPEN only work in 1 bpp mode???
444 // No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!!
445 // This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside
447 if (DCOMPEN | BCOMPEN)
449 //Temp, for testing Hover Strike
450 //Doesn't seem to do it... Why?
451 //What needs to happen here is twofold. First, the address generator in the outer loop has
452 //to honor the BPP when calculating the start address (which it kinda does already). Second,
453 //it has to step bit by bit when using BCOMPEN. How to do this???
455 //small problem with this approach: it's not accurate... We need a proper address to begin with
456 //and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!!
459 uint32 pixShift = (~bitPos) & (bppSrc - 1);
460 srcdata = (srcdata >> pixShift) & 0x01;
463 // if (bitPos % bppSrc == 0)
464 // a2_x += 0x00010000;
467 Interesting (Hover Strike--large letter):
469 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
470 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
471 A1 step values: -2 (X), 1 (Y)
472 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
473 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
474 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
475 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
477 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
478 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
479 A1 step values: -8 (X), 1 (Y)
480 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
481 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
482 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
483 A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000
485 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
486 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
487 A1 step values: -1 (X), 1 (Y)
488 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
489 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
490 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
491 A1 x/y: 118/12, A2 x/y: 70/0 Pattern: 000000F300000000
493 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
494 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
495 A1 step values: -8 (X), 1 (Y)
496 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
497 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
498 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
499 A1 x/y: 119/12, A2 x/y: 71/0 Pattern: 000000F300000000
501 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
502 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
503 A1 step values: -1 (X), 1 (Y)
504 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
505 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
506 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
507 A1 x/y: 127/12, A2 x/y: 66/0 Pattern: 000000F300000000
509 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
510 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
511 A1 step values: -8 (X), 1 (Y)
512 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
513 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
514 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
515 A1 x/y: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000
521 //WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit);
522 // compare source pixel with pattern pixel
524 Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: 05810001]
525 CMD -> src: SRCEN dst: misc: a1ctl: mode: ity: PATDSEL z-op: op: LFU_REPLACE ctrl: BCOMPEN
526 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
527 A2 -> pitch: 1 phrases, depth: 1bpp, z-off: 0, width: 16 (10), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
531 // AvP is still wrong, could be cuz it's doing A1 -> A2...
533 // Src is the 1bpp bitmap... DST is the PATTERN!!!
534 // This seems to solve at least ONE of the problems with MC3D...
535 // Why should this be inverted???
536 // Bcuz it is. This is supposed to be used only for a bit -> pixel expansion...
537 /* if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
538 // if (srcdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
540 /* uint32 A2bpp = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
541 if (A2bpp == 1 || A2bpp == 16 || A2bpp == 8)
542 inhibit = (srcdata == 0 ? 1: 0);
543 // inhibit = !srcdata;
545 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
546 // What it boils down to is this:
553 // compare destination pixel with pattern pixel
554 if (dstdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
555 // if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
559 // This is DEFINITELY WRONG
560 // if (a1_phrase_mode || a2_phrase_mode)
561 // inhibit = !inhibit;
566 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
567 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
570 // compute the write data and store
573 // Houston, we have a problem...
574 // Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's
576 //Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008]
577 // CMD -> src: dst: DSTEN misc: a1ctl: mode: GOURD ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
578 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
579 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
580 // A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700
584 // use pattern data for write data
585 writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
589 /*if (blit_start_log)
590 WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/
592 // intensity addition
593 //Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!!
594 /* writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
595 if (!(TOPBEN) && writedata > 0xFF)
598 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
599 if (!(TOPNEN) && writedata > 0xFFF)
600 // writedata = 0xFFF;
602 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/
603 //notneeded--writedata &= 0xFFFF;
604 /*if (blit_start_log)
605 WriteLog("writedata: %08X\n", writedata);//*/
607 Hover Strike ADDDSEL blit:
609 Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208]
610 CMD -> src: dst: DSTEN misc: a1ctl: UPDA1 mode: ity: ADDDSEL z-op: op: LFU_CLEAR ctrl:
611 A1 step values: -320 (X), 1 (Y)
612 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
613 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
614 A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD
616 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
620 //This is correct now, but slow...
621 int16 s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000),
630 writedata = (uint32)sum;
633 //This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!!
634 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
636 if (!TOPNEN && writedata > 0xFFF)
641 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
645 if (LFU_NAN) writedata |= ~srcdata & ~dstdata;
646 if (LFU_NA) writedata |= ~srcdata & dstdata;
647 if (LFU_AN) writedata |= srcdata & ~dstdata;
648 if (LFU_A) writedata |= srcdata & dstdata;
651 //Although, this looks like it's OK... (even if it is shitty!)
652 //According to JTRM, this is part of the four things the blitter does with the write data (the other
653 //three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL
654 //(see above blit example)...
656 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
660 int intensity = srcdata & 0xFF;
661 int ia = gd_ia >> 16;
663 ia = 0xFFFFFF00 | ia;
667 if (intensity > 0xFF)
669 writedata = (srcdata & 0xFF00) | intensity;
678 //Tried 2nd below for Hover Strike: No dice.
679 if (/*a1_phrase_mode || */BKGWREN || !inhibit)
680 // if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit)
682 /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
684 uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
685 // (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
686 if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
687 WriteLog("32bpp pixel write: A1 Phrase mode --> ");
689 // write to the destination
690 WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
692 WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
695 else // if (DSTA2) // Data movement: A1 -> A2
697 // load src data and Z
700 srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
702 srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
703 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
704 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
708 srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
709 if (cmd & 0x001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
710 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
713 // load dst data and Z
716 dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
718 dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
720 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
724 dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
726 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
730 srczdata = z_i[colour_index] >> 16;
732 // apply z comparator
733 if (Z_OP_INF) if (srczdata < dstzdata) inhibit = 1;
734 if (Z_OP_EQU) if (srczdata == dstzdata) inhibit = 1;
735 if (Z_OP_SUP) if (srczdata > dstzdata) inhibit = 1;
737 // apply data comparator
738 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
739 if (DCOMPEN | BCOMPEN)
743 // compare source pixel with pattern pixel
744 // AvP: Numbers are correct, but sprites are not!
745 //This doesn't seem to be a problem... But could still be wrong...
746 /* if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
747 // if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
749 // This is probably not 100% correct... It works in the 1bpp case
750 // (in A1 <- A2 mode, that is...)
751 // AvP: This is causing blocks to be written instead of bit patterns...
753 // NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
754 /* uint32 A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
755 if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
756 inhibit = (srcdata == 0 ? 1: 0);
758 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
759 // What it boils down to is this:
765 // compare destination pixel with pattern pixel
766 if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
767 // if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
771 // This is DEFINITELY WRONG
772 // if (a1_phrase_mode || a2_phrase_mode)
773 // inhibit = !inhibit;
778 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
779 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
782 // compute the write data and store
787 // use pattern data for write data
788 writedata= READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
792 // intensity addition
793 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
794 if (!(TOPBEN) && writedata > 0xFF)
796 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
797 if (!(TOPNEN) && writedata > 0xFFF)
799 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
804 writedata |= ~srcdata & ~dstdata;
806 writedata |= ~srcdata & dstdata;
808 writedata |= srcdata & ~dstdata;
810 writedata |= srcdata & dstdata;
814 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
818 int intensity = srcdata & 0xFF;
819 int ia = gd_ia >> 16;
821 ia = 0xFFFFFF00 | ia;
825 if (intensity > 0xFF)
827 writedata = (srcdata & 0xFF00) | intensity;
836 if (/*a2_phrase_mode || */BKGWREN || !inhibit)
840 uint32 offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
841 // (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
842 WriteLog("[%08X:%04X] ", offset, writedata);
844 // write to the destination
845 WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
848 WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
852 // Update x and y (inner loop)
853 //Now it does! But crappy, crappy, crappy! !!! FIX !!! [DONE]
854 //This is less than ideal, but it works...
857 a1_x += a1_xadd, a1_y += a1_yadd;
858 a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
862 a1_y += a1_yadd, a2_y = (a2_y + a2_yadd) & a2_mask_y;
866 if (bitPos % bppSrc == 0)
867 a2_x = (a2_x + a2_xadd) & a2_mask_x;
871 a2_x = (a2_x + a2_xadd) & a2_mask_x;
872 if (bitPos % bppSrc == 0)
878 z_i[colour_index] += zadd;
880 if (GOURD || SRCSHADE)
882 gd_i[colour_index] += gd_ia;
883 //Hmm, this doesn't seem to do anything...
884 //But it is correct according to the JTRM...!
885 if ((int32)gd_i[colour_index] < 0)
886 gd_i[colour_index] = 0;
887 if (gd_i[colour_index] > 0x00FFFFFF)
888 gd_i[colour_index] = 0x00FFFFFF;//*/
890 gd_c[colour_index] += gd_ca;
891 if ((int32)gd_c[colour_index] < 0)
892 gd_c[colour_index] = 0;
893 if (gd_c[colour_index] > 0x000000FF)
894 gd_c[colour_index] = 0x000000FF;//*/
897 if (GOURD || SRCSHADE || GOURZ)
900 //This screws things up WORSE (for the BIOS opening screen)
901 // if (a1_phrase_mode || a2_phrase_mode)
902 colour_index = (colour_index + 1) & 0x03;
907 Here's the problem... The phrase mode code!
908 Blit! (00100000 -> 00148000) count: 327 x 267, A1/2_FLAGS: 00004420/00004420 [cmd: 41802E01]
909 CMD -> src: SRCEN dst: misc: a1ctl: UPDA1 UPDA2 mode: DSTA2 GOURZ ity: z-op: op: LFU_REPLACE ctrl: SRCSHADE
910 A1 step values: -327 (X), 1 (Y)
911 A2 step values: -327 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
912 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
913 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
914 A1 x/y: 28/58, A2 x/y: 28/58 Pattern: 00EA7BEA77EA77EA SRCDATA: 7BFF7BFF7BFF7BFF
916 Below fixes it, but then borks:
919 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
920 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
921 A1 step values: -15 (X), 1 (Y)
922 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
923 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
924 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
925 A1 x/y: 173/144, A2 x/y: 4052/0
927 Lesse, with pre-add we'd have:
930 00001111222233334444555566667777
933 |rolls back to here. Hmm.
936 //NOTE: The way to fix the CD BIOS is to uncomment below and comment the stuff after
937 // the phrase mode mucking around. But it fucks up everything else...
941 a2_y += a2_step_y;//*/
943 //New: Phrase mode taken into account! :-p
944 /* if (a1_phrase_mode) // v1
946 // Bump the pointer to the next phrase boundary
947 // Even though it works, this is crappy... Clean it up!
948 uint32 size = 64 / a1_psize;
950 // Crappy kludge... ('aligning' source to destination)
951 if (a2_phrase_mode && DSTA2)
953 uint32 extra = (a2_start >> 16) % size;
957 uint32 newx = (a1_x >> 16) / size;
958 uint32 newxrem = (a1_x >> 16) % size;
960 a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
962 if (a1_phrase_mode) // v2
964 // Bump the pointer to the next phrase boundary
965 // Even though it works, this is crappy... Clean it up!
966 uint32 size = 64 / a1_psize;
968 // Crappy kludge... ('aligning' source to destination)
969 if (a2_phrase_mode && DSTA2)
971 uint32 extra = (a2_start >> 16) % size;
975 uint32 pixelSize = (size - 1) << 16;
976 a1_x = (a1_x + pixelSize) & ~pixelSize;
979 /* if (a2_phrase_mode) // v1
981 // Bump the pointer to the next phrase boundary
982 // Even though it works, this is crappy... Clean it up!
983 uint32 size = 64 / a2_psize;
985 // Crappy kludge... ('aligning' source to destination)
986 // Prolly should do this for A1 channel as well... [DONE]
987 if (a1_phrase_mode && !DSTA2)
989 uint32 extra = (a1_start >> 16) % size;
993 uint32 newx = (a2_x >> 16) / size;
994 uint32 newxrem = (a2_x >> 16) % size;
996 a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
998 if (a2_phrase_mode) // v1
1000 // Bump the pointer to the next phrase boundary
1001 // Even though it works, this is crappy... Clean it up!
1002 uint32 size = 64 / a2_psize;
1004 // Crappy kludge... ('aligning' source to destination)
1005 // Prolly should do this for A1 channel as well... [DONE]
1006 if (a1_phrase_mode && !DSTA2)
1008 uint32 extra = (a1_start >> 16) % size;
1009 a2_x += extra << 16;
1012 uint32 pixelSize = (size - 1) << 16;
1013 a2_x = (a2_x + pixelSize) & ~pixelSize;
1016 //Not entirely: This still mucks things up... !!! FIX !!!
1017 //Should this go before or after the phrase mode mucking around?
1018 /* a1_x += a1_step_x;
1021 a2_y += a2_step_y;//*/
1024 // write values back to registers
1025 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
1026 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
1027 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
1031 void blitter_blit(uint32 cmd)
1033 //Apparently this is doing *something*, just not sure exactly what...
1034 /*if (cmd == 0x41802E01)
1036 WriteLog("BLIT: Found our blit. Was: %08X ", cmd);
1038 WriteLog("Is: %08X\n", cmd);
1041 uint32 pitchValue[4] = { 0, 1, 3, 2 };
1044 dst = (cmd >> 3) & 0x07;
1045 misc = (cmd >> 6) & 0x03;
1046 a1ctl = (cmd >> 8) & 0x7;
1047 mode = (cmd >> 11) & 0x07;
1048 ity = (cmd >> 14) & 0x0F;
1049 zop = (cmd >> 18) & 0x07;
1050 op = (cmd >> 21) & 0x0F;
1051 ctrl = (cmd >> 25) & 0x3F;
1053 // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
1054 // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
1055 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1056 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1058 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
1059 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
1061 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
1062 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
1063 // a1_pitch = (REG(A1_FLAGS) & 3) ^ ((REG(A1_FLAGS) & 2) >> 1);
1064 // a2_pitch = (REG(A2_FLAGS) & 3) ^ ((REG(A2_FLAGS) & 2) >> 1);
1065 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
1066 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
1068 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
1069 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
1071 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1072 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1073 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1074 //But it seems to fuck up T2K! !!! FIX !!!
1075 //Could it be sign extended??? Doesn't seem to be so according to JTRM
1076 // a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
1077 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1078 // a1_y &= 0x0FFFFFFF;
1080 // a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
1081 // According to JTRM, this must give a *whole number* of phrases in the current
1082 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1083 UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1084 a1_width = ((0x04 | m) << e) >> 2;//*/
1086 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1087 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1088 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1089 //But it seems to fuck up T2K! !!! FIX !!!
1090 // a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
1091 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1092 // a2_y &= 0x0FFFFFFF;
1094 // a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
1095 // According to JTRM, this must give a *whole number* of phrases in the current
1096 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1097 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1098 a2_width = ((0x04 | m) << e) >> 2;//*/
1099 a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
1100 a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
1102 // Check for "use mask" flag
1103 if (!(REG(A2_FLAGS) & 0x8000))
1105 a2_mask_x = 0xFFFFFFFF; // must be 16.16
1106 a2_mask_y = 0xFFFFFFFF; // must be 16.16
1111 // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
1112 a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
1117 // determine a1_xadd
1118 switch (xadd_a1_control)
1121 // This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
1122 // add phrase offset to X and truncate
1127 // add pixelsize (1) to X
1131 // add zero (for those nice vertical lines)
1135 // add the contents of the increment register
1136 a1_xadd = (REG(A1_INC) << 16) | (REG(A1_FINC) & 0x0000FFFF);
1137 a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
1142 //Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801]
1143 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD
1144 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD
1145 //if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// &&
1146 // UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1147 //Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it...
1148 //if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801)
1149 // A1 x/y: 14368/7, A2 x/y: 150/36
1150 //This is it... The problem...
1151 //if ((a1_x >> 16) == 14368) // 14368 = $3820
1152 // return; //Lesse what we got...
1162 // determine a2_xadd
1163 switch (xadd_a2_control)
1166 // add phrase offset to X and truncate
1171 // add pixelsize (1) to X
1175 // add zero (for those nice vertical lines)
1178 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
1180 WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
1181 // add the contents of the increment register
1182 // since there is no register for a2 we just add 1
1183 //Let's do nothing, since it's not listed as a valid bit combo...
1184 // a2_xadd = 1 << 16;
1191 // Modify outer loop steps based on blitter command
1199 a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
1200 a1_step_y = (REG(A1_FSTEP) >> 16);
1203 a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
1204 a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
1207 a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
1208 a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
1210 outer_loop = n_lines;
1215 a1_clip_x = REG(A1_CLIP) & 0x7FFF,
1216 a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
1218 // This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX]
1219 // Err, this is pixel size... (and it's OK)
1220 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
1221 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
1228 for(int v=0; v<4; v++)
1229 z_i[v] = REG(PHRASEZ0 + v*4);
1233 if (GOURD || GOURZ || SRCSHADE)
1235 gd_c[0] = blitter_ram[PATTERNDATA + 0];
1236 gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
1237 | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
1239 gd_c[1] = blitter_ram[PATTERNDATA + 2];
1240 gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
1241 | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
1243 gd_c[2] = blitter_ram[PATTERNDATA + 4];
1244 gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
1245 | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
1247 gd_c[3] = blitter_ram[PATTERNDATA + 6];
1248 gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
1249 | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
1251 gouraud_add = REG(INTENSITYINC);
1253 gd_ia = gouraud_add & 0x00FFFFFF;
1254 if (gd_ia & 0x00800000)
1255 gd_ia = 0xFF000000 | gd_ia;
1257 gd_ca = (gouraud_add >> 24) & 0xFF;
1258 if (gd_ca & 0x00000080)
1259 gd_ca = 0xFFFFFF00 | gd_ca;
1262 // Bit comparitor fixing...
1265 // Determine the data flow direction...
1267 a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07));
1271 /* if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!!
1273 // Determine the data flow direction...
1281 WriteLog("Blit!\n");
1282 WriteLog(" cmd = 0x%.8x\n",cmd);
1283 WriteLog(" a1_base = %08X\n", a1_addr);
1284 WriteLog(" a1_pitch = %d\n", a1_pitch);
1285 WriteLog(" a1_psize = %d\n", a1_psize);
1286 WriteLog(" a1_width = %d\n", a1_width);
1287 WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1288 WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0);
1289 WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1290 WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1291 WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0);
1292 WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0);
1293 WriteLog(" a1_zoffs = %i\n",a1_zoffs);
1295 WriteLog(" a2_base = %08X\n", a2_addr);
1296 WriteLog(" a2_pitch = %d\n", a2_pitch);
1297 WriteLog(" a2_psize = %d\n", a2_psize);
1298 WriteLog(" a2_width = %d\n", a2_width);
1299 WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1300 WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0);
1301 WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1302 WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1303 WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0);
1304 WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0);
1305 WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x);
1306 WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y);
1307 WriteLog(" a2_zoffs = %i\n",a2_zoffs);
1309 WriteLog(" count = %d x %d\n", n_pixels, n_lines);
1311 WriteLog(" command = %08X\n", cmd);
1312 WriteLog(" dsten = %i\n",DSTEN);
1313 WriteLog(" srcen = %i\n",SRCEN);
1314 WriteLog(" patdsel = %i\n",PATDSEL);
1315 WriteLog(" color = 0x%.8x\n",REG(PATTERNDATA));
1316 WriteLog(" dcompen = %i\n",DCOMPEN);
1317 WriteLog(" bcompen = %i\n",BCOMPEN);
1318 WriteLog(" cmpdst = %i\n",CMPDST);
1319 WriteLog(" GOURZ = %i\n",GOURZ);
1320 WriteLog(" GOURD = %i\n",GOURD);
1321 WriteLog(" SRCSHADE= %i\n",SRCSHADE);
1325 //NOTE: Pitch is ignored!
1327 //This *might* be the altimeter blits (they are)...
1328 //On captured screen, x-pos for black (inner) is 259, for pink is 257
1329 //Black is short by 3, pink is short by 1...
1331 Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1332 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1333 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1334 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1335 A1 x/y: 262/124, A2 x/y: 128/0
1336 Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1337 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1338 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1339 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1340 A1 x/y: 264/117, A2 x/y: 407/0
1342 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1343 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1344 A1 step values: -10 (X), 1 (Y)
1345 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1346 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1347 A1 x/y: 262/132, A2 x/y: 129/0
1348 Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1349 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1350 A1 step values: -8 (X), 1 (Y)
1351 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1352 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1353 A1 x/y: 264/128, A2 x/y: 336/0
1355 264v vCursor ends up here...
1359 262v vCursor ends up here...
1363 Fixed! Now for more:
1365 ; This looks like the ship icon in the upper left corner...
1367 Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1368 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1369 A1 step values: -12 (X), 1 (Y)
1370 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1371 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1372 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1373 A1 x/y: 20/24, A2 x/y: 5780/0
1377 More (not sure this is a blitter problem as much as it's a GPU problem):
1378 All but the "M" are trashed...
1379 This does *NOT* look like a blitter problem, as it's rendering properly...
1380 Actually, if you look at the A1 step values, there IS a discrepancy!
1384 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1385 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1386 A1 step values: -14 (X), 1 (Y)
1387 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1388 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1389 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1390 A1 x/y: 134/144, A2 x/y: 2516/0
1395 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1396 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1397 A1 step values: -13 (X), 1 (Y)
1398 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1399 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1400 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1401 A1 x/y: 147/144, A2 x/y: 2660/0
1405 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1406 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1407 A1 step values: -12 (X), 1 (Y)
1408 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1409 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1410 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1411 A1 x/y: 160/144, A2 x/y: 3764/0
1415 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1416 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1417 A1 step values: -15 (X), 1 (Y)
1418 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1419 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1420 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1421 A1 x/y: 173/144, A2 x/y: 4052/0
1424 //extern int op_start_log;
1427 char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
1428 char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
1429 char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1430 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1431 uint32 /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
1432 a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F,
1433 zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/;
1434 UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1435 uint32 p1 = a1f & 0x07, p2 = a2f & 0x07,
1436 d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
1437 zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
1438 w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
1439 ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
1440 UINT32 iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
1441 UINT32 iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
1442 WriteLog("Blit! (%08X %s %08X) count: %d x %d, A1/2_FLAGS: %08X/%08X [cmd: %08X]\n", a1_addr, (mode&0x01 ? "->" : "<-"), a2_addr, n_pixels, n_lines, a1f, a2f, cmd);
1443 // WriteLog(" CMD -> src: %d, dst: %d, misc: %d, a1ctl: %d, mode: %d, ity: %1X, z-op: %d, op: %1X, ctrl: %02X\n", src, dst, misc, a1ctl, mode, ity, zop, op, ctrl);
1445 WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
1446 WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
1447 WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
1448 WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
1449 WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "GOURZ" : ""));
1450 WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : ""));
1451 WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
1452 WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
1453 WriteLog("ctrl: %s%s%s%s%s%s\n", (cmd & 0x02000000 ? "CMPDST " : ""), (cmd & 0x04000000 ? "BCOMPEN " : ""), (cmd & 0x08000000 ? "DCOMPEN " : ""), (cmd & 0x10000000 ? "BKGWREN " : ""), (cmd & 0x20000000 ? "BUSHI " : ""), (cmd & 0x40000000 ? "SRCSHADE" : ""));
1456 WriteLog(" A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16);
1459 WriteLog(" A2 step values: %d (X), %d (Y) [mask (%sused): %08X - %08X/%08X]\n", a2_step_x >> 16, a2_step_y >> 16, (a2f & 0x8000 ? "" : "un"), REG(A2_MASK), a2_mask_x, a2_mask_y);
1461 WriteLog(" A1 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p1, bppStr[d1], zo1, iw1, w1, ctrlStr[ac1&0x03], (ac1&0x04 ? "YADD1" : "YADD0"), (ac1&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac1&0x10 ? "YSIGNSUB" : "YSIGNADD"));
1462 WriteLog(" A2 -> pitch: %d phrases, depth: %s, z-off: %d, width: %d (%02X), addctl: %s %s %s %s\n", 1 << p2, bppStr[d2], zo2, iw2, w2, ctrlStr[ac2&0x03], (ac2&0x04 ? "YADD1" : "YADD0"), (ac2&0x08 ? "XSIGNSUB" : "XSIGNADD"), (ac2&0x10 ? "YSIGNSUB" : "YSIGNADD"));
1463 WriteLog(" A1 x/y: %d/%d, A2 x/y: %d/%d Pattern: %08X%08X SRCDATA: %08X%08X\n", a1_x >> 16, a1_y >> 16, a2_x >> 16, a2_y >> 16, REG(PATTERNDATA), REG(PATTERNDATA + 4), REG(SRCDATA), REG(SRCDATA + 4));
1464 // blit_start_log = 0;
1465 // op_start_log = 1;
1468 blitter_working = 1;
1469 //#ifndef USE_GENERIC_BLITTER
1470 // if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
1472 blitter_generic(cmd);
1474 /*if (blit_start_log)
1476 if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
1478 WriteLog("\nBytes at 004D58:\n");
1479 for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
1480 WriteLog("%02X ", JaguarReadByte(i));
1481 WriteLog("\nBytes at F03000:\n");
1482 for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
1483 WriteLog("%02X ", JaguarReadByte(i));
1488 blitter_working = 0;
1491 void blitter_init(void)
1496 void blitter_reset(void)
1498 memset(blitter_ram, 0x00, 0xA0);
1501 void blitter_done(void)
1503 WriteLog("BLIT: Done.\n");
1506 uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1511 //This isn't cycle accurate--how to fix? !!! FIX !!!
1512 if (offset == (0x38 + 3))
1513 return 0x01; // always idle
1515 //Attempted fix for AvP:
1516 if (offset >= 0x04 && offset <= 0x07)
1517 // return (offset > 0x05 ? blitter_ram[PIXLINECOUNTER + offset - 0x04] : 0x00);
1518 // return 0x00; // WO register! What does it expect to see here???
1519 //This is it. I wonder if it just ignores the lower three bits?
1520 return blitter_ram[A1_PIXEL + offset - 0x04];
1522 return blitter_ram[offset];
1526 uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1528 return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
1532 uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1534 return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
1537 void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1539 /*if (offset & 0xFF == 0x7B)
1540 WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
1543 // if ((offset >= 0x7C) && (offset <= 0x9B))
1544 // This handles writes to INTENSITY0-3 by also writing them to their proper places in
1545 // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
1546 if ((offset >= 0x7C) && (offset <= 0x9B))//8B))
1550 // INTENSITY registers 0-3
1552 case 0x7D: blitter_ram[PATTERNDATA + 1] = data; break;
1553 case 0x7E: blitter_ram[SRCDATA + 0] = data; break;
1554 case 0x7F: blitter_ram[SRCDATA + 1] = data; break;
1557 case 0x81: blitter_ram[PATTERNDATA + 3] = data; break;
1558 case 0x82: blitter_ram[SRCDATA + 2] = data; break;
1559 case 0x83: blitter_ram[SRCDATA + 3] = data; break;
1562 case 0x85: blitter_ram[PATTERNDATA + 5] = data; break;
1563 case 0x86: blitter_ram[SRCDATA + 4] = data; break;
1564 case 0x87: blitter_ram[SRCDATA + 5] = data; break;
1567 case 0x89: blitter_ram[PATTERNDATA + 7] = data; break;
1568 case 0x8A: blitter_ram[SRCDATA + 6] = data; break;
1569 case 0x8B: blitter_ram[SRCDATA + 7] = data; break;
1572 case 0x8C: blitter_ram[SRCZINT + 0] = data; break;
1573 case 0x8D: blitter_ram[SRCZINT + 1] = data; break;
1574 case 0x8E: blitter_ram[SRCZFRAC + 0] = data; break;
1575 case 0x8F: blitter_ram[SRCZFRAC + 1] = data; break;
1577 case 0x90: blitter_ram[SRCZINT + 2] = data; break;
1578 case 0x91: blitter_ram[SRCZINT + 3] = data; break;
1579 case 0x92: blitter_ram[SRCZFRAC + 2] = data; break;
1580 case 0x93: blitter_ram[SRCZFRAC + 3] = data; break;
1582 case 0x94: blitter_ram[SRCZINT + 4] = data; break;
1583 case 0x95: blitter_ram[SRCZINT + 5] = data; break;
1584 case 0x96: blitter_ram[SRCZFRAC + 4] = data; break;
1585 case 0x97: blitter_ram[SRCZFRAC + 5] = data; break;
1587 case 0x98: blitter_ram[SRCZINT + 6] = data; break;
1588 case 0x99: blitter_ram[SRCZINT + 7] = data; break;
1589 case 0x9A: blitter_ram[SRCZFRAC + 6] = data; break;
1590 case 0x9B: blitter_ram[SRCZFRAC + 7] = data; break;
1594 blitter_ram[offset] = data;
1597 void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1600 /* if (offset & 0xFF == A1_PIXEL && data == 14368)
1602 WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1603 extern bool doGPUDis;
1606 if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368)
1608 WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1609 extern bool doGPUDis;
1614 BlitterWriteByte(offset+0, (data>>8) & 0xFF, who);
1615 BlitterWriteByte(offset+1, data & 0xFF, who);
1617 if ((offset & 0xFF) == 0x3A)
1618 // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
1619 // But then again, according to the Jaguar docs, this is correct...!
1621 /*extern int blit_start_log;
1622 extern bool doGPUDis;
1625 WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
1628 blitter_blit(GET32(blitter_ram, 0x38));
1633 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1636 /* if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368)
1638 WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1639 extern bool doGPUDis;
1644 BlitterWriteWord(offset, data >> 16, who);
1645 BlitterWriteWord(offset+2, data & 0xFFFF, who);
1650 uint32 cmd = GET32(blitter_ram, 0x38);
1652 WriteLog("Blit!\n");
1653 WriteLog(" cmd = %08X\n", cmd);
1654 WriteLog(" a1_base = %08X\n", a1_addr);
1655 WriteLog(" a1_pitch = %d\n", a1_pitch);
1656 WriteLog(" a1_psize = %d\n", a1_psize);
1657 WriteLog(" a1_width = %d\n", a1_width);
1658 WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1659 WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0);
1660 WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1661 WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1662 WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0);
1663 WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0);
1664 WriteLog(" a1_zoffs = %i\n",a1_zoffs);
1666 WriteLog(" a2_base = %08X\n", a2_addr);
1667 WriteLog(" a2_pitch = %d\n", a2_pitch);
1668 WriteLog(" a2_psize = %d\n", a2_psize);
1669 WriteLog(" a2_width = %d\n", a2_width);
1670 WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1671 WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0);
1672 WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1673 WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1674 WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0);
1675 WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0);
1676 WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x);
1677 WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y);
1678 WriteLog(" a2_zoffs = %i\n",a2_zoffs);
1680 WriteLog(" count = %d x %d\n", n_pixels, n_lines);
1682 WriteLog(" COMMAND = %08X\n", cmd);
1683 WriteLog(" DSTEN = %s\n", (DSTEN ? "1" : "0"));
1684 WriteLog(" SRCEN = %s\n", (SRCEN ? "1" : "0"));
1685 WriteLog(" PATDSEL = %s\n", (PATDSEL ? "1" : "0"));
1686 WriteLog(" COLOR = %08X\n", REG(PATTERNDATA));
1687 WriteLog(" DCOMPEN = %s\n", (DCOMPEN ? "1" : "0"));
1688 WriteLog(" BCOMPEN = %s\n", (BCOMPEN ? "1" : "0"));
1689 WriteLog(" CMPDST = %s\n", (CMPDST ? "1" : "0"));
1690 WriteLog(" GOURZ = %s\n", (GOURZ ? "1" : "0"));
1691 WriteLog(" GOURD = %s\n", (GOURD ? "1" : "0"));
1692 WriteLog(" SRCSHADE = %s\n", (SRCSHADE ? "1" : "0"));