Fix a random crash when reading the source lines information
[clinton/Virtual-Jaguar-Rx.git] / src / blitter.cpp
1 //
2 // Blitter core
3 //
4 // by James Hammons
5 // (C) 2010 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
9 //
10 // Who When What
11 // --- ---------- -----------------------------------------------------------
12 // JLH 01/16/2010 Created this log ;-)
13 // JPM 06/06/2016 Visual Studio support
14 //
15
16 //
17 // I owe a debt of gratitude to Curt Vendel and to John Mathieson--to Curt
18 // for supplying the Oberon ASIC nets and to John for making them available
19 // to Curt. ;-) Without that excellent documentation which shows *exactly*
20 // what's going on inside the TOM chip, we'd all still be guessing as to how
21 // the wily blitter and other pieces of the Jaguar puzzle actually work.
22 // Now how about those JERRY ASIC nets gentlemen...? [We have those now!] ;-)
23 //
24
25 #include "blitter.h"
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include "jaguar.h"
31 #include "log.h"
32 //#include "memory.h"
33 #include "settings.h"
34
35 // Various conditional compilation goodies...
36
37 //#define LOG_BLITS
38
39 #define USE_ORIGINAL_BLITTER
40 //#define USE_MIDSUMMER_BLITTER
41 #define USE_MIDSUMMER_BLITTER_MKII
42
43 #ifdef USE_ORIGINAL_BLITTER
44 #ifdef USE_MIDSUMMER_BLITTER_MKII
45 #define USE_BOTH_BLITTERS
46 #endif
47 #endif
48
49
50 // External global variables
51
52 extern int jaguar_active_memory_dumps;
53
54 // Local global variables
55
56 int start_logging = 0;
57 uint8_t blitter_working = 0;
58 bool startConciseBlitLogging = false;
59 bool logBlit = false;
60
61 // Blitter register RAM (most of it is hidden from the user)
62
63 static uint8_t blitter_ram[0x100];
64
65 // Other crapola
66
67 bool specialLog = false;
68 extern int effect_start;
69 extern int blit_start_log;
70 void BlitterMidsummer(uint32_t cmd);
71 void BlitterMidsummer2(void);
72
73 #define REG(A) (((uint32_t)blitter_ram[(A)] << 24) | ((uint32_t)blitter_ram[(A)+1] << 16) \
74 | ((uint32_t)blitter_ram[(A)+2] << 8) | (uint32_t)blitter_ram[(A)+3])
75 #define WREG(A,D) (blitter_ram[(A)] = ((D)>>24)&0xFF, blitter_ram[(A)+1] = ((D)>>16)&0xFF, \
76 blitter_ram[(A)+2] = ((D)>>8)&0xFF, blitter_ram[(A)+3] = (D)&0xFF)
77
78 // Blitter registers (offsets from F02200)
79
80 #define A1_BASE ((uint32_t)0x00)
81 #define A1_FLAGS ((uint32_t)0x04)
82 #define A1_CLIP ((uint32_t)0x08) // Height and width values for clipping
83 #define A1_PIXEL ((uint32_t)0x0C) // Integer part of the pixel (Y.i and X.i)
84 #define A1_STEP ((uint32_t)0x10) // Integer part of the step
85 #define A1_FSTEP ((uint32_t)0x14) // Fractional part of the step
86 #define A1_FPIXEL ((uint32_t)0x18) // Fractional part of the pixel (Y.f and X.f)
87 #define A1_INC ((uint32_t)0x1C) // Integer part of the increment
88 #define A1_FINC ((uint32_t)0x20) // Fractional part of the increment
89 #define A2_BASE ((uint32_t)0x24)
90 #define A2_FLAGS ((uint32_t)0x28)
91 #define A2_MASK ((uint32_t)0x2C) // Modulo values for x and y (M.y and M.x)
92 #define A2_PIXEL ((uint32_t)0x30) // Integer part of the pixel (no fractional part for A2)
93 #define A2_STEP ((uint32_t)0x34) // Integer part of the step (no fractional part for A2)
94 #define COMMAND ((uint32_t)0x38)
95 #define PIXLINECOUNTER ((uint32_t)0x3C) // Inner & outer loop values
96 #define SRCDATA ((uint32_t)0x40)
97 #define DSTDATA ((uint32_t)0x48)
98 #define DSTZ ((uint32_t)0x50)
99 #define SRCZINT ((uint32_t)0x58)
100 #define SRCZFRAC ((uint32_t)0x60)
101 #define PATTERNDATA ((uint32_t)0x68)
102 #define INTENSITYINC ((uint32_t)0x70)
103 #define ZINC ((uint32_t)0x74)
104 #define COLLISIONCTRL ((uint32_t)0x78)
105 #define PHRASEINT0 ((uint32_t)0x7C)
106 #define PHRASEINT1 ((uint32_t)0x80)
107 #define PHRASEINT2 ((uint32_t)0x84)
108 #define PHRASEINT3 ((uint32_t)0x88)
109 #define PHRASEZ0 ((uint32_t)0x8C)
110 #define PHRASEZ1 ((uint32_t)0x90)
111 #define PHRASEZ2 ((uint32_t)0x94)
112 #define PHRASEZ3 ((uint32_t)0x98)
113
114 // Blitter command bits
115
116 #define SRCEN (cmd & 0x00000001)
117 #define SRCENZ (cmd & 0x00000002)
118 #define SRCENX (cmd & 0x00000004)
119 #define DSTEN (cmd & 0x00000008)
120 #define DSTENZ (cmd & 0x00000010)
121 #define DSTWRZ (cmd & 0x00000020)
122 #define CLIPA1 (cmd & 0x00000040)
123
124 #define UPDA1F (cmd & 0x00000100)
125 #define UPDA1 (cmd & 0x00000200)
126 #define UPDA2 (cmd & 0x00000400)
127
128 #define DSTA2 (cmd & 0x00000800)
129
130 #define Z_OP_INF (cmd & 0x00040000)
131 #define Z_OP_EQU (cmd & 0x00080000)
132 #define Z_OP_SUP (cmd & 0x00100000)
133
134 #define LFU_NAN (cmd & 0x00200000)
135 #define LFU_NA (cmd & 0x00400000)
136 #define LFU_AN (cmd & 0x00800000)
137 #define LFU_A (cmd & 0x01000000)
138
139 #define CMPDST (cmd & 0x02000000)
140 #define BCOMPEN (cmd & 0x04000000)
141 #define DCOMPEN (cmd & 0x08000000)
142
143 #define PATDSEL (cmd & 0x00010000)
144 #define ADDDSEL (cmd & 0x00020000)
145 #define TOPBEN (cmd & 0x00004000)
146 #define TOPNEN (cmd & 0x00008000)
147 #define BKGWREN (cmd & 0x10000000)
148 #define GOURD (cmd & 0x00001000)
149 #define GOURZ (cmd & 0x00002000)
150 #define SRCSHADE (cmd & 0x40000000)
151
152
153 #define XADDPHR 0
154 #define XADDPIX 1
155 #define XADD0 2
156 #define XADDINC 3
157
158 #define XSIGNSUB_A1 (REG(A1_FLAGS)&0x080000)
159 #define XSIGNSUB_A2 (REG(A2_FLAGS)&0x080000)
160
161 #define YSIGNSUB_A1 (REG(A1_FLAGS)&0x100000)
162 #define YSIGNSUB_A2 (REG(A2_FLAGS)&0x100000)
163
164 #define YADD1_A1 (REG(A1_FLAGS)&0x040000)
165 #define YADD1_A2 (REG(A2_FLAGS)&0x040000)
166
167 /*******************************************************************************
168 ********************** STUFF CUT BELOW THIS LINE! ******************************
169 *******************************************************************************/
170 #ifdef USE_ORIGINAL_BLITTER // We're ditching this crap for now...
171
172 //Put 'em back, once we fix the problem!!! [KO]
173 // 1 bpp pixel read
174 #define PIXEL_SHIFT_1(a) (((~a##_x) >> 16) & 7)
175 #define PIXEL_OFFSET_1(a) (((((uint32_t)a##_y >> 16) * a##_width / 8) + (((uint32_t)a##_x >> 19) & ~7)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 19) & 7))
176 #define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a), BLITTER) >> PIXEL_SHIFT_1(a)) & 0x01)
177 //#define READ_PIXEL_1(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_1(a)) >> PIXEL_SHIFT_1(a)) & 0x01)
178
179 // 2 bpp pixel read
180 #define PIXEL_SHIFT_2(a) (((~a##_x) >> 15) & 6)
181 #define PIXEL_OFFSET_2(a) (((((uint32_t)a##_y >> 16) * a##_width / 4) + (((uint32_t)a##_x >> 18) & ~7)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 18) & 7))
182 #define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a), BLITTER) >> PIXEL_SHIFT_2(a)) & 0x03)
183 //#define READ_PIXEL_2(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_2(a)) >> PIXEL_SHIFT_2(a)) & 0x03)
184
185 // 4 bpp pixel read
186 #define PIXEL_SHIFT_4(a) (((~a##_x) >> 14) & 4)
187 #define PIXEL_OFFSET_4(a) (((((uint32_t)a##_y >> 16) * (a##_width/2)) + (((uint32_t)a##_x >> 17) & ~7)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 17) & 7))
188 #define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a), BLITTER) >> PIXEL_SHIFT_4(a)) & 0x0f)
189 //#define READ_PIXEL_4(a) ((JaguarReadByte(a##_addr+PIXEL_OFFSET_4(a)) >> PIXEL_SHIFT_4(a)) & 0x0f)
190
191 // 8 bpp pixel read
192 #define PIXEL_OFFSET_8(a) (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~7)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 7))
193 #define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a), BLITTER))
194 //#define READ_PIXEL_8(a) (JaguarReadByte(a##_addr+PIXEL_OFFSET_8(a)))
195
196 // 16 bpp pixel read
197 #define PIXEL_OFFSET_16(a) (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~3)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 3))
198 #define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1), BLITTER))
199 //#define READ_PIXEL_16(a) (JaguarReadWord(a##_addr+(PIXEL_OFFSET_16(a)<<1)))
200
201 // 32 bpp pixel read
202 #define PIXEL_OFFSET_32(a) (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 1))
203 #define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), BLITTER))
204 //#define READ_PIXEL_32(a) (JaguarReadLong(a##_addr+(PIXEL_OFFSET_32(a)<<2)))
205
206 // pixel read
207 #define READ_PIXEL(a,f) (\
208 (((f>>3)&0x07) == 0) ? (READ_PIXEL_1(a)) : \
209 (((f>>3)&0x07) == 1) ? (READ_PIXEL_2(a)) : \
210 (((f>>3)&0x07) == 2) ? (READ_PIXEL_4(a)) : \
211 (((f>>3)&0x07) == 3) ? (READ_PIXEL_8(a)) : \
212 (((f>>3)&0x07) == 4) ? (READ_PIXEL_16(a)) : \
213 (((f>>3)&0x07) == 5) ? (READ_PIXEL_32(a)) : 0)
214
215 // 16 bpp z data read
216 #define ZDATA_OFFSET_16(a) (PIXEL_OFFSET_16(a) + a##_zoffs * 4)
217 #define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), BLITTER))
218 //#define READ_ZDATA_16(a) (JaguarReadWord(a##_addr+(ZDATA_OFFSET_16(a)<<1)))
219
220 // z data read
221 #define READ_ZDATA(a,f) (READ_ZDATA_16(a))
222
223 // 16 bpp z data write
224 #define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d, BLITTER); }
225 //#define WRITE_ZDATA_16(a,d) { JaguarWriteWord(a##_addr+(ZDATA_OFFSET_16(a)<<1), d); }
226
227 // z data write
228 #define WRITE_ZDATA(a,f,d) WRITE_ZDATA_16(a,d);
229
230 // 1 bpp r data read
231 #define READ_RDATA_1(r,a,p) ((p) ? ((REG(r+(((uint32_t)a##_x >> 19) & 0x04))) >> (((uint32_t)a##_x >> 16) & 0x1F)) & 0x0001 : (REG(r) & 0x0001))
232
233 // 2 bpp r data read
234 #define READ_RDATA_2(r,a,p) ((p) ? ((REG(r+(((uint32_t)a##_x >> 18) & 0x04))) >> (((uint32_t)a##_x >> 15) & 0x3E)) & 0x0003 : (REG(r) & 0x0003))
235
236 // 4 bpp r data read
237 #define READ_RDATA_4(r,a,p) ((p) ? ((REG(r+(((uint32_t)a##_x >> 17) & 0x04))) >> (((uint32_t)a##_x >> 14) & 0x28)) & 0x000F : (REG(r) & 0x000F))
238
239 // 8 bpp r data read
240 #define READ_RDATA_8(r,a,p) ((p) ? ((REG(r+(((uint32_t)a##_x >> 16) & 0x04))) >> (((uint32_t)a##_x >> 13) & 0x18)) & 0x00FF : (REG(r) & 0x00FF))
241
242 // 16 bpp r data read
243 #define READ_RDATA_16(r,a,p) ((p) ? ((REG(r+(((uint32_t)a##_x >> 15) & 0x04))) >> (((uint32_t)a##_x >> 12) & 0x10)) & 0xFFFF : (REG(r) & 0xFFFF))
244
245 // 32 bpp r data read
246 #define READ_RDATA_32(r,a,p) ((p) ? REG(r+(((uint32_t)a##_x >> 14) & 0x04)) : REG(r))
247
248 // register data read
249 #define READ_RDATA(r,a,f,p) (\
250 (((f>>3)&0x07) == 0) ? (READ_RDATA_1(r,a,p)) : \
251 (((f>>3)&0x07) == 1) ? (READ_RDATA_2(r,a,p)) : \
252 (((f>>3)&0x07) == 2) ? (READ_RDATA_4(r,a,p)) : \
253 (((f>>3)&0x07) == 3) ? (READ_RDATA_8(r,a,p)) : \
254 (((f>>3)&0x07) == 4) ? (READ_RDATA_16(r,a,p)) : \
255 (((f>>3)&0x07) == 5) ? (READ_RDATA_32(r,a,p)) : 0)
256
257 // 1 bpp pixel write
258 #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); }
259 //#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))); }
260
261 // 2 bpp pixel write
262 #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); }
263 //#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))); }
264
265 // 4 bpp pixel write
266 #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); }
267 //#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))); }
268
269 // 8 bpp pixel write
270 #define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d, BLITTER); }
271 //#define WRITE_PIXEL_8(a,d) { JaguarWriteByte(a##_addr+PIXEL_OFFSET_8(a), d); }
272
273 // 16 bpp pixel write
274 //#define WRITE_PIXEL_16(a,d) { JaguarWriteWord(a##_addr+(PIXEL_OFFSET_16(a)<<1),d); }
275 #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)); }
276 //#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)); }
277
278 // 32 bpp pixel write
279 #define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d, BLITTER); }
280 //#define WRITE_PIXEL_32(a,d) { JaguarWriteLong(a##_addr+(PIXEL_OFFSET_32(a)<<2), d); }
281
282 // pixel write
283 #define WRITE_PIXEL(a,f,d) {\
284 switch ((f>>3)&0x07) { \
285 case 0: WRITE_PIXEL_1(a,d); break; \
286 case 1: WRITE_PIXEL_2(a,d); break; \
287 case 2: WRITE_PIXEL_4(a,d); break; \
288 case 3: WRITE_PIXEL_8(a,d); break; \
289 case 4: WRITE_PIXEL_16(a,d); break; \
290 case 5: WRITE_PIXEL_32(a,d); break; \
291 }}
292
293 // Width in Pixels of a Scanline
294 // This is a pretranslation of the value found in the A1 & A2 flags: It's really a floating point value
295 // of the form EEEEMM where MM is the mantissa with an implied "1." in front of it and the EEEE value is
296 // the exponent. Valid values for the exponent range from 0 to 11 (decimal). It's easiest to think of it
297 // as a floating point bit pattern being followed by a number of zeroes. So, e.g., 001101 translates to
298 // 1.01 (the "1." being implied) x (2 ^ 3) or 1010 -> 10 in base 10 (i.e., 1.01 with the decimal place
299 // being shifted to the right 3 places).
300 /*static uint32_t blitter_scanline_width[48] =
301 {
302 0, 0, 0, 0, // Note: This would really translate to 1, 1, 1, 1
303 2, 0, 0, 0,
304 4, 0, 6, 0,
305 8, 10, 12, 14,
306 16, 20, 24, 28,
307 32, 40, 48, 56,
308 64, 80, 96, 112,
309 128, 160, 192, 224,
310 256, 320, 384, 448,
311 512, 640, 768, 896,
312 1024, 1280, 1536, 1792,
313 2048, 2560, 3072, 3584
314 };//*/
315
316 //static uint8_t * tom_ram_8;
317 //static uint8_t * paletteRam;
318 static uint8_t src;
319 static uint8_t dst;
320 static uint8_t misc;
321 static uint8_t a1ctl;
322 static uint8_t mode;
323 static uint8_t ity;
324 static uint8_t zop;
325 static uint8_t op;
326 static uint8_t ctrl;
327 static uint32_t a1_addr;
328 static uint32_t a2_addr;
329 static int32_t a1_zoffs;
330 static int32_t a2_zoffs;
331 static uint32_t xadd_a1_control;
332 static uint32_t xadd_a2_control;
333 static int32_t a1_pitch;
334 static int32_t a2_pitch;
335 static uint32_t n_pixels;
336 static uint32_t n_lines;
337 static int32_t a1_x;
338 static int32_t a1_y;
339 static int32_t a1_width;
340 static int32_t a2_x;
341 static int32_t a2_y;
342 static int32_t a2_width;
343 static int32_t a2_mask_x;
344 static int32_t a2_mask_y;
345 static int32_t a1_xadd;
346 static int32_t a1_yadd;
347 static int32_t a2_xadd;
348 static int32_t a2_yadd;
349 static uint8_t a1_phrase_mode;
350 static uint8_t a2_phrase_mode;
351 static int32_t a1_step_x = 0;
352 static int32_t a1_step_y = 0;
353 static int32_t a2_step_x = 0;
354 static int32_t a2_step_y = 0;
355 static uint32_t outer_loop;
356 static uint32_t inner_loop;
357 static uint32_t a2_psize;
358 static uint32_t a1_psize;
359 static uint32_t gouraud_add;
360 //static uint32_t gouraud_data;
361 //static uint16_t gint[4];
362 //static uint16_t gfrac[4];
363 //static uint8_t gcolour[4];
364 static int gd_i[4];
365 static int gd_c[4];
366 static int gd_ia, gd_ca;
367 static int colour_index = 0;
368 static int32_t zadd;
369 static uint32_t z_i[4];
370
371 static int32_t a1_clip_x, a1_clip_y;
372
373 // In the spirit of "get it right first, *then* optimize" I've taken the liberty
374 // of removing all the unnecessary code caching. If it turns out to be a good way
375 // to optimize the blitter, then we may revisit it in the future...
376
377 //
378 // Generic blit handler
379 //
380 void blitter_generic(uint32_t cmd)
381 {
382 /*
383 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
384 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
385 A1 step values: -2 (X), 1 (Y)
386 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
387 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
388 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
389 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
390 */
391 //if (effect_start)
392 // specialLog = true;
393 /*if (cmd == 0x1401060C && blit_start_log)
394 specialLog = true;//*/
395 //Testing only!
396 //uint32_t logGo = ((cmd == 0x01800E01 && REG(A1_BASE) == 0x898000) ? 1 : 0);
397 uint32_t srcdata, srczdata, dstdata, dstzdata, writedata, inhibit;
398 uint32_t bppSrc = (DSTA2 ? 1 << ((REG(A1_FLAGS) >> 3) & 0x07) : 1 << ((REG(A2_FLAGS) >> 3) & 0x07));
399
400 if (specialLog)
401 {
402 WriteLog("About to do n x m blit (BM width is ? pixels)...\n");
403 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);
404 }
405 /* if (BCOMPEN)
406 {
407 if (DSTA2)
408 a1_xadd = 0;
409 else
410 a2_xadd = 0;
411 }//*/
412
413 while (outer_loop--)
414 {
415 if (specialLog)
416 {
417 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
418 }
419 uint32_t a1_start = a1_x, a2_start = a2_x, bitPos = 0;
420
421 //Kludge for Hover Strike...
422 //I wonder if this kludge is in conjunction with the SRCENX down below...
423 // This isn't so much a kludge but the way things work in BCOMPEN mode...!
424 if (BCOMPEN && SRCENX)
425 {
426 if (n_pixels < bppSrc)
427 bitPos = bppSrc - n_pixels;
428 }
429
430 inner_loop = n_pixels;
431 while (inner_loop--)
432 {
433 if (specialLog)
434 {
435 WriteLog(" A1_X/Y = %08X/%08X, A2_X/Y = %08X/%08X\n", a1_x, a1_y, a2_x, a2_y);
436 }
437 srcdata = srczdata = dstdata = dstzdata = writedata = inhibit = 0;
438
439 if (!DSTA2) // Data movement: A1 <- A2
440 {
441 // load src data and Z
442 // if (SRCEN)
443 if (SRCEN || SRCENX) // Not sure if this is correct... (seems to be...!)
444 {
445 srcdata = READ_PIXEL(a2, REG(A2_FLAGS));
446
447 if (SRCENZ)
448 srczdata = READ_ZDATA(a2, REG(A2_FLAGS));
449 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
450 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
451 }
452 else // Use SRCDATA register...
453 {
454 srcdata = READ_RDATA(SRCDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
455
456 if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
457 srczdata = READ_RDATA(SRCZINT, a2, REG(A2_FLAGS), a2_phrase_mode);
458 }
459
460 // load dst data and Z
461 if (DSTEN)
462 {
463 dstdata = READ_PIXEL(a1, REG(A1_FLAGS));
464
465 if (DSTENZ)
466 dstzdata = READ_ZDATA(a1, REG(A1_FLAGS));
467 else
468 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
469 }
470 else
471 {
472 dstdata = READ_RDATA(DSTDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
473
474 if (DSTENZ)
475 dstzdata = READ_RDATA(DSTZ, a1, REG(A1_FLAGS), a1_phrase_mode);
476 }
477
478 /*This wasn't working... // a1 clipping
479 if (cmd & 0x00000040)
480 {
481 if (a1_x < 0 || a1_y < 0 || (a1_x >> 16) >= (REG(A1_CLIP) & 0x7FFF)
482 || (a1_y >> 16) >= ((REG(A1_CLIP) >> 16) & 0x7FFF))
483 inhibit = 1;
484 }//*/
485
486 if (GOURZ)
487 srczdata = z_i[colour_index] >> 16;
488
489 // apply z comparator
490 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
491 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
492 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
493
494 // apply data comparator
495 // Note: DCOMPEN only works in 8/16 bpp modes! !!! FIX !!!
496 // Does BCOMPEN only work in 1 bpp mode???
497 // No, but it always does a 1 bit expansion no matter what the BPP of the channel is set to. !!! FIX !!!
498 // This is bit tricky... We need to fix the XADD value so that it acts like a 1BPP value while inside
499 // an 8BPP space.
500 if (DCOMPEN | BCOMPEN)
501 {
502 //Temp, for testing Hover Strike
503 //Doesn't seem to do it... Why?
504 //What needs to happen here is twofold. First, the address generator in the outer loop has
505 //to honor the BPP when calculating the start address (which it kinda does already). Second,
506 //it has to step bit by bit when using BCOMPEN. How to do this???
507 if (BCOMPEN)
508 //small problem with this approach: it's not accurate... We need a proper address to begin with
509 //and *then* we can do the bit stepping from there the way it's *supposed* to be done... !!! FIX !!!
510 //[DONE]
511 {
512 uint32_t pixShift = (~bitPos) & (bppSrc - 1);
513 srcdata = (srcdata >> pixShift) & 0x01;
514
515 bitPos++;
516 // if (bitPos % bppSrc == 0)
517 // a2_x += 0x00010000;
518 }
519 /*
520 Interesting (Hover Strike--large letter):
521
522 Blit! (0018FA70 <- 008DDC40) count: 2 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
523 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
524 A1 step values: -2 (X), 1 (Y)
525 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
526 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
527 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
528 A1 x/y: 100/12, A2 x/y: 106/0 Pattern: 000000F300000000
529
530 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
531 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
532 A1 step values: -8 (X), 1 (Y)
533 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
534 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
535 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
536 A1 x/y: 102/12, A2 x/y: 107/0 Pattern: 000000F300000000
537
538 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
539 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
540 A1 step values: -1 (X), 1 (Y)
541 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
542 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
543 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
544 A1 x/y: 118/12, A2 x/y: 70/0 Pattern: 000000F300000000
545
546 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
547 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
548 A1 step values: -8 (X), 1 (Y)
549 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
550 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
551 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
552 A1 x/y: 119/12, A2 x/y: 71/0 Pattern: 000000F300000000
553
554 Blit! (0018FA70 <- 008DDC40) count: 1 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
555 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
556 A1 step values: -1 (X), 1 (Y)
557 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
558 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
559 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
560 A1 x/y: 127/12, A2 x/y: 66/0 Pattern: 000000F300000000
561
562 Blit! (0018FA70 <- 008DDC40) count: 8 x 13, A1/2_FLAGS: 00014218/00013C18 [cmd: 1401060C]
563 CMD -> src: SRCENX dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl: BCOMPEN BKGWREN
564 A1 step values: -8 (X), 1 (Y)
565 A2 step values: -1 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
566 A1 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
567 A2 -> pitch: 1 phrases, depth: 8bpp, z-off: 0, width: 192 (1E), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
568 A1 x/y: 128/12, A2 x/y: 67/0 Pattern: 000000F300000000
569 */
570
571
572 if (!CMPDST)
573 {
574 //WriteLog("Blitter: BCOMPEN set on command %08X inhibit prev:%u, now:", cmd, inhibit);
575 // compare source pixel with pattern pixel
576 /*
577 Blit! (000B8250 <- 0012C3A0) count: 16 x 1, A1/2_FLAGS: 00014420/00012000 [cmd: 05810001]
578 CMD -> src: SRCEN dst: misc: a1ctl: mode: ity: PATDSEL z-op: op: LFU_REPLACE ctrl: BCOMPEN
579 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
580 A2 -> pitch: 1 phrases, depth: 1bpp, z-off: 0, width: 16 (10), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
581 x/y: 0/20
582 ...
583 */
584 // AvP is still wrong, could be cuz it's doing A1 -> A2...
585
586 // Src is the 1bpp bitmap... DST is the PATTERN!!!
587 // This seems to solve at least ONE of the problems with MC3D...
588 // Why should this be inverted???
589 // Bcuz it is. This is supposed to be used only for a bit -> pixel expansion...
590 /* if (srcdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
591 // if (srcdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
592 inhibit = 1;//*/
593 /* uint32_t A2bpp = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
594 if (A2bpp == 1 || A2bpp == 16 || A2bpp == 8)
595 inhibit = (srcdata == 0 ? 1: 0);
596 // inhibit = !srcdata;
597 else
598 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A2bpp);//*/
599 // What it boils down to is this:
600
601 if (srcdata == 0)
602 inhibit = 1;//*/
603 }
604 else
605 {
606 // compare destination pixel with pattern pixel
607 if (dstdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
608 // if (dstdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
609 inhibit = 1;
610 }
611
612 // This is DEFINITELY WRONG
613 // if (a1_phrase_mode || a2_phrase_mode)
614 // inhibit = !inhibit;
615 }
616
617 if (CLIPA1)
618 {
619 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
620 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
621 }
622
623 // compute the write data and store
624 if (!inhibit)
625 {
626 // Houston, we have a problem...
627 // Look here, at PATDSEL and GOURD. If both are active (as they are on the BIOS intro), then there's
628 // a conflict! E.g.:
629 //Blit! (00100000 <- 000095D0) count: 3 x 1, A1/2_FLAGS: 00014220/00004020 [cmd: 00011008]
630 // CMD -> src: dst: DSTEN misc: a1ctl: mode: GOURD ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
631 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
632 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
633 // A1 x/y: 90/171, A2 x/y: 808/0 Pattern: 776D770077007700
634
635 if (PATDSEL)
636 {
637 // use pattern data for write data
638 writedata = READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
639 }
640 else if (ADDDSEL)
641 {
642 /*if (blit_start_log)
643 WriteLog("BLIT: ADDDSEL srcdata: %08X\, dstdata: %08X, ", srcdata, dstdata);//*/
644
645 // intensity addition
646 //Ok, this is wrong... Or is it? Yes, it's wrong! !!! FIX !!!
647 /* writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
648 if (!(TOPBEN) && writedata > 0xFF)
649 // writedata = 0xFF;
650 writedata &= 0xFF;
651 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
652 if (!(TOPNEN) && writedata > 0xFFF)
653 // writedata = 0xFFF;
654 writedata &= 0xFFF;
655 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);//*/
656 //notneeded--writedata &= 0xFFFF;
657 /*if (blit_start_log)
658 WriteLog("writedata: %08X\n", writedata);//*/
659 /*
660 Hover Strike ADDDSEL blit:
661
662 Blit! (00098D90 <- 0081DDC0) count: 320 x 287, A1/2_FLAGS: 00004220/00004020 [cmd: 00020208]
663 CMD -> src: dst: DSTEN misc: a1ctl: UPDA1 mode: ity: ADDDSEL z-op: op: LFU_CLEAR ctrl:
664 A1 step values: -320 (X), 1 (Y)
665 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
666 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 256 (20), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
667 A1 x/y: 0/0, A2 x/y: 3288/0 Pattern: 0000000000000000 SRCDATA: 00FD00FD00FD00FD
668 */
669 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
670
671 if (!TOPBEN)
672 {
673 //This is correct now, but slow...
674 int16_t s = (srcdata & 0xFF) | (srcdata & 0x80 ? 0xFF00 : 0x0000),
675 d = dstdata & 0xFF;
676 int16_t sum = s + d;
677
678 if (sum < 0)
679 writedata = 0x00;
680 else if (sum > 0xFF)
681 writedata = 0xFF;
682 else
683 writedata = (uint32_t)sum;
684 }
685
686 //This doesn't seem right... Looks like it would muck up the low byte... !!! FIX !!!
687 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
688
689 if (!TOPNEN && writedata > 0xFFF)
690 {
691 writedata &= 0xFFF;
692 }
693
694 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
695 }
696 else
697 {
698 if (LFU_NAN) writedata |= ~srcdata & ~dstdata;
699 if (LFU_NA) writedata |= ~srcdata & dstdata;
700 if (LFU_AN) writedata |= srcdata & ~dstdata;
701 if (LFU_A) writedata |= srcdata & dstdata;
702 }
703
704 //Although, this looks like it's OK... (even if it is shitty!)
705 //According to JTRM, this is part of the four things the blitter does with the write data (the other
706 //three being PATDSEL, ADDDSEL, and LFU (default). I'm not sure which gets precedence, this or PATDSEL
707 //(see above blit example)...
708 if (GOURD)
709 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
710
711 if (SRCSHADE)
712 {
713 int intensity = srcdata & 0xFF;
714 int ia = gd_ia >> 16;
715 if (ia & 0x80)
716 ia = 0xFFFFFF00 | ia;
717 intensity += ia;
718 if (intensity < 0)
719 intensity = 0;
720 if (intensity > 0xFF)
721 intensity = 0xFF;
722 writedata = (srcdata & 0xFF00) | intensity;
723 }
724 }
725 else
726 {
727 writedata = dstdata;
728 srczdata = dstzdata;
729 }
730
731 //Tried 2nd below for Hover Strike: No dice.
732 if (/*a1_phrase_mode || */BKGWREN || !inhibit)
733 // if (/*a1_phrase_mode || BKGWREN ||*/ !inhibit)
734 {
735 /*if (((REG(A1_FLAGS) >> 3) & 0x07) == 5)
736 {
737 uint32_t offset = a1_addr+(PIXEL_OFFSET_32(a1)<<2);
738 // (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 1))
739 if ((offset >= 0x1FF020 && offset <= 0x1FF03F) || (offset >= 0x1FF820 && offset <= 0x1FF83F))
740 WriteLog("32bpp pixel write: A1 Phrase mode --> ");
741 }//*/
742 // write to the destination
743 WRITE_PIXEL(a1, REG(A1_FLAGS), writedata);
744 if (DSTWRZ)
745 WRITE_ZDATA(a1, REG(A1_FLAGS), srczdata);
746 }
747 }
748 else // if (DSTA2) // Data movement: A1 -> A2
749 {
750 // load src data and Z
751 if (SRCEN)
752 {
753 srcdata = READ_PIXEL(a1, REG(A1_FLAGS));
754 if (SRCENZ)
755 srczdata = READ_ZDATA(a1, REG(A1_FLAGS));
756 else if (cmd & 0x0001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
757 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
758 }
759 else
760 {
761 srcdata = READ_RDATA(SRCDATA, a1, REG(A1_FLAGS), a1_phrase_mode);
762 if (cmd & 0x001C020) // PATDSEL | TOPBEN | TOPNEN | DSTWRZ
763 srczdata = READ_RDATA(SRCZINT, a1, REG(A1_FLAGS), a1_phrase_mode);
764 }
765
766 // load dst data and Z
767 if (DSTEN)
768 {
769 dstdata = READ_PIXEL(a2, REG(A2_FLAGS));
770 if (DSTENZ)
771 dstzdata = READ_ZDATA(a2, REG(A2_FLAGS));
772 else
773 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
774 }
775 else
776 {
777 dstdata = READ_RDATA(DSTDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
778 if (DSTENZ)
779 dstzdata = READ_RDATA(DSTZ, a2, REG(A2_FLAGS), a2_phrase_mode);
780 }
781
782 if (GOURZ)
783 srczdata = z_i[colour_index] >> 16;
784
785 // apply z comparator
786 if (Z_OP_INF && srczdata < dstzdata) inhibit = 1;
787 if (Z_OP_EQU && srczdata == dstzdata) inhibit = 1;
788 if (Z_OP_SUP && srczdata > dstzdata) inhibit = 1;
789
790 // apply data comparator
791 //NOTE: The bit comparator (BCOMPEN) is NOT the same at the data comparator!
792 if (DCOMPEN | BCOMPEN)
793 {
794 if (!CMPDST)
795 {
796 // compare source pixel with pattern pixel
797 // AvP: Numbers are correct, but sprites are not!
798 //This doesn't seem to be a problem... But could still be wrong...
799 /* if (srcdata == READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
800 // if (srcdata != READ_RDATA(PATTERNDATA, a1, REG(A1_FLAGS), a1_phrase_mode))
801 inhibit = 1;//*/
802 // This is probably not 100% correct... It works in the 1bpp case
803 // (in A1 <- A2 mode, that is...)
804 // AvP: This is causing blocks to be written instead of bit patterns...
805 // Works now...
806 // NOTE: We really should separate out the BCOMPEN & DCOMPEN stuff!
807 /* uint32_t A1bpp = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
808 if (A1bpp == 1 || A1bpp == 16 || A1bpp == 8)
809 inhibit = (srcdata == 0 ? 1: 0);
810 else
811 WriteLog("Blitter: Bad BPP (%u) selected for BCOMPEN mode!\n", A1bpp);//*/
812 // What it boils down to is this:
813 if (srcdata == 0)
814 inhibit = 1;//*/
815 }
816 else
817 {
818 // compare destination pixel with pattern pixel
819 if (dstdata == READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
820 // if (dstdata != READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode))
821 inhibit = 1;
822 }
823
824 // This is DEFINITELY WRONG
825 // if (a1_phrase_mode || a2_phrase_mode)
826 // inhibit = !inhibit;
827 }
828
829 if (CLIPA1)
830 {
831 inhibit |= (((a1_x >> 16) < a1_clip_x && (a1_x >> 16) >= 0
832 && (a1_y >> 16) < a1_clip_y && (a1_y >> 16) >= 0) ? 0 : 1);
833 }
834
835 // compute the write data and store
836 if (!inhibit)
837 {
838 if (PATDSEL)
839 {
840 // use pattern data for write data
841 writedata = READ_RDATA(PATTERNDATA, a2, REG(A2_FLAGS), a2_phrase_mode);
842 }
843 else if (ADDDSEL)
844 {
845 // intensity addition
846 writedata = (srcdata & 0xFF) + (dstdata & 0xFF);
847 if (!(TOPBEN) && writedata > 0xFF)
848 writedata = 0xFF;
849 writedata |= (srcdata & 0xF00) + (dstdata & 0xF00);
850 if (!(TOPNEN) && writedata > 0xFFF)
851 writedata = 0xFFF;
852 writedata |= (srcdata & 0xF000) + (dstdata & 0xF000);
853 }
854 else
855 {
856 if (LFU_NAN)
857 writedata |= ~srcdata & ~dstdata;
858 if (LFU_NA)
859 writedata |= ~srcdata & dstdata;
860 if (LFU_AN)
861 writedata |= srcdata & ~dstdata;
862 if (LFU_A)
863 writedata |= srcdata & dstdata;
864 }
865
866 if (GOURD)
867 writedata = ((gd_c[colour_index]) << 8) | (gd_i[colour_index] >> 16);
868
869 if (SRCSHADE)
870 {
871 int intensity = srcdata & 0xFF;
872 int ia = gd_ia >> 16;
873 if (ia & 0x80)
874 ia = 0xFFFFFF00 | ia;
875 intensity += ia;
876 if (intensity < 0)
877 intensity = 0;
878 if (intensity > 0xFF)
879 intensity = 0xFF;
880 writedata = (srcdata & 0xFF00) | intensity;
881 }
882 }
883 else
884 {
885 writedata = dstdata;
886 srczdata = dstzdata;
887 }
888
889 if (/*a2_phrase_mode || */BKGWREN || !inhibit)
890 {
891 /*if (logGo)
892 {
893 uint32_t offset = a2_addr+(PIXEL_OFFSET_16(a2)<<1);
894 // (((((uint32_t)a##_y >> 16) * a##_width) + (((uint32_t)a##_x >> 16) & ~1)) * (1 + a##_pitch) + (((uint32_t)a##_x >> 16) & 1))
895 WriteLog("[%08X:%04X] ", offset, writedata);
896 }//*/
897 // write to the destination
898 WRITE_PIXEL(a2, REG(A2_FLAGS), writedata);
899
900 if (DSTWRZ)
901 WRITE_ZDATA(a2, REG(A2_FLAGS), srczdata);
902 }
903 }
904
905 // Update x and y (inner loop)
906 //Now it does! But crappy, crappy, crappy! !!! FIX !!! [DONE]
907 //This is less than ideal, but it works...
908 if (!BCOMPEN)
909 {//*/
910 a1_x += a1_xadd, a1_y += a1_yadd;
911 a2_x = (a2_x + a2_xadd) & a2_mask_x, a2_y = (a2_y + a2_yadd) & a2_mask_y;
912 }
913 else
914 {
915 a1_y += a1_yadd, a2_y = (a2_y + a2_yadd) & a2_mask_y;
916 if (!DSTA2)
917 {
918 a1_x += a1_xadd;
919 if (bitPos % bppSrc == 0)
920 a2_x = (a2_x + a2_xadd) & a2_mask_x;
921 }
922 else
923 {
924 a2_x = (a2_x + a2_xadd) & a2_mask_x;
925 if (bitPos % bppSrc == 0)
926 a1_x += a1_xadd;
927 }
928 }//*/
929
930 if (GOURZ)
931 z_i[colour_index] += zadd;
932
933 if (GOURD || SRCSHADE)
934 {
935 gd_i[colour_index] += gd_ia;
936 //Hmm, this doesn't seem to do anything...
937 //But it is correct according to the JTRM...!
938 if ((int32_t)gd_i[colour_index] < 0)
939 gd_i[colour_index] = 0;
940 if (gd_i[colour_index] > 0x00FFFFFF)
941 gd_i[colour_index] = 0x00FFFFFF;//*/
942
943 gd_c[colour_index] += gd_ca;
944 if ((int32_t)gd_c[colour_index] < 0)
945 gd_c[colour_index] = 0;
946 if (gd_c[colour_index] > 0x000000FF)
947 gd_c[colour_index] = 0x000000FF;//*/
948 }
949
950 if (GOURD || SRCSHADE || GOURZ)
951 {
952 if (a1_phrase_mode)
953 //This screws things up WORSE (for the BIOS opening screen)
954 // if (a1_phrase_mode || a2_phrase_mode)
955 colour_index = (colour_index + 1) & 0x03;
956 }
957 }
958
959 /*
960 Here's the problem... The phrase mode code!
961 Blit! (00100000 -> 00148000) count: 327 x 267, A1/2_FLAGS: 00004420/00004420 [cmd: 41802E01]
962 CMD -> src: SRCEN dst: misc: a1ctl: UPDA1 UPDA2 mode: DSTA2 GOURZ ity: z-op: op: LFU_REPLACE ctrl: SRCSHADE
963 A1 step values: -327 (X), 1 (Y)
964 A2 step values: -327 (X), 1 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
965 A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
966 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 384 (22), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
967 A1 x/y: 28/58, A2 x/y: 28/58 Pattern: 00EA7BEA77EA77EA SRCDATA: 7BFF7BFF7BFF7BFF
968
969 Below fixes it, but then borks:
970 ; O
971
972 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
973 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
974 A1 step values: -15 (X), 1 (Y)
975 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
976 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
977 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
978 A1 x/y: 173/144, A2 x/y: 4052/0
979
980 Lesse, with pre-add we'd have:
981
982 oooooooooooo
983 00001111222233334444555566667777
984 ^ ^starts here...
985 | ^ends here.
986 |rolls back to here. Hmm.
987
988 */
989 //NOTE: The way to fix the CD BIOS is to uncomment below and comment the stuff after
990 // the phrase mode mucking around. But it fucks up everything else...
991 //#define SCREWY_CD_DEPENDENT
992 #ifdef SCREWY_CD_DEPENDENT
993 a1_x += a1_step_x;
994 a1_y += a1_step_y;
995 a2_x += a2_step_x;
996 a2_y += a2_step_y;//*/
997 #endif
998
999 //New: Phrase mode taken into account! :-p
1000 /* if (a1_phrase_mode) // v1
1001 {
1002 // Bump the pointer to the next phrase boundary
1003 // Even though it works, this is crappy... Clean it up!
1004 uint32_t size = 64 / a1_psize;
1005
1006 // Crappy kludge... ('aligning' source to destination)
1007 if (a2_phrase_mode && DSTA2)
1008 {
1009 uint32_t extra = (a2_start >> 16) % size;
1010 a1_x += extra << 16;
1011 }
1012
1013 uint32_t newx = (a1_x >> 16) / size;
1014 uint32_t newxrem = (a1_x >> 16) % size;
1015 a1_x &= 0x0000FFFF;
1016 a1_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
1017 }//*/
1018 if (a1_phrase_mode) // v2
1019 {
1020 // Bump the pointer to the next phrase boundary
1021 // Even though it works, this is crappy... Clean it up!
1022 uint32_t size = 64 / a1_psize;
1023
1024 // Crappy kludge... ('aligning' source to destination)
1025 if (a2_phrase_mode && DSTA2)
1026 {
1027 uint32_t extra = (a2_start >> 16) % size;
1028 a1_x += extra << 16;
1029 }
1030
1031 uint32_t pixelSize = (size - 1) << 16;
1032 a1_x = (a1_x + pixelSize) & ~pixelSize;
1033 }
1034
1035 /* if (a2_phrase_mode) // v1
1036 {
1037 // Bump the pointer to the next phrase boundary
1038 // Even though it works, this is crappy... Clean it up!
1039 uint32_t size = 64 / a2_psize;
1040
1041 // Crappy kludge... ('aligning' source to destination)
1042 // Prolly should do this for A1 channel as well... [DONE]
1043 if (a1_phrase_mode && !DSTA2)
1044 {
1045 uint32_t extra = (a1_start >> 16) % size;
1046 a2_x += extra << 16;
1047 }
1048
1049 uint32_t newx = (a2_x >> 16) / size;
1050 uint32_t newxrem = (a2_x >> 16) % size;
1051 a2_x &= 0x0000FFFF;
1052 a2_x |= (((newx + (newxrem == 0 ? 0 : 1)) * size) & 0xFFFF) << 16;
1053 }//*/
1054 if (a2_phrase_mode) // v1
1055 {
1056 // Bump the pointer to the next phrase boundary
1057 // Even though it works, this is crappy... Clean it up!
1058 uint32_t size = 64 / a2_psize;
1059
1060 // Crappy kludge... ('aligning' source to destination)
1061 // Prolly should do this for A1 channel as well... [DONE]
1062 if (a1_phrase_mode && !DSTA2)
1063 {
1064 uint32_t extra = (a1_start >> 16) % size;
1065 a2_x += extra << 16;
1066 }
1067
1068 uint32_t pixelSize = (size - 1) << 16;
1069 a2_x = (a2_x + pixelSize) & ~pixelSize;
1070 }
1071
1072 //Not entirely: This still mucks things up... !!! FIX !!!
1073 //Should this go before or after the phrase mode mucking around?
1074 #ifndef SCREWY_CD_DEPENDENT
1075 a1_x += a1_step_x;
1076 a1_y += a1_step_y;
1077 a2_x += a2_step_x;
1078 a2_y += a2_step_y;//*/
1079 #endif
1080 }
1081
1082 // write values back to registers
1083 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
1084 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
1085 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
1086 specialLog = false;
1087 }
1088
1089 void blitter_blit(uint32_t cmd)
1090 {
1091 //Apparently this is doing *something*, just not sure exactly what...
1092 /*if (cmd == 0x41802E01)
1093 {
1094 WriteLog("BLIT: Found our blit. Was: %08X ", cmd);
1095 cmd = 0x01800E01;
1096 WriteLog("Is: %08X\n", cmd);
1097 }//*/
1098
1099 uint32_t pitchValue[4] = { 0, 1, 3, 2 };
1100 colour_index = 0;
1101 src = cmd & 0x07;
1102 dst = (cmd >> 3) & 0x07;
1103 misc = (cmd >> 6) & 0x03;
1104 a1ctl = (cmd >> 8) & 0x7;
1105 mode = (cmd >> 11) & 0x07;
1106 ity = (cmd >> 14) & 0x0F;
1107 zop = (cmd >> 18) & 0x07;
1108 op = (cmd >> 21) & 0x0F;
1109 ctrl = (cmd >> 25) & 0x3F;
1110
1111 // Addresses in A1/2_BASE are *phrase* aligned, i.e., bottom three bits are ignored!
1112 // NOTE: This fixes Rayman's bad collision detection AND keeps T2K working!
1113 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1114 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1115
1116 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
1117 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
1118
1119 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
1120 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
1121
1122 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
1123 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
1124
1125 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
1126 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
1127
1128 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1129 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1130 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1131 //But it seems to fuck up T2K! !!! FIX !!!
1132 //Could it be sign extended??? Doesn't seem to be so according to JTRM
1133 // a1_x &= 0x7FFFFFFF, a1_y &= 0x0FFFFFFF;
1134 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1135 // a1_y &= 0x0FFFFFFF;
1136
1137 // a1_width = blitter_scanline_width[((REG(A1_FLAGS) & 0x00007E00) >> 9)];
1138 // According to JTRM, this must give a *whole number* of phrases in the current
1139 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1140 uint32_t m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1141 a1_width = ((0x04 | m) << e) >> 2;//*/
1142
1143 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1144 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1145 //According to the JTRM, X is restricted to 15 bits and Y is restricted to 12.
1146 //But it seems to fuck up T2K! !!! FIX !!!
1147 // a2_x &= 0x7FFFFFFF, a2_y &= 0x0FFFFFFF;
1148 //Actually, it says that the X is 16 bits. But it still seems to mess with the Y when restricted to 12...
1149 // a2_y &= 0x0FFFFFFF;
1150
1151 // a2_width = blitter_scanline_width[((REG(A2_FLAGS) & 0x00007E00) >> 9)];
1152 // According to JTRM, this must give a *whole number* of phrases in the current
1153 // pixel size (this means the lookup above is WRONG)... !!! FIX !!!
1154 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1155 a2_width = ((0x04 | m) << e) >> 2;//*/
1156 a2_mask_x = ((REG(A2_MASK) & 0x0000FFFF) << 16) | 0xFFFF;
1157 a2_mask_y = (REG(A2_MASK) & 0xFFFF0000) | 0xFFFF;
1158
1159 // Check for "use mask" flag
1160 if (!(REG(A2_FLAGS) & 0x8000))
1161 {
1162 a2_mask_x = 0xFFFFFFFF; // must be 16.16
1163 a2_mask_y = 0xFFFFFFFF; // must be 16.16
1164 }
1165
1166 a1_phrase_mode = 0;
1167
1168 // According to the official documentation, a hardware bug ties A2's yadd bit to A1's...
1169 a2_yadd = a1_yadd = (YADD1_A1 ? 1 << 16 : 0);
1170
1171 if (YSIGNSUB_A1)
1172 a1_yadd = -a1_yadd;
1173
1174 // determine a1_xadd
1175 switch (xadd_a1_control)
1176 {
1177 case XADDPHR:
1178 // This is a documented Jaguar bug relating to phrase mode and truncation... Look into it!
1179 // add phrase offset to X and truncate
1180 a1_xadd = 1 << 16;
1181 a1_phrase_mode = 1;
1182 break;
1183 case XADDPIX:
1184 // add pixelsize (1) to X
1185 a1_xadd = 1 << 16;
1186 break;
1187 case XADD0:
1188 // add zero (for those nice vertical lines)
1189 a1_xadd = 0;
1190 break;
1191 case XADDINC:
1192 // add the contents of the increment register
1193 a1_xadd = (REG(A1_INC) << 16) | (REG(A1_FINC) & 0x0000FFFF);
1194 a1_yadd = (REG(A1_INC) & 0xFFFF0000) | (REG(A1_FINC) >> 16);
1195 break;
1196 }
1197
1198
1199 //Blit! (0011D000 -> 000B9600) count: 228 x 1, A1/2_FLAGS: 00073820/00064220 [cmd: 41802801]
1200 // A1 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 128 (1C), addctl: XADDINC YADD1 XSIGNADD YSIGNADD
1201 // A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 320 (21), addctl: XADD0 YADD1 XSIGNADD YSIGNADD
1202 //if (YADD1_A1 && YADD1_A2 && xadd_a2_control == XADD0 && xadd_a1_control == XADDINC)// &&
1203 // uint32_t a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1204 //Ok, so this ISN'T it... Prolly the XADDPHR code above that's doing it...
1205 //if (REG(A1_FLAGS) == 0x00073820 && REG(A2_FLAGS) == 0x00064220 && cmd == 0x41802801)
1206 // A1 x/y: 14368/7, A2 x/y: 150/36
1207 //This is it... The problem...
1208 //if ((a1_x >> 16) == 14368) // 14368 = $3820
1209 // return; //Lesse what we got...
1210
1211 if (XSIGNSUB_A1)
1212 a1_xadd = -a1_xadd;
1213
1214 if (YSIGNSUB_A2)
1215 a2_yadd = -a2_yadd;
1216
1217 a2_phrase_mode = 0;
1218
1219 // determine a2_xadd
1220 switch (xadd_a2_control)
1221 {
1222 case XADDPHR:
1223 // add phrase offset to X and truncate
1224 a2_xadd = 1 << 16;
1225 a2_phrase_mode = 1;
1226 break;
1227 case XADDPIX:
1228 // add pixelsize (1) to X
1229 a2_xadd = 1 << 16;
1230 break;
1231 case XADD0:
1232 // add zero (for those nice vertical lines)
1233 a2_xadd = 0;
1234 break;
1235 //This really isn't a valid bit combo for A2... Shouldn't this cause the blitter to just say no?
1236 case XADDINC:
1237 WriteLog("BLIT: Asked to use invalid bit combo (XADDINC) for A2...\n");
1238 // add the contents of the increment register
1239 // since there is no register for a2 we just add 1
1240 //Let's do nothing, since it's not listed as a valid bit combo...
1241 // a2_xadd = 1 << 16;
1242 break;
1243 }
1244
1245 if (XSIGNSUB_A2)
1246 a2_xadd = -a2_xadd;
1247
1248 // Modify outer loop steps based on blitter command
1249
1250 a1_step_x = 0;
1251 a1_step_y = 0;
1252 a2_step_x = 0;
1253 a2_step_y = 0;
1254
1255 if (UPDA1F)
1256 a1_step_x = (REG(A1_FSTEP) & 0xFFFF),
1257 a1_step_y = (REG(A1_FSTEP) >> 16);
1258
1259 if (UPDA1)
1260 a1_step_x |= ((REG(A1_STEP) & 0x0000FFFF) << 16),
1261 a1_step_y |= ((REG(A1_STEP) & 0xFFFF0000));
1262
1263 if (UPDA2)
1264 a2_step_x = (REG(A2_STEP) & 0x0000FFFF) << 16,
1265 a2_step_y = (REG(A2_STEP) & 0xFFFF0000);
1266
1267 outer_loop = n_lines;
1268
1269 // Clipping...
1270
1271 if (CLIPA1)
1272 a1_clip_x = REG(A1_CLIP) & 0x7FFF,
1273 a1_clip_y = (REG(A1_CLIP) >> 16) & 0x7FFF;
1274
1275 // This phrase sizing is incorrect as well... !!! FIX !!! [NOTHING TO FIX]
1276 // Err, this is pixel size... (and it's OK)
1277 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
1278 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
1279
1280 // Z-buffering
1281 if (GOURZ)
1282 {
1283 zadd = REG(ZINC);
1284
1285 for(int v=0; v<4; v++)
1286 z_i[v] = REG(PHRASEZ0 + v*4);
1287 }
1288
1289 // Gouraud shading
1290 if (GOURD || GOURZ || SRCSHADE)
1291 {
1292 gd_c[0] = blitter_ram[PATTERNDATA + 6];
1293 gd_i[0] = ((uint32_t)blitter_ram[PATTERNDATA + 7] << 16)
1294 | ((uint32_t)blitter_ram[SRCDATA + 6] << 8) | blitter_ram[SRCDATA + 7];
1295
1296 gd_c[1] = blitter_ram[PATTERNDATA + 4];
1297 gd_i[1] = ((uint32_t)blitter_ram[PATTERNDATA + 5] << 16)
1298 | ((uint32_t)blitter_ram[SRCDATA + 4] << 8) | blitter_ram[SRCDATA + 5];
1299
1300 gd_c[2] = blitter_ram[PATTERNDATA + 2];
1301 gd_i[2] = ((uint32_t)blitter_ram[PATTERNDATA + 3] << 16)
1302 | ((uint32_t)blitter_ram[SRCDATA + 2] << 8) | blitter_ram[SRCDATA + 3];
1303
1304 gd_c[3] = blitter_ram[PATTERNDATA + 0];
1305 gd_i[3] = ((uint32_t)blitter_ram[PATTERNDATA + 1] << 16)
1306 | ((uint32_t)blitter_ram[SRCDATA + 0] << 8) | blitter_ram[SRCDATA + 1];
1307
1308 gouraud_add = REG(INTENSITYINC);
1309
1310 gd_ia = gouraud_add & 0x00FFFFFF;
1311 if (gd_ia & 0x00800000)
1312 gd_ia = 0xFF000000 | gd_ia;
1313
1314 gd_ca = (gouraud_add >> 24) & 0xFF;
1315 if (gd_ca & 0x00000080)
1316 gd_ca = 0xFFFFFF00 | gd_ca;
1317 }
1318
1319 // Bit comparitor fixing...
1320 /* if (BCOMPEN)
1321 {
1322 // Determine the data flow direction...
1323 if (!DSTA2)
1324 a2_step_x /= (1 << ((REG(A2_FLAGS) >> 3) & 0x07));
1325 else
1326 ;//add this later
1327 }//*/
1328 /* if (BCOMPEN)//Kludge for Hover Strike... !!! FIX !!!
1329 {
1330 // Determine the data flow direction...
1331 if (!DSTA2)
1332 a2_x <<= 3;
1333 }//*/
1334
1335 #ifdef LOG_BLITS
1336 if (start_logging)
1337 {
1338 WriteLog("Blit!\n");
1339 WriteLog(" cmd = 0x%.8x\n",cmd);
1340 WriteLog(" a1_base = %08X\n", a1_addr);
1341 WriteLog(" a1_pitch = %d\n", a1_pitch);
1342 WriteLog(" a1_psize = %d\n", a1_psize);
1343 WriteLog(" a1_width = %d\n", a1_width);
1344 WriteLog(" a1_xadd = %f (phrase=%d)\n", (float)a1_xadd / 65536.0, a1_phrase_mode);
1345 WriteLog(" a1_yadd = %f\n", (float)a1_yadd / 65536.0);
1346 WriteLog(" a1_xstep = %f\n", (float)a1_step_x / 65536.0);
1347 WriteLog(" a1_ystep = %f\n", (float)a1_step_y / 65536.0);
1348 WriteLog(" a1_x = %f\n", (float)a1_x / 65536.0);
1349 WriteLog(" a1_y = %f\n", (float)a1_y / 65536.0);
1350 WriteLog(" a1_zoffs = %i\n",a1_zoffs);
1351
1352 WriteLog(" a2_base = %08X\n", a2_addr);
1353 WriteLog(" a2_pitch = %d\n", a2_pitch);
1354 WriteLog(" a2_psize = %d\n", a2_psize);
1355 WriteLog(" a2_width = %d\n", a2_width);
1356 WriteLog(" a2_xadd = %f (phrase=%d)\n", (float)a2_xadd / 65536.0, a2_phrase_mode);
1357 WriteLog(" a2_yadd = %f\n", (float)a2_yadd / 65536.0);
1358 WriteLog(" a2_xstep = %f\n", (float)a2_step_x / 65536.0);
1359 WriteLog(" a2_ystep = %f\n", (float)a2_step_y / 65536.0);
1360 WriteLog(" a2_x = %f\n", (float)a2_x / 65536.0);
1361 WriteLog(" a2_y = %f\n", (float)a2_y / 65536.0);
1362 WriteLog(" a2_mask_x= 0x%.4x\n",a2_mask_x);
1363 WriteLog(" a2_mask_y= 0x%.4x\n",a2_mask_y);
1364 WriteLog(" a2_zoffs = %i\n",a2_zoffs);
1365
1366 WriteLog(" count = %d x %d\n", n_pixels, n_lines);
1367
1368 WriteLog(" command = %08X\n", cmd);
1369 WriteLog(" dsten = %i\n",DSTEN);
1370 WriteLog(" srcen = %i\n",SRCEN);
1371 WriteLog(" patdsel = %i\n",PATDSEL);
1372 WriteLog(" color = 0x%.8x\n",REG(PATTERNDATA));
1373 WriteLog(" dcompen = %i\n",DCOMPEN);
1374 WriteLog(" bcompen = %i\n",BCOMPEN);
1375 WriteLog(" cmpdst = %i\n",CMPDST);
1376 WriteLog(" GOURZ = %i\n",GOURZ);
1377 WriteLog(" GOURD = %i\n",GOURD);
1378 WriteLog(" SRCSHADE= %i\n",SRCSHADE);
1379 }
1380 #endif
1381
1382 //NOTE: Pitch is ignored!
1383
1384 //This *might* be the altimeter blits (they are)...
1385 //On captured screen, x-pos for black (inner) is 259, for pink is 257
1386 //Black is short by 3, pink is short by 1...
1387 /*
1388 Blit! (00110000 <- 000BF010) count: 9 x 31, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1389 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1390 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1391 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1392 A1 x/y: 262/124, A2 x/y: 128/0
1393 Blit! (00110000 <- 000BF010) count: 5 x 38, 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 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1396 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1397 A1 x/y: 264/117, A2 x/y: 407/0
1398
1399 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1400 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1401 A1 step values: -10 (X), 1 (Y)
1402 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1403 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1404 A1 x/y: 262/132, A2 x/y: 129/0
1405 Blit! (00110000 <- 000BF010) count: 5 x 27, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
1406 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
1407 A1 step values: -8 (X), 1 (Y)
1408 A1 -> pitch: 4(2) phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1409 A2 -> pitch: 1(0) phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
1410 A1 x/y: 264/128, A2 x/y: 336/0
1411
1412 264v vCursor ends up here...
1413 xxxxx...`
1414 111122223333
1415
1416 262v vCursor ends up here...
1417 xxxxxxxxx.'
1418 1111222233334444
1419
1420 Fixed! Now for more:
1421
1422 ; This looks like the ship icon in the upper left corner...
1423
1424 Blit! (00110000 <- 0010B2A8) count: 11 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1425 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1426 A1 step values: -12 (X), 1 (Y)
1427 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1428 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1429 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1430 A1 x/y: 20/24, A2 x/y: 5780/0
1431
1432 Also fixed!
1433
1434 More (not sure this is a blitter problem as much as it's a GPU problem):
1435 All but the "M" are trashed...
1436 This does *NOT* look like a blitter problem, as it's rendering properly...
1437 Actually, if you look at the A1 step values, there IS a discrepancy!
1438
1439 ; D
1440
1441 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1442 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1443 A1 step values: -14 (X), 1 (Y)
1444 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1445 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1446 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1447 A1 x/y: 134/144, A2 x/y: 2516/0
1448 ;129,146: +5,-2
1449
1450 ; E
1451
1452 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1453 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1454 A1 step values: -13 (X), 1 (Y)
1455 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1456 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1457 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1458 A1 x/y: 147/144, A2 x/y: 2660/0
1459
1460 ; M
1461
1462 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1463 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1464 A1 step values: -12 (X), 1 (Y)
1465 A2 step values: 0 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1466 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1467 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1468 A1 x/y: 160/144, A2 x/y: 3764/0
1469
1470 ; O
1471
1472 Blit! (00110000 <- 0010B2A8) count: 12 x 12, A1/2_FLAGS: 000042E2/00000020 [cmd: 09800609]
1473 CMD -> src: SRCEN dst: DSTEN misc: a1ctl: UPDA1 UPDA2 mode: ity: z-op: op: LFU_REPLACE ctrl: DCOMPEN
1474 A1 step values: -15 (X), 1 (Y)
1475 A2 step values: -4 (X), 0 (Y) [mask (unused): 00000000 - FFFFFFFF/FFFFFFFF]
1476 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1477 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
1478 A1 x/y: 173/144, A2 x/y: 4052/0
1479
1480 */
1481 //extern int op_start_log;
1482 if (blit_start_log)
1483 {
1484 const char * ctrlStr[4] = { "XADDPHR\0", "XADDPIX\0", "XADD0\0", "XADDINC\0" };
1485 const char * bppStr[8] = { "1bpp\0", "2bpp\0", "4bpp\0", "8bpp\0", "16bpp\0", "32bpp\0", "???\0", "!!!\0" };
1486 const char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1487 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1488 uint32_t /*src = cmd & 0x07, dst = (cmd >> 3) & 0x07, misc = (cmd >> 6) & 0x03,
1489 a1ctl = (cmd >> 8) & 0x07,*/ mode = (cmd >> 11) & 0x07/*, ity = (cmd >> 14) & 0x0F,
1490 zop = (cmd >> 18) & 0x07, op = (cmd >> 21) & 0x0F, ctrl = (cmd >> 25) & 0x3F*/;
1491 uint32_t a1f = REG(A1_FLAGS), a2f = REG(A2_FLAGS);
1492 uint32_t p1 = a1f & 0x07, p2 = a2f & 0x07,
1493 d1 = (a1f >> 3) & 0x07, d2 = (a2f >> 3) & 0x07,
1494 zo1 = (a1f >> 6) & 0x07, zo2 = (a2f >> 6) & 0x07,
1495 w1 = (a1f >> 9) & 0x3F, w2 = (a2f >> 9) & 0x3F,
1496 ac1 = (a1f >> 16) & 0x1F, ac2 = (a2f >> 16) & 0x1F;
1497 uint32_t iw1 = ((0x04 | (w1 & 0x03)) << ((w1 & 0x3C) >> 2)) >> 2;
1498 uint32_t iw2 = ((0x04 | (w2 & 0x03)) << ((w2 & 0x3C) >> 2)) >> 2;
1499 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);
1500 // 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);
1501
1502 WriteLog(" CMD -> src: %s%s%s ", (cmd & 0x0001 ? "SRCEN " : ""), (cmd & 0x0002 ? "SRCENZ " : ""), (cmd & 0x0004 ? "SRCENX" : ""));
1503 WriteLog("dst: %s%s%s ", (cmd & 0x0008 ? "DSTEN " : ""), (cmd & 0x0010 ? "DSTENZ " : ""), (cmd & 0x0020 ? "DSTWRZ" : ""));
1504 WriteLog("misc: %s%s ", (cmd & 0x0040 ? "CLIP_A1 " : ""), (cmd & 0x0080 ? "???" : ""));
1505 WriteLog("a1ctl: %s%s%s ", (cmd & 0x0100 ? "UPDA1F " : ""), (cmd & 0x0200 ? "UPDA1 " : ""), (cmd & 0x0400 ? "UPDA2" : ""));
1506 WriteLog("mode: %s%s%s ", (cmd & 0x0800 ? "DSTA2 " : ""), (cmd & 0x1000 ? "GOURD " : ""), (cmd & 0x2000 ? "GOURZ" : ""));
1507 WriteLog("ity: %s%s%s%s ", (cmd & 0x4000 ? "TOPBEN " : ""), (cmd & 0x8000 ? "TOPNEN " : ""), (cmd & 0x00010000 ? "PATDSEL" : ""), (cmd & 0x00020000 ? "ADDDSEL" : ""));
1508 WriteLog("z-op: %s%s%s ", (cmd & 0x00040000 ? "ZMODELT " : ""), (cmd & 0x00080000 ? "ZMODEEQ " : ""), (cmd & 0x00100000 ? "ZMODEGT" : ""));
1509 WriteLog("op: %s ", opStr[(cmd >> 21) & 0x0F]);
1510 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" : ""));
1511
1512 if (UPDA1)
1513 WriteLog(" A1 step values: %d (X), %d (Y)\n", a1_step_x >> 16, a1_step_y >> 16);
1514
1515 if (UPDA2)
1516 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);
1517
1518 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"));
1519 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"));
1520 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));
1521 // blit_start_log = 0;
1522 // op_start_log = 1;
1523 }
1524
1525 blitter_working = 1;
1526 //#ifndef USE_GENERIC_BLITTER
1527 // if (!blitter_execute_cached_code(blitter_in_cache(cmd)))
1528 //#endif
1529 blitter_generic(cmd);
1530
1531 /*if (blit_start_log)
1532 {
1533 if (a1_addr == 0xF03000 && a2_addr == 0x004D58)
1534 {
1535 WriteLog("\nBytes at 004D58:\n");
1536 for(int i=0x004D58; i<0x004D58+(10*127*4); i++)
1537 WriteLog("%02X ", JaguarReadByte(i));
1538 WriteLog("\nBytes at F03000:\n");
1539 for(int i=0xF03000; i<0xF03000+(6*127*4); i++)
1540 WriteLog("%02X ", JaguarReadByte(i));
1541 WriteLog("\n\n");
1542 }
1543 }//*/
1544
1545 blitter_working = 0;
1546 }
1547 #endif // of the #if 0 near the top...
1548 /*******************************************************************************
1549 ********************** STUFF CUT ABOVE THIS LINE! ******************************
1550 *******************************************************************************/
1551
1552
1553 void BlitterInit(void)
1554 {
1555 BlitterReset();
1556 }
1557
1558
1559 void BlitterReset(void)
1560 {
1561 memset(blitter_ram, 0x00, 0xA0);
1562 }
1563
1564
1565 void BlitterDone(void)
1566 {
1567 WriteLog("BLIT: Done.\n");
1568 }
1569
1570
1571 uint8_t BlitterReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1572 {
1573 offset &= 0xFF;
1574
1575 // status register
1576 //This isn't cycle accurate--how to fix? !!! FIX !!!
1577 //Probably have to do some multi-threaded implementation or at least a reentrant safe implementation...
1578 //Real hardware returns $00000805, just like the JTRM says.
1579 if (offset == (0x38 + 0))
1580 return 0x00;
1581 if (offset == (0x38 + 1))
1582 return 0x00;
1583 if (offset == (0x38 + 2))
1584 return 0x08;
1585 if (offset == (0x38 + 3))
1586 return 0x05; // always idle/never stopped (collision detection ignored!)
1587
1588 // CHECK HERE ONCE THIS FIX HAS BEEN TESTED: [X]
1589 //Fix for AvP:
1590 if (offset >= 0x04 && offset <= 0x07)
1591 //This is it. I wonder if it just ignores the lower three bits?
1592 //No, this is a documented Jaguar I bug. It also bites the read at $F02230 as well...
1593 return blitter_ram[offset + 0x08]; // A1_PIXEL ($F0220C) read at $F02204
1594
1595 if (offset >= 0x2C && offset <= 0x2F)
1596 return blitter_ram[offset + 0x04]; // A2_PIXEL ($F02230) read at $F0222C
1597
1598 return blitter_ram[offset];
1599 }
1600
1601
1602 //Crappy!
1603 uint16_t BlitterReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1604 {
1605 return ((uint16_t)BlitterReadByte(offset, who) << 8) | (uint16_t)BlitterReadByte(offset+1, who);
1606 }
1607
1608
1609 //Crappy!
1610 uint32_t BlitterReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1611 {
1612 return (BlitterReadWord(offset, who) << 16) | BlitterReadWord(offset+2, who);
1613 }
1614
1615
1616 void BlitterWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
1617 {
1618 /*if (offset & 0xFF == 0x7B)
1619 WriteLog("--> Wrote to B_STOP: value -> %02X\n", data);*/
1620 offset &= 0xFF;
1621 /*if ((offset >= PATTERNDATA) && (offset < PATTERNDATA + 8))
1622 {
1623 printf("--> %s wrote %02X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - PATTERNDATA);
1624 fflush(stdout);
1625 }//*/
1626
1627 // This handles writes to INTENSITY0-3 by also writing them to their proper places in
1628 // PATTERNDATA & SOURCEDATA (should do the same for the Z registers! !!! FIX !!! [DONE])
1629 if ((offset >= 0x7C) && (offset <= 0x9B))
1630 {
1631 switch (offset)
1632 {
1633 // INTENSITY registers 0-3
1634 case 0x7C: break;
1635 case 0x7D: blitter_ram[PATTERNDATA + 7] = data; break;
1636 case 0x7E: blitter_ram[SRCDATA + 6] = data; break;
1637 case 0x7F: blitter_ram[SRCDATA + 7] = data; break;
1638
1639 case 0x80: break;
1640 case 0x81: blitter_ram[PATTERNDATA + 5] = data; break;
1641 case 0x82: blitter_ram[SRCDATA + 4] = data; break;
1642 case 0x83: blitter_ram[SRCDATA + 5] = data; break;
1643
1644 case 0x84: break;
1645 case 0x85: blitter_ram[PATTERNDATA + 3] = data; break;
1646 case 0x86: blitter_ram[SRCDATA + 2] = data; break;
1647 case 0x87: blitter_ram[SRCDATA + 3] = data; break;
1648
1649 case 0x88: break;
1650 case 0x89: blitter_ram[PATTERNDATA + 1] = data; break;
1651 case 0x8A: blitter_ram[SRCDATA + 0] = data; break;
1652 case 0x8B: blitter_ram[SRCDATA + 1] = data; break;
1653
1654
1655 // Z registers 0-3
1656 case 0x8C: blitter_ram[SRCZINT + 6] = data; break;
1657 case 0x8D: blitter_ram[SRCZINT + 7] = data; break;
1658 case 0x8E: blitter_ram[SRCZFRAC + 6] = data; break;
1659 case 0x8F: blitter_ram[SRCZFRAC + 7] = data; break;
1660
1661 case 0x90: blitter_ram[SRCZINT + 4] = data; break;
1662 case 0x91: blitter_ram[SRCZINT + 5] = data; break;
1663 case 0x92: blitter_ram[SRCZFRAC + 4] = data; break;
1664 case 0x93: blitter_ram[SRCZFRAC + 5] = data; break;
1665
1666 case 0x94: blitter_ram[SRCZINT + 2] = data; break;
1667 case 0x95: blitter_ram[SRCZINT + 3] = data; break;
1668 case 0x96: blitter_ram[SRCZFRAC + 2] = data; break;
1669 case 0x97: blitter_ram[SRCZFRAC + 3] = data; break;
1670
1671 case 0x98: blitter_ram[SRCZINT + 0] = data; break;
1672 case 0x99: blitter_ram[SRCZINT + 1] = data; break;
1673 case 0x9A: blitter_ram[SRCZFRAC + 0] = data; break;
1674 case 0x9B: blitter_ram[SRCZFRAC + 1] = data; break;
1675 }
1676 }
1677
1678 // It looks weird, but this is how the 64 bit registers are actually handled...!
1679
1680 else if ((offset >= SRCDATA + 0) && (offset <= SRCDATA + 3)
1681 || (offset >= DSTDATA + 0) && (offset <= DSTDATA + 3)
1682 || (offset >= DSTZ + 0) && (offset <= DSTZ + 3)
1683 || (offset >= SRCZINT + 0) && (offset <= SRCZINT + 3)
1684 || (offset >= SRCZFRAC + 0) && (offset <= SRCZFRAC + 3)
1685 || (offset >= PATTERNDATA + 0) && (offset <= PATTERNDATA + 3))
1686 {
1687 blitter_ram[offset + 4] = data;
1688 }
1689 else if ((offset >= SRCDATA + 4) && (offset <= SRCDATA + 7)
1690 || (offset >= DSTDATA + 4) && (offset <= DSTDATA + 7)
1691 || (offset >= DSTZ + 4) && (offset <= DSTZ + 7)
1692 || (offset >= SRCZINT + 4) && (offset <= SRCZINT + 7)
1693 || (offset >= SRCZFRAC + 4) && (offset <= SRCZFRAC + 7)
1694 || (offset >= PATTERNDATA + 4) && (offset <= PATTERNDATA + 7))
1695 {
1696 blitter_ram[offset - 4] = data;
1697 }
1698 else
1699 blitter_ram[offset] = data;
1700 }
1701
1702
1703 void BlitterWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
1704 {
1705 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1706 {
1707 printf("----> %s wrote %04X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1708 fflush(stdout);
1709 }*/
1710 //#if 1
1711 /* if (offset & 0xFF == A1_PIXEL && data == 14368)
1712 {
1713 WriteLog("\n1\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1714 extern bool doGPUDis;
1715 doGPUDis = true;
1716 }
1717 if ((offset & 0xFF) == (A1_PIXEL + 2) && data == 14368)
1718 {
1719 WriteLog("\n2\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1720 extern bool doGPUDis;
1721 doGPUDis = true;
1722 }//*/
1723 //#endif
1724
1725 BlitterWriteByte(offset + 0, data >> 8, who);
1726 BlitterWriteByte(offset + 1, data & 0xFF, who);
1727
1728 if ((offset & 0xFF) == 0x3A)
1729 // I.e., the second write of 32-bit value--not convinced this is the best way to do this!
1730 // But then again, according to the Jaguar docs, this is correct...!
1731 /*extern int blit_start_log;
1732 extern bool doGPUDis;
1733 if (blit_start_log)
1734 {
1735 WriteLog("BLIT: Blitter started by %s...\n", whoName[who]);
1736 doGPUDis = true;
1737 }//*/
1738 #ifndef USE_BOTH_BLITTERS
1739 #ifdef USE_ORIGINAL_BLITTER
1740 blitter_blit(GET32(blitter_ram, 0x38));
1741 #endif
1742 #ifdef USE_MIDSUMMER_BLITTER
1743 BlitterMidsummer(GET32(blitter_ram, 0x38));
1744 #endif
1745 #ifdef USE_MIDSUMMER_BLITTER_MKII
1746 BlitterMidsummer2();
1747 #endif
1748 #else
1749 {
1750 if (vjs.useFastBlitter)
1751 blitter_blit(GET32(blitter_ram, 0x38));
1752 else
1753 BlitterMidsummer2();
1754 }
1755 #endif
1756 }
1757 //F02278,9,A,B
1758
1759
1760 void BlitterWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
1761 {
1762 /*if (((offset & 0xFF) >= PATTERNDATA) && ((offset & 0xFF) < PATTERNDATA + 8))
1763 {
1764 printf("------> %s wrote %08X to byte %u of PATTERNDATA...\n", whoName[who], data, offset - (0xF02200 + PATTERNDATA));
1765 fflush(stdout);
1766 }//*/
1767 //#if 1
1768 /* if ((offset & 0xFF) == A1_PIXEL && (data & 0xFFFF) == 14368)
1769 {
1770 WriteLog("\n3\nA1_PIXEL written by %s (%u)...\n\n\n", whoName[who], data);
1771 extern bool doGPUDis;
1772 doGPUDis = true;
1773 }//*/
1774 //#endif
1775
1776 BlitterWriteWord(offset + 0, data >> 16, who);
1777 BlitterWriteWord(offset + 2, data & 0xFFFF, who);
1778 }
1779
1780
1781 void LogBlit(void)
1782 {
1783 const char * opStr[16] = { "LFU_CLEAR", "LFU_NSAND", "LFU_NSAD", "LFU_NOTS", "LFU_SAND", "LFU_NOTD", "LFU_N_SXORD", "LFU_NSORND",
1784 "LFU_SAD", "LFU_XOR", "LFU_D", "LFU_NSORD", "LFU_REPLACE", "LFU_SORND", "LFU_SORD", "LFU_ONE" };
1785 uint32_t cmd = GET32(blitter_ram, 0x38);
1786 uint32_t m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1787 uint32_t a1_width = ((0x04 | m) << e) >> 2;
1788 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1789 uint32_t a2_width = ((0x04 | m) << e) >> 2;
1790
1791 WriteLog("Blit!\n");
1792 WriteLog(" COMMAND = %08X\n", cmd);
1793 WriteLog(" a1_base = %08X\n", REG(A1_BASE));
1794 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),
1795 (REG(A1_FLAGS) & 0x100000 ? '1' : '0'),
1796 (REG(A1_FLAGS) & 0x080000 ? '1' : '0'),
1797 (REG(A1_FLAGS) & 0x040000 ? '1' : '0'),
1798 (REG(A1_FLAGS) & 0x020000 ? '1' : '0'),
1799 (REG(A1_FLAGS) & 0x010000 ? '1' : '0'),
1800 (REG(A1_FLAGS) & 0x004000 ? '1' : '0'),
1801 (REG(A1_FLAGS) & 0x002000 ? '1' : '0'),
1802 (REG(A1_FLAGS) & 0x001000 ? '1' : '0'),
1803 (REG(A1_FLAGS) & 0x000800 ? '1' : '0'),
1804 (REG(A1_FLAGS) & 0x000400 ? '1' : '0'),
1805 (REG(A1_FLAGS) & 0x000200 ? '1' : '0'),
1806 (REG(A1_FLAGS) & 0x000100 ? '1' : '0'),
1807 (REG(A1_FLAGS) & 0x000080 ? '1' : '0'),
1808 (REG(A1_FLAGS) & 0x000040 ? '1' : '0'),
1809 (REG(A1_FLAGS) & 0x000020 ? '1' : '0'),
1810 (REG(A1_FLAGS) & 0x000010 ? '1' : '0'),
1811 (REG(A1_FLAGS) & 0x000008 ? '1' : '0'),
1812 (REG(A1_FLAGS) & 0x000002 ? '1' : '0'),
1813 (REG(A1_FLAGS) & 0x000001 ? '1' : '0'));
1814 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1815 REG(A1_FLAGS) & 0x00003, (REG(A1_FLAGS) & 0x00038) >> 3,
1816 (REG(A1_FLAGS) & 0x001C0) >> 6, a1_width, (REG(A1_FLAGS) & 0x30000) >> 16);
1817 WriteLog(" a1_clip = %u, %u (%08X)\n", GET16(blitter_ram, A1_CLIP + 2), GET16(blitter_ram, A1_CLIP + 0), GET32(blitter_ram, A1_CLIP));
1818 WriteLog(" a1_pixel = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A1_PIXEL + 2), (int16_t)GET16(blitter_ram, A1_PIXEL + 0), GET32(blitter_ram, A1_PIXEL));
1819 WriteLog(" a1_step = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A1_STEP + 2), (int16_t)GET16(blitter_ram, A1_STEP + 0), GET32(blitter_ram, A1_STEP));
1820 WriteLog(" a1_fstep = %u, %u (%08X)\n", GET16(blitter_ram, A1_FSTEP + 2), GET16(blitter_ram, A1_FSTEP + 0), GET32(blitter_ram, A1_FSTEP));
1821 WriteLog(" a1_fpixel= %u, %u (%08X)\n", GET16(blitter_ram, A1_FPIXEL + 2), GET16(blitter_ram, A1_FPIXEL + 0), GET32(blitter_ram, A1_FPIXEL));
1822 WriteLog(" a1_inc = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A1_INC + 2), (int16_t)GET16(blitter_ram, A1_INC + 0), GET32(blitter_ram, A1_INC));
1823 WriteLog(" a1_finc = %u, %u (%08X)\n", GET16(blitter_ram, A1_FINC + 2), GET16(blitter_ram, A1_FINC + 0), GET32(blitter_ram, A1_FINC));
1824
1825 WriteLog(" a2_base = %08X\n", REG(A2_BASE));
1826 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),
1827 (REG(A2_FLAGS) & 0x100000 ? '1' : '0'),
1828 (REG(A2_FLAGS) & 0x080000 ? '1' : '0'),
1829 (REG(A2_FLAGS) & 0x040000 ? '1' : '0'),
1830 (REG(A2_FLAGS) & 0x020000 ? '1' : '0'),
1831 (REG(A2_FLAGS) & 0x010000 ? '1' : '0'),
1832 (REG(A2_FLAGS) & 0x008000 ? '1' : '0'),
1833 (REG(A2_FLAGS) & 0x004000 ? '1' : '0'),
1834 (REG(A2_FLAGS) & 0x002000 ? '1' : '0'),
1835 (REG(A2_FLAGS) & 0x001000 ? '1' : '0'),
1836 (REG(A2_FLAGS) & 0x000800 ? '1' : '0'),
1837 (REG(A2_FLAGS) & 0x000400 ? '1' : '0'),
1838 (REG(A2_FLAGS) & 0x000200 ? '1' : '0'),
1839 (REG(A2_FLAGS) & 0x000100 ? '1' : '0'),
1840 (REG(A2_FLAGS) & 0x000080 ? '1' : '0'),
1841 (REG(A2_FLAGS) & 0x000040 ? '1' : '0'),
1842 (REG(A2_FLAGS) & 0x000020 ? '1' : '0'),
1843 (REG(A2_FLAGS) & 0x000010 ? '1' : '0'),
1844 (REG(A2_FLAGS) & 0x000008 ? '1' : '0'),
1845 (REG(A2_FLAGS) & 0x000002 ? '1' : '0'),
1846 (REG(A2_FLAGS) & 0x000001 ? '1' : '0'));
1847 WriteLog(" pitch=%u, pixSz=%u, zOff=%u, width=%u, xCtrl=%u\n",
1848 REG(A2_FLAGS) & 0x00003, (REG(A2_FLAGS) & 0x00038) >> 3,
1849 (REG(A2_FLAGS) & 0x001C0) >> 6, a2_width, (REG(A2_FLAGS) & 0x30000) >> 16);
1850 WriteLog(" a2_mask = %u, %u (%08X)\n", GET16(blitter_ram, A2_MASK + 2), GET16(blitter_ram, A2_MASK + 0), GET32(blitter_ram, A2_MASK));
1851 WriteLog(" a2_pixel = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A2_PIXEL + 2), (int16_t)GET16(blitter_ram, A2_PIXEL + 0), GET32(blitter_ram, A2_PIXEL));
1852 WriteLog(" a2_step = %d, %d (%08X)\n", (int16_t)GET16(blitter_ram, A2_STEP + 2), (int16_t)GET16(blitter_ram, A2_STEP + 0), GET32(blitter_ram, A2_STEP));
1853
1854 WriteLog(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
1855
1856 WriteLog(" SRCEN = %s\n", (SRCEN ? "1" : "0"));
1857 WriteLog(" SRCENZ = %s\n", (SRCENZ ? "1" : "0"));
1858 WriteLog(" SRCENX = %s\n", (SRCENX ? "1" : "0"));
1859 WriteLog(" DSTEN = %s\n", (DSTEN ? "1" : "0"));
1860 WriteLog(" DSTENZ = %s\n", (DSTENZ ? "1" : "0"));
1861 WriteLog(" DSTWRZ = %s\n", (DSTWRZ ? "1" : "0"));
1862 WriteLog(" CLIPA1 = %s\n", (CLIPA1 ? "1" : "0"));
1863 WriteLog(" UPDA1F = %s\n", (UPDA1F ? "1" : "0"));
1864 WriteLog(" UPDA1 = %s\n", (UPDA1 ? "1" : "0"));
1865 WriteLog(" UPDA2 = %s\n", (UPDA2 ? "1" : "0"));
1866 WriteLog(" DSTA2 = %s\n", (DSTA2 ? "1" : "0"));
1867 WriteLog(" ZOP = %s %s %s\n", (Z_OP_INF ? "<" : ""), (Z_OP_EQU ? "=" : ""), (Z_OP_SUP ? ">" : ""));
1868 WriteLog("+-LFUFUNC = %s\n", opStr[(cmd >> 21) & 0x0F]);
1869 WriteLog("| PATDSEL = %s (PD=%08X%08X)\n", (PATDSEL ? "1" : "0"), REG(PATTERNDATA), REG(PATTERNDATA + 4));
1870 WriteLog("+-ADDDSEL = %s\n", (ADDDSEL ? "1" : "0"));
1871 WriteLog(" CMPDST = %s\n", (CMPDST ? "1" : "0"));
1872 WriteLog(" BCOMPEN = %s\n", (BCOMPEN ? "1" : "0"));
1873 WriteLog(" DCOMPEN = %s\n", (DCOMPEN ? "1" : "0"));
1874 WriteLog(" TOPBEN = %s\n", (TOPBEN ? "1" : "0"));
1875 WriteLog(" TOPNEN = %s\n", (TOPNEN ? "1" : "0"));
1876 WriteLog(" BKGWREN = %s\n", (BKGWREN ? "1" : "0"));
1877 WriteLog(" GOURD = %s (II=%08X, SD=%08X%08X)\n", (GOURD ? "1" : "0"), REG(INTENSITYINC), REG(SRCDATA), REG(SRCDATA + 4));
1878 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),
1879 REG(SRCZINT), REG(SRCZINT + 4), REG(SRCZFRAC), REG(SRCZFRAC + 4));
1880 WriteLog(" SRCSHADE = %s\n", (SRCSHADE ? "1" : "0"));
1881 }
1882
1883
1884 #ifdef USE_MIDSUMMER_BLITTER
1885 //
1886 // Here's an attempt to write a blitter that conforms to the Midsummer specs--since
1887 // it's supposedly backwards compatible, it should work well...
1888 //
1889 //#define LOG_BLITTER_MEMORY_ACCESSES
1890
1891 #define DATINIT (false)
1892 #define TXTEXT (false)
1893 #define POLYGON (false)
1894
1895 void BlitterMidsummer(uint32_t cmd)
1896 {
1897 #ifdef LOG_BLITS
1898 LogBlit();
1899 #endif
1900 uint32_t outer_loop, inner_loop, a1_addr, a2_addr;
1901 int32_t a1_x, a1_y, a2_x, a2_y, a1_width, a2_width;
1902 uint8_t a1_phrase_mode, a2_phrase_mode;
1903
1904 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
1905 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
1906 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
1907 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
1908 uint32_t m = (REG(A1_FLAGS) >> 9) & 0x03, e = (REG(A1_FLAGS) >> 11) & 0x0F;
1909 a1_width = ((0x04 | m) << e) >> 2;//*/
1910 a2_x = (REG(A2_PIXEL) & 0x0000FFFF) << 16;
1911 a2_y = (REG(A2_PIXEL) & 0xFFFF0000);
1912 m = (REG(A2_FLAGS) >> 9) & 0x03, e = (REG(A2_FLAGS) >> 11) & 0x0F;
1913 a2_width = ((0x04 | m) << e) >> 2;//*/
1914
1915 a1_phrase_mode = a2_phrase_mode = 0;
1916
1917 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
1918 a1_phrase_mode = 1;
1919
1920 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
1921 a2_phrase_mode = 1;
1922
1923 #define INNER0 (inner_loop == 0)
1924 #define OUTER0 (outer_loop == 0)
1925
1926 // $01800005 has SRCENX, may have to investigate further...
1927 // $00011008 has GOURD & DSTEN.
1928 // $41802F41 has SRCSHADE, CLIPA1
1929 /*bool logBlit = false;
1930 if (cmd != 0x00010200 && cmd != 0x01800001 && cmd != 0x01800005
1931 && cmd != 0x00011008 && cmd !=0x41802F41)
1932 {
1933 logBlit = true;
1934 LogBlit();
1935 }//*/
1936
1937 uint64_t srcData = GET64(blitter_ram, SRCDATA), srcXtraData,
1938 dstData = GET64(blitter_ram, DSTDATA), writeData;
1939 uint32_t srcAddr, dstAddr;
1940 uint8_t bitCount, a1PixelSize, a2PixelSize;
1941
1942 // JTRM says phrase mode only works for 8BPP or higher, so let's try this...
1943 uint32_t phraseOffset[8] = { 8, 8, 8, 8, 4, 2, 0, 0 };
1944 uint8_t pixelShift[8] = { 3, 2, 1, 0, 1, 2, 0, 0 };
1945
1946 a1PixelSize = (blitter_ram[A1_FLAGS + 3] >> 3) & 0x07;
1947 a2PixelSize = (blitter_ram[A2_FLAGS + 3] >> 3) & 0x07;
1948
1949 outer_loop = GET16(blitter_ram, PIXLINECOUNTER + 0);
1950
1951 if (outer_loop == 0)
1952 outer_loop = 0x10000;
1953
1954 // We just list the states here and jump from state to state in order to
1955 // keep things somewhat clear. Optimization/cleanups later.
1956
1957 //idle: // Blitter is idle, and will not perform any bus activity
1958 /*
1959 idle Blitter is off the bus, and no activity takes place.
1960 if GO if DATINIT goto init_if
1961 else goto inner
1962 */
1963 if (DATINIT)
1964 goto init_if;
1965 else
1966 goto inner;
1967
1968 /*
1969 inner Inner loop is active, read and write cycles are performed
1970 */
1971 inner: // Run inner loop state machine (asserts step from its idle state)
1972 inner_loop = GET16(blitter_ram, PIXLINECOUNTER + 2);
1973
1974 if (inner_loop == 0)
1975 inner_loop = 0x10000;
1976
1977 /*
1978 ------------------------------
1979 idle: Inactive, blitter is idle or passing round outer loop
1980 idle Another state in the outer loop is active. No bus transfers are performed.
1981 if STEP
1982 if SRCENX goto sreadx
1983 else if TXTEXT goto txtread
1984 else if SRCEN goto sread
1985 else if DSTEN goto dread
1986 else if DSTENZ goto dzread
1987 else goto dwrite
1988 */
1989 if (SRCENX)
1990 goto sreadx;
1991 else if (TXTEXT)
1992 goto txtread;
1993 else if (SRCEN)
1994 goto sread;
1995 else if (DSTEN)
1996 goto dread;
1997 else if (DSTENZ)
1998 goto dzread;
1999 else
2000 goto dwrite;
2001
2002 /*
2003 sreadx Extra source data read at the start of an inner loop pass.
2004 if STEP
2005 if SRCENZ goto szreadx
2006 else if TXTEXT goto txtread
2007 else if SRCEN goto sread
2008 else if DSTEN goto dread
2009 else if DSTENZ goto dzread
2010 else goto dwrite
2011 */
2012 sreadx: // Extra source data read
2013 if (SRCENZ)
2014 goto szreadx;
2015 else if (TXTEXT)
2016 goto txtread;
2017 else if (SRCEN)
2018 goto sread;
2019 else if (DSTEN)
2020 goto dread;
2021 else if (DSTENZ)
2022 goto dzread;
2023 else
2024 goto dwrite;
2025
2026 /*
2027 szreadx Extra source Z read as the start of an inner loop pass.
2028 if STEP
2029 if TXTEXT goto txtread
2030 else goto sread
2031 */
2032 szreadx: // Extra source Z read
2033 if (TXTEXT)
2034 goto txtread;
2035 else
2036 goto sread;
2037
2038 /*
2039 txtread Read texture data from external memory. This state is only used for external texture.
2040 TEXTEXT is the condition TEXTMODE=1.
2041 if STEP
2042 if SRCEN goto sread
2043 else if DSTEN goto dread
2044 else if DSTENZ goto dzread
2045 else goto dwrite
2046 */
2047 txtread: // Read external texture data
2048 if (SRCEN)
2049 goto sread;
2050 else if (DSTEN)
2051 goto dread;
2052 else if (DSTENZ)
2053 goto dzread;
2054 else
2055 goto dwrite;
2056
2057 /*
2058 sread Source data read.
2059 if STEP
2060 if SRCENZ goto szread
2061 else if DSTEN goto dread
2062 else if DSTENZ goto dzread
2063 else goto dwrite
2064 */
2065 sread: // Source data read
2066 //The JTRM doesn't really specify the internal structure of the source data read, but I would
2067 //imagine that if it's in phrase mode that it starts by reading the phrase that the window is
2068 //pointing at. Likewise, the pixel (if in BPP 1, 2 & 4, chopped) otherwise. It probably still
2069 //transfers an entire phrase even in pixel mode.
2070 //Odd thought: Does it expand, e.g., 1 BPP pixels into 32 BPP internally? Hmm...
2071 //No.
2072 /*
2073 a1_addr = REG(A1_BASE) & 0xFFFFFFF8;
2074 a2_addr = REG(A2_BASE) & 0xFFFFFFF8;
2075 a1_zoffs = (REG(A1_FLAGS) >> 6) & 7;
2076 a2_zoffs = (REG(A2_FLAGS) >> 6) & 7;
2077 xadd_a1_control = (REG(A1_FLAGS) >> 16) & 0x03;
2078 xadd_a2_control = (REG(A2_FLAGS) >> 16) & 0x03;
2079 a1_pitch = pitchValue[(REG(A1_FLAGS) & 0x03)];
2080 a2_pitch = pitchValue[(REG(A2_FLAGS) & 0x03)];
2081 n_pixels = REG(PIXLINECOUNTER) & 0xFFFF;
2082 n_lines = (REG(PIXLINECOUNTER) >> 16) & 0xFFFF;
2083 a1_x = (REG(A1_PIXEL) << 16) | (REG(A1_FPIXEL) & 0xFFFF);
2084 a1_y = (REG(A1_PIXEL) & 0xFFFF0000) | (REG(A1_FPIXEL) >> 16);
2085 a2_psize = 1 << ((REG(A2_FLAGS) >> 3) & 0x07);
2086 a1_psize = 1 << ((REG(A1_FLAGS) >> 3) & 0x07);
2087 a1_phrase_mode = 0;
2088 a2_phrase_mode = 0;
2089 a1_width = ((0x04 | m) << e) >> 2;
2090 a2_width = ((0x04 | m) << e) >> 2;
2091
2092 // write values back to registers
2093 WREG(A1_PIXEL, (a1_y & 0xFFFF0000) | ((a1_x >> 16) & 0xFFFF));
2094 WREG(A1_FPIXEL, (a1_y << 16) | (a1_x & 0xFFFF));
2095 WREG(A2_PIXEL, (a2_y & 0xFFFF0000) | ((a2_x >> 16) & 0xFFFF));
2096 */
2097 // Calculate the address to be read...
2098
2099 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2100 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2101 //for 8BPP. !!! FIX !!!
2102 srcAddr = (DSTA2 ? a1_addr : a2_addr);
2103
2104 /* if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2105 {
2106 srcAddr += (((DSTA2 ? a1_x : a2_x) >> 16)
2107 + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width)));
2108 }
2109 else*/
2110 {
2111 // uint32_t pixAddr = ((DSTA2 ? a1_x : a2_x) >> 16)
2112 // + (((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2113 int32_t pixAddr = (int16_t)((DSTA2 ? a1_x : a2_x) >> 16)
2114 + ((int16_t)((DSTA2 ? a1_y : a2_y) >> 16) * (DSTA2 ? a1_width : a2_width));
2115
2116 if ((DSTA2 ? a1PixelSize : a2PixelSize) < 3)
2117 pixAddr >>= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2118 else if ((DSTA2 ? a1PixelSize : a2PixelSize) > 3)
2119 pixAddr <<= pixelShift[(DSTA2 ? a1PixelSize : a2PixelSize)];
2120
2121 srcAddr += pixAddr;
2122 }
2123
2124 // And read it!
2125
2126 if ((DSTA2 ? a1_phrase_mode : a2_phrase_mode) == 1)
2127 {
2128 srcData = ((uint64_t)JaguarReadLong(srcAddr, BLITTER) << 32)
2129 | (uint64_t)JaguarReadLong(srcAddr + 4, BLITTER);
2130 }
2131 else
2132 {
2133 //1,2,&4BPP are wrong here... !!! FIX !!!
2134 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 0) // 1 BPP
2135 srcData = JaguarReadByte(srcAddr, BLITTER);
2136 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 1) // 2 BPP
2137 srcData = JaguarReadByte(srcAddr, BLITTER);
2138 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 2) // 4 BPP
2139 srcData = JaguarReadByte(srcAddr, BLITTER);
2140 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 3) // 8 BPP
2141 srcData = JaguarReadByte(srcAddr, BLITTER);
2142 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 4) // 16 BPP
2143 srcData = JaguarReadWord(srcAddr, BLITTER);
2144 if ((DSTA2 ? a1PixelSize : a2PixelSize) == 5) // 32 BPP
2145 srcData = JaguarReadLong(srcAddr, BLITTER);
2146 }
2147
2148 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2149 if (logBlit)
2150 WriteLog("BLITTER: srcAddr=%08X, srcData=%08X %08X\n", srcAddr, (uint32_t)(srcData >> 32), (uint32_t)(srcData & 0xFFFFFFFF));
2151 #endif
2152
2153 if (SRCENZ)
2154 goto szread;
2155 else if (DSTEN)
2156 goto dread;
2157 else if (DSTENZ)
2158 goto dzread;
2159 else
2160 goto dwrite;
2161
2162 szread: // Source Z read
2163 /*
2164 szread Source Z read.
2165 if STEP
2166 if DSTEN goto dread
2167 else if DSTENZ goto dzread
2168 else goto dwrite
2169 */
2170 if (DSTEN)
2171 goto dread;
2172 else if (DSTENZ)
2173 goto dzread;
2174 else
2175 goto dwrite;
2176
2177 dread: // Destination data read
2178 /*
2179 dread Destination data read.
2180 if STEP
2181 if DSTENZ goto dzread
2182 else goto dwrite
2183 */
2184 // Calculate the destination address to be read...
2185
2186 //Need to fix phrase mode calcs here, since they should *step* by eight, not mulitply.
2187 //Also, need to fix various differing BPP modes here, since offset won't be correct except
2188 //for 8BPP. !!! FIX !!!
2189 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2190
2191 {
2192 // uint32_t pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2193 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2194 int32_t pixAddr = (int16_t)((DSTA2 ? a2_x : a1_x) >> 16)
2195 + ((int16_t)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2196
2197 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2198 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2199 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2200 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2201
2202 dstAddr += pixAddr;
2203 }
2204
2205 // And read it!
2206
2207 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2208 {
2209 dstData = ((uint64_t)JaguarReadLong(srcAddr, BLITTER) << 32)
2210 | (uint64_t)JaguarReadLong(srcAddr + 4, BLITTER);
2211 }
2212 else
2213 {
2214 //1,2,&4BPP are wrong here... !!! FIX !!!
2215 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2216 dstData = JaguarReadByte(dstAddr, BLITTER);
2217 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2218 dstData = JaguarReadByte(dstAddr, BLITTER);
2219 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2220 dstData = JaguarReadByte(dstAddr, BLITTER);
2221 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2222 dstData = JaguarReadByte(dstAddr, BLITTER);
2223 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2224 dstData = JaguarReadWord(dstAddr, BLITTER);
2225 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2226 dstData = JaguarReadLong(dstAddr, BLITTER);
2227 }
2228
2229 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2230 if (logBlit)
2231 WriteLog("BLITTER (dread): dstAddr=%08X, dstData=%08X %08X\n", dstAddr, (uint32_t)(dstData >> 32), (uint32_t)(dstData & 0xFFFFFFFF));
2232 #endif
2233
2234 if (DSTENZ)
2235 goto dzread;
2236 else
2237 goto dwrite;
2238
2239 dzread: // Destination Z read
2240 /*
2241 dzread Destination Z read.
2242 if STEP goto dwrite
2243 */
2244 goto dwrite;
2245
2246 dwrite: // Destination data write
2247 /*
2248 dwrite Destination write. Every pass round the inner loop must go through this state..
2249 if STEP
2250 if DSTWRZ goto dzwrite
2251 else if INNER0 goto idle
2252 else if TXTEXT goto txtread
2253 else if SRCEN goto sread
2254 else if DSTEN goto dread
2255 else if DSTENZ goto dzread
2256 else goto dwrite
2257 */
2258 /*
2259 Blit!
2260 a1_base = 00100000
2261 a1_pitch = 0
2262 a1_psize = 16
2263 a1_width = 320
2264 a1_xadd = 1.000000 (phrase=0)
2265 a1_yadd = 0.000000
2266 a1_x = 159.000000
2267 a1_y = 1.000000
2268 a1_zoffs = 0
2269 a2_base = 000095D0
2270 a2_pitch = 0
2271 a2_psize = 16
2272 a2_width = 256
2273 a2_xadd = 1.000000 (phrase=1)
2274 a2_yadd = 0.000000
2275 a2_x = 2.000000
2276 a2_y = 0.000000
2277 a2_mask_x= 0xFFFFFFFF
2278 a2_mask_y= 0xFFFFFFFF
2279 a2_zoffs = 0
2280 count = 2 x 1
2281 COMMAND = 00011008
2282 SRCEN = 0
2283 DSTEN = 1
2284 UPDA1F = 0
2285 UPDA1 = 0
2286 UPDA2 = 0
2287 DSTA2 = 0
2288 --LFUFUNC = LFU_CLEAR
2289 | PATDSEL = 1 (PD=77C7 7700 7700 7700)
2290 --ADDDSEL = 0
2291 GOURD = 1 (II=00FC 1A00, SD=FF00 0000 0000 0000)
2292 */
2293
2294 //Still need to do CLIPA1 and SRCSHADE and GOURD and GOURZ...
2295
2296 // Check clipping...
2297
2298 if (CLIPA1)
2299 {
2300 uint16_t x = a1_x >> 16, y = a1_y >> 16;
2301
2302 if (x >= GET16(blitter_ram, A1_CLIP + 2) || y >= GET16(blitter_ram, A1_CLIP))
2303 goto inhibitWrite;
2304 }
2305
2306 // Figure out what gets written...
2307
2308 if (PATDSEL)
2309 {
2310 writeData = GET64(blitter_ram, PATTERNDATA);
2311 //GOURD works properly only in 16BPP mode...
2312 //SRCDATA holds the intensity fractions...
2313 //Does GOURD get calc'ed here or somewhere else???
2314 //Temporary testing kludge...
2315 //if (GOURD)
2316 // writeData >>= 48;
2317 // writeData = 0xFF88;
2318 //OK, it's not writing an entire strip of pixels... Why?
2319 //bad incrementing, that's why!
2320 }
2321 else if (ADDDSEL)
2322 {
2323 // Apparently this only works with 16-bit pixels. Not sure if it works in phrase mode either.
2324 //Also, take TOPBEN & TOPNEN into account here as well...
2325 writeData = srcData + dstData;
2326 }
2327 else // LFUFUNC is the default...
2328 {
2329 writeData = 0;
2330
2331 if (LFU_NAN)
2332 writeData |= ~srcData & ~dstData;
2333 if (LFU_NA)
2334 writeData |= ~srcData & dstData;
2335 if (LFU_AN)
2336 writeData |= srcData & ~dstData;
2337 if (LFU_A)
2338 writeData |= srcData & dstData;
2339 }
2340
2341 // Calculate the address to be written...
2342
2343 dstAddr = (DSTA2 ? a2_addr : a1_addr);
2344
2345 /* if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2346 {
2347 //both of these calculate the wrong address because they don't take into account
2348 //pixel sizes...
2349 dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2350 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2351 }
2352 else*/
2353 {
2354 /* dstAddr += ((DSTA2 ? a2_x : a1_x) >> 16)
2355 + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));*/
2356 // uint32_t pixAddr = ((DSTA2 ? a2_x : a1_x) >> 16)
2357 // + (((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2358 int32_t pixAddr = (int16_t)((DSTA2 ? a2_x : a1_x) >> 16)
2359 + ((int16_t)((DSTA2 ? a2_y : a1_y) >> 16) * (DSTA2 ? a2_width : a1_width));
2360
2361 if ((DSTA2 ? a2PixelSize : a1PixelSize) < 3)
2362 pixAddr >>= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2363 else if ((DSTA2 ? a2PixelSize : a1PixelSize) > 3)
2364 pixAddr <<= pixelShift[(DSTA2 ? a2PixelSize : a1PixelSize)];
2365
2366 dstAddr += pixAddr;
2367 }
2368
2369 // And write it!
2370
2371 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2372 {
2373 JaguarWriteLong(dstAddr, writeData >> 32, BLITTER);
2374 JaguarWriteLong(dstAddr + 4, writeData & 0xFFFFFFFF, BLITTER);
2375 }
2376 else
2377 {
2378 //1,2,&4BPP are wrong here... !!! FIX !!!
2379 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 0) // 1 BPP
2380 JaguarWriteByte(dstAddr, writeData, BLITTER);
2381 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 1) // 2 BPP
2382 JaguarWriteByte(dstAddr, writeData, BLITTER);
2383 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 2) // 4 BPP
2384 JaguarWriteByte(dstAddr, writeData, BLITTER);
2385 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 3) // 8 BPP
2386 JaguarWriteByte(dstAddr, writeData, BLITTER);
2387 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 4) // 16 BPP
2388 JaguarWriteWord(dstAddr, writeData, BLITTER);
2389 if ((DSTA2 ? a2PixelSize : a1PixelSize) == 5) // 32 BPP
2390 JaguarWriteLong(dstAddr, writeData, BLITTER);
2391 }
2392
2393 #ifdef LOG_BLITTER_MEMORY_ACCESSES
2394 if (logBlit)
2395 WriteLog("BLITTER: dstAddr=%08X, writeData=%08X %08X\n", dstAddr, (uint32_t)(writeData >> 32), (uint32_t)(writeData & 0xFFFFFFFF));
2396 #endif
2397
2398 inhibitWrite://Should this go here? or on the other side of the X/Y incrementing?
2399 //Seems OK here... for now.
2400
2401 // Do funky X/Y incrementation here as well... !!! FIX !!!
2402
2403 // Handle A1 channel stepping
2404
2405 if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 0)
2406 a1_x += phraseOffset[a1PixelSize] << 16;
2407 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 1)
2408 a1_x += (blitter_ram[A1_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2409 /* else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 2)
2410 a1_x += 0 << 16; */
2411 else if ((blitter_ram[A1_FLAGS + 1] & 0x03) == 3)
2412 {
2413 //Always add the FINC here??? That was the problem with the BIOS screen... So perhaps.
2414 a1_x += GET16(blitter_ram, A1_FINC + 2);
2415 a1_y += GET16(blitter_ram, A1_FINC + 0);
2416
2417 a1_x += GET16(blitter_ram, A1_INC + 2) << 16;
2418 a1_y += GET16(blitter_ram, A1_INC + 0) << 16;
2419 }
2420
2421 if ((blitter_ram[A1_FLAGS + 1] & 0x04) && (blitter_ram[A1_FLAGS + 1] & 0x03 != 3))
2422 a1_y += (blitter_ram[A1_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2423
2424 // Handle A2 channel stepping
2425
2426 if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 0)
2427 a2_x += phraseOffset[a2PixelSize] << 16;
2428 else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 1)
2429 a2_x += (blitter_ram[A2_FLAGS + 1] & 0x08 ? -1 << 16 : 1 << 16);
2430 /* else if ((blitter_ram[A2_FLAGS + 1] & 0x03) == 2)
2431 a2_x += 0 << 16; */
2432
2433 if (blitter_ram[A2_FLAGS + 1] & 0x04)
2434 a2_y += (blitter_ram[A2_FLAGS + 1] & 0x10 ? -1 << 16 : 1 << 16);
2435
2436 //Need to fix this so that it subtracts (saturating, of course) the correct number of pixels
2437 //in phrase mode... !!! FIX !!! [DONE]
2438 //Need to fix this so that it counts down the correct item. Does it count the
2439 //source or the destination phrase mode???
2440 //It shouldn't matter, because we *should* end up processing the same amount
2441 //the same number of pixels... Not sure though.
2442 if ((DSTA2 ? a2_phrase_mode : a1_phrase_mode) == 1)
2443 {
2444 if (inner_loop < phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize])
2445 inner_loop = 0;
2446 else
2447 inner_loop -= phraseOffset[DSTA2 ? a2PixelSize : a1PixelSize];
2448 }
2449 else
2450 inner_loop--;
2451
2452
2453 if (DSTWRZ)
2454 goto dzwrite;
2455 else if (INNER0)
2456 goto indone;
2457 else if (TXTEXT)
2458 goto txtread;
2459 else if (SRCEN)
2460 goto sread;
2461 else if (DSTEN)
2462 goto dread;
2463 else if (DSTENZ)
2464 goto dzread;
2465 else
2466 goto dwrite;
2467
2468 dzwrite: // Destination Z write
2469 /*
2470 dzwrite Destination Z write.
2471 if STEP
2472 if INNER0 goto idle
2473 else if TXTEXT goto txtread
2474 else if SRCEN goto sread
2475 else if DSTEN goto dread
2476 else if DSTENZ goto dzread
2477 else goto dwrite
2478 */
2479 if (INNER0)
2480 goto indone;
2481 else if (TXTEXT)
2482 goto txtread;
2483 else if (SRCEN)
2484 goto sread;
2485 else if (DSTEN)
2486 goto dread;
2487 else if (DSTENZ)
2488 goto dzread;
2489 else
2490 goto dwrite;
2491
2492 /*
2493 ------------------------------
2494 if INDONE if OUTER0 goto idle
2495 else if UPDA1F goto a1fupdate
2496 else if UPDA1 goto a1update
2497 else if GOURZ.POLYGON goto zfupdate
2498 else if UPDA2 goto a2update
2499 else if DATINIT goto init_if
2500 else restart inner
2501 */
2502 indone:
2503 outer_loop--;
2504
2505
2506 if (OUTER0)
2507 goto blitter_done;
2508 else if (UPDA1F)
2509 goto a1fupdate;
2510 else if (UPDA1)
2511 goto a1update;
2512 //kill this, for now...
2513 // else if (GOURZ.POLYGON)
2514 // goto zfupdate;
2515 else if (UPDA2)
2516 goto a2update;
2517 else if (DATINIT)
2518 goto init_if;
2519 else
2520 goto inner;
2521
2522 a1fupdate: // Update A1 pointer fractions and more (see below)
2523 /*
2524 a1fupdate A1 step fraction is added to A1 pointer fraction
2525 POLYGON true: A1 step delta X and Y fraction parts are added to the A1
2526 step X and Y fraction parts (the value prior to this add is used for
2527 the step to pointer add).
2528 POLYGON true: inner count step fraction is added to the inner count
2529 fraction part
2530 POLYGON.GOURD true: the I fraction step is added to the computed
2531 intensity fraction parts +
2532 POLYGON.GOURD true: the I fraction step delta is added to the I
2533 fraction step
2534 goto a1update
2535 */
2536 /*
2537 #define A1_PIXEL ((uint32_t)0x0C) // Integer part of the pixel (Y.i and X.i)
2538 #define A1_STEP ((uint32_t)0x10) // Integer part of the step
2539 #define A1_FSTEP ((uint32_t)0x14) // Fractional part of the step
2540 #define A1_FPIXEL ((uint32_t)0x18) // Fractional part of the pixel (Y.f and X.f)
2541 */
2542
2543 // This is all kinda murky. All we have are the Midsummer docs to give us any guidance,
2544 // and it's incomplete or filled with errors (like above). Aarrrgggghhhhh!
2545
2546 //This isn't right. Is it? I don't think the fractional parts are signed...
2547 // a1_x += (int32_t)((int16_t)GET16(blitter_ram, A1_FSTEP + 2));
2548 // a1_y += (int32_t)((int16_t)GET16(blitter_ram, A1_FSTEP + 0));
2549 a1_x += GET16(blitter_ram, A1_FSTEP + 2);
2550 a1_y += GET16(blitter_ram, A1_FSTEP + 0);
2551
2552 goto a1update;
2553
2554 a1update: // Update A1 pointer integers
2555 /*
2556 a1update A1 step is added to A1 pointer, with carry from the fractional add
2557 POLYGON true: A1 step delta X and Y integer parts are added to the A1
2558 step X and Y integer parts, with carry from the corresponding
2559 fractional part add (again, the value prior to this add is used for
2560 the step to pointer add).
2561 POLYGON true: inner count step is added to the inner count, with carry
2562 POLYGON.GOURD true: the I step is added to the computed intensities,
2563 with carry +
2564 POLYGON.GOURD true: the I step delta is added to the I step, with
2565 carry the texture X and Y step delta values are added to the X and Y
2566 step values.
2567 if GOURZ.POLYGON goto zfupdate
2568 else if UPDA2 goto a2update
2569 else if DATINIT goto init_if
2570 else restart inner
2571 */
2572 a1_x += (int32_t)(GET16(blitter_ram, A1_STEP + 2) << 16);
2573 a1_y += (int32_t)(GET16(blitter_ram, A1_STEP + 0) << 16);
2574
2575
2576 //kill this, for now...
2577 // if (GOURZ.POLYGON)
2578 if (false)
2579 goto zfupdate;
2580 else if (UPDA2)
2581 goto a2update;
2582 else if (DATINIT)
2583 goto init_if;
2584 else
2585 goto inner;
2586
2587 zfupdate: // Update computed Z step fractions
2588 /*
2589 zfupdate the Z fraction step is added to the computed Z fraction parts +
2590 the Z fraction step delta is added to the Z fraction step
2591 goto zupdate
2592 */
2593 goto zupdate;
2594
2595 zupdate: // Update computed Z step integers
2596 /*
2597 zupdate the Z step is added to the computed Zs, with carry +
2598 the Z step delta is added to the Z step, with carry
2599 if UPDA2 goto a2update
2600 else if DATINIT goto init_if
2601 else restart inner
2602 */
2603 if (UPDA2)
2604 goto a2update;
2605 else if (DATINIT)
2606 goto init_if;
2607 else
2608 goto inner;
2609
2610 a2update: // Update A2 pointer
2611 /*
2612 a2update A2 step is added to the A2 pointer
2613 if DATINIT goto init_if
2614 else restart inner
2615 */
2616 a2_x += (int32_t)(GET16(blitter_ram, A2_STEP + 2) << 16);
2617 a2_y += (int32_t)(GET16(blitter_ram, A2_STEP + 0) << 16);
2618
2619
2620 if (DATINIT)
2621 goto init_if;
2622 else
2623 goto inner;
2624
2625 init_if: // Initialise intensity fractions and texture X
2626 /*
2627 init_if Initialise the fractional part of the computed intensity fields, from
2628 the increment and step registers. The texture X integer and fractional
2629 parts can also be initialised.
2630 goto init_ii
2631 */
2632 goto init_ii;
2633
2634 init_ii: // Initialise intensity integers and texture Y
2635 /*
2636 init_ii Initialise the integer part of the computed intensity, and texture Y
2637 integer and fractional parts
2638 if GOURZ goto init_zf
2639 else goto inner
2640 */
2641 if (GOURZ)
2642 goto init_zf;
2643 else
2644 goto inner;
2645
2646 init_zf: // Initialise Z fractions
2647 /*
2648 init_zf Initialise the fractional part of the computed Z fields.
2649 goto init_zi
2650 */
2651 goto init_zi;
2652
2653 init_zi: // Initialise Z integers
2654 /*
2655 init_zi Initialise the integer part of the computed Z fields.
2656 goto inner
2657 */
2658 goto inner;
2659
2660
2661 /*
2662 The outer loop state machine fires off the inner loop, and controls the updating
2663 process between passes through the inner loop.
2664
2665 + -- these functions are irrelevant if the DATINIT function is enabled, which it
2666 will normally be.
2667
2668 All these states will complete in one clock cycle, with the exception of the idle
2669 state, which means the blitter is quiescent; and the inner state, which takes as
2670 long as is required to complete one strip of pixels. It is therefore possible for
2671 the blitter to spend a maximum of nine clock cycles of inactivity between passes
2672 through the inner loop.
2673 */
2674
2675 blitter_done:
2676 {}
2677 }
2678 #endif
2679
2680
2681 //
2682 // Here's attempt #2--taken from the Oberon chip specs!
2683 //
2684
2685 #ifdef USE_MIDSUMMER_BLITTER_MKII
2686
2687 void ADDRGEN(uint32_t &, uint32_t &, bool, bool,
2688 uint16_t, uint16_t, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
2689 uint16_t, uint16_t, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t);
2690 void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
2691 uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
2692 uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
2693 uint32_t zinc, uint32_t zstep);
2694 void ADD16SAT(uint16_t &r, uint8_t &co, uint16_t a, uint16_t b, uint8_t cin, bool sat, bool eightbit, bool hicinh);
2695 void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y,
2696 int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y,
2697 int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst,
2698 bool adda_yconst, bool addareg, bool suba_x, bool suba_y);
2699 void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y,
2700 int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y);
2701 void DATAMUX(int16_t &data_x, int16_t &data_y, uint32_t gpu_din, int16_t addq_x, int16_t addq_y, bool addqsel);
2702 void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
2703 uint16_t adda_x, uint16_t adda_y, uint16_t addb_x, uint16_t addb_y, uint8_t modx, bool suba_x, bool suba_y);
2704 void DATA(uint64_t &wdata, uint8_t &dcomp, uint8_t &zcomp, bool &nowrite,
2705 bool big_pix, bool cmpdst, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, bool daddq_sel, uint8_t data_sel,
2706 uint8_t dbinh, uint8_t dend, uint8_t dstart, uint64_t dstd, uint32_t iinc, uint8_t lfu_func, uint64_t &patd, bool patdadd,
2707 bool phrase_mode, uint64_t srcd, bool srcdread, bool srczread, bool srcz2add, uint8_t zmode,
2708 bool bcompen, bool bkgwren, bool dcompen, uint8_t icount, uint8_t pixsize,
2709 uint64_t &srcz, uint64_t dstz, uint32_t zinc);
2710 void COMP_CTRL(uint8_t &dbinh, bool &nowrite,
2711 bool bcompen, bool big_pix, bool bkgwren, uint8_t dcomp, bool dcompen, uint8_t icount,
2712 uint8_t pixsize, bool phrase_mode, uint8_t srcd, uint8_t zcomp);
2713 #define VERBOSE_BLITTER_LOGGING
2714
2715 void BlitterMidsummer2(void)
2716 {
2717 #ifdef LOG_BLITS
2718 LogBlit();
2719 #endif
2720 if (startConciseBlitLogging)
2721 LogBlit();
2722
2723 // Here's what the specs say the state machine does. Note that this can probably be
2724 // greatly simplified (also, it's different from what John has in his Oberon docs):
2725 //Will remove stuff that isn't in Jaguar I once fully described (stuff like texture won't
2726 //be described here at all)...
2727
2728 uint32_t cmd = GET32(blitter_ram, COMMAND);
2729
2730 #if 0
2731 logBlit = false;
2732 if (
2733 cmd != 0x00010200 && // PATDSEL
2734 cmd != 0x01800001 // SRCEN LFUFUNC=C
2735 && cmd != 0x01800005
2736 //Boot ROM ATARI letters:
2737 && cmd != 0x00011008 // DSTEN GOURD PATDSEL
2738 //Boot ROM spinning cube:
2739 && cmd != 0x41802F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
2740 //T2K intro screen:
2741 && cmd != 0x01800E01 // SRCEN UPDA1 UPDA2 DSTA2 LFUFUNC=C
2742 //T2K TEMPEST letters:
2743 && cmd != 0x09800741 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 LFUFUNC=C DCOMPEN
2744 //Static letters on Cybermorph intro screen:
2745 && cmd != 0x09800609 // SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
2746 //Static pic on title screen:
2747 && cmd != 0x01800601 // SRCEN UPDA1 UPDA2 LFUFUNC=C
2748 //Turning letters on Cybermorph intro screen:
2749 // && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2750 && cmd != 0x00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
2751 && cmd != 0x09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
2752 && cmd != 0x09800209 // SRCEN DSTEN UPDA1 LFUFUNC=C DCOMPEN
2753 && cmd != 0x00011200 // UPDA1 GOURD PATDSEL
2754 //Start of Hover Strike (clearing screen):
2755 && cmd != 0x00010000 // PATDSEL
2756 //Hover Strike text:
2757 && cmd != 0x1401060C // SRCENX DSTEN UPDA1 UPDA2 PATDSEL BCOMPEN BKGWREN
2758 //Hover Strike 3D stuff
2759 && cmd != 0x01902839 // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2760 //Hover Strike darkening on intro to play (briefing) screen
2761 && cmd != 0x00020208 // DSTEN UPDA1 ADDDSEL
2762 //Trevor McFur stuff:
2763 && cmd != 0x05810601 // SRCEN UPDA1 UPDA2 PATDSEL BCOMPEN
2764 && cmd != 0x01800201 // SRCEN UPDA1 LFUFUNC=C
2765 //T2K:
2766 && cmd != 0x00011000 // GOURD PATDSEL
2767 && cmd != 0x00011040 // CLIP_A1 GOURD PATDSEL
2768 //Checkered flag:
2769 && cmd != 0x01800000 // LFUFUNC=C
2770 && cmd != 0x01800401 //
2771 && cmd != 0x01800040 //
2772 && cmd != 0x00020008 //
2773 // && cmd != 0x09800F41 // SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 LFUFUNC=C DCOMPEN
2774 )
2775 logBlit = true;//*/
2776 #else
2777 logBlit = true;
2778 #endif
2779 if (blit_start_log == 0) // Wait for the signal...
2780 logBlit = false;//*/
2781 //temp, for testing...
2782 /*if (cmd != 0x49820609)
2783 logBlit = false;//*/
2784
2785 /*
2786 Some T2K unique blits:
2787 logBlit = F, cmd = 00010200 *
2788 logBlit = F, cmd = 00011000
2789 logBlit = F, cmd = 00011040
2790 logBlit = F, cmd = 01800005 *
2791 logBlit = F, cmd = 09800741 *
2792
2793 Hover Strike mission selection screen:
2794 Blit! (CMD = 01902839) // SRCEN DSTEN DSTENZ DSTWRZ DSTA2 GOURZ ZMODE=4 LFUFUNC=C
2795
2796 Checkered Flag blits in the screw up zone:
2797 Blit! (CMD = 01800001) // SRCEN LFUFUNC=C
2798 Blit! (CMD = 01800000) // LFUFUNC=C
2799 Blit! (CMD = 00010000) // PATDSEL
2800
2801 Wolfenstein 3D in the fuckup zone:
2802 Blit! (CMD = 01800000) // LFUFUNC=C
2803 */
2804
2805 //printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2806 //fflush(stdout);
2807 //logBlit = true;
2808
2809 /*
2810 Blit! (CMD = 00011040)
2811 Flags: CLIP_A1 GOURD PATDSEL
2812 count = 18 x 1
2813 a1_base = 00100000, a2_base = 0081F6A8
2814 a1_x = 00A7, a1_y = 0014, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0001, a2_y = 0000
2815 a1_step_x = FE80, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFF8, a2_step_y = 0001
2816 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
2817 a1_win_x = 0180, a1_win_y = 0118, a2_mask_x = 0000, a2_mask_y = 0000
2818 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
2819 a1_pixsize = 4, a2_pixsize = 4
2820 */
2821 //Testing T2K...
2822 /*logBlit = false;
2823 if (cmd == 0x00011040
2824 && (GET16(blitter_ram, A1_PIXEL + 2) == 0x00A7) && (GET16(blitter_ram, A1_PIXEL + 0) == 0x0014)
2825 && (GET16(blitter_ram, A2_PIXEL + 2) == 0x0001) && (GET16(blitter_ram, A2_PIXEL + 0) == 0x0000)
2826 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 18))
2827 logBlit = true;*/
2828
2829 // Line states passed in via the command register
2830
2831 bool srcen = (SRCEN), srcenx = (SRCENX), srcenz = (SRCENZ),
2832 dsten = (DSTEN), dstenz = (DSTENZ), dstwrz = (DSTWRZ), clip_a1 = (CLIPA1),
2833 upda1 = (UPDA1), upda1f = (UPDA1F), upda2 = (UPDA2), dsta2 = (DSTA2),
2834 gourd = (GOURD), gourz = (GOURZ), topben = (TOPBEN), topnen = (TOPNEN),
2835 patdsel = (PATDSEL), adddsel = (ADDDSEL), cmpdst = (CMPDST), bcompen = (BCOMPEN),
2836 dcompen = (DCOMPEN), bkgwren = (BKGWREN), srcshade = (SRCSHADE);
2837
2838 uint8_t zmode = (cmd & 0x01C0000) >> 18, lfufunc = (cmd & 0x1E00000) >> 21;
2839 //Missing: BUSHI
2840 //Where to find various lines:
2841 // clip_a1 -> inner
2842 // gourd -> dcontrol, inner, outer, state
2843 // gourz -> dcontrol, inner, outer, state
2844 // cmpdst -> blit, data, datacomp, state
2845 // bcompen -> acontrol, inner, mcontrol, state
2846 // dcompen -> inner, state
2847 // bkgwren -> inner, state
2848 // srcshade -> dcontrol, inner, state
2849 // adddsel -> dcontrol
2850 //NOTE: ADDDSEL takes precedence over PATDSEL, PATDSEL over LFU_FUNC
2851 #ifdef VERBOSE_BLITTER_LOGGING
2852 if (logBlit)
2853 {
2854 char zfs[512], lfus[512];
2855 zfs[0] = lfus[0] = 0;
2856 if (dstwrz || dstenz || gourz)
2857 sprintf(zfs, " ZMODE=%X", zmode);
2858 if (!(patdsel || adddsel))
2859 sprintf(lfus, " LFUFUNC=%X", lfufunc);
2860 WriteLog("\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,
2861 (srcen ? " SRCEN" : ""), (srcenx ? " SRCENX" : ""), (srcenz ? " SRCENZ" : ""),
2862 (dsten ? " DSTEN" : ""), (dstenz ? " DSTENZ" : ""), (dstwrz ? " DSTWRZ" : ""),
2863 (clip_a1 ? " CLIP_A1" : ""), (upda1 ? " UPDA1" : ""), (upda1f ? " UPDA1F" : ""),
2864 (upda2 ? " UPDA2" : ""), (dsta2 ? " DSTA2" : ""), (gourd ? " GOURD" : ""),
2865 (gourz ? " GOURZ" : ""), (topben ? " TOPBEN" : ""), (topnen ? " TOPNEN" : ""),
2866 (patdsel ? " PATDSEL" : ""), (adddsel ? " ADDDSEL" : ""), zfs, lfus, (cmpdst ? " CMPDST" : ""),
2867 (bcompen ? " BCOMPEN" : ""), (dcompen ? " DCOMPEN" : ""), (bkgwren ? " BKGWREN" : ""),
2868 (srcshade ? " SRCSHADE" : ""));
2869 WriteLog(" count = %d x %d\n", GET16(blitter_ram, PIXLINECOUNTER + 2), GET16(blitter_ram, PIXLINECOUNTER));
2870 }
2871 #endif
2872
2873 // Lines that don't exist in Jaguar I (and will never be asserted)
2874
2875 bool polygon = false, datinit = false, a1_stepld = false, a2_stepld = false, ext_int = false;
2876 bool istepadd = false, istepfadd = false, finneradd = false, inneradd = false;
2877 bool zstepfadd = false, zstepadd = false;
2878
2879 // Various state lines (initial state--basically the reset state of the FDSYNCs)
2880
2881 bool go = true, idle = true, inner = false, a1fupdate = false, a1update = false,
2882 zfupdate = false, zupdate = false, a2update = false, init_if = false, init_ii = false,
2883 init_zf = false, init_zi = false;
2884
2885 bool outer0 = false, indone = false;
2886
2887 bool idlei, inneri, a1fupdatei, a1updatei, zfupdatei, zupdatei, a2updatei, init_ifi, init_iii,
2888 init_zfi, init_zii;
2889
2890 bool notgzandp = !(gourz && polygon);
2891
2892 // Various registers set up by user
2893
2894 uint16_t ocount = GET16(blitter_ram, PIXLINECOUNTER);
2895 uint8_t a1_pitch = blitter_ram[A1_FLAGS + 3] & 0x03;
2896 uint8_t a2_pitch = blitter_ram[A2_FLAGS + 3] & 0x03;
2897 uint8_t a1_pixsize = (blitter_ram[A1_FLAGS + 3] & 0x38) >> 3;
2898 uint8_t a2_pixsize = (blitter_ram[A2_FLAGS + 3] & 0x38) >> 3;
2899 uint8_t a1_zoffset = (GET16(blitter_ram, A1_FLAGS + 2) >> 6) & 0x07;
2900 uint8_t a2_zoffset = (GET16(blitter_ram, A2_FLAGS + 2) >> 6) & 0x07;
2901 uint8_t a1_width = (blitter_ram[A1_FLAGS + 2] >> 1) & 0x3F;
2902 uint8_t a2_width = (blitter_ram[A2_FLAGS + 2] >> 1) & 0x3F;
2903 bool a2_mask = blitter_ram[A2_FLAGS + 2] & 0x80;
2904 uint8_t a1addx = blitter_ram[A1_FLAGS + 1] & 0x03, a2addx = blitter_ram[A2_FLAGS + 1] & 0x03;
2905 bool a1addy = blitter_ram[A1_FLAGS + 1] & 0x04, a2addy = blitter_ram[A2_FLAGS + 1] & 0x04;
2906 bool a1xsign = blitter_ram[A1_FLAGS + 1] & 0x08, a2xsign = blitter_ram[A2_FLAGS + 1] & 0x08;
2907 bool a1ysign = blitter_ram[A1_FLAGS + 1] & 0x10, a2ysign = blitter_ram[A2_FLAGS + 1] & 0x10;
2908 uint32_t a1_base = GET32(blitter_ram, A1_BASE) & 0xFFFFFFF8; // Phrase aligned by ignoring bottom 3 bits
2909 uint32_t a2_base = GET32(blitter_ram, A2_BASE) & 0xFFFFFFF8;
2910
2911 uint16_t a1_win_x = GET16(blitter_ram, A1_CLIP + 2) & 0x7FFF;
2912 uint16_t a1_win_y = GET16(blitter_ram, A1_CLIP + 0) & 0x7FFF;
2913 int16_t a1_x = (int16_t)GET16(blitter_ram, A1_PIXEL + 2);
2914 int16_t a1_y = (int16_t)GET16(blitter_ram, A1_PIXEL + 0);
2915 int16_t a1_step_x = (int16_t)GET16(blitter_ram, A1_STEP + 2);
2916 int16_t a1_step_y = (int16_t)GET16(blitter_ram, A1_STEP + 0);
2917 uint16_t a1_stepf_x = GET16(blitter_ram, A1_FSTEP + 2);
2918 uint16_t a1_stepf_y = GET16(blitter_ram, A1_FSTEP + 0);
2919 uint16_t a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
2920 uint16_t a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
2921 int16_t a1_inc_x = (int16_t)GET16(blitter_ram, A1_INC + 2);
2922 int16_t a1_inc_y = (int16_t)GET16(blitter_ram, A1_INC + 0);
2923 uint16_t a1_incf_x = GET16(blitter_ram, A1_FINC + 2);
2924 uint16_t a1_incf_y = GET16(blitter_ram, A1_FINC + 0);
2925
2926 int16_t a2_x = (int16_t)GET16(blitter_ram, A2_PIXEL + 2);
2927 int16_t a2_y = (int16_t)GET16(blitter_ram, A2_PIXEL + 0);
2928 uint16_t a2_mask_x = GET16(blitter_ram, A2_MASK + 2);
2929 uint16_t a2_mask_y = GET16(blitter_ram, A2_MASK + 0);
2930 int16_t a2_step_x = (int16_t)GET16(blitter_ram, A2_STEP + 2);
2931 int16_t a2_step_y = (int16_t)GET16(blitter_ram, A2_STEP + 0);
2932
2933 uint64_t srcd1 = GET64(blitter_ram, SRCDATA);
2934 uint64_t srcd2 = 0;
2935 uint64_t dstd = GET64(blitter_ram, DSTDATA);
2936 uint64_t patd = GET64(blitter_ram, PATTERNDATA);
2937 uint32_t iinc = GET32(blitter_ram, INTENSITYINC);
2938 uint64_t srcz1 = GET64(blitter_ram, SRCZINT);
2939 uint64_t srcz2 = GET64(blitter_ram, SRCZFRAC);
2940 uint64_t dstz = GET64(blitter_ram, DSTZ);
2941 uint32_t zinc = GET32(blitter_ram, ZINC);
2942 uint32_t collision = GET32(blitter_ram, COLLISIONCTRL);// 0=RESUME, 1=ABORT, 2=STOPEN
2943
2944 uint8_t pixsize = (dsta2 ? a2_pixsize : a1_pixsize); // From ACONTROL
2945
2946 //Testing Trevor McFur--I *think* it's the circle on the lower RHS of the screen...
2947 /*logBlit = false;
2948 if (cmd == 0x05810601 && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 96)
2949 && (GET16(blitter_ram, PIXLINECOUNTER + 0) == 72))
2950 logBlit = true;//*/
2951 //Testing...
2952 //if (cmd == 0x1401060C) patd = 0xFFFFFFFFFFFFFFFFLL;
2953 //if (cmd == 0x1401060C) patd = 0x00000000000000FFLL;
2954 //If it's still not working (bcompen-patd) then see who's writing what to patd and where...
2955 //Still not OK. Check to see who's writing what to where in patd!
2956 //It looks like M68K is writing to the top half of patd... Hmm...
2957 /*
2958 ----> M68K wrote 0000 to byte 15737344 of PATTERNDATA...
2959 --> M68K wrote 00 to byte 0 of PATTERNDATA...
2960 --> M68K wrote 00 to byte 1 of PATTERNDATA...
2961 ----> M68K wrote 00FF to byte 15737346 of PATTERNDATA...
2962 --> M68K wrote 00 to byte 2 of PATTERNDATA...
2963 --> M68K wrote FF to byte 3 of PATTERNDATA...
2964 logBlit = F, cmd = 1401060C
2965
2966 Wren0 := ND6 (wren\[0], gpua\[5], gpua\[6..8], bliten, gpu_memw);
2967 Wren1 := ND6 (wren\[1], gpua[5], gpua\[6..8], bliten, gpu_memw);
2968 Wren2 := ND6 (wren\[2], gpua\[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2969 Wren3 := ND6 (wren\[3], gpua[5], gpua[6], gpua\[7..8], bliten, gpu_memw);
2970
2971 --> 0 000x xx00
2972 Dec0 := D38GH (a1baseld, a1flagld, a1winld, a1ptrld, a1stepld, a1stepfld, a1fracld, a1incld, gpua[2..4], wren\[0]);
2973 --> 0 001x xx00
2974 Dec1 := D38GH (a1incfld, a2baseld, a2flagld, a2maskld, a2ptrldg, a2stepld, cmdldt, countldt, gpua[2..4], wren\[1]);
2975 --> 0 010x xx00
2976 Dec2 := D38GH (srcd1ldg[0..1], dstdldg[0..1], dstzldg[0..1], srcz1ldg[0..1], gpua[2..4], wren\[2]);
2977 --> 0 011x xx00
2978 Dec3 := D38GH (srcz2ld[0..1], patdld[0..1], iincld, zincld, stopld, intld[0], gpua[2..4], wren\[3]);
2979
2980 wren[3] is asserted when gpu address bus = 0 011x xx00
2981 patdld[0] -> 0 0110 1000 -> $F02268 (lo 32 bits)
2982 patdld[1] -> 0 0110 1100 -> $F0226C (hi 32 bits)
2983
2984 So... It's reversed! The data organization of the patd register is [low 32][high 32]! !!! FIX !!! [DONE]
2985 And fix all the other 64 bit registers [DONE]
2986 */
2987 /*if (cmd == 0x1401060C)
2988 {
2989 printf("logBlit = %s, cmd = %08X\n", (logBlit ? "T" : "F"), cmd);
2990 fflush(stdout);
2991 }*/
2992 /*logBlit = false;
2993 if ((cmd == 0x00010200) && (GET16(blitter_ram, PIXLINECOUNTER + 2) == 9))
2994 logBlit = true;
2995
2996 ; Pink altimeter bar
2997
2998 Blit! (00110000 <- 000BF010) count: 9 x 23, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
2999 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
3000 A1 step values: -10 (X), 1 (Y)
3001 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
3002 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
3003 A1 x/y: 262/132, A2 x/y: 129/0
3004 ;x-coord is 257 in pic, so add 5
3005 ;20 for ship, 33 for #... Let's see if we can find 'em!
3006
3007 ; Black altimeter bar
3008
3009 Blit! (00110000 <- 000BF010) count: 5 x 29, A1/2_FLAGS: 000042E2/00010020 [cmd: 00010200]
3010 CMD -> src: dst: misc: a1ctl: UPDA1 mode: ity: PATDSEL z-op: op: LFU_CLEAR ctrl:
3011 A1 step values: -8 (X), 1 (Y)
3012 A1 -> pitch: 4 phrases, depth: 16bpp, z-off: 3, width: 320 (21), addctl: XADDPHR YADD0 XSIGNADD YSIGNADD
3013 A2 -> pitch: 1 phrases, depth: 16bpp, z-off: 0, width: 1 (00), addctl: XADDPIX YADD0 XSIGNADD YSIGNADD
3014 A1 x/y: 264/126, A2 x/y: 336/0
3015
3016 Here's the pink bar--note that it's phrase mode without dread, so how does this work???
3017 Not sure, but I *think* that somehow it MUXes the data at the write site in on the left or right side
3018 of the write data when masked in phrase mode. I'll have to do some tracing to see if this is the mechanism
3019 it uses or not...
3020
3021 Blit! (CMD = 00010200)
3022 Flags: UPDA1 PATDSEL
3023 count = 9 x 11
3024 a1_base = 00110010, a2_base = 000BD7E0
3025 a1_x = 0106, a1_y = 0090, a1_frac_x = 0000, a1_frac_y = 8000, a2_x = 025A, a2_y = 0000
3026 a1_step_x = FFF6, a1_step_y = 0001, a1_stepf_x = 5E00, a1_stepf_y = D100, a2_step_x = FFF7, a2_step_y = 0001
3027 a1_inc_x = 0001, a1_inc_y = FFFF, a1_incf_x = 0000, a1_incf_y = E000
3028 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
3029 a2_mask=F a1add=+phr/+0 a2add=+1/+0
3030 a1_pixsize = 4, a2_pixsize = 4
3031 srcd=BAC673AC2C92E578 dstd=0000000000000000 patd=74C074C074C074C0 iinc=0002E398
3032 srcz1=7E127E12000088DA srcz2=DBE06DF000000000 dstz=0000000000000000 zinc=FFFE4840, coll=0
3033 Phrase mode is ON
3034 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3035 Entering INNER state...
3036 Entering DWRITE state...
3037 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)
3038 Entering A1_ADD state [a1_x=0106, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3039 Entering DWRITE state...
3040 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)
3041 Entering A1_ADD state [a1_x=0108, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3042 Entering DWRITE state...
3043 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)
3044 Entering A1_ADD state [a1_x=010C, a1_y=0090, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3045 Entering IDLE_INNER state...
3046 Leaving INNER state... (ocount=000A)
3047 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3048 Entering A1UPDATE state... (272/144 -> 262/145)
3049 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3050 Entering INNER state...
3051 */
3052
3053 // Bugs in Jaguar I
3054
3055 a2addy = a1addy; // A2 channel Y add bit is tied to A1's
3056
3057 //if (logBlit && (ocount > 20)) logBlit = false;
3058 #ifdef VERBOSE_BLITTER_LOGGING
3059 if (logBlit)
3060 {
3061 WriteLog(" a1_base = %08X, a2_base = %08X\n", a1_base, a2_base);
3062 WriteLog(" a1_x = %04X, a1_y = %04X, a1_frac_x = %04X, a1_frac_y = %04X, a2_x = %04X, a2_y = %04X\n", (uint16_t)a1_x, (uint16_t)a1_y, a1_frac_x, a1_frac_y, (uint16_t)a2_x, (uint16_t)a2_y);
3063 WriteLog(" 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_t)a1_step_x, (uint16_t)a1_step_y, a1_stepf_x, a1_stepf_y, (uint16_t)a2_step_x, (uint16_t)a2_step_y);
3064 WriteLog(" a1_inc_x = %04X, a1_inc_y = %04X, a1_incf_x = %04X, a1_incf_y = %04X\n", (uint16_t)a1_inc_x, (uint16_t)a1_inc_y, a1_incf_x, a1_incf_y);
3065 WriteLog(" 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);
3066 char x_add_str[4][4] = { "phr", "1", "0", "inc" };
3067 WriteLog(" a2_mask=%s a1add=%s%s/%s%s a2add=%s%s/%s%s\n", (a2_mask ? "T" : "F"), (a1xsign ? "-" : "+"), x_add_str[a1addx],
3068 (a1ysign ? "-" : "+"), (a1addy ? "1" : "0"), (a2xsign ? "-" : "+"), x_add_str[a2addx],
3069 (a2ysign ? "-" : "+"), (a2addy ? "1" : "0"));
3070 WriteLog(" a1_pixsize = %u, a2_pixsize = %u\n", a1_pixsize, a2_pixsize);
3071 WriteLog(" srcd=%08X%08X dstd=%08X%08X patd=%08X%08X iinc=%08X\n",
3072 (uint32_t)(srcd1 >> 32), (uint32_t)(srcd1 & 0xFFFFFFFF),
3073 (uint32_t)(dstd >> 32), (uint32_t)(dstd & 0xFFFFFFFF),
3074 (uint32_t)(patd >> 32), (uint32_t)(patd & 0xFFFFFFFF), iinc);
3075 WriteLog(" srcz1=%08X%08X srcz2=%08X%08X dstz=%08X%08X zinc=%08X, coll=%X\n",
3076 (uint32_t)(srcz1 >> 32), (uint32_t)(srcz1 & 0xFFFFFFFF),
3077 (uint32_t)(srcz2 >> 32), (uint32_t)(srcz2 & 0xFFFFFFFF),
3078 (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF), zinc, collision);
3079 }
3080 #endif
3081
3082 // Various state lines set up by user
3083
3084 bool phrase_mode = ((!dsta2 && a1addx == 0) || (dsta2 && a2addx == 0) ? true : false); // From ACONTROL
3085 #ifdef VERBOSE_BLITTER_LOGGING
3086 if (logBlit)
3087 WriteLog(" Phrase mode is %s\n", (phrase_mode ? "ON" : "off"));
3088 #endif
3089 //logBlit = false;
3090
3091 // Stopgap vars to simulate various lines
3092
3093 uint16_t a1FracCInX = 0, a1FracCInY = 0;
3094
3095 while (true)
3096 {
3097 // IDLE
3098
3099 if ((idle && !go) || (inner && outer0 && indone))
3100 {
3101 #ifdef VERBOSE_BLITTER_LOGGING
3102 if (logBlit)
3103 WriteLog(" Entering IDLE state...\n");
3104 #endif
3105 idlei = true;
3106
3107 //Instead of a return, let's try breaking out of the loop...
3108 break;
3109 // return;
3110 }
3111 else
3112 idlei = false;
3113
3114 // INNER LOOP ACTIVE
3115 /*
3116 Entering DWRITE state... (icount=0000, inc=4)
3117 Entering IDLE_INNER state...
3118 Leaving INNER state... (ocount=00EF)
3119 [in=T a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3120 Entering INNER state...
3121 Now:
3122 [in=F a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3123 */
3124
3125 if ((idle && go && !datinit)
3126 || (inner && !indone)
3127 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && !datinit)
3128 || (a1update && !upda2 && notgzandp && !datinit)
3129 || (zupdate && !upda2 && !datinit)
3130 || (a2update && !datinit)
3131 || (init_ii && !gourz)
3132 || (init_zi))
3133 {
3134 inneri = true;
3135 }
3136 else
3137 inneri = false;
3138
3139 // A1 FRACTION UPDATE
3140
3141 if (inner && indone && !outer0 && upda1f)
3142 {
3143 a1fupdatei = true;
3144 }
3145 else
3146 a1fupdatei = false;
3147
3148 // A1 POINTER UPDATE
3149
3150 if ((a1fupdate)
3151 || (inner && indone && !outer0 && !upda1f && upda1))
3152 {
3153 a1updatei = true;
3154 }
3155 else
3156 a1updatei = false;
3157
3158 // Z FRACTION UPDATE
3159
3160 if ((a1update && gourz && polygon)
3161 || (inner && indone && !outer0 && !upda1f && !upda1 && gourz && polygon))
3162 {
3163 zfupdatei = true;
3164 }
3165 else
3166 zfupdatei = false;
3167
3168 // Z INTEGER UPDATE
3169
3170 if (zfupdate)
3171 {
3172 zupdatei = true;
3173 }
3174 else
3175 zupdatei = false;
3176
3177 // A2 POINTER UPDATE
3178
3179 if ((a1update && upda2 && notgzandp)
3180 || (zupdate && upda2)
3181 || (inner && indone && !outer0 && !upda1f && notgzandp && !upda1 && upda2))
3182 {
3183 a2updatei = true;
3184 }
3185 else
3186 a2updatei = false;
3187
3188 // INITIALIZE INTENSITY FRACTION
3189
3190 if ((zupdate && !upda2 && datinit)
3191 || (a1update && !upda2 && datinit && notgzandp)
3192 || (inner && indone && !outer0 && !upda1f && !upda1 && notgzandp && !upda2 && datinit)
3193 || (a2update && datinit)
3194 || (idle && go && datinit))
3195 {
3196 init_ifi = true;
3197 }
3198 else
3199 init_ifi = false;
3200
3201 // INITIALIZE INTENSITY INTEGER
3202
3203 if (init_if)
3204 {
3205 init_iii = true;
3206 }
3207 else
3208 init_iii = false;
3209
3210 // INITIALIZE Z FRACTION
3211
3212 if (init_ii && gourz)
3213 {
3214 init_zfi = true;
3215 }
3216 else
3217 init_zfi = false;
3218
3219 // INITIALIZE Z INTEGER
3220
3221 if (init_zf)
3222 {
3223 init_zii = true;
3224 }
3225 else
3226 init_zii = false;
3227
3228 // Here we move the fooi into their foo counterparts in order to simulate the moving
3229 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3230
3231 idle = idlei;
3232 inner = inneri;
3233 a1fupdate = a1fupdatei;
3234 a1update = a1updatei;
3235 zfupdate = zfupdatei; // *
3236 zupdate = zupdatei; // *
3237 a2update = a2updatei;
3238 init_if = init_ifi; // *
3239 init_ii = init_iii; // *
3240 init_zf = init_zfi; // *
3241 init_zi = init_zii; // *
3242 // * denotes states that will never assert for Jaguar I
3243 #ifdef VERBOSE_BLITTER_LOGGING
3244 if (logBlit)
3245 WriteLog(" [in=%c a1f=%c a1=%c zf=%c z=%c a2=%c iif=%c iii=%c izf=%c izi=%c]\n",
3246 (inner ? 'T' : 'F'), (a1fupdate ? 'T' : 'F'), (a1update ? 'T' : 'F'),
3247 (zfupdate ? 'T' : 'F'), (zupdate ? 'T' : 'F'), (a2update ? 'T' : 'F'),
3248 (init_if ? 'T' : 'F'), (init_ii ? 'T' : 'F'), (init_zf ? 'T' : 'F'),
3249 (init_zi ? 'T' : 'F'));
3250 #endif
3251
3252 // Now, depending on how we want to handle things, we could either put the implementation
3253 // of the various pieces up above, or handle them down below here.
3254
3255 // Let's try postprocessing for now...
3256
3257 if (inner)
3258 {
3259 indone = false;
3260 #ifdef VERBOSE_BLITTER_LOGGING
3261 if (logBlit)
3262 WriteLog(" Entering INNER state...\n");
3263 #endif
3264 uint16_t icount = GET16(blitter_ram, PIXLINECOUNTER + 2);
3265 bool idle_inner = true, step = true, sreadx = false, szreadx = false, sread = false,
3266 szread = false, dread = false, dzread = false, dwrite = false, dzwrite = false;
3267 bool inner0 = false;
3268 bool idle_inneri, sreadxi, szreadxi, sreadi, szreadi, dreadi, dzreadi, dwritei, dzwritei;
3269
3270 // State lines that will never assert in Jaguar I
3271
3272 bool textext = false, txtread = false;
3273
3274 //other stuff
3275 uint8_t srcshift = 0;
3276 bool sshftld = true; // D flipflop (D -> Q): instart -> sshftld
3277 //NOTE: sshftld probably is only asserted at the beginning of the inner loop. !!! FIX !!!
3278 /*
3279 Blit! (CMD = 01800005)
3280 Flags: SRCEN SRCENX LFUFUNC=C
3281 count = 626 x 1
3282 a1_base = 00037290, a2_base = 000095D0
3283 a1_x = 0000, a1_y = 0000, a2_x = 0002, a2_y = 0000
3284 a1_pixsize = 4, a2_pixsize = 4
3285 srcd=0000000000000000, dstd=0000000000000000, patd=0000000000000000
3286 Phrase mode is ON
3287 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
3288 Entering INNER state...
3289 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
3290 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
3291 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3292 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3293 Source read address/pix address: 000095D8/0 [0054003800009814]
3294 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3295 Entering DWRITE state...
3296 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
3297 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3298 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
3299 Source read address/pix address: 000095E0/0 [00009968000377C7]
3300 Entering A2_ADD state [a2_x=0008, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3301 Entering DWRITE state...
3302 Dest write address/pix address: 00037298/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026A, inc=4)
3303 Entering A1_ADD state [a1_x=0004, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
3304 */
3305
3306 // while (!idle_inner)
3307 while (true)
3308 {
3309 // IDLE
3310
3311 if ((idle_inner && !step)
3312 || (dzwrite && step && inner0)
3313 || (dwrite && step && !dstwrz && inner0))
3314 {
3315 #ifdef VERBOSE_BLITTER_LOGGING
3316 if (logBlit)
3317 WriteLog(" Entering IDLE_INNER state...\n");
3318 #endif
3319 idle_inneri = true;
3320 break;
3321 }
3322 else
3323 idle_inneri = false;
3324
3325 // EXTRA SOURCE DATA READ
3326
3327 if ((idle_inner && step && srcenx)
3328 || (sreadx && !step))
3329 {
3330 sreadxi = true;
3331 }
3332 else
3333 sreadxi = false;
3334
3335 // EXTRA SOURCE ZED READ
3336
3337 if ((sreadx && step && srcenz)
3338 || (szreadx && !step))
3339 {
3340 szreadxi = true;
3341 }
3342 else
3343 szreadxi = false;
3344
3345 // TEXTURE DATA READ (not implemented because not in Jaguar I)
3346
3347 // SOURCE DATA READ
3348
3349 if ((szreadx && step && !textext)
3350 || (sreadx && step && !srcenz && srcen)
3351 || (idle_inner && step && !srcenx && !textext && srcen)
3352 || (dzwrite && step && !inner0 && !textext && srcen)
3353 || (dwrite && step && !dstwrz && !inner0 && !textext && srcen)
3354 || (txtread && step && srcen)
3355 || (sread && !step))
3356 {
3357 sreadi = true;
3358 }
3359 else
3360 sreadi = false;
3361
3362 // SOURCE ZED READ
3363
3364 if ((sread && step && srcenz)
3365 || (szread && !step))
3366 {
3367 szreadi = true;
3368 }
3369 else
3370 szreadi = false;
3371
3372 // DESTINATION DATA READ
3373
3374 if ((szread && step && dsten)
3375 || (sread && step && !srcenz && dsten)
3376 || (sreadx && step && !srcenz && !textext && !srcen && dsten)
3377 || (idle_inner && step && !srcenx && !textext && !srcen && dsten)
3378 || (dzwrite && step && !inner0 && !textext && !srcen && dsten)
3379 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && dsten)
3380 || (txtread && step && !srcen && dsten)
3381 || (dread && !step))
3382 {
3383 dreadi = true;
3384 }
3385 else
3386 dreadi = false;
3387
3388 // DESTINATION ZED READ
3389
3390 if ((dread && step && dstenz)
3391 || (szread && step && !dsten && dstenz)
3392 || (sread && step && !srcenz && !dsten && dstenz)
3393 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && dstenz)
3394 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && dstenz)
3395 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && dstenz)
3396 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && dstenz)
3397 || (txtread && step && !srcen && !dsten && dstenz)
3398 || (dzread && !step))
3399 {
3400 dzreadi = true;
3401 }
3402 else
3403 dzreadi = false;
3404
3405 // DESTINATION DATA WRITE
3406
3407 if ((dzread && step)
3408 || (dread && step && !dstenz)
3409 || (szread && step && !dsten && !dstenz)
3410 || (sread && step && !srcenz && !dsten && !dstenz)
3411 || (txtread && step && !srcen && !dsten && !dstenz)
3412 || (sreadx && step && !srcenz && !textext && !srcen && !dsten && !dstenz)
3413 || (idle_inner && step && !srcenx && !textext && !srcen && !dsten && !dstenz)
3414 || (dzwrite && step && !inner0 && !textext && !srcen && !dsten && !dstenz)
3415 || (dwrite && step && !dstwrz && !inner0 && !textext && !srcen && !dsten && !dstenz)
3416 || (dwrite && !step))
3417 {
3418 dwritei = true;
3419 }
3420 else
3421 dwritei = false;
3422
3423 // DESTINATION ZED WRITE
3424
3425 if ((dzwrite && !step)
3426 || (dwrite && step && dstwrz))
3427 {
3428 dzwritei = true;
3429 }
3430 else
3431 dzwritei = false;
3432
3433 //Kludge: A QnD way to make sure that sshftld is asserted only for the first
3434 // cycle of the inner loop...
3435 sshftld = idle_inner;
3436
3437 // Here we move the fooi into their foo counterparts in order to simulate the moving
3438 // of data into the various FDSYNCs... Each time we loop we simulate one clock cycle...
3439
3440 idle_inner = idle_inneri;
3441 sreadx = sreadxi;
3442 szreadx = szreadxi;
3443 sread = sreadi;
3444 szread = szreadi;
3445 dread = dreadi;
3446 dzread = dzreadi;
3447 dwrite = dwritei;
3448 dzwrite = dzwritei;
3449
3450 // Here's a few more decodes--not sure if they're supposed to go here or not...
3451
3452 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
3453
3454 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
3455
3456 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
3457 bool gendst = dreadi || dzreadi || dwritei || dzwritei;
3458 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
3459
3460 bool zaddr = szreadx || szread || dzread || dzwrite;
3461
3462 // Some stuff from MCONTROL.NET--not sure if this is the correct use of this decode or not...
3463 /*Fontread\ := OND1 (fontread\, sread[1], sreadx[1], bcompen);
3464 Fontread := INV1 (fontread, fontread\);
3465 Justt := NAN3 (justt, fontread\, phrase_mode, tactive\);
3466 Justify := TS (justify, justt, busen);*/
3467 bool fontread = (sread || sreadx) && bcompen;
3468 bool justify = !(!fontread && phrase_mode /*&& tactive*/);
3469
3470 /* Generate inner loop update enables */
3471 /*
3472 A1_addi := MX2 (a1_addi, dsta_addi, srca_addi, dsta2);
3473 A2_addi := MX2 (a2_addi, srca_addi, dsta_addi, dsta2);
3474 A1_add := FD1 (a1_add, a1_add\, a1_addi, clk);
3475 A2_add := FD1 (a2_add, a2_add\, a2_addi, clk);
3476 A2_addb := BUF1 (a2_addb, a2_add);
3477 */
3478 bool a1_add = (dsta2 ? srca_addi : dsta_addi);
3479 bool a2_add = (dsta2 ? dsta_addi : srca_addi);
3480
3481 /* Address adder input A register selection
3482 000 A1 step integer part
3483 001 A1 step fraction part
3484 010 A1 increment integer part
3485 011 A1 increment fraction part
3486 100 A2 step
3487
3488 bit 2 = a2update
3489 bit 1 = /a2update . (a1_add . a1addx[0..1])
3490 bit 0 = /a2update . ( a1fupdate
3491 + a1_add . atick[0] . a1addx[0..1])
3492 The /a2update term on bits 0 and 1 is redundant.
3493 Now look-ahead based
3494 */
3495 uint8_t addasel = (a1fupdate || (a1_add && a1addx == 3) ? 0x01 : 0x00);
3496 addasel |= (a1_add && a1addx == 3 ? 0x02 : 0x00);
3497 addasel |= (a2update ? 0x04 : 0x00);
3498 /* Address adder input A X constant selection
3499 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all
3500 zeroes when they are all 1
3501 Remember - these are pixels, so to add one phrase the pixel size
3502 has to be taken into account to get the appropriate value.
3503 for A1
3504 if a1addx[0..1] are 00 set 6 - pixel size
3505 if a1addx[0..1] are 01 set the value 000
3506 if a1addx[0..1] are 10 set the value 111
3507 similarly for A2
3508 JLH: Also, 11 will likewise set the value to 111
3509 */
3510 uint8_t a1_xconst = 6 - a1_pixsize, a2_xconst = 6 - a2_pixsize;
3511
3512 if (a1addx == 1)
3513 a1_xconst = 0;
3514 else if (a1addx & 0x02)
3515 a1_xconst = 7;
3516
3517 if (a2addx == 1)
3518 a2_xconst = 0;
3519 else if (a2addx & 0x02)
3520 a2_xconst = 7;
3521
3522 uint8_t adda_xconst = (a2_add ? a2_xconst : a1_xconst);
3523 /* Address adder input A Y constant selection
3524 22 June 94 - This was erroneous, because only the a1addy bit was reflected here.
3525 Therefore, the selection has to be controlled by a bug fix bit.
3526 JLH: Bug fix bit in Jaguar II--not in Jaguar I!
3527 */
3528 bool adda_yconst = a1addy;
3529 /* Address adder input A register versus constant selection
3530 given by a1_add . a1addx[0..1]
3531 + a1update
3532 + a1fupdate
3533 + a2_add . a2addx[0..1]
3534 + a2update
3535 */
3536 bool addareg = ((a1_add && a1addx == 3) || a1update || a1fupdate
3537 || (a2_add && a2addx == 3) || a2update ? true : false);
3538 /* The adders can be put into subtract mode in add pixel size
3539 mode when the corresponding flags are set */
3540 bool suba_x = ((a1_add && a1xsign && a1addx == 1) || (a2_add && a2xsign && a2addx == 1) ? true : false);
3541 bool suba_y = ((a1_add && a1addy && a1ysign) || (a2_add && a2addy && a2ysign) ? true : false);
3542 /* Address adder input B selection
3543 00 A1 pointer
3544 01 A2 pointer
3545 10 A1 fraction
3546 11 Zero
3547
3548 Bit 1 = a1fupdate
3549 + (a1_add . atick[0] . a1addx[0..1])
3550 + a1fupdate . a1_stepld
3551 + a1update . a1_stepld
3552 + a2update . a2_stepld
3553 Bit 0 = a2update + a2_add
3554 + a1fupdate . a1_stepld
3555 + a1update . a1_stepld
3556 + a2update . a2_stepld
3557 */
3558 uint8_t addbsel = (a2update || a2_add || (a1fupdate && a1_stepld)
3559 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x01 : 0x00);
3560 addbsel |= (a1fupdate || (a1_add && a1addx == 3) || (a1fupdate && a1_stepld)
3561 || (a1update && a1_stepld) || (a2update && a2_stepld) ? 0x02 : 0x00);
3562
3563 /* The modulo bits are used to align X onto a phrase boundary when
3564 it is being updated by one phrase
3565 000 no mask
3566 001 mask bit 0
3567 010 mask bits 1-0
3568 ..
3569 110 mask bits 5-0
3570
3571 Masking is enabled for a1 when a1addx[0..1] is 00, and the value
3572 is 6 - the pixel size (again!)
3573 */
3574 uint8_t maska1 = (a1_add && a1addx == 0 ? 6 - a1_pixsize : 0);
3575 uint8_t maska2 = (a2_add && a2addx == 0 ? 6 - a2_pixsize : 0);
3576 uint8_t modx = (a2_add ? maska2 : maska1);
3577 /* Generate load strobes for the increment updates */
3578
3579 /*A1pldt := NAN2 (a1pldt, atick[1], a1_add);
3580 A1ptrldi := NAN2 (a1ptrldi, a1update\, a1pldt);
3581
3582 A1fldt := NAN4 (a1fldt, atick[0], a1_add, a1addx[0..1]);
3583 A1fracldi := NAN2 (a1fracldi, a1fupdate\, a1fldt);
3584
3585 A2pldt := NAN2 (a2pldt, atick[1], a2_add);
3586 A2ptrldi := NAN2 (a2ptrldi, a2update\, a2pldt);*/
3587 bool a1fracldi = a1fupdate || (a1_add && a1addx == 3);
3588
3589 // Some more from DCONTROL...
3590 // atick[] just MAY be important here! We're assuming it's true and dropping the term...
3591 // That will probably screw up some of the lower terms that seem to rely on the timing of it...
3592 #ifdef _MSC_VER
3593 #pragma message("Warning: srcdreadd is not properly initialized!")
3594 #else
3595 #warning "srcdreadd is not properly initialized!"
3596 #endif // _MSC_VER
3597 bool srcdreadd = false; // Set in INNER.NET
3598 //Shadeadd\ := NAN2H (shadeadd\, dwrite, srcshade);
3599 //Shadeadd := INV2 (shadeadd, shadeadd\);
3600 bool shadeadd = dwrite && srcshade;
3601 /* Data adder control, input A selection
3602 000 Destination data
3603 001 Initialiser pixel value
3604 100 Source data - computed intensity fraction
3605 101 Pattern data - computed intensity
3606 110 Source zed 1 - computed zed
3607 111 Source zed 2 - computed zed fraction
3608
3609 Bit 0 = dwrite . gourd . atick[1]
3610 + dzwrite . gourz . atick[0]
3611 + istepadd
3612 + zstepfadd
3613 + init_if + init_ii + init_zf + init_zi
3614 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3615 + zstepadd
3616 + zstepfadd
3617 Bit 2 = (gourd + gourz) . /(init_if + init_ii + init_zf + init_zi)
3618 + dwrite . srcshade
3619 */
3620 uint8_t daddasel = ((dwrite && gourd) || (dzwrite && gourz) || istepadd || zstepfadd
3621 || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3622 daddasel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3623 daddasel |= (((gourd || gourz) && !(init_if || init_ii || init_zf || init_zi))
3624 || (dwrite && srcshade) ? 0x04 : 0x00);
3625 /* Data adder control, input B selection
3626 0000 Source data
3627 0001 Data initialiser increment
3628 0100 Bottom 16 bits of I increment repeated four times
3629 0101 Top 16 bits of I increment repeated four times
3630 0110 Bottom 16 bits of Z increment repeated four times
3631 0111 Top 16 bits of Z increment repeated four times
3632 1100 Bottom 16 bits of I step repeated four times
3633 1101 Top 16 bits of I step repeated four times
3634 1110 Bottom 16 bits of Z step repeated four times
3635 1111 Top 16 bits of Z step repeated four times
3636
3637 Bit 0 = dwrite . gourd . atick[1]
3638 + dzwrite . gourz . atick[1]
3639 + dwrite . srcshade
3640 + istepadd
3641 + zstepadd
3642 + init_if + init_ii + init_zf + init_zi
3643 Bit 1 = dzwrite . gourz . (atick[0] + atick[1])
3644 + zstepadd
3645 + zstepfadd
3646 Bit 2 = dwrite . gourd . (atick[0] + atick[1])
3647 + dzwrite . gourz . (atick[0] + atick[1])
3648 + dwrite . srcshade
3649 + istepadd + istepfadd + zstepadd + zstepfadd
3650 Bit 3 = istepadd + istepfadd + zstepadd + zstepfadd
3651 */
3652 uint8_t daddbsel = ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3653 || istepadd || zstepadd || init_if || init_ii || init_zf || init_zi ? 0x01 : 0x00);
3654 daddbsel |= ((dzwrite && gourz) || zstepadd || zstepfadd ? 0x02 : 0x00);
3655 daddbsel |= ((dwrite && gourd) || (dzwrite && gourz) || (dwrite && srcshade)
3656 || istepadd || istepfadd || zstepadd || zstepfadd ? 0x04 : 0x00);
3657 daddbsel |= (istepadd && istepfadd && zstepadd && zstepfadd ? 0x08 : 0x00);
3658 /* Data adder mode control
3659 000 16-bit normal add
3660 001 16-bit saturating add with carry
3661 010 8-bit saturating add with carry, carry into top byte is
3662 inhibited (YCrCb)
3663 011 8-bit saturating add with carry, carry into top byte and
3664 between top nybbles is inhibited (CRY)
3665 100 16-bit normal add with carry
3666 101 16-bit saturating add
3667 110 8-bit saturating add, carry into top byte is inhibited
3668 111 8-bit saturating add, carry into top byte and between top
3669 nybbles is inhibited
3670
3671 The first five are used for Gouraud calculations, the latter three
3672 for adding source and destination data
3673
3674 Bit 0 = dzwrite . gourz . atick[1]
3675 + dwrite . gourd . atick[1] . /topnen . /topben . /ext_int
3676 + dwrite . gourd . atick[1] . topnen . topben . /ext_int
3677 + zstepadd
3678 + istepadd . /topnen . /topben . /ext_int
3679 + istepadd . topnen . topben . /ext_int
3680 + /gourd . /gourz . /topnen . /topben
3681 + /gourd . /gourz . topnen . topben
3682 + shadeadd . /topnen . /topben
3683 + shadeadd . topnen . topben
3684 + init_ii . /topnen . /topben . /ext_int
3685 + init_ii . topnen . topben . /ext_int
3686 + init_zi
3687
3688 Bit 1 = dwrite . gourd . atick[1] . /topben . /ext_int
3689 + istepadd . /topben . /ext_int
3690 + /gourd . /gourz . /topben
3691 + shadeadd . /topben
3692 + init_ii . /topben . /ext_int
3693
3694 Bit 2 = /gourd . /gourz
3695 + shadeadd
3696 + dwrite . gourd . atick[1] . ext_int
3697 + istepadd . ext_int
3698 + init_ii . ext_int
3699 */
3700 uint8_t daddmode = ((dzwrite && gourz) || (dwrite && gourd && !topnen && !topben && !ext_int)
3701 || (dwrite && gourd && topnen && topben && !ext_int) || zstepadd
3702 || (istepadd && !topnen && !topben && !ext_int)
3703 || (istepadd && topnen && topben && !ext_int) || (!gourd && !gourz && !topnen && !topben)
3704 || (!gourd && !gourz && topnen && topben) || (shadeadd && !topnen && !topben)
3705 || (shadeadd && topnen && topben) || (init_ii && !topnen && !topben && !ext_int)
3706 || (init_ii && topnen && topben && !ext_int) || init_zi ? 0x01 : 0x00);
3707 daddmode |= ((dwrite && gourd && !topben && !ext_int) || (istepadd && !topben && !ext_int)
3708 || (!gourd && !gourz && !topben) || (shadeadd && !topben)
3709 || (init_ii && !topben && !ext_int) ? 0x02 : 0x00);
3710 daddmode |= ((!gourd && !gourz) || shadeadd || (dwrite && gourd && ext_int)
3711 || (istepadd && ext_int) || (init_ii && ext_int) ? 0x04 : 0x00);
3712 /* Data add load controls
3713 Pattern fraction (dest data) is loaded on
3714 dwrite . gourd . atick[0]
3715 + istepfadd . /datinit
3716 + init_if
3717 Pattern data is loaded on
3718 dwrite . gourd . atick[1]
3719 + istepadd . /datinit . /datinit
3720 + init_ii
3721 Source z1 is loaded on
3722 dzwrite . gourz . atick[1]
3723 + zstepadd . /datinit . /datinit
3724 + init_zi
3725 Source z2 is loaded on
3726 dzwrite . gourz . atick[0]
3727 + zstepfadd
3728 + init_zf
3729 Texture map shaded data is loaded on
3730 srcdreadd . srcshade
3731 */
3732 bool patfadd = (dwrite && gourd) || (istepfadd && !datinit) || init_if;
3733 bool patdadd = (dwrite && gourd) || (istepadd && !datinit) || init_ii;
3734 bool srcz1add = (dzwrite && gourz) || (zstepadd && !datinit) || init_zi;
3735 bool srcz2add = (dzwrite && gourz) || zstepfadd || init_zf;
3736 bool srcshadd = srcdreadd && srcshade;
3737 bool daddq_sel = patfadd || patdadd || srcz1add || srcz2add || srcshadd;
3738 /* Select write data
3739 This has to be controlled from stage 1 of the pipe-line, delayed
3740 by one tick, as the write occurs in the cycle after the ack.
3741
3742 00 pattern data
3743 01 lfu data
3744 10 adder output
3745 11 source zed
3746
3747 Bit 0 = /patdsel . /adddsel
3748 + dzwrite1d
3749 Bit 1 = adddsel
3750 + dzwrite1d
3751 */
3752 uint8_t data_sel = ((!patdsel && !adddsel) || dzwrite ? 0x01 : 0x00)
3753 | (adddsel || dzwrite ? 0x02 : 0x00);
3754
3755 uint32_t address, pixAddr;
3756 ADDRGEN(address, pixAddr, gena2i, zaddr,
3757 a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3758 a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3759
3760 //Here's my guess as to how the addresses get truncated to phrase boundaries in phrase mode...
3761 if (!justify)
3762 address &= 0xFFFFF8;
3763
3764 /* Generate source alignment shift
3765 -------------------------------
3766 The source alignment shift for data move is the difference between
3767 the source and destination X pointers, multiplied by the pixel
3768 size. Only the low six bits of the pointers are of interest, as
3769 pixel sizes are always a power of 2 and window rows are always
3770 phrase aligned.
3771
3772 When not in phrase mode, the top 3 bits of the shift value are
3773 set to zero (2/26).
3774
3775 Source shifting is also used to extract bits for bit-to-byte
3776 expansion in phrase mode. This involves only the bottom three
3777 bits of the shift value, and is based on the offset within the
3778 phrase of the destination X pointer, in pixels.
3779
3780 Source shifting is disabled when srcen is not set.
3781 */
3782 uint8_t dstxp = (dsta2 ? a2_x : a1_x) & 0x3F;
3783 uint8_t srcxp = (dsta2 ? a1_x : a2_x) & 0x3F;
3784 uint8_t shftv = ((dstxp - srcxp) << pixsize) & 0x3F;
3785 /* The phrase mode alignment count is given by the phrase offset
3786 of the first pixel, for bit to byte expansion */
3787 uint8_t pobb = 0;
3788
3789 if (pixsize == 3)
3790 pobb = dstxp & 0x07;
3791 if (pixsize == 4)
3792 pobb = dstxp & 0x03;
3793 if (pixsize == 5)
3794 pobb = dstxp & 0x01;
3795
3796 bool pobbsel = phrase_mode && bcompen;
3797 uint8_t loshd = (pobbsel ? pobb : shftv) & 0x07;
3798 uint8_t shfti = (srcen || pobbsel ? (sshftld ? loshd : srcshift & 0x07) : 0);
3799 /* Enable for high bits is srcen . phrase_mode */
3800 shfti |= (srcen && phrase_mode ? (sshftld ? shftv & 0x38 : srcshift & 0x38) : 0);
3801 srcshift = shfti;
3802
3803 if (sreadx)
3804 {
3805 #ifdef VERBOSE_BLITTER_LOGGING
3806 if (logBlit)
3807 WriteLog(" Entering SREADX state...");
3808 #endif
3809 //uint32_t srcAddr, pixAddr;
3810 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3811 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3812 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3813 srcd2 = srcd1;
3814 srcd1 = ((uint64_t)JaguarReadLong(address + 0, BLITTER) << 32)
3815 | (uint64_t)JaguarReadLong(address + 4, BLITTER);
3816 //Kludge to take pixel size into account...
3817 //Hmm. If we're not in phrase mode, this is most likely NOT going to be used...
3818 //Actually, it would be--because of BCOMPEN expansion, for example...
3819 if (!phrase_mode)
3820 {
3821 if (bcompen)
3822 srcd1 >>= 56;
3823 else
3824 {
3825 if (pixsize == 5)
3826 srcd1 >>= 32;
3827 else if (pixsize == 4)
3828 srcd1 >>= 48;
3829 else
3830 srcd1 >>= 56;
3831 }
3832 }//*/
3833 #ifdef VERBOSE_BLITTER_LOGGING
3834 if (logBlit)
3835 WriteLog(" Source extra read address/pix address: %08X/%1X [%08X%08X]\n",
3836 address, pixAddr, (uint32_t)(srcd1 >> 32), (uint32_t)(srcd1 & 0xFFFFFFFF));
3837 #endif
3838 }
3839
3840 if (szreadx)
3841 {
3842 #ifdef VERBOSE_BLITTER_LOGGING
3843 if (logBlit)
3844 WriteLog(" Entering SZREADX state...");
3845 #endif
3846 srcz2 = srcz1;
3847 srcz1 = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
3848 #ifdef VERBOSE_BLITTER_LOGGING
3849 if (logBlit)
3850 WriteLog(" Src Z extra read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3851 (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF));
3852 #endif
3853 }
3854
3855 if (sread)
3856 {
3857 #ifdef VERBOSE_BLITTER_LOGGING
3858 if (logBlit)
3859 WriteLog(" Entering SREAD state...");
3860 #endif
3861 //uint32_t srcAddr, pixAddr;
3862 //ADDRGEN(srcAddr, pixAddr, gena2i, zaddr,
3863 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3864 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3865 srcd2 = srcd1;
3866 srcd1 = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
3867 //Kludge to take pixel size into account...
3868 if (!phrase_mode)
3869 {
3870 if (bcompen)
3871 srcd1 >>= 56;
3872 else
3873 {
3874 if (pixsize == 5)
3875 srcd1 >>= 32;
3876 else if (pixsize == 4)
3877 srcd1 >>= 48;
3878 else
3879 srcd1 >>= 56;
3880 }
3881 }
3882 #ifdef VERBOSE_BLITTER_LOGGING
3883 if (logBlit)
3884 {
3885 WriteLog(" Source read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3886 (uint32_t)(srcd1 >> 32), (uint32_t)(srcd1 & 0xFFFFFFFF));
3887 //fflush(stdout);
3888 }
3889 #endif
3890 }
3891
3892 if (szread)
3893 {
3894 #ifdef VERBOSE_BLITTER_LOGGING
3895 if (logBlit)
3896 {
3897 WriteLog(" Entering SZREAD state...");
3898 //fflush(stdout);
3899 }
3900 #endif
3901 srcz2 = srcz1;
3902 srcz1 = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
3903 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3904 if (!phrase_mode && pixsize == 4)
3905 srcz1 >>= 48;
3906
3907 #ifdef VERBOSE_BLITTER_LOGGING
3908 if (logBlit)
3909 {
3910 WriteLog(" Src Z read address/pix address: %08X/%1X [%08X%08X]\n", address, pixAddr,
3911 (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF));
3912 }
3913 #endif
3914 }
3915
3916 if (dread)
3917 {
3918 #ifdef VERBOSE_BLITTER_LOGGING
3919 if (logBlit)
3920 WriteLog(" Entering DREAD state...");
3921 #endif
3922 //uint32_t dstAddr, pixAddr;
3923 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
3924 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
3925 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
3926 dstd = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
3927 //Kludge to take pixel size into account...
3928 if (!phrase_mode)
3929 {
3930 if (pixsize == 5)
3931 dstd >>= 32;
3932 else if (pixsize == 4)
3933 dstd >>= 48;
3934 else
3935 dstd >>= 56;
3936 }
3937 #ifdef VERBOSE_BLITTER_LOGGING
3938 if (logBlit)
3939 WriteLog(" Dest read address/pix address: %08X/%1X [%08X%08X]\n", address,
3940 pixAddr, (uint32_t)(dstd >> 32), (uint32_t)(dstd & 0xFFFFFFFF));
3941 #endif
3942 }
3943
3944 if (dzread)
3945 {
3946 // Is Z always 64 bit read? Or sometimes 16 bit (dependent on phrase_mode)?
3947 #ifdef VERBOSE_BLITTER_LOGGING
3948 if (logBlit)
3949 WriteLog(" Entering DZREAD state...");
3950 #endif
3951 dstz = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
3952 //Kludge to take pixel size into account... I believe that it only has to take 16BPP mode into account. Not sure tho.
3953 if (!phrase_mode && pixsize == 4)
3954 dstz >>= 48;
3955
3956 #ifdef VERBOSE_BLITTER_LOGGING
3957 if (logBlit)
3958 WriteLog(" Dest Z read address/pix address: %08X/%1X [%08X%08X]\n", address,
3959 pixAddr, (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF));
3960 #endif
3961 }
3962
3963 // These vars should probably go further up in the code... !!! FIX !!!
3964 // We can't preassign these unless they're static...
3965 //uint64_t srcz = 0; // These are assigned to shut up stupid compiler warnings--dwrite is ALWAYS asserted
3966 //bool winhibit = false;
3967 uint64_t srcz;
3968 bool winhibit;
3969 //NOTE: SRCSHADE requires GOURZ to be set to work properly--another Jaguar I bug
3970 if (dwrite)
3971 {
3972 #ifdef VERBOSE_BLITTER_LOGGING
3973 if (logBlit)
3974 WriteLog(" Entering DWRITE state...");
3975 #endif
3976 //Counter is done on the dwrite state...! (We'll do it first, since it affects dstart/dend calculations.)
3977 //Here's the voodoo for figuring the correct amount of pixels in phrase mode (or not):
3978 int8_t inct = -((dsta2 ? a2_x : a1_x) & 0x07); // From INNER_CNT
3979 uint8_t inc = 0;
3980 inc = (!phrase_mode || (phrase_mode && (inct & 0x01)) ? 0x01 : 0x00);
3981 inc |= (phrase_mode && (((pixsize == 3 || pixsize == 4) && (inct & 0x02)) || pixsize == 5 && !(inct & 0x01)) ? 0x02 : 0x00);
3982 inc |= (phrase_mode && ((pixsize == 3 && (inct & 0x04)) || (pixsize == 4 && !(inct & 0x03))) ? 0x04 : 0x00);
3983 inc |= (phrase_mode && pixsize == 3 && !(inct & 0x07) ? 0x08 : 0x00);
3984
3985 uint16_t oldicount = icount; // Save icount to detect underflow...
3986 icount -= inc;
3987
3988 if (icount == 0 || ((icount & 0x8000) && !(oldicount & 0x8000)))
3989 inner0 = true;
3990 // X/Y stepping is also done here, I think...No. It's done when a1_add or a2_add is asserted...
3991
3992 //*********************************************************************************
3993 //Start & end write mask computations...
3994 //*********************************************************************************
3995
3996 uint8_t dstart = 0;
3997
3998 if (pixsize == 3)
3999 dstart = (dstxp & 0x07) << 3;
4000 if (pixsize == 4)
4001 dstart = (dstxp & 0x03) << 4;
4002 if (pixsize == 5)
4003 dstart = (dstxp & 0x01) << 5;
4004
4005 dstart = (phrase_mode ? dstart : pixAddr & 0x07);
4006
4007 //This is the other Jaguar I bug... Normally, should ALWAYS select a1_x here.
4008 uint16_t dstxwr = (dsta2 ? a2_x : a1_x) & 0x7FFE;
4009 uint16_t pseq = dstxwr ^ (a1_win_x & 0x7FFE);
4010 pseq = (pixsize == 5 ? pseq : pseq & 0x7FFC);
4011 pseq = ((pixsize & 0x06) == 4 ? pseq : pseq & 0x7FF8);
4012 bool penden = clip_a1 && (pseq == 0);
4013 uint8_t window_mask = 0;
4014
4015 if (pixsize == 3)
4016 window_mask = (a1_win_x & 0x07) << 3;
4017 if (pixsize == 4)
4018 window_mask = (a1_win_x & 0x03) << 4;
4019 if (pixsize == 5)
4020 window_mask = (a1_win_x & 0x01) << 5;
4021
4022 window_mask = (penden ? window_mask : 0);
4023
4024 /*
4025 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4026 Source extra read address/pix address: 000095D0/0 [000004E40000001C]
4027 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4028 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4029 Source read address/pix address: 000095D8/0 [0054003800009814]
4030 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4031 Entering DWRITE state...
4032 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)
4033 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4034
4035 (icount=026E, inc=4)
4036 icount & 0x03 = 0x02
4037 << 4 = 0x20
4038
4039 window_mask = 0x1000
4040
4041 Therefore, it chooses the inner_mask over the window_mask every time! Argh!
4042 This is because we did this wrong:
4043 Innerm[3-5] := AN2 (inner_mask[3-5], imb[3-5], inner0);
4044 NOTE! This doesn't fix the problem because inner0 is asserted too late to help here. !!! FIX !!! [Should be DONE]
4045 */
4046
4047 /* The mask to be used if within one phrase of the end of the inner
4048 loop, similarly */
4049 uint8_t inner_mask = 0;
4050
4051 if (pixsize == 3)
4052 inner_mask = (icount & 0x07) << 3;
4053 if (pixsize == 4)
4054 inner_mask = (icount & 0x03) << 4;
4055 if (pixsize == 5)
4056 inner_mask = (icount & 0x01) << 5;
4057 if (!inner0)
4058 inner_mask = 0;
4059 /* The actual mask used should be the lesser of the window masks and
4060 the inner mask, where is all cases 000 means 1000. */
4061 window_mask = (window_mask == 0 ? 0x40 : window_mask);
4062 inner_mask = (inner_mask == 0 ? 0x40 : inner_mask);
4063 uint8_t emask = (window_mask > inner_mask ? inner_mask : window_mask);
4064 /* The mask to be used for the pixel size, to which must be added
4065 the bit offset */
4066 uint8_t pma = pixAddr + (1 << pixsize);
4067 /* Select the mask */
4068 uint8_t dend = (phrase_mode ? emask : pma);
4069
4070 /* The cycle width in phrase mode is normally one phrase. However,
4071 at the start and end it may be narrower. The start and end masks
4072 are used to generate this. The width is given by:
4073
4074 8 - start mask - (8 - end mask)
4075 = end mask - start mask
4076
4077 This is only used for writes in phrase mode.
4078 Start and end from the address level of the pipeline are used.
4079 */
4080 uint8_t pwidth = (((dend | dstart) & 0x07) == 0 ? 0x08 : (dend - dstart) & 0x07);
4081
4082 //uint32_t dstAddr, pixAddr;
4083 //ADDRGEN(dstAddr, pixAddr, gena2i, zaddr,
4084 // a1_x, a1_y, a1_base, a1_pitch, a1_pixsize, a1_width, a1_zoffset,
4085 // a2_x, a2_y, a2_base, a2_pitch, a2_pixsize, a2_width, a2_zoffset);
4086 #ifdef VERBOSE_BLITTER_LOGGING
4087 if (logBlit)
4088 WriteLog(" Dest write address/pix address: %08X/%1X", address, pixAddr);
4089 #endif
4090
4091 //More testing... This is almost certainly wrong, but how else does this work???
4092 //Seems to kinda work... But still, this doesn't seem to make any sense!
4093 if (phrase_mode && !dsten)
4094 dstd = ((uint64_t)JaguarReadLong(address, BLITTER) << 32) | (uint64_t)JaguarReadLong(address + 4, BLITTER);
4095
4096 //Testing only... for now...
4097 //This is wrong because the write data is a combination of srcd and dstd--either run
4098 //thru the LFU or in PATDSEL or ADDDSEL mode. [DONE now, thru DATA module]
4099 // Precedence is ADDDSEL > PATDSEL > LFU.
4100 //Also, doesn't take into account the start & end masks, or the phrase width...
4101 //Now it does!
4102
4103 // srcd2 = xxxx xxxx 0123 4567, srcd = 8901 2345 xxxx xxxx, srcshift = $20 (32)
4104 uint64_t srcd = (srcd2 << (64 - srcshift)) | (srcd1 >> srcshift);
4105 //bleh, ugly ugly ugly
4106 if (srcshift == 0)
4107 srcd = srcd1;
4108
4109 //NOTE: This only works with pixel sizes less than 8BPP...
4110 //DOUBLE NOTE: Still need to do regression testing to ensure that this doesn't break other stuff... !!! CHECK !!!
4111 if (!phrase_mode && srcshift != 0)
4112 srcd = ((srcd2 & 0xFF) << (8 - srcshift)) | ((srcd1 & 0xFF) >> srcshift);
4113
4114 //Z DATA() stuff done here... And it has to be done before any Z shifting...
4115 //Note that we need to have phrase mode start/end support here... (Not since we moved it from dzwrite...!)
4116 /*
4117 Here are a couple of Cybermorph blits with Z:
4118 $00113078 // DSTEN DSTENZ DSTWRZ CLIP_A1 GOURD GOURZ PATDSEL ZMODE=4
4119 $09900F39 // SRCEN DSTEN DSTENZ DSTWRZ UPDA1 UPDA1F UPDA2 DSTA2 ZMODE=4 LFUFUNC=C DCOMPEN
4120
4121 We're having the same phrase mode overwrite problem we had with the pixels... !!! FIX !!!
4122 Odd. It's equating 0 with 0... Even though ZMODE is $04 (less than)!
4123 */
4124 if (gourz)
4125 {
4126 /*
4127 void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
4128 uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
4129 uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
4130 uint32_t zinc, uint32_t zstep)
4131 */
4132 uint16_t addq[4];
4133 uint8_t initcin[4] = { 0, 0, 0, 0 };
4134 ADDARRAY(addq, 7/*daddasel*/, 6/*daddbsel*/, 0/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4135 srcz2 = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
4136 ADDARRAY(addq, 6/*daddasel*/, 7/*daddbsel*/, 1/*daddmode*/, 0, 0, initcin, 0, 0, 0, 0, 0, srcz1, srcz2, zinc, 0);
4137 srcz1 = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
4138
4139 #if 0//def VERBOSE_BLITTER_LOGGING
4140 if (logBlit)
4141 WriteLog("\n[srcz1=%08X%08X, srcz2=%08X%08X, zinc=%08X",
4142 (uint32_t)(srcz1 >> 32), (uint32_t)(srcz1 & 0xFFFFFFFF),
4143 (uint32_t)(srcz2 >> 32), (uint32_t)(srcz2 & 0xFFFFFFFF), zinc);
4144 #endif
4145 }
4146
4147 uint8_t zSrcShift = srcshift & 0x30;
4148 srcz = (srcz2 << (64 - zSrcShift)) | (srcz1 >> zSrcShift);
4149 //bleh, ugly ugly ugly
4150 if (zSrcShift == 0)
4151 srcz = srcz1;
4152
4153 #if 0//def VERBOSE_BLITTER_LOGGING
4154 if (logBlit)
4155 WriteLog(" srcz=%08X%08X]\n", (uint32_t)(srcz >> 32), (uint32_t)(srcz & 0xFFFFFFFF));
4156 #endif
4157
4158 //When in SRCSHADE mode, it adds the IINC to the read source (from LFU???)
4159 //According to following line, it gets LFU mode. But does it feed the source into the LFU
4160 //after the add?
4161 //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)
4162 //Let's try this:
4163 if (srcshade)
4164 {
4165 //NOTE: This is basically doubling the work done by DATA--since this is what
4166 // ADDARRAY is loaded with when srschshade is enabled... !!! FIX !!!
4167 // Also note that it doesn't work properly unless GOURZ is set--there's the clue!
4168 uint16_t addq[4];
4169 uint8_t initcin[4] = { 0, 0, 0, 0 };
4170 ADDARRAY(addq, 4/*daddasel*/, 5/*daddbsel*/, 7/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4171 srcd = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
4172 }
4173 //Seems to work... Not 100% sure tho.
4174 //end try this
4175
4176 //Temporary kludge, to see if the fractional pattern does anything...
4177 //This works, BTW
4178 //But it seems to mess up in Cybermorph... the shading should be smooth but it isn't...
4179 //Seems the carry out is lost again... !!! FIX !!! [DONE--see below]
4180 if (patfadd)
4181 {
4182 uint16_t addq[4];
4183 uint8_t initcin[4] = { 0, 0, 0, 0 };
4184 ADDARRAY(addq, 4/*daddasel*/, 4/*daddbsel*/, 0/*daddmode*/, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
4185 srcd1 = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
4186 }
4187
4188 //Note that we still don't take atick[0] & [1] into account here, so this will skip half of the data needed... !!! FIX !!!
4189 //Not yet enumerated: dbinh, srcdread, srczread
4190 //Also, should do srcshift on the z value in phrase mode... !!! FIX !!! [DONE]
4191 //As well as add a srcz variable we can set external to this state... !!! FIX !!! [DONE]
4192
4193 uint64_t wdata;
4194 uint8_t dcomp, zcomp;
4195 DATA(wdata, dcomp, zcomp, winhibit,
4196 true, cmpdst, daddasel, daddbsel, daddmode, daddq_sel, data_sel, 0/*dbinh*/,
4197 dend, dstart, dstd, iinc, lfufunc, patd, patdadd,
4198 phrase_mode, srcd, false/*srcdread*/, false/*srczread*/, srcz2add, zmode,
4199 bcompen, bkgwren, dcompen, icount & 0x07, pixsize,
4200 srcz, dstz, zinc);
4201 /*
4202 Seems that the phrase mode writes with DCOMPEN and DSTEN are corrupting inside of DATA: !!! FIX !!!
4203 It's fairly random as well. 7CFE -> 7DFE, 7FCA -> 78CA, 7FA4 -> 78A4, 7F88 -> 8F88
4204 It could be related to an uninitialized variable, like the zmode bug...
4205 [DONE]
4206 It was a bug in the dech38el data--it returned $FF for ungated instead of $00...
4207
4208 Blit! (CMD = 09800609)
4209 Flags: SRCEN DSTEN UPDA1 UPDA2 LFUFUNC=C DCOMPEN
4210 count = 10 x 12
4211 a1_base = 00110000, a2_base = 0010B2A8
4212 a1_x = 004B, a1_y = 00D8, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0704, a2_y = 0000
4213 a1_step_x = FFF3, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = FFFC, a2_step_y = 0000
4214 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4215 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4216 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4217 a1_pixsize = 4, a2_pixsize = 4
4218 srcd=0000000000000000 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4219 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4220 Phrase mode is ON
4221 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4222 Entering INNER state...
4223 Entering SREAD state... Source read address/pix address: 0010C0B0/0 [0000000078047804]
4224 Entering A2_ADD state [a2_x=0704, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4225 Entering DREAD state...
4226 Dest read address/pix address: 00197240/0 [0000000000000028]
4227 Entering DWRITE state...
4228 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)
4229 Entering A1_ADD state [a1_x=004B, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4230 Entering SREAD state... Source read address/pix address: 0010C0B8/0 [7804780478047804]
4231 Entering A2_ADD state [a2_x=0708, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4232 Entering DREAD state...
4233 Dest read address/pix address: 00197260/0 [0028000000200008]
4234 Entering DWRITE state...
4235 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)
4236 Entering A1_ADD state [a1_x=004C, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4237 Entering SREAD state... Source read address/pix address: 0010C0C0/0 [0000000000000000]
4238 Entering A2_ADD state [a2_x=070C, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4239 Entering DREAD state...
4240 Dest read address/pix address: 00197280/0 [0008001800180018]
4241 Entering DWRITE state...
4242 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)
4243 Entering A1_ADD state [a1_x=0050, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4244 Entering SREAD state... Source read address/pix address: 0010C0C8/0 [000078047BFE7BFE]
4245 Entering A2_ADD state [a2_x=0710, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4246 Entering DREAD state...
4247 Dest read address/pix address: 001972A0/0 [0008002000000000]
4248 Entering DWRITE state...
4249 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)
4250 Entering A1_ADD state [a1_x=0054, a1_y=00D8, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4251 Entering IDLE_INNER state...
4252 */
4253
4254 //Why isn't this taken care of in DATA? Because, DATA is modifying its local copy instead of the one used here.
4255 //!!! FIX !!! [DONE]
4256 //if (patdadd)
4257 // patd = wdata;
4258
4259 //if (patfadd)
4260 // srcd1 = wdata;
4261
4262 /*
4263 DEF ADDRCOMP (
4264 a1_outside // A1 pointer is outside window bounds
4265 :OUT;
4266 INT16/ a1_x
4267 INT16/ a1_y
4268 INT15/ a1_win_x
4269 INT15/ a1_win_y
4270 :IN);
4271 BEGIN
4272
4273 // The address is outside if negative, or if greater than or equal
4274 // to the window size
4275
4276 A1_xcomp := MAG_15 (a1xgr, a1xeq, a1xlt, a1_x{0..14}, a1_win_x{0..14});
4277 A1_ycomp := MAG_15 (a1ygr, a1yeq, a1ylt, a1_y{0..14}, a1_win_y{0..14});
4278 A1_outside := OR6 (a1_outside, a1_x{15}, a1xgr, a1xeq, a1_y{15}, a1ygr, a1yeq);
4279 */
4280 //NOTE: There seems to be an off-by-one bug here in the clip_a1 section... !!! FIX !!!
4281 // Actually, seems to be related to phrase mode writes...
4282 // Or is it? Could be related to non-15-bit compares as above?
4283 if (clip_a1 && ((a1_x & 0x8000) || (a1_y & 0x8000) || (a1_x >= a1_win_x) || (a1_y >= a1_win_y)))
4284 winhibit = true;
4285
4286 if (!winhibit)
4287 {
4288 if (phrase_mode)
4289 {
4290 JaguarWriteLong(address + 0, wdata >> 32, BLITTER);
4291 JaguarWriteLong(address + 4, wdata & 0xFFFFFFFF, BLITTER);
4292 }
4293 else
4294 {
4295 if (pixsize == 5)
4296 JaguarWriteLong(address, wdata & 0xFFFFFFFF, BLITTER);
4297 else if (pixsize == 4)
4298 JaguarWriteWord(address, wdata & 0x0000FFFF, BLITTER);
4299 else
4300 JaguarWriteByte(address, wdata & 0x000000FF, BLITTER);
4301 }
4302 }
4303
4304 #ifdef VERBOSE_BLITTER_LOGGING
4305 if (logBlit)
4306 {
4307 WriteLog(" [%08X%08X]%s", (uint32_t)(wdata >> 32), (uint32_t)(wdata & 0xFFFFFFFF), (winhibit ? "[X]" : ""));
4308 WriteLog(" (icount=%04X, inc=%u)\n", icount, (uint16_t)inc);
4309 WriteLog(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4310 WriteLog("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4311 }
4312 #endif
4313 }
4314
4315 if (dzwrite)
4316 {
4317 // OK, here's the big insight: When NOT in GOURZ mode, srcz1 & 2 function EXACTLY the same way that
4318 // srcd1 & 2 work--there's an implicit shift from srcz1 to srcz2 whenever srcz1 is read.
4319 // OTHERWISE, srcz1 is the integer for the computed Z and srcz2 is the fractional part.
4320 // Writes to srcz1 & 2 follow the same pattern as the other 64-bit registers--low 32 at the low address,
4321 // high 32 at the high address (little endian!).
4322 // NOTE: GOURZ is still not properly supported. Check patd/patf handling...
4323 // Phrase mode start/end masks are not properly supported either...
4324 #ifdef VERBOSE_BLITTER_LOGGING
4325 if (logBlit)
4326 {
4327 WriteLog(" Entering DZWRITE state...");
4328 WriteLog(" Dest Z write address/pix address: %08X/%1X [%08X%08X]\n", address,
4329 pixAddr, (uint32_t)(srcz >> 32), (uint32_t)(srcz & 0xFFFFFFFF));
4330 }
4331 #endif
4332 //This is not correct... !!! FIX !!!
4333 //Should be OK now... We'll see...
4334 //Nope. Having the same starstep write problems in phrase mode as we had with pixels... !!! FIX !!!
4335 //This is not causing the problem in Hover Strike... :-/
4336 //The problem was with the SREADX not shifting. Still problems with Z comparisons & other text in pregame screen...
4337 if (!winhibit)
4338 {
4339 if (phrase_mode)
4340 {
4341 JaguarWriteLong(address + 0, srcz >> 32, BLITTER);
4342 JaguarWriteLong(address + 4, srcz & 0xFFFFFFFF, BLITTER);
4343 }
4344 else
4345 {
4346 if (pixsize == 4)
4347 JaguarWriteWord(address, srcz & 0x0000FFFF, BLITTER);
4348 }
4349 }//*/
4350 #ifdef VERBOSE_BLITTER_LOGGING
4351 if (logBlit)
4352 {
4353 // printf(" [%08X%08X]\n", (uint32_t)(srcz >> 32), (uint32_t)(srcz & 0xFFFFFFFF));
4354 // fflush(stdout);
4355 //printf(" [dstart=%X dend=%X pwidth=%X srcshift=%X]", dstart, dend, pwidth, srcshift);
4356 WriteLog(" [dstart=? dend=? pwidth=? srcshift=%X]", srcshift);
4357 WriteLog("[daas=%X dabs=%X dam=%X ds=%X daq=%s]\n", daddasel, daddbsel, daddmode, data_sel, (daddq_sel ? "T" : "F"));
4358 // fflush(stdout);
4359 }
4360 #endif
4361 }
4362
4363 /*
4364 This is because the address generator was using only 15 bits of the X when it should have
4365 used 16!
4366
4367 There's a slight problem here: The X pointer isn't wrapping like it should when it hits
4368 the edge of the window... Notice how the X isn't reset at the edge of the window:
4369
4370 Blit! (CMD = 00010000)
4371 Flags: PATDSEL
4372 count = 160 x 261
4373 a1_base = 000E8008, a2_base = 0001FA68
4374 a1_x = 0000, a1_y = 0000, a1_frac_x = 0000, a1_frac_y = 0000, a2_x = 0000, a2_y = 0000
4375 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 0000, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4376 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4377 a1_win_x = 0000, a1_win_y = 0000, a2_mask_x = 0000, a2_mask_y = 0000
4378 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4379 a1_pixsize = 5, a2_pixsize = 5
4380 srcd=7717771777177717 dstd=0000000000000000 patd=7730773077307730 iinc=00000000
4381 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4382 Phrase mode is ON
4383 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4384 Entering INNER state...
4385 Entering DWRITE state... Dest write address/pix address: 000E8008/0 [7730773077307730] (icount=009E, inc=2)
4386 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4387 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4388 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4389 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4390 Entering DWRITE state... Dest write address/pix address: 000E8018/0 [7730773077307730] (icount=009C, inc=2)
4391 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4392 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4393 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4394 Entering A1_ADD state [a1_x=0002, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4395
4396 ...
4397
4398 Entering A1_ADD state [a1_x=009C, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4399 Entering DWRITE state... Dest write address/pix address: 000E84F8/0 [7730773077307730] (icount=0000, inc=2)
4400 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4401 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4402 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4403 Entering A1_ADD state [a1_x=009E, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4404 Entering IDLE_INNER state...
4405
4406 Leaving INNER state... (ocount=0104)
4407 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4408
4409 Entering INNER state...
4410 Entering DWRITE state... Dest write address/pix address: 000E8508/0 [7730773077307730] (icount=009E, inc=2)
4411 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4412 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4413 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4414 Entering A1_ADD state [a1_x=00A0, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4415 Entering DWRITE state... Dest write address/pix address: 000E8518/0 [7730773077307730] (icount=009C, inc=2)
4416 srcz=0000000000000000][dcomp=AA zcomp=00 dbinh=00]
4417 [srcz=0000000000000000 dstz=0000000000000000 zwdata=0000000000000000 mask=7FFF]
4418 [dstart=0 dend=40 pwidth=8 srcshift=0][daas=0 dabs=0 dam=7 ds=0 daq=F]
4419 Entering A1_ADD state [a1_x=00A2, a1_y=0000, addasel=0, addbsel=0, modx=1, addareg=F, adda_xconst=1, adda_yconst=0]...
4420
4421 */
4422
4423 if (a1_add)
4424 {
4425 #ifdef VERBOSE_BLITTER_LOGGING
4426 if (logBlit)
4427 {
4428 //printf(" Entering A1_ADD state [addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
4429 WriteLog(" 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"));
4430 //fflush(stdout);
4431 }
4432 #endif
4433 int16_t adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4434 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4435 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4436 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4437 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4438
4439 #if 0//def VERBOSE_BLITTER_LOGGING
4440 if (logBlit)
4441 {
4442 WriteLog(" [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);
4443 //fflush(stdout);
4444 }
4445 #endif
4446 //Now, write to what???
4447 //a2ptrld comes from a2ptrldi...
4448 //I believe it's addbsel that determines the writeback...
4449 // This is where atick[0] & [1] come in, in determining which part (fractional, integer)
4450 // gets written to...
4451 //a1_x = addq_x;
4452 //a1_y = addq_y;
4453 //Kludge, to get A1 channel increment working...
4454 if (a1addx == 3)
4455 {
4456 a1_frac_x = addq_x, a1_frac_y = addq_y;
4457
4458 addasel = 2, addbsel = 0, a1fracldi = false;
4459 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4460 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4461 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4462 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4463
4464 a1_x = addq_x, a1_y = addq_y;
4465 }
4466 else
4467 a1_x = addq_x, a1_y = addq_y;
4468 }
4469
4470 if (a2_add)
4471 {
4472 #ifdef VERBOSE_BLITTER_LOGGING
4473 if (logBlit)
4474 {
4475 //printf(" Entering A2_ADD state [addasel=%X, addbsel=%X, modx=%X, addareg=%s, adda_xconst=%u, adda_yconst=%s]...\n", addasel, addbsel, modx, (addareg ? "T" : "F"), adda_xconst, (adda_yconst ? "1" : "0"));
4476 WriteLog(" 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"));
4477 //fflush(stdout);
4478 }
4479 #endif
4480 //void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y,
4481 // int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y,
4482 // int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst,
4483 // bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
4484 //void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y,
4485 // int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y)
4486 //void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
4487 // int16_t adda_x, int16_t adda_y, int16_t addb_x, int16_t addb_y, uint8_t modx, bool suba_x, bool suba_y)
4488 //void DATAMUX(int16_t &data_x, int16_t &data_y, uint32_t gpu_din, int16_t addq_x, int16_t addq_y, bool addqsel)
4489 int16_t adda_x, adda_y, addb_x, addb_y, data_x, data_y, addq_x, addq_y;
4490 ADDAMUX(adda_x, adda_y, addasel, a1_step_x, a1_step_y, a1_stepf_x, a1_stepf_y, a2_step_x, a2_step_y,
4491 a1_inc_x, a1_inc_y, a1_incf_x, a1_incf_y, adda_xconst, adda_yconst, addareg, suba_x, suba_y);
4492 ADDBMUX(addb_x, addb_y, addbsel, a1_x, a1_y, a2_x, a2_y, a1_frac_x, a1_frac_y);
4493 ADDRADD(addq_x, addq_y, a1fracldi, adda_x, adda_y, addb_x, addb_y, modx, suba_x, suba_y);
4494
4495 #if 0//def VERBOSE_BLITTER_LOGGING
4496 if (logBlit)
4497 {
4498 WriteLog(" [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);
4499 //fflush(stdout);
4500 }
4501 #endif
4502 //Now, write to what???
4503 //a2ptrld comes from a2ptrldi...
4504 //I believe it's addbsel that determines the writeback...
4505 a2_x = addq_x;
4506 a2_y = addq_y;
4507 }
4508 }
4509 /*
4510 Flags: SRCEN CLIP_A1 UPDA1 UPDA1F UPDA2 DSTA2 GOURZ ZMODE=0 LFUFUNC=C SRCSHADE
4511 count = 64 x 55
4512 a1_base = 0015B000, a2_base = 0014B000
4513 a1_x = 0000, a1_y = 0000, a1_frac_x = 8000, a1_frac_y = 8000, a2_x = 001F, a2_y = 0038
4514 a1_step_x = FFFFFFC0, a1_step_y = 0001, a1_stepf_x = 0000, a1_stepf_y = 2AAA, a2_step_x = FFFFFFC0, a2_step_y = 0001
4515 a1_inc_x = 0001, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4516 a1_win_x = 0040, a1_win_y = 0040, a2_mask_x = 0000, a2_mask_y = 0000
4517 a2_mask=F a1add=+inc/+0 a2add=+1/+0
4518 a1_pixsize = 4, a2_pixsize = 4
4519 srcd=FF00FF00FF00FF00 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4520 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, col=0
4521 Phrase mode is off
4522 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4523 Entering INNER state...
4524 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4525 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4526 Entering DWRITE state...
4527 Dest write address/pix address: 0014E83E/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003F, inc=1)
4528 Entering A2_ADD state [a2_x=001F, a2_y=0038, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4529 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4530 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4531 Entering DWRITE state...
4532 Dest write address/pix address: 0014E942/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003E, inc=1)
4533 Entering A2_ADD state [a2_x=0021, a2_y=0039, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4534 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4535 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4536 Entering DWRITE state...
4537 Dest write address/pix address: 0014EA46/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003D, inc=1)
4538 Entering A2_ADD state [a2_x=0023, a2_y=003A, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4539 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4540 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4541 Entering DWRITE state...
4542 Dest write address/pix address: 0014EB4A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=003C, inc=1)
4543 Entering A2_ADD state [a2_x=0025, a2_y=003B, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4544 ...
4545 Entering SREAD state... Source read address/pix address: 0015B000/0 [6505650565056505]
4546 Entering A1_ADD state [a1_x=FFFF8000, a1_y=FFFF8000, addasel=3, addbsel=2, modx=0, addareg=T, adda_xconst=7, adda_yconst=0]...
4547 Entering DWRITE state...
4548 Dest write address/pix address: 0015283A/0 [dstart=0 dend=10 pwidth=8 srcshift=0][daas=4 dabs=5 dam=7 ds=1 daq=F] [0000000000006505] (icount=0000, inc=1)
4549 Entering A2_ADD state [a2_x=009D, a2_y=0077, addasel=0, addbsel=1, modx=0, addareg=F, adda_xconst=0, adda_yconst=0]...
4550 Entering IDLE_INNER state...
4551 Leaving INNER state... (ocount=0036)
4552 [in=F a1f=T a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4553 Entering A1FUPDATE state...
4554 [in=F a1f=F a1=T zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4555 Entering A1UPDATE state... (-32768/-32768 -> 32704/-32767)
4556 [in=F a1f=F a1=F zf=F z=F a2=T iif=F iii=F izf=F izi=F]
4557 Entering A2UPDATE state... (159/120 -> 95/121)
4558 [in=T a1f=F a1=F zf=F z=F a2=F iif=F iii=F izf=F izi=F]
4559 Entering INNER state...
4560 */
4561
4562 #ifdef VERBOSE_BLITTER_LOGGING
4563 if (logBlit)
4564 {
4565 WriteLog(" Leaving INNER state...");
4566 //fflush(stdout);
4567 }
4568 #endif
4569 indone = true;
4570 // The outer counter is updated here as well on the clock cycle...
4571
4572 /* the inner loop is started whenever another state is about to
4573 cause the inner state to go active */
4574 //Instart := ND7 (instart, innert[0], innert[2..7]);
4575
4576 //Actually, it's done only when inner gets asserted without the 2nd line of conditions
4577 //(inner AND !indone)
4578 //fixed now...
4579 //Since we don't get here until the inner loop is finished (indone = true) we can get
4580 //away with doing it here...!
4581 ocount--;
4582
4583 if (ocount == 0)
4584 outer0 = true;
4585 #ifdef VERBOSE_BLITTER_LOGGING
4586 if (logBlit)
4587 {
4588 WriteLog(" (ocount=%04X)\n", ocount);
4589 //fflush(stdout);
4590 }
4591 #endif
4592 }
4593
4594 if (a1fupdate)
4595 {
4596 #ifdef VERBOSE_BLITTER_LOGGING
4597 if (logBlit)
4598 {
4599 WriteLog(" Entering A1FUPDATE state...\n");
4600 //fflush(stdout);
4601 }
4602 #endif
4603 uint32_t a1_frac_xt = (uint32_t)a1_frac_x + (uint32_t)a1_stepf_x;
4604 uint32_t a1_frac_yt = (uint32_t)a1_frac_y + (uint32_t)a1_stepf_y;
4605 a1FracCInX = a1_frac_xt >> 16;
4606 a1FracCInY = a1_frac_yt >> 16;
4607 a1_frac_x = (uint16_t)(a1_frac_xt & 0xFFFF);
4608 a1_frac_y = (uint16_t)(a1_frac_yt & 0xFFFF);
4609 }
4610
4611 if (a1update)
4612 {
4613 #ifdef VERBOSE_BLITTER_LOGGING
4614 if (logBlit)
4615 {
4616 WriteLog(" Entering A1UPDATE state... (%d/%d -> ", a1_x, a1_y);
4617 //fflush(stdout);
4618 }
4619 #endif
4620 a1_x += a1_step_x + a1FracCInX;
4621 a1_y += a1_step_y + a1FracCInY;
4622 #ifdef VERBOSE_BLITTER_LOGGING
4623 if (logBlit)
4624 {
4625 WriteLog("%d/%d)\n", a1_x, a1_y);
4626 //fflush(stdout);
4627 }
4628 #endif
4629 }
4630
4631 if (a2update)
4632 {
4633 #ifdef VERBOSE_BLITTER_LOGGING
4634 if (logBlit)
4635 {
4636 WriteLog(" Entering A2UPDATE state... (%d/%d -> ", a2_x, a2_y);
4637 //fflush(stdout);
4638 }
4639 #endif
4640 a2_x += a2_step_x;
4641 a2_y += a2_step_y;
4642 #ifdef VERBOSE_BLITTER_LOGGING
4643 if (logBlit)
4644 {
4645 WriteLog("%d/%d)\n", a2_x, a2_y);
4646 //fflush(stdout);
4647 }
4648 #endif
4649 }
4650 }
4651
4652 // We never get here! !!! FIX !!!
4653
4654 #ifdef VERBOSE_BLITTER_LOGGING
4655 if (logBlit)
4656 {
4657 WriteLog("Done!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
4658 GET16(blitter_ram, A1_PIXEL + 2),
4659 GET16(blitter_ram, A1_PIXEL + 0),
4660 GET16(blitter_ram, A1_FPIXEL + 2),
4661 GET16(blitter_ram, A1_FPIXEL + 0),
4662 GET16(blitter_ram, A2_PIXEL + 2),
4663 GET16(blitter_ram, A2_PIXEL + 0));
4664 // fflush(stdout);
4665 }
4666 #endif
4667
4668 // Write values back to registers (in real blitter, these are continuously updated)
4669 SET16(blitter_ram, A1_PIXEL + 2, a1_x);
4670 SET16(blitter_ram, A1_PIXEL + 0, a1_y);
4671 SET16(blitter_ram, A1_FPIXEL + 2, a1_frac_x);
4672 SET16(blitter_ram, A1_FPIXEL + 0, a1_frac_y);
4673 SET16(blitter_ram, A2_PIXEL + 2, a2_x);
4674 SET16(blitter_ram, A2_PIXEL + 0, a2_y);
4675
4676 #ifdef VERBOSE_BLITTER_LOGGING
4677 if (logBlit)
4678 {
4679 WriteLog("Writeback!\na1_x=%04X a1_y=%04X a1_frac_x=%04X a1_frac_y=%04X a2_x=%04X a2_y%04X\n",
4680 GET16(blitter_ram, A1_PIXEL + 2),
4681 GET16(blitter_ram, A1_PIXEL + 0),
4682 GET16(blitter_ram, A1_FPIXEL + 2),
4683 GET16(blitter_ram, A1_FPIXEL + 0),
4684 GET16(blitter_ram, A2_PIXEL + 2),
4685 GET16(blitter_ram, A2_PIXEL + 0));
4686 // fflush(stdout);
4687 }
4688 #endif
4689 }
4690
4691
4692 /*
4693 int16_t a1_x = (int16_t)GET16(blitter_ram, A1_PIXEL + 2);
4694 int16_t a1_y = (int16_t)GET16(blitter_ram, A1_PIXEL + 0);
4695 uint16_t a1_frac_x = GET16(blitter_ram, A1_FPIXEL + 2);
4696 uint16_t a1_frac_y = GET16(blitter_ram, A1_FPIXEL + 0);
4697 int16_t a2_x = (int16_t)GET16(blitter_ram, A2_PIXEL + 2);
4698 int16_t a2_y = (int16_t)GET16(blitter_ram, A2_PIXEL + 0);
4699
4700 Seems that the ending a1_x should be written between blits, but it doesn't seem to be...
4701
4702 Blit! (CMD = 01800000)
4703 Flags: LFUFUNC=C
4704 count = 28672 x 1
4705 a1_base = 00050000, a2_base = 00070000
4706 a1_x = 0000, a1_y = 0000, a1_frac_x = 49CD, a1_frac_y = 0000, a2_x = 0033, a2_y = 0001
4707 a1_step_x = 0000, a1_step_y = 0000, a1_stepf_x = 939A, a1_stepf_y = 0000, a2_step_x = 0000, a2_step_y = 0000
4708 a1_inc_x = 0000, a1_inc_y = 0000, a1_incf_x = 0000, a1_incf_y = 0000
4709 a1_win_x = 0100, a1_win_y = 0020, a2_mask_x = 0000, a2_mask_y = 0000
4710 a2_mask=F a1add=+phr/+0 a2add=+phr/+0
4711 a1_pixsize = 4, a2_pixsize = 3
4712 srcd=DEDEDEDEDEDEDEDE dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4713 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4714 Phrase mode is ON
4715
4716 Blit! (CMD = 01800000)
4717 Flags: LFUFUNC=C
4718 count = 28672 x 1
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=D6D6D6D6D6D6D6D6 dstd=0000000000000000 patd=0000000000000000 iinc=00000000
4727 srcz1=0000000000000000 srcz2=0000000000000000 dstz=0000000000000000 zinc=00000000, coll=0
4728 Phrase mode is ON
4729 */
4730
4731
4732
4733 // Various pieces of the blitter puzzle are teased out here...
4734
4735
4736
4737 /*
4738 DEF ADDRGEN (
4739 INT24/ address // byte address
4740 pixa[0..2] // bit part of address, un-pipe-lined
4741 :OUT;
4742 INT16/ a1_x
4743 INT16/ a1_y
4744 INT21/ a1_base
4745 a1_pitch[0..1]
4746 a1_pixsize[0..2]
4747 a1_width[0..5]
4748 a1_zoffset[0..1]
4749 INT16/ a2_x
4750 INT16/ a2_y
4751 INT21/ a2_base
4752 a2_pitch[0..1]
4753 a2_pixsize[0..2]
4754 a2_width[0..5]
4755 a2_zoffset[0..1]
4756 apipe // load address pipe-line latch
4757 clk // co-processor clock
4758 gena2 // generate A2 as opposed to A1
4759 zaddr // generate Z address
4760 :IN);
4761 */
4762
4763 void ADDRGEN(uint32_t &address, uint32_t &pixa, bool gena2, bool zaddr,
4764 uint16_t a1_x, uint16_t a1_y, uint32_t a1_base, uint8_t a1_pitch, uint8_t a1_pixsize, uint8_t a1_width, uint8_t a1_zoffset,
4765 uint16_t a2_x, uint16_t a2_y, uint32_t a2_base, uint8_t a2_pitch, uint8_t a2_pixsize, uint8_t a2_width, uint8_t a2_zoffset)
4766 {
4767 // uint16_t x = (gena2 ? a2_x : a1_x) & 0x7FFF;
4768 uint16_t x = (gena2 ? a2_x : a1_x) & 0xFFFF; // Actually uses all 16 bits to generate address...!
4769 uint16_t y = (gena2 ? a2_y : a1_y) & 0x0FFF;
4770 uint8_t width = (gena2 ? a2_width : a1_width);
4771 uint8_t pixsize = (gena2 ? a2_pixsize : a1_pixsize);
4772 uint8_t pitch = (gena2 ? a2_pitch : a1_pitch);
4773 uint32_t base = (gena2 ? a2_base : a1_base) >> 3;//Only upper 21 bits are passed around the bus? Seems like it...
4774 uint8_t zoffset = (gena2 ? a2_zoffset : a1_zoffset);
4775
4776 uint32_t ytm = ((uint32_t)y << 2) + (width & 0x02 ? (uint32_t)y << 1 : 0) + (width & 0x01 ? (uint32_t)y : 0);
4777
4778 uint32_t ya = (ytm << (width >> 2)) >> 2;
4779
4780 uint32_t pa = ya + x;
4781
4782 /*uint32*/ pixa = pa << pixsize;
4783
4784 uint8_t pt = ((pitch & 0x01) && !(pitch & 0x02) ? 0x01 : 0x00)
4785 | (!(pitch & 0x01) && (pitch & 0x02) ? 0x02 : 0x00);
4786 // uint32_t phradr = pixa << pt;
4787 uint32_t phradr = (pixa >> 6) << pt;
4788 uint32_t shup = (pitch == 0x03 ? (pixa >> 6) : 0);
4789
4790 uint8_t za = (zaddr ? zoffset : 0) & 0x03;
4791 // uint32_t addr = za + (phradr & 0x07) + (shup << 1) + base;
4792 uint32_t addr = za + phradr + (shup << 1) + base;
4793 /*uint32*/ address = ((pixa & 0x38) >> 3) | ((addr & 0x1FFFFF) << 3);
4794 #if 0//def VERBOSE_BLITTER_LOGGING
4795 if (logBlit)
4796 {
4797 WriteLog(" [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);
4798 WriteLog(" [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);
4799 //fflush(stdout);
4800 }
4801 #endif
4802 pixa &= 0x07;
4803 /*
4804 Entering INNER state...
4805 [gena2=T, x=0002, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4806 [ytm=0, ya=0, pa=2, pixa=20, pt=0, phradr=0, shup=0, za=0, addr=12BA, address=95D4]
4807 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4808 Source extra read address/pix address: 000095D4/0 [0000001C00540038]
4809 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4810 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4811 [ytm=0, ya=0, pa=4, pixa=40, pt=0, phradr=1, shup=0, za=0, addr=12BB, address=95D8]
4812 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4813 Source read address/pix address: 000095D8/0 [0054003800009814]
4814 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4815 [gena2=F, x=0000, y=0000, w=20, pxsz=4, ptch=0, b=00006E52, zoff=0]
4816 [ytm=0, ya=0, pa=0, pixa=0, pt=0, phradr=0, shup=0, za=0, addr=6E52, address=37290]
4817 Entering DWRITE state...
4818 Dest write address/pix address: 00037290/0 [dstart=0 dend=20 pwidth=8 srcshift=0] (icount=026E, inc=4)
4819 Entering A1_ADD state [a1_x=0000, a1_y=0000, addasel=0, addbsel=0, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4820 [gena2=T, x=0008, y=0000, w=20, pxsz=4, ptch=0, b=000012BA, zoff=0]
4821 [ytm=0, ya=0, pa=8, pixa=80, pt=0, phradr=2, shup=0, za=0, addr=12BC, address=95E0]
4822 */
4823 /*
4824 Obviously wrong:
4825 Entering SREAD state...
4826 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4827 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10AC, address=8560]
4828 Source read address/pix address: 00008560/0 [8C27981B327E00F0]
4829
4830 2nd pass (still wrong):
4831 Entering SREAD state...
4832 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4833 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=40, shup=0, za=0, addr=10EC, address=8760]
4834 Source read address/pix address: 00008760/0 [00E06DC04581880C]
4835
4836 Correct!:
4837 Entering SREAD state...
4838 [gena2=T, x=0004, y=0000, w=20, pxsz=4, ptch=0, b=000010AC, zoff=0]
4839 [ytm=0, ya=0, pa=4, pixa=0, pt=0, phradr=1, shup=0, za=0, addr=10AD, address=8568]
4840 Source read address/pix address: 00008568/0 [6267981A327C00F0]
4841
4842 OK, now we're back into incorrect (or is it?):
4843 Entering SREADX state... [dstart=0 dend=20 pwidth=8 srcshift=20]
4844 Source extra read address/pix address: 000095D4/0 [0000 001C 0054 0038]
4845 Entering A2_ADD state [a2_x=0002, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4846 Entering SREAD state... [dstart=0 dend=20 pwidth=8 srcshift=0]
4847 Source read address/pix address: 000095D8/0 [0054 0038 0000 9814]
4848 Entering A2_ADD state [a2_x=0004, a2_y=0000, addasel=0, addbsel=1, modx=2, addareg=F, adda_xconst=2, adda_yconst=0]...
4849 I think this may be correct...!
4850 */
4851 }
4852
4853 /*
4854 // source and destination address update conditions
4855
4856 Sraat0 := AN2 (sraat[0], sreadxi, srcenz\);
4857 Sraat1 := AN2 (sraat[1], sreadi, srcenz\);
4858 Srca_addi := OR4 (srca_addi, szreadxi, szreadi, sraat[0..1]);
4859 Srca_add := FD1Q (srca_add, srca_addi, clk);
4860
4861 Dstaat := AN2 (dstaat, dwritei, dstwrz\);
4862 Dsta_addi := OR2 (dsta_addi, dzwritei, dstaat);
4863 // Dsta_add := FD1Q (dsta_add, dsta_addi, clk);
4864
4865 // source and destination address generate conditions
4866
4867 Gensrc := OR4 (gensrc, sreadxi, szreadxi, sreadi, szreadi);
4868 Gendst := OR4 (gendst, dreadi, dzreadi, dwritei, dzwritei);
4869 Dsta2\ := INV1 (dsta2\, dsta2);
4870 Gena2t0 := NAN2 (gena2t[0], gensrc, dsta2\);
4871 Gena2t1 := NAN2 (gena2t[1], gendst, dsta2);
4872 Gena2i := NAN2 (gena2i, gena2t[0..1]);
4873 Gena2 := FD1QU (gena2, gena2i, clk);
4874
4875 Zaddr := OR4 (zaddr, szreadx, szread, dzread, dzwrite);
4876 */
4877
4878 /*void foo(void)
4879 {
4880 // Basically, the above translates to:
4881 bool srca_addi = (sreadxi && !srcenz) || (sreadi && !srcenz) || szreadxi || szreadi;
4882
4883 bool dsta_addi = (dwritei && !dstwrz) || dzwritei;
4884
4885 bool gensrc = sreadxi || szreadxi || sreadi || szreadi;
4886 bool gendst = dreadi || szreadi || dwritei || dzwritei;
4887 bool gena2i = (gensrc && !dsta2) || (gendst && dsta2);
4888
4889 bool zaddr = szreadx || szread || dzread || dzwrite;
4890 }*/
4891
4892 /*
4893 // source data reads
4894
4895 Srcdpset\ := NAN2 (srcdpset\, readreq, sread);
4896 Srcdpt1 := NAN2 (srcdpt[1], srcdpend, srcdack\);
4897 Srcdpt2 := NAN2 (srcdpt[2], srcdpset\, srcdpt[1]);
4898 Srcdpend := FD2Q (srcdpend, srcdpt[2], clk, reset\);
4899
4900 Srcdxpset\ := NAN2 (srcdxpset\, readreq, sreadx);
4901 Srcdxpt1 := NAN2 (srcdxpt[1], srcdxpend, srcdxack\);
4902 Srcdxpt2 := NAN2 (srcdxpt[2], srcdxpset\, srcdxpt[1]);
4903 Srcdxpend := FD2Q (srcdxpend, srcdxpt[2], clk, reset\);
4904
4905 Sdpend := OR2 (sdpend, srcdxpend, srcdpend);
4906 Srcdreadt := AN2 (srcdreadt, sdpend, read_ack);
4907
4908 //2/9/92 - enhancement?
4909 //Load srcdread on the next tick as well to modify it in srcshade
4910
4911 Srcdreadd := FD1Q (srcdreadd, srcdreadt, clk);
4912 Srcdread := AOR1 (srcdread, srcshade, srcdreadd, srcdreadt);
4913
4914 // source zed reads
4915
4916 Srczpset\ := NAN2 (srczpset\, readreq, szread);
4917 Srczpt1 := NAN2 (srczpt[1], srczpend, srczack\);
4918 Srczpt2 := NAN2 (srczpt[2], srczpset\, srczpt[1]);
4919 Srczpend := FD2Q (srczpend, srczpt[2], clk, reset\);
4920
4921 Srczxpset\ := NAN2 (srczxpset\, readreq, szreadx);
4922 Srczxpt1 := NAN2 (srczxpt[1], srczxpend, srczxack\);
4923 Srczxpt2 := NAN2 (srczxpt[2], srczxpset\, srczxpt[1]);
4924 Srczxpend := FD2Q (srczxpend, srczxpt[2], clk, reset\);
4925
4926 Szpend := OR2 (szpend, srczpend, srczxpend);
4927 Srczread := AN2 (srczread, szpend, read_ack);
4928
4929 // destination data reads
4930
4931 Dstdpset\ := NAN2 (dstdpset\, readreq, dread);
4932 Dstdpt0 := NAN2 (dstdpt[0], dstdpend, dstdack\);
4933 Dstdpt1 := NAN2 (dstdpt[1], dstdpset\, dstdpt[0]);
4934 Dstdpend := FD2Q (dstdpend, dstdpt[1], clk, reset\);
4935 Dstdread := AN2 (dstdread, dstdpend, read_ack);
4936
4937 // destination zed reads
4938
4939 Dstzpset\ := NAN2 (dstzpset\, readreq, dzread);
4940 Dstzpt0 := NAN2 (dstzpt[0], dstzpend, dstzack\);
4941 Dstzpt1 := NAN2 (dstzpt[1], dstzpset\, dstzpt[0]);
4942 Dstzpend := FD2Q (dstzpend, dstzpt[1], clk, reset\);
4943 Dstzread := AN2 (dstzread, dstzpend, read_ack);
4944 */
4945
4946 /*void foo2(void)
4947 {
4948 // Basically, the above translates to:
4949 bool srcdpend = (readreq && sread) || (srcdpend && !srcdack);
4950 bool srcdxpend = (readreq && sreadx) || (srcdxpend && !srcdxack);
4951 bool sdpend = srcxpend || srcdpend;
4952 bool srcdread = ((sdpend && read_ack) && srcshade) || (sdpend && read_ack);//the latter term is lookahead
4953
4954 }*/
4955
4956
4957 ////////////////////////////////////////////////////////////////////////////////////////////
4958 ////////////////////////////////////////////////////////////////////////////////////////////
4959 // Here's an important bit: The source data adder logic. Need to track down the inputs!!! //
4960 ////////////////////////////////////////////////////////////////////////////////////////////
4961 ////////////////////////////////////////////////////////////////////////////////////////////
4962
4963 /*
4964 DEF ADDARRAY (
4965 INT16/ addq[0..3]
4966 :OUT;
4967 clk
4968 daddasel[0..2] // data adder input A selection
4969 daddbsel[0..3]
4970 daddmode[0..2]
4971 INT32/ dstd[0..1]
4972 INT32/ iinc
4973 initcin[0..3] // carry into the adders from the initializers
4974 initinc[0..63] // the initialisation increment
4975 initpix[0..15] // Data initialiser pixel value
4976 INT32/ istep
4977 INT32/ patd[0..1]
4978 INT32/ srcdlo
4979 INT32/ srcdhi
4980 INT32/ srcz1[0..1]
4981 INT32/ srcz2[0..1]
4982 reset\
4983 INT32/ zinc
4984 INT32/ zstep
4985 :IN);
4986 */
4987 void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
4988 uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
4989 uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
4990 uint32_t zinc, uint32_t zstep)
4991 {
4992 uint32_t initpix2 = ((uint32_t)initpix << 16) | initpix;
4993 uint32_t addalo[8], addahi[8];
4994 addalo[0] = dstd & 0xFFFFFFFF;
4995 addalo[1] = initpix2;
4996 addalo[2] = 0;
4997 addalo[3] = 0;
4998 addalo[4] = srcd & 0xFFFFFFFF;
4999 addalo[5] = patd & 0xFFFFFFFF;
5000 addalo[6] = srcz1 & 0xFFFFFFFF;
5001 addalo[7] = srcz2 & 0xFFFFFFFF;
5002 addahi[0] = dstd >> 32;
5003 addahi[1] = initpix2;
5004 addahi[2] = 0;
5005 addahi[3] = 0;
5006 addahi[4] = srcd >> 32;
5007 addahi[5] = patd >> 32;
5008 addahi[6] = srcz1 >> 32;
5009 addahi[7] = srcz2 >> 32;
5010 uint16_t adda[4];
5011 adda[0] = addalo[daddasel] & 0xFFFF;
5012 adda[1] = addalo[daddasel] >> 16;
5013 adda[2] = addahi[daddasel] & 0xFFFF;
5014 adda[3] = addahi[daddasel] >> 16;
5015
5016 uint16_t wordmux[8];
5017 wordmux[0] = iinc & 0xFFFF;
5018 wordmux[1] = iinc >> 16;
5019 wordmux[2] = zinc & 0xFFFF;
5020 wordmux[3] = zinc >> 16;;
5021 wordmux[4] = istep & 0xFFFF;
5022 wordmux[5] = istep >> 16;;
5023 wordmux[6] = zstep & 0xFFFF;
5024 wordmux[7] = zstep >> 16;;
5025 uint16_t word = wordmux[((daddbsel & 0x08) >> 1) | (daddbsel & 0x03)];
5026 uint16_t addb[4];
5027 bool dbsel2 = daddbsel & 0x04;
5028 bool iincsel = (daddbsel & 0x01) && !(daddbsel & 0x04);
5029
5030 if (!dbsel2 && !iincsel)
5031 addb[0] = srcd & 0xFFFF,
5032 addb[1] = (srcd >> 16) & 0xFFFF,
5033 addb[2] = (srcd >> 32) & 0xFFFF,
5034 addb[3] = (srcd >> 48) & 0xFFFF;
5035 else if (dbsel2 && !iincsel)
5036 addb[0] = addb[1] = addb[2] = addb[3] = word;
5037 else if (!dbsel2 && iincsel)
5038 addb[0] = initinc & 0xFFFF,
5039 addb[1] = (initinc >> 16) & 0xFFFF,
5040 addb[2] = (initinc >> 32) & 0xFFFF,
5041 addb[3] = (initinc >> 48) & 0xFFFF;
5042 else
5043 addb[0] = addb[1] = addb[2] = addb[3] = 0;
5044
5045 uint8_t cinsel = (daddmode >= 1 && daddmode <= 4 ? 1 : 0);
5046
5047 static uint8_t co[4];//These are preserved between calls...
5048 uint8_t cin[4];
5049
5050 for(int i=0; i<4; i++)
5051 cin[i] = initcin[i] | (co[i] & cinsel);
5052
5053 bool eightbit = daddmode & 0x02;
5054 bool sat = daddmode & 0x03;
5055 bool hicinh = ((daddmode & 0x03) == 0x03);
5056
5057 //Note that the carry out is saved between calls to this function...
5058 for(int i=0; i<4; i++)
5059 ADD16SAT(addq[i], co[i], adda[i], addb[i], cin[i], sat, eightbit, hicinh);
5060 }
5061
5062
5063 /*
5064 DEF ADD16SAT (
5065 INT16/ r // result
5066 co // carry out
5067 :IO;
5068 INT16/ a
5069 INT16/ b
5070 cin
5071 sat
5072 eightbit
5073 hicinh
5074 :IN);
5075 */
5076 void ADD16SAT(uint16_t &r, uint8_t &co, uint16_t a, uint16_t b, uint8_t cin, bool sat, bool eightbit, bool hicinh)
5077 {
5078 /*if (logBlit)
5079 {
5080 printf("--> [sat=%s 8b=%s hicinh=%s] %04X + %04X (+ %u) = ", (sat ? "T" : "F"), (eightbit ? "T" : "F"), (hicinh ? "T" : "F"), a, b, cin);
5081 fflush(stdout);
5082 }*/
5083 uint8_t carry[4];
5084 uint32_t qt = (a & 0xFF) + (b & 0xFF) + cin;
5085 carry[0] = (qt & 0x0100 ? 1 : 0);
5086 uint16_t q = qt & 0x00FF;
5087 carry[1] = (carry[0] && !eightbit ? carry[0] : 0);
5088 qt = (a & 0x0F00) + (b & 0x0F00) + (carry[1] << 8);
5089 carry[2] = (qt & 0x1000 ? 1 : 0);
5090 q |= qt & 0x0F00;
5091 carry[3] = (carry[2] && !hicinh ? carry[2] : 0);
5092 qt = (a & 0xF000) + (b & 0xF000) + (carry[3] << 12);
5093 co = (qt & 0x10000 ? 1 : 0);
5094 q |= qt & 0xF000;
5095
5096 uint8_t btop = (eightbit ? (b & 0x0080) >> 7 : (b & 0x8000) >> 15);
5097 uint8_t ctop = (eightbit ? carry[0] : co);
5098
5099 bool saturate = sat && (btop ^ ctop);
5100 bool hisaturate = saturate && !eightbit;
5101 /*if (logBlit)
5102 {
5103 printf("bt=%u ct=%u s=%u hs=%u] ", btop, ctop, saturate, hisaturate);
5104 fflush(stdout);
5105 }*/
5106
5107 r = (saturate ? (ctop ? 0x00FF : 0x0000) : q & 0x00FF);
5108 r |= (hisaturate ? (ctop ? 0xFF00 : 0x0000) : q & 0xFF00);
5109 /*if (logBlit)
5110 {
5111 printf("%04X (co=%u)\n", r, co);
5112 fflush(stdout);
5113 }*/
5114 }
5115
5116
5117 /** ADDAMUX - Address adder input A selection *******************
5118
5119 This module generates the data loaded into the address adder input A. This is
5120 the update value, and can be one of four registers : A1 step, A2 step, A1
5121 increment and A1 fraction. It can complement these values to perform
5122 subtraction, and it can generate constants to increment / decrement the window
5123 pointers.
5124
5125 addasel[0..2] select the register to add
5126
5127 000 A1 step integer part
5128 001 A1 step fraction part
5129 010 A1 increment integer part
5130 011 A1 increment fraction part
5131 100 A2 step
5132
5133 adda_xconst[0..2] generate a power of 2 in the range 1-64 or all zeroes when
5134 they are all 1.
5135
5136 addareg selects register value to be added as opposed to constant
5137 value.
5138
5139 suba_x, suba_y complement the X and Y values
5140
5141 */
5142
5143 /*
5144 DEF ADDAMUX (
5145 INT16/ adda_x
5146 INT16/ adda_y
5147 :OUT;
5148 addasel[0..2]
5149 INT16/ a1_step_x
5150 INT16/ a1_step_y
5151 INT16/ a1_stepf_x
5152 INT16/ a1_stepf_y
5153 INT16/ a2_step_x
5154 INT16/ a2_step_y
5155 INT16/ a1_inc_x
5156 INT16/ a1_inc_y
5157 INT16/ a1_incf_x
5158 INT16/ a1_incf_y
5159 adda_xconst[0..2]
5160 adda_yconst
5161 addareg
5162 suba_x
5163 suba_y :IN);
5164 */
5165 void ADDAMUX(int16_t &adda_x, int16_t &adda_y, uint8_t addasel, int16_t a1_step_x, int16_t a1_step_y,
5166 int16_t a1_stepf_x, int16_t a1_stepf_y, int16_t a2_step_x, int16_t a2_step_y,
5167 int16_t a1_inc_x, int16_t a1_inc_y, int16_t a1_incf_x, int16_t a1_incf_y, uint8_t adda_xconst,
5168 bool adda_yconst, bool addareg, bool suba_x, bool suba_y)
5169 {
5170
5171 /*INT16/ addac_x, addac_y, addar_x, addar_y, addart_x, addart_y,
5172 INT16/ addas_x, addas_y, suba_x16, suba_y16
5173 :LOCAL;
5174 BEGIN
5175
5176 Zero := TIE0 (zero);*/
5177
5178 /* Multiplex the register terms */
5179
5180 /*Addaselb[0-2] := BUF8 (addaselb[0-2], addasel[0-2]);
5181 Addart_x := MX4 (addart_x, a1_step_x, a1_stepf_x, a1_inc_x, a1_incf_x, addaselb[0..1]);
5182 Addar_x := MX2 (addar_x, addart_x, a2_step_x, addaselb[2]);
5183 Addart_y := MX4 (addart_y, a1_step_y, a1_stepf_y, a1_inc_y, a1_incf_y, addaselb[0..1]);
5184 Addar_y := MX2 (addar_y, addart_y, a2_step_y, addaselb[2]);*/
5185
5186 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5187 int16_t xterm[4], yterm[4];
5188 xterm[0] = a1_step_x, xterm[1] = a1_stepf_x, xterm[2] = a1_inc_x, xterm[3] = a1_incf_x;
5189 yterm[0] = a1_step_y, yterm[1] = a1_stepf_y, yterm[2] = a1_inc_y, yterm[3] = a1_incf_y;
5190 int16_t addar_x = (addasel & 0x04 ? a2_step_x : xterm[addasel & 0x03]);
5191 int16_t addar_y = (addasel & 0x04 ? a2_step_y : yterm[addasel & 0x03]);
5192 //////////////////////////////////////////////////////////////////////////////////////
5193
5194 /* Generate a constant value - this is a power of 2 in the range
5195 0-64, or zero. The control bits are adda_xconst[0..2], when they
5196 are all 1 the result is 0.
5197 Constants for Y can only be 0 or 1 */
5198
5199 /*Addac_xlo := D38H (addac_x[0..6], unused[0], adda_xconst[0..2]);
5200 Unused[0] := DUMMY (unused[0]);
5201
5202 Addac_x := JOIN (addac_x, addac_x[0..6], zero, zero, zero, zero, zero, zero, zero, zero, zero);
5203 Addac_y := JOIN (addac_y, adda_yconst, zero, zero, zero, zero, zero, zero, zero, zero, zero, zero,
5204 zero, zero, zero, zero, zero);*/
5205 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5206 int16_t addac_x = (adda_xconst == 0x07 ? 0 : 1 << adda_xconst);
5207 int16_t addac_y = (adda_yconst ? 0x01 : 0);
5208 //////////////////////////////////////////////////////////////////////////////////////
5209
5210 /* Select between constant value and register value */
5211
5212 /*Addas_x := MX2 (addas_x, addac_x, addar_x, addareg);
5213 Addas_y := MX2 (addas_y, addac_y, addar_y, addareg);*/
5214 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5215 int16_t addas_x = (addareg ? addar_x : addac_x);
5216 int16_t addas_y = (addareg ? addar_y : addac_y);
5217 //////////////////////////////////////////////////////////////////////////////////////
5218
5219 /* Complement these values (complement flag gives adder carry in)*/
5220
5221 /*Suba_x16 := JOIN (suba_x16, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x,
5222 suba_x, suba_x, suba_x, suba_x, suba_x, suba_x, suba_x);
5223 Suba_y16 := JOIN (suba_y16, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y,
5224 suba_y, suba_y, suba_y, suba_y, suba_y, suba_y, suba_y);
5225 Adda_x := EO (adda_x, suba_x16, addas_x);
5226 Adda_y := EO (adda_y, suba_y16, addas_y);*/
5227 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5228 adda_x = addas_x ^ (suba_x ? 0xFFFF : 0x0000);
5229 adda_y = addas_y ^ (suba_y ? 0xFFFF : 0x0000);
5230 //////////////////////////////////////////////////////////////////////////////////////
5231
5232 //END;
5233 }
5234
5235
5236 /** ADDBMUX - Address adder input B selection *******************
5237
5238 This module selects the register to be updated by the address
5239 adder. This can be one of three registers, the A1 and A2
5240 pointers, or the A1 fractional part. It can also be zero, so that the step
5241 registers load directly into the pointers.
5242 */
5243
5244 /*DEF ADDBMUX (
5245 INT16/ addb_x
5246 INT16/ addb_y
5247 :OUT;
5248 addbsel[0..1]
5249 INT16/ a1_x
5250 INT16/ a1_y
5251 INT16/ a2_x
5252 INT16/ a2_y
5253 INT16/ a1_frac_x
5254 INT16/ a1_frac_y
5255 :IN);
5256 INT16/ zero16 :LOCAL;
5257 BEGIN*/
5258 void ADDBMUX(int16_t &addb_x, int16_t &addb_y, uint8_t addbsel, int16_t a1_x, int16_t a1_y,
5259 int16_t a2_x, int16_t a2_y, int16_t a1_frac_x, int16_t a1_frac_y)
5260 {
5261
5262 /*Zero := TIE0 (zero);
5263 Zero16 := JOIN (zero16, zero, zero, zero, zero, zero, zero, zero,
5264 zero, zero, zero, zero, zero, zero, zero, zero, zero);
5265 Addbselb[0-1] := BUF8 (addbselb[0-1], addbsel[0-1]);
5266 Addb_x := MX4 (addb_x, a1_x, a2_x, a1_frac_x, zero16, addbselb[0..1]);
5267 Addb_y := MX4 (addb_y, a1_y, a2_y, a1_frac_y, zero16, addbselb[0..1]);*/
5268 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5269 int16_t xterm[4], yterm[4];
5270 xterm[0] = a1_x, xterm[1] = a2_x, xterm[2] = a1_frac_x, xterm[3] = 0;
5271 yterm[0] = a1_y, yterm[1] = a2_y, yterm[2] = a1_frac_y, yterm[3] = 0;
5272 addb_x = xterm[addbsel & 0x03];
5273 addb_y = yterm[addbsel & 0x03];
5274 //////////////////////////////////////////////////////////////////////////////////////
5275
5276 //END;
5277 }
5278
5279
5280 /** DATAMUX - Address local data bus selection ******************
5281
5282 Select between the adder output and the input data bus
5283 */
5284
5285 /*DEF DATAMUX (
5286 INT16/ data_x
5287 INT16/ data_y
5288 :OUT;
5289 INT32/ gpu_din
5290 INT16/ addq_x
5291 INT16/ addq_y
5292 addqsel
5293 :IN);
5294
5295 INT16/ gpu_lo, gpu_hi
5296 :LOCAL;
5297 BEGIN*/
5298 void DATAMUX(int16_t &data_x, int16_t &data_y, uint32_t gpu_din, int16_t addq_x, int16_t addq_y, bool addqsel)
5299 {
5300 /*Gpu_lo := JOIN (gpu_lo, gpu_din{0..15});
5301 Gpu_hi := JOIN (gpu_hi, gpu_din{16..31});
5302
5303 Addqselb := BUF8 (addqselb, addqsel);
5304 Data_x := MX2 (data_x, gpu_lo, addq_x, addqselb);
5305 Data_y := MX2 (data_y, gpu_hi, addq_y, addqselb);*/
5306 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5307 data_x = (addqsel ? addq_x : (int16_t)(gpu_din & 0xFFFF));
5308 data_y = (addqsel ? addq_y : (int16_t)(gpu_din >> 16));
5309 //////////////////////////////////////////////////////////////////////////////////////
5310
5311 //END;
5312 }
5313
5314
5315 /******************************************************************
5316 addradd
5317 29/11/90
5318
5319 Blitter Address Adder
5320 ---------------------
5321 The blitter address adder is a pair of sixteen bit adders, one
5322 each for X and Y. The multiplexing of the input terms is
5323 performed elsewhere, but this adder can also perform modulo
5324 arithmetic to align X-addresses onto phrase boundaries.
5325
5326 modx[0..2] take values
5327 000 no mask
5328 001 mask bit 0
5329 010 mask bits 1-0
5330 ..
5331 110 mask bits 5-0
5332
5333 ******************************************************************/
5334
5335 /*IMPORT duplo, tosh;
5336
5337 DEF ADDRADD (
5338 INT16/ addq_x
5339 INT16/ addq_y
5340 :OUT;
5341 a1fracldi // propagate address adder carry
5342 INT16/ adda_x
5343 INT16/ adda_y
5344 INT16/ addb_x
5345 INT16/ addb_y
5346 clk[0] // co-processor clock
5347 modx[0..2]
5348 suba_x
5349 suba_y
5350 :IN);
5351
5352 BEGIN
5353
5354 Zero := TIE0 (zero);*/
5355 void ADDRADD(int16_t &addq_x, int16_t &addq_y, bool a1fracldi,
5356 uint16_t adda_x, uint16_t adda_y, uint16_t addb_x, uint16_t addb_y, uint8_t modx, bool suba_x, bool suba_y)
5357 {
5358
5359 /* Perform the addition */
5360
5361 /*Adder_x := ADD16 (addqt_x[0..15], co_x, adda_x{0..15}, addb_x{0..15}, ci_x);
5362 Adder_y := ADD16 (addq_y[0..15], co_y, adda_y{0..15}, addb_y{0..15}, ci_y);*/
5363
5364 /* latch carry and propagate if required */
5365
5366 /*Cxt0 := AN2 (cxt[0], co_x, a1fracldi);
5367 Cxt1 := FD1Q (cxt[1], cxt[0], clk[0]);
5368 Ci_x := EO (ci_x, cxt[1], suba_x);
5369
5370 yt0 := AN2 (cyt[0], co_y, a1fracldi);
5371 Cyt1 := FD1Q (cyt[1], cyt[0], clk[0]);
5372 Ci_y := EO (ci_y, cyt[1], suba_y);*/
5373
5374 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5375 //I'm sure the following will generate a bunch of warnings, but will have to do for now.
5376 static uint16_t co_x = 0, co_y = 0; // Carry out has to propogate between function calls...
5377 uint16_t ci_x = co_x ^ (suba_x ? 1 : 0);
5378 uint16_t ci_y = co_y ^ (suba_y ? 1 : 0);
5379 uint32_t addqt_x = adda_x + addb_x + ci_x;
5380 uint32_t addqt_y = adda_y + addb_y + ci_y;
5381 co_x = ((addqt_x & 0x10000) && a1fracldi ? 1 : 0);
5382 co_y = ((addqt_y & 0x10000) && a1fracldi ? 1 : 0);
5383 //////////////////////////////////////////////////////////////////////////////////////
5384
5385 /* Mask low bits of X to 0 if required */
5386
5387 /*Masksel := D38H (unused[0], masksel[0..4], maskbit[5], unused[1], modx[0..2]);
5388
5389 Maskbit[0-4] := OR2 (maskbit[0-4], masksel[0-4], maskbit[1-5]);
5390
5391 Mask[0-5] := MX2 (addq_x[0-5], addqt_x[0-5], zero, maskbit[0-5]);
5392
5393 Addq_x := JOIN (addq_x, addq_x[0..5], addqt_x[6..15]);
5394 Addq_y := JOIN (addq_y, addq_y[0..15]);*/
5395
5396 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5397 uint16_t mask[8] = { 0xFFFF, 0xFFFE, 0xFFFC, 0xFFF8, 0xFFF0, 0xFFE0, 0xFFC0, 0x0000 };
5398 addq_x = addqt_x & mask[modx];
5399 addq_y = addqt_y & 0xFFFF;
5400 //////////////////////////////////////////////////////////////////////////////////////
5401
5402 //Unused[0-1] := DUMMY (unused[0-1]);
5403
5404 //END;
5405 }
5406
5407
5408 /*
5409 DEF DATA (
5410 wdata[0..63] // co-processor write data bus
5411 :BUS;
5412 dcomp[0..7] // data byte equal flags
5413 srcd[0..7] // bits to use for bit to byte expansion
5414 zcomp[0..3] // output from Z comparators
5415 :OUT;
5416 a1_x[0..1] // low two bits of A1 X pointer
5417 big_pix // pixel organisation is big-endian
5418 blitter_active // blitter is active
5419 clk // co-processor clock
5420 cmpdst // compare dest rather than source
5421 colorld // load the pattern color fields
5422 daddasel[0..2] // data adder input A selection
5423 daddbsel[0..3] // data adder input B selection
5424 daddmode[0..2] // data adder mode
5425 daddq_sel // select adder output vs. GPU data
5426 data[0..63] // co-processor read data bus
5427 data_ena // enable write data
5428 data_sel[0..1] // select data to write
5429 dbinh\[0..7] // byte oriented changed data inhibits
5430 dend[0..5] // end of changed write data zone
5431 dpipe[0..1] // load computed data pipe-line latch
5432 dstart[0..5] // start of changed write data zone
5433 dstdld[0..1] // dest data load (two halves)
5434 dstzld[0..1] // dest zed load (two halves)
5435 ext_int // enable extended precision intensity calculations
5436 INT32/ gpu_din // GPU data bus
5437 iincld // I increment load
5438 iincldx // alternate I increment load
5439 init_if // initialise I fraction phase
5440 init_ii // initialise I integer phase
5441 init_zf // initialise Z fraction phase
5442 intld[0..3] // computed intensities load
5443 istepadd // intensity step integer add
5444 istepfadd // intensity step fraction add
5445 istepld // I step load
5446 istepdld // I step delta load
5447 lfu_func[0..3] // LFU function code
5448 patdadd // pattern data gouraud add
5449 patdld[0..1] // pattern data load (two halves)
5450 pdsel[0..1] // select pattern data type
5451 phrase_mode // phrase write mode
5452 reload // transfer contents of double buffers
5453 reset\ // system reset
5454 srcd1ld[0..1] // source register 1 load (two halves)
5455 srcdread // source data read load enable
5456 srczread // source zed read load enable
5457 srcshift[0..5] // source alignment shift
5458 srcz1ld[0..1] // source zed 1 load (two halves)
5459 srcz2add // zed fraction gouraud add
5460 srcz2ld[0..1] // source zed 2 load (two halves)
5461 textrgb // texture mapping in RGB mode
5462 txtd[0..63] // data from the texture unit
5463 zedld[0..3] // computed zeds load
5464 zincld // Z increment load
5465 zmode[0..2] // Z comparator mode
5466 zpipe[0..1] // load computed zed pipe-line latch
5467 zstepadd // zed step integer add
5468 zstepfadd // zed step fraction add
5469 zstepld // Z step load
5470 zstepdld // Z step delta load
5471 :IN);
5472 */
5473
5474 void DATA(uint64_t &wdata, uint8_t &dcomp, uint8_t &zcomp, bool &nowrite,
5475 bool big_pix, bool cmpdst, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode, bool daddq_sel, uint8_t data_sel,
5476 uint8_t dbinh, uint8_t dend, uint8_t dstart, uint64_t dstd, uint32_t iinc, uint8_t lfu_func, uint64_t &patd, bool patdadd,
5477 bool phrase_mode, uint64_t srcd, bool srcdread, bool srczread, bool srcz2add, uint8_t zmode,
5478 bool bcompen, bool bkgwren, bool dcompen, uint8_t icount, uint8_t pixsize,
5479 uint64_t &srcz, uint64_t dstz, uint32_t zinc)
5480 {
5481 /*
5482 Stuff we absolutely *need* to have passed in/out:
5483 IN:
5484 patdadd, dstd, srcd, patd, daddasel, daddbsel, daddmode, iinc, srcz1, srcz2, big_pix, phrase_mode, cmpdst
5485 OUT:
5486 changed patd (wdata I guess...) (Nope. We pass it back directly now...)
5487 */
5488
5489 // Source data registers
5490
5491 /*Data_src := DATA_SRC (srcdlo, srcdhi, srcz[0..1], srczo[0..1], srczp[0..1], srcz1[0..1], srcz2[0..1], big_pix,
5492 clk, gpu_din, intld[0..3], local_data0, local_data1, srcd1ld[0..1], srcdread, srczread, srcshift[0..5],
5493 srcz1ld[0..1], srcz2add, srcz2ld[0..1], zedld[0..3], zpipe[0..1]);
5494 Srcd[0-7] := JOIN (srcd[0-7], srcdlo{0-7});
5495 Srcd[8-31] := JOIN (srcd[8-31], srcdlo{8-31});
5496 Srcd[32-63] := JOIN (srcd[32-63], srcdhi{0-31});*/
5497
5498 // Destination data registers
5499
5500 /*Data_dst := DATA_DST (dstd[0..63], dstz[0..1], clk, dstdld[0..1], dstzld[0..1], load_data[0..1]);
5501 Dstdlo := JOIN (dstdlo, dstd[0..31]);
5502 Dstdhi := JOIN (dstdhi, dstd[32..63]);*/
5503
5504 // Pattern and Color data registers
5505
5506 // Looks like this is simply another register file for the pattern data registers. No adding or anything funky
5507 // going on. Note that patd & patdv will output the same info.
5508 // Patdldl/h (patdld[0..1]) can select the local_data bus to overwrite the current pattern data...
5509 // Actually, it can be either patdld OR patdadd...!
5510 /*Data_pat := DATA_PAT (colord[0..15], int0dp[8..10], int1dp[8..10], int2dp[8..10], int3dp[8..10], mixsel[0..2],
5511 patd[0..63], patdv[0..1], clk, colorld, dpipe[0], ext_int, gpu_din, intld[0..3], local_data0, local_data1,
5512 patdadd, patdld[0..1], reload, reset\);
5513 Patdlo := JOIN (patdlo, patd[0..31]);
5514 Patdhi := JOIN (patdhi, patd[32..63]);*/
5515
5516 // Multiplying data Mixer (NOT IN JAGUAR I)
5517
5518 /*Datamix := DATAMIX (patdo[0..1], clk, colord[0..15], dpipe[1], dstd[0..63], int0dp[8..10], int1dp[8..10],
5519 int2dp[8..10], int3dp[8..10], mixsel[0..2], patd[0..63], pdsel[0..1], srcd[0..63], textrgb, txtd[0..63]);*/
5520
5521 // Logic function unit
5522
5523 /*Lfu := LFU (lfu[0..1], srcdlo, srcdhi, dstdlo, dstdhi, lfu_func[0..3]);*/
5524 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5525 uint64_t funcmask[2] = { 0, 0xFFFFFFFFFFFFFFFFLL };
5526 uint64_t func0 = funcmask[lfu_func & 0x01];
5527 uint64_t func1 = funcmask[(lfu_func >> 1) & 0x01];
5528 uint64_t func2 = funcmask[(lfu_func >> 2) & 0x01];
5529 uint64_t func3 = funcmask[(lfu_func >> 3) & 0x01];
5530 uint64_t lfu = (~srcd & ~dstd & func0) | (~srcd & dstd & func1) | (srcd & ~dstd & func2) | (srcd & dstd & func3);
5531 //////////////////////////////////////////////////////////////////////////////////////
5532
5533 // Increment and Step Registers
5534
5535 // Does it do anything without the step add lines? Check it!
5536 // No. This is pretty much just a register file without the Jaguar II lines...
5537 /*Inc_step := INC_STEP (iinc, istep[0..31], zinc, zstep[0..31], clk, ext_int, gpu_din, iincld, iincldx, istepadd,
5538 istepfadd, istepld, istepdld, reload, reset\, zincld, zstepadd, zstepfadd, zstepld, zstepdld);
5539 Istep := JOIN (istep, istep[0..31]);
5540 Zstep := JOIN (zstep, zstep[0..31]);*/
5541
5542 // Pixel data comparator
5543
5544 /*Datacomp := DATACOMP (dcomp[0..7], cmpdst, dstdlo, dstdhi, patdlo, patdhi, srcdlo, srcdhi);*/
5545 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5546 dcomp = 0;
5547 uint64_t cmpd = patd ^ (cmpdst ? dstd : srcd);
5548
5549 if ((cmpd & 0x00000000000000FFLL) == 0)
5550 dcomp |= 0x01;
5551 if ((cmpd & 0x000000000000FF00LL) == 0)
5552 dcomp |= 0x02;
5553 if ((cmpd & 0x0000000000FF0000LL) == 0)
5554 dcomp |= 0x04;
5555 if ((cmpd & 0x00000000FF000000LL) == 0)
5556 dcomp |= 0x08;
5557 if ((cmpd & 0x000000FF00000000LL) == 0)
5558 dcomp |= 0x10;
5559 if ((cmpd & 0x0000FF0000000000LL) == 0)
5560 dcomp |= 0x20;
5561 if ((cmpd & 0x00FF000000000000LL) == 0)
5562 dcomp |= 0x40;
5563 if ((cmpd & 0xFF00000000000000LL) == 0)
5564 dcomp |= 0x80;
5565 //////////////////////////////////////////////////////////////////////////////////////
5566
5567 // Zed comparator for Z-buffer operations
5568
5569 /*Zedcomp := ZEDCOMP (zcomp[0..3], srczp[0..1], dstz[0..1], zmode[0..2]);*/
5570 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5571 //srczp is srcz pipelined, also it goes through a source shift as well...
5572 /*The shift is basically like so (each piece is 16 bits long):
5573
5574 0 1 2 3 4 5 6
5575 srcz1lolo srcz1lohi srcz1hilo srcz1hihi srcrz2lolo srcz2lohi srcz2hilo
5576
5577 with srcshift bits 4 & 5 selecting the start position
5578 */
5579 //So... basically what we have here is:
5580 zcomp = 0;
5581
5582 if ((((srcz & 0x000000000000FFFFLL) < (dstz & 0x000000000000FFFFLL)) && (zmode & 0x01))
5583 || (((srcz & 0x000000000000FFFFLL) == (dstz & 0x000000000000FFFFLL)) && (zmode & 0x02))
5584 || (((srcz & 0x000000000000FFFFLL) > (dstz & 0x000000000000FFFFLL)) && (zmode & 0x04)))
5585 zcomp |= 0x01;
5586
5587 if ((((srcz & 0x00000000FFFF0000LL) < (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x01))
5588 || (((srcz & 0x00000000FFFF0000LL) == (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x02))
5589 || (((srcz & 0x00000000FFFF0000LL) > (dstz & 0x00000000FFFF0000LL)) && (zmode & 0x04)))
5590 zcomp |= 0x02;
5591
5592 if ((((srcz & 0x0000FFFF00000000LL) < (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x01))
5593 || (((srcz & 0x0000FFFF00000000LL) == (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x02))
5594 || (((srcz & 0x0000FFFF00000000LL) > (dstz & 0x0000FFFF00000000LL)) && (zmode & 0x04)))
5595 zcomp |= 0x04;
5596
5597 if ((((srcz & 0xFFFF000000000000LL) < (dstz & 0xFFFF000000000000LL)) && (zmode & 0x01))
5598 || (((srcz & 0xFFFF000000000000LL) == (dstz & 0xFFFF000000000000LL)) && (zmode & 0x02))
5599 || (((srcz & 0xFFFF000000000000LL) > (dstz & 0xFFFF000000000000LL)) && (zmode & 0x04)))
5600 zcomp |= 0x08;
5601
5602 //TEMP, TO TEST IF ZCOMP IS THE CULPRIT...
5603 //Nope, this is NOT the problem...
5604 //zcomp=0;
5605 // We'll do the comparison/bit/byte inhibits here, since that's they way it happens
5606 // in the real thing (dcomp goes out to COMP_CTRL and back into DATA through dbinh)...
5607 #if 1
5608 uint8_t dbinht;
5609 // bool nowrite;
5610 COMP_CTRL(dbinht, nowrite,
5611 bcompen, true/*big_pix*/, bkgwren, dcomp, dcompen, icount, pixsize, phrase_mode, srcd & 0xFF, zcomp);
5612 dbinh = dbinht;
5613 // dbinh = 0x00;
5614 #endif
5615
5616 #if 1
5617 #ifdef VERBOSE_BLITTER_LOGGING
5618 if (logBlit)
5619 WriteLog("\n[dcomp=%02X zcomp=%02X dbinh=%02X]\n", dcomp, zcomp, dbinh);
5620 #endif
5621 #endif
5622 //////////////////////////////////////////////////////////////////////////////////////
5623
5624 // 22 Mar 94
5625 // The data initializer - allows all four initial values to be computed from one (NOT IN JAGUAR I)
5626
5627 /*Datinit := DATINIT (initcin[0..3], initinc[0..63], initpix[0..15], a1_x[0..1], big_pix, clk, iinc, init_if, init_ii,
5628 init_zf, istep[0..31], zinc, zstep[0..31]);*/
5629
5630 // Adder array for Z and intensity increments
5631
5632 /*Addarray := ADDARRAY (addq[0..3], clk, daddasel[0..2], daddbsel[0..3], daddmode[0..2], dstdlo, dstdhi, iinc,
5633 initcin[0..3], initinc[0..63], initpix[0..15], istep, patdv[0..1], srcdlo, srcdhi, srcz1[0..1],
5634 srcz2[0..1], reset\, zinc, zstep);*/
5635 /*void ADDARRAY(uint16_t * addq, uint8_t daddasel, uint8_t daddbsel, uint8_t daddmode,
5636 uint64_t dstd, uint32_t iinc, uint8_t initcin[], uint64_t initinc, uint16_t initpix,
5637 uint32_t istep, uint64_t patd, uint64_t srcd, uint64_t srcz1, uint64_t srcz2,
5638 uint32_t zinc, uint32_t zstep)*/
5639 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5640 uint16_t addq[4];
5641 uint8_t initcin[4] = { 0, 0, 0, 0 };
5642 ADDARRAY(addq, daddasel, daddbsel, daddmode, dstd, iinc, initcin, 0, 0, 0, patd, srcd, 0, 0, 0, 0);
5643
5644 //This is normally done asynchronously above (thru local_data) when in patdadd mode...
5645 //And now it's passed back to the caller to be persistent between calls...!
5646 //But it's causing some serious fuck-ups in T2K now... !!! FIX !!! [DONE--???]
5647 //Weird! It doesn't anymore...!
5648 if (patdadd)
5649 patd = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
5650 //////////////////////////////////////////////////////////////////////////////////////
5651
5652 // Local data bus multiplexer
5653
5654 /*Local_mux := LOCAL_MUX (local_data[0..1], load_data[0..1],
5655 addq[0..3], gpu_din, data[0..63], blitter_active, daddq_sel);
5656 Local_data0 := JOIN (local_data0, local_data[0]);
5657 Local_data1 := JOIN (local_data1, local_data[1]);*/
5658 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5659 //////////////////////////////////////////////////////////////////////////////////////
5660
5661 // Data output multiplexer and tri-state drive
5662
5663 /*Data_mux := DATA_MUX (wdata[0..63], addq[0..3], big_pix, dstdlo, dstdhi, dstz[0..1], data_sel[0..1], data_ena,
5664 dstart[0..5], dend[0..5], dbinh\[0..7], lfu[0..1], patdo[0..1], phrase_mode, srczo[0..1]);*/
5665 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5666 // NOTE: patdo comes from DATAMIX and can be considered the same as patd for Jaguar I
5667
5668 //////////////////////////////////////////////////////////////////////////////////////
5669 //}
5670
5671 /*DEF DATA_MUX (
5672 wdata[0..63] // co-processor rwrite data bus
5673 :BUS;
5674 INT16/ addq[0..3]
5675 big_pix // Pixel organisation is big-endian
5676 INT32/ dstdlo
5677 INT32/ dstdhi
5678 INT32/ dstzlo
5679 INT32/ dstzhi
5680 data_sel[0..1] // source of write data
5681 data_ena // enable write data onto read/write bus
5682 dstart[0..5] // start of changed write data
5683 dend[0..5] // end of changed write data
5684 dbinh\[0..7] // byte oriented changed data inhibits
5685 INT32/ lfu[0..1]
5686 INT32/ patd[0..1]
5687 phrase_mode // phrase write mode
5688 INT32/ srczlo
5689 INT32/ srczhi
5690 :IN);*/
5691
5692 /*INT32/ addql[0..1], ddatlo, ddathi zero32
5693 :LOCAL;
5694 BEGIN
5695
5696 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5697 Zero := TIE0 (zero);
5698 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);*/
5699
5700 /* Generate a changed data mask */
5701
5702 /*Edis := OR6 (edis\, dend[0..5]);
5703 Ecoarse := DECL38E (e_coarse\[0..7], dend[3..5], edis\);
5704 E_coarse[0] := INV1 (e_coarse[0], e_coarse\[0]);
5705 Efine := DECL38E (unused[0], e_fine\[1..7], dend[0..2], e_coarse[0]);*/
5706 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5707 uint8_t decl38e[2][8] = { { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
5708 { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } };
5709 uint8_t dech38[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 };
5710 uint8_t dech38el[2][8] = { { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 },
5711 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };
5712
5713 int en = (dend & 0x3F ? 1 : 0);
5714 uint8_t e_coarse = decl38e[en][(dend & 0x38) >> 3]; // Actually, this is e_coarse inverted...
5715 uint8_t e_fine = decl38e[(e_coarse & 0x01) ^ 0x01][dend & 0x07];
5716 e_fine &= 0xFE;
5717 //////////////////////////////////////////////////////////////////////////////////////
5718
5719 /*Scoarse := DECH38 (s_coarse[0..7], dstart[3..5]);
5720 Sfen\ := INV1 (sfen\, s_coarse[0]);
5721 Sfine := DECH38EL (s_fine[0..7], dstart[0..2], sfen\);*/
5722 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5723 uint8_t s_coarse = dech38[(dstart & 0x38) >> 3];
5724 uint8_t s_fine = dech38el[(s_coarse & 0x01) ^ 0x01][dstart & 0x07];
5725 //////////////////////////////////////////////////////////////////////////////////////
5726
5727 /*Maskt[0] := BUF1 (maskt[0], s_fine[0]);
5728 Maskt[1-7] := OAN1P (maskt[1-7], maskt[0-6], s_fine[1-7], e_fine\[1-7]);*/
5729 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5730 uint16_t maskt = s_fine & 0x0001;
5731 maskt |= (((maskt & 0x0001) || (s_fine & 0x02)) && (e_fine & 0x02) ? 0x0002 : 0x0000);
5732 maskt |= (((maskt & 0x0002) || (s_fine & 0x04)) && (e_fine & 0x04) ? 0x0004 : 0x0000);
5733 maskt |= (((maskt & 0x0004) || (s_fine & 0x08)) && (e_fine & 0x08) ? 0x0008 : 0x0000);
5734 maskt |= (((maskt & 0x0008) || (s_fine & 0x10)) && (e_fine & 0x10) ? 0x0010 : 0x0000);
5735 maskt |= (((maskt & 0x0010) || (s_fine & 0x20)) && (e_fine & 0x20) ? 0x0020 : 0x0000);
5736 maskt |= (((maskt & 0x0020) || (s_fine & 0x40)) && (e_fine & 0x40) ? 0x0040 : 0x0000);
5737 maskt |= (((maskt & 0x0040) || (s_fine & 0x80)) && (e_fine & 0x80) ? 0x0080 : 0x0000);
5738 //////////////////////////////////////////////////////////////////////////////////////
5739
5740 /* Produce a look-ahead on the ripple carry:
5741 masktla = s_coarse[0] . /e_coarse[0] */
5742 /*Masktla := AN2 (masktla, s_coarse[0], e_coarse\[0]);
5743 Maskt[8] := OAN1P (maskt[8], masktla, s_coarse[1], e_coarse\[1]);
5744 Maskt[9-14] := OAN1P (maskt[9-14], maskt[8-13], s_coarse[2-7], e_coarse\[2-7]);*/
5745 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5746 maskt |= (((s_coarse & e_coarse & 0x01) || (s_coarse & 0x02)) && (e_coarse & 0x02) ? 0x0100 : 0x0000);
5747 maskt |= (((maskt & 0x0100) || (s_coarse & 0x04)) && (e_coarse & 0x04) ? 0x0200 : 0x0000);
5748 maskt |= (((maskt & 0x0200) || (s_coarse & 0x08)) && (e_coarse & 0x08) ? 0x0400 : 0x0000);
5749 maskt |= (((maskt & 0x0400) || (s_coarse & 0x10)) && (e_coarse & 0x10) ? 0x0800 : 0x0000);
5750 maskt |= (((maskt & 0x0800) || (s_coarse & 0x20)) && (e_coarse & 0x20) ? 0x1000 : 0x0000);
5751 maskt |= (((maskt & 0x1000) || (s_coarse & 0x40)) && (e_coarse & 0x40) ? 0x2000 : 0x0000);
5752 maskt |= (((maskt & 0x2000) || (s_coarse & 0x80)) && (e_coarse & 0x80) ? 0x4000 : 0x0000);
5753 //////////////////////////////////////////////////////////////////////////////////////
5754
5755 /* The bit terms are mirrored for big-endian pixels outside phrase
5756 mode. The byte terms are mirrored for big-endian pixels in phrase
5757 mode. */
5758
5759 /*Mirror_bit := AN2M (mir_bit, phrase_mode\, big_pix);
5760 Mirror_byte := AN2H (mir_byte, phrase_mode, big_pix);
5761
5762 Masktb[14] := BUF1 (masktb[14], maskt[14]);
5763 Masku[0] := MX4 (masku[0], maskt[0], maskt[7], maskt[14], zero, mir_bit, mir_byte);
5764 Masku[1] := MX4 (masku[1], maskt[1], maskt[6], maskt[14], zero, mir_bit, mir_byte);
5765 Masku[2] := MX4 (masku[2], maskt[2], maskt[5], maskt[14], zero, mir_bit, mir_byte);
5766 Masku[3] := MX4 (masku[3], maskt[3], maskt[4], masktb[14], zero, mir_bit, mir_byte);
5767 Masku[4] := MX4 (masku[4], maskt[4], maskt[3], masktb[14], zero, mir_bit, mir_byte);
5768 Masku[5] := MX4 (masku[5], maskt[5], maskt[2], masktb[14], zero, mir_bit, mir_byte);
5769 Masku[6] := MX4 (masku[6], maskt[6], maskt[1], masktb[14], zero, mir_bit, mir_byte);
5770 Masku[7] := MX4 (masku[7], maskt[7], maskt[0], masktb[14], zero, mir_bit, mir_byte);
5771 Masku[8] := MX2 (masku[8], maskt[8], maskt[13], mir_byte);
5772 Masku[9] := MX2 (masku[9], maskt[9], maskt[12], mir_byte);
5773 Masku[10] := MX2 (masku[10], maskt[10], maskt[11], mir_byte);
5774 Masku[11] := MX2 (masku[11], maskt[11], maskt[10], mir_byte);
5775 Masku[12] := MX2 (masku[12], maskt[12], maskt[9], mir_byte);
5776 Masku[13] := MX2 (masku[13], maskt[13], maskt[8], mir_byte);
5777 Masku[14] := MX2 (masku[14], maskt[14], maskt[0], mir_byte);*/
5778 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5779 bool mir_bit = true/*big_pix*/ && !phrase_mode;
5780 bool mir_byte = true/*big_pix*/ && phrase_mode;
5781 uint16_t masku = maskt;
5782
5783 if (mir_bit)
5784 {
5785 masku &= 0xFF00;
5786 masku |= (maskt >> 7) & 0x0001;
5787 masku |= (maskt >> 5) & 0x0002;
5788 masku |= (maskt >> 3) & 0x0004;
5789 masku |= (maskt >> 1) & 0x0008;
5790 masku |= (maskt << 1) & 0x0010;
5791 masku |= (maskt << 3) & 0x0020;
5792 masku |= (maskt << 5) & 0x0040;
5793 masku |= (maskt << 7) & 0x0080;
5794 }
5795
5796 if (mir_byte)
5797 {
5798 masku = 0;
5799 masku |= (maskt >> 14) & 0x0001;
5800 masku |= (maskt >> 13) & 0x0002;
5801 masku |= (maskt >> 12) & 0x0004;
5802 masku |= (maskt >> 11) & 0x0008;
5803 masku |= (maskt >> 10) & 0x0010;
5804 masku |= (maskt >> 9) & 0x0020;
5805 masku |= (maskt >> 8) & 0x0040;
5806 masku |= (maskt >> 7) & 0x0080;
5807
5808 masku |= (maskt >> 5) & 0x0100;
5809 masku |= (maskt >> 3) & 0x0200;
5810 masku |= (maskt >> 1) & 0x0400;
5811 masku |= (maskt << 1) & 0x0800;
5812 masku |= (maskt << 3) & 0x1000;
5813 masku |= (maskt << 5) & 0x2000;
5814 masku |= (maskt << 7) & 0x4000;
5815 }
5816 //////////////////////////////////////////////////////////////////////////////////////
5817
5818 /* The maskt terms define the area for changed data, but the byte
5819 inhibit terms can override these */
5820
5821 /*Mask[0-7] := AN2 (mask[0-7], masku[0-7], dbinh\[0]);
5822 Mask[8-14] := AN2H (mask[8-14], masku[8-14], dbinh\[1-7]);*/
5823 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5824 uint16_t mask = masku & (!(dbinh & 0x01) ? 0xFFFF : 0xFF00);
5825 mask &= ~(((uint16_t)dbinh & 0x00FE) << 7);
5826 //////////////////////////////////////////////////////////////////////////////////////
5827
5828 /*Addql[0] := JOIN (addql[0], addq[0..1]);
5829 Addql[1] := JOIN (addql[1], addq[2..3]);
5830
5831 Dsel0b[0-1] := BUF8 (dsel0b[0-1], data_sel[0]);
5832 Dsel1b[0-1] := BUF8 (dsel1b[0-1], data_sel[1]);
5833 Ddatlo := MX4 (ddatlo, patd[0], lfu[0], addql[0], zero32, dsel0b[0], dsel1b[0]);
5834 Ddathi := MX4 (ddathi, patd[1], lfu[1], addql[1], zero32, dsel0b[1], dsel1b[1]);*/
5835 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5836 uint64_t dmux[4];
5837 dmux[0] = patd;
5838 dmux[1] = lfu;
5839 dmux[2] = ((uint64_t)addq[3] << 48) | ((uint64_t)addq[2] << 32) | ((uint64_t)addq[1] << 16) | (uint64_t)addq[0];
5840 dmux[3] = 0;
5841 uint64_t ddat = dmux[data_sel];
5842 //////////////////////////////////////////////////////////////////////////////////////
5843
5844 /*Zed_sel := AN2 (zed_sel, data_sel[0..1]);
5845 Zed_selb[0-1] := BUF8 (zed_selb[0-1], zed_sel);
5846
5847 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]);
5848 Dat[8-15] := MX4 (dat[8-15], dstdlo{8-15}, ddatlo{8-15}, dstzlo{8-15}, srczlo{8-15}, mask[8], zed_selb[0]);
5849 Dat[16-23] := MX4 (dat[16-23], dstdlo{16-23}, ddatlo{16-23}, dstzlo{16-23}, srczlo{16-23}, mask[9], zed_selb[0]);
5850 Dat[24-31] := MX4 (dat[24-31], dstdlo{24-31}, ddatlo{24-31}, dstzlo{24-31}, srczlo{24-31}, mask[10], zed_selb[0]);
5851 Dat[32-39] := MX4 (dat[32-39], dstdhi{0-7}, ddathi{0-7}, dstzhi{0-7}, srczhi{0-7}, mask[11], zed_selb[1]);
5852 Dat[40-47] := MX4 (dat[40-47], dstdhi{8-15}, ddathi{8-15}, dstzhi{8-15}, srczhi{8-15}, mask[12], zed_selb[1]);
5853 Dat[48-55] := MX4 (dat[48-55], dstdhi{16-23}, ddathi{16-23}, dstzhi{16-23}, srczhi{16-23}, mask[13], zed_selb[1]);
5854 Dat[56-63] := MX4 (dat[56-63], dstdhi{24-31}, ddathi{24-31}, dstzhi{24-31}, srczhi{24-31}, mask[14], zed_selb[1]);*/
5855 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5856 wdata = ((ddat & mask) | (dstd & ~mask)) & 0x00000000000000FFLL;
5857 wdata |= (mask & 0x0100 ? ddat : dstd) & 0x000000000000FF00LL;
5858 wdata |= (mask & 0x0200 ? ddat : dstd) & 0x0000000000FF0000LL;
5859 wdata |= (mask & 0x0400 ? ddat : dstd) & 0x00000000FF000000LL;
5860 wdata |= (mask & 0x0800 ? ddat : dstd) & 0x000000FF00000000LL;
5861 wdata |= (mask & 0x1000 ? ddat : dstd) & 0x0000FF0000000000LL;
5862 wdata |= (mask & 0x2000 ? ddat : dstd) & 0x00FF000000000000LL;
5863 wdata |= (mask & 0x4000 ? ddat : dstd) & 0xFF00000000000000LL;
5864 /*if (logBlit)
5865 {
5866 printf("\n[ddat=%08X%08X dstd=%08X%08X wdata=%08X%08X mask=%04X]\n",
5867 (uint32_t)(ddat >> 32), (uint32_t)(ddat & 0xFFFFFFFF),
5868 (uint32_t)(dstd >> 32), (uint32_t)(dstd & 0xFFFFFFFF),
5869 (uint32_t)(wdata >> 32), (uint32_t)(wdata & 0xFFFFFFFF), mask);
5870 fflush(stdout);
5871 }//*/
5872 //This is a crappy way of handling this, but it should work for now...
5873 uint64_t zwdata;
5874 zwdata = ((srcz & mask) | (dstz & ~mask)) & 0x00000000000000FFLL;
5875 zwdata |= (mask & 0x0100 ? srcz : dstz) & 0x000000000000FF00LL;
5876 zwdata |= (mask & 0x0200 ? srcz : dstz) & 0x0000000000FF0000LL;
5877 zwdata |= (mask & 0x0400 ? srcz : dstz) & 0x00000000FF000000LL;
5878 zwdata |= (mask & 0x0800 ? srcz : dstz) & 0x000000FF00000000LL;
5879 zwdata |= (mask & 0x1000 ? srcz : dstz) & 0x0000FF0000000000LL;
5880 zwdata |= (mask & 0x2000 ? srcz : dstz) & 0x00FF000000000000LL;
5881 zwdata |= (mask & 0x4000 ? srcz : dstz) & 0xFF00000000000000LL;
5882 if (logBlit)
5883 {
5884 WriteLog("\n[srcz=%08X%08X dstz=%08X%08X zwdata=%08X%08X mask=%04X]\n",
5885 (uint32_t)(srcz >> 32), (uint32_t)(srcz & 0xFFFFFFFF),
5886 (uint32_t)(dstz >> 32), (uint32_t)(dstz & 0xFFFFFFFF),
5887 (uint32_t)(zwdata >> 32), (uint32_t)(zwdata & 0xFFFFFFFF), mask);
5888 // fflush(stdout);
5889 }//*/
5890 srcz = zwdata;
5891 //////////////////////////////////////////////////////////////////////////////////////
5892
5893 /*Data_enab[0-1] := BUF8 (data_enab[0-1], data_ena);
5894 Datadrv[0-31] := TS (wdata[0-31], dat[0-31], data_enab[0]);
5895 Datadrv[32-63] := TS (wdata[32-63], dat[32-63], data_enab[1]);
5896
5897 Unused[0] := DUMMY (unused[0]);
5898
5899 END;*/
5900 }
5901
5902
5903 /** COMP_CTRL - Comparator output control logic *****************
5904
5905 This block is responsible for taking the comparator outputs and
5906 using them as appropriate to inhibit writes. Two methods are
5907 supported for inhibiting write data:
5908
5909 - suppression of the inner loop controlled write operation
5910 - a set of eight byte inhibit lines to write back dest data
5911
5912 The first technique is used in pixel oriented modes, the second in
5913 phrase mode, but the phrase mode form is only applicable to eight
5914 and sixteen bit pixel modes.
5915
5916 Writes can be suppressed by data being equal, by the Z comparator
5917 conditions being met, or by the bit to pixel expansion scheme.
5918
5919 Pipe-lining issues: the data derived comparator outputs are stable
5920 until the next data read, well after the affected write from this
5921 operation. However, the inner counter bits can count immediately
5922 before the ack for the last write. Therefore, it is necessary to
5923 delay bcompbit select terms by one inner loop pipe-line stage,
5924 when generating the select for the data control - the output is
5925 delayed one further tick to give it write data timing (2/34).
5926
5927 There is also a problem with computed data - the new values are
5928 calculated before the write associated with the old value has been
5929 performed. The is taken care of within the zed comparator by
5930 pipe-lining the comparator inputs where appropriate.
5931 */
5932
5933 //#define LOG_COMP_CTRL
5934 /*DEF COMP_CTRL (
5935 dbinh\[0..7] // destination byte inhibit lines
5936 nowrite // suppress inner loop write operation
5937 :OUT;
5938 bcompen // bit selector inhibit enable
5939 big_pix // pixels are big-endian
5940 bkgwren // enable dest data write in pix inhibit
5941 clk // co-processor clock
5942 dcomp[0..7] // output of data byte comparators
5943 dcompen // data comparator inhibit enable
5944 icount[0..2] // low bits of inner count
5945 pixsize[0..2] // destination pixel size
5946 phrase_mode // phrase write mode
5947 srcd[0..7] // bits to use for bit to byte expansion
5948 step_inner // inner loop advance
5949 zcomp[0..3] // output of word zed comparators
5950 :IN);*/
5951 void COMP_CTRL(uint8_t &dbinh, bool &nowrite,
5952 bool bcompen, bool big_pix, bool bkgwren, uint8_t dcomp, bool dcompen, uint8_t icount,
5953 uint8_t pixsize, bool phrase_mode, uint8_t srcd, uint8_t zcomp)
5954 {
5955 //BEGIN
5956
5957 /*Bkgwren\ := INV1 (bkgwren\, bkgwren);
5958 Phrase_mode\ := INV1 (phrase_mode\, phrase_mode);
5959 Pixsize\[0-2] := INV2 (pixsize\[0-2], pixsize[0-2]);*/
5960
5961 /* The bit comparator bits are derived from the source data, which
5962 will have been suitably aligned for phrase mode. The contents of
5963 the inner counter are used to select which bit to use.
5964
5965 When not in phrase mode the inner count value is used to select
5966 one bit. It is assumed that the count has already occurred, so,
5967 7 selects bit 0, etc. In big-endian pixel mode, this turns round,
5968 so that a count of 7 selects bit 7.
5969
5970 In phrase mode, the eight bits are used directly, and this mode is
5971 only applicable to 8-bit pixel mode (2/34) */
5972
5973 /*Bcompselt[0-2] := EO (bcompselt[0-2], icount[0-2], big_pix);
5974 Bcompbit := MX8 (bcompbit, srcd[7], srcd[6], srcd[5],
5975 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompselt[0..2]);
5976 Bcompbit\ := INV1 (bcompbit\, bcompbit);*/
5977 ////////////////////////////////////// C++ CODE //////////////////////////////////////
5978 #ifdef LOG_COMP_CTRL
5979 if (logBlit)
5980 {
5981 WriteLog("\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);
5982 WriteLog("\n ");
5983 // fflush(stdout);
5984 }
5985 #endif
5986 uint8_t bcompselt = (big_pix ? ~icount : icount) & 0x07;
5987 uint8_t bitmask[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
5988 bool bcompbit = srcd & bitmask[bcompselt];
5989 //////////////////////////////////////////////////////////////////////////////////////
5990
5991 /* pipe-line the count */
5992 /*Bcompsel[0-2] := FDSYNC (bcompsel[0-2], bcompselt[0-2], step_inner, clk);
5993 Bcompbt := MX8 (bcompbitpt, srcd[7], srcd[6], srcd[5],
5994 srcd[4], srcd[3], srcd[2], srcd[1], srcd[0], bcompsel[0..2]);
5995 Bcompbitp := FD1Q (bcompbitp, bcompbitpt, clk);
5996 Bcompbitp\ := INV1 (bcompbitp\, bcompbitp);*/
5997
5998 /* For pixel mode, generate the write inhibit signal for all modes
5999 on bit inhibit, for 8 and 16 bit modes on comparator inhibit, and
6000 for 16 bit mode on Z inhibit
6001
6002 Nowrite = bcompen . /bcompbit . /phrase_mode
6003 + dcompen . dcomp[0] . /phrase_mode . pixsize = 011
6004 + dcompen . dcomp[0..1] . /phrase_mode . pixsize = 100
6005 + zcomp[0] . /phrase_mode . pixsize = 100
6006 */
6007
6008 /*Nowt0 := NAN3 (nowt[0], bcompen, bcompbit\, phrase_mode\);
6009 Nowt1 := ND6 (nowt[1], dcompen, dcomp[0], phrase_mode\, pixsize\[2], pixsize[0..1]);
6010 Nowt2 := ND7 (nowt[2], dcompen, dcomp[0..1], phrase_mode\, pixsize[2], pixsize\[0..1]);
6011 Nowt3 := NAN5 (nowt[3], zcomp[0], phrase_mode\, pixsize[2], pixsize\[0..1]);
6012 Nowt4 := NAN4 (nowt[4], nowt[0..3]);
6013 Nowrite := AN2 (nowrite, nowt[4], bkgwren\);*/
6014 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6015 nowrite = ((bcompen && !bcompbit && !phrase_mode)
6016 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
6017 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
6018 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4)))
6019 && !bkgwren;
6020 //////////////////////////////////////////////////////////////////////////////////////
6021
6022 /*Winht := NAN3 (winht, bcompen, bcompbitp\, phrase_mode\);
6023 Winhibit := NAN4 (winhibit, winht, nowt[1..3]);*/
6024 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6025 //This is the same as above, but with bcompbit delayed one tick and called 'winhibit'
6026 //Small difference: Besides the pipeline effect, it's also not using !bkgwren...
6027 // bool winhibit = (bcompen && !
6028 bool winhibit = (bcompen && !bcompbit && !phrase_mode)
6029 || (dcompen && (dcomp & 0x01) && !phrase_mode && (pixsize == 3))
6030 || (dcompen && ((dcomp & 0x03) == 0x03) && !phrase_mode && (pixsize == 4))
6031 || ((zcomp & 0x01) && !phrase_mode && (pixsize == 4));
6032 #ifdef LOG_COMP_CTRL
6033 if (logBlit)
6034 {
6035 WriteLog("[nw=%s wi=%s]", (nowrite ? "T" : "F"), (winhibit ? "T" : "F"));
6036 // fflush(stdout);
6037 }
6038 #endif
6039 //////////////////////////////////////////////////////////////////////////////////////
6040
6041 /* For phrase mode, generate the byte inhibit signals for eight bit
6042 mode 011, or sixteen bit mode 100
6043 dbinh\[0] = pixsize[2] . zcomp[0]
6044 + pixsize[2] . dcomp[0] . dcomp[1] . dcompen
6045 + /pixsize[2] . dcomp[0] . dcompen
6046 + /srcd[0] . bcompen
6047
6048 Inhibits 0-3 are also used when not in phrase mode to write back
6049 destination data.
6050 */
6051
6052 /*Srcd\[0-7] := INV1 (srcd\[0-7], srcd[0-7]);
6053
6054 Di0t0 := NAN2H (di0t[0], pixsize[2], zcomp[0]);
6055 Di0t1 := NAN4H (di0t[1], pixsize[2], dcomp[0..1], dcompen);
6056 Di0t2 := NAN2 (di0t[2], srcd\[0], bcompen);
6057 Di0t3 := NAN3 (di0t[3], pixsize\[2], dcomp[0], dcompen);
6058 Di0t4 := NAN4 (di0t[4], di0t[0..3]);
6059 Dbinh[0] := ANR1P (dbinh\[0], di0t[4], phrase_mode, winhibit);*/
6060 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6061 dbinh = 0;
6062 bool di0t0_1 = ((pixsize & 0x04) && (zcomp & 0x01))
6063 || ((pixsize & 0x04) && (dcomp & 0x01) && (dcomp & 0x02) && dcompen);
6064 bool di0t4 = di0t0_1
6065 || (!(srcd & 0x01) && bcompen)
6066 || (!(pixsize & 0x04) && (dcomp & 0x01) && dcompen);
6067 dbinh |= (!((di0t4 && phrase_mode) || winhibit) ? 0x01 : 0x00);
6068 #ifdef LOG_COMP_CTRL
6069 if (logBlit)
6070 {
6071 WriteLog("[di0t0_1=%s di0t4=%s]", (di0t0_1 ? "T" : "F"), (di0t4 ? "T" : "F"));
6072 // fflush(stdout);
6073 }
6074 #endif
6075 //////////////////////////////////////////////////////////////////////////////////////
6076
6077 /*Di1t0 := NAN3 (di1t[0], pixsize\[2], dcomp[1], dcompen);
6078 Di1t1 := NAN2 (di1t[1], srcd\[1], bcompen);
6079 Di1t2 := NAN4 (di1t[2], di0t[0..1], di1t[0..1]);
6080 Dbinh[1] := ANR1 (dbinh\[1], di1t[2], phrase_mode, winhibit);*/
6081 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6082 bool di1t2 = di0t0_1
6083 || (!(srcd & 0x02) && bcompen)
6084 || (!(pixsize & 0x04) && (dcomp & 0x02) && dcompen);
6085 dbinh |= (!((di1t2 && phrase_mode) || winhibit) ? 0x02 : 0x00);
6086 #ifdef LOG_COMP_CTRL
6087 if (logBlit)
6088 {
6089 WriteLog("[di1t2=%s]", (di1t2 ? "T" : "F"));
6090 // fflush(stdout);
6091 }
6092 #endif
6093 //////////////////////////////////////////////////////////////////////////////////////
6094
6095 /*Di2t0 := NAN2H (di2t[0], pixsize[2], zcomp[1]);
6096 Di2t1 := NAN4H (di2t[1], pixsize[2], dcomp[2..3], dcompen);
6097 Di2t2 := NAN2 (di2t[2], srcd\[2], bcompen);
6098 Di2t3 := NAN3 (di2t[3], pixsize\[2], dcomp[2], dcompen);
6099 Di2t4 := NAN4 (di2t[4], di2t[0..3]);
6100 Dbinh[2] := ANR1 (dbinh\[2], di2t[4], phrase_mode, winhibit);*/
6101 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6102 //[bcompen=F dcompen=T phrase_mode=T bkgwren=F][nw=F wi=F]
6103 //[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]
6104 //[dcomp=$00 dbinh=$0C][7804780400007804] (icount=0005, inc=4)
6105 bool di2t0_1 = ((pixsize & 0x04) && (zcomp & 0x02))
6106 || ((pixsize & 0x04) && (dcomp & 0x04) && (dcomp & 0x08) && dcompen);
6107 bool di2t4 = di2t0_1
6108 || (!(srcd & 0x04) && bcompen)
6109 || (!(pixsize & 0x04) && (dcomp & 0x04) && dcompen);
6110 dbinh |= (!((di2t4 && phrase_mode) || winhibit) ? 0x04 : 0x00);
6111 #ifdef LOG_COMP_CTRL
6112 if (logBlit)
6113 {
6114 WriteLog("[di2t0_1=%s di2t4=%s]", (di2t0_1 ? "T" : "F"), (di2t4 ? "T" : "F"));
6115 // fflush(stdout);
6116 }
6117 #endif
6118 //////////////////////////////////////////////////////////////////////////////////////
6119
6120 /*Di3t0 := NAN3 (di3t[0], pixsize\[2], dcomp[3], dcompen);
6121 Di3t1 := NAN2 (di3t[1], srcd\[3], bcompen);
6122 Di3t2 := NAN4 (di3t[2], di2t[0..1], di3t[0..1]);
6123 Dbinh[3] := ANR1 (dbinh\[3], di3t[2], phrase_mode, winhibit);*/
6124 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6125 bool di3t2 = di2t0_1
6126 || (!(srcd & 0x08) && bcompen)
6127 || (!(pixsize & 0x04) && (dcomp & 0x08) && dcompen);
6128 dbinh |= (!((di3t2 && phrase_mode) || winhibit) ? 0x08 : 0x00);
6129 #ifdef LOG_COMP_CTRL
6130 if (logBlit)
6131 {
6132 WriteLog("[di3t2=%s]", (di3t2 ? "T" : "F"));
6133 // fflush(stdout);
6134 }
6135 #endif
6136 //////////////////////////////////////////////////////////////////////////////////////
6137
6138 /*Di4t0 := NAN2H (di4t[0], pixsize[2], zcomp[2]);
6139 Di4t1 := NAN4H (di4t[1], pixsize[2], dcomp[4..5], dcompen);
6140 Di4t2 := NAN2 (di4t[2], srcd\[4], bcompen);
6141 Di4t3 := NAN3 (di4t[3], pixsize\[2], dcomp[4], dcompen);
6142 Di4t4 := NAN4 (di4t[4], di4t[0..3]);
6143 Dbinh[4] := NAN2 (dbinh\[4], di4t[4], phrase_mode);*/
6144 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6145 bool di4t0_1 = ((pixsize & 0x04) && (zcomp & 0x04))
6146 || ((pixsize & 0x04) && (dcomp & 0x10) && (dcomp & 0x20) && dcompen);
6147 bool di4t4 = di4t0_1
6148 || (!(srcd & 0x10) && bcompen)
6149 || (!(pixsize & 0x04) && (dcomp & 0x10) && dcompen);
6150 dbinh |= (!(di4t4 && phrase_mode) ? 0x10 : 0x00);
6151 #ifdef LOG_COMP_CTRL
6152 if (logBlit)
6153 {
6154 WriteLog("[di4t0_1=%s di2t4=%s]", (di4t0_1 ? "T" : "F"), (di4t4 ? "T" : "F"));
6155 // fflush(stdout);
6156 }
6157 #endif
6158 //////////////////////////////////////////////////////////////////////////////////////
6159
6160 /*Di5t0 := NAN3 (di5t[0], pixsize\[2], dcomp[5], dcompen);
6161 Di5t1 := NAN2 (di5t[1], srcd\[5], bcompen);
6162 Di5t2 := NAN4 (di5t[2], di4t[0..1], di5t[0..1]);
6163 Dbinh[5] := NAN2 (dbinh\[5], di5t[2], phrase_mode);*/
6164 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6165 bool di5t2 = di4t0_1
6166 || (!(srcd & 0x20) && bcompen)
6167 || (!(pixsize & 0x04) && (dcomp & 0x20) && dcompen);
6168 dbinh |= (!(di5t2 && phrase_mode) ? 0x20 : 0x00);
6169 #ifdef LOG_COMP_CTRL
6170 if (logBlit)
6171 {
6172 WriteLog("[di5t2=%s]", (di5t2 ? "T" : "F"));
6173 // fflush(stdout);
6174 }
6175 #endif
6176 //////////////////////////////////////////////////////////////////////////////////////
6177
6178 /*Di6t0 := NAN2H (di6t[0], pixsize[2], zcomp[3]);
6179 Di6t1 := NAN4H (di6t[1], pixsize[2], dcomp[6..7], dcompen);
6180 Di6t2 := NAN2 (di6t[2], srcd\[6], bcompen);
6181 Di6t3 := NAN3 (di6t[3], pixsize\[2], dcomp[6], dcompen);
6182 Di6t4 := NAN4 (di6t[4], di6t[0..3]);
6183 Dbinh[6] := NAN2 (dbinh\[6], di6t[4], phrase_mode);*/
6184 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6185 bool di6t0_1 = ((pixsize & 0x04) && (zcomp & 0x08))
6186 || ((pixsize & 0x04) && (dcomp & 0x40) && (dcomp & 0x80) && dcompen);
6187 bool di6t4 = di6t0_1
6188 || (!(srcd & 0x40) && bcompen)
6189 || (!(pixsize & 0x04) && (dcomp & 0x40) && dcompen);
6190 dbinh |= (!(di6t4 && phrase_mode) ? 0x40 : 0x00);
6191 #ifdef LOG_COMP_CTRL
6192 if (logBlit)
6193 {
6194 WriteLog("[di6t0_1=%s di6t4=%s]", (di6t0_1 ? "T" : "F"), (di6t4 ? "T" : "F"));
6195 // fflush(stdout);
6196 }
6197 #endif
6198 //////////////////////////////////////////////////////////////////////////////////////
6199
6200 /*Di7t0 := NAN3 (di7t[0], pixsize\[2], dcomp[7], dcompen);
6201 Di7t1 := NAN2 (di7t[1], srcd\[7], bcompen);
6202 Di7t2 := NAN4 (di7t[2], di6t[0..1], di7t[0..1]);
6203 Dbinh[7] := NAN2 (dbinh\[7], di7t[2], phrase_mode);*/
6204 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6205 bool di7t2 = di6t0_1
6206 || (!(srcd & 0x80) && bcompen)
6207 || (!(pixsize & 0x04) && (dcomp & 0x80) && dcompen);
6208 dbinh |= (!(di7t2 && phrase_mode) ? 0x80 : 0x00);
6209 #ifdef LOG_COMP_CTRL
6210 if (logBlit)
6211 {
6212 WriteLog("[di7t2=%s]", (di7t2 ? "T" : "F"));
6213 // fflush(stdout);
6214 }
6215 #endif
6216 //////////////////////////////////////////////////////////////////////////////////////
6217
6218 //END;
6219 //kludge
6220 dbinh = ~dbinh;
6221 #ifdef LOG_COMP_CTRL
6222 if (logBlit)
6223 {
6224 WriteLog("[dcomp=$%02X dbinh=$%02X]\n ", dcomp, dbinh);
6225 // fflush(stdout);
6226 }
6227 #endif
6228 }
6229
6230
6231 ////////////////////////////////////// C++ CODE //////////////////////////////////////
6232 //////////////////////////////////////////////////////////////////////////////////////
6233
6234 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6235 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6236 // !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!! TESTING !!!
6237
6238 #endif
6239