6 // I owe a debt of gratitude to Curt Vendel and to John Mathieson--to Curt
7 // for supplying the Oberon ASIC nets and to John for making them available
8 // to Curt. ;-) Without that excellent documentation which shows *exactly*
9 // what's going on inside the TOM chip, we'd all still be guessing as to how
10 // the wily blitter and other pieces of the Jaguar puzzle actually work.
16 // Various conditional compilation goodies...
18 //#define USE_ORIGINAL_BLITTER
19 //#define USE_MIDSUMMER_BLITTER
20 #define USE_MIDSUMMER_BLITTER_MKII
22 // External global variables
24 extern int jaguar_active_memory_dumps;
26 // Local global variables
28 int start_logging = 0;
29 uint8 blitter_working = 0;
31 // Blitter register RAM (most of it is hidden from the user)
33 static uint8 blitter_ram[0x100];
37 bool specialLog = false;
38 extern int effect_start;
39 extern int blit_start_log;
40 void BlitterMidsummer(uint32 cmd);
41 void BlitterMidsummer2(void);
43 #define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
44 | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
45 #define WREG(A,D) (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
46 blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
48 // Blitter registers (offsets from F02200)
50 #define A1_BASE ((UINT32)0x00)
51 #define A1_FLAGS ((UINT32)0x04)
52 #define A1_CLIP ((UINT32)0x08) // Height and width values for clipping
53 #define A1_PIXEL ((UINT32)0x0C) // Integer part of the pixel (Y.i and X.i)
54 #define A1_STEP ((UINT32)0x10) // Integer part of the step
55 #define A1_FSTEP ((UINT32)0x14) // Fractional part of the step
56 #define A1_FPIXEL ((UINT32)0x18) // Fractional part of the pixel (Y.f and X.f)
57 #define A1_INC ((UINT32)0x1C) // Integer part of the increment
58 #define A1_FINC ((UINT32)0x20) // Fractional part of the increment
59 #define A2_BASE ((UINT32)0x24)
60 #define A2_FLAGS ((UINT32)0x28)
61 #define A2_MASK ((UINT32)0x2C) // Modulo values for x and y (M.y and M.x)
62 #define A2_PIXEL ((UINT32)0x30) // Integer part of the pixel (no fractional part for A2)
63 #define A2_STEP ((UINT32)0x34) // Integer part of the step (no fractional part for A2)
64 #define COMMAND ((UINT32)0x38)
65 #define PIXLINECOUNTER ((UINT32)0x3C) // Inner & outer loop values
66 #define SRCDATA ((UINT32)0x40)
67 #define DSTDATA ((UINT32)0x48)
68 #define DSTZ ((UINT32)0x50)
69 #define SRCZINT ((UINT32)0x58)
70 #define SRCZFRAC ((UINT32)0x60)
71 #define PATTERNDATA ((UINT32)0x68)
72 #define INTENSITYINC ((UINT32)0x70)
73 #define ZINC ((UINT32)0x74)
74 #define COLLISIONCTRL ((UINT32)0x78)
75 #define PHRASEINT0 ((UINT32)0x7C)
76 #define PHRASEINT1 ((UINT32)0x80)
77 #define PHRASEINT2 ((UINT32)0x84)
78 #define PHRASEINT3 ((UINT32)0x88)
79 #define PHRASEZ0 ((UINT32)0x8C)
80 #define PHRASEZ1 ((UINT32)0x90)
81 #define PHRASEZ2 ((UINT32)0x94)
82 #define PHRASEZ3 ((UINT32)0x98)
84 // Blitter command bits
86 #define SRCEN (cmd & 0x00000001)
87 #define SRCENZ (cmd & 0x00000002)
88 #define SRCENX (cmd & 0x00000004)
89 #define DSTEN (cmd & 0x00000008)
90 #define DSTENZ (cmd & 0x00000010)
91 #define DSTWRZ (cmd & 0x00000020)
92 #define CLIPA1 (cmd & 0x00000040)
94 #define UPDA1F (cmd & 0x00000100)
95 #define UPDA1 (cmd & 0x00000200)
96 #define UPDA2 (cmd & 0x00000400)
98 #define DSTA2 (cmd & 0x00000800)
100 #define Z_OP_INF (cmd & 0x00040000)
101 #define Z_OP_EQU (cmd & 0x00080000)
102 #define Z_OP_SUP (cmd & 0x00100000)
104 #define LFU_NAN (cmd & 0x00200000)
105 #define LFU_NA (cmd & 0x00400000)
106 #define LFU_AN (cmd & 0x00800000)
107 #define LFU_A (cmd & 0x01000000)
109 #define CMPDST (cmd & 0x02000000)
110 #define BCOMPEN (cmd & 0x04000000)
111 #define DCOMPEN (cmd & 0x08000000)
113 #define PATDSEL (cmd & 0x00010000)
114 #define ADDDSEL (cmd & 0x00020000)
115 #define TOPBEN (cmd & 0x00004000)
116 #define TOPNEN (cmd & 0x00008000)
117 #define BKGWREN (cmd & 0x10000000)
118 #define GOURD (cmd & 0x00001000)
119 #define GOURZ (cmd & 0x00002000)
120 #define SRCSHADE (cmd & 0x40000000)
128 #define XSIGNSUB_A1 (REG(A1_FLAGS)&0x080000)
129 #define XSIGNSUB_A2 (REG(A2_FLAGS)&0x080000)
131 #define YSIGNSUB_A1 (REG(A1_FLAGS)&0x100000)
132 #define YSIGNSUB_A2 (REG(A2_FLAGS)&0x100000)
134 #define YADD1_A1 (REG(A1_FLAGS)&0x040000)
135 #define YADD1_A2 (REG(A2_FLAGS)&0x040000)
137 /*******************************************************************************
138 ********************** STUFF CUT BELOW THIS LINE! ******************************
139 *******************************************************************************/
140 #ifdef USE_ORIGINAL_BLITTER // We're ditching this crap for now...
142 //Put 'em back, once we fix the problem!!! [KO]
144 #define PIXEL_SHIFT_1(a) (((~a##_x) >> 16) & 7)
145 #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))
146 #define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
147 //#define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
150 #define PIXEL_SHIFT_2(a) (((~a##_x) >> 15) & 6)
151 #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))
152 #define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03)
153 //#define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
156 #define PIXEL_SHIFT_4(a) (((~a##_x) >> 14) & 4)
157 #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))
158 #define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f)
159 //#define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
162 #define PIXEL_OFFSET_8(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 7))
163 #define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER))
164 //#define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a)))
167 #define PIXEL_OFFSET_16(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 3))
168 #define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER))
169 //#define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
172 #define PIXEL_OFFSET_32(a) (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
173 #define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER))
174 //#define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
177 #define READ_PIXEL(a,f) (\
178 (((f>>3)&0x07) == 0) ? (READ_PIXEL_1(a)) : \
179 (((f>>3)&0x07) == 1) ? (READ_PIXEL_2(a)) : \
180 (((f>>3)&0x07) == 2) ? (READ_PIXEL_4(a)) : \
181 (((f>>3)&0x07) == 3) ? (READ_PIXEL_8(a)) : \
182 (((f>>3)&0x07) == 4) ? (READ_PIXEL_16(a)) : \
183 (((f>>3)&0x07) == 5) ? (READ_PIXEL_32(a)) : 0)
185 // 16 bpp z data read
186 #define ZDATA_OFFSET_16(a) (PIXEL_OFFSET_16(a) + a##_zoffs * 4)
187 #define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER))
188 //#define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
191 #define READ_ZDATA(a,f) (READ_ZDATA_16(a))
193 // 16 bpp z data write
194 #define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); }
195 //#define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); }
198 #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d);
201 #define READ_RDATA_1(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 19) & 0x04))) >> (((UINT32)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001))
204 #define READ_RDATA_2(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 18) & 0x04))) >> (((UINT32)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003))
207 #define READ_RDATA_4(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 17) & 0x04))) >> (((UINT32)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F))
210 #define READ_RDATA_8(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 16) & 0x04))) >> (((UINT32)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF))
212 // 16 bpp r data read
213 #define READ_RDATA_16(r,a,p) ((p) ? ((REG(r+(((UINT32)a##_x >> 15) & 0x04))) >> (((UINT32)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF))
215 // 32 bpp r data read
216 #define READ_RDATA_32(r,a,p) ((p) ? REG(r+(((UINT32)a##_x >> 14) & 0x04)) : REG(r))
218 // register data read
219 #define READ_RDATA(r,a,f,p) (\
220 (((f>>3)&0x07) == 0) ? (READ_RDATA_1(r,a,p)) : \
221 (((f>>3)&0x07) == 1) ? (READ_RDATA_2(r,a,p)) : \
222 (((f>>3)&0x07) == 2) ? (READ_RDATA_4(r,a,p)) : \
223 (((f>>3)&0x07) == 3) ? (READ_RDATA_8(r,a,p)) : \
224 (((f>>3)&0x07) == 4) ? (READ_RDATA_16(r,a,p)) : \
225 (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0)
228 #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); }
229 //#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))); }
232 #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); }
233 //#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))); }
236 #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); }
237 //#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))); }
240 #define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d, BLITTER); }
241 //#define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d); }
243 // 16 bpp pixel write
244 //#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
245 #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)); }
246 //#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)); }
248 // 32 bpp pixel write
249 #define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); }
250 //#define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); }
253 #define WRITE_PIXEL(a,f,d) {\
254 switch ((f>>3)&0x07) { \
255 case 0: WRITE_PIXEL_1(a,d); break; \
256 case 1: WRITE_PIXEL_2(a,d); break; \
257 case 2: WRITE_PIXEL_4(a,d); break; \
258 case 3: WRITE_PIXEL_8(a,d); break; \
259 case 4: WRITE_PIXEL_16(a,d); break; \
260 case 5: WRITE_PIXEL_32(a,d); break; \
263 // Width in Pixels of a Scanline
264 // This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
265 // of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
266 // the exponent. Valid values for the exponent range from 0 to 11 (decimal). It's easiest to think of it
267 // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to
268 // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place
269 // being shifted to the right 3 places).
270 /*static uint32 blitter_scanline_width[48] =
272 0, 0, 0, 0, // Note: This would really translate to 1, 1, 1, 1
282 1024, 1280, 1536, 1792,
283 2048, 2560, 3072, 3584
286 //static uint8 * tom_ram_8;
287 //static uint8 * paletteRam;
297 static uint32 a1_addr;
298 static uint32 a2_addr;
299 static int32 a1_zoffs;
300 static int32 a2_zoffs;
301 static uint32 xadd_a1_control;
302 static uint32 xadd_a2_control;
303 static int32 a1_pitch;
304 static int32 a2_pitch;
305 static uint32 n_pixels;
306 static uint32 n_lines;
309 static int32 a1_width;
312 static int32 a2_width;
313 static int32 a2_mask_x;
314 static int32 a2_mask_y;
315 static int32 a1_xadd;
316 static int32 a1_yadd;
317 static int32 a2_xadd;
318 static int32 a2_yadd;
319 static uint8 a1_phrase_mode;
320 static uint8 a2_phrase_mode;
321 static int32 a1_step_x = 0;
322 static int32 a1_step_y = 0;
323 static int32 a2_step_x = 0;
324 static int32 a2_step_y = 0;
325 static uint32 outer_loop;
326 static uint32 inner_loop;
327 static uint32 a2_psize;
328 static uint32 a1_psize;
329 static uint32 gouraud_add;
330 //static uint32 gouraud_data;
331 //static uint16 gint[4];
332 //static uint16 gfrac[4];
333 //static uint8 gcolour[4];
336 static int gd_ia, gd_ca;
337 static int colour_index = 0;
339 static uint32 z_i[4];
341 static int32 a1_clip_x, a1_clip_y;
343 // In the spirit of "get it right first, *then* optimize" I've taken the liberty
344 // of removing all the unnecessary code caching. If it turns out to be a good way
345 // to optimize the blitter, then we may revisit it in the future...
348 // Generic blit handler
350 void blitter_generic(uint32 cmd)
353 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
354 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
355 A1 step values: -2 (X), 1 (Y)
356 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
357 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
358 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
359 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
362 // specialLog = true;
363 /*if (cmd == 0x1401060C && blit_start_log)
364 specialLog = true;//*/
366 //uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
367 uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
368 uint32 bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07));
372 WriteLog("About to do n x m blit (BM width is ? pixels)...\n");
373 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);
387 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
389 uint32 a1_start = a1_x, a2_start = a2_x, bitPos = 0;
391 //Kludge for Hover Strike...
392 //I wonder if this kludge is in conjunction with the SRCENX down below...
393 // This isn't so much a kludge but the way things work in BCOMPEN mode...!
394 if (BCOMPEN && SRCENX)
396 if (n_pixels < bppSrc)
397 bitPos = bppSrc - n_pixels;
400 inner_loop = n_pixels;
405 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
407 srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
409 if (!DSTA2) // Data movement: A1 <- A2
411 // load src data and Z
413 if (SRCEN || SRCENX) // Not sure if this is correct... (seems to be...!)
415 srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
418 srczdata = READ_ZDATA(a2, REG(A2_FLAGS));
419 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
420 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
422 else // Use SRCDATA register...
424 srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
426 if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
427 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
430 // load dst data and Z
433 dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
436 dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
438 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
442 dstdata = READ_RDATA(DSTDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
445 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
448 /*This wasn't working... // a1 clipping
449 if (cmd & 0x00000040)
451 if (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7FFF)
452 || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7FFF))
457 srczdata = z_i[colour_index] >> 16;
459 // apply z comparator
460 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
461 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
462 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
464 // apply data comparator
465 // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
466 // Does BCOMPEN only work in 1 bpp mode???
467 // No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!!
468 // This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside
470 if (DCOMPEN | BCOMPEN)
472 //Temp, for testing Hover Strike
473 //Doesn't seem to do it... Why?
474 //What needs to happen here is twofold. First, the address generator in the outer loop has
475 //to honor the BPP when calculating the start address (which it kinda does already). Second,
476 //it has to step bit by bit when using BCOMPEN. How to do this???
478 //small problem with this approach: it's not accurate... We need a proper address to begin with
479 //and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!!
482 uint32 pixShift = (~bitPos) & (bppSrc - 1);
483 srcdata = (srcdata >> pixShift) & 0x01;
486 // if (bitPos % bppSrc == 0)
487 // a2_x += 0x00010000;
490 Interesting (Hover Strike--large letter):
492 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
493 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
494 A1 step values: -2 (X), 1 (Y)
495 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
496 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
497 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
498 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
500 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
501 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
502 A1 step values: -8 (X), 1 (Y)
503 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
504 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
505 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
506 A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000
508 Blit! (0018FA70 <- 008DDC40) count: 1 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: -1 (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: 118/12, A2 x/y: 70/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: 119/12, A2 x/y: 71/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: 127/12, A2 x/y: 66/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: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000
544 //WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit);
545 // compare source pixel with pattern pixel
547 Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: 05810001]
548 CMD -> src: SRCEN dst: misc: a1ctl: mode: ity: PATDSEL z-op: op: LFU_REPLACE ctrl: BCOMPEN
549 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
550 A2 -> pitch: 1 phrases, depth: 1bpp, z-off: 0, width: 16 (10), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
554 // AvP is still wrong, could be cuz it's doing A1 -> A2...
556 // Src is the 1bpp bitmap... DST is the PATTERN!!!
557 // This seems to solve at least ONE of the problems with MC3D...
558 // Why should this be inverted???
559 // Bcuz it is. This is supposed to be used only for a bit -> pixel expansion...
560 /* if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
561 // if (srcdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
563 /* uint32 A2bpp = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
564 if (A2bpp == 1 || A2bpp == 16 || A2bpp == 8)
565 inhibit = (srcdata == 0 ? 1: 0);
566 // inhibit = !srcdata;
568 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
569 // What it boils down to is this:
576 // compare destination pixel with pattern pixel
577 if (dstdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
578 // if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
582 // This is DEFINITELY WRONG
583 // if (a1_phrase_mode || a2_phrase_mode)
584 // inhibit = !inhibit;
589 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
590 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
593 // compute the write data and store
596 // Houston, we have a problem...
597 // Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's
599 //Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008]
600 // CMD -> src: dst: DSTEN misc: a1ctl: mode: GOURD ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
601 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
602 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
603 // A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700
607 // use pattern data for write data
608 writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
612 /*if (blit_start_log)
613 WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/
615 // intensity addition
616 //Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!!
617 /* writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
618 if (!(TOPBEN) && writedata > 0xFF)
621 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
622 if (!(TOPNEN) && writedata > 0xFFF)
623 // writedata = 0xFFF;
625 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/
626 //notneeded--writedata &= 0xFFFF;
627 /*if (blit_start_log)
628 WriteLog("writedata: %08X\n", writedata);//*/
630 Hover Strike ADDDSEL blit:
632 Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208]
633 CMD -> src: dst: DSTEN misc: a1ctl: UPDA1 mode: ity: ADDDSEL z-op: op: LFU_CLEAR ctrl:
634 A1 step values: -320 (X), 1 (Y)
635 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
636 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
637 A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD
639 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
643 //This is correct now, but slow...
644 int16 s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000),
653 writedata = (uint32)sum;
656 //This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!!
657 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
659 if (!TOPNEN && writedata > 0xFFF)
664 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
668 if (LFU_NAN) writedata |= ~srcdata & ~dstdata;
669 if (LFU_NA) writedata |= ~srcdata & dstdata;
670 if (LFU_AN) writedata |= srcdata & ~dstdata;
671 if (LFU_A) writedata |= srcdata & dstdata;
674 //Although, this looks like it's OK... (even if it is shitty!)
675 //According to JTRM, this is part of the four things the blitter does with the write data (the other
676 //three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL
677 //(see above blit example)...
679 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
683 int intensity = srcdata & 0xFF;
684 int ia = gd_ia >> 16;
686 ia = 0xFFFFFF00 | ia;
690 if (intensity > 0xFF)
692 writedata = (srcdata & 0xFF00) | intensity;
701 //Tried 2nd below for Hover Strike: No dice.
702 if (/*a1_phrase_mode || */BKGWREN || !inhibit)
703 // if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit)
705 /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
707 uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
708 // (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
709 if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
710 WriteLog("32bpp pixel write: A1 Phrase mode --> ");
712 // write to the destination
713 WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
715 WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
718 else // if (DSTA2) // Data movement: A1 -> A2
720 // load src data and Z
723 srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
725 srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
726 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
727 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
731 srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
732 if (cmd & 0x001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
733 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
736 // load dst data and Z
739 dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
741 dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
743 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
747 dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
749 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
753 srczdata = z_i[colour_index] >> 16;
755 // apply z comparator
756 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
757 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
758 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
760 // apply data comparator
761 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
762 if (DCOMPEN | BCOMPEN)
766 // compare source pixel with pattern pixel
767 // AvP: Numbers are correct, but sprites are not!
768 //This doesn't seem to be a problem... But could still be wrong...
769 /* if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
770 // if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
772 // This is probably not 100% correct... It works in the 1bpp case
773 // (in A1 <- A2 mode, that is...)
774 // AvP: This is causing blocks to be written instead of bit patterns...
776 // NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
777 /* uint32 A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
778 if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
779 inhibit = (srcdata == 0 ? 1: 0);
781 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
782 // What it boils down to is this:
788 // compare destination pixel with pattern pixel
789 if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
790 // if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
794 // This is DEFINITELY WRONG
795 // if (a1_phrase_mode || a2_phrase_mode)
796 // inhibit = !inhibit;
801 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
802 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
805 // compute the write data and store
810 // use pattern data for write data
811 writedata = READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
815 // intensity addition
816 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
817 if (!(TOPBEN) && writedata > 0xFF)
819 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
820 if (!(TOPNEN) && writedata > 0xFFF)
822 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
827 writedata |= ~srcdata & ~dstdata;
829 writedata |= ~srcdata & dstdata;
831 writedata |= srcdata & ~dstdata;
833 writedata |= srcdata & dstdata;
837 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
841 int intensity = srcdata & 0xFF;
842 int ia = gd_ia >> 16;
844 ia = 0xFFFFFF00 | ia;
848 if (intensity > 0xFF)
850 writedata = (srcdata & 0xFF00) | intensity;
859 if (/*a2_phrase_mode || */BKGWREN || !inhibit)
863 uint32 offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
864 // (((((UINT32)a##_y >> 16) * a##_width) + (((UINT32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((UINT32)a##_x >> 16) & 1))
865 WriteLog("[%08X:%04X] ", offset, writedata);
867 // write to the destination
868 WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
871 WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
875 // Update x and y (inner loop)
876 //Now it does! But crappy, crappy, crappy! !!! FIX !!! [DONE]
877 //This is less than ideal, but it works...
880 a1_x += a1_xadd, a1_y += a1_yadd;
881 a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
885 a1_y += a1_yadd, a2_y = (a2_y + a2_yadd) & a2_mask_y;
889 if (bitPos % bppSrc == 0)
890 a2_x = (a2_x + a2_xadd) & a2_mask_x;
894 a2_x = (a2_x + a2_xadd) & a2_mask_x;
895 if (bitPos % bppSrc == 0)
901 z_i[colour_index] += zadd;
903 if (GOURD || SRCSHADE)
905 gd_i[colour_index] += gd_ia;
906 //Hmm, this doesn't seem to do anything...
907 //But it is correct according to the JTRM...!
908 if ((int32)gd_i[colour_index] < 0)
909 gd_i[colour_index] = 0;
910 if (gd_i[colour_index] > 0x00FFFFFF)
911 gd_i[colour_index] = 0x00FFFFFF;//*/
913 gd_c[colour_index] += gd_ca;
914 if ((int32)gd_c[colour_index] < 0)
915 gd_c[colour_index] = 0;
916 if (gd_c[colour_index] > 0x000000FF)
917 gd_c[colour_index] = 0x000000FF;//*/
920 if (GOURD || SRCSHADE || GOURZ)
923 //This screws things up WORSE (for the BIOS opening screen)
924 // if (a1_phrase_mode || a2_phrase_mode)
925 colour_index = (colour_index + 1) & 0x03;
930 Here's the problem... The phrase mode code!
931 Blit! (00100000 -> 00148000) count: 327 x 267, A1/2_FLAGS: 00004420/00004420 [cmd: 41802E01]
932 CMD -> src: SRCEN dst: misc: a1ctl: UPDA1 UPDA2 mode: DSTA2 GOURZ ity: z-op: op: LFU_REPLACE ctrl: SRCSHADE
933 A1 step values: -327 (X), 1 (Y)
934 A2 step values: -327 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
935 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
936 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
937 A1 x/y: 28/58, A2 x/y: 28/58 Pattern: 00EA7BEA77EA77EA SRCDATA: 7BFF7BFF7BFF7BFF
939 Below fixes it, but then borks:
942 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
943 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
944 A1 step values: -15 (X), 1 (Y)
945 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
946 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
947 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
948 A1 x/y: 173/144, A2 x/y: 4052/0
950 Lesse, with pre-add we'd have:
953 00001111222233334444555566667777
956 |rolls back to here. Hmm.
959 //NOTE: The way to fix the CD BIOS is to uncomment below and comment the stuff after
960 // the phrase mode mucking around. But it fucks up everything else...
961 //#define SCREWY_CD_DEPENDENT
962 #ifdef SCREWY_CD_DEPENDENT
966 a2_y += a2_step_y;//*/
969 //New: Phrase mode taken into account! :-p
970 /* if (a1_phrase_mode) // v1
972 // Bump the pointer to the next phrase boundary
973 // Even though it works, this is crappy... Clean it up!
974 uint32 size = 64 / a1_psize;
976 // Crappy kludge... ('aligning' source to destination)
977 if (a2_phrase_mode && DSTA2)
979 uint32 extra = (a2_start >> 16) % size;
983 uint32 newx = (a1_x >> 16) / size;
984 uint32 newxrem = (a1_x >> 16) % size;
986 a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
988 if (a1_phrase_mode) // v2
990 // Bump the pointer to the next phrase boundary
991 // Even though it works, this is crappy... Clean it up!
992 uint32 size = 64 / a1_psize;
994 // Crappy kludge... ('aligning' source to destination)
995 if (a2_phrase_mode && DSTA2)
997 uint32 extra = (a2_start >> 16) % size;
1001 uint32 pixelSize = (size - 1) << 16;
1002 a1_x = (a1_x + pixelSize) & ~pixelSize;
1005 /* if (a2_phrase_mode) // v1
1007 // Bump the pointer to the next phrase boundary
1008 // Even though it works, this is crappy... Clean it up!
1009 uint32 size = 64 / a2_psize;
1011 // Crappy kludge... ('aligning' source to destination)
1012 // Prolly should do this for A1 channel as well... [DONE]
1013 if (a1_phrase_mode && !DSTA2)
1015 uint32 extra = (a1_start >> 16) % size;
1016 a2_x += extra << 16;
1019 uint32 newx = (a2_x >> 16) / size;
1020 uint32 newxrem = (a2_x >> 16) % size;
1022 a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
1024 if (a2_phrase_mode) // v1
1026 // Bump the pointer to the next phrase boundary
1027 // Even though it works, this is crappy... Clean it up!
1028 uint32 size = 64 / a2_psize;
1030 // Crappy kludge... ('aligning' source to destination)
1031 // Prolly should do this for A1 channel as well... [DONE]
1032 if (a1_phrase_mode && !DSTA2)
1034 uint32 extra = (a1_start >> 16) % size;
1035 a2_x += extra << 16;
1038 uint32 pixelSize = (size - 1) << 16;
1039 a2_x = (a2_x + pixelSize) & ~pixelSize;
1042 //Not entirely: This still mucks things up... !!! FIX !!!
1043 //Should this go before or after the phrase mode mucking around?
1044 #ifndef SCREWY_CD_DEPENDENT
1048 a2_y += a2_step_y;//*/
1052 // write values back to registers
1053 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
1054 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
1055 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
1059 void blitter_blit(uint32 cmd)
1061 //Apparently this is doing *something*, just not sure exactly what...
1062 /*if (cmd == 0x41802E01)
1064 WriteLog("BLIT: Found our blit. Was: %08X ", cmd);
1066 WriteLog("Is: %08X\n", cmd);
1069 uint32 pitchValue[4] = { 0, 1, 3, 2 };
1072 dst = (cmd >> 3) & 0x07;
1073 misc = (cmd >> 6) & 0x03;
1074 a1ctl = (cmd >> 8) & 0x7;
1075 mode = (cmd >> 11) & 0x07;
1076 ity = (cmd >> 14) & 0x0F;
1077 zop = (cmd >> 18) & 0x07;
1078 op = (cmd >> 21) & 0x0F;
1079 ctrl = (cmd >> 25) & 0x3F;
1081 // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
1082 // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
1083 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1084 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1086 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
1087 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
1089 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
1090 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
1092 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
1093 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
1095 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
1096 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
1098 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1099 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1100 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1101 //But it seems to fuck up T2K! !!! FIX !!!
1102 //Could it be sign extended??? Doesn't seem to be so according to JTRM
1103 // a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
1104 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1105 // a1_y &= 0x0FFFFFFF;
1107 // a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
1108 // According to JTRM, this must give a *whole number* of phrases in the current
1109 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1110 UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1111 a1_width = ((0x04 | m) << e) >> 2;//*/
1113 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1114 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1115 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1116 //But it seems to fuck up T2K! !!! FIX !!!
1117 // a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
1118 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1119 // a2_y &= 0x0FFFFFFF;
1121 // a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
1122 // According to JTRM, this must give a *whole number* of phrases in the current
1123 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1124 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1125 a2_width = ((0x04 | m) << e) >> 2;//*/
1126 a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
1127 a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
1129 // Check for "use mask" flag
1130 if (!(REG(A2_FLAGS) & 0x8000))
1132 a2_mask_x = 0xFFFFFFFF; // must be 16.16
1133 a2_mask_y = 0xFFFFFFFF; // must be 16.16
1138 // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
1139 a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
1144 // determine a1_xadd
1145 switch (xadd_a1_control)
1148 // This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
1149 // add phrase offset to X and truncate
1154 // add pixelsize (1) to X
1158 // add zero (for those nice vertical lines)
1162 // add the contents of the increment register
1163 a1_xadd = (REG(A1_INC) << 16) | (REG(A1_FINC) & 0x0000FFFF);
1164 a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
1169 //Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801]
1170 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD
1171 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD
1172 //if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// &&
1173 // UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1174 //Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it...
1175 //if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801)
1176 // A1 x/y: 14368/7, A2 x/y: 150/36
1177 //This is it... The problem...
1178 //if ((a1_x >> 16) == 14368) // 14368 = $3820
1179 // return; //Lesse what we got...
1189 // determine a2_xadd
1190 switch (xadd_a2_control)
1193 // add phrase offset to X and truncate
1198 // add pixelsize (1) to X
1202 // add zero (for those nice vertical lines)
1205 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
1207 WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
1208 // add the contents of the increment register
1209 // since there is no register for a2 we just add 1
1210 //Let's do nothing, since it's not listed as a valid bit combo...
1211 // a2_xadd = 1 << 16;
1218 // Modify outer loop steps based on blitter command
1226 a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
1227 a1_step_y = (REG(A1_FSTEP) >> 16);
1230 a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
1231 a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
1234 a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
1235 a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
1237 outer_loop = n_lines;
1242 a1_clip_x = REG(A1_CLIP) & 0x7FFF,
1243 a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
1245 // This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX]
1246 // Err, this is pixel size... (and it's OK)
1247 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
1248 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
1255 for(int v=0; v<4; v++)
1256 z_i[v] = REG(PHRASEZ0 + v*4);
1260 if (GOURD || GOURZ || SRCSHADE)
1262 gd_c[0] = blitter_ram[PATTERNDATA + 6];
1263 gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
1264 | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
1266 gd_c[1] = blitter_ram[PATTERNDATA + 4];
1267 gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
1268 | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
1270 gd_c[2] = blitter_ram[PATTERNDATA + 2];
1271 gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
1272 | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
1274 gd_c[3] = blitter_ram[PATTERNDATA + 0];
1275 gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
1276 | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
1278 gouraud_add = REG(INTENSITYINC);
1280 gd_ia = gouraud_add & 0x00FFFFFF;
1281 if (gd_ia & 0x00800000)
1282 gd_ia = 0xFF000000 | gd_ia;
1284 gd_ca = (gouraud_add >> 24) & 0xFF;
1285 if (gd_ca & 0x00000080)
1286 gd_ca = 0xFFFFFF00 | gd_ca;
1289 // Bit comparitor fixing...
1292 // Determine the data flow direction...
1294 a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07));
1298 /* if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!!
1300 // Determine the data flow direction...
1308 WriteLog("Blit!\n");
1309 WriteLog(" cmd = 0x%.8x\n",cmd);
1310 WriteLog(" a1_base = %08X\n", a1_addr);
1311 WriteLog(" a1_pitch = %d\n", a1_pitch);
1312 WriteLog(" a1_psize = %d\n", a1_psize);
1313 WriteLog(" a1_width = %d\n", a1_width);
1314 WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1315 WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0);
1316 WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1317 WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1318 WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0);
1319 WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0);
1320 WriteLog(" a1_zoffs = %i\n",a1_zoffs);
1322 WriteLog(" a2_base = %08X\n", a2_addr);
1323 WriteLog(" a2_pitch = %d\n", a2_pitch);
1324 WriteLog(" a2_psize = %d\n", a2_psize);
1325 WriteLog(" a2_width = %d\n", a2_width);
1326 WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1327 WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0);
1328 WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1329 WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1330 WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0);
1331 WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0);
1332 WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x);
1333 WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y);
1334 WriteLog(" a2_zoffs = %i\n",a2_zoffs);
1336 WriteLog(" count = %d x %d\n", n_pixels, n_lines);
1338 WriteLog(" command = %08X\n", cmd);
1339 WriteLog(" dsten = %i\n",DSTEN);
1340 WriteLog(" srcen = %i\n",SRCEN);
1341 WriteLog(" patdsel = %i\n",PATDSEL);
1342 WriteLog(" color = 0x%.8x\n",REG(PATTERNDATA));
1343 WriteLog(" dcompen = %i\n",DCOMPEN);
1344 WriteLog(" bcompen = %i\n",BCOMPEN);
1345 WriteLog(" cmpdst = %i\n",CMPDST);
1346 WriteLog(" GOURZ = %i\n",GOURZ);
1347 WriteLog(" GOURD = %i\n",GOURD);
1348 WriteLog(" SRCSHADE= %i\n",SRCSHADE);
1352 //NOTE: Pitch is ignored!
1354 //This *might* be the altimeter blits (they are)...
1355 //On captured screen, x-pos for black (inner) is 259, for pink is 257
1356 //Black is short by 3, pink is short by 1...
1358 Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1359 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1360 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1361 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1362 A1 x/y: 262/124, A2 x/y: 128/0
1363 Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1364 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1365 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1366 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1367 A1 x/y: 264/117, A2 x/y: 407/0
1369 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1370 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1371 A1 step values: -10 (X), 1 (Y)
1372 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1373 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1374 A1 x/y: 262/132, A2 x/y: 129/0
1375 Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1376 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1377 A1 step values: -8 (X), 1 (Y)
1378 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1379 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1380 A1 x/y: 264/128, A2 x/y: 336/0
1382 264v vCursor ends up here...
1386 262v vCursor ends up here...
1390 Fixed! Now for more:
1392 ; This looks like the ship icon in the upper left corner...
1394 Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1395 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1396 A1 step values: -12 (X), 1 (Y)
1397 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1398 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1399 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1400 A1 x/y: 20/24, A2 x/y: 5780/0
1404 More (not sure this is a blitter problem as much as it's a GPU problem):
1405 All but the "M" are trashed...
1406 This does *NOT* look like a blitter problem, as it's rendering properly...
1407 Actually, if you look at the A1 step values, there IS a discrepancy!
1411 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1412 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1413 A1 step values: -14 (X), 1 (Y)
1414 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1415 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1416 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1417 A1 x/y: 134/144, A2 x/y: 2516/0
1422 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1423 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1424 A1 step values: -13 (X), 1 (Y)
1425 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1426 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1427 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1428 A1 x/y: 147/144, A2 x/y: 2660/0
1432 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1433 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1434 A1 step values: -12 (X), 1 (Y)
1435 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1436 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1437 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1438 A1 x/y: 160/144, A2 x/y: 3764/0
1442 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1443 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1444 A1 step values: -15 (X), 1 (Y)
1445 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1446 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1447 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1448 A1 x/y: 173/144, A2 x/y: 4052/0
1451 //extern int op_start_log;
1454 char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
1455 char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
1456 char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1457 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1458 uint32 /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
1459 a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F,
1460 zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/;
1461 UINT32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1462 uint32 p1 = a1f & 0x07, p2 = a2f & 0x07,
1463 d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
1464 zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
1465 w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
1466 ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
1467 UINT32 iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
1468 UINT32 iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
1469 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);
1470 // 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);
1472 WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
1473 WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
1474 WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
1475 WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
1476 WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "GOURZ" : ""));
1477 WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : ""));
1478 WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
1479 WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
1480 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" : ""));
1483 WriteLog(" A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16);
1486 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);
1488 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"));
1489 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"));
1490 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));
1491 // blit_start_log = 0;
1492 // op_start_log = 1;
1495 blitter_working = 1;
1496 //#ifndef USE_GENERIC_BLITTER
1497 // if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
1499 blitter_generic(cmd);
1501 /*if (blit_start_log)
1503 if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
1505 WriteLog("\nBytes at 004D58:\n");
1506 for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
1507 WriteLog("%02X ", JaguarReadByte(i));
1508 WriteLog("\nBytes at F03000:\n");
1509 for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
1510 WriteLog("%02X ", JaguarReadByte(i));
1515 blitter_working = 0;
1517 #endif // of the #if 0 near the top...
1518 /*******************************************************************************
1519 ********************** STUFF CUT ABOVE THIS LINE! ******************************
1520 *******************************************************************************/
1522 void blitter_init(void)
1527 void blitter_reset(void)
1529 memset(blitter_ram, 0x00, 0xA0);
1532 void blitter_done(void)
1534 WriteLog("BLIT: Done.\n");
1537 uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1542 //This isn't cycle accurate--how to fix? !!! FIX !!!
1543 //Probably have to do some multi-threaded implementation or at least a reentrant safe implementation...
1544 if (offset == (0x38 + 3))
1545 return 0x01; // always idle
1547 // CHECK HERE ONCE THIS FIX HAS BEEN TESTED: [ ]
1549 if (offset >= 0x04 && offset <= 0x07)
1550 //This is it. I wonder if it just ignores the lower three bits?
1551 //No, this is a documented Jaguar I bug. It also bites the read at $F02230 as well...
1552 return blitter_ram[offset + 0x08]; // A1_PIXEL ($F0220C) read at $F02204
1554 if (offset >= 0x2C && offset <= 0x2F)
1555 return blitter_ram[offset + 0x04]; // A2_PIXEL ($F02230) read at $F0222C
1557 return blitter_ram[offset];
1561 uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1563 return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
1567 uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1569 return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
1572 void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1574 /*if (offset & 0xFF == 0x7B)
1575 WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
1577 /*if ((offset >= PATTERNDATA) && (offset < PATTERNDATA + 8))
1579 printf("--> %s wrote %02X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - PATTERNDATA);
1583 // This handles writes to INTENSITY0-3 by also writing them to their proper places in
1584 // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
1585 if ((offset >= 0x7C) && (offset <= 0x9B))
1589 // INTENSITY registers 0-3
1591 case 0x7D: blitter_ram[PATTERNDATA + 7] = data; break;
1592 case 0x7E: blitter_ram[SRCDATA + 6] = data; break;
1593 case 0x7F: blitter_ram[SRCDATA + 7] = data; break;
1596 case 0x81: blitter_ram[PATTERNDATA + 5] = data; break;
1597 case 0x82: blitter_ram[SRCDATA + 4] = data; break;
1598 case 0x83: blitter_ram[SRCDATA + 5] = data; break;
1601 case 0x85: blitter_ram[PATTERNDATA + 3] = data; break;
1602 case 0x86: blitter_ram[SRCDATA + 2] = data; break;
1603 case 0x87: blitter_ram[SRCDATA + 3] = data; break;
1606 case 0x89: blitter_ram[PATTERNDATA + 1] = data; break;
1607 case 0x8A: blitter_ram[SRCDATA + 0] = data; break;
1608 case 0x8B: blitter_ram[SRCDATA + 1] = data; break;
1612 case 0x8C: blitter_ram[SRCZINT + 6] = data; break;
1613 case 0x8D: blitter_ram[SRCZINT + 7] = data; break;
1614 case 0x8E: blitter_ram[SRCZFRAC + 6] = data; break;
1615 case 0x8F: blitter_ram[SRCZFRAC + 7] = data; break;
1617 case 0x90: blitter_ram[SRCZINT + 4] = data; break;
1618 case 0x91: blitter_ram[SRCZINT + 5] = data; break;
1619 case 0x92: blitter_ram[SRCZFRAC + 4] = data; break;
1620 case 0x93: blitter_ram[SRCZFRAC + 5] = data; break;
1622 case 0x94: blitter_ram[SRCZINT + 2] = data; break;
1623 case 0x95: blitter_ram[SRCZINT + 3] = data; break;
1624 case 0x96: blitter_ram[SRCZFRAC + 2] = data; break;
1625 case 0x97: blitter_ram[SRCZFRAC + 3] = data; break;
1627 case 0x98: blitter_ram[SRCZINT + 0] = data; break;
1628 case 0x99: blitter_ram[SRCZINT + 1] = data; break;
1629 case 0x9A: blitter_ram[SRCZFRAC + 0] = data; break;
1630 case 0x9B: blitter_ram[SRCZFRAC + 1] = data; break;
1634 // It looks weird, but this is how the 64 bit registers are actually handled...!
1636 else if ((offset >= SRCDATA + 0) && (offset <= SRCDATA + 3)
1637 || (offset >= DSTDATA + 0) && (offset <= DSTDATA + 3)
1638 || (offset >= DSTZ + 0) && (offset <= DSTZ + 3)
1639 || (offset >= SRCZINT + 0) && (offset <= SRCZINT + 3)
1640 || (offset >= SRCZFRAC + 0) && (offset <= SRCZFRAC + 3)
1641 || (offset >= PATTERNDATA + 0) && (offset <= PATTERNDATA + 3))
1643 blitter_ram[offset + 4] = data;
1645 else if ((offset >= SRCDATA + 4) && (offset <= SRCDATA + 7)
1646 || (offset >= DSTDATA + 4) && (offset <= DSTDATA + 7)
1647 || (offset >= DSTZ + 4) && (offset <= DSTZ + 7)
1648 || (offset >= SRCZINT + 4) && (offset <= SRCZINT + 7)
1649 || (offset >= SRCZFRAC + 4) && (offset <= SRCZFRAC + 7)
1650 || (offset >= PATTERNDATA + 4) && (offset <= PATTERNDATA + 7))
1652 blitter_ram[offset - 4] = data;
1655 blitter_ram[offset] = data;
1658 void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1660 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1662 printf("----> %s wrote %04X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1666 /* if (offset & 0xFF == A1_PIXEL && data == 14368)
1668 WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1669 extern bool doGPUDis;
1672 if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368)
1674 WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1675 extern bool doGPUDis;
1680 BlitterWriteByte(offset + 0, data >> 8, who);
1681 BlitterWriteByte(offset + 1, data & 0xFF, who);
1683 if ((offset & 0xFF) == 0x3A)
1684 // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
1685 // But then again, according to the Jaguar docs, this is correct...!
1686 /*extern int blit_start_log;
1687 extern bool doGPUDis;
1690 WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
1693 #ifdef USE_ORIGINAL_BLITTER
1694 blitter_blit(GET32(blitter_ram, 0x38));
1696 #ifdef USE_MIDSUMMER_BLITTER
1697 BlitterMidsummer(GET32(blitter_ram, 0x38));
1699 #ifdef USE_MIDSUMMER_BLITTER_MKII
1700 BlitterMidsummer2();
1705 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1707 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1709 printf("------> %s wrote %08X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1713 /* if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368)
1715 WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1716 extern bool doGPUDis;
1721 BlitterWriteWord(offset + 0, data >> 16, who);
1722 BlitterWriteWord(offset + 2, data & 0xFFFF, who);
1727 char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1728 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1729 uint32 cmd = GET32(blitter_ram, 0x38);
1730 UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1731 UINT32 a1_width = ((0x04 | m) << e) >> 2;
1732 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1733 UINT32 a2_width = ((0x04 | m) << e) >> 2;
1735 WriteLog("Blit!\n");
1736 WriteLog(" COMMAND = %08X\n", cmd);
1737 WriteLog(" a1_base = %08X\n", REG(A1_BASE));
1738 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),
1739 (REG(A1_FLAGS) & 0x100000 ? '1' : '0'),
1740 (REG(A1_FLAGS) & 0x080000 ? '1' : '0'),
1741 (REG(A1_FLAGS) & 0x040000 ? '1' : '0'),
1742 (REG(A1_FLAGS) & 0x020000 ? '1' : '0'),
1743 (REG(A1_FLAGS) & 0x010000 ? '1' : '0'),
1744 (REG(A1_FLAGS) & 0x004000 ? '1' : '0'),
1745 (REG(A1_FLAGS) & 0x002000 ? '1' : '0'),
1746 (REG(A1_FLAGS) & 0x001000 ? '1' : '0'),
1747 (REG(A1_FLAGS) & 0x000800 ? '1' : '0'),
1748 (REG(A1_FLAGS) & 0x000400 ? '1' : '0'),
1749 (REG(A1_FLAGS) & 0x000200 ? '1' : '0'),
1750 (REG(A1_FLAGS) & 0x000100 ? '1' : '0'),
1751 (REG(A1_FLAGS) & 0x000080 ? '1' : '0'),
1752 (REG(A1_FLAGS) & 0x000040 ? '1' : '0'),
1753 (REG(A1_FLAGS) & 0x000020 ? '1' : '0'),
1754 (REG(A1_FLAGS) & 0x000010 ? '1' : '0'),
1755 (REG(A1_FLAGS) & 0x000008 ? '1' : '0'),
1756 (REG(A1_FLAGS) & 0x000002 ? '1' : '0'),
1757 (REG(A1_FLAGS) & 0x000001 ? '1' : '0'));
1758 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1759 REG(A1_FLAGS) & 0x00003, (REG(A1_FLAGS) & 0x00038) >> 3,
1760 (REG(A1_FLAGS) & 0x001C0) >> 6, a1_width, (REG(A1_FLAGS) & 0x30000) >> 16);
1761 WriteLog(" a1_clip = %u, %u (%08X)\n", GET16(blitter_ram, A1_CLIP + 2), GET16(blitter_ram, A1_CLIP + 0), GET32(blitter_ram, A1_CLIP));
1762 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));
1763 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));
1764 WriteLog(" a1_fstep = %u, %u (%08X)\n", GET16(blitter_ram, A1_FSTEP + 2), GET16(blitter_ram, A1_FSTEP + 0), GET32(blitter_ram, A1_FSTEP));
1765 WriteLog(" a1_fpixel= %u, %u (%08X)\n", GET16(blitter_ram, A1_FPIXEL + 2), GET16(blitter_ram, A1_FPIXEL + 0), GET32(blitter_ram, A1_FPIXEL));
1766 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));
1767 WriteLog(" a1_finc = %u, %u (%08X)\n", GET16(blitter_ram, A1_FINC + 2), GET16(blitter_ram, A1_FINC + 0), GET32(blitter_ram, A1_FINC));
1769 WriteLog(" a2_base = %08X\n", REG(A2_BASE));
1770 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),
1771 (REG(A2_FLAGS) & 0x100000 ? '1' : '0'),
1772 (REG(A2_FLAGS) & 0x080000 ? '1' : '0'),
1773 (REG(A2_FLAGS) & 0x040000 ? '1' : '0'),
1774 (REG(A2_FLAGS) & 0x020000 ? '1' : '0'),
1775 (REG(A2_FLAGS) & 0x010000 ? '1' : '0'),
1776 (REG(A2_FLAGS) & 0x008000 ? '1' : '0'),
1777 (REG(A2_FLAGS) & 0x004000 ? '1' : '0'),
1778 (REG(A2_FLAGS) & 0x002000 ? '1' : '0'),
1779 (REG(A2_FLAGS) & 0x001000 ? '1' : '0'),
1780 (REG(A2_FLAGS) & 0x000800 ? '1' : '0'),
1781 (REG(A2_FLAGS) & 0x000400 ? '1' : '0'),
1782 (REG(A2_FLAGS) & 0x000200 ? '1' : '0'),
1783 (REG(A2_FLAGS) & 0x000100 ? '1' : '0'),
1784 (REG(A2_FLAGS) & 0x000080 ? '1' : '0'),
1785 (REG(A2_FLAGS) & 0x000040 ? '1' : '0'),
1786 (REG(A2_FLAGS) & 0x000020 ? '1' : '0'),
1787 (REG(A2_FLAGS) & 0x000010 ? '1' : '0'),
1788 (REG(A2_FLAGS) & 0x000008 ? '1' : '0'),
1789 (REG(A2_FLAGS) & 0x000002 ? '1' : '0'),
1790 (REG(A2_FLAGS) & 0x000001 ? '1' : '0'));
1791 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1792 REG(A2_FLAGS) & 0x00003, (REG(A2_FLAGS) & 0x00038) >> 3,
1793 (REG(A2_FLAGS) & 0x001C0) >> 6, a2_width, (REG(A2_FLAGS) & 0x30000) >> 16);
1794 WriteLog(" a2_mask = %u, %u (%08X)\n", GET16(blitter_ram, A2_MASK + 2), GET16(blitter_ram, A2_MASK + 0), GET32(blitter_ram, A2_MASK));
1795 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));
1796 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));
1798 WriteLog(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
1800 WriteLog(" SRCEN = %s\n", (SRCEN ? "1" : "0"));
1801 WriteLog(" SRCENZ = %s\n", (SRCENZ ? "1" : "0"));
1802 WriteLog(" SRCENX = %s\n", (SRCENX ? "1" : "0"));
1803 WriteLog(" DSTEN = %s\n", (DSTEN ? "1" : "0"));
1804 WriteLog(" DSTENZ = %s\n", (DSTENZ ? "1" : "0"));
1805 WriteLog(" DSTWRZ = %s\n", (DSTWRZ ? "1" : "0"));
1806 WriteLog(" CLIPA1 = %s\n", (CLIPA1 ? "1" : "0"));
1807 WriteLog(" UPDA1F = %s\n", (UPDA1F ? "1" : "0"));
1808 WriteLog(" UPDA1 = %s\n", (UPDA1 ? "1" : "0"));
1809 WriteLog(" UPDA2 = %s\n", (UPDA2 ? "1" : "0"));
1810 WriteLog(" DSTA2 = %s\n", (DSTA2 ? "1" : "0"));
1811 WriteLog(" ZOP = %s %s %s\n", (Z_OP_INF ? "<" : ""), (Z_OP_EQU ? "=" : ""), (Z_OP_SUP ? ">" : ""));
1812 WriteLog("--LFUFUNC = %s\n", opStr[(cmd >> 21) & 0x0F]);
1813 WriteLog("| PATDSEL = %s (PD=%08X%08X)\n", (PATDSEL ? "1" : "0"), REG(PATTERNDATA), REG(PATTERNDATA + 4));
1814 WriteLog("--ADDDSEL = %s\n", (ADDDSEL ? "1" : "0"));
1815 WriteLog(" CMPDST = %s\n", (CMPDST ? "1" : "0"));
1816 WriteLog(" BCOMPEN = %s\n", (BCOMPEN ? "1" : "0"));
1817 WriteLog(" DCOMPEN = %s\n", (DCOMPEN ? "1" : "0"));
1818 WriteLog(" TOPBEN = %s\n", (TOPBEN ? "1" : "0"));
1819 WriteLog(" TOPNEN = %s\n", (TOPNEN ? "1" : "0"));
1820 WriteLog(" BKGWREN = %s\n", (BKGWREN ? "1" : "0"));
1821 WriteLog(" GOURD = %s (II=%08X, SD=%08X%08X)\n", (GOURD ? "1" : "0"), REG(INTENSITYINC), REG(SRCDATA), REG(SRCDATA + 4));
1822 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),
1823 REG(SRCZINT), REG(SRCZINT + 4), REG(SRCZFRAC), REG(SRCZFRAC + 4));
1824 WriteLog(" SRCSHADE = %s\n", (SRCSHADE ? "1" : "0"));
1828 #ifdef USE_MIDSUMMER_BLITTER
1830 // Here's an attempt to write a blitter that conforms to the Midsummer specs--since
1831 // it's supposedly backwards compatible, it should work well...
1833 //#define LOG_BLITTER_MEMORY_ACCESSES
1835 #define DATINIT (false)
1836 #define TXTEXT (false)
1837 #define POLYGON (false)
1839 void BlitterMidsummer(uint32 cmd)
1841 uint32 outer_loop, inner_loop, a1_addr, a2_addr;
1842 int32 a1_x, a1_y, a2_x, a2_y, a1_width, a2_width;
1843 uint8 a1_phrase_mode, a2_phrase_mode;
1845 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1846 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1847 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1848 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1849 UINT32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1850 a1_width = ((0x04 | m) << e) >> 2;//*/
1851 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1852 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1853 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1854 a2_width = ((0x04 | m) << e) >> 2;//*/
1856 a1_phrase_mode = a2_phrase_mode = 0;
1858 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
1861 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
1864 #define INNER0 (inner_loop == 0)
1865 #define OUTER0 (outer_loop == 0)
1867 // $01800005 has SRCENX, may have to investigate further...
1868 // $00011008 has GOURD & DSTEN.
1869 // $41802F41 has SRCSHADE, CLIPA1
1870 /*bool logBlit = false;
1871 if (cmd != 0x00010200 && cmd != 0x01800001 && cmd != 0x01800005
1872 && cmd != 0x00011008 && cmd !=0x41802F41)
1878 uint64 srcData = GET64(blitter_ram, SRCDATA), srcXtraData,
1879 dstData = GET64(blitter_ram, DSTDATA), writeData;
1880 uint32 srcAddr, dstAddr;
1881 uint8 bitCount, a1PixelSize, a2PixelSize;
1883 // JTRM says phrase mode only works for 8BPP or higher, so let's try this...
1884 uint32 phraseOffset[8] = { 8, 8, 8, 8, 4, 2, 0, 0 };
1885 uint8 pixelShift[8] = { 3, 2, 1, 0, 1, 2, 0, 0 };
1887 a1PixelSize = (blitter_ram[A1_FLAGS + 3] >> 3) & 0x07;
1888 a2PixelSize = (blitter_ram[A2_FLAGS + 3] >> 3) & 0x07;
1890 outer_loop = GET16(blitter_ram, PIXLINECOUNTER + 0);
1892 if (outer_loop == 0)
1893 outer_loop = 0x10000;
1895 // We just list the states here and jump from state to state in order to
1896 // keep things somewhat clear. Optimization/cleanups later.
1898 //idle: // Blitter is idle, and will not perform any bus activity
1900 idle Blitter is off the bus, and no activity takes place.
1901 if GO if DATINIT goto init_if
1910 inner Inner loop is active, read and write cycles are performed
1912 inner: // Run inner loop state machine (asserts step from its idle state)
1913 inner_loop = GET16(blitter_ram, PIXLINECOUNTER + 2);
1915 if (inner_loop == 0)
1916 inner_loop = 0x10000;
1919 ------------------------------
1920 idle: Inactive, blitter is idle or passing round outer loop
1921 idle Another state in the outer loop is active. No bus transfers are performed.
1923 if SRCENX goto sreadx
1924 else if TXTEXT goto txtread
1925 else if SRCEN goto sread
1926 else if DSTEN goto dread
1927 else if DSTENZ goto dzread
1944 sreadx Extra source data read at the start of an inner loop pass.
1946 if SRCENZ goto szreadx
1947 else if TXTEXT goto txtread
1948 else if SRCEN goto sread
1949 else if DSTEN goto dread
1950 else if DSTENZ goto dzread
1953 sreadx: // Extra source data read
1968 szreadx Extra source Z read as the start of an inner loop pass.
1970 if TXTEXT goto txtread
1973 szreadx: // Extra source Z read
1980 txtread Read texture data from external memory. This state is only used for external texture.
1981 TEXTEXT is the condition TEXTMODE=1.
1984 else if DSTEN goto dread
1985 else if DSTENZ goto dzread
1988 txtread: // Read external texture data
1999 sread Source data read.
2001 if SRCENZ goto szread
2002 else if DSTEN goto dread
2003 else if DSTENZ goto dzread
2006 sread: // Source data read
2007 //The JTRM doesn't really specify the internal structure of the source data read, but I would
2008 //imagine that if it's in phrase mode that it starts by reading the phrase that the window is
2009 //pointing at. Likewise, the pixel (if in BPP 1, 2 & 4, chopped) otherwise. It probably still
2010 //transfers an entire phrase even in pixel mode.
2011 //Odd thought: Does it expand, e.g., 1 BPP pixels into 32 BPP internally? Hmm...
2014 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
2015 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
2016 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
2017 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
2018 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
2019 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
2020 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
2021 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
2022 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
2023 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
2024 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
2025 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
2026 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
2027 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
2030 a1_width = ((0x04 | m) << e) >> 2;
2031 a2_width = ((0x04 | m) << e) >> 2;
2033 // write values back to registers
2034 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
2035 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
2036 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
2038 // Calculate the address to be read...
2040 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2041 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2042 //for 8BPP. !!! FIX !!!
2043 srcAddr = (DSTA2 ? a1_addr : a2_addr);
2045 /* if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2047 srcAddr += (((DSTA2 ? a1_x : a2_x) >> 16)
2048 + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width)));
2052 // uint32 pixAddr = ((DSTA2 ? a1_x : a2_x) >> 16)
2053 // + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2054 int32 pixAddr = (int16)((DSTA2 ? a1_x : a2_x) >> 16)
2055 + ((int16)((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2057 if ((DSTA2 ? a1PixelSize : a2PixelSize) < 3)
2058 pixAddr >>= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2059 else if ((DSTA2 ? a1PixelSize : a2PixelSize) > 3)
2060 pixAddr <<= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2067 if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2069 srcData = ((uint64)JaguarReadLong(srcAddr, BLITTER) << 32)
2070 | (uint64)JaguarReadLong(srcAddr + 4, BLITTER);
2074 //1,2,&4BPP are wrong here... !!! FIX !!!
2075 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 0) // 1 BPP
2076 srcData = JaguarReadByte(srcAddr, BLITTER);
2077 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 1) // 2 BPP
2078 srcData = JaguarReadByte(srcAddr, BLITTER);
2079 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 2) // 4 BPP
2080 srcData = JaguarReadByte(srcAddr, BLITTER);
2081 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 3) // 8 BPP
2082 srcData = JaguarReadByte(srcAddr, BLITTER);
2083 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 4) // 16 BPP
2084 srcData = JaguarReadWord(srcAddr, BLITTER);
2085 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 5) // 32 BPP
2086 srcData = JaguarReadLong(srcAddr, BLITTER);
2089 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2091 WriteLog("BLITTER: srcAddr=%08X, srcData=%08X %08X\n", srcAddr, (uint32)(srcData >> 32), (uint32)(srcData & 0xFFFFFFFF));
2103 szread: // Source Z read
2105 szread Source Z read.
2108 else if DSTENZ goto dzread
2118 dread: // Destination data read
2120 dread Destination data read.
2122 if DSTENZ goto dzread
2125 // Calculate the destination address to be read...
2127 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2128 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2129 //for 8BPP. !!! FIX !!!
2130 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2133 // uint32 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2134 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2135 int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
2136 + ((int16)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2138 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2139 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2140 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2141 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2148 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2150 dstData = ((uint64)JaguarReadLong(srcAddr, BLITTER) << 32)
2151 | (uint64)JaguarReadLong(srcAddr + 4, BLITTER);
2155 //1,2,&4BPP are wrong here... !!! FIX !!!
2156 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2157 dstData = JaguarReadByte(dstAddr, BLITTER);
2158 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2159 dstData = JaguarReadByte(dstAddr, BLITTER);
2160 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2161 dstData = JaguarReadByte(dstAddr, BLITTER);
2162 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2163 dstData = JaguarReadByte(dstAddr, BLITTER);
2164 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2165 dstData = JaguarReadWord(dstAddr, BLITTER);
2166 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2167 dstData = JaguarReadLong(dstAddr, BLITTER);
2170 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2172 WriteLog("BLITTER (dread): dstAddr=%08X, dstData=%08X %08X\n", dstAddr, (uint32)(dstData >> 32), (uint32)(dstData & 0xFFFFFFFF));
2180 dzread: // Destination Z read
2182 dzread Destination Z read.
2187 dwrite: // Destination data write
2189 dwrite Destination write. Every pass round the inner loop must go through this state..
2191 if DSTWRZ goto dzwrite
2192 else if INNER0 goto idle
2193 else if TXTEXT goto txtread
2194 else if SRCEN goto sread
2195 else if DSTEN goto dread
2196 else if DSTENZ goto dzread
2205 a1_xadd = 1.000000 (phrase=0)
2214 a2_xadd = 1.000000 (phrase=1)
2218 a2_mask_x= 0xFFFFFFFF
2219 a2_mask_y= 0xFFFFFFFF
2229 --LFUFUNC = LFU_CLEAR
2230 | PATDSEL = 1 (PD=77C7 7700 7700 7700)
2232 GOURD = 1 (II=00FC 1A00, SD=FF00 0000 0000 0000)
2235 //Still need to do CLIPA1 and SRCSHADE and GOURD and GOURZ...
2237 // Check clipping...
2241 uint16 x = a1_x >> 16, y = a1_y >> 16;
2243 if (x >= GET16(blitter_ram, A1_CLIP + 2) || y >= GET16(blitter_ram, A1_CLIP))
2247 // Figure out what gets written...
2251 writeData = GET64(blitter_ram, PATTERNDATA);
2252 //GOURD works properly only in 16BPP mode...
2253 //SRCDATA holds the intensity fractions...
2254 //Does GOURD get calc'ed here or somewhere else???
2255 //Temporary testing kludge...
2257 // writeData >>= 48;
2258 // writeData = 0xFF88;
2259 //OK, it's not writing an entire strip of pixels... Why?
2260 //bad incrementing, that's why!
2264 // Apparently this only works with 16-bit pixels. Not sure if it works in phrase mode either.
2265 //Also, take TOPBEN & TOPNEN into account here as well...
2266 writeData = srcData + dstData;
2268 else // LFUFUNC is the default...
2273 writeData |= ~srcData & ~dstData;
2275 writeData |= ~srcData & dstData;
2277 writeData |= srcData & ~dstData;
2279 writeData |= srcData & dstData;
2282 // Calculate the address to be written...
2284 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2286 /* if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2288 //both of these calculate the wrong address because they don't take into account
2290 dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2291 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2295 /* dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2296 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));*/
2297 // uint32 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2298 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2299 int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
2300 + ((int16)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2302 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2303 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2304 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2305 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2312 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2314 JaguarWriteLong(dstAddr, writeData >> 32, BLITTER);
2315 JaguarWriteLong(dstAddr + 4, writeData & 0xFFFFFFFF, BLITTER);
2319 //1,2,&4BPP are wrong here... !!! FIX !!!
2320 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2321 JaguarWriteByte(dstAddr, writeData, BLITTER);
2322 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2323 JaguarWriteByte(dstAddr, writeData, BLITTER);
2324 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2325 JaguarWriteByte(dstAddr, writeData, BLITTER);
2326 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2327 JaguarWriteByte(dstAddr, writeData, BLITTER);
2328 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2329 JaguarWriteWord(dstAddr, writeData, BLITTER);
2330 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2331 JaguarWriteLong(dstAddr, writeData, BLITTER);
2334 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2336 WriteLog("BLITTER: dstAddr=%08X, writeData=%08X %08X\n", dstAddr, (uint32)(writeData >> 32), (uint32)(writeData & 0xFFFFFFFF));
2339 inhibitWrite://Should this go here? or on the other side of the X/Y incrementing?
2340 //Seems OK here... for now.
2342 // Do funky X/Y incrementation here as well... !!! FIX !!!
2344 // Handle A1 channel stepping
2346 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
2347 a1_x += phraseOffset[a1PixelSize] << 16;
2348 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 1)
2349 a1_x += (blitter_ram[A1_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2350 /* else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 2)
2352 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 3)
2354 //Always add the FINC here??? That was the problem with the BIOS screen... So perhaps.
2355 a1_x += GET16(blitter_ram, A1_FINC + 2);
2356 a1_y += GET16(blitter_ram, A1_FINC + 0);
2358 a1_x += GET16(blitter_ram, A1_INC + 2) << 16;
2359 a1_y += GET16(blitter_ram, A1_INC + 0) << 16;
2362 if ((blitter_ram[A1_FLAGS + 1] & 0x04) && (blitter_ram[A1_FLAGS + 1] & 0x03 != 3))
2363 a1_y += (blitter_ram[A1_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2365 // Handle A2 channel stepping
2367 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
2368 a2_x += phraseOffset[a2PixelSize] << 16;
2369 else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 1)
2370 a2_x += (blitter_ram[A2_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2371 /* else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 2)
2374 if (blitter_ram[A2_FLAGS + 1] & 0x04)
2375 a2_y += (blitter_ram[A2_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2377 //Need to fix this so that it subtracts (saturating, of course) the correct number of pixels
2378 //in phrase mode... !!! FIX !!! [DONE]
2379 //Need to fix this so that it counts down the correct item. Does it count the
2380 //source or the destination phrase mode???
2381 //It shouldn't matter, because we *should* end up processing the same amount
2382 //the same number of pixels... Not sure though.
2383 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2385 if (inner_loop < phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize])
2388 inner_loop -= phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize];
2409 dzwrite: // Destination Z write
2411 dzwrite Destination Z write.
2414 else if TXTEXT goto txtread
2415 else if SRCEN goto sread
2416 else if DSTEN goto dread
2417 else if DSTENZ goto dzread
2434 ------------------------------
2435 if INDONE if OUTER0 goto idle
2436 else if UPDA1F goto a1fupdate
2437 else if UPDA1 goto a1update
2438 else if GOURZ.POLYGON goto zfupdate
2439 else if UPDA2 goto a2update
2440 else if DATINIT goto init_if
2453 //kill this, for now...
2454 // else if (GOURZ.POLYGON)
2463 a1fupdate: // Update A1 pointer fractions and more (see below)
2465 a1fupdate A1 step fraction is added to A1 pointer fraction
2466 POLYGON true: A1 step delta X and Y fraction parts are added to the A1
2467 step X and Y fraction parts (the value prior to this add is used for
2468 the step to pointer add).
2469 POLYGON true: inner count step fraction is added to the inner count
2471 POLYGON.GOURD true: the I fraction step is added to the computed
2472 intensity fraction parts +
2473 POLYGON.GOURD true: the I fraction step delta is added to the I
2478 #define A1_PIXEL ((UINT32)0x0C) // Integer part of the pixel (Y.i and X.i)
2479 #define A1_STEP ((UINT32)0x10) // Integer part of the step
2480 #define A1_FSTEP ((UINT32)0x14) // Fractional part of the step
2481 #define A1_FPIXEL ((UINT32)0x18) // Fractional part of the pixel (Y.f and X.f)
2484 // This is all kinda murky. All we have are the Midsummer docs to give us any guidance,
2485 // and it's incomplete or filled with errors (like above). Aarrrgggghhhhh!
2487 //This isn't right. Is it? I don't think the fractional parts are signed...
2488 // a1_x += (int32)((int16)GET16(blitter_ram, A1_FSTEP + 2));
2489 // a1_y += (int32)((int16)GET16(blitter_ram, A1_FSTEP + 0));
2490 a1_x += GET16(blitter_ram, A1_FSTEP + 2);
2491 a1_y += GET16(blitter_ram, A1_FSTEP + 0);
2495 a1update: // Update A1 pointer integers
2497 a1update A1 step is added to A1 pointer, with carry from the fractional add
2498 POLYGON true: A1 step delta X and Y integer parts are added to the A1
2499 step X and Y integer parts, with carry from the corresponding
2500 fractional part add (again, the value prior to this add is used for
2501 the step to pointer add).
2502 POLYGON true: inner count step is added to the inner count, with carry
2503 POLYGON.GOURD true: the I step is added to the computed intensities,
2505 POLYGON.GOURD true: the I step delta is added to the I step, with
2506 carry the texture X and Y step delta values are added to the X and Y
2508 if GOURZ.POLYGON goto zfupdate
2509 else if UPDA2 goto a2update
2510 else if DATINIT goto init_if
2513 a1_x += (int32)(GET16(blitter_ram, A1_STEP + 2) << 16);
2514 a1_y += (int32)(GET16(blitter_ram, A1_STEP + 0) << 16);
2517 //kill this, for now...
2518 // if (GOURZ.POLYGON)
2528 zfupdate: // Update computed Z step fractions
2530 zfupdate the Z fraction step is added to the computed Z fraction parts +
2531 the Z fraction step delta is added to the Z fraction step
2536 zupdate: // Update computed Z step integers
2538 zupdate the Z step is added to the computed Zs, with carry +
2539 the Z step delta is added to the Z step, with carry
2540 if UPDA2 goto a2update
2541 else if DATINIT goto init_if
2551 a2update: // Update A2 pointer
2553 a2update A2 step is added to the A2 pointer
2554 if DATINIT goto init_if
2557 a2_x += (int32)(GET16(blitter_ram, A2_STEP + 2) << 16);
2558 a2_y += (int32)(GET16(blitter_ram, A2_STEP + 0) << 16);
2566 init_if: // Initialise intensity fractions and texture X
2568 init_if Initialise the fractional part of the computed intensity fields, from
2569 the increment and step registers. The texture X integer and fractional
2570 parts can also be initialised.
2575 init_ii: // Initialise intensity integers and texture Y
2577 init_ii Initialise the integer part of the computed intensity, and texture Y
2578 integer and fractional parts
2579 if GOURZ goto init_zf
2587 init_zf: // Initialise Z fractions
2589 init_zf Initialise the fractional part of the computed Z fields.
2594 init_zi: // Initialise Z integers
2596 init_zi Initialise the integer part of the computed Z fields.
2603 The outer loop state machine fires off the inner loop, and controls the updating
2604 process between passes through the inner loop.
2606 + -- these functions are irrelevant if the DATINIT function is enabled, which it
2609 All these states will complete in one clock cycle, with the exception of the idle
2610 state, which means the blitter is quiescent; and the inner state, which takes as
2611 long as is required to complete one strip of pixels. It is therefore possible for
2612 the blitter to spend a maximum of nine clock cycles of inactivity between passes
2613 through the inner loop.
2623 // Here's attempt #2--taken from the Oberon chip specs!
2626 #ifdef USE_MIDSUMMER_BLITTER_MKII
2628 void ADDRGEN(uint32 &, uint32 &, bool, bool,
2629 uint16, uint16, uint32, uint8, uint8, uint8, uint8,
2630 uint16, uint16, uint32, uint8, uint8, uint8, uint8);
2631 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
2632 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
2633 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
2634 uint32 zinc, uint32 zstep);
2635 void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh);
2636 void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
2637 int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
2638 int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
2639 bool adda_yconst, bool addareg, bool suba_x, bool suba_y);
2640 void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
2641 int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y);
2642 void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel);
2643 void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
2644 uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y);
2645 void DATA(uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
2646 bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
2647 uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 &patd, bool patdadd,
2648 bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
2649 bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize,
2650 uint64 &srcz, uint64 dstz, uint32 zinc);
2651 void COMP_CTRL(uint8 &dbinh, bool &nowrite,
2652 bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
2653 uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp);
2654 #define VERBOSE_BLITTER_LOGGING
2655 bool logBlit = false;
2657 void BlitterMidsummer2(void)
2659 // Here's what the specs say the state machine does. Note that this can probably be
2660 // greatly simplified (also, it's different from what John has in his Oberon docs):
2661 //Will remove stuff that isn't in Jaguar I once fully described (stuff like texture won't
2662 //be described here at all)...
2664 uint32 cmd = GET32(blitter_ram, COMMAND);
2666 // $01800005 has SRCENX, may have to investigate further...
2667 // $00011008 has GOURD & DSTEN.
2668 // $41802F41 has SRCSHADE, CLIPA1
2671 cmd != 0x00010200 && // PATDSEL
2673 && cmd != 0x01800005
2674 //Boot ROM ATARI letters:
2675 && cmd != 0x00011008 // DSTEN GOURD PATDSEL
2676 //Boot ROM spinning cube:
2677 && cmd != 0x41802F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
2679 && cmd != 0x01800E01 // SRCEN UPDA1 UPDA2 DSTA2 LFUFUNC=C
2680 //T2K TEMPEST letters:
2681 && cmd != 0x09800741 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 LFUFUNC=C DCOMPEN
2682 //Static letters on Cybermorph intro screen:
2683 && cmd != 0x09800609 // SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
2684 //Static pic on title screen:
2685 && cmd != 0x01800601 // SRCEN UPDA1 UPDA2 LFUFUNC=C
2686 //Turning letters on Cybermorph intro screen:
2687 && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2688 && cmd != 0x00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
2689 && cmd != 0x09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
2690 && cmd != 0x09800209 // SRCEN DSTEN UPDA1 LFUFUNC=C DCOMPEN
2691 && cmd != 0x00011200 // UPDA1 GOURD PATDSEL
2692 //Start of Hover Strike (clearing screen):
2693 && cmd != 0x00010000 // PATDSEL
2694 //Hover Strike text:
2695 // && cmd != 0x1401060C // SRCENX DSTEN UPDA1 UPDA2 PATDSEL BCOMPEN BKGWREN
2696 //Hover Strike 3D stuff
2697 && cmd != 0x01902839 // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2698 //Trevor McFur stuff:
2699 && cmd != 0x05810601 // SRCEN UPDA1 UPDA2 PATDSEL BCOMPEN
2700 && cmd != 0x01800201 // SRCEN UPDA1 LFUFUNC=C
2702 && cmd != 0x00011000 // GOURD PATDSEL
2703 && cmd != 0x00011040 // CLIP_A1 GOURD PATDSEL
2707 if (blit_start_log == 0) // Wait for the signal...
2708 logBlit = false;//*/
2710 Some T2K unique blits:
2711 logBlit = F, cmd = 00010200 *
2712 logBlit = F, cmd = 00011000
2713 logBlit = F, cmd = 00011040
2714 logBlit = F, cmd = 01800005 *
2715 logBlit = F, cmd = 09800741 *
2716 Hover Strike mission selection screen:
2717 Blit! (CMD = 01902839) // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2720 //printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2725 Blit! (CMD = 00011040)
2726 Flags: CLIP_A1 GOURD PATDSEL
2728 a1_base = 00100000, a2_base = 0081F6A8
2729 a1_x = 00A7, a1_y = 0014, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0001, a2_y = 0000
2730 a1_step_x = FE80, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFF8, a2_step_y = 0001
2731 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
2732 a1_win_x = 0180, a1_win_y = 0118, a2_mask_x = 0000, a2_mask_y = 0000
2733 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
2734 a1_pixsize = 4, a2_pixsize = 4
2738 if (cmd == 0x00011040
2739 && (GET16(blitter_ram, A1_PIXEL + 2) == 0x00A7) && (GET16(blitter_ram, A1_PIXEL + 0) == 0x0014)
2740 && (GET16(blitter_ram, A2_PIXEL + 2) == 0x0001) && (GET16(blitter_ram, A2_PIXEL + 0) == 0x0000)
2741 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 18))
2744 // Line states passed in via the command register
2746 bool srcen = (SRCEN), srcenx = (SRCENX), srcenz = (SRCENZ),
2747 dsten = (DSTEN), dstenz = (DSTENZ), dstwrz = (DSTWRZ), clip_a1 = (CLIPA1),
2748 upda1 = (UPDA1), upda1f = (UPDA1F), upda2 = (UPDA2), dsta2 = (DSTA2),
2749 gourd = (GOURD), gourz = (GOURZ), topben = (TOPBEN), topnen = (TOPNEN),
2750 patdsel = (PATDSEL), adddsel = (ADDDSEL), cmpdst = (CMPDST), bcompen = (BCOMPEN),
2751 dcompen = (DCOMPEN), bkgwren = (BKGWREN), srcshade = (SRCSHADE);
2753 uint8 zmode = (cmd & 0x01C0000) >> 18, lfufunc = (cmd & 0x1E00000) >> 21;
2755 //Where to find various lines:
2757 // gourd -> dcontrol, inner, outer, state
2758 // gourz -> dcontrol, inner, outer, state
2759 // cmpdst -> blit, data, datacomp, state
2760 // bcompen -> acontrol, inner, mcontrol, state
2761 // dcompen -> inner, state
2762 // bkgwren -> inner, state
2763 // srcshade -> dcontrol, inner, state
2764 // adddsel -> dcontrol
2765 //NOTE: ADDDSEL takes precedence over PATDSEL, PATDSEL over LFU_FUNC
2766 #ifdef VERBOSE_BLITTER_LOGGING
2769 char zfs[512], lfus[512];
2770 zfs[0] = lfus[0] = 0;
2771 if (dstwrz || dstenz || gourz)
2772 sprintf(zfs, " ZMODE=%X", zmode);
2773 if (!(patdsel || adddsel))
2774 sprintf(lfus, " LFUFUNC=%X", lfufunc);
2775 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,
2776 (srcen ? " SRCEN" : ""), (srcenx ? " SRCENX" : ""), (srcenz ? " SRCENZ" : ""),
2777 (dsten ? " DSTEN" : ""), (dstenz ? " DSTENZ" : ""), (dstwrz ? " DSTWRZ" : ""),
2778 (clip_a1 ? " CLIP_A1" : ""), (upda1 ? " UPDA1" : ""), (upda1f ? " UPDA1F" : ""),
2779 (upda2 ? " UPDA2" : ""), (dsta2 ? " DSTA2" : ""), (gourd ? " GOURD" : ""),
2780 (gourz ? " GOURZ" : ""), (topben ? " TOPBEN" : ""), (topnen ? " TOPNEN" : ""),
2781 (patdsel ? " PATDSEL" : ""), (adddsel ? " ADDDSEL" : ""), zfs, lfus, (cmpdst ? " CMPDST" : ""),
2782 (bcompen ? " BCOMPEN" : ""), (dcompen ? " DCOMPEN" : ""), (bkgwren ? " BKGWREN" : ""),
2783 (srcshade ? " SRCSHADE" : ""));
2784 printf(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
2789 // Lines that don't exist in Jaguar I (and will never be asserted)
2791 bool polygon = false, datinit = false, a1_stepld = false, a2_stepld = false, ext_int = false;
2792 bool istepadd = false, istepfadd = false, finneradd = false, inneradd = false;
2793 bool zstepfadd = false, zstepadd = false;
2795 // Various state lines (initial state--basically the reset state of the FDSYNCs)
2797 bool go = true, idle = true, inner = false, a1fupdate = false, a1update = false,
2798 zfupdate = false, zupdate = false, a2update = false, init_if = false, init_ii = false,
2799 init_zf = false, init_zi = false;
2801 bool outer0 = false, indone = false;
2803 bool idlei, inneri, a1fupdatei, a1updatei, zfupdatei, zupdatei, a2updatei, init_ifi, init_iii,
2806 bool notgzandp = !(gourz && polygon);
2808 // Various registers set up by user
2810 uint16 ocount = GET16(blitter_ram, PIXLINECOUNTER);
2811 uint8 a1_pitch = blitter_ram[A1_FLAGS + 3] & 0x03;
2812 uint8 a2_pitch = blitter_ram[A2_FLAGS + 3] & 0x03;
2813 uint8 a1_pixsize = (blitter_ram[A1_FLAGS + 3] & 0x38) >> 3;
2814 uint8 a2_pixsize = (blitter_ram[A2_FLAGS + 3] & 0x38) >> 3;
2815 uint8 a1_zoffset = (GET16(blitter_ram, A1_FLAGS + 2) >> 6) & 0x07;
2816 uint8 a2_zoffset = (GET16(blitter_ram, A2_FLAGS + 2) >> 6) & 0x07;
2817 uint8 a1_width = (blitter_ram[A1_FLAGS + 2] >> 1) & 0x3F;
2818 uint8 a2_width = (blitter_ram[A2_FLAGS + 2] >> 1) & 0x3F;
2819 bool a2_mask = blitter_ram[A2_FLAGS + 2] & 0x80;
2820 uint8 a1addx = blitter_ram[A1_FLAGS + 1] & 0x03, a2addx = blitter_ram[A2_FLAGS + 1] & 0x03;
2821 bool a1addy = blitter_ram[A1_FLAGS + 1] & 0x04, a2addy = blitter_ram[A2_FLAGS + 1] & 0x04;
2822 bool a1xsign = blitter_ram[A1_FLAGS + 1] & 0x08, a2xsign = blitter_ram[A2_FLAGS + 1] & 0x08;
2823 bool a1ysign = blitter_ram[A1_FLAGS + 1] & 0x10, a2ysign = blitter_ram[A2_FLAGS + 1] & 0x10;
2824 uint32 a1_base = GET32(blitter_ram, A1_BASE) & 0xFFFFFFF8; // Phrase aligned by ignoring bottom 3 bits
2825 uint32 a2_base = GET32(blitter_ram, A2_BASE) & 0xFFFFFFF8;
2827 uint16 a1_win_x = GET16(blitter_ram, A1_CLIP + 2) & 0x7FFF;
2828 uint16 a1_win_y = GET16(blitter_ram, A1_CLIP + 0) & 0x7FFF;
2829 int16 a1_x = (int16)GET16(blitter_ram, A1_PIXEL + 2);
2830 int16 a1_y = (int16)GET16(blitter_ram, A1_PIXEL + 0);
2831 int16 a1_step_x = (int16)GET16(blitter_ram, A1_STEP + 2);
2832 int16 a1_step_y = (int16)GET16(blitter_ram, A1_STEP + 0);
2833 uint16 a1_stepf_x = GET16(blitter_ram, A1_FSTEP + 2);
2834 uint16 a1_stepf_y = GET16(blitter_ram, A1_FSTEP + 0);
2835 uint16 a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
2836 uint16 a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
2837 int16 a1_inc_x = (int16)GET16(blitter_ram, A1_INC + 2);
2838 int16 a1_inc_y = (int16)GET16(blitter_ram, A1_INC + 0);
2839 uint16 a1_incf_x = GET16(blitter_ram, A1_FINC + 2);
2840 uint16 a1_incf_y = GET16(blitter_ram, A1_FINC + 0);
2842 int16 a2_x = (int16)GET16(blitter_ram, A2_PIXEL + 2);
2843 int16 a2_y = (int16)GET16(blitter_ram, A2_PIXEL + 0);
2844 uint16 a2_mask_x = GET16(blitter_ram, A2_MASK + 2);
2845 uint16 a2_mask_y = GET16(blitter_ram, A2_MASK + 0);
2846 int16 a2_step_x = (int16)GET16(blitter_ram, A2_STEP + 2);
2847 int16 a2_step_y = (int16)GET16(blitter_ram, A2_STEP + 0);
2849 uint64 srcd1 = GET64(blitter_ram, SRCDATA);
2851 uint64 dstd = GET64(blitter_ram, DSTDATA);
2852 uint64 patd = GET64(blitter_ram, PATTERNDATA);
2853 uint32 iinc = GET32(blitter_ram, INTENSITYINC);
2854 uint64 srcz1 = GET64(blitter_ram, SRCZINT);
2855 uint64 srcz2 = GET64(blitter_ram, SRCZFRAC);
2856 uint64 dstz = GET64(blitter_ram, DSTZ);
2857 uint32 zinc = GET32(blitter_ram, ZINC);
2858 uint32 collision = GET32(blitter_ram, COLLISIONCTRL);// 0=RESUME, 1=ABORT, 2=STOPEN
2860 uint8 pixsize = (dsta2 ? a2_pixsize : a1_pixsize); // From ACONTROL
2862 //Testing Trevor McFur--I *think* it's the circle on the lower RHS of the screen...
2864 if (cmd == 0x05810601 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 96)
2865 && (GET16(blitter_ram, PIXLINECOUNTER + 0) == 72))
2868 //if (cmd == 0x1401060C) patd = 0xFFFFFFFFFFFFFFFFLL;
2869 //if (cmd == 0x1401060C) patd = 0x00000000000000FFLL;
2870 //If it's still not working (bcompen-patd) then see who's writing what to patd and where...
2871 //Still not OK. Check to see who's writing what to where in patd!
2872 //It looks like M68K is writing to the top half of patd... Hmm...
2874 ----> M68K wrote 0000 to byte 15737344 of PATTERNDATA...
2875 --> M68K wrote 00 to byte 0 of PATTERNDATA...
2876 --> M68K wrote 00 to byte 1 of PATTERNDATA...
2877 ----> M68K wrote 00FF to byte 15737346 of PATTERNDATA...
2878 --> M68K wrote 00 to byte 2 of PATTERNDATA...
2879 --> M68K wrote FF to byte 3 of PATTERNDATA...
2880 logBlit = F, cmd = 1401060C
2882 Wren0 := ND6 (wren\[0], gpua\[5], gpua\[6..8], bliten, gpu_memw);
2883 Wren1 := ND6 (wren\[1], gpua[5], gpua\[6..8], bliten, gpu_memw);
2884 Wren2 := ND6 (wren\[2], gpua\[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2885 Wren3 := ND6 (wren\[3], gpua[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2888 Dec0 := D38GH (a1baseld, a1flagld, a1winld, a1ptrld, a1stepld, a1stepfld, a1fracld, a1incld, gpua[2..4], wren\[0]);
2890 Dec1 := D38GH (a1incfld, a2baseld, a2flagld, a2maskld, a2ptrldg, a2stepld, cmdldt, countldt, gpua[2..4], wren\[1]);
2892 Dec2 := D38GH (srcd1ldg[0..1], dstdldg[0..1], dstzldg[0..1], srcz1ldg[0..1], gpua[2..4], wren\[2]);
2894 Dec3 := D38GH (srcz2ld[0..1], patdld[0..1], iincld, zincld, stopld, intld[0], gpua[2..4], wren\[3]);
2896 wren[3] is asserted when gpu address bus = 0 011x xx00
2897 patdld[0] -> 0 0110 1000 -> $F02268 (lo 32 bits)
2898 patdld[1] -> 0 0110 1100 -> $F0226C (hi 32 bits)
2900 So... It's reversed! The data organization of the patd register is [low 32][high 32]! !!! FIX !!! [DONE]
2901 And fix all the other 64 bit registers [DONE]
2903 /*if (cmd == 0x1401060C)
2905 printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2909 if ((cmd == 0x00010200) && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 9))
2912 ; Pink altimeter bar
2914 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2915 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
2916 A1 step values: -10 (X), 1 (Y)
2917 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
2918 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
2919 A1 x/y: 262/132, A2 x/y: 129/0
2920 ;x-coord is 257 in pic, so add 5
2921 ;20 for ship, 33 for #... Let's see if we can find 'em!
2923 ; Black altimeter bar
2925 Blit! (00110000 <- 000BF010) count: 5 x 29, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2926 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
2927 A1 step values: -8 (X), 1 (Y)
2928 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
2929 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
2930 A1 x/y: 264/126, A2 x/y: 336/0
2932 Here's the pink bar--note that it's phrase mode without dread, so how does this work???
2933 Not sure, but I *think* that somehow it MUXes the data at the write site in on the left or right side
2934 of the write data when masked in phrase mode. I'll have to do some tracing to see if this is the mechanism
2937 Blit! (CMD = 00010200)
2938 Flags: UPDA1 PATDSEL
2940 a1_base = 00110010, a2_base = 000BD7E0
2941 a1_x = 0106, a1_y = 0090, a1_frac_x = 0000, a1_frac_y = 8000, a2_x = 025A, a2_y = 0000
2942 a1_step_x = FFF6, a1_step_y = 0001, a1_stepf_x = 5E00, a1_stepf_y = D100, a2_step_x = FFF7, a2_step_y = 0001
2943 a1_inc_x = 0001, a1_inc_y = FFFF, a1_incf_x = 0000, a1_incf_y = E000
2944 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
2945 a2_mask=F a1add=+phr/+0 a2add=+1/+0
2946 a1_pixsize = 4, a2_pixsize = 4
2947 srcd=BAC673AC2C92E578 dstd=0000000000000000 patd=74C074C074C074C0 iinc=0002E398
2948 srcz1=7E127E12000088DA srcz2=DBE06DF000000000 dstz=0000000000000000 zinc=FFFE4840, coll=0
2950 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2951 Entering INNER state...
2952 Entering DWRITE state...
2953 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)
2954 Entering A1_ADD state [a1_x=0106, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2955 Entering DWRITE state...
2956 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)
2957 Entering A1_ADD state [a1_x=0108, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2958 Entering DWRITE state...
2959 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)
2960 Entering A1_ADD state [a1_x=010C, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
2961 Entering IDLE_INNER state...
2962 Leaving INNER state... (ocount=000A)
2963 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2964 Entering A1UPDATE state... (272/144 -> 262/145)
2965 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2966 Entering INNER state...
2971 a2addy = a1addy; // A2 channel Y add bit is tied to A1's
2973 //if (logBlit && (ocount > 20)) logBlit = false;
2974 #ifdef VERBOSE_BLITTER_LOGGING
2977 printf(" a1_base = %08X, a2_base = %08X\n", a1_base, a2_base);
2978 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);
2979 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);
2980 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);
2981 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);
2982 char x_add_str[4][4] = { "phr", "1", "0", "inc" };
2983 printf(" a2_mask=%s a1add=%s%s/%s%s a2add=%s%s/%s%s\n", (a2_mask ? "T" : "F"), (a1xsign ? "-" : "+"), x_add_str[a1addx],
2984 (a1ysign ? "-" : "+"), (a1addy ? "1" : "0"), (a2xsign ? "-" : "+"), x_add_str[a2addx],
2985 (a2ysign ? "-" : "+"), (a2addy ? "1" : "0"));
2986 printf(" a1_pixsize = %u, a2_pixsize = %u\n", a1_pixsize, a2_pixsize);
2987 printf(" srcd=%08X%08X dstd=%08X%08X patd=%08X%08X iinc=%08X\n",
2988 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF),
2989 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
2990 (uint32)(patd >> 32), (uint32)(patd & 0xFFFFFFFF), iinc);
2991 printf(" srcz1=%08X%08X srcz2=%08X%08X dstz=%08X%08X zinc=%08X, coll=%X\n",
2992 (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
2993 (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF),
2994 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF), zinc, collision);
2998 // Various state lines set up by user
3000 bool phrase_mode = ((!dsta2 && a1addx == 0) || (dsta2 && a2addx == 0) ? true : false); // From ACONTROL
3001 #ifdef VERBOSE_BLITTER_LOGGING
3004 printf(" Phrase mode is %s\n", (phrase_mode ? "ON" : "off"));
3010 // Stopgap vars to simulate various lines
3012 uint16 a1FracCInX = 0, a1FracCInY = 0;
3018 if ((idle && !go) || (inner && outer0 && indone))
3020 #ifdef VERBOSE_BLITTER_LOGGING
3023 printf(" Entering IDLE state...\n");
3034 // INNER LOOP ACTIVE
3036 Entering DWRITE state... (icount=0000, inc=4)
3037 Entering IDLE_INNER state...
3038 Leaving INNER state... (ocount=00EF)
3039 [in=T a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3040 Entering INNER state...
3042 [in=F a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3045 if ((idle && go && !datinit)
3046 || (inner && !indone)
3047 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && !datinit)
3048 || (a1update && !upda2 && notgzandp && !datinit)
3049 || (zupdate && !upda2 && !datinit)
3050 || (a2update && !datinit)
3051 || (init_ii && !gourz)
3059 // A1 FRACTION UPDATE
3061 if (inner && indone && !outer0 && upda1f)
3068 // A1 POINTER UPDATE
3071 || (inner && indone && !outer0 && !upda1f && upda1))
3078 // Z FRACTION UPDATE
3080 if ((a1update && gourz && polygon)
3081 || (inner && indone && !outer0 && !upda1f && !upda1 && gourz && polygon))
3097 // A2 POINTER UPDATE
3099 if ((a1update && upda2 && notgzandp)
3100 || (zupdate && upda2)
3101 || (inner && indone && !outer0 && !upda1f && notgzandp && !upda1 && upda2))
3108 // INITIALIZE INTENSITY FRACTION
3110 if ((zupdate && !upda2 && datinit)
3111 || (a1update && !upda2 && datinit && notgzandp)
3112 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && datinit)
3113 || (a2update && datinit)
3114 || (idle && go && datinit))
3121 // INITIALIZE INTENSITY INTEGER
3130 // INITIALIZE Z FRACTION
3132 if (init_ii && gourz)
3139 // INITIALIZE Z INTEGER
3148 // Here we move the fooi into their foo counterparts in order to simulate the moving
3149 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3153 a1fupdate = a1fupdatei;
3154 a1update = a1updatei;
3155 zfupdate = zfupdatei; // *
3156 zupdate = zupdatei; // *
3157 a2update = a2updatei;
3158 init_if = init_ifi; // *
3159 init_ii = init_iii; // *
3160 init_zf = init_zfi; // *
3161 init_zi = init_zii; // *
3162 // * denotes states that will never assert for Jaguar I
3163 #ifdef VERBOSE_BLITTER_LOGGING
3166 printf(" [in=%c a1f=%c a1=%c zf=%c z=%c a2=%c iif=%c iii=%c izf=%c izi=%c]\n",
3167 (inner ? 'T' : 'F'), (a1fupdate ? 'T' : 'F'), (a1update ? 'T' : 'F'), (zfupdate ? 'T' : 'F'),
3168 (zupdate ? 'T' : 'F'), (a2update ? 'T' : 'F'), (init_if ? 'T' : 'F'), (init_ii ? 'T' : 'F'),
3169 (init_zf ? 'T' : 'F'), (init_zi ? 'T' : 'F'));
3174 // Now, depending on how we want to handle things, we could either put the implementation
3175 // of the various pieces up above, or handle them down below here.
3177 // Let's try postprocessing for now...
3182 #ifdef VERBOSE_BLITTER_LOGGING
3185 printf(" Entering INNER state...\n");
3189 uint16 icount = GET16(blitter_ram, PIXLINECOUNTER + 2);
3190 bool idle_inner = true, step = true, sreadx = false, szreadx = false, sread = false,
3191 szread = false, dread = false, dzread = false, dwrite = false, dzwrite = false;
3192 bool inner0 = false;
3193 bool idle_inneri, sreadxi, szreadxi, sreadi, szreadi, dreadi, dzreadi, dwritei, dzwritei;
3195 // State lines that will never assert in Jaguar I
3197 bool textext = false, txtread = false;
3201 bool sshftld = true; // D flipflop (D -> Q): instart -> sshftld
3202 //NOTE: sshftld probably is only asserted at the beginning of the inner loop. !!! FIX !!!
3204 Blit! (CMD = 01800005)
3205 Flags: SRCEN SRCENX LFUFUNC=C
3207 a1_base = 00037290, a2_base = 000095D0
3208 a1_x = 0000, a1_y = 0000, a2_x = 0002, a2_y = 0000
3209 a1_pixsize = 4, a2_pixsize = 4
3210 srcd=0000000000000000, dstd=0000000000000000, patd=0000000000000000
3212 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3213 Entering INNER state...
3214 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
3215 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
3216 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3217 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3218 Source read address/pix address: 000095D8/0 [0054003800009814]
3219 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3220 Entering DWRITE state...
3221 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
3222 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3223 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3224 Source read address/pix address: 000095E0/0 [00009968000377C7]
3225 Entering A2_ADD state [a2_x=0008, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3226 Entering DWRITE state...
3227 Dest write address/pix address: 00037298/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026A, inc=4)
3228 Entering A1_ADD state [a1_x=0004, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3231 // while (!idle_inner)
3236 if ((idle_inner && !step)
3237 || (dzwrite && step && inner0)
3238 || (dwrite && step && !dstwrz && inner0))
3240 #ifdef VERBOSE_BLITTER_LOGGING
3243 printf(" Entering IDLE_INNER state...\n");
3251 idle_inneri = false;
3253 // EXTRA SOURCE DATA READ
3255 if ((idle_inner && step && srcenx)
3256 || (sreadx && !step))
3263 // EXTRA SOURCE ZED READ
3265 if ((sreadx && step && srcenz)
3266 || (szreadx && !step))
3273 // TEXTURE DATA READ (not implemented because not in Jaguar I)
3277 if ((szreadx && step && !textext)
3278 || (sreadx && step && !srcenz && srcen)
3279 || (idle_inner && step && !srcenx && !textext && srcen)
3280 || (dzwrite && step && !inner0 && !textext && srcen)
3281 || (dwrite && step && !dstwrz && !inner0 && !textext && srcen)
3282 || (txtread && step && srcen)
3283 || (sread && !step))
3292 if ((sread && step && srcenz)
3293 || (szread && !step))
3300 // DESTINATION DATA READ
3302 if ((szread && step && dsten)
3303 || (sread && step && !srcenz && dsten)
3304 || (sreadx && step && !srcenz && !textext && !srcen && dsten)
3305 || (idle_inner && step && !srcenx && !textext && !srcen && dsten)
3306 || (dzwrite && step && !inner0 && !textext && !srcen && dsten)
3307 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && dsten)
3308 || (txtread && step && !srcen && dsten)
3309 || (dread && !step))
3316 // DESTINATION ZED READ
3318 if ((dread && step && dstenz)
3319 || (szread && step && !dsten && dstenz)
3320 || (sread && step && !srcenz && !dsten && dstenz)
3321 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && dstenz)
3322 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && dstenz)
3323 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && dstenz)
3324 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && dstenz)
3325 || (txtread && step && !srcen && !dsten && dstenz)
3326 || (dzread && !step))
3333 // DESTINATION DATA WRITE
3335 if ((dzread && step)
3336 || (dread && step && !dstenz)
3337 || (szread && step && !dsten && !dstenz)
3338 || (sread && step && !srcenz && !dsten && !dstenz)
3339 || (txtread && step && !srcen && !dsten && !dstenz)
3340 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && !dstenz)
3341 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && !dstenz)
3342 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && !dstenz)
3343 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && !dstenz)
3344 || (dwrite && !step))
3351 // DESTINATION ZED WRITE
3353 if ((dzwrite && !step)
3354 || (dwrite && step && dstwrz))
3361 //Kludge: A QnD way to make sure that sshftld is asserted only for the first
3362 // cycle of the inner loop...
3363 sshftld = idle_inner;
3365 // Here we move the fooi into their foo counterparts in order to simulate the moving
3366 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3368 idle_inner = idle_inneri;
3378 // Here's a few more decodes--not sure if they're supposed to go here or not...
3380 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
3382 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
3384 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
3385 bool gendst = dreadi || szreadi || dwritei || dzwritei;
3386 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
3388 bool zaddr = szreadx || szread || dzread || dzwrite;
3390 // Some stuff from MCONTROL.NET--not sure if this is the correct use of this decode or not...
3391 /*Fontread\ := OND1 (fontread\, sread[1], sreadx[1], bcompen);
3392 Fontread := INV1 (fontread, fontread\);
3393 Justt := NAN3 (justt, fontread\, phrase_mode, tactive\);
3394 Justify := TS (justify, justt, busen);*/
3395 bool fontread = (sread || sreadx) && bcompen;
3396 bool justify = !(!fontread && phrase_mode /*&& tactive*/);
3398 /* Generate inner loop update enables */
3400 A1_addi := MX2 (a1_addi, dsta_addi, srca_addi, dsta2);
3401 A2_addi := MX2 (a2_addi, srca_addi, dsta_addi, dsta2);
3402 A1_add := FD1 (a1_add, a1_add\, a1_addi, clk);
3403 A2_add := FD1 (a2_add, a2_add\, a2_addi, clk);
3404 A2_addb := BUF1 (a2_addb, a2_add);
3406 bool a1_add = (dsta2 ? srca_addi : dsta_addi);
3407 bool a2_add = (dsta2 ? dsta_addi : srca_addi);
3409 /* Address adder input A register selection
3410 000 A1 step integer part
3411 001 A1 step fraction part
3412 010 A1 increment integer part
3413 011 A1 increment fraction part
3417 bit 1 = /a2update . (a1_add . a1addx[0..1])
3418 bit 0 = /a2update . ( a1fupdate
3419 + a1_add . atick[0] . a1addx[0..1])
3420 The /a2update term on bits 0 and 1 is redundant.
3421 Now look-ahead based
3423 uint8 addasel = (a1fupdate || (a1_add && a1addx == 3) ? 0x01 : 0x00);
3424 addasel |= (a1_add && a1addx == 3 ? 0x02 : 0x00);
3425 addasel |= (a2update ? 0x04 : 0x00);
3426 /* Address adder input A X constant selection
3427 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all
3428 zeroes when they are all 1
3429 Remember - these are pixels, so to add one phrase the pixel size
3430 has to be taken into account to get the appropriate value.
3432 if a1addx[0..1] are 00 set 6 - pixel size
3433 if a1addx[0..1] are 01 set the value 000
3434 if a1addx[0..1] are 10 set the value 111
3436 JLH: Also, 11 will likewise set the value to 111
3438 uint8 a1_xconst = 6 - a1_pixsize, a2_xconst = 6 - a2_pixsize;
3442 else if (a1addx & 0x02)
3447 else if (a2addx & 0x02)
3450 uint8 adda_xconst = (a2_add ? a2_xconst : a1_xconst);
3451 /* Address adder input A Y constant selection
3452 22 June 94 - This was erroneous, because only the a1addy bit was reflected here.
3453 Therefore, the selection has to be controlled by a bug fix bit.
3454 JLH: Bug fix bit in Jaguar II--not in Jaguar I!
3456 bool adda_yconst = a1addy;
3457 /* Address adder input A register versus constant selection
3458 given by a1_add . a1addx[0..1]
3461 + a2_add . a2addx[0..1]
3464 bool addareg = ((a1_add && a1addx == 3) || a1update || a1fupdate
3465 || (a2_add && a2addx == 3) || a2update ? true : false);
3466 /* The adders can be put into subtract mode in add pixel size
3467 mode when the corresponding flags are set */
3468 bool suba_x = ((a1_add && a1xsign && a1addx == 1) || (a2_add && a2xsign && a2addx == 1) ? true : false);
3469 bool suba_y = ((a1_add && a1addy && a1ysign) || (a2_add && a2addy && a2ysign) ? true : false);
3470 /* Address adder input B selection
3477 + (a1_add . atick[0] . a1addx[0..1])
3478 + a1fupdate . a1_stepld
3479 + a1update . a1_stepld
3480 + a2update . a2_stepld
3481 Bit 0 = a2update + a2_add
3482 + a1fupdate . a1_stepld
3483 + a1update . a1_stepld
3484 + a2update . a2_stepld
3486 uint8 addbsel = (a2update || a2_add || (a1fupdate && a1_stepld)
3487 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x01 : 0x00);
3488 addbsel |= (a1fupdate || (a1_add && a1addx == 3) || (a1fupdate && a1_stepld)
3489 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x02 : 0x00);
3491 /* The modulo bits are used to align X onto a phrase boundary when
3492 it is being updated by one phrase
3499 Masking is enabled for a1 when a1addx[0..1] is 00, and the value
3500 is 6 - the pixel size (again!)
3502 uint8 maska1 = (a1_add && a1addx == 0 ? 6 - a1_pixsize : 0);
3503 uint8 maska2 = (a2_add && a2addx == 0 ? 6 - a2_pixsize : 0);
3504 uint8 modx = (a2_add ? maska2 : maska1);
3505 /* Generate load strobes for the increment updates */
3507 /*A1pldt := NAN2 (a1pldt, atick[1], a1_add);
3508 A1ptrldi := NAN2 (a1ptrldi, a1update\, a1pldt);
3510 A1fldt := NAN4 (a1fldt, atick[0], a1_add, a1addx[0..1]);
3511 A1fracldi := NAN2 (a1fracldi, a1fupdate\, a1fldt);
3513 A2pldt := NAN2 (a2pldt, atick[1], a2_add);
3514 A2ptrldi := NAN2 (a2ptrldi, a2update\, a2pldt);*/
3515 bool a1fracldi = a1fupdate || (a1_add && a1addx == 3);
3517 // Some more from DCONTROL...
3518 // atick[] just MAY be important here! We're assuming it's true and dropping the term...
3519 // That will probably screw up some of the lower terms that seem to rely on the timing of it...
3520 #warning srcdreadd is not properly initialized!
3521 bool srcdreadd = false; // Set in INNER.NET
3522 //Shadeadd\ := NAN2H (shadeadd\, dwrite, srcshade);
3523 //Shadeadd := INV2 (shadeadd, shadeadd\);
3524 bool shadeadd = dwrite && srcshade;
3525 /* Data adder control, input A selection
3526 000 Destination data
3527 001 Initialiser pixel value
3528 100 Source data - computed intensity fraction
3529 101 Pattern data - computed intensity
3530 110 Source zed 1 - computed zed
3531 111 Source zed 2 - computed zed fraction
3533 Bit 0 = dwrite . gourd . atick[1]
3534 + dzwrite . gourz . atick[0]
3537 + init_if + init_ii + init_zf + init_zi
3538 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3541 Bit 2 = (gourd + gourz) . /(init_if + init_ii + init_zf + init_zi)
3544 uint8 daddasel = ((dwrite && gourd) || (dzwrite && gourz) || istepadd || zstepfadd
3545 || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3546 daddasel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3547 daddasel |= (((gourd || gourz) && !(init_if || init_ii || init_zf || init_zi))
3548 || (dwrite && srcshade) ? 0x04 : 0x00);
3549 /* Data adder control, input B selection
3551 0001 Data initialiser increment
3552 0100 Bottom 16 bits of I increment repeated four times
3553 0101 Top 16 bits of I increment repeated four times
3554 0110 Bottom 16 bits of Z increment repeated four times
3555 0111 Top 16 bits of Z increment repeated four times
3556 1100 Bottom 16 bits of I step repeated four times
3557 1101 Top 16 bits of I step repeated four times
3558 1110 Bottom 16 bits of Z step repeated four times
3559 1111 Top 16 bits of Z step repeated four times
3561 Bit 0 = dwrite . gourd . atick[1]
3562 + dzwrite . gourz . atick[1]
3566 + init_if + init_ii + init_zf + init_zi
3567 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3570 Bit 2 = dwrite . gourd . (atick[0] + atick[1])
3571 + dzwrite . gourz . (atick[0] + atick[1])
3573 + istepadd + istepfadd + zstepadd + zstepfadd
3574 Bit 3 = istepadd + istepfadd + zstepadd + zstepfadd
3576 uint8 daddbsel = ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3577 || istepadd || zstepadd || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3578 daddbsel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3579 daddbsel |= ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3580 || istepadd || istepfadd || zstepadd || zstepfadd ? 0x04 : 0x00);
3581 daddbsel |= (istepadd && istepfadd && zstepadd && zstepfadd ? 0x08 : 0x00);
3582 /* Data adder mode control
3583 000 16-bit normal add
3584 001 16-bit saturating add with carry
3585 010 8-bit saturating add with carry, carry into top byte is
3587 011 8-bit saturating add with carry, carry into top byte and
3588 between top nybbles is inhibited (CRY)
3589 100 16-bit normal add with carry
3590 101 16-bit saturating add
3591 110 8-bit saturating add, carry into top byte is inhibited
3592 111 8-bit saturating add, carry into top byte and between top
3593 nybbles is inhibited
3595 The first five are used for Gouraud calculations, the latter three
3596 for adding source and destination data
3598 Bit 0 = dzwrite . gourz . atick[1]
3599 + dwrite . gourd . atick[1] . /topnen . /topben . /ext_int
3600 + dwrite . gourd . atick[1] . topnen . topben . /ext_int
3602 + istepadd . /topnen . /topben . /ext_int
3603 + istepadd . topnen . topben . /ext_int
3604 + /gourd . /gourz . /topnen . /topben
3605 + /gourd . /gourz . topnen . topben
3606 + shadeadd . /topnen . /topben
3607 + shadeadd . topnen . topben
3608 + init_ii . /topnen . /topben . /ext_int
3609 + init_ii . topnen . topben . /ext_int
3612 Bit 1 = dwrite . gourd . atick[1] . /topben . /ext_int
3613 + istepadd . /topben . /ext_int
3614 + /gourd . /gourz . /topben
3615 + shadeadd . /topben
3616 + init_ii . /topben . /ext_int
3618 Bit 2 = /gourd . /gourz
3620 + dwrite . gourd . atick[1] . ext_int
3621 + istepadd . ext_int
3624 uint8 daddmode = ((dzwrite && gourz) || (dwrite && gourd && !topnen && !topben && !ext_int)
3625 || (dwrite && gourd && topnen && topben && !ext_int) || zstepadd
3626 || (istepadd && !topnen && !topben && !ext_int)
3627 || (istepadd && topnen && topben && !ext_int) || (!gourd && !gourz && !topnen && !topben)
3628 || (!gourd && !gourz && topnen && topben) || (shadeadd && !topnen && !topben)
3629 || (shadeadd && topnen && topben) || (init_ii && !topnen && !topben && !ext_int)
3630 || (init_ii && topnen && topben && !ext_int) || init_zi ? 0x01 : 0x00);
3631 daddmode |= ((dwrite && gourd && !topben && !ext_int) || (istepadd && !topben && !ext_int)
3632 || (!gourd && !gourz && !topben) || (shadeadd && !topben)
3633 || (init_ii && !topben && !ext_int) ? 0x02 : 0x00);
3634 daddmode |= ((!gourd && !gourz) || shadeadd || (dwrite && gourd && ext_int)
3635 || (istepadd && ext_int) || (init_ii && ext_int) ? 0x04 : 0x00);
3636 /* Data add load controls
3637 Pattern fraction (dest data) is loaded on
3638 dwrite . gourd . atick[0]
3639 + istepfadd . /datinit
3641 Pattern data is loaded on
3642 dwrite . gourd . atick[1]
3643 + istepadd . /datinit . /datinit
3645 Source z1 is loaded on
3646 dzwrite . gourz . atick[1]
3647 + zstepadd . /datinit . /datinit
3649 Source z2 is loaded on
3650 dzwrite . gourz . atick[0]
3653 Texture map shaded data is loaded on
3654 srcdreadd . srcshade
3656 bool patfadd = (dwrite && gourd) || (istepfadd && !datinit) || init_if;
3657 bool patdadd = (dwrite && gourd) || (istepadd && !datinit) || init_ii;
3658 bool srcz1add = (dzwrite && gourz) || (zstepadd && !datinit) || init_zi;
3659 bool srcz2add = (dzwrite && gourz) || zstepfadd || init_zf;
3660 bool srcshadd = srcdreadd && srcshade;
3661 bool daddq_sel = patfadd || patdadd || srcz1add || srcz2add || srcshadd;
3662 /* Select write data
3663 This has to be controlled from stage 1 of the pipe-line, delayed
3664 by one tick, as the write occurs in the cycle after the ack.
3671 Bit 0 = /patdsel . /adddsel
3676 uint8 data_sel = ((!patdsel && !adddsel) || dzwrite ? 0x01 : 0x00)
3677 | (adddsel || dzwrite ? 0x02 : 0x00);
3679 uint32 address, pixAddr;
3680 ADDRGEN(address, pixAddr, gena2i, zaddr,
3681 a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3682 a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3684 //Here's my guess as to how the addresses get truncated to phrase boundaries in phrase mode...
3686 address &= 0xFFFFF8;
3688 /* Generate source alignment shift
3689 -------------------------------
3690 The source alignment shift for data move is the difference between
3691 the source and destination X pointers, multiplied by the pixel
3692 size. Only the low six bits of the pointers are of interest, as
3693 pixel sizes are always a power of 2 and window rows are always
3696 When not in phrase mode, the top 3 bits of the shift value are
3699 Source shifting is also used to extract bits for bit-to-byte
3700 expansion in phrase mode. This involves only the bottom three
3701 bits of the shift value, and is based on the offset within the
3702 phrase of the destination X pointer, in pixels.
3704 Source shifting is disabled when srcen is not set.
3706 uint8 dstxp = (dsta2 ? a2_x : a1_x) & 0x3F;
3707 uint8 srcxp = (dsta2 ? a1_x : a2_x) & 0x3F;
3708 uint8 shftv = ((dstxp - srcxp) << pixsize) & 0x3F;
3709 /* The phrase mode alignment count is given by the phrase offset
3710 of the first pixel, for bit to byte expansion */
3714 pobb = dstxp & 0x07;
3716 pobb = dstxp & 0x03;
3718 pobb = dstxp & 0x01;
3720 bool pobbsel = phrase_mode && bcompen;
3721 uint8 loshd = (pobbsel ? pobb : shftv) & 0x07;
3722 uint8 shfti = (srcen || pobbsel ? (sshftld ? loshd : srcshift & 0x07) : 0);
3723 /* Enable for high bits is srcen . phrase_mode */
3724 shfti |= (srcen && phrase_mode ? (sshftld ? shftv & 0x38 : srcshift & 0x38) : 0);
3729 #ifdef VERBOSE_BLITTER_LOGGING
3732 printf(" Entering SREADX state...");
3733 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
3737 //uint32 srcAddr, pixAddr;
3738 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3739 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3740 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3742 srcd1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3743 //Kludge to take pixel size into account...
3744 //Hmm. If we're not in phrase mode, this is most likely NOT going to be used...
3745 //Actually, it would be--because of BCOMPEN expansion, for example...
3750 else if (pixsize == 4)
3755 #ifdef VERBOSE_BLITTER_LOGGING
3758 printf(" Source extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3759 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
3767 #ifdef VERBOSE_BLITTER_LOGGING
3770 printf(" Entering SZREADX state...");
3775 srcz1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3776 #ifdef VERBOSE_BLITTER_LOGGING
3779 printf(" Src Z extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3780 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3788 #ifdef VERBOSE_BLITTER_LOGGING
3791 printf(" Entering SREAD state...");
3792 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
3796 //uint32 srcAddr, pixAddr;
3797 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3798 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3799 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3801 srcd1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3802 //Kludge to take pixel size into account...
3811 else if (pixsize == 4)
3817 #ifdef VERBOSE_BLITTER_LOGGING
3820 printf(" Source read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3821 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
3829 #ifdef VERBOSE_BLITTER_LOGGING
3832 printf(" Entering SZREAD state...");
3837 srcz1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3838 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3839 if (!phrase_mode && pixsize == 4)
3842 #ifdef VERBOSE_BLITTER_LOGGING
3845 printf(" Src Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3846 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3854 #ifdef VERBOSE_BLITTER_LOGGING
3857 printf(" Entering DREAD state...");
3861 //uint32 dstAddr, pixAddr;
3862 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
3863 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3864 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3865 dstd = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3866 //Kludge to take pixel size into account...
3871 else if (pixsize == 4)
3876 #ifdef VERBOSE_BLITTER_LOGGING
3879 printf(" Dest read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3880 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF));
3888 // Is Z always 64 bit read? Or sometimes 16 bit (dependent on phrase_mode)?
3889 #ifdef VERBOSE_BLITTER_LOGGING
3892 printf(" Entering DZREAD state...");
3896 dstz = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3897 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3898 if (!phrase_mode && pixsize == 4)
3901 #ifdef VERBOSE_BLITTER_LOGGING
3904 printf(" Dest Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3905 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3911 // These vars should probably go further up in the code... !!! FIX !!!
3912 // We can't preassign these unless they're static...
3913 //uint64 srcz = 0; // These are assigned to shut up stupid compiler warnings--dwrite is ALWAYS asserted
3914 //bool winhibit = false;
3917 //NOTE: SRCSHADE requires GOURZ to be set to work properly--another Jaguar I bug
3920 #ifdef VERBOSE_BLITTER_LOGGING
3923 printf(" Entering DWRITE state...");
3927 //Counter is done on the dwrite state...! (We'll do it first, since it affects dstart/dend calculations.)
3928 //Here's the voodoo for figuring the correct amount of pixels in phrase mode (or not):
3929 int8 inct = -((dsta2 ? a2_x : a1_x) & 0x07); // From INNER_CNT
3931 inc = (!phrase_mode || (phrase_mode && (inct & 0x01)) ? 0x01 : 0x00);
3932 inc |= (phrase_mode && (((pixsize == 3 || pixsize == 4) && (inct & 0x02)) || pixsize == 5 && !(inct & 0x01)) ? 0x02 : 0x00);
3933 inc |= (phrase_mode && ((pixsize == 3 && (inct & 0x04)) || (pixsize == 4 && !(inct & 0x03))) ? 0x04 : 0x00);
3934 inc |= (phrase_mode && pixsize == 3 && !(inct & 0x07) ? 0x08 : 0x00);
3936 uint16 oldicount = icount; // Save icount to detect underflow...
3939 if (icount == 0 || ((icount & 0x8000) && !(oldicount & 0x8000)))
3941 // X/Y stepping is also done here, I think...No. It's done when a1_add or a2_add is asserted...
3943 //*********************************************************************************
3944 //Start & end write mask computations...
3945 //*********************************************************************************
3950 dstart = (dstxp & 0x07) << 3;
3952 dstart = (dstxp & 0x03) << 4;
3954 dstart = (dstxp & 0x01) << 5;
3956 dstart = (phrase_mode ? dstart : pixAddr & 0x07);
3958 //This is the other Jaguar I bug... Normally, should ALWAYS select a1_x here.
3959 uint16 dstxwr = (dsta2 ? a2_x : a1_x) & 0x7FFE;
3960 uint16 pseq = dstxwr ^ (a1_win_x & 0x7FFE);
3961 pseq = (pixsize == 5 ? pseq : pseq & 0x7FFC);
3962 pseq = ((pixsize & 0x06) == 4 ? pseq : pseq & 0x7FF8);
3963 bool penden = clip_a1 && (pseq == 0);
3964 uint8 window_mask = 0;
3967 window_mask = (a1_win_x & 0x07) << 3;
3969 window_mask = (a1_win_x & 0x03) << 4;
3971 window_mask = (a1_win_x & 0x01) << 5;
3973 window_mask = (penden ? window_mask : 0);
3976 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
3977 Source extra read address/pix address: 000095D0/0 [000004E40000001C]
3978 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3979 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=20]
3980 Source read address/pix address: 000095D8/0 [0054003800009814]
3981 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3982 Entering DWRITE state...
3983 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)
3984 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3986 (icount=026E, inc=4)
3987 icount & 0x03 = 0x02
3990 window_mask = 0x1000
3992 Therefore, it chooses the inner_mask over the window_mask every time! Argh!
3993 This is because we did this wrong:
3994 Innerm[3-5] := AN2 (inner_mask[3-5], imb[3-5], inner0);
3995 NOTE! This doesn't fix the problem because inner0 is asserted too late to help here. !!! FIX !!! [Should be DONE]
3998 /* The mask to be used if within one phrase of the end of the inner
4000 uint8 inner_mask = 0;
4003 inner_mask = (icount & 0x07) << 3;
4005 inner_mask = (icount & 0x03) << 4;
4007 inner_mask = (icount & 0x01) << 5;
4010 /* The actual mask used should be the lesser of the window masks and
4011 the inner mask, where is all cases 000 means 1000. */
4012 window_mask = (window_mask == 0 ? 0x40 : window_mask);
4013 inner_mask = (inner_mask == 0 ? 0x40 : inner_mask);
4014 uint8 emask = (window_mask > inner_mask ? inner_mask : window_mask);
4015 /* The mask to be used for the pixel size, to which must be added
4017 uint8 pma = pixAddr + (1 << pixsize);
4018 /* Select the mask */
4019 uint8 dend = (phrase_mode ? emask : pma);
4021 /* The cycle width in phrase mode is normally one phrase. However,
4022 at the start and end it may be narrower. The start and end masks
4023 are used to generate this. The width is given by:
4025 8 - start mask - (8 - end mask)
4026 = end mask - start mask
4028 This is only used for writes in phrase mode.
4029 Start and end from the address level of the pipeline are used.
4031 uint8 pwidth = (((dend | dstart) & 0x07) == 0 ? 0x08 : (dend - dstart) & 0x07);
4033 //uint32 dstAddr, pixAddr;
4034 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
4035 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
4036 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
4037 #ifdef VERBOSE_BLITTER_LOGGING
4040 printf(" Dest write address/pix address: %08X/%1X", address, pixAddr);
4045 //More testing... This is almost certainly wrong, but how else does this work???
4046 //Seems to kinda work... But still, this doesn't seem to make any sense!
4047 if (phrase_mode && !dsten)
4048 dstd = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
4050 //Testing only... for now...
4051 //This is wrong because the write data is a combination of srcd and dstd--either run
4052 //thru the LFU or in PATDSEL or ADDDSEL mode. [DONE now, thru DATA module]
4053 // Precedence is ADDDSEL > PATDSEL > LFU.
4054 //Also, doesn't take into account the start & end masks, or the phrase width...
4057 // srcd2 = xxxx xxxx 0123 4567, srcd = 8901 2345 xxxx xxxx, srcshift = $20 (32)
4058 uint64 srcd = (srcd2 << (64 - srcshift)) | (srcd1 >> srcshift);
4059 //bleh, ugly ugly ugly
4063 //Z DATA() stuff done here... And it has to be done before any Z shifting...
4064 //Note that we need to have phrase mode start/end support here... (Not since we moved it from dzwrite...!)
4066 Here are a couple of Cybermorph blits with Z:
4067 $00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
4068 $09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
4070 We're having the same phrase mode overwrite problem we had with the pixels... !!! FIX !!!
4071 Odd. It's equating 0 with 0... Even though ZMODE is $04 (less than)!
4076 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
4077 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
4078 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
4079 uint32 zinc, uint32 zstep)
4082 uint8 initcin[4] = { 0, 0, 0, 0 };
4083 ADDARRAY(addq, 7/*daddasel*/, 6/*daddbsel*/, 0/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4084 srcz2 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4085 ADDARRAY(addq, 6/*daddasel*/, 7/*daddbsel*/, 1/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4086 srcz1 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4088 #ifdef VERBOSE_BLITTER_LOGGING
4091 printf("\n[srcz1=%08X%08X, srcz2=%08X%08X, zinc=%08X",
4092 (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
4093 (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF), zinc);
4099 uint8 zSrcShift = srcshift & 0x30;
4100 srcz = (srcz2 << (64 - zSrcShift)) | (srcz1 >> zSrcShift);
4101 //bleh, ugly ugly ugly
4105 #ifdef VERBOSE_BLITTER_LOGGING
4108 printf(" srcz=%08X%08X]\n", (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4113 //When in SRCSHADE mode, it adds the IINC to the read source (from LFU???)
4114 //According to following line, it gets LFU mode. But does it feed the source into the LFU
4116 //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)
4120 //NOTE: This is basically doubling the work done by DATA--since this is what
4121 // ADDARRAY is loaded with when srschshade is enabled... !!! FIX !!!
4122 // Also note that it doesn't work properly unless GOURZ is set--there's the clue!
4124 uint8 initcin[4] = { 0, 0, 0, 0 };
4125 ADDARRAY(addq, 4/*daddasel*/, 5/*daddbsel*/, 7/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4126 srcd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4128 //Seems to work... Not 100% sure tho.
4131 //Temporary kludge, to see if the fractional pattern does anything...
4133 //But it seems to mess up in Cybermorph... the shading should be smooth but it isn't...
4134 //Seems the carry out is lost again... !!! FIX !!! [DONE--see below]
4138 uint8 initcin[4] = { 0, 0, 0, 0 };
4139 ADDARRAY(addq, 4/*daddasel*/, 4/*daddbsel*/, 0/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4140 srcd1 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4143 //Note that we still don't take atick[0] & [1] into account here, so this will skip half of the data needed... !!! FIX !!!
4144 //Not yet enumerated: dbinh, srcdread, srczread
4145 //Also, should do srcshift on the z value in phrase mode... !!! FIX !!! [DONE]
4146 //As well as add a srcz variable we can set external to this state... !!! FIX !!! [DONE]
4150 DATA(wdata, dcomp, zcomp, winhibit,
4151 true, cmpdst, daddasel, daddbsel, daddmode, daddq_sel, data_sel, 0/*dbinh*/,
4152 dend, dstart, dstd, iinc, lfufunc, patd, patdadd,
4153 phrase_mode, srcd, false/*srcdread*/, false/*srczread*/, srcz2add, zmode,
4154 bcompen, bkgwren, dcompen, icount & 0x07, pixsize,
4157 Seems that the phrase mode writes with DCOMPEN and DSTEN are corrupting inside of DATA: !!! FIX !!!
4158 It's fairly random as well. 7CFE -> 7DFE, 7FCA -> 78CA, 7FA4 -> 78A4, 7F88 -> 8F88
4159 It could be related to an uninitialized variable, like the zmode bug...
4161 It was a bug in the dech38el data--it returned $FF for ungated instead of $00...
4163 Blit! (CMD = 09800609)
4164 Flags: SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
4166 a1_base = 00110000, a2_base = 0010B2A8
4167 a1_x = 004B, a1_y = 00D8, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0704, a2_y = 0000
4168 a1_step_x = FFF3, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFFC, a2_step_y = 0000
4169 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4170 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4171 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4172 a1_pixsize = 4, a2_pixsize = 4
4173 srcd=0000000000000000 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4174 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4176 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4177 Entering INNER state...
4178 Entering SREAD state... Source read address/pix address: 0010C0B0/0 [0000000078047804]
4179 Entering A2_ADD state [a2_x=0704, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4180 Entering DREAD state...
4181 Dest read address/pix address: 00197240/0 [0000000000000028]
4182 Entering DWRITE state...
4183 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)
4184 Entering A1_ADD state [a1_x=004B, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4185 Entering SREAD state... Source read address/pix address: 0010C0B8/0 [7804780478047804]
4186 Entering A2_ADD state [a2_x=0708, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4187 Entering DREAD state...
4188 Dest read address/pix address: 00197260/0 [0028000000200008]
4189 Entering DWRITE state...
4190 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)
4191 Entering A1_ADD state [a1_x=004C, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4192 Entering SREAD state... Source read address/pix address: 0010C0C0/0 [0000000000000000]
4193 Entering A2_ADD state [a2_x=070C, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4194 Entering DREAD state...
4195 Dest read address/pix address: 00197280/0 [0008001800180018]
4196 Entering DWRITE state...
4197 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)
4198 Entering A1_ADD state [a1_x=0050, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4199 Entering SREAD state... Source read address/pix address: 0010C0C8/0 [000078047BFE7BFE]
4200 Entering A2_ADD state [a2_x=0710, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4201 Entering DREAD state...
4202 Dest read address/pix address: 001972A0/0 [0008002000000000]
4203 Entering DWRITE state...
4204 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)
4205 Entering A1_ADD state [a1_x=0054, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4206 Entering IDLE_INNER state...
4209 //Why isn't this taken care of in DATA? Because, DATA is modifying its local copy instead of the one used here.
4210 //!!! FIX !!! [DONE]
4219 a1_outside // A1 pointer is outside window bounds
4228 // The address is outside if negative, or if greater than or equal
4229 // to the window size
4231 A1_xcomp := MAG_15 (a1xgr, a1xeq, a1xlt, a1_x{0..14}, a1_win_x{0..14});
4232 A1_ycomp := MAG_15 (a1ygr, a1yeq, a1ylt, a1_y{0..14}, a1_win_y{0..14});
4233 A1_outside := OR6 (a1_outside, a1_x{15}, a1xgr, a1xeq, a1_y{15}, a1ygr, a1yeq);
4235 //NOTE: There seems to be an off-by-one bug here in the clip_a1 section... !!! FIX !!!
4236 // Actually, seems to be related to phrase mode writes...
4237 // Or is it? Could be related to non-15-bit compares as above?
4238 if (clip_a1 && ((a1_x & 0x8000) || (a1_y & 0x8000) || (a1_x >= a1_win_x) || (a1_y >= a1_win_y)))
4245 JaguarWriteLong(address + 0, wdata >> 32, BLITTER);
4246 JaguarWriteLong(address + 4, wdata & 0xFFFFFFFF, BLITTER);
4251 JaguarWriteLong(address, wdata & 0xFFFFFFFF, BLITTER);
4252 else if (pixsize == 4)
4253 JaguarWriteWord(address, wdata & 0x0000FFFF, BLITTER);
4255 JaguarWriteByte(address, wdata & 0x000000FF, BLITTER);
4259 #ifdef VERBOSE_BLITTER_LOGGING
4262 printf(" [%08X%08X]", (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF));
4263 printf(" (icount=%04X, inc=%u)\n", icount, (uint16)inc);
4264 printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4265 printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4273 // OK, here's the big insight: When NOT in GOURZ mode, srcz1 & 2 function EXACTLY the same way that
4274 // srcd1 & 2 work--there's an implicit shift from srcz1 to srcz2 whenever srcz1 is read.
4275 // OTHERWISE, srcz1 is the integer for the computed Z and srcz2 is the fractional part.
4276 // Writes to srcz1 & 2 follow the same pattern as the other 64-bit registers--low 32 at the low address,
4277 // high 32 at the high address (little endian!).
4278 // NOTE: GOURZ is still not properly supported. Check patd/patf handling...
4279 // Phrase mode start/end masks are not properly supported either...
4280 #ifdef VERBOSE_BLITTER_LOGGING
4283 printf(" Entering DZWRITE state...");
4284 printf(" Dest Z write address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
4285 (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4289 //This is not correct... !!! FIX !!!
4290 //Should be OK now... We'll see...
4291 //Nope. Having the same starstep write problems in phrase mode as we had with pixels... !!! FIX !!!
4292 //This is not causing the problem in Hover Strike... :-/
4293 //The problem was with the SREADX not shifting. Still problems with Z comparisons & other text in pregame screen...
4298 JaguarWriteLong(address + 0, srcz >> 32, BLITTER);
4299 JaguarWriteLong(address + 4, srcz & 0xFFFFFFFF, BLITTER);
4304 JaguarWriteWord(address, srcz & 0x0000FFFF, BLITTER);
4307 #ifdef VERBOSE_BLITTER_LOGGING
4310 // printf(" [%08X%08X]\n", (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4312 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4313 printf(" [dstart=? dend=? pwidth=? srcshift=%X]", srcshift);
4314 printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4322 #ifdef VERBOSE_BLITTER_LOGGING
4325 //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"));
4326 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"));
4330 int16 adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4331 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4332 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4333 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4334 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4336 #if 0//def VERBOSE_BLITTER_LOGGING
4339 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);
4343 //Now, write to what???
4344 //a2ptrld comes from a2ptrldi...
4345 //I believe it's addbsel that determines the writeback...
4346 // This is where atick[0] & [1] come in, in determining which part (fractional, integer)
4347 // gets written to...
4350 //Kludge, to get A1 channel increment working...
4353 a1_frac_x = addq_x, a1_frac_y = addq_y;
4355 addasel = 2, addbsel = 0, a1fracldi = false;
4356 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4357 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4358 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4359 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4361 a1_x = addq_x, a1_y = addq_y;
4364 a1_x = addq_x, a1_y = addq_y;
4369 #ifdef VERBOSE_BLITTER_LOGGING
4372 //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"));
4373 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"));
4377 //void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
4378 // int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
4379 // int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
4380 // bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
4381 //void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
4382 // int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
4383 //void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
4384 // int16 adda_x, int16 adda_y, int16 addb_x, int16 addb_y, uint8 modx, bool suba_x, bool suba_y)
4385 //void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
4386 int16 adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4387 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4388 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4389 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4390 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4392 #if 0//def VERBOSE_BLITTER_LOGGING
4395 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);
4399 //Now, write to what???
4400 //a2ptrld comes from a2ptrldi...
4401 //I believe it's addbsel that determines the writeback...
4407 Flags: SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
4409 a1_base = 0015B000, a2_base = 0014B000
4410 a1_x = 0000, a1_y = 0000, a1_frac_x = 8000, a1_frac_y = 8000, a2_x = 001F, a2_y = 0038
4411 a1_step_x = FFFFFFC0, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 2AAA, a2_step_x = FFFFFFC0, a2_step_y = 0001
4412 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4413 a1_win_x = 0040, a1_win_y = 0040, a2_mask_x = 0000, a2_mask_y = 0000
4414 a2_mask=F a1add=+inc/+0 a2add=+1/+0
4415 a1_pixsize = 4, a2_pixsize = 4
4416 srcd=FF00FF00FF00FF00 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4417 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, col=0
4419 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4420 Entering INNER state...
4421 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4422 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4423 Entering DWRITE state...
4424 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)
4425 Entering A2_ADD state [a2_x=001F, a2_y=0038, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4426 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4427 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4428 Entering DWRITE state...
4429 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)
4430 Entering A2_ADD state [a2_x=0021, a2_y=0039, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4431 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4432 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4433 Entering DWRITE state...
4434 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)
4435 Entering A2_ADD state [a2_x=0023, a2_y=003A, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4436 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4437 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4438 Entering DWRITE state...
4439 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)
4440 Entering A2_ADD state [a2_x=0025, a2_y=003B, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4442 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4443 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4444 Entering DWRITE state...
4445 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)
4446 Entering A2_ADD state [a2_x=009D, a2_y=0077, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4447 Entering IDLE_INNER state...
4448 Leaving INNER state... (ocount=0036)
4449 [in=F a1f=T a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4450 Entering A1FUPDATE state...
4451 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4452 Entering A1UPDATE state... (-32768/-32768 -> 32704/-32767)
4453 [in=F a1f=F a1=F zf=F z=F a2=T iif=F iii=F izf=F izi=F]
4454 Entering A2UPDATE state... (159/120 -> 95/121)
4455 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4456 Entering INNER state...
4459 #ifdef VERBOSE_BLITTER_LOGGING
4462 printf(" Leaving INNER state...");
4467 // The outer counter is updated here as well on the clock cycle...
4469 /* the inner loop is started whenever another state is about to
4470 cause the inner state to go active */
4471 //Instart := ND7 (instart, innert[0], innert[2..7]);
4473 //Actually, it's done only when inner gets asserted without the 2nd line of conditions
4474 //(inner AND !indone)
4476 //Since we don't get here until the inner loop is finished (indone = true) we can get
4477 //away with doing it here...!
4482 #ifdef VERBOSE_BLITTER_LOGGING
4485 printf(" (ocount=%04X)\n", ocount);
4493 #ifdef VERBOSE_BLITTER_LOGGING
4496 printf(" Entering A1FUPDATE state...\n");
4500 uint32 a1_frac_xt = (uint32)a1_frac_x + (uint32)a1_stepf_x;
4501 uint32 a1_frac_yt = (uint32)a1_frac_y + (uint32)a1_stepf_y;
4502 a1FracCInX = a1_frac_xt >> 16;
4503 a1FracCInY = a1_frac_yt >> 16;
4504 a1_frac_x = (uint16)(a1_frac_xt & 0xFFFF);
4505 a1_frac_y = (uint16)(a1_frac_yt & 0xFFFF);
4510 #ifdef VERBOSE_BLITTER_LOGGING
4513 printf(" Entering A1UPDATE state... (%d/%d -> ", a1_x, a1_y);
4517 a1_x += a1_step_x + a1FracCInX;
4518 a1_y += a1_step_y + a1FracCInY;
4519 #ifdef VERBOSE_BLITTER_LOGGING
4522 printf("%d/%d)\n", a1_x, a1_y);
4530 #ifdef VERBOSE_BLITTER_LOGGING
4533 printf(" Entering A2UPDATE state... (%d/%d -> ", a2_x, a2_y);
4539 #ifdef VERBOSE_BLITTER_LOGGING
4542 printf("%d/%d)\n", a2_x, a2_y);
4549 // Write values back to registers (in real blitter, these are continuously updated)
4550 SET16(blitter_ram, A1_PIXEL + 0, a1_y);
4551 SET16(blitter_ram, A1_PIXEL + 2, a1_x);
4552 SET16(blitter_ram, A1_FPIXEL + 0, a1_frac_y);
4553 SET16(blitter_ram, A1_FPIXEL + 2, a1_frac_x);
4554 SET16(blitter_ram, A2_PIXEL + 0, a2_y);
4555 SET16(blitter_ram, A2_PIXEL + 2, a2_x);
4560 The latest that doesn't work properly:
4562 Blit! (CMD = 09800741)
4563 Flags: SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 LFUFUNC=C DCOMPEN
4565 a1_base = 00050000, a2_base = 0083F400
4566 a1_x = 003D, a1_y = 00AD, a1_frac_x = 8000, a1_frac_y = 0000, a2_x = 0027, a2_y = 00A4
4567 a1_step_x = FFF1, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFF1, a2_step_y = 0001
4568 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4569 a1_win_x = 0180, a1_win_y = 0118, a2_mask_x = 0000, a2_mask_y = 0000
4570 a2_mask=F a1add=+inc/+0 a2add=+1/+0
4571 a1_pixsize = 4, a2_pixsize = 4
4572 srcd=0000000000000000 dstd=0000000000000000 patd=0000000000000000 iinc=00FFF000
4573 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, col=2
4575 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4576 Entering INNER state...
4577 Entering SREAD state... Source read address/pix address: 00858E4E/0 [0000000000000000]
4578 Entering A2_ADD state [a2_x=0027, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4579 Entering DWRITE state...
4580 Dest write address/pix address: 0007077A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=000E, inc=1)
4581 Entering A1_ADD state [a1_x=003D, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4582 Entering SREAD state... Source read address/pix address: 00858E50/0 [0000000000000000]
4583 Entering A2_ADD state [a2_x=0028, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4584 Entering DWRITE state...
4585 Dest write address/pix address: 0007077C/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=000D, inc=1)
4586 Entering A1_ADD state [a1_x=003E, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4587 Entering SREAD state... Source read address/pix address: 00858E52/0 [0000000000000000]
4588 Entering A2_ADD state [a2_x=0029, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4589 Entering DWRITE state...
4590 Dest write address/pix address: 0007077E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=000C, inc=1)
4591 Entering A1_ADD state [a1_x=003F, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4592 Entering SREAD state... Source read address/pix address: 00858E54/0 [000000000000014A]
4593 Entering A2_ADD state [a2_x=002A, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4594 Entering DWRITE state...
4595 Dest write address/pix address: 00070780/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=000B, inc=1)
4596 Entering A1_ADD state [a1_x=0040, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4597 Entering SREAD state... Source read address/pix address: 00858E56/0 [000000000000014A]
4598 Entering A2_ADD state [a2_x=002B, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4599 Entering DWRITE state...
4600 Dest write address/pix address: 00070782/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=000A, inc=1)
4601 Entering A1_ADD state [a1_x=0041, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4602 Entering SREAD state... Source read address/pix address: 00858E58/0 [000000000000014A]
4603 Entering A2_ADD state [a2_x=002C, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4604 Entering DWRITE state...
4605 Dest write address/pix address: 00070784/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0009, inc=1)
4606 Entering A1_ADD state [a1_x=0042, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4607 Entering SREAD state... Source read address/pix address: 00858E5A/0 [000000000000014A]
4608 Entering A2_ADD state [a2_x=002D, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4609 Entering DWRITE state...
4610 Dest write address/pix address: 00070786/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0008, inc=1)
4611 Entering A1_ADD state [a1_x=0043, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4612 Entering SREAD state... Source read address/pix address: 00858E5C/0 [000000000000014A]
4613 Entering A2_ADD state [a2_x=002E, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4614 Entering DWRITE state...
4615 Dest write address/pix address: 00070788/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0007, inc=1)
4616 Entering A1_ADD state [a1_x=0044, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4617 Entering SREAD state... Source read address/pix address: 00858E5E/0 [000000000000014A]
4618 Entering A2_ADD state [a2_x=002F, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4619 Entering DWRITE state...
4620 Dest write address/pix address: 0007078A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0006, inc=1)
4621 Entering A1_ADD state [a1_x=0045, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4622 Entering SREAD state... Source read address/pix address: 00858E60/0 [000000000000014A]
4623 Entering A2_ADD state [a2_x=0030, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4624 Entering DWRITE state...
4625 Dest write address/pix address: 0007078C/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0005, inc=1)
4626 Entering A1_ADD state [a1_x=0046, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4627 Entering SREAD state... Source read address/pix address: 00858E62/0 [000000000000014A]
4628 Entering A2_ADD state [a2_x=0031, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4629 Entering DWRITE state...
4630 Dest write address/pix address: 0007078E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0004, inc=1)
4631 Entering A1_ADD state [a1_x=0047, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4632 Entering SREAD state... Source read address/pix address: 00858E64/0 [000000000000014A]
4633 Entering A2_ADD state [a2_x=0032, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4634 Entering DWRITE state...
4635 Dest write address/pix address: 00070790/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [000000000000014A] (icount=0003, inc=1)
4636 Entering A1_ADD state [a1_x=0048, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4637 Entering SREAD state... Source read address/pix address: 00858E66/0 [0000000000000000]
4638 Entering A2_ADD state [a2_x=0033, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4639 Entering DWRITE state...
4640 Dest write address/pix address: 00070792/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=0002, inc=1)
4641 Entering A1_ADD state [a1_x=0049, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4642 Entering SREAD state... Source read address/pix address: 00858E68/0 [0000000000000000]
4643 Entering A2_ADD state [a2_x=0034, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4644 Entering DWRITE state...
4645 Dest write address/pix address: 00070794/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=0001, inc=1)
4646 Entering A1_ADD state [a1_x=004A, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4647 Entering SREAD state... Source read address/pix address: 00858E6A/0 [0000000000000000]
4648 Entering A2_ADD state [a2_x=0035, a2_y=00A4, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4649 Entering DWRITE state...
4650 Dest write address/pix address: 00070796/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=1 daq=F] [0000000000000000] (icount=0000, inc=1)
4651 Entering A1_ADD state [a1_x=004B, a1_y=00AD, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4652 Entering IDLE_INNER state...
4653 Leaving INNER state... (ocount=0011)
4654 [in=F a1f=T a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4655 Entering A1FUPDATE state...
4656 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4657 Entering A1UPDATE state... (76/173 -> 61/174)
4658 [in=F a1f=F a1=F zf=F z=F a2=T iif=F iii=F izf=F izi=F]
4659 Entering A2UPDATE state... (54/164 -> 39/165)
4660 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4661 Entering INNER state...
4665 // Various pieces of the blitter puzzle are teased out here...
4671 INT24/ address // byte address
4672 pixa[0..2] // bit part of address, un-pipe-lined
4688 apipe // load address pipe-line latch
4689 clk // co-processor clock
4690 gena2 // generate A2 as opposed to A1
4691 zaddr // generate Z address
4695 void ADDRGEN(uint32 &address, uint32 &pixa, bool gena2, bool zaddr,
4696 uint16 a1_x, uint16 a1_y, uint32 a1_base, uint8 a1_pitch, uint8 a1_pixsize, uint8 a1_width, uint8 a1_zoffset,
4697 uint16 a2_x, uint16 a2_y, uint32 a2_base, uint8 a2_pitch, uint8 a2_pixsize, uint8 a2_width, uint8 a2_zoffset)
4699 uint16 x = (gena2 ? a2_x : a1_x) & 0x7FFF;
4700 uint16 y = (gena2 ? a2_y : a1_y) & 0x0FFF;
4701 uint8 width = (gena2 ? a2_width : a1_width);
4702 uint8 pixsize = (gena2 ? a2_pixsize : a1_pixsize);
4703 uint8 pitch = (gena2 ? a2_pitch : a1_pitch);
4704 uint32 base = (gena2 ? a2_base : a1_base) >> 3;//Only upper 21 bits are passed around the bus? Seems like it...
4705 uint8 zoffset = (gena2 ? a2_zoffset : a1_zoffset);
4707 uint32 ytm = ((uint32)y << 2) + (width & 0x02 ? (uint32)y << 1 : 0) + (width & 0x01 ? (uint32)y : 0);
4709 uint32 ya = (ytm << (width >> 2)) >> 2;
4713 /*uint32*/ pixa = pa << pixsize;
4715 uint8 pt = ((pitch & 0x01) && !(pitch & 0x02) ? 0x01 : 0x00)
4716 | (!(pitch & 0x01) && (pitch & 0x02) ? 0x02 : 0x00);
4717 // uint32 phradr = pixa << pt;
4718 uint32 phradr = (pixa >> 6) << pt;
4719 uint32 shup = (pitch == 0x03 ? (pixa >> 6) : 0);
4721 uint8 za = (zaddr ? zoffset : 0) & 0x03;
4722 // uint32 addr = za + (phradr & 0x07) + (shup << 1) + base;
4723 uint32 addr = za + phradr + (shup << 1) + base;
4724 /*uint32*/ address = ((pixa & 0x38) >> 3) | ((addr & 0x1FFFFF) << 3);
4725 #if 0//def VERBOSE_BLITTER_LOGGING
4728 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);
4729 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);
4735 Entering INNER state...
4736 [gena2=T, x=0002, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4737 [ytm=0, ya=0, pa=2, pixa=20, pt=0, phradr=0, shup=0, za=0, addr=12BA, address=95D4]
4738 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4739 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
4740 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4741 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4742 [ytm=0, ya=0, pa=4, pixa=40, pt=0, phradr=1, shup=0, za=0, addr=12BB, address=95D8]
4743 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4744 Source read address/pix address: 000095D8/0 [0054003800009814]
4745 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4746 [gena2=F, x=0000, y=0000, w=20, pxsz=4, ptch=0, b=00006E52, zoff=0]
4747 [ytm=0, ya=0, pa=0, pixa=0, pt=0, phradr=0, shup=0, za=0, addr=6E52, address=37290]
4748 Entering DWRITE state...
4749 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
4750 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4751 [gena2=T, x=0008, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4752 [ytm=0, ya=0, pa=8, pixa=80, pt=0, phradr=2, shup=0, za=0, addr=12BC, address=95E0]
4756 Entering SREAD state...
4757 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4758 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10AC, address=8560]
4759 Source read address/pix address: 00008560/0 [8C27981B327E00F0]
4761 2nd pass (still wrong):
4762 Entering SREAD state...
4763 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4764 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10EC, address=8760]
4765 Source read address/pix address: 00008760/0 [00E06DC04581880C]
4768 Entering SREAD state...
4769 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4770 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=1, shup=0, za=0, addr=10AD, address=8568]
4771 Source read address/pix address: 00008568/0 [6267981A327C00F0]
4773 OK, now we're back into incorrect (or is it?):
4774 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4775 Source extra read address/pix address: 000095D4/0 [0000 001C 0054 0038]
4776 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4777 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4778 Source read address/pix address: 000095D8/0 [0054 0038 0000 9814]
4779 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4780 I think this may be correct...!
4785 // source and destination address update conditions
4787 Sraat0 := AN2 (sraat[0], sreadxi, srcenz\);
4788 Sraat1 := AN2 (sraat[1], sreadi, srcenz\);
4789 Srca_addi := OR4 (srca_addi, szreadxi, szreadi, sraat[0..1]);
4790 Srca_add := FD1Q (srca_add, srca_addi, clk);
4792 Dstaat := AN2 (dstaat, dwritei, dstwrz\);
4793 Dsta_addi := OR2 (dsta_addi, dzwritei, dstaat);
4794 // Dsta_add := FD1Q (dsta_add, dsta_addi, clk);
4796 // source and destination address generate conditions
4798 Gensrc := OR4 (gensrc, sreadxi, szreadxi, sreadi, szreadi);
4799 Gendst := OR4 (gendst, dreadi, dzreadi, dwritei, dzwritei);
4800 Dsta2\ := INV1 (dsta2\, dsta2);
4801 Gena2t0 := NAN2 (gena2t[0], gensrc, dsta2\);
4802 Gena2t1 := NAN2 (gena2t[1], gendst, dsta2);
4803 Gena2i := NAN2 (gena2i, gena2t[0..1]);
4804 Gena2 := FD1QU (gena2, gena2i, clk);
4806 Zaddr := OR4 (zaddr, szreadx, szread, dzread, dzwrite);
4811 // Basically, the above translates to:
4812 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
4814 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
4816 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
4817 bool gendst = dreadi || szreadi || dwritei || dzwritei;
4818 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
4820 bool zaddr = szreadx || szread || dzread || dzwrite;
4824 // source data reads
4826 Srcdpset\ := NAN2 (srcdpset\, readreq, sread);
4827 Srcdpt1 := NAN2 (srcdpt[1], srcdpend, srcdack\);
4828 Srcdpt2 := NAN2 (srcdpt[2], srcdpset\, srcdpt[1]);
4829 Srcdpend := FD2Q (srcdpend, srcdpt[2], clk, reset\);
4831 Srcdxpset\ := NAN2 (srcdxpset\, readreq, sreadx);
4832 Srcdxpt1 := NAN2 (srcdxpt[1], srcdxpend, srcdxack\);
4833 Srcdxpt2 := NAN2 (srcdxpt[2], srcdxpset\, srcdxpt[1]);
4834 Srcdxpend := FD2Q (srcdxpend, srcdxpt[2], clk, reset\);
4836 Sdpend := OR2 (sdpend, srcdxpend, srcdpend);
4837 Srcdreadt := AN2 (srcdreadt, sdpend, read_ack);
4839 //2/9/92 - enhancement?
4840 //Load srcdread on the next tick as well to modify it in srcshade
4842 Srcdreadd := FD1Q (srcdreadd, srcdreadt, clk);
4843 Srcdread := AOR1 (srcdread, srcshade, srcdreadd, srcdreadt);
4847 Srczpset\ := NAN2 (srczpset\, readreq, szread);
4848 Srczpt1 := NAN2 (srczpt[1], srczpend, srczack\);
4849 Srczpt2 := NAN2 (srczpt[2], srczpset\, srczpt[1]);
4850 Srczpend := FD2Q (srczpend, srczpt[2], clk, reset\);
4852 Srczxpset\ := NAN2 (srczxpset\, readreq, szreadx);
4853 Srczxpt1 := NAN2 (srczxpt[1], srczxpend, srczxack\);
4854 Srczxpt2 := NAN2 (srczxpt[2], srczxpset\, srczxpt[1]);
4855 Srczxpend := FD2Q (srczxpend, srczxpt[2], clk, reset\);
4857 Szpend := OR2 (szpend, srczpend, srczxpend);
4858 Srczread := AN2 (srczread, szpend, read_ack);
4860 // destination data reads
4862 Dstdpset\ := NAN2 (dstdpset\, readreq, dread);
4863 Dstdpt0 := NAN2 (dstdpt[0], dstdpend, dstdack\);
4864 Dstdpt1 := NAN2 (dstdpt[1], dstdpset\, dstdpt[0]);
4865 Dstdpend := FD2Q (dstdpend, dstdpt[1], clk, reset\);
4866 Dstdread := AN2 (dstdread, dstdpend, read_ack);
4868 // destination zed reads
4870 Dstzpset\ := NAN2 (dstzpset\, readreq, dzread);
4871 Dstzpt0 := NAN2 (dstzpt[0], dstzpend, dstzack\);
4872 Dstzpt1 := NAN2 (dstzpt[1], dstzpset\, dstzpt[0]);
4873 Dstzpend := FD2Q (dstzpend, dstzpt[1], clk, reset\);
4874 Dstzread := AN2 (dstzread, dstzpend, read_ack);
4879 // Basically, the above translates to:
4880 bool srcdpend = (readreq && sread) || (srcdpend && !srcdack);
4881 bool srcdxpend = (readreq && sreadx) || (srcdxpend && !srcdxack);
4882 bool sdpend = srcxpend || srcdpend;
4883 bool srcdread = ((sdpend && read_ack) && srcshade) || (sdpend && read_ack);//the latter term is lookahead
4887 ////////////////////////////////////////////////////////////////////////////////////////////
4888 ////////////////////////////////////////////////////////////////////////////////////////////
4889 // Here's an important bit: The source data adder logic. Need to track down the inputs!!! //
4890 ////////////////////////////////////////////////////////////////////////////////////////////
4891 ////////////////////////////////////////////////////////////////////////////////////////////
4898 daddasel[0..2] // data adder input A selection
4903 initcin[0..3] // carry into the adders from the initializers
4904 initinc[0..63] // the initialisation increment
4905 initpix[0..15] // Data initialiser pixel value
4917 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
4918 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
4919 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
4920 uint32 zinc, uint32 zstep)
4922 uint32 initpix2 = ((uint32)initpix << 16) | initpix;
4923 uint32 addalo[8], addahi[8];
4924 addalo[0] = dstd & 0xFFFFFFFF;
4925 addalo[1] = initpix2;
4928 addalo[4] = srcd & 0xFFFFFFFF;
4929 addalo[5] = patd & 0xFFFFFFFF;
4930 addalo[6] = srcz1 & 0xFFFFFFFF;
4931 addalo[7] = srcz2 & 0xFFFFFFFF;
4932 addahi[0] = dstd >> 32;
4933 addahi[1] = initpix2;
4936 addahi[4] = srcd >> 32;
4937 addahi[5] = patd >> 32;
4938 addahi[6] = srcz1 >> 32;
4939 addahi[7] = srcz2 >> 32;
4941 adda[0] = addalo[daddasel] & 0xFFFF;
4942 adda[1] = addalo[daddasel] >> 16;
4943 adda[2] = addahi[daddasel] & 0xFFFF;
4944 adda[3] = addahi[daddasel] >> 16;
4947 wordmux[0] = iinc & 0xFFFF;
4948 wordmux[1] = iinc >> 16;
4949 wordmux[2] = zinc & 0xFFFF;
4950 wordmux[3] = zinc >> 16;;
4951 wordmux[4] = istep & 0xFFFF;
4952 wordmux[5] = istep >> 16;;
4953 wordmux[6] = zstep & 0xFFFF;
4954 wordmux[7] = zstep >> 16;;
4955 uint16 word = wordmux[((daddbsel & 0x08) >> 1) | (daddbsel & 0x03)];
4957 bool dbsel2 = daddbsel & 0x04;
4958 bool iincsel = (daddbsel & 0x01) && !(daddbsel & 0x04);
4960 if (!dbsel2 && !iincsel)
4961 addb[0] = srcd & 0xFFFF,
4962 addb[1] = (srcd >> 16) & 0xFFFF,
4963 addb[2] = (srcd >> 32) & 0xFFFF,
4964 addb[3] = (srcd >> 48) & 0xFFFF;
4965 else if (dbsel2 && !iincsel)
4966 addb[0] = addb[1] = addb[2] = addb[3] = word;
4967 else if (!dbsel2 && iincsel)
4968 addb[0] = initinc & 0xFFFF,
4969 addb[1] = (initinc >> 16) & 0xFFFF,
4970 addb[2] = (initinc >> 32) & 0xFFFF,
4971 addb[3] = (initinc >> 48) & 0xFFFF;
4973 addb[0] = addb[1] = addb[2] = addb[3] = 0;
4975 uint8 cinsel = (daddmode >= 1 && daddmode <= 4 ? 1 : 0);
4977 static uint8 co[4];//These are preserved between calls...
4980 for(int i=0; i<4; i++)
4981 cin[i] = initcin[i] | (co[i] & cinsel);
4983 bool eightbit = daddmode & 0x02;
4984 bool sat = daddmode & 0x03;
4985 bool hicinh = ((daddmode & 0x03) == 0x03);
4987 //Note that the carry out is saved between calls to this function...
4988 for(int i=0; i<4; i++)
4989 ADD16SAT(addq[i], co[i], adda[i], addb[i], cin[i], sat, eightbit, hicinh);
5005 void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh)
5009 printf("--> [sat=%s 8b=%s hicinh=%s] %04X + %04X (+ %u) = ", (sat ? "T" : "F"), (eightbit ? "T" : "F"), (hicinh ? "T" : "F"), a, b, cin);
5013 uint32 qt = (a & 0xFF) + (b & 0xFF) + cin;
5014 carry[0] = (qt & 0x0100 ? 1 : 0);
5015 uint16 q = qt & 0x00FF;
5016 carry[1] = (carry[0] && !eightbit ? carry[0] : 0);
5017 qt = (a & 0x0F00) + (b & 0x0F00) + (carry[1] << 8);
5018 carry[2] = (qt & 0x1000 ? 1 : 0);
5020 carry[3] = (carry[2] && !hicinh ? carry[2] : 0);
5021 qt = (a & 0xF000) + (b & 0xF000) + (carry[3] << 12);
5022 co = (qt & 0x10000 ? 1 : 0);
5025 uint8 btop = (eightbit ? (b & 0x0080) >> 7 : (b & 0x8000) >> 15);
5026 uint8 ctop = (eightbit ? carry[0] : co);
5028 bool saturate = sat && (btop ^ ctop);
5029 bool hisaturate = saturate && !eightbit;
5032 printf("bt=%u ct=%u s=%u hs=%u] ", btop, ctop, saturate, hisaturate);
5036 r = (saturate ? (ctop ? 0x00FF : 0x0000) : q & 0x00FF);
5037 r |= (hisaturate ? (ctop ? 0xFF00 : 0x0000) : q & 0xFF00);
5040 printf("%04X (co=%u)\n", r, co);
5045 /** ADDAMUX - Address adder input A selection *******************
5047 This module generates the data loaded into the address adder input A. This is
5048 the update value, and can be one of four registers : A1 step, A2 step, A1
5049 increment and A1 fraction. It can complement these values to perform
5050 subtraction, and it can generate constants to increment / decrement the window
5053 addasel[0..2] select the register to add
5055 000 A1 step integer part
5056 001 A1 step fraction part
5057 010 A1 increment integer part
5058 011 A1 increment fraction part
5061 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all zeroes when
5064 addareg selects register value to be added as opposed to constant
5067 suba_x, suba_y complement the X and Y values
5093 void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
5094 int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
5095 int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
5096 bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
5099 /*INT16/ addac_x, addac_y, addar_x, addar_y, addart_x, addart_y,
5100 INT16/ addas_x, addas_y, suba_x16, suba_y16
5104 Zero := TIE0 (zero);*/
5106 /* Multiplex the register terms */
5108 /*Addaselb[0-2] := BUF8 (addaselb[0-2], addasel[0-2]);
5109 Addart_x := MX4 (addart_x, a1_step_x, a1_stepf_x, a1_inc_x, a1_incf_x, addaselb[0..1]);
5110 Addar_x := MX2 (addar_x, addart_x, a2_step_x, addaselb[2]);
5111 Addart_y := MX4 (addart_y, a1_step_y, a1_stepf_y, a1_inc_y, a1_incf_y, addaselb[0..1]);
5112 Addar_y := MX2 (addar_y, addart_y, a2_step_y, addaselb[2]);*/
5114 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5115 int16 xterm[4], yterm[4];
5116 xterm[0] = a1_step_x, xterm[1] = a1_stepf_x, xterm[2] = a1_inc_x, xterm[3] = a1_incf_x;
5117 yterm[0] = a1_step_y, yterm[1] = a1_stepf_y, yterm[2] = a1_inc_y, yterm[3] = a1_incf_y;
5118 int16 addar_x = (addasel & 0x04 ? a2_step_x : xterm[addasel & 0x03]);
5119 int16 addar_y = (addasel & 0x04 ? a2_step_y : yterm[addasel & 0x03]);
5120 //////////////////////////////////////////////////////////////////////////////////////
5122 /* Generate a constant value - this is a power of 2 in the range
5123 0-64, or zero. The control bits are adda_xconst[0..2], when they
5124 are all 1 the result is 0.
5125 Constants for Y can only be 0 or 1 */
5127 /*Addac_xlo := D38H (addac_x[0..6], unused[0], adda_xconst[0..2]);
5128 Unused[0] := DUMMY (unused[0]);
5130 Addac_x := JOIN (addac_x, addac_x[0..6], zero, zero, zero, zero, zero, zero, zero, zero, zero);
5131 Addac_y := JOIN (addac_y, adda_yconst, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero,
5132 zero, zero, zero, zero, zero);*/
5133 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5134 int16 addac_x = (adda_xconst == 0x07 ? 0 : 1 << adda_xconst);
5135 int16 addac_y = (adda_yconst ? 0x01 : 0);
5136 //////////////////////////////////////////////////////////////////////////////////////
5138 /* Select between constant value and register value */
5140 /*Addas_x := MX2 (addas_x, addac_x, addar_x, addareg);
5141 Addas_y := MX2 (addas_y, addac_y, addar_y, addareg);*/
5142 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5143 int16 addas_x = (addareg ? addar_x : addac_x);
5144 int16 addas_y = (addareg ? addar_y : addac_y);
5145 //////////////////////////////////////////////////////////////////////////////////////
5147 /* Complement these values (complement flag gives adder carry in)*/
5149 /*Suba_x16 := JOIN (suba_x16, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x,
5150 suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x);
5151 Suba_y16 := JOIN (suba_y16, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y,
5152 suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y);
5153 Adda_x := EO (adda_x, suba_x16, addas_x);
5154 Adda_y := EO (adda_y, suba_y16, addas_y);*/
5155 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5156 adda_x = addas_x ^ (suba_x ? 0xFFFF : 0x0000);
5157 adda_y = addas_y ^ (suba_y ? 0xFFFF : 0x0000);
5158 //////////////////////////////////////////////////////////////////////////////////////
5163 /** ADDBMUX - Address adder input B selection *******************
5165 This module selects the register to be updated by the address
5166 adder. This can be one of three registers, the A1 and A2
5167 pointers, or the A1 fractional part. It can also be zero, so that the step
5168 registers load directly into the pointers.
5183 INT16/ zero16 :LOCAL;
5185 void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
5186 int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
5189 /*Zero := TIE0 (zero);
5190 Zero16 := JOIN (zero16, zero, zero, zero, zero, zero, zero, zero,
5191 zero, zero, zero, zero, zero, zero, zero, zero, zero);
5192 Addbselb[0-1] := BUF8 (addbselb[0-1], addbsel[0-1]);
5193 Addb_x := MX4 (addb_x, a1_x, a2_x, a1_frac_x, zero16, addbselb[0..1]);
5194 Addb_y := MX4 (addb_y, a1_y, a2_y, a1_frac_y, zero16, addbselb[0..1]);*/
5195 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5196 int16 xterm[4], yterm[4];
5197 xterm[0] = a1_x, xterm[1] = a2_x, xterm[2] = a1_frac_x, xterm[3] = 0;
5198 yterm[0] = a1_y, yterm[1] = a2_y, yterm[2] = a1_frac_y, yterm[3] = 0;
5199 addb_x = xterm[addbsel & 0x03];
5200 addb_y = yterm[addbsel & 0x03];
5201 //////////////////////////////////////////////////////////////////////////////////////
5206 /** DATAMUX - Address local data bus selection ******************
5208 Select between the adder output and the input data bus
5221 INT16/ gpu_lo, gpu_hi
5224 void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
5226 /*Gpu_lo := JOIN (gpu_lo, gpu_din{0..15});
5227 Gpu_hi := JOIN (gpu_hi, gpu_din{16..31});
5229 Addqselb := BUF8 (addqselb, addqsel);
5230 Data_x := MX2 (data_x, gpu_lo, addq_x, addqselb);
5231 Data_y := MX2 (data_y, gpu_hi, addq_y, addqselb);*/
5232 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5233 data_x = (addqsel ? addq_x : (int16)(gpu_din & 0xFFFF));
5234 data_y = (addqsel ? addq_y : (int16)(gpu_din >> 16));
5235 //////////////////////////////////////////////////////////////////////////////////////
5240 /******************************************************************
5244 Blitter Address Adder
5245 ---------------------
5246 The blitter address adder is a pair of sixteen bit adders, one
5247 each for X and Y. The multiplexing of the input terms is
5248 performed elsewhere, but this adder can also perform modulo
5249 arithmetic to align X-addresses onto phrase boundaries.
5251 modx[0..2] take values
5258 ******************************************************************/
5260 /*IMPORT duplo, tosh;
5266 a1fracldi // propagate address adder carry
5271 clk[0] // co-processor clock
5279 Zero := TIE0 (zero);*/
5280 void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
5281 uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y)
5284 /* Perform the addition */
5286 /*Adder_x := ADD16 (addqt_x[0..15], co_x, adda_x{0..15}, addb_x{0..15}, ci_x);
5287 Adder_y := ADD16 (addq_y[0..15], co_y, adda_y{0..15}, addb_y{0..15}, ci_y);*/
5289 /* latch carry and propagate if required */
5291 /*Cxt0 := AN2 (cxt[0], co_x, a1fracldi);
5292 Cxt1 := FD1Q (cxt[1], cxt[0], clk[0]);
5293 Ci_x := EO (ci_x, cxt[1], suba_x);
5295 yt0 := AN2 (cyt[0], co_y, a1fracldi);
5296 Cyt1 := FD1Q (cyt[1], cyt[0], clk[0]);
5297 Ci_y := EO (ci_y, cyt[1], suba_y);*/
5299 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5300 //I'm sure the following will generate a bunch of warnings, but will have to do for now.
5301 static uint16 co_x = 0, co_y = 0; // Carry out has to propogate between function calls...
5302 uint16 ci_x = co_x ^ (suba_x ? 1 : 0);
5303 uint16 ci_y = co_y ^ (suba_y ? 1 : 0);
5304 uint32 addqt_x = adda_x + addb_x + ci_x;
5305 uint32 addqt_y = adda_y + addb_y + ci_y;
5306 co_x = ((addqt_x & 0x10000) && a1fracldi ? 1 : 0);
5307 co_y = ((addqt_y & 0x10000) && a1fracldi ? 1 : 0);
5308 //////////////////////////////////////////////////////////////////////////////////////
5310 /* Mask low bits of X to 0 if required */
5312 /*Masksel := D38H (unused[0], masksel[0..4], maskbit[5], unused[1], modx[0..2]);
5314 Maskbit[0-4] := OR2 (maskbit[0-4], masksel[0-4], maskbit[1-5]);
5316 Mask[0-5] := MX2 (addq_x[0-5], addqt_x[0-5], zero, maskbit[0-5]);
5318 Addq_x := JOIN (addq_x, addq_x[0..5], addqt_x[6..15]);
5319 Addq_y := JOIN (addq_y, addq_y[0..15]);*/
5321 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5322 int16 mask[8] = { 0xFFFF, 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, 0xFFE0, 0xFFC0, 0x0000 };
5323 addq_x = addqt_x & mask[modx];
5324 addq_y = addqt_y & 0xFFFF;
5325 //////////////////////////////////////////////////////////////////////////////////////
5327 //Unused[0-1] := DUMMY (unused[0-1]);
5334 wdata[0..63] // co-processor write data bus
5336 dcomp[0..7] // data byte equal flags
5337 srcd[0..7] // bits to use for bit to byte expansion
5338 zcomp[0..3] // output from Z comparators
5340 a1_x[0..1] // low two bits of A1 X pointer
5341 big_pix // pixel organisation is big-endian
5342 blitter_active // blitter is active
5343 clk // co-processor clock
5344 cmpdst // compare dest rather than source
5345 colorld // load the pattern color fields
5346 daddasel[0..2] // data adder input A selection
5347 daddbsel[0..3] // data adder input B selection
5348 daddmode[0..2] // data adder mode
5349 daddq_sel // select adder output vs. GPU data
5350 data[0..63] // co-processor read data bus
5351 data_ena // enable write data
5352 data_sel[0..1] // select data to write
5353 dbinh\[0..7] // byte oriented changed data inhibits
5354 dend[0..5] // end of changed write data zone
5355 dpipe[0..1] // load computed data pipe-line latch
5356 dstart[0..5] // start of changed write data zone
5357 dstdld[0..1] // dest data load (two halves)
5358 dstzld[0..1] // dest zed load (two halves)
5359 ext_int // enable extended precision intensity calculations
5360 INT32/ gpu_din // GPU data bus
5361 iincld // I increment load
5362 iincldx // alternate I increment load
5363 init_if // initialise I fraction phase
5364 init_ii // initialise I integer phase
5365 init_zf // initialise Z fraction phase
5366 intld[0..3] // computed intensities load
5367 istepadd // intensity step integer add
5368 istepfadd // intensity step fraction add
5369 istepld // I step load
5370 istepdld // I step delta load
5371 lfu_func[0..3] // LFU function code
5372 patdadd // pattern data gouraud add
5373 patdld[0..1] // pattern data load (two halves)
5374 pdsel[0..1] // select pattern data type
5375 phrase_mode // phrase write mode
5376 reload // transfer contents of double buffers
5377 reset\ // system reset
5378 srcd1ld[0..1] // source register 1 load (two halves)
5379 srcdread // source data read load enable
5380 srczread // source zed read load enable
5381 srcshift[0..5] // source alignment shift
5382 srcz1ld[0..1] // source zed 1 load (two halves)
5383 srcz2add // zed fraction gouraud add
5384 srcz2ld[0..1] // source zed 2 load (two halves)
5385 textrgb // texture mapping in RGB mode
5386 txtd[0..63] // data from the texture unit
5387 zedld[0..3] // computed zeds load
5388 zincld // Z increment load
5389 zmode[0..2] // Z comparator mode
5390 zpipe[0..1] // load computed zed pipe-line latch
5391 zstepadd // zed step integer add
5392 zstepfadd // zed step fraction add
5393 zstepld // Z step load
5394 zstepdld // Z step delta load
5398 void DATA(uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
5399 bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
5400 uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 &patd, bool patdadd,
5401 bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
5402 bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize,
5403 uint64 &srcz, uint64 dstz, uint32 zinc)
5406 Stuff we absolutely *need* to have passed in/out:
5408 patdadd, dstd, srcd, patd, daddasel, daddbsel, daddmode, iinc, srcz1, srcz2, big_pix, phrase_mode, cmpdst
5410 changed patd (wdata I guess...) (Nope. We pass it back directly now...)
5413 // Source data registers
5415 /*Data_src := DATA_SRC (srcdlo, srcdhi, srcz[0..1], srczo[0..1], srczp[0..1], srcz1[0..1], srcz2[0..1], big_pix,
5416 clk, gpu_din, intld[0..3], local_data0, local_data1, srcd1ld[0..1], srcdread, srczread, srcshift[0..5],
5417 srcz1ld[0..1], srcz2add, srcz2ld[0..1], zedld[0..3], zpipe[0..1]);
5418 Srcd[0-7] := JOIN (srcd[0-7], srcdlo{0-7});
5419 Srcd[8-31] := JOIN (srcd[8-31], srcdlo{8-31});
5420 Srcd[32-63] := JOIN (srcd[32-63], srcdhi{0-31});*/
5422 // Destination data registers
5424 /*Data_dst := DATA_DST (dstd[0..63], dstz[0..1], clk, dstdld[0..1], dstzld[0..1], load_data[0..1]);
5425 Dstdlo := JOIN (dstdlo, dstd[0..31]);
5426 Dstdhi := JOIN (dstdhi, dstd[32..63]);*/
5428 // Pattern and Color data registers
5430 // Looks like this is simply another register file for the pattern data registers. No adding or anything funky
5431 // going on. Note that patd & patdv will output the same info.
5432 // Patdldl/h (patdld[0..1]) can select the local_data bus to overwrite the current pattern data...
5433 // Actually, it can be either patdld OR patdadd...!
5434 /*Data_pat := DATA_PAT (colord[0..15], int0dp[8..10], int1dp[8..10], int2dp[8..10], int3dp[8..10], mixsel[0..2],
5435 patd[0..63], patdv[0..1], clk, colorld, dpipe[0], ext_int, gpu_din, intld[0..3], local_data0, local_data1,
5436 patdadd, patdld[0..1], reload, reset\);
5437 Patdlo := JOIN (patdlo, patd[0..31]);
5438 Patdhi := JOIN (patdhi, patd[32..63]);*/
5440 // Multiplying data Mixer (NOT IN JAGUAR I)
5442 /*Datamix := DATAMIX (patdo[0..1], clk, colord[0..15], dpipe[1], dstd[0..63], int0dp[8..10], int1dp[8..10],
5443 int2dp[8..10], int3dp[8..10], mixsel[0..2], patd[0..63], pdsel[0..1], srcd[0..63], textrgb, txtd[0..63]);*/
5445 // Logic function unit
5447 /*Lfu := LFU (lfu[0..1], srcdlo, srcdhi, dstdlo, dstdhi, lfu_func[0..3]);*/
5448 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5449 uint64 funcmask[2] = { 0, 0xFFFFFFFFFFFFFFFFLL };
5450 uint64 func0 = funcmask[lfu_func & 0x01];
5451 uint64 func1 = funcmask[(lfu_func >> 1) & 0x01];
5452 uint64 func2 = funcmask[(lfu_func >> 2) & 0x01];
5453 uint64 func3 = funcmask[(lfu_func >> 3) & 0x01];
5454 uint64 lfu = (~srcd & ~dstd & func0) | (~srcd & dstd & func1) | (srcd & ~dstd & func2) | (srcd & dstd & func3);
5455 //////////////////////////////////////////////////////////////////////////////////////
5457 // Increment and Step Registers
5459 // Does it do anything without the step add lines? Check it!
5460 // No. This is pretty much just a register file without the Jaguar II lines...
5461 /*Inc_step := INC_STEP (iinc, istep[0..31], zinc, zstep[0..31], clk, ext_int, gpu_din, iincld, iincldx, istepadd,
5462 istepfadd, istepld, istepdld, reload, reset\, zincld, zstepadd, zstepfadd, zstepld, zstepdld);
5463 Istep := JOIN (istep, istep[0..31]);
5464 Zstep := JOIN (zstep, zstep[0..31]);*/
5466 // Pixel data comparator
5468 /*Datacomp := DATACOMP (dcomp[0..7], cmpdst, dstdlo, dstdhi, patdlo, patdhi, srcdlo, srcdhi);*/
5469 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5471 uint64 cmpd = patd ^ (cmpdst ? dstd : srcd);
5473 if ((cmpd & 0x00000000000000FFLL) == 0)
5475 if ((cmpd & 0x000000000000FF00LL) == 0)
5477 if ((cmpd & 0x0000000000FF0000LL) == 0)
5479 if ((cmpd & 0x00000000FF000000LL) == 0)
5481 if ((cmpd & 0x000000FF00000000LL) == 0)
5483 if ((cmpd & 0x0000FF0000000000LL) == 0)
5485 if ((cmpd & 0x00FF000000000000LL) == 0)
5487 if ((cmpd & 0xFF00000000000000LL) == 0)
5489 //////////////////////////////////////////////////////////////////////////////////////
5491 // Zed comparator for Z-buffer operations
5493 /*Zedcomp := ZEDCOMP (zcomp[0..3], srczp[0..1], dstz[0..1], zmode[0..2]);*/
5494 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5495 //srczp is srcz pipelined, also it goes through a source shift as well...
5496 /*The shift is basically like so (each piece is 16 bits long):
5499 srcz1lolo srcz1lohi srcz1hilo srcz1hihi srcrz2lolo srcz2lohi srcz2hilo
5501 with srcshift bits 4 & 5 selecting the start position
5503 //So... basically what we have here is:
5506 if ((((srcz & 0x000000000000FFFFLL) < (dstz & 0x000000000000FFFFLL)) && (zmode & 0x01))
5507 || (((srcz & 0x000000000000FFFFLL) == (dstz & 0x000000000000FFFFLL)) && (zmode & 0x02))
5508 || (((srcz & 0x000000000000FFFFLL) > (dstz & 0x000000000000FFFFLL)) && (zmode & 0x04)))
5511 if ((((srcz & 0x00000000FFFF0000LL) < (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x01))
5512 || (((srcz & 0x00000000FFFF0000LL) == (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x02))
5513 || (((srcz & 0x00000000FFFF0000LL) > (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x04)))
5516 if ((((srcz & 0x0000FFFF00000000LL) < (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x01))
5517 || (((srcz & 0x0000FFFF00000000LL) == (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x02))
5518 || (((srcz & 0x0000FFFF00000000LL) > (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x04)))
5521 if ((((srcz & 0xFFFF000000000000LL) < (dstz & 0xFFFF000000000000LL)) && (zmode & 0x01))
5522 || (((srcz & 0xFFFF000000000000LL) == (dstz & 0xFFFF000000000000LL)) && (zmode & 0x02))
5523 || (((srcz & 0xFFFF000000000000LL) > (dstz & 0xFFFF000000000000LL)) && (zmode & 0x04)))
5526 //TEMP, TO TEST IF ZCOMP IS THE CULPRIT...
5527 //Nope, this is NOT the problem...
5529 // We'll do the comparison/bit/byte inhibits here, since that's they way it happens
5530 // in the real thing (dcomp goes out to COMP_CTRL and back into DATA through dbinh)...
5534 COMP_CTRL(dbinht, nowrite,
5535 bcompen, true/*big_pix*/, bkgwren, dcomp, dcompen, icount, pixsize, phrase_mode, srcd & 0xFF, zcomp);
5541 #ifdef VERBOSE_BLITTER_LOGGING
5544 printf("\n[dcomp=%02X zcomp=%02X dbinh=%02X]\n", dcomp, zcomp, dbinh);
5549 //////////////////////////////////////////////////////////////////////////////////////
5552 // The data initializer - allows all four initial values to be computed from one (NOT IN JAGUAR I)
5554 /*Datinit := DATINIT (initcin[0..3], initinc[0..63], initpix[0..15], a1_x[0..1], big_pix, clk, iinc, init_if, init_ii,
5555 init_zf, istep[0..31], zinc, zstep[0..31]);*/
5557 // Adder array for Z and intensity increments
5559 /*Addarray := ADDARRAY (addq[0..3], clk, daddasel[0..2], daddbsel[0..3], daddmode[0..2], dstdlo, dstdhi, iinc,
5560 initcin[0..3], initinc[0..63], initpix[0..15], istep, patdv[0..1], srcdlo, srcdhi, srcz1[0..1],
5561 srcz2[0..1], reset\, zinc, zstep);*/
5562 /*void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
5563 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
5564 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
5565 uint32 zinc, uint32 zstep)*/
5566 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5568 uint8 initcin[4] = { 0, 0, 0, 0 };
5569 ADDARRAY(addq, daddasel, daddbsel, daddmode, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
5571 //This is normally done asynchronously above (thru local_data) when in patdadd mode...
5572 //And now it's passed back to the caller to be persistent between calls...!
5573 //But it's causing some serious fuck-ups in T2K now... !!! FIX !!! [DONE--???]
5574 //Weird! It doesn't anymore...!
5576 patd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
5577 //////////////////////////////////////////////////////////////////////////////////////
5579 // Local data bus multiplexer
5581 /*Local_mux := LOCAL_MUX (local_data[0..1], load_data[0..1],
5582 addq[0..3], gpu_din, data[0..63], blitter_active, daddq_sel);
5583 Local_data0 := JOIN (local_data0, local_data[0]);
5584 Local_data1 := JOIN (local_data1, local_data[1]);*/
5585 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5586 //////////////////////////////////////////////////////////////////////////////////////
5588 // Data output multiplexer and tri-state drive
5590 /*Data_mux := DATA_MUX (wdata[0..63], addq[0..3], big_pix, dstdlo, dstdhi, dstz[0..1], data_sel[0..1], data_ena,
5591 dstart[0..5], dend[0..5], dbinh\[0..7], lfu[0..1], patdo[0..1], phrase_mode, srczo[0..1]);*/
5592 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5593 // NOTE: patdo comes from DATAMIX and can be considered the same as patd for Jaguar I
5595 //////////////////////////////////////////////////////////////////////////////////////
5599 wdata[0..63] // co-processor rwrite data bus
5602 big_pix // Pixel organisation is big-endian
5607 data_sel[0..1] // source of write data
5608 data_ena // enable write data onto read/write bus
5609 dstart[0..5] // start of changed write data
5610 dend[0..5] // end of changed write data
5611 dbinh\[0..7] // byte oriented changed data inhibits
5614 phrase_mode // phrase write mode
5619 /*INT32/ addql[0..1], ddatlo, ddathi zero32
5623 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5624 Zero := TIE0 (zero);
5625 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);*/
5627 /* Generate a changed data mask */
5629 /*Edis := OR6 (edis\, dend[0..5]);
5630 Ecoarse := DECL38E (e_coarse\[0..7], dend[3..5], edis\);
5631 E_coarse[0] := INV1 (e_coarse[0], e_coarse\[0]);
5632 Efine := DECL38E (unused[0], e_fine\[1..7], dend[0..2], e_coarse[0]);*/
5633 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5634 uint8 decl38e[2][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
5635 { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } };
5636 uint8 dech38[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
5637 uint8 dech38el[2][8] = { { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
5638 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
5640 int en = (dend & 0x3F ? 1 : 0);
5641 uint8 e_coarse = decl38e[en][(dend & 0x38) >> 3]; // Actually, this is e_coarse inverted...
5642 uint8 e_fine = decl38e[(e_coarse & 0x01) ^ 0x01][dend & 0x07];
5644 //////////////////////////////////////////////////////////////////////////////////////
5646 /*Scoarse := DECH38 (s_coarse[0..7], dstart[3..5]);
5647 Sfen\ := INV1 (sfen\, s_coarse[0]);
5648 Sfine := DECH38EL (s_fine[0..7], dstart[0..2], sfen\);*/
5649 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5650 uint8 s_coarse = dech38[(dstart & 0x38) >> 3];
5651 uint8 s_fine = dech38el[(s_coarse & 0x01) ^ 0x01][dstart & 0x07];
5652 //////////////////////////////////////////////////////////////////////////////////////
5654 /*Maskt[0] := BUF1 (maskt[0], s_fine[0]);
5655 Maskt[1-7] := OAN1P (maskt[1-7], maskt[0-6], s_fine[1-7], e_fine\[1-7]);*/
5656 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5657 uint16 maskt = s_fine & 0x0001;
5658 maskt |= (((maskt & 0x0001) || (s_fine & 0x02)) && (e_fine & 0x02) ? 0x0002 : 0x0000);
5659 maskt |= (((maskt & 0x0002) || (s_fine & 0x04)) && (e_fine & 0x04) ? 0x0004 : 0x0000);
5660 maskt |= (((maskt & 0x0004) || (s_fine & 0x08)) && (e_fine & 0x08) ? 0x0008 : 0x0000);
5661 maskt |= (((maskt & 0x0008) || (s_fine & 0x10)) && (e_fine & 0x10) ? 0x0010 : 0x0000);
5662 maskt |= (((maskt & 0x0010) || (s_fine & 0x20)) && (e_fine & 0x20) ? 0x0020 : 0x0000);
5663 maskt |= (((maskt & 0x0020) || (s_fine & 0x40)) && (e_fine & 0x40) ? 0x0040 : 0x0000);
5664 maskt |= (((maskt & 0x0040) || (s_fine & 0x80)) && (e_fine & 0x80) ? 0x0080 : 0x0000);
5665 //////////////////////////////////////////////////////////////////////////////////////
5667 /* Produce a look-ahead on the ripple carry:
5668 masktla = s_coarse[0] . /e_coarse[0] */
5669 /*Masktla := AN2 (masktla, s_coarse[0], e_coarse\[0]);
5670 Maskt[8] := OAN1P (maskt[8], masktla, s_coarse[1], e_coarse\[1]);
5671 Maskt[9-14] := OAN1P (maskt[9-14], maskt[8-13], s_coarse[2-7], e_coarse\[2-7]);*/
5672 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5673 maskt |= (((s_coarse & e_coarse & 0x01) || (s_coarse & 0x02)) && (e_coarse & 0x02) ? 0x0100 : 0x0000);
5674 maskt |= (((maskt & 0x0100) || (s_coarse & 0x04)) && (e_coarse & 0x04) ? 0x0200 : 0x0000);
5675 maskt |= (((maskt & 0x0200) || (s_coarse & 0x08)) && (e_coarse & 0x08) ? 0x0400 : 0x0000);
5676 maskt |= (((maskt & 0x0400) || (s_coarse & 0x10)) && (e_coarse & 0x10) ? 0x0800 : 0x0000);
5677 maskt |= (((maskt & 0x0800) || (s_coarse & 0x20)) && (e_coarse & 0x20) ? 0x1000 : 0x0000);
5678 maskt |= (((maskt & 0x1000) || (s_coarse & 0x40)) && (e_coarse & 0x40) ? 0x2000 : 0x0000);
5679 maskt |= (((maskt & 0x2000) || (s_coarse & 0x80)) && (e_coarse & 0x80) ? 0x4000 : 0x0000);
5680 //////////////////////////////////////////////////////////////////////////////////////
5682 /* The bit terms are mirrored for big-endian pixels outside phrase
5683 mode. The byte terms are mirrored for big-endian pixels in phrase
5686 /*Mirror_bit := AN2M (mir_bit, phrase_mode\, big_pix);
5687 Mirror_byte := AN2H (mir_byte, phrase_mode, big_pix);
5689 Masktb[14] := BUF1 (masktb[14], maskt[14]);
5690 Masku[0] := MX4 (masku[0], maskt[0], maskt[7], maskt[14], zero, mir_bit, mir_byte);
5691 Masku[1] := MX4 (masku[1], maskt[1], maskt[6], maskt[14], zero, mir_bit, mir_byte);
5692 Masku[2] := MX4 (masku[2], maskt[2], maskt[5], maskt[14], zero, mir_bit, mir_byte);
5693 Masku[3] := MX4 (masku[3], maskt[3], maskt[4], masktb[14], zero, mir_bit, mir_byte);
5694 Masku[4] := MX4 (masku[4], maskt[4], maskt[3], masktb[14], zero, mir_bit, mir_byte);
5695 Masku[5] := MX4 (masku[5], maskt[5], maskt[2], masktb[14], zero, mir_bit, mir_byte);
5696 Masku[6] := MX4 (masku[6], maskt[6], maskt[1], masktb[14], zero, mir_bit, mir_byte);
5697 Masku[7] := MX4 (masku[7], maskt[7], maskt[0], masktb[14], zero, mir_bit, mir_byte);
5698 Masku[8] := MX2 (masku[8], maskt[8], maskt[13], mir_byte);
5699 Masku[9] := MX2 (masku[9], maskt[9], maskt[12], mir_byte);
5700 Masku[10] := MX2 (masku[10], maskt[10], maskt[11], mir_byte);
5701 Masku[11] := MX2 (masku[11], maskt[11], maskt[10], mir_byte);
5702 Masku[12] := MX2 (masku[12], maskt[12], maskt[9], mir_byte);
5703 Masku[13] := MX2 (masku[13], maskt[13], maskt[8], mir_byte);
5704 Masku[14] := MX2 (masku[14], maskt[14], maskt[0], mir_byte);*/
5705 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5706 bool mir_bit = true/*big_pix*/ && !phrase_mode;
5707 bool mir_byte = true/*big_pix*/ && phrase_mode;
5708 uint16 masku = maskt;
5713 masku |= (maskt >> 7) & 0x0001;
5714 masku |= (maskt >> 5) & 0x0002;
5715 masku |= (maskt >> 3) & 0x0004;
5716 masku |= (maskt >> 1) & 0x0008;
5717 masku |= (maskt << 1) & 0x0010;
5718 masku |= (maskt << 3) & 0x0020;
5719 masku |= (maskt << 5) & 0x0040;
5720 masku |= (maskt << 7) & 0x0080;
5726 masku |= (maskt >> 14) & 0x0001;
5727 masku |= (maskt >> 13) & 0x0002;
5728 masku |= (maskt >> 12) & 0x0004;
5729 masku |= (maskt >> 11) & 0x0008;
5730 masku |= (maskt >> 10) & 0x0010;
5731 masku |= (maskt >> 9) & 0x0020;
5732 masku |= (maskt >> 8) & 0x0040;
5733 masku |= (maskt >> 7) & 0x0080;
5735 masku |= (maskt >> 5) & 0x0100;
5736 masku |= (maskt >> 3) & 0x0200;
5737 masku |= (maskt >> 1) & 0x0400;
5738 masku |= (maskt << 1) & 0x0800;
5739 masku |= (maskt << 3) & 0x1000;
5740 masku |= (maskt << 5) & 0x2000;
5741 masku |= (maskt << 7) & 0x4000;
5743 //////////////////////////////////////////////////////////////////////////////////////
5745 /* The maskt terms define the area for changed data, but the byte
5746 inhibit terms can override these */
5748 /*Mask[0-7] := AN2 (mask[0-7], masku[0-7], dbinh\[0]);
5749 Mask[8-14] := AN2H (mask[8-14], masku[8-14], dbinh\[1-7]);*/
5750 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5751 uint16 mask = masku & (!(dbinh & 0x01) ? 0xFFFF : 0xFF00);
5752 mask &= ~(((uint16)dbinh & 0x00FE) << 7);
5753 //////////////////////////////////////////////////////////////////////////////////////
5755 /*Addql[0] := JOIN (addql[0], addq[0..1]);
5756 Addql[1] := JOIN (addql[1], addq[2..3]);
5758 Dsel0b[0-1] := BUF8 (dsel0b[0-1], data_sel[0]);
5759 Dsel1b[0-1] := BUF8 (dsel1b[0-1], data_sel[1]);
5760 Ddatlo := MX4 (ddatlo, patd[0], lfu[0], addql[0], zero32, dsel0b[0], dsel1b[0]);
5761 Ddathi := MX4 (ddathi, patd[1], lfu[1], addql[1], zero32, dsel0b[1], dsel1b[1]);*/
5762 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5766 dmux[2] = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
5768 uint64 ddat = dmux[data_sel];
5769 //////////////////////////////////////////////////////////////////////////////////////
5771 /*Zed_sel := AN2 (zed_sel, data_sel[0..1]);
5772 Zed_selb[0-1] := BUF8 (zed_selb[0-1], zed_sel);
5774 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]);
5775 Dat[8-15] := MX4 (dat[8-15], dstdlo{8-15}, ddatlo{8-15}, dstzlo{8-15}, srczlo{8-15}, mask[8], zed_selb[0]);
5776 Dat[16-23] := MX4 (dat[16-23], dstdlo{16-23}, ddatlo{16-23}, dstzlo{16-23}, srczlo{16-23}, mask[9], zed_selb[0]);
5777 Dat[24-31] := MX4 (dat[24-31], dstdlo{24-31}, ddatlo{24-31}, dstzlo{24-31}, srczlo{24-31}, mask[10], zed_selb[0]);
5778 Dat[32-39] := MX4 (dat[32-39], dstdhi{0-7}, ddathi{0-7}, dstzhi{0-7}, srczhi{0-7}, mask[11], zed_selb[1]);
5779 Dat[40-47] := MX4 (dat[40-47], dstdhi{8-15}, ddathi{8-15}, dstzhi{8-15}, srczhi{8-15}, mask[12], zed_selb[1]);
5780 Dat[48-55] := MX4 (dat[48-55], dstdhi{16-23}, ddathi{16-23}, dstzhi{16-23}, srczhi{16-23}, mask[13], zed_selb[1]);
5781 Dat[56-63] := MX4 (dat[56-63], dstdhi{24-31}, ddathi{24-31}, dstzhi{24-31}, srczhi{24-31}, mask[14], zed_selb[1]);*/
5782 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5783 wdata = ((ddat & mask) | (dstd & ~mask)) & 0x00000000000000FFLL;
5784 wdata |= (mask & 0x0100 ? ddat : dstd) & 0x000000000000FF00LL;
5785 wdata |= (mask & 0x0200 ? ddat : dstd) & 0x0000000000FF0000LL;
5786 wdata |= (mask & 0x0400 ? ddat : dstd) & 0x00000000FF000000LL;
5787 wdata |= (mask & 0x0800 ? ddat : dstd) & 0x000000FF00000000LL;
5788 wdata |= (mask & 0x1000 ? ddat : dstd) & 0x0000FF0000000000LL;
5789 wdata |= (mask & 0x2000 ? ddat : dstd) & 0x00FF000000000000LL;
5790 wdata |= (mask & 0x4000 ? ddat : dstd) & 0xFF00000000000000LL;
5793 printf("\n[ddat=%08X%08X dstd=%08X%08X wdata=%08X%08X mask=%04X]\n",
5794 (uint32)(ddat >> 32), (uint32)(ddat & 0xFFFFFFFF),
5795 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
5796 (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF), mask);
5799 //This is a crappy way of handling this, but it should work for now...
5801 zwdata = ((srcz & mask) | (dstz & ~mask)) & 0x00000000000000FFLL;
5802 zwdata |= (mask & 0x0100 ? srcz : dstz) & 0x000000000000FF00LL;
5803 zwdata |= (mask & 0x0200 ? srcz : dstz) & 0x0000000000FF0000LL;
5804 zwdata |= (mask & 0x0400 ? srcz : dstz) & 0x00000000FF000000LL;
5805 zwdata |= (mask & 0x0800 ? srcz : dstz) & 0x000000FF00000000LL;
5806 zwdata |= (mask & 0x1000 ? srcz : dstz) & 0x0000FF0000000000LL;
5807 zwdata |= (mask & 0x2000 ? srcz : dstz) & 0x00FF000000000000LL;
5808 zwdata |= (mask & 0x4000 ? srcz : dstz) & 0xFF00000000000000LL;
5811 printf("\n[srcz=%08X%08X dstz=%08X%08X zwdata=%08X%08X mask=%04X]\n",
5812 (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF),
5813 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF),
5814 (uint32)(zwdata >> 32), (uint32)(zwdata & 0xFFFFFFFF), mask);
5818 //////////////////////////////////////////////////////////////////////////////////////
5820 /*Data_enab[0-1] := BUF8 (data_enab[0-1], data_ena);
5821 Datadrv[0-31] := TS (wdata[0-31], dat[0-31], data_enab[0]);
5822 Datadrv[32-63] := TS (wdata[32-63], dat[32-63], data_enab[1]);
5824 Unused[0] := DUMMY (unused[0]);
5829 /** COMP_CTRL - Comparator output control logic *****************
5831 This block is responsible for taking the comparator outputs and
5832 using them as appropriate to inhibit writes. Two methods are
5833 supported for inhibiting write data:
5835 - suppression of the inner loop controlled write operation
5836 - a set of eight byte inhibit lines to write back dest data
5838 The first technique is used in pixel oriented modes, the second in
5839 phrase mode, but the phrase mode form is only applicable to eight
5840 and sixteen bit pixel modes.
5842 Writes can be suppressed by data being equal, by the Z comparator
5843 conditions being met, or by the bit to pixel expansion scheme.
5845 Pipe-lining issues: the data derived comparator outputs are stable
5846 until the next data read, well after the affected write from this
5847 operation. However, the inner counter bits can count immediately
5848 before the ack for the last write. Therefore, it is necessary to
5849 delay bcompbit select terms by one inner loop pipe-line stage,
5850 when generating the select for the data control - the output is
5851 delayed one further tick to give it write data timing (2/34).
5853 There is also a problem with computed data - the new values are
5854 calculated before the write associated with the old value has been
5855 performed. The is taken care of within the zed comparator by
5856 pipe-lining the comparator inputs where appropriate.
5859 //#define LOG_COMP_CTRL
5861 dbinh\[0..7] // destination byte inhibit lines
5862 nowrite // suppress inner loop write operation
5864 bcompen // bit selector inhibit enable
5865 big_pix // pixels are big-endian
5866 bkgwren // enable dest data write in pix inhibit
5867 clk // co-processor clock
5868 dcomp[0..7] // output of data byte comparators
5869 dcompen // data comparator inhibit enable
5870 icount[0..2] // low bits of inner count
5871 pixsize[0..2] // destination pixel size
5872 phrase_mode // phrase write mode
5873 srcd[0..7] // bits to use for bit to byte expansion
5874 step_inner // inner loop advance
5875 zcomp[0..3] // output of word zed comparators
5877 void COMP_CTRL(uint8 &dbinh, bool &nowrite,
5878 bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
5879 uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp)
5883 /*Bkgwren\ := INV1 (bkgwren\, bkgwren);
5884 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5885 Pixsize\[0-2] := INV2 (pixsize\[0-2], pixsize[0-2]);*/
5887 /* The bit comparator bits are derived from the source data, which
5888 will have been suitably aligned for phrase mode. The contents of
5889 the inner counter are used to select which bit to use.
5891 When not in phrase mode the inner count value is used to select
5892 one bit. It is assumed that the count has already occurred, so,
5893 7 selects bit 0, etc. In big-endian pixel mode, this turns round,
5894 so that a count of 7 selects bit 7.
5896 In phrase mode, the eight bits are used directly, and this mode is
5897 only applicable to 8-bit pixel mode (2/34) */
5899 /*Bcompselt[0-2] := EO (bcompselt[0-2], icount[0-2], big_pix);
5900 Bcompbit := MX8 (bcompbit, srcd[7], srcd[6], srcd[5],
5901 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompselt[0..2]);
5902 Bcompbit\ := INV1 (bcompbit\, bcompbit);*/
5903 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5904 #ifdef LOG_COMP_CTRL
5907 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);
5912 uint8 bcompselt = (big_pix ? ~icount : icount) & 0x07;
5913 uint8 bitmask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
5914 bool bcompbit = srcd & bitmask[bcompselt];
5915 //////////////////////////////////////////////////////////////////////////////////////
5917 /* pipe-line the count */
5918 /*Bcompsel[0-2] := FDSYNC (bcompsel[0-2], bcompselt[0-2], step_inner, clk);
5919 Bcompbt := MX8 (bcompbitpt, srcd[7], srcd[6], srcd[5],
5920 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompsel[0..2]);
5921 Bcompbitp := FD1Q (bcompbitp, bcompbitpt, clk);
5922 Bcompbitp\ := INV1 (bcompbitp\, bcompbitp);*/
5924 /* For pixel mode, generate the write inhibit signal for all modes
5925 on bit inhibit, for 8 and 16 bit modes on comparator inhibit, and
5926 for 16 bit mode on Z inhibit
5928 Nowrite = bcompen . /bcompbit . /phrase_mode
5929 + dcompen . dcomp[0] . /phrase_mode . pixsize = 011
5930 + dcompen . dcomp[0..1] . /phrase_mode . pixsize = 100
5931 + zcomp[0] . /phrase_mode . pixsize = 100
5934 /*Nowt0 := NAN3 (nowt[0], bcompen, bcompbit\, phrase_mode\);
5935 Nowt1 := ND6 (nowt[1], dcompen, dcomp[0], phrase_mode\, pixsize\[2], pixsize[0..1]);
5936 Nowt2 := ND7 (nowt[2], dcompen, dcomp[0..1], phrase_mode\, pixsize[2], pixsize\[0..1]);
5937 Nowt3 := NAN5 (nowt[3], zcomp[0], phrase_mode\, pixsize[2], pixsize\[0..1]);
5938 Nowt4 := NAN4 (nowt[4], nowt[0..3]);
5939 Nowrite := AN2 (nowrite, nowt[4], bkgwren\);*/
5940 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5941 nowrite = ((bcompen && !bcompbit && !phrase_mode)
5942 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
5943 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
5944 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4)))
5946 //////////////////////////////////////////////////////////////////////////////////////
5948 /*Winht := NAN3 (winht, bcompen, bcompbitp\, phrase_mode\);
5949 Winhibit := NAN4 (winhibit, winht, nowt[1..3]);*/
5950 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5951 //This is the same as above, but with bcompbit delayed one tick and called 'winhibit'
5952 //Small difference: Besides the pipeline effect, it's also not using !bkgwren...
5953 // bool winhibit = (bcompen && !
5954 bool winhibit = (bcompen && !bcompbit && !phrase_mode)
5955 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
5956 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
5957 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4));
5958 #ifdef LOG_COMP_CTRL
5961 printf("[nw=%s wi=%s]", (nowrite ? "T" : "F"), (winhibit ? "T" : "F"));
5965 //////////////////////////////////////////////////////////////////////////////////////
5967 /* For phrase mode, generate the byte inhibit signals for eight bit
5968 mode 011, or sixteen bit mode 100
5969 dbinh\[0] = pixsize[2] . zcomp[0]
5970 + pixsize[2] . dcomp[0] . dcomp[1] . dcompen
5971 + /pixsize[2] . dcomp[0] . dcompen
5972 + /srcd[0] . bcompen
5974 Inhibits 0-3 are also used when not in phrase mode to write back
5978 /*Srcd\[0-7] := INV1 (srcd\[0-7], srcd[0-7]);
5980 Di0t0 := NAN2H (di0t[0], pixsize[2], zcomp[0]);
5981 Di0t1 := NAN4H (di0t[1], pixsize[2], dcomp[0..1], dcompen);
5982 Di0t2 := NAN2 (di0t[2], srcd\[0], bcompen);
5983 Di0t3 := NAN3 (di0t[3], pixsize\[2], dcomp[0], dcompen);
5984 Di0t4 := NAN4 (di0t[4], di0t[0..3]);
5985 Dbinh[0] := ANR1P (dbinh\[0], di0t[4], phrase_mode, winhibit);*/
5986 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5988 bool di0t0_1 = ((pixsize & 0x04) && (zcomp & 0x01))
5989 || ((pixsize & 0x04) && (dcomp & 0x01) && (dcomp & 0x02) && dcompen);
5990 bool di0t4 = di0t0_1
5991 || (!(srcd & 0x01) && bcompen)
5992 || (!(pixsize & 0x04) && (dcomp & 0x01) && dcompen);
5993 dbinh |= (!((di0t4 && phrase_mode) || winhibit) ? 0x01 : 0x00);
5994 #ifdef LOG_COMP_CTRL
5997 printf("[di0t0_1=%s di0t4=%s]", (di0t0_1 ? "T" : "F"), (di0t4 ? "T" : "F"));
6001 //////////////////////////////////////////////////////////////////////////////////////
6003 /*Di1t0 := NAN3 (di1t[0], pixsize\[2], dcomp[1], dcompen);
6004 Di1t1 := NAN2 (di1t[1], srcd\[1], bcompen);
6005 Di1t2 := NAN4 (di1t[2], di0t[0..1], di1t[0..1]);
6006 Dbinh[1] := ANR1 (dbinh\[1], di1t[2], phrase_mode, winhibit);*/
6007 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6008 bool di1t2 = di0t0_1
6009 || (!(srcd & 0x02) && bcompen)
6010 || (!(pixsize & 0x04) && (dcomp & 0x02) && dcompen);
6011 dbinh |= (!((di1t2 && phrase_mode) || winhibit) ? 0x02 : 0x00);
6012 #ifdef LOG_COMP_CTRL
6015 printf("[di1t2=%s]", (di1t2 ? "T" : "F"));
6019 //////////////////////////////////////////////////////////////////////////////////////
6021 /*Di2t0 := NAN2H (di2t[0], pixsize[2], zcomp[1]);
6022 Di2t1 := NAN4H (di2t[1], pixsize[2], dcomp[2..3], dcompen);
6023 Di2t2 := NAN2 (di2t[2], srcd\[2], bcompen);
6024 Di2t3 := NAN3 (di2t[3], pixsize\[2], dcomp[2], dcompen);
6025 Di2t4 := NAN4 (di2t[4], di2t[0..3]);
6026 Dbinh[2] := ANR1 (dbinh\[2], di2t[4], phrase_mode, winhibit);*/
6027 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6028 //[bcompen=F dcompen=T phrase_mode=T bkgwren=F][nw=F wi=F]
6029 //[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]
6030 //[dcomp=$00 dbinh=$0C][7804780400007804] (icount=0005, inc=4)
6031 bool di2t0_1 = ((pixsize & 0x04) && (zcomp & 0x02))
6032 || ((pixsize & 0x04) && (dcomp & 0x04) && (dcomp & 0x08) && dcompen);
6033 bool di2t4 = di2t0_1
6034 || (!(srcd & 0x04) && bcompen)
6035 || (!(pixsize & 0x04) && (dcomp & 0x04) && dcompen);
6036 dbinh |= (!((di2t4 && phrase_mode) || winhibit) ? 0x04 : 0x00);
6037 #ifdef LOG_COMP_CTRL
6040 printf("[di2t0_1=%s di2t4=%s]", (di2t0_1 ? "T" : "F"), (di2t4 ? "T" : "F"));
6044 //////////////////////////////////////////////////////////////////////////////////////
6046 /*Di3t0 := NAN3 (di3t[0], pixsize\[2], dcomp[3], dcompen);
6047 Di3t1 := NAN2 (di3t[1], srcd\[3], bcompen);
6048 Di3t2 := NAN4 (di3t[2], di2t[0..1], di3t[0..1]);
6049 Dbinh[3] := ANR1 (dbinh\[3], di3t[2], phrase_mode, winhibit);*/
6050 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6051 bool di3t2 = di2t0_1
6052 || (!(srcd & 0x08) && bcompen)
6053 || (!(pixsize & 0x04) && (dcomp & 0x08) && dcompen);
6054 dbinh |= (!((di3t2 && phrase_mode) || winhibit) ? 0x08 : 0x00);
6055 #ifdef LOG_COMP_CTRL
6058 printf("[di3t2=%s]", (di3t2 ? "T" : "F"));
6062 //////////////////////////////////////////////////////////////////////////////////////
6064 /*Di4t0 := NAN2H (di4t[0], pixsize[2], zcomp[2]);
6065 Di4t1 := NAN4H (di4t[1], pixsize[2], dcomp[4..5], dcompen);
6066 Di4t2 := NAN2 (di4t[2], srcd\[4], bcompen);
6067 Di4t3 := NAN3 (di4t[3], pixsize\[2], dcomp[4], dcompen);
6068 Di4t4 := NAN4 (di4t[4], di4t[0..3]);
6069 Dbinh[4] := NAN2 (dbinh\[4], di4t[4], phrase_mode);*/
6070 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6071 bool di4t0_1 = ((pixsize & 0x04) && (zcomp & 0x04))
6072 || ((pixsize & 0x04) && (dcomp & 0x10) && (dcomp & 0x20) && dcompen);
6073 bool di4t4 = di4t0_1
6074 || (!(srcd & 0x10) && bcompen)
6075 || (!(pixsize & 0x04) && (dcomp & 0x10) && dcompen);
6076 dbinh |= (!(di4t4 && phrase_mode) ? 0x10 : 0x00);
6077 #ifdef LOG_COMP_CTRL
6080 printf("[di4t0_1=%s di2t4=%s]", (di4t0_1 ? "T" : "F"), (di4t4 ? "T" : "F"));
6084 //////////////////////////////////////////////////////////////////////////////////////
6086 /*Di5t0 := NAN3 (di5t[0], pixsize\[2], dcomp[5], dcompen);
6087 Di5t1 := NAN2 (di5t[1], srcd\[5], bcompen);
6088 Di5t2 := NAN4 (di5t[2], di4t[0..1], di5t[0..1]);
6089 Dbinh[5] := NAN2 (dbinh\[5], di5t[2], phrase_mode);*/
6090 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6091 bool di5t2 = di4t0_1
6092 || (!(srcd & 0x20) && bcompen)
6093 || (!(pixsize & 0x04) && (dcomp & 0x20) && dcompen);
6094 dbinh |= (!(di5t2 && phrase_mode) ? 0x20 : 0x00);
6095 #ifdef LOG_COMP_CTRL
6098 printf("[di5t2=%s]", (di5t2 ? "T" : "F"));
6102 //////////////////////////////////////////////////////////////////////////////////////
6104 /*Di6t0 := NAN2H (di6t[0], pixsize[2], zcomp[3]);
6105 Di6t1 := NAN4H (di6t[1], pixsize[2], dcomp[6..7], dcompen);
6106 Di6t2 := NAN2 (di6t[2], srcd\[6], bcompen);
6107 Di6t3 := NAN3 (di6t[3], pixsize\[2], dcomp[6], dcompen);
6108 Di6t4 := NAN4 (di6t[4], di6t[0..3]);
6109 Dbinh[6] := NAN2 (dbinh\[6], di6t[4], phrase_mode);*/
6110 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6111 bool di6t0_1 = ((pixsize & 0x04) && (zcomp & 0x08))
6112 || ((pixsize & 0x04) && (dcomp & 0x40) && (dcomp & 0x80) && dcompen);
6113 bool di6t4 = di6t0_1
6114 || (!(srcd & 0x40) && bcompen)
6115 || (!(pixsize & 0x04) && (dcomp & 0x40) && dcompen);
6116 dbinh |= (!(di6t4 && phrase_mode) ? 0x40 : 0x00);
6117 #ifdef LOG_COMP_CTRL
6120 printf("[di6t0_1=%s di6t4=%s]", (di6t0_1 ? "T" : "F"), (di6t4 ? "T" : "F"));
6124 //////////////////////////////////////////////////////////////////////////////////////
6126 /*Di7t0 := NAN3 (di7t[0], pixsize\[2], dcomp[7], dcompen);
6127 Di7t1 := NAN2 (di7t[1], srcd\[7], bcompen);
6128 Di7t2 := NAN4 (di7t[2], di6t[0..1], di7t[0..1]);
6129 Dbinh[7] := NAN2 (dbinh\[7], di7t[2], phrase_mode);*/
6130 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6131 bool di7t2 = di6t0_1
6132 || (!(srcd & 0x80) && bcompen)
6133 || (!(pixsize & 0x04) && (dcomp & 0x80) && dcompen);
6134 dbinh |= (!(di7t2 && phrase_mode) ? 0x80 : 0x00);
6135 #ifdef LOG_COMP_CTRL
6138 printf("[di7t2=%s]", (di7t2 ? "T" : "F"));
6142 //////////////////////////////////////////////////////////////////////////////////////
6147 #ifdef LOG_COMP_CTRL
6150 printf("[dcomp=$%02X dbinh=$%02X]\n ", dcomp, dbinh);
6157 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6158 //////////////////////////////////////////////////////////////////////////////////////