6 // I owe a debt of gratitude to Curt Vendel and to John Mathieson--to Curt
7 // for supplying the Oberon ASIC nets and to John for making them available
8 // to Curt. ;-) Without that excellent documentation which shows *exactly*
9 // what's going on inside the TOM chip, we'd all still be guessing as to how
10 // the wily blitter and other pieces of the Jaguar puzzle actually work.
11 // Now how about those JERRY ASIC nets gentlemen...? ;-)
22 // Various conditional compilation goodies...
24 //#define USE_ORIGINAL_BLITTER
25 //#define USE_MIDSUMMER_BLITTER
26 #define USE_MIDSUMMER_BLITTER_MKII
28 // External global variables
30 extern int jaguar_active_memory_dumps;
32 // Local global variables
34 int start_logging = 0;
35 uint8 blitter_working = 0;
37 // Blitter register RAM (most of it is hidden from the user)
39 static uint8 blitter_ram[0x100];
43 bool specialLog = false;
44 extern int effect_start;
45 extern int blit_start_log;
46 void BlitterMidsummer(uint32 cmd);
47 void BlitterMidsummer2(void);
49 #define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
50 | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
51 #define WREG(A,D) (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
52 blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
54 // Blitter registers (offsets from F02200)
56 #define A1_BASE ((uint32)0x00)
57 #define A1_FLAGS ((uint32)0x04)
58 #define A1_CLIP ((uint32)0x08) // Height and width values for clipping
59 #define A1_PIXEL ((uint32)0x0C) // Integer part of the pixel (Y.i and X.i)
60 #define A1_STEP ((uint32)0x10) // Integer part of the step
61 #define A1_FSTEP ((uint32)0x14) // Fractional part of the step
62 #define A1_FPIXEL ((uint32)0x18) // Fractional part of the pixel (Y.f and X.f)
63 #define A1_INC ((uint32)0x1C) // Integer part of the increment
64 #define A1_FINC ((uint32)0x20) // Fractional part of the increment
65 #define A2_BASE ((uint32)0x24)
66 #define A2_FLAGS ((uint32)0x28)
67 #define A2_MASK ((uint32)0x2C) // Modulo values for x and y (M.y and M.x)
68 #define A2_PIXEL ((uint32)0x30) // Integer part of the pixel (no fractional part for A2)
69 #define A2_STEP ((uint32)0x34) // Integer part of the step (no fractional part for A2)
70 #define COMMAND ((uint32)0x38)
71 #define PIXLINECOUNTER ((uint32)0x3C) // Inner & outer loop values
72 #define SRCDATA ((uint32)0x40)
73 #define DSTDATA ((uint32)0x48)
74 #define DSTZ ((uint32)0x50)
75 #define SRCZINT ((uint32)0x58)
76 #define SRCZFRAC ((uint32)0x60)
77 #define PATTERNDATA ((uint32)0x68)
78 #define INTENSITYINC ((uint32)0x70)
79 #define ZINC ((uint32)0x74)
80 #define COLLISIONCTRL ((uint32)0x78)
81 #define PHRASEINT0 ((uint32)0x7C)
82 #define PHRASEINT1 ((uint32)0x80)
83 #define PHRASEINT2 ((uint32)0x84)
84 #define PHRASEINT3 ((uint32)0x88)
85 #define PHRASEZ0 ((uint32)0x8C)
86 #define PHRASEZ1 ((uint32)0x90)
87 #define PHRASEZ2 ((uint32)0x94)
88 #define PHRASEZ3 ((uint32)0x98)
90 // Blitter command bits
92 #define SRCEN (cmd & 0x00000001)
93 #define SRCENZ (cmd & 0x00000002)
94 #define SRCENX (cmd & 0x00000004)
95 #define DSTEN (cmd & 0x00000008)
96 #define DSTENZ (cmd & 0x00000010)
97 #define DSTWRZ (cmd & 0x00000020)
98 #define CLIPA1 (cmd & 0x00000040)
100 #define UPDA1F (cmd & 0x00000100)
101 #define UPDA1 (cmd & 0x00000200)
102 #define UPDA2 (cmd & 0x00000400)
104 #define DSTA2 (cmd & 0x00000800)
106 #define Z_OP_INF (cmd & 0x00040000)
107 #define Z_OP_EQU (cmd & 0x00080000)
108 #define Z_OP_SUP (cmd & 0x00100000)
110 #define LFU_NAN (cmd & 0x00200000)
111 #define LFU_NA (cmd & 0x00400000)
112 #define LFU_AN (cmd & 0x00800000)
113 #define LFU_A (cmd & 0x01000000)
115 #define CMPDST (cmd & 0x02000000)
116 #define BCOMPEN (cmd & 0x04000000)
117 #define DCOMPEN (cmd & 0x08000000)
119 #define PATDSEL (cmd & 0x00010000)
120 #define ADDDSEL (cmd & 0x00020000)
121 #define TOPBEN (cmd & 0x00004000)
122 #define TOPNEN (cmd & 0x00008000)
123 #define BKGWREN (cmd & 0x10000000)
124 #define GOURD (cmd & 0x00001000)
125 #define GOURZ (cmd & 0x00002000)
126 #define SRCSHADE (cmd & 0x40000000)
134 #define XSIGNSUB_A1 (REG(A1_FLAGS)&0x080000)
135 #define XSIGNSUB_A2 (REG(A2_FLAGS)&0x080000)
137 #define YSIGNSUB_A1 (REG(A1_FLAGS)&0x100000)
138 #define YSIGNSUB_A2 (REG(A2_FLAGS)&0x100000)
140 #define YADD1_A1 (REG(A1_FLAGS)&0x040000)
141 #define YADD1_A2 (REG(A2_FLAGS)&0x040000)
143 /*******************************************************************************
144 ********************** STUFF CUT BELOW THIS LINE! ******************************
145 *******************************************************************************/
146 #ifdef USE_ORIGINAL_BLITTER // We're ditching this crap for now...
148 //Put 'em back, once we fix the problem!!! [KO]
150 #define PIXEL_SHIFT_1(a) (((~a##_x) >> 16) & 7)
151 #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))
152 #define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
153 //#define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
156 #define PIXEL_SHIFT_2(a) (((~a##_x) >> 15) & 6)
157 #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))
158 #define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03)
159 //#define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
162 #define PIXEL_SHIFT_4(a) (((~a##_x) >> 14) & 4)
163 #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))
164 #define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f)
165 //#define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
168 #define PIXEL_OFFSET_8(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 7))
169 #define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER))
170 //#define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a)))
173 #define PIXEL_OFFSET_16(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 3))
174 #define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER))
175 //#define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
178 #define PIXEL_OFFSET_32(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
179 #define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER))
180 //#define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
183 #define READ_PIXEL(a,f) (\
184 (((f>>3)&0x07) == 0) ? (READ_PIXEL_1(a)) : \
185 (((f>>3)&0x07) == 1) ? (READ_PIXEL_2(a)) : \
186 (((f>>3)&0x07) == 2) ? (READ_PIXEL_4(a)) : \
187 (((f>>3)&0x07) == 3) ? (READ_PIXEL_8(a)) : \
188 (((f>>3)&0x07) == 4) ? (READ_PIXEL_16(a)) : \
189 (((f>>3)&0x07) == 5) ? (READ_PIXEL_32(a)) : 0)
191 // 16 bpp z data read
192 #define ZDATA_OFFSET_16(a) (PIXEL_OFFSET_16(a) + a##_zoffs * 4)
193 #define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER))
194 //#define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
197 #define READ_ZDATA(a,f) (READ_ZDATA_16(a))
199 // 16 bpp z data write
200 #define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); }
201 //#define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); }
204 #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d);
207 #define READ_RDATA_1(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 19) & 0x04))) >> (((uint32)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001))
210 #define READ_RDATA_2(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 18) & 0x04))) >> (((uint32)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003))
213 #define READ_RDATA_4(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 17) & 0x04))) >> (((uint32)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F))
216 #define READ_RDATA_8(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 16) & 0x04))) >> (((uint32)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF))
218 // 16 bpp r data read
219 #define READ_RDATA_16(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 15) & 0x04))) >> (((uint32)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF))
221 // 32 bpp r data read
222 #define READ_RDATA_32(r,a,p) ((p) ? REG(r+(((uint32)a##_x >> 14) & 0x04)) : REG(r))
224 // register data read
225 #define READ_RDATA(r,a,f,p) (\
226 (((f>>3)&0x07) == 0) ? (READ_RDATA_1(r,a,p)) : \
227 (((f>>3)&0x07) == 1) ? (READ_RDATA_2(r,a,p)) : \
228 (((f>>3)&0x07) == 2) ? (READ_RDATA_4(r,a,p)) : \
229 (((f>>3)&0x07) == 3) ? (READ_RDATA_8(r,a,p)) : \
230 (((f>>3)&0x07) == 4) ? (READ_RDATA_16(r,a,p)) : \
231 (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0)
234 #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); }
235 //#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))); }
238 #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); }
239 //#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))); }
242 #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); }
243 //#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))); }
246 #define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d, BLITTER); }
247 //#define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d); }
249 // 16 bpp pixel write
250 //#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
251 #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)); }
252 //#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)); }
254 // 32 bpp pixel write
255 #define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); }
256 //#define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); }
259 #define WRITE_PIXEL(a,f,d) {\
260 switch ((f>>3)&0x07) { \
261 case 0: WRITE_PIXEL_1(a,d); break; \
262 case 1: WRITE_PIXEL_2(a,d); break; \
263 case 2: WRITE_PIXEL_4(a,d); break; \
264 case 3: WRITE_PIXEL_8(a,d); break; \
265 case 4: WRITE_PIXEL_16(a,d); break; \
266 case 5: WRITE_PIXEL_32(a,d); break; \
269 // Width in Pixels of a Scanline
270 // This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
271 // of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
272 // the exponent. Valid values for the exponent range from 0 to 11 (decimal). It's easiest to think of it
273 // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to
274 // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place
275 // being shifted to the right 3 places).
276 /*static uint32 blitter_scanline_width[48] =
278 0, 0, 0, 0, // Note: This would really translate to 1, 1, 1, 1
288 1024, 1280, 1536, 1792,
289 2048, 2560, 3072, 3584
292 //static uint8 * tom_ram_8;
293 //static uint8 * paletteRam;
303 static uint32 a1_addr;
304 static uint32 a2_addr;
305 static int32 a1_zoffs;
306 static int32 a2_zoffs;
307 static uint32 xadd_a1_control;
308 static uint32 xadd_a2_control;
309 static int32 a1_pitch;
310 static int32 a2_pitch;
311 static uint32 n_pixels;
312 static uint32 n_lines;
315 static int32 a1_width;
318 static int32 a2_width;
319 static int32 a2_mask_x;
320 static int32 a2_mask_y;
321 static int32 a1_xadd;
322 static int32 a1_yadd;
323 static int32 a2_xadd;
324 static int32 a2_yadd;
325 static uint8 a1_phrase_mode;
326 static uint8 a2_phrase_mode;
327 static int32 a1_step_x = 0;
328 static int32 a1_step_y = 0;
329 static int32 a2_step_x = 0;
330 static int32 a2_step_y = 0;
331 static uint32 outer_loop;
332 static uint32 inner_loop;
333 static uint32 a2_psize;
334 static uint32 a1_psize;
335 static uint32 gouraud_add;
336 //static uint32 gouraud_data;
337 //static uint16 gint[4];
338 //static uint16 gfrac[4];
339 //static uint8 gcolour[4];
342 static int gd_ia, gd_ca;
343 static int colour_index = 0;
345 static uint32 z_i[4];
347 static int32 a1_clip_x, a1_clip_y;
349 // In the spirit of "get it right first, *then* optimize" I've taken the liberty
350 // of removing all the unnecessary code caching. If it turns out to be a good way
351 // to optimize the blitter, then we may revisit it in the future...
354 // Generic blit handler
356 void blitter_generic(uint32 cmd)
359 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
360 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
361 A1 step values: -2 (X), 1 (Y)
362 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
363 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
364 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
365 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
368 // specialLog = true;
369 /*if (cmd == 0x1401060C && blit_start_log)
370 specialLog = true;//*/
372 //uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
373 uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
374 uint32 bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07));
378 WriteLog("About to do n x m blit (BM width is ? pixels)...\n");
379 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);
393 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
395 uint32 a1_start = a1_x, a2_start = a2_x, bitPos = 0;
397 //Kludge for Hover Strike...
398 //I wonder if this kludge is in conjunction with the SRCENX down below...
399 // This isn't so much a kludge but the way things work in BCOMPEN mode...!
400 if (BCOMPEN && SRCENX)
402 if (n_pixels < bppSrc)
403 bitPos = bppSrc - n_pixels;
406 inner_loop = n_pixels;
411 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
413 srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
415 if (!DSTA2) // Data movement: A1 <- A2
417 // load src data and Z
419 if (SRCEN || SRCENX) // Not sure if this is correct... (seems to be...!)
421 srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
424 srczdata = READ_ZDATA(a2, REG(A2_FLAGS));
425 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
426 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
428 else // Use SRCDATA register...
430 srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
432 if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
433 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
436 // load dst data and Z
439 dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
442 dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
444 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
448 dstdata = READ_RDATA(DSTDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
451 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
454 /*This wasn't working... // a1 clipping
455 if (cmd & 0x00000040)
457 if (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7FFF)
458 || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7FFF))
463 srczdata = z_i[colour_index] >> 16;
465 // apply z comparator
466 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
467 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
468 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
470 // apply data comparator
471 // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
472 // Does BCOMPEN only work in 1 bpp mode???
473 // No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!!
474 // This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside
476 if (DCOMPEN | BCOMPEN)
478 //Temp, for testing Hover Strike
479 //Doesn't seem to do it... Why?
480 //What needs to happen here is twofold. First, the address generator in the outer loop has
481 //to honor the BPP when calculating the start address (which it kinda does already). Second,
482 //it has to step bit by bit when using BCOMPEN. How to do this???
484 //small problem with this approach: it's not accurate... We need a proper address to begin with
485 //and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!!
488 uint32 pixShift = (~bitPos) & (bppSrc - 1);
489 srcdata = (srcdata >> pixShift) & 0x01;
492 // if (bitPos % bppSrc == 0)
493 // a2_x += 0x00010000;
496 Interesting (Hover Strike--large letter):
498 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
499 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
500 A1 step values: -2 (X), 1 (Y)
501 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
502 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
503 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
504 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
506 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
507 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
508 A1 step values: -8 (X), 1 (Y)
509 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
510 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
511 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
512 A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000
514 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
515 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
516 A1 step values: -1 (X), 1 (Y)
517 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
518 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
519 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
520 A1 x/y: 118/12, A2 x/y: 70/0 Pattern: 000000F300000000
522 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
523 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
524 A1 step values: -8 (X), 1 (Y)
525 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
526 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
527 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
528 A1 x/y: 119/12, A2 x/y: 71/0 Pattern: 000000F300000000
530 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
531 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
532 A1 step values: -1 (X), 1 (Y)
533 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
534 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
535 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
536 A1 x/y: 127/12, A2 x/y: 66/0 Pattern: 000000F300000000
538 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
539 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
540 A1 step values: -8 (X), 1 (Y)
541 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
542 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
543 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
544 A1 x/y: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000
550 //WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit);
551 // compare source pixel with pattern pixel
553 Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: 05810001]
554 CMD -> src: SRCEN dst: misc: a1ctl: mode: ity: PATDSEL z-op: op: LFU_REPLACE ctrl: BCOMPEN
555 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
556 A2 -> pitch: 1 phrases, depth: 1bpp, z-off: 0, width: 16 (10), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
560 // AvP is still wrong, could be cuz it's doing A1 -> A2...
562 // Src is the 1bpp bitmap... DST is the PATTERN!!!
563 // This seems to solve at least ONE of the problems with MC3D...
564 // Why should this be inverted???
565 // Bcuz it is. This is supposed to be used only for a bit -> pixel expansion...
566 /* if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
567 // if (srcdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
569 /* uint32 A2bpp = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
570 if (A2bpp == 1 || A2bpp == 16 || A2bpp == 8)
571 inhibit = (srcdata == 0 ? 1: 0);
572 // inhibit = !srcdata;
574 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
575 // What it boils down to is this:
582 // compare destination pixel with pattern pixel
583 if (dstdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
584 // if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
588 // This is DEFINITELY WRONG
589 // if (a1_phrase_mode || a2_phrase_mode)
590 // inhibit = !inhibit;
595 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
596 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
599 // compute the write data and store
602 // Houston, we have a problem...
603 // Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's
605 //Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008]
606 // CMD -> src: dst: DSTEN misc: a1ctl: mode: GOURD ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
607 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
608 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
609 // A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700
613 // use pattern data for write data
614 writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
618 /*if (blit_start_log)
619 WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/
621 // intensity addition
622 //Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!!
623 /* writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
624 if (!(TOPBEN) && writedata > 0xFF)
627 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
628 if (!(TOPNEN) && writedata > 0xFFF)
629 // writedata = 0xFFF;
631 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/
632 //notneeded--writedata &= 0xFFFF;
633 /*if (blit_start_log)
634 WriteLog("writedata: %08X\n", writedata);//*/
636 Hover Strike ADDDSEL blit:
638 Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208]
639 CMD -> src: dst: DSTEN misc: a1ctl: UPDA1 mode: ity: ADDDSEL z-op: op: LFU_CLEAR ctrl:
640 A1 step values: -320 (X), 1 (Y)
641 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
642 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
643 A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD
645 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
649 //This is correct now, but slow...
650 int16 s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000),
659 writedata = (uint32)sum;
662 //This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!!
663 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
665 if (!TOPNEN && writedata > 0xFFF)
670 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
674 if (LFU_NAN) writedata |= ~srcdata & ~dstdata;
675 if (LFU_NA) writedata |= ~srcdata & dstdata;
676 if (LFU_AN) writedata |= srcdata & ~dstdata;
677 if (LFU_A) writedata |= srcdata & dstdata;
680 //Although, this looks like it's OK... (even if it is shitty!)
681 //According to JTRM, this is part of the four things the blitter does with the write data (the other
682 //three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL
683 //(see above blit example)...
685 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
689 int intensity = srcdata & 0xFF;
690 int ia = gd_ia >> 16;
692 ia = 0xFFFFFF00 | ia;
696 if (intensity > 0xFF)
698 writedata = (srcdata & 0xFF00) | intensity;
707 //Tried 2nd below for Hover Strike: No dice.
708 if (/*a1_phrase_mode || */BKGWREN || !inhibit)
709 // if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit)
711 /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
713 uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
714 // (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
715 if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
716 WriteLog("32bpp pixel write: A1 Phrase mode --> ");
718 // write to the destination
719 WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
721 WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
724 else // if (DSTA2) // Data movement: A1 -> A2
726 // load src data and Z
729 srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
731 srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
732 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
733 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
737 srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
738 if (cmd & 0x001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
739 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
742 // load dst data and Z
745 dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
747 dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
749 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
753 dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
755 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
759 srczdata = z_i[colour_index] >> 16;
761 // apply z comparator
762 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
763 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
764 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
766 // apply data comparator
767 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
768 if (DCOMPEN | BCOMPEN)
772 // compare source pixel with pattern pixel
773 // AvP: Numbers are correct, but sprites are not!
774 //This doesn't seem to be a problem... But could still be wrong...
775 /* if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
776 // if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
778 // This is probably not 100% correct... It works in the 1bpp case
779 // (in A1 <- A2 mode, that is...)
780 // AvP: This is causing blocks to be written instead of bit patterns...
782 // NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
783 /* uint32 A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
784 if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
785 inhibit = (srcdata == 0 ? 1: 0);
787 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
788 // What it boils down to is this:
794 // compare destination pixel with pattern pixel
795 if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
796 // if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
800 // This is DEFINITELY WRONG
801 // if (a1_phrase_mode || a2_phrase_mode)
802 // inhibit = !inhibit;
807 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
808 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
811 // compute the write data and store
816 // use pattern data for write data
817 writedata = READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
821 // intensity addition
822 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
823 if (!(TOPBEN) && writedata > 0xFF)
825 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
826 if (!(TOPNEN) && writedata > 0xFFF)
828 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
833 writedata |= ~srcdata & ~dstdata;
835 writedata |= ~srcdata & dstdata;
837 writedata |= srcdata & ~dstdata;
839 writedata |= srcdata & dstdata;
843 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
847 int intensity = srcdata & 0xFF;
848 int ia = gd_ia >> 16;
850 ia = 0xFFFFFF00 | ia;
854 if (intensity > 0xFF)
856 writedata = (srcdata & 0xFF00) | intensity;
865 if (/*a2_phrase_mode || */BKGWREN || !inhibit)
869 uint32 offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
870 // (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
871 WriteLog("[%08X:%04X] ", offset, writedata);
873 // write to the destination
874 WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
877 WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
881 // Update x and y (inner loop)
882 //Now it does! But crappy, crappy, crappy! !!! FIX !!! [DONE]
883 //This is less than ideal, but it works...
886 a1_x += a1_xadd, a1_y += a1_yadd;
887 a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
891 a1_y += a1_yadd, a2_y = (a2_y + a2_yadd) & a2_mask_y;
895 if (bitPos % bppSrc == 0)
896 a2_x = (a2_x + a2_xadd) & a2_mask_x;
900 a2_x = (a2_x + a2_xadd) & a2_mask_x;
901 if (bitPos % bppSrc == 0)
907 z_i[colour_index] += zadd;
909 if (GOURD || SRCSHADE)
911 gd_i[colour_index] += gd_ia;
912 //Hmm, this doesn't seem to do anything...
913 //But it is correct according to the JTRM...!
914 if ((int32)gd_i[colour_index] < 0)
915 gd_i[colour_index] = 0;
916 if (gd_i[colour_index] > 0x00FFFFFF)
917 gd_i[colour_index] = 0x00FFFFFF;//*/
919 gd_c[colour_index] += gd_ca;
920 if ((int32)gd_c[colour_index] < 0)
921 gd_c[colour_index] = 0;
922 if (gd_c[colour_index] > 0x000000FF)
923 gd_c[colour_index] = 0x000000FF;//*/
926 if (GOURD || SRCSHADE || GOURZ)
929 //This screws things up WORSE (for the BIOS opening screen)
930 // if (a1_phrase_mode || a2_phrase_mode)
931 colour_index = (colour_index + 1) & 0x03;
936 Here's the problem... The phrase mode code!
937 Blit! (00100000 -> 00148000) count: 327 x 267, A1/2_FLAGS: 00004420/00004420 [cmd: 41802E01]
938 CMD -> src: SRCEN dst: misc: a1ctl: UPDA1 UPDA2 mode: DSTA2 GOURZ ity: z-op: op: LFU_REPLACE ctrl: SRCSHADE
939 A1 step values: -327 (X), 1 (Y)
940 A2 step values: -327 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
941 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
942 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
943 A1 x/y: 28/58, A2 x/y: 28/58 Pattern: 00EA7BEA77EA77EA SRCDATA: 7BFF7BFF7BFF7BFF
945 Below fixes it, but then borks:
948 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
949 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
950 A1 step values: -15 (X), 1 (Y)
951 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
952 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
953 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
954 A1 x/y: 173/144, A2 x/y: 4052/0
956 Lesse, with pre-add we'd have:
959 00001111222233334444555566667777
962 |rolls back to here. Hmm.
965 //NOTE: The way to fix the CD BIOS is to uncomment below and comment the stuff after
966 // the phrase mode mucking around. But it fucks up everything else...
967 //#define SCREWY_CD_DEPENDENT
968 #ifdef SCREWY_CD_DEPENDENT
972 a2_y += a2_step_y;//*/
975 //New: Phrase mode taken into account! :-p
976 /* if (a1_phrase_mode) // v1
978 // Bump the pointer to the next phrase boundary
979 // Even though it works, this is crappy... Clean it up!
980 uint32 size = 64 / a1_psize;
982 // Crappy kludge... ('aligning' source to destination)
983 if (a2_phrase_mode && DSTA2)
985 uint32 extra = (a2_start >> 16) % size;
989 uint32 newx = (a1_x >> 16) / size;
990 uint32 newxrem = (a1_x >> 16) % size;
992 a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
994 if (a1_phrase_mode) // v2
996 // Bump the pointer to the next phrase boundary
997 // Even though it works, this is crappy... Clean it up!
998 uint32 size = 64 / a1_psize;
1000 // Crappy kludge... ('aligning' source to destination)
1001 if (a2_phrase_mode && DSTA2)
1003 uint32 extra = (a2_start >> 16) % size;
1004 a1_x += extra << 16;
1007 uint32 pixelSize = (size - 1) << 16;
1008 a1_x = (a1_x + pixelSize) & ~pixelSize;
1011 /* if (a2_phrase_mode) // v1
1013 // Bump the pointer to the next phrase boundary
1014 // Even though it works, this is crappy... Clean it up!
1015 uint32 size = 64 / a2_psize;
1017 // Crappy kludge... ('aligning' source to destination)
1018 // Prolly should do this for A1 channel as well... [DONE]
1019 if (a1_phrase_mode && !DSTA2)
1021 uint32 extra = (a1_start >> 16) % size;
1022 a2_x += extra << 16;
1025 uint32 newx = (a2_x >> 16) / size;
1026 uint32 newxrem = (a2_x >> 16) % size;
1028 a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
1030 if (a2_phrase_mode) // v1
1032 // Bump the pointer to the next phrase boundary
1033 // Even though it works, this is crappy... Clean it up!
1034 uint32 size = 64 / a2_psize;
1036 // Crappy kludge... ('aligning' source to destination)
1037 // Prolly should do this for A1 channel as well... [DONE]
1038 if (a1_phrase_mode && !DSTA2)
1040 uint32 extra = (a1_start >> 16) % size;
1041 a2_x += extra << 16;
1044 uint32 pixelSize = (size - 1) << 16;
1045 a2_x = (a2_x + pixelSize) & ~pixelSize;
1048 //Not entirely: This still mucks things up... !!! FIX !!!
1049 //Should this go before or after the phrase mode mucking around?
1050 #ifndef SCREWY_CD_DEPENDENT
1054 a2_y += a2_step_y;//*/
1058 // write values back to registers
1059 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
1060 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
1061 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
1065 void blitter_blit(uint32 cmd)
1067 //Apparently this is doing *something*, just not sure exactly what...
1068 /*if (cmd == 0x41802E01)
1070 WriteLog("BLIT: Found our blit. Was: %08X ", cmd);
1072 WriteLog("Is: %08X\n", cmd);
1075 uint32 pitchValue[4] = { 0, 1, 3, 2 };
1078 dst = (cmd >> 3) & 0x07;
1079 misc = (cmd >> 6) & 0x03;
1080 a1ctl = (cmd >> 8) & 0x7;
1081 mode = (cmd >> 11) & 0x07;
1082 ity = (cmd >> 14) & 0x0F;
1083 zop = (cmd >> 18) & 0x07;
1084 op = (cmd >> 21) & 0x0F;
1085 ctrl = (cmd >> 25) & 0x3F;
1087 // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
1088 // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
1089 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1090 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1092 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
1093 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
1095 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
1096 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
1098 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
1099 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
1101 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
1102 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
1104 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1105 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1106 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1107 //But it seems to fuck up T2K! !!! FIX !!!
1108 //Could it be sign extended??? Doesn't seem to be so according to JTRM
1109 // a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
1110 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1111 // a1_y &= 0x0FFFFFFF;
1113 // a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
1114 // According to JTRM, this must give a *whole number* of phrases in the current
1115 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1116 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1117 a1_width = ((0x04 | m) << e) >> 2;//*/
1119 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1120 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1121 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1122 //But it seems to fuck up T2K! !!! FIX !!!
1123 // a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
1124 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1125 // a2_y &= 0x0FFFFFFF;
1127 // a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
1128 // According to JTRM, this must give a *whole number* of phrases in the current
1129 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1130 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1131 a2_width = ((0x04 | m) << e) >> 2;//*/
1132 a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
1133 a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
1135 // Check for "use mask" flag
1136 if (!(REG(A2_FLAGS) & 0x8000))
1138 a2_mask_x = 0xFFFFFFFF; // must be 16.16
1139 a2_mask_y = 0xFFFFFFFF; // must be 16.16
1144 // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
1145 a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
1150 // determine a1_xadd
1151 switch (xadd_a1_control)
1154 // This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
1155 // add phrase offset to X and truncate
1160 // add pixelsize (1) to X
1164 // add zero (for those nice vertical lines)
1168 // add the contents of the increment register
1169 a1_xadd = (REG(A1_INC) << 16) | (REG(A1_FINC) & 0x0000FFFF);
1170 a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
1175 //Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801]
1176 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD
1177 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD
1178 //if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// &&
1179 // uint32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1180 //Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it...
1181 //if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801)
1182 // A1 x/y: 14368/7, A2 x/y: 150/36
1183 //This is it... The problem...
1184 //if ((a1_x >> 16) == 14368) // 14368 = $3820
1185 // return; //Lesse what we got...
1195 // determine a2_xadd
1196 switch (xadd_a2_control)
1199 // add phrase offset to X and truncate
1204 // add pixelsize (1) to X
1208 // add zero (for those nice vertical lines)
1211 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
1213 WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
1214 // add the contents of the increment register
1215 // since there is no register for a2 we just add 1
1216 //Let's do nothing, since it's not listed as a valid bit combo...
1217 // a2_xadd = 1 << 16;
1224 // Modify outer loop steps based on blitter command
1232 a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
1233 a1_step_y = (REG(A1_FSTEP) >> 16);
1236 a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
1237 a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
1240 a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
1241 a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
1243 outer_loop = n_lines;
1248 a1_clip_x = REG(A1_CLIP) & 0x7FFF,
1249 a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
1251 // This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX]
1252 // Err, this is pixel size... (and it's OK)
1253 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
1254 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
1261 for(int v=0; v<4; v++)
1262 z_i[v] = REG(PHRASEZ0 + v*4);
1266 if (GOURD || GOURZ || SRCSHADE)
1268 gd_c[0] = blitter_ram[PATTERNDATA + 6];
1269 gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
1270 | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
1272 gd_c[1] = blitter_ram[PATTERNDATA + 4];
1273 gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
1274 | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
1276 gd_c[2] = blitter_ram[PATTERNDATA + 2];
1277 gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
1278 | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
1280 gd_c[3] = blitter_ram[PATTERNDATA + 0];
1281 gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
1282 | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
1284 gouraud_add = REG(INTENSITYINC);
1286 gd_ia = gouraud_add & 0x00FFFFFF;
1287 if (gd_ia & 0x00800000)
1288 gd_ia = 0xFF000000 | gd_ia;
1290 gd_ca = (gouraud_add >> 24) & 0xFF;
1291 if (gd_ca & 0x00000080)
1292 gd_ca = 0xFFFFFF00 | gd_ca;
1295 // Bit comparitor fixing...
1298 // Determine the data flow direction...
1300 a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07));
1304 /* if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!!
1306 // Determine the data flow direction...
1314 WriteLog("Blit!\n");
1315 WriteLog(" cmd = 0x%.8x\n",cmd);
1316 WriteLog(" a1_base = %08X\n", a1_addr);
1317 WriteLog(" a1_pitch = %d\n", a1_pitch);
1318 WriteLog(" a1_psize = %d\n", a1_psize);
1319 WriteLog(" a1_width = %d\n", a1_width);
1320 WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1321 WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0);
1322 WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1323 WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1324 WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0);
1325 WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0);
1326 WriteLog(" a1_zoffs = %i\n",a1_zoffs);
1328 WriteLog(" a2_base = %08X\n", a2_addr);
1329 WriteLog(" a2_pitch = %d\n", a2_pitch);
1330 WriteLog(" a2_psize = %d\n", a2_psize);
1331 WriteLog(" a2_width = %d\n", a2_width);
1332 WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1333 WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0);
1334 WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1335 WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1336 WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0);
1337 WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0);
1338 WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x);
1339 WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y);
1340 WriteLog(" a2_zoffs = %i\n",a2_zoffs);
1342 WriteLog(" count = %d x %d\n", n_pixels, n_lines);
1344 WriteLog(" command = %08X\n", cmd);
1345 WriteLog(" dsten = %i\n",DSTEN);
1346 WriteLog(" srcen = %i\n",SRCEN);
1347 WriteLog(" patdsel = %i\n",PATDSEL);
1348 WriteLog(" color = 0x%.8x\n",REG(PATTERNDATA));
1349 WriteLog(" dcompen = %i\n",DCOMPEN);
1350 WriteLog(" bcompen = %i\n",BCOMPEN);
1351 WriteLog(" cmpdst = %i\n",CMPDST);
1352 WriteLog(" GOURZ = %i\n",GOURZ);
1353 WriteLog(" GOURD = %i\n",GOURD);
1354 WriteLog(" SRCSHADE= %i\n",SRCSHADE);
1358 //NOTE: Pitch is ignored!
1360 //This *might* be the altimeter blits (they are)...
1361 //On captured screen, x-pos for black (inner) is 259, for pink is 257
1362 //Black is short by 3, pink is short by 1...
1364 Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1365 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1366 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1367 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1368 A1 x/y: 262/124, A2 x/y: 128/0
1369 Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1370 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
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: XADDPIX YADD0 XSIGNADD YSIGNADD
1373 A1 x/y: 264/117, A2 x/y: 407/0
1375 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1376 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1377 A1 step values: -10 (X), 1 (Y)
1378 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1379 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1380 A1 x/y: 262/132, A2 x/y: 129/0
1381 Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1382 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1383 A1 step values: -8 (X), 1 (Y)
1384 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1385 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1386 A1 x/y: 264/128, A2 x/y: 336/0
1388 264v vCursor ends up here...
1392 262v vCursor ends up here...
1396 Fixed! Now for more:
1398 ; This looks like the ship icon in the upper left corner...
1400 Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1401 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1402 A1 step values: -12 (X), 1 (Y)
1403 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1404 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1405 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1406 A1 x/y: 20/24, A2 x/y: 5780/0
1410 More (not sure this is a blitter problem as much as it's a GPU problem):
1411 All but the "M" are trashed...
1412 This does *NOT* look like a blitter problem, as it's rendering properly...
1413 Actually, if you look at the A1 step values, there IS a discrepancy!
1417 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1418 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1419 A1 step values: -14 (X), 1 (Y)
1420 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1421 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1422 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1423 A1 x/y: 134/144, A2 x/y: 2516/0
1428 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1429 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1430 A1 step values: -13 (X), 1 (Y)
1431 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1432 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1433 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1434 A1 x/y: 147/144, A2 x/y: 2660/0
1438 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1439 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1440 A1 step values: -12 (X), 1 (Y)
1441 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1442 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1443 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1444 A1 x/y: 160/144, A2 x/y: 3764/0
1448 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1449 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1450 A1 step values: -15 (X), 1 (Y)
1451 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1452 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1453 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1454 A1 x/y: 173/144, A2 x/y: 4052/0
1457 //extern int op_start_log;
1460 char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
1461 char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
1462 char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1463 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1464 uint32 /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
1465 a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F,
1466 zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/;
1467 uint32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1468 uint32 p1 = a1f & 0x07, p2 = a2f & 0x07,
1469 d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
1470 zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
1471 w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
1472 ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
1473 uint32 iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
1474 uint32 iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
1475 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);
1476 // 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);
1478 WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
1479 WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
1480 WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
1481 WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
1482 WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "GOURZ" : ""));
1483 WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : ""));
1484 WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
1485 WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
1486 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" : ""));
1489 WriteLog(" A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16);
1492 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);
1494 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"));
1495 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"));
1496 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));
1497 // blit_start_log = 0;
1498 // op_start_log = 1;
1501 blitter_working = 1;
1502 //#ifndef USE_GENERIC_BLITTER
1503 // if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
1505 blitter_generic(cmd);
1507 /*if (blit_start_log)
1509 if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
1511 WriteLog("\nBytes at 004D58:\n");
1512 for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
1513 WriteLog("%02X ", JaguarReadByte(i));
1514 WriteLog("\nBytes at F03000:\n");
1515 for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
1516 WriteLog("%02X ", JaguarReadByte(i));
1521 blitter_working = 0;
1523 #endif // of the #if 0 near the top...
1524 /*******************************************************************************
1525 ********************** STUFF CUT ABOVE THIS LINE! ******************************
1526 *******************************************************************************/
1528 void blitter_init(void)
1533 void blitter_reset(void)
1535 memset(blitter_ram, 0x00, 0xA0);
1538 void blitter_done(void)
1540 WriteLog("BLIT: Done.\n");
1543 uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1548 //This isn't cycle accurate--how to fix? !!! FIX !!!
1549 //Probably have to do some multi-threaded implementation or at least a reentrant safe implementation...
1550 if (offset == (0x38 + 3))
1551 return 0x01; // always idle
1553 // CHECK HERE ONCE THIS FIX HAS BEEN TESTED: [ ]
1555 if (offset >= 0x04 && offset <= 0x07)
1556 //This is it. I wonder if it just ignores the lower three bits?
1557 //No, this is a documented Jaguar I bug. It also bites the read at $F02230 as well...
1558 return blitter_ram[offset + 0x08]; // A1_PIXEL ($F0220C) read at $F02204
1560 if (offset >= 0x2C && offset <= 0x2F)
1561 return blitter_ram[offset + 0x04]; // A2_PIXEL ($F02230) read at $F0222C
1563 return blitter_ram[offset];
1567 uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1569 return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
1573 uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1575 return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
1578 void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1580 /*if (offset & 0xFF == 0x7B)
1581 WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
1583 /*if ((offset >= PATTERNDATA) && (offset < PATTERNDATA + 8))
1585 printf("--> %s wrote %02X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - PATTERNDATA);
1589 // This handles writes to INTENSITY0-3 by also writing them to their proper places in
1590 // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
1591 if ((offset >= 0x7C) && (offset <= 0x9B))
1595 // INTENSITY registers 0-3
1597 case 0x7D: blitter_ram[PATTERNDATA + 7] = data; break;
1598 case 0x7E: blitter_ram[SRCDATA + 6] = data; break;
1599 case 0x7F: blitter_ram[SRCDATA + 7] = data; break;
1602 case 0x81: blitter_ram[PATTERNDATA + 5] = data; break;
1603 case 0x82: blitter_ram[SRCDATA + 4] = data; break;
1604 case 0x83: blitter_ram[SRCDATA + 5] = data; break;
1607 case 0x85: blitter_ram[PATTERNDATA + 3] = data; break;
1608 case 0x86: blitter_ram[SRCDATA + 2] = data; break;
1609 case 0x87: blitter_ram[SRCDATA + 3] = data; break;
1612 case 0x89: blitter_ram[PATTERNDATA + 1] = data; break;
1613 case 0x8A: blitter_ram[SRCDATA + 0] = data; break;
1614 case 0x8B: blitter_ram[SRCDATA + 1] = data; break;
1618 case 0x8C: blitter_ram[SRCZINT + 6] = data; break;
1619 case 0x8D: blitter_ram[SRCZINT + 7] = data; break;
1620 case 0x8E: blitter_ram[SRCZFRAC + 6] = data; break;
1621 case 0x8F: blitter_ram[SRCZFRAC + 7] = data; break;
1623 case 0x90: blitter_ram[SRCZINT + 4] = data; break;
1624 case 0x91: blitter_ram[SRCZINT + 5] = data; break;
1625 case 0x92: blitter_ram[SRCZFRAC + 4] = data; break;
1626 case 0x93: blitter_ram[SRCZFRAC + 5] = data; break;
1628 case 0x94: blitter_ram[SRCZINT + 2] = data; break;
1629 case 0x95: blitter_ram[SRCZINT + 3] = data; break;
1630 case 0x96: blitter_ram[SRCZFRAC + 2] = data; break;
1631 case 0x97: blitter_ram[SRCZFRAC + 3] = data; break;
1633 case 0x98: blitter_ram[SRCZINT + 0] = data; break;
1634 case 0x99: blitter_ram[SRCZINT + 1] = data; break;
1635 case 0x9A: blitter_ram[SRCZFRAC + 0] = data; break;
1636 case 0x9B: blitter_ram[SRCZFRAC + 1] = data; break;
1640 // It looks weird, but this is how the 64 bit registers are actually handled...!
1642 else if ((offset >= SRCDATA + 0) && (offset <= SRCDATA + 3)
1643 || (offset >= DSTDATA + 0) && (offset <= DSTDATA + 3)
1644 || (offset >= DSTZ + 0) && (offset <= DSTZ + 3)
1645 || (offset >= SRCZINT + 0) && (offset <= SRCZINT + 3)
1646 || (offset >= SRCZFRAC + 0) && (offset <= SRCZFRAC + 3)
1647 || (offset >= PATTERNDATA + 0) && (offset <= PATTERNDATA + 3))
1649 blitter_ram[offset + 4] = data;
1651 else if ((offset >= SRCDATA + 4) && (offset <= SRCDATA + 7)
1652 || (offset >= DSTDATA + 4) && (offset <= DSTDATA + 7)
1653 || (offset >= DSTZ + 4) && (offset <= DSTZ + 7)
1654 || (offset >= SRCZINT + 4) && (offset <= SRCZINT + 7)
1655 || (offset >= SRCZFRAC + 4) && (offset <= SRCZFRAC + 7)
1656 || (offset >= PATTERNDATA + 4) && (offset <= PATTERNDATA + 7))
1658 blitter_ram[offset - 4] = data;
1661 blitter_ram[offset] = data;
1664 void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1666 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1668 printf("----> %s wrote %04X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1672 /* if (offset & 0xFF == A1_PIXEL && data == 14368)
1674 WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1675 extern bool doGPUDis;
1678 if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368)
1680 WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1681 extern bool doGPUDis;
1686 BlitterWriteByte(offset + 0, data >> 8, who);
1687 BlitterWriteByte(offset + 1, data & 0xFF, who);
1689 if ((offset & 0xFF) == 0x3A)
1690 // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
1691 // But then again, according to the Jaguar docs, this is correct...!
1692 /*extern int blit_start_log;
1693 extern bool doGPUDis;
1696 WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
1699 #ifdef USE_ORIGINAL_BLITTER
1700 blitter_blit(GET32(blitter_ram, 0x38));
1702 #ifdef USE_MIDSUMMER_BLITTER
1703 BlitterMidsummer(GET32(blitter_ram, 0x38));
1705 #ifdef USE_MIDSUMMER_BLITTER_MKII
1706 BlitterMidsummer2();
1711 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1713 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1715 printf("------> %s wrote %08X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1719 /* if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368)
1721 WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1722 extern bool doGPUDis;
1727 BlitterWriteWord(offset + 0, data >> 16, who);
1728 BlitterWriteWord(offset + 2, data & 0xFFFF, who);
1733 const char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1734 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1735 uint32 cmd = GET32(blitter_ram, 0x38);
1736 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1737 uint32 a1_width = ((0x04 | m) << e) >> 2;
1738 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1739 uint32 a2_width = ((0x04 | m) << e) >> 2;
1741 WriteLog("Blit!\n");
1742 WriteLog(" COMMAND = %08X\n", cmd);
1743 WriteLog(" a1_base = %08X\n", REG(A1_BASE));
1744 WriteLog(" a1_flags = %08X (%c %c %c %c%c . %c%c%c%c%c%c %c%c%c %c%c%c . %c%c)\n", REG(A1_FLAGS),
1745 (REG(A1_FLAGS) & 0x100000 ? '1' : '0'),
1746 (REG(A1_FLAGS) & 0x080000 ? '1' : '0'),
1747 (REG(A1_FLAGS) & 0x040000 ? '1' : '0'),
1748 (REG(A1_FLAGS) & 0x020000 ? '1' : '0'),
1749 (REG(A1_FLAGS) & 0x010000 ? '1' : '0'),
1750 (REG(A1_FLAGS) & 0x004000 ? '1' : '0'),
1751 (REG(A1_FLAGS) & 0x002000 ? '1' : '0'),
1752 (REG(A1_FLAGS) & 0x001000 ? '1' : '0'),
1753 (REG(A1_FLAGS) & 0x000800 ? '1' : '0'),
1754 (REG(A1_FLAGS) & 0x000400 ? '1' : '0'),
1755 (REG(A1_FLAGS) & 0x000200 ? '1' : '0'),
1756 (REG(A1_FLAGS) & 0x000100 ? '1' : '0'),
1757 (REG(A1_FLAGS) & 0x000080 ? '1' : '0'),
1758 (REG(A1_FLAGS) & 0x000040 ? '1' : '0'),
1759 (REG(A1_FLAGS) & 0x000020 ? '1' : '0'),
1760 (REG(A1_FLAGS) & 0x000010 ? '1' : '0'),
1761 (REG(A1_FLAGS) & 0x000008 ? '1' : '0'),
1762 (REG(A1_FLAGS) & 0x000002 ? '1' : '0'),
1763 (REG(A1_FLAGS) & 0x000001 ? '1' : '0'));
1764 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1765 REG(A1_FLAGS) & 0x00003, (REG(A1_FLAGS) & 0x00038) >> 3,
1766 (REG(A1_FLAGS) & 0x001C0) >> 6, a1_width, (REG(A1_FLAGS) & 0x30000) >> 16);
1767 WriteLog(" a1_clip = %u, %u (%08X)\n", GET16(blitter_ram, A1_CLIP + 2), GET16(blitter_ram, A1_CLIP + 0), GET32(blitter_ram, A1_CLIP));
1768 WriteLog(" a1_pixel = %d, %d (%08X)\n", (int16)GET16(blitter_ram, A1_PIXEL + 2), (int16)GET16(blitter_ram, A1_PIXEL + 0), GET32(blitter_ram, A1_PIXEL));
1769 WriteLog(" a1_step = %d, %d (%08X)\n", (int16)GET16(blitter_ram, A1_STEP + 2), (int16)GET16(blitter_ram, A1_STEP + 0), GET32(blitter_ram, A1_STEP));
1770 WriteLog(" a1_fstep = %u, %u (%08X)\n", GET16(blitter_ram, A1_FSTEP + 2), GET16(blitter_ram, A1_FSTEP + 0), GET32(blitter_ram, A1_FSTEP));
1771 WriteLog(" a1_fpixel= %u, %u (%08X)\n", GET16(blitter_ram, A1_FPIXEL + 2), GET16(blitter_ram, A1_FPIXEL + 0), GET32(blitter_ram, A1_FPIXEL));
1772 WriteLog(" a1_inc = %d, %d (%08X)\n", (int16)GET16(blitter_ram, A1_INC + 2), (int16)GET16(blitter_ram, A1_INC + 0), GET32(blitter_ram, A1_INC));
1773 WriteLog(" a1_finc = %u, %u (%08X)\n", GET16(blitter_ram, A1_FINC + 2), GET16(blitter_ram, A1_FINC + 0), GET32(blitter_ram, A1_FINC));
1775 WriteLog(" a2_base = %08X\n", REG(A2_BASE));
1776 WriteLog(" a2_flags = %08X (%c %c %c %c%c %c %c%c%c%c%c%c %c%c%c %c%c%c . %c%c)\n", REG(A2_FLAGS),
1777 (REG(A2_FLAGS) & 0x100000 ? '1' : '0'),
1778 (REG(A2_FLAGS) & 0x080000 ? '1' : '0'),
1779 (REG(A2_FLAGS) & 0x040000 ? '1' : '0'),
1780 (REG(A2_FLAGS) & 0x020000 ? '1' : '0'),
1781 (REG(A2_FLAGS) & 0x010000 ? '1' : '0'),
1782 (REG(A2_FLAGS) & 0x008000 ? '1' : '0'),
1783 (REG(A2_FLAGS) & 0x004000 ? '1' : '0'),
1784 (REG(A2_FLAGS) & 0x002000 ? '1' : '0'),
1785 (REG(A2_FLAGS) & 0x001000 ? '1' : '0'),
1786 (REG(A2_FLAGS) & 0x000800 ? '1' : '0'),
1787 (REG(A2_FLAGS) & 0x000400 ? '1' : '0'),
1788 (REG(A2_FLAGS) & 0x000200 ? '1' : '0'),
1789 (REG(A2_FLAGS) & 0x000100 ? '1' : '0'),
1790 (REG(A2_FLAGS) & 0x000080 ? '1' : '0'),
1791 (REG(A2_FLAGS) & 0x000040 ? '1' : '0'),
1792 (REG(A2_FLAGS) & 0x000020 ? '1' : '0'),
1793 (REG(A2_FLAGS) & 0x000010 ? '1' : '0'),
1794 (REG(A2_FLAGS) & 0x000008 ? '1' : '0'),
1795 (REG(A2_FLAGS) & 0x000002 ? '1' : '0'),
1796 (REG(A2_FLAGS) & 0x000001 ? '1' : '0'));
1797 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1798 REG(A2_FLAGS) & 0x00003, (REG(A2_FLAGS) & 0x00038) >> 3,
1799 (REG(A2_FLAGS) & 0x001C0) >> 6, a2_width, (REG(A2_FLAGS) & 0x30000) >> 16);
1800 WriteLog(" a2_mask = %u, %u (%08X)\n", GET16(blitter_ram, A2_MASK + 2), GET16(blitter_ram, A2_MASK + 0), GET32(blitter_ram, A2_MASK));
1801 WriteLog(" a2_pixel = %d, %d (%08X)\n", (int16)GET16(blitter_ram, A2_PIXEL + 2), (int16)GET16(blitter_ram, A2_PIXEL + 0), GET32(blitter_ram, A2_PIXEL));
1802 WriteLog(" a2_step = %d, %d (%08X)\n", (int16)GET16(blitter_ram, A2_STEP + 2), (int16)GET16(blitter_ram, A2_STEP + 0), GET32(blitter_ram, A2_STEP));
1804 WriteLog(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
1806 WriteLog(" SRCEN = %s\n", (SRCEN ? "1" : "0"));
1807 WriteLog(" SRCENZ = %s\n", (SRCENZ ? "1" : "0"));
1808 WriteLog(" SRCENX = %s\n", (SRCENX ? "1" : "0"));
1809 WriteLog(" DSTEN = %s\n", (DSTEN ? "1" : "0"));
1810 WriteLog(" DSTENZ = %s\n", (DSTENZ ? "1" : "0"));
1811 WriteLog(" DSTWRZ = %s\n", (DSTWRZ ? "1" : "0"));
1812 WriteLog(" CLIPA1 = %s\n", (CLIPA1 ? "1" : "0"));
1813 WriteLog(" UPDA1F = %s\n", (UPDA1F ? "1" : "0"));
1814 WriteLog(" UPDA1 = %s\n", (UPDA1 ? "1" : "0"));
1815 WriteLog(" UPDA2 = %s\n", (UPDA2 ? "1" : "0"));
1816 WriteLog(" DSTA2 = %s\n", (DSTA2 ? "1" : "0"));
1817 WriteLog(" ZOP = %s %s %s\n", (Z_OP_INF ? "<" : ""), (Z_OP_EQU ? "=" : ""), (Z_OP_SUP ? ">" : ""));
1818 WriteLog("--LFUFUNC = %s\n", opStr[(cmd >> 21) & 0x0F]);
1819 WriteLog("| PATDSEL = %s (PD=%08X%08X)\n", (PATDSEL ? "1" : "0"), REG(PATTERNDATA), REG(PATTERNDATA + 4));
1820 WriteLog("--ADDDSEL = %s\n", (ADDDSEL ? "1" : "0"));
1821 WriteLog(" CMPDST = %s\n", (CMPDST ? "1" : "0"));
1822 WriteLog(" BCOMPEN = %s\n", (BCOMPEN ? "1" : "0"));
1823 WriteLog(" DCOMPEN = %s\n", (DCOMPEN ? "1" : "0"));
1824 WriteLog(" TOPBEN = %s\n", (TOPBEN ? "1" : "0"));
1825 WriteLog(" TOPNEN = %s\n", (TOPNEN ? "1" : "0"));
1826 WriteLog(" BKGWREN = %s\n", (BKGWREN ? "1" : "0"));
1827 WriteLog(" GOURD = %s (II=%08X, SD=%08X%08X)\n", (GOURD ? "1" : "0"), REG(INTENSITYINC), REG(SRCDATA), REG(SRCDATA + 4));
1828 WriteLog(" GOURZ = %s (ZI=%08X, ZD=%08X%08X, SZ1=%08X%08X, SZ2=%08X%08X)\n", (GOURZ ? "1" : "0"), REG(ZINC), REG(DSTZ), REG(DSTZ + 4),
1829 REG(SRCZINT), REG(SRCZINT + 4), REG(SRCZFRAC), REG(SRCZFRAC + 4));
1830 WriteLog(" SRCSHADE = %s\n", (SRCSHADE ? "1" : "0"));
1834 #ifdef USE_MIDSUMMER_BLITTER
1836 // Here's an attempt to write a blitter that conforms to the Midsummer specs--since
1837 // it's supposedly backwards compatible, it should work well...
1839 //#define LOG_BLITTER_MEMORY_ACCESSES
1841 #define DATINIT (false)
1842 #define TXTEXT (false)
1843 #define POLYGON (false)
1845 void BlitterMidsummer(uint32 cmd)
1847 uint32 outer_loop, inner_loop, a1_addr, a2_addr;
1848 int32 a1_x, a1_y, a2_x, a2_y, a1_width, a2_width;
1849 uint8 a1_phrase_mode, a2_phrase_mode;
1851 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1852 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1853 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1854 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1855 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1856 a1_width = ((0x04 | m) << e) >> 2;//*/
1857 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1858 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1859 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1860 a2_width = ((0x04 | m) << e) >> 2;//*/
1862 a1_phrase_mode = a2_phrase_mode = 0;
1864 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
1867 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
1870 #define INNER0 (inner_loop == 0)
1871 #define OUTER0 (outer_loop == 0)
1873 // $01800005 has SRCENX, may have to investigate further...
1874 // $00011008 has GOURD & DSTEN.
1875 // $41802F41 has SRCSHADE, CLIPA1
1876 /*bool logBlit = false;
1877 if (cmd != 0x00010200 && cmd != 0x01800001 && cmd != 0x01800005
1878 && cmd != 0x00011008 && cmd !=0x41802F41)
1884 uint64 srcData = GET64(blitter_ram, SRCDATA), srcXtraData,
1885 dstData = GET64(blitter_ram, DSTDATA), writeData;
1886 uint32 srcAddr, dstAddr;
1887 uint8 bitCount, a1PixelSize, a2PixelSize;
1889 // JTRM says phrase mode only works for 8BPP or higher, so let's try this...
1890 uint32 phraseOffset[8] = { 8, 8, 8, 8, 4, 2, 0, 0 };
1891 uint8 pixelShift[8] = { 3, 2, 1, 0, 1, 2, 0, 0 };
1893 a1PixelSize = (blitter_ram[A1_FLAGS + 3] >> 3) & 0x07;
1894 a2PixelSize = (blitter_ram[A2_FLAGS + 3] >> 3) & 0x07;
1896 outer_loop = GET16(blitter_ram, PIXLINECOUNTER + 0);
1898 if (outer_loop == 0)
1899 outer_loop = 0x10000;
1901 // We just list the states here and jump from state to state in order to
1902 // keep things somewhat clear. Optimization/cleanups later.
1904 //idle: // Blitter is idle, and will not perform any bus activity
1906 idle Blitter is off the bus, and no activity takes place.
1907 if GO if DATINIT goto init_if
1916 inner Inner loop is active, read and write cycles are performed
1918 inner: // Run inner loop state machine (asserts step from its idle state)
1919 inner_loop = GET16(blitter_ram, PIXLINECOUNTER + 2);
1921 if (inner_loop == 0)
1922 inner_loop = 0x10000;
1925 ------------------------------
1926 idle: Inactive, blitter is idle or passing round outer loop
1927 idle Another state in the outer loop is active. No bus transfers are performed.
1929 if SRCENX goto sreadx
1930 else if TXTEXT goto txtread
1931 else if SRCEN goto sread
1932 else if DSTEN goto dread
1933 else if DSTENZ goto dzread
1950 sreadx Extra source data read at the start of an inner loop pass.
1952 if SRCENZ goto szreadx
1953 else if TXTEXT goto txtread
1954 else if SRCEN goto sread
1955 else if DSTEN goto dread
1956 else if DSTENZ goto dzread
1959 sreadx: // Extra source data read
1974 szreadx Extra source Z read as the start of an inner loop pass.
1976 if TXTEXT goto txtread
1979 szreadx: // Extra source Z read
1986 txtread Read texture data from external memory. This state is only used for external texture.
1987 TEXTEXT is the condition TEXTMODE=1.
1990 else if DSTEN goto dread
1991 else if DSTENZ goto dzread
1994 txtread: // Read external texture data
2005 sread Source data read.
2007 if SRCENZ goto szread
2008 else if DSTEN goto dread
2009 else if DSTENZ goto dzread
2012 sread: // Source data read
2013 //The JTRM doesn't really specify the internal structure of the source data read, but I would
2014 //imagine that if it's in phrase mode that it starts by reading the phrase that the window is
2015 //pointing at. Likewise, the pixel (if in BPP 1, 2 & 4, chopped) otherwise. It probably still
2016 //transfers an entire phrase even in pixel mode.
2017 //Odd thought: Does it expand, e.g., 1 BPP pixels into 32 BPP internally? Hmm...
2020 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
2021 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
2022 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
2023 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
2024 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
2025 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
2026 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
2027 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
2028 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
2029 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
2030 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
2031 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
2032 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
2033 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
2036 a1_width = ((0x04 | m) << e) >> 2;
2037 a2_width = ((0x04 | m) << e) >> 2;
2039 // write values back to registers
2040 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
2041 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
2042 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
2044 // Calculate the address to be read...
2046 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2047 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2048 //for 8BPP. !!! FIX !!!
2049 srcAddr = (DSTA2 ? a1_addr : a2_addr);
2051 /* if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2053 srcAddr += (((DSTA2 ? a1_x : a2_x) >> 16)
2054 + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width)));
2058 // uint32 pixAddr = ((DSTA2 ? a1_x : a2_x) >> 16)
2059 // + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2060 int32 pixAddr = (int16)((DSTA2 ? a1_x : a2_x) >> 16)
2061 + ((int16)((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2063 if ((DSTA2 ? a1PixelSize : a2PixelSize) < 3)
2064 pixAddr >>= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2065 else if ((DSTA2 ? a1PixelSize : a2PixelSize) > 3)
2066 pixAddr <<= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2073 if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2075 srcData = ((uint64)JaguarReadLong(srcAddr, BLITTER) << 32)
2076 | (uint64)JaguarReadLong(srcAddr + 4, BLITTER);
2080 //1,2,&4BPP are wrong here... !!! FIX !!!
2081 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 0) // 1 BPP
2082 srcData = JaguarReadByte(srcAddr, BLITTER);
2083 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 1) // 2 BPP
2084 srcData = JaguarReadByte(srcAddr, BLITTER);
2085 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 2) // 4 BPP
2086 srcData = JaguarReadByte(srcAddr, BLITTER);
2087 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 3) // 8 BPP
2088 srcData = JaguarReadByte(srcAddr, BLITTER);
2089 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 4) // 16 BPP
2090 srcData = JaguarReadWord(srcAddr, BLITTER);
2091 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 5) // 32 BPP
2092 srcData = JaguarReadLong(srcAddr, BLITTER);
2095 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2097 WriteLog("BLITTER: srcAddr=%08X, srcData=%08X %08X\n", srcAddr, (uint32)(srcData >> 32), (uint32)(srcData & 0xFFFFFFFF));
2109 szread: // Source Z read
2111 szread Source Z read.
2114 else if DSTENZ goto dzread
2124 dread: // Destination data read
2126 dread Destination data read.
2128 if DSTENZ goto dzread
2131 // Calculate the destination address to be read...
2133 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2134 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2135 //for 8BPP. !!! FIX !!!
2136 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2139 // uint32 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2140 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2141 int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
2142 + ((int16)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2144 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2145 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2146 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2147 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2154 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2156 dstData = ((uint64)JaguarReadLong(srcAddr, BLITTER) << 32)
2157 | (uint64)JaguarReadLong(srcAddr + 4, BLITTER);
2161 //1,2,&4BPP are wrong here... !!! FIX !!!
2162 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2163 dstData = JaguarReadByte(dstAddr, BLITTER);
2164 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2165 dstData = JaguarReadByte(dstAddr, BLITTER);
2166 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2167 dstData = JaguarReadByte(dstAddr, BLITTER);
2168 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2169 dstData = JaguarReadByte(dstAddr, BLITTER);
2170 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2171 dstData = JaguarReadWord(dstAddr, BLITTER);
2172 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2173 dstData = JaguarReadLong(dstAddr, BLITTER);
2176 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2178 WriteLog("BLITTER (dread): dstAddr=%08X, dstData=%08X %08X\n", dstAddr, (uint32)(dstData >> 32), (uint32)(dstData & 0xFFFFFFFF));
2186 dzread: // Destination Z read
2188 dzread Destination Z read.
2193 dwrite: // Destination data write
2195 dwrite Destination write. Every pass round the inner loop must go through this state..
2197 if DSTWRZ goto dzwrite
2198 else if INNER0 goto idle
2199 else if TXTEXT goto txtread
2200 else if SRCEN goto sread
2201 else if DSTEN goto dread
2202 else if DSTENZ goto dzread
2211 a1_xadd = 1.000000 (phrase=0)
2220 a2_xadd = 1.000000 (phrase=1)
2224 a2_mask_x= 0xFFFFFFFF
2225 a2_mask_y= 0xFFFFFFFF
2235 --LFUFUNC = LFU_CLEAR
2236 | PATDSEL = 1 (PD=77C7 7700 7700 7700)
2238 GOURD = 1 (II=00FC 1A00, SD=FF00 0000 0000 0000)
2241 //Still need to do CLIPA1 and SRCSHADE and GOURD and GOURZ...
2243 // Check clipping...
2247 uint16 x = a1_x >> 16, y = a1_y >> 16;
2249 if (x >= GET16(blitter_ram, A1_CLIP + 2) || y >= GET16(blitter_ram, A1_CLIP))
2253 // Figure out what gets written...
2257 writeData = GET64(blitter_ram, PATTERNDATA);
2258 //GOURD works properly only in 16BPP mode...
2259 //SRCDATA holds the intensity fractions...
2260 //Does GOURD get calc'ed here or somewhere else???
2261 //Temporary testing kludge...
2263 // writeData >>= 48;
2264 // writeData = 0xFF88;
2265 //OK, it's not writing an entire strip of pixels... Why?
2266 //bad incrementing, that's why!
2270 // Apparently this only works with 16-bit pixels. Not sure if it works in phrase mode either.
2271 //Also, take TOPBEN & TOPNEN into account here as well...
2272 writeData = srcData + dstData;
2274 else // LFUFUNC is the default...
2279 writeData |= ~srcData & ~dstData;
2281 writeData |= ~srcData & dstData;
2283 writeData |= srcData & ~dstData;
2285 writeData |= srcData & dstData;
2288 // Calculate the address to be written...
2290 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2292 /* if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2294 //both of these calculate the wrong address because they don't take into account
2296 dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2297 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2301 /* dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2302 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));*/
2303 // uint32 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2304 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2305 int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
2306 + ((int16)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2308 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2309 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2310 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2311 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2318 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2320 JaguarWriteLong(dstAddr, writeData >> 32, BLITTER);
2321 JaguarWriteLong(dstAddr + 4, writeData & 0xFFFFFFFF, BLITTER);
2325 //1,2,&4BPP are wrong here... !!! FIX !!!
2326 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2327 JaguarWriteByte(dstAddr, writeData, BLITTER);
2328 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2329 JaguarWriteByte(dstAddr, writeData, BLITTER);
2330 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2331 JaguarWriteByte(dstAddr, writeData, BLITTER);
2332 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2333 JaguarWriteByte(dstAddr, writeData, BLITTER);
2334 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2335 JaguarWriteWord(dstAddr, writeData, BLITTER);
2336 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2337 JaguarWriteLong(dstAddr, writeData, BLITTER);
2340 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2342 WriteLog("BLITTER: dstAddr=%08X, writeData=%08X %08X\n", dstAddr, (uint32)(writeData >> 32), (uint32)(writeData & 0xFFFFFFFF));
2345 inhibitWrite://Should this go here? or on the other side of the X/Y incrementing?
2346 //Seems OK here... for now.
2348 // Do funky X/Y incrementation here as well... !!! FIX !!!
2350 // Handle A1 channel stepping
2352 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
2353 a1_x += phraseOffset[a1PixelSize] << 16;
2354 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 1)
2355 a1_x += (blitter_ram[A1_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2356 /* else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 2)
2358 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 3)
2360 //Always add the FINC here??? That was the problem with the BIOS screen... So perhaps.
2361 a1_x += GET16(blitter_ram, A1_FINC + 2);
2362 a1_y += GET16(blitter_ram, A1_FINC + 0);
2364 a1_x += GET16(blitter_ram, A1_INC + 2) << 16;
2365 a1_y += GET16(blitter_ram, A1_INC + 0) << 16;
2368 if ((blitter_ram[A1_FLAGS + 1] & 0x04) && (blitter_ram[A1_FLAGS + 1] & 0x03 != 3))
2369 a1_y += (blitter_ram[A1_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2371 // Handle A2 channel stepping
2373 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
2374 a2_x += phraseOffset[a2PixelSize] << 16;
2375 else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 1)
2376 a2_x += (blitter_ram[A2_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2377 /* else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 2)
2380 if (blitter_ram[A2_FLAGS + 1] & 0x04)
2381 a2_y += (blitter_ram[A2_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2383 //Need to fix this so that it subtracts (saturating, of course) the correct number of pixels
2384 //in phrase mode... !!! FIX !!! [DONE]
2385 //Need to fix this so that it counts down the correct item. Does it count the
2386 //source or the destination phrase mode???
2387 //It shouldn't matter, because we *should* end up processing the same amount
2388 //the same number of pixels... Not sure though.
2389 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2391 if (inner_loop < phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize])
2394 inner_loop -= phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize];
2415 dzwrite: // Destination Z write
2417 dzwrite Destination Z write.
2420 else if TXTEXT goto txtread
2421 else if SRCEN goto sread
2422 else if DSTEN goto dread
2423 else if DSTENZ goto dzread
2440 ------------------------------
2441 if INDONE if OUTER0 goto idle
2442 else if UPDA1F goto a1fupdate
2443 else if UPDA1 goto a1update
2444 else if GOURZ.POLYGON goto zfupdate
2445 else if UPDA2 goto a2update
2446 else if DATINIT goto init_if
2459 //kill this, for now...
2460 // else if (GOURZ.POLYGON)
2469 a1fupdate: // Update A1 pointer fractions and more (see below)
2471 a1fupdate A1 step fraction is added to A1 pointer fraction
2472 POLYGON true: A1 step delta X and Y fraction parts are added to the A1
2473 step X and Y fraction parts (the value prior to this add is used for
2474 the step to pointer add).
2475 POLYGON true: inner count step fraction is added to the inner count
2477 POLYGON.GOURD true: the I fraction step is added to the computed
2478 intensity fraction parts +
2479 POLYGON.GOURD true: the I fraction step delta is added to the I
2484 #define A1_PIXEL ((uint32)0x0C) // Integer part of the pixel (Y.i and X.i)
2485 #define A1_STEP ((uint32)0x10) // Integer part of the step
2486 #define A1_FSTEP ((uint32)0x14) // Fractional part of the step
2487 #define A1_FPIXEL ((uint32)0x18) // Fractional part of the pixel (Y.f and X.f)
2490 // This is all kinda murky. All we have are the Midsummer docs to give us any guidance,
2491 // and it's incomplete or filled with errors (like above). Aarrrgggghhhhh!
2493 //This isn't right. Is it? I don't think the fractional parts are signed...
2494 // a1_x += (int32)((int16)GET16(blitter_ram, A1_FSTEP + 2));
2495 // a1_y += (int32)((int16)GET16(blitter_ram, A1_FSTEP + 0));
2496 a1_x += GET16(blitter_ram, A1_FSTEP + 2);
2497 a1_y += GET16(blitter_ram, A1_FSTEP + 0);
2501 a1update: // Update A1 pointer integers
2503 a1update A1 step is added to A1 pointer, with carry from the fractional add
2504 POLYGON true: A1 step delta X and Y integer parts are added to the A1
2505 step X and Y integer parts, with carry from the corresponding
2506 fractional part add (again, the value prior to this add is used for
2507 the step to pointer add).
2508 POLYGON true: inner count step is added to the inner count, with carry
2509 POLYGON.GOURD true: the I step is added to the computed intensities,
2511 POLYGON.GOURD true: the I step delta is added to the I step, with
2512 carry the texture X and Y step delta values are added to the X and Y
2514 if GOURZ.POLYGON goto zfupdate
2515 else if UPDA2 goto a2update
2516 else if DATINIT goto init_if
2519 a1_x += (int32)(GET16(blitter_ram, A1_STEP + 2) << 16);
2520 a1_y += (int32)(GET16(blitter_ram, A1_STEP + 0) << 16);
2523 //kill this, for now...
2524 // if (GOURZ.POLYGON)
2534 zfupdate: // Update computed Z step fractions
2536 zfupdate the Z fraction step is added to the computed Z fraction parts +
2537 the Z fraction step delta is added to the Z fraction step
2542 zupdate: // Update computed Z step integers
2544 zupdate the Z step is added to the computed Zs, with carry +
2545 the Z step delta is added to the Z step, with carry
2546 if UPDA2 goto a2update
2547 else if DATINIT goto init_if
2557 a2update: // Update A2 pointer
2559 a2update A2 step is added to the A2 pointer
2560 if DATINIT goto init_if
2563 a2_x += (int32)(GET16(blitter_ram, A2_STEP + 2) << 16);
2564 a2_y += (int32)(GET16(blitter_ram, A2_STEP + 0) << 16);
2572 init_if: // Initialise intensity fractions and texture X
2574 init_if Initialise the fractional part of the computed intensity fields, from
2575 the increment and step registers. The texture X integer and fractional
2576 parts can also be initialised.
2581 init_ii: // Initialise intensity integers and texture Y
2583 init_ii Initialise the integer part of the computed intensity, and texture Y
2584 integer and fractional parts
2585 if GOURZ goto init_zf
2593 init_zf: // Initialise Z fractions
2595 init_zf Initialise the fractional part of the computed Z fields.
2600 init_zi: // Initialise Z integers
2602 init_zi Initialise the integer part of the computed Z fields.
2609 The outer loop state machine fires off the inner loop, and controls the updating
2610 process between passes through the inner loop.
2612 + -- these functions are irrelevant if the DATINIT function is enabled, which it
2615 All these states will complete in one clock cycle, with the exception of the idle
2616 state, which means the blitter is quiescent; and the inner state, which takes as
2617 long as is required to complete one strip of pixels. It is therefore possible for
2618 the blitter to spend a maximum of nine clock cycles of inactivity between passes
2619 through the inner loop.
2629 // Here's attempt #2--taken from the Oberon chip specs!
2632 #ifdef USE_MIDSUMMER_BLITTER_MKII
2634 void ADDRGEN(uint32 &, uint32 &, bool, bool,
2635 uint16, uint16, uint32, uint8, uint8, uint8, uint8,
2636 uint16, uint16, uint32, uint8, uint8, uint8, uint8);
2637 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
2638 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
2639 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
2640 uint32 zinc, uint32 zstep);
2641 void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh);
2642 void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
2643 int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
2644 int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
2645 bool adda_yconst, bool addareg, bool suba_x, bool suba_y);
2646 void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
2647 int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y);
2648 void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel);
2649 void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
2650 uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y);
2651 void DATA(uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
2652 bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
2653 uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 &patd, bool patdadd,
2654 bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
2655 bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize,
2656 uint64 &srcz, uint64 dstz, uint32 zinc);
2657 void COMP_CTRL(uint8 &dbinh, bool &nowrite,
2658 bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
2659 uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp);
2660 #define VERBOSE_BLITTER_LOGGING
2661 bool logBlit = false;
2663 void BlitterMidsummer2(void)
2665 // Here's what the specs say the state machine does. Note that this can probably be
2666 // greatly simplified (also, it's different from what John has in his Oberon docs):
2667 //Will remove stuff that isn't in Jaguar I once fully described (stuff like texture won't
2668 //be described here at all)...
2670 uint32 cmd = GET32(blitter_ram, COMMAND);
2674 cmd != 0x00010200 && // PATDSEL
2675 cmd != 0x01800001 // SRCEN LFUFUNC=C
2676 && cmd != 0x01800005
2677 //Boot ROM ATARI letters:
2678 && cmd != 0x00011008 // DSTEN GOURD PATDSEL
2679 //Boot ROM spinning cube:
2680 && cmd != 0x41802F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
2682 && cmd != 0x01800E01 // SRCEN UPDA1 UPDA2 DSTA2 LFUFUNC=C
2683 //T2K TEMPEST letters:
2684 && cmd != 0x09800741 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 LFUFUNC=C DCOMPEN
2685 //Static letters on Cybermorph intro screen:
2686 && cmd != 0x09800609 // SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
2687 //Static pic on title screen:
2688 && cmd != 0x01800601 // SRCEN UPDA1 UPDA2 LFUFUNC=C
2689 //Turning letters on Cybermorph intro screen:
2690 // && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2691 && cmd != 0x00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
2692 && cmd != 0x09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
2693 && cmd != 0x09800209 // SRCEN DSTEN UPDA1 LFUFUNC=C DCOMPEN
2694 && cmd != 0x00011200 // UPDA1 GOURD PATDSEL
2695 //Start of Hover Strike (clearing screen):
2696 && cmd != 0x00010000 // PATDSEL
2697 //Hover Strike text:
2698 && cmd != 0x1401060C // SRCENX DSTEN UPDA1 UPDA2 PATDSEL BCOMPEN BKGWREN
2699 //Hover Strike 3D stuff
2700 && cmd != 0x01902839 // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2701 //Hover Strike darkening on intro to play (briefing) screen
2702 && cmd != 0x00020208 // DSTEN UPDA1 ADDDSEL
2703 //Trevor McFur stuff:
2704 && cmd != 0x05810601 // SRCEN UPDA1 UPDA2 PATDSEL BCOMPEN
2705 && cmd != 0x01800201 // SRCEN UPDA1 LFUFUNC=C
2707 && cmd != 0x00011000 // GOURD PATDSEL
2708 && cmd != 0x00011040 // CLIP_A1 GOURD PATDSEL
2710 && cmd != 0x01800000 // LFUFUNC=C
2711 && cmd != 0x01800401 //
2712 && cmd != 0x01800040 //
2713 && cmd != 0x00020008 //
2714 // && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2718 if (blit_start_log == 0) // Wait for the signal...
2719 logBlit = false;//*/
2721 Some T2K unique blits:
2722 logBlit = F, cmd = 00010200 *
2723 logBlit = F, cmd = 00011000
2724 logBlit = F, cmd = 00011040
2725 logBlit = F, cmd = 01800005 *
2726 logBlit = F, cmd = 09800741 *
2728 Hover Strike mission selection screen:
2729 Blit! (CMD = 01902839) // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2731 Checkered Flag blits in the screw up zone:
2732 Blit! (CMD = 01800001) // SRCEN LFUFUNC=C
2733 Blit! (CMD = 01800000) // LFUFUNC=C
2734 Blit! (CMD = 00010000) // PATDSEL
2736 Wolfenstein 3D in the fuckup zone:
2737 Blit! (CMD = 01800000) // LFUFUNC=C
2740 //printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2745 Blit! (CMD = 00011040)
2746 Flags: CLIP_A1 GOURD PATDSEL
2748 a1_base = 00100000, a2_base = 0081F6A8
2749 a1_x = 00A7, a1_y = 0014, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0001, a2_y = 0000
2750 a1_step_x = FE80, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFF8, a2_step_y = 0001
2751 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
2752 a1_win_x = 0180, a1_win_y = 0118, a2_mask_x = 0000, a2_mask_y = 0000
2753 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
2754 a1_pixsize = 4, a2_pixsize = 4
2758 if (cmd == 0x00011040
2759 && (GET16(blitter_ram, A1_PIXEL + 2) == 0x00A7) && (GET16(blitter_ram, A1_PIXEL + 0) == 0x0014)
2760 && (GET16(blitter_ram, A2_PIXEL + 2) == 0x0001) && (GET16(blitter_ram, A2_PIXEL + 0) == 0x0000)
2761 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 18))
2764 // Line states passed in via the command register
2766 bool srcen = (SRCEN), srcenx = (SRCENX), srcenz = (SRCENZ),
2767 dsten = (DSTEN), dstenz = (DSTENZ), dstwrz = (DSTWRZ), clip_a1 = (CLIPA1),
2768 upda1 = (UPDA1), upda1f = (UPDA1F), upda2 = (UPDA2), dsta2 = (DSTA2),
2769 gourd = (GOURD), gourz = (GOURZ), topben = (TOPBEN), topnen = (TOPNEN),
2770 patdsel = (PATDSEL), adddsel = (ADDDSEL), cmpdst = (CMPDST), bcompen = (BCOMPEN),
2771 dcompen = (DCOMPEN), bkgwren = (BKGWREN), srcshade = (SRCSHADE);
2773 uint8 zmode = (cmd & 0x01C0000) >> 18, lfufunc = (cmd & 0x1E00000) >> 21;
2775 //Where to find various lines:
2777 // gourd -> dcontrol, inner, outer, state
2778 // gourz -> dcontrol, inner, outer, state
2779 // cmpdst -> blit, data, datacomp, state
2780 // bcompen -> acontrol, inner, mcontrol, state
2781 // dcompen -> inner, state
2782 // bkgwren -> inner, state
2783 // srcshade -> dcontrol, inner, state
2784 // adddsel -> dcontrol
2785 //NOTE: ADDDSEL takes precedence over PATDSEL, PATDSEL over LFU_FUNC
2786 #ifdef VERBOSE_BLITTER_LOGGING
2789 char zfs[512], lfus[512];
2790 zfs[0] = lfus[0] = 0;
2791 if (dstwrz || dstenz || gourz)
2792 sprintf(zfs, " ZMODE=%X", zmode);
2793 if (!(patdsel || adddsel))
2794 sprintf(lfus, " LFUFUNC=%X", lfufunc);
2795 printf("\nBlit! (CMD = %08X)\nFlags:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", cmd,
2796 (srcen ? " SRCEN" : ""), (srcenx ? " SRCENX" : ""), (srcenz ? " SRCENZ" : ""),
2797 (dsten ? " DSTEN" : ""), (dstenz ? " DSTENZ" : ""), (dstwrz ? " DSTWRZ" : ""),
2798 (clip_a1 ? " CLIP_A1" : ""), (upda1 ? " UPDA1" : ""), (upda1f ? " UPDA1F" : ""),
2799 (upda2 ? " UPDA2" : ""), (dsta2 ? " DSTA2" : ""), (gourd ? " GOURD" : ""),
2800 (gourz ? " GOURZ" : ""), (topben ? " TOPBEN" : ""), (topnen ? " TOPNEN" : ""),
2801 (patdsel ? " PATDSEL" : ""), (adddsel ? " ADDDSEL" : ""), zfs, lfus, (cmpdst ? " CMPDST" : ""),
2802 (bcompen ? " BCOMPEN" : ""), (dcompen ? " DCOMPEN" : ""), (bkgwren ? " BKGWREN" : ""),
2803 (srcshade ? " SRCSHADE" : ""));
2804 printf(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
2809 // Lines that don't exist in Jaguar I (and will never be asserted)
2811 bool polygon = false, datinit = false, a1_stepld = false, a2_stepld = false, ext_int = false;
2812 bool istepadd = false, istepfadd = false, finneradd = false, inneradd = false;
2813 bool zstepfadd = false, zstepadd = false;
2815 // Various state lines (initial state--basically the reset state of the FDSYNCs)
2817 bool go = true, idle = true, inner = false, a1fupdate = false, a1update = false,
2818 zfupdate = false, zupdate = false, a2update = false, init_if = false, init_ii = false,
2819 init_zf = false, init_zi = false;
2821 bool outer0 = false, indone = false;
2823 bool idlei, inneri, a1fupdatei, a1updatei, zfupdatei, zupdatei, a2updatei, init_ifi, init_iii,
2826 bool notgzandp = !(gourz && polygon);
2828 // Various registers set up by user
2830 uint16 ocount = GET16(blitter_ram, PIXLINECOUNTER);
2831 uint8 a1_pitch = blitter_ram[A1_FLAGS + 3] & 0x03;
2832 uint8 a2_pitch = blitter_ram[A2_FLAGS + 3] & 0x03;
2833 uint8 a1_pixsize = (blitter_ram[A1_FLAGS + 3] & 0x38) >> 3;
2834 uint8 a2_pixsize = (blitter_ram[A2_FLAGS + 3] & 0x38) >> 3;
2835 uint8 a1_zoffset = (GET16(blitter_ram, A1_FLAGS + 2) >> 6) & 0x07;
2836 uint8 a2_zoffset = (GET16(blitter_ram, A2_FLAGS + 2) >> 6) & 0x07;
2837 uint8 a1_width = (blitter_ram[A1_FLAGS + 2] >> 1) & 0x3F;
2838 uint8 a2_width = (blitter_ram[A2_FLAGS + 2] >> 1) & 0x3F;
2839 bool a2_mask = blitter_ram[A2_FLAGS + 2] & 0x80;
2840 uint8 a1addx = blitter_ram[A1_FLAGS + 1] & 0x03, a2addx = blitter_ram[A2_FLAGS + 1] & 0x03;
2841 bool a1addy = blitter_ram[A1_FLAGS + 1] & 0x04, a2addy = blitter_ram[A2_FLAGS + 1] & 0x04;
2842 bool a1xsign = blitter_ram[A1_FLAGS + 1] & 0x08, a2xsign = blitter_ram[A2_FLAGS + 1] & 0x08;
2843 bool a1ysign = blitter_ram[A1_FLAGS + 1] & 0x10, a2ysign = blitter_ram[A2_FLAGS + 1] & 0x10;
2844 uint32 a1_base = GET32(blitter_ram, A1_BASE) & 0xFFFFFFF8; // Phrase aligned by ignoring bottom 3 bits
2845 uint32 a2_base = GET32(blitter_ram, A2_BASE) & 0xFFFFFFF8;
2847 uint16 a1_win_x = GET16(blitter_ram, A1_CLIP + 2) & 0x7FFF;
2848 uint16 a1_win_y = GET16(blitter_ram, A1_CLIP + 0) & 0x7FFF;
2849 int16 a1_x = (int16)GET16(blitter_ram, A1_PIXEL + 2);
2850 int16 a1_y = (int16)GET16(blitter_ram, A1_PIXEL + 0);
2851 int16 a1_step_x = (int16)GET16(blitter_ram, A1_STEP + 2);
2852 int16 a1_step_y = (int16)GET16(blitter_ram, A1_STEP + 0);
2853 uint16 a1_stepf_x = GET16(blitter_ram, A1_FSTEP + 2);
2854 uint16 a1_stepf_y = GET16(blitter_ram, A1_FSTEP + 0);
2855 uint16 a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
2856 uint16 a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
2857 int16 a1_inc_x = (int16)GET16(blitter_ram, A1_INC + 2);
2858 int16 a1_inc_y = (int16)GET16(blitter_ram, A1_INC + 0);
2859 uint16 a1_incf_x = GET16(blitter_ram, A1_FINC + 2);
2860 uint16 a1_incf_y = GET16(blitter_ram, A1_FINC + 0);
2862 int16 a2_x = (int16)GET16(blitter_ram, A2_PIXEL + 2);
2863 int16 a2_y = (int16)GET16(blitter_ram, A2_PIXEL + 0);
2864 uint16 a2_mask_x = GET16(blitter_ram, A2_MASK + 2);
2865 uint16 a2_mask_y = GET16(blitter_ram, A2_MASK + 0);
2866 int16 a2_step_x = (int16)GET16(blitter_ram, A2_STEP + 2);
2867 int16 a2_step_y = (int16)GET16(blitter_ram, A2_STEP + 0);
2869 uint64 srcd1 = GET64(blitter_ram, SRCDATA);
2871 uint64 dstd = GET64(blitter_ram, DSTDATA);
2872 uint64 patd = GET64(blitter_ram, PATTERNDATA);
2873 uint32 iinc = GET32(blitter_ram, INTENSITYINC);
2874 uint64 srcz1 = GET64(blitter_ram, SRCZINT);
2875 uint64 srcz2 = GET64(blitter_ram, SRCZFRAC);
2876 uint64 dstz = GET64(blitter_ram, DSTZ);
2877 uint32 zinc = GET32(blitter_ram, ZINC);
2878 uint32 collision = GET32(blitter_ram, COLLISIONCTRL);// 0=RESUME, 1=ABORT, 2=STOPEN
2880 uint8 pixsize = (dsta2 ? a2_pixsize : a1_pixsize); // From ACONTROL
2882 //Testing Trevor McFur--I *think* it's the circle on the lower RHS of the screen...
2884 if (cmd == 0x05810601 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 96)
2885 && (GET16(blitter_ram, PIXLINECOUNTER + 0) == 72))
2888 //if (cmd == 0x1401060C) patd = 0xFFFFFFFFFFFFFFFFLL;
2889 //if (cmd == 0x1401060C) patd = 0x00000000000000FFLL;
2890 //If it's still not working (bcompen-patd) then see who's writing what to patd and where...
2891 //Still not OK. Check to see who's writing what to where in patd!
2892 //It looks like M68K is writing to the top half of patd... Hmm...
2894 ----> M68K wrote 0000 to byte 15737344 of PATTERNDATA...
2895 --> M68K wrote 00 to byte 0 of PATTERNDATA...
2896 --> M68K wrote 00 to byte 1 of PATTERNDATA...
2897 ----> M68K wrote 00FF to byte 15737346 of PATTERNDATA...
2898 --> M68K wrote 00 to byte 2 of PATTERNDATA...
2899 --> M68K wrote FF to byte 3 of PATTERNDATA...
2900 logBlit = F, cmd = 1401060C
2902 Wren0 := ND6 (wren\[0], gpua\[5], gpua\[6..8], bliten, gpu_memw);
2903 Wren1 := ND6 (wren\[1], gpua[5], gpua\[6..8], bliten, gpu_memw);
2904 Wren2 := ND6 (wren\[2], gpua\[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2905 Wren3 := ND6 (wren\[3], gpua[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2908 Dec0 := D38GH (a1baseld, a1flagld, a1winld, a1ptrld, a1stepld, a1stepfld, a1fracld, a1incld, gpua[2..4], wren\[0]);
2910 Dec1 := D38GH (a1incfld, a2baseld, a2flagld, a2maskld, a2ptrldg, a2stepld, cmdldt, countldt, gpua[2..4], wren\[1]);
2912 Dec2 := D38GH (srcd1ldg[0..1], dstdldg[0..1], dstzldg[0..1], srcz1ldg[0..1], gpua[2..4], wren\[2]);
2914 Dec3 := D38GH (srcz2ld[0..1], patdld[0..1], iincld, zincld, stopld, intld[0], gpua[2..4], wren\[3]);
2916 wren[3] is asserted when gpu address bus = 0 011x xx00
2917 patdld[0] -> 0 0110 1000 -> $F02268 (lo 32 bits)
2918 patdld[1] -> 0 0110 1100 -> $F0226C (hi 32 bits)
2920 So... It's reversed! The data organization of the patd register is [low 32][high 32]! !!! FIX !!! [DONE]
2921 And fix all the other 64 bit registers [DONE]
2923 /*if (cmd == 0x1401060C)
2925 printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2929 if ((cmd == 0x00010200) && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 9))
2932 ; Pink altimeter bar
2934 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2935 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
2936 A1 step values: -10 (X), 1 (Y)
2937 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
2938 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
2939 A1 x/y: 262/132, A2 x/y: 129/0
2940 ;x-coord is 257 in pic, so add 5
2941 ;20 for ship, 33 for #... Let's see if we can find 'em!
2943 ; Black altimeter bar
2945 Blit! (00110000 <- 000BF010) count: 5 x 29, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2946 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
2947 A1 step values: -8 (X), 1 (Y)
2948 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
2949 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
2950 A1 x/y: 264/126, A2 x/y: 336/0
2952 Here's the pink bar--note that it's phrase mode without dread, so how does this work???
2953 Not sure, but I *think* that somehow it MUXes the data at the write site in on the left or right side
2954 of the write data when masked in phrase mode. I'll have to do some tracing to see if this is the mechanism
2957 Blit! (CMD = 00010200)
2958 Flags: UPDA1 PATDSEL
2960 a1_base = 00110010, a2_base = 000BD7E0
2961 a1_x = 0106, a1_y = 0090, a1_frac_x = 0000, a1_frac_y = 8000, a2_x = 025A, a2_y = 0000
2962 a1_step_x = FFF6, a1_step_y = 0001, a1_stepf_x = 5E00, a1_stepf_y = D100, a2_step_x = FFF7, a2_step_y = 0001
2963 a1_inc_x = 0001, a1_inc_y = FFFF, a1_incf_x = 0000, a1_incf_y = E000
2964 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
2965 a2_mask=F a1add=+phr/+0 a2add=+1/+0
2966 a1_pixsize = 4, a2_pixsize = 4
2967 srcd=BAC673AC2C92E578 dstd=0000000000000000 patd=74C074C074C074C0 iinc=0002E398
2968 srcz1=7E127E12000088DA srcz2=DBE06DF000000000 dstz=0000000000000000 zinc=FFFE4840, coll=0
2970 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2971 Entering INNER state...
2972 Entering DWRITE state...
2973 Dest write address/pix address: 0016A830/0 [dstart=20 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F] [7400000074C074C0] (icount=0007, inc=2)
2974 Entering A1_ADD state [a1_x=0106, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2975 Entering DWRITE state...
2976 Dest write address/pix address: 0016A850/0 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F] [74C074C074C074C0] (icount=0003, inc=4)
2977 Entering A1_ADD state [a1_x=0108, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2978 Entering DWRITE state...
2979 Dest write address/pix address: 0016A870/0 [dstart=0 dend=30 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F] [74C074C074C00000] (icount=FFFF, inc=4)
2980 Entering A1_ADD state [a1_x=010C, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2981 Entering IDLE_INNER state...
2982 Leaving INNER state... (ocount=000A)
2983 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2984 Entering A1UPDATE state... (272/144 -> 262/145)
2985 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2986 Entering INNER state...
2991 a2addy = a1addy; // A2 channel Y add bit is tied to A1's
2993 //if (logBlit && (ocount > 20)) logBlit = false;
2994 #ifdef VERBOSE_BLITTER_LOGGING
2997 printf(" a1_base = %08X, a2_base = %08X\n", a1_base, a2_base);
2998 printf(" a1_x = %04X, a1_y = %04X, a1_frac_x = %04X, a1_frac_y = %04X, a2_x = %04X, a2_y = %04X\n", (uint16)a1_x, (uint16)a1_y, a1_frac_x, a1_frac_y, (uint16)a2_x, (uint16)a2_y);
2999 printf(" a1_step_x = %04X, a1_step_y = %04X, a1_stepf_x = %04X, a1_stepf_y = %04X, a2_step_x = %04X, a2_step_y = %04X\n", (uint16)a1_step_x, (uint16)a1_step_y, a1_stepf_x, a1_stepf_y, (uint16)a2_step_x, (uint16)a2_step_y);
3000 printf(" a1_inc_x = %04X, a1_inc_y = %04X, a1_incf_x = %04X, a1_incf_y = %04X\n", (uint16)a1_inc_x, (uint16)a1_inc_y, a1_incf_x, a1_incf_y);
3001 printf(" a1_win_x = %04X, a1_win_y = %04X, a2_mask_x = %04X, a2_mask_y = %04X\n", a1_win_x, a1_win_y, a2_mask_x, a2_mask_y);
3002 char x_add_str[4][4] = { "phr", "1", "0", "inc" };
3003 printf(" a2_mask=%s a1add=%s%s/%s%s a2add=%s%s/%s%s\n", (a2_mask ? "T" : "F"), (a1xsign ? "-" : "+"), x_add_str[a1addx],
3004 (a1ysign ? "-" : "+"), (a1addy ? "1" : "0"), (a2xsign ? "-" : "+"), x_add_str[a2addx],
3005 (a2ysign ? "-" : "+"), (a2addy ? "1" : "0"));
3006 printf(" a1_pixsize = %u, a2_pixsize = %u\n", a1_pixsize, a2_pixsize);
3007 printf(" srcd=%08X%08X dstd=%08X%08X patd=%08X%08X iinc=%08X\n",
3008 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF),
3009 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
3010 (uint32)(patd >> 32), (uint32)(patd & 0xFFFFFFFF), iinc);
3011 printf(" srcz1=%08X%08X srcz2=%08X%08X dstz=%08X%08X zinc=%08X, coll=%X\n",
3012 (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
3013 (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF),
3014 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF), zinc, collision);
3018 // Various state lines set up by user
3020 bool phrase_mode = ((!dsta2 && a1addx == 0) || (dsta2 && a2addx == 0) ? true : false); // From ACONTROL
3021 #ifdef VERBOSE_BLITTER_LOGGING
3024 printf(" Phrase mode is %s\n", (phrase_mode ? "ON" : "off"));
3030 // Stopgap vars to simulate various lines
3032 uint16 a1FracCInX = 0, a1FracCInY = 0;
3038 if ((idle && !go) || (inner && outer0 && indone))
3040 #ifdef VERBOSE_BLITTER_LOGGING
3043 printf(" Entering IDLE state...\n");
3049 //Instead of a return, let's try breaking out of the loop...
3056 // INNER LOOP ACTIVE
3058 Entering DWRITE state... (icount=0000, inc=4)
3059 Entering IDLE_INNER state...
3060 Leaving INNER state... (ocount=00EF)
3061 [in=T a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3062 Entering INNER state...
3064 [in=F a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3067 if ((idle && go && !datinit)
3068 || (inner && !indone)
3069 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && !datinit)
3070 || (a1update && !upda2 && notgzandp && !datinit)
3071 || (zupdate && !upda2 && !datinit)
3072 || (a2update && !datinit)
3073 || (init_ii && !gourz)
3081 // A1 FRACTION UPDATE
3083 if (inner && indone && !outer0 && upda1f)
3090 // A1 POINTER UPDATE
3093 || (inner && indone && !outer0 && !upda1f && upda1))
3100 // Z FRACTION UPDATE
3102 if ((a1update && gourz && polygon)
3103 || (inner && indone && !outer0 && !upda1f && !upda1 && gourz && polygon))
3119 // A2 POINTER UPDATE
3121 if ((a1update && upda2 && notgzandp)
3122 || (zupdate && upda2)
3123 || (inner && indone && !outer0 && !upda1f && notgzandp && !upda1 && upda2))
3130 // INITIALIZE INTENSITY FRACTION
3132 if ((zupdate && !upda2 && datinit)
3133 || (a1update && !upda2 && datinit && notgzandp)
3134 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && datinit)
3135 || (a2update && datinit)
3136 || (idle && go && datinit))
3143 // INITIALIZE INTENSITY INTEGER
3152 // INITIALIZE Z FRACTION
3154 if (init_ii && gourz)
3161 // INITIALIZE Z INTEGER
3170 // Here we move the fooi into their foo counterparts in order to simulate the moving
3171 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3175 a1fupdate = a1fupdatei;
3176 a1update = a1updatei;
3177 zfupdate = zfupdatei; // *
3178 zupdate = zupdatei; // *
3179 a2update = a2updatei;
3180 init_if = init_ifi; // *
3181 init_ii = init_iii; // *
3182 init_zf = init_zfi; // *
3183 init_zi = init_zii; // *
3184 // * denotes states that will never assert for Jaguar I
3185 #ifdef VERBOSE_BLITTER_LOGGING
3188 printf(" [in=%c a1f=%c a1=%c zf=%c z=%c a2=%c iif=%c iii=%c izf=%c izi=%c]\n",
3189 (inner ? 'T' : 'F'), (a1fupdate ? 'T' : 'F'), (a1update ? 'T' : 'F'), (zfupdate ? 'T' : 'F'),
3190 (zupdate ? 'T' : 'F'), (a2update ? 'T' : 'F'), (init_if ? 'T' : 'F'), (init_ii ? 'T' : 'F'),
3191 (init_zf ? 'T' : 'F'), (init_zi ? 'T' : 'F'));
3196 // Now, depending on how we want to handle things, we could either put the implementation
3197 // of the various pieces up above, or handle them down below here.
3199 // Let's try postprocessing for now...
3204 #ifdef VERBOSE_BLITTER_LOGGING
3207 printf(" Entering INNER state...\n");
3211 uint16 icount = GET16(blitter_ram, PIXLINECOUNTER + 2);
3212 bool idle_inner = true, step = true, sreadx = false, szreadx = false, sread = false,
3213 szread = false, dread = false, dzread = false, dwrite = false, dzwrite = false;
3214 bool inner0 = false;
3215 bool idle_inneri, sreadxi, szreadxi, sreadi, szreadi, dreadi, dzreadi, dwritei, dzwritei;
3217 // State lines that will never assert in Jaguar I
3219 bool textext = false, txtread = false;
3223 bool sshftld = true; // D flipflop (D -> Q): instart -> sshftld
3224 //NOTE: sshftld probably is only asserted at the beginning of the inner loop. !!! FIX !!!
3226 Blit! (CMD = 01800005)
3227 Flags: SRCEN SRCENX LFUFUNC=C
3229 a1_base = 00037290, a2_base = 000095D0
3230 a1_x = 0000, a1_y = 0000, a2_x = 0002, a2_y = 0000
3231 a1_pixsize = 4, a2_pixsize = 4
3232 srcd=0000000000000000, dstd=0000000000000000, patd=0000000000000000
3234 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3235 Entering INNER state...
3236 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
3237 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
3238 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3239 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3240 Source read address/pix address: 000095D8/0 [0054003800009814]
3241 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3242 Entering DWRITE state...
3243 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
3244 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3245 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3246 Source read address/pix address: 000095E0/0 [00009968000377C7]
3247 Entering A2_ADD state [a2_x=0008, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3248 Entering DWRITE state...
3249 Dest write address/pix address: 00037298/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026A, inc=4)
3250 Entering A1_ADD state [a1_x=0004, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3253 // while (!idle_inner)
3258 if ((idle_inner && !step)
3259 || (dzwrite && step && inner0)
3260 || (dwrite && step && !dstwrz && inner0))
3262 #ifdef VERBOSE_BLITTER_LOGGING
3265 printf(" Entering IDLE_INNER state...\n");
3273 idle_inneri = false;
3275 // EXTRA SOURCE DATA READ
3277 if ((idle_inner && step && srcenx)
3278 || (sreadx && !step))
3285 // EXTRA SOURCE ZED READ
3287 if ((sreadx && step && srcenz)
3288 || (szreadx && !step))
3295 // TEXTURE DATA READ (not implemented because not in Jaguar I)
3299 if ((szreadx && step && !textext)
3300 || (sreadx && step && !srcenz && srcen)
3301 || (idle_inner && step && !srcenx && !textext && srcen)
3302 || (dzwrite && step && !inner0 && !textext && srcen)
3303 || (dwrite && step && !dstwrz && !inner0 && !textext && srcen)
3304 || (txtread && step && srcen)
3305 || (sread && !step))
3314 if ((sread && step && srcenz)
3315 || (szread && !step))
3322 // DESTINATION DATA READ
3324 if ((szread && step && dsten)
3325 || (sread && step && !srcenz && dsten)
3326 || (sreadx && step && !srcenz && !textext && !srcen && dsten)
3327 || (idle_inner && step && !srcenx && !textext && !srcen && dsten)
3328 || (dzwrite && step && !inner0 && !textext && !srcen && dsten)
3329 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && dsten)
3330 || (txtread && step && !srcen && dsten)
3331 || (dread && !step))
3338 // DESTINATION ZED READ
3340 if ((dread && step && dstenz)
3341 || (szread && step && !dsten && dstenz)
3342 || (sread && step && !srcenz && !dsten && dstenz)
3343 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && dstenz)
3344 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && dstenz)
3345 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && dstenz)
3346 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && dstenz)
3347 || (txtread && step && !srcen && !dsten && dstenz)
3348 || (dzread && !step))
3355 // DESTINATION DATA WRITE
3357 if ((dzread && step)
3358 || (dread && step && !dstenz)
3359 || (szread && step && !dsten && !dstenz)
3360 || (sread && step && !srcenz && !dsten && !dstenz)
3361 || (txtread && step && !srcen && !dsten && !dstenz)
3362 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && !dstenz)
3363 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && !dstenz)
3364 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && !dstenz)
3365 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && !dstenz)
3366 || (dwrite && !step))
3373 // DESTINATION ZED WRITE
3375 if ((dzwrite && !step)
3376 || (dwrite && step && dstwrz))
3383 //Kludge: A QnD way to make sure that sshftld is asserted only for the first
3384 // cycle of the inner loop...
3385 sshftld = idle_inner;
3387 // Here we move the fooi into their foo counterparts in order to simulate the moving
3388 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3390 idle_inner = idle_inneri;
3400 // Here's a few more decodes--not sure if they're supposed to go here or not...
3402 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
3404 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
3406 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
3407 bool gendst = dreadi || dzreadi || dwritei || dzwritei;
3408 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
3410 bool zaddr = szreadx || szread || dzread || dzwrite;
3412 // Some stuff from MCONTROL.NET--not sure if this is the correct use of this decode or not...
3413 /*Fontread\ := OND1 (fontread\, sread[1], sreadx[1], bcompen);
3414 Fontread := INV1 (fontread, fontread\);
3415 Justt := NAN3 (justt, fontread\, phrase_mode, tactive\);
3416 Justify := TS (justify, justt, busen);*/
3417 bool fontread = (sread || sreadx) && bcompen;
3418 bool justify = !(!fontread && phrase_mode /*&& tactive*/);
3420 /* Generate inner loop update enables */
3422 A1_addi := MX2 (a1_addi, dsta_addi, srca_addi, dsta2);
3423 A2_addi := MX2 (a2_addi, srca_addi, dsta_addi, dsta2);
3424 A1_add := FD1 (a1_add, a1_add\, a1_addi, clk);
3425 A2_add := FD1 (a2_add, a2_add\, a2_addi, clk);
3426 A2_addb := BUF1 (a2_addb, a2_add);
3428 bool a1_add = (dsta2 ? srca_addi : dsta_addi);
3429 bool a2_add = (dsta2 ? dsta_addi : srca_addi);
3431 /* Address adder input A register selection
3432 000 A1 step integer part
3433 001 A1 step fraction part
3434 010 A1 increment integer part
3435 011 A1 increment fraction part
3439 bit 1 = /a2update . (a1_add . a1addx[0..1])
3440 bit 0 = /a2update . ( a1fupdate
3441 + a1_add . atick[0] . a1addx[0..1])
3442 The /a2update term on bits 0 and 1 is redundant.
3443 Now look-ahead based
3445 uint8 addasel = (a1fupdate || (a1_add && a1addx == 3) ? 0x01 : 0x00);
3446 addasel |= (a1_add && a1addx == 3 ? 0x02 : 0x00);
3447 addasel |= (a2update ? 0x04 : 0x00);
3448 /* Address adder input A X constant selection
3449 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all
3450 zeroes when they are all 1
3451 Remember - these are pixels, so to add one phrase the pixel size
3452 has to be taken into account to get the appropriate value.
3454 if a1addx[0..1] are 00 set 6 - pixel size
3455 if a1addx[0..1] are 01 set the value 000
3456 if a1addx[0..1] are 10 set the value 111
3458 JLH: Also, 11 will likewise set the value to 111
3460 uint8 a1_xconst = 6 - a1_pixsize, a2_xconst = 6 - a2_pixsize;
3464 else if (a1addx & 0x02)
3469 else if (a2addx & 0x02)
3472 uint8 adda_xconst = (a2_add ? a2_xconst : a1_xconst);
3473 /* Address adder input A Y constant selection
3474 22 June 94 - This was erroneous, because only the a1addy bit was reflected here.
3475 Therefore, the selection has to be controlled by a bug fix bit.
3476 JLH: Bug fix bit in Jaguar II--not in Jaguar I!
3478 bool adda_yconst = a1addy;
3479 /* Address adder input A register versus constant selection
3480 given by a1_add . a1addx[0..1]
3483 + a2_add . a2addx[0..1]
3486 bool addareg = ((a1_add && a1addx == 3) || a1update || a1fupdate
3487 || (a2_add && a2addx == 3) || a2update ? true : false);
3488 /* The adders can be put into subtract mode in add pixel size
3489 mode when the corresponding flags are set */
3490 bool suba_x = ((a1_add && a1xsign && a1addx == 1) || (a2_add && a2xsign && a2addx == 1) ? true : false);
3491 bool suba_y = ((a1_add && a1addy && a1ysign) || (a2_add && a2addy && a2ysign) ? true : false);
3492 /* Address adder input B selection
3499 + (a1_add . atick[0] . a1addx[0..1])
3500 + a1fupdate . a1_stepld
3501 + a1update . a1_stepld
3502 + a2update . a2_stepld
3503 Bit 0 = a2update + a2_add
3504 + a1fupdate . a1_stepld
3505 + a1update . a1_stepld
3506 + a2update . a2_stepld
3508 uint8 addbsel = (a2update || a2_add || (a1fupdate && a1_stepld)
3509 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x01 : 0x00);
3510 addbsel |= (a1fupdate || (a1_add && a1addx == 3) || (a1fupdate && a1_stepld)
3511 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x02 : 0x00);
3513 /* The modulo bits are used to align X onto a phrase boundary when
3514 it is being updated by one phrase
3521 Masking is enabled for a1 when a1addx[0..1] is 00, and the value
3522 is 6 - the pixel size (again!)
3524 uint8 maska1 = (a1_add && a1addx == 0 ? 6 - a1_pixsize : 0);
3525 uint8 maska2 = (a2_add && a2addx == 0 ? 6 - a2_pixsize : 0);
3526 uint8 modx = (a2_add ? maska2 : maska1);
3527 /* Generate load strobes for the increment updates */
3529 /*A1pldt := NAN2 (a1pldt, atick[1], a1_add);
3530 A1ptrldi := NAN2 (a1ptrldi, a1update\, a1pldt);
3532 A1fldt := NAN4 (a1fldt, atick[0], a1_add, a1addx[0..1]);
3533 A1fracldi := NAN2 (a1fracldi, a1fupdate\, a1fldt);
3535 A2pldt := NAN2 (a2pldt, atick[1], a2_add);
3536 A2ptrldi := NAN2 (a2ptrldi, a2update\, a2pldt);*/
3537 bool a1fracldi = a1fupdate || (a1_add && a1addx == 3);
3539 // Some more from DCONTROL...
3540 // atick[] just MAY be important here! We're assuming it's true and dropping the term...
3541 // That will probably screw up some of the lower terms that seem to rely on the timing of it...
3542 #warning srcdreadd is not properly initialized!
3543 bool srcdreadd = false; // Set in INNER.NET
3544 //Shadeadd\ := NAN2H (shadeadd\, dwrite, srcshade);
3545 //Shadeadd := INV2 (shadeadd, shadeadd\);
3546 bool shadeadd = dwrite && srcshade;
3547 /* Data adder control, input A selection
3548 000 Destination data
3549 001 Initialiser pixel value
3550 100 Source data - computed intensity fraction
3551 101 Pattern data - computed intensity
3552 110 Source zed 1 - computed zed
3553 111 Source zed 2 - computed zed fraction
3555 Bit 0 = dwrite . gourd . atick[1]
3556 + dzwrite . gourz . atick[0]
3559 + init_if + init_ii + init_zf + init_zi
3560 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3563 Bit 2 = (gourd + gourz) . /(init_if + init_ii + init_zf + init_zi)
3566 uint8 daddasel = ((dwrite && gourd) || (dzwrite && gourz) || istepadd || zstepfadd
3567 || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3568 daddasel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3569 daddasel |= (((gourd || gourz) && !(init_if || init_ii || init_zf || init_zi))
3570 || (dwrite && srcshade) ? 0x04 : 0x00);
3571 /* Data adder control, input B selection
3573 0001 Data initialiser increment
3574 0100 Bottom 16 bits of I increment repeated four times
3575 0101 Top 16 bits of I increment repeated four times
3576 0110 Bottom 16 bits of Z increment repeated four times
3577 0111 Top 16 bits of Z increment repeated four times
3578 1100 Bottom 16 bits of I step repeated four times
3579 1101 Top 16 bits of I step repeated four times
3580 1110 Bottom 16 bits of Z step repeated four times
3581 1111 Top 16 bits of Z step repeated four times
3583 Bit 0 = dwrite . gourd . atick[1]
3584 + dzwrite . gourz . atick[1]
3588 + init_if + init_ii + init_zf + init_zi
3589 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3592 Bit 2 = dwrite . gourd . (atick[0] + atick[1])
3593 + dzwrite . gourz . (atick[0] + atick[1])
3595 + istepadd + istepfadd + zstepadd + zstepfadd
3596 Bit 3 = istepadd + istepfadd + zstepadd + zstepfadd
3598 uint8 daddbsel = ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3599 || istepadd || zstepadd || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3600 daddbsel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3601 daddbsel |= ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3602 || istepadd || istepfadd || zstepadd || zstepfadd ? 0x04 : 0x00);
3603 daddbsel |= (istepadd && istepfadd && zstepadd && zstepfadd ? 0x08 : 0x00);
3604 /* Data adder mode control
3605 000 16-bit normal add
3606 001 16-bit saturating add with carry
3607 010 8-bit saturating add with carry, carry into top byte is
3609 011 8-bit saturating add with carry, carry into top byte and
3610 between top nybbles is inhibited (CRY)
3611 100 16-bit normal add with carry
3612 101 16-bit saturating add
3613 110 8-bit saturating add, carry into top byte is inhibited
3614 111 8-bit saturating add, carry into top byte and between top
3615 nybbles is inhibited
3617 The first five are used for Gouraud calculations, the latter three
3618 for adding source and destination data
3620 Bit 0 = dzwrite . gourz . atick[1]
3621 + dwrite . gourd . atick[1] . /topnen . /topben . /ext_int
3622 + dwrite . gourd . atick[1] . topnen . topben . /ext_int
3624 + istepadd . /topnen . /topben . /ext_int
3625 + istepadd . topnen . topben . /ext_int
3626 + /gourd . /gourz . /topnen . /topben
3627 + /gourd . /gourz . topnen . topben
3628 + shadeadd . /topnen . /topben
3629 + shadeadd . topnen . topben
3630 + init_ii . /topnen . /topben . /ext_int
3631 + init_ii . topnen . topben . /ext_int
3634 Bit 1 = dwrite . gourd . atick[1] . /topben . /ext_int
3635 + istepadd . /topben . /ext_int
3636 + /gourd . /gourz . /topben
3637 + shadeadd . /topben
3638 + init_ii . /topben . /ext_int
3640 Bit 2 = /gourd . /gourz
3642 + dwrite . gourd . atick[1] . ext_int
3643 + istepadd . ext_int
3646 uint8 daddmode = ((dzwrite && gourz) || (dwrite && gourd && !topnen && !topben && !ext_int)
3647 || (dwrite && gourd && topnen && topben && !ext_int) || zstepadd
3648 || (istepadd && !topnen && !topben && !ext_int)
3649 || (istepadd && topnen && topben && !ext_int) || (!gourd && !gourz && !topnen && !topben)
3650 || (!gourd && !gourz && topnen && topben) || (shadeadd && !topnen && !topben)
3651 || (shadeadd && topnen && topben) || (init_ii && !topnen && !topben && !ext_int)
3652 || (init_ii && topnen && topben && !ext_int) || init_zi ? 0x01 : 0x00);
3653 daddmode |= ((dwrite && gourd && !topben && !ext_int) || (istepadd && !topben && !ext_int)
3654 || (!gourd && !gourz && !topben) || (shadeadd && !topben)
3655 || (init_ii && !topben && !ext_int) ? 0x02 : 0x00);
3656 daddmode |= ((!gourd && !gourz) || shadeadd || (dwrite && gourd && ext_int)
3657 || (istepadd && ext_int) || (init_ii && ext_int) ? 0x04 : 0x00);
3658 /* Data add load controls
3659 Pattern fraction (dest data) is loaded on
3660 dwrite . gourd . atick[0]
3661 + istepfadd . /datinit
3663 Pattern data is loaded on
3664 dwrite . gourd . atick[1]
3665 + istepadd . /datinit . /datinit
3667 Source z1 is loaded on
3668 dzwrite . gourz . atick[1]
3669 + zstepadd . /datinit . /datinit
3671 Source z2 is loaded on
3672 dzwrite . gourz . atick[0]
3675 Texture map shaded data is loaded on
3676 srcdreadd . srcshade
3678 bool patfadd = (dwrite && gourd) || (istepfadd && !datinit) || init_if;
3679 bool patdadd = (dwrite && gourd) || (istepadd && !datinit) || init_ii;
3680 bool srcz1add = (dzwrite && gourz) || (zstepadd && !datinit) || init_zi;
3681 bool srcz2add = (dzwrite && gourz) || zstepfadd || init_zf;
3682 bool srcshadd = srcdreadd && srcshade;
3683 bool daddq_sel = patfadd || patdadd || srcz1add || srcz2add || srcshadd;
3684 /* Select write data
3685 This has to be controlled from stage 1 of the pipe-line, delayed
3686 by one tick, as the write occurs in the cycle after the ack.
3693 Bit 0 = /patdsel . /adddsel
3698 uint8 data_sel = ((!patdsel && !adddsel) || dzwrite ? 0x01 : 0x00)
3699 | (adddsel || dzwrite ? 0x02 : 0x00);
3701 uint32 address, pixAddr;
3702 ADDRGEN(address, pixAddr, gena2i, zaddr,
3703 a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3704 a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3706 //Here's my guess as to how the addresses get truncated to phrase boundaries in phrase mode...
3708 address &= 0xFFFFF8;
3710 /* Generate source alignment shift
3711 -------------------------------
3712 The source alignment shift for data move is the difference between
3713 the source and destination X pointers, multiplied by the pixel
3714 size. Only the low six bits of the pointers are of interest, as
3715 pixel sizes are always a power of 2 and window rows are always
3718 When not in phrase mode, the top 3 bits of the shift value are
3721 Source shifting is also used to extract bits for bit-to-byte
3722 expansion in phrase mode. This involves only the bottom three
3723 bits of the shift value, and is based on the offset within the
3724 phrase of the destination X pointer, in pixels.
3726 Source shifting is disabled when srcen is not set.
3728 uint8 dstxp = (dsta2 ? a2_x : a1_x) & 0x3F;
3729 uint8 srcxp = (dsta2 ? a1_x : a2_x) & 0x3F;
3730 uint8 shftv = ((dstxp - srcxp) << pixsize) & 0x3F;
3731 /* The phrase mode alignment count is given by the phrase offset
3732 of the first pixel, for bit to byte expansion */
3736 pobb = dstxp & 0x07;
3738 pobb = dstxp & 0x03;
3740 pobb = dstxp & 0x01;
3742 bool pobbsel = phrase_mode && bcompen;
3743 uint8 loshd = (pobbsel ? pobb : shftv) & 0x07;
3744 uint8 shfti = (srcen || pobbsel ? (sshftld ? loshd : srcshift & 0x07) : 0);
3745 /* Enable for high bits is srcen . phrase_mode */
3746 shfti |= (srcen && phrase_mode ? (sshftld ? shftv & 0x38 : srcshift & 0x38) : 0);
3751 #ifdef VERBOSE_BLITTER_LOGGING
3754 printf(" Entering SREADX state...");
3755 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
3759 //uint32 srcAddr, pixAddr;
3760 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3761 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3762 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3764 srcd1 = ((uint64)JaguarReadLong(address + 0, BLITTER) << 32)
3765 | (uint64)JaguarReadLong(address + 4, BLITTER);
3766 //Kludge to take pixel size into account...
3767 //Hmm. If we're not in phrase mode, this is most likely NOT going to be used...
3768 //Actually, it would be--because of BCOMPEN expansion, for example...
3777 else if (pixsize == 4)
3783 #ifdef VERBOSE_BLITTER_LOGGING
3786 printf(" Source extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3787 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
3795 #ifdef VERBOSE_BLITTER_LOGGING
3798 printf(" Entering SZREADX state...");
3803 srcz1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3804 #ifdef VERBOSE_BLITTER_LOGGING
3807 printf(" Src Z extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3808 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3816 #ifdef VERBOSE_BLITTER_LOGGING
3819 printf(" Entering SREAD state...");
3820 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
3824 //uint32 srcAddr, pixAddr;
3825 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3826 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3827 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3829 srcd1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3830 //Kludge to take pixel size into account...
3839 else if (pixsize == 4)
3845 #ifdef VERBOSE_BLITTER_LOGGING
3848 printf(" Source read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3849 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
3857 #ifdef VERBOSE_BLITTER_LOGGING
3860 printf(" Entering SZREAD state...");
3865 srcz1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3866 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3867 if (!phrase_mode && pixsize == 4)
3870 #ifdef VERBOSE_BLITTER_LOGGING
3873 printf(" Src Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3874 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3882 #ifdef VERBOSE_BLITTER_LOGGING
3885 printf(" Entering DREAD state...");
3889 //uint32 dstAddr, pixAddr;
3890 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
3891 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3892 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3893 dstd = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3894 //Kludge to take pixel size into account...
3899 else if (pixsize == 4)
3904 #ifdef VERBOSE_BLITTER_LOGGING
3907 printf(" Dest read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3908 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF));
3916 // Is Z always 64 bit read? Or sometimes 16 bit (dependent on phrase_mode)?
3917 #ifdef VERBOSE_BLITTER_LOGGING
3920 printf(" Entering DZREAD state...");
3924 dstz = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3925 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3926 if (!phrase_mode && pixsize == 4)
3929 #ifdef VERBOSE_BLITTER_LOGGING
3932 printf(" Dest Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3933 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3939 // These vars should probably go further up in the code... !!! FIX !!!
3940 // We can't preassign these unless they're static...
3941 //uint64 srcz = 0; // These are assigned to shut up stupid compiler warnings--dwrite is ALWAYS asserted
3942 //bool winhibit = false;
3945 //NOTE: SRCSHADE requires GOURZ to be set to work properly--another Jaguar I bug
3948 #ifdef VERBOSE_BLITTER_LOGGING
3951 printf(" Entering DWRITE state...");
3955 //Counter is done on the dwrite state...! (We'll do it first, since it affects dstart/dend calculations.)
3956 //Here's the voodoo for figuring the correct amount of pixels in phrase mode (or not):
3957 int8 inct = -((dsta2 ? a2_x : a1_x) & 0x07); // From INNER_CNT
3959 inc = (!phrase_mode || (phrase_mode && (inct & 0x01)) ? 0x01 : 0x00);
3960 inc |= (phrase_mode && (((pixsize == 3 || pixsize == 4) && (inct & 0x02)) || pixsize == 5 && !(inct & 0x01)) ? 0x02 : 0x00);
3961 inc |= (phrase_mode && ((pixsize == 3 && (inct & 0x04)) || (pixsize == 4 && !(inct & 0x03))) ? 0x04 : 0x00);
3962 inc |= (phrase_mode && pixsize == 3 && !(inct & 0x07) ? 0x08 : 0x00);
3964 uint16 oldicount = icount; // Save icount to detect underflow...
3967 if (icount == 0 || ((icount & 0x8000) && !(oldicount & 0x8000)))
3969 // X/Y stepping is also done here, I think...No. It's done when a1_add or a2_add is asserted...
3971 //*********************************************************************************
3972 //Start & end write mask computations...
3973 //*********************************************************************************
3978 dstart = (dstxp & 0x07) << 3;
3980 dstart = (dstxp & 0x03) << 4;
3982 dstart = (dstxp & 0x01) << 5;
3984 dstart = (phrase_mode ? dstart : pixAddr & 0x07);
3986 //This is the other Jaguar I bug... Normally, should ALWAYS select a1_x here.
3987 uint16 dstxwr = (dsta2 ? a2_x : a1_x) & 0x7FFE;
3988 uint16 pseq = dstxwr ^ (a1_win_x & 0x7FFE);
3989 pseq = (pixsize == 5 ? pseq : pseq & 0x7FFC);
3990 pseq = ((pixsize & 0x06) == 4 ? pseq : pseq & 0x7FF8);
3991 bool penden = clip_a1 && (pseq == 0);
3992 uint8 window_mask = 0;
3995 window_mask = (a1_win_x & 0x07) << 3;
3997 window_mask = (a1_win_x & 0x03) << 4;
3999 window_mask = (a1_win_x & 0x01) << 5;
4001 window_mask = (penden ? window_mask : 0);
4004 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4005 Source extra read address/pix address: 000095D0/0 [000004E40000001C]
4006 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4007 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4008 Source read address/pix address: 000095D8/0 [0054003800009814]
4009 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4010 Entering DWRITE state...
4011 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=20][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000001C00000000] (icount=026E, inc=4)
4012 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4014 (icount=026E, inc=4)
4015 icount & 0x03 = 0x02
4018 window_mask = 0x1000
4020 Therefore, it chooses the inner_mask over the window_mask every time! Argh!
4021 This is because we did this wrong:
4022 Innerm[3-5] := AN2 (inner_mask[3-5], imb[3-5], inner0);
4023 NOTE! This doesn't fix the problem because inner0 is asserted too late to help here. !!! FIX !!! [Should be DONE]
4026 /* The mask to be used if within one phrase of the end of the inner
4028 uint8 inner_mask = 0;
4031 inner_mask = (icount & 0x07) << 3;
4033 inner_mask = (icount & 0x03) << 4;
4035 inner_mask = (icount & 0x01) << 5;
4038 /* The actual mask used should be the lesser of the window masks and
4039 the inner mask, where is all cases 000 means 1000. */
4040 window_mask = (window_mask == 0 ? 0x40 : window_mask);
4041 inner_mask = (inner_mask == 0 ? 0x40 : inner_mask);
4042 uint8 emask = (window_mask > inner_mask ? inner_mask : window_mask);
4043 /* The mask to be used for the pixel size, to which must be added
4045 uint8 pma = pixAddr + (1 << pixsize);
4046 /* Select the mask */
4047 uint8 dend = (phrase_mode ? emask : pma);
4049 /* The cycle width in phrase mode is normally one phrase. However,
4050 at the start and end it may be narrower. The start and end masks
4051 are used to generate this. The width is given by:
4053 8 - start mask - (8 - end mask)
4054 = end mask - start mask
4056 This is only used for writes in phrase mode.
4057 Start and end from the address level of the pipeline are used.
4059 uint8 pwidth = (((dend | dstart) & 0x07) == 0 ? 0x08 : (dend - dstart) & 0x07);
4061 //uint32 dstAddr, pixAddr;
4062 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
4063 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
4064 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
4065 #ifdef VERBOSE_BLITTER_LOGGING
4068 printf(" Dest write address/pix address: %08X/%1X", address, pixAddr);
4073 //More testing... This is almost certainly wrong, but how else does this work???
4074 //Seems to kinda work... But still, this doesn't seem to make any sense!
4075 if (phrase_mode && !dsten)
4076 dstd = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
4078 //Testing only... for now...
4079 //This is wrong because the write data is a combination of srcd and dstd--either run
4080 //thru the LFU or in PATDSEL or ADDDSEL mode. [DONE now, thru DATA module]
4081 // Precedence is ADDDSEL > PATDSEL > LFU.
4082 //Also, doesn't take into account the start & end masks, or the phrase width...
4085 // srcd2 = xxxx xxxx 0123 4567, srcd = 8901 2345 xxxx xxxx, srcshift = $20 (32)
4086 uint64 srcd = (srcd2 << (64 - srcshift)) | (srcd1 >> srcshift);
4087 //bleh, ugly ugly ugly
4091 //NOTE: This only works with pixel sizes less than 8BPP...
4092 //DOUBLE NOTE: Still need to do regression testing to ensure that this doesn't break other stuff... !!! CHECK !!!
4093 if (!phrase_mode && srcshift != 0)
4094 srcd = ((srcd2 & 0xFF) << (8 - srcshift)) | ((srcd1 & 0xFF) >> srcshift);
4096 //Z DATA() stuff done here... And it has to be done before any Z shifting...
4097 //Note that we need to have phrase mode start/end support here... (Not since we moved it from dzwrite...!)
4099 Here are a couple of Cybermorph blits with Z:
4100 $00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
4101 $09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
4103 We're having the same phrase mode overwrite problem we had with the pixels... !!! FIX !!!
4104 Odd. It's equating 0 with 0... Even though ZMODE is $04 (less than)!
4109 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
4110 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
4111 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
4112 uint32 zinc, uint32 zstep)
4115 uint8 initcin[4] = { 0, 0, 0, 0 };
4116 ADDARRAY(addq, 7/*daddasel*/, 6/*daddbsel*/, 0/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4117 srcz2 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4118 ADDARRAY(addq, 6/*daddasel*/, 7/*daddbsel*/, 1/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4119 srcz1 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4121 #if 0//def VERBOSE_BLITTER_LOGGING
4124 printf("\n[srcz1=%08X%08X, srcz2=%08X%08X, zinc=%08X",
4125 (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
4126 (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF), zinc);
4132 uint8 zSrcShift = srcshift & 0x30;
4133 srcz = (srcz2 << (64 - zSrcShift)) | (srcz1 >> zSrcShift);
4134 //bleh, ugly ugly ugly
4138 #if 0//def VERBOSE_BLITTER_LOGGING
4141 printf(" srcz=%08X%08X]\n", (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4146 //When in SRCSHADE mode, it adds the IINC to the read source (from LFU???)
4147 //According to following line, it gets LFU mode. But does it feed the source into the LFU
4149 //Dest write address/pix address: 0014E83E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003F, inc=1)
4153 //NOTE: This is basically doubling the work done by DATA--since this is what
4154 // ADDARRAY is loaded with when srschshade is enabled... !!! FIX !!!
4155 // Also note that it doesn't work properly unless GOURZ is set--there's the clue!
4157 uint8 initcin[4] = { 0, 0, 0, 0 };
4158 ADDARRAY(addq, 4/*daddasel*/, 5/*daddbsel*/, 7/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4159 srcd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4161 //Seems to work... Not 100% sure tho.
4164 //Temporary kludge, to see if the fractional pattern does anything...
4166 //But it seems to mess up in Cybermorph... the shading should be smooth but it isn't...
4167 //Seems the carry out is lost again... !!! FIX !!! [DONE--see below]
4171 uint8 initcin[4] = { 0, 0, 0, 0 };
4172 ADDARRAY(addq, 4/*daddasel*/, 4/*daddbsel*/, 0/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4173 srcd1 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4176 //Note that we still don't take atick[0] & [1] into account here, so this will skip half of the data needed... !!! FIX !!!
4177 //Not yet enumerated: dbinh, srcdread, srczread
4178 //Also, should do srcshift on the z value in phrase mode... !!! FIX !!! [DONE]
4179 //As well as add a srcz variable we can set external to this state... !!! FIX !!! [DONE]
4183 DATA(wdata, dcomp, zcomp, winhibit,
4184 true, cmpdst, daddasel, daddbsel, daddmode, daddq_sel, data_sel, 0/*dbinh*/,
4185 dend, dstart, dstd, iinc, lfufunc, patd, patdadd,
4186 phrase_mode, srcd, false/*srcdread*/, false/*srczread*/, srcz2add, zmode,
4187 bcompen, bkgwren, dcompen, icount & 0x07, pixsize,
4190 Seems that the phrase mode writes with DCOMPEN and DSTEN are corrupting inside of DATA: !!! FIX !!!
4191 It's fairly random as well. 7CFE -> 7DFE, 7FCA -> 78CA, 7FA4 -> 78A4, 7F88 -> 8F88
4192 It could be related to an uninitialized variable, like the zmode bug...
4194 It was a bug in the dech38el data--it returned $FF for ungated instead of $00...
4196 Blit! (CMD = 09800609)
4197 Flags: SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
4199 a1_base = 00110000, a2_base = 0010B2A8
4200 a1_x = 004B, a1_y = 00D8, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0704, a2_y = 0000
4201 a1_step_x = FFF3, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFFC, a2_step_y = 0000
4202 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4203 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4204 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4205 a1_pixsize = 4, a2_pixsize = 4
4206 srcd=0000000000000000 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4207 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4209 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4210 Entering INNER state...
4211 Entering SREAD state... Source read address/pix address: 0010C0B0/0 [0000000078047804]
4212 Entering A2_ADD state [a2_x=0704, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4213 Entering DREAD state...
4214 Dest read address/pix address: 00197240/0 [0000000000000028]
4215 Entering DWRITE state...
4216 Dest write address/pix address: 00197240/0 [dstart=30 dend=40 pwidth=8 srcshift=30][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000028] (icount=0009, inc=1)
4217 Entering A1_ADD state [a1_x=004B, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4218 Entering SREAD state... Source read address/pix address: 0010C0B8/0 [7804780478047804]
4219 Entering A2_ADD state [a2_x=0708, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4220 Entering DREAD state...
4221 Dest read address/pix address: 00197260/0 [0028000000200008]
4222 Entering DWRITE state...
4223 Dest write address/pix address: 00197260/0 [dstart=0 dend=40 pwidth=8 srcshift=30][daas=0 dabs=0 dam=7 ds=1 daq=F] [0028780478047804] (icount=0005, inc=4)
4224 Entering A1_ADD state [a1_x=004C, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4225 Entering SREAD state... Source read address/pix address: 0010C0C0/0 [0000000000000000]
4226 Entering A2_ADD state [a2_x=070C, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4227 Entering DREAD state...
4228 Dest read address/pix address: 00197280/0 [0008001800180018]
4229 Entering DWRITE state...
4230 Dest write address/pix address: 00197280/0 [dstart=0 dend=40 pwidth=8 srcshift=30][daas=0 dabs=0 dam=7 ds=1 daq=F] [7804780478040018] (icount=0001, inc=4)
4231 Entering A1_ADD state [a1_x=0050, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4232 Entering SREAD state... Source read address/pix address: 0010C0C8/0 [000078047BFE7BFE]
4233 Entering A2_ADD state [a2_x=0710, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4234 Entering DREAD state...
4235 Dest read address/pix address: 001972A0/0 [0008002000000000]
4236 Entering DWRITE state...
4237 Dest write address/pix address: 001972A0/0 [dstart=0 dend=10 pwidth=8 srcshift=30][daas=0 dabs=0 dam=7 ds=1 daq=F] [0008002000000000] (icount=FFFD, inc=4)
4238 Entering A1_ADD state [a1_x=0054, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4239 Entering IDLE_INNER state...
4242 //Why isn't this taken care of in DATA? Because, DATA is modifying its local copy instead of the one used here.
4243 //!!! FIX !!! [DONE]
4252 a1_outside // A1 pointer is outside window bounds
4261 // The address is outside if negative, or if greater than or equal
4262 // to the window size
4264 A1_xcomp := MAG_15 (a1xgr, a1xeq, a1xlt, a1_x{0..14}, a1_win_x{0..14});
4265 A1_ycomp := MAG_15 (a1ygr, a1yeq, a1ylt, a1_y{0..14}, a1_win_y{0..14});
4266 A1_outside := OR6 (a1_outside, a1_x{15}, a1xgr, a1xeq, a1_y{15}, a1ygr, a1yeq);
4268 //NOTE: There seems to be an off-by-one bug here in the clip_a1 section... !!! FIX !!!
4269 // Actually, seems to be related to phrase mode writes...
4270 // Or is it? Could be related to non-15-bit compares as above?
4271 if (clip_a1 && ((a1_x & 0x8000) || (a1_y & 0x8000) || (a1_x >= a1_win_x) || (a1_y >= a1_win_y)))
4278 JaguarWriteLong(address + 0, wdata >> 32, BLITTER);
4279 JaguarWriteLong(address + 4, wdata & 0xFFFFFFFF, BLITTER);
4284 JaguarWriteLong(address, wdata & 0xFFFFFFFF, BLITTER);
4285 else if (pixsize == 4)
4286 JaguarWriteWord(address, wdata & 0x0000FFFF, BLITTER);
4288 JaguarWriteByte(address, wdata & 0x000000FF, BLITTER);
4292 #ifdef VERBOSE_BLITTER_LOGGING
4295 printf(" [%08X%08X]%s", (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF), (winhibit ? "[X]" : ""));
4296 printf(" (icount=%04X, inc=%u)\n", icount, (uint16)inc);
4297 printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4298 printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4306 // OK, here's the big insight: When NOT in GOURZ mode, srcz1 & 2 function EXACTLY the same way that
4307 // srcd1 & 2 work--there's an implicit shift from srcz1 to srcz2 whenever srcz1 is read.
4308 // OTHERWISE, srcz1 is the integer for the computed Z and srcz2 is the fractional part.
4309 // Writes to srcz1 & 2 follow the same pattern as the other 64-bit registers--low 32 at the low address,
4310 // high 32 at the high address (little endian!).
4311 // NOTE: GOURZ is still not properly supported. Check patd/patf handling...
4312 // Phrase mode start/end masks are not properly supported either...
4313 #ifdef VERBOSE_BLITTER_LOGGING
4316 printf(" Entering DZWRITE state...");
4317 printf(" Dest Z write address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
4318 (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4322 //This is not correct... !!! FIX !!!
4323 //Should be OK now... We'll see...
4324 //Nope. Having the same starstep write problems in phrase mode as we had with pixels... !!! FIX !!!
4325 //This is not causing the problem in Hover Strike... :-/
4326 //The problem was with the SREADX not shifting. Still problems with Z comparisons & other text in pregame screen...
4331 JaguarWriteLong(address + 0, srcz >> 32, BLITTER);
4332 JaguarWriteLong(address + 4, srcz & 0xFFFFFFFF, BLITTER);
4337 JaguarWriteWord(address, srcz & 0x0000FFFF, BLITTER);
4340 #ifdef VERBOSE_BLITTER_LOGGING
4343 // printf(" [%08X%08X]\n", (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4345 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4346 printf(" [dstart=? dend=? pwidth=? srcshift=%X]", srcshift);
4347 printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4354 This is because the address generator was using only 15 bits of the X when it should have
4357 There's a slight problem here: The X pointer isn't wrapping like it should when it hits
4358 the edge of the window... Notice how the X isn't reset at the edge of the window:
4360 Blit! (CMD = 00010000)
4363 a1_base = 000E8008, a2_base = 0001FA68
4364 a1_x = 0000, a1_y = 0000, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0000, a2_y = 0000
4365 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4366 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4367 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4368 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4369 a1_pixsize = 5, a2_pixsize = 5
4370 srcd=7717771777177717 dstd=0000000000000000 patd=7730773077307730 iinc=00000000
4371 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4373 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4374 Entering INNER state...
4375 Entering DWRITE state... Dest write address/pix address: 000E8008/0 [7730773077307730] (icount=009E, inc=2)
4376 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4377 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4378 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4379 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4380 Entering DWRITE state... Dest write address/pix address: 000E8018/0 [7730773077307730] (icount=009C, inc=2)
4381 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4382 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4383 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4384 Entering A1_ADD state [a1_x=0002, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4388 Entering A1_ADD state [a1_x=009C, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4389 Entering DWRITE state... Dest write address/pix address: 000E84F8/0 [7730773077307730] (icount=0000, inc=2)
4390 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4391 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4392 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4393 Entering A1_ADD state [a1_x=009E, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4394 Entering IDLE_INNER state...
4396 Leaving INNER state... (ocount=0104)
4397 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4399 Entering INNER state...
4400 Entering DWRITE state... Dest write address/pix address: 000E8508/0 [7730773077307730] (icount=009E, inc=2)
4401 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4402 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4403 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4404 Entering A1_ADD state [a1_x=00A0, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4405 Entering DWRITE state... Dest write address/pix address: 000E8518/0 [7730773077307730] (icount=009C, inc=2)
4406 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4407 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4408 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4409 Entering A1_ADD state [a1_x=00A2, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4415 #ifdef VERBOSE_BLITTER_LOGGING
4418 //printf(" Entering A1_ADD state [addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
4419 printf(" Entering A1_ADD state [a1_x=%04X, a1_y=%04X, addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", a1_x, a1_y, addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
4423 int16 adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4424 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4425 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4426 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4427 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4429 #if 0//def VERBOSE_BLITTER_LOGGING
4432 printf(" [adda_x=%d, adda_y=%d, addb_x=%d, addb_y=%d, addq_x=%d, addq_y=%d]\n", adda_x, adda_y, addb_x, addb_y, addq_x, addq_y);
4436 //Now, write to what???
4437 //a2ptrld comes from a2ptrldi...
4438 //I believe it's addbsel that determines the writeback...
4439 // This is where atick[0] & [1] come in, in determining which part (fractional, integer)
4440 // gets written to...
4443 //Kludge, to get A1 channel increment working...
4446 a1_frac_x = addq_x, a1_frac_y = addq_y;
4448 addasel = 2, addbsel = 0, a1fracldi = false;
4449 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4450 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4451 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4452 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4454 a1_x = addq_x, a1_y = addq_y;
4457 a1_x = addq_x, a1_y = addq_y;
4462 #ifdef VERBOSE_BLITTER_LOGGING
4465 //printf(" Entering A2_ADD state [addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
4466 printf(" Entering A2_ADD state [a2_x=%04X, a2_y=%04X, addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", a2_x, a2_y, addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
4470 //void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
4471 // int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
4472 // int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
4473 // bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
4474 //void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
4475 // int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
4476 //void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
4477 // int16 adda_x, int16 adda_y, int16 addb_x, int16 addb_y, uint8 modx, bool suba_x, bool suba_y)
4478 //void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
4479 int16 adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4480 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4481 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4482 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4483 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4485 #if 0//def VERBOSE_BLITTER_LOGGING
4488 printf(" [adda_x=%d, adda_y=%d, addb_x=%d, addb_y=%d, addq_x=%d, addq_y=%d]\n", adda_x, adda_y, addb_x, addb_y, addq_x, addq_y);
4492 //Now, write to what???
4493 //a2ptrld comes from a2ptrldi...
4494 //I believe it's addbsel that determines the writeback...
4500 Flags: SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
4502 a1_base = 0015B000, a2_base = 0014B000
4503 a1_x = 0000, a1_y = 0000, a1_frac_x = 8000, a1_frac_y = 8000, a2_x = 001F, a2_y = 0038
4504 a1_step_x = FFFFFFC0, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 2AAA, a2_step_x = FFFFFFC0, a2_step_y = 0001
4505 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4506 a1_win_x = 0040, a1_win_y = 0040, a2_mask_x = 0000, a2_mask_y = 0000
4507 a2_mask=F a1add=+inc/+0 a2add=+1/+0
4508 a1_pixsize = 4, a2_pixsize = 4
4509 srcd=FF00FF00FF00FF00 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4510 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, col=0
4512 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4513 Entering INNER state...
4514 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4515 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4516 Entering DWRITE state...
4517 Dest write address/pix address: 0014E83E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003F, inc=1)
4518 Entering A2_ADD state [a2_x=001F, a2_y=0038, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4519 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4520 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4521 Entering DWRITE state...
4522 Dest write address/pix address: 0014E942/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003E, inc=1)
4523 Entering A2_ADD state [a2_x=0021, a2_y=0039, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4524 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4525 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4526 Entering DWRITE state...
4527 Dest write address/pix address: 0014EA46/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003D, inc=1)
4528 Entering A2_ADD state [a2_x=0023, a2_y=003A, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4529 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4530 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4531 Entering DWRITE state...
4532 Dest write address/pix address: 0014EB4A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003C, inc=1)
4533 Entering A2_ADD state [a2_x=0025, a2_y=003B, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4535 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4536 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4537 Entering DWRITE state...
4538 Dest write address/pix address: 0015283A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=0000, inc=1)
4539 Entering A2_ADD state [a2_x=009D, a2_y=0077, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4540 Entering IDLE_INNER state...
4541 Leaving INNER state... (ocount=0036)
4542 [in=F a1f=T a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4543 Entering A1FUPDATE state...
4544 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4545 Entering A1UPDATE state... (-32768/-32768 -> 32704/-32767)
4546 [in=F a1f=F a1=F zf=F z=F a2=T iif=F iii=F izf=F izi=F]
4547 Entering A2UPDATE state... (159/120 -> 95/121)
4548 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4549 Entering INNER state...
4552 #ifdef VERBOSE_BLITTER_LOGGING
4555 printf(" Leaving INNER state...");
4560 // The outer counter is updated here as well on the clock cycle...
4562 /* the inner loop is started whenever another state is about to
4563 cause the inner state to go active */
4564 //Instart := ND7 (instart, innert[0], innert[2..7]);
4566 //Actually, it's done only when inner gets asserted without the 2nd line of conditions
4567 //(inner AND !indone)
4569 //Since we don't get here until the inner loop is finished (indone = true) we can get
4570 //away with doing it here...!
4575 #ifdef VERBOSE_BLITTER_LOGGING
4578 printf(" (ocount=%04X)\n", ocount);
4586 #ifdef VERBOSE_BLITTER_LOGGING
4589 printf(" Entering A1FUPDATE state...\n");
4593 uint32 a1_frac_xt = (uint32)a1_frac_x + (uint32)a1_stepf_x;
4594 uint32 a1_frac_yt = (uint32)a1_frac_y + (uint32)a1_stepf_y;
4595 a1FracCInX = a1_frac_xt >> 16;
4596 a1FracCInY = a1_frac_yt >> 16;
4597 a1_frac_x = (uint16)(a1_frac_xt & 0xFFFF);
4598 a1_frac_y = (uint16)(a1_frac_yt & 0xFFFF);
4603 #ifdef VERBOSE_BLITTER_LOGGING
4606 printf(" Entering A1UPDATE state... (%d/%d -> ", a1_x, a1_y);
4610 a1_x += a1_step_x + a1FracCInX;
4611 a1_y += a1_step_y + a1FracCInY;
4612 #ifdef VERBOSE_BLITTER_LOGGING
4615 printf("%d/%d)\n", a1_x, a1_y);
4623 #ifdef VERBOSE_BLITTER_LOGGING
4626 printf(" Entering A2UPDATE state... (%d/%d -> ", a2_x, a2_y);
4632 #ifdef VERBOSE_BLITTER_LOGGING
4635 printf("%d/%d)\n", a2_x, a2_y);
4642 // We never get here! !!! FIX !!!
4644 #ifdef VERBOSE_BLITTER_LOGGING
4647 printf("Done!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
4648 GET16(blitter_ram, A1_PIXEL + 2),
4649 GET16(blitter_ram, A1_PIXEL + 0),
4650 GET16(blitter_ram, A1_FPIXEL + 2),
4651 GET16(blitter_ram, A1_FPIXEL + 0),
4652 GET16(blitter_ram, A2_PIXEL + 2),
4653 GET16(blitter_ram, A2_PIXEL + 0));
4658 // Write values back to registers (in real blitter, these are continuously updated)
4659 SET16(blitter_ram, A1_PIXEL + 2, a1_x);
4660 SET16(blitter_ram, A1_PIXEL + 0, a1_y);
4661 SET16(blitter_ram, A1_FPIXEL + 2, a1_frac_x);
4662 SET16(blitter_ram, A1_FPIXEL + 0, a1_frac_y);
4663 SET16(blitter_ram, A2_PIXEL + 2, a2_x);
4664 SET16(blitter_ram, A2_PIXEL + 0, a2_y);
4666 #ifdef VERBOSE_BLITTER_LOGGING
4669 printf("Writeback!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
4670 GET16(blitter_ram, A1_PIXEL + 2),
4671 GET16(blitter_ram, A1_PIXEL + 0),
4672 GET16(blitter_ram, A1_FPIXEL + 2),
4673 GET16(blitter_ram, A1_FPIXEL + 0),
4674 GET16(blitter_ram, A2_PIXEL + 2),
4675 GET16(blitter_ram, A2_PIXEL + 0));
4682 int16 a1_x = (int16)GET16(blitter_ram, A1_PIXEL + 2);
4683 int16 a1_y = (int16)GET16(blitter_ram, A1_PIXEL + 0);
4684 uint16 a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
4685 uint16 a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
4686 int16 a2_x = (int16)GET16(blitter_ram, A2_PIXEL + 2);
4687 int16 a2_y = (int16)GET16(blitter_ram, A2_PIXEL + 0);
4689 Seems that the ending a1_x should be written between blits, but it doesn't seem to be...
4691 Blit! (CMD = 01800000)
4694 a1_base = 00050000, a2_base = 00070000
4695 a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
4696 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4697 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4698 a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
4699 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4700 a1_pixsize = 4, a2_pixsize = 3
4701 srcd=DEDEDEDEDEDEDEDE dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4702 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4705 Blit! (CMD = 01800000)
4708 a1_base = 00050000, a2_base = 00070000
4709 a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
4710 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4711 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4712 a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
4713 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4714 a1_pixsize = 4, a2_pixsize = 3
4715 srcd=D6D6D6D6D6D6D6D6 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4716 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4722 // Various pieces of the blitter puzzle are teased out here...
4728 INT24/ address // byte address
4729 pixa[0..2] // bit part of address, un-pipe-lined
4745 apipe // load address pipe-line latch
4746 clk // co-processor clock
4747 gena2 // generate A2 as opposed to A1
4748 zaddr // generate Z address
4752 void ADDRGEN(uint32 &address, uint32 &pixa, bool gena2, bool zaddr,
4753 uint16 a1_x, uint16 a1_y, uint32 a1_base, uint8 a1_pitch, uint8 a1_pixsize, uint8 a1_width, uint8 a1_zoffset,
4754 uint16 a2_x, uint16 a2_y, uint32 a2_base, uint8 a2_pitch, uint8 a2_pixsize, uint8 a2_width, uint8 a2_zoffset)
4756 // uint16 x = (gena2 ? a2_x : a1_x) & 0x7FFF;
4757 uint16 x = (gena2 ? a2_x : a1_x) & 0xFFFF; // Actually uses all 16 bits to generate address...!
4758 uint16 y = (gena2 ? a2_y : a1_y) & 0x0FFF;
4759 uint8 width = (gena2 ? a2_width : a1_width);
4760 uint8 pixsize = (gena2 ? a2_pixsize : a1_pixsize);
4761 uint8 pitch = (gena2 ? a2_pitch : a1_pitch);
4762 uint32 base = (gena2 ? a2_base : a1_base) >> 3;//Only upper 21 bits are passed around the bus? Seems like it...
4763 uint8 zoffset = (gena2 ? a2_zoffset : a1_zoffset);
4765 uint32 ytm = ((uint32)y << 2) + (width & 0x02 ? (uint32)y << 1 : 0) + (width & 0x01 ? (uint32)y : 0);
4767 uint32 ya = (ytm << (width >> 2)) >> 2;
4771 /*uint32*/ pixa = pa << pixsize;
4773 uint8 pt = ((pitch & 0x01) && !(pitch & 0x02) ? 0x01 : 0x00)
4774 | (!(pitch & 0x01) && (pitch & 0x02) ? 0x02 : 0x00);
4775 // uint32 phradr = pixa << pt;
4776 uint32 phradr = (pixa >> 6) << pt;
4777 uint32 shup = (pitch == 0x03 ? (pixa >> 6) : 0);
4779 uint8 za = (zaddr ? zoffset : 0) & 0x03;
4780 // uint32 addr = za + (phradr & 0x07) + (shup << 1) + base;
4781 uint32 addr = za + phradr + (shup << 1) + base;
4782 /*uint32*/ address = ((pixa & 0x38) >> 3) | ((addr & 0x1FFFFF) << 3);
4783 #if 0//def VERBOSE_BLITTER_LOGGING
4786 printf(" [gena2=%s, x=%04X, y=%04X, w=%1X, pxsz=%1X, ptch=%1X, b=%08X, zoff=%1X]\n", (gena2 ? "T" : "F"), x, y, width, pixsize, pitch, base, zoffset);
4787 printf(" [ytm=%X, ya=%X, pa=%X, pixa=%X, pt=%X, phradr=%X, shup=%X, za=%X, addr=%X, address=%X]\n", ytm, ya, pa, pixa, pt, phradr, shup, za, addr, address);
4793 Entering INNER state...
4794 [gena2=T, x=0002, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4795 [ytm=0, ya=0, pa=2, pixa=20, pt=0, phradr=0, shup=0, za=0, addr=12BA, address=95D4]
4796 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4797 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
4798 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4799 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4800 [ytm=0, ya=0, pa=4, pixa=40, pt=0, phradr=1, shup=0, za=0, addr=12BB, address=95D8]
4801 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4802 Source read address/pix address: 000095D8/0 [0054003800009814]
4803 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4804 [gena2=F, x=0000, y=0000, w=20, pxsz=4, ptch=0, b=00006E52, zoff=0]
4805 [ytm=0, ya=0, pa=0, pixa=0, pt=0, phradr=0, shup=0, za=0, addr=6E52, address=37290]
4806 Entering DWRITE state...
4807 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
4808 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4809 [gena2=T, x=0008, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4810 [ytm=0, ya=0, pa=8, pixa=80, pt=0, phradr=2, shup=0, za=0, addr=12BC, address=95E0]
4814 Entering SREAD state...
4815 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4816 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10AC, address=8560]
4817 Source read address/pix address: 00008560/0 [8C27981B327E00F0]
4819 2nd pass (still wrong):
4820 Entering SREAD state...
4821 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4822 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10EC, address=8760]
4823 Source read address/pix address: 00008760/0 [00E06DC04581880C]
4826 Entering SREAD state...
4827 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4828 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=1, shup=0, za=0, addr=10AD, address=8568]
4829 Source read address/pix address: 00008568/0 [6267981A327C00F0]
4831 OK, now we're back into incorrect (or is it?):
4832 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4833 Source extra read address/pix address: 000095D4/0 [0000 001C 0054 0038]
4834 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4835 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4836 Source read address/pix address: 000095D8/0 [0054 0038 0000 9814]
4837 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4838 I think this may be correct...!
4843 // source and destination address update conditions
4845 Sraat0 := AN2 (sraat[0], sreadxi, srcenz\);
4846 Sraat1 := AN2 (sraat[1], sreadi, srcenz\);
4847 Srca_addi := OR4 (srca_addi, szreadxi, szreadi, sraat[0..1]);
4848 Srca_add := FD1Q (srca_add, srca_addi, clk);
4850 Dstaat := AN2 (dstaat, dwritei, dstwrz\);
4851 Dsta_addi := OR2 (dsta_addi, dzwritei, dstaat);
4852 // Dsta_add := FD1Q (dsta_add, dsta_addi, clk);
4854 // source and destination address generate conditions
4856 Gensrc := OR4 (gensrc, sreadxi, szreadxi, sreadi, szreadi);
4857 Gendst := OR4 (gendst, dreadi, dzreadi, dwritei, dzwritei);
4858 Dsta2\ := INV1 (dsta2\, dsta2);
4859 Gena2t0 := NAN2 (gena2t[0], gensrc, dsta2\);
4860 Gena2t1 := NAN2 (gena2t[1], gendst, dsta2);
4861 Gena2i := NAN2 (gena2i, gena2t[0..1]);
4862 Gena2 := FD1QU (gena2, gena2i, clk);
4864 Zaddr := OR4 (zaddr, szreadx, szread, dzread, dzwrite);
4869 // Basically, the above translates to:
4870 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
4872 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
4874 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
4875 bool gendst = dreadi || szreadi || dwritei || dzwritei;
4876 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
4878 bool zaddr = szreadx || szread || dzread || dzwrite;
4882 // source data reads
4884 Srcdpset\ := NAN2 (srcdpset\, readreq, sread);
4885 Srcdpt1 := NAN2 (srcdpt[1], srcdpend, srcdack\);
4886 Srcdpt2 := NAN2 (srcdpt[2], srcdpset\, srcdpt[1]);
4887 Srcdpend := FD2Q (srcdpend, srcdpt[2], clk, reset\);
4889 Srcdxpset\ := NAN2 (srcdxpset\, readreq, sreadx);
4890 Srcdxpt1 := NAN2 (srcdxpt[1], srcdxpend, srcdxack\);
4891 Srcdxpt2 := NAN2 (srcdxpt[2], srcdxpset\, srcdxpt[1]);
4892 Srcdxpend := FD2Q (srcdxpend, srcdxpt[2], clk, reset\);
4894 Sdpend := OR2 (sdpend, srcdxpend, srcdpend);
4895 Srcdreadt := AN2 (srcdreadt, sdpend, read_ack);
4897 //2/9/92 - enhancement?
4898 //Load srcdread on the next tick as well to modify it in srcshade
4900 Srcdreadd := FD1Q (srcdreadd, srcdreadt, clk);
4901 Srcdread := AOR1 (srcdread, srcshade, srcdreadd, srcdreadt);
4905 Srczpset\ := NAN2 (srczpset\, readreq, szread);
4906 Srczpt1 := NAN2 (srczpt[1], srczpend, srczack\);
4907 Srczpt2 := NAN2 (srczpt[2], srczpset\, srczpt[1]);
4908 Srczpend := FD2Q (srczpend, srczpt[2], clk, reset\);
4910 Srczxpset\ := NAN2 (srczxpset\, readreq, szreadx);
4911 Srczxpt1 := NAN2 (srczxpt[1], srczxpend, srczxack\);
4912 Srczxpt2 := NAN2 (srczxpt[2], srczxpset\, srczxpt[1]);
4913 Srczxpend := FD2Q (srczxpend, srczxpt[2], clk, reset\);
4915 Szpend := OR2 (szpend, srczpend, srczxpend);
4916 Srczread := AN2 (srczread, szpend, read_ack);
4918 // destination data reads
4920 Dstdpset\ := NAN2 (dstdpset\, readreq, dread);
4921 Dstdpt0 := NAN2 (dstdpt[0], dstdpend, dstdack\);
4922 Dstdpt1 := NAN2 (dstdpt[1], dstdpset\, dstdpt[0]);
4923 Dstdpend := FD2Q (dstdpend, dstdpt[1], clk, reset\);
4924 Dstdread := AN2 (dstdread, dstdpend, read_ack);
4926 // destination zed reads
4928 Dstzpset\ := NAN2 (dstzpset\, readreq, dzread);
4929 Dstzpt0 := NAN2 (dstzpt[0], dstzpend, dstzack\);
4930 Dstzpt1 := NAN2 (dstzpt[1], dstzpset\, dstzpt[0]);
4931 Dstzpend := FD2Q (dstzpend, dstzpt[1], clk, reset\);
4932 Dstzread := AN2 (dstzread, dstzpend, read_ack);
4937 // Basically, the above translates to:
4938 bool srcdpend = (readreq && sread) || (srcdpend && !srcdack);
4939 bool srcdxpend = (readreq && sreadx) || (srcdxpend && !srcdxack);
4940 bool sdpend = srcxpend || srcdpend;
4941 bool srcdread = ((sdpend && read_ack) && srcshade) || (sdpend && read_ack);//the latter term is lookahead
4945 ////////////////////////////////////////////////////////////////////////////////////////////
4946 ////////////////////////////////////////////////////////////////////////////////////////////
4947 // Here's an important bit: The source data adder logic. Need to track down the inputs!!! //
4948 ////////////////////////////////////////////////////////////////////////////////////////////
4949 ////////////////////////////////////////////////////////////////////////////////////////////
4956 daddasel[0..2] // data adder input A selection
4961 initcin[0..3] // carry into the adders from the initializers
4962 initinc[0..63] // the initialisation increment
4963 initpix[0..15] // Data initialiser pixel value
4975 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
4976 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
4977 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
4978 uint32 zinc, uint32 zstep)
4980 uint32 initpix2 = ((uint32)initpix << 16) | initpix;
4981 uint32 addalo[8], addahi[8];
4982 addalo[0] = dstd & 0xFFFFFFFF;
4983 addalo[1] = initpix2;
4986 addalo[4] = srcd & 0xFFFFFFFF;
4987 addalo[5] = patd & 0xFFFFFFFF;
4988 addalo[6] = srcz1 & 0xFFFFFFFF;
4989 addalo[7] = srcz2 & 0xFFFFFFFF;
4990 addahi[0] = dstd >> 32;
4991 addahi[1] = initpix2;
4994 addahi[4] = srcd >> 32;
4995 addahi[5] = patd >> 32;
4996 addahi[6] = srcz1 >> 32;
4997 addahi[7] = srcz2 >> 32;
4999 adda[0] = addalo[daddasel] & 0xFFFF;
5000 adda[1] = addalo[daddasel] >> 16;
5001 adda[2] = addahi[daddasel] & 0xFFFF;
5002 adda[3] = addahi[daddasel] >> 16;
5005 wordmux[0] = iinc & 0xFFFF;
5006 wordmux[1] = iinc >> 16;
5007 wordmux[2] = zinc & 0xFFFF;
5008 wordmux[3] = zinc >> 16;;
5009 wordmux[4] = istep & 0xFFFF;
5010 wordmux[5] = istep >> 16;;
5011 wordmux[6] = zstep & 0xFFFF;
5012 wordmux[7] = zstep >> 16;;
5013 uint16 word = wordmux[((daddbsel & 0x08) >> 1) | (daddbsel & 0x03)];
5015 bool dbsel2 = daddbsel & 0x04;
5016 bool iincsel = (daddbsel & 0x01) && !(daddbsel & 0x04);
5018 if (!dbsel2 && !iincsel)
5019 addb[0] = srcd & 0xFFFF,
5020 addb[1] = (srcd >> 16) & 0xFFFF,
5021 addb[2] = (srcd >> 32) & 0xFFFF,
5022 addb[3] = (srcd >> 48) & 0xFFFF;
5023 else if (dbsel2 && !iincsel)
5024 addb[0] = addb[1] = addb[2] = addb[3] = word;
5025 else if (!dbsel2 && iincsel)
5026 addb[0] = initinc & 0xFFFF,
5027 addb[1] = (initinc >> 16) & 0xFFFF,
5028 addb[2] = (initinc >> 32) & 0xFFFF,
5029 addb[3] = (initinc >> 48) & 0xFFFF;
5031 addb[0] = addb[1] = addb[2] = addb[3] = 0;
5033 uint8 cinsel = (daddmode >= 1 && daddmode <= 4 ? 1 : 0);
5035 static uint8 co[4];//These are preserved between calls...
5038 for(int i=0; i<4; i++)
5039 cin[i] = initcin[i] | (co[i] & cinsel);
5041 bool eightbit = daddmode & 0x02;
5042 bool sat = daddmode & 0x03;
5043 bool hicinh = ((daddmode & 0x03) == 0x03);
5045 //Note that the carry out is saved between calls to this function...
5046 for(int i=0; i<4; i++)
5047 ADD16SAT(addq[i], co[i], adda[i], addb[i], cin[i], sat, eightbit, hicinh);
5063 void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh)
5067 printf("--> [sat=%s 8b=%s hicinh=%s] %04X + %04X (+ %u) = ", (sat ? "T" : "F"), (eightbit ? "T" : "F"), (hicinh ? "T" : "F"), a, b, cin);
5071 uint32 qt = (a & 0xFF) + (b & 0xFF) + cin;
5072 carry[0] = (qt & 0x0100 ? 1 : 0);
5073 uint16 q = qt & 0x00FF;
5074 carry[1] = (carry[0] && !eightbit ? carry[0] : 0);
5075 qt = (a & 0x0F00) + (b & 0x0F00) + (carry[1] << 8);
5076 carry[2] = (qt & 0x1000 ? 1 : 0);
5078 carry[3] = (carry[2] && !hicinh ? carry[2] : 0);
5079 qt = (a & 0xF000) + (b & 0xF000) + (carry[3] << 12);
5080 co = (qt & 0x10000 ? 1 : 0);
5083 uint8 btop = (eightbit ? (b & 0x0080) >> 7 : (b & 0x8000) >> 15);
5084 uint8 ctop = (eightbit ? carry[0] : co);
5086 bool saturate = sat && (btop ^ ctop);
5087 bool hisaturate = saturate && !eightbit;
5090 printf("bt=%u ct=%u s=%u hs=%u] ", btop, ctop, saturate, hisaturate);
5094 r = (saturate ? (ctop ? 0x00FF : 0x0000) : q & 0x00FF);
5095 r |= (hisaturate ? (ctop ? 0xFF00 : 0x0000) : q & 0xFF00);
5098 printf("%04X (co=%u)\n", r, co);
5103 /** ADDAMUX - Address adder input A selection *******************
5105 This module generates the data loaded into the address adder input A. This is
5106 the update value, and can be one of four registers : A1 step, A2 step, A1
5107 increment and A1 fraction. It can complement these values to perform
5108 subtraction, and it can generate constants to increment / decrement the window
5111 addasel[0..2] select the register to add
5113 000 A1 step integer part
5114 001 A1 step fraction part
5115 010 A1 increment integer part
5116 011 A1 increment fraction part
5119 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all zeroes when
5122 addareg selects register value to be added as opposed to constant
5125 suba_x, suba_y complement the X and Y values
5151 void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
5152 int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
5153 int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
5154 bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
5157 /*INT16/ addac_x, addac_y, addar_x, addar_y, addart_x, addart_y,
5158 INT16/ addas_x, addas_y, suba_x16, suba_y16
5162 Zero := TIE0 (zero);*/
5164 /* Multiplex the register terms */
5166 /*Addaselb[0-2] := BUF8 (addaselb[0-2], addasel[0-2]);
5167 Addart_x := MX4 (addart_x, a1_step_x, a1_stepf_x, a1_inc_x, a1_incf_x, addaselb[0..1]);
5168 Addar_x := MX2 (addar_x, addart_x, a2_step_x, addaselb[2]);
5169 Addart_y := MX4 (addart_y, a1_step_y, a1_stepf_y, a1_inc_y, a1_incf_y, addaselb[0..1]);
5170 Addar_y := MX2 (addar_y, addart_y, a2_step_y, addaselb[2]);*/
5172 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5173 int16 xterm[4], yterm[4];
5174 xterm[0] = a1_step_x, xterm[1] = a1_stepf_x, xterm[2] = a1_inc_x, xterm[3] = a1_incf_x;
5175 yterm[0] = a1_step_y, yterm[1] = a1_stepf_y, yterm[2] = a1_inc_y, yterm[3] = a1_incf_y;
5176 int16 addar_x = (addasel & 0x04 ? a2_step_x : xterm[addasel & 0x03]);
5177 int16 addar_y = (addasel & 0x04 ? a2_step_y : yterm[addasel & 0x03]);
5178 //////////////////////////////////////////////////////////////////////////////////////
5180 /* Generate a constant value - this is a power of 2 in the range
5181 0-64, or zero. The control bits are adda_xconst[0..2], when they
5182 are all 1 the result is 0.
5183 Constants for Y can only be 0 or 1 */
5185 /*Addac_xlo := D38H (addac_x[0..6], unused[0], adda_xconst[0..2]);
5186 Unused[0] := DUMMY (unused[0]);
5188 Addac_x := JOIN (addac_x, addac_x[0..6], zero, zero, zero, zero, zero, zero, zero, zero, zero);
5189 Addac_y := JOIN (addac_y, adda_yconst, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero,
5190 zero, zero, zero, zero, zero);*/
5191 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5192 int16 addac_x = (adda_xconst == 0x07 ? 0 : 1 << adda_xconst);
5193 int16 addac_y = (adda_yconst ? 0x01 : 0);
5194 //////////////////////////////////////////////////////////////////////////////////////
5196 /* Select between constant value and register value */
5198 /*Addas_x := MX2 (addas_x, addac_x, addar_x, addareg);
5199 Addas_y := MX2 (addas_y, addac_y, addar_y, addareg);*/
5200 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5201 int16 addas_x = (addareg ? addar_x : addac_x);
5202 int16 addas_y = (addareg ? addar_y : addac_y);
5203 //////////////////////////////////////////////////////////////////////////////////////
5205 /* Complement these values (complement flag gives adder carry in)*/
5207 /*Suba_x16 := JOIN (suba_x16, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x,
5208 suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x);
5209 Suba_y16 := JOIN (suba_y16, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y,
5210 suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y);
5211 Adda_x := EO (adda_x, suba_x16, addas_x);
5212 Adda_y := EO (adda_y, suba_y16, addas_y);*/
5213 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5214 adda_x = addas_x ^ (suba_x ? 0xFFFF : 0x0000);
5215 adda_y = addas_y ^ (suba_y ? 0xFFFF : 0x0000);
5216 //////////////////////////////////////////////////////////////////////////////////////
5221 /** ADDBMUX - Address adder input B selection *******************
5223 This module selects the register to be updated by the address
5224 adder. This can be one of three registers, the A1 and A2
5225 pointers, or the A1 fractional part. It can also be zero, so that the step
5226 registers load directly into the pointers.
5241 INT16/ zero16 :LOCAL;
5243 void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
5244 int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
5247 /*Zero := TIE0 (zero);
5248 Zero16 := JOIN (zero16, zero, zero, zero, zero, zero, zero, zero,
5249 zero, zero, zero, zero, zero, zero, zero, zero, zero);
5250 Addbselb[0-1] := BUF8 (addbselb[0-1], addbsel[0-1]);
5251 Addb_x := MX4 (addb_x, a1_x, a2_x, a1_frac_x, zero16, addbselb[0..1]);
5252 Addb_y := MX4 (addb_y, a1_y, a2_y, a1_frac_y, zero16, addbselb[0..1]);*/
5253 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5254 int16 xterm[4], yterm[4];
5255 xterm[0] = a1_x, xterm[1] = a2_x, xterm[2] = a1_frac_x, xterm[3] = 0;
5256 yterm[0] = a1_y, yterm[1] = a2_y, yterm[2] = a1_frac_y, yterm[3] = 0;
5257 addb_x = xterm[addbsel & 0x03];
5258 addb_y = yterm[addbsel & 0x03];
5259 //////////////////////////////////////////////////////////////////////////////////////
5264 /** DATAMUX - Address local data bus selection ******************
5266 Select between the adder output and the input data bus
5279 INT16/ gpu_lo, gpu_hi
5282 void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
5284 /*Gpu_lo := JOIN (gpu_lo, gpu_din{0..15});
5285 Gpu_hi := JOIN (gpu_hi, gpu_din{16..31});
5287 Addqselb := BUF8 (addqselb, addqsel);
5288 Data_x := MX2 (data_x, gpu_lo, addq_x, addqselb);
5289 Data_y := MX2 (data_y, gpu_hi, addq_y, addqselb);*/
5290 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5291 data_x = (addqsel ? addq_x : (int16)(gpu_din & 0xFFFF));
5292 data_y = (addqsel ? addq_y : (int16)(gpu_din >> 16));
5293 //////////////////////////////////////////////////////////////////////////////////////
5298 /******************************************************************
5302 Blitter Address Adder
5303 ---------------------
5304 The blitter address adder is a pair of sixteen bit adders, one
5305 each for X and Y. The multiplexing of the input terms is
5306 performed elsewhere, but this adder can also perform modulo
5307 arithmetic to align X-addresses onto phrase boundaries.
5309 modx[0..2] take values
5316 ******************************************************************/
5318 /*IMPORT duplo, tosh;
5324 a1fracldi // propagate address adder carry
5329 clk[0] // co-processor clock
5337 Zero := TIE0 (zero);*/
5338 void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
5339 uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y)
5342 /* Perform the addition */
5344 /*Adder_x := ADD16 (addqt_x[0..15], co_x, adda_x{0..15}, addb_x{0..15}, ci_x);
5345 Adder_y := ADD16 (addq_y[0..15], co_y, adda_y{0..15}, addb_y{0..15}, ci_y);*/
5347 /* latch carry and propagate if required */
5349 /*Cxt0 := AN2 (cxt[0], co_x, a1fracldi);
5350 Cxt1 := FD1Q (cxt[1], cxt[0], clk[0]);
5351 Ci_x := EO (ci_x, cxt[1], suba_x);
5353 yt0 := AN2 (cyt[0], co_y, a1fracldi);
5354 Cyt1 := FD1Q (cyt[1], cyt[0], clk[0]);
5355 Ci_y := EO (ci_y, cyt[1], suba_y);*/
5357 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5358 //I'm sure the following will generate a bunch of warnings, but will have to do for now.
5359 static uint16 co_x = 0, co_y = 0; // Carry out has to propogate between function calls...
5360 uint16 ci_x = co_x ^ (suba_x ? 1 : 0);
5361 uint16 ci_y = co_y ^ (suba_y ? 1 : 0);
5362 uint32 addqt_x = adda_x + addb_x + ci_x;
5363 uint32 addqt_y = adda_y + addb_y + ci_y;
5364 co_x = ((addqt_x & 0x10000) && a1fracldi ? 1 : 0);
5365 co_y = ((addqt_y & 0x10000) && a1fracldi ? 1 : 0);
5366 //////////////////////////////////////////////////////////////////////////////////////
5368 /* Mask low bits of X to 0 if required */
5370 /*Masksel := D38H (unused[0], masksel[0..4], maskbit[5], unused[1], modx[0..2]);
5372 Maskbit[0-4] := OR2 (maskbit[0-4], masksel[0-4], maskbit[1-5]);
5374 Mask[0-5] := MX2 (addq_x[0-5], addqt_x[0-5], zero, maskbit[0-5]);
5376 Addq_x := JOIN (addq_x, addq_x[0..5], addqt_x[6..15]);
5377 Addq_y := JOIN (addq_y, addq_y[0..15]);*/
5379 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5380 int16 mask[8] = { 0xFFFF, 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, 0xFFE0, 0xFFC0, 0x0000 };
5381 addq_x = addqt_x & mask[modx];
5382 addq_y = addqt_y & 0xFFFF;
5383 //////////////////////////////////////////////////////////////////////////////////////
5385 //Unused[0-1] := DUMMY (unused[0-1]);
5392 wdata[0..63] // co-processor write data bus
5394 dcomp[0..7] // data byte equal flags
5395 srcd[0..7] // bits to use for bit to byte expansion
5396 zcomp[0..3] // output from Z comparators
5398 a1_x[0..1] // low two bits of A1 X pointer
5399 big_pix // pixel organisation is big-endian
5400 blitter_active // blitter is active
5401 clk // co-processor clock
5402 cmpdst // compare dest rather than source
5403 colorld // load the pattern color fields
5404 daddasel[0..2] // data adder input A selection
5405 daddbsel[0..3] // data adder input B selection
5406 daddmode[0..2] // data adder mode
5407 daddq_sel // select adder output vs. GPU data
5408 data[0..63] // co-processor read data bus
5409 data_ena // enable write data
5410 data_sel[0..1] // select data to write
5411 dbinh\[0..7] // byte oriented changed data inhibits
5412 dend[0..5] // end of changed write data zone
5413 dpipe[0..1] // load computed data pipe-line latch
5414 dstart[0..5] // start of changed write data zone
5415 dstdld[0..1] // dest data load (two halves)
5416 dstzld[0..1] // dest zed load (two halves)
5417 ext_int // enable extended precision intensity calculations
5418 INT32/ gpu_din // GPU data bus
5419 iincld // I increment load
5420 iincldx // alternate I increment load
5421 init_if // initialise I fraction phase
5422 init_ii // initialise I integer phase
5423 init_zf // initialise Z fraction phase
5424 intld[0..3] // computed intensities load
5425 istepadd // intensity step integer add
5426 istepfadd // intensity step fraction add
5427 istepld // I step load
5428 istepdld // I step delta load
5429 lfu_func[0..3] // LFU function code
5430 patdadd // pattern data gouraud add
5431 patdld[0..1] // pattern data load (two halves)
5432 pdsel[0..1] // select pattern data type
5433 phrase_mode // phrase write mode
5434 reload // transfer contents of double buffers
5435 reset\ // system reset
5436 srcd1ld[0..1] // source register 1 load (two halves)
5437 srcdread // source data read load enable
5438 srczread // source zed read load enable
5439 srcshift[0..5] // source alignment shift
5440 srcz1ld[0..1] // source zed 1 load (two halves)
5441 srcz2add // zed fraction gouraud add
5442 srcz2ld[0..1] // source zed 2 load (two halves)
5443 textrgb // texture mapping in RGB mode
5444 txtd[0..63] // data from the texture unit
5445 zedld[0..3] // computed zeds load
5446 zincld // Z increment load
5447 zmode[0..2] // Z comparator mode
5448 zpipe[0..1] // load computed zed pipe-line latch
5449 zstepadd // zed step integer add
5450 zstepfadd // zed step fraction add
5451 zstepld // Z step load
5452 zstepdld // Z step delta load
5456 void DATA(uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
5457 bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
5458 uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 &patd, bool patdadd,
5459 bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
5460 bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize,
5461 uint64 &srcz, uint64 dstz, uint32 zinc)
5464 Stuff we absolutely *need* to have passed in/out:
5466 patdadd, dstd, srcd, patd, daddasel, daddbsel, daddmode, iinc, srcz1, srcz2, big_pix, phrase_mode, cmpdst
5468 changed patd (wdata I guess...) (Nope. We pass it back directly now...)
5471 // Source data registers
5473 /*Data_src := DATA_SRC (srcdlo, srcdhi, srcz[0..1], srczo[0..1], srczp[0..1], srcz1[0..1], srcz2[0..1], big_pix,
5474 clk, gpu_din, intld[0..3], local_data0, local_data1, srcd1ld[0..1], srcdread, srczread, srcshift[0..5],
5475 srcz1ld[0..1], srcz2add, srcz2ld[0..1], zedld[0..3], zpipe[0..1]);
5476 Srcd[0-7] := JOIN (srcd[0-7], srcdlo{0-7});
5477 Srcd[8-31] := JOIN (srcd[8-31], srcdlo{8-31});
5478 Srcd[32-63] := JOIN (srcd[32-63], srcdhi{0-31});*/
5480 // Destination data registers
5482 /*Data_dst := DATA_DST (dstd[0..63], dstz[0..1], clk, dstdld[0..1], dstzld[0..1], load_data[0..1]);
5483 Dstdlo := JOIN (dstdlo, dstd[0..31]);
5484 Dstdhi := JOIN (dstdhi, dstd[32..63]);*/
5486 // Pattern and Color data registers
5488 // Looks like this is simply another register file for the pattern data registers. No adding or anything funky
5489 // going on. Note that patd & patdv will output the same info.
5490 // Patdldl/h (patdld[0..1]) can select the local_data bus to overwrite the current pattern data...
5491 // Actually, it can be either patdld OR patdadd...!
5492 /*Data_pat := DATA_PAT (colord[0..15], int0dp[8..10], int1dp[8..10], int2dp[8..10], int3dp[8..10], mixsel[0..2],
5493 patd[0..63], patdv[0..1], clk, colorld, dpipe[0], ext_int, gpu_din, intld[0..3], local_data0, local_data1,
5494 patdadd, patdld[0..1], reload, reset\);
5495 Patdlo := JOIN (patdlo, patd[0..31]);
5496 Patdhi := JOIN (patdhi, patd[32..63]);*/
5498 // Multiplying data Mixer (NOT IN JAGUAR I)
5500 /*Datamix := DATAMIX (patdo[0..1], clk, colord[0..15], dpipe[1], dstd[0..63], int0dp[8..10], int1dp[8..10],
5501 int2dp[8..10], int3dp[8..10], mixsel[0..2], patd[0..63], pdsel[0..1], srcd[0..63], textrgb, txtd[0..63]);*/
5503 // Logic function unit
5505 /*Lfu := LFU (lfu[0..1], srcdlo, srcdhi, dstdlo, dstdhi, lfu_func[0..3]);*/
5506 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5507 uint64 funcmask[2] = { 0, 0xFFFFFFFFFFFFFFFFLL };
5508 uint64 func0 = funcmask[lfu_func & 0x01];
5509 uint64 func1 = funcmask[(lfu_func >> 1) & 0x01];
5510 uint64 func2 = funcmask[(lfu_func >> 2) & 0x01];
5511 uint64 func3 = funcmask[(lfu_func >> 3) & 0x01];
5512 uint64 lfu = (~srcd & ~dstd & func0) | (~srcd & dstd & func1) | (srcd & ~dstd & func2) | (srcd & dstd & func3);
5513 //////////////////////////////////////////////////////////////////////////////////////
5515 // Increment and Step Registers
5517 // Does it do anything without the step add lines? Check it!
5518 // No. This is pretty much just a register file without the Jaguar II lines...
5519 /*Inc_step := INC_STEP (iinc, istep[0..31], zinc, zstep[0..31], clk, ext_int, gpu_din, iincld, iincldx, istepadd,
5520 istepfadd, istepld, istepdld, reload, reset\, zincld, zstepadd, zstepfadd, zstepld, zstepdld);
5521 Istep := JOIN (istep, istep[0..31]);
5522 Zstep := JOIN (zstep, zstep[0..31]);*/
5524 // Pixel data comparator
5526 /*Datacomp := DATACOMP (dcomp[0..7], cmpdst, dstdlo, dstdhi, patdlo, patdhi, srcdlo, srcdhi);*/
5527 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5529 uint64 cmpd = patd ^ (cmpdst ? dstd : srcd);
5531 if ((cmpd & 0x00000000000000FFLL) == 0)
5533 if ((cmpd & 0x000000000000FF00LL) == 0)
5535 if ((cmpd & 0x0000000000FF0000LL) == 0)
5537 if ((cmpd & 0x00000000FF000000LL) == 0)
5539 if ((cmpd & 0x000000FF00000000LL) == 0)
5541 if ((cmpd & 0x0000FF0000000000LL) == 0)
5543 if ((cmpd & 0x00FF000000000000LL) == 0)
5545 if ((cmpd & 0xFF00000000000000LL) == 0)
5547 //////////////////////////////////////////////////////////////////////////////////////
5549 // Zed comparator for Z-buffer operations
5551 /*Zedcomp := ZEDCOMP (zcomp[0..3], srczp[0..1], dstz[0..1], zmode[0..2]);*/
5552 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5553 //srczp is srcz pipelined, also it goes through a source shift as well...
5554 /*The shift is basically like so (each piece is 16 bits long):
5557 srcz1lolo srcz1lohi srcz1hilo srcz1hihi srcrz2lolo srcz2lohi srcz2hilo
5559 with srcshift bits 4 & 5 selecting the start position
5561 //So... basically what we have here is:
5564 if ((((srcz & 0x000000000000FFFFLL) < (dstz & 0x000000000000FFFFLL)) && (zmode & 0x01))
5565 || (((srcz & 0x000000000000FFFFLL) == (dstz & 0x000000000000FFFFLL)) && (zmode & 0x02))
5566 || (((srcz & 0x000000000000FFFFLL) > (dstz & 0x000000000000FFFFLL)) && (zmode & 0x04)))
5569 if ((((srcz & 0x00000000FFFF0000LL) < (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x01))
5570 || (((srcz & 0x00000000FFFF0000LL) == (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x02))
5571 || (((srcz & 0x00000000FFFF0000LL) > (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x04)))
5574 if ((((srcz & 0x0000FFFF00000000LL) < (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x01))
5575 || (((srcz & 0x0000FFFF00000000LL) == (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x02))
5576 || (((srcz & 0x0000FFFF00000000LL) > (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x04)))
5579 if ((((srcz & 0xFFFF000000000000LL) < (dstz & 0xFFFF000000000000LL)) && (zmode & 0x01))
5580 || (((srcz & 0xFFFF000000000000LL) == (dstz & 0xFFFF000000000000LL)) && (zmode & 0x02))
5581 || (((srcz & 0xFFFF000000000000LL) > (dstz & 0xFFFF000000000000LL)) && (zmode & 0x04)))
5584 //TEMP, TO TEST IF ZCOMP IS THE CULPRIT...
5585 //Nope, this is NOT the problem...
5587 // We'll do the comparison/bit/byte inhibits here, since that's they way it happens
5588 // in the real thing (dcomp goes out to COMP_CTRL and back into DATA through dbinh)...
5592 COMP_CTRL(dbinht, nowrite,
5593 bcompen, true/*big_pix*/, bkgwren, dcomp, dcompen, icount, pixsize, phrase_mode, srcd & 0xFF, zcomp);
5599 #ifdef VERBOSE_BLITTER_LOGGING
5602 printf("\n[dcomp=%02X zcomp=%02X dbinh=%02X]\n", dcomp, zcomp, dbinh);
5607 //////////////////////////////////////////////////////////////////////////////////////
5610 // The data initializer - allows all four initial values to be computed from one (NOT IN JAGUAR I)
5612 /*Datinit := DATINIT (initcin[0..3], initinc[0..63], initpix[0..15], a1_x[0..1], big_pix, clk, iinc, init_if, init_ii,
5613 init_zf, istep[0..31], zinc, zstep[0..31]);*/
5615 // Adder array for Z and intensity increments
5617 /*Addarray := ADDARRAY (addq[0..3], clk, daddasel[0..2], daddbsel[0..3], daddmode[0..2], dstdlo, dstdhi, iinc,
5618 initcin[0..3], initinc[0..63], initpix[0..15], istep, patdv[0..1], srcdlo, srcdhi, srcz1[0..1],
5619 srcz2[0..1], reset\, zinc, zstep);*/
5620 /*void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
5621 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
5622 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
5623 uint32 zinc, uint32 zstep)*/
5624 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5626 uint8 initcin[4] = { 0, 0, 0, 0 };
5627 ADDARRAY(addq, daddasel, daddbsel, daddmode, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
5629 //This is normally done asynchronously above (thru local_data) when in patdadd mode...
5630 //And now it's passed back to the caller to be persistent between calls...!
5631 //But it's causing some serious fuck-ups in T2K now... !!! FIX !!! [DONE--???]
5632 //Weird! It doesn't anymore...!
5634 patd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
5635 //////////////////////////////////////////////////////////////////////////////////////
5637 // Local data bus multiplexer
5639 /*Local_mux := LOCAL_MUX (local_data[0..1], load_data[0..1],
5640 addq[0..3], gpu_din, data[0..63], blitter_active, daddq_sel);
5641 Local_data0 := JOIN (local_data0, local_data[0]);
5642 Local_data1 := JOIN (local_data1, local_data[1]);*/
5643 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5644 //////////////////////////////////////////////////////////////////////////////////////
5646 // Data output multiplexer and tri-state drive
5648 /*Data_mux := DATA_MUX (wdata[0..63], addq[0..3], big_pix, dstdlo, dstdhi, dstz[0..1], data_sel[0..1], data_ena,
5649 dstart[0..5], dend[0..5], dbinh\[0..7], lfu[0..1], patdo[0..1], phrase_mode, srczo[0..1]);*/
5650 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5651 // NOTE: patdo comes from DATAMIX and can be considered the same as patd for Jaguar I
5653 //////////////////////////////////////////////////////////////////////////////////////
5657 wdata[0..63] // co-processor rwrite data bus
5660 big_pix // Pixel organisation is big-endian
5665 data_sel[0..1] // source of write data
5666 data_ena // enable write data onto read/write bus
5667 dstart[0..5] // start of changed write data
5668 dend[0..5] // end of changed write data
5669 dbinh\[0..7] // byte oriented changed data inhibits
5672 phrase_mode // phrase write mode
5677 /*INT32/ addql[0..1], ddatlo, ddathi zero32
5681 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5682 Zero := TIE0 (zero);
5683 Zero32 := JOIN (zero32, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero);*/
5685 /* Generate a changed data mask */
5687 /*Edis := OR6 (edis\, dend[0..5]);
5688 Ecoarse := DECL38E (e_coarse\[0..7], dend[3..5], edis\);
5689 E_coarse[0] := INV1 (e_coarse[0], e_coarse\[0]);
5690 Efine := DECL38E (unused[0], e_fine\[1..7], dend[0..2], e_coarse[0]);*/
5691 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5692 uint8 decl38e[2][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
5693 { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } };
5694 uint8 dech38[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
5695 uint8 dech38el[2][8] = { { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
5696 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
5698 int en = (dend & 0x3F ? 1 : 0);
5699 uint8 e_coarse = decl38e[en][(dend & 0x38) >> 3]; // Actually, this is e_coarse inverted...
5700 uint8 e_fine = decl38e[(e_coarse & 0x01) ^ 0x01][dend & 0x07];
5702 //////////////////////////////////////////////////////////////////////////////////////
5704 /*Scoarse := DECH38 (s_coarse[0..7], dstart[3..5]);
5705 Sfen\ := INV1 (sfen\, s_coarse[0]);
5706 Sfine := DECH38EL (s_fine[0..7], dstart[0..2], sfen\);*/
5707 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5708 uint8 s_coarse = dech38[(dstart & 0x38) >> 3];
5709 uint8 s_fine = dech38el[(s_coarse & 0x01) ^ 0x01][dstart & 0x07];
5710 //////////////////////////////////////////////////////////////////////////////////////
5712 /*Maskt[0] := BUF1 (maskt[0], s_fine[0]);
5713 Maskt[1-7] := OAN1P (maskt[1-7], maskt[0-6], s_fine[1-7], e_fine\[1-7]);*/
5714 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5715 uint16 maskt = s_fine & 0x0001;
5716 maskt |= (((maskt & 0x0001) || (s_fine & 0x02)) && (e_fine & 0x02) ? 0x0002 : 0x0000);
5717 maskt |= (((maskt & 0x0002) || (s_fine & 0x04)) && (e_fine & 0x04) ? 0x0004 : 0x0000);
5718 maskt |= (((maskt & 0x0004) || (s_fine & 0x08)) && (e_fine & 0x08) ? 0x0008 : 0x0000);
5719 maskt |= (((maskt & 0x0008) || (s_fine & 0x10)) && (e_fine & 0x10) ? 0x0010 : 0x0000);
5720 maskt |= (((maskt & 0x0010) || (s_fine & 0x20)) && (e_fine & 0x20) ? 0x0020 : 0x0000);
5721 maskt |= (((maskt & 0x0020) || (s_fine & 0x40)) && (e_fine & 0x40) ? 0x0040 : 0x0000);
5722 maskt |= (((maskt & 0x0040) || (s_fine & 0x80)) && (e_fine & 0x80) ? 0x0080 : 0x0000);
5723 //////////////////////////////////////////////////////////////////////////////////////
5725 /* Produce a look-ahead on the ripple carry:
5726 masktla = s_coarse[0] . /e_coarse[0] */
5727 /*Masktla := AN2 (masktla, s_coarse[0], e_coarse\[0]);
5728 Maskt[8] := OAN1P (maskt[8], masktla, s_coarse[1], e_coarse\[1]);
5729 Maskt[9-14] := OAN1P (maskt[9-14], maskt[8-13], s_coarse[2-7], e_coarse\[2-7]);*/
5730 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5731 maskt |= (((s_coarse & e_coarse & 0x01) || (s_coarse & 0x02)) && (e_coarse & 0x02) ? 0x0100 : 0x0000);
5732 maskt |= (((maskt & 0x0100) || (s_coarse & 0x04)) && (e_coarse & 0x04) ? 0x0200 : 0x0000);
5733 maskt |= (((maskt & 0x0200) || (s_coarse & 0x08)) && (e_coarse & 0x08) ? 0x0400 : 0x0000);
5734 maskt |= (((maskt & 0x0400) || (s_coarse & 0x10)) && (e_coarse & 0x10) ? 0x0800 : 0x0000);
5735 maskt |= (((maskt & 0x0800) || (s_coarse & 0x20)) && (e_coarse & 0x20) ? 0x1000 : 0x0000);
5736 maskt |= (((maskt & 0x1000) || (s_coarse & 0x40)) && (e_coarse & 0x40) ? 0x2000 : 0x0000);
5737 maskt |= (((maskt & 0x2000) || (s_coarse & 0x80)) && (e_coarse & 0x80) ? 0x4000 : 0x0000);
5738 //////////////////////////////////////////////////////////////////////////////////////
5740 /* The bit terms are mirrored for big-endian pixels outside phrase
5741 mode. The byte terms are mirrored for big-endian pixels in phrase
5744 /*Mirror_bit := AN2M (mir_bit, phrase_mode\, big_pix);
5745 Mirror_byte := AN2H (mir_byte, phrase_mode, big_pix);
5747 Masktb[14] := BUF1 (masktb[14], maskt[14]);
5748 Masku[0] := MX4 (masku[0], maskt[0], maskt[7], maskt[14], zero, mir_bit, mir_byte);
5749 Masku[1] := MX4 (masku[1], maskt[1], maskt[6], maskt[14], zero, mir_bit, mir_byte);
5750 Masku[2] := MX4 (masku[2], maskt[2], maskt[5], maskt[14], zero, mir_bit, mir_byte);
5751 Masku[3] := MX4 (masku[3], maskt[3], maskt[4], masktb[14], zero, mir_bit, mir_byte);
5752 Masku[4] := MX4 (masku[4], maskt[4], maskt[3], masktb[14], zero, mir_bit, mir_byte);
5753 Masku[5] := MX4 (masku[5], maskt[5], maskt[2], masktb[14], zero, mir_bit, mir_byte);
5754 Masku[6] := MX4 (masku[6], maskt[6], maskt[1], masktb[14], zero, mir_bit, mir_byte);
5755 Masku[7] := MX4 (masku[7], maskt[7], maskt[0], masktb[14], zero, mir_bit, mir_byte);
5756 Masku[8] := MX2 (masku[8], maskt[8], maskt[13], mir_byte);
5757 Masku[9] := MX2 (masku[9], maskt[9], maskt[12], mir_byte);
5758 Masku[10] := MX2 (masku[10], maskt[10], maskt[11], mir_byte);
5759 Masku[11] := MX2 (masku[11], maskt[11], maskt[10], mir_byte);
5760 Masku[12] := MX2 (masku[12], maskt[12], maskt[9], mir_byte);
5761 Masku[13] := MX2 (masku[13], maskt[13], maskt[8], mir_byte);
5762 Masku[14] := MX2 (masku[14], maskt[14], maskt[0], mir_byte);*/
5763 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5764 bool mir_bit = true/*big_pix*/ && !phrase_mode;
5765 bool mir_byte = true/*big_pix*/ && phrase_mode;
5766 uint16 masku = maskt;
5771 masku |= (maskt >> 7) & 0x0001;
5772 masku |= (maskt >> 5) & 0x0002;
5773 masku |= (maskt >> 3) & 0x0004;
5774 masku |= (maskt >> 1) & 0x0008;
5775 masku |= (maskt << 1) & 0x0010;
5776 masku |= (maskt << 3) & 0x0020;
5777 masku |= (maskt << 5) & 0x0040;
5778 masku |= (maskt << 7) & 0x0080;
5784 masku |= (maskt >> 14) & 0x0001;
5785 masku |= (maskt >> 13) & 0x0002;
5786 masku |= (maskt >> 12) & 0x0004;
5787 masku |= (maskt >> 11) & 0x0008;
5788 masku |= (maskt >> 10) & 0x0010;
5789 masku |= (maskt >> 9) & 0x0020;
5790 masku |= (maskt >> 8) & 0x0040;
5791 masku |= (maskt >> 7) & 0x0080;
5793 masku |= (maskt >> 5) & 0x0100;
5794 masku |= (maskt >> 3) & 0x0200;
5795 masku |= (maskt >> 1) & 0x0400;
5796 masku |= (maskt << 1) & 0x0800;
5797 masku |= (maskt << 3) & 0x1000;
5798 masku |= (maskt << 5) & 0x2000;
5799 masku |= (maskt << 7) & 0x4000;
5801 //////////////////////////////////////////////////////////////////////////////////////
5803 /* The maskt terms define the area for changed data, but the byte
5804 inhibit terms can override these */
5806 /*Mask[0-7] := AN2 (mask[0-7], masku[0-7], dbinh\[0]);
5807 Mask[8-14] := AN2H (mask[8-14], masku[8-14], dbinh\[1-7]);*/
5808 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5809 uint16 mask = masku & (!(dbinh & 0x01) ? 0xFFFF : 0xFF00);
5810 mask &= ~(((uint16)dbinh & 0x00FE) << 7);
5811 //////////////////////////////////////////////////////////////////////////////////////
5813 /*Addql[0] := JOIN (addql[0], addq[0..1]);
5814 Addql[1] := JOIN (addql[1], addq[2..3]);
5816 Dsel0b[0-1] := BUF8 (dsel0b[0-1], data_sel[0]);
5817 Dsel1b[0-1] := BUF8 (dsel1b[0-1], data_sel[1]);
5818 Ddatlo := MX4 (ddatlo, patd[0], lfu[0], addql[0], zero32, dsel0b[0], dsel1b[0]);
5819 Ddathi := MX4 (ddathi, patd[1], lfu[1], addql[1], zero32, dsel0b[1], dsel1b[1]);*/
5820 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5824 dmux[2] = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
5826 uint64 ddat = dmux[data_sel];
5827 //////////////////////////////////////////////////////////////////////////////////////
5829 /*Zed_sel := AN2 (zed_sel, data_sel[0..1]);
5830 Zed_selb[0-1] := BUF8 (zed_selb[0-1], zed_sel);
5832 Dat[0-7] := MX4 (dat[0-7], dstdlo{0-7}, ddatlo{0-7}, dstzlo{0-7}, srczlo{0-7}, mask[0-7], zed_selb[0]);
5833 Dat[8-15] := MX4 (dat[8-15], dstdlo{8-15}, ddatlo{8-15}, dstzlo{8-15}, srczlo{8-15}, mask[8], zed_selb[0]);
5834 Dat[16-23] := MX4 (dat[16-23], dstdlo{16-23}, ddatlo{16-23}, dstzlo{16-23}, srczlo{16-23}, mask[9], zed_selb[0]);
5835 Dat[24-31] := MX4 (dat[24-31], dstdlo{24-31}, ddatlo{24-31}, dstzlo{24-31}, srczlo{24-31}, mask[10], zed_selb[0]);
5836 Dat[32-39] := MX4 (dat[32-39], dstdhi{0-7}, ddathi{0-7}, dstzhi{0-7}, srczhi{0-7}, mask[11], zed_selb[1]);
5837 Dat[40-47] := MX4 (dat[40-47], dstdhi{8-15}, ddathi{8-15}, dstzhi{8-15}, srczhi{8-15}, mask[12], zed_selb[1]);
5838 Dat[48-55] := MX4 (dat[48-55], dstdhi{16-23}, ddathi{16-23}, dstzhi{16-23}, srczhi{16-23}, mask[13], zed_selb[1]);
5839 Dat[56-63] := MX4 (dat[56-63], dstdhi{24-31}, ddathi{24-31}, dstzhi{24-31}, srczhi{24-31}, mask[14], zed_selb[1]);*/
5840 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5841 wdata = ((ddat & mask) | (dstd & ~mask)) & 0x00000000000000FFLL;
5842 wdata |= (mask & 0x0100 ? ddat : dstd) & 0x000000000000FF00LL;
5843 wdata |= (mask & 0x0200 ? ddat : dstd) & 0x0000000000FF0000LL;
5844 wdata |= (mask & 0x0400 ? ddat : dstd) & 0x00000000FF000000LL;
5845 wdata |= (mask & 0x0800 ? ddat : dstd) & 0x000000FF00000000LL;
5846 wdata |= (mask & 0x1000 ? ddat : dstd) & 0x0000FF0000000000LL;
5847 wdata |= (mask & 0x2000 ? ddat : dstd) & 0x00FF000000000000LL;
5848 wdata |= (mask & 0x4000 ? ddat : dstd) & 0xFF00000000000000LL;
5851 printf("\n[ddat=%08X%08X dstd=%08X%08X wdata=%08X%08X mask=%04X]\n",
5852 (uint32)(ddat >> 32), (uint32)(ddat & 0xFFFFFFFF),
5853 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
5854 (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF), mask);
5857 //This is a crappy way of handling this, but it should work for now...
5859 zwdata = ((srcz & mask) | (dstz & ~mask)) & 0x00000000000000FFLL;
5860 zwdata |= (mask & 0x0100 ? srcz : dstz) & 0x000000000000FF00LL;
5861 zwdata |= (mask & 0x0200 ? srcz : dstz) & 0x0000000000FF0000LL;
5862 zwdata |= (mask & 0x0400 ? srcz : dstz) & 0x00000000FF000000LL;
5863 zwdata |= (mask & 0x0800 ? srcz : dstz) & 0x000000FF00000000LL;
5864 zwdata |= (mask & 0x1000 ? srcz : dstz) & 0x0000FF0000000000LL;
5865 zwdata |= (mask & 0x2000 ? srcz : dstz) & 0x00FF000000000000LL;
5866 zwdata |= (mask & 0x4000 ? srcz : dstz) & 0xFF00000000000000LL;
5869 printf("\n[srcz=%08X%08X dstz=%08X%08X zwdata=%08X%08X mask=%04X]\n",
5870 (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF),
5871 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF),
5872 (uint32)(zwdata >> 32), (uint32)(zwdata & 0xFFFFFFFF), mask);
5876 //////////////////////////////////////////////////////////////////////////////////////
5878 /*Data_enab[0-1] := BUF8 (data_enab[0-1], data_ena);
5879 Datadrv[0-31] := TS (wdata[0-31], dat[0-31], data_enab[0]);
5880 Datadrv[32-63] := TS (wdata[32-63], dat[32-63], data_enab[1]);
5882 Unused[0] := DUMMY (unused[0]);
5887 /** COMP_CTRL - Comparator output control logic *****************
5889 This block is responsible for taking the comparator outputs and
5890 using them as appropriate to inhibit writes. Two methods are
5891 supported for inhibiting write data:
5893 - suppression of the inner loop controlled write operation
5894 - a set of eight byte inhibit lines to write back dest data
5896 The first technique is used in pixel oriented modes, the second in
5897 phrase mode, but the phrase mode form is only applicable to eight
5898 and sixteen bit pixel modes.
5900 Writes can be suppressed by data being equal, by the Z comparator
5901 conditions being met, or by the bit to pixel expansion scheme.
5903 Pipe-lining issues: the data derived comparator outputs are stable
5904 until the next data read, well after the affected write from this
5905 operation. However, the inner counter bits can count immediately
5906 before the ack for the last write. Therefore, it is necessary to
5907 delay bcompbit select terms by one inner loop pipe-line stage,
5908 when generating the select for the data control - the output is
5909 delayed one further tick to give it write data timing (2/34).
5911 There is also a problem with computed data - the new values are
5912 calculated before the write associated with the old value has been
5913 performed. The is taken care of within the zed comparator by
5914 pipe-lining the comparator inputs where appropriate.
5917 //#define LOG_COMP_CTRL
5919 dbinh\[0..7] // destination byte inhibit lines
5920 nowrite // suppress inner loop write operation
5922 bcompen // bit selector inhibit enable
5923 big_pix // pixels are big-endian
5924 bkgwren // enable dest data write in pix inhibit
5925 clk // co-processor clock
5926 dcomp[0..7] // output of data byte comparators
5927 dcompen // data comparator inhibit enable
5928 icount[0..2] // low bits of inner count
5929 pixsize[0..2] // destination pixel size
5930 phrase_mode // phrase write mode
5931 srcd[0..7] // bits to use for bit to byte expansion
5932 step_inner // inner loop advance
5933 zcomp[0..3] // output of word zed comparators
5935 void COMP_CTRL(uint8 &dbinh, bool &nowrite,
5936 bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
5937 uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp)
5941 /*Bkgwren\ := INV1 (bkgwren\, bkgwren);
5942 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5943 Pixsize\[0-2] := INV2 (pixsize\[0-2], pixsize[0-2]);*/
5945 /* The bit comparator bits are derived from the source data, which
5946 will have been suitably aligned for phrase mode. The contents of
5947 the inner counter are used to select which bit to use.
5949 When not in phrase mode the inner count value is used to select
5950 one bit. It is assumed that the count has already occurred, so,
5951 7 selects bit 0, etc. In big-endian pixel mode, this turns round,
5952 so that a count of 7 selects bit 7.
5954 In phrase mode, the eight bits are used directly, and this mode is
5955 only applicable to 8-bit pixel mode (2/34) */
5957 /*Bcompselt[0-2] := EO (bcompselt[0-2], icount[0-2], big_pix);
5958 Bcompbit := MX8 (bcompbit, srcd[7], srcd[6], srcd[5],
5959 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompselt[0..2]);
5960 Bcompbit\ := INV1 (bcompbit\, bcompbit);*/
5961 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5962 #ifdef LOG_COMP_CTRL
5965 printf("\n [bcompen=%s dcompen=%s phrase_mode=%s bkgwren=%s dcomp=%02X zcomp=%02X]", (bcompen ? "T" : "F"), (dcompen ? "T" : "F"), (phrase_mode ? "T" : "F"), (bkgwren ? "T" : "F"), dcomp, zcomp);
5970 uint8 bcompselt = (big_pix ? ~icount : icount) & 0x07;
5971 uint8 bitmask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
5972 bool bcompbit = srcd & bitmask[bcompselt];
5973 //////////////////////////////////////////////////////////////////////////////////////
5975 /* pipe-line the count */
5976 /*Bcompsel[0-2] := FDSYNC (bcompsel[0-2], bcompselt[0-2], step_inner, clk);
5977 Bcompbt := MX8 (bcompbitpt, srcd[7], srcd[6], srcd[5],
5978 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompsel[0..2]);
5979 Bcompbitp := FD1Q (bcompbitp, bcompbitpt, clk);
5980 Bcompbitp\ := INV1 (bcompbitp\, bcompbitp);*/
5982 /* For pixel mode, generate the write inhibit signal for all modes
5983 on bit inhibit, for 8 and 16 bit modes on comparator inhibit, and
5984 for 16 bit mode on Z inhibit
5986 Nowrite = bcompen . /bcompbit . /phrase_mode
5987 + dcompen . dcomp[0] . /phrase_mode . pixsize = 011
5988 + dcompen . dcomp[0..1] . /phrase_mode . pixsize = 100
5989 + zcomp[0] . /phrase_mode . pixsize = 100
5992 /*Nowt0 := NAN3 (nowt[0], bcompen, bcompbit\, phrase_mode\);
5993 Nowt1 := ND6 (nowt[1], dcompen, dcomp[0], phrase_mode\, pixsize\[2], pixsize[0..1]);
5994 Nowt2 := ND7 (nowt[2], dcompen, dcomp[0..1], phrase_mode\, pixsize[2], pixsize\[0..1]);
5995 Nowt3 := NAN5 (nowt[3], zcomp[0], phrase_mode\, pixsize[2], pixsize\[0..1]);
5996 Nowt4 := NAN4 (nowt[4], nowt[0..3]);
5997 Nowrite := AN2 (nowrite, nowt[4], bkgwren\);*/
5998 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5999 nowrite = ((bcompen && !bcompbit && !phrase_mode)
6000 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
6001 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
6002 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4)))
6004 //////////////////////////////////////////////////////////////////////////////////////
6006 /*Winht := NAN3 (winht, bcompen, bcompbitp\, phrase_mode\);
6007 Winhibit := NAN4 (winhibit, winht, nowt[1..3]);*/
6008 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6009 //This is the same as above, but with bcompbit delayed one tick and called 'winhibit'
6010 //Small difference: Besides the pipeline effect, it's also not using !bkgwren...
6011 // bool winhibit = (bcompen && !
6012 bool winhibit = (bcompen && !bcompbit && !phrase_mode)
6013 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
6014 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
6015 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4));
6016 #ifdef LOG_COMP_CTRL
6019 printf("[nw=%s wi=%s]", (nowrite ? "T" : "F"), (winhibit ? "T" : "F"));
6023 //////////////////////////////////////////////////////////////////////////////////////
6025 /* For phrase mode, generate the byte inhibit signals for eight bit
6026 mode 011, or sixteen bit mode 100
6027 dbinh\[0] = pixsize[2] . zcomp[0]
6028 + pixsize[2] . dcomp[0] . dcomp[1] . dcompen
6029 + /pixsize[2] . dcomp[0] . dcompen
6030 + /srcd[0] . bcompen
6032 Inhibits 0-3 are also used when not in phrase mode to write back
6036 /*Srcd\[0-7] := INV1 (srcd\[0-7], srcd[0-7]);
6038 Di0t0 := NAN2H (di0t[0], pixsize[2], zcomp[0]);
6039 Di0t1 := NAN4H (di0t[1], pixsize[2], dcomp[0..1], dcompen);
6040 Di0t2 := NAN2 (di0t[2], srcd\[0], bcompen);
6041 Di0t3 := NAN3 (di0t[3], pixsize\[2], dcomp[0], dcompen);
6042 Di0t4 := NAN4 (di0t[4], di0t[0..3]);
6043 Dbinh[0] := ANR1P (dbinh\[0], di0t[4], phrase_mode, winhibit);*/
6044 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6046 bool di0t0_1 = ((pixsize & 0x04) && (zcomp & 0x01))
6047 || ((pixsize & 0x04) && (dcomp & 0x01) && (dcomp & 0x02) && dcompen);
6048 bool di0t4 = di0t0_1
6049 || (!(srcd & 0x01) && bcompen)
6050 || (!(pixsize & 0x04) && (dcomp & 0x01) && dcompen);
6051 dbinh |= (!((di0t4 && phrase_mode) || winhibit) ? 0x01 : 0x00);
6052 #ifdef LOG_COMP_CTRL
6055 printf("[di0t0_1=%s di0t4=%s]", (di0t0_1 ? "T" : "F"), (di0t4 ? "T" : "F"));
6059 //////////////////////////////////////////////////////////////////////////////////////
6061 /*Di1t0 := NAN3 (di1t[0], pixsize\[2], dcomp[1], dcompen);
6062 Di1t1 := NAN2 (di1t[1], srcd\[1], bcompen);
6063 Di1t2 := NAN4 (di1t[2], di0t[0..1], di1t[0..1]);
6064 Dbinh[1] := ANR1 (dbinh\[1], di1t[2], phrase_mode, winhibit);*/
6065 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6066 bool di1t2 = di0t0_1
6067 || (!(srcd & 0x02) && bcompen)
6068 || (!(pixsize & 0x04) && (dcomp & 0x02) && dcompen);
6069 dbinh |= (!((di1t2 && phrase_mode) || winhibit) ? 0x02 : 0x00);
6070 #ifdef LOG_COMP_CTRL
6073 printf("[di1t2=%s]", (di1t2 ? "T" : "F"));
6077 //////////////////////////////////////////////////////////////////////////////////////
6079 /*Di2t0 := NAN2H (di2t[0], pixsize[2], zcomp[1]);
6080 Di2t1 := NAN4H (di2t[1], pixsize[2], dcomp[2..3], dcompen);
6081 Di2t2 := NAN2 (di2t[2], srcd\[2], bcompen);
6082 Di2t3 := NAN3 (di2t[3], pixsize\[2], dcomp[2], dcompen);
6083 Di2t4 := NAN4 (di2t[4], di2t[0..3]);
6084 Dbinh[2] := ANR1 (dbinh\[2], di2t[4], phrase_mode, winhibit);*/
6085 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6086 //[bcompen=F dcompen=T phrase_mode=T bkgwren=F][nw=F wi=F]
6087 //[di0t0_1=F di0t4=F][di1t2=F][di2t0_1=T di2t4=T][di3t2=T][di4t0_1=F di2t4=F][di5t2=F][di6t0_1=F di6t4=F][di7t2=F]
6088 //[dcomp=$00 dbinh=$0C][7804780400007804] (icount=0005, inc=4)
6089 bool di2t0_1 = ((pixsize & 0x04) && (zcomp & 0x02))
6090 || ((pixsize & 0x04) && (dcomp & 0x04) && (dcomp & 0x08) && dcompen);
6091 bool di2t4 = di2t0_1
6092 || (!(srcd & 0x04) && bcompen)
6093 || (!(pixsize & 0x04) && (dcomp & 0x04) && dcompen);
6094 dbinh |= (!((di2t4 && phrase_mode) || winhibit) ? 0x04 : 0x00);
6095 #ifdef LOG_COMP_CTRL
6098 printf("[di2t0_1=%s di2t4=%s]", (di2t0_1 ? "T" : "F"), (di2t4 ? "T" : "F"));
6102 //////////////////////////////////////////////////////////////////////////////////////
6104 /*Di3t0 := NAN3 (di3t[0], pixsize\[2], dcomp[3], dcompen);
6105 Di3t1 := NAN2 (di3t[1], srcd\[3], bcompen);
6106 Di3t2 := NAN4 (di3t[2], di2t[0..1], di3t[0..1]);
6107 Dbinh[3] := ANR1 (dbinh\[3], di3t[2], phrase_mode, winhibit);*/
6108 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6109 bool di3t2 = di2t0_1
6110 || (!(srcd & 0x08) && bcompen)
6111 || (!(pixsize & 0x04) && (dcomp & 0x08) && dcompen);
6112 dbinh |= (!((di3t2 && phrase_mode) || winhibit) ? 0x08 : 0x00);
6113 #ifdef LOG_COMP_CTRL
6116 printf("[di3t2=%s]", (di3t2 ? "T" : "F"));
6120 //////////////////////////////////////////////////////////////////////////////////////
6122 /*Di4t0 := NAN2H (di4t[0], pixsize[2], zcomp[2]);
6123 Di4t1 := NAN4H (di4t[1], pixsize[2], dcomp[4..5], dcompen);
6124 Di4t2 := NAN2 (di4t[2], srcd\[4], bcompen);
6125 Di4t3 := NAN3 (di4t[3], pixsize\[2], dcomp[4], dcompen);
6126 Di4t4 := NAN4 (di4t[4], di4t[0..3]);
6127 Dbinh[4] := NAN2 (dbinh\[4], di4t[4], phrase_mode);*/
6128 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6129 bool di4t0_1 = ((pixsize & 0x04) && (zcomp & 0x04))
6130 || ((pixsize & 0x04) && (dcomp & 0x10) && (dcomp & 0x20) && dcompen);
6131 bool di4t4 = di4t0_1
6132 || (!(srcd & 0x10) && bcompen)
6133 || (!(pixsize & 0x04) && (dcomp & 0x10) && dcompen);
6134 dbinh |= (!(di4t4 && phrase_mode) ? 0x10 : 0x00);
6135 #ifdef LOG_COMP_CTRL
6138 printf("[di4t0_1=%s di2t4=%s]", (di4t0_1 ? "T" : "F"), (di4t4 ? "T" : "F"));
6142 //////////////////////////////////////////////////////////////////////////////////////
6144 /*Di5t0 := NAN3 (di5t[0], pixsize\[2], dcomp[5], dcompen);
6145 Di5t1 := NAN2 (di5t[1], srcd\[5], bcompen);
6146 Di5t2 := NAN4 (di5t[2], di4t[0..1], di5t[0..1]);
6147 Dbinh[5] := NAN2 (dbinh\[5], di5t[2], phrase_mode);*/
6148 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6149 bool di5t2 = di4t0_1
6150 || (!(srcd & 0x20) && bcompen)
6151 || (!(pixsize & 0x04) && (dcomp & 0x20) && dcompen);
6152 dbinh |= (!(di5t2 && phrase_mode) ? 0x20 : 0x00);
6153 #ifdef LOG_COMP_CTRL
6156 printf("[di5t2=%s]", (di5t2 ? "T" : "F"));
6160 //////////////////////////////////////////////////////////////////////////////////////
6162 /*Di6t0 := NAN2H (di6t[0], pixsize[2], zcomp[3]);
6163 Di6t1 := NAN4H (di6t[1], pixsize[2], dcomp[6..7], dcompen);
6164 Di6t2 := NAN2 (di6t[2], srcd\[6], bcompen);
6165 Di6t3 := NAN3 (di6t[3], pixsize\[2], dcomp[6], dcompen);
6166 Di6t4 := NAN4 (di6t[4], di6t[0..3]);
6167 Dbinh[6] := NAN2 (dbinh\[6], di6t[4], phrase_mode);*/
6168 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6169 bool di6t0_1 = ((pixsize & 0x04) && (zcomp & 0x08))
6170 || ((pixsize & 0x04) && (dcomp & 0x40) && (dcomp & 0x80) && dcompen);
6171 bool di6t4 = di6t0_1
6172 || (!(srcd & 0x40) && bcompen)
6173 || (!(pixsize & 0x04) && (dcomp & 0x40) && dcompen);
6174 dbinh |= (!(di6t4 && phrase_mode) ? 0x40 : 0x00);
6175 #ifdef LOG_COMP_CTRL
6178 printf("[di6t0_1=%s di6t4=%s]", (di6t0_1 ? "T" : "F"), (di6t4 ? "T" : "F"));
6182 //////////////////////////////////////////////////////////////////////////////////////
6184 /*Di7t0 := NAN3 (di7t[0], pixsize\[2], dcomp[7], dcompen);
6185 Di7t1 := NAN2 (di7t[1], srcd\[7], bcompen);
6186 Di7t2 := NAN4 (di7t[2], di6t[0..1], di7t[0..1]);
6187 Dbinh[7] := NAN2 (dbinh\[7], di7t[2], phrase_mode);*/
6188 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6189 bool di7t2 = di6t0_1
6190 || (!(srcd & 0x80) && bcompen)
6191 || (!(pixsize & 0x04) && (dcomp & 0x80) && dcompen);
6192 dbinh |= (!(di7t2 && phrase_mode) ? 0x80 : 0x00);
6193 #ifdef LOG_COMP_CTRL
6196 printf("[di7t2=%s]", (di7t2 ? "T" : "F"));
6200 //////////////////////////////////////////////////////////////////////////////////////
6205 #ifdef LOG_COMP_CTRL
6208 printf("[dcomp=$%02X dbinh=$%02X]\n ", dcomp, dbinh);
6215 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6216 //////////////////////////////////////////////////////////////////////////////////////
6218 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6219 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6220 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!