5 // (C) 2010 Underground Software
7 // JLH = James L. Hammons <jlhamm@acm.org>
10 // --- ---------- -------------------------------------------------------------
11 // JLH 01/16/2010 Created this log ;-)
15 // I owe a debt of gratitude to Curt Vendel and to John Mathieson--to Curt
16 // for supplying the Oberon ASIC nets and to John for making them available
17 // to Curt. ;-) Without that excellent documentation which shows *exactly*
18 // what's going on inside the TOM chip, we'd all still be guessing as to how
19 // the wily blitter and other pieces of the Jaguar puzzle actually work.
20 // Now how about those JERRY ASIC nets gentlemen...? [We have those now!] ;-)
32 // Various conditional compilation goodies...
34 //#define USE_ORIGINAL_BLITTER
35 //#define USE_MIDSUMMER_BLITTER
36 #define USE_MIDSUMMER_BLITTER_MKII
38 // External global variables
40 extern int jaguar_active_memory_dumps;
42 // Local global variables
44 int start_logging = 0;
45 uint8 blitter_working = 0;
47 // Blitter register RAM (most of it is hidden from the user)
49 static uint8 blitter_ram[0x100];
53 bool specialLog = false;
54 extern int effect_start;
55 extern int blit_start_log;
56 void BlitterMidsummer(uint32 cmd);
57 void BlitterMidsummer2(void);
59 #define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
60 | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
61 #define WREG(A,D) (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
62 blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
64 // Blitter registers (offsets from F02200)
66 #define A1_BASE ((uint32)0x00)
67 #define A1_FLAGS ((uint32)0x04)
68 #define A1_CLIP ((uint32)0x08) // Height and width values for clipping
69 #define A1_PIXEL ((uint32)0x0C) // Integer part of the pixel (Y.i and X.i)
70 #define A1_STEP ((uint32)0x10) // Integer part of the step
71 #define A1_FSTEP ((uint32)0x14) // Fractional part of the step
72 #define A1_FPIXEL ((uint32)0x18) // Fractional part of the pixel (Y.f and X.f)
73 #define A1_INC ((uint32)0x1C) // Integer part of the increment
74 #define A1_FINC ((uint32)0x20) // Fractional part of the increment
75 #define A2_BASE ((uint32)0x24)
76 #define A2_FLAGS ((uint32)0x28)
77 #define A2_MASK ((uint32)0x2C) // Modulo values for x and y (M.y and M.x)
78 #define A2_PIXEL ((uint32)0x30) // Integer part of the pixel (no fractional part for A2)
79 #define A2_STEP ((uint32)0x34) // Integer part of the step (no fractional part for A2)
80 #define COMMAND ((uint32)0x38)
81 #define PIXLINECOUNTER ((uint32)0x3C) // Inner & outer loop values
82 #define SRCDATA ((uint32)0x40)
83 #define DSTDATA ((uint32)0x48)
84 #define DSTZ ((uint32)0x50)
85 #define SRCZINT ((uint32)0x58)
86 #define SRCZFRAC ((uint32)0x60)
87 #define PATTERNDATA ((uint32)0x68)
88 #define INTENSITYINC ((uint32)0x70)
89 #define ZINC ((uint32)0x74)
90 #define COLLISIONCTRL ((uint32)0x78)
91 #define PHRASEINT0 ((uint32)0x7C)
92 #define PHRASEINT1 ((uint32)0x80)
93 #define PHRASEINT2 ((uint32)0x84)
94 #define PHRASEINT3 ((uint32)0x88)
95 #define PHRASEZ0 ((uint32)0x8C)
96 #define PHRASEZ1 ((uint32)0x90)
97 #define PHRASEZ2 ((uint32)0x94)
98 #define PHRASEZ3 ((uint32)0x98)
100 // Blitter command bits
102 #define SRCEN (cmd & 0x00000001)
103 #define SRCENZ (cmd & 0x00000002)
104 #define SRCENX (cmd & 0x00000004)
105 #define DSTEN (cmd & 0x00000008)
106 #define DSTENZ (cmd & 0x00000010)
107 #define DSTWRZ (cmd & 0x00000020)
108 #define CLIPA1 (cmd & 0x00000040)
110 #define UPDA1F (cmd & 0x00000100)
111 #define UPDA1 (cmd & 0x00000200)
112 #define UPDA2 (cmd & 0x00000400)
114 #define DSTA2 (cmd & 0x00000800)
116 #define Z_OP_INF (cmd & 0x00040000)
117 #define Z_OP_EQU (cmd & 0x00080000)
118 #define Z_OP_SUP (cmd & 0x00100000)
120 #define LFU_NAN (cmd & 0x00200000)
121 #define LFU_NA (cmd & 0x00400000)
122 #define LFU_AN (cmd & 0x00800000)
123 #define LFU_A (cmd & 0x01000000)
125 #define CMPDST (cmd & 0x02000000)
126 #define BCOMPEN (cmd & 0x04000000)
127 #define DCOMPEN (cmd & 0x08000000)
129 #define PATDSEL (cmd & 0x00010000)
130 #define ADDDSEL (cmd & 0x00020000)
131 #define TOPBEN (cmd & 0x00004000)
132 #define TOPNEN (cmd & 0x00008000)
133 #define BKGWREN (cmd & 0x10000000)
134 #define GOURD (cmd & 0x00001000)
135 #define GOURZ (cmd & 0x00002000)
136 #define SRCSHADE (cmd & 0x40000000)
144 #define XSIGNSUB_A1 (REG(A1_FLAGS)&0x080000)
145 #define XSIGNSUB_A2 (REG(A2_FLAGS)&0x080000)
147 #define YSIGNSUB_A1 (REG(A1_FLAGS)&0x100000)
148 #define YSIGNSUB_A2 (REG(A2_FLAGS)&0x100000)
150 #define YADD1_A1 (REG(A1_FLAGS)&0x040000)
151 #define YADD1_A2 (REG(A2_FLAGS)&0x040000)
153 /*******************************************************************************
154 ********************** STUFF CUT BELOW THIS LINE! ******************************
155 *******************************************************************************/
156 #ifdef USE_ORIGINAL_BLITTER // We're ditching this crap for now...
158 //Put 'em back, once we fix the problem!!! [KO]
160 #define PIXEL_SHIFT_1(a) (((~a##_x) >> 16) & 7)
161 #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))
162 #define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
163 //#define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
166 #define PIXEL_SHIFT_2(a) (((~a##_x) >> 15) & 6)
167 #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))
168 #define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03)
169 //#define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
172 #define PIXEL_SHIFT_4(a) (((~a##_x) >> 14) & 4)
173 #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))
174 #define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f)
175 //#define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
178 #define PIXEL_OFFSET_8(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 7))
179 #define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER))
180 //#define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a)))
183 #define PIXEL_OFFSET_16(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 3))
184 #define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER))
185 //#define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
188 #define PIXEL_OFFSET_32(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
189 #define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER))
190 //#define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
193 #define READ_PIXEL(a,f) (\
194 (((f>>3)&0x07) == 0) ? (READ_PIXEL_1(a)) : \
195 (((f>>3)&0x07) == 1) ? (READ_PIXEL_2(a)) : \
196 (((f>>3)&0x07) == 2) ? (READ_PIXEL_4(a)) : \
197 (((f>>3)&0x07) == 3) ? (READ_PIXEL_8(a)) : \
198 (((f>>3)&0x07) == 4) ? (READ_PIXEL_16(a)) : \
199 (((f>>3)&0x07) == 5) ? (READ_PIXEL_32(a)) : 0)
201 // 16 bpp z data read
202 #define ZDATA_OFFSET_16(a) (PIXEL_OFFSET_16(a) + a##_zoffs * 4)
203 #define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER))
204 //#define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
207 #define READ_ZDATA(a,f) (READ_ZDATA_16(a))
209 // 16 bpp z data write
210 #define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); }
211 //#define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); }
214 #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d);
217 #define READ_RDATA_1(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 19) & 0x04))) >> (((uint32)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001))
220 #define READ_RDATA_2(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 18) & 0x04))) >> (((uint32)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003))
223 #define READ_RDATA_4(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 17) & 0x04))) >> (((uint32)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F))
226 #define READ_RDATA_8(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 16) & 0x04))) >> (((uint32)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF))
228 // 16 bpp r data read
229 #define READ_RDATA_16(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 15) & 0x04))) >> (((uint32)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF))
231 // 32 bpp r data read
232 #define READ_RDATA_32(r,a,p) ((p) ? REG(r+(((uint32)a##_x >> 14) & 0x04)) : REG(r))
234 // register data read
235 #define READ_RDATA(r,a,f,p) (\
236 (((f>>3)&0x07) == 0) ? (READ_RDATA_1(r,a,p)) : \
237 (((f>>3)&0x07) == 1) ? (READ_RDATA_2(r,a,p)) : \
238 (((f>>3)&0x07) == 2) ? (READ_RDATA_4(r,a,p)) : \
239 (((f>>3)&0x07) == 3) ? (READ_RDATA_8(r,a,p)) : \
240 (((f>>3)&0x07) == 4) ? (READ_RDATA_16(r,a,p)) : \
241 (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0)
244 #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); }
245 //#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))); }
248 #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); }
249 //#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))); }
252 #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); }
253 //#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))); }
256 #define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d, BLITTER); }
257 //#define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d); }
259 // 16 bpp pixel write
260 //#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
261 #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)); }
262 //#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)); }
264 // 32 bpp pixel write
265 #define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); }
266 //#define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); }
269 #define WRITE_PIXEL(a,f,d) {\
270 switch ((f>>3)&0x07) { \
271 case 0: WRITE_PIXEL_1(a,d); break; \
272 case 1: WRITE_PIXEL_2(a,d); break; \
273 case 2: WRITE_PIXEL_4(a,d); break; \
274 case 3: WRITE_PIXEL_8(a,d); break; \
275 case 4: WRITE_PIXEL_16(a,d); break; \
276 case 5: WRITE_PIXEL_32(a,d); break; \
279 // Width in Pixels of a Scanline
280 // This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
281 // of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
282 // the exponent. Valid values for the exponent range from 0 to 11 (decimal). It's easiest to think of it
283 // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to
284 // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place
285 // being shifted to the right 3 places).
286 /*static uint32 blitter_scanline_width[48] =
288 0, 0, 0, 0, // Note: This would really translate to 1, 1, 1, 1
298 1024, 1280, 1536, 1792,
299 2048, 2560, 3072, 3584
302 //static uint8 * tom_ram_8;
303 //static uint8 * paletteRam;
313 static uint32 a1_addr;
314 static uint32 a2_addr;
315 static int32 a1_zoffs;
316 static int32 a2_zoffs;
317 static uint32 xadd_a1_control;
318 static uint32 xadd_a2_control;
319 static int32 a1_pitch;
320 static int32 a2_pitch;
321 static uint32 n_pixels;
322 static uint32 n_lines;
325 static int32 a1_width;
328 static int32 a2_width;
329 static int32 a2_mask_x;
330 static int32 a2_mask_y;
331 static int32 a1_xadd;
332 static int32 a1_yadd;
333 static int32 a2_xadd;
334 static int32 a2_yadd;
335 static uint8 a1_phrase_mode;
336 static uint8 a2_phrase_mode;
337 static int32 a1_step_x = 0;
338 static int32 a1_step_y = 0;
339 static int32 a2_step_x = 0;
340 static int32 a2_step_y = 0;
341 static uint32 outer_loop;
342 static uint32 inner_loop;
343 static uint32 a2_psize;
344 static uint32 a1_psize;
345 static uint32 gouraud_add;
346 //static uint32 gouraud_data;
347 //static uint16 gint[4];
348 //static uint16 gfrac[4];
349 //static uint8 gcolour[4];
352 static int gd_ia, gd_ca;
353 static int colour_index = 0;
355 static uint32 z_i[4];
357 static int32 a1_clip_x, a1_clip_y;
359 // In the spirit of "get it right first, *then* optimize" I've taken the liberty
360 // of removing all the unnecessary code caching. If it turns out to be a good way
361 // to optimize the blitter, then we may revisit it in the future...
364 // Generic blit handler
366 void blitter_generic(uint32 cmd)
369 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
370 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
371 A1 step values: -2 (X), 1 (Y)
372 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
373 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
374 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
375 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
378 // specialLog = true;
379 /*if (cmd == 0x1401060C && blit_start_log)
380 specialLog = true;//*/
382 //uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
383 uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
384 uint32 bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07));
388 WriteLog("About to do n x m blit (BM width is ? pixels)...\n");
389 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);
403 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
405 uint32 a1_start = a1_x, a2_start = a2_x, bitPos = 0;
407 //Kludge for Hover Strike...
408 //I wonder if this kludge is in conjunction with the SRCENX down below...
409 // This isn't so much a kludge but the way things work in BCOMPEN mode...!
410 if (BCOMPEN && SRCENX)
412 if (n_pixels < bppSrc)
413 bitPos = bppSrc - n_pixels;
416 inner_loop = n_pixels;
421 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
423 srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
425 if (!DSTA2) // Data movement: A1 <- A2
427 // load src data and Z
429 if (SRCEN || SRCENX) // Not sure if this is correct... (seems to be...!)
431 srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
434 srczdata = READ_ZDATA(a2, REG(A2_FLAGS));
435 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
436 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
438 else // Use SRCDATA register...
440 srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
442 if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
443 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
446 // load dst data and Z
449 dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
452 dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
454 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
458 dstdata = READ_RDATA(DSTDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
461 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
464 /*This wasn't working... // a1 clipping
465 if (cmd & 0x00000040)
467 if (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7FFF)
468 || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7FFF))
473 srczdata = z_i[colour_index] >> 16;
475 // apply z comparator
476 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
477 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
478 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
480 // apply data comparator
481 // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
482 // Does BCOMPEN only work in 1 bpp mode???
483 // No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!!
484 // This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside
486 if (DCOMPEN | BCOMPEN)
488 //Temp, for testing Hover Strike
489 //Doesn't seem to do it... Why?
490 //What needs to happen here is twofold. First, the address generator in the outer loop has
491 //to honor the BPP when calculating the start address (which it kinda does already). Second,
492 //it has to step bit by bit when using BCOMPEN. How to do this???
494 //small problem with this approach: it's not accurate... We need a proper address to begin with
495 //and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!!
498 uint32 pixShift = (~bitPos) & (bppSrc - 1);
499 srcdata = (srcdata >> pixShift) & 0x01;
502 // if (bitPos % bppSrc == 0)
503 // a2_x += 0x00010000;
506 Interesting (Hover Strike--large letter):
508 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
509 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
510 A1 step values: -2 (X), 1 (Y)
511 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
512 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
513 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
514 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
516 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
517 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
518 A1 step values: -8 (X), 1 (Y)
519 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
520 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
521 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
522 A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000
524 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
525 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
526 A1 step values: -1 (X), 1 (Y)
527 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
528 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
529 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
530 A1 x/y: 118/12, A2 x/y: 70/0 Pattern: 000000F300000000
532 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
533 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
534 A1 step values: -8 (X), 1 (Y)
535 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
536 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
537 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
538 A1 x/y: 119/12, A2 x/y: 71/0 Pattern: 000000F300000000
540 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
541 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
542 A1 step values: -1 (X), 1 (Y)
543 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
544 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
545 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
546 A1 x/y: 127/12, A2 x/y: 66/0 Pattern: 000000F300000000
548 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
549 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
550 A1 step values: -8 (X), 1 (Y)
551 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
552 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
553 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
554 A1 x/y: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000
560 //WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit);
561 // compare source pixel with pattern pixel
563 Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: 05810001]
564 CMD -> src: SRCEN dst: misc: a1ctl: mode: ity: PATDSEL z-op: op: LFU_REPLACE ctrl: BCOMPEN
565 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
566 A2 -> pitch: 1 phrases, depth: 1bpp, z-off: 0, width: 16 (10), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
570 // AvP is still wrong, could be cuz it's doing A1 -> A2...
572 // Src is the 1bpp bitmap... DST is the PATTERN!!!
573 // This seems to solve at least ONE of the problems with MC3D...
574 // Why should this be inverted???
575 // Bcuz it is. This is supposed to be used only for a bit -> pixel expansion...
576 /* if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
577 // if (srcdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
579 /* uint32 A2bpp = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
580 if (A2bpp == 1 || A2bpp == 16 || A2bpp == 8)
581 inhibit = (srcdata == 0 ? 1: 0);
582 // inhibit = !srcdata;
584 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
585 // What it boils down to is this:
592 // compare destination pixel with pattern pixel
593 if (dstdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
594 // if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
598 // This is DEFINITELY WRONG
599 // if (a1_phrase_mode || a2_phrase_mode)
600 // inhibit = !inhibit;
605 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
606 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
609 // compute the write data and store
612 // Houston, we have a problem...
613 // Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's
615 //Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008]
616 // CMD -> src: dst: DSTEN misc: a1ctl: mode: GOURD ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
617 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
618 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
619 // A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700
623 // use pattern data for write data
624 writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
628 /*if (blit_start_log)
629 WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/
631 // intensity addition
632 //Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!!
633 /* writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
634 if (!(TOPBEN) && writedata > 0xFF)
637 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
638 if (!(TOPNEN) && writedata > 0xFFF)
639 // writedata = 0xFFF;
641 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/
642 //notneeded--writedata &= 0xFFFF;
643 /*if (blit_start_log)
644 WriteLog("writedata: %08X\n", writedata);//*/
646 Hover Strike ADDDSEL blit:
648 Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208]
649 CMD -> src: dst: DSTEN misc: a1ctl: UPDA1 mode: ity: ADDDSEL z-op: op: LFU_CLEAR ctrl:
650 A1 step values: -320 (X), 1 (Y)
651 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
652 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
653 A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD
655 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
659 //This is correct now, but slow...
660 int16 s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000),
669 writedata = (uint32)sum;
672 //This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!!
673 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
675 if (!TOPNEN && writedata > 0xFFF)
680 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
684 if (LFU_NAN) writedata |= ~srcdata & ~dstdata;
685 if (LFU_NA) writedata |= ~srcdata & dstdata;
686 if (LFU_AN) writedata |= srcdata & ~dstdata;
687 if (LFU_A) writedata |= srcdata & dstdata;
690 //Although, this looks like it's OK... (even if it is shitty!)
691 //According to JTRM, this is part of the four things the blitter does with the write data (the other
692 //three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL
693 //(see above blit example)...
695 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
699 int intensity = srcdata & 0xFF;
700 int ia = gd_ia >> 16;
702 ia = 0xFFFFFF00 | ia;
706 if (intensity > 0xFF)
708 writedata = (srcdata & 0xFF00) | intensity;
717 //Tried 2nd below for Hover Strike: No dice.
718 if (/*a1_phrase_mode || */BKGWREN || !inhibit)
719 // if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit)
721 /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
723 uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
724 // (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
725 if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
726 WriteLog("32bpp pixel write: A1 Phrase mode --> ");
728 // write to the destination
729 WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
731 WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
734 else // if (DSTA2) // Data movement: A1 -> A2
736 // load src data and Z
739 srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
741 srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
742 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
743 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
747 srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
748 if (cmd & 0x001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
749 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
752 // load dst data and Z
755 dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
757 dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
759 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
763 dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
765 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
769 srczdata = z_i[colour_index] >> 16;
771 // apply z comparator
772 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
773 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
774 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
776 // apply data comparator
777 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
778 if (DCOMPEN | BCOMPEN)
782 // compare source pixel with pattern pixel
783 // AvP: Numbers are correct, but sprites are not!
784 //This doesn't seem to be a problem... But could still be wrong...
785 /* if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
786 // if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
788 // This is probably not 100% correct... It works in the 1bpp case
789 // (in A1 <- A2 mode, that is...)
790 // AvP: This is causing blocks to be written instead of bit patterns...
792 // NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
793 /* uint32 A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
794 if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
795 inhibit = (srcdata == 0 ? 1: 0);
797 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
798 // What it boils down to is this:
804 // compare destination pixel with pattern pixel
805 if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
806 // if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
810 // This is DEFINITELY WRONG
811 // if (a1_phrase_mode || a2_phrase_mode)
812 // inhibit = !inhibit;
817 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
818 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
821 // compute the write data and store
826 // use pattern data for write data
827 writedata = READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
831 // intensity addition
832 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
833 if (!(TOPBEN) && writedata > 0xFF)
835 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
836 if (!(TOPNEN) && writedata > 0xFFF)
838 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
843 writedata |= ~srcdata & ~dstdata;
845 writedata |= ~srcdata & dstdata;
847 writedata |= srcdata & ~dstdata;
849 writedata |= srcdata & dstdata;
853 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
857 int intensity = srcdata & 0xFF;
858 int ia = gd_ia >> 16;
860 ia = 0xFFFFFF00 | ia;
864 if (intensity > 0xFF)
866 writedata = (srcdata & 0xFF00) | intensity;
875 if (/*a2_phrase_mode || */BKGWREN || !inhibit)
879 uint32 offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
880 // (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
881 WriteLog("[%08X:%04X] ", offset, writedata);
883 // write to the destination
884 WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
887 WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
891 // Update x and y (inner loop)
892 //Now it does! But crappy, crappy, crappy! !!! FIX !!! [DONE]
893 //This is less than ideal, but it works...
896 a1_x += a1_xadd, a1_y += a1_yadd;
897 a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
901 a1_y += a1_yadd, a2_y = (a2_y + a2_yadd) & a2_mask_y;
905 if (bitPos % bppSrc == 0)
906 a2_x = (a2_x + a2_xadd) & a2_mask_x;
910 a2_x = (a2_x + a2_xadd) & a2_mask_x;
911 if (bitPos % bppSrc == 0)
917 z_i[colour_index] += zadd;
919 if (GOURD || SRCSHADE)
921 gd_i[colour_index] += gd_ia;
922 //Hmm, this doesn't seem to do anything...
923 //But it is correct according to the JTRM...!
924 if ((int32)gd_i[colour_index] < 0)
925 gd_i[colour_index] = 0;
926 if (gd_i[colour_index] > 0x00FFFFFF)
927 gd_i[colour_index] = 0x00FFFFFF;//*/
929 gd_c[colour_index] += gd_ca;
930 if ((int32)gd_c[colour_index] < 0)
931 gd_c[colour_index] = 0;
932 if (gd_c[colour_index] > 0x000000FF)
933 gd_c[colour_index] = 0x000000FF;//*/
936 if (GOURD || SRCSHADE || GOURZ)
939 //This screws things up WORSE (for the BIOS opening screen)
940 // if (a1_phrase_mode || a2_phrase_mode)
941 colour_index = (colour_index + 1) & 0x03;
946 Here's the problem... The phrase mode code!
947 Blit! (00100000 -> 00148000) count: 327 x 267, A1/2_FLAGS: 00004420/00004420 [cmd: 41802E01]
948 CMD -> src: SRCEN dst: misc: a1ctl: UPDA1 UPDA2 mode: DSTA2 GOURZ ity: z-op: op: LFU_REPLACE ctrl: SRCSHADE
949 A1 step values: -327 (X), 1 (Y)
950 A2 step values: -327 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
951 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
952 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
953 A1 x/y: 28/58, A2 x/y: 28/58 Pattern: 00EA7BEA77EA77EA SRCDATA: 7BFF7BFF7BFF7BFF
955 Below fixes it, but then borks:
958 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
959 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
960 A1 step values: -15 (X), 1 (Y)
961 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
962 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
963 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
964 A1 x/y: 173/144, A2 x/y: 4052/0
966 Lesse, with pre-add we'd have:
969 00001111222233334444555566667777
972 |rolls back to here. Hmm.
975 //NOTE: The way to fix the CD BIOS is to uncomment below and comment the stuff after
976 // the phrase mode mucking around. But it fucks up everything else...
977 //#define SCREWY_CD_DEPENDENT
978 #ifdef SCREWY_CD_DEPENDENT
982 a2_y += a2_step_y;//*/
985 //New: Phrase mode taken into account! :-p
986 /* if (a1_phrase_mode) // v1
988 // Bump the pointer to the next phrase boundary
989 // Even though it works, this is crappy... Clean it up!
990 uint32 size = 64 / a1_psize;
992 // Crappy kludge... ('aligning' source to destination)
993 if (a2_phrase_mode && DSTA2)
995 uint32 extra = (a2_start >> 16) % size;
999 uint32 newx = (a1_x >> 16) / size;
1000 uint32 newxrem = (a1_x >> 16) % size;
1002 a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
1004 if (a1_phrase_mode) // v2
1006 // Bump the pointer to the next phrase boundary
1007 // Even though it works, this is crappy... Clean it up!
1008 uint32 size = 64 / a1_psize;
1010 // Crappy kludge... ('aligning' source to destination)
1011 if (a2_phrase_mode && DSTA2)
1013 uint32 extra = (a2_start >> 16) % size;
1014 a1_x += extra << 16;
1017 uint32 pixelSize = (size - 1) << 16;
1018 a1_x = (a1_x + pixelSize) & ~pixelSize;
1021 /* if (a2_phrase_mode) // v1
1023 // Bump the pointer to the next phrase boundary
1024 // Even though it works, this is crappy... Clean it up!
1025 uint32 size = 64 / a2_psize;
1027 // Crappy kludge... ('aligning' source to destination)
1028 // Prolly should do this for A1 channel as well... [DONE]
1029 if (a1_phrase_mode && !DSTA2)
1031 uint32 extra = (a1_start >> 16) % size;
1032 a2_x += extra << 16;
1035 uint32 newx = (a2_x >> 16) / size;
1036 uint32 newxrem = (a2_x >> 16) % size;
1038 a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
1040 if (a2_phrase_mode) // v1
1042 // Bump the pointer to the next phrase boundary
1043 // Even though it works, this is crappy... Clean it up!
1044 uint32 size = 64 / a2_psize;
1046 // Crappy kludge... ('aligning' source to destination)
1047 // Prolly should do this for A1 channel as well... [DONE]
1048 if (a1_phrase_mode && !DSTA2)
1050 uint32 extra = (a1_start >> 16) % size;
1051 a2_x += extra << 16;
1054 uint32 pixelSize = (size - 1) << 16;
1055 a2_x = (a2_x + pixelSize) & ~pixelSize;
1058 //Not entirely: This still mucks things up... !!! FIX !!!
1059 //Should this go before or after the phrase mode mucking around?
1060 #ifndef SCREWY_CD_DEPENDENT
1064 a2_y += a2_step_y;//*/
1068 // write values back to registers
1069 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
1070 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
1071 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
1075 void blitter_blit(uint32 cmd)
1077 //Apparently this is doing *something*, just not sure exactly what...
1078 /*if (cmd == 0x41802E01)
1080 WriteLog("BLIT: Found our blit. Was: %08X ", cmd);
1082 WriteLog("Is: %08X\n", cmd);
1085 uint32 pitchValue[4] = { 0, 1, 3, 2 };
1088 dst = (cmd >> 3) & 0x07;
1089 misc = (cmd >> 6) & 0x03;
1090 a1ctl = (cmd >> 8) & 0x7;
1091 mode = (cmd >> 11) & 0x07;
1092 ity = (cmd >> 14) & 0x0F;
1093 zop = (cmd >> 18) & 0x07;
1094 op = (cmd >> 21) & 0x0F;
1095 ctrl = (cmd >> 25) & 0x3F;
1097 // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
1098 // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
1099 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1100 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1102 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
1103 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
1105 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
1106 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
1108 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
1109 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
1111 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
1112 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
1114 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1115 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1116 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1117 //But it seems to fuck up T2K! !!! FIX !!!
1118 //Could it be sign extended??? Doesn't seem to be so according to JTRM
1119 // a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
1120 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1121 // a1_y &= 0x0FFFFFFF;
1123 // a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
1124 // According to JTRM, this must give a *whole number* of phrases in the current
1125 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1126 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1127 a1_width = ((0x04 | m) << e) >> 2;//*/
1129 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1130 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1131 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1132 //But it seems to fuck up T2K! !!! FIX !!!
1133 // a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
1134 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1135 // a2_y &= 0x0FFFFFFF;
1137 // a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
1138 // According to JTRM, this must give a *whole number* of phrases in the current
1139 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1140 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1141 a2_width = ((0x04 | m) << e) >> 2;//*/
1142 a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
1143 a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
1145 // Check for "use mask" flag
1146 if (!(REG(A2_FLAGS) & 0x8000))
1148 a2_mask_x = 0xFFFFFFFF; // must be 16.16
1149 a2_mask_y = 0xFFFFFFFF; // must be 16.16
1154 // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
1155 a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
1160 // determine a1_xadd
1161 switch (xadd_a1_control)
1164 // This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
1165 // add phrase offset to X and truncate
1170 // add pixelsize (1) to X
1174 // add zero (for those nice vertical lines)
1178 // add the contents of the increment register
1179 a1_xadd = (REG(A1_INC) << 16) | (REG(A1_FINC) & 0x0000FFFF);
1180 a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
1185 //Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801]
1186 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD
1187 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD
1188 //if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// &&
1189 // uint32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1190 //Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it...
1191 //if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801)
1192 // A1 x/y: 14368/7, A2 x/y: 150/36
1193 //This is it... The problem...
1194 //if ((a1_x >> 16) == 14368) // 14368 = $3820
1195 // return; //Lesse what we got...
1205 // determine a2_xadd
1206 switch (xadd_a2_control)
1209 // add phrase offset to X and truncate
1214 // add pixelsize (1) to X
1218 // add zero (for those nice vertical lines)
1221 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
1223 WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
1224 // add the contents of the increment register
1225 // since there is no register for a2 we just add 1
1226 //Let's do nothing, since it's not listed as a valid bit combo...
1227 // a2_xadd = 1 << 16;
1234 // Modify outer loop steps based on blitter command
1242 a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
1243 a1_step_y = (REG(A1_FSTEP) >> 16);
1246 a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
1247 a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
1250 a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
1251 a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
1253 outer_loop = n_lines;
1258 a1_clip_x = REG(A1_CLIP) & 0x7FFF,
1259 a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
1261 // This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX]
1262 // Err, this is pixel size... (and it's OK)
1263 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
1264 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
1271 for(int v=0; v<4; v++)
1272 z_i[v] = REG(PHRASEZ0 + v*4);
1276 if (GOURD || GOURZ || SRCSHADE)
1278 gd_c[0] = blitter_ram[PATTERNDATA + 6];
1279 gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
1280 | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
1282 gd_c[1] = blitter_ram[PATTERNDATA + 4];
1283 gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
1284 | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
1286 gd_c[2] = blitter_ram[PATTERNDATA + 2];
1287 gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
1288 | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
1290 gd_c[3] = blitter_ram[PATTERNDATA + 0];
1291 gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
1292 | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
1294 gouraud_add = REG(INTENSITYINC);
1296 gd_ia = gouraud_add & 0x00FFFFFF;
1297 if (gd_ia & 0x00800000)
1298 gd_ia = 0xFF000000 | gd_ia;
1300 gd_ca = (gouraud_add >> 24) & 0xFF;
1301 if (gd_ca & 0x00000080)
1302 gd_ca = 0xFFFFFF00 | gd_ca;
1305 // Bit comparitor fixing...
1308 // Determine the data flow direction...
1310 a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07));
1314 /* if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!!
1316 // Determine the data flow direction...
1324 WriteLog("Blit!\n");
1325 WriteLog(" cmd = 0x%.8x\n",cmd);
1326 WriteLog(" a1_base = %08X\n", a1_addr);
1327 WriteLog(" a1_pitch = %d\n", a1_pitch);
1328 WriteLog(" a1_psize = %d\n", a1_psize);
1329 WriteLog(" a1_width = %d\n", a1_width);
1330 WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1331 WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0);
1332 WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1333 WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1334 WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0);
1335 WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0);
1336 WriteLog(" a1_zoffs = %i\n",a1_zoffs);
1338 WriteLog(" a2_base = %08X\n", a2_addr);
1339 WriteLog(" a2_pitch = %d\n", a2_pitch);
1340 WriteLog(" a2_psize = %d\n", a2_psize);
1341 WriteLog(" a2_width = %d\n", a2_width);
1342 WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1343 WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0);
1344 WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1345 WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1346 WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0);
1347 WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0);
1348 WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x);
1349 WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y);
1350 WriteLog(" a2_zoffs = %i\n",a2_zoffs);
1352 WriteLog(" count = %d x %d\n", n_pixels, n_lines);
1354 WriteLog(" command = %08X\n", cmd);
1355 WriteLog(" dsten = %i\n",DSTEN);
1356 WriteLog(" srcen = %i\n",SRCEN);
1357 WriteLog(" patdsel = %i\n",PATDSEL);
1358 WriteLog(" color = 0x%.8x\n",REG(PATTERNDATA));
1359 WriteLog(" dcompen = %i\n",DCOMPEN);
1360 WriteLog(" bcompen = %i\n",BCOMPEN);
1361 WriteLog(" cmpdst = %i\n",CMPDST);
1362 WriteLog(" GOURZ = %i\n",GOURZ);
1363 WriteLog(" GOURD = %i\n",GOURD);
1364 WriteLog(" SRCSHADE= %i\n",SRCSHADE);
1368 //NOTE: Pitch is ignored!
1370 //This *might* be the altimeter blits (they are)...
1371 //On captured screen, x-pos for black (inner) is 259, for pink is 257
1372 //Black is short by 3, pink is short by 1...
1374 Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1375 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1376 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1377 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1378 A1 x/y: 262/124, A2 x/y: 128/0
1379 Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1380 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1381 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1382 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1383 A1 x/y: 264/117, A2 x/y: 407/0
1385 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1386 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1387 A1 step values: -10 (X), 1 (Y)
1388 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1389 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1390 A1 x/y: 262/132, A2 x/y: 129/0
1391 Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1392 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1393 A1 step values: -8 (X), 1 (Y)
1394 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1395 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1396 A1 x/y: 264/128, A2 x/y: 336/0
1398 264v vCursor ends up here...
1402 262v vCursor ends up here...
1406 Fixed! Now for more:
1408 ; This looks like the ship icon in the upper left corner...
1410 Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1411 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1412 A1 step values: -12 (X), 1 (Y)
1413 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1414 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1415 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1416 A1 x/y: 20/24, A2 x/y: 5780/0
1420 More (not sure this is a blitter problem as much as it's a GPU problem):
1421 All but the "M" are trashed...
1422 This does *NOT* look like a blitter problem, as it's rendering properly...
1423 Actually, if you look at the A1 step values, there IS a discrepancy!
1427 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1428 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1429 A1 step values: -14 (X), 1 (Y)
1430 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1431 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1432 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1433 A1 x/y: 134/144, A2 x/y: 2516/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: -13 (X), 1 (Y)
1441 A2 step values: -4 (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: 147/144, A2 x/y: 2660/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: -12 (X), 1 (Y)
1451 A2 step values: 0 (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: 160/144, A2 x/y: 3764/0
1458 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1459 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1460 A1 step values: -15 (X), 1 (Y)
1461 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1462 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1463 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1464 A1 x/y: 173/144, A2 x/y: 4052/0
1467 //extern int op_start_log;
1470 char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
1471 char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
1472 char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1473 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1474 uint32 /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
1475 a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F,
1476 zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/;
1477 uint32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1478 uint32 p1 = a1f & 0x07, p2 = a2f & 0x07,
1479 d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
1480 zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
1481 w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
1482 ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
1483 uint32 iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
1484 uint32 iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
1485 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);
1486 // 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);
1488 WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
1489 WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
1490 WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
1491 WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
1492 WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "GOURZ" : ""));
1493 WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : ""));
1494 WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
1495 WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
1496 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" : ""));
1499 WriteLog(" A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16);
1502 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);
1504 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"));
1505 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"));
1506 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));
1507 // blit_start_log = 0;
1508 // op_start_log = 1;
1511 blitter_working = 1;
1512 //#ifndef USE_GENERIC_BLITTER
1513 // if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
1515 blitter_generic(cmd);
1517 /*if (blit_start_log)
1519 if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
1521 WriteLog("\nBytes at 004D58:\n");
1522 for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
1523 WriteLog("%02X ", JaguarReadByte(i));
1524 WriteLog("\nBytes at F03000:\n");
1525 for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
1526 WriteLog("%02X ", JaguarReadByte(i));
1531 blitter_working = 0;
1533 #endif // of the #if 0 near the top...
1534 /*******************************************************************************
1535 ********************** STUFF CUT ABOVE THIS LINE! ******************************
1536 *******************************************************************************/
1538 void BlitterInit(void)
1543 void BlitterReset(void)
1545 memset(blitter_ram, 0x00, 0xA0);
1548 void BlitterDone(void)
1550 WriteLog("BLIT: Done.\n");
1553 uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1558 //This isn't cycle accurate--how to fix? !!! FIX !!!
1559 //Probably have to do some multi-threaded implementation or at least a reentrant safe implementation...
1560 if (offset == (0x38 + 3))
1561 return 0x01; // always idle
1563 // CHECK HERE ONCE THIS FIX HAS BEEN TESTED: [ ]
1565 if (offset >= 0x04 && offset <= 0x07)
1566 //This is it. I wonder if it just ignores the lower three bits?
1567 //No, this is a documented Jaguar I bug. It also bites the read at $F02230 as well...
1568 return blitter_ram[offset + 0x08]; // A1_PIXEL ($F0220C) read at $F02204
1570 if (offset >= 0x2C && offset <= 0x2F)
1571 return blitter_ram[offset + 0x04]; // A2_PIXEL ($F02230) read at $F0222C
1573 return blitter_ram[offset];
1577 uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1579 return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
1583 uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1585 return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
1588 void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1590 /*if (offset & 0xFF == 0x7B)
1591 WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
1593 /*if ((offset >= PATTERNDATA) && (offset < PATTERNDATA + 8))
1595 printf("--> %s wrote %02X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - PATTERNDATA);
1599 // This handles writes to INTENSITY0-3 by also writing them to their proper places in
1600 // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
1601 if ((offset >= 0x7C) && (offset <= 0x9B))
1605 // INTENSITY registers 0-3
1607 case 0x7D: blitter_ram[PATTERNDATA + 7] = data; break;
1608 case 0x7E: blitter_ram[SRCDATA + 6] = data; break;
1609 case 0x7F: blitter_ram[SRCDATA + 7] = data; break;
1612 case 0x81: blitter_ram[PATTERNDATA + 5] = data; break;
1613 case 0x82: blitter_ram[SRCDATA + 4] = data; break;
1614 case 0x83: blitter_ram[SRCDATA + 5] = data; break;
1617 case 0x85: blitter_ram[PATTERNDATA + 3] = data; break;
1618 case 0x86: blitter_ram[SRCDATA + 2] = data; break;
1619 case 0x87: blitter_ram[SRCDATA + 3] = data; break;
1622 case 0x89: blitter_ram[PATTERNDATA + 1] = data; break;
1623 case 0x8A: blitter_ram[SRCDATA + 0] = data; break;
1624 case 0x8B: blitter_ram[SRCDATA + 1] = data; break;
1628 case 0x8C: blitter_ram[SRCZINT + 6] = data; break;
1629 case 0x8D: blitter_ram[SRCZINT + 7] = data; break;
1630 case 0x8E: blitter_ram[SRCZFRAC + 6] = data; break;
1631 case 0x8F: blitter_ram[SRCZFRAC + 7] = data; break;
1633 case 0x90: blitter_ram[SRCZINT + 4] = data; break;
1634 case 0x91: blitter_ram[SRCZINT + 5] = data; break;
1635 case 0x92: blitter_ram[SRCZFRAC + 4] = data; break;
1636 case 0x93: blitter_ram[SRCZFRAC + 5] = data; break;
1638 case 0x94: blitter_ram[SRCZINT + 2] = data; break;
1639 case 0x95: blitter_ram[SRCZINT + 3] = data; break;
1640 case 0x96: blitter_ram[SRCZFRAC + 2] = data; break;
1641 case 0x97: blitter_ram[SRCZFRAC + 3] = data; break;
1643 case 0x98: blitter_ram[SRCZINT + 0] = data; break;
1644 case 0x99: blitter_ram[SRCZINT + 1] = data; break;
1645 case 0x9A: blitter_ram[SRCZFRAC + 0] = data; break;
1646 case 0x9B: blitter_ram[SRCZFRAC + 1] = data; break;
1650 // It looks weird, but this is how the 64 bit registers are actually handled...!
1652 else if ((offset >= SRCDATA + 0) && (offset <= SRCDATA + 3)
1653 || (offset >= DSTDATA + 0) && (offset <= DSTDATA + 3)
1654 || (offset >= DSTZ + 0) && (offset <= DSTZ + 3)
1655 || (offset >= SRCZINT + 0) && (offset <= SRCZINT + 3)
1656 || (offset >= SRCZFRAC + 0) && (offset <= SRCZFRAC + 3)
1657 || (offset >= PATTERNDATA + 0) && (offset <= PATTERNDATA + 3))
1659 blitter_ram[offset + 4] = data;
1661 else if ((offset >= SRCDATA + 4) && (offset <= SRCDATA + 7)
1662 || (offset >= DSTDATA + 4) && (offset <= DSTDATA + 7)
1663 || (offset >= DSTZ + 4) && (offset <= DSTZ + 7)
1664 || (offset >= SRCZINT + 4) && (offset <= SRCZINT + 7)
1665 || (offset >= SRCZFRAC + 4) && (offset <= SRCZFRAC + 7)
1666 || (offset >= PATTERNDATA + 4) && (offset <= PATTERNDATA + 7))
1668 blitter_ram[offset - 4] = data;
1671 blitter_ram[offset] = data;
1674 void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1676 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1678 printf("----> %s wrote %04X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1682 /* if (offset & 0xFF == A1_PIXEL && data == 14368)
1684 WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1685 extern bool doGPUDis;
1688 if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368)
1690 WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1691 extern bool doGPUDis;
1696 BlitterWriteByte(offset + 0, data >> 8, who);
1697 BlitterWriteByte(offset + 1, data & 0xFF, who);
1699 if ((offset & 0xFF) == 0x3A)
1700 // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
1701 // But then again, according to the Jaguar docs, this is correct...!
1702 /*extern int blit_start_log;
1703 extern bool doGPUDis;
1706 WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
1709 #ifdef USE_ORIGINAL_BLITTER
1710 blitter_blit(GET32(blitter_ram, 0x38));
1712 #ifdef USE_MIDSUMMER_BLITTER
1713 BlitterMidsummer(GET32(blitter_ram, 0x38));
1715 #ifdef USE_MIDSUMMER_BLITTER_MKII
1716 BlitterMidsummer2();
1721 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1723 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1725 printf("------> %s wrote %08X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1729 /* if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368)
1731 WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1732 extern bool doGPUDis;
1737 BlitterWriteWord(offset + 0, data >> 16, who);
1738 BlitterWriteWord(offset + 2, data & 0xFFFF, who);
1743 const char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1744 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1745 uint32 cmd = GET32(blitter_ram, 0x38);
1746 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1747 uint32 a1_width = ((0x04 | m) << e) >> 2;
1748 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1749 uint32 a2_width = ((0x04 | m) << e) >> 2;
1751 WriteLog("Blit!\n");
1752 WriteLog(" COMMAND = %08X\n", cmd);
1753 WriteLog(" a1_base = %08X\n", REG(A1_BASE));
1754 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),
1755 (REG(A1_FLAGS) & 0x100000 ? '1' : '0'),
1756 (REG(A1_FLAGS) & 0x080000 ? '1' : '0'),
1757 (REG(A1_FLAGS) & 0x040000 ? '1' : '0'),
1758 (REG(A1_FLAGS) & 0x020000 ? '1' : '0'),
1759 (REG(A1_FLAGS) & 0x010000 ? '1' : '0'),
1760 (REG(A1_FLAGS) & 0x004000 ? '1' : '0'),
1761 (REG(A1_FLAGS) & 0x002000 ? '1' : '0'),
1762 (REG(A1_FLAGS) & 0x001000 ? '1' : '0'),
1763 (REG(A1_FLAGS) & 0x000800 ? '1' : '0'),
1764 (REG(A1_FLAGS) & 0x000400 ? '1' : '0'),
1765 (REG(A1_FLAGS) & 0x000200 ? '1' : '0'),
1766 (REG(A1_FLAGS) & 0x000100 ? '1' : '0'),
1767 (REG(A1_FLAGS) & 0x000080 ? '1' : '0'),
1768 (REG(A1_FLAGS) & 0x000040 ? '1' : '0'),
1769 (REG(A1_FLAGS) & 0x000020 ? '1' : '0'),
1770 (REG(A1_FLAGS) & 0x000010 ? '1' : '0'),
1771 (REG(A1_FLAGS) & 0x000008 ? '1' : '0'),
1772 (REG(A1_FLAGS) & 0x000002 ? '1' : '0'),
1773 (REG(A1_FLAGS) & 0x000001 ? '1' : '0'));
1774 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1775 REG(A1_FLAGS) & 0x00003, (REG(A1_FLAGS) & 0x00038) >> 3,
1776 (REG(A1_FLAGS) & 0x001C0) >> 6, a1_width, (REG(A1_FLAGS) & 0x30000) >> 16);
1777 WriteLog(" a1_clip = %u, %u (%08X)\n", GET16(blitter_ram, A1_CLIP + 2), GET16(blitter_ram, A1_CLIP + 0), GET32(blitter_ram, A1_CLIP));
1778 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));
1779 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));
1780 WriteLog(" a1_fstep = %u, %u (%08X)\n", GET16(blitter_ram, A1_FSTEP + 2), GET16(blitter_ram, A1_FSTEP + 0), GET32(blitter_ram, A1_FSTEP));
1781 WriteLog(" a1_fpixel= %u, %u (%08X)\n", GET16(blitter_ram, A1_FPIXEL + 2), GET16(blitter_ram, A1_FPIXEL + 0), GET32(blitter_ram, A1_FPIXEL));
1782 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));
1783 WriteLog(" a1_finc = %u, %u (%08X)\n", GET16(blitter_ram, A1_FINC + 2), GET16(blitter_ram, A1_FINC + 0), GET32(blitter_ram, A1_FINC));
1785 WriteLog(" a2_base = %08X\n", REG(A2_BASE));
1786 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),
1787 (REG(A2_FLAGS) & 0x100000 ? '1' : '0'),
1788 (REG(A2_FLAGS) & 0x080000 ? '1' : '0'),
1789 (REG(A2_FLAGS) & 0x040000 ? '1' : '0'),
1790 (REG(A2_FLAGS) & 0x020000 ? '1' : '0'),
1791 (REG(A2_FLAGS) & 0x010000 ? '1' : '0'),
1792 (REG(A2_FLAGS) & 0x008000 ? '1' : '0'),
1793 (REG(A2_FLAGS) & 0x004000 ? '1' : '0'),
1794 (REG(A2_FLAGS) & 0x002000 ? '1' : '0'),
1795 (REG(A2_FLAGS) & 0x001000 ? '1' : '0'),
1796 (REG(A2_FLAGS) & 0x000800 ? '1' : '0'),
1797 (REG(A2_FLAGS) & 0x000400 ? '1' : '0'),
1798 (REG(A2_FLAGS) & 0x000200 ? '1' : '0'),
1799 (REG(A2_FLAGS) & 0x000100 ? '1' : '0'),
1800 (REG(A2_FLAGS) & 0x000080 ? '1' : '0'),
1801 (REG(A2_FLAGS) & 0x000040 ? '1' : '0'),
1802 (REG(A2_FLAGS) & 0x000020 ? '1' : '0'),
1803 (REG(A2_FLAGS) & 0x000010 ? '1' : '0'),
1804 (REG(A2_FLAGS) & 0x000008 ? '1' : '0'),
1805 (REG(A2_FLAGS) & 0x000002 ? '1' : '0'),
1806 (REG(A2_FLAGS) & 0x000001 ? '1' : '0'));
1807 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1808 REG(A2_FLAGS) & 0x00003, (REG(A2_FLAGS) & 0x00038) >> 3,
1809 (REG(A2_FLAGS) & 0x001C0) >> 6, a2_width, (REG(A2_FLAGS) & 0x30000) >> 16);
1810 WriteLog(" a2_mask = %u, %u (%08X)\n", GET16(blitter_ram, A2_MASK + 2), GET16(blitter_ram, A2_MASK + 0), GET32(blitter_ram, A2_MASK));
1811 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));
1812 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));
1814 WriteLog(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
1816 WriteLog(" SRCEN = %s\n", (SRCEN ? "1" : "0"));
1817 WriteLog(" SRCENZ = %s\n", (SRCENZ ? "1" : "0"));
1818 WriteLog(" SRCENX = %s\n", (SRCENX ? "1" : "0"));
1819 WriteLog(" DSTEN = %s\n", (DSTEN ? "1" : "0"));
1820 WriteLog(" DSTENZ = %s\n", (DSTENZ ? "1" : "0"));
1821 WriteLog(" DSTWRZ = %s\n", (DSTWRZ ? "1" : "0"));
1822 WriteLog(" CLIPA1 = %s\n", (CLIPA1 ? "1" : "0"));
1823 WriteLog(" UPDA1F = %s\n", (UPDA1F ? "1" : "0"));
1824 WriteLog(" UPDA1 = %s\n", (UPDA1 ? "1" : "0"));
1825 WriteLog(" UPDA2 = %s\n", (UPDA2 ? "1" : "0"));
1826 WriteLog(" DSTA2 = %s\n", (DSTA2 ? "1" : "0"));
1827 WriteLog(" ZOP = %s %s %s\n", (Z_OP_INF ? "<" : ""), (Z_OP_EQU ? "=" : ""), (Z_OP_SUP ? ">" : ""));
1828 WriteLog("--LFUFUNC = %s\n", opStr[(cmd >> 21) & 0x0F]);
1829 WriteLog("| PATDSEL = %s (PD=%08X%08X)\n", (PATDSEL ? "1" : "0"), REG(PATTERNDATA), REG(PATTERNDATA + 4));
1830 WriteLog("--ADDDSEL = %s\n", (ADDDSEL ? "1" : "0"));
1831 WriteLog(" CMPDST = %s\n", (CMPDST ? "1" : "0"));
1832 WriteLog(" BCOMPEN = %s\n", (BCOMPEN ? "1" : "0"));
1833 WriteLog(" DCOMPEN = %s\n", (DCOMPEN ? "1" : "0"));
1834 WriteLog(" TOPBEN = %s\n", (TOPBEN ? "1" : "0"));
1835 WriteLog(" TOPNEN = %s\n", (TOPNEN ? "1" : "0"));
1836 WriteLog(" BKGWREN = %s\n", (BKGWREN ? "1" : "0"));
1837 WriteLog(" GOURD = %s (II=%08X, SD=%08X%08X)\n", (GOURD ? "1" : "0"), REG(INTENSITYINC), REG(SRCDATA), REG(SRCDATA + 4));
1838 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),
1839 REG(SRCZINT), REG(SRCZINT + 4), REG(SRCZFRAC), REG(SRCZFRAC + 4));
1840 WriteLog(" SRCSHADE = %s\n", (SRCSHADE ? "1" : "0"));
1844 #ifdef USE_MIDSUMMER_BLITTER
1846 // Here's an attempt to write a blitter that conforms to the Midsummer specs--since
1847 // it's supposedly backwards compatible, it should work well...
1849 //#define LOG_BLITTER_MEMORY_ACCESSES
1851 #define DATINIT (false)
1852 #define TXTEXT (false)
1853 #define POLYGON (false)
1855 void BlitterMidsummer(uint32 cmd)
1857 uint32 outer_loop, inner_loop, a1_addr, a2_addr;
1858 int32 a1_x, a1_y, a2_x, a2_y, a1_width, a2_width;
1859 uint8 a1_phrase_mode, a2_phrase_mode;
1861 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1862 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1863 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1864 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1865 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1866 a1_width = ((0x04 | m) << e) >> 2;//*/
1867 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1868 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1869 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1870 a2_width = ((0x04 | m) << e) >> 2;//*/
1872 a1_phrase_mode = a2_phrase_mode = 0;
1874 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
1877 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
1880 #define INNER0 (inner_loop == 0)
1881 #define OUTER0 (outer_loop == 0)
1883 // $01800005 has SRCENX, may have to investigate further...
1884 // $00011008 has GOURD & DSTEN.
1885 // $41802F41 has SRCSHADE, CLIPA1
1886 /*bool logBlit = false;
1887 if (cmd != 0x00010200 && cmd != 0x01800001 && cmd != 0x01800005
1888 && cmd != 0x00011008 && cmd !=0x41802F41)
1894 uint64 srcData = GET64(blitter_ram, SRCDATA), srcXtraData,
1895 dstData = GET64(blitter_ram, DSTDATA), writeData;
1896 uint32 srcAddr, dstAddr;
1897 uint8 bitCount, a1PixelSize, a2PixelSize;
1899 // JTRM says phrase mode only works for 8BPP or higher, so let's try this...
1900 uint32 phraseOffset[8] = { 8, 8, 8, 8, 4, 2, 0, 0 };
1901 uint8 pixelShift[8] = { 3, 2, 1, 0, 1, 2, 0, 0 };
1903 a1PixelSize = (blitter_ram[A1_FLAGS + 3] >> 3) & 0x07;
1904 a2PixelSize = (blitter_ram[A2_FLAGS + 3] >> 3) & 0x07;
1906 outer_loop = GET16(blitter_ram, PIXLINECOUNTER + 0);
1908 if (outer_loop == 0)
1909 outer_loop = 0x10000;
1911 // We just list the states here and jump from state to state in order to
1912 // keep things somewhat clear. Optimization/cleanups later.
1914 //idle: // Blitter is idle, and will not perform any bus activity
1916 idle Blitter is off the bus, and no activity takes place.
1917 if GO if DATINIT goto init_if
1926 inner Inner loop is active, read and write cycles are performed
1928 inner: // Run inner loop state machine (asserts step from its idle state)
1929 inner_loop = GET16(blitter_ram, PIXLINECOUNTER + 2);
1931 if (inner_loop == 0)
1932 inner_loop = 0x10000;
1935 ------------------------------
1936 idle: Inactive, blitter is idle or passing round outer loop
1937 idle Another state in the outer loop is active. No bus transfers are performed.
1939 if SRCENX goto sreadx
1940 else if TXTEXT goto txtread
1941 else if SRCEN goto sread
1942 else if DSTEN goto dread
1943 else if DSTENZ goto dzread
1960 sreadx Extra source data read at the start of an inner loop pass.
1962 if SRCENZ goto szreadx
1963 else if TXTEXT goto txtread
1964 else if SRCEN goto sread
1965 else if DSTEN goto dread
1966 else if DSTENZ goto dzread
1969 sreadx: // Extra source data read
1984 szreadx Extra source Z read as the start of an inner loop pass.
1986 if TXTEXT goto txtread
1989 szreadx: // Extra source Z read
1996 txtread Read texture data from external memory. This state is only used for external texture.
1997 TEXTEXT is the condition TEXTMODE=1.
2000 else if DSTEN goto dread
2001 else if DSTENZ goto dzread
2004 txtread: // Read external texture data
2015 sread Source data read.
2017 if SRCENZ goto szread
2018 else if DSTEN goto dread
2019 else if DSTENZ goto dzread
2022 sread: // Source data read
2023 //The JTRM doesn't really specify the internal structure of the source data read, but I would
2024 //imagine that if it's in phrase mode that it starts by reading the phrase that the window is
2025 //pointing at. Likewise, the pixel (if in BPP 1, 2 & 4, chopped) otherwise. It probably still
2026 //transfers an entire phrase even in pixel mode.
2027 //Odd thought: Does it expand, e.g., 1 BPP pixels into 32 BPP internally? Hmm...
2030 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
2031 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
2032 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
2033 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
2034 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
2035 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
2036 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
2037 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
2038 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
2039 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
2040 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
2041 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
2042 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
2043 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
2046 a1_width = ((0x04 | m) << e) >> 2;
2047 a2_width = ((0x04 | m) << e) >> 2;
2049 // write values back to registers
2050 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
2051 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
2052 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
2054 // Calculate the address to be read...
2056 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2057 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2058 //for 8BPP. !!! FIX !!!
2059 srcAddr = (DSTA2 ? a1_addr : a2_addr);
2061 /* if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2063 srcAddr += (((DSTA2 ? a1_x : a2_x) >> 16)
2064 + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width)));
2068 // uint32 pixAddr = ((DSTA2 ? a1_x : a2_x) >> 16)
2069 // + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2070 int32 pixAddr = (int16)((DSTA2 ? a1_x : a2_x) >> 16)
2071 + ((int16)((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2073 if ((DSTA2 ? a1PixelSize : a2PixelSize) < 3)
2074 pixAddr >>= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2075 else if ((DSTA2 ? a1PixelSize : a2PixelSize) > 3)
2076 pixAddr <<= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2083 if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2085 srcData = ((uint64)JaguarReadLong(srcAddr, BLITTER) << 32)
2086 | (uint64)JaguarReadLong(srcAddr + 4, BLITTER);
2090 //1,2,&4BPP are wrong here... !!! FIX !!!
2091 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 0) // 1 BPP
2092 srcData = JaguarReadByte(srcAddr, BLITTER);
2093 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 1) // 2 BPP
2094 srcData = JaguarReadByte(srcAddr, BLITTER);
2095 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 2) // 4 BPP
2096 srcData = JaguarReadByte(srcAddr, BLITTER);
2097 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 3) // 8 BPP
2098 srcData = JaguarReadByte(srcAddr, BLITTER);
2099 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 4) // 16 BPP
2100 srcData = JaguarReadWord(srcAddr, BLITTER);
2101 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 5) // 32 BPP
2102 srcData = JaguarReadLong(srcAddr, BLITTER);
2105 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2107 WriteLog("BLITTER: srcAddr=%08X, srcData=%08X %08X\n", srcAddr, (uint32)(srcData >> 32), (uint32)(srcData & 0xFFFFFFFF));
2119 szread: // Source Z read
2121 szread Source Z read.
2124 else if DSTENZ goto dzread
2134 dread: // Destination data read
2136 dread Destination data read.
2138 if DSTENZ goto dzread
2141 // Calculate the destination address to be read...
2143 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2144 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2145 //for 8BPP. !!! FIX !!!
2146 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2149 // uint32 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2150 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2151 int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
2152 + ((int16)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2154 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2155 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2156 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2157 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2164 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2166 dstData = ((uint64)JaguarReadLong(srcAddr, BLITTER) << 32)
2167 | (uint64)JaguarReadLong(srcAddr + 4, BLITTER);
2171 //1,2,&4BPP are wrong here... !!! FIX !!!
2172 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2173 dstData = JaguarReadByte(dstAddr, BLITTER);
2174 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2175 dstData = JaguarReadByte(dstAddr, BLITTER);
2176 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2177 dstData = JaguarReadByte(dstAddr, BLITTER);
2178 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2179 dstData = JaguarReadByte(dstAddr, BLITTER);
2180 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2181 dstData = JaguarReadWord(dstAddr, BLITTER);
2182 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2183 dstData = JaguarReadLong(dstAddr, BLITTER);
2186 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2188 WriteLog("BLITTER (dread): dstAddr=%08X, dstData=%08X %08X\n", dstAddr, (uint32)(dstData >> 32), (uint32)(dstData & 0xFFFFFFFF));
2196 dzread: // Destination Z read
2198 dzread Destination Z read.
2203 dwrite: // Destination data write
2205 dwrite Destination write. Every pass round the inner loop must go through this state..
2207 if DSTWRZ goto dzwrite
2208 else if INNER0 goto idle
2209 else if TXTEXT goto txtread
2210 else if SRCEN goto sread
2211 else if DSTEN goto dread
2212 else if DSTENZ goto dzread
2221 a1_xadd = 1.000000 (phrase=0)
2230 a2_xadd = 1.000000 (phrase=1)
2234 a2_mask_x= 0xFFFFFFFF
2235 a2_mask_y= 0xFFFFFFFF
2245 --LFUFUNC = LFU_CLEAR
2246 | PATDSEL = 1 (PD=77C7 7700 7700 7700)
2248 GOURD = 1 (II=00FC 1A00, SD=FF00 0000 0000 0000)
2251 //Still need to do CLIPA1 and SRCSHADE and GOURD and GOURZ...
2253 // Check clipping...
2257 uint16 x = a1_x >> 16, y = a1_y >> 16;
2259 if (x >= GET16(blitter_ram, A1_CLIP + 2) || y >= GET16(blitter_ram, A1_CLIP))
2263 // Figure out what gets written...
2267 writeData = GET64(blitter_ram, PATTERNDATA);
2268 //GOURD works properly only in 16BPP mode...
2269 //SRCDATA holds the intensity fractions...
2270 //Does GOURD get calc'ed here or somewhere else???
2271 //Temporary testing kludge...
2273 // writeData >>= 48;
2274 // writeData = 0xFF88;
2275 //OK, it's not writing an entire strip of pixels... Why?
2276 //bad incrementing, that's why!
2280 // Apparently this only works with 16-bit pixels. Not sure if it works in phrase mode either.
2281 //Also, take TOPBEN & TOPNEN into account here as well...
2282 writeData = srcData + dstData;
2284 else // LFUFUNC is the default...
2289 writeData |= ~srcData & ~dstData;
2291 writeData |= ~srcData & dstData;
2293 writeData |= srcData & ~dstData;
2295 writeData |= srcData & dstData;
2298 // Calculate the address to be written...
2300 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2302 /* if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2304 //both of these calculate the wrong address because they don't take into account
2306 dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2307 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2311 /* dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2312 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));*/
2313 // uint32 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2314 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2315 int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
2316 + ((int16)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2318 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2319 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2320 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2321 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2328 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2330 JaguarWriteLong(dstAddr, writeData >> 32, BLITTER);
2331 JaguarWriteLong(dstAddr + 4, writeData & 0xFFFFFFFF, BLITTER);
2335 //1,2,&4BPP are wrong here... !!! FIX !!!
2336 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2337 JaguarWriteByte(dstAddr, writeData, BLITTER);
2338 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2339 JaguarWriteByte(dstAddr, writeData, BLITTER);
2340 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2341 JaguarWriteByte(dstAddr, writeData, BLITTER);
2342 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2343 JaguarWriteByte(dstAddr, writeData, BLITTER);
2344 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2345 JaguarWriteWord(dstAddr, writeData, BLITTER);
2346 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2347 JaguarWriteLong(dstAddr, writeData, BLITTER);
2350 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2352 WriteLog("BLITTER: dstAddr=%08X, writeData=%08X %08X\n", dstAddr, (uint32)(writeData >> 32), (uint32)(writeData & 0xFFFFFFFF));
2355 inhibitWrite://Should this go here? or on the other side of the X/Y incrementing?
2356 //Seems OK here... for now.
2358 // Do funky X/Y incrementation here as well... !!! FIX !!!
2360 // Handle A1 channel stepping
2362 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
2363 a1_x += phraseOffset[a1PixelSize] << 16;
2364 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 1)
2365 a1_x += (blitter_ram[A1_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2366 /* else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 2)
2368 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 3)
2370 //Always add the FINC here??? That was the problem with the BIOS screen... So perhaps.
2371 a1_x += GET16(blitter_ram, A1_FINC + 2);
2372 a1_y += GET16(blitter_ram, A1_FINC + 0);
2374 a1_x += GET16(blitter_ram, A1_INC + 2) << 16;
2375 a1_y += GET16(blitter_ram, A1_INC + 0) << 16;
2378 if ((blitter_ram[A1_FLAGS + 1] & 0x04) && (blitter_ram[A1_FLAGS + 1] & 0x03 != 3))
2379 a1_y += (blitter_ram[A1_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2381 // Handle A2 channel stepping
2383 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
2384 a2_x += phraseOffset[a2PixelSize] << 16;
2385 else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 1)
2386 a2_x += (blitter_ram[A2_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2387 /* else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 2)
2390 if (blitter_ram[A2_FLAGS + 1] & 0x04)
2391 a2_y += (blitter_ram[A2_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2393 //Need to fix this so that it subtracts (saturating, of course) the correct number of pixels
2394 //in phrase mode... !!! FIX !!! [DONE]
2395 //Need to fix this so that it counts down the correct item. Does it count the
2396 //source or the destination phrase mode???
2397 //It shouldn't matter, because we *should* end up processing the same amount
2398 //the same number of pixels... Not sure though.
2399 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2401 if (inner_loop < phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize])
2404 inner_loop -= phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize];
2425 dzwrite: // Destination Z write
2427 dzwrite Destination Z write.
2430 else if TXTEXT goto txtread
2431 else if SRCEN goto sread
2432 else if DSTEN goto dread
2433 else if DSTENZ goto dzread
2450 ------------------------------
2451 if INDONE if OUTER0 goto idle
2452 else if UPDA1F goto a1fupdate
2453 else if UPDA1 goto a1update
2454 else if GOURZ.POLYGON goto zfupdate
2455 else if UPDA2 goto a2update
2456 else if DATINIT goto init_if
2469 //kill this, for now...
2470 // else if (GOURZ.POLYGON)
2479 a1fupdate: // Update A1 pointer fractions and more (see below)
2481 a1fupdate A1 step fraction is added to A1 pointer fraction
2482 POLYGON true: A1 step delta X and Y fraction parts are added to the A1
2483 step X and Y fraction parts (the value prior to this add is used for
2484 the step to pointer add).
2485 POLYGON true: inner count step fraction is added to the inner count
2487 POLYGON.GOURD true: the I fraction step is added to the computed
2488 intensity fraction parts +
2489 POLYGON.GOURD true: the I fraction step delta is added to the I
2494 #define A1_PIXEL ((uint32)0x0C) // Integer part of the pixel (Y.i and X.i)
2495 #define A1_STEP ((uint32)0x10) // Integer part of the step
2496 #define A1_FSTEP ((uint32)0x14) // Fractional part of the step
2497 #define A1_FPIXEL ((uint32)0x18) // Fractional part of the pixel (Y.f and X.f)
2500 // This is all kinda murky. All we have are the Midsummer docs to give us any guidance,
2501 // and it's incomplete or filled with errors (like above). Aarrrgggghhhhh!
2503 //This isn't right. Is it? I don't think the fractional parts are signed...
2504 // a1_x += (int32)((int16)GET16(blitter_ram, A1_FSTEP + 2));
2505 // a1_y += (int32)((int16)GET16(blitter_ram, A1_FSTEP + 0));
2506 a1_x += GET16(blitter_ram, A1_FSTEP + 2);
2507 a1_y += GET16(blitter_ram, A1_FSTEP + 0);
2511 a1update: // Update A1 pointer integers
2513 a1update A1 step is added to A1 pointer, with carry from the fractional add
2514 POLYGON true: A1 step delta X and Y integer parts are added to the A1
2515 step X and Y integer parts, with carry from the corresponding
2516 fractional part add (again, the value prior to this add is used for
2517 the step to pointer add).
2518 POLYGON true: inner count step is added to the inner count, with carry
2519 POLYGON.GOURD true: the I step is added to the computed intensities,
2521 POLYGON.GOURD true: the I step delta is added to the I step, with
2522 carry the texture X and Y step delta values are added to the X and Y
2524 if GOURZ.POLYGON goto zfupdate
2525 else if UPDA2 goto a2update
2526 else if DATINIT goto init_if
2529 a1_x += (int32)(GET16(blitter_ram, A1_STEP + 2) << 16);
2530 a1_y += (int32)(GET16(blitter_ram, A1_STEP + 0) << 16);
2533 //kill this, for now...
2534 // if (GOURZ.POLYGON)
2544 zfupdate: // Update computed Z step fractions
2546 zfupdate the Z fraction step is added to the computed Z fraction parts +
2547 the Z fraction step delta is added to the Z fraction step
2552 zupdate: // Update computed Z step integers
2554 zupdate the Z step is added to the computed Zs, with carry +
2555 the Z step delta is added to the Z step, with carry
2556 if UPDA2 goto a2update
2557 else if DATINIT goto init_if
2567 a2update: // Update A2 pointer
2569 a2update A2 step is added to the A2 pointer
2570 if DATINIT goto init_if
2573 a2_x += (int32)(GET16(blitter_ram, A2_STEP + 2) << 16);
2574 a2_y += (int32)(GET16(blitter_ram, A2_STEP + 0) << 16);
2582 init_if: // Initialise intensity fractions and texture X
2584 init_if Initialise the fractional part of the computed intensity fields, from
2585 the increment and step registers. The texture X integer and fractional
2586 parts can also be initialised.
2591 init_ii: // Initialise intensity integers and texture Y
2593 init_ii Initialise the integer part of the computed intensity, and texture Y
2594 integer and fractional parts
2595 if GOURZ goto init_zf
2603 init_zf: // Initialise Z fractions
2605 init_zf Initialise the fractional part of the computed Z fields.
2610 init_zi: // Initialise Z integers
2612 init_zi Initialise the integer part of the computed Z fields.
2619 The outer loop state machine fires off the inner loop, and controls the updating
2620 process between passes through the inner loop.
2622 + -- these functions are irrelevant if the DATINIT function is enabled, which it
2625 All these states will complete in one clock cycle, with the exception of the idle
2626 state, which means the blitter is quiescent; and the inner state, which takes as
2627 long as is required to complete one strip of pixels. It is therefore possible for
2628 the blitter to spend a maximum of nine clock cycles of inactivity between passes
2629 through the inner loop.
2639 // Here's attempt #2--taken from the Oberon chip specs!
2642 #ifdef USE_MIDSUMMER_BLITTER_MKII
2644 void ADDRGEN(uint32 &, uint32 &, bool, bool,
2645 uint16, uint16, uint32, uint8, uint8, uint8, uint8,
2646 uint16, uint16, uint32, uint8, uint8, uint8, uint8);
2647 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
2648 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
2649 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
2650 uint32 zinc, uint32 zstep);
2651 void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh);
2652 void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
2653 int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
2654 int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
2655 bool adda_yconst, bool addareg, bool suba_x, bool suba_y);
2656 void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
2657 int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y);
2658 void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel);
2659 void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
2660 uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y);
2661 void DATA(uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
2662 bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
2663 uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 &patd, bool patdadd,
2664 bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
2665 bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize,
2666 uint64 &srcz, uint64 dstz, uint32 zinc);
2667 void COMP_CTRL(uint8 &dbinh, bool &nowrite,
2668 bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
2669 uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp);
2670 #define VERBOSE_BLITTER_LOGGING
2671 bool logBlit = false;
2673 void BlitterMidsummer2(void)
2675 // Here's what the specs say the state machine does. Note that this can probably be
2676 // greatly simplified (also, it's different from what John has in his Oberon docs):
2677 //Will remove stuff that isn't in Jaguar I once fully described (stuff like texture won't
2678 //be described here at all)...
2680 uint32 cmd = GET32(blitter_ram, COMMAND);
2684 cmd != 0x00010200 && // PATDSEL
2685 cmd != 0x01800001 // SRCEN LFUFUNC=C
2686 && cmd != 0x01800005
2687 //Boot ROM ATARI letters:
2688 && cmd != 0x00011008 // DSTEN GOURD PATDSEL
2689 //Boot ROM spinning cube:
2690 && cmd != 0x41802F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
2692 && cmd != 0x01800E01 // SRCEN UPDA1 UPDA2 DSTA2 LFUFUNC=C
2693 //T2K TEMPEST letters:
2694 && cmd != 0x09800741 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 LFUFUNC=C DCOMPEN
2695 //Static letters on Cybermorph intro screen:
2696 && cmd != 0x09800609 // SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
2697 //Static pic on title screen:
2698 && cmd != 0x01800601 // SRCEN UPDA1 UPDA2 LFUFUNC=C
2699 //Turning letters on Cybermorph intro screen:
2700 // && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2701 && cmd != 0x00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
2702 && cmd != 0x09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
2703 && cmd != 0x09800209 // SRCEN DSTEN UPDA1 LFUFUNC=C DCOMPEN
2704 && cmd != 0x00011200 // UPDA1 GOURD PATDSEL
2705 //Start of Hover Strike (clearing screen):
2706 && cmd != 0x00010000 // PATDSEL
2707 //Hover Strike text:
2708 && cmd != 0x1401060C // SRCENX DSTEN UPDA1 UPDA2 PATDSEL BCOMPEN BKGWREN
2709 //Hover Strike 3D stuff
2710 && cmd != 0x01902839 // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2711 //Hover Strike darkening on intro to play (briefing) screen
2712 && cmd != 0x00020208 // DSTEN UPDA1 ADDDSEL
2713 //Trevor McFur stuff:
2714 && cmd != 0x05810601 // SRCEN UPDA1 UPDA2 PATDSEL BCOMPEN
2715 && cmd != 0x01800201 // SRCEN UPDA1 LFUFUNC=C
2717 && cmd != 0x00011000 // GOURD PATDSEL
2718 && cmd != 0x00011040 // CLIP_A1 GOURD PATDSEL
2720 && cmd != 0x01800000 // LFUFUNC=C
2721 && cmd != 0x01800401 //
2722 && cmd != 0x01800040 //
2723 && cmd != 0x00020008 //
2724 // && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2728 if (blit_start_log == 0) // Wait for the signal...
2729 logBlit = false;//*/
2731 Some T2K unique blits:
2732 logBlit = F, cmd = 00010200 *
2733 logBlit = F, cmd = 00011000
2734 logBlit = F, cmd = 00011040
2735 logBlit = F, cmd = 01800005 *
2736 logBlit = F, cmd = 09800741 *
2738 Hover Strike mission selection screen:
2739 Blit! (CMD = 01902839) // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2741 Checkered Flag blits in the screw up zone:
2742 Blit! (CMD = 01800001) // SRCEN LFUFUNC=C
2743 Blit! (CMD = 01800000) // LFUFUNC=C
2744 Blit! (CMD = 00010000) // PATDSEL
2746 Wolfenstein 3D in the fuckup zone:
2747 Blit! (CMD = 01800000) // LFUFUNC=C
2750 //printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2755 Blit! (CMD = 00011040)
2756 Flags: CLIP_A1 GOURD PATDSEL
2758 a1_base = 00100000, a2_base = 0081F6A8
2759 a1_x = 00A7, a1_y = 0014, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0001, a2_y = 0000
2760 a1_step_x = FE80, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFF8, a2_step_y = 0001
2761 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
2762 a1_win_x = 0180, a1_win_y = 0118, a2_mask_x = 0000, a2_mask_y = 0000
2763 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
2764 a1_pixsize = 4, a2_pixsize = 4
2768 if (cmd == 0x00011040
2769 && (GET16(blitter_ram, A1_PIXEL + 2) == 0x00A7) && (GET16(blitter_ram, A1_PIXEL + 0) == 0x0014)
2770 && (GET16(blitter_ram, A2_PIXEL + 2) == 0x0001) && (GET16(blitter_ram, A2_PIXEL + 0) == 0x0000)
2771 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 18))
2774 // Line states passed in via the command register
2776 bool srcen = (SRCEN), srcenx = (SRCENX), srcenz = (SRCENZ),
2777 dsten = (DSTEN), dstenz = (DSTENZ), dstwrz = (DSTWRZ), clip_a1 = (CLIPA1),
2778 upda1 = (UPDA1), upda1f = (UPDA1F), upda2 = (UPDA2), dsta2 = (DSTA2),
2779 gourd = (GOURD), gourz = (GOURZ), topben = (TOPBEN), topnen = (TOPNEN),
2780 patdsel = (PATDSEL), adddsel = (ADDDSEL), cmpdst = (CMPDST), bcompen = (BCOMPEN),
2781 dcompen = (DCOMPEN), bkgwren = (BKGWREN), srcshade = (SRCSHADE);
2783 uint8 zmode = (cmd & 0x01C0000) >> 18, lfufunc = (cmd & 0x1E00000) >> 21;
2785 //Where to find various lines:
2787 // gourd -> dcontrol, inner, outer, state
2788 // gourz -> dcontrol, inner, outer, state
2789 // cmpdst -> blit, data, datacomp, state
2790 // bcompen -> acontrol, inner, mcontrol, state
2791 // dcompen -> inner, state
2792 // bkgwren -> inner, state
2793 // srcshade -> dcontrol, inner, state
2794 // adddsel -> dcontrol
2795 //NOTE: ADDDSEL takes precedence over PATDSEL, PATDSEL over LFU_FUNC
2796 #ifdef VERBOSE_BLITTER_LOGGING
2799 char zfs[512], lfus[512];
2800 zfs[0] = lfus[0] = 0;
2801 if (dstwrz || dstenz || gourz)
2802 sprintf(zfs, " ZMODE=%X", zmode);
2803 if (!(patdsel || adddsel))
2804 sprintf(lfus, " LFUFUNC=%X", lfufunc);
2805 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,
2806 (srcen ? " SRCEN" : ""), (srcenx ? " SRCENX" : ""), (srcenz ? " SRCENZ" : ""),
2807 (dsten ? " DSTEN" : ""), (dstenz ? " DSTENZ" : ""), (dstwrz ? " DSTWRZ" : ""),
2808 (clip_a1 ? " CLIP_A1" : ""), (upda1 ? " UPDA1" : ""), (upda1f ? " UPDA1F" : ""),
2809 (upda2 ? " UPDA2" : ""), (dsta2 ? " DSTA2" : ""), (gourd ? " GOURD" : ""),
2810 (gourz ? " GOURZ" : ""), (topben ? " TOPBEN" : ""), (topnen ? " TOPNEN" : ""),
2811 (patdsel ? " PATDSEL" : ""), (adddsel ? " ADDDSEL" : ""), zfs, lfus, (cmpdst ? " CMPDST" : ""),
2812 (bcompen ? " BCOMPEN" : ""), (dcompen ? " DCOMPEN" : ""), (bkgwren ? " BKGWREN" : ""),
2813 (srcshade ? " SRCSHADE" : ""));
2814 printf(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
2819 // Lines that don't exist in Jaguar I (and will never be asserted)
2821 bool polygon = false, datinit = false, a1_stepld = false, a2_stepld = false, ext_int = false;
2822 bool istepadd = false, istepfadd = false, finneradd = false, inneradd = false;
2823 bool zstepfadd = false, zstepadd = false;
2825 // Various state lines (initial state--basically the reset state of the FDSYNCs)
2827 bool go = true, idle = true, inner = false, a1fupdate = false, a1update = false,
2828 zfupdate = false, zupdate = false, a2update = false, init_if = false, init_ii = false,
2829 init_zf = false, init_zi = false;
2831 bool outer0 = false, indone = false;
2833 bool idlei, inneri, a1fupdatei, a1updatei, zfupdatei, zupdatei, a2updatei, init_ifi, init_iii,
2836 bool notgzandp = !(gourz && polygon);
2838 // Various registers set up by user
2840 uint16 ocount = GET16(blitter_ram, PIXLINECOUNTER);
2841 uint8 a1_pitch = blitter_ram[A1_FLAGS + 3] & 0x03;
2842 uint8 a2_pitch = blitter_ram[A2_FLAGS + 3] & 0x03;
2843 uint8 a1_pixsize = (blitter_ram[A1_FLAGS + 3] & 0x38) >> 3;
2844 uint8 a2_pixsize = (blitter_ram[A2_FLAGS + 3] & 0x38) >> 3;
2845 uint8 a1_zoffset = (GET16(blitter_ram, A1_FLAGS + 2) >> 6) & 0x07;
2846 uint8 a2_zoffset = (GET16(blitter_ram, A2_FLAGS + 2) >> 6) & 0x07;
2847 uint8 a1_width = (blitter_ram[A1_FLAGS + 2] >> 1) & 0x3F;
2848 uint8 a2_width = (blitter_ram[A2_FLAGS + 2] >> 1) & 0x3F;
2849 bool a2_mask = blitter_ram[A2_FLAGS + 2] & 0x80;
2850 uint8 a1addx = blitter_ram[A1_FLAGS + 1] & 0x03, a2addx = blitter_ram[A2_FLAGS + 1] & 0x03;
2851 bool a1addy = blitter_ram[A1_FLAGS + 1] & 0x04, a2addy = blitter_ram[A2_FLAGS + 1] & 0x04;
2852 bool a1xsign = blitter_ram[A1_FLAGS + 1] & 0x08, a2xsign = blitter_ram[A2_FLAGS + 1] & 0x08;
2853 bool a1ysign = blitter_ram[A1_FLAGS + 1] & 0x10, a2ysign = blitter_ram[A2_FLAGS + 1] & 0x10;
2854 uint32 a1_base = GET32(blitter_ram, A1_BASE) & 0xFFFFFFF8; // Phrase aligned by ignoring bottom 3 bits
2855 uint32 a2_base = GET32(blitter_ram, A2_BASE) & 0xFFFFFFF8;
2857 uint16 a1_win_x = GET16(blitter_ram, A1_CLIP + 2) & 0x7FFF;
2858 uint16 a1_win_y = GET16(blitter_ram, A1_CLIP + 0) & 0x7FFF;
2859 int16 a1_x = (int16)GET16(blitter_ram, A1_PIXEL + 2);
2860 int16 a1_y = (int16)GET16(blitter_ram, A1_PIXEL + 0);
2861 int16 a1_step_x = (int16)GET16(blitter_ram, A1_STEP + 2);
2862 int16 a1_step_y = (int16)GET16(blitter_ram, A1_STEP + 0);
2863 uint16 a1_stepf_x = GET16(blitter_ram, A1_FSTEP + 2);
2864 uint16 a1_stepf_y = GET16(blitter_ram, A1_FSTEP + 0);
2865 uint16 a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
2866 uint16 a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
2867 int16 a1_inc_x = (int16)GET16(blitter_ram, A1_INC + 2);
2868 int16 a1_inc_y = (int16)GET16(blitter_ram, A1_INC + 0);
2869 uint16 a1_incf_x = GET16(blitter_ram, A1_FINC + 2);
2870 uint16 a1_incf_y = GET16(blitter_ram, A1_FINC + 0);
2872 int16 a2_x = (int16)GET16(blitter_ram, A2_PIXEL + 2);
2873 int16 a2_y = (int16)GET16(blitter_ram, A2_PIXEL + 0);
2874 uint16 a2_mask_x = GET16(blitter_ram, A2_MASK + 2);
2875 uint16 a2_mask_y = GET16(blitter_ram, A2_MASK + 0);
2876 int16 a2_step_x = (int16)GET16(blitter_ram, A2_STEP + 2);
2877 int16 a2_step_y = (int16)GET16(blitter_ram, A2_STEP + 0);
2879 uint64 srcd1 = GET64(blitter_ram, SRCDATA);
2881 uint64 dstd = GET64(blitter_ram, DSTDATA);
2882 uint64 patd = GET64(blitter_ram, PATTERNDATA);
2883 uint32 iinc = GET32(blitter_ram, INTENSITYINC);
2884 uint64 srcz1 = GET64(blitter_ram, SRCZINT);
2885 uint64 srcz2 = GET64(blitter_ram, SRCZFRAC);
2886 uint64 dstz = GET64(blitter_ram, DSTZ);
2887 uint32 zinc = GET32(blitter_ram, ZINC);
2888 uint32 collision = GET32(blitter_ram, COLLISIONCTRL);// 0=RESUME, 1=ABORT, 2=STOPEN
2890 uint8 pixsize = (dsta2 ? a2_pixsize : a1_pixsize); // From ACONTROL
2892 //Testing Trevor McFur--I *think* it's the circle on the lower RHS of the screen...
2894 if (cmd == 0x05810601 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 96)
2895 && (GET16(blitter_ram, PIXLINECOUNTER + 0) == 72))
2898 //if (cmd == 0x1401060C) patd = 0xFFFFFFFFFFFFFFFFLL;
2899 //if (cmd == 0x1401060C) patd = 0x00000000000000FFLL;
2900 //If it's still not working (bcompen-patd) then see who's writing what to patd and where...
2901 //Still not OK. Check to see who's writing what to where in patd!
2902 //It looks like M68K is writing to the top half of patd... Hmm...
2904 ----> M68K wrote 0000 to byte 15737344 of PATTERNDATA...
2905 --> M68K wrote 00 to byte 0 of PATTERNDATA...
2906 --> M68K wrote 00 to byte 1 of PATTERNDATA...
2907 ----> M68K wrote 00FF to byte 15737346 of PATTERNDATA...
2908 --> M68K wrote 00 to byte 2 of PATTERNDATA...
2909 --> M68K wrote FF to byte 3 of PATTERNDATA...
2910 logBlit = F, cmd = 1401060C
2912 Wren0 := ND6 (wren\[0], gpua\[5], gpua\[6..8], bliten, gpu_memw);
2913 Wren1 := ND6 (wren\[1], gpua[5], gpua\[6..8], bliten, gpu_memw);
2914 Wren2 := ND6 (wren\[2], gpua\[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2915 Wren3 := ND6 (wren\[3], gpua[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2918 Dec0 := D38GH (a1baseld, a1flagld, a1winld, a1ptrld, a1stepld, a1stepfld, a1fracld, a1incld, gpua[2..4], wren\[0]);
2920 Dec1 := D38GH (a1incfld, a2baseld, a2flagld, a2maskld, a2ptrldg, a2stepld, cmdldt, countldt, gpua[2..4], wren\[1]);
2922 Dec2 := D38GH (srcd1ldg[0..1], dstdldg[0..1], dstzldg[0..1], srcz1ldg[0..1], gpua[2..4], wren\[2]);
2924 Dec3 := D38GH (srcz2ld[0..1], patdld[0..1], iincld, zincld, stopld, intld[0], gpua[2..4], wren\[3]);
2926 wren[3] is asserted when gpu address bus = 0 011x xx00
2927 patdld[0] -> 0 0110 1000 -> $F02268 (lo 32 bits)
2928 patdld[1] -> 0 0110 1100 -> $F0226C (hi 32 bits)
2930 So... It's reversed! The data organization of the patd register is [low 32][high 32]! !!! FIX !!! [DONE]
2931 And fix all the other 64 bit registers [DONE]
2933 /*if (cmd == 0x1401060C)
2935 printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2939 if ((cmd == 0x00010200) && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 9))
2942 ; Pink altimeter bar
2944 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2945 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
2946 A1 step values: -10 (X), 1 (Y)
2947 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
2948 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
2949 A1 x/y: 262/132, A2 x/y: 129/0
2950 ;x-coord is 257 in pic, so add 5
2951 ;20 for ship, 33 for #... Let's see if we can find 'em!
2953 ; Black altimeter bar
2955 Blit! (00110000 <- 000BF010) count: 5 x 29, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2956 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
2957 A1 step values: -8 (X), 1 (Y)
2958 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
2959 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
2960 A1 x/y: 264/126, A2 x/y: 336/0
2962 Here's the pink bar--note that it's phrase mode without dread, so how does this work???
2963 Not sure, but I *think* that somehow it MUXes the data at the write site in on the left or right side
2964 of the write data when masked in phrase mode. I'll have to do some tracing to see if this is the mechanism
2967 Blit! (CMD = 00010200)
2968 Flags: UPDA1 PATDSEL
2970 a1_base = 00110010, a2_base = 000BD7E0
2971 a1_x = 0106, a1_y = 0090, a1_frac_x = 0000, a1_frac_y = 8000, a2_x = 025A, a2_y = 0000
2972 a1_step_x = FFF6, a1_step_y = 0001, a1_stepf_x = 5E00, a1_stepf_y = D100, a2_step_x = FFF7, a2_step_y = 0001
2973 a1_inc_x = 0001, a1_inc_y = FFFF, a1_incf_x = 0000, a1_incf_y = E000
2974 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
2975 a2_mask=F a1add=+phr/+0 a2add=+1/+0
2976 a1_pixsize = 4, a2_pixsize = 4
2977 srcd=BAC673AC2C92E578 dstd=0000000000000000 patd=74C074C074C074C0 iinc=0002E398
2978 srcz1=7E127E12000088DA srcz2=DBE06DF000000000 dstz=0000000000000000 zinc=FFFE4840, coll=0
2980 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2981 Entering INNER state...
2982 Entering DWRITE state...
2983 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)
2984 Entering A1_ADD state [a1_x=0106, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2985 Entering DWRITE state...
2986 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)
2987 Entering A1_ADD state [a1_x=0108, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2988 Entering DWRITE state...
2989 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)
2990 Entering A1_ADD state [a1_x=010C, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2991 Entering IDLE_INNER state...
2992 Leaving INNER state... (ocount=000A)
2993 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2994 Entering A1UPDATE state... (272/144 -> 262/145)
2995 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2996 Entering INNER state...
3001 a2addy = a1addy; // A2 channel Y add bit is tied to A1's
3003 //if (logBlit && (ocount > 20)) logBlit = false;
3004 #ifdef VERBOSE_BLITTER_LOGGING
3007 printf(" a1_base = %08X, a2_base = %08X\n", a1_base, a2_base);
3008 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);
3009 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);
3010 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);
3011 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);
3012 char x_add_str[4][4] = { "phr", "1", "0", "inc" };
3013 printf(" a2_mask=%s a1add=%s%s/%s%s a2add=%s%s/%s%s\n", (a2_mask ? "T" : "F"), (a1xsign ? "-" : "+"), x_add_str[a1addx],
3014 (a1ysign ? "-" : "+"), (a1addy ? "1" : "0"), (a2xsign ? "-" : "+"), x_add_str[a2addx],
3015 (a2ysign ? "-" : "+"), (a2addy ? "1" : "0"));
3016 printf(" a1_pixsize = %u, a2_pixsize = %u\n", a1_pixsize, a2_pixsize);
3017 printf(" srcd=%08X%08X dstd=%08X%08X patd=%08X%08X iinc=%08X\n",
3018 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF),
3019 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
3020 (uint32)(patd >> 32), (uint32)(patd & 0xFFFFFFFF), iinc);
3021 printf(" srcz1=%08X%08X srcz2=%08X%08X dstz=%08X%08X zinc=%08X, coll=%X\n",
3022 (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
3023 (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF),
3024 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF), zinc, collision);
3028 // Various state lines set up by user
3030 bool phrase_mode = ((!dsta2 && a1addx == 0) || (dsta2 && a2addx == 0) ? true : false); // From ACONTROL
3031 #ifdef VERBOSE_BLITTER_LOGGING
3034 printf(" Phrase mode is %s\n", (phrase_mode ? "ON" : "off"));
3040 // Stopgap vars to simulate various lines
3042 uint16 a1FracCInX = 0, a1FracCInY = 0;
3048 if ((idle && !go) || (inner && outer0 && indone))
3050 #ifdef VERBOSE_BLITTER_LOGGING
3053 printf(" Entering IDLE state...\n");
3059 //Instead of a return, let's try breaking out of the loop...
3066 // INNER LOOP ACTIVE
3068 Entering DWRITE state... (icount=0000, inc=4)
3069 Entering IDLE_INNER state...
3070 Leaving INNER state... (ocount=00EF)
3071 [in=T a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3072 Entering INNER state...
3074 [in=F a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3077 if ((idle && go && !datinit)
3078 || (inner && !indone)
3079 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && !datinit)
3080 || (a1update && !upda2 && notgzandp && !datinit)
3081 || (zupdate && !upda2 && !datinit)
3082 || (a2update && !datinit)
3083 || (init_ii && !gourz)
3091 // A1 FRACTION UPDATE
3093 if (inner && indone && !outer0 && upda1f)
3100 // A1 POINTER UPDATE
3103 || (inner && indone && !outer0 && !upda1f && upda1))
3110 // Z FRACTION UPDATE
3112 if ((a1update && gourz && polygon)
3113 || (inner && indone && !outer0 && !upda1f && !upda1 && gourz && polygon))
3129 // A2 POINTER UPDATE
3131 if ((a1update && upda2 && notgzandp)
3132 || (zupdate && upda2)
3133 || (inner && indone && !outer0 && !upda1f && notgzandp && !upda1 && upda2))
3140 // INITIALIZE INTENSITY FRACTION
3142 if ((zupdate && !upda2 && datinit)
3143 || (a1update && !upda2 && datinit && notgzandp)
3144 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && datinit)
3145 || (a2update && datinit)
3146 || (idle && go && datinit))
3153 // INITIALIZE INTENSITY INTEGER
3162 // INITIALIZE Z FRACTION
3164 if (init_ii && gourz)
3171 // INITIALIZE Z INTEGER
3180 // Here we move the fooi into their foo counterparts in order to simulate the moving
3181 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3185 a1fupdate = a1fupdatei;
3186 a1update = a1updatei;
3187 zfupdate = zfupdatei; // *
3188 zupdate = zupdatei; // *
3189 a2update = a2updatei;
3190 init_if = init_ifi; // *
3191 init_ii = init_iii; // *
3192 init_zf = init_zfi; // *
3193 init_zi = init_zii; // *
3194 // * denotes states that will never assert for Jaguar I
3195 #ifdef VERBOSE_BLITTER_LOGGING
3198 printf(" [in=%c a1f=%c a1=%c zf=%c z=%c a2=%c iif=%c iii=%c izf=%c izi=%c]\n",
3199 (inner ? 'T' : 'F'), (a1fupdate ? 'T' : 'F'), (a1update ? 'T' : 'F'), (zfupdate ? 'T' : 'F'),
3200 (zupdate ? 'T' : 'F'), (a2update ? 'T' : 'F'), (init_if ? 'T' : 'F'), (init_ii ? 'T' : 'F'),
3201 (init_zf ? 'T' : 'F'), (init_zi ? 'T' : 'F'));
3206 // Now, depending on how we want to handle things, we could either put the implementation
3207 // of the various pieces up above, or handle them down below here.
3209 // Let's try postprocessing for now...
3214 #ifdef VERBOSE_BLITTER_LOGGING
3217 printf(" Entering INNER state...\n");
3221 uint16 icount = GET16(blitter_ram, PIXLINECOUNTER + 2);
3222 bool idle_inner = true, step = true, sreadx = false, szreadx = false, sread = false,
3223 szread = false, dread = false, dzread = false, dwrite = false, dzwrite = false;
3224 bool inner0 = false;
3225 bool idle_inneri, sreadxi, szreadxi, sreadi, szreadi, dreadi, dzreadi, dwritei, dzwritei;
3227 // State lines that will never assert in Jaguar I
3229 bool textext = false, txtread = false;
3233 bool sshftld = true; // D flipflop (D -> Q): instart -> sshftld
3234 //NOTE: sshftld probably is only asserted at the beginning of the inner loop. !!! FIX !!!
3236 Blit! (CMD = 01800005)
3237 Flags: SRCEN SRCENX LFUFUNC=C
3239 a1_base = 00037290, a2_base = 000095D0
3240 a1_x = 0000, a1_y = 0000, a2_x = 0002, a2_y = 0000
3241 a1_pixsize = 4, a2_pixsize = 4
3242 srcd=0000000000000000, dstd=0000000000000000, patd=0000000000000000
3244 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3245 Entering INNER state...
3246 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
3247 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
3248 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3249 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3250 Source read address/pix address: 000095D8/0 [0054003800009814]
3251 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3252 Entering DWRITE state...
3253 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
3254 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3255 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3256 Source read address/pix address: 000095E0/0 [00009968000377C7]
3257 Entering A2_ADD state [a2_x=0008, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3258 Entering DWRITE state...
3259 Dest write address/pix address: 00037298/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026A, inc=4)
3260 Entering A1_ADD state [a1_x=0004, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3263 // while (!idle_inner)
3268 if ((idle_inner && !step)
3269 || (dzwrite && step && inner0)
3270 || (dwrite && step && !dstwrz && inner0))
3272 #ifdef VERBOSE_BLITTER_LOGGING
3275 printf(" Entering IDLE_INNER state...\n");
3283 idle_inneri = false;
3285 // EXTRA SOURCE DATA READ
3287 if ((idle_inner && step && srcenx)
3288 || (sreadx && !step))
3295 // EXTRA SOURCE ZED READ
3297 if ((sreadx && step && srcenz)
3298 || (szreadx && !step))
3305 // TEXTURE DATA READ (not implemented because not in Jaguar I)
3309 if ((szreadx && step && !textext)
3310 || (sreadx && step && !srcenz && srcen)
3311 || (idle_inner && step && !srcenx && !textext && srcen)
3312 || (dzwrite && step && !inner0 && !textext && srcen)
3313 || (dwrite && step && !dstwrz && !inner0 && !textext && srcen)
3314 || (txtread && step && srcen)
3315 || (sread && !step))
3324 if ((sread && step && srcenz)
3325 || (szread && !step))
3332 // DESTINATION DATA READ
3334 if ((szread && step && dsten)
3335 || (sread && step && !srcenz && dsten)
3336 || (sreadx && step && !srcenz && !textext && !srcen && dsten)
3337 || (idle_inner && step && !srcenx && !textext && !srcen && dsten)
3338 || (dzwrite && step && !inner0 && !textext && !srcen && dsten)
3339 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && dsten)
3340 || (txtread && step && !srcen && dsten)
3341 || (dread && !step))
3348 // DESTINATION ZED READ
3350 if ((dread && step && dstenz)
3351 || (szread && step && !dsten && dstenz)
3352 || (sread && step && !srcenz && !dsten && dstenz)
3353 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && dstenz)
3354 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && dstenz)
3355 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && dstenz)
3356 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && dstenz)
3357 || (txtread && step && !srcen && !dsten && dstenz)
3358 || (dzread && !step))
3365 // DESTINATION DATA WRITE
3367 if ((dzread && step)
3368 || (dread && step && !dstenz)
3369 || (szread && step && !dsten && !dstenz)
3370 || (sread && step && !srcenz && !dsten && !dstenz)
3371 || (txtread && step && !srcen && !dsten && !dstenz)
3372 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && !dstenz)
3373 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && !dstenz)
3374 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && !dstenz)
3375 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && !dstenz)
3376 || (dwrite && !step))
3383 // DESTINATION ZED WRITE
3385 if ((dzwrite && !step)
3386 || (dwrite && step && dstwrz))
3393 //Kludge: A QnD way to make sure that sshftld is asserted only for the first
3394 // cycle of the inner loop...
3395 sshftld = idle_inner;
3397 // Here we move the fooi into their foo counterparts in order to simulate the moving
3398 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3400 idle_inner = idle_inneri;
3410 // Here's a few more decodes--not sure if they're supposed to go here or not...
3412 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
3414 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
3416 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
3417 bool gendst = dreadi || dzreadi || dwritei || dzwritei;
3418 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
3420 bool zaddr = szreadx || szread || dzread || dzwrite;
3422 // Some stuff from MCONTROL.NET--not sure if this is the correct use of this decode or not...
3423 /*Fontread\ := OND1 (fontread\, sread[1], sreadx[1], bcompen);
3424 Fontread := INV1 (fontread, fontread\);
3425 Justt := NAN3 (justt, fontread\, phrase_mode, tactive\);
3426 Justify := TS (justify, justt, busen);*/
3427 bool fontread = (sread || sreadx) && bcompen;
3428 bool justify = !(!fontread && phrase_mode /*&& tactive*/);
3430 /* Generate inner loop update enables */
3432 A1_addi := MX2 (a1_addi, dsta_addi, srca_addi, dsta2);
3433 A2_addi := MX2 (a2_addi, srca_addi, dsta_addi, dsta2);
3434 A1_add := FD1 (a1_add, a1_add\, a1_addi, clk);
3435 A2_add := FD1 (a2_add, a2_add\, a2_addi, clk);
3436 A2_addb := BUF1 (a2_addb, a2_add);
3438 bool a1_add = (dsta2 ? srca_addi : dsta_addi);
3439 bool a2_add = (dsta2 ? dsta_addi : srca_addi);
3441 /* Address adder input A register selection
3442 000 A1 step integer part
3443 001 A1 step fraction part
3444 010 A1 increment integer part
3445 011 A1 increment fraction part
3449 bit 1 = /a2update . (a1_add . a1addx[0..1])
3450 bit 0 = /a2update . ( a1fupdate
3451 + a1_add . atick[0] . a1addx[0..1])
3452 The /a2update term on bits 0 and 1 is redundant.
3453 Now look-ahead based
3455 uint8 addasel = (a1fupdate || (a1_add && a1addx == 3) ? 0x01 : 0x00);
3456 addasel |= (a1_add && a1addx == 3 ? 0x02 : 0x00);
3457 addasel |= (a2update ? 0x04 : 0x00);
3458 /* Address adder input A X constant selection
3459 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all
3460 zeroes when they are all 1
3461 Remember - these are pixels, so to add one phrase the pixel size
3462 has to be taken into account to get the appropriate value.
3464 if a1addx[0..1] are 00 set 6 - pixel size
3465 if a1addx[0..1] are 01 set the value 000
3466 if a1addx[0..1] are 10 set the value 111
3468 JLH: Also, 11 will likewise set the value to 111
3470 uint8 a1_xconst = 6 - a1_pixsize, a2_xconst = 6 - a2_pixsize;
3474 else if (a1addx & 0x02)
3479 else if (a2addx & 0x02)
3482 uint8 adda_xconst = (a2_add ? a2_xconst : a1_xconst);
3483 /* Address adder input A Y constant selection
3484 22 June 94 - This was erroneous, because only the a1addy bit was reflected here.
3485 Therefore, the selection has to be controlled by a bug fix bit.
3486 JLH: Bug fix bit in Jaguar II--not in Jaguar I!
3488 bool adda_yconst = a1addy;
3489 /* Address adder input A register versus constant selection
3490 given by a1_add . a1addx[0..1]
3493 + a2_add . a2addx[0..1]
3496 bool addareg = ((a1_add && a1addx == 3) || a1update || a1fupdate
3497 || (a2_add && a2addx == 3) || a2update ? true : false);
3498 /* The adders can be put into subtract mode in add pixel size
3499 mode when the corresponding flags are set */
3500 bool suba_x = ((a1_add && a1xsign && a1addx == 1) || (a2_add && a2xsign && a2addx == 1) ? true : false);
3501 bool suba_y = ((a1_add && a1addy && a1ysign) || (a2_add && a2addy && a2ysign) ? true : false);
3502 /* Address adder input B selection
3509 + (a1_add . atick[0] . a1addx[0..1])
3510 + a1fupdate . a1_stepld
3511 + a1update . a1_stepld
3512 + a2update . a2_stepld
3513 Bit 0 = a2update + a2_add
3514 + a1fupdate . a1_stepld
3515 + a1update . a1_stepld
3516 + a2update . a2_stepld
3518 uint8 addbsel = (a2update || a2_add || (a1fupdate && a1_stepld)
3519 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x01 : 0x00);
3520 addbsel |= (a1fupdate || (a1_add && a1addx == 3) || (a1fupdate && a1_stepld)
3521 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x02 : 0x00);
3523 /* The modulo bits are used to align X onto a phrase boundary when
3524 it is being updated by one phrase
3531 Masking is enabled for a1 when a1addx[0..1] is 00, and the value
3532 is 6 - the pixel size (again!)
3534 uint8 maska1 = (a1_add && a1addx == 0 ? 6 - a1_pixsize : 0);
3535 uint8 maska2 = (a2_add && a2addx == 0 ? 6 - a2_pixsize : 0);
3536 uint8 modx = (a2_add ? maska2 : maska1);
3537 /* Generate load strobes for the increment updates */
3539 /*A1pldt := NAN2 (a1pldt, atick[1], a1_add);
3540 A1ptrldi := NAN2 (a1ptrldi, a1update\, a1pldt);
3542 A1fldt := NAN4 (a1fldt, atick[0], a1_add, a1addx[0..1]);
3543 A1fracldi := NAN2 (a1fracldi, a1fupdate\, a1fldt);
3545 A2pldt := NAN2 (a2pldt, atick[1], a2_add);
3546 A2ptrldi := NAN2 (a2ptrldi, a2update\, a2pldt);*/
3547 bool a1fracldi = a1fupdate || (a1_add && a1addx == 3);
3549 // Some more from DCONTROL...
3550 // atick[] just MAY be important here! We're assuming it's true and dropping the term...
3551 // That will probably screw up some of the lower terms that seem to rely on the timing of it...
3552 #warning srcdreadd is not properly initialized!
3553 bool srcdreadd = false; // Set in INNER.NET
3554 //Shadeadd\ := NAN2H (shadeadd\, dwrite, srcshade);
3555 //Shadeadd := INV2 (shadeadd, shadeadd\);
3556 bool shadeadd = dwrite && srcshade;
3557 /* Data adder control, input A selection
3558 000 Destination data
3559 001 Initialiser pixel value
3560 100 Source data - computed intensity fraction
3561 101 Pattern data - computed intensity
3562 110 Source zed 1 - computed zed
3563 111 Source zed 2 - computed zed fraction
3565 Bit 0 = dwrite . gourd . atick[1]
3566 + dzwrite . gourz . atick[0]
3569 + init_if + init_ii + init_zf + init_zi
3570 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3573 Bit 2 = (gourd + gourz) . /(init_if + init_ii + init_zf + init_zi)
3576 uint8 daddasel = ((dwrite && gourd) || (dzwrite && gourz) || istepadd || zstepfadd
3577 || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3578 daddasel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3579 daddasel |= (((gourd || gourz) && !(init_if || init_ii || init_zf || init_zi))
3580 || (dwrite && srcshade) ? 0x04 : 0x00);
3581 /* Data adder control, input B selection
3583 0001 Data initialiser increment
3584 0100 Bottom 16 bits of I increment repeated four times
3585 0101 Top 16 bits of I increment repeated four times
3586 0110 Bottom 16 bits of Z increment repeated four times
3587 0111 Top 16 bits of Z increment repeated four times
3588 1100 Bottom 16 bits of I step repeated four times
3589 1101 Top 16 bits of I step repeated four times
3590 1110 Bottom 16 bits of Z step repeated four times
3591 1111 Top 16 bits of Z step repeated four times
3593 Bit 0 = dwrite . gourd . atick[1]
3594 + dzwrite . gourz . atick[1]
3598 + init_if + init_ii + init_zf + init_zi
3599 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3602 Bit 2 = dwrite . gourd . (atick[0] + atick[1])
3603 + dzwrite . gourz . (atick[0] + atick[1])
3605 + istepadd + istepfadd + zstepadd + zstepfadd
3606 Bit 3 = istepadd + istepfadd + zstepadd + zstepfadd
3608 uint8 daddbsel = ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3609 || istepadd || zstepadd || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3610 daddbsel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3611 daddbsel |= ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3612 || istepadd || istepfadd || zstepadd || zstepfadd ? 0x04 : 0x00);
3613 daddbsel |= (istepadd && istepfadd && zstepadd && zstepfadd ? 0x08 : 0x00);
3614 /* Data adder mode control
3615 000 16-bit normal add
3616 001 16-bit saturating add with carry
3617 010 8-bit saturating add with carry, carry into top byte is
3619 011 8-bit saturating add with carry, carry into top byte and
3620 between top nybbles is inhibited (CRY)
3621 100 16-bit normal add with carry
3622 101 16-bit saturating add
3623 110 8-bit saturating add, carry into top byte is inhibited
3624 111 8-bit saturating add, carry into top byte and between top
3625 nybbles is inhibited
3627 The first five are used for Gouraud calculations, the latter three
3628 for adding source and destination data
3630 Bit 0 = dzwrite . gourz . atick[1]
3631 + dwrite . gourd . atick[1] . /topnen . /topben . /ext_int
3632 + dwrite . gourd . atick[1] . topnen . topben . /ext_int
3634 + istepadd . /topnen . /topben . /ext_int
3635 + istepadd . topnen . topben . /ext_int
3636 + /gourd . /gourz . /topnen . /topben
3637 + /gourd . /gourz . topnen . topben
3638 + shadeadd . /topnen . /topben
3639 + shadeadd . topnen . topben
3640 + init_ii . /topnen . /topben . /ext_int
3641 + init_ii . topnen . topben . /ext_int
3644 Bit 1 = dwrite . gourd . atick[1] . /topben . /ext_int
3645 + istepadd . /topben . /ext_int
3646 + /gourd . /gourz . /topben
3647 + shadeadd . /topben
3648 + init_ii . /topben . /ext_int
3650 Bit 2 = /gourd . /gourz
3652 + dwrite . gourd . atick[1] . ext_int
3653 + istepadd . ext_int
3656 uint8 daddmode = ((dzwrite && gourz) || (dwrite && gourd && !topnen && !topben && !ext_int)
3657 || (dwrite && gourd && topnen && topben && !ext_int) || zstepadd
3658 || (istepadd && !topnen && !topben && !ext_int)
3659 || (istepadd && topnen && topben && !ext_int) || (!gourd && !gourz && !topnen && !topben)
3660 || (!gourd && !gourz && topnen && topben) || (shadeadd && !topnen && !topben)
3661 || (shadeadd && topnen && topben) || (init_ii && !topnen && !topben && !ext_int)
3662 || (init_ii && topnen && topben && !ext_int) || init_zi ? 0x01 : 0x00);
3663 daddmode |= ((dwrite && gourd && !topben && !ext_int) || (istepadd && !topben && !ext_int)
3664 || (!gourd && !gourz && !topben) || (shadeadd && !topben)
3665 || (init_ii && !topben && !ext_int) ? 0x02 : 0x00);
3666 daddmode |= ((!gourd && !gourz) || shadeadd || (dwrite && gourd && ext_int)
3667 || (istepadd && ext_int) || (init_ii && ext_int) ? 0x04 : 0x00);
3668 /* Data add load controls
3669 Pattern fraction (dest data) is loaded on
3670 dwrite . gourd . atick[0]
3671 + istepfadd . /datinit
3673 Pattern data is loaded on
3674 dwrite . gourd . atick[1]
3675 + istepadd . /datinit . /datinit
3677 Source z1 is loaded on
3678 dzwrite . gourz . atick[1]
3679 + zstepadd . /datinit . /datinit
3681 Source z2 is loaded on
3682 dzwrite . gourz . atick[0]
3685 Texture map shaded data is loaded on
3686 srcdreadd . srcshade
3688 bool patfadd = (dwrite && gourd) || (istepfadd && !datinit) || init_if;
3689 bool patdadd = (dwrite && gourd) || (istepadd && !datinit) || init_ii;
3690 bool srcz1add = (dzwrite && gourz) || (zstepadd && !datinit) || init_zi;
3691 bool srcz2add = (dzwrite && gourz) || zstepfadd || init_zf;
3692 bool srcshadd = srcdreadd && srcshade;
3693 bool daddq_sel = patfadd || patdadd || srcz1add || srcz2add || srcshadd;
3694 /* Select write data
3695 This has to be controlled from stage 1 of the pipe-line, delayed
3696 by one tick, as the write occurs in the cycle after the ack.
3703 Bit 0 = /patdsel . /adddsel
3708 uint8 data_sel = ((!patdsel && !adddsel) || dzwrite ? 0x01 : 0x00)
3709 | (adddsel || dzwrite ? 0x02 : 0x00);
3711 uint32 address, pixAddr;
3712 ADDRGEN(address, pixAddr, gena2i, zaddr,
3713 a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3714 a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3716 //Here's my guess as to how the addresses get truncated to phrase boundaries in phrase mode...
3718 address &= 0xFFFFF8;
3720 /* Generate source alignment shift
3721 -------------------------------
3722 The source alignment shift for data move is the difference between
3723 the source and destination X pointers, multiplied by the pixel
3724 size. Only the low six bits of the pointers are of interest, as
3725 pixel sizes are always a power of 2 and window rows are always
3728 When not in phrase mode, the top 3 bits of the shift value are
3731 Source shifting is also used to extract bits for bit-to-byte
3732 expansion in phrase mode. This involves only the bottom three
3733 bits of the shift value, and is based on the offset within the
3734 phrase of the destination X pointer, in pixels.
3736 Source shifting is disabled when srcen is not set.
3738 uint8 dstxp = (dsta2 ? a2_x : a1_x) & 0x3F;
3739 uint8 srcxp = (dsta2 ? a1_x : a2_x) & 0x3F;
3740 uint8 shftv = ((dstxp - srcxp) << pixsize) & 0x3F;
3741 /* The phrase mode alignment count is given by the phrase offset
3742 of the first pixel, for bit to byte expansion */
3746 pobb = dstxp & 0x07;
3748 pobb = dstxp & 0x03;
3750 pobb = dstxp & 0x01;
3752 bool pobbsel = phrase_mode && bcompen;
3753 uint8 loshd = (pobbsel ? pobb : shftv) & 0x07;
3754 uint8 shfti = (srcen || pobbsel ? (sshftld ? loshd : srcshift & 0x07) : 0);
3755 /* Enable for high bits is srcen . phrase_mode */
3756 shfti |= (srcen && phrase_mode ? (sshftld ? shftv & 0x38 : srcshift & 0x38) : 0);
3761 #ifdef VERBOSE_BLITTER_LOGGING
3764 printf(" Entering SREADX state...");
3765 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
3769 //uint32 srcAddr, pixAddr;
3770 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3771 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3772 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3774 srcd1 = ((uint64)JaguarReadLong(address + 0, BLITTER) << 32)
3775 | (uint64)JaguarReadLong(address + 4, BLITTER);
3776 //Kludge to take pixel size into account...
3777 //Hmm. If we're not in phrase mode, this is most likely NOT going to be used...
3778 //Actually, it would be--because of BCOMPEN expansion, for example...
3787 else if (pixsize == 4)
3793 #ifdef VERBOSE_BLITTER_LOGGING
3796 printf(" Source extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3797 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
3805 #ifdef VERBOSE_BLITTER_LOGGING
3808 printf(" Entering SZREADX state...");
3813 srcz1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3814 #ifdef VERBOSE_BLITTER_LOGGING
3817 printf(" Src Z extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3818 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3826 #ifdef VERBOSE_BLITTER_LOGGING
3829 printf(" Entering SREAD state...");
3830 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
3834 //uint32 srcAddr, pixAddr;
3835 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3836 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3837 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3839 srcd1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3840 //Kludge to take pixel size into account...
3849 else if (pixsize == 4)
3855 #ifdef VERBOSE_BLITTER_LOGGING
3858 printf(" Source read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3859 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
3867 #ifdef VERBOSE_BLITTER_LOGGING
3870 printf(" Entering SZREAD state...");
3875 srcz1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3876 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3877 if (!phrase_mode && pixsize == 4)
3880 #ifdef VERBOSE_BLITTER_LOGGING
3883 printf(" Src Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3884 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3892 #ifdef VERBOSE_BLITTER_LOGGING
3895 printf(" Entering DREAD state...");
3899 //uint32 dstAddr, pixAddr;
3900 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
3901 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3902 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3903 dstd = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3904 //Kludge to take pixel size into account...
3909 else if (pixsize == 4)
3914 #ifdef VERBOSE_BLITTER_LOGGING
3917 printf(" Dest read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3918 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF));
3926 // Is Z always 64 bit read? Or sometimes 16 bit (dependent on phrase_mode)?
3927 #ifdef VERBOSE_BLITTER_LOGGING
3930 printf(" Entering DZREAD state...");
3934 dstz = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3935 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3936 if (!phrase_mode && pixsize == 4)
3939 #ifdef VERBOSE_BLITTER_LOGGING
3942 printf(" Dest Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3943 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3949 // These vars should probably go further up in the code... !!! FIX !!!
3950 // We can't preassign these unless they're static...
3951 //uint64 srcz = 0; // These are assigned to shut up stupid compiler warnings--dwrite is ALWAYS asserted
3952 //bool winhibit = false;
3955 //NOTE: SRCSHADE requires GOURZ to be set to work properly--another Jaguar I bug
3958 #ifdef VERBOSE_BLITTER_LOGGING
3961 printf(" Entering DWRITE state...");
3965 //Counter is done on the dwrite state...! (We'll do it first, since it affects dstart/dend calculations.)
3966 //Here's the voodoo for figuring the correct amount of pixels in phrase mode (or not):
3967 int8 inct = -((dsta2 ? a2_x : a1_x) & 0x07); // From INNER_CNT
3969 inc = (!phrase_mode || (phrase_mode && (inct & 0x01)) ? 0x01 : 0x00);
3970 inc |= (phrase_mode && (((pixsize == 3 || pixsize == 4) && (inct & 0x02)) || pixsize == 5 && !(inct & 0x01)) ? 0x02 : 0x00);
3971 inc |= (phrase_mode && ((pixsize == 3 && (inct & 0x04)) || (pixsize == 4 && !(inct & 0x03))) ? 0x04 : 0x00);
3972 inc |= (phrase_mode && pixsize == 3 && !(inct & 0x07) ? 0x08 : 0x00);
3974 uint16 oldicount = icount; // Save icount to detect underflow...
3977 if (icount == 0 || ((icount & 0x8000) && !(oldicount & 0x8000)))
3979 // X/Y stepping is also done here, I think...No. It's done when a1_add or a2_add is asserted...
3981 //*********************************************************************************
3982 //Start & end write mask computations...
3983 //*********************************************************************************
3988 dstart = (dstxp & 0x07) << 3;
3990 dstart = (dstxp & 0x03) << 4;
3992 dstart = (dstxp & 0x01) << 5;
3994 dstart = (phrase_mode ? dstart : pixAddr & 0x07);
3996 //This is the other Jaguar I bug... Normally, should ALWAYS select a1_x here.
3997 uint16 dstxwr = (dsta2 ? a2_x : a1_x) & 0x7FFE;
3998 uint16 pseq = dstxwr ^ (a1_win_x & 0x7FFE);
3999 pseq = (pixsize == 5 ? pseq : pseq & 0x7FFC);
4000 pseq = ((pixsize & 0x06) == 4 ? pseq : pseq & 0x7FF8);
4001 bool penden = clip_a1 && (pseq == 0);
4002 uint8 window_mask = 0;
4005 window_mask = (a1_win_x & 0x07) << 3;
4007 window_mask = (a1_win_x & 0x03) << 4;
4009 window_mask = (a1_win_x & 0x01) << 5;
4011 window_mask = (penden ? window_mask : 0);
4014 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4015 Source extra read address/pix address: 000095D0/0 [000004E40000001C]
4016 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4017 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4018 Source read address/pix address: 000095D8/0 [0054003800009814]
4019 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4020 Entering DWRITE state...
4021 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)
4022 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4024 (icount=026E, inc=4)
4025 icount & 0x03 = 0x02
4028 window_mask = 0x1000
4030 Therefore, it chooses the inner_mask over the window_mask every time! Argh!
4031 This is because we did this wrong:
4032 Innerm[3-5] := AN2 (inner_mask[3-5], imb[3-5], inner0);
4033 NOTE! This doesn't fix the problem because inner0 is asserted too late to help here. !!! FIX !!! [Should be DONE]
4036 /* The mask to be used if within one phrase of the end of the inner
4038 uint8 inner_mask = 0;
4041 inner_mask = (icount & 0x07) << 3;
4043 inner_mask = (icount & 0x03) << 4;
4045 inner_mask = (icount & 0x01) << 5;
4048 /* The actual mask used should be the lesser of the window masks and
4049 the inner mask, where is all cases 000 means 1000. */
4050 window_mask = (window_mask == 0 ? 0x40 : window_mask);
4051 inner_mask = (inner_mask == 0 ? 0x40 : inner_mask);
4052 uint8 emask = (window_mask > inner_mask ? inner_mask : window_mask);
4053 /* The mask to be used for the pixel size, to which must be added
4055 uint8 pma = pixAddr + (1 << pixsize);
4056 /* Select the mask */
4057 uint8 dend = (phrase_mode ? emask : pma);
4059 /* The cycle width in phrase mode is normally one phrase. However,
4060 at the start and end it may be narrower. The start and end masks
4061 are used to generate this. The width is given by:
4063 8 - start mask - (8 - end mask)
4064 = end mask - start mask
4066 This is only used for writes in phrase mode.
4067 Start and end from the address level of the pipeline are used.
4069 uint8 pwidth = (((dend | dstart) & 0x07) == 0 ? 0x08 : (dend - dstart) & 0x07);
4071 //uint32 dstAddr, pixAddr;
4072 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
4073 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
4074 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
4075 #ifdef VERBOSE_BLITTER_LOGGING
4078 printf(" Dest write address/pix address: %08X/%1X", address, pixAddr);
4083 //More testing... This is almost certainly wrong, but how else does this work???
4084 //Seems to kinda work... But still, this doesn't seem to make any sense!
4085 if (phrase_mode && !dsten)
4086 dstd = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
4088 //Testing only... for now...
4089 //This is wrong because the write data is a combination of srcd and dstd--either run
4090 //thru the LFU or in PATDSEL or ADDDSEL mode. [DONE now, thru DATA module]
4091 // Precedence is ADDDSEL > PATDSEL > LFU.
4092 //Also, doesn't take into account the start & end masks, or the phrase width...
4095 // srcd2 = xxxx xxxx 0123 4567, srcd = 8901 2345 xxxx xxxx, srcshift = $20 (32)
4096 uint64 srcd = (srcd2 << (64 - srcshift)) | (srcd1 >> srcshift);
4097 //bleh, ugly ugly ugly
4101 //NOTE: This only works with pixel sizes less than 8BPP...
4102 //DOUBLE NOTE: Still need to do regression testing to ensure that this doesn't break other stuff... !!! CHECK !!!
4103 if (!phrase_mode && srcshift != 0)
4104 srcd = ((srcd2 & 0xFF) << (8 - srcshift)) | ((srcd1 & 0xFF) >> srcshift);
4106 //Z DATA() stuff done here... And it has to be done before any Z shifting...
4107 //Note that we need to have phrase mode start/end support here... (Not since we moved it from dzwrite...!)
4109 Here are a couple of Cybermorph blits with Z:
4110 $00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
4111 $09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
4113 We're having the same phrase mode overwrite problem we had with the pixels... !!! FIX !!!
4114 Odd. It's equating 0 with 0... Even though ZMODE is $04 (less than)!
4119 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
4120 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
4121 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
4122 uint32 zinc, uint32 zstep)
4125 uint8 initcin[4] = { 0, 0, 0, 0 };
4126 ADDARRAY(addq, 7/*daddasel*/, 6/*daddbsel*/, 0/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4127 srcz2 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4128 ADDARRAY(addq, 6/*daddasel*/, 7/*daddbsel*/, 1/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4129 srcz1 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4131 #if 0//def VERBOSE_BLITTER_LOGGING
4134 printf("\n[srcz1=%08X%08X, srcz2=%08X%08X, zinc=%08X",
4135 (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
4136 (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF), zinc);
4142 uint8 zSrcShift = srcshift & 0x30;
4143 srcz = (srcz2 << (64 - zSrcShift)) | (srcz1 >> zSrcShift);
4144 //bleh, ugly ugly ugly
4148 #if 0//def VERBOSE_BLITTER_LOGGING
4151 printf(" srcz=%08X%08X]\n", (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4156 //When in SRCSHADE mode, it adds the IINC to the read source (from LFU???)
4157 //According to following line, it gets LFU mode. But does it feed the source into the LFU
4159 //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)
4163 //NOTE: This is basically doubling the work done by DATA--since this is what
4164 // ADDARRAY is loaded with when srschshade is enabled... !!! FIX !!!
4165 // Also note that it doesn't work properly unless GOURZ is set--there's the clue!
4167 uint8 initcin[4] = { 0, 0, 0, 0 };
4168 ADDARRAY(addq, 4/*daddasel*/, 5/*daddbsel*/, 7/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4169 srcd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4171 //Seems to work... Not 100% sure tho.
4174 //Temporary kludge, to see if the fractional pattern does anything...
4176 //But it seems to mess up in Cybermorph... the shading should be smooth but it isn't...
4177 //Seems the carry out is lost again... !!! FIX !!! [DONE--see below]
4181 uint8 initcin[4] = { 0, 0, 0, 0 };
4182 ADDARRAY(addq, 4/*daddasel*/, 4/*daddbsel*/, 0/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4183 srcd1 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4186 //Note that we still don't take atick[0] & [1] into account here, so this will skip half of the data needed... !!! FIX !!!
4187 //Not yet enumerated: dbinh, srcdread, srczread
4188 //Also, should do srcshift on the z value in phrase mode... !!! FIX !!! [DONE]
4189 //As well as add a srcz variable we can set external to this state... !!! FIX !!! [DONE]
4193 DATA(wdata, dcomp, zcomp, winhibit,
4194 true, cmpdst, daddasel, daddbsel, daddmode, daddq_sel, data_sel, 0/*dbinh*/,
4195 dend, dstart, dstd, iinc, lfufunc, patd, patdadd,
4196 phrase_mode, srcd, false/*srcdread*/, false/*srczread*/, srcz2add, zmode,
4197 bcompen, bkgwren, dcompen, icount & 0x07, pixsize,
4200 Seems that the phrase mode writes with DCOMPEN and DSTEN are corrupting inside of DATA: !!! FIX !!!
4201 It's fairly random as well. 7CFE -> 7DFE, 7FCA -> 78CA, 7FA4 -> 78A4, 7F88 -> 8F88
4202 It could be related to an uninitialized variable, like the zmode bug...
4204 It was a bug in the dech38el data--it returned $FF for ungated instead of $00...
4206 Blit! (CMD = 09800609)
4207 Flags: SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
4209 a1_base = 00110000, a2_base = 0010B2A8
4210 a1_x = 004B, a1_y = 00D8, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0704, a2_y = 0000
4211 a1_step_x = FFF3, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFFC, a2_step_y = 0000
4212 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4213 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4214 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4215 a1_pixsize = 4, a2_pixsize = 4
4216 srcd=0000000000000000 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4217 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4219 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4220 Entering INNER state...
4221 Entering SREAD state... Source read address/pix address: 0010C0B0/0 [0000000078047804]
4222 Entering A2_ADD state [a2_x=0704, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4223 Entering DREAD state...
4224 Dest read address/pix address: 00197240/0 [0000000000000028]
4225 Entering DWRITE state...
4226 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)
4227 Entering A1_ADD state [a1_x=004B, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4228 Entering SREAD state... Source read address/pix address: 0010C0B8/0 [7804780478047804]
4229 Entering A2_ADD state [a2_x=0708, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4230 Entering DREAD state...
4231 Dest read address/pix address: 00197260/0 [0028000000200008]
4232 Entering DWRITE state...
4233 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)
4234 Entering A1_ADD state [a1_x=004C, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4235 Entering SREAD state... Source read address/pix address: 0010C0C0/0 [0000000000000000]
4236 Entering A2_ADD state [a2_x=070C, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4237 Entering DREAD state...
4238 Dest read address/pix address: 00197280/0 [0008001800180018]
4239 Entering DWRITE state...
4240 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)
4241 Entering A1_ADD state [a1_x=0050, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4242 Entering SREAD state... Source read address/pix address: 0010C0C8/0 [000078047BFE7BFE]
4243 Entering A2_ADD state [a2_x=0710, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4244 Entering DREAD state...
4245 Dest read address/pix address: 001972A0/0 [0008002000000000]
4246 Entering DWRITE state...
4247 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)
4248 Entering A1_ADD state [a1_x=0054, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4249 Entering IDLE_INNER state...
4252 //Why isn't this taken care of in DATA? Because, DATA is modifying its local copy instead of the one used here.
4253 //!!! FIX !!! [DONE]
4262 a1_outside // A1 pointer is outside window bounds
4271 // The address is outside if negative, or if greater than or equal
4272 // to the window size
4274 A1_xcomp := MAG_15 (a1xgr, a1xeq, a1xlt, a1_x{0..14}, a1_win_x{0..14});
4275 A1_ycomp := MAG_15 (a1ygr, a1yeq, a1ylt, a1_y{0..14}, a1_win_y{0..14});
4276 A1_outside := OR6 (a1_outside, a1_x{15}, a1xgr, a1xeq, a1_y{15}, a1ygr, a1yeq);
4278 //NOTE: There seems to be an off-by-one bug here in the clip_a1 section... !!! FIX !!!
4279 // Actually, seems to be related to phrase mode writes...
4280 // Or is it? Could be related to non-15-bit compares as above?
4281 if (clip_a1 && ((a1_x & 0x8000) || (a1_y & 0x8000) || (a1_x >= a1_win_x) || (a1_y >= a1_win_y)))
4288 JaguarWriteLong(address + 0, wdata >> 32, BLITTER);
4289 JaguarWriteLong(address + 4, wdata & 0xFFFFFFFF, BLITTER);
4294 JaguarWriteLong(address, wdata & 0xFFFFFFFF, BLITTER);
4295 else if (pixsize == 4)
4296 JaguarWriteWord(address, wdata & 0x0000FFFF, BLITTER);
4298 JaguarWriteByte(address, wdata & 0x000000FF, BLITTER);
4302 #ifdef VERBOSE_BLITTER_LOGGING
4305 printf(" [%08X%08X]%s", (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF), (winhibit ? "[X]" : ""));
4306 printf(" (icount=%04X, inc=%u)\n", icount, (uint16)inc);
4307 printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4308 printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4316 // OK, here's the big insight: When NOT in GOURZ mode, srcz1 & 2 function EXACTLY the same way that
4317 // srcd1 & 2 work--there's an implicit shift from srcz1 to srcz2 whenever srcz1 is read.
4318 // OTHERWISE, srcz1 is the integer for the computed Z and srcz2 is the fractional part.
4319 // Writes to srcz1 & 2 follow the same pattern as the other 64-bit registers--low 32 at the low address,
4320 // high 32 at the high address (little endian!).
4321 // NOTE: GOURZ is still not properly supported. Check patd/patf handling...
4322 // Phrase mode start/end masks are not properly supported either...
4323 #ifdef VERBOSE_BLITTER_LOGGING
4326 printf(" Entering DZWRITE state...");
4327 printf(" Dest Z write address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
4328 (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4332 //This is not correct... !!! FIX !!!
4333 //Should be OK now... We'll see...
4334 //Nope. Having the same starstep write problems in phrase mode as we had with pixels... !!! FIX !!!
4335 //This is not causing the problem in Hover Strike... :-/
4336 //The problem was with the SREADX not shifting. Still problems with Z comparisons & other text in pregame screen...
4341 JaguarWriteLong(address + 0, srcz >> 32, BLITTER);
4342 JaguarWriteLong(address + 4, srcz & 0xFFFFFFFF, BLITTER);
4347 JaguarWriteWord(address, srcz & 0x0000FFFF, BLITTER);
4350 #ifdef VERBOSE_BLITTER_LOGGING
4353 // printf(" [%08X%08X]\n", (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4355 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4356 printf(" [dstart=? dend=? pwidth=? srcshift=%X]", srcshift);
4357 printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4364 This is because the address generator was using only 15 bits of the X when it should have
4367 There's a slight problem here: The X pointer isn't wrapping like it should when it hits
4368 the edge of the window... Notice how the X isn't reset at the edge of the window:
4370 Blit! (CMD = 00010000)
4373 a1_base = 000E8008, a2_base = 0001FA68
4374 a1_x = 0000, a1_y = 0000, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0000, a2_y = 0000
4375 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4376 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4377 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4378 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4379 a1_pixsize = 5, a2_pixsize = 5
4380 srcd=7717771777177717 dstd=0000000000000000 patd=7730773077307730 iinc=00000000
4381 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4383 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4384 Entering INNER state...
4385 Entering DWRITE state... Dest write address/pix address: 000E8008/0 [7730773077307730] (icount=009E, inc=2)
4386 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4387 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4388 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4389 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4390 Entering DWRITE state... Dest write address/pix address: 000E8018/0 [7730773077307730] (icount=009C, inc=2)
4391 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4392 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4393 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4394 Entering A1_ADD state [a1_x=0002, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4398 Entering A1_ADD state [a1_x=009C, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4399 Entering DWRITE state... Dest write address/pix address: 000E84F8/0 [7730773077307730] (icount=0000, inc=2)
4400 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4401 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4402 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4403 Entering A1_ADD state [a1_x=009E, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4404 Entering IDLE_INNER state...
4406 Leaving INNER state... (ocount=0104)
4407 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4409 Entering INNER state...
4410 Entering DWRITE state... Dest write address/pix address: 000E8508/0 [7730773077307730] (icount=009E, inc=2)
4411 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4412 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4413 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4414 Entering A1_ADD state [a1_x=00A0, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4415 Entering DWRITE state... Dest write address/pix address: 000E8518/0 [7730773077307730] (icount=009C, inc=2)
4416 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4417 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4418 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4419 Entering A1_ADD state [a1_x=00A2, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4425 #ifdef VERBOSE_BLITTER_LOGGING
4428 //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"));
4429 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"));
4433 int16 adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4434 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4435 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4436 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4437 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4439 #if 0//def VERBOSE_BLITTER_LOGGING
4442 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);
4446 //Now, write to what???
4447 //a2ptrld comes from a2ptrldi...
4448 //I believe it's addbsel that determines the writeback...
4449 // This is where atick[0] & [1] come in, in determining which part (fractional, integer)
4450 // gets written to...
4453 //Kludge, to get A1 channel increment working...
4456 a1_frac_x = addq_x, a1_frac_y = addq_y;
4458 addasel = 2, addbsel = 0, a1fracldi = false;
4459 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4460 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4461 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4462 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4464 a1_x = addq_x, a1_y = addq_y;
4467 a1_x = addq_x, a1_y = addq_y;
4472 #ifdef VERBOSE_BLITTER_LOGGING
4475 //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"));
4476 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"));
4480 //void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
4481 // int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
4482 // int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
4483 // bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
4484 //void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
4485 // int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
4486 //void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
4487 // int16 adda_x, int16 adda_y, int16 addb_x, int16 addb_y, uint8 modx, bool suba_x, bool suba_y)
4488 //void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
4489 int16 adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4490 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4491 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4492 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4493 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4495 #if 0//def VERBOSE_BLITTER_LOGGING
4498 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);
4502 //Now, write to what???
4503 //a2ptrld comes from a2ptrldi...
4504 //I believe it's addbsel that determines the writeback...
4510 Flags: SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
4512 a1_base = 0015B000, a2_base = 0014B000
4513 a1_x = 0000, a1_y = 0000, a1_frac_x = 8000, a1_frac_y = 8000, a2_x = 001F, a2_y = 0038
4514 a1_step_x = FFFFFFC0, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 2AAA, a2_step_x = FFFFFFC0, a2_step_y = 0001
4515 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4516 a1_win_x = 0040, a1_win_y = 0040, a2_mask_x = 0000, a2_mask_y = 0000
4517 a2_mask=F a1add=+inc/+0 a2add=+1/+0
4518 a1_pixsize = 4, a2_pixsize = 4
4519 srcd=FF00FF00FF00FF00 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4520 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, col=0
4522 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4523 Entering INNER state...
4524 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4525 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4526 Entering DWRITE state...
4527 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)
4528 Entering A2_ADD state [a2_x=001F, a2_y=0038, 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: 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)
4533 Entering A2_ADD state [a2_x=0021, a2_y=0039, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4534 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4535 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4536 Entering DWRITE state...
4537 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)
4538 Entering A2_ADD state [a2_x=0023, a2_y=003A, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4539 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4540 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4541 Entering DWRITE state...
4542 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)
4543 Entering A2_ADD state [a2_x=0025, a2_y=003B, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4545 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4546 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4547 Entering DWRITE state...
4548 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)
4549 Entering A2_ADD state [a2_x=009D, a2_y=0077, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4550 Entering IDLE_INNER state...
4551 Leaving INNER state... (ocount=0036)
4552 [in=F a1f=T a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4553 Entering A1FUPDATE state...
4554 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4555 Entering A1UPDATE state... (-32768/-32768 -> 32704/-32767)
4556 [in=F a1f=F a1=F zf=F z=F a2=T iif=F iii=F izf=F izi=F]
4557 Entering A2UPDATE state... (159/120 -> 95/121)
4558 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4559 Entering INNER state...
4562 #ifdef VERBOSE_BLITTER_LOGGING
4565 printf(" Leaving INNER state...");
4570 // The outer counter is updated here as well on the clock cycle...
4572 /* the inner loop is started whenever another state is about to
4573 cause the inner state to go active */
4574 //Instart := ND7 (instart, innert[0], innert[2..7]);
4576 //Actually, it's done only when inner gets asserted without the 2nd line of conditions
4577 //(inner AND !indone)
4579 //Since we don't get here until the inner loop is finished (indone = true) we can get
4580 //away with doing it here...!
4585 #ifdef VERBOSE_BLITTER_LOGGING
4588 printf(" (ocount=%04X)\n", ocount);
4596 #ifdef VERBOSE_BLITTER_LOGGING
4599 printf(" Entering A1FUPDATE state...\n");
4603 uint32 a1_frac_xt = (uint32)a1_frac_x + (uint32)a1_stepf_x;
4604 uint32 a1_frac_yt = (uint32)a1_frac_y + (uint32)a1_stepf_y;
4605 a1FracCInX = a1_frac_xt >> 16;
4606 a1FracCInY = a1_frac_yt >> 16;
4607 a1_frac_x = (uint16)(a1_frac_xt & 0xFFFF);
4608 a1_frac_y = (uint16)(a1_frac_yt & 0xFFFF);
4613 #ifdef VERBOSE_BLITTER_LOGGING
4616 printf(" Entering A1UPDATE state... (%d/%d -> ", a1_x, a1_y);
4620 a1_x += a1_step_x + a1FracCInX;
4621 a1_y += a1_step_y + a1FracCInY;
4622 #ifdef VERBOSE_BLITTER_LOGGING
4625 printf("%d/%d)\n", a1_x, a1_y);
4633 #ifdef VERBOSE_BLITTER_LOGGING
4636 printf(" Entering A2UPDATE state... (%d/%d -> ", a2_x, a2_y);
4642 #ifdef VERBOSE_BLITTER_LOGGING
4645 printf("%d/%d)\n", a2_x, a2_y);
4652 // We never get here! !!! FIX !!!
4654 #ifdef VERBOSE_BLITTER_LOGGING
4657 printf("Done!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
4658 GET16(blitter_ram, A1_PIXEL + 2),
4659 GET16(blitter_ram, A1_PIXEL + 0),
4660 GET16(blitter_ram, A1_FPIXEL + 2),
4661 GET16(blitter_ram, A1_FPIXEL + 0),
4662 GET16(blitter_ram, A2_PIXEL + 2),
4663 GET16(blitter_ram, A2_PIXEL + 0));
4668 // Write values back to registers (in real blitter, these are continuously updated)
4669 SET16(blitter_ram, A1_PIXEL + 2, a1_x);
4670 SET16(blitter_ram, A1_PIXEL + 0, a1_y);
4671 SET16(blitter_ram, A1_FPIXEL + 2, a1_frac_x);
4672 SET16(blitter_ram, A1_FPIXEL + 0, a1_frac_y);
4673 SET16(blitter_ram, A2_PIXEL + 2, a2_x);
4674 SET16(blitter_ram, A2_PIXEL + 0, a2_y);
4676 #ifdef VERBOSE_BLITTER_LOGGING
4679 printf("Writeback!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
4680 GET16(blitter_ram, A1_PIXEL + 2),
4681 GET16(blitter_ram, A1_PIXEL + 0),
4682 GET16(blitter_ram, A1_FPIXEL + 2),
4683 GET16(blitter_ram, A1_FPIXEL + 0),
4684 GET16(blitter_ram, A2_PIXEL + 2),
4685 GET16(blitter_ram, A2_PIXEL + 0));
4692 int16 a1_x = (int16)GET16(blitter_ram, A1_PIXEL + 2);
4693 int16 a1_y = (int16)GET16(blitter_ram, A1_PIXEL + 0);
4694 uint16 a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
4695 uint16 a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
4696 int16 a2_x = (int16)GET16(blitter_ram, A2_PIXEL + 2);
4697 int16 a2_y = (int16)GET16(blitter_ram, A2_PIXEL + 0);
4699 Seems that the ending a1_x should be written between blits, but it doesn't seem to be...
4701 Blit! (CMD = 01800000)
4704 a1_base = 00050000, a2_base = 00070000
4705 a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
4706 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4707 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4708 a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
4709 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4710 a1_pixsize = 4, a2_pixsize = 3
4711 srcd=DEDEDEDEDEDEDEDE dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4712 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4715 Blit! (CMD = 01800000)
4718 a1_base = 00050000, a2_base = 00070000
4719 a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
4720 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4721 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4722 a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
4723 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4724 a1_pixsize = 4, a2_pixsize = 3
4725 srcd=D6D6D6D6D6D6D6D6 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4726 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4732 // Various pieces of the blitter puzzle are teased out here...
4738 INT24/ address // byte address
4739 pixa[0..2] // bit part of address, un-pipe-lined
4755 apipe // load address pipe-line latch
4756 clk // co-processor clock
4757 gena2 // generate A2 as opposed to A1
4758 zaddr // generate Z address
4762 void ADDRGEN(uint32 &address, uint32 &pixa, bool gena2, bool zaddr,
4763 uint16 a1_x, uint16 a1_y, uint32 a1_base, uint8 a1_pitch, uint8 a1_pixsize, uint8 a1_width, uint8 a1_zoffset,
4764 uint16 a2_x, uint16 a2_y, uint32 a2_base, uint8 a2_pitch, uint8 a2_pixsize, uint8 a2_width, uint8 a2_zoffset)
4766 // uint16 x = (gena2 ? a2_x : a1_x) & 0x7FFF;
4767 uint16 x = (gena2 ? a2_x : a1_x) & 0xFFFF; // Actually uses all 16 bits to generate address...!
4768 uint16 y = (gena2 ? a2_y : a1_y) & 0x0FFF;
4769 uint8 width = (gena2 ? a2_width : a1_width);
4770 uint8 pixsize = (gena2 ? a2_pixsize : a1_pixsize);
4771 uint8 pitch = (gena2 ? a2_pitch : a1_pitch);
4772 uint32 base = (gena2 ? a2_base : a1_base) >> 3;//Only upper 21 bits are passed around the bus? Seems like it...
4773 uint8 zoffset = (gena2 ? a2_zoffset : a1_zoffset);
4775 uint32 ytm = ((uint32)y << 2) + (width & 0x02 ? (uint32)y << 1 : 0) + (width & 0x01 ? (uint32)y : 0);
4777 uint32 ya = (ytm << (width >> 2)) >> 2;
4781 /*uint32*/ pixa = pa << pixsize;
4783 uint8 pt = ((pitch & 0x01) && !(pitch & 0x02) ? 0x01 : 0x00)
4784 | (!(pitch & 0x01) && (pitch & 0x02) ? 0x02 : 0x00);
4785 // uint32 phradr = pixa << pt;
4786 uint32 phradr = (pixa >> 6) << pt;
4787 uint32 shup = (pitch == 0x03 ? (pixa >> 6) : 0);
4789 uint8 za = (zaddr ? zoffset : 0) & 0x03;
4790 // uint32 addr = za + (phradr & 0x07) + (shup << 1) + base;
4791 uint32 addr = za + phradr + (shup << 1) + base;
4792 /*uint32*/ address = ((pixa & 0x38) >> 3) | ((addr & 0x1FFFFF) << 3);
4793 #if 0//def VERBOSE_BLITTER_LOGGING
4796 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);
4797 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);
4803 Entering INNER state...
4804 [gena2=T, x=0002, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4805 [ytm=0, ya=0, pa=2, pixa=20, pt=0, phradr=0, shup=0, za=0, addr=12BA, address=95D4]
4806 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4807 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
4808 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4809 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4810 [ytm=0, ya=0, pa=4, pixa=40, pt=0, phradr=1, shup=0, za=0, addr=12BB, address=95D8]
4811 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4812 Source read address/pix address: 000095D8/0 [0054003800009814]
4813 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4814 [gena2=F, x=0000, y=0000, w=20, pxsz=4, ptch=0, b=00006E52, zoff=0]
4815 [ytm=0, ya=0, pa=0, pixa=0, pt=0, phradr=0, shup=0, za=0, addr=6E52, address=37290]
4816 Entering DWRITE state...
4817 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
4818 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4819 [gena2=T, x=0008, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4820 [ytm=0, ya=0, pa=8, pixa=80, pt=0, phradr=2, shup=0, za=0, addr=12BC, address=95E0]
4824 Entering SREAD state...
4825 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4826 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10AC, address=8560]
4827 Source read address/pix address: 00008560/0 [8C27981B327E00F0]
4829 2nd pass (still wrong):
4830 Entering SREAD state...
4831 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4832 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10EC, address=8760]
4833 Source read address/pix address: 00008760/0 [00E06DC04581880C]
4836 Entering SREAD state...
4837 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4838 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=1, shup=0, za=0, addr=10AD, address=8568]
4839 Source read address/pix address: 00008568/0 [6267981A327C00F0]
4841 OK, now we're back into incorrect (or is it?):
4842 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4843 Source extra read address/pix address: 000095D4/0 [0000 001C 0054 0038]
4844 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4845 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4846 Source read address/pix address: 000095D8/0 [0054 0038 0000 9814]
4847 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4848 I think this may be correct...!
4853 // source and destination address update conditions
4855 Sraat0 := AN2 (sraat[0], sreadxi, srcenz\);
4856 Sraat1 := AN2 (sraat[1], sreadi, srcenz\);
4857 Srca_addi := OR4 (srca_addi, szreadxi, szreadi, sraat[0..1]);
4858 Srca_add := FD1Q (srca_add, srca_addi, clk);
4860 Dstaat := AN2 (dstaat, dwritei, dstwrz\);
4861 Dsta_addi := OR2 (dsta_addi, dzwritei, dstaat);
4862 // Dsta_add := FD1Q (dsta_add, dsta_addi, clk);
4864 // source and destination address generate conditions
4866 Gensrc := OR4 (gensrc, sreadxi, szreadxi, sreadi, szreadi);
4867 Gendst := OR4 (gendst, dreadi, dzreadi, dwritei, dzwritei);
4868 Dsta2\ := INV1 (dsta2\, dsta2);
4869 Gena2t0 := NAN2 (gena2t[0], gensrc, dsta2\);
4870 Gena2t1 := NAN2 (gena2t[1], gendst, dsta2);
4871 Gena2i := NAN2 (gena2i, gena2t[0..1]);
4872 Gena2 := FD1QU (gena2, gena2i, clk);
4874 Zaddr := OR4 (zaddr, szreadx, szread, dzread, dzwrite);
4879 // Basically, the above translates to:
4880 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
4882 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
4884 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
4885 bool gendst = dreadi || szreadi || dwritei || dzwritei;
4886 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
4888 bool zaddr = szreadx || szread || dzread || dzwrite;
4892 // source data reads
4894 Srcdpset\ := NAN2 (srcdpset\, readreq, sread);
4895 Srcdpt1 := NAN2 (srcdpt[1], srcdpend, srcdack\);
4896 Srcdpt2 := NAN2 (srcdpt[2], srcdpset\, srcdpt[1]);
4897 Srcdpend := FD2Q (srcdpend, srcdpt[2], clk, reset\);
4899 Srcdxpset\ := NAN2 (srcdxpset\, readreq, sreadx);
4900 Srcdxpt1 := NAN2 (srcdxpt[1], srcdxpend, srcdxack\);
4901 Srcdxpt2 := NAN2 (srcdxpt[2], srcdxpset\, srcdxpt[1]);
4902 Srcdxpend := FD2Q (srcdxpend, srcdxpt[2], clk, reset\);
4904 Sdpend := OR2 (sdpend, srcdxpend, srcdpend);
4905 Srcdreadt := AN2 (srcdreadt, sdpend, read_ack);
4907 //2/9/92 - enhancement?
4908 //Load srcdread on the next tick as well to modify it in srcshade
4910 Srcdreadd := FD1Q (srcdreadd, srcdreadt, clk);
4911 Srcdread := AOR1 (srcdread, srcshade, srcdreadd, srcdreadt);
4915 Srczpset\ := NAN2 (srczpset\, readreq, szread);
4916 Srczpt1 := NAN2 (srczpt[1], srczpend, srczack\);
4917 Srczpt2 := NAN2 (srczpt[2], srczpset\, srczpt[1]);
4918 Srczpend := FD2Q (srczpend, srczpt[2], clk, reset\);
4920 Srczxpset\ := NAN2 (srczxpset\, readreq, szreadx);
4921 Srczxpt1 := NAN2 (srczxpt[1], srczxpend, srczxack\);
4922 Srczxpt2 := NAN2 (srczxpt[2], srczxpset\, srczxpt[1]);
4923 Srczxpend := FD2Q (srczxpend, srczxpt[2], clk, reset\);
4925 Szpend := OR2 (szpend, srczpend, srczxpend);
4926 Srczread := AN2 (srczread, szpend, read_ack);
4928 // destination data reads
4930 Dstdpset\ := NAN2 (dstdpset\, readreq, dread);
4931 Dstdpt0 := NAN2 (dstdpt[0], dstdpend, dstdack\);
4932 Dstdpt1 := NAN2 (dstdpt[1], dstdpset\, dstdpt[0]);
4933 Dstdpend := FD2Q (dstdpend, dstdpt[1], clk, reset\);
4934 Dstdread := AN2 (dstdread, dstdpend, read_ack);
4936 // destination zed reads
4938 Dstzpset\ := NAN2 (dstzpset\, readreq, dzread);
4939 Dstzpt0 := NAN2 (dstzpt[0], dstzpend, dstzack\);
4940 Dstzpt1 := NAN2 (dstzpt[1], dstzpset\, dstzpt[0]);
4941 Dstzpend := FD2Q (dstzpend, dstzpt[1], clk, reset\);
4942 Dstzread := AN2 (dstzread, dstzpend, read_ack);
4947 // Basically, the above translates to:
4948 bool srcdpend = (readreq && sread) || (srcdpend && !srcdack);
4949 bool srcdxpend = (readreq && sreadx) || (srcdxpend && !srcdxack);
4950 bool sdpend = srcxpend || srcdpend;
4951 bool srcdread = ((sdpend && read_ack) && srcshade) || (sdpend && read_ack);//the latter term is lookahead
4955 ////////////////////////////////////////////////////////////////////////////////////////////
4956 ////////////////////////////////////////////////////////////////////////////////////////////
4957 // Here's an important bit: The source data adder logic. Need to track down the inputs!!! //
4958 ////////////////////////////////////////////////////////////////////////////////////////////
4959 ////////////////////////////////////////////////////////////////////////////////////////////
4966 daddasel[0..2] // data adder input A selection
4971 initcin[0..3] // carry into the adders from the initializers
4972 initinc[0..63] // the initialisation increment
4973 initpix[0..15] // Data initialiser pixel value
4985 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
4986 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
4987 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
4988 uint32 zinc, uint32 zstep)
4990 uint32 initpix2 = ((uint32)initpix << 16) | initpix;
4991 uint32 addalo[8], addahi[8];
4992 addalo[0] = dstd & 0xFFFFFFFF;
4993 addalo[1] = initpix2;
4996 addalo[4] = srcd & 0xFFFFFFFF;
4997 addalo[5] = patd & 0xFFFFFFFF;
4998 addalo[6] = srcz1 & 0xFFFFFFFF;
4999 addalo[7] = srcz2 & 0xFFFFFFFF;
5000 addahi[0] = dstd >> 32;
5001 addahi[1] = initpix2;
5004 addahi[4] = srcd >> 32;
5005 addahi[5] = patd >> 32;
5006 addahi[6] = srcz1 >> 32;
5007 addahi[7] = srcz2 >> 32;
5009 adda[0] = addalo[daddasel] & 0xFFFF;
5010 adda[1] = addalo[daddasel] >> 16;
5011 adda[2] = addahi[daddasel] & 0xFFFF;
5012 adda[3] = addahi[daddasel] >> 16;
5015 wordmux[0] = iinc & 0xFFFF;
5016 wordmux[1] = iinc >> 16;
5017 wordmux[2] = zinc & 0xFFFF;
5018 wordmux[3] = zinc >> 16;;
5019 wordmux[4] = istep & 0xFFFF;
5020 wordmux[5] = istep >> 16;;
5021 wordmux[6] = zstep & 0xFFFF;
5022 wordmux[7] = zstep >> 16;;
5023 uint16 word = wordmux[((daddbsel & 0x08) >> 1) | (daddbsel & 0x03)];
5025 bool dbsel2 = daddbsel & 0x04;
5026 bool iincsel = (daddbsel & 0x01) && !(daddbsel & 0x04);
5028 if (!dbsel2 && !iincsel)
5029 addb[0] = srcd & 0xFFFF,
5030 addb[1] = (srcd >> 16) & 0xFFFF,
5031 addb[2] = (srcd >> 32) & 0xFFFF,
5032 addb[3] = (srcd >> 48) & 0xFFFF;
5033 else if (dbsel2 && !iincsel)
5034 addb[0] = addb[1] = addb[2] = addb[3] = word;
5035 else if (!dbsel2 && iincsel)
5036 addb[0] = initinc & 0xFFFF,
5037 addb[1] = (initinc >> 16) & 0xFFFF,
5038 addb[2] = (initinc >> 32) & 0xFFFF,
5039 addb[3] = (initinc >> 48) & 0xFFFF;
5041 addb[0] = addb[1] = addb[2] = addb[3] = 0;
5043 uint8 cinsel = (daddmode >= 1 && daddmode <= 4 ? 1 : 0);
5045 static uint8 co[4];//These are preserved between calls...
5048 for(int i=0; i<4; i++)
5049 cin[i] = initcin[i] | (co[i] & cinsel);
5051 bool eightbit = daddmode & 0x02;
5052 bool sat = daddmode & 0x03;
5053 bool hicinh = ((daddmode & 0x03) == 0x03);
5055 //Note that the carry out is saved between calls to this function...
5056 for(int i=0; i<4; i++)
5057 ADD16SAT(addq[i], co[i], adda[i], addb[i], cin[i], sat, eightbit, hicinh);
5073 void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh)
5077 printf("--> [sat=%s 8b=%s hicinh=%s] %04X + %04X (+ %u) = ", (sat ? "T" : "F"), (eightbit ? "T" : "F"), (hicinh ? "T" : "F"), a, b, cin);
5081 uint32 qt = (a & 0xFF) + (b & 0xFF) + cin;
5082 carry[0] = (qt & 0x0100 ? 1 : 0);
5083 uint16 q = qt & 0x00FF;
5084 carry[1] = (carry[0] && !eightbit ? carry[0] : 0);
5085 qt = (a & 0x0F00) + (b & 0x0F00) + (carry[1] << 8);
5086 carry[2] = (qt & 0x1000 ? 1 : 0);
5088 carry[3] = (carry[2] && !hicinh ? carry[2] : 0);
5089 qt = (a & 0xF000) + (b & 0xF000) + (carry[3] << 12);
5090 co = (qt & 0x10000 ? 1 : 0);
5093 uint8 btop = (eightbit ? (b & 0x0080) >> 7 : (b & 0x8000) >> 15);
5094 uint8 ctop = (eightbit ? carry[0] : co);
5096 bool saturate = sat && (btop ^ ctop);
5097 bool hisaturate = saturate && !eightbit;
5100 printf("bt=%u ct=%u s=%u hs=%u] ", btop, ctop, saturate, hisaturate);
5104 r = (saturate ? (ctop ? 0x00FF : 0x0000) : q & 0x00FF);
5105 r |= (hisaturate ? (ctop ? 0xFF00 : 0x0000) : q & 0xFF00);
5108 printf("%04X (co=%u)\n", r, co);
5113 /** ADDAMUX - Address adder input A selection *******************
5115 This module generates the data loaded into the address adder input A. This is
5116 the update value, and can be one of four registers : A1 step, A2 step, A1
5117 increment and A1 fraction. It can complement these values to perform
5118 subtraction, and it can generate constants to increment / decrement the window
5121 addasel[0..2] select the register to add
5123 000 A1 step integer part
5124 001 A1 step fraction part
5125 010 A1 increment integer part
5126 011 A1 increment fraction part
5129 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all zeroes when
5132 addareg selects register value to be added as opposed to constant
5135 suba_x, suba_y complement the X and Y values
5161 void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
5162 int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
5163 int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
5164 bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
5167 /*INT16/ addac_x, addac_y, addar_x, addar_y, addart_x, addart_y,
5168 INT16/ addas_x, addas_y, suba_x16, suba_y16
5172 Zero := TIE0 (zero);*/
5174 /* Multiplex the register terms */
5176 /*Addaselb[0-2] := BUF8 (addaselb[0-2], addasel[0-2]);
5177 Addart_x := MX4 (addart_x, a1_step_x, a1_stepf_x, a1_inc_x, a1_incf_x, addaselb[0..1]);
5178 Addar_x := MX2 (addar_x, addart_x, a2_step_x, addaselb[2]);
5179 Addart_y := MX4 (addart_y, a1_step_y, a1_stepf_y, a1_inc_y, a1_incf_y, addaselb[0..1]);
5180 Addar_y := MX2 (addar_y, addart_y, a2_step_y, addaselb[2]);*/
5182 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5183 int16 xterm[4], yterm[4];
5184 xterm[0] = a1_step_x, xterm[1] = a1_stepf_x, xterm[2] = a1_inc_x, xterm[3] = a1_incf_x;
5185 yterm[0] = a1_step_y, yterm[1] = a1_stepf_y, yterm[2] = a1_inc_y, yterm[3] = a1_incf_y;
5186 int16 addar_x = (addasel & 0x04 ? a2_step_x : xterm[addasel & 0x03]);
5187 int16 addar_y = (addasel & 0x04 ? a2_step_y : yterm[addasel & 0x03]);
5188 //////////////////////////////////////////////////////////////////////////////////////
5190 /* Generate a constant value - this is a power of 2 in the range
5191 0-64, or zero. The control bits are adda_xconst[0..2], when they
5192 are all 1 the result is 0.
5193 Constants for Y can only be 0 or 1 */
5195 /*Addac_xlo := D38H (addac_x[0..6], unused[0], adda_xconst[0..2]);
5196 Unused[0] := DUMMY (unused[0]);
5198 Addac_x := JOIN (addac_x, addac_x[0..6], zero, zero, zero, zero, zero, zero, zero, zero, zero);
5199 Addac_y := JOIN (addac_y, adda_yconst, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero,
5200 zero, zero, zero, zero, zero);*/
5201 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5202 int16 addac_x = (adda_xconst == 0x07 ? 0 : 1 << adda_xconst);
5203 int16 addac_y = (adda_yconst ? 0x01 : 0);
5204 //////////////////////////////////////////////////////////////////////////////////////
5206 /* Select between constant value and register value */
5208 /*Addas_x := MX2 (addas_x, addac_x, addar_x, addareg);
5209 Addas_y := MX2 (addas_y, addac_y, addar_y, addareg);*/
5210 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5211 int16 addas_x = (addareg ? addar_x : addac_x);
5212 int16 addas_y = (addareg ? addar_y : addac_y);
5213 //////////////////////////////////////////////////////////////////////////////////////
5215 /* Complement these values (complement flag gives adder carry in)*/
5217 /*Suba_x16 := JOIN (suba_x16, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x,
5218 suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x);
5219 Suba_y16 := JOIN (suba_y16, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y,
5220 suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y);
5221 Adda_x := EO (adda_x, suba_x16, addas_x);
5222 Adda_y := EO (adda_y, suba_y16, addas_y);*/
5223 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5224 adda_x = addas_x ^ (suba_x ? 0xFFFF : 0x0000);
5225 adda_y = addas_y ^ (suba_y ? 0xFFFF : 0x0000);
5226 //////////////////////////////////////////////////////////////////////////////////////
5231 /** ADDBMUX - Address adder input B selection *******************
5233 This module selects the register to be updated by the address
5234 adder. This can be one of three registers, the A1 and A2
5235 pointers, or the A1 fractional part. It can also be zero, so that the step
5236 registers load directly into the pointers.
5251 INT16/ zero16 :LOCAL;
5253 void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
5254 int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
5257 /*Zero := TIE0 (zero);
5258 Zero16 := JOIN (zero16, zero, zero, zero, zero, zero, zero, zero,
5259 zero, zero, zero, zero, zero, zero, zero, zero, zero);
5260 Addbselb[0-1] := BUF8 (addbselb[0-1], addbsel[0-1]);
5261 Addb_x := MX4 (addb_x, a1_x, a2_x, a1_frac_x, zero16, addbselb[0..1]);
5262 Addb_y := MX4 (addb_y, a1_y, a2_y, a1_frac_y, zero16, addbselb[0..1]);*/
5263 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5264 int16 xterm[4], yterm[4];
5265 xterm[0] = a1_x, xterm[1] = a2_x, xterm[2] = a1_frac_x, xterm[3] = 0;
5266 yterm[0] = a1_y, yterm[1] = a2_y, yterm[2] = a1_frac_y, yterm[3] = 0;
5267 addb_x = xterm[addbsel & 0x03];
5268 addb_y = yterm[addbsel & 0x03];
5269 //////////////////////////////////////////////////////////////////////////////////////
5274 /** DATAMUX - Address local data bus selection ******************
5276 Select between the adder output and the input data bus
5289 INT16/ gpu_lo, gpu_hi
5292 void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
5294 /*Gpu_lo := JOIN (gpu_lo, gpu_din{0..15});
5295 Gpu_hi := JOIN (gpu_hi, gpu_din{16..31});
5297 Addqselb := BUF8 (addqselb, addqsel);
5298 Data_x := MX2 (data_x, gpu_lo, addq_x, addqselb);
5299 Data_y := MX2 (data_y, gpu_hi, addq_y, addqselb);*/
5300 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5301 data_x = (addqsel ? addq_x : (int16)(gpu_din & 0xFFFF));
5302 data_y = (addqsel ? addq_y : (int16)(gpu_din >> 16));
5303 //////////////////////////////////////////////////////////////////////////////////////
5308 /******************************************************************
5312 Blitter Address Adder
5313 ---------------------
5314 The blitter address adder is a pair of sixteen bit adders, one
5315 each for X and Y. The multiplexing of the input terms is
5316 performed elsewhere, but this adder can also perform modulo
5317 arithmetic to align X-addresses onto phrase boundaries.
5319 modx[0..2] take values
5326 ******************************************************************/
5328 /*IMPORT duplo, tosh;
5334 a1fracldi // propagate address adder carry
5339 clk[0] // co-processor clock
5347 Zero := TIE0 (zero);*/
5348 void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
5349 uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y)
5352 /* Perform the addition */
5354 /*Adder_x := ADD16 (addqt_x[0..15], co_x, adda_x{0..15}, addb_x{0..15}, ci_x);
5355 Adder_y := ADD16 (addq_y[0..15], co_y, adda_y{0..15}, addb_y{0..15}, ci_y);*/
5357 /* latch carry and propagate if required */
5359 /*Cxt0 := AN2 (cxt[0], co_x, a1fracldi);
5360 Cxt1 := FD1Q (cxt[1], cxt[0], clk[0]);
5361 Ci_x := EO (ci_x, cxt[1], suba_x);
5363 yt0 := AN2 (cyt[0], co_y, a1fracldi);
5364 Cyt1 := FD1Q (cyt[1], cyt[0], clk[0]);
5365 Ci_y := EO (ci_y, cyt[1], suba_y);*/
5367 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5368 //I'm sure the following will generate a bunch of warnings, but will have to do for now.
5369 static uint16 co_x = 0, co_y = 0; // Carry out has to propogate between function calls...
5370 uint16 ci_x = co_x ^ (suba_x ? 1 : 0);
5371 uint16 ci_y = co_y ^ (suba_y ? 1 : 0);
5372 uint32 addqt_x = adda_x + addb_x + ci_x;
5373 uint32 addqt_y = adda_y + addb_y + ci_y;
5374 co_x = ((addqt_x & 0x10000) && a1fracldi ? 1 : 0);
5375 co_y = ((addqt_y & 0x10000) && a1fracldi ? 1 : 0);
5376 //////////////////////////////////////////////////////////////////////////////////////
5378 /* Mask low bits of X to 0 if required */
5380 /*Masksel := D38H (unused[0], masksel[0..4], maskbit[5], unused[1], modx[0..2]);
5382 Maskbit[0-4] := OR2 (maskbit[0-4], masksel[0-4], maskbit[1-5]);
5384 Mask[0-5] := MX2 (addq_x[0-5], addqt_x[0-5], zero, maskbit[0-5]);
5386 Addq_x := JOIN (addq_x, addq_x[0..5], addqt_x[6..15]);
5387 Addq_y := JOIN (addq_y, addq_y[0..15]);*/
5389 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5390 int16 mask[8] = { 0xFFFF, 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, 0xFFE0, 0xFFC0, 0x0000 };
5391 addq_x = addqt_x & mask[modx];
5392 addq_y = addqt_y & 0xFFFF;
5393 //////////////////////////////////////////////////////////////////////////////////////
5395 //Unused[0-1] := DUMMY (unused[0-1]);
5402 wdata[0..63] // co-processor write data bus
5404 dcomp[0..7] // data byte equal flags
5405 srcd[0..7] // bits to use for bit to byte expansion
5406 zcomp[0..3] // output from Z comparators
5408 a1_x[0..1] // low two bits of A1 X pointer
5409 big_pix // pixel organisation is big-endian
5410 blitter_active // blitter is active
5411 clk // co-processor clock
5412 cmpdst // compare dest rather than source
5413 colorld // load the pattern color fields
5414 daddasel[0..2] // data adder input A selection
5415 daddbsel[0..3] // data adder input B selection
5416 daddmode[0..2] // data adder mode
5417 daddq_sel // select adder output vs. GPU data
5418 data[0..63] // co-processor read data bus
5419 data_ena // enable write data
5420 data_sel[0..1] // select data to write
5421 dbinh\[0..7] // byte oriented changed data inhibits
5422 dend[0..5] // end of changed write data zone
5423 dpipe[0..1] // load computed data pipe-line latch
5424 dstart[0..5] // start of changed write data zone
5425 dstdld[0..1] // dest data load (two halves)
5426 dstzld[0..1] // dest zed load (two halves)
5427 ext_int // enable extended precision intensity calculations
5428 INT32/ gpu_din // GPU data bus
5429 iincld // I increment load
5430 iincldx // alternate I increment load
5431 init_if // initialise I fraction phase
5432 init_ii // initialise I integer phase
5433 init_zf // initialise Z fraction phase
5434 intld[0..3] // computed intensities load
5435 istepadd // intensity step integer add
5436 istepfadd // intensity step fraction add
5437 istepld // I step load
5438 istepdld // I step delta load
5439 lfu_func[0..3] // LFU function code
5440 patdadd // pattern data gouraud add
5441 patdld[0..1] // pattern data load (two halves)
5442 pdsel[0..1] // select pattern data type
5443 phrase_mode // phrase write mode
5444 reload // transfer contents of double buffers
5445 reset\ // system reset
5446 srcd1ld[0..1] // source register 1 load (two halves)
5447 srcdread // source data read load enable
5448 srczread // source zed read load enable
5449 srcshift[0..5] // source alignment shift
5450 srcz1ld[0..1] // source zed 1 load (two halves)
5451 srcz2add // zed fraction gouraud add
5452 srcz2ld[0..1] // source zed 2 load (two halves)
5453 textrgb // texture mapping in RGB mode
5454 txtd[0..63] // data from the texture unit
5455 zedld[0..3] // computed zeds load
5456 zincld // Z increment load
5457 zmode[0..2] // Z comparator mode
5458 zpipe[0..1] // load computed zed pipe-line latch
5459 zstepadd // zed step integer add
5460 zstepfadd // zed step fraction add
5461 zstepld // Z step load
5462 zstepdld // Z step delta load
5466 void DATA(uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
5467 bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
5468 uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 &patd, bool patdadd,
5469 bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
5470 bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize,
5471 uint64 &srcz, uint64 dstz, uint32 zinc)
5474 Stuff we absolutely *need* to have passed in/out:
5476 patdadd, dstd, srcd, patd, daddasel, daddbsel, daddmode, iinc, srcz1, srcz2, big_pix, phrase_mode, cmpdst
5478 changed patd (wdata I guess...) (Nope. We pass it back directly now...)
5481 // Source data registers
5483 /*Data_src := DATA_SRC (srcdlo, srcdhi, srcz[0..1], srczo[0..1], srczp[0..1], srcz1[0..1], srcz2[0..1], big_pix,
5484 clk, gpu_din, intld[0..3], local_data0, local_data1, srcd1ld[0..1], srcdread, srczread, srcshift[0..5],
5485 srcz1ld[0..1], srcz2add, srcz2ld[0..1], zedld[0..3], zpipe[0..1]);
5486 Srcd[0-7] := JOIN (srcd[0-7], srcdlo{0-7});
5487 Srcd[8-31] := JOIN (srcd[8-31], srcdlo{8-31});
5488 Srcd[32-63] := JOIN (srcd[32-63], srcdhi{0-31});*/
5490 // Destination data registers
5492 /*Data_dst := DATA_DST (dstd[0..63], dstz[0..1], clk, dstdld[0..1], dstzld[0..1], load_data[0..1]);
5493 Dstdlo := JOIN (dstdlo, dstd[0..31]);
5494 Dstdhi := JOIN (dstdhi, dstd[32..63]);*/
5496 // Pattern and Color data registers
5498 // Looks like this is simply another register file for the pattern data registers. No adding or anything funky
5499 // going on. Note that patd & patdv will output the same info.
5500 // Patdldl/h (patdld[0..1]) can select the local_data bus to overwrite the current pattern data...
5501 // Actually, it can be either patdld OR patdadd...!
5502 /*Data_pat := DATA_PAT (colord[0..15], int0dp[8..10], int1dp[8..10], int2dp[8..10], int3dp[8..10], mixsel[0..2],
5503 patd[0..63], patdv[0..1], clk, colorld, dpipe[0], ext_int, gpu_din, intld[0..3], local_data0, local_data1,
5504 patdadd, patdld[0..1], reload, reset\);
5505 Patdlo := JOIN (patdlo, patd[0..31]);
5506 Patdhi := JOIN (patdhi, patd[32..63]);*/
5508 // Multiplying data Mixer (NOT IN JAGUAR I)
5510 /*Datamix := DATAMIX (patdo[0..1], clk, colord[0..15], dpipe[1], dstd[0..63], int0dp[8..10], int1dp[8..10],
5511 int2dp[8..10], int3dp[8..10], mixsel[0..2], patd[0..63], pdsel[0..1], srcd[0..63], textrgb, txtd[0..63]);*/
5513 // Logic function unit
5515 /*Lfu := LFU (lfu[0..1], srcdlo, srcdhi, dstdlo, dstdhi, lfu_func[0..3]);*/
5516 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5517 uint64 funcmask[2] = { 0, 0xFFFFFFFFFFFFFFFFLL };
5518 uint64 func0 = funcmask[lfu_func & 0x01];
5519 uint64 func1 = funcmask[(lfu_func >> 1) & 0x01];
5520 uint64 func2 = funcmask[(lfu_func >> 2) & 0x01];
5521 uint64 func3 = funcmask[(lfu_func >> 3) & 0x01];
5522 uint64 lfu = (~srcd & ~dstd & func0) | (~srcd & dstd & func1) | (srcd & ~dstd & func2) | (srcd & dstd & func3);
5523 //////////////////////////////////////////////////////////////////////////////////////
5525 // Increment and Step Registers
5527 // Does it do anything without the step add lines? Check it!
5528 // No. This is pretty much just a register file without the Jaguar II lines...
5529 /*Inc_step := INC_STEP (iinc, istep[0..31], zinc, zstep[0..31], clk, ext_int, gpu_din, iincld, iincldx, istepadd,
5530 istepfadd, istepld, istepdld, reload, reset\, zincld, zstepadd, zstepfadd, zstepld, zstepdld);
5531 Istep := JOIN (istep, istep[0..31]);
5532 Zstep := JOIN (zstep, zstep[0..31]);*/
5534 // Pixel data comparator
5536 /*Datacomp := DATACOMP (dcomp[0..7], cmpdst, dstdlo, dstdhi, patdlo, patdhi, srcdlo, srcdhi);*/
5537 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5539 uint64 cmpd = patd ^ (cmpdst ? dstd : srcd);
5541 if ((cmpd & 0x00000000000000FFLL) == 0)
5543 if ((cmpd & 0x000000000000FF00LL) == 0)
5545 if ((cmpd & 0x0000000000FF0000LL) == 0)
5547 if ((cmpd & 0x00000000FF000000LL) == 0)
5549 if ((cmpd & 0x000000FF00000000LL) == 0)
5551 if ((cmpd & 0x0000FF0000000000LL) == 0)
5553 if ((cmpd & 0x00FF000000000000LL) == 0)
5555 if ((cmpd & 0xFF00000000000000LL) == 0)
5557 //////////////////////////////////////////////////////////////////////////////////////
5559 // Zed comparator for Z-buffer operations
5561 /*Zedcomp := ZEDCOMP (zcomp[0..3], srczp[0..1], dstz[0..1], zmode[0..2]);*/
5562 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5563 //srczp is srcz pipelined, also it goes through a source shift as well...
5564 /*The shift is basically like so (each piece is 16 bits long):
5567 srcz1lolo srcz1lohi srcz1hilo srcz1hihi srcrz2lolo srcz2lohi srcz2hilo
5569 with srcshift bits 4 & 5 selecting the start position
5571 //So... basically what we have here is:
5574 if ((((srcz & 0x000000000000FFFFLL) < (dstz & 0x000000000000FFFFLL)) && (zmode & 0x01))
5575 || (((srcz & 0x000000000000FFFFLL) == (dstz & 0x000000000000FFFFLL)) && (zmode & 0x02))
5576 || (((srcz & 0x000000000000FFFFLL) > (dstz & 0x000000000000FFFFLL)) && (zmode & 0x04)))
5579 if ((((srcz & 0x00000000FFFF0000LL) < (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x01))
5580 || (((srcz & 0x00000000FFFF0000LL) == (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x02))
5581 || (((srcz & 0x00000000FFFF0000LL) > (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x04)))
5584 if ((((srcz & 0x0000FFFF00000000LL) < (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x01))
5585 || (((srcz & 0x0000FFFF00000000LL) == (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x02))
5586 || (((srcz & 0x0000FFFF00000000LL) > (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x04)))
5589 if ((((srcz & 0xFFFF000000000000LL) < (dstz & 0xFFFF000000000000LL)) && (zmode & 0x01))
5590 || (((srcz & 0xFFFF000000000000LL) == (dstz & 0xFFFF000000000000LL)) && (zmode & 0x02))
5591 || (((srcz & 0xFFFF000000000000LL) > (dstz & 0xFFFF000000000000LL)) && (zmode & 0x04)))
5594 //TEMP, TO TEST IF ZCOMP IS THE CULPRIT...
5595 //Nope, this is NOT the problem...
5597 // We'll do the comparison/bit/byte inhibits here, since that's they way it happens
5598 // in the real thing (dcomp goes out to COMP_CTRL and back into DATA through dbinh)...
5602 COMP_CTRL(dbinht, nowrite,
5603 bcompen, true/*big_pix*/, bkgwren, dcomp, dcompen, icount, pixsize, phrase_mode, srcd & 0xFF, zcomp);
5609 #ifdef VERBOSE_BLITTER_LOGGING
5612 printf("\n[dcomp=%02X zcomp=%02X dbinh=%02X]\n", dcomp, zcomp, dbinh);
5617 //////////////////////////////////////////////////////////////////////////////////////
5620 // The data initializer - allows all four initial values to be computed from one (NOT IN JAGUAR I)
5622 /*Datinit := DATINIT (initcin[0..3], initinc[0..63], initpix[0..15], a1_x[0..1], big_pix, clk, iinc, init_if, init_ii,
5623 init_zf, istep[0..31], zinc, zstep[0..31]);*/
5625 // Adder array for Z and intensity increments
5627 /*Addarray := ADDARRAY (addq[0..3], clk, daddasel[0..2], daddbsel[0..3], daddmode[0..2], dstdlo, dstdhi, iinc,
5628 initcin[0..3], initinc[0..63], initpix[0..15], istep, patdv[0..1], srcdlo, srcdhi, srcz1[0..1],
5629 srcz2[0..1], reset\, zinc, zstep);*/
5630 /*void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
5631 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
5632 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
5633 uint32 zinc, uint32 zstep)*/
5634 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5636 uint8 initcin[4] = { 0, 0, 0, 0 };
5637 ADDARRAY(addq, daddasel, daddbsel, daddmode, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
5639 //This is normally done asynchronously above (thru local_data) when in patdadd mode...
5640 //And now it's passed back to the caller to be persistent between calls...!
5641 //But it's causing some serious fuck-ups in T2K now... !!! FIX !!! [DONE--???]
5642 //Weird! It doesn't anymore...!
5644 patd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
5645 //////////////////////////////////////////////////////////////////////////////////////
5647 // Local data bus multiplexer
5649 /*Local_mux := LOCAL_MUX (local_data[0..1], load_data[0..1],
5650 addq[0..3], gpu_din, data[0..63], blitter_active, daddq_sel);
5651 Local_data0 := JOIN (local_data0, local_data[0]);
5652 Local_data1 := JOIN (local_data1, local_data[1]);*/
5653 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5654 //////////////////////////////////////////////////////////////////////////////////////
5656 // Data output multiplexer and tri-state drive
5658 /*Data_mux := DATA_MUX (wdata[0..63], addq[0..3], big_pix, dstdlo, dstdhi, dstz[0..1], data_sel[0..1], data_ena,
5659 dstart[0..5], dend[0..5], dbinh\[0..7], lfu[0..1], patdo[0..1], phrase_mode, srczo[0..1]);*/
5660 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5661 // NOTE: patdo comes from DATAMIX and can be considered the same as patd for Jaguar I
5663 //////////////////////////////////////////////////////////////////////////////////////
5667 wdata[0..63] // co-processor rwrite data bus
5670 big_pix // Pixel organisation is big-endian
5675 data_sel[0..1] // source of write data
5676 data_ena // enable write data onto read/write bus
5677 dstart[0..5] // start of changed write data
5678 dend[0..5] // end of changed write data
5679 dbinh\[0..7] // byte oriented changed data inhibits
5682 phrase_mode // phrase write mode
5687 /*INT32/ addql[0..1], ddatlo, ddathi zero32
5691 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5692 Zero := TIE0 (zero);
5693 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);*/
5695 /* Generate a changed data mask */
5697 /*Edis := OR6 (edis\, dend[0..5]);
5698 Ecoarse := DECL38E (e_coarse\[0..7], dend[3..5], edis\);
5699 E_coarse[0] := INV1 (e_coarse[0], e_coarse\[0]);
5700 Efine := DECL38E (unused[0], e_fine\[1..7], dend[0..2], e_coarse[0]);*/
5701 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5702 uint8 decl38e[2][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
5703 { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } };
5704 uint8 dech38[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
5705 uint8 dech38el[2][8] = { { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
5706 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
5708 int en = (dend & 0x3F ? 1 : 0);
5709 uint8 e_coarse = decl38e[en][(dend & 0x38) >> 3]; // Actually, this is e_coarse inverted...
5710 uint8 e_fine = decl38e[(e_coarse & 0x01) ^ 0x01][dend & 0x07];
5712 //////////////////////////////////////////////////////////////////////////////////////
5714 /*Scoarse := DECH38 (s_coarse[0..7], dstart[3..5]);
5715 Sfen\ := INV1 (sfen\, s_coarse[0]);
5716 Sfine := DECH38EL (s_fine[0..7], dstart[0..2], sfen\);*/
5717 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5718 uint8 s_coarse = dech38[(dstart & 0x38) >> 3];
5719 uint8 s_fine = dech38el[(s_coarse & 0x01) ^ 0x01][dstart & 0x07];
5720 //////////////////////////////////////////////////////////////////////////////////////
5722 /*Maskt[0] := BUF1 (maskt[0], s_fine[0]);
5723 Maskt[1-7] := OAN1P (maskt[1-7], maskt[0-6], s_fine[1-7], e_fine\[1-7]);*/
5724 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5725 uint16 maskt = s_fine & 0x0001;
5726 maskt |= (((maskt & 0x0001) || (s_fine & 0x02)) && (e_fine & 0x02) ? 0x0002 : 0x0000);
5727 maskt |= (((maskt & 0x0002) || (s_fine & 0x04)) && (e_fine & 0x04) ? 0x0004 : 0x0000);
5728 maskt |= (((maskt & 0x0004) || (s_fine & 0x08)) && (e_fine & 0x08) ? 0x0008 : 0x0000);
5729 maskt |= (((maskt & 0x0008) || (s_fine & 0x10)) && (e_fine & 0x10) ? 0x0010 : 0x0000);
5730 maskt |= (((maskt & 0x0010) || (s_fine & 0x20)) && (e_fine & 0x20) ? 0x0020 : 0x0000);
5731 maskt |= (((maskt & 0x0020) || (s_fine & 0x40)) && (e_fine & 0x40) ? 0x0040 : 0x0000);
5732 maskt |= (((maskt & 0x0040) || (s_fine & 0x80)) && (e_fine & 0x80) ? 0x0080 : 0x0000);
5733 //////////////////////////////////////////////////////////////////////////////////////
5735 /* Produce a look-ahead on the ripple carry:
5736 masktla = s_coarse[0] . /e_coarse[0] */
5737 /*Masktla := AN2 (masktla, s_coarse[0], e_coarse\[0]);
5738 Maskt[8] := OAN1P (maskt[8], masktla, s_coarse[1], e_coarse\[1]);
5739 Maskt[9-14] := OAN1P (maskt[9-14], maskt[8-13], s_coarse[2-7], e_coarse\[2-7]);*/
5740 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5741 maskt |= (((s_coarse & e_coarse & 0x01) || (s_coarse & 0x02)) && (e_coarse & 0x02) ? 0x0100 : 0x0000);
5742 maskt |= (((maskt & 0x0100) || (s_coarse & 0x04)) && (e_coarse & 0x04) ? 0x0200 : 0x0000);
5743 maskt |= (((maskt & 0x0200) || (s_coarse & 0x08)) && (e_coarse & 0x08) ? 0x0400 : 0x0000);
5744 maskt |= (((maskt & 0x0400) || (s_coarse & 0x10)) && (e_coarse & 0x10) ? 0x0800 : 0x0000);
5745 maskt |= (((maskt & 0x0800) || (s_coarse & 0x20)) && (e_coarse & 0x20) ? 0x1000 : 0x0000);
5746 maskt |= (((maskt & 0x1000) || (s_coarse & 0x40)) && (e_coarse & 0x40) ? 0x2000 : 0x0000);
5747 maskt |= (((maskt & 0x2000) || (s_coarse & 0x80)) && (e_coarse & 0x80) ? 0x4000 : 0x0000);
5748 //////////////////////////////////////////////////////////////////////////////////////
5750 /* The bit terms are mirrored for big-endian pixels outside phrase
5751 mode. The byte terms are mirrored for big-endian pixels in phrase
5754 /*Mirror_bit := AN2M (mir_bit, phrase_mode\, big_pix);
5755 Mirror_byte := AN2H (mir_byte, phrase_mode, big_pix);
5757 Masktb[14] := BUF1 (masktb[14], maskt[14]);
5758 Masku[0] := MX4 (masku[0], maskt[0], maskt[7], maskt[14], zero, mir_bit, mir_byte);
5759 Masku[1] := MX4 (masku[1], maskt[1], maskt[6], maskt[14], zero, mir_bit, mir_byte);
5760 Masku[2] := MX4 (masku[2], maskt[2], maskt[5], maskt[14], zero, mir_bit, mir_byte);
5761 Masku[3] := MX4 (masku[3], maskt[3], maskt[4], masktb[14], zero, mir_bit, mir_byte);
5762 Masku[4] := MX4 (masku[4], maskt[4], maskt[3], masktb[14], zero, mir_bit, mir_byte);
5763 Masku[5] := MX4 (masku[5], maskt[5], maskt[2], masktb[14], zero, mir_bit, mir_byte);
5764 Masku[6] := MX4 (masku[6], maskt[6], maskt[1], masktb[14], zero, mir_bit, mir_byte);
5765 Masku[7] := MX4 (masku[7], maskt[7], maskt[0], masktb[14], zero, mir_bit, mir_byte);
5766 Masku[8] := MX2 (masku[8], maskt[8], maskt[13], mir_byte);
5767 Masku[9] := MX2 (masku[9], maskt[9], maskt[12], mir_byte);
5768 Masku[10] := MX2 (masku[10], maskt[10], maskt[11], mir_byte);
5769 Masku[11] := MX2 (masku[11], maskt[11], maskt[10], mir_byte);
5770 Masku[12] := MX2 (masku[12], maskt[12], maskt[9], mir_byte);
5771 Masku[13] := MX2 (masku[13], maskt[13], maskt[8], mir_byte);
5772 Masku[14] := MX2 (masku[14], maskt[14], maskt[0], mir_byte);*/
5773 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5774 bool mir_bit = true/*big_pix*/ && !phrase_mode;
5775 bool mir_byte = true/*big_pix*/ && phrase_mode;
5776 uint16 masku = maskt;
5781 masku |= (maskt >> 7) & 0x0001;
5782 masku |= (maskt >> 5) & 0x0002;
5783 masku |= (maskt >> 3) & 0x0004;
5784 masku |= (maskt >> 1) & 0x0008;
5785 masku |= (maskt << 1) & 0x0010;
5786 masku |= (maskt << 3) & 0x0020;
5787 masku |= (maskt << 5) & 0x0040;
5788 masku |= (maskt << 7) & 0x0080;
5794 masku |= (maskt >> 14) & 0x0001;
5795 masku |= (maskt >> 13) & 0x0002;
5796 masku |= (maskt >> 12) & 0x0004;
5797 masku |= (maskt >> 11) & 0x0008;
5798 masku |= (maskt >> 10) & 0x0010;
5799 masku |= (maskt >> 9) & 0x0020;
5800 masku |= (maskt >> 8) & 0x0040;
5801 masku |= (maskt >> 7) & 0x0080;
5803 masku |= (maskt >> 5) & 0x0100;
5804 masku |= (maskt >> 3) & 0x0200;
5805 masku |= (maskt >> 1) & 0x0400;
5806 masku |= (maskt << 1) & 0x0800;
5807 masku |= (maskt << 3) & 0x1000;
5808 masku |= (maskt << 5) & 0x2000;
5809 masku |= (maskt << 7) & 0x4000;
5811 //////////////////////////////////////////////////////////////////////////////////////
5813 /* The maskt terms define the area for changed data, but the byte
5814 inhibit terms can override these */
5816 /*Mask[0-7] := AN2 (mask[0-7], masku[0-7], dbinh\[0]);
5817 Mask[8-14] := AN2H (mask[8-14], masku[8-14], dbinh\[1-7]);*/
5818 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5819 uint16 mask = masku & (!(dbinh & 0x01) ? 0xFFFF : 0xFF00);
5820 mask &= ~(((uint16)dbinh & 0x00FE) << 7);
5821 //////////////////////////////////////////////////////////////////////////////////////
5823 /*Addql[0] := JOIN (addql[0], addq[0..1]);
5824 Addql[1] := JOIN (addql[1], addq[2..3]);
5826 Dsel0b[0-1] := BUF8 (dsel0b[0-1], data_sel[0]);
5827 Dsel1b[0-1] := BUF8 (dsel1b[0-1], data_sel[1]);
5828 Ddatlo := MX4 (ddatlo, patd[0], lfu[0], addql[0], zero32, dsel0b[0], dsel1b[0]);
5829 Ddathi := MX4 (ddathi, patd[1], lfu[1], addql[1], zero32, dsel0b[1], dsel1b[1]);*/
5830 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5834 dmux[2] = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
5836 uint64 ddat = dmux[data_sel];
5837 //////////////////////////////////////////////////////////////////////////////////////
5839 /*Zed_sel := AN2 (zed_sel, data_sel[0..1]);
5840 Zed_selb[0-1] := BUF8 (zed_selb[0-1], zed_sel);
5842 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]);
5843 Dat[8-15] := MX4 (dat[8-15], dstdlo{8-15}, ddatlo{8-15}, dstzlo{8-15}, srczlo{8-15}, mask[8], zed_selb[0]);
5844 Dat[16-23] := MX4 (dat[16-23], dstdlo{16-23}, ddatlo{16-23}, dstzlo{16-23}, srczlo{16-23}, mask[9], zed_selb[0]);
5845 Dat[24-31] := MX4 (dat[24-31], dstdlo{24-31}, ddatlo{24-31}, dstzlo{24-31}, srczlo{24-31}, mask[10], zed_selb[0]);
5846 Dat[32-39] := MX4 (dat[32-39], dstdhi{0-7}, ddathi{0-7}, dstzhi{0-7}, srczhi{0-7}, mask[11], zed_selb[1]);
5847 Dat[40-47] := MX4 (dat[40-47], dstdhi{8-15}, ddathi{8-15}, dstzhi{8-15}, srczhi{8-15}, mask[12], zed_selb[1]);
5848 Dat[48-55] := MX4 (dat[48-55], dstdhi{16-23}, ddathi{16-23}, dstzhi{16-23}, srczhi{16-23}, mask[13], zed_selb[1]);
5849 Dat[56-63] := MX4 (dat[56-63], dstdhi{24-31}, ddathi{24-31}, dstzhi{24-31}, srczhi{24-31}, mask[14], zed_selb[1]);*/
5850 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5851 wdata = ((ddat & mask) | (dstd & ~mask)) & 0x00000000000000FFLL;
5852 wdata |= (mask & 0x0100 ? ddat : dstd) & 0x000000000000FF00LL;
5853 wdata |= (mask & 0x0200 ? ddat : dstd) & 0x0000000000FF0000LL;
5854 wdata |= (mask & 0x0400 ? ddat : dstd) & 0x00000000FF000000LL;
5855 wdata |= (mask & 0x0800 ? ddat : dstd) & 0x000000FF00000000LL;
5856 wdata |= (mask & 0x1000 ? ddat : dstd) & 0x0000FF0000000000LL;
5857 wdata |= (mask & 0x2000 ? ddat : dstd) & 0x00FF000000000000LL;
5858 wdata |= (mask & 0x4000 ? ddat : dstd) & 0xFF00000000000000LL;
5861 printf("\n[ddat=%08X%08X dstd=%08X%08X wdata=%08X%08X mask=%04X]\n",
5862 (uint32)(ddat >> 32), (uint32)(ddat & 0xFFFFFFFF),
5863 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
5864 (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF), mask);
5867 //This is a crappy way of handling this, but it should work for now...
5869 zwdata = ((srcz & mask) | (dstz & ~mask)) & 0x00000000000000FFLL;
5870 zwdata |= (mask & 0x0100 ? srcz : dstz) & 0x000000000000FF00LL;
5871 zwdata |= (mask & 0x0200 ? srcz : dstz) & 0x0000000000FF0000LL;
5872 zwdata |= (mask & 0x0400 ? srcz : dstz) & 0x00000000FF000000LL;
5873 zwdata |= (mask & 0x0800 ? srcz : dstz) & 0x000000FF00000000LL;
5874 zwdata |= (mask & 0x1000 ? srcz : dstz) & 0x0000FF0000000000LL;
5875 zwdata |= (mask & 0x2000 ? srcz : dstz) & 0x00FF000000000000LL;
5876 zwdata |= (mask & 0x4000 ? srcz : dstz) & 0xFF00000000000000LL;
5879 printf("\n[srcz=%08X%08X dstz=%08X%08X zwdata=%08X%08X mask=%04X]\n",
5880 (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF),
5881 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF),
5882 (uint32)(zwdata >> 32), (uint32)(zwdata & 0xFFFFFFFF), mask);
5886 //////////////////////////////////////////////////////////////////////////////////////
5888 /*Data_enab[0-1] := BUF8 (data_enab[0-1], data_ena);
5889 Datadrv[0-31] := TS (wdata[0-31], dat[0-31], data_enab[0]);
5890 Datadrv[32-63] := TS (wdata[32-63], dat[32-63], data_enab[1]);
5892 Unused[0] := DUMMY (unused[0]);
5897 /** COMP_CTRL - Comparator output control logic *****************
5899 This block is responsible for taking the comparator outputs and
5900 using them as appropriate to inhibit writes. Two methods are
5901 supported for inhibiting write data:
5903 - suppression of the inner loop controlled write operation
5904 - a set of eight byte inhibit lines to write back dest data
5906 The first technique is used in pixel oriented modes, the second in
5907 phrase mode, but the phrase mode form is only applicable to eight
5908 and sixteen bit pixel modes.
5910 Writes can be suppressed by data being equal, by the Z comparator
5911 conditions being met, or by the bit to pixel expansion scheme.
5913 Pipe-lining issues: the data derived comparator outputs are stable
5914 until the next data read, well after the affected write from this
5915 operation. However, the inner counter bits can count immediately
5916 before the ack for the last write. Therefore, it is necessary to
5917 delay bcompbit select terms by one inner loop pipe-line stage,
5918 when generating the select for the data control - the output is
5919 delayed one further tick to give it write data timing (2/34).
5921 There is also a problem with computed data - the new values are
5922 calculated before the write associated with the old value has been
5923 performed. The is taken care of within the zed comparator by
5924 pipe-lining the comparator inputs where appropriate.
5927 //#define LOG_COMP_CTRL
5929 dbinh\[0..7] // destination byte inhibit lines
5930 nowrite // suppress inner loop write operation
5932 bcompen // bit selector inhibit enable
5933 big_pix // pixels are big-endian
5934 bkgwren // enable dest data write in pix inhibit
5935 clk // co-processor clock
5936 dcomp[0..7] // output of data byte comparators
5937 dcompen // data comparator inhibit enable
5938 icount[0..2] // low bits of inner count
5939 pixsize[0..2] // destination pixel size
5940 phrase_mode // phrase write mode
5941 srcd[0..7] // bits to use for bit to byte expansion
5942 step_inner // inner loop advance
5943 zcomp[0..3] // output of word zed comparators
5945 void COMP_CTRL(uint8 &dbinh, bool &nowrite,
5946 bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
5947 uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp)
5951 /*Bkgwren\ := INV1 (bkgwren\, bkgwren);
5952 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5953 Pixsize\[0-2] := INV2 (pixsize\[0-2], pixsize[0-2]);*/
5955 /* The bit comparator bits are derived from the source data, which
5956 will have been suitably aligned for phrase mode. The contents of
5957 the inner counter are used to select which bit to use.
5959 When not in phrase mode the inner count value is used to select
5960 one bit. It is assumed that the count has already occurred, so,
5961 7 selects bit 0, etc. In big-endian pixel mode, this turns round,
5962 so that a count of 7 selects bit 7.
5964 In phrase mode, the eight bits are used directly, and this mode is
5965 only applicable to 8-bit pixel mode (2/34) */
5967 /*Bcompselt[0-2] := EO (bcompselt[0-2], icount[0-2], big_pix);
5968 Bcompbit := MX8 (bcompbit, srcd[7], srcd[6], srcd[5],
5969 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompselt[0..2]);
5970 Bcompbit\ := INV1 (bcompbit\, bcompbit);*/
5971 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5972 #ifdef LOG_COMP_CTRL
5975 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);
5980 uint8 bcompselt = (big_pix ? ~icount : icount) & 0x07;
5981 uint8 bitmask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
5982 bool bcompbit = srcd & bitmask[bcompselt];
5983 //////////////////////////////////////////////////////////////////////////////////////
5985 /* pipe-line the count */
5986 /*Bcompsel[0-2] := FDSYNC (bcompsel[0-2], bcompselt[0-2], step_inner, clk);
5987 Bcompbt := MX8 (bcompbitpt, srcd[7], srcd[6], srcd[5],
5988 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompsel[0..2]);
5989 Bcompbitp := FD1Q (bcompbitp, bcompbitpt, clk);
5990 Bcompbitp\ := INV1 (bcompbitp\, bcompbitp);*/
5992 /* For pixel mode, generate the write inhibit signal for all modes
5993 on bit inhibit, for 8 and 16 bit modes on comparator inhibit, and
5994 for 16 bit mode on Z inhibit
5996 Nowrite = bcompen . /bcompbit . /phrase_mode
5997 + dcompen . dcomp[0] . /phrase_mode . pixsize = 011
5998 + dcompen . dcomp[0..1] . /phrase_mode . pixsize = 100
5999 + zcomp[0] . /phrase_mode . pixsize = 100
6002 /*Nowt0 := NAN3 (nowt[0], bcompen, bcompbit\, phrase_mode\);
6003 Nowt1 := ND6 (nowt[1], dcompen, dcomp[0], phrase_mode\, pixsize\[2], pixsize[0..1]);
6004 Nowt2 := ND7 (nowt[2], dcompen, dcomp[0..1], phrase_mode\, pixsize[2], pixsize\[0..1]);
6005 Nowt3 := NAN5 (nowt[3], zcomp[0], phrase_mode\, pixsize[2], pixsize\[0..1]);
6006 Nowt4 := NAN4 (nowt[4], nowt[0..3]);
6007 Nowrite := AN2 (nowrite, nowt[4], bkgwren\);*/
6008 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6009 nowrite = ((bcompen && !bcompbit && !phrase_mode)
6010 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
6011 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
6012 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4)))
6014 //////////////////////////////////////////////////////////////////////////////////////
6016 /*Winht := NAN3 (winht, bcompen, bcompbitp\, phrase_mode\);
6017 Winhibit := NAN4 (winhibit, winht, nowt[1..3]);*/
6018 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6019 //This is the same as above, but with bcompbit delayed one tick and called 'winhibit'
6020 //Small difference: Besides the pipeline effect, it's also not using !bkgwren...
6021 // bool winhibit = (bcompen && !
6022 bool winhibit = (bcompen && !bcompbit && !phrase_mode)
6023 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
6024 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
6025 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4));
6026 #ifdef LOG_COMP_CTRL
6029 printf("[nw=%s wi=%s]", (nowrite ? "T" : "F"), (winhibit ? "T" : "F"));
6033 //////////////////////////////////////////////////////////////////////////////////////
6035 /* For phrase mode, generate the byte inhibit signals for eight bit
6036 mode 011, or sixteen bit mode 100
6037 dbinh\[0] = pixsize[2] . zcomp[0]
6038 + pixsize[2] . dcomp[0] . dcomp[1] . dcompen
6039 + /pixsize[2] . dcomp[0] . dcompen
6040 + /srcd[0] . bcompen
6042 Inhibits 0-3 are also used when not in phrase mode to write back
6046 /*Srcd\[0-7] := INV1 (srcd\[0-7], srcd[0-7]);
6048 Di0t0 := NAN2H (di0t[0], pixsize[2], zcomp[0]);
6049 Di0t1 := NAN4H (di0t[1], pixsize[2], dcomp[0..1], dcompen);
6050 Di0t2 := NAN2 (di0t[2], srcd\[0], bcompen);
6051 Di0t3 := NAN3 (di0t[3], pixsize\[2], dcomp[0], dcompen);
6052 Di0t4 := NAN4 (di0t[4], di0t[0..3]);
6053 Dbinh[0] := ANR1P (dbinh\[0], di0t[4], phrase_mode, winhibit);*/
6054 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6056 bool di0t0_1 = ((pixsize & 0x04) && (zcomp & 0x01))
6057 || ((pixsize & 0x04) && (dcomp & 0x01) && (dcomp & 0x02) && dcompen);
6058 bool di0t4 = di0t0_1
6059 || (!(srcd & 0x01) && bcompen)
6060 || (!(pixsize & 0x04) && (dcomp & 0x01) && dcompen);
6061 dbinh |= (!((di0t4 && phrase_mode) || winhibit) ? 0x01 : 0x00);
6062 #ifdef LOG_COMP_CTRL
6065 printf("[di0t0_1=%s di0t4=%s]", (di0t0_1 ? "T" : "F"), (di0t4 ? "T" : "F"));
6069 //////////////////////////////////////////////////////////////////////////////////////
6071 /*Di1t0 := NAN3 (di1t[0], pixsize\[2], dcomp[1], dcompen);
6072 Di1t1 := NAN2 (di1t[1], srcd\[1], bcompen);
6073 Di1t2 := NAN4 (di1t[2], di0t[0..1], di1t[0..1]);
6074 Dbinh[1] := ANR1 (dbinh\[1], di1t[2], phrase_mode, winhibit);*/
6075 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6076 bool di1t2 = di0t0_1
6077 || (!(srcd & 0x02) && bcompen)
6078 || (!(pixsize & 0x04) && (dcomp & 0x02) && dcompen);
6079 dbinh |= (!((di1t2 && phrase_mode) || winhibit) ? 0x02 : 0x00);
6080 #ifdef LOG_COMP_CTRL
6083 printf("[di1t2=%s]", (di1t2 ? "T" : "F"));
6087 //////////////////////////////////////////////////////////////////////////////////////
6089 /*Di2t0 := NAN2H (di2t[0], pixsize[2], zcomp[1]);
6090 Di2t1 := NAN4H (di2t[1], pixsize[2], dcomp[2..3], dcompen);
6091 Di2t2 := NAN2 (di2t[2], srcd\[2], bcompen);
6092 Di2t3 := NAN3 (di2t[3], pixsize\[2], dcomp[2], dcompen);
6093 Di2t4 := NAN4 (di2t[4], di2t[0..3]);
6094 Dbinh[2] := ANR1 (dbinh\[2], di2t[4], phrase_mode, winhibit);*/
6095 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6096 //[bcompen=F dcompen=T phrase_mode=T bkgwren=F][nw=F wi=F]
6097 //[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]
6098 //[dcomp=$00 dbinh=$0C][7804780400007804] (icount=0005, inc=4)
6099 bool di2t0_1 = ((pixsize & 0x04) && (zcomp & 0x02))
6100 || ((pixsize & 0x04) && (dcomp & 0x04) && (dcomp & 0x08) && dcompen);
6101 bool di2t4 = di2t0_1
6102 || (!(srcd & 0x04) && bcompen)
6103 || (!(pixsize & 0x04) && (dcomp & 0x04) && dcompen);
6104 dbinh |= (!((di2t4 && phrase_mode) || winhibit) ? 0x04 : 0x00);
6105 #ifdef LOG_COMP_CTRL
6108 printf("[di2t0_1=%s di2t4=%s]", (di2t0_1 ? "T" : "F"), (di2t4 ? "T" : "F"));
6112 //////////////////////////////////////////////////////////////////////////////////////
6114 /*Di3t0 := NAN3 (di3t[0], pixsize\[2], dcomp[3], dcompen);
6115 Di3t1 := NAN2 (di3t[1], srcd\[3], bcompen);
6116 Di3t2 := NAN4 (di3t[2], di2t[0..1], di3t[0..1]);
6117 Dbinh[3] := ANR1 (dbinh\[3], di3t[2], phrase_mode, winhibit);*/
6118 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6119 bool di3t2 = di2t0_1
6120 || (!(srcd & 0x08) && bcompen)
6121 || (!(pixsize & 0x04) && (dcomp & 0x08) && dcompen);
6122 dbinh |= (!((di3t2 && phrase_mode) || winhibit) ? 0x08 : 0x00);
6123 #ifdef LOG_COMP_CTRL
6126 printf("[di3t2=%s]", (di3t2 ? "T" : "F"));
6130 //////////////////////////////////////////////////////////////////////////////////////
6132 /*Di4t0 := NAN2H (di4t[0], pixsize[2], zcomp[2]);
6133 Di4t1 := NAN4H (di4t[1], pixsize[2], dcomp[4..5], dcompen);
6134 Di4t2 := NAN2 (di4t[2], srcd\[4], bcompen);
6135 Di4t3 := NAN3 (di4t[3], pixsize\[2], dcomp[4], dcompen);
6136 Di4t4 := NAN4 (di4t[4], di4t[0..3]);
6137 Dbinh[4] := NAN2 (dbinh\[4], di4t[4], phrase_mode);*/
6138 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6139 bool di4t0_1 = ((pixsize & 0x04) && (zcomp & 0x04))
6140 || ((pixsize & 0x04) && (dcomp & 0x10) && (dcomp & 0x20) && dcompen);
6141 bool di4t4 = di4t0_1
6142 || (!(srcd & 0x10) && bcompen)
6143 || (!(pixsize & 0x04) && (dcomp & 0x10) && dcompen);
6144 dbinh |= (!(di4t4 && phrase_mode) ? 0x10 : 0x00);
6145 #ifdef LOG_COMP_CTRL
6148 printf("[di4t0_1=%s di2t4=%s]", (di4t0_1 ? "T" : "F"), (di4t4 ? "T" : "F"));
6152 //////////////////////////////////////////////////////////////////////////////////////
6154 /*Di5t0 := NAN3 (di5t[0], pixsize\[2], dcomp[5], dcompen);
6155 Di5t1 := NAN2 (di5t[1], srcd\[5], bcompen);
6156 Di5t2 := NAN4 (di5t[2], di4t[0..1], di5t[0..1]);
6157 Dbinh[5] := NAN2 (dbinh\[5], di5t[2], phrase_mode);*/
6158 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6159 bool di5t2 = di4t0_1
6160 || (!(srcd & 0x20) && bcompen)
6161 || (!(pixsize & 0x04) && (dcomp & 0x20) && dcompen);
6162 dbinh |= (!(di5t2 && phrase_mode) ? 0x20 : 0x00);
6163 #ifdef LOG_COMP_CTRL
6166 printf("[di5t2=%s]", (di5t2 ? "T" : "F"));
6170 //////////////////////////////////////////////////////////////////////////////////////
6172 /*Di6t0 := NAN2H (di6t[0], pixsize[2], zcomp[3]);
6173 Di6t1 := NAN4H (di6t[1], pixsize[2], dcomp[6..7], dcompen);
6174 Di6t2 := NAN2 (di6t[2], srcd\[6], bcompen);
6175 Di6t3 := NAN3 (di6t[3], pixsize\[2], dcomp[6], dcompen);
6176 Di6t4 := NAN4 (di6t[4], di6t[0..3]);
6177 Dbinh[6] := NAN2 (dbinh\[6], di6t[4], phrase_mode);*/
6178 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6179 bool di6t0_1 = ((pixsize & 0x04) && (zcomp & 0x08))
6180 || ((pixsize & 0x04) && (dcomp & 0x40) && (dcomp & 0x80) && dcompen);
6181 bool di6t4 = di6t0_1
6182 || (!(srcd & 0x40) && bcompen)
6183 || (!(pixsize & 0x04) && (dcomp & 0x40) && dcompen);
6184 dbinh |= (!(di6t4 && phrase_mode) ? 0x40 : 0x00);
6185 #ifdef LOG_COMP_CTRL
6188 printf("[di6t0_1=%s di6t4=%s]", (di6t0_1 ? "T" : "F"), (di6t4 ? "T" : "F"));
6192 //////////////////////////////////////////////////////////////////////////////////////
6194 /*Di7t0 := NAN3 (di7t[0], pixsize\[2], dcomp[7], dcompen);
6195 Di7t1 := NAN2 (di7t[1], srcd\[7], bcompen);
6196 Di7t2 := NAN4 (di7t[2], di6t[0..1], di7t[0..1]);
6197 Dbinh[7] := NAN2 (dbinh\[7], di7t[2], phrase_mode);*/
6198 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6199 bool di7t2 = di6t0_1
6200 || (!(srcd & 0x80) && bcompen)
6201 || (!(pixsize & 0x04) && (dcomp & 0x80) && dcompen);
6202 dbinh |= (!(di7t2 && phrase_mode) ? 0x80 : 0x00);
6203 #ifdef LOG_COMP_CTRL
6206 printf("[di7t2=%s]", (di7t2 ? "T" : "F"));
6210 //////////////////////////////////////////////////////////////////////////////////////
6215 #ifdef LOG_COMP_CTRL
6218 printf("[dcomp=$%02X dbinh=$%02X]\n ", dcomp, dbinh);
6225 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6226 //////////////////////////////////////////////////////////////////////////////////////
6228 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6229 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6230 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!