5 // (C) 2010 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- -------------------------------------------------------------
11 // JLH 01/16/2010 Created this log ;-)
15 // I owe a debt of gratitude to Curt Vendel and to John Mathieson--to Curt
16 // for supplying the Oberon ASIC nets and to John for making them available
17 // to Curt. ;-) Without that excellent documentation which shows *exactly*
18 // what's going on inside the TOM chip, we'd all still be guessing as to how
19 // the wily blitter and other pieces of the Jaguar puzzle actually work.
20 // Now how about those JERRY ASIC nets gentlemen...? [We have those now!] ;-)
32 // Various conditional compilation goodies...
36 //#define USE_ORIGINAL_BLITTER
37 //#define USE_MIDSUMMER_BLITTER
38 #define USE_MIDSUMMER_BLITTER_MKII
40 // External global variables
42 extern int jaguar_active_memory_dumps;
44 // Local global variables
46 int start_logging = 0;
47 uint8 blitter_working = 0;
49 // Blitter register RAM (most of it is hidden from the user)
51 static uint8 blitter_ram[0x100];
55 bool specialLog = false;
56 extern int effect_start;
57 extern int blit_start_log;
58 void BlitterMidsummer(uint32 cmd);
59 void BlitterMidsummer2(void);
61 #define REG(A) (((uint32)blitter_ram[(A)] << 24) | ((uint32)blitter_ram[(A)+1] << 16) \
62 | ((uint32)blitter_ram[(A)+2] << 8) | (uint32)blitter_ram[(A)+3])
63 #define WREG(A,D) (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
64 blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
66 // Blitter registers (offsets from F02200)
68 #define A1_BASE ((uint32)0x00)
69 #define A1_FLAGS ((uint32)0x04)
70 #define A1_CLIP ((uint32)0x08) // Height and width values for clipping
71 #define A1_PIXEL ((uint32)0x0C) // Integer part of the pixel (Y.i and X.i)
72 #define A1_STEP ((uint32)0x10) // Integer part of the step
73 #define A1_FSTEP ((uint32)0x14) // Fractional part of the step
74 #define A1_FPIXEL ((uint32)0x18) // Fractional part of the pixel (Y.f and X.f)
75 #define A1_INC ((uint32)0x1C) // Integer part of the increment
76 #define A1_FINC ((uint32)0x20) // Fractional part of the increment
77 #define A2_BASE ((uint32)0x24)
78 #define A2_FLAGS ((uint32)0x28)
79 #define A2_MASK ((uint32)0x2C) // Modulo values for x and y (M.y and M.x)
80 #define A2_PIXEL ((uint32)0x30) // Integer part of the pixel (no fractional part for A2)
81 #define A2_STEP ((uint32)0x34) // Integer part of the step (no fractional part for A2)
82 #define COMMAND ((uint32)0x38)
83 #define PIXLINECOUNTER ((uint32)0x3C) // Inner & outer loop values
84 #define SRCDATA ((uint32)0x40)
85 #define DSTDATA ((uint32)0x48)
86 #define DSTZ ((uint32)0x50)
87 #define SRCZINT ((uint32)0x58)
88 #define SRCZFRAC ((uint32)0x60)
89 #define PATTERNDATA ((uint32)0x68)
90 #define INTENSITYINC ((uint32)0x70)
91 #define ZINC ((uint32)0x74)
92 #define COLLISIONCTRL ((uint32)0x78)
93 #define PHRASEINT0 ((uint32)0x7C)
94 #define PHRASEINT1 ((uint32)0x80)
95 #define PHRASEINT2 ((uint32)0x84)
96 #define PHRASEINT3 ((uint32)0x88)
97 #define PHRASEZ0 ((uint32)0x8C)
98 #define PHRASEZ1 ((uint32)0x90)
99 #define PHRASEZ2 ((uint32)0x94)
100 #define PHRASEZ3 ((uint32)0x98)
102 // Blitter command bits
104 #define SRCEN (cmd & 0x00000001)
105 #define SRCENZ (cmd & 0x00000002)
106 #define SRCENX (cmd & 0x00000004)
107 #define DSTEN (cmd & 0x00000008)
108 #define DSTENZ (cmd & 0x00000010)
109 #define DSTWRZ (cmd & 0x00000020)
110 #define CLIPA1 (cmd & 0x00000040)
112 #define UPDA1F (cmd & 0x00000100)
113 #define UPDA1 (cmd & 0x00000200)
114 #define UPDA2 (cmd & 0x00000400)
116 #define DSTA2 (cmd & 0x00000800)
118 #define Z_OP_INF (cmd & 0x00040000)
119 #define Z_OP_EQU (cmd & 0x00080000)
120 #define Z_OP_SUP (cmd & 0x00100000)
122 #define LFU_NAN (cmd & 0x00200000)
123 #define LFU_NA (cmd & 0x00400000)
124 #define LFU_AN (cmd & 0x00800000)
125 #define LFU_A (cmd & 0x01000000)
127 #define CMPDST (cmd & 0x02000000)
128 #define BCOMPEN (cmd & 0x04000000)
129 #define DCOMPEN (cmd & 0x08000000)
131 #define PATDSEL (cmd & 0x00010000)
132 #define ADDDSEL (cmd & 0x00020000)
133 #define TOPBEN (cmd & 0x00004000)
134 #define TOPNEN (cmd & 0x00008000)
135 #define BKGWREN (cmd & 0x10000000)
136 #define GOURD (cmd & 0x00001000)
137 #define GOURZ (cmd & 0x00002000)
138 #define SRCSHADE (cmd & 0x40000000)
146 #define XSIGNSUB_A1 (REG(A1_FLAGS)&0x080000)
147 #define XSIGNSUB_A2 (REG(A2_FLAGS)&0x080000)
149 #define YSIGNSUB_A1 (REG(A1_FLAGS)&0x100000)
150 #define YSIGNSUB_A2 (REG(A2_FLAGS)&0x100000)
152 #define YADD1_A1 (REG(A1_FLAGS)&0x040000)
153 #define YADD1_A2 (REG(A2_FLAGS)&0x040000)
155 /*******************************************************************************
156 ********************** STUFF CUT BELOW THIS LINE! ******************************
157 *******************************************************************************/
158 #ifdef USE_ORIGINAL_BLITTER // We're ditching this crap for now...
160 //Put 'em back, once we fix the problem!!! [KO]
162 #define PIXEL_SHIFT_1(a) (((~a##_x) >> 16) & 7)
163 #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))
164 #define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
165 //#define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
168 #define PIXEL_SHIFT_2(a) (((~a##_x) >> 15) & 6)
169 #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))
170 #define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03)
171 //#define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
174 #define PIXEL_SHIFT_4(a) (((~a##_x) >> 14) & 4)
175 #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))
176 #define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f)
177 //#define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
180 #define PIXEL_OFFSET_8(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 7))
181 #define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER))
182 //#define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a)))
185 #define PIXEL_OFFSET_16(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 3))
186 #define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER))
187 //#define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
190 #define PIXEL_OFFSET_32(a) (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
191 #define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER))
192 //#define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
195 #define READ_PIXEL(a,f) (\
196 (((f>>3)&0x07) == 0) ? (READ_PIXEL_1(a)) : \
197 (((f>>3)&0x07) == 1) ? (READ_PIXEL_2(a)) : \
198 (((f>>3)&0x07) == 2) ? (READ_PIXEL_4(a)) : \
199 (((f>>3)&0x07) == 3) ? (READ_PIXEL_8(a)) : \
200 (((f>>3)&0x07) == 4) ? (READ_PIXEL_16(a)) : \
201 (((f>>3)&0x07) == 5) ? (READ_PIXEL_32(a)) : 0)
203 // 16 bpp z data read
204 #define ZDATA_OFFSET_16(a) (PIXEL_OFFSET_16(a) + a##_zoffs * 4)
205 #define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER))
206 //#define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
209 #define READ_ZDATA(a,f) (READ_ZDATA_16(a))
211 // 16 bpp z data write
212 #define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); }
213 //#define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); }
216 #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d);
219 #define READ_RDATA_1(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 19) & 0x04))) >> (((uint32)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001))
222 #define READ_RDATA_2(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 18) & 0x04))) >> (((uint32)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003))
225 #define READ_RDATA_4(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 17) & 0x04))) >> (((uint32)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F))
228 #define READ_RDATA_8(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 16) & 0x04))) >> (((uint32)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF))
230 // 16 bpp r data read
231 #define READ_RDATA_16(r,a,p) ((p) ? ((REG(r+(((uint32)a##_x >> 15) & 0x04))) >> (((uint32)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF))
233 // 32 bpp r data read
234 #define READ_RDATA_32(r,a,p) ((p) ? REG(r+(((uint32)a##_x >> 14) & 0x04)) : REG(r))
236 // register data read
237 #define READ_RDATA(r,a,f,p) (\
238 (((f>>3)&0x07) == 0) ? (READ_RDATA_1(r,a,p)) : \
239 (((f>>3)&0x07) == 1) ? (READ_RDATA_2(r,a,p)) : \
240 (((f>>3)&0x07) == 2) ? (READ_RDATA_4(r,a,p)) : \
241 (((f>>3)&0x07) == 3) ? (READ_RDATA_8(r,a,p)) : \
242 (((f>>3)&0x07) == 4) ? (READ_RDATA_16(r,a,p)) : \
243 (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0)
246 #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); }
247 //#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))); }
250 #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); }
251 //#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))); }
254 #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); }
255 //#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))); }
258 #define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d, BLITTER); }
259 //#define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d); }
261 // 16 bpp pixel write
262 //#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
263 #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)); }
264 //#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)); }
266 // 32 bpp pixel write
267 #define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); }
268 //#define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); }
271 #define WRITE_PIXEL(a,f,d) {\
272 switch ((f>>3)&0x07) { \
273 case 0: WRITE_PIXEL_1(a,d); break; \
274 case 1: WRITE_PIXEL_2(a,d); break; \
275 case 2: WRITE_PIXEL_4(a,d); break; \
276 case 3: WRITE_PIXEL_8(a,d); break; \
277 case 4: WRITE_PIXEL_16(a,d); break; \
278 case 5: WRITE_PIXEL_32(a,d); break; \
281 // Width in Pixels of a Scanline
282 // This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
283 // of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
284 // the exponent. Valid values for the exponent range from 0 to 11 (decimal). It's easiest to think of it
285 // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to
286 // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place
287 // being shifted to the right 3 places).
288 /*static uint32 blitter_scanline_width[48] =
290 0, 0, 0, 0, // Note: This would really translate to 1, 1, 1, 1
300 1024, 1280, 1536, 1792,
301 2048, 2560, 3072, 3584
304 //static uint8 * tom_ram_8;
305 //static uint8 * paletteRam;
315 static uint32 a1_addr;
316 static uint32 a2_addr;
317 static int32 a1_zoffs;
318 static int32 a2_zoffs;
319 static uint32 xadd_a1_control;
320 static uint32 xadd_a2_control;
321 static int32 a1_pitch;
322 static int32 a2_pitch;
323 static uint32 n_pixels;
324 static uint32 n_lines;
327 static int32 a1_width;
330 static int32 a2_width;
331 static int32 a2_mask_x;
332 static int32 a2_mask_y;
333 static int32 a1_xadd;
334 static int32 a1_yadd;
335 static int32 a2_xadd;
336 static int32 a2_yadd;
337 static uint8 a1_phrase_mode;
338 static uint8 a2_phrase_mode;
339 static int32 a1_step_x = 0;
340 static int32 a1_step_y = 0;
341 static int32 a2_step_x = 0;
342 static int32 a2_step_y = 0;
343 static uint32 outer_loop;
344 static uint32 inner_loop;
345 static uint32 a2_psize;
346 static uint32 a1_psize;
347 static uint32 gouraud_add;
348 //static uint32 gouraud_data;
349 //static uint16 gint[4];
350 //static uint16 gfrac[4];
351 //static uint8 gcolour[4];
354 static int gd_ia, gd_ca;
355 static int colour_index = 0;
357 static uint32 z_i[4];
359 static int32 a1_clip_x, a1_clip_y;
361 // In the spirit of "get it right first, *then* optimize" I've taken the liberty
362 // of removing all the unnecessary code caching. If it turns out to be a good way
363 // to optimize the blitter, then we may revisit it in the future...
366 // Generic blit handler
368 void blitter_generic(uint32 cmd)
371 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
372 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
373 A1 step values: -2 (X), 1 (Y)
374 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
375 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
376 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
377 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
380 // specialLog = true;
381 /*if (cmd == 0x1401060C && blit_start_log)
382 specialLog = true;//*/
384 //uint32 logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
385 uint32 srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
386 uint32 bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07));
390 WriteLog("About to do n x m blit (BM width is ? pixels)...\n");
391 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);
405 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
407 uint32 a1_start = a1_x, a2_start = a2_x, bitPos = 0;
409 //Kludge for Hover Strike...
410 //I wonder if this kludge is in conjunction with the SRCENX down below...
411 // This isn't so much a kludge but the way things work in BCOMPEN mode...!
412 if (BCOMPEN && SRCENX)
414 if (n_pixels < bppSrc)
415 bitPos = bppSrc - n_pixels;
418 inner_loop = n_pixels;
423 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
425 srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
427 if (!DSTA2) // Data movement: A1 <- A2
429 // load src data and Z
431 if (SRCEN || SRCENX) // Not sure if this is correct... (seems to be...!)
433 srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
436 srczdata = READ_ZDATA(a2, REG(A2_FLAGS));
437 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
438 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
440 else // Use SRCDATA register...
442 srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
444 if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
445 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
448 // load dst data and Z
451 dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
454 dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
456 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
460 dstdata = READ_RDATA(DSTDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
463 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
466 /*This wasn't working... // a1 clipping
467 if (cmd & 0x00000040)
469 if (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7FFF)
470 || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7FFF))
475 srczdata = z_i[colour_index] >> 16;
477 // apply z comparator
478 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
479 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
480 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
482 // apply data comparator
483 // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
484 // Does BCOMPEN only work in 1 bpp mode???
485 // No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!!
486 // This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside
488 if (DCOMPEN | BCOMPEN)
490 //Temp, for testing Hover Strike
491 //Doesn't seem to do it... Why?
492 //What needs to happen here is twofold. First, the address generator in the outer loop has
493 //to honor the BPP when calculating the start address (which it kinda does already). Second,
494 //it has to step bit by bit when using BCOMPEN. How to do this???
496 //small problem with this approach: it's not accurate... We need a proper address to begin with
497 //and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!!
500 uint32 pixShift = (~bitPos) & (bppSrc - 1);
501 srcdata = (srcdata >> pixShift) & 0x01;
504 // if (bitPos % bppSrc == 0)
505 // a2_x += 0x00010000;
508 Interesting (Hover Strike--large letter):
510 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
511 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
512 A1 step values: -2 (X), 1 (Y)
513 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
514 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
515 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
516 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
518 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
519 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
520 A1 step values: -8 (X), 1 (Y)
521 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
522 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
523 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
524 A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000
526 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
527 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
528 A1 step values: -1 (X), 1 (Y)
529 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
530 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
531 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
532 A1 x/y: 118/12, A2 x/y: 70/0 Pattern: 000000F300000000
534 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
535 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
536 A1 step values: -8 (X), 1 (Y)
537 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
538 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
539 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
540 A1 x/y: 119/12, A2 x/y: 71/0 Pattern: 000000F300000000
542 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
543 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
544 A1 step values: -1 (X), 1 (Y)
545 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
546 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
547 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
548 A1 x/y: 127/12, A2 x/y: 66/0 Pattern: 000000F300000000
550 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
551 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
552 A1 step values: -8 (X), 1 (Y)
553 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
554 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
555 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
556 A1 x/y: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000
562 //WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit);
563 // compare source pixel with pattern pixel
565 Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: 05810001]
566 CMD -> src: SRCEN dst: misc: a1ctl: mode: ity: PATDSEL z-op: op: LFU_REPLACE ctrl: BCOMPEN
567 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
568 A2 -> pitch: 1 phrases, depth: 1bpp, z-off: 0, width: 16 (10), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
572 // AvP is still wrong, could be cuz it's doing A1 -> A2...
574 // Src is the 1bpp bitmap... DST is the PATTERN!!!
575 // This seems to solve at least ONE of the problems with MC3D...
576 // Why should this be inverted???
577 // Bcuz it is. This is supposed to be used only for a bit -> pixel expansion...
578 /* if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
579 // if (srcdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
581 /* uint32 A2bpp = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
582 if (A2bpp == 1 || A2bpp == 16 || A2bpp == 8)
583 inhibit = (srcdata == 0 ? 1: 0);
584 // inhibit = !srcdata;
586 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
587 // What it boils down to is this:
594 // compare destination pixel with pattern pixel
595 if (dstdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
596 // if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
600 // This is DEFINITELY WRONG
601 // if (a1_phrase_mode || a2_phrase_mode)
602 // inhibit = !inhibit;
607 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
608 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
611 // compute the write data and store
614 // Houston, we have a problem...
615 // Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's
617 //Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008]
618 // CMD -> src: dst: DSTEN misc: a1ctl: mode: GOURD ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
619 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
620 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
621 // A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700
625 // use pattern data for write data
626 writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
630 /*if (blit_start_log)
631 WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/
633 // intensity addition
634 //Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!!
635 /* writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
636 if (!(TOPBEN) && writedata > 0xFF)
639 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
640 if (!(TOPNEN) && writedata > 0xFFF)
641 // writedata = 0xFFF;
643 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/
644 //notneeded--writedata &= 0xFFFF;
645 /*if (blit_start_log)
646 WriteLog("writedata: %08X\n", writedata);//*/
648 Hover Strike ADDDSEL blit:
650 Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208]
651 CMD -> src: dst: DSTEN misc: a1ctl: UPDA1 mode: ity: ADDDSEL z-op: op: LFU_CLEAR ctrl:
652 A1 step values: -320 (X), 1 (Y)
653 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
654 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
655 A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD
657 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
661 //This is correct now, but slow...
662 int16 s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000),
671 writedata = (uint32)sum;
674 //This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!!
675 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
677 if (!TOPNEN && writedata > 0xFFF)
682 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
686 if (LFU_NAN) writedata |= ~srcdata & ~dstdata;
687 if (LFU_NA) writedata |= ~srcdata & dstdata;
688 if (LFU_AN) writedata |= srcdata & ~dstdata;
689 if (LFU_A) writedata |= srcdata & dstdata;
692 //Although, this looks like it's OK... (even if it is shitty!)
693 //According to JTRM, this is part of the four things the blitter does with the write data (the other
694 //three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL
695 //(see above blit example)...
697 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
701 int intensity = srcdata & 0xFF;
702 int ia = gd_ia >> 16;
704 ia = 0xFFFFFF00 | ia;
708 if (intensity > 0xFF)
710 writedata = (srcdata & 0xFF00) | intensity;
719 //Tried 2nd below for Hover Strike: No dice.
720 if (/*a1_phrase_mode || */BKGWREN || !inhibit)
721 // if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit)
723 /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
725 uint32 offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
726 // (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
727 if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
728 WriteLog("32bpp pixel write: A1 Phrase mode --> ");
730 // write to the destination
731 WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
733 WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
736 else // if (DSTA2) // Data movement: A1 -> A2
738 // load src data and Z
741 srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
743 srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
744 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
745 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
749 srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
750 if (cmd & 0x001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
751 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
754 // load dst data and Z
757 dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
759 dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
761 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
765 dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
767 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
771 srczdata = z_i[colour_index] >> 16;
773 // apply z comparator
774 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
775 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
776 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
778 // apply data comparator
779 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
780 if (DCOMPEN | BCOMPEN)
784 // compare source pixel with pattern pixel
785 // AvP: Numbers are correct, but sprites are not!
786 //This doesn't seem to be a problem... But could still be wrong...
787 /* if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
788 // if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
790 // This is probably not 100% correct... It works in the 1bpp case
791 // (in A1 <- A2 mode, that is...)
792 // AvP: This is causing blocks to be written instead of bit patterns...
794 // NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
795 /* uint32 A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
796 if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
797 inhibit = (srcdata == 0 ? 1: 0);
799 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
800 // What it boils down to is this:
806 // compare destination pixel with pattern pixel
807 if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
808 // if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
812 // This is DEFINITELY WRONG
813 // if (a1_phrase_mode || a2_phrase_mode)
814 // inhibit = !inhibit;
819 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
820 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
823 // compute the write data and store
828 // use pattern data for write data
829 writedata = READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
833 // intensity addition
834 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
835 if (!(TOPBEN) && writedata > 0xFF)
837 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
838 if (!(TOPNEN) && writedata > 0xFFF)
840 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
845 writedata |= ~srcdata & ~dstdata;
847 writedata |= ~srcdata & dstdata;
849 writedata |= srcdata & ~dstdata;
851 writedata |= srcdata & dstdata;
855 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
859 int intensity = srcdata & 0xFF;
860 int ia = gd_ia >> 16;
862 ia = 0xFFFFFF00 | ia;
866 if (intensity > 0xFF)
868 writedata = (srcdata & 0xFF00) | intensity;
877 if (/*a2_phrase_mode || */BKGWREN || !inhibit)
881 uint32 offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
882 // (((((uint32)a##_y >> 16) * a##_width) + (((uint32)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32)a##_x >> 16) & 1))
883 WriteLog("[%08X:%04X] ", offset, writedata);
885 // write to the destination
886 WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
889 WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
893 // Update x and y (inner loop)
894 //Now it does! But crappy, crappy, crappy! !!! FIX !!! [DONE]
895 //This is less than ideal, but it works...
898 a1_x += a1_xadd, a1_y += a1_yadd;
899 a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
903 a1_y += a1_yadd, a2_y = (a2_y + a2_yadd) & a2_mask_y;
907 if (bitPos % bppSrc == 0)
908 a2_x = (a2_x + a2_xadd) & a2_mask_x;
912 a2_x = (a2_x + a2_xadd) & a2_mask_x;
913 if (bitPos % bppSrc == 0)
919 z_i[colour_index] += zadd;
921 if (GOURD || SRCSHADE)
923 gd_i[colour_index] += gd_ia;
924 //Hmm, this doesn't seem to do anything...
925 //But it is correct according to the JTRM...!
926 if ((int32)gd_i[colour_index] < 0)
927 gd_i[colour_index] = 0;
928 if (gd_i[colour_index] > 0x00FFFFFF)
929 gd_i[colour_index] = 0x00FFFFFF;//*/
931 gd_c[colour_index] += gd_ca;
932 if ((int32)gd_c[colour_index] < 0)
933 gd_c[colour_index] = 0;
934 if (gd_c[colour_index] > 0x000000FF)
935 gd_c[colour_index] = 0x000000FF;//*/
938 if (GOURD || SRCSHADE || GOURZ)
941 //This screws things up WORSE (for the BIOS opening screen)
942 // if (a1_phrase_mode || a2_phrase_mode)
943 colour_index = (colour_index + 1) & 0x03;
948 Here's the problem... The phrase mode code!
949 Blit! (00100000 -> 00148000) count: 327 x 267, A1/2_FLAGS: 00004420/00004420 [cmd: 41802E01]
950 CMD -> src: SRCEN dst: misc: a1ctl: UPDA1 UPDA2 mode: DSTA2 GOURZ ity: z-op: op: LFU_REPLACE ctrl: SRCSHADE
951 A1 step values: -327 (X), 1 (Y)
952 A2 step values: -327 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
953 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
954 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
955 A1 x/y: 28/58, A2 x/y: 28/58 Pattern: 00EA7BEA77EA77EA SRCDATA: 7BFF7BFF7BFF7BFF
957 Below fixes it, but then borks:
960 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
961 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
962 A1 step values: -15 (X), 1 (Y)
963 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
964 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
965 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
966 A1 x/y: 173/144, A2 x/y: 4052/0
968 Lesse, with pre-add we'd have:
971 00001111222233334444555566667777
974 |rolls back to here. Hmm.
977 //NOTE: The way to fix the CD BIOS is to uncomment below and comment the stuff after
978 // the phrase mode mucking around. But it fucks up everything else...
979 //#define SCREWY_CD_DEPENDENT
980 #ifdef SCREWY_CD_DEPENDENT
984 a2_y += a2_step_y;//*/
987 //New: Phrase mode taken into account! :-p
988 /* if (a1_phrase_mode) // v1
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 newx = (a1_x >> 16) / size;
1002 uint32 newxrem = (a1_x >> 16) % size;
1004 a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
1006 if (a1_phrase_mode) // v2
1008 // Bump the pointer to the next phrase boundary
1009 // Even though it works, this is crappy... Clean it up!
1010 uint32 size = 64 / a1_psize;
1012 // Crappy kludge... ('aligning' source to destination)
1013 if (a2_phrase_mode && DSTA2)
1015 uint32 extra = (a2_start >> 16) % size;
1016 a1_x += extra << 16;
1019 uint32 pixelSize = (size - 1) << 16;
1020 a1_x = (a1_x + pixelSize) & ~pixelSize;
1023 /* if (a2_phrase_mode) // v1
1025 // Bump the pointer to the next phrase boundary
1026 // Even though it works, this is crappy... Clean it up!
1027 uint32 size = 64 / a2_psize;
1029 // Crappy kludge... ('aligning' source to destination)
1030 // Prolly should do this for A1 channel as well... [DONE]
1031 if (a1_phrase_mode && !DSTA2)
1033 uint32 extra = (a1_start >> 16) % size;
1034 a2_x += extra << 16;
1037 uint32 newx = (a2_x >> 16) / size;
1038 uint32 newxrem = (a2_x >> 16) % size;
1040 a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
1042 if (a2_phrase_mode) // v1
1044 // Bump the pointer to the next phrase boundary
1045 // Even though it works, this is crappy... Clean it up!
1046 uint32 size = 64 / a2_psize;
1048 // Crappy kludge... ('aligning' source to destination)
1049 // Prolly should do this for A1 channel as well... [DONE]
1050 if (a1_phrase_mode && !DSTA2)
1052 uint32 extra = (a1_start >> 16) % size;
1053 a2_x += extra << 16;
1056 uint32 pixelSize = (size - 1) << 16;
1057 a2_x = (a2_x + pixelSize) & ~pixelSize;
1060 //Not entirely: This still mucks things up... !!! FIX !!!
1061 //Should this go before or after the phrase mode mucking around?
1062 #ifndef SCREWY_CD_DEPENDENT
1066 a2_y += a2_step_y;//*/
1070 // write values back to registers
1071 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
1072 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
1073 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
1077 void blitter_blit(uint32 cmd)
1079 //Apparently this is doing *something*, just not sure exactly what...
1080 /*if (cmd == 0x41802E01)
1082 WriteLog("BLIT: Found our blit. Was: %08X ", cmd);
1084 WriteLog("Is: %08X\n", cmd);
1087 uint32 pitchValue[4] = { 0, 1, 3, 2 };
1090 dst = (cmd >> 3) & 0x07;
1091 misc = (cmd >> 6) & 0x03;
1092 a1ctl = (cmd >> 8) & 0x7;
1093 mode = (cmd >> 11) & 0x07;
1094 ity = (cmd >> 14) & 0x0F;
1095 zop = (cmd >> 18) & 0x07;
1096 op = (cmd >> 21) & 0x0F;
1097 ctrl = (cmd >> 25) & 0x3F;
1099 // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
1100 // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
1101 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1102 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1104 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
1105 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
1107 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
1108 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
1110 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
1111 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
1113 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
1114 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
1116 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1117 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1118 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1119 //But it seems to fuck up T2K! !!! FIX !!!
1120 //Could it be sign extended??? Doesn't seem to be so according to JTRM
1121 // a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
1122 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1123 // a1_y &= 0x0FFFFFFF;
1125 // a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
1126 // According to JTRM, this must give a *whole number* of phrases in the current
1127 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1128 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1129 a1_width = ((0x04 | m) << e) >> 2;//*/
1131 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1132 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1133 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1134 //But it seems to fuck up T2K! !!! FIX !!!
1135 // a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
1136 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1137 // a2_y &= 0x0FFFFFFF;
1139 // a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
1140 // According to JTRM, this must give a *whole number* of phrases in the current
1141 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1142 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1143 a2_width = ((0x04 | m) << e) >> 2;//*/
1144 a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
1145 a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
1147 // Check for "use mask" flag
1148 if (!(REG(A2_FLAGS) & 0x8000))
1150 a2_mask_x = 0xFFFFFFFF; // must be 16.16
1151 a2_mask_y = 0xFFFFFFFF; // must be 16.16
1156 // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
1157 a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
1162 // determine a1_xadd
1163 switch (xadd_a1_control)
1166 // This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
1167 // add phrase offset to X and truncate
1172 // add pixelsize (1) to X
1176 // add zero (for those nice vertical lines)
1180 // add the contents of the increment register
1181 a1_xadd = (REG(A1_INC) << 16) | (REG(A1_FINC) & 0x0000FFFF);
1182 a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
1187 //Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801]
1188 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD
1189 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD
1190 //if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// &&
1191 // uint32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1192 //Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it...
1193 //if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801)
1194 // A1 x/y: 14368/7, A2 x/y: 150/36
1195 //This is it... The problem...
1196 //if ((a1_x >> 16) == 14368) // 14368 = $3820
1197 // return; //Lesse what we got...
1207 // determine a2_xadd
1208 switch (xadd_a2_control)
1211 // add phrase offset to X and truncate
1216 // add pixelsize (1) to X
1220 // add zero (for those nice vertical lines)
1223 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
1225 WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
1226 // add the contents of the increment register
1227 // since there is no register for a2 we just add 1
1228 //Let's do nothing, since it's not listed as a valid bit combo...
1229 // a2_xadd = 1 << 16;
1236 // Modify outer loop steps based on blitter command
1244 a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
1245 a1_step_y = (REG(A1_FSTEP) >> 16);
1248 a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
1249 a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
1252 a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
1253 a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
1255 outer_loop = n_lines;
1260 a1_clip_x = REG(A1_CLIP) & 0x7FFF,
1261 a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
1263 // This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX]
1264 // Err, this is pixel size... (and it's OK)
1265 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
1266 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
1273 for(int v=0; v<4; v++)
1274 z_i[v] = REG(PHRASEZ0 + v*4);
1278 if (GOURD || GOURZ || SRCSHADE)
1280 gd_c[0] = blitter_ram[PATTERNDATA + 6];
1281 gd_i[0] = ((uint32)blitter_ram[PATTERNDATA + 7] << 16)
1282 | ((uint32)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
1284 gd_c[1] = blitter_ram[PATTERNDATA + 4];
1285 gd_i[1] = ((uint32)blitter_ram[PATTERNDATA + 5] << 16)
1286 | ((uint32)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
1288 gd_c[2] = blitter_ram[PATTERNDATA + 2];
1289 gd_i[2] = ((uint32)blitter_ram[PATTERNDATA + 3] << 16)
1290 | ((uint32)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
1292 gd_c[3] = blitter_ram[PATTERNDATA + 0];
1293 gd_i[3] = ((uint32)blitter_ram[PATTERNDATA + 1] << 16)
1294 | ((uint32)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
1296 gouraud_add = REG(INTENSITYINC);
1298 gd_ia = gouraud_add & 0x00FFFFFF;
1299 if (gd_ia & 0x00800000)
1300 gd_ia = 0xFF000000 | gd_ia;
1302 gd_ca = (gouraud_add >> 24) & 0xFF;
1303 if (gd_ca & 0x00000080)
1304 gd_ca = 0xFFFFFF00 | gd_ca;
1307 // Bit comparitor fixing...
1310 // Determine the data flow direction...
1312 a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07));
1316 /* if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!!
1318 // Determine the data flow direction...
1326 WriteLog("Blit!\n");
1327 WriteLog(" cmd = 0x%.8x\n",cmd);
1328 WriteLog(" a1_base = %08X\n", a1_addr);
1329 WriteLog(" a1_pitch = %d\n", a1_pitch);
1330 WriteLog(" a1_psize = %d\n", a1_psize);
1331 WriteLog(" a1_width = %d\n", a1_width);
1332 WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1333 WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0);
1334 WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1335 WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1336 WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0);
1337 WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0);
1338 WriteLog(" a1_zoffs = %i\n",a1_zoffs);
1340 WriteLog(" a2_base = %08X\n", a2_addr);
1341 WriteLog(" a2_pitch = %d\n", a2_pitch);
1342 WriteLog(" a2_psize = %d\n", a2_psize);
1343 WriteLog(" a2_width = %d\n", a2_width);
1344 WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1345 WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0);
1346 WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1347 WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1348 WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0);
1349 WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0);
1350 WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x);
1351 WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y);
1352 WriteLog(" a2_zoffs = %i\n",a2_zoffs);
1354 WriteLog(" count = %d x %d\n", n_pixels, n_lines);
1356 WriteLog(" command = %08X\n", cmd);
1357 WriteLog(" dsten = %i\n",DSTEN);
1358 WriteLog(" srcen = %i\n",SRCEN);
1359 WriteLog(" patdsel = %i\n",PATDSEL);
1360 WriteLog(" color = 0x%.8x\n",REG(PATTERNDATA));
1361 WriteLog(" dcompen = %i\n",DCOMPEN);
1362 WriteLog(" bcompen = %i\n",BCOMPEN);
1363 WriteLog(" cmpdst = %i\n",CMPDST);
1364 WriteLog(" GOURZ = %i\n",GOURZ);
1365 WriteLog(" GOURD = %i\n",GOURD);
1366 WriteLog(" SRCSHADE= %i\n",SRCSHADE);
1370 //NOTE: Pitch is ignored!
1372 //This *might* be the altimeter blits (they are)...
1373 //On captured screen, x-pos for black (inner) is 259, for pink is 257
1374 //Black is short by 3, pink is short by 1...
1376 Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1377 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1378 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1379 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1380 A1 x/y: 262/124, A2 x/y: 128/0
1381 Blit! (00110000 <- 000BF010) count: 5 x 38, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1382 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1383 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1384 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1385 A1 x/y: 264/117, A2 x/y: 407/0
1387 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1388 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1389 A1 step values: -10 (X), 1 (Y)
1390 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1391 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1392 A1 x/y: 262/132, A2 x/y: 129/0
1393 Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1394 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1395 A1 step values: -8 (X), 1 (Y)
1396 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1397 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1398 A1 x/y: 264/128, A2 x/y: 336/0
1400 264v vCursor ends up here...
1404 262v vCursor ends up here...
1408 Fixed! Now for more:
1410 ; This looks like the ship icon in the upper left corner...
1412 Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1413 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1414 A1 step values: -12 (X), 1 (Y)
1415 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1416 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1417 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1418 A1 x/y: 20/24, A2 x/y: 5780/0
1422 More (not sure this is a blitter problem as much as it's a GPU problem):
1423 All but the "M" are trashed...
1424 This does *NOT* look like a blitter problem, as it's rendering properly...
1425 Actually, if you look at the A1 step values, there IS a discrepancy!
1429 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1430 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1431 A1 step values: -14 (X), 1 (Y)
1432 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1433 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1434 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1435 A1 x/y: 134/144, A2 x/y: 2516/0
1440 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1441 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1442 A1 step values: -13 (X), 1 (Y)
1443 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1444 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1445 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1446 A1 x/y: 147/144, A2 x/y: 2660/0
1450 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1451 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1452 A1 step values: -12 (X), 1 (Y)
1453 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1454 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1455 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1456 A1 x/y: 160/144, A2 x/y: 3764/0
1460 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1461 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1462 A1 step values: -15 (X), 1 (Y)
1463 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1464 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1465 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1466 A1 x/y: 173/144, A2 x/y: 4052/0
1469 //extern int op_start_log;
1472 char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
1473 char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
1474 char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1475 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1476 uint32 /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
1477 a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F,
1478 zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/;
1479 uint32 a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1480 uint32 p1 = a1f & 0x07, p2 = a2f & 0x07,
1481 d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
1482 zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
1483 w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
1484 ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
1485 uint32 iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
1486 uint32 iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
1487 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);
1488 // 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);
1490 WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
1491 WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
1492 WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
1493 WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
1494 WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "GOURZ" : ""));
1495 WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : ""));
1496 WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
1497 WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
1498 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" : ""));
1501 WriteLog(" A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16);
1504 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);
1506 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"));
1507 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"));
1508 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));
1509 // blit_start_log = 0;
1510 // op_start_log = 1;
1513 blitter_working = 1;
1514 //#ifndef USE_GENERIC_BLITTER
1515 // if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
1517 blitter_generic(cmd);
1519 /*if (blit_start_log)
1521 if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
1523 WriteLog("\nBytes at 004D58:\n");
1524 for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
1525 WriteLog("%02X ", JaguarReadByte(i));
1526 WriteLog("\nBytes at F03000:\n");
1527 for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
1528 WriteLog("%02X ", JaguarReadByte(i));
1533 blitter_working = 0;
1535 #endif // of the #if 0 near the top...
1536 /*******************************************************************************
1537 ********************** STUFF CUT ABOVE THIS LINE! ******************************
1538 *******************************************************************************/
1540 void BlitterInit(void)
1545 void BlitterReset(void)
1547 memset(blitter_ram, 0x00, 0xA0);
1550 void BlitterDone(void)
1552 WriteLog("BLIT: Done.\n");
1555 uint8 BlitterReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1560 //This isn't cycle accurate--how to fix? !!! FIX !!!
1561 //Probably have to do some multi-threaded implementation or at least a reentrant safe implementation...
1562 //Real hardware returns $00000805, just like the JTRM says.
1563 if (offset == (0x38 + 0))
1565 if (offset == (0x38 + 1))
1567 if (offset == (0x38 + 2))
1569 if (offset == (0x38 + 3))
1570 return 0x05; // always idle/never stopped (collision detection ignored!)
1572 // CHECK HERE ONCE THIS FIX HAS BEEN TESTED: [X]
1574 if (offset >= 0x04 && offset <= 0x07)
1575 //This is it. I wonder if it just ignores the lower three bits?
1576 //No, this is a documented Jaguar I bug. It also bites the read at $F02230 as well...
1577 return blitter_ram[offset + 0x08]; // A1_PIXEL ($F0220C) read at $F02204
1579 if (offset >= 0x2C && offset <= 0x2F)
1580 return blitter_ram[offset + 0x04]; // A2_PIXEL ($F02230) read at $F0222C
1582 return blitter_ram[offset];
1586 uint16 BlitterReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1588 return ((uint16)BlitterReadByte(offset, who) << 8) | (uint16)BlitterReadByte(offset+1, who);
1592 uint32 BlitterReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
1594 return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
1597 void BlitterWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1599 /*if (offset & 0xFF == 0x7B)
1600 WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
1602 /*if ((offset >= PATTERNDATA) && (offset < PATTERNDATA + 8))
1604 printf("--> %s wrote %02X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - PATTERNDATA);
1608 // This handles writes to INTENSITY0-3 by also writing them to their proper places in
1609 // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
1610 if ((offset >= 0x7C) && (offset <= 0x9B))
1614 // INTENSITY registers 0-3
1616 case 0x7D: blitter_ram[PATTERNDATA + 7] = data; break;
1617 case 0x7E: blitter_ram[SRCDATA + 6] = data; break;
1618 case 0x7F: blitter_ram[SRCDATA + 7] = data; break;
1621 case 0x81: blitter_ram[PATTERNDATA + 5] = data; break;
1622 case 0x82: blitter_ram[SRCDATA + 4] = data; break;
1623 case 0x83: blitter_ram[SRCDATA + 5] = data; break;
1626 case 0x85: blitter_ram[PATTERNDATA + 3] = data; break;
1627 case 0x86: blitter_ram[SRCDATA + 2] = data; break;
1628 case 0x87: blitter_ram[SRCDATA + 3] = data; break;
1631 case 0x89: blitter_ram[PATTERNDATA + 1] = data; break;
1632 case 0x8A: blitter_ram[SRCDATA + 0] = data; break;
1633 case 0x8B: blitter_ram[SRCDATA + 1] = data; break;
1637 case 0x8C: blitter_ram[SRCZINT + 6] = data; break;
1638 case 0x8D: blitter_ram[SRCZINT + 7] = data; break;
1639 case 0x8E: blitter_ram[SRCZFRAC + 6] = data; break;
1640 case 0x8F: blitter_ram[SRCZFRAC + 7] = data; break;
1642 case 0x90: blitter_ram[SRCZINT + 4] = data; break;
1643 case 0x91: blitter_ram[SRCZINT + 5] = data; break;
1644 case 0x92: blitter_ram[SRCZFRAC + 4] = data; break;
1645 case 0x93: blitter_ram[SRCZFRAC + 5] = data; break;
1647 case 0x94: blitter_ram[SRCZINT + 2] = data; break;
1648 case 0x95: blitter_ram[SRCZINT + 3] = data; break;
1649 case 0x96: blitter_ram[SRCZFRAC + 2] = data; break;
1650 case 0x97: blitter_ram[SRCZFRAC + 3] = data; break;
1652 case 0x98: blitter_ram[SRCZINT + 0] = data; break;
1653 case 0x99: blitter_ram[SRCZINT + 1] = data; break;
1654 case 0x9A: blitter_ram[SRCZFRAC + 0] = data; break;
1655 case 0x9B: blitter_ram[SRCZFRAC + 1] = data; break;
1659 // It looks weird, but this is how the 64 bit registers are actually handled...!
1661 else if ((offset >= SRCDATA + 0) && (offset <= SRCDATA + 3)
1662 || (offset >= DSTDATA + 0) && (offset <= DSTDATA + 3)
1663 || (offset >= DSTZ + 0) && (offset <= DSTZ + 3)
1664 || (offset >= SRCZINT + 0) && (offset <= SRCZINT + 3)
1665 || (offset >= SRCZFRAC + 0) && (offset <= SRCZFRAC + 3)
1666 || (offset >= PATTERNDATA + 0) && (offset <= PATTERNDATA + 3))
1668 blitter_ram[offset + 4] = data;
1670 else if ((offset >= SRCDATA + 4) && (offset <= SRCDATA + 7)
1671 || (offset >= DSTDATA + 4) && (offset <= DSTDATA + 7)
1672 || (offset >= DSTZ + 4) && (offset <= DSTZ + 7)
1673 || (offset >= SRCZINT + 4) && (offset <= SRCZINT + 7)
1674 || (offset >= SRCZFRAC + 4) && (offset <= SRCZFRAC + 7)
1675 || (offset >= PATTERNDATA + 4) && (offset <= PATTERNDATA + 7))
1677 blitter_ram[offset - 4] = data;
1680 blitter_ram[offset] = data;
1683 void BlitterWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1685 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1687 printf("----> %s wrote %04X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1691 /* if (offset & 0xFF == A1_PIXEL && data == 14368)
1693 WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1694 extern bool doGPUDis;
1697 if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368)
1699 WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1700 extern bool doGPUDis;
1705 BlitterWriteByte(offset + 0, data >> 8, who);
1706 BlitterWriteByte(offset + 1, data & 0xFF, who);
1708 if ((offset & 0xFF) == 0x3A)
1709 // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
1710 // But then again, according to the Jaguar docs, this is correct...!
1711 /*extern int blit_start_log;
1712 extern bool doGPUDis;
1715 WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
1718 #ifdef USE_ORIGINAL_BLITTER
1719 blitter_blit(GET32(blitter_ram, 0x38));
1721 #ifdef USE_MIDSUMMER_BLITTER
1722 BlitterMidsummer(GET32(blitter_ram, 0x38));
1724 #ifdef USE_MIDSUMMER_BLITTER_MKII
1725 BlitterMidsummer2();
1730 void BlitterWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
1732 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1734 printf("------> %s wrote %08X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1738 /* if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368)
1740 WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1741 extern bool doGPUDis;
1746 BlitterWriteWord(offset + 0, data >> 16, who);
1747 BlitterWriteWord(offset + 2, data & 0xFFFF, who);
1752 const char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1753 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1754 uint32 cmd = GET32(blitter_ram, 0x38);
1755 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1756 uint32 a1_width = ((0x04 | m) << e) >> 2;
1757 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1758 uint32 a2_width = ((0x04 | m) << e) >> 2;
1760 WriteLog("Blit!\n");
1761 WriteLog(" COMMAND = %08X\n", cmd);
1762 WriteLog(" a1_base = %08X\n", REG(A1_BASE));
1763 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),
1764 (REG(A1_FLAGS) & 0x100000 ? '1' : '0'),
1765 (REG(A1_FLAGS) & 0x080000 ? '1' : '0'),
1766 (REG(A1_FLAGS) & 0x040000 ? '1' : '0'),
1767 (REG(A1_FLAGS) & 0x020000 ? '1' : '0'),
1768 (REG(A1_FLAGS) & 0x010000 ? '1' : '0'),
1769 (REG(A1_FLAGS) & 0x004000 ? '1' : '0'),
1770 (REG(A1_FLAGS) & 0x002000 ? '1' : '0'),
1771 (REG(A1_FLAGS) & 0x001000 ? '1' : '0'),
1772 (REG(A1_FLAGS) & 0x000800 ? '1' : '0'),
1773 (REG(A1_FLAGS) & 0x000400 ? '1' : '0'),
1774 (REG(A1_FLAGS) & 0x000200 ? '1' : '0'),
1775 (REG(A1_FLAGS) & 0x000100 ? '1' : '0'),
1776 (REG(A1_FLAGS) & 0x000080 ? '1' : '0'),
1777 (REG(A1_FLAGS) & 0x000040 ? '1' : '0'),
1778 (REG(A1_FLAGS) & 0x000020 ? '1' : '0'),
1779 (REG(A1_FLAGS) & 0x000010 ? '1' : '0'),
1780 (REG(A1_FLAGS) & 0x000008 ? '1' : '0'),
1781 (REG(A1_FLAGS) & 0x000002 ? '1' : '0'),
1782 (REG(A1_FLAGS) & 0x000001 ? '1' : '0'));
1783 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1784 REG(A1_FLAGS) & 0x00003, (REG(A1_FLAGS) & 0x00038) >> 3,
1785 (REG(A1_FLAGS) & 0x001C0) >> 6, a1_width, (REG(A1_FLAGS) & 0x30000) >> 16);
1786 WriteLog(" a1_clip = %u, %u (%08X)\n", GET16(blitter_ram, A1_CLIP + 2), GET16(blitter_ram, A1_CLIP + 0), GET32(blitter_ram, A1_CLIP));
1787 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));
1788 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));
1789 WriteLog(" a1_fstep = %u, %u (%08X)\n", GET16(blitter_ram, A1_FSTEP + 2), GET16(blitter_ram, A1_FSTEP + 0), GET32(blitter_ram, A1_FSTEP));
1790 WriteLog(" a1_fpixel= %u, %u (%08X)\n", GET16(blitter_ram, A1_FPIXEL + 2), GET16(blitter_ram, A1_FPIXEL + 0), GET32(blitter_ram, A1_FPIXEL));
1791 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));
1792 WriteLog(" a1_finc = %u, %u (%08X)\n", GET16(blitter_ram, A1_FINC + 2), GET16(blitter_ram, A1_FINC + 0), GET32(blitter_ram, A1_FINC));
1794 WriteLog(" a2_base = %08X\n", REG(A2_BASE));
1795 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),
1796 (REG(A2_FLAGS) & 0x100000 ? '1' : '0'),
1797 (REG(A2_FLAGS) & 0x080000 ? '1' : '0'),
1798 (REG(A2_FLAGS) & 0x040000 ? '1' : '0'),
1799 (REG(A2_FLAGS) & 0x020000 ? '1' : '0'),
1800 (REG(A2_FLAGS) & 0x010000 ? '1' : '0'),
1801 (REG(A2_FLAGS) & 0x008000 ? '1' : '0'),
1802 (REG(A2_FLAGS) & 0x004000 ? '1' : '0'),
1803 (REG(A2_FLAGS) & 0x002000 ? '1' : '0'),
1804 (REG(A2_FLAGS) & 0x001000 ? '1' : '0'),
1805 (REG(A2_FLAGS) & 0x000800 ? '1' : '0'),
1806 (REG(A2_FLAGS) & 0x000400 ? '1' : '0'),
1807 (REG(A2_FLAGS) & 0x000200 ? '1' : '0'),
1808 (REG(A2_FLAGS) & 0x000100 ? '1' : '0'),
1809 (REG(A2_FLAGS) & 0x000080 ? '1' : '0'),
1810 (REG(A2_FLAGS) & 0x000040 ? '1' : '0'),
1811 (REG(A2_FLAGS) & 0x000020 ? '1' : '0'),
1812 (REG(A2_FLAGS) & 0x000010 ? '1' : '0'),
1813 (REG(A2_FLAGS) & 0x000008 ? '1' : '0'),
1814 (REG(A2_FLAGS) & 0x000002 ? '1' : '0'),
1815 (REG(A2_FLAGS) & 0x000001 ? '1' : '0'));
1816 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1817 REG(A2_FLAGS) & 0x00003, (REG(A2_FLAGS) & 0x00038) >> 3,
1818 (REG(A2_FLAGS) & 0x001C0) >> 6, a2_width, (REG(A2_FLAGS) & 0x30000) >> 16);
1819 WriteLog(" a2_mask = %u, %u (%08X)\n", GET16(blitter_ram, A2_MASK + 2), GET16(blitter_ram, A2_MASK + 0), GET32(blitter_ram, A2_MASK));
1820 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));
1821 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));
1823 WriteLog(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
1825 WriteLog(" SRCEN = %s\n", (SRCEN ? "1" : "0"));
1826 WriteLog(" SRCENZ = %s\n", (SRCENZ ? "1" : "0"));
1827 WriteLog(" SRCENX = %s\n", (SRCENX ? "1" : "0"));
1828 WriteLog(" DSTEN = %s\n", (DSTEN ? "1" : "0"));
1829 WriteLog(" DSTENZ = %s\n", (DSTENZ ? "1" : "0"));
1830 WriteLog(" DSTWRZ = %s\n", (DSTWRZ ? "1" : "0"));
1831 WriteLog(" CLIPA1 = %s\n", (CLIPA1 ? "1" : "0"));
1832 WriteLog(" UPDA1F = %s\n", (UPDA1F ? "1" : "0"));
1833 WriteLog(" UPDA1 = %s\n", (UPDA1 ? "1" : "0"));
1834 WriteLog(" UPDA2 = %s\n", (UPDA2 ? "1" : "0"));
1835 WriteLog(" DSTA2 = %s\n", (DSTA2 ? "1" : "0"));
1836 WriteLog(" ZOP = %s %s %s\n", (Z_OP_INF ? "<" : ""), (Z_OP_EQU ? "=" : ""), (Z_OP_SUP ? ">" : ""));
1837 WriteLog("+-LFUFUNC = %s\n", opStr[(cmd >> 21) & 0x0F]);
1838 WriteLog("| PATDSEL = %s (PD=%08X%08X)\n", (PATDSEL ? "1" : "0"), REG(PATTERNDATA), REG(PATTERNDATA + 4));
1839 WriteLog("+-ADDDSEL = %s\n", (ADDDSEL ? "1" : "0"));
1840 WriteLog(" CMPDST = %s\n", (CMPDST ? "1" : "0"));
1841 WriteLog(" BCOMPEN = %s\n", (BCOMPEN ? "1" : "0"));
1842 WriteLog(" DCOMPEN = %s\n", (DCOMPEN ? "1" : "0"));
1843 WriteLog(" TOPBEN = %s\n", (TOPBEN ? "1" : "0"));
1844 WriteLog(" TOPNEN = %s\n", (TOPNEN ? "1" : "0"));
1845 WriteLog(" BKGWREN = %s\n", (BKGWREN ? "1" : "0"));
1846 WriteLog(" GOURD = %s (II=%08X, SD=%08X%08X)\n", (GOURD ? "1" : "0"), REG(INTENSITYINC), REG(SRCDATA), REG(SRCDATA + 4));
1847 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),
1848 REG(SRCZINT), REG(SRCZINT + 4), REG(SRCZFRAC), REG(SRCZFRAC + 4));
1849 WriteLog(" SRCSHADE = %s\n", (SRCSHADE ? "1" : "0"));
1853 #ifdef USE_MIDSUMMER_BLITTER
1855 // Here's an attempt to write a blitter that conforms to the Midsummer specs--since
1856 // it's supposedly backwards compatible, it should work well...
1858 //#define LOG_BLITTER_MEMORY_ACCESSES
1860 #define DATINIT (false)
1861 #define TXTEXT (false)
1862 #define POLYGON (false)
1864 void BlitterMidsummer(uint32 cmd)
1869 uint32 outer_loop, inner_loop, a1_addr, a2_addr;
1870 int32 a1_x, a1_y, a2_x, a2_y, a1_width, a2_width;
1871 uint8 a1_phrase_mode, a2_phrase_mode;
1873 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1874 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1875 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1876 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1877 uint32 m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1878 a1_width = ((0x04 | m) << e) >> 2;//*/
1879 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1880 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1881 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1882 a2_width = ((0x04 | m) << e) >> 2;//*/
1884 a1_phrase_mode = a2_phrase_mode = 0;
1886 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
1889 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
1892 #define INNER0 (inner_loop == 0)
1893 #define OUTER0 (outer_loop == 0)
1895 // $01800005 has SRCENX, may have to investigate further...
1896 // $00011008 has GOURD & DSTEN.
1897 // $41802F41 has SRCSHADE, CLIPA1
1898 /*bool logBlit = false;
1899 if (cmd != 0x00010200 && cmd != 0x01800001 && cmd != 0x01800005
1900 && cmd != 0x00011008 && cmd !=0x41802F41)
1906 uint64 srcData = GET64(blitter_ram, SRCDATA), srcXtraData,
1907 dstData = GET64(blitter_ram, DSTDATA), writeData;
1908 uint32 srcAddr, dstAddr;
1909 uint8 bitCount, a1PixelSize, a2PixelSize;
1911 // JTRM says phrase mode only works for 8BPP or higher, so let's try this...
1912 uint32 phraseOffset[8] = { 8, 8, 8, 8, 4, 2, 0, 0 };
1913 uint8 pixelShift[8] = { 3, 2, 1, 0, 1, 2, 0, 0 };
1915 a1PixelSize = (blitter_ram[A1_FLAGS + 3] >> 3) & 0x07;
1916 a2PixelSize = (blitter_ram[A2_FLAGS + 3] >> 3) & 0x07;
1918 outer_loop = GET16(blitter_ram, PIXLINECOUNTER + 0);
1920 if (outer_loop == 0)
1921 outer_loop = 0x10000;
1923 // We just list the states here and jump from state to state in order to
1924 // keep things somewhat clear. Optimization/cleanups later.
1926 //idle: // Blitter is idle, and will not perform any bus activity
1928 idle Blitter is off the bus, and no activity takes place.
1929 if GO if DATINIT goto init_if
1938 inner Inner loop is active, read and write cycles are performed
1940 inner: // Run inner loop state machine (asserts step from its idle state)
1941 inner_loop = GET16(blitter_ram, PIXLINECOUNTER + 2);
1943 if (inner_loop == 0)
1944 inner_loop = 0x10000;
1947 ------------------------------
1948 idle: Inactive, blitter is idle or passing round outer loop
1949 idle Another state in the outer loop is active. No bus transfers are performed.
1951 if SRCENX goto sreadx
1952 else if TXTEXT goto txtread
1953 else if SRCEN goto sread
1954 else if DSTEN goto dread
1955 else if DSTENZ goto dzread
1972 sreadx Extra source data read at the start of an inner loop pass.
1974 if SRCENZ goto szreadx
1975 else if TXTEXT goto txtread
1976 else if SRCEN goto sread
1977 else if DSTEN goto dread
1978 else if DSTENZ goto dzread
1981 sreadx: // Extra source data read
1996 szreadx Extra source Z read as the start of an inner loop pass.
1998 if TXTEXT goto txtread
2001 szreadx: // Extra source Z read
2008 txtread Read texture data from external memory. This state is only used for external texture.
2009 TEXTEXT is the condition TEXTMODE=1.
2012 else if DSTEN goto dread
2013 else if DSTENZ goto dzread
2016 txtread: // Read external texture data
2027 sread Source data read.
2029 if SRCENZ goto szread
2030 else if DSTEN goto dread
2031 else if DSTENZ goto dzread
2034 sread: // Source data read
2035 //The JTRM doesn't really specify the internal structure of the source data read, but I would
2036 //imagine that if it's in phrase mode that it starts by reading the phrase that the window is
2037 //pointing at. Likewise, the pixel (if in BPP 1, 2 & 4, chopped) otherwise. It probably still
2038 //transfers an entire phrase even in pixel mode.
2039 //Odd thought: Does it expand, e.g., 1 BPP pixels into 32 BPP internally? Hmm...
2042 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
2043 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
2044 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
2045 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
2046 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
2047 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
2048 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
2049 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
2050 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
2051 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
2052 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
2053 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
2054 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
2055 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
2058 a1_width = ((0x04 | m) << e) >> 2;
2059 a2_width = ((0x04 | m) << e) >> 2;
2061 // write values back to registers
2062 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
2063 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
2064 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
2066 // Calculate the address to be read...
2068 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2069 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2070 //for 8BPP. !!! FIX !!!
2071 srcAddr = (DSTA2 ? a1_addr : a2_addr);
2073 /* if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2075 srcAddr += (((DSTA2 ? a1_x : a2_x) >> 16)
2076 + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width)));
2080 // uint32 pixAddr = ((DSTA2 ? a1_x : a2_x) >> 16)
2081 // + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2082 int32 pixAddr = (int16)((DSTA2 ? a1_x : a2_x) >> 16)
2083 + ((int16)((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2085 if ((DSTA2 ? a1PixelSize : a2PixelSize) < 3)
2086 pixAddr >>= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2087 else if ((DSTA2 ? a1PixelSize : a2PixelSize) > 3)
2088 pixAddr <<= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2095 if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2097 srcData = ((uint64)JaguarReadLong(srcAddr, BLITTER) << 32)
2098 | (uint64)JaguarReadLong(srcAddr + 4, BLITTER);
2102 //1,2,&4BPP are wrong here... !!! FIX !!!
2103 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 0) // 1 BPP
2104 srcData = JaguarReadByte(srcAddr, BLITTER);
2105 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 1) // 2 BPP
2106 srcData = JaguarReadByte(srcAddr, BLITTER);
2107 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 2) // 4 BPP
2108 srcData = JaguarReadByte(srcAddr, BLITTER);
2109 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 3) // 8 BPP
2110 srcData = JaguarReadByte(srcAddr, BLITTER);
2111 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 4) // 16 BPP
2112 srcData = JaguarReadWord(srcAddr, BLITTER);
2113 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 5) // 32 BPP
2114 srcData = JaguarReadLong(srcAddr, BLITTER);
2117 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2119 WriteLog("BLITTER: srcAddr=%08X, srcData=%08X %08X\n", srcAddr, (uint32)(srcData >> 32), (uint32)(srcData & 0xFFFFFFFF));
2131 szread: // Source Z read
2133 szread Source Z read.
2136 else if DSTENZ goto dzread
2146 dread: // Destination data read
2148 dread Destination data read.
2150 if DSTENZ goto dzread
2153 // Calculate the destination address to be read...
2155 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2156 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2157 //for 8BPP. !!! FIX !!!
2158 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2161 // uint32 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2162 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2163 int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
2164 + ((int16)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2166 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2167 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2168 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2169 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2176 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2178 dstData = ((uint64)JaguarReadLong(srcAddr, BLITTER) << 32)
2179 | (uint64)JaguarReadLong(srcAddr + 4, BLITTER);
2183 //1,2,&4BPP are wrong here... !!! FIX !!!
2184 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2185 dstData = JaguarReadByte(dstAddr, BLITTER);
2186 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2187 dstData = JaguarReadByte(dstAddr, BLITTER);
2188 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2189 dstData = JaguarReadByte(dstAddr, BLITTER);
2190 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2191 dstData = JaguarReadByte(dstAddr, BLITTER);
2192 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2193 dstData = JaguarReadWord(dstAddr, BLITTER);
2194 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2195 dstData = JaguarReadLong(dstAddr, BLITTER);
2198 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2200 WriteLog("BLITTER (dread): dstAddr=%08X, dstData=%08X %08X\n", dstAddr, (uint32)(dstData >> 32), (uint32)(dstData & 0xFFFFFFFF));
2208 dzread: // Destination Z read
2210 dzread Destination Z read.
2215 dwrite: // Destination data write
2217 dwrite Destination write. Every pass round the inner loop must go through this state..
2219 if DSTWRZ goto dzwrite
2220 else if INNER0 goto idle
2221 else if TXTEXT goto txtread
2222 else if SRCEN goto sread
2223 else if DSTEN goto dread
2224 else if DSTENZ goto dzread
2233 a1_xadd = 1.000000 (phrase=0)
2242 a2_xadd = 1.000000 (phrase=1)
2246 a2_mask_x= 0xFFFFFFFF
2247 a2_mask_y= 0xFFFFFFFF
2257 --LFUFUNC = LFU_CLEAR
2258 | PATDSEL = 1 (PD=77C7 7700 7700 7700)
2260 GOURD = 1 (II=00FC 1A00, SD=FF00 0000 0000 0000)
2263 //Still need to do CLIPA1 and SRCSHADE and GOURD and GOURZ...
2265 // Check clipping...
2269 uint16 x = a1_x >> 16, y = a1_y >> 16;
2271 if (x >= GET16(blitter_ram, A1_CLIP + 2) || y >= GET16(blitter_ram, A1_CLIP))
2275 // Figure out what gets written...
2279 writeData = GET64(blitter_ram, PATTERNDATA);
2280 //GOURD works properly only in 16BPP mode...
2281 //SRCDATA holds the intensity fractions...
2282 //Does GOURD get calc'ed here or somewhere else???
2283 //Temporary testing kludge...
2285 // writeData >>= 48;
2286 // writeData = 0xFF88;
2287 //OK, it's not writing an entire strip of pixels... Why?
2288 //bad incrementing, that's why!
2292 // Apparently this only works with 16-bit pixels. Not sure if it works in phrase mode either.
2293 //Also, take TOPBEN & TOPNEN into account here as well...
2294 writeData = srcData + dstData;
2296 else // LFUFUNC is the default...
2301 writeData |= ~srcData & ~dstData;
2303 writeData |= ~srcData & dstData;
2305 writeData |= srcData & ~dstData;
2307 writeData |= srcData & dstData;
2310 // Calculate the address to be written...
2312 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2314 /* if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2316 //both of these calculate the wrong address because they don't take into account
2318 dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2319 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2323 /* dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2324 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));*/
2325 // uint32 pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2326 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2327 int32 pixAddr = (int16)((DSTA2 ? a2_x : a1_x) >> 16)
2328 + ((int16)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2330 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2331 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2332 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2333 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2340 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2342 JaguarWriteLong(dstAddr, writeData >> 32, BLITTER);
2343 JaguarWriteLong(dstAddr + 4, writeData & 0xFFFFFFFF, BLITTER);
2347 //1,2,&4BPP are wrong here... !!! FIX !!!
2348 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2349 JaguarWriteByte(dstAddr, writeData, BLITTER);
2350 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2351 JaguarWriteByte(dstAddr, writeData, BLITTER);
2352 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2353 JaguarWriteByte(dstAddr, writeData, BLITTER);
2354 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2355 JaguarWriteByte(dstAddr, writeData, BLITTER);
2356 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2357 JaguarWriteWord(dstAddr, writeData, BLITTER);
2358 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2359 JaguarWriteLong(dstAddr, writeData, BLITTER);
2362 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2364 WriteLog("BLITTER: dstAddr=%08X, writeData=%08X %08X\n", dstAddr, (uint32)(writeData >> 32), (uint32)(writeData & 0xFFFFFFFF));
2367 inhibitWrite://Should this go here? or on the other side of the X/Y incrementing?
2368 //Seems OK here... for now.
2370 // Do funky X/Y incrementation here as well... !!! FIX !!!
2372 // Handle A1 channel stepping
2374 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
2375 a1_x += phraseOffset[a1PixelSize] << 16;
2376 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 1)
2377 a1_x += (blitter_ram[A1_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2378 /* else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 2)
2380 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 3)
2382 //Always add the FINC here??? That was the problem with the BIOS screen... So perhaps.
2383 a1_x += GET16(blitter_ram, A1_FINC + 2);
2384 a1_y += GET16(blitter_ram, A1_FINC + 0);
2386 a1_x += GET16(blitter_ram, A1_INC + 2) << 16;
2387 a1_y += GET16(blitter_ram, A1_INC + 0) << 16;
2390 if ((blitter_ram[A1_FLAGS + 1] & 0x04) && (blitter_ram[A1_FLAGS + 1] & 0x03 != 3))
2391 a1_y += (blitter_ram[A1_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2393 // Handle A2 channel stepping
2395 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
2396 a2_x += phraseOffset[a2PixelSize] << 16;
2397 else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 1)
2398 a2_x += (blitter_ram[A2_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2399 /* else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 2)
2402 if (blitter_ram[A2_FLAGS + 1] & 0x04)
2403 a2_y += (blitter_ram[A2_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2405 //Need to fix this so that it subtracts (saturating, of course) the correct number of pixels
2406 //in phrase mode... !!! FIX !!! [DONE]
2407 //Need to fix this so that it counts down the correct item. Does it count the
2408 //source or the destination phrase mode???
2409 //It shouldn't matter, because we *should* end up processing the same amount
2410 //the same number of pixels... Not sure though.
2411 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2413 if (inner_loop < phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize])
2416 inner_loop -= phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize];
2437 dzwrite: // Destination Z write
2439 dzwrite Destination Z write.
2442 else if TXTEXT goto txtread
2443 else if SRCEN goto sread
2444 else if DSTEN goto dread
2445 else if DSTENZ goto dzread
2462 ------------------------------
2463 if INDONE if OUTER0 goto idle
2464 else if UPDA1F goto a1fupdate
2465 else if UPDA1 goto a1update
2466 else if GOURZ.POLYGON goto zfupdate
2467 else if UPDA2 goto a2update
2468 else if DATINIT goto init_if
2481 //kill this, for now...
2482 // else if (GOURZ.POLYGON)
2491 a1fupdate: // Update A1 pointer fractions and more (see below)
2493 a1fupdate A1 step fraction is added to A1 pointer fraction
2494 POLYGON true: A1 step delta X and Y fraction parts are added to the A1
2495 step X and Y fraction parts (the value prior to this add is used for
2496 the step to pointer add).
2497 POLYGON true: inner count step fraction is added to the inner count
2499 POLYGON.GOURD true: the I fraction step is added to the computed
2500 intensity fraction parts +
2501 POLYGON.GOURD true: the I fraction step delta is added to the I
2506 #define A1_PIXEL ((uint32)0x0C) // Integer part of the pixel (Y.i and X.i)
2507 #define A1_STEP ((uint32)0x10) // Integer part of the step
2508 #define A1_FSTEP ((uint32)0x14) // Fractional part of the step
2509 #define A1_FPIXEL ((uint32)0x18) // Fractional part of the pixel (Y.f and X.f)
2512 // This is all kinda murky. All we have are the Midsummer docs to give us any guidance,
2513 // and it's incomplete or filled with errors (like above). Aarrrgggghhhhh!
2515 //This isn't right. Is it? I don't think the fractional parts are signed...
2516 // a1_x += (int32)((int16)GET16(blitter_ram, A1_FSTEP + 2));
2517 // a1_y += (int32)((int16)GET16(blitter_ram, A1_FSTEP + 0));
2518 a1_x += GET16(blitter_ram, A1_FSTEP + 2);
2519 a1_y += GET16(blitter_ram, A1_FSTEP + 0);
2523 a1update: // Update A1 pointer integers
2525 a1update A1 step is added to A1 pointer, with carry from the fractional add
2526 POLYGON true: A1 step delta X and Y integer parts are added to the A1
2527 step X and Y integer parts, with carry from the corresponding
2528 fractional part add (again, the value prior to this add is used for
2529 the step to pointer add).
2530 POLYGON true: inner count step is added to the inner count, with carry
2531 POLYGON.GOURD true: the I step is added to the computed intensities,
2533 POLYGON.GOURD true: the I step delta is added to the I step, with
2534 carry the texture X and Y step delta values are added to the X and Y
2536 if GOURZ.POLYGON goto zfupdate
2537 else if UPDA2 goto a2update
2538 else if DATINIT goto init_if
2541 a1_x += (int32)(GET16(blitter_ram, A1_STEP + 2) << 16);
2542 a1_y += (int32)(GET16(blitter_ram, A1_STEP + 0) << 16);
2545 //kill this, for now...
2546 // if (GOURZ.POLYGON)
2556 zfupdate: // Update computed Z step fractions
2558 zfupdate the Z fraction step is added to the computed Z fraction parts +
2559 the Z fraction step delta is added to the Z fraction step
2564 zupdate: // Update computed Z step integers
2566 zupdate the Z step is added to the computed Zs, with carry +
2567 the Z step delta is added to the Z step, with carry
2568 if UPDA2 goto a2update
2569 else if DATINIT goto init_if
2579 a2update: // Update A2 pointer
2581 a2update A2 step is added to the A2 pointer
2582 if DATINIT goto init_if
2585 a2_x += (int32)(GET16(blitter_ram, A2_STEP + 2) << 16);
2586 a2_y += (int32)(GET16(blitter_ram, A2_STEP + 0) << 16);
2594 init_if: // Initialise intensity fractions and texture X
2596 init_if Initialise the fractional part of the computed intensity fields, from
2597 the increment and step registers. The texture X integer and fractional
2598 parts can also be initialised.
2603 init_ii: // Initialise intensity integers and texture Y
2605 init_ii Initialise the integer part of the computed intensity, and texture Y
2606 integer and fractional parts
2607 if GOURZ goto init_zf
2615 init_zf: // Initialise Z fractions
2617 init_zf Initialise the fractional part of the computed Z fields.
2622 init_zi: // Initialise Z integers
2624 init_zi Initialise the integer part of the computed Z fields.
2631 The outer loop state machine fires off the inner loop, and controls the updating
2632 process between passes through the inner loop.
2634 + -- these functions are irrelevant if the DATINIT function is enabled, which it
2637 All these states will complete in one clock cycle, with the exception of the idle
2638 state, which means the blitter is quiescent; and the inner state, which takes as
2639 long as is required to complete one strip of pixels. It is therefore possible for
2640 the blitter to spend a maximum of nine clock cycles of inactivity between passes
2641 through the inner loop.
2651 // Here's attempt #2--taken from the Oberon chip specs!
2654 #ifdef USE_MIDSUMMER_BLITTER_MKII
2656 void ADDRGEN(uint32 &, uint32 &, bool, bool,
2657 uint16, uint16, uint32, uint8, uint8, uint8, uint8,
2658 uint16, uint16, uint32, uint8, uint8, uint8, uint8);
2659 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
2660 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
2661 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
2662 uint32 zinc, uint32 zstep);
2663 void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh);
2664 void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
2665 int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
2666 int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
2667 bool adda_yconst, bool addareg, bool suba_x, bool suba_y);
2668 void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
2669 int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y);
2670 void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel);
2671 void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
2672 uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y);
2673 void DATA(uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
2674 bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
2675 uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 &patd, bool patdadd,
2676 bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
2677 bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize,
2678 uint64 &srcz, uint64 dstz, uint32 zinc);
2679 void COMP_CTRL(uint8 &dbinh, bool &nowrite,
2680 bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
2681 uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp);
2682 #define VERBOSE_BLITTER_LOGGING
2683 bool logBlit = false;
2685 void BlitterMidsummer2(void)
2690 // Here's what the specs say the state machine does. Note that this can probably be
2691 // greatly simplified (also, it's different from what John has in his Oberon docs):
2692 //Will remove stuff that isn't in Jaguar I once fully described (stuff like texture won't
2693 //be described here at all)...
2695 uint32 cmd = GET32(blitter_ram, COMMAND);
2699 cmd != 0x00010200 && // PATDSEL
2700 cmd != 0x01800001 // SRCEN LFUFUNC=C
2701 && cmd != 0x01800005
2702 //Boot ROM ATARI letters:
2703 && cmd != 0x00011008 // DSTEN GOURD PATDSEL
2704 //Boot ROM spinning cube:
2705 && cmd != 0x41802F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
2707 && cmd != 0x01800E01 // SRCEN UPDA1 UPDA2 DSTA2 LFUFUNC=C
2708 //T2K TEMPEST letters:
2709 && cmd != 0x09800741 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 LFUFUNC=C DCOMPEN
2710 //Static letters on Cybermorph intro screen:
2711 && cmd != 0x09800609 // SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
2712 //Static pic on title screen:
2713 && cmd != 0x01800601 // SRCEN UPDA1 UPDA2 LFUFUNC=C
2714 //Turning letters on Cybermorph intro screen:
2715 // && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2716 && cmd != 0x00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
2717 && cmd != 0x09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
2718 && cmd != 0x09800209 // SRCEN DSTEN UPDA1 LFUFUNC=C DCOMPEN
2719 && cmd != 0x00011200 // UPDA1 GOURD PATDSEL
2720 //Start of Hover Strike (clearing screen):
2721 && cmd != 0x00010000 // PATDSEL
2722 //Hover Strike text:
2723 && cmd != 0x1401060C // SRCENX DSTEN UPDA1 UPDA2 PATDSEL BCOMPEN BKGWREN
2724 //Hover Strike 3D stuff
2725 && cmd != 0x01902839 // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2726 //Hover Strike darkening on intro to play (briefing) screen
2727 && cmd != 0x00020208 // DSTEN UPDA1 ADDDSEL
2728 //Trevor McFur stuff:
2729 && cmd != 0x05810601 // SRCEN UPDA1 UPDA2 PATDSEL BCOMPEN
2730 && cmd != 0x01800201 // SRCEN UPDA1 LFUFUNC=C
2732 && cmd != 0x00011000 // GOURD PATDSEL
2733 && cmd != 0x00011040 // CLIP_A1 GOURD PATDSEL
2735 && cmd != 0x01800000 // LFUFUNC=C
2736 && cmd != 0x01800401 //
2737 && cmd != 0x01800040 //
2738 && cmd != 0x00020008 //
2739 // && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2743 if (blit_start_log == 0) // Wait for the signal...
2744 logBlit = false;//*/
2746 Some T2K unique blits:
2747 logBlit = F, cmd = 00010200 *
2748 logBlit = F, cmd = 00011000
2749 logBlit = F, cmd = 00011040
2750 logBlit = F, cmd = 01800005 *
2751 logBlit = F, cmd = 09800741 *
2753 Hover Strike mission selection screen:
2754 Blit! (CMD = 01902839) // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2756 Checkered Flag blits in the screw up zone:
2757 Blit! (CMD = 01800001) // SRCEN LFUFUNC=C
2758 Blit! (CMD = 01800000) // LFUFUNC=C
2759 Blit! (CMD = 00010000) // PATDSEL
2761 Wolfenstein 3D in the fuckup zone:
2762 Blit! (CMD = 01800000) // LFUFUNC=C
2765 //printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2770 Blit! (CMD = 00011040)
2771 Flags: CLIP_A1 GOURD PATDSEL
2773 a1_base = 00100000, a2_base = 0081F6A8
2774 a1_x = 00A7, a1_y = 0014, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0001, a2_y = 0000
2775 a1_step_x = FE80, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFF8, a2_step_y = 0001
2776 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
2777 a1_win_x = 0180, a1_win_y = 0118, a2_mask_x = 0000, a2_mask_y = 0000
2778 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
2779 a1_pixsize = 4, a2_pixsize = 4
2783 if (cmd == 0x00011040
2784 && (GET16(blitter_ram, A1_PIXEL + 2) == 0x00A7) && (GET16(blitter_ram, A1_PIXEL + 0) == 0x0014)
2785 && (GET16(blitter_ram, A2_PIXEL + 2) == 0x0001) && (GET16(blitter_ram, A2_PIXEL + 0) == 0x0000)
2786 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 18))
2789 // Line states passed in via the command register
2791 bool srcen = (SRCEN), srcenx = (SRCENX), srcenz = (SRCENZ),
2792 dsten = (DSTEN), dstenz = (DSTENZ), dstwrz = (DSTWRZ), clip_a1 = (CLIPA1),
2793 upda1 = (UPDA1), upda1f = (UPDA1F), upda2 = (UPDA2), dsta2 = (DSTA2),
2794 gourd = (GOURD), gourz = (GOURZ), topben = (TOPBEN), topnen = (TOPNEN),
2795 patdsel = (PATDSEL), adddsel = (ADDDSEL), cmpdst = (CMPDST), bcompen = (BCOMPEN),
2796 dcompen = (DCOMPEN), bkgwren = (BKGWREN), srcshade = (SRCSHADE);
2798 uint8 zmode = (cmd & 0x01C0000) >> 18, lfufunc = (cmd & 0x1E00000) >> 21;
2800 //Where to find various lines:
2802 // gourd -> dcontrol, inner, outer, state
2803 // gourz -> dcontrol, inner, outer, state
2804 // cmpdst -> blit, data, datacomp, state
2805 // bcompen -> acontrol, inner, mcontrol, state
2806 // dcompen -> inner, state
2807 // bkgwren -> inner, state
2808 // srcshade -> dcontrol, inner, state
2809 // adddsel -> dcontrol
2810 //NOTE: ADDDSEL takes precedence over PATDSEL, PATDSEL over LFU_FUNC
2811 #ifdef VERBOSE_BLITTER_LOGGING
2814 char zfs[512], lfus[512];
2815 zfs[0] = lfus[0] = 0;
2816 if (dstwrz || dstenz || gourz)
2817 sprintf(zfs, " ZMODE=%X", zmode);
2818 if (!(patdsel || adddsel))
2819 sprintf(lfus, " LFUFUNC=%X", lfufunc);
2820 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,
2821 (srcen ? " SRCEN" : ""), (srcenx ? " SRCENX" : ""), (srcenz ? " SRCENZ" : ""),
2822 (dsten ? " DSTEN" : ""), (dstenz ? " DSTENZ" : ""), (dstwrz ? " DSTWRZ" : ""),
2823 (clip_a1 ? " CLIP_A1" : ""), (upda1 ? " UPDA1" : ""), (upda1f ? " UPDA1F" : ""),
2824 (upda2 ? " UPDA2" : ""), (dsta2 ? " DSTA2" : ""), (gourd ? " GOURD" : ""),
2825 (gourz ? " GOURZ" : ""), (topben ? " TOPBEN" : ""), (topnen ? " TOPNEN" : ""),
2826 (patdsel ? " PATDSEL" : ""), (adddsel ? " ADDDSEL" : ""), zfs, lfus, (cmpdst ? " CMPDST" : ""),
2827 (bcompen ? " BCOMPEN" : ""), (dcompen ? " DCOMPEN" : ""), (bkgwren ? " BKGWREN" : ""),
2828 (srcshade ? " SRCSHADE" : ""));
2829 printf(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
2834 // Lines that don't exist in Jaguar I (and will never be asserted)
2836 bool polygon = false, datinit = false, a1_stepld = false, a2_stepld = false, ext_int = false;
2837 bool istepadd = false, istepfadd = false, finneradd = false, inneradd = false;
2838 bool zstepfadd = false, zstepadd = false;
2840 // Various state lines (initial state--basically the reset state of the FDSYNCs)
2842 bool go = true, idle = true, inner = false, a1fupdate = false, a1update = false,
2843 zfupdate = false, zupdate = false, a2update = false, init_if = false, init_ii = false,
2844 init_zf = false, init_zi = false;
2846 bool outer0 = false, indone = false;
2848 bool idlei, inneri, a1fupdatei, a1updatei, zfupdatei, zupdatei, a2updatei, init_ifi, init_iii,
2851 bool notgzandp = !(gourz && polygon);
2853 // Various registers set up by user
2855 uint16 ocount = GET16(blitter_ram, PIXLINECOUNTER);
2856 uint8 a1_pitch = blitter_ram[A1_FLAGS + 3] & 0x03;
2857 uint8 a2_pitch = blitter_ram[A2_FLAGS + 3] & 0x03;
2858 uint8 a1_pixsize = (blitter_ram[A1_FLAGS + 3] & 0x38) >> 3;
2859 uint8 a2_pixsize = (blitter_ram[A2_FLAGS + 3] & 0x38) >> 3;
2860 uint8 a1_zoffset = (GET16(blitter_ram, A1_FLAGS + 2) >> 6) & 0x07;
2861 uint8 a2_zoffset = (GET16(blitter_ram, A2_FLAGS + 2) >> 6) & 0x07;
2862 uint8 a1_width = (blitter_ram[A1_FLAGS + 2] >> 1) & 0x3F;
2863 uint8 a2_width = (blitter_ram[A2_FLAGS + 2] >> 1) & 0x3F;
2864 bool a2_mask = blitter_ram[A2_FLAGS + 2] & 0x80;
2865 uint8 a1addx = blitter_ram[A1_FLAGS + 1] & 0x03, a2addx = blitter_ram[A2_FLAGS + 1] & 0x03;
2866 bool a1addy = blitter_ram[A1_FLAGS + 1] & 0x04, a2addy = blitter_ram[A2_FLAGS + 1] & 0x04;
2867 bool a1xsign = blitter_ram[A1_FLAGS + 1] & 0x08, a2xsign = blitter_ram[A2_FLAGS + 1] & 0x08;
2868 bool a1ysign = blitter_ram[A1_FLAGS + 1] & 0x10, a2ysign = blitter_ram[A2_FLAGS + 1] & 0x10;
2869 uint32 a1_base = GET32(blitter_ram, A1_BASE) & 0xFFFFFFF8; // Phrase aligned by ignoring bottom 3 bits
2870 uint32 a2_base = GET32(blitter_ram, A2_BASE) & 0xFFFFFFF8;
2872 uint16 a1_win_x = GET16(blitter_ram, A1_CLIP + 2) & 0x7FFF;
2873 uint16 a1_win_y = GET16(blitter_ram, A1_CLIP + 0) & 0x7FFF;
2874 int16 a1_x = (int16)GET16(blitter_ram, A1_PIXEL + 2);
2875 int16 a1_y = (int16)GET16(blitter_ram, A1_PIXEL + 0);
2876 int16 a1_step_x = (int16)GET16(blitter_ram, A1_STEP + 2);
2877 int16 a1_step_y = (int16)GET16(blitter_ram, A1_STEP + 0);
2878 uint16 a1_stepf_x = GET16(blitter_ram, A1_FSTEP + 2);
2879 uint16 a1_stepf_y = GET16(blitter_ram, A1_FSTEP + 0);
2880 uint16 a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
2881 uint16 a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
2882 int16 a1_inc_x = (int16)GET16(blitter_ram, A1_INC + 2);
2883 int16 a1_inc_y = (int16)GET16(blitter_ram, A1_INC + 0);
2884 uint16 a1_incf_x = GET16(blitter_ram, A1_FINC + 2);
2885 uint16 a1_incf_y = GET16(blitter_ram, A1_FINC + 0);
2887 int16 a2_x = (int16)GET16(blitter_ram, A2_PIXEL + 2);
2888 int16 a2_y = (int16)GET16(blitter_ram, A2_PIXEL + 0);
2889 uint16 a2_mask_x = GET16(blitter_ram, A2_MASK + 2);
2890 uint16 a2_mask_y = GET16(blitter_ram, A2_MASK + 0);
2891 int16 a2_step_x = (int16)GET16(blitter_ram, A2_STEP + 2);
2892 int16 a2_step_y = (int16)GET16(blitter_ram, A2_STEP + 0);
2894 uint64 srcd1 = GET64(blitter_ram, SRCDATA);
2896 uint64 dstd = GET64(blitter_ram, DSTDATA);
2897 uint64 patd = GET64(blitter_ram, PATTERNDATA);
2898 uint32 iinc = GET32(blitter_ram, INTENSITYINC);
2899 uint64 srcz1 = GET64(blitter_ram, SRCZINT);
2900 uint64 srcz2 = GET64(blitter_ram, SRCZFRAC);
2901 uint64 dstz = GET64(blitter_ram, DSTZ);
2902 uint32 zinc = GET32(blitter_ram, ZINC);
2903 uint32 collision = GET32(blitter_ram, COLLISIONCTRL);// 0=RESUME, 1=ABORT, 2=STOPEN
2905 uint8 pixsize = (dsta2 ? a2_pixsize : a1_pixsize); // From ACONTROL
2907 //Testing Trevor McFur--I *think* it's the circle on the lower RHS of the screen...
2909 if (cmd == 0x05810601 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 96)
2910 && (GET16(blitter_ram, PIXLINECOUNTER + 0) == 72))
2913 //if (cmd == 0x1401060C) patd = 0xFFFFFFFFFFFFFFFFLL;
2914 //if (cmd == 0x1401060C) patd = 0x00000000000000FFLL;
2915 //If it's still not working (bcompen-patd) then see who's writing what to patd and where...
2916 //Still not OK. Check to see who's writing what to where in patd!
2917 //It looks like M68K is writing to the top half of patd... Hmm...
2919 ----> M68K wrote 0000 to byte 15737344 of PATTERNDATA...
2920 --> M68K wrote 00 to byte 0 of PATTERNDATA...
2921 --> M68K wrote 00 to byte 1 of PATTERNDATA...
2922 ----> M68K wrote 00FF to byte 15737346 of PATTERNDATA...
2923 --> M68K wrote 00 to byte 2 of PATTERNDATA...
2924 --> M68K wrote FF to byte 3 of PATTERNDATA...
2925 logBlit = F, cmd = 1401060C
2927 Wren0 := ND6 (wren\[0], gpua\[5], gpua\[6..8], bliten, gpu_memw);
2928 Wren1 := ND6 (wren\[1], gpua[5], gpua\[6..8], bliten, gpu_memw);
2929 Wren2 := ND6 (wren\[2], gpua\[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2930 Wren3 := ND6 (wren\[3], gpua[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2933 Dec0 := D38GH (a1baseld, a1flagld, a1winld, a1ptrld, a1stepld, a1stepfld, a1fracld, a1incld, gpua[2..4], wren\[0]);
2935 Dec1 := D38GH (a1incfld, a2baseld, a2flagld, a2maskld, a2ptrldg, a2stepld, cmdldt, countldt, gpua[2..4], wren\[1]);
2937 Dec2 := D38GH (srcd1ldg[0..1], dstdldg[0..1], dstzldg[0..1], srcz1ldg[0..1], gpua[2..4], wren\[2]);
2939 Dec3 := D38GH (srcz2ld[0..1], patdld[0..1], iincld, zincld, stopld, intld[0], gpua[2..4], wren\[3]);
2941 wren[3] is asserted when gpu address bus = 0 011x xx00
2942 patdld[0] -> 0 0110 1000 -> $F02268 (lo 32 bits)
2943 patdld[1] -> 0 0110 1100 -> $F0226C (hi 32 bits)
2945 So... It's reversed! The data organization of the patd register is [low 32][high 32]! !!! FIX !!! [DONE]
2946 And fix all the other 64 bit registers [DONE]
2948 /*if (cmd == 0x1401060C)
2950 printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2954 if ((cmd == 0x00010200) && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 9))
2957 ; Pink altimeter bar
2959 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2960 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
2961 A1 step values: -10 (X), 1 (Y)
2962 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
2963 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
2964 A1 x/y: 262/132, A2 x/y: 129/0
2965 ;x-coord is 257 in pic, so add 5
2966 ;20 for ship, 33 for #... Let's see if we can find 'em!
2968 ; Black altimeter bar
2970 Blit! (00110000 <- 000BF010) count: 5 x 29, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2971 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
2972 A1 step values: -8 (X), 1 (Y)
2973 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
2974 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
2975 A1 x/y: 264/126, A2 x/y: 336/0
2977 Here's the pink bar--note that it's phrase mode without dread, so how does this work???
2978 Not sure, but I *think* that somehow it MUXes the data at the write site in on the left or right side
2979 of the write data when masked in phrase mode. I'll have to do some tracing to see if this is the mechanism
2982 Blit! (CMD = 00010200)
2983 Flags: UPDA1 PATDSEL
2985 a1_base = 00110010, a2_base = 000BD7E0
2986 a1_x = 0106, a1_y = 0090, a1_frac_x = 0000, a1_frac_y = 8000, a2_x = 025A, a2_y = 0000
2987 a1_step_x = FFF6, a1_step_y = 0001, a1_stepf_x = 5E00, a1_stepf_y = D100, a2_step_x = FFF7, a2_step_y = 0001
2988 a1_inc_x = 0001, a1_inc_y = FFFF, a1_incf_x = 0000, a1_incf_y = E000
2989 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
2990 a2_mask=F a1add=+phr/+0 a2add=+1/+0
2991 a1_pixsize = 4, a2_pixsize = 4
2992 srcd=BAC673AC2C92E578 dstd=0000000000000000 patd=74C074C074C074C0 iinc=0002E398
2993 srcz1=7E127E12000088DA srcz2=DBE06DF000000000 dstz=0000000000000000 zinc=FFFE4840, coll=0
2995 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
2996 Entering INNER state...
2997 Entering DWRITE state...
2998 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)
2999 Entering A1_ADD state [a1_x=0106, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3000 Entering DWRITE state...
3001 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)
3002 Entering A1_ADD state [a1_x=0108, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3003 Entering DWRITE state...
3004 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)
3005 Entering A1_ADD state [a1_x=010C, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3006 Entering IDLE_INNER state...
3007 Leaving INNER state... (ocount=000A)
3008 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3009 Entering A1UPDATE state... (272/144 -> 262/145)
3010 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3011 Entering INNER state...
3016 a2addy = a1addy; // A2 channel Y add bit is tied to A1's
3018 //if (logBlit && (ocount > 20)) logBlit = false;
3019 #ifdef VERBOSE_BLITTER_LOGGING
3022 printf(" a1_base = %08X, a2_base = %08X\n", a1_base, a2_base);
3023 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);
3024 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);
3025 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);
3026 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);
3027 char x_add_str[4][4] = { "phr", "1", "0", "inc" };
3028 printf(" a2_mask=%s a1add=%s%s/%s%s a2add=%s%s/%s%s\n", (a2_mask ? "T" : "F"), (a1xsign ? "-" : "+"), x_add_str[a1addx],
3029 (a1ysign ? "-" : "+"), (a1addy ? "1" : "0"), (a2xsign ? "-" : "+"), x_add_str[a2addx],
3030 (a2ysign ? "-" : "+"), (a2addy ? "1" : "0"));
3031 printf(" a1_pixsize = %u, a2_pixsize = %u\n", a1_pixsize, a2_pixsize);
3032 printf(" srcd=%08X%08X dstd=%08X%08X patd=%08X%08X iinc=%08X\n",
3033 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF),
3034 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
3035 (uint32)(patd >> 32), (uint32)(patd & 0xFFFFFFFF), iinc);
3036 printf(" srcz1=%08X%08X srcz2=%08X%08X dstz=%08X%08X zinc=%08X, coll=%X\n",
3037 (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
3038 (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF),
3039 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF), zinc, collision);
3043 // Various state lines set up by user
3045 bool phrase_mode = ((!dsta2 && a1addx == 0) || (dsta2 && a2addx == 0) ? true : false); // From ACONTROL
3046 #ifdef VERBOSE_BLITTER_LOGGING
3049 printf(" Phrase mode is %s\n", (phrase_mode ? "ON" : "off"));
3055 // Stopgap vars to simulate various lines
3057 uint16 a1FracCInX = 0, a1FracCInY = 0;
3063 if ((idle && !go) || (inner && outer0 && indone))
3065 #ifdef VERBOSE_BLITTER_LOGGING
3068 printf(" Entering IDLE state...\n");
3074 //Instead of a return, let's try breaking out of the loop...
3081 // INNER LOOP ACTIVE
3083 Entering DWRITE state... (icount=0000, inc=4)
3084 Entering IDLE_INNER state...
3085 Leaving INNER state... (ocount=00EF)
3086 [in=T a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3087 Entering INNER state...
3089 [in=F a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3092 if ((idle && go && !datinit)
3093 || (inner && !indone)
3094 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && !datinit)
3095 || (a1update && !upda2 && notgzandp && !datinit)
3096 || (zupdate && !upda2 && !datinit)
3097 || (a2update && !datinit)
3098 || (init_ii && !gourz)
3106 // A1 FRACTION UPDATE
3108 if (inner && indone && !outer0 && upda1f)
3115 // A1 POINTER UPDATE
3118 || (inner && indone && !outer0 && !upda1f && upda1))
3125 // Z FRACTION UPDATE
3127 if ((a1update && gourz && polygon)
3128 || (inner && indone && !outer0 && !upda1f && !upda1 && gourz && polygon))
3144 // A2 POINTER UPDATE
3146 if ((a1update && upda2 && notgzandp)
3147 || (zupdate && upda2)
3148 || (inner && indone && !outer0 && !upda1f && notgzandp && !upda1 && upda2))
3155 // INITIALIZE INTENSITY FRACTION
3157 if ((zupdate && !upda2 && datinit)
3158 || (a1update && !upda2 && datinit && notgzandp)
3159 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && datinit)
3160 || (a2update && datinit)
3161 || (idle && go && datinit))
3168 // INITIALIZE INTENSITY INTEGER
3177 // INITIALIZE Z FRACTION
3179 if (init_ii && gourz)
3186 // INITIALIZE Z INTEGER
3195 // Here we move the fooi into their foo counterparts in order to simulate the moving
3196 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3200 a1fupdate = a1fupdatei;
3201 a1update = a1updatei;
3202 zfupdate = zfupdatei; // *
3203 zupdate = zupdatei; // *
3204 a2update = a2updatei;
3205 init_if = init_ifi; // *
3206 init_ii = init_iii; // *
3207 init_zf = init_zfi; // *
3208 init_zi = init_zii; // *
3209 // * denotes states that will never assert for Jaguar I
3210 #ifdef VERBOSE_BLITTER_LOGGING
3213 printf(" [in=%c a1f=%c a1=%c zf=%c z=%c a2=%c iif=%c iii=%c izf=%c izi=%c]\n",
3214 (inner ? 'T' : 'F'), (a1fupdate ? 'T' : 'F'), (a1update ? 'T' : 'F'), (zfupdate ? 'T' : 'F'),
3215 (zupdate ? 'T' : 'F'), (a2update ? 'T' : 'F'), (init_if ? 'T' : 'F'), (init_ii ? 'T' : 'F'),
3216 (init_zf ? 'T' : 'F'), (init_zi ? 'T' : 'F'));
3221 // Now, depending on how we want to handle things, we could either put the implementation
3222 // of the various pieces up above, or handle them down below here.
3224 // Let's try postprocessing for now...
3229 #ifdef VERBOSE_BLITTER_LOGGING
3232 printf(" Entering INNER state...\n");
3236 uint16 icount = GET16(blitter_ram, PIXLINECOUNTER + 2);
3237 bool idle_inner = true, step = true, sreadx = false, szreadx = false, sread = false,
3238 szread = false, dread = false, dzread = false, dwrite = false, dzwrite = false;
3239 bool inner0 = false;
3240 bool idle_inneri, sreadxi, szreadxi, sreadi, szreadi, dreadi, dzreadi, dwritei, dzwritei;
3242 // State lines that will never assert in Jaguar I
3244 bool textext = false, txtread = false;
3248 bool sshftld = true; // D flipflop (D -> Q): instart -> sshftld
3249 //NOTE: sshftld probably is only asserted at the beginning of the inner loop. !!! FIX !!!
3251 Blit! (CMD = 01800005)
3252 Flags: SRCEN SRCENX LFUFUNC=C
3254 a1_base = 00037290, a2_base = 000095D0
3255 a1_x = 0000, a1_y = 0000, a2_x = 0002, a2_y = 0000
3256 a1_pixsize = 4, a2_pixsize = 4
3257 srcd=0000000000000000, dstd=0000000000000000, patd=0000000000000000
3259 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3260 Entering INNER state...
3261 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
3262 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
3263 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3264 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3265 Source read address/pix address: 000095D8/0 [0054003800009814]
3266 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3267 Entering DWRITE state...
3268 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
3269 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3270 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3271 Source read address/pix address: 000095E0/0 [00009968000377C7]
3272 Entering A2_ADD state [a2_x=0008, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3273 Entering DWRITE state...
3274 Dest write address/pix address: 00037298/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026A, inc=4)
3275 Entering A1_ADD state [a1_x=0004, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3278 // while (!idle_inner)
3283 if ((idle_inner && !step)
3284 || (dzwrite && step && inner0)
3285 || (dwrite && step && !dstwrz && inner0))
3287 #ifdef VERBOSE_BLITTER_LOGGING
3290 printf(" Entering IDLE_INNER state...\n");
3298 idle_inneri = false;
3300 // EXTRA SOURCE DATA READ
3302 if ((idle_inner && step && srcenx)
3303 || (sreadx && !step))
3310 // EXTRA SOURCE ZED READ
3312 if ((sreadx && step && srcenz)
3313 || (szreadx && !step))
3320 // TEXTURE DATA READ (not implemented because not in Jaguar I)
3324 if ((szreadx && step && !textext)
3325 || (sreadx && step && !srcenz && srcen)
3326 || (idle_inner && step && !srcenx && !textext && srcen)
3327 || (dzwrite && step && !inner0 && !textext && srcen)
3328 || (dwrite && step && !dstwrz && !inner0 && !textext && srcen)
3329 || (txtread && step && srcen)
3330 || (sread && !step))
3339 if ((sread && step && srcenz)
3340 || (szread && !step))
3347 // DESTINATION DATA READ
3349 if ((szread && step && dsten)
3350 || (sread && step && !srcenz && dsten)
3351 || (sreadx && step && !srcenz && !textext && !srcen && dsten)
3352 || (idle_inner && step && !srcenx && !textext && !srcen && dsten)
3353 || (dzwrite && step && !inner0 && !textext && !srcen && dsten)
3354 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && dsten)
3355 || (txtread && step && !srcen && dsten)
3356 || (dread && !step))
3363 // DESTINATION ZED READ
3365 if ((dread && step && dstenz)
3366 || (szread && step && !dsten && dstenz)
3367 || (sread && step && !srcenz && !dsten && dstenz)
3368 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && dstenz)
3369 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && dstenz)
3370 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && dstenz)
3371 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && dstenz)
3372 || (txtread && step && !srcen && !dsten && dstenz)
3373 || (dzread && !step))
3380 // DESTINATION DATA WRITE
3382 if ((dzread && step)
3383 || (dread && step && !dstenz)
3384 || (szread && step && !dsten && !dstenz)
3385 || (sread && step && !srcenz && !dsten && !dstenz)
3386 || (txtread && step && !srcen && !dsten && !dstenz)
3387 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && !dstenz)
3388 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && !dstenz)
3389 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && !dstenz)
3390 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && !dstenz)
3391 || (dwrite && !step))
3398 // DESTINATION ZED WRITE
3400 if ((dzwrite && !step)
3401 || (dwrite && step && dstwrz))
3408 //Kludge: A QnD way to make sure that sshftld is asserted only for the first
3409 // cycle of the inner loop...
3410 sshftld = idle_inner;
3412 // Here we move the fooi into their foo counterparts in order to simulate the moving
3413 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3415 idle_inner = idle_inneri;
3425 // Here's a few more decodes--not sure if they're supposed to go here or not...
3427 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
3429 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
3431 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
3432 bool gendst = dreadi || dzreadi || dwritei || dzwritei;
3433 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
3435 bool zaddr = szreadx || szread || dzread || dzwrite;
3437 // Some stuff from MCONTROL.NET--not sure if this is the correct use of this decode or not...
3438 /*Fontread\ := OND1 (fontread\, sread[1], sreadx[1], bcompen);
3439 Fontread := INV1 (fontread, fontread\);
3440 Justt := NAN3 (justt, fontread\, phrase_mode, tactive\);
3441 Justify := TS (justify, justt, busen);*/
3442 bool fontread = (sread || sreadx) && bcompen;
3443 bool justify = !(!fontread && phrase_mode /*&& tactive*/);
3445 /* Generate inner loop update enables */
3447 A1_addi := MX2 (a1_addi, dsta_addi, srca_addi, dsta2);
3448 A2_addi := MX2 (a2_addi, srca_addi, dsta_addi, dsta2);
3449 A1_add := FD1 (a1_add, a1_add\, a1_addi, clk);
3450 A2_add := FD1 (a2_add, a2_add\, a2_addi, clk);
3451 A2_addb := BUF1 (a2_addb, a2_add);
3453 bool a1_add = (dsta2 ? srca_addi : dsta_addi);
3454 bool a2_add = (dsta2 ? dsta_addi : srca_addi);
3456 /* Address adder input A register selection
3457 000 A1 step integer part
3458 001 A1 step fraction part
3459 010 A1 increment integer part
3460 011 A1 increment fraction part
3464 bit 1 = /a2update . (a1_add . a1addx[0..1])
3465 bit 0 = /a2update . ( a1fupdate
3466 + a1_add . atick[0] . a1addx[0..1])
3467 The /a2update term on bits 0 and 1 is redundant.
3468 Now look-ahead based
3470 uint8 addasel = (a1fupdate || (a1_add && a1addx == 3) ? 0x01 : 0x00);
3471 addasel |= (a1_add && a1addx == 3 ? 0x02 : 0x00);
3472 addasel |= (a2update ? 0x04 : 0x00);
3473 /* Address adder input A X constant selection
3474 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all
3475 zeroes when they are all 1
3476 Remember - these are pixels, so to add one phrase the pixel size
3477 has to be taken into account to get the appropriate value.
3479 if a1addx[0..1] are 00 set 6 - pixel size
3480 if a1addx[0..1] are 01 set the value 000
3481 if a1addx[0..1] are 10 set the value 111
3483 JLH: Also, 11 will likewise set the value to 111
3485 uint8 a1_xconst = 6 - a1_pixsize, a2_xconst = 6 - a2_pixsize;
3489 else if (a1addx & 0x02)
3494 else if (a2addx & 0x02)
3497 uint8 adda_xconst = (a2_add ? a2_xconst : a1_xconst);
3498 /* Address adder input A Y constant selection
3499 22 June 94 - This was erroneous, because only the a1addy bit was reflected here.
3500 Therefore, the selection has to be controlled by a bug fix bit.
3501 JLH: Bug fix bit in Jaguar II--not in Jaguar I!
3503 bool adda_yconst = a1addy;
3504 /* Address adder input A register versus constant selection
3505 given by a1_add . a1addx[0..1]
3508 + a2_add . a2addx[0..1]
3511 bool addareg = ((a1_add && a1addx == 3) || a1update || a1fupdate
3512 || (a2_add && a2addx == 3) || a2update ? true : false);
3513 /* The adders can be put into subtract mode in add pixel size
3514 mode when the corresponding flags are set */
3515 bool suba_x = ((a1_add && a1xsign && a1addx == 1) || (a2_add && a2xsign && a2addx == 1) ? true : false);
3516 bool suba_y = ((a1_add && a1addy && a1ysign) || (a2_add && a2addy && a2ysign) ? true : false);
3517 /* Address adder input B selection
3524 + (a1_add . atick[0] . a1addx[0..1])
3525 + a1fupdate . a1_stepld
3526 + a1update . a1_stepld
3527 + a2update . a2_stepld
3528 Bit 0 = a2update + a2_add
3529 + a1fupdate . a1_stepld
3530 + a1update . a1_stepld
3531 + a2update . a2_stepld
3533 uint8 addbsel = (a2update || a2_add || (a1fupdate && a1_stepld)
3534 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x01 : 0x00);
3535 addbsel |= (a1fupdate || (a1_add && a1addx == 3) || (a1fupdate && a1_stepld)
3536 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x02 : 0x00);
3538 /* The modulo bits are used to align X onto a phrase boundary when
3539 it is being updated by one phrase
3546 Masking is enabled for a1 when a1addx[0..1] is 00, and the value
3547 is 6 - the pixel size (again!)
3549 uint8 maska1 = (a1_add && a1addx == 0 ? 6 - a1_pixsize : 0);
3550 uint8 maska2 = (a2_add && a2addx == 0 ? 6 - a2_pixsize : 0);
3551 uint8 modx = (a2_add ? maska2 : maska1);
3552 /* Generate load strobes for the increment updates */
3554 /*A1pldt := NAN2 (a1pldt, atick[1], a1_add);
3555 A1ptrldi := NAN2 (a1ptrldi, a1update\, a1pldt);
3557 A1fldt := NAN4 (a1fldt, atick[0], a1_add, a1addx[0..1]);
3558 A1fracldi := NAN2 (a1fracldi, a1fupdate\, a1fldt);
3560 A2pldt := NAN2 (a2pldt, atick[1], a2_add);
3561 A2ptrldi := NAN2 (a2ptrldi, a2update\, a2pldt);*/
3562 bool a1fracldi = a1fupdate || (a1_add && a1addx == 3);
3564 // Some more from DCONTROL...
3565 // atick[] just MAY be important here! We're assuming it's true and dropping the term...
3566 // That will probably screw up some of the lower terms that seem to rely on the timing of it...
3567 #warning srcdreadd is not properly initialized!
3568 bool srcdreadd = false; // Set in INNER.NET
3569 //Shadeadd\ := NAN2H (shadeadd\, dwrite, srcshade);
3570 //Shadeadd := INV2 (shadeadd, shadeadd\);
3571 bool shadeadd = dwrite && srcshade;
3572 /* Data adder control, input A selection
3573 000 Destination data
3574 001 Initialiser pixel value
3575 100 Source data - computed intensity fraction
3576 101 Pattern data - computed intensity
3577 110 Source zed 1 - computed zed
3578 111 Source zed 2 - computed zed fraction
3580 Bit 0 = dwrite . gourd . atick[1]
3581 + dzwrite . gourz . atick[0]
3584 + init_if + init_ii + init_zf + init_zi
3585 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3588 Bit 2 = (gourd + gourz) . /(init_if + init_ii + init_zf + init_zi)
3591 uint8 daddasel = ((dwrite && gourd) || (dzwrite && gourz) || istepadd || zstepfadd
3592 || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3593 daddasel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3594 daddasel |= (((gourd || gourz) && !(init_if || init_ii || init_zf || init_zi))
3595 || (dwrite && srcshade) ? 0x04 : 0x00);
3596 /* Data adder control, input B selection
3598 0001 Data initialiser increment
3599 0100 Bottom 16 bits of I increment repeated four times
3600 0101 Top 16 bits of I increment repeated four times
3601 0110 Bottom 16 bits of Z increment repeated four times
3602 0111 Top 16 bits of Z increment repeated four times
3603 1100 Bottom 16 bits of I step repeated four times
3604 1101 Top 16 bits of I step repeated four times
3605 1110 Bottom 16 bits of Z step repeated four times
3606 1111 Top 16 bits of Z step repeated four times
3608 Bit 0 = dwrite . gourd . atick[1]
3609 + dzwrite . gourz . atick[1]
3613 + init_if + init_ii + init_zf + init_zi
3614 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3617 Bit 2 = dwrite . gourd . (atick[0] + atick[1])
3618 + dzwrite . gourz . (atick[0] + atick[1])
3620 + istepadd + istepfadd + zstepadd + zstepfadd
3621 Bit 3 = istepadd + istepfadd + zstepadd + zstepfadd
3623 uint8 daddbsel = ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3624 || istepadd || zstepadd || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3625 daddbsel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3626 daddbsel |= ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3627 || istepadd || istepfadd || zstepadd || zstepfadd ? 0x04 : 0x00);
3628 daddbsel |= (istepadd && istepfadd && zstepadd && zstepfadd ? 0x08 : 0x00);
3629 /* Data adder mode control
3630 000 16-bit normal add
3631 001 16-bit saturating add with carry
3632 010 8-bit saturating add with carry, carry into top byte is
3634 011 8-bit saturating add with carry, carry into top byte and
3635 between top nybbles is inhibited (CRY)
3636 100 16-bit normal add with carry
3637 101 16-bit saturating add
3638 110 8-bit saturating add, carry into top byte is inhibited
3639 111 8-bit saturating add, carry into top byte and between top
3640 nybbles is inhibited
3642 The first five are used for Gouraud calculations, the latter three
3643 for adding source and destination data
3645 Bit 0 = dzwrite . gourz . atick[1]
3646 + dwrite . gourd . atick[1] . /topnen . /topben . /ext_int
3647 + dwrite . gourd . atick[1] . topnen . topben . /ext_int
3649 + istepadd . /topnen . /topben . /ext_int
3650 + istepadd . topnen . topben . /ext_int
3651 + /gourd . /gourz . /topnen . /topben
3652 + /gourd . /gourz . topnen . topben
3653 + shadeadd . /topnen . /topben
3654 + shadeadd . topnen . topben
3655 + init_ii . /topnen . /topben . /ext_int
3656 + init_ii . topnen . topben . /ext_int
3659 Bit 1 = dwrite . gourd . atick[1] . /topben . /ext_int
3660 + istepadd . /topben . /ext_int
3661 + /gourd . /gourz . /topben
3662 + shadeadd . /topben
3663 + init_ii . /topben . /ext_int
3665 Bit 2 = /gourd . /gourz
3667 + dwrite . gourd . atick[1] . ext_int
3668 + istepadd . ext_int
3671 uint8 daddmode = ((dzwrite && gourz) || (dwrite && gourd && !topnen && !topben && !ext_int)
3672 || (dwrite && gourd && topnen && topben && !ext_int) || zstepadd
3673 || (istepadd && !topnen && !topben && !ext_int)
3674 || (istepadd && topnen && topben && !ext_int) || (!gourd && !gourz && !topnen && !topben)
3675 || (!gourd && !gourz && topnen && topben) || (shadeadd && !topnen && !topben)
3676 || (shadeadd && topnen && topben) || (init_ii && !topnen && !topben && !ext_int)
3677 || (init_ii && topnen && topben && !ext_int) || init_zi ? 0x01 : 0x00);
3678 daddmode |= ((dwrite && gourd && !topben && !ext_int) || (istepadd && !topben && !ext_int)
3679 || (!gourd && !gourz && !topben) || (shadeadd && !topben)
3680 || (init_ii && !topben && !ext_int) ? 0x02 : 0x00);
3681 daddmode |= ((!gourd && !gourz) || shadeadd || (dwrite && gourd && ext_int)
3682 || (istepadd && ext_int) || (init_ii && ext_int) ? 0x04 : 0x00);
3683 /* Data add load controls
3684 Pattern fraction (dest data) is loaded on
3685 dwrite . gourd . atick[0]
3686 + istepfadd . /datinit
3688 Pattern data is loaded on
3689 dwrite . gourd . atick[1]
3690 + istepadd . /datinit . /datinit
3692 Source z1 is loaded on
3693 dzwrite . gourz . atick[1]
3694 + zstepadd . /datinit . /datinit
3696 Source z2 is loaded on
3697 dzwrite . gourz . atick[0]
3700 Texture map shaded data is loaded on
3701 srcdreadd . srcshade
3703 bool patfadd = (dwrite && gourd) || (istepfadd && !datinit) || init_if;
3704 bool patdadd = (dwrite && gourd) || (istepadd && !datinit) || init_ii;
3705 bool srcz1add = (dzwrite && gourz) || (zstepadd && !datinit) || init_zi;
3706 bool srcz2add = (dzwrite && gourz) || zstepfadd || init_zf;
3707 bool srcshadd = srcdreadd && srcshade;
3708 bool daddq_sel = patfadd || patdadd || srcz1add || srcz2add || srcshadd;
3709 /* Select write data
3710 This has to be controlled from stage 1 of the pipe-line, delayed
3711 by one tick, as the write occurs in the cycle after the ack.
3718 Bit 0 = /patdsel . /adddsel
3723 uint8 data_sel = ((!patdsel && !adddsel) || dzwrite ? 0x01 : 0x00)
3724 | (adddsel || dzwrite ? 0x02 : 0x00);
3726 uint32 address, pixAddr;
3727 ADDRGEN(address, pixAddr, gena2i, zaddr,
3728 a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3729 a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3731 //Here's my guess as to how the addresses get truncated to phrase boundaries in phrase mode...
3733 address &= 0xFFFFF8;
3735 /* Generate source alignment shift
3736 -------------------------------
3737 The source alignment shift for data move is the difference between
3738 the source and destination X pointers, multiplied by the pixel
3739 size. Only the low six bits of the pointers are of interest, as
3740 pixel sizes are always a power of 2 and window rows are always
3743 When not in phrase mode, the top 3 bits of the shift value are
3746 Source shifting is also used to extract bits for bit-to-byte
3747 expansion in phrase mode. This involves only the bottom three
3748 bits of the shift value, and is based on the offset within the
3749 phrase of the destination X pointer, in pixels.
3751 Source shifting is disabled when srcen is not set.
3753 uint8 dstxp = (dsta2 ? a2_x : a1_x) & 0x3F;
3754 uint8 srcxp = (dsta2 ? a1_x : a2_x) & 0x3F;
3755 uint8 shftv = ((dstxp - srcxp) << pixsize) & 0x3F;
3756 /* The phrase mode alignment count is given by the phrase offset
3757 of the first pixel, for bit to byte expansion */
3761 pobb = dstxp & 0x07;
3763 pobb = dstxp & 0x03;
3765 pobb = dstxp & 0x01;
3767 bool pobbsel = phrase_mode && bcompen;
3768 uint8 loshd = (pobbsel ? pobb : shftv) & 0x07;
3769 uint8 shfti = (srcen || pobbsel ? (sshftld ? loshd : srcshift & 0x07) : 0);
3770 /* Enable for high bits is srcen . phrase_mode */
3771 shfti |= (srcen && phrase_mode ? (sshftld ? shftv & 0x38 : srcshift & 0x38) : 0);
3776 #ifdef VERBOSE_BLITTER_LOGGING
3779 printf(" Entering SREADX state...");
3780 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
3784 //uint32 srcAddr, pixAddr;
3785 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3786 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3787 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3789 srcd1 = ((uint64)JaguarReadLong(address + 0, BLITTER) << 32)
3790 | (uint64)JaguarReadLong(address + 4, BLITTER);
3791 //Kludge to take pixel size into account...
3792 //Hmm. If we're not in phrase mode, this is most likely NOT going to be used...
3793 //Actually, it would be--because of BCOMPEN expansion, for example...
3802 else if (pixsize == 4)
3808 #ifdef VERBOSE_BLITTER_LOGGING
3811 printf(" Source extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3812 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
3820 #ifdef VERBOSE_BLITTER_LOGGING
3823 printf(" Entering SZREADX state...");
3828 srcz1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3829 #ifdef VERBOSE_BLITTER_LOGGING
3832 printf(" Src Z extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3833 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3841 #ifdef VERBOSE_BLITTER_LOGGING
3844 printf(" Entering SREAD state...");
3845 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]\n", dstart, dend, pwidth, srcshift);
3849 //uint32 srcAddr, pixAddr;
3850 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3851 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3852 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3854 srcd1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3855 //Kludge to take pixel size into account...
3864 else if (pixsize == 4)
3870 #ifdef VERBOSE_BLITTER_LOGGING
3873 printf(" Source read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3874 (uint32)(srcd1 >> 32), (uint32)(srcd1 & 0xFFFFFFFF));
3882 #ifdef VERBOSE_BLITTER_LOGGING
3885 printf(" Entering SZREAD state...");
3890 srcz1 = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3891 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3892 if (!phrase_mode && pixsize == 4)
3895 #ifdef VERBOSE_BLITTER_LOGGING
3898 printf(" Src Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3899 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3907 #ifdef VERBOSE_BLITTER_LOGGING
3910 printf(" Entering DREAD state...");
3914 //uint32 dstAddr, pixAddr;
3915 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
3916 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3917 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3918 dstd = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3919 //Kludge to take pixel size into account...
3924 else if (pixsize == 4)
3929 #ifdef VERBOSE_BLITTER_LOGGING
3932 printf(" Dest read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3933 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF));
3941 // Is Z always 64 bit read? Or sometimes 16 bit (dependent on phrase_mode)?
3942 #ifdef VERBOSE_BLITTER_LOGGING
3945 printf(" Entering DZREAD state...");
3949 dstz = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
3950 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3951 if (!phrase_mode && pixsize == 4)
3954 #ifdef VERBOSE_BLITTER_LOGGING
3957 printf(" Dest Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3958 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF));
3964 // These vars should probably go further up in the code... !!! FIX !!!
3965 // We can't preassign these unless they're static...
3966 //uint64 srcz = 0; // These are assigned to shut up stupid compiler warnings--dwrite is ALWAYS asserted
3967 //bool winhibit = false;
3970 //NOTE: SRCSHADE requires GOURZ to be set to work properly--another Jaguar I bug
3973 #ifdef VERBOSE_BLITTER_LOGGING
3976 printf(" Entering DWRITE state...");
3980 //Counter is done on the dwrite state...! (We'll do it first, since it affects dstart/dend calculations.)
3981 //Here's the voodoo for figuring the correct amount of pixels in phrase mode (or not):
3982 int8 inct = -((dsta2 ? a2_x : a1_x) & 0x07); // From INNER_CNT
3984 inc = (!phrase_mode || (phrase_mode && (inct & 0x01)) ? 0x01 : 0x00);
3985 inc |= (phrase_mode && (((pixsize == 3 || pixsize == 4) && (inct & 0x02)) || pixsize == 5 && !(inct & 0x01)) ? 0x02 : 0x00);
3986 inc |= (phrase_mode && ((pixsize == 3 && (inct & 0x04)) || (pixsize == 4 && !(inct & 0x03))) ? 0x04 : 0x00);
3987 inc |= (phrase_mode && pixsize == 3 && !(inct & 0x07) ? 0x08 : 0x00);
3989 uint16 oldicount = icount; // Save icount to detect underflow...
3992 if (icount == 0 || ((icount & 0x8000) && !(oldicount & 0x8000)))
3994 // X/Y stepping is also done here, I think...No. It's done when a1_add or a2_add is asserted...
3996 //*********************************************************************************
3997 //Start & end write mask computations...
3998 //*********************************************************************************
4003 dstart = (dstxp & 0x07) << 3;
4005 dstart = (dstxp & 0x03) << 4;
4007 dstart = (dstxp & 0x01) << 5;
4009 dstart = (phrase_mode ? dstart : pixAddr & 0x07);
4011 //This is the other Jaguar I bug... Normally, should ALWAYS select a1_x here.
4012 uint16 dstxwr = (dsta2 ? a2_x : a1_x) & 0x7FFE;
4013 uint16 pseq = dstxwr ^ (a1_win_x & 0x7FFE);
4014 pseq = (pixsize == 5 ? pseq : pseq & 0x7FFC);
4015 pseq = ((pixsize & 0x06) == 4 ? pseq : pseq & 0x7FF8);
4016 bool penden = clip_a1 && (pseq == 0);
4017 uint8 window_mask = 0;
4020 window_mask = (a1_win_x & 0x07) << 3;
4022 window_mask = (a1_win_x & 0x03) << 4;
4024 window_mask = (a1_win_x & 0x01) << 5;
4026 window_mask = (penden ? window_mask : 0);
4029 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4030 Source extra read address/pix address: 000095D0/0 [000004E40000001C]
4031 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4032 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4033 Source read address/pix address: 000095D8/0 [0054003800009814]
4034 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4035 Entering DWRITE state...
4036 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)
4037 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4039 (icount=026E, inc=4)
4040 icount & 0x03 = 0x02
4043 window_mask = 0x1000
4045 Therefore, it chooses the inner_mask over the window_mask every time! Argh!
4046 This is because we did this wrong:
4047 Innerm[3-5] := AN2 (inner_mask[3-5], imb[3-5], inner0);
4048 NOTE! This doesn't fix the problem because inner0 is asserted too late to help here. !!! FIX !!! [Should be DONE]
4051 /* The mask to be used if within one phrase of the end of the inner
4053 uint8 inner_mask = 0;
4056 inner_mask = (icount & 0x07) << 3;
4058 inner_mask = (icount & 0x03) << 4;
4060 inner_mask = (icount & 0x01) << 5;
4063 /* The actual mask used should be the lesser of the window masks and
4064 the inner mask, where is all cases 000 means 1000. */
4065 window_mask = (window_mask == 0 ? 0x40 : window_mask);
4066 inner_mask = (inner_mask == 0 ? 0x40 : inner_mask);
4067 uint8 emask = (window_mask > inner_mask ? inner_mask : window_mask);
4068 /* The mask to be used for the pixel size, to which must be added
4070 uint8 pma = pixAddr + (1 << pixsize);
4071 /* Select the mask */
4072 uint8 dend = (phrase_mode ? emask : pma);
4074 /* The cycle width in phrase mode is normally one phrase. However,
4075 at the start and end it may be narrower. The start and end masks
4076 are used to generate this. The width is given by:
4078 8 - start mask - (8 - end mask)
4079 = end mask - start mask
4081 This is only used for writes in phrase mode.
4082 Start and end from the address level of the pipeline are used.
4084 uint8 pwidth = (((dend | dstart) & 0x07) == 0 ? 0x08 : (dend - dstart) & 0x07);
4086 //uint32 dstAddr, pixAddr;
4087 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
4088 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
4089 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
4090 #ifdef VERBOSE_BLITTER_LOGGING
4093 printf(" Dest write address/pix address: %08X/%1X", address, pixAddr);
4098 //More testing... This is almost certainly wrong, but how else does this work???
4099 //Seems to kinda work... But still, this doesn't seem to make any sense!
4100 if (phrase_mode && !dsten)
4101 dstd = ((uint64)JaguarReadLong(address, BLITTER) << 32) | (uint64)JaguarReadLong(address + 4, BLITTER);
4103 //Testing only... for now...
4104 //This is wrong because the write data is a combination of srcd and dstd--either run
4105 //thru the LFU or in PATDSEL or ADDDSEL mode. [DONE now, thru DATA module]
4106 // Precedence is ADDDSEL > PATDSEL > LFU.
4107 //Also, doesn't take into account the start & end masks, or the phrase width...
4110 // srcd2 = xxxx xxxx 0123 4567, srcd = 8901 2345 xxxx xxxx, srcshift = $20 (32)
4111 uint64 srcd = (srcd2 << (64 - srcshift)) | (srcd1 >> srcshift);
4112 //bleh, ugly ugly ugly
4116 //NOTE: This only works with pixel sizes less than 8BPP...
4117 //DOUBLE NOTE: Still need to do regression testing to ensure that this doesn't break other stuff... !!! CHECK !!!
4118 if (!phrase_mode && srcshift != 0)
4119 srcd = ((srcd2 & 0xFF) << (8 - srcshift)) | ((srcd1 & 0xFF) >> srcshift);
4121 //Z DATA() stuff done here... And it has to be done before any Z shifting...
4122 //Note that we need to have phrase mode start/end support here... (Not since we moved it from dzwrite...!)
4124 Here are a couple of Cybermorph blits with Z:
4125 $00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
4126 $09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
4128 We're having the same phrase mode overwrite problem we had with the pixels... !!! FIX !!!
4129 Odd. It's equating 0 with 0... Even though ZMODE is $04 (less than)!
4134 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
4135 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
4136 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
4137 uint32 zinc, uint32 zstep)
4140 uint8 initcin[4] = { 0, 0, 0, 0 };
4141 ADDARRAY(addq, 7/*daddasel*/, 6/*daddbsel*/, 0/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4142 srcz2 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4143 ADDARRAY(addq, 6/*daddasel*/, 7/*daddbsel*/, 1/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4144 srcz1 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4146 #if 0//def VERBOSE_BLITTER_LOGGING
4149 printf("\n[srcz1=%08X%08X, srcz2=%08X%08X, zinc=%08X",
4150 (uint32)(srcz1 >> 32), (uint32)(srcz1 & 0xFFFFFFFF),
4151 (uint32)(srcz2 >> 32), (uint32)(srcz2 & 0xFFFFFFFF), zinc);
4157 uint8 zSrcShift = srcshift & 0x30;
4158 srcz = (srcz2 << (64 - zSrcShift)) | (srcz1 >> zSrcShift);
4159 //bleh, ugly ugly ugly
4163 #if 0//def VERBOSE_BLITTER_LOGGING
4166 printf(" srcz=%08X%08X]\n", (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4171 //When in SRCSHADE mode, it adds the IINC to the read source (from LFU???)
4172 //According to following line, it gets LFU mode. But does it feed the source into the LFU
4174 //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)
4178 //NOTE: This is basically doubling the work done by DATA--since this is what
4179 // ADDARRAY is loaded with when srschshade is enabled... !!! FIX !!!
4180 // Also note that it doesn't work properly unless GOURZ is set--there's the clue!
4182 uint8 initcin[4] = { 0, 0, 0, 0 };
4183 ADDARRAY(addq, 4/*daddasel*/, 5/*daddbsel*/, 7/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4184 srcd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4186 //Seems to work... Not 100% sure tho.
4189 //Temporary kludge, to see if the fractional pattern does anything...
4191 //But it seems to mess up in Cybermorph... the shading should be smooth but it isn't...
4192 //Seems the carry out is lost again... !!! FIX !!! [DONE--see below]
4196 uint8 initcin[4] = { 0, 0, 0, 0 };
4197 ADDARRAY(addq, 4/*daddasel*/, 4/*daddbsel*/, 0/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4198 srcd1 = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
4201 //Note that we still don't take atick[0] & [1] into account here, so this will skip half of the data needed... !!! FIX !!!
4202 //Not yet enumerated: dbinh, srcdread, srczread
4203 //Also, should do srcshift on the z value in phrase mode... !!! FIX !!! [DONE]
4204 //As well as add a srcz variable we can set external to this state... !!! FIX !!! [DONE]
4208 DATA(wdata, dcomp, zcomp, winhibit,
4209 true, cmpdst, daddasel, daddbsel, daddmode, daddq_sel, data_sel, 0/*dbinh*/,
4210 dend, dstart, dstd, iinc, lfufunc, patd, patdadd,
4211 phrase_mode, srcd, false/*srcdread*/, false/*srczread*/, srcz2add, zmode,
4212 bcompen, bkgwren, dcompen, icount & 0x07, pixsize,
4215 Seems that the phrase mode writes with DCOMPEN and DSTEN are corrupting inside of DATA: !!! FIX !!!
4216 It's fairly random as well. 7CFE -> 7DFE, 7FCA -> 78CA, 7FA4 -> 78A4, 7F88 -> 8F88
4217 It could be related to an uninitialized variable, like the zmode bug...
4219 It was a bug in the dech38el data--it returned $FF for ungated instead of $00...
4221 Blit! (CMD = 09800609)
4222 Flags: SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
4224 a1_base = 00110000, a2_base = 0010B2A8
4225 a1_x = 004B, a1_y = 00D8, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0704, a2_y = 0000
4226 a1_step_x = FFF3, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFFC, a2_step_y = 0000
4227 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4228 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4229 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4230 a1_pixsize = 4, a2_pixsize = 4
4231 srcd=0000000000000000 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4232 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4234 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4235 Entering INNER state...
4236 Entering SREAD state... Source read address/pix address: 0010C0B0/0 [0000000078047804]
4237 Entering A2_ADD state [a2_x=0704, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4238 Entering DREAD state...
4239 Dest read address/pix address: 00197240/0 [0000000000000028]
4240 Entering DWRITE state...
4241 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)
4242 Entering A1_ADD state [a1_x=004B, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4243 Entering SREAD state... Source read address/pix address: 0010C0B8/0 [7804780478047804]
4244 Entering A2_ADD state [a2_x=0708, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4245 Entering DREAD state...
4246 Dest read address/pix address: 00197260/0 [0028000000200008]
4247 Entering DWRITE state...
4248 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)
4249 Entering A1_ADD state [a1_x=004C, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4250 Entering SREAD state... Source read address/pix address: 0010C0C0/0 [0000000000000000]
4251 Entering A2_ADD state [a2_x=070C, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4252 Entering DREAD state...
4253 Dest read address/pix address: 00197280/0 [0008001800180018]
4254 Entering DWRITE state...
4255 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)
4256 Entering A1_ADD state [a1_x=0050, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4257 Entering SREAD state... Source read address/pix address: 0010C0C8/0 [000078047BFE7BFE]
4258 Entering A2_ADD state [a2_x=0710, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4259 Entering DREAD state...
4260 Dest read address/pix address: 001972A0/0 [0008002000000000]
4261 Entering DWRITE state...
4262 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)
4263 Entering A1_ADD state [a1_x=0054, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4264 Entering IDLE_INNER state...
4267 //Why isn't this taken care of in DATA? Because, DATA is modifying its local copy instead of the one used here.
4268 //!!! FIX !!! [DONE]
4277 a1_outside // A1 pointer is outside window bounds
4286 // The address is outside if negative, or if greater than or equal
4287 // to the window size
4289 A1_xcomp := MAG_15 (a1xgr, a1xeq, a1xlt, a1_x{0..14}, a1_win_x{0..14});
4290 A1_ycomp := MAG_15 (a1ygr, a1yeq, a1ylt, a1_y{0..14}, a1_win_y{0..14});
4291 A1_outside := OR6 (a1_outside, a1_x{15}, a1xgr, a1xeq, a1_y{15}, a1ygr, a1yeq);
4293 //NOTE: There seems to be an off-by-one bug here in the clip_a1 section... !!! FIX !!!
4294 // Actually, seems to be related to phrase mode writes...
4295 // Or is it? Could be related to non-15-bit compares as above?
4296 if (clip_a1 && ((a1_x & 0x8000) || (a1_y & 0x8000) || (a1_x >= a1_win_x) || (a1_y >= a1_win_y)))
4303 JaguarWriteLong(address + 0, wdata >> 32, BLITTER);
4304 JaguarWriteLong(address + 4, wdata & 0xFFFFFFFF, BLITTER);
4309 JaguarWriteLong(address, wdata & 0xFFFFFFFF, BLITTER);
4310 else if (pixsize == 4)
4311 JaguarWriteWord(address, wdata & 0x0000FFFF, BLITTER);
4313 JaguarWriteByte(address, wdata & 0x000000FF, BLITTER);
4317 #ifdef VERBOSE_BLITTER_LOGGING
4320 printf(" [%08X%08X]%s", (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF), (winhibit ? "[X]" : ""));
4321 printf(" (icount=%04X, inc=%u)\n", icount, (uint16)inc);
4322 printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4323 printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4331 // OK, here's the big insight: When NOT in GOURZ mode, srcz1 & 2 function EXACTLY the same way that
4332 // srcd1 & 2 work--there's an implicit shift from srcz1 to srcz2 whenever srcz1 is read.
4333 // OTHERWISE, srcz1 is the integer for the computed Z and srcz2 is the fractional part.
4334 // Writes to srcz1 & 2 follow the same pattern as the other 64-bit registers--low 32 at the low address,
4335 // high 32 at the high address (little endian!).
4336 // NOTE: GOURZ is still not properly supported. Check patd/patf handling...
4337 // Phrase mode start/end masks are not properly supported either...
4338 #ifdef VERBOSE_BLITTER_LOGGING
4341 printf(" Entering DZWRITE state...");
4342 printf(" Dest Z write address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
4343 (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4347 //This is not correct... !!! FIX !!!
4348 //Should be OK now... We'll see...
4349 //Nope. Having the same starstep write problems in phrase mode as we had with pixels... !!! FIX !!!
4350 //This is not causing the problem in Hover Strike... :-/
4351 //The problem was with the SREADX not shifting. Still problems with Z comparisons & other text in pregame screen...
4356 JaguarWriteLong(address + 0, srcz >> 32, BLITTER);
4357 JaguarWriteLong(address + 4, srcz & 0xFFFFFFFF, BLITTER);
4362 JaguarWriteWord(address, srcz & 0x0000FFFF, BLITTER);
4365 #ifdef VERBOSE_BLITTER_LOGGING
4368 // printf(" [%08X%08X]\n", (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF));
4370 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4371 printf(" [dstart=? dend=? pwidth=? srcshift=%X]", srcshift);
4372 printf("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4379 This is because the address generator was using only 15 bits of the X when it should have
4382 There's a slight problem here: The X pointer isn't wrapping like it should when it hits
4383 the edge of the window... Notice how the X isn't reset at the edge of the window:
4385 Blit! (CMD = 00010000)
4388 a1_base = 000E8008, a2_base = 0001FA68
4389 a1_x = 0000, a1_y = 0000, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0000, a2_y = 0000
4390 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4391 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4392 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4393 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4394 a1_pixsize = 5, a2_pixsize = 5
4395 srcd=7717771777177717 dstd=0000000000000000 patd=7730773077307730 iinc=00000000
4396 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4398 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4399 Entering INNER state...
4400 Entering DWRITE state... Dest write address/pix address: 000E8008/0 [7730773077307730] (icount=009E, inc=2)
4401 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4402 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4403 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4404 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4405 Entering DWRITE state... Dest write address/pix address: 000E8018/0 [7730773077307730] (icount=009C, inc=2)
4406 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4407 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4408 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4409 Entering A1_ADD state [a1_x=0002, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4413 Entering A1_ADD state [a1_x=009C, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4414 Entering DWRITE state... Dest write address/pix address: 000E84F8/0 [7730773077307730] (icount=0000, inc=2)
4415 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4416 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4417 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4418 Entering A1_ADD state [a1_x=009E, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4419 Entering IDLE_INNER state...
4421 Leaving INNER state... (ocount=0104)
4422 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4424 Entering INNER state...
4425 Entering DWRITE state... Dest write address/pix address: 000E8508/0 [7730773077307730] (icount=009E, inc=2)
4426 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4427 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4428 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4429 Entering A1_ADD state [a1_x=00A0, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4430 Entering DWRITE state... Dest write address/pix address: 000E8518/0 [7730773077307730] (icount=009C, inc=2)
4431 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4432 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4433 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4434 Entering A1_ADD state [a1_x=00A2, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4440 #ifdef VERBOSE_BLITTER_LOGGING
4443 //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"));
4444 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"));
4448 int16 adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4449 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4450 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4451 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4452 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4454 #if 0//def VERBOSE_BLITTER_LOGGING
4457 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);
4461 //Now, write to what???
4462 //a2ptrld comes from a2ptrldi...
4463 //I believe it's addbsel that determines the writeback...
4464 // This is where atick[0] & [1] come in, in determining which part (fractional, integer)
4465 // gets written to...
4468 //Kludge, to get A1 channel increment working...
4471 a1_frac_x = addq_x, a1_frac_y = addq_y;
4473 addasel = 2, addbsel = 0, a1fracldi = false;
4474 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4475 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4476 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4477 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4479 a1_x = addq_x, a1_y = addq_y;
4482 a1_x = addq_x, a1_y = addq_y;
4487 #ifdef VERBOSE_BLITTER_LOGGING
4490 //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"));
4491 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"));
4495 //void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
4496 // int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
4497 // int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
4498 // bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
4499 //void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
4500 // int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
4501 //void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
4502 // int16 adda_x, int16 adda_y, int16 addb_x, int16 addb_y, uint8 modx, bool suba_x, bool suba_y)
4503 //void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
4504 int16 adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4505 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4506 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4507 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4508 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4510 #if 0//def VERBOSE_BLITTER_LOGGING
4513 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);
4517 //Now, write to what???
4518 //a2ptrld comes from a2ptrldi...
4519 //I believe it's addbsel that determines the writeback...
4525 Flags: SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
4527 a1_base = 0015B000, a2_base = 0014B000
4528 a1_x = 0000, a1_y = 0000, a1_frac_x = 8000, a1_frac_y = 8000, a2_x = 001F, a2_y = 0038
4529 a1_step_x = FFFFFFC0, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 2AAA, a2_step_x = FFFFFFC0, a2_step_y = 0001
4530 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4531 a1_win_x = 0040, a1_win_y = 0040, a2_mask_x = 0000, a2_mask_y = 0000
4532 a2_mask=F a1add=+inc/+0 a2add=+1/+0
4533 a1_pixsize = 4, a2_pixsize = 4
4534 srcd=FF00FF00FF00FF00 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4535 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, col=0
4537 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4538 Entering INNER state...
4539 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4540 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4541 Entering DWRITE state...
4542 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)
4543 Entering A2_ADD state [a2_x=001F, a2_y=0038, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4544 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4545 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4546 Entering DWRITE state...
4547 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)
4548 Entering A2_ADD state [a2_x=0021, a2_y=0039, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4549 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4550 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4551 Entering DWRITE state...
4552 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)
4553 Entering A2_ADD state [a2_x=0023, a2_y=003A, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4554 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4555 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4556 Entering DWRITE state...
4557 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)
4558 Entering A2_ADD state [a2_x=0025, a2_y=003B, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4560 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4561 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4562 Entering DWRITE state...
4563 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)
4564 Entering A2_ADD state [a2_x=009D, a2_y=0077, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4565 Entering IDLE_INNER state...
4566 Leaving INNER state... (ocount=0036)
4567 [in=F a1f=T a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4568 Entering A1FUPDATE state...
4569 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4570 Entering A1UPDATE state... (-32768/-32768 -> 32704/-32767)
4571 [in=F a1f=F a1=F zf=F z=F a2=T iif=F iii=F izf=F izi=F]
4572 Entering A2UPDATE state... (159/120 -> 95/121)
4573 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4574 Entering INNER state...
4577 #ifdef VERBOSE_BLITTER_LOGGING
4580 printf(" Leaving INNER state...");
4585 // The outer counter is updated here as well on the clock cycle...
4587 /* the inner loop is started whenever another state is about to
4588 cause the inner state to go active */
4589 //Instart := ND7 (instart, innert[0], innert[2..7]);
4591 //Actually, it's done only when inner gets asserted without the 2nd line of conditions
4592 //(inner AND !indone)
4594 //Since we don't get here until the inner loop is finished (indone = true) we can get
4595 //away with doing it here...!
4600 #ifdef VERBOSE_BLITTER_LOGGING
4603 printf(" (ocount=%04X)\n", ocount);
4611 #ifdef VERBOSE_BLITTER_LOGGING
4614 printf(" Entering A1FUPDATE state...\n");
4618 uint32 a1_frac_xt = (uint32)a1_frac_x + (uint32)a1_stepf_x;
4619 uint32 a1_frac_yt = (uint32)a1_frac_y + (uint32)a1_stepf_y;
4620 a1FracCInX = a1_frac_xt >> 16;
4621 a1FracCInY = a1_frac_yt >> 16;
4622 a1_frac_x = (uint16)(a1_frac_xt & 0xFFFF);
4623 a1_frac_y = (uint16)(a1_frac_yt & 0xFFFF);
4628 #ifdef VERBOSE_BLITTER_LOGGING
4631 printf(" Entering A1UPDATE state... (%d/%d -> ", a1_x, a1_y);
4635 a1_x += a1_step_x + a1FracCInX;
4636 a1_y += a1_step_y + a1FracCInY;
4637 #ifdef VERBOSE_BLITTER_LOGGING
4640 printf("%d/%d)\n", a1_x, a1_y);
4648 #ifdef VERBOSE_BLITTER_LOGGING
4651 printf(" Entering A2UPDATE state... (%d/%d -> ", a2_x, a2_y);
4657 #ifdef VERBOSE_BLITTER_LOGGING
4660 printf("%d/%d)\n", a2_x, a2_y);
4667 // We never get here! !!! FIX !!!
4669 #ifdef VERBOSE_BLITTER_LOGGING
4672 printf("Done!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
4673 GET16(blitter_ram, A1_PIXEL + 2),
4674 GET16(blitter_ram, A1_PIXEL + 0),
4675 GET16(blitter_ram, A1_FPIXEL + 2),
4676 GET16(blitter_ram, A1_FPIXEL + 0),
4677 GET16(blitter_ram, A2_PIXEL + 2),
4678 GET16(blitter_ram, A2_PIXEL + 0));
4683 // Write values back to registers (in real blitter, these are continuously updated)
4684 SET16(blitter_ram, A1_PIXEL + 2, a1_x);
4685 SET16(blitter_ram, A1_PIXEL + 0, a1_y);
4686 SET16(blitter_ram, A1_FPIXEL + 2, a1_frac_x);
4687 SET16(blitter_ram, A1_FPIXEL + 0, a1_frac_y);
4688 SET16(blitter_ram, A2_PIXEL + 2, a2_x);
4689 SET16(blitter_ram, A2_PIXEL + 0, a2_y);
4691 #ifdef VERBOSE_BLITTER_LOGGING
4694 printf("Writeback!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
4695 GET16(blitter_ram, A1_PIXEL + 2),
4696 GET16(blitter_ram, A1_PIXEL + 0),
4697 GET16(blitter_ram, A1_FPIXEL + 2),
4698 GET16(blitter_ram, A1_FPIXEL + 0),
4699 GET16(blitter_ram, A2_PIXEL + 2),
4700 GET16(blitter_ram, A2_PIXEL + 0));
4707 int16 a1_x = (int16)GET16(blitter_ram, A1_PIXEL + 2);
4708 int16 a1_y = (int16)GET16(blitter_ram, A1_PIXEL + 0);
4709 uint16 a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
4710 uint16 a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
4711 int16 a2_x = (int16)GET16(blitter_ram, A2_PIXEL + 2);
4712 int16 a2_y = (int16)GET16(blitter_ram, A2_PIXEL + 0);
4714 Seems that the ending a1_x should be written between blits, but it doesn't seem to be...
4716 Blit! (CMD = 01800000)
4719 a1_base = 00050000, a2_base = 00070000
4720 a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
4721 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4722 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4723 a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
4724 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4725 a1_pixsize = 4, a2_pixsize = 3
4726 srcd=DEDEDEDEDEDEDEDE dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4727 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4730 Blit! (CMD = 01800000)
4733 a1_base = 00050000, a2_base = 00070000
4734 a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
4735 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4736 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4737 a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
4738 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4739 a1_pixsize = 4, a2_pixsize = 3
4740 srcd=D6D6D6D6D6D6D6D6 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4741 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4747 // Various pieces of the blitter puzzle are teased out here...
4753 INT24/ address // byte address
4754 pixa[0..2] // bit part of address, un-pipe-lined
4770 apipe // load address pipe-line latch
4771 clk // co-processor clock
4772 gena2 // generate A2 as opposed to A1
4773 zaddr // generate Z address
4777 void ADDRGEN(uint32 &address, uint32 &pixa, bool gena2, bool zaddr,
4778 uint16 a1_x, uint16 a1_y, uint32 a1_base, uint8 a1_pitch, uint8 a1_pixsize, uint8 a1_width, uint8 a1_zoffset,
4779 uint16 a2_x, uint16 a2_y, uint32 a2_base, uint8 a2_pitch, uint8 a2_pixsize, uint8 a2_width, uint8 a2_zoffset)
4781 // uint16 x = (gena2 ? a2_x : a1_x) & 0x7FFF;
4782 uint16 x = (gena2 ? a2_x : a1_x) & 0xFFFF; // Actually uses all 16 bits to generate address...!
4783 uint16 y = (gena2 ? a2_y : a1_y) & 0x0FFF;
4784 uint8 width = (gena2 ? a2_width : a1_width);
4785 uint8 pixsize = (gena2 ? a2_pixsize : a1_pixsize);
4786 uint8 pitch = (gena2 ? a2_pitch : a1_pitch);
4787 uint32 base = (gena2 ? a2_base : a1_base) >> 3;//Only upper 21 bits are passed around the bus? Seems like it...
4788 uint8 zoffset = (gena2 ? a2_zoffset : a1_zoffset);
4790 uint32 ytm = ((uint32)y << 2) + (width & 0x02 ? (uint32)y << 1 : 0) + (width & 0x01 ? (uint32)y : 0);
4792 uint32 ya = (ytm << (width >> 2)) >> 2;
4796 /*uint32*/ pixa = pa << pixsize;
4798 uint8 pt = ((pitch & 0x01) && !(pitch & 0x02) ? 0x01 : 0x00)
4799 | (!(pitch & 0x01) && (pitch & 0x02) ? 0x02 : 0x00);
4800 // uint32 phradr = pixa << pt;
4801 uint32 phradr = (pixa >> 6) << pt;
4802 uint32 shup = (pitch == 0x03 ? (pixa >> 6) : 0);
4804 uint8 za = (zaddr ? zoffset : 0) & 0x03;
4805 // uint32 addr = za + (phradr & 0x07) + (shup << 1) + base;
4806 uint32 addr = za + phradr + (shup << 1) + base;
4807 /*uint32*/ address = ((pixa & 0x38) >> 3) | ((addr & 0x1FFFFF) << 3);
4808 #if 0//def VERBOSE_BLITTER_LOGGING
4811 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);
4812 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);
4818 Entering INNER state...
4819 [gena2=T, x=0002, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4820 [ytm=0, ya=0, pa=2, pixa=20, pt=0, phradr=0, shup=0, za=0, addr=12BA, address=95D4]
4821 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4822 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
4823 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4824 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4825 [ytm=0, ya=0, pa=4, pixa=40, pt=0, phradr=1, shup=0, za=0, addr=12BB, address=95D8]
4826 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4827 Source read address/pix address: 000095D8/0 [0054003800009814]
4828 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4829 [gena2=F, x=0000, y=0000, w=20, pxsz=4, ptch=0, b=00006E52, zoff=0]
4830 [ytm=0, ya=0, pa=0, pixa=0, pt=0, phradr=0, shup=0, za=0, addr=6E52, address=37290]
4831 Entering DWRITE state...
4832 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
4833 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4834 [gena2=T, x=0008, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4835 [ytm=0, ya=0, pa=8, pixa=80, pt=0, phradr=2, shup=0, za=0, addr=12BC, address=95E0]
4839 Entering SREAD state...
4840 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4841 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10AC, address=8560]
4842 Source read address/pix address: 00008560/0 [8C27981B327E00F0]
4844 2nd pass (still wrong):
4845 Entering SREAD state...
4846 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4847 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10EC, address=8760]
4848 Source read address/pix address: 00008760/0 [00E06DC04581880C]
4851 Entering SREAD state...
4852 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4853 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=1, shup=0, za=0, addr=10AD, address=8568]
4854 Source read address/pix address: 00008568/0 [6267981A327C00F0]
4856 OK, now we're back into incorrect (or is it?):
4857 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4858 Source extra read address/pix address: 000095D4/0 [0000 001C 0054 0038]
4859 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4860 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4861 Source read address/pix address: 000095D8/0 [0054 0038 0000 9814]
4862 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4863 I think this may be correct...!
4868 // source and destination address update conditions
4870 Sraat0 := AN2 (sraat[0], sreadxi, srcenz\);
4871 Sraat1 := AN2 (sraat[1], sreadi, srcenz\);
4872 Srca_addi := OR4 (srca_addi, szreadxi, szreadi, sraat[0..1]);
4873 Srca_add := FD1Q (srca_add, srca_addi, clk);
4875 Dstaat := AN2 (dstaat, dwritei, dstwrz\);
4876 Dsta_addi := OR2 (dsta_addi, dzwritei, dstaat);
4877 // Dsta_add := FD1Q (dsta_add, dsta_addi, clk);
4879 // source and destination address generate conditions
4881 Gensrc := OR4 (gensrc, sreadxi, szreadxi, sreadi, szreadi);
4882 Gendst := OR4 (gendst, dreadi, dzreadi, dwritei, dzwritei);
4883 Dsta2\ := INV1 (dsta2\, dsta2);
4884 Gena2t0 := NAN2 (gena2t[0], gensrc, dsta2\);
4885 Gena2t1 := NAN2 (gena2t[1], gendst, dsta2);
4886 Gena2i := NAN2 (gena2i, gena2t[0..1]);
4887 Gena2 := FD1QU (gena2, gena2i, clk);
4889 Zaddr := OR4 (zaddr, szreadx, szread, dzread, dzwrite);
4894 // Basically, the above translates to:
4895 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
4897 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
4899 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
4900 bool gendst = dreadi || szreadi || dwritei || dzwritei;
4901 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
4903 bool zaddr = szreadx || szread || dzread || dzwrite;
4907 // source data reads
4909 Srcdpset\ := NAN2 (srcdpset\, readreq, sread);
4910 Srcdpt1 := NAN2 (srcdpt[1], srcdpend, srcdack\);
4911 Srcdpt2 := NAN2 (srcdpt[2], srcdpset\, srcdpt[1]);
4912 Srcdpend := FD2Q (srcdpend, srcdpt[2], clk, reset\);
4914 Srcdxpset\ := NAN2 (srcdxpset\, readreq, sreadx);
4915 Srcdxpt1 := NAN2 (srcdxpt[1], srcdxpend, srcdxack\);
4916 Srcdxpt2 := NAN2 (srcdxpt[2], srcdxpset\, srcdxpt[1]);
4917 Srcdxpend := FD2Q (srcdxpend, srcdxpt[2], clk, reset\);
4919 Sdpend := OR2 (sdpend, srcdxpend, srcdpend);
4920 Srcdreadt := AN2 (srcdreadt, sdpend, read_ack);
4922 //2/9/92 - enhancement?
4923 //Load srcdread on the next tick as well to modify it in srcshade
4925 Srcdreadd := FD1Q (srcdreadd, srcdreadt, clk);
4926 Srcdread := AOR1 (srcdread, srcshade, srcdreadd, srcdreadt);
4930 Srczpset\ := NAN2 (srczpset\, readreq, szread);
4931 Srczpt1 := NAN2 (srczpt[1], srczpend, srczack\);
4932 Srczpt2 := NAN2 (srczpt[2], srczpset\, srczpt[1]);
4933 Srczpend := FD2Q (srczpend, srczpt[2], clk, reset\);
4935 Srczxpset\ := NAN2 (srczxpset\, readreq, szreadx);
4936 Srczxpt1 := NAN2 (srczxpt[1], srczxpend, srczxack\);
4937 Srczxpt2 := NAN2 (srczxpt[2], srczxpset\, srczxpt[1]);
4938 Srczxpend := FD2Q (srczxpend, srczxpt[2], clk, reset\);
4940 Szpend := OR2 (szpend, srczpend, srczxpend);
4941 Srczread := AN2 (srczread, szpend, read_ack);
4943 // destination data reads
4945 Dstdpset\ := NAN2 (dstdpset\, readreq, dread);
4946 Dstdpt0 := NAN2 (dstdpt[0], dstdpend, dstdack\);
4947 Dstdpt1 := NAN2 (dstdpt[1], dstdpset\, dstdpt[0]);
4948 Dstdpend := FD2Q (dstdpend, dstdpt[1], clk, reset\);
4949 Dstdread := AN2 (dstdread, dstdpend, read_ack);
4951 // destination zed reads
4953 Dstzpset\ := NAN2 (dstzpset\, readreq, dzread);
4954 Dstzpt0 := NAN2 (dstzpt[0], dstzpend, dstzack\);
4955 Dstzpt1 := NAN2 (dstzpt[1], dstzpset\, dstzpt[0]);
4956 Dstzpend := FD2Q (dstzpend, dstzpt[1], clk, reset\);
4957 Dstzread := AN2 (dstzread, dstzpend, read_ack);
4962 // Basically, the above translates to:
4963 bool srcdpend = (readreq && sread) || (srcdpend && !srcdack);
4964 bool srcdxpend = (readreq && sreadx) || (srcdxpend && !srcdxack);
4965 bool sdpend = srcxpend || srcdpend;
4966 bool srcdread = ((sdpend && read_ack) && srcshade) || (sdpend && read_ack);//the latter term is lookahead
4970 ////////////////////////////////////////////////////////////////////////////////////////////
4971 ////////////////////////////////////////////////////////////////////////////////////////////
4972 // Here's an important bit: The source data adder logic. Need to track down the inputs!!! //
4973 ////////////////////////////////////////////////////////////////////////////////////////////
4974 ////////////////////////////////////////////////////////////////////////////////////////////
4981 daddasel[0..2] // data adder input A selection
4986 initcin[0..3] // carry into the adders from the initializers
4987 initinc[0..63] // the initialisation increment
4988 initpix[0..15] // Data initialiser pixel value
5000 void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
5001 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
5002 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
5003 uint32 zinc, uint32 zstep)
5005 uint32 initpix2 = ((uint32)initpix << 16) | initpix;
5006 uint32 addalo[8], addahi[8];
5007 addalo[0] = dstd & 0xFFFFFFFF;
5008 addalo[1] = initpix2;
5011 addalo[4] = srcd & 0xFFFFFFFF;
5012 addalo[5] = patd & 0xFFFFFFFF;
5013 addalo[6] = srcz1 & 0xFFFFFFFF;
5014 addalo[7] = srcz2 & 0xFFFFFFFF;
5015 addahi[0] = dstd >> 32;
5016 addahi[1] = initpix2;
5019 addahi[4] = srcd >> 32;
5020 addahi[5] = patd >> 32;
5021 addahi[6] = srcz1 >> 32;
5022 addahi[7] = srcz2 >> 32;
5024 adda[0] = addalo[daddasel] & 0xFFFF;
5025 adda[1] = addalo[daddasel] >> 16;
5026 adda[2] = addahi[daddasel] & 0xFFFF;
5027 adda[3] = addahi[daddasel] >> 16;
5030 wordmux[0] = iinc & 0xFFFF;
5031 wordmux[1] = iinc >> 16;
5032 wordmux[2] = zinc & 0xFFFF;
5033 wordmux[3] = zinc >> 16;;
5034 wordmux[4] = istep & 0xFFFF;
5035 wordmux[5] = istep >> 16;;
5036 wordmux[6] = zstep & 0xFFFF;
5037 wordmux[7] = zstep >> 16;;
5038 uint16 word = wordmux[((daddbsel & 0x08) >> 1) | (daddbsel & 0x03)];
5040 bool dbsel2 = daddbsel & 0x04;
5041 bool iincsel = (daddbsel & 0x01) && !(daddbsel & 0x04);
5043 if (!dbsel2 && !iincsel)
5044 addb[0] = srcd & 0xFFFF,
5045 addb[1] = (srcd >> 16) & 0xFFFF,
5046 addb[2] = (srcd >> 32) & 0xFFFF,
5047 addb[3] = (srcd >> 48) & 0xFFFF;
5048 else if (dbsel2 && !iincsel)
5049 addb[0] = addb[1] = addb[2] = addb[3] = word;
5050 else if (!dbsel2 && iincsel)
5051 addb[0] = initinc & 0xFFFF,
5052 addb[1] = (initinc >> 16) & 0xFFFF,
5053 addb[2] = (initinc >> 32) & 0xFFFF,
5054 addb[3] = (initinc >> 48) & 0xFFFF;
5056 addb[0] = addb[1] = addb[2] = addb[3] = 0;
5058 uint8 cinsel = (daddmode >= 1 && daddmode <= 4 ? 1 : 0);
5060 static uint8 co[4];//These are preserved between calls...
5063 for(int i=0; i<4; i++)
5064 cin[i] = initcin[i] | (co[i] & cinsel);
5066 bool eightbit = daddmode & 0x02;
5067 bool sat = daddmode & 0x03;
5068 bool hicinh = ((daddmode & 0x03) == 0x03);
5070 //Note that the carry out is saved between calls to this function...
5071 for(int i=0; i<4; i++)
5072 ADD16SAT(addq[i], co[i], adda[i], addb[i], cin[i], sat, eightbit, hicinh);
5088 void ADD16SAT(uint16 &r, uint8 &co, uint16 a, uint16 b, uint8 cin, bool sat, bool eightbit, bool hicinh)
5092 printf("--> [sat=%s 8b=%s hicinh=%s] %04X + %04X (+ %u) = ", (sat ? "T" : "F"), (eightbit ? "T" : "F"), (hicinh ? "T" : "F"), a, b, cin);
5096 uint32 qt = (a & 0xFF) + (b & 0xFF) + cin;
5097 carry[0] = (qt & 0x0100 ? 1 : 0);
5098 uint16 q = qt & 0x00FF;
5099 carry[1] = (carry[0] && !eightbit ? carry[0] : 0);
5100 qt = (a & 0x0F00) + (b & 0x0F00) + (carry[1] << 8);
5101 carry[2] = (qt & 0x1000 ? 1 : 0);
5103 carry[3] = (carry[2] && !hicinh ? carry[2] : 0);
5104 qt = (a & 0xF000) + (b & 0xF000) + (carry[3] << 12);
5105 co = (qt & 0x10000 ? 1 : 0);
5108 uint8 btop = (eightbit ? (b & 0x0080) >> 7 : (b & 0x8000) >> 15);
5109 uint8 ctop = (eightbit ? carry[0] : co);
5111 bool saturate = sat && (btop ^ ctop);
5112 bool hisaturate = saturate && !eightbit;
5115 printf("bt=%u ct=%u s=%u hs=%u] ", btop, ctop, saturate, hisaturate);
5119 r = (saturate ? (ctop ? 0x00FF : 0x0000) : q & 0x00FF);
5120 r |= (hisaturate ? (ctop ? 0xFF00 : 0x0000) : q & 0xFF00);
5123 printf("%04X (co=%u)\n", r, co);
5128 /** ADDAMUX - Address adder input A selection *******************
5130 This module generates the data loaded into the address adder input A. This is
5131 the update value, and can be one of four registers : A1 step, A2 step, A1
5132 increment and A1 fraction. It can complement these values to perform
5133 subtraction, and it can generate constants to increment / decrement the window
5136 addasel[0..2] select the register to add
5138 000 A1 step integer part
5139 001 A1 step fraction part
5140 010 A1 increment integer part
5141 011 A1 increment fraction part
5144 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all zeroes when
5147 addareg selects register value to be added as opposed to constant
5150 suba_x, suba_y complement the X and Y values
5176 void ADDAMUX(int16 &adda_x, int16 &adda_y, uint8 addasel, int16 a1_step_x, int16 a1_step_y,
5177 int16 a1_stepf_x, int16 a1_stepf_y, int16 a2_step_x, int16 a2_step_y,
5178 int16 a1_inc_x, int16 a1_inc_y, int16 a1_incf_x, int16 a1_incf_y, uint8 adda_xconst,
5179 bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
5182 /*INT16/ addac_x, addac_y, addar_x, addar_y, addart_x, addart_y,
5183 INT16/ addas_x, addas_y, suba_x16, suba_y16
5187 Zero := TIE0 (zero);*/
5189 /* Multiplex the register terms */
5191 /*Addaselb[0-2] := BUF8 (addaselb[0-2], addasel[0-2]);
5192 Addart_x := MX4 (addart_x, a1_step_x, a1_stepf_x, a1_inc_x, a1_incf_x, addaselb[0..1]);
5193 Addar_x := MX2 (addar_x, addart_x, a2_step_x, addaselb[2]);
5194 Addart_y := MX4 (addart_y, a1_step_y, a1_stepf_y, a1_inc_y, a1_incf_y, addaselb[0..1]);
5195 Addar_y := MX2 (addar_y, addart_y, a2_step_y, addaselb[2]);*/
5197 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5198 int16 xterm[4], yterm[4];
5199 xterm[0] = a1_step_x, xterm[1] = a1_stepf_x, xterm[2] = a1_inc_x, xterm[3] = a1_incf_x;
5200 yterm[0] = a1_step_y, yterm[1] = a1_stepf_y, yterm[2] = a1_inc_y, yterm[3] = a1_incf_y;
5201 int16 addar_x = (addasel & 0x04 ? a2_step_x : xterm[addasel & 0x03]);
5202 int16 addar_y = (addasel & 0x04 ? a2_step_y : yterm[addasel & 0x03]);
5203 //////////////////////////////////////////////////////////////////////////////////////
5205 /* Generate a constant value - this is a power of 2 in the range
5206 0-64, or zero. The control bits are adda_xconst[0..2], when they
5207 are all 1 the result is 0.
5208 Constants for Y can only be 0 or 1 */
5210 /*Addac_xlo := D38H (addac_x[0..6], unused[0], adda_xconst[0..2]);
5211 Unused[0] := DUMMY (unused[0]);
5213 Addac_x := JOIN (addac_x, addac_x[0..6], zero, zero, zero, zero, zero, zero, zero, zero, zero);
5214 Addac_y := JOIN (addac_y, adda_yconst, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero,
5215 zero, zero, zero, zero, zero);*/
5216 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5217 int16 addac_x = (adda_xconst == 0x07 ? 0 : 1 << adda_xconst);
5218 int16 addac_y = (adda_yconst ? 0x01 : 0);
5219 //////////////////////////////////////////////////////////////////////////////////////
5221 /* Select between constant value and register value */
5223 /*Addas_x := MX2 (addas_x, addac_x, addar_x, addareg);
5224 Addas_y := MX2 (addas_y, addac_y, addar_y, addareg);*/
5225 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5226 int16 addas_x = (addareg ? addar_x : addac_x);
5227 int16 addas_y = (addareg ? addar_y : addac_y);
5228 //////////////////////////////////////////////////////////////////////////////////////
5230 /* Complement these values (complement flag gives adder carry in)*/
5232 /*Suba_x16 := JOIN (suba_x16, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x,
5233 suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x);
5234 Suba_y16 := JOIN (suba_y16, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y,
5235 suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y);
5236 Adda_x := EO (adda_x, suba_x16, addas_x);
5237 Adda_y := EO (adda_y, suba_y16, addas_y);*/
5238 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5239 adda_x = addas_x ^ (suba_x ? 0xFFFF : 0x0000);
5240 adda_y = addas_y ^ (suba_y ? 0xFFFF : 0x0000);
5241 //////////////////////////////////////////////////////////////////////////////////////
5246 /** ADDBMUX - Address adder input B selection *******************
5248 This module selects the register to be updated by the address
5249 adder. This can be one of three registers, the A1 and A2
5250 pointers, or the A1 fractional part. It can also be zero, so that the step
5251 registers load directly into the pointers.
5266 INT16/ zero16 :LOCAL;
5268 void ADDBMUX(int16 &addb_x, int16 &addb_y, uint8 addbsel, int16 a1_x, int16 a1_y,
5269 int16 a2_x, int16 a2_y, int16 a1_frac_x, int16 a1_frac_y)
5272 /*Zero := TIE0 (zero);
5273 Zero16 := JOIN (zero16, zero, zero, zero, zero, zero, zero, zero,
5274 zero, zero, zero, zero, zero, zero, zero, zero, zero);
5275 Addbselb[0-1] := BUF8 (addbselb[0-1], addbsel[0-1]);
5276 Addb_x := MX4 (addb_x, a1_x, a2_x, a1_frac_x, zero16, addbselb[0..1]);
5277 Addb_y := MX4 (addb_y, a1_y, a2_y, a1_frac_y, zero16, addbselb[0..1]);*/
5278 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5279 int16 xterm[4], yterm[4];
5280 xterm[0] = a1_x, xterm[1] = a2_x, xterm[2] = a1_frac_x, xterm[3] = 0;
5281 yterm[0] = a1_y, yterm[1] = a2_y, yterm[2] = a1_frac_y, yterm[3] = 0;
5282 addb_x = xterm[addbsel & 0x03];
5283 addb_y = yterm[addbsel & 0x03];
5284 //////////////////////////////////////////////////////////////////////////////////////
5289 /** DATAMUX - Address local data bus selection ******************
5291 Select between the adder output and the input data bus
5304 INT16/ gpu_lo, gpu_hi
5307 void DATAMUX(int16 &data_x, int16 &data_y, uint32 gpu_din, int16 addq_x, int16 addq_y, bool addqsel)
5309 /*Gpu_lo := JOIN (gpu_lo, gpu_din{0..15});
5310 Gpu_hi := JOIN (gpu_hi, gpu_din{16..31});
5312 Addqselb := BUF8 (addqselb, addqsel);
5313 Data_x := MX2 (data_x, gpu_lo, addq_x, addqselb);
5314 Data_y := MX2 (data_y, gpu_hi, addq_y, addqselb);*/
5315 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5316 data_x = (addqsel ? addq_x : (int16)(gpu_din & 0xFFFF));
5317 data_y = (addqsel ? addq_y : (int16)(gpu_din >> 16));
5318 //////////////////////////////////////////////////////////////////////////////////////
5323 /******************************************************************
5327 Blitter Address Adder
5328 ---------------------
5329 The blitter address adder is a pair of sixteen bit adders, one
5330 each for X and Y. The multiplexing of the input terms is
5331 performed elsewhere, but this adder can also perform modulo
5332 arithmetic to align X-addresses onto phrase boundaries.
5334 modx[0..2] take values
5341 ******************************************************************/
5343 /*IMPORT duplo, tosh;
5349 a1fracldi // propagate address adder carry
5354 clk[0] // co-processor clock
5362 Zero := TIE0 (zero);*/
5363 void ADDRADD(int16 &addq_x, int16 &addq_y, bool a1fracldi,
5364 uint16 adda_x, uint16 adda_y, uint16 addb_x, uint16 addb_y, uint8 modx, bool suba_x, bool suba_y)
5367 /* Perform the addition */
5369 /*Adder_x := ADD16 (addqt_x[0..15], co_x, adda_x{0..15}, addb_x{0..15}, ci_x);
5370 Adder_y := ADD16 (addq_y[0..15], co_y, adda_y{0..15}, addb_y{0..15}, ci_y);*/
5372 /* latch carry and propagate if required */
5374 /*Cxt0 := AN2 (cxt[0], co_x, a1fracldi);
5375 Cxt1 := FD1Q (cxt[1], cxt[0], clk[0]);
5376 Ci_x := EO (ci_x, cxt[1], suba_x);
5378 yt0 := AN2 (cyt[0], co_y, a1fracldi);
5379 Cyt1 := FD1Q (cyt[1], cyt[0], clk[0]);
5380 Ci_y := EO (ci_y, cyt[1], suba_y);*/
5382 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5383 //I'm sure the following will generate a bunch of warnings, but will have to do for now.
5384 static uint16 co_x = 0, co_y = 0; // Carry out has to propogate between function calls...
5385 uint16 ci_x = co_x ^ (suba_x ? 1 : 0);
5386 uint16 ci_y = co_y ^ (suba_y ? 1 : 0);
5387 uint32 addqt_x = adda_x + addb_x + ci_x;
5388 uint32 addqt_y = adda_y + addb_y + ci_y;
5389 co_x = ((addqt_x & 0x10000) && a1fracldi ? 1 : 0);
5390 co_y = ((addqt_y & 0x10000) && a1fracldi ? 1 : 0);
5391 //////////////////////////////////////////////////////////////////////////////////////
5393 /* Mask low bits of X to 0 if required */
5395 /*Masksel := D38H (unused[0], masksel[0..4], maskbit[5], unused[1], modx[0..2]);
5397 Maskbit[0-4] := OR2 (maskbit[0-4], masksel[0-4], maskbit[1-5]);
5399 Mask[0-5] := MX2 (addq_x[0-5], addqt_x[0-5], zero, maskbit[0-5]);
5401 Addq_x := JOIN (addq_x, addq_x[0..5], addqt_x[6..15]);
5402 Addq_y := JOIN (addq_y, addq_y[0..15]);*/
5404 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5405 int16 mask[8] = { 0xFFFF, 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, 0xFFE0, 0xFFC0, 0x0000 };
5406 addq_x = addqt_x & mask[modx];
5407 addq_y = addqt_y & 0xFFFF;
5408 //////////////////////////////////////////////////////////////////////////////////////
5410 //Unused[0-1] := DUMMY (unused[0-1]);
5417 wdata[0..63] // co-processor write data bus
5419 dcomp[0..7] // data byte equal flags
5420 srcd[0..7] // bits to use for bit to byte expansion
5421 zcomp[0..3] // output from Z comparators
5423 a1_x[0..1] // low two bits of A1 X pointer
5424 big_pix // pixel organisation is big-endian
5425 blitter_active // blitter is active
5426 clk // co-processor clock
5427 cmpdst // compare dest rather than source
5428 colorld // load the pattern color fields
5429 daddasel[0..2] // data adder input A selection
5430 daddbsel[0..3] // data adder input B selection
5431 daddmode[0..2] // data adder mode
5432 daddq_sel // select adder output vs. GPU data
5433 data[0..63] // co-processor read data bus
5434 data_ena // enable write data
5435 data_sel[0..1] // select data to write
5436 dbinh\[0..7] // byte oriented changed data inhibits
5437 dend[0..5] // end of changed write data zone
5438 dpipe[0..1] // load computed data pipe-line latch
5439 dstart[0..5] // start of changed write data zone
5440 dstdld[0..1] // dest data load (two halves)
5441 dstzld[0..1] // dest zed load (two halves)
5442 ext_int // enable extended precision intensity calculations
5443 INT32/ gpu_din // GPU data bus
5444 iincld // I increment load
5445 iincldx // alternate I increment load
5446 init_if // initialise I fraction phase
5447 init_ii // initialise I integer phase
5448 init_zf // initialise Z fraction phase
5449 intld[0..3] // computed intensities load
5450 istepadd // intensity step integer add
5451 istepfadd // intensity step fraction add
5452 istepld // I step load
5453 istepdld // I step delta load
5454 lfu_func[0..3] // LFU function code
5455 patdadd // pattern data gouraud add
5456 patdld[0..1] // pattern data load (two halves)
5457 pdsel[0..1] // select pattern data type
5458 phrase_mode // phrase write mode
5459 reload // transfer contents of double buffers
5460 reset\ // system reset
5461 srcd1ld[0..1] // source register 1 load (two halves)
5462 srcdread // source data read load enable
5463 srczread // source zed read load enable
5464 srcshift[0..5] // source alignment shift
5465 srcz1ld[0..1] // source zed 1 load (two halves)
5466 srcz2add // zed fraction gouraud add
5467 srcz2ld[0..1] // source zed 2 load (two halves)
5468 textrgb // texture mapping in RGB mode
5469 txtd[0..63] // data from the texture unit
5470 zedld[0..3] // computed zeds load
5471 zincld // Z increment load
5472 zmode[0..2] // Z comparator mode
5473 zpipe[0..1] // load computed zed pipe-line latch
5474 zstepadd // zed step integer add
5475 zstepfadd // zed step fraction add
5476 zstepld // Z step load
5477 zstepdld // Z step delta load
5481 void DATA(uint64 &wdata, uint8 &dcomp, uint8 &zcomp, bool &nowrite,
5482 bool big_pix, bool cmpdst, uint8 daddasel, uint8 daddbsel, uint8 daddmode, bool daddq_sel, uint8 data_sel,
5483 uint8 dbinh, uint8 dend, uint8 dstart, uint64 dstd, uint32 iinc, uint8 lfu_func, uint64 &patd, bool patdadd,
5484 bool phrase_mode, uint64 srcd, bool srcdread, bool srczread, bool srcz2add, uint8 zmode,
5485 bool bcompen, bool bkgwren, bool dcompen, uint8 icount, uint8 pixsize,
5486 uint64 &srcz, uint64 dstz, uint32 zinc)
5489 Stuff we absolutely *need* to have passed in/out:
5491 patdadd, dstd, srcd, patd, daddasel, daddbsel, daddmode, iinc, srcz1, srcz2, big_pix, phrase_mode, cmpdst
5493 changed patd (wdata I guess...) (Nope. We pass it back directly now...)
5496 // Source data registers
5498 /*Data_src := DATA_SRC (srcdlo, srcdhi, srcz[0..1], srczo[0..1], srczp[0..1], srcz1[0..1], srcz2[0..1], big_pix,
5499 clk, gpu_din, intld[0..3], local_data0, local_data1, srcd1ld[0..1], srcdread, srczread, srcshift[0..5],
5500 srcz1ld[0..1], srcz2add, srcz2ld[0..1], zedld[0..3], zpipe[0..1]);
5501 Srcd[0-7] := JOIN (srcd[0-7], srcdlo{0-7});
5502 Srcd[8-31] := JOIN (srcd[8-31], srcdlo{8-31});
5503 Srcd[32-63] := JOIN (srcd[32-63], srcdhi{0-31});*/
5505 // Destination data registers
5507 /*Data_dst := DATA_DST (dstd[0..63], dstz[0..1], clk, dstdld[0..1], dstzld[0..1], load_data[0..1]);
5508 Dstdlo := JOIN (dstdlo, dstd[0..31]);
5509 Dstdhi := JOIN (dstdhi, dstd[32..63]);*/
5511 // Pattern and Color data registers
5513 // Looks like this is simply another register file for the pattern data registers. No adding or anything funky
5514 // going on. Note that patd & patdv will output the same info.
5515 // Patdldl/h (patdld[0..1]) can select the local_data bus to overwrite the current pattern data...
5516 // Actually, it can be either patdld OR patdadd...!
5517 /*Data_pat := DATA_PAT (colord[0..15], int0dp[8..10], int1dp[8..10], int2dp[8..10], int3dp[8..10], mixsel[0..2],
5518 patd[0..63], patdv[0..1], clk, colorld, dpipe[0], ext_int, gpu_din, intld[0..3], local_data0, local_data1,
5519 patdadd, patdld[0..1], reload, reset\);
5520 Patdlo := JOIN (patdlo, patd[0..31]);
5521 Patdhi := JOIN (patdhi, patd[32..63]);*/
5523 // Multiplying data Mixer (NOT IN JAGUAR I)
5525 /*Datamix := DATAMIX (patdo[0..1], clk, colord[0..15], dpipe[1], dstd[0..63], int0dp[8..10], int1dp[8..10],
5526 int2dp[8..10], int3dp[8..10], mixsel[0..2], patd[0..63], pdsel[0..1], srcd[0..63], textrgb, txtd[0..63]);*/
5528 // Logic function unit
5530 /*Lfu := LFU (lfu[0..1], srcdlo, srcdhi, dstdlo, dstdhi, lfu_func[0..3]);*/
5531 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5532 uint64 funcmask[2] = { 0, 0xFFFFFFFFFFFFFFFFLL };
5533 uint64 func0 = funcmask[lfu_func & 0x01];
5534 uint64 func1 = funcmask[(lfu_func >> 1) & 0x01];
5535 uint64 func2 = funcmask[(lfu_func >> 2) & 0x01];
5536 uint64 func3 = funcmask[(lfu_func >> 3) & 0x01];
5537 uint64 lfu = (~srcd & ~dstd & func0) | (~srcd & dstd & func1) | (srcd & ~dstd & func2) | (srcd & dstd & func3);
5538 //////////////////////////////////////////////////////////////////////////////////////
5540 // Increment and Step Registers
5542 // Does it do anything without the step add lines? Check it!
5543 // No. This is pretty much just a register file without the Jaguar II lines...
5544 /*Inc_step := INC_STEP (iinc, istep[0..31], zinc, zstep[0..31], clk, ext_int, gpu_din, iincld, iincldx, istepadd,
5545 istepfadd, istepld, istepdld, reload, reset\, zincld, zstepadd, zstepfadd, zstepld, zstepdld);
5546 Istep := JOIN (istep, istep[0..31]);
5547 Zstep := JOIN (zstep, zstep[0..31]);*/
5549 // Pixel data comparator
5551 /*Datacomp := DATACOMP (dcomp[0..7], cmpdst, dstdlo, dstdhi, patdlo, patdhi, srcdlo, srcdhi);*/
5552 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5554 uint64 cmpd = patd ^ (cmpdst ? dstd : srcd);
5556 if ((cmpd & 0x00000000000000FFLL) == 0)
5558 if ((cmpd & 0x000000000000FF00LL) == 0)
5560 if ((cmpd & 0x0000000000FF0000LL) == 0)
5562 if ((cmpd & 0x00000000FF000000LL) == 0)
5564 if ((cmpd & 0x000000FF00000000LL) == 0)
5566 if ((cmpd & 0x0000FF0000000000LL) == 0)
5568 if ((cmpd & 0x00FF000000000000LL) == 0)
5570 if ((cmpd & 0xFF00000000000000LL) == 0)
5572 //////////////////////////////////////////////////////////////////////////////////////
5574 // Zed comparator for Z-buffer operations
5576 /*Zedcomp := ZEDCOMP (zcomp[0..3], srczp[0..1], dstz[0..1], zmode[0..2]);*/
5577 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5578 //srczp is srcz pipelined, also it goes through a source shift as well...
5579 /*The shift is basically like so (each piece is 16 bits long):
5582 srcz1lolo srcz1lohi srcz1hilo srcz1hihi srcrz2lolo srcz2lohi srcz2hilo
5584 with srcshift bits 4 & 5 selecting the start position
5586 //So... basically what we have here is:
5589 if ((((srcz & 0x000000000000FFFFLL) < (dstz & 0x000000000000FFFFLL)) && (zmode & 0x01))
5590 || (((srcz & 0x000000000000FFFFLL) == (dstz & 0x000000000000FFFFLL)) && (zmode & 0x02))
5591 || (((srcz & 0x000000000000FFFFLL) > (dstz & 0x000000000000FFFFLL)) && (zmode & 0x04)))
5594 if ((((srcz & 0x00000000FFFF0000LL) < (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x01))
5595 || (((srcz & 0x00000000FFFF0000LL) == (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x02))
5596 || (((srcz & 0x00000000FFFF0000LL) > (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x04)))
5599 if ((((srcz & 0x0000FFFF00000000LL) < (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x01))
5600 || (((srcz & 0x0000FFFF00000000LL) == (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x02))
5601 || (((srcz & 0x0000FFFF00000000LL) > (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x04)))
5604 if ((((srcz & 0xFFFF000000000000LL) < (dstz & 0xFFFF000000000000LL)) && (zmode & 0x01))
5605 || (((srcz & 0xFFFF000000000000LL) == (dstz & 0xFFFF000000000000LL)) && (zmode & 0x02))
5606 || (((srcz & 0xFFFF000000000000LL) > (dstz & 0xFFFF000000000000LL)) && (zmode & 0x04)))
5609 //TEMP, TO TEST IF ZCOMP IS THE CULPRIT...
5610 //Nope, this is NOT the problem...
5612 // We'll do the comparison/bit/byte inhibits here, since that's they way it happens
5613 // in the real thing (dcomp goes out to COMP_CTRL and back into DATA through dbinh)...
5617 COMP_CTRL(dbinht, nowrite,
5618 bcompen, true/*big_pix*/, bkgwren, dcomp, dcompen, icount, pixsize, phrase_mode, srcd & 0xFF, zcomp);
5624 #ifdef VERBOSE_BLITTER_LOGGING
5627 printf("\n[dcomp=%02X zcomp=%02X dbinh=%02X]\n", dcomp, zcomp, dbinh);
5632 //////////////////////////////////////////////////////////////////////////////////////
5635 // The data initializer - allows all four initial values to be computed from one (NOT IN JAGUAR I)
5637 /*Datinit := DATINIT (initcin[0..3], initinc[0..63], initpix[0..15], a1_x[0..1], big_pix, clk, iinc, init_if, init_ii,
5638 init_zf, istep[0..31], zinc, zstep[0..31]);*/
5640 // Adder array for Z and intensity increments
5642 /*Addarray := ADDARRAY (addq[0..3], clk, daddasel[0..2], daddbsel[0..3], daddmode[0..2], dstdlo, dstdhi, iinc,
5643 initcin[0..3], initinc[0..63], initpix[0..15], istep, patdv[0..1], srcdlo, srcdhi, srcz1[0..1],
5644 srcz2[0..1], reset\, zinc, zstep);*/
5645 /*void ADDARRAY(uint16 * addq, uint8 daddasel, uint8 daddbsel, uint8 daddmode,
5646 uint64 dstd, uint32 iinc, uint8 initcin[], uint64 initinc, uint16 initpix,
5647 uint32 istep, uint64 patd, uint64 srcd, uint64 srcz1, uint64 srcz2,
5648 uint32 zinc, uint32 zstep)*/
5649 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5651 uint8 initcin[4] = { 0, 0, 0, 0 };
5652 ADDARRAY(addq, daddasel, daddbsel, daddmode, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
5654 //This is normally done asynchronously above (thru local_data) when in patdadd mode...
5655 //And now it's passed back to the caller to be persistent between calls...!
5656 //But it's causing some serious fuck-ups in T2K now... !!! FIX !!! [DONE--???]
5657 //Weird! It doesn't anymore...!
5659 patd = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
5660 //////////////////////////////////////////////////////////////////////////////////////
5662 // Local data bus multiplexer
5664 /*Local_mux := LOCAL_MUX (local_data[0..1], load_data[0..1],
5665 addq[0..3], gpu_din, data[0..63], blitter_active, daddq_sel);
5666 Local_data0 := JOIN (local_data0, local_data[0]);
5667 Local_data1 := JOIN (local_data1, local_data[1]);*/
5668 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5669 //////////////////////////////////////////////////////////////////////////////////////
5671 // Data output multiplexer and tri-state drive
5673 /*Data_mux := DATA_MUX (wdata[0..63], addq[0..3], big_pix, dstdlo, dstdhi, dstz[0..1], data_sel[0..1], data_ena,
5674 dstart[0..5], dend[0..5], dbinh\[0..7], lfu[0..1], patdo[0..1], phrase_mode, srczo[0..1]);*/
5675 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5676 // NOTE: patdo comes from DATAMIX and can be considered the same as patd for Jaguar I
5678 //////////////////////////////////////////////////////////////////////////////////////
5682 wdata[0..63] // co-processor rwrite data bus
5685 big_pix // Pixel organisation is big-endian
5690 data_sel[0..1] // source of write data
5691 data_ena // enable write data onto read/write bus
5692 dstart[0..5] // start of changed write data
5693 dend[0..5] // end of changed write data
5694 dbinh\[0..7] // byte oriented changed data inhibits
5697 phrase_mode // phrase write mode
5702 /*INT32/ addql[0..1], ddatlo, ddathi zero32
5706 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5707 Zero := TIE0 (zero);
5708 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);*/
5710 /* Generate a changed data mask */
5712 /*Edis := OR6 (edis\, dend[0..5]);
5713 Ecoarse := DECL38E (e_coarse\[0..7], dend[3..5], edis\);
5714 E_coarse[0] := INV1 (e_coarse[0], e_coarse\[0]);
5715 Efine := DECL38E (unused[0], e_fine\[1..7], dend[0..2], e_coarse[0]);*/
5716 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5717 uint8 decl38e[2][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
5718 { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } };
5719 uint8 dech38[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
5720 uint8 dech38el[2][8] = { { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
5721 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
5723 int en = (dend & 0x3F ? 1 : 0);
5724 uint8 e_coarse = decl38e[en][(dend & 0x38) >> 3]; // Actually, this is e_coarse inverted...
5725 uint8 e_fine = decl38e[(e_coarse & 0x01) ^ 0x01][dend & 0x07];
5727 //////////////////////////////////////////////////////////////////////////////////////
5729 /*Scoarse := DECH38 (s_coarse[0..7], dstart[3..5]);
5730 Sfen\ := INV1 (sfen\, s_coarse[0]);
5731 Sfine := DECH38EL (s_fine[0..7], dstart[0..2], sfen\);*/
5732 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5733 uint8 s_coarse = dech38[(dstart & 0x38) >> 3];
5734 uint8 s_fine = dech38el[(s_coarse & 0x01) ^ 0x01][dstart & 0x07];
5735 //////////////////////////////////////////////////////////////////////////////////////
5737 /*Maskt[0] := BUF1 (maskt[0], s_fine[0]);
5738 Maskt[1-7] := OAN1P (maskt[1-7], maskt[0-6], s_fine[1-7], e_fine\[1-7]);*/
5739 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5740 uint16 maskt = s_fine & 0x0001;
5741 maskt |= (((maskt & 0x0001) || (s_fine & 0x02)) && (e_fine & 0x02) ? 0x0002 : 0x0000);
5742 maskt |= (((maskt & 0x0002) || (s_fine & 0x04)) && (e_fine & 0x04) ? 0x0004 : 0x0000);
5743 maskt |= (((maskt & 0x0004) || (s_fine & 0x08)) && (e_fine & 0x08) ? 0x0008 : 0x0000);
5744 maskt |= (((maskt & 0x0008) || (s_fine & 0x10)) && (e_fine & 0x10) ? 0x0010 : 0x0000);
5745 maskt |= (((maskt & 0x0010) || (s_fine & 0x20)) && (e_fine & 0x20) ? 0x0020 : 0x0000);
5746 maskt |= (((maskt & 0x0020) || (s_fine & 0x40)) && (e_fine & 0x40) ? 0x0040 : 0x0000);
5747 maskt |= (((maskt & 0x0040) || (s_fine & 0x80)) && (e_fine & 0x80) ? 0x0080 : 0x0000);
5748 //////////////////////////////////////////////////////////////////////////////////////
5750 /* Produce a look-ahead on the ripple carry:
5751 masktla = s_coarse[0] . /e_coarse[0] */
5752 /*Masktla := AN2 (masktla, s_coarse[0], e_coarse\[0]);
5753 Maskt[8] := OAN1P (maskt[8], masktla, s_coarse[1], e_coarse\[1]);
5754 Maskt[9-14] := OAN1P (maskt[9-14], maskt[8-13], s_coarse[2-7], e_coarse\[2-7]);*/
5755 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5756 maskt |= (((s_coarse & e_coarse & 0x01) || (s_coarse & 0x02)) && (e_coarse & 0x02) ? 0x0100 : 0x0000);
5757 maskt |= (((maskt & 0x0100) || (s_coarse & 0x04)) && (e_coarse & 0x04) ? 0x0200 : 0x0000);
5758 maskt |= (((maskt & 0x0200) || (s_coarse & 0x08)) && (e_coarse & 0x08) ? 0x0400 : 0x0000);
5759 maskt |= (((maskt & 0x0400) || (s_coarse & 0x10)) && (e_coarse & 0x10) ? 0x0800 : 0x0000);
5760 maskt |= (((maskt & 0x0800) || (s_coarse & 0x20)) && (e_coarse & 0x20) ? 0x1000 : 0x0000);
5761 maskt |= (((maskt & 0x1000) || (s_coarse & 0x40)) && (e_coarse & 0x40) ? 0x2000 : 0x0000);
5762 maskt |= (((maskt & 0x2000) || (s_coarse & 0x80)) && (e_coarse & 0x80) ? 0x4000 : 0x0000);
5763 //////////////////////////////////////////////////////////////////////////////////////
5765 /* The bit terms are mirrored for big-endian pixels outside phrase
5766 mode. The byte terms are mirrored for big-endian pixels in phrase
5769 /*Mirror_bit := AN2M (mir_bit, phrase_mode\, big_pix);
5770 Mirror_byte := AN2H (mir_byte, phrase_mode, big_pix);
5772 Masktb[14] := BUF1 (masktb[14], maskt[14]);
5773 Masku[0] := MX4 (masku[0], maskt[0], maskt[7], maskt[14], zero, mir_bit, mir_byte);
5774 Masku[1] := MX4 (masku[1], maskt[1], maskt[6], maskt[14], zero, mir_bit, mir_byte);
5775 Masku[2] := MX4 (masku[2], maskt[2], maskt[5], maskt[14], zero, mir_bit, mir_byte);
5776 Masku[3] := MX4 (masku[3], maskt[3], maskt[4], masktb[14], zero, mir_bit, mir_byte);
5777 Masku[4] := MX4 (masku[4], maskt[4], maskt[3], masktb[14], zero, mir_bit, mir_byte);
5778 Masku[5] := MX4 (masku[5], maskt[5], maskt[2], masktb[14], zero, mir_bit, mir_byte);
5779 Masku[6] := MX4 (masku[6], maskt[6], maskt[1], masktb[14], zero, mir_bit, mir_byte);
5780 Masku[7] := MX4 (masku[7], maskt[7], maskt[0], masktb[14], zero, mir_bit, mir_byte);
5781 Masku[8] := MX2 (masku[8], maskt[8], maskt[13], mir_byte);
5782 Masku[9] := MX2 (masku[9], maskt[9], maskt[12], mir_byte);
5783 Masku[10] := MX2 (masku[10], maskt[10], maskt[11], mir_byte);
5784 Masku[11] := MX2 (masku[11], maskt[11], maskt[10], mir_byte);
5785 Masku[12] := MX2 (masku[12], maskt[12], maskt[9], mir_byte);
5786 Masku[13] := MX2 (masku[13], maskt[13], maskt[8], mir_byte);
5787 Masku[14] := MX2 (masku[14], maskt[14], maskt[0], mir_byte);*/
5788 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5789 bool mir_bit = true/*big_pix*/ && !phrase_mode;
5790 bool mir_byte = true/*big_pix*/ && phrase_mode;
5791 uint16 masku = maskt;
5796 masku |= (maskt >> 7) & 0x0001;
5797 masku |= (maskt >> 5) & 0x0002;
5798 masku |= (maskt >> 3) & 0x0004;
5799 masku |= (maskt >> 1) & 0x0008;
5800 masku |= (maskt << 1) & 0x0010;
5801 masku |= (maskt << 3) & 0x0020;
5802 masku |= (maskt << 5) & 0x0040;
5803 masku |= (maskt << 7) & 0x0080;
5809 masku |= (maskt >> 14) & 0x0001;
5810 masku |= (maskt >> 13) & 0x0002;
5811 masku |= (maskt >> 12) & 0x0004;
5812 masku |= (maskt >> 11) & 0x0008;
5813 masku |= (maskt >> 10) & 0x0010;
5814 masku |= (maskt >> 9) & 0x0020;
5815 masku |= (maskt >> 8) & 0x0040;
5816 masku |= (maskt >> 7) & 0x0080;
5818 masku |= (maskt >> 5) & 0x0100;
5819 masku |= (maskt >> 3) & 0x0200;
5820 masku |= (maskt >> 1) & 0x0400;
5821 masku |= (maskt << 1) & 0x0800;
5822 masku |= (maskt << 3) & 0x1000;
5823 masku |= (maskt << 5) & 0x2000;
5824 masku |= (maskt << 7) & 0x4000;
5826 //////////////////////////////////////////////////////////////////////////////////////
5828 /* The maskt terms define the area for changed data, but the byte
5829 inhibit terms can override these */
5831 /*Mask[0-7] := AN2 (mask[0-7], masku[0-7], dbinh\[0]);
5832 Mask[8-14] := AN2H (mask[8-14], masku[8-14], dbinh\[1-7]);*/
5833 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5834 uint16 mask = masku & (!(dbinh & 0x01) ? 0xFFFF : 0xFF00);
5835 mask &= ~(((uint16)dbinh & 0x00FE) << 7);
5836 //////////////////////////////////////////////////////////////////////////////////////
5838 /*Addql[0] := JOIN (addql[0], addq[0..1]);
5839 Addql[1] := JOIN (addql[1], addq[2..3]);
5841 Dsel0b[0-1] := BUF8 (dsel0b[0-1], data_sel[0]);
5842 Dsel1b[0-1] := BUF8 (dsel1b[0-1], data_sel[1]);
5843 Ddatlo := MX4 (ddatlo, patd[0], lfu[0], addql[0], zero32, dsel0b[0], dsel1b[0]);
5844 Ddathi := MX4 (ddathi, patd[1], lfu[1], addql[1], zero32, dsel0b[1], dsel1b[1]);*/
5845 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5849 dmux[2] = ((uint64)addq[3] << 48) | ((uint64)addq[2] << 32) | ((uint64)addq[1] << 16) | (uint64)addq[0];
5851 uint64 ddat = dmux[data_sel];
5852 //////////////////////////////////////////////////////////////////////////////////////
5854 /*Zed_sel := AN2 (zed_sel, data_sel[0..1]);
5855 Zed_selb[0-1] := BUF8 (zed_selb[0-1], zed_sel);
5857 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]);
5858 Dat[8-15] := MX4 (dat[8-15], dstdlo{8-15}, ddatlo{8-15}, dstzlo{8-15}, srczlo{8-15}, mask[8], zed_selb[0]);
5859 Dat[16-23] := MX4 (dat[16-23], dstdlo{16-23}, ddatlo{16-23}, dstzlo{16-23}, srczlo{16-23}, mask[9], zed_selb[0]);
5860 Dat[24-31] := MX4 (dat[24-31], dstdlo{24-31}, ddatlo{24-31}, dstzlo{24-31}, srczlo{24-31}, mask[10], zed_selb[0]);
5861 Dat[32-39] := MX4 (dat[32-39], dstdhi{0-7}, ddathi{0-7}, dstzhi{0-7}, srczhi{0-7}, mask[11], zed_selb[1]);
5862 Dat[40-47] := MX4 (dat[40-47], dstdhi{8-15}, ddathi{8-15}, dstzhi{8-15}, srczhi{8-15}, mask[12], zed_selb[1]);
5863 Dat[48-55] := MX4 (dat[48-55], dstdhi{16-23}, ddathi{16-23}, dstzhi{16-23}, srczhi{16-23}, mask[13], zed_selb[1]);
5864 Dat[56-63] := MX4 (dat[56-63], dstdhi{24-31}, ddathi{24-31}, dstzhi{24-31}, srczhi{24-31}, mask[14], zed_selb[1]);*/
5865 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5866 wdata = ((ddat & mask) | (dstd & ~mask)) & 0x00000000000000FFLL;
5867 wdata |= (mask & 0x0100 ? ddat : dstd) & 0x000000000000FF00LL;
5868 wdata |= (mask & 0x0200 ? ddat : dstd) & 0x0000000000FF0000LL;
5869 wdata |= (mask & 0x0400 ? ddat : dstd) & 0x00000000FF000000LL;
5870 wdata |= (mask & 0x0800 ? ddat : dstd) & 0x000000FF00000000LL;
5871 wdata |= (mask & 0x1000 ? ddat : dstd) & 0x0000FF0000000000LL;
5872 wdata |= (mask & 0x2000 ? ddat : dstd) & 0x00FF000000000000LL;
5873 wdata |= (mask & 0x4000 ? ddat : dstd) & 0xFF00000000000000LL;
5876 printf("\n[ddat=%08X%08X dstd=%08X%08X wdata=%08X%08X mask=%04X]\n",
5877 (uint32)(ddat >> 32), (uint32)(ddat & 0xFFFFFFFF),
5878 (uint32)(dstd >> 32), (uint32)(dstd & 0xFFFFFFFF),
5879 (uint32)(wdata >> 32), (uint32)(wdata & 0xFFFFFFFF), mask);
5882 //This is a crappy way of handling this, but it should work for now...
5884 zwdata = ((srcz & mask) | (dstz & ~mask)) & 0x00000000000000FFLL;
5885 zwdata |= (mask & 0x0100 ? srcz : dstz) & 0x000000000000FF00LL;
5886 zwdata |= (mask & 0x0200 ? srcz : dstz) & 0x0000000000FF0000LL;
5887 zwdata |= (mask & 0x0400 ? srcz : dstz) & 0x00000000FF000000LL;
5888 zwdata |= (mask & 0x0800 ? srcz : dstz) & 0x000000FF00000000LL;
5889 zwdata |= (mask & 0x1000 ? srcz : dstz) & 0x0000FF0000000000LL;
5890 zwdata |= (mask & 0x2000 ? srcz : dstz) & 0x00FF000000000000LL;
5891 zwdata |= (mask & 0x4000 ? srcz : dstz) & 0xFF00000000000000LL;
5894 printf("\n[srcz=%08X%08X dstz=%08X%08X zwdata=%08X%08X mask=%04X]\n",
5895 (uint32)(srcz >> 32), (uint32)(srcz & 0xFFFFFFFF),
5896 (uint32)(dstz >> 32), (uint32)(dstz & 0xFFFFFFFF),
5897 (uint32)(zwdata >> 32), (uint32)(zwdata & 0xFFFFFFFF), mask);
5901 //////////////////////////////////////////////////////////////////////////////////////
5903 /*Data_enab[0-1] := BUF8 (data_enab[0-1], data_ena);
5904 Datadrv[0-31] := TS (wdata[0-31], dat[0-31], data_enab[0]);
5905 Datadrv[32-63] := TS (wdata[32-63], dat[32-63], data_enab[1]);
5907 Unused[0] := DUMMY (unused[0]);
5912 /** COMP_CTRL - Comparator output control logic *****************
5914 This block is responsible for taking the comparator outputs and
5915 using them as appropriate to inhibit writes. Two methods are
5916 supported for inhibiting write data:
5918 - suppression of the inner loop controlled write operation
5919 - a set of eight byte inhibit lines to write back dest data
5921 The first technique is used in pixel oriented modes, the second in
5922 phrase mode, but the phrase mode form is only applicable to eight
5923 and sixteen bit pixel modes.
5925 Writes can be suppressed by data being equal, by the Z comparator
5926 conditions being met, or by the bit to pixel expansion scheme.
5928 Pipe-lining issues: the data derived comparator outputs are stable
5929 until the next data read, well after the affected write from this
5930 operation. However, the inner counter bits can count immediately
5931 before the ack for the last write. Therefore, it is necessary to
5932 delay bcompbit select terms by one inner loop pipe-line stage,
5933 when generating the select for the data control - the output is
5934 delayed one further tick to give it write data timing (2/34).
5936 There is also a problem with computed data - the new values are
5937 calculated before the write associated with the old value has been
5938 performed. The is taken care of within the zed comparator by
5939 pipe-lining the comparator inputs where appropriate.
5942 //#define LOG_COMP_CTRL
5944 dbinh\[0..7] // destination byte inhibit lines
5945 nowrite // suppress inner loop write operation
5947 bcompen // bit selector inhibit enable
5948 big_pix // pixels are big-endian
5949 bkgwren // enable dest data write in pix inhibit
5950 clk // co-processor clock
5951 dcomp[0..7] // output of data byte comparators
5952 dcompen // data comparator inhibit enable
5953 icount[0..2] // low bits of inner count
5954 pixsize[0..2] // destination pixel size
5955 phrase_mode // phrase write mode
5956 srcd[0..7] // bits to use for bit to byte expansion
5957 step_inner // inner loop advance
5958 zcomp[0..3] // output of word zed comparators
5960 void COMP_CTRL(uint8 &dbinh, bool &nowrite,
5961 bool bcompen, bool big_pix, bool bkgwren, uint8 dcomp, bool dcompen, uint8 icount,
5962 uint8 pixsize, bool phrase_mode, uint8 srcd, uint8 zcomp)
5966 /*Bkgwren\ := INV1 (bkgwren\, bkgwren);
5967 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5968 Pixsize\[0-2] := INV2 (pixsize\[0-2], pixsize[0-2]);*/
5970 /* The bit comparator bits are derived from the source data, which
5971 will have been suitably aligned for phrase mode. The contents of
5972 the inner counter are used to select which bit to use.
5974 When not in phrase mode the inner count value is used to select
5975 one bit. It is assumed that the count has already occurred, so,
5976 7 selects bit 0, etc. In big-endian pixel mode, this turns round,
5977 so that a count of 7 selects bit 7.
5979 In phrase mode, the eight bits are used directly, and this mode is
5980 only applicable to 8-bit pixel mode (2/34) */
5982 /*Bcompselt[0-2] := EO (bcompselt[0-2], icount[0-2], big_pix);
5983 Bcompbit := MX8 (bcompbit, srcd[7], srcd[6], srcd[5],
5984 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompselt[0..2]);
5985 Bcompbit\ := INV1 (bcompbit\, bcompbit);*/
5986 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5987 #ifdef LOG_COMP_CTRL
5990 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);
5995 uint8 bcompselt = (big_pix ? ~icount : icount) & 0x07;
5996 uint8 bitmask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
5997 bool bcompbit = srcd & bitmask[bcompselt];
5998 //////////////////////////////////////////////////////////////////////////////////////
6000 /* pipe-line the count */
6001 /*Bcompsel[0-2] := FDSYNC (bcompsel[0-2], bcompselt[0-2], step_inner, clk);
6002 Bcompbt := MX8 (bcompbitpt, srcd[7], srcd[6], srcd[5],
6003 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompsel[0..2]);
6004 Bcompbitp := FD1Q (bcompbitp, bcompbitpt, clk);
6005 Bcompbitp\ := INV1 (bcompbitp\, bcompbitp);*/
6007 /* For pixel mode, generate the write inhibit signal for all modes
6008 on bit inhibit, for 8 and 16 bit modes on comparator inhibit, and
6009 for 16 bit mode on Z inhibit
6011 Nowrite = bcompen . /bcompbit . /phrase_mode
6012 + dcompen . dcomp[0] . /phrase_mode . pixsize = 011
6013 + dcompen . dcomp[0..1] . /phrase_mode . pixsize = 100
6014 + zcomp[0] . /phrase_mode . pixsize = 100
6017 /*Nowt0 := NAN3 (nowt[0], bcompen, bcompbit\, phrase_mode\);
6018 Nowt1 := ND6 (nowt[1], dcompen, dcomp[0], phrase_mode\, pixsize\[2], pixsize[0..1]);
6019 Nowt2 := ND7 (nowt[2], dcompen, dcomp[0..1], phrase_mode\, pixsize[2], pixsize\[0..1]);
6020 Nowt3 := NAN5 (nowt[3], zcomp[0], phrase_mode\, pixsize[2], pixsize\[0..1]);
6021 Nowt4 := NAN4 (nowt[4], nowt[0..3]);
6022 Nowrite := AN2 (nowrite, nowt[4], bkgwren\);*/
6023 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6024 nowrite = ((bcompen && !bcompbit && !phrase_mode)
6025 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
6026 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
6027 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4)))
6029 //////////////////////////////////////////////////////////////////////////////////////
6031 /*Winht := NAN3 (winht, bcompen, bcompbitp\, phrase_mode\);
6032 Winhibit := NAN4 (winhibit, winht, nowt[1..3]);*/
6033 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6034 //This is the same as above, but with bcompbit delayed one tick and called 'winhibit'
6035 //Small difference: Besides the pipeline effect, it's also not using !bkgwren...
6036 // bool winhibit = (bcompen && !
6037 bool winhibit = (bcompen && !bcompbit && !phrase_mode)
6038 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
6039 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
6040 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4));
6041 #ifdef LOG_COMP_CTRL
6044 printf("[nw=%s wi=%s]", (nowrite ? "T" : "F"), (winhibit ? "T" : "F"));
6048 //////////////////////////////////////////////////////////////////////////////////////
6050 /* For phrase mode, generate the byte inhibit signals for eight bit
6051 mode 011, or sixteen bit mode 100
6052 dbinh\[0] = pixsize[2] . zcomp[0]
6053 + pixsize[2] . dcomp[0] . dcomp[1] . dcompen
6054 + /pixsize[2] . dcomp[0] . dcompen
6055 + /srcd[0] . bcompen
6057 Inhibits 0-3 are also used when not in phrase mode to write back
6061 /*Srcd\[0-7] := INV1 (srcd\[0-7], srcd[0-7]);
6063 Di0t0 := NAN2H (di0t[0], pixsize[2], zcomp[0]);
6064 Di0t1 := NAN4H (di0t[1], pixsize[2], dcomp[0..1], dcompen);
6065 Di0t2 := NAN2 (di0t[2], srcd\[0], bcompen);
6066 Di0t3 := NAN3 (di0t[3], pixsize\[2], dcomp[0], dcompen);
6067 Di0t4 := NAN4 (di0t[4], di0t[0..3]);
6068 Dbinh[0] := ANR1P (dbinh\[0], di0t[4], phrase_mode, winhibit);*/
6069 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6071 bool di0t0_1 = ((pixsize & 0x04) && (zcomp & 0x01))
6072 || ((pixsize & 0x04) && (dcomp & 0x01) && (dcomp & 0x02) && dcompen);
6073 bool di0t4 = di0t0_1
6074 || (!(srcd & 0x01) && bcompen)
6075 || (!(pixsize & 0x04) && (dcomp & 0x01) && dcompen);
6076 dbinh |= (!((di0t4 && phrase_mode) || winhibit) ? 0x01 : 0x00);
6077 #ifdef LOG_COMP_CTRL
6080 printf("[di0t0_1=%s di0t4=%s]", (di0t0_1 ? "T" : "F"), (di0t4 ? "T" : "F"));
6084 //////////////////////////////////////////////////////////////////////////////////////
6086 /*Di1t0 := NAN3 (di1t[0], pixsize\[2], dcomp[1], dcompen);
6087 Di1t1 := NAN2 (di1t[1], srcd\[1], bcompen);
6088 Di1t2 := NAN4 (di1t[2], di0t[0..1], di1t[0..1]);
6089 Dbinh[1] := ANR1 (dbinh\[1], di1t[2], phrase_mode, winhibit);*/
6090 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6091 bool di1t2 = di0t0_1
6092 || (!(srcd & 0x02) && bcompen)
6093 || (!(pixsize & 0x04) && (dcomp & 0x02) && dcompen);
6094 dbinh |= (!((di1t2 && phrase_mode) || winhibit) ? 0x02 : 0x00);
6095 #ifdef LOG_COMP_CTRL
6098 printf("[di1t2=%s]", (di1t2 ? "T" : "F"));
6102 //////////////////////////////////////////////////////////////////////////////////////
6104 /*Di2t0 := NAN2H (di2t[0], pixsize[2], zcomp[1]);
6105 Di2t1 := NAN4H (di2t[1], pixsize[2], dcomp[2..3], dcompen);
6106 Di2t2 := NAN2 (di2t[2], srcd\[2], bcompen);
6107 Di2t3 := NAN3 (di2t[3], pixsize\[2], dcomp[2], dcompen);
6108 Di2t4 := NAN4 (di2t[4], di2t[0..3]);
6109 Dbinh[2] := ANR1 (dbinh\[2], di2t[4], phrase_mode, winhibit);*/
6110 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6111 //[bcompen=F dcompen=T phrase_mode=T bkgwren=F][nw=F wi=F]
6112 //[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]
6113 //[dcomp=$00 dbinh=$0C][7804780400007804] (icount=0005, inc=4)
6114 bool di2t0_1 = ((pixsize & 0x04) && (zcomp & 0x02))
6115 || ((pixsize & 0x04) && (dcomp & 0x04) && (dcomp & 0x08) && dcompen);
6116 bool di2t4 = di2t0_1
6117 || (!(srcd & 0x04) && bcompen)
6118 || (!(pixsize & 0x04) && (dcomp & 0x04) && dcompen);
6119 dbinh |= (!((di2t4 && phrase_mode) || winhibit) ? 0x04 : 0x00);
6120 #ifdef LOG_COMP_CTRL
6123 printf("[di2t0_1=%s di2t4=%s]", (di2t0_1 ? "T" : "F"), (di2t4 ? "T" : "F"));
6127 //////////////////////////////////////////////////////////////////////////////////////
6129 /*Di3t0 := NAN3 (di3t[0], pixsize\[2], dcomp[3], dcompen);
6130 Di3t1 := NAN2 (di3t[1], srcd\[3], bcompen);
6131 Di3t2 := NAN4 (di3t[2], di2t[0..1], di3t[0..1]);
6132 Dbinh[3] := ANR1 (dbinh\[3], di3t[2], phrase_mode, winhibit);*/
6133 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6134 bool di3t2 = di2t0_1
6135 || (!(srcd & 0x08) && bcompen)
6136 || (!(pixsize & 0x04) && (dcomp & 0x08) && dcompen);
6137 dbinh |= (!((di3t2 && phrase_mode) || winhibit) ? 0x08 : 0x00);
6138 #ifdef LOG_COMP_CTRL
6141 printf("[di3t2=%s]", (di3t2 ? "T" : "F"));
6145 //////////////////////////////////////////////////////////////////////////////////////
6147 /*Di4t0 := NAN2H (di4t[0], pixsize[2], zcomp[2]);
6148 Di4t1 := NAN4H (di4t[1], pixsize[2], dcomp[4..5], dcompen);
6149 Di4t2 := NAN2 (di4t[2], srcd\[4], bcompen);
6150 Di4t3 := NAN3 (di4t[3], pixsize\[2], dcomp[4], dcompen);
6151 Di4t4 := NAN4 (di4t[4], di4t[0..3]);
6152 Dbinh[4] := NAN2 (dbinh\[4], di4t[4], phrase_mode);*/
6153 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6154 bool di4t0_1 = ((pixsize & 0x04) && (zcomp & 0x04))
6155 || ((pixsize & 0x04) && (dcomp & 0x10) && (dcomp & 0x20) && dcompen);
6156 bool di4t4 = di4t0_1
6157 || (!(srcd & 0x10) && bcompen)
6158 || (!(pixsize & 0x04) && (dcomp & 0x10) && dcompen);
6159 dbinh |= (!(di4t4 && phrase_mode) ? 0x10 : 0x00);
6160 #ifdef LOG_COMP_CTRL
6163 printf("[di4t0_1=%s di2t4=%s]", (di4t0_1 ? "T" : "F"), (di4t4 ? "T" : "F"));
6167 //////////////////////////////////////////////////////////////////////////////////////
6169 /*Di5t0 := NAN3 (di5t[0], pixsize\[2], dcomp[5], dcompen);
6170 Di5t1 := NAN2 (di5t[1], srcd\[5], bcompen);
6171 Di5t2 := NAN4 (di5t[2], di4t[0..1], di5t[0..1]);
6172 Dbinh[5] := NAN2 (dbinh\[5], di5t[2], phrase_mode);*/
6173 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6174 bool di5t2 = di4t0_1
6175 || (!(srcd & 0x20) && bcompen)
6176 || (!(pixsize & 0x04) && (dcomp & 0x20) && dcompen);
6177 dbinh |= (!(di5t2 && phrase_mode) ? 0x20 : 0x00);
6178 #ifdef LOG_COMP_CTRL
6181 printf("[di5t2=%s]", (di5t2 ? "T" : "F"));
6185 //////////////////////////////////////////////////////////////////////////////////////
6187 /*Di6t0 := NAN2H (di6t[0], pixsize[2], zcomp[3]);
6188 Di6t1 := NAN4H (di6t[1], pixsize[2], dcomp[6..7], dcompen);
6189 Di6t2 := NAN2 (di6t[2], srcd\[6], bcompen);
6190 Di6t3 := NAN3 (di6t[3], pixsize\[2], dcomp[6], dcompen);
6191 Di6t4 := NAN4 (di6t[4], di6t[0..3]);
6192 Dbinh[6] := NAN2 (dbinh\[6], di6t[4], phrase_mode);*/
6193 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6194 bool di6t0_1 = ((pixsize & 0x04) && (zcomp & 0x08))
6195 || ((pixsize & 0x04) && (dcomp & 0x40) && (dcomp & 0x80) && dcompen);
6196 bool di6t4 = di6t0_1
6197 || (!(srcd & 0x40) && bcompen)
6198 || (!(pixsize & 0x04) && (dcomp & 0x40) && dcompen);
6199 dbinh |= (!(di6t4 && phrase_mode) ? 0x40 : 0x00);
6200 #ifdef LOG_COMP_CTRL
6203 printf("[di6t0_1=%s di6t4=%s]", (di6t0_1 ? "T" : "F"), (di6t4 ? "T" : "F"));
6207 //////////////////////////////////////////////////////////////////////////////////////
6209 /*Di7t0 := NAN3 (di7t[0], pixsize\[2], dcomp[7], dcompen);
6210 Di7t1 := NAN2 (di7t[1], srcd\[7], bcompen);
6211 Di7t2 := NAN4 (di7t[2], di6t[0..1], di7t[0..1]);
6212 Dbinh[7] := NAN2 (dbinh\[7], di7t[2], phrase_mode);*/
6213 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6214 bool di7t2 = di6t0_1
6215 || (!(srcd & 0x80) && bcompen)
6216 || (!(pixsize & 0x04) && (dcomp & 0x80) && dcompen);
6217 dbinh |= (!(di7t2 && phrase_mode) ? 0x80 : 0x00);
6218 #ifdef LOG_COMP_CTRL
6221 printf("[di7t2=%s]", (di7t2 ? "T" : "F"));
6225 //////////////////////////////////////////////////////////////////////////////////////
6230 #ifdef LOG_COMP_CTRL
6233 printf("[dcomp=$%02X dbinh=$%02X]\n ", dcomp, dbinh);
6240 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6241 //////////////////////////////////////////////////////////////////////////////////////
6243 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6244 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6245 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!