1 #include <stdlib.h>
2 #include <stddef.h>
3 #include <math.h>
4 #include "ibm.h"
5 #include "device.h"
6 #include "mem.h"
7 #include "pci.h"
8 #include "thread.h"
9 #include "timer.h"
10 #include "video.h"
11 #include "vid_svga.h"
12 #include "vid_voodoo.h"
13 #include "vid_voodoo_dither.h"
14
15 #ifdef MIN
16 #undef MIN
17 #endif
18 #ifdef CLAMP
19 #undef CLAMP
20 #endif
21
22 #define MIN(a, b) ((a) < (b) ? (a) : (b))
23
24 #define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x)))
25 #define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x)))
26
27 #define LOD_MAX 8
28
29 #define TEX_DIRTY_SHIFT 10
30
31 #define TEX_CACHE_MAX 64
32
33 enum
34 {
35 VOODOO_1 = 0,
36 VOODOO_SB50 = 1,
37 VOODOO_2 = 2
38 };
39
40 static uint32_t texture_offset[LOD_MAX+3] =
41 {
42 0,
43 256*256,
44 256*256 + 128*128,
45 256*256 + 128*128 + 64*64,
46 256*256 + 128*128 + 64*64 + 32*32,
47 256*256 + 128*128 + 64*64 + 32*32 + 16*16,
48 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8,
49 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4,
50 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2,
51 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1,
52 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1 + 1
53 };
54
55 static int tris = 0;
56
57 static uint64_t status_time = 0;
58
59 typedef union int_float
60 {
61 uint32_t i;
62 float f;
63 } int_float;
64
65 typedef struct rgb_t
66 {
67 uint8_t b, g, r;
68 uint8_t pad;
69 } rgb_t;
70 typedef struct rgba8_t
71 {
72 uint8_t b, g, r, a;
73 } rgba8_t;
74
75 typedef union rgba_u
76 {
77 struct
78 {
79 uint8_t b, g, r, a;
80 } rgba;
81 uint32_t u;
82 } rgba_u;
83
84 #define FIFO_SIZE 65536
85 #define FIFO_MASK (FIFO_SIZE - 1)
86 #define FIFO_ENTRY_SIZE (1 << 31)
87
88 #define FIFO_ENTRIES (voodoo->fifo_write_idx - voodoo->fifo_read_idx)
89 #define FIFO_FULL ((voodoo->fifo_write_idx - voodoo->fifo_read_idx) >= FIFO_SIZE-4)
90 #define FIFO_EMPTY (voodoo->fifo_read_idx == voodoo->fifo_write_idx)
91
92 #define FIFO_TYPE 0xff000000
93 #define FIFO_ADDR 0x00ffffff
94
95 enum
96 {
97 FIFO_INVALID = (0x00 << 24),
98 FIFO_WRITEL_REG = (0x01 << 24),
99 FIFO_WRITEW_FB = (0x02 << 24),
100 FIFO_WRITEL_FB = (0x03 << 24),
101 FIFO_WRITEL_TEX = (0x04 << 24)
102 };
103
104 #define PARAM_SIZE 1024
105 #define PARAM_MASK (PARAM_SIZE - 1)
106 #define PARAM_ENTRY_SIZE (1 << 31)
107
108 #define PARAM_ENTRIES_1 (voodoo->params_write_idx - voodoo->params_read_idx[0])
109 #define PARAM_ENTRIES_2 (voodoo->params_write_idx - voodoo->params_read_idx[1])
110 #define PARAM_FULL_1 ((voodoo->params_write_idx - voodoo->params_read_idx[0]) >= PARAM_SIZE)
111 #define PARAM_FULL_2 ((voodoo->params_write_idx - voodoo->params_read_idx[1]) >= PARAM_SIZE)
112 #define PARAM_EMPTY_1 (voodoo->params_read_idx[0] == voodoo->params_write_idx)
113 #define PARAM_EMPTY_2 (voodoo->params_read_idx[1] == voodoo->params_write_idx)
114
115 typedef struct
116 {
117 uint32_t addr_type;
118 uint32_t val;
119 } fifo_entry_t;
120
121 static rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000];
122
123 typedef struct voodoo_params_t
124 {
125 int command;
126
127 int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy;
128
129 uint32_t startR, startG, startB, startZ, startA;
130
131 int32_t dBdX, dGdX, dRdX, dAdX, dZdX;
132
133 int32_t dBdY, dGdY, dRdY, dAdY, dZdY;
134
135 int64_t startW, dWdX, dWdY;
136
137 struct
138 {
139 int64_t startS, startT, startW, p1;
140 int64_t dSdX, dTdX, dWdX, p2;
141 int64_t dSdY, dTdY, dWdY, p3;
142 } tmu[2];
143
144 uint32_t color0, color1;
145
146 uint32_t fbzMode;
147 uint32_t fbzColorPath;
148
149 uint32_t fogMode;
150 rgb_t fogColor;
151 struct
152 {
153 uint8_t fog, dfog;
154 } fogTable[64];
155
156 uint32_t alphaMode;
157
158 uint32_t zaColor;
159
160 int chromaKey_r, chromaKey_g, chromaKey_b;
161 uint32_t chromaKey;
162
163 uint32_t textureMode[2];
164 uint32_t tLOD[2];
165
166 uint32_t texBaseAddr[2], texBaseAddr1[2], texBaseAddr2[2], texBaseAddr38[2];
167
168 uint32_t tex_base[2][LOD_MAX+2];
169 uint32_t tex_end[2][LOD_MAX+2];
170 int tex_width[2];
171 int tex_w_mask[2][LOD_MAX+2];
172 int tex_w_nmask[2][LOD_MAX+2];
173 int tex_h_mask[2][LOD_MAX+2];
174 int tex_shift[2][LOD_MAX+2];
175 int tex_lod[2][LOD_MAX+2];
176 int tex_entry[2];
177 int detail_max[2], detail_bias[2], detail_scale[2];
178
179 uint32_t draw_offset, aux_offset;
180
181 int tformat[2];
182
183 int clipLeft, clipRight, clipLowY, clipHighY;
184
185 int sign;
186
187 uint32_t front_offset;
188
189 uint32_t swapbufferCMD;
190
191 uint32_t stipple;
192 } voodoo_params_t;
193
194 typedef struct texture_t
195 {
196 uint32_t base;
197 uint32_t tLOD;
198 volatile int refcount, refcount_r[2];
199 int is16;
200 uint32_t palette_checksum;
201 uint32_t addr_start[4], addr_end[4];
202 uint32_t *data;
203 } texture_t;
204
205 typedef struct voodoo_t
206 {
207 mem_mapping_t mapping;
208
209 int pci_enable;
210
211 uint8_t dac_data[8];
212 int dac_reg, dac_reg_ff;
213 uint8_t dac_readdata;
214 uint16_t dac_pll_regs[16];
215
216 float pixel_clock;
217 int line_time;
218
219 voodoo_params_t params;
220
221 uint32_t fbiInit0, fbiInit1, fbiInit2, fbiInit3, fbiInit4;
222 uint32_t fbiInit5, fbiInit6, fbiInit7; /*Voodoo 2*/
223
224 uint32_t initEnable;
225
226 uint32_t lfbMode;
227
228 uint32_t memBaseAddr;
229
230 int_float fvertexAx, fvertexAy, fvertexBx, fvertexBy, fvertexCx, fvertexCy;
231
232 uint32_t front_offset, back_offset;
233
234 uint32_t fb_read_offset, fb_write_offset;
235
236 int row_width;
237 int block_width;
238
239 uint8_t *fb_mem, *tex_mem[2];
240 uint16_t *tex_mem_w[2];
241
242 int rgb_sel;
243
244 uint32_t trexInit1[2];
245
246 uint32_t tmuConfig;
247
248 int swap_count;
249
250 int disp_buffer, draw_buffer;
251 int timer_count;
252
253 int line;
254 svga_t *svga;
255
256 uint32_t backPorch;
257 uint32_t videoDimensions;
258 uint32_t hSync, vSync;
259
260 int h_total, v_total, v_disp;
261 int h_disp;
262 int v_retrace;
263
264 struct
265 {
266 uint32_t y[4], i[4], q[4];
267 } nccTable[2][2];
268
269 rgba_u palette[2][256];
270
271 rgba_u ncc_lookup[2][2][256];
272 int ncc_dirty[2];
273
274 thread_t *fifo_thread;
275 thread_t *render_thread[2];
276 event_t *wake_fifo_thread;
277 event_t *wake_main_thread;
278 event_t *fifo_not_full_event;
279 event_t *render_not_full_event[2];
280 event_t *wake_render_thread[2];
281
282 int voodoo_busy;
283 int render_voodoo_busy[2];
284
285 int render_threads;
286 int odd_even_mask;
287
288 int pixel_count[2], texel_count[2], tri_count, frame_count;
289 int pixel_count_old[2], texel_count_old[2];
290 int wr_count, rd_count, tex_count;
291
292 int retrace_count;
293 int swap_interval;
294 uint32_t swap_offset;
295 int swap_pending;
296
297 int bilinear_enabled;
298
299 int fb_size;
300 uint32_t fb_mask;
301
302 int texture_size;
303 uint32_t texture_mask;
304
305 int dual_tmus;
306 int type;
307
308 fifo_entry_t fifo[FIFO_SIZE];
309 volatile int fifo_read_idx, fifo_write_idx;
310 volatile int cmd_read, cmd_written, cmd_written_fifo;
311
312 voodoo_params_t params_buffer[PARAM_SIZE];
313 volatile int params_read_idx[2], params_write_idx;
314
315 uint32_t cmdfifo_base, cmdfifo_end;
316 int cmdfifo_rp;
317 volatile int cmdfifo_depth_rd, cmdfifo_depth_wr;
318 uint32_t cmdfifo_amin, cmdfifo_amax;
319
320 uint32_t sSetupMode;
321 struct
322 {
323 float sVx, sVy;
324 float sRed, sGreen, sBlue, sAlpha;
325 float sVz, sWb;
326 float sW0, sS0, sT0;
327 float sW1, sS1, sT1;
328 } verts[4];
329 int vertex_num;
330 int num_verticies;
331
332 int flush;
333
334 int scrfilter;
335 int scrfilterEnabled;
336 int scrfilterThreshold;
337 int scrfilterThresholdOld;
338
339 uint32_t last_write_addr;
340
341 uint32_t fbiPixelsIn;
342 uint32_t fbiChromaFail;
343 uint32_t fbiZFuncFail;
344 uint32_t fbiAFuncFail;
345 uint32_t fbiPixelsOut;
346
347 uint32_t bltSrcBaseAddr;
348 uint32_t bltDstBaseAddr;
349 int bltSrcXYStride, bltDstXYStride;
350 uint32_t bltSrcChromaRange, bltDstChromaRange;
351 int bltSrcChromaMinR, bltSrcChromaMinG, bltSrcChromaMinB;
352 int bltSrcChromaMaxR, bltSrcChromaMaxG, bltSrcChromaMaxB;
353 int bltDstChromaMinR, bltDstChromaMinG, bltDstChromaMinB;
354 int bltDstChromaMaxR, bltDstChromaMaxG, bltDstChromaMaxB;
355
356 int bltClipRight, bltClipLeft;
357 int bltClipHighY, bltClipLowY;
358
359 int bltSrcX, bltSrcY;
360 int bltDstX, bltDstY;
361 int bltSizeX, bltSizeY;
362 int bltRop[4];
363 uint16_t bltColorFg, bltColorBg;
364
365 uint32_t bltCommand;
366
367 struct
368 {
369 int dst_x, dst_y;
370 int cur_x;
371 int size_x, size_y;
372 int x_dir, y_dir;
373 int dst_stride;
374 } blt;
375
376 rgb_t clutData[33];
377 int clutData_dirty;
378 rgb_t clutData256[256];
379 uint32_t video_16to32[0x10000];
380
381 uint8_t dirty_line[1024];
382 int dirty_line_low, dirty_line_high;
383
384 int fb_write_buffer, fb_draw_buffer;
385 int buffer_cutoff;
386
387 int read_time, write_time, burst_time;
388
389 int wake_timer;
390
391 uint8_t thefilter[256][256]; // pixel filter, feeding from one or two
392 uint8_t thefilterg[256][256]; // for green
393 uint8_t thefilterb[256][256]; // for blue
394
395 /* the voodoo adds purple lines for some reason */
396 uint16_t purpleline[256][3];
397
398 texture_t texture_cache[2][TEX_CACHE_MAX];
399 uint8_t texture_present[2][4096];
400 int texture_last_removed;
401
402 uint32_t palette_checksum[2];
403 int palette_dirty[2];
404
405 uint64_t time;
406 int render_time[2];
407
408 int use_recompiler;
409 void *codegen_data;
410
411 struct voodoo_set_t *set;
412 } voodoo_t;
413
414 typedef struct voodoo_set_t
415 {
416 voodoo_t *voodoos[2];
417
418 mem_mapping_t snoop_mapping;
419
420 int nr_cards;
421 } voodoo_set_t;
422
423 static inline void wait_for_render_thread_idle(voodoo_t *voodoo);
424
425 enum
426 {
427 SST_status = 0x000,
428 SST_intrCtrl = 0x004,
429
430 SST_vertexAx = 0x008,
431 SST_vertexAy = 0x00c,
432 SST_vertexBx = 0x010,
433 SST_vertexBy = 0x014,
434 SST_vertexCx = 0x018,
435 SST_vertexCy = 0x01c,
436
437 SST_startR = 0x0020,
438 SST_startG = 0x0024,
439 SST_startB = 0x0028,
440 SST_startZ = 0x002c,
441 SST_startA = 0x0030,
442 SST_startS = 0x0034,
443 SST_startT = 0x0038,
444 SST_startW = 0x003c,
445
446 SST_dRdX = 0x0040,
447 SST_dGdX = 0x0044,
448 SST_dBdX = 0x0048,
449 SST_dZdX = 0x004c,
450 SST_dAdX = 0x0050,
451 SST_dSdX = 0x0054,
452 SST_dTdX = 0x0058,
453 SST_dWdX = 0x005c,
454
455 SST_dRdY = 0x0060,
456 SST_dGdY = 0x0064,
457 SST_dBdY = 0x0068,
458 SST_dZdY = 0x006c,
459 SST_dAdY = 0x0070,
460 SST_dSdY = 0x0074,
461 SST_dTdY = 0x0078,
462 SST_dWdY = 0x007c,
463
464 SST_triangleCMD = 0x0080,
465
466 SST_fvertexAx = 0x088,
467 SST_fvertexAy = 0x08c,
468 SST_fvertexBx = 0x090,
469 SST_fvertexBy = 0x094,
470 SST_fvertexCx = 0x098,
471 SST_fvertexCy = 0x09c,
472
473 SST_fstartR = 0x00a0,
474 SST_fstartG = 0x00a4,
475 SST_fstartB = 0x00a8,
476 SST_fstartZ = 0x00ac,
477 SST_fstartA = 0x00b0,
478 SST_fstartS = 0x00b4,
479 SST_fstartT = 0x00b8,
480 SST_fstartW = 0x00bc,
481
482 SST_fdRdX = 0x00c0,
483 SST_fdGdX = 0x00c4,
484 SST_fdBdX = 0x00c8,
485 SST_fdZdX = 0x00cc,
486 SST_fdAdX = 0x00d0,
487 SST_fdSdX = 0x00d4,
488 SST_fdTdX = 0x00d8,
489 SST_fdWdX = 0x00dc,
490
491 SST_fdRdY = 0x00e0,
492 SST_fdGdY = 0x00e4,
493 SST_fdBdY = 0x00e8,
494 SST_fdZdY = 0x00ec,
495 SST_fdAdY = 0x00f0,
496 SST_fdSdY = 0x00f4,
497 SST_fdTdY = 0x00f8,
498 SST_fdWdY = 0x00fc,
499
500 SST_ftriangleCMD = 0x0100,
501
502 SST_fbzColorPath = 0x104,
503 SST_fogMode = 0x108,
504
505 SST_alphaMode = 0x10c,
506 SST_fbzMode = 0x110,
507 SST_lfbMode = 0x114,
508
509 SST_clipLeftRight = 0x118,
510 SST_clipLowYHighY = 0x11c,
511
512 SST_nopCMD = 0x120,
513 SST_fastfillCMD = 0x124,
514 SST_swapbufferCMD = 0x128,
515
516 SST_fogColor = 0x12c,
517 SST_zaColor = 0x130,
518 SST_chromaKey = 0x134,
519
520 SST_userIntrCMD = 0x13c,
521 SST_stipple = 0x140,
522 SST_color0 = 0x144,
523 SST_color1 = 0x148,
524
525 SST_fbiPixelsIn = 0x14c,
526 SST_fbiChromaFail = 0x150,
527 SST_fbiZFuncFail = 0x154,
528 SST_fbiAFuncFail = 0x158,
529 SST_fbiPixelsOut = 0x15c,
530
531 SST_fogTable00 = 0x160,
532 SST_fogTable01 = 0x164,
533 SST_fogTable02 = 0x168,
534 SST_fogTable03 = 0x16c,
535 SST_fogTable04 = 0x170,
536 SST_fogTable05 = 0x174,
537 SST_fogTable06 = 0x178,
538 SST_fogTable07 = 0x17c,
539 SST_fogTable08 = 0x180,
540 SST_fogTable09 = 0x184,
541 SST_fogTable0a = 0x188,
542 SST_fogTable0b = 0x18c,
543 SST_fogTable0c = 0x190,
544 SST_fogTable0d = 0x194,
545 SST_fogTable0e = 0x198,
546 SST_fogTable0f = 0x19c,
547 SST_fogTable10 = 0x1a0,
548 SST_fogTable11 = 0x1a4,
549 SST_fogTable12 = 0x1a8,
550 SST_fogTable13 = 0x1ac,
551 SST_fogTable14 = 0x1b0,
552 SST_fogTable15 = 0x1b4,
553 SST_fogTable16 = 0x1b8,
554 SST_fogTable17 = 0x1bc,
555 SST_fogTable18 = 0x1c0,
556 SST_fogTable19 = 0x1c4,
557 SST_fogTable1a = 0x1c8,
558 SST_fogTable1b = 0x1cc,
559 SST_fogTable1c = 0x1d0,
560 SST_fogTable1d = 0x1d4,
561 SST_fogTable1e = 0x1d8,
562 SST_fogTable1f = 0x1dc,
563
564 SST_cmdFifoBaseAddr = 0x1e0,
565 SST_cmdFifoBump = 0x1e4,
566 SST_cmdFifoRdPtr = 0x1e8,
567 SST_cmdFifoAMin = 0x1ec,
568 SST_cmdFifoAMax = 0x1f0,
569 SST_cmdFifoDepth = 0x1f4,
570 SST_cmdFifoHoles = 0x1f8,
571
572 SST_fbiInit4 = 0x200,
573 SST_vRetrace = 0x204,
574 SST_backPorch = 0x208,
575 SST_videoDimensions = 0x20c,
576 SST_fbiInit0 = 0x210,
577 SST_fbiInit1 = 0x214,
578 SST_fbiInit2 = 0x218,
579 SST_fbiInit3 = 0x21c,
580 SST_hSync = 0x220,
581 SST_vSync = 0x224,
582 SST_clutData = 0x228,
583 SST_dacData = 0x22c,
584
585 SST_scrFilter = 0x230,
586
587 SST_hvRetrace = 0x240,
588 SST_fbiInit5 = 0x244,
589 SST_fbiInit6 = 0x248,
590 SST_fbiInit7 = 0x24c,
591
592 SST_sSetupMode = 0x260,
593 SST_sVx = 0x264,
594 SST_sVy = 0x268,
595 SST_sARGB = 0x26c,
596 SST_sRed = 0x270,
597 SST_sGreen = 0x274,
598 SST_sBlue = 0x278,
599 SST_sAlpha = 0x27c,
600 SST_sVz = 0x280,
601 SST_sWb = 0x284,
602 SST_sW0 = 0x288,
603 SST_sS0 = 0x28c,
604 SST_sT0 = 0x290,
605 SST_sW1 = 0x294,
606 SST_sS1 = 0x298,
607 SST_sT1 = 0x29c,
608
609 SST_sDrawTriCMD = 0x2a0,
610 SST_sBeginTriCMD = 0x2a4,
611
612 SST_bltSrcBaseAddr = 0x2c0,
613 SST_bltDstBaseAddr = 0x2c4,
614 SST_bltXYStrides = 0x2c8,
615 SST_bltSrcChromaRange = 0x2cc,
616 SST_bltDstChromaRange = 0x2d0,
617 SST_bltClipX = 0x2d4,
618 SST_bltClipY = 0x2d8,
619
620 SST_bltSrcXY = 0x2e0,
621 SST_bltDstXY = 0x2e4,
622 SST_bltSize = 0x2e8,
623 SST_bltRop = 0x2ec,
624 SST_bltColor = 0x2f0,
625
626 SST_bltCommand = 0x2f8,
627 SST_bltData = 0x2fc,
628
629 SST_textureMode = 0x300,
630 SST_tLOD = 0x304,
631 SST_tDetail = 0x308,
632 SST_texBaseAddr = 0x30c,
633 SST_texBaseAddr1 = 0x310,
634 SST_texBaseAddr2 = 0x314,
635 SST_texBaseAddr38 = 0x318,
636
637 SST_trexInit1 = 0x320,
638
639 SST_nccTable0_Y0 = 0x324,
640 SST_nccTable0_Y1 = 0x328,
641 SST_nccTable0_Y2 = 0x32c,
642 SST_nccTable0_Y3 = 0x330,
643 SST_nccTable0_I0 = 0x334,
644 SST_nccTable0_I1 = 0x338,
645 SST_nccTable0_I2 = 0x33c,
646 SST_nccTable0_I3 = 0x340,
647 SST_nccTable0_Q0 = 0x344,
648 SST_nccTable0_Q1 = 0x348,
649 SST_nccTable0_Q2 = 0x34c,
650 SST_nccTable0_Q3 = 0x350,
651
652 SST_nccTable1_Y0 = 0x354,
653 SST_nccTable1_Y1 = 0x358,
654 SST_nccTable1_Y2 = 0x35c,
655 SST_nccTable1_Y3 = 0x360,
656 SST_nccTable1_I0 = 0x364,
657 SST_nccTable1_I1 = 0x368,
658 SST_nccTable1_I2 = 0x36c,
659 SST_nccTable1_I3 = 0x370,
660 SST_nccTable1_Q0 = 0x374,
661 SST_nccTable1_Q1 = 0x378,
662 SST_nccTable1_Q2 = 0x37c,
663 SST_nccTable1_Q3 = 0x380,
664
665 SST_remap_status = 0x000 | 0x400,
666
667 SST_remap_vertexAx = 0x008 | 0x400,
668 SST_remap_vertexAy = 0x00c | 0x400,
669 SST_remap_vertexBx = 0x010 | 0x400,
670 SST_remap_vertexBy = 0x014 | 0x400,
671 SST_remap_vertexCx = 0x018 | 0x400,
672 SST_remap_vertexCy = 0x01c | 0x400,
673
674 SST_remap_startR = 0x0020 | 0x400,
675 SST_remap_startG = 0x002c | 0x400,
676 SST_remap_startB = 0x0038 | 0x400,
677 SST_remap_startZ = 0x0044 | 0x400,
678 SST_remap_startA = 0x0050 | 0x400,
679 SST_remap_startS = 0x005c | 0x400,
680 SST_remap_startT = 0x0068 | 0x400,
681 SST_remap_startW = 0x0074 | 0x400,
682
683 SST_remap_dRdX = 0x0024 | 0x400,
684 SST_remap_dGdX = 0x0030 | 0x400,
685 SST_remap_dBdX = 0x003c | 0x400,
686 SST_remap_dZdX = 0x0048 | 0x400,
687 SST_remap_dAdX = 0x0054 | 0x400,
688 SST_remap_dSdX = 0x0060 | 0x400,
689 SST_remap_dTdX = 0x006c | 0x400,
690 SST_remap_dWdX = 0x0078 | 0x400,
691
692 SST_remap_dRdY = 0x0028 | 0x400,
693 SST_remap_dGdY = 0x0034 | 0x400,
694 SST_remap_dBdY = 0x0040 | 0x400,
695 SST_remap_dZdY = 0x004c | 0x400,
696 SST_remap_dAdY = 0x0058 | 0x400,
697 SST_remap_dSdY = 0x0064 | 0x400,
698 SST_remap_dTdY = 0x0070 | 0x400,
699 SST_remap_dWdY = 0x007c | 0x400,
700
701 SST_remap_triangleCMD = 0x0080 | 0x400,
702
703 SST_remap_fvertexAx = 0x088 | 0x400,
704 SST_remap_fvertexAy = 0x08c | 0x400,
705 SST_remap_fvertexBx = 0x090 | 0x400,
706 SST_remap_fvertexBy = 0x094 | 0x400,
707 SST_remap_fvertexCx = 0x098 | 0x400,
708 SST_remap_fvertexCy = 0x09c | 0x400,
709
710 SST_remap_fstartR = 0x00a0 | 0x400,
711 SST_remap_fstartG = 0x00ac | 0x400,
712 SST_remap_fstartB = 0x00b8 | 0x400,
713 SST_remap_fstartZ = 0x00c4 | 0x400,
714 SST_remap_fstartA = 0x00d0 | 0x400,
715 SST_remap_fstartS = 0x00dc | 0x400,
716 SST_remap_fstartT = 0x00e8 | 0x400,
717 SST_remap_fstartW = 0x00f4 | 0x400,
718
719 SST_remap_fdRdX = 0x00a4 | 0x400,
720 SST_remap_fdGdX = 0x00b0 | 0x400,
721 SST_remap_fdBdX = 0x00bc | 0x400,
722 SST_remap_fdZdX = 0x00c8 | 0x400,
723 SST_remap_fdAdX = 0x00d4 | 0x400,
724 SST_remap_fdSdX = 0x00e0 | 0x400,
725 SST_remap_fdTdX = 0x00ec | 0x400,
726 SST_remap_fdWdX = 0x00f8 | 0x400,
727
728 SST_remap_fdRdY = 0x00a8 | 0x400,
729 SST_remap_fdGdY = 0x00b4 | 0x400,
730 SST_remap_fdBdY = 0x00c0 | 0x400,
731 SST_remap_fdZdY = 0x00cc | 0x400,
732 SST_remap_fdAdY = 0x00d8 | 0x400,
733 SST_remap_fdSdY = 0x00e4 | 0x400,
734 SST_remap_fdTdY = 0x00f0 | 0x400,
735 SST_remap_fdWdY = 0x00fc | 0x400,
736 };
737
738 enum
739 {
740 LFB_WRITE_FRONT = 0x0000,
741 LFB_WRITE_BACK = 0x0010,
742 LFB_WRITE_MASK = 0x0030
743 };
744
745 enum
746 {
747 LFB_READ_FRONT = 0x0000,
748 LFB_READ_BACK = 0x0040,
749 LFB_READ_AUX = 0x0080,
750 LFB_READ_MASK = 0x00c0
751 };
752
753 enum
754 {
755 LFB_FORMAT_RGB565 = 0,
756 LFB_FORMAT_RGB555 = 1,
757 LFB_FORMAT_ARGB1555 = 2,
758 LFB_FORMAT_ARGB8888 = 5,
759 LFB_FORMAT_DEPTH = 15,
760 LFB_FORMAT_MASK = 15
761 };
762
763 enum
764 {
765 LFB_WRITE_COLOUR = 1,
766 LFB_WRITE_DEPTH = 2
767 };
768
769 enum
770 {
771 FBZ_CHROMAKEY = (1 << 1),
772 FBZ_W_BUFFER = (1 << 3),
773 FBZ_DEPTH_ENABLE = (1 << 4),
774
775 FBZ_DITHER = (1 << 8),
776 FBZ_RGB_WMASK = (1 << 9),
777 FBZ_DEPTH_WMASK = (1 << 10),
778 FBZ_DITHER_2x2 = (1 << 11),
779
780 FBZ_DRAW_FRONT = 0x0000,
781 FBZ_DRAW_BACK = 0x4000,
782 FBZ_DRAW_MASK = 0xc000,
783
784 FBZ_DEPTH_BIAS = (1 << 16),
785
786 FBZ_DEPTH_SOURCE = (1 << 20),
787
788 FBZ_PARAM_ADJUST = (1 << 26)
789 };
790
791 enum
792 {
793 TEX_RGB332 = 0x0,
794 TEX_Y4I2Q2 = 0x1,
795 TEX_A8 = 0x2,
796 TEX_I8 = 0x3,
797 TEX_AI8 = 0x4,
798 TEX_PAL8 = 0x5,
799 TEX_APAL8 = 0x6,
800 TEX_ARGB8332 = 0x8,
801 TEX_A8Y4I2Q2 = 0x9,
802 TEX_R5G6B5 = 0xa,
803 TEX_ARGB1555 = 0xb,
804 TEX_ARGB4444 = 0xc,
805 TEX_A8I8 = 0xd,
806 TEX_APAL88 = 0xe
807 };
808
809 enum
810 {
811 TEXTUREMODE_NCC_SEL = (1 << 5),
812 TEXTUREMODE_TCLAMPS = (1 << 6),
813 TEXTUREMODE_TCLAMPT = (1 << 7),
814 TEXTUREMODE_TRILINEAR = (1 << 30)
815 };
816
817 enum
818 {
819 FBIINIT0_VGA_PASS = 1,
820 FBIINIT0_GRAPHICS_RESET = (1 << 1)
821 };
822
823 enum
824 {
825 FBIINIT1_MULTI_SST = (1 << 2), /*Voodoo Graphics only*/
826 FBIINIT1_VIDEO_RESET = (1 << 8),
827 FBIINIT1_SLI_ENABLE = (1 << 23)
828 };
829
830 enum
831 {
832 FBIINIT2_SWAP_ALGORITHM_MASK = (3 << 9)
833 };
834
835 enum
836 {
837 FBIINIT2_SWAP_ALGORITHM_DAC_VSYNC = (0 << 9),
838 FBIINIT2_SWAP_ALGORITHM_DAC_DATA = (1 << 9),
839 FBIINIT2_SWAP_ALGORITHM_PCI_FIFO_STALL = (2 << 9),
840 FBIINIT2_SWAP_ALGORITHM_SLI_SYNC = (3 << 9)
841 };
842
843 enum
844 {
845 FBIINIT3_REMAP = 1
846 };
847
848 enum
849 {
850 FBIINIT5_MULTI_CVG = (1 << 14)
851 };
852
853 enum
854 {
855 FBIINIT7_CMDFIFO_ENABLE = (1 << 8)
856 };
857
858 enum
859 {
860 CC_LOCALSELECT_ITER_RGB = 0,
861 CC_LOCALSELECT_TEX = 1,
862 CC_LOCALSELECT_COLOR1 = 2,
863 CC_LOCALSELECT_LFB = 3
864 };
865
866 enum
867 {
868 CCA_LOCALSELECT_ITER_A = 0,
869 CCA_LOCALSELECT_COLOR0 = 1,
870 CCA_LOCALSELECT_ITER_Z = 2
871 };
872
873 enum
874 {
875 C_SEL_ITER_RGB = 0,
876 C_SEL_TEX = 1,
877 C_SEL_COLOR1 = 2,
878 C_SEL_LFB = 3
879 };
880
881 enum
882 {
883 A_SEL_ITER_A = 0,
884 A_SEL_TEX = 1,
885 A_SEL_COLOR1 = 2,
886 A_SEL_LFB = 3
887 };
888
889 enum
890 {
891 CC_MSELECT_ZERO = 0,
892 CC_MSELECT_CLOCAL = 1,
893 CC_MSELECT_AOTHER = 2,
894 CC_MSELECT_ALOCAL = 3,
895 CC_MSELECT_TEX = 4,
896 CC_MSELECT_TEXRGB = 5
897 };
898
899 enum
900 {
901 CCA_MSELECT_ZERO = 0,
902 CCA_MSELECT_ALOCAL = 1,
903 CCA_MSELECT_AOTHER = 2,
904 CCA_MSELECT_ALOCAL2 = 3,
905 CCA_MSELECT_TEX = 4
906 };
907
908 enum
909 {
910 TC_MSELECT_ZERO = 0,
911 TC_MSELECT_CLOCAL = 1,
912 TC_MSELECT_AOTHER = 2,
913 TC_MSELECT_ALOCAL = 3,
914 TC_MSELECT_DETAIL = 4,
915 TC_MSELECT_LOD_FRAC = 5
916 };
917
918 enum
919 {
920 TCA_MSELECT_ZERO = 0,
921 TCA_MSELECT_CLOCAL = 1,
922 TCA_MSELECT_AOTHER = 2,
923 TCA_MSELECT_ALOCAL = 3,
924 TCA_MSELECT_DETAIL = 4,
925 TCA_MSELECT_LOD_FRAC = 5
926 };
927
928 enum
929 {
930 CC_ADD_CLOCAL = 1,
931 CC_ADD_ALOCAL = 2
932 };
933
934 enum
935 {
936 CCA_ADD_CLOCAL = 1,
937 CCA_ADD_ALOCAL = 2
938 };
939
940 enum
941 {
942 AFUNC_AZERO = 0x0,
943 AFUNC_ASRC_ALPHA = 0x1,
944 AFUNC_A_COLOR = 0x2,
945 AFUNC_ADST_ALPHA = 0x3,
946 AFUNC_AONE = 0x4,
947 AFUNC_AOMSRC_ALPHA = 0x5,
948 AFUNC_AOM_COLOR = 0x6,
949 AFUNC_AOMDST_ALPHA = 0x7,
950 AFUNC_ASATURATE = 0xf
951 };
952
953 enum
954 {
955 AFUNC_ACOLORBEFOREFOG = 0xf
956 };
957
958 enum
959 {
960 AFUNC_NEVER = 0,
961 AFUNC_LESSTHAN = 1,
962 AFUNC_EQUAL = 2,
963 AFUNC_LESSTHANEQUAL = 3,
964 AFUNC_GREATERTHAN = 4,
965 AFUNC_NOTEQUAL = 5,
966 AFUNC_GREATERTHANEQUAL = 6,
967 AFUNC_ALWAYS = 7
968 };
969
970 enum
971 {
972 DEPTHOP_NEVER = 0,
973 DEPTHOP_LESSTHAN = 1,
974 DEPTHOP_EQUAL = 2,
975 DEPTHOP_LESSTHANEQUAL = 3,
976 DEPTHOP_GREATERTHAN = 4,
977 DEPTHOP_NOTEQUAL = 5,
978 DEPTHOP_GREATERTHANEQUAL = 6,
979 DEPTHOP_ALWAYS = 7
980 };
981
982 enum
983 {
984 FOG_ENABLE = 0x01,
985 FOG_ADD = 0x02,
986 FOG_MULT = 0x04,
987 FOG_ALPHA = 0x08,
988 FOG_Z = 0x10,
989 FOG_W = 0x18,
990 FOG_CONSTANT = 0x20
991 };
992
993 enum
994 {
995 LOD_ODD = (1 << 18),
996 LOD_SPLIT = (1 << 19),
997 LOD_S_IS_WIDER = (1 << 20),
998 LOD_TMULTIBASEADDR = (1 << 24),
999 LOD_TMIRROR_S = (1 << 28),
1000 LOD_TMIRROR_T = (1 << 29)
1001 };
1002 enum
1003 {
1004 CMD_INVALID = 0,
1005 CMD_DRAWTRIANGLE,
1006 CMD_FASTFILL,
1007 CMD_SWAPBUF
1008 };
1009
1010 enum
1011 {
1012 FBZCP_TEXTURE_ENABLED = (1 << 27)
1013 };
1014
1015 enum
1016 {
1017 BLTCMD_SRC_TILED = (1 << 14),
1018 BLTCMD_DST_TILED = (1 << 15)
1019 };
1020
1021 enum
1022 {
1023 INITENABLE_SLI_MASTER_SLAVE = (1 << 11)
1024 };
1025
1026 #define TEXTUREMODE_MASK 0x3ffff000
1027 #define TEXTUREMODE_PASSTHROUGH 0
1028
1029 #define TEXTUREMODE_LOCAL_MASK 0x00643000
1030 #define TEXTUREMODE_LOCAL 0x00241000
1031
1032 static void voodoo_threshold_check(voodoo_t *voodoo);
1033
voodoo_update_ncc(voodoo_t * voodoo,int tmu)1034 static void voodoo_update_ncc(voodoo_t *voodoo, int tmu)
1035 {
1036 int tbl;
1037
1038 for (tbl = 0; tbl < 2; tbl++)
1039 {
1040 int col;
1041
1042 for (col = 0; col < 256; col++)
1043 {
1044 int y = (col >> 4), i = (col >> 2) & 3, q = col & 3;
1045 int i_r, i_g, i_b;
1046 int q_r, q_g, q_b;
1047
1048 y = (voodoo->nccTable[tmu][tbl].y[y >> 2] >> ((y & 3) * 8)) & 0xff;
1049
1050 i_r = (voodoo->nccTable[tmu][tbl].i[i] >> 18) & 0x1ff;
1051 if (i_r & 0x100)
1052 i_r |= 0xfffffe00;
1053 i_g = (voodoo->nccTable[tmu][tbl].i[i] >> 9) & 0x1ff;
1054 if (i_g & 0x100)
1055 i_g |= 0xfffffe00;
1056 i_b = voodoo->nccTable[tmu][tbl].i[i] & 0x1ff;
1057 if (i_b & 0x100)
1058 i_b |= 0xfffffe00;
1059
1060 q_r = (voodoo->nccTable[tmu][tbl].q[q] >> 18) & 0x1ff;
1061 if (q_r & 0x100)
1062 q_r |= 0xfffffe00;
1063 q_g = (voodoo->nccTable[tmu][tbl].q[q] >> 9) & 0x1ff;
1064 if (q_g & 0x100)
1065 q_g |= 0xfffffe00;
1066 q_b = voodoo->nccTable[tmu][tbl].q[q] & 0x1ff;
1067 if (q_b & 0x100)
1068 q_b |= 0xfffffe00;
1069
1070 voodoo->ncc_lookup[tmu][tbl][col].rgba.r = CLAMP(y + i_r + q_r);
1071 voodoo->ncc_lookup[tmu][tbl][col].rgba.g = CLAMP(y + i_g + q_g);
1072 voodoo->ncc_lookup[tmu][tbl][col].rgba.b = CLAMP(y + i_b + q_b);
1073 voodoo->ncc_lookup[tmu][tbl][col].rgba.a = 0xff;
1074 }
1075 }
1076 }
1077
1078 #define SLI_ENABLED (voodoo->fbiInit1 & FBIINIT1_SLI_ENABLE)
1079 #define TRIPLE_BUFFER ((voodoo->fbiInit2 & 0x10) || (voodoo->fbiInit5 & 0x600) == 0x400)
voodoo_recalc(voodoo_t * voodoo)1080 static void voodoo_recalc(voodoo_t *voodoo)
1081 {
1082 uint32_t buffer_offset = ((voodoo->fbiInit2 >> 11) & 511) * 4096;
1083
1084 voodoo->params.front_offset = voodoo->disp_buffer*buffer_offset;
1085 voodoo->back_offset = voodoo->draw_buffer*buffer_offset;
1086
1087 voodoo->buffer_cutoff = TRIPLE_BUFFER ? (buffer_offset * 4) : (buffer_offset * 3);
1088 if (TRIPLE_BUFFER)
1089 voodoo->params.aux_offset = buffer_offset * 3;
1090 else
1091 voodoo->params.aux_offset = buffer_offset * 2;
1092
1093 switch (voodoo->lfbMode & LFB_WRITE_MASK)
1094 {
1095 case LFB_WRITE_FRONT:
1096 voodoo->fb_write_offset = voodoo->params.front_offset;
1097 voodoo->fb_write_buffer = voodoo->disp_buffer;
1098 break;
1099 case LFB_WRITE_BACK:
1100 voodoo->fb_write_offset = voodoo->back_offset;
1101 voodoo->fb_write_buffer = voodoo->draw_buffer;
1102 break;
1103
1104 default:
1105 /*BreakNeck sets invalid LFB write buffer select*/
1106 voodoo->fb_write_offset = voodoo->params.front_offset;
1107 break;
1108 }
1109
1110 switch (voodoo->lfbMode & LFB_READ_MASK)
1111 {
1112 case LFB_READ_FRONT:
1113 voodoo->fb_read_offset = voodoo->params.front_offset;
1114 break;
1115 case LFB_READ_BACK:
1116 voodoo->fb_read_offset = voodoo->back_offset;
1117 break;
1118 case LFB_READ_AUX:
1119 voodoo->fb_read_offset = voodoo->params.aux_offset;
1120 break;
1121
1122 default:
1123 fatal("voodoo_recalc : unknown lfb source\n");
1124 }
1125
1126 switch (voodoo->params.fbzMode & FBZ_DRAW_MASK)
1127 {
1128 case FBZ_DRAW_FRONT:
1129 voodoo->params.draw_offset = voodoo->params.front_offset;
1130 voodoo->fb_draw_buffer = voodoo->disp_buffer;
1131 break;
1132 case FBZ_DRAW_BACK:
1133 voodoo->params.draw_offset = voodoo->back_offset;
1134 voodoo->fb_draw_buffer = voodoo->draw_buffer;
1135 break;
1136
1137 default:
1138 fatal("voodoo_recalc : unknown draw buffer\n");
1139 }
1140
1141 voodoo->block_width = ((voodoo->fbiInit1 >> 4) & 15) * 2;
1142 if (voodoo->fbiInit6 & (1 << 30))
1143 voodoo->block_width += 1;
1144 if (voodoo->fbiInit1 & (1 << 24))
1145 voodoo->block_width += 32;
1146 voodoo->row_width = voodoo->block_width * 32 * 2;
1147
1148 /* pclog("voodoo_recalc : front_offset %08X back_offset %08X aux_offset %08X draw_offset %08x\n", voodoo->params.front_offset, voodoo->back_offset, voodoo->params.aux_offset, voodoo->params.draw_offset);
1149 pclog(" fb_read_offset %08X fb_write_offset %08X row_width %i %08x %08x\n", voodoo->fb_read_offset, voodoo->fb_write_offset, voodoo->row_width, voodoo->lfbMode, voodoo->params.fbzMode);*/
1150 }
1151
voodoo_recalc_tex(voodoo_t * voodoo,int tmu)1152 static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu)
1153 {
1154 int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3;
1155 int width = 256, height = 256;
1156 int shift = 8;
1157 int lod;
1158 uint32_t base = voodoo->params.texBaseAddr[tmu];
1159 uint32_t offset = 0;
1160 int tex_lod = 0;
1161
1162 if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER)
1163 height >>= aspect;
1164 else
1165 {
1166 width >>= aspect;
1167 shift -= aspect;
1168 }
1169
1170 if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD))
1171 {
1172 width >>= 1;
1173 height >>= 1;
1174 shift--;
1175 tex_lod++;
1176 if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)
1177 base = voodoo->params.texBaseAddr1[tmu];
1178 }
1179
1180 for (lod = 0; lod <= LOD_MAX+1; lod++)
1181 {
1182 if (!width)
1183 width = 1;
1184 if (!height)
1185 height = 1;
1186 if (shift < 0)
1187 shift = 0;
1188 voodoo->params.tex_base[tmu][lod] = base + offset;
1189 if (voodoo->params.tformat[tmu] & 8)
1190 voodoo->params.tex_end[tmu][lod] = base + offset + (width * height * 2);
1191 else
1192 voodoo->params.tex_end[tmu][lod] = base + offset + (width * height);
1193 voodoo->params.tex_w_mask[tmu][lod] = width - 1;
1194 voodoo->params.tex_w_nmask[tmu][lod] = ~(width - 1);
1195 voodoo->params.tex_h_mask[tmu][lod] = height - 1;
1196 voodoo->params.tex_shift[tmu][lod] = shift;
1197 voodoo->params.tex_lod[tmu][lod] = tex_lod;
1198
1199 if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) || ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD)))
1200 {
1201 if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0)
1202 {
1203 if (voodoo->params.tformat[tmu] & 8)
1204 offset += width * height * 2;
1205 else
1206 offset += width * height;
1207
1208 if (voodoo->params.tLOD[tmu] & LOD_SPLIT)
1209 {
1210 width >>= 2;
1211 height >>= 2;
1212 shift -= 2;
1213 tex_lod += 2;
1214 }
1215 else
1216 {
1217 width >>= 1;
1218 height >>= 1;
1219 shift--;
1220 tex_lod++;
1221 }
1222
1223 if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)
1224 {
1225 switch (tex_lod)
1226 {
1227 case 0:
1228 base = voodoo->params.texBaseAddr[tmu];
1229 break;
1230 case 1:
1231 base = voodoo->params.texBaseAddr1[tmu];
1232 break;
1233 case 2:
1234 base = voodoo->params.texBaseAddr2[tmu];
1235 break;
1236 default:
1237 base = voodoo->params.texBaseAddr38[tmu];
1238 break;
1239 }
1240 }
1241 }
1242 }
1243 }
1244
1245 voodoo->params.tex_width[tmu] = width;
1246 }
1247
1248 #define makergba(r, g, b, a) ((b) | ((g) << 8) | ((r) << 16) | ((a) << 24))
1249
use_texture(voodoo_t * voodoo,voodoo_params_t * params,int tmu)1250 static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
1251 {
1252 int c, d;
1253 int lod;
1254 int lod_min, lod_max;
1255 uint32_t addr = 0, addr_end;
1256 uint32_t palette_checksum;
1257
1258 lod_min = (params->tLOD[tmu] >> 2) & 15;
1259 lod_max = (params->tLOD[tmu] >> 8) & 15;
1260
1261 if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88)
1262 {
1263 if (voodoo->palette_dirty[tmu])
1264 {
1265 palette_checksum = 0;
1266
1267 for (c = 0; c < 256; c++)
1268 palette_checksum ^= voodoo->palette[tmu][c].u;
1269
1270 voodoo->palette_checksum[tmu] = palette_checksum;
1271 voodoo->palette_dirty[tmu] = 0;
1272 }
1273 else
1274 palette_checksum = voodoo->palette_checksum[tmu];
1275 }
1276 else
1277 palette_checksum = 0;
1278
1279 if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR))
1280 addr = params->texBaseAddr1[tmu];
1281 else
1282 addr = params->texBaseAddr[tmu];
1283
1284 /*Try to find texture in cache*/
1285 for (c = 0; c < TEX_CACHE_MAX; c++)
1286 {
1287 if (voodoo->texture_cache[tmu][c].base == addr &&
1288 voodoo->texture_cache[tmu][c].tLOD == (params->tLOD[tmu] & 0xf00fff) &&
1289 voodoo->texture_cache[tmu][c].palette_checksum == palette_checksum)
1290 {
1291 params->tex_entry[tmu] = c;
1292 voodoo->texture_cache[tmu][c].refcount++;
1293 return;
1294 }
1295 }
1296
1297 /*Texture not found, search for unused texture*/
1298 do
1299 {
1300 for (c = 0; c < TEX_CACHE_MAX; c++)
1301 {
1302 voodoo->texture_last_removed++;
1303 voodoo->texture_last_removed &= (TEX_CACHE_MAX-1);
1304 if (voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[0] &&
1305 (voodoo->render_threads == 1 || voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[1]))
1306 break;
1307 }
1308 if (c == TEX_CACHE_MAX)
1309 wait_for_render_thread_idle(voodoo);
1310 } while (c == TEX_CACHE_MAX);
1311 if (c == TEX_CACHE_MAX)
1312 fatal("Texture cache full!\n");
1313
1314 c = voodoo->texture_last_removed;
1315
1316
1317 if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR))
1318 voodoo->texture_cache[tmu][c].base = params->texBaseAddr1[tmu];
1319 else
1320 voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu];
1321 voodoo->texture_cache[tmu][c].tLOD = params->tLOD[tmu] & 0xf00fff;
1322
1323 lod_min = (params->tLOD[tmu] >> 2) & 15;
1324 lod_max = (params->tLOD[tmu] >> 8) & 15;
1325 // pclog(" add new texture to %i tformat=%i %08x LOD=%i-%i tmu=%i\n", c, voodoo->params.tformat[tmu], params->texBaseAddr[tmu], lod_min, lod_max, tmu);
1326 lod_min = MIN(lod_min, 8);
1327 lod_max = MIN(lod_max, 8);
1328 for (lod = lod_min; lod <= lod_max; lod++)
1329 {
1330 uint32_t *base = &voodoo->texture_cache[tmu][c].data[texture_offset[lod]];
1331 uint32_t tex_addr = params->tex_base[tmu][lod] & voodoo->texture_mask;
1332 int x, y;
1333 int shift = 8 - params->tex_lod[tmu][lod];
1334 rgba_u *pal;
1335
1336 //pclog(" LOD %i : %08x - %08x %i %i,%i\n", lod, params->tex_base[tmu][lod] & voodoo->texture_mask, addr, voodoo->params.tformat[tmu], voodoo->params.tex_w_mask[tmu][lod],voodoo->params.tex_h_mask[tmu][lod]);
1337
1338
1339 switch (params->tformat[tmu])
1340 {
1341 case TEX_RGB332:
1342 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1343 {
1344 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1345 {
1346 uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
1347
1348 base[x] = makergba(rgb332[dat].r, rgb332[dat].g, rgb332[dat].b, 0xff);
1349 }
1350 tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
1351 base += (1 << shift);
1352 }
1353 break;
1354
1355 case TEX_Y4I2Q2:
1356 pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0];
1357 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1358 {
1359 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1360 {
1361 uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
1362
1363 base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff);
1364 }
1365 tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
1366 base += (1 << shift);
1367 }
1368 break;
1369
1370 case TEX_A8:
1371 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1372 {
1373 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1374 {
1375 uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
1376
1377 base[x] = makergba(dat, dat, dat, dat);
1378 }
1379 tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
1380 base += (1 << shift);
1381 }
1382 break;
1383
1384 case TEX_I8:
1385 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1386 {
1387 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1388 {
1389 uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
1390
1391 base[x] = makergba(dat, dat, dat, 0xff);
1392 }
1393 tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
1394 base += (1 << shift);
1395 }
1396 break;
1397
1398 case TEX_AI8:
1399 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1400 {
1401 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1402 {
1403 uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
1404
1405 base[x] = makergba((dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0xf0) | ((dat >> 4) & 0x0f));
1406 }
1407 tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
1408 base += (1 << shift);
1409 }
1410 break;
1411
1412 case TEX_PAL8:
1413 pal = voodoo->palette[tmu];
1414 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1415 {
1416 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1417 {
1418 uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
1419
1420 base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff);
1421 }
1422 tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
1423 base += (1 << shift);
1424 }
1425 break;
1426
1427 case TEX_APAL8:
1428 pal = voodoo->palette[tmu];
1429 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1430 {
1431 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1432 {
1433 uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask];
1434
1435 int r = ((pal[dat].rgba.r & 3) << 6) | ((pal[dat].rgba.g & 0xf0) >> 2) | (pal[dat].rgba.r & 3);
1436 int g = ((pal[dat].rgba.g & 0xf) << 4) | ((pal[dat].rgba.b & 0xc0) >> 4) | ((pal[dat].rgba.g & 0xf) >> 2);
1437 int b = ((pal[dat].rgba.b & 0x3f) << 2) | ((pal[dat].rgba.b & 0x30) >> 4);
1438 int a = (pal[dat].rgba.r & 0xfc) | ((pal[dat].rgba.r & 0xc0) >> 6);
1439
1440 base[x] = makergba(r, g, b, a);
1441 }
1442 tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]);
1443 base += (1 << shift);
1444 }
1445 break;
1446
1447 case TEX_ARGB8332:
1448 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1449 {
1450 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1451 {
1452 uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
1453
1454 base[x] = makergba(rgb332[dat & 0xff].r, rgb332[dat & 0xff].g, rgb332[dat & 0xff].b, dat >> 8);
1455 }
1456 tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
1457 base += (1 << shift);
1458 }
1459 break;
1460
1461 case TEX_A8Y4I2Q2:
1462 pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0];
1463 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1464 {
1465 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1466 {
1467 uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
1468
1469 base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8);
1470 }
1471 tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
1472 base += (1 << shift);
1473 }
1474 break;
1475
1476 case TEX_R5G6B5:
1477 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1478 {
1479 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1480 {
1481 uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
1482
1483 base[x] = makergba(rgb565[dat].r, rgb565[dat].g, rgb565[dat].b, 0xff);
1484 }
1485 tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
1486 base += (1 << shift);
1487 }
1488 break;
1489
1490 case TEX_ARGB1555:
1491 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1492 {
1493 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1494 {
1495 uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
1496
1497 base[x] = makergba(argb1555[dat].r, argb1555[dat].g, argb1555[dat].b, argb1555[dat].a);
1498 }
1499 tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
1500 base += (1 << shift);
1501 }
1502 break;
1503
1504 case TEX_ARGB4444:
1505 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1506 {
1507 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1508 {
1509 uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
1510
1511 base[x] = makergba(argb4444[dat].r, argb4444[dat].g, argb4444[dat].b, argb4444[dat].a);
1512 }
1513 tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
1514 base += (1 << shift);
1515 }
1516 break;
1517
1518 case TEX_A8I8:
1519 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1520 {
1521 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1522 {
1523 uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
1524
1525 base[x] = makergba(dat & 0xff, dat & 0xff, dat & 0xff, dat >> 8);
1526 }
1527 tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
1528 base += (1 << shift);
1529 }
1530 break;
1531
1532 case TEX_APAL88:
1533 pal = voodoo->palette[tmu];
1534 for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++)
1535 {
1536 for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++)
1537 {
1538 uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask];
1539
1540 base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8);
1541 }
1542 tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1));
1543 base += (1 << shift);
1544 }
1545 break;
1546
1547 default:
1548 fatal("Unknown texture format %i\n", params->tformat[tmu]);
1549 }
1550 }
1551
1552 voodoo->texture_cache[tmu][c].is16 = voodoo->params.tformat[tmu] & 8;
1553
1554 if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88)
1555 voodoo->texture_cache[tmu][c].palette_checksum = palette_checksum;
1556 else
1557 voodoo->texture_cache[tmu][c].palette_checksum = 0;
1558
1559 if (lod_min == 0)
1560 {
1561 voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->params.tex_base[tmu][0];
1562 voodoo->texture_cache[tmu][c].addr_end[0] = voodoo->params.tex_end[tmu][0];
1563 }
1564 else
1565 voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->texture_cache[tmu][c].addr_end[0] = 0;
1566
1567 if (lod_min <= 1 && lod_max >= 1)
1568 {
1569 voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->params.tex_base[tmu][1];
1570 voodoo->texture_cache[tmu][c].addr_end[1] = voodoo->params.tex_end[tmu][1];
1571 }
1572 else
1573 voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->texture_cache[tmu][c].addr_end[1] = 0;
1574
1575 if (lod_min <= 2 && lod_max >= 2)
1576 {
1577 voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->params.tex_base[tmu][2];
1578 voodoo->texture_cache[tmu][c].addr_end[2] = voodoo->params.tex_end[tmu][2];
1579 }
1580 else
1581 voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->texture_cache[tmu][c].addr_end[2] = 0;
1582
1583 if (lod_max >= 3)
1584 {
1585 voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->params.tex_base[tmu][(lod_min > 3) ? lod_min : 3];
1586 voodoo->texture_cache[tmu][c].addr_end[3] = voodoo->params.tex_end[tmu][(lod_max < 8) ? lod_max : 8];
1587 }
1588 else
1589 voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->texture_cache[tmu][c].addr_end[3] = 0;
1590
1591
1592 for (d = 0; d < 4; d++)
1593 {
1594 addr = voodoo->texture_cache[tmu][c].addr_start[d];
1595 addr_end = voodoo->texture_cache[tmu][c].addr_end[d];
1596
1597 if (addr_end != 0)
1598 {
1599 for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT))
1600 voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
1601 }
1602 }
1603
1604 params->tex_entry[tmu] = c;
1605 voodoo->texture_cache[tmu][c].refcount++;
1606 }
1607
flush_texture_cache(voodoo_t * voodoo,uint32_t dirty_addr,int tmu)1608 static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu)
1609 {
1610 int wait_for_idle = 0;
1611 int c;
1612
1613 memset(voodoo->texture_present[tmu], 0, sizeof(voodoo->texture_present[0]));
1614 // pclog("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present));
1615 for (c = 0; c < TEX_CACHE_MAX; c++)
1616 {
1617 if (voodoo->texture_cache[tmu][c].base != -1)
1618 {
1619 int d;
1620
1621 for (d = 0; d < 4; d++)
1622 {
1623 int addr_start = voodoo->texture_cache[tmu][c].addr_start[d];
1624 int addr_end = voodoo->texture_cache[tmu][c].addr_end[d];
1625
1626 if (addr_end != 0)
1627 {
1628 int addr_start_masked = addr_start & voodoo->texture_mask & ~0x3ff;
1629 int addr_end_masked = ((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff;
1630
1631 if (addr_end_masked < addr_start_masked)
1632 addr_end_masked = voodoo->texture_mask+1;
1633 if (dirty_addr >= addr_start_masked && dirty_addr < addr_end_masked)
1634 {
1635 // pclog(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base);
1636
1637 if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] ||
1638 (voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1]))
1639 wait_for_idle = 1;
1640
1641 voodoo->texture_cache[tmu][c].base = -1;
1642 }
1643 else
1644 {
1645 for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT))
1646 voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1;
1647 }
1648 }
1649 }
1650 }
1651 }
1652 if (wait_for_idle)
1653 wait_for_render_thread_idle(voodoo);
1654 }
1655
1656 typedef struct voodoo_state_t
1657 {
1658 int xstart, xend, xdir;
1659 uint32_t base_r, base_g, base_b, base_a, base_z;
1660 struct
1661 {
1662 int64_t base_s, base_t, base_w;
1663 int lod;
1664 } tmu[2];
1665 int64_t base_w;
1666 int lod;
1667 int lod_min[2], lod_max[2];
1668 int dx1, dx2;
1669 int y, yend, ydir;
1670 int32_t dxAB, dxAC, dxBC;
1671 int tex_b[2], tex_g[2], tex_r[2], tex_a[2];
1672 int tex_s, tex_t;
1673 int clamp_s[2], clamp_t[2];
1674
1675 int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy;
1676
1677 uint32_t *tex[2][LOD_MAX+1];
1678 int tformat;
1679
1680 int *tex_w_mask[2];
1681 int *tex_h_mask[2];
1682 int *tex_shift[2];
1683 int *tex_lod[2];
1684
1685 uint16_t *fb_mem, *aux_mem;
1686
1687 int32_t ib, ig, ir, ia;
1688 int32_t z;
1689
1690 int32_t new_depth;
1691
1692 int64_t tmu0_s, tmu0_t;
1693 int64_t tmu0_w;
1694 int64_t tmu1_s, tmu1_t;
1695 int64_t tmu1_w;
1696 int64_t w;
1697
1698 int pixel_count, texel_count;
1699 int x, x2;
1700
1701 uint32_t w_depth;
1702
1703 float log_temp;
1704 uint32_t ebp_store;
1705 uint32_t texBaseAddr;
1706
1707 int lod_frac[2];
1708 } voodoo_state_t;
1709
1710 static int voodoo_output = 0;
1711
1712 static uint8_t logtable[256] =
1713 {
1714 0x00,0x01,0x02,0x04,0x05,0x07,0x08,0x09,0x0b,0x0c,0x0e,0x0f,0x10,0x12,0x13,0x15,
1715 0x16,0x17,0x19,0x1a,0x1b,0x1d,0x1e,0x1f,0x21,0x22,0x23,0x25,0x26,0x27,0x28,0x2a,
1716 0x2b,0x2c,0x2e,0x2f,0x30,0x31,0x33,0x34,0x35,0x36,0x38,0x39,0x3a,0x3b,0x3d,0x3e,
1717 0x3f,0x40,0x41,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x50,0x51,
1718 0x52,0x53,0x54,0x55,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x60,0x61,0x62,0x63,
1719 0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,
1720 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x83,0x84,0x85,
1721 0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,
1722 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa2,0xa3,
1723 0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xad,0xae,0xaf,0xb0,0xb1,0xb2,
1724 0xb3,0xb4,0xb5,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbc,0xbd,0xbe,0xbf,0xc0,
1725 0xc1,0xc2,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xcd,
1726 0xce,0xcf,0xd0,0xd1,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd6,0xd7,0xd8,0xd9,0xda,0xda,
1727 0xdb,0xdc,0xdd,0xde,0xde,0xdf,0xe0,0xe1,0xe1,0xe2,0xe3,0xe4,0xe5,0xe5,0xe6,0xe7,
1728 0xe8,0xe8,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3,
1729 0xf4,0xf5,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xfa,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff
1730 };
1731
fastlog(uint64_t val)1732 static inline int fastlog(uint64_t val)
1733 {
1734 uint64_t oldval = val;
1735 int exp = 63;
1736 int frac;
1737
1738 if (!val || val & (1ULL << 63))
1739 return 0x80000000;
1740
1741 if (!(val & 0xffffffff00000000))
1742 {
1743 exp -= 32;
1744 val <<= 32;
1745 }
1746 if (!(val & 0xffff000000000000))
1747 {
1748 exp -= 16;
1749 val <<= 16;
1750 }
1751 if (!(val & 0xff00000000000000))
1752 {
1753 exp -= 8;
1754 val <<= 8;
1755 }
1756 if (!(val & 0xf000000000000000))
1757 {
1758 exp -= 4;
1759 val <<= 4;
1760 }
1761 if (!(val & 0xc000000000000000))
1762 {
1763 exp -= 2;
1764 val <<= 2;
1765 }
1766 if (!(val & 0x8000000000000000))
1767 {
1768 exp -= 1;
1769 val <<= 1;
1770 }
1771
1772 if (exp >= 8)
1773 frac = (oldval >> (exp - 8)) & 0xff;
1774 else
1775 frac = (oldval << (8 - exp)) & 0xff;
1776
1777 return (exp << 8) | logtable[frac];
1778 }
1779
voodoo_fls(uint16_t val)1780 static inline int voodoo_fls(uint16_t val)
1781 {
1782 int num = 0;
1783
1784 //pclog("fls(%04x) = ", val);
1785 if (!(val & 0xff00))
1786 {
1787 num += 8;
1788 val <<= 8;
1789 }
1790 if (!(val & 0xf000))
1791 {
1792 num += 4;
1793 val <<= 4;
1794 }
1795 if (!(val & 0xc000))
1796 {
1797 num += 2;
1798 val <<= 2;
1799 }
1800 if (!(val & 0x8000))
1801 {
1802 num += 1;
1803 val <<= 1;
1804 }
1805 //pclog("%i %04x\n", num, val);
1806 return num;
1807 }
1808
1809 typedef struct voodoo_texture_state_t
1810 {
1811 int s, t;
1812 int w_mask, h_mask;
1813 int tex_shift;
1814 } voodoo_texture_state_t;
1815
tex_read(voodoo_state_t * state,voodoo_texture_state_t * texture_state,int tmu)1816 static inline void tex_read(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int tmu)
1817 {
1818 uint32_t dat;
1819
1820 if (texture_state->s & ~texture_state->w_mask)
1821 {
1822 if (state->clamp_s[tmu])
1823 {
1824 if (texture_state->s < 0)
1825 texture_state->s = 0;
1826 if (texture_state->s > texture_state->w_mask)
1827 texture_state->s = texture_state->w_mask;
1828 }
1829 else
1830 texture_state->s &= texture_state->w_mask;
1831 }
1832 if (texture_state->t & ~texture_state->h_mask)
1833 {
1834 if (state->clamp_t[tmu])
1835 {
1836 if (texture_state->t < 0)
1837 texture_state->t = 0;
1838 if (texture_state->t > texture_state->h_mask)
1839 texture_state->t = texture_state->h_mask;
1840 }
1841 else
1842 texture_state->t &= texture_state->h_mask;
1843 }
1844
1845 dat = state->tex[tmu][state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)];
1846
1847 state->tex_b[tmu] = dat & 0xff;
1848 state->tex_g[tmu] = (dat >> 8) & 0xff;
1849 state->tex_r[tmu] = (dat >> 16) & 0xff;
1850 state->tex_a[tmu] = (dat >> 24) & 0xff;
1851 }
1852
1853 #define LOW4(x) ((x & 0x0f) | ((x & 0x0f) << 4))
1854 #define HIGH4(x) ((x & 0xf0) | ((x & 0xf0) >> 4))
1855
tex_read_4(voodoo_state_t * state,voodoo_texture_state_t * texture_state,int s,int t,int * d,int tmu,int x)1856 static inline void tex_read_4(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int s, int t, int *d, int tmu, int x)
1857 {
1858 rgba_u dat[4];
1859
1860 if (((s | (s + 1)) & ~texture_state->w_mask) || ((t | (t + 1)) & ~texture_state->h_mask))
1861 {
1862 int c;
1863 for (c = 0; c < 4; c++)
1864 {
1865 int _s = s + (c & 1);
1866 int _t = t + ((c & 2) >> 1);
1867
1868 if (_s & ~texture_state->w_mask)
1869 {
1870 if (state->clamp_s[tmu])
1871 {
1872 if (_s < 0)
1873 _s = 0;
1874 if (_s > texture_state->w_mask)
1875 _s = texture_state->w_mask;
1876 }
1877 else
1878 _s &= texture_state->w_mask;
1879 }
1880 if (_t & ~texture_state->h_mask)
1881 {
1882 if (state->clamp_t[tmu])
1883 {
1884 if (_t < 0)
1885 _t = 0;
1886 if (_t > texture_state->h_mask)
1887 _t = texture_state->h_mask;
1888 }
1889 else
1890 _t &= texture_state->h_mask;
1891 }
1892 dat[c].u = state->tex[tmu][state->lod][_s + (_t << texture_state->tex_shift)];
1893 }
1894 }
1895 else
1896 {
1897 dat[0].u = state->tex[tmu][state->lod][s + (t << texture_state->tex_shift)];
1898 dat[1].u = state->tex[tmu][state->lod][s + 1 + (t << texture_state->tex_shift)];
1899 dat[2].u = state->tex[tmu][state->lod][s + ((t + 1) << texture_state->tex_shift)];
1900 dat[3].u = state->tex[tmu][state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)];
1901 }
1902
1903 state->tex_r[tmu] = (dat[0].rgba.r * d[0] + dat[1].rgba.r * d[1] + dat[2].rgba.r * d[2] + dat[3].rgba.r * d[3]) >> 8;
1904 state->tex_g[tmu] = (dat[0].rgba.g * d[0] + dat[1].rgba.g * d[1] + dat[2].rgba.g * d[2] + dat[3].rgba.g * d[3]) >> 8;
1905 state->tex_b[tmu] = (dat[0].rgba.b * d[0] + dat[1].rgba.b * d[1] + dat[2].rgba.b * d[2] + dat[3].rgba.b * d[3]) >> 8;
1906 state->tex_a[tmu] = (dat[0].rgba.a * d[0] + dat[1].rgba.a * d[1] + dat[2].rgba.a * d[2] + dat[3].rgba.a * d[3]) >> 8;
1907 }
1908
voodoo_get_texture(voodoo_t * voodoo,voodoo_params_t * params,voodoo_state_t * state,int tmu,int x)1909 static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x)
1910 {
1911 voodoo_texture_state_t texture_state;
1912 int d[4];
1913 int s, t;
1914 int tex_lod = state->tex_lod[tmu][state->lod];
1915
1916 texture_state.w_mask = state->tex_w_mask[tmu][state->lod];
1917 texture_state.h_mask = state->tex_h_mask[tmu][state->lod];
1918 texture_state.tex_shift = 8 - tex_lod;
1919
1920 if (params->tLOD[tmu] & LOD_TMIRROR_S)
1921 {
1922 if (state->tex_s & 0x1000)
1923 state->tex_s = ~state->tex_s;
1924 }
1925 if (params->tLOD[tmu] & LOD_TMIRROR_T)
1926 {
1927 if (state->tex_t & 0x1000)
1928 state->tex_t = ~state->tex_t;
1929 }
1930
1931 if (voodoo->bilinear_enabled && params->textureMode[tmu] & 6)
1932 {
1933 int _ds, dt;
1934
1935 state->tex_s -= 1 << (3+tex_lod);
1936 state->tex_t -= 1 << (3+tex_lod);
1937
1938 s = state->tex_s >> tex_lod;
1939 t = state->tex_t >> tex_lod;
1940
1941 _ds = s & 0xf;
1942 dt = t & 0xf;
1943
1944 s >>= 4;
1945 t >>= 4;
1946 //if (x == 80)
1947 //if (voodoo_output)
1948 // pclog("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, _ds, dt);
1949 d[0] = (16 - _ds) * (16 - dt);
1950 d[1] = _ds * (16 - dt);
1951 d[2] = (16 - _ds) * dt;
1952 d[3] = _ds * dt;
1953
1954 // texture_state.s = s;
1955 // texture_state.t = t;
1956 tex_read_4(state, &texture_state, s, t, d, tmu, x);
1957
1958
1959 /* state->tex_r = (tex_samples[0].rgba.r * d[0] + tex_samples[1].rgba.r * d[1] + tex_samples[2].rgba.r * d[2] + tex_samples[3].rgba.r * d[3]) >> 8;
1960 state->tex_g = (tex_samples[0].rgba.g * d[0] + tex_samples[1].rgba.g * d[1] + tex_samples[2].rgba.g * d[2] + tex_samples[3].rgba.g * d[3]) >> 8;
1961 state->tex_b = (tex_samples[0].rgba.b * d[0] + tex_samples[1].rgba.b * d[1] + tex_samples[2].rgba.b * d[2] + tex_samples[3].rgba.b * d[3]) >> 8;
1962 state->tex_a = (tex_samples[0].rgba.a * d[0] + tex_samples[1].rgba.a * d[1] + tex_samples[2].rgba.a * d[2] + tex_samples[3].rgba.a * d[3]) >> 8;*/
1963 /* state->tex_r = tex_samples[0].r;
1964 state->tex_g = tex_samples[0].g;
1965 state->tex_b = tex_samples[0].b;
1966 state->tex_a = tex_samples[0].a;*/
1967 }
1968 else
1969 {
1970 // rgba_t tex_samples;
1971 // voodoo_texture_state_t texture_state;
1972 // int s = state->tex_s >> (18+state->lod);
1973 // int t = state->tex_t >> (18+state->lod);
1974 // int s, t;
1975
1976 // state->tex_s -= 1 << (17+state->lod);
1977 // state->tex_t -= 1 << (17+state->lod);
1978
1979 s = state->tex_s >> (4+tex_lod);
1980 t = state->tex_t >> (4+tex_lod);
1981
1982 texture_state.s = s;
1983 texture_state.t = t;
1984 tex_read(state, &texture_state, tmu);
1985
1986 /* state->tex_r = tex_samples[0].rgba.r;
1987 state->tex_g = tex_samples[0].rgba.g;
1988 state->tex_b = tex_samples[0].rgba.b;
1989 state->tex_a = tex_samples[0].rgba.a;*/
1990 }
1991 }
1992
voodoo_tmu_fetch(voodoo_t * voodoo,voodoo_params_t * params,voodoo_state_t * state,int tmu,int x)1993 static inline void voodoo_tmu_fetch(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x)
1994 {
1995 if (params->textureMode[tmu] & 1)
1996 {
1997 int64_t _w = 0;
1998
1999 if (tmu)
2000 {
2001 if (state->tmu1_w)
2002 _w = (int64_t)((1ULL << 48) / state->tmu1_w);
2003 state->tex_s = (int32_t)(((((state->tmu1_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
2004 state->tex_t = (int32_t)(((((state->tmu1_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
2005 }
2006 else
2007 {
2008 if (state->tmu0_w)
2009 _w = (int64_t)((1ULL << 48) / state->tmu0_w);
2010 state->tex_s = (int32_t)(((((state->tmu0_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
2011 state->tex_t = (int32_t)(((((state->tmu0_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30);
2012 }
2013
2014 state->lod = state->tmu[tmu].lod + (fastlog(_w) - (19 << 8));
2015 }
2016 else
2017 {
2018 if (tmu)
2019 {
2020 state->tex_s = (int32_t)(state->tmu1_s >> (14+14));
2021 state->tex_t = (int32_t)(state->tmu1_t >> (14+14));
2022 }
2023 else
2024 {
2025 state->tex_s = (int32_t)(state->tmu0_s >> (14+14));
2026 state->tex_t = (int32_t)(state->tmu0_t >> (14+14));
2027 }
2028 state->lod = state->tmu[tmu].lod;
2029 }
2030
2031 if (state->lod < state->lod_min[tmu])
2032 state->lod = state->lod_min[tmu];
2033 else if (state->lod > state->lod_max[tmu])
2034 state->lod = state->lod_max[tmu];
2035 state->lod_frac[tmu] = state->lod & 0xff;
2036 state->lod >>= 8;
2037
2038 voodoo_get_texture(voodoo, params, state, tmu, x);
2039 }
2040
2041 #define DEPTH_TEST(comp_depth) \
2042 do \
2043 { \
2044 switch (depth_op) \
2045 { \
2046 case DEPTHOP_NEVER: \
2047 voodoo->fbiZFuncFail++; \
2048 goto skip_pixel; \
2049 case DEPTHOP_LESSTHAN: \
2050 if (!(comp_depth < old_depth)) \
2051 { \
2052 voodoo->fbiZFuncFail++; \
2053 goto skip_pixel; \
2054 } \
2055 break; \
2056 case DEPTHOP_EQUAL: \
2057 if (!(comp_depth == old_depth)) \
2058 { \
2059 voodoo->fbiZFuncFail++; \
2060 goto skip_pixel; \
2061 } \
2062 break; \
2063 case DEPTHOP_LESSTHANEQUAL: \
2064 if (!(comp_depth <= old_depth)) \
2065 { \
2066 voodoo->fbiZFuncFail++; \
2067 goto skip_pixel; \
2068 } \
2069 break; \
2070 case DEPTHOP_GREATERTHAN: \
2071 if (!(comp_depth > old_depth)) \
2072 { \
2073 voodoo->fbiZFuncFail++; \
2074 goto skip_pixel; \
2075 } \
2076 break; \
2077 case DEPTHOP_NOTEQUAL: \
2078 if (!(comp_depth != old_depth)) \
2079 { \
2080 voodoo->fbiZFuncFail++; \
2081 goto skip_pixel; \
2082 } \
2083 break; \
2084 case DEPTHOP_GREATERTHANEQUAL: \
2085 if (!(comp_depth >= old_depth)) \
2086 { \
2087 voodoo->fbiZFuncFail++; \
2088 goto skip_pixel; \
2089 } \
2090 break; \
2091 case DEPTHOP_ALWAYS: \
2092 break; \
2093 } \
2094 } while (0)
2095
2096 #define APPLY_FOG(src_r, src_g, src_b, z, ia, w) \
2097 do \
2098 { \
2099 if (params->fogMode & FOG_CONSTANT) \
2100 { \
2101 src_r += params->fogColor.r; \
2102 src_g += params->fogColor.g; \
2103 src_b += params->fogColor.b; \
2104 } \
2105 else \
2106 { \
2107 int fog_r, fog_g, fog_b, fog_a = 0; \
2108 int fog_idx; \
2109 \
2110 if (!(params->fogMode & FOG_ADD)) \
2111 { \
2112 fog_r = params->fogColor.r; \
2113 fog_g = params->fogColor.g; \
2114 fog_b = params->fogColor.b; \
2115 } \
2116 else \
2117 fog_r = fog_g = fog_b = 0; \
2118 \
2119 if (!(params->fogMode & FOG_MULT)) \
2120 { \
2121 fog_r -= src_r; \
2122 fog_g -= src_g; \
2123 fog_b -= src_b; \
2124 } \
2125 \
2126 switch (params->fogMode & (FOG_Z|FOG_ALPHA)) \
2127 { \
2128 case 0: \
2129 fog_idx = (w_depth >> 10) & 0x3f; \
2130 \
2131 fog_a = params->fogTable[fog_idx].fog; \
2132 fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; \
2133 break; \
2134 case FOG_Z: \
2135 fog_a = (z >> 20) & 0xff; \
2136 break; \
2137 case FOG_ALPHA: \
2138 fog_a = CLAMP(ia >> 12); \
2139 break; \
2140 case FOG_W: \
2141 fog_a = CLAMP((w >> 32) & 0xff); \
2142 break; \
2143 } \
2144 fog_a++; \
2145 \
2146 fog_r = (fog_r * fog_a) >> 8; \
2147 fog_g = (fog_g * fog_a) >> 8; \
2148 fog_b = (fog_b * fog_a) >> 8; \
2149 \
2150 if (params->fogMode & FOG_MULT) \
2151 { \
2152 src_r = fog_r; \
2153 src_g = fog_g; \
2154 src_b = fog_b; \
2155 } \
2156 else \
2157 { \
2158 src_r += fog_r; \
2159 src_g += fog_g; \
2160 src_b += fog_b; \
2161 } \
2162 } \
2163 \
2164 src_r = CLAMP(src_r); \
2165 src_g = CLAMP(src_g); \
2166 src_b = CLAMP(src_b); \
2167 } while (0)
2168
2169 #define ALPHA_TEST(src_a) \
2170 do \
2171 { \
2172 switch (alpha_func) \
2173 { \
2174 case AFUNC_NEVER: \
2175 voodoo->fbiAFuncFail++; \
2176 goto skip_pixel; \
2177 case AFUNC_LESSTHAN: \
2178 if (!(src_a < a_ref)) \
2179 { \
2180 voodoo->fbiAFuncFail++; \
2181 goto skip_pixel; \
2182 } \
2183 break; \
2184 case AFUNC_EQUAL: \
2185 if (!(src_a == a_ref)) \
2186 { \
2187 voodoo->fbiAFuncFail++; \
2188 goto skip_pixel; \
2189 } \
2190 break; \
2191 case AFUNC_LESSTHANEQUAL: \
2192 if (!(src_a <= a_ref)) \
2193 { \
2194 voodoo->fbiAFuncFail++; \
2195 goto skip_pixel; \
2196 } \
2197 break; \
2198 case AFUNC_GREATERTHAN: \
2199 if (!(src_a > a_ref)) \
2200 { \
2201 voodoo->fbiAFuncFail++; \
2202 goto skip_pixel; \
2203 } \
2204 break; \
2205 case AFUNC_NOTEQUAL: \
2206 if (!(src_a != a_ref)) \
2207 { \
2208 voodoo->fbiAFuncFail++; \
2209 goto skip_pixel; \
2210 } \
2211 break; \
2212 case AFUNC_GREATERTHANEQUAL: \
2213 if (!(src_a >= a_ref)) \
2214 { \
2215 voodoo->fbiAFuncFail++; \
2216 goto skip_pixel; \
2217 } \
2218 break; \
2219 case AFUNC_ALWAYS: \
2220 break; \
2221 } \
2222 } while (0)
2223
2224 #define ALPHA_BLEND(src_r, src_g, src_b, src_a) \
2225 do \
2226 { \
2227 int _a; \
2228 int newdest_r = 0, newdest_g = 0, newdest_b = 0; \
2229 \
2230 switch (dest_afunc) \
2231 { \
2232 case AFUNC_AZERO: \
2233 newdest_r = newdest_g = newdest_b = 0; \
2234 break; \
2235 case AFUNC_ASRC_ALPHA: \
2236 newdest_r = (dest_r * src_a) / 255; \
2237 newdest_g = (dest_g * src_a) / 255; \
2238 newdest_b = (dest_b * src_a) / 255; \
2239 break; \
2240 case AFUNC_A_COLOR: \
2241 newdest_r = (dest_r * src_r) / 255; \
2242 newdest_g = (dest_g * src_g) / 255; \
2243 newdest_b = (dest_b * src_b) / 255; \
2244 break; \
2245 case AFUNC_ADST_ALPHA: \
2246 newdest_r = (dest_r * dest_a) / 255; \
2247 newdest_g = (dest_g * dest_a) / 255; \
2248 newdest_b = (dest_b * dest_a) / 255; \
2249 break; \
2250 case AFUNC_AONE: \
2251 newdest_r = dest_r; \
2252 newdest_g = dest_g; \
2253 newdest_b = dest_b; \
2254 break; \
2255 case AFUNC_AOMSRC_ALPHA: \
2256 newdest_r = (dest_r * (255-src_a)) / 255; \
2257 newdest_g = (dest_g * (255-src_a)) / 255; \
2258 newdest_b = (dest_b * (255-src_a)) / 255; \
2259 break; \
2260 case AFUNC_AOM_COLOR: \
2261 newdest_r = (dest_r * (255-src_r)) / 255; \
2262 newdest_g = (dest_g * (255-src_g)) / 255; \
2263 newdest_b = (dest_b * (255-src_b)) / 255; \
2264 break; \
2265 case AFUNC_AOMDST_ALPHA: \
2266 newdest_r = (dest_r * (255-dest_a)) / 255; \
2267 newdest_g = (dest_g * (255-dest_a)) / 255; \
2268 newdest_b = (dest_b * (255-dest_a)) / 255; \
2269 break; \
2270 case AFUNC_ASATURATE: \
2271 _a = MIN(src_a, 1-dest_a); \
2272 newdest_r = (dest_r * _a) / 255; \
2273 newdest_g = (dest_g * _a) / 255; \
2274 newdest_b = (dest_b * _a) / 255; \
2275 break; \
2276 } \
2277 \
2278 switch (src_afunc) \
2279 { \
2280 case AFUNC_AZERO: \
2281 src_r = src_g = src_b = 0; \
2282 break; \
2283 case AFUNC_ASRC_ALPHA: \
2284 src_r = (src_r * src_a) / 255; \
2285 src_g = (src_g * src_a) / 255; \
2286 src_b = (src_b * src_a) / 255; \
2287 break; \
2288 case AFUNC_A_COLOR: \
2289 src_r = (src_r * dest_r) / 255; \
2290 src_g = (src_g * dest_g) / 255; \
2291 src_b = (src_b * dest_b) / 255; \
2292 break; \
2293 case AFUNC_ADST_ALPHA: \
2294 src_r = (src_r * dest_a) / 255; \
2295 src_g = (src_g * dest_a) / 255; \
2296 src_b = (src_b * dest_a) / 255; \
2297 break; \
2298 case AFUNC_AONE: \
2299 break; \
2300 case AFUNC_AOMSRC_ALPHA: \
2301 src_r = (src_r * (255-src_a)) / 255; \
2302 src_g = (src_g * (255-src_a)) / 255; \
2303 src_b = (src_b * (255-src_a)) / 255; \
2304 break; \
2305 case AFUNC_AOM_COLOR: \
2306 src_r = (src_r * (255-dest_r)) / 255; \
2307 src_g = (src_g * (255-dest_g)) / 255; \
2308 src_b = (src_b * (255-dest_b)) / 255; \
2309 break; \
2310 case AFUNC_AOMDST_ALPHA: \
2311 src_r = (src_r * (255-dest_a)) / 255; \
2312 src_g = (src_g * (255-dest_a)) / 255; \
2313 src_b = (src_b * (255-dest_a)) / 255; \
2314 break; \
2315 case AFUNC_ACOLORBEFOREFOG: \
2316 fatal("AFUNC_ACOLORBEFOREFOG\n"); \
2317 break; \
2318 } \
2319 \
2320 src_r += newdest_r; \
2321 src_g += newdest_g; \
2322 src_b += newdest_b; \
2323 \
2324 src_r = CLAMP(src_r); \
2325 src_g = CLAMP(src_g); \
2326 src_b = CLAMP(src_b); \
2327 } while(0)
2328
2329
2330 #define _rgb_sel ( params->fbzColorPath & 3)
2331 #define a_sel ( (params->fbzColorPath >> 2) & 3)
2332 #define cc_localselect ( params->fbzColorPath & (1 << 4))
2333 #define cca_localselect ( (params->fbzColorPath >> 5) & 3)
2334 #define cc_localselect_override ( params->fbzColorPath & (1 << 7))
2335 #define cc_zero_other ( params->fbzColorPath & (1 << 8))
2336 #define cc_sub_clocal ( params->fbzColorPath & (1 << 9))
2337 #define cc_mselect ( (params->fbzColorPath >> 10) & 7)
2338 #define cc_reverse_blend ( params->fbzColorPath & (1 << 13))
2339 #define cc_add ( (params->fbzColorPath >> 14) & 3)
2340 #define cc_add_alocal ( params->fbzColorPath & (1 << 15))
2341 #define cc_invert_output ( params->fbzColorPath & (1 << 16))
2342 #define cca_zero_other ( params->fbzColorPath & (1 << 17))
2343 #define cca_sub_clocal ( params->fbzColorPath & (1 << 18))
2344 #define cca_mselect ( (params->fbzColorPath >> 19) & 7)
2345 #define cca_reverse_blend ( params->fbzColorPath & (1 << 22))
2346 #define cca_add ( (params->fbzColorPath >> 23) & 3)
2347 #define cca_invert_output ( params->fbzColorPath & (1 << 25))
2348 #define tc_zero_other (params->textureMode[0] & (1 << 12))
2349 #define tc_sub_clocal (params->textureMode[0] & (1 << 13))
2350 #define tc_mselect ((params->textureMode[0] >> 14) & 7)
2351 #define tc_reverse_blend (params->textureMode[0] & (1 << 17))
2352 #define tc_add_clocal (params->textureMode[0] & (1 << 18))
2353 #define tc_add_alocal (params->textureMode[0] & (1 << 19))
2354 #define tc_invert_output (params->textureMode[0] & (1 << 20))
2355 #define tca_zero_other (params->textureMode[0] & (1 << 21))
2356 #define tca_sub_clocal (params->textureMode[0] & (1 << 22))
2357 #define tca_mselect ((params->textureMode[0] >> 23) & 7)
2358 #define tca_reverse_blend (params->textureMode[0] & (1 << 26))
2359 #define tca_add_clocal (params->textureMode[0] & (1 << 27))
2360 #define tca_add_alocal (params->textureMode[0] & (1 << 28))
2361 #define tca_invert_output (params->textureMode[0] & (1 << 29))
2362
2363 #define tc_sub_clocal_1 (params->textureMode[1] & (1 << 13))
2364 #define tc_mselect_1 ((params->textureMode[1] >> 14) & 7)
2365 #define tc_reverse_blend_1 (params->textureMode[1] & (1 << 17))
2366 #define tc_add_clocal_1 (params->textureMode[1] & (1 << 18))
2367 #define tc_add_alocal_1 (params->textureMode[1] & (1 << 19))
2368 #define tca_sub_clocal_1 (params->textureMode[1] & (1 << 22))
2369 #define tca_mselect_1 ((params->textureMode[1] >> 23) & 7)
2370 #define tca_reverse_blend_1 (params->textureMode[1] & (1 << 26))
2371 #define tca_add_clocal_1 (params->textureMode[1] & (1 << 27))
2372 #define tca_add_alocal_1 (params->textureMode[1] & (1 << 28))
2373
2374 #define src_afunc ( (params->alphaMode >> 8) & 0xf)
2375 #define dest_afunc ( (params->alphaMode >> 12) & 0xf)
2376 #define alpha_func ( (params->alphaMode >> 1) & 7)
2377 #define a_ref ( params->alphaMode >> 24)
2378 #define depth_op ( (params->fbzMode >> 5) & 7)
2379 #define dither ( params->fbzMode & FBZ_DITHER)
2380 #define dither2x2 (params->fbzMode & FBZ_DITHER_2x2)
2381
2382 /*Perform texture fetch and blending for both TMUs*/
voodoo_tmu_fetch_and_blend(voodoo_t * voodoo,voodoo_params_t * params,voodoo_state_t * state,int x)2383 static inline void voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int x)
2384 {
2385 int r,g,b,a;
2386 int c_reverse, a_reverse;
2387 // int c_reverse1, a_reverse1;
2388 int factor_r = 0, factor_g = 0, factor_b = 0, factor_a = 0;
2389
2390 voodoo_tmu_fetch(voodoo, params, state, 1, x);
2391
2392 if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && (state->lod & 1))
2393 {
2394 c_reverse = tc_reverse_blend;
2395 a_reverse = tca_reverse_blend;
2396 }
2397 else
2398 {
2399 c_reverse = !tc_reverse_blend;
2400 a_reverse = !tca_reverse_blend;
2401 }
2402 /* c_reverse1 = c_reverse;
2403 a_reverse1 = a_reverse;*/
2404 if (tc_sub_clocal_1)
2405 {
2406 switch (tc_mselect_1)
2407 {
2408 case TC_MSELECT_ZERO:
2409 factor_r = factor_g = factor_b = 0;
2410 break;
2411 case TC_MSELECT_CLOCAL:
2412 factor_r = state->tex_r[1];
2413 factor_g = state->tex_g[1];
2414 factor_b = state->tex_b[1];
2415 break;
2416 case TC_MSELECT_AOTHER:
2417 factor_r = factor_g = factor_b = 0;
2418 break;
2419 case TC_MSELECT_ALOCAL:
2420 factor_r = factor_g = factor_b = state->tex_a[1];
2421 break;
2422 case TC_MSELECT_DETAIL:
2423 factor_r = (params->detail_bias[1] - state->lod) << params->detail_scale[1];
2424 if (factor_r > params->detail_max[1])
2425 factor_r = params->detail_max[1];
2426 factor_g = factor_b = factor_r;
2427 break;
2428 case TC_MSELECT_LOD_FRAC:
2429 factor_r = factor_g = factor_b = state->lod_frac[1];
2430 break;
2431 }
2432 if (!c_reverse)
2433 {
2434 r = (-state->tex_r[1] * (factor_r + 1)) >> 8;
2435 g = (-state->tex_g[1] * (factor_g + 1)) >> 8;
2436 b = (-state->tex_b[1] * (factor_b + 1)) >> 8;
2437 }
2438 else
2439 {
2440 r = (-state->tex_r[1] * ((factor_r^0xff) + 1)) >> 8;
2441 g = (-state->tex_g[1] * ((factor_g^0xff) + 1)) >> 8;
2442 b = (-state->tex_b[1] * ((factor_b^0xff) + 1)) >> 8;
2443 }
2444 if (tc_add_clocal_1)
2445 {
2446 r += state->tex_r[1];
2447 g += state->tex_g[1];
2448 b += state->tex_b[1];
2449 }
2450 else if (tc_add_alocal_1)
2451 {
2452 r += state->tex_a[1];
2453 g += state->tex_a[1];
2454 b += state->tex_a[1];
2455 }
2456 state->tex_r[1] = CLAMP(r);
2457 state->tex_g[1] = CLAMP(g);
2458 state->tex_b[1] = CLAMP(b);
2459 }
2460 if (tca_sub_clocal_1)
2461 {
2462 switch (tca_mselect_1)
2463 {
2464 case TCA_MSELECT_ZERO:
2465 factor_a = 0;
2466 break;
2467 case TCA_MSELECT_CLOCAL:
2468 factor_a = state->tex_a[1];
2469 break;
2470 case TCA_MSELECT_AOTHER:
2471 factor_a = 0;
2472 break;
2473 case TCA_MSELECT_ALOCAL:
2474 factor_a = state->tex_a[1];
2475 break;
2476 case TCA_MSELECT_DETAIL:
2477 factor_a = (params->detail_bias[1] - state->lod) << params->detail_scale[1];
2478 if (factor_a > params->detail_max[1])
2479 factor_a = params->detail_max[1];
2480 break;
2481 case TCA_MSELECT_LOD_FRAC:
2482 factor_a = state->lod_frac[1];
2483 break;
2484 }
2485 if (!a_reverse)
2486 a = (-state->tex_a[1] * ((factor_a ^ 0xff) + 1)) >> 8;
2487 else
2488 a = (-state->tex_a[1] * (factor_a + 1)) >> 8;
2489 if (tca_add_clocal_1 || tca_add_alocal_1)
2490 a += state->tex_a[1];
2491 state->tex_a[1] = CLAMP(a);
2492 }
2493
2494
2495 voodoo_tmu_fetch(voodoo, params, state, 0, x);
2496
2497 if ((params->textureMode[0] & TEXTUREMODE_TRILINEAR) && (state->lod & 1))
2498 {
2499 c_reverse = tc_reverse_blend;
2500 a_reverse = tca_reverse_blend;
2501 }
2502 else
2503 {
2504 c_reverse = !tc_reverse_blend;
2505 a_reverse = !tca_reverse_blend;
2506 }
2507
2508 if (!tc_zero_other)
2509 {
2510 r = state->tex_r[1];
2511 g = state->tex_g[1];
2512 b = state->tex_b[1];
2513 }
2514 else
2515 r = g = b = 0;
2516 if (tc_sub_clocal)
2517 {
2518 r -= state->tex_r[0];
2519 g -= state->tex_g[0];
2520 b -= state->tex_b[0];
2521 }
2522 switch (tc_mselect)
2523 {
2524 case TC_MSELECT_ZERO:
2525 factor_r = factor_g = factor_b = 0;
2526 break;
2527 case TC_MSELECT_CLOCAL:
2528 factor_r = state->tex_r[0];
2529 factor_g = state->tex_g[0];
2530 factor_b = state->tex_b[0];
2531 break;
2532 case TC_MSELECT_AOTHER:
2533 factor_r = factor_g = factor_b = state->tex_a[1];
2534 break;
2535 case TC_MSELECT_ALOCAL:
2536 factor_r = factor_g = factor_b = state->tex_a[0];
2537 break;
2538 case TC_MSELECT_DETAIL:
2539 factor_r = (params->detail_bias[0] - state->lod) << params->detail_scale[0];
2540 if (factor_r > params->detail_max[0])
2541 factor_r = params->detail_max[0];
2542 factor_g = factor_b = factor_r;
2543 break;
2544 case TC_MSELECT_LOD_FRAC:
2545 factor_r = factor_g = factor_b = state->lod_frac[0];
2546 break;
2547 }
2548 if (!c_reverse)
2549 {
2550 r = (r * (factor_r + 1)) >> 8;
2551 g = (g * (factor_g + 1)) >> 8;
2552 b = (b * (factor_b + 1)) >> 8;
2553 }
2554 else
2555 {
2556 r = (r * ((factor_r^0xff) + 1)) >> 8;
2557 g = (g * ((factor_g^0xff) + 1)) >> 8;
2558 b = (b * ((factor_b^0xff) + 1)) >> 8;
2559 }
2560 if (tc_add_clocal)
2561 {
2562 r += state->tex_r[0];
2563 g += state->tex_g[0];
2564 b += state->tex_b[0];
2565 }
2566 else if (tc_add_alocal)
2567 {
2568 r += state->tex_a[0];
2569 g += state->tex_a[0];
2570 b += state->tex_a[0];
2571 }
2572
2573 if (!tca_zero_other)
2574 a = state->tex_a[1];
2575 else
2576 a = 0;
2577 if (tca_sub_clocal)
2578 a -= state->tex_a[0];
2579 switch (tca_mselect)
2580 {
2581 case TCA_MSELECT_ZERO:
2582 factor_a = 0;
2583 break;
2584 case TCA_MSELECT_CLOCAL:
2585 factor_a = state->tex_a[0];
2586 break;
2587 case TCA_MSELECT_AOTHER:
2588 factor_a = state->tex_a[1];
2589 break;
2590 case TCA_MSELECT_ALOCAL:
2591 factor_a = state->tex_a[0];
2592 break;
2593 case TCA_MSELECT_DETAIL:
2594 factor_a = (params->detail_bias[0] - state->lod) << params->detail_scale[0];
2595 if (factor_a > params->detail_max[0])
2596 factor_a = params->detail_max[0];
2597 break;
2598 case TCA_MSELECT_LOD_FRAC:
2599 factor_a = state->lod_frac[0];
2600 break;
2601 }
2602 if (a_reverse)
2603 a = (a * ((factor_a ^ 0xff) + 1)) >> 8;
2604 else
2605 a = (a * (factor_a + 1)) >> 8;
2606 if (tca_add_clocal || tca_add_alocal)
2607 a += state->tex_a[0];
2608
2609
2610 state->tex_r[0] = CLAMP(r);
2611 state->tex_g[0] = CLAMP(g);
2612 state->tex_b[0] = CLAMP(b);
2613 state->tex_a[0] = CLAMP(a);
2614
2615 if (tc_invert_output)
2616 {
2617 state->tex_r[0] ^= 0xff;
2618 state->tex_g[0] ^= 0xff;
2619 state->tex_b[0] ^= 0xff;
2620 }
2621 if (tca_invert_output)
2622 state->tex_a[0] ^= 0xff;
2623 }
2624
2625 #if (defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__)
2626 #include "vid_voodoo_codegen_x86.h"
2627 #elif (defined __amd64__)
2628 #include "vid_voodoo_codegen_x86-64.h"
2629 #else
2630 #define NO_CODEGEN
2631 static int voodoo_recomp = 0;
2632 #endif
2633
voodoo_half_triangle(voodoo_t * voodoo,voodoo_params_t * params,voodoo_state_t * state,int ystart,int yend,int odd_even)2634 static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even)
2635 {
2636 /* int rgb_sel = params->fbzColorPath & 3;
2637 int a_sel = (params->fbzColorPath >> 2) & 3;
2638 int cc_localselect = params->fbzColorPath & (1 << 4);
2639 int cca_localselect = (params->fbzColorPath >> 5) & 3;
2640 int cc_localselect_override = params->fbzColorPath & (1 << 7);
2641 int cc_zero_other = params->fbzColorPath & (1 << 8);
2642 int cc_sub_clocal = params->fbzColorPath & (1 << 9);
2643 int cc_mselect = (params->fbzColorPath >> 10) & 7;
2644 int cc_reverse_blend = params->fbzColorPath & (1 << 13);
2645 int cc_add = (params->fbzColorPath >> 14) & 3;
2646 int cc_add_alocal = params->fbzColorPath & (1 << 15);
2647 int cc_invert_output = params->fbzColorPath & (1 << 16);
2648 int cca_zero_other = params->fbzColorPath & (1 << 17);
2649 int cca_sub_clocal = params->fbzColorPath & (1 << 18);
2650 int cca_mselect = (params->fbzColorPath >> 19) & 7;
2651 int cca_reverse_blend = params->fbzColorPath & (1 << 22);
2652 int cca_add = (params->fbzColorPath >> 23) & 3;
2653 int cca_invert_output = params->fbzColorPath & (1 << 25);
2654 int src_afunc = (params->alphaMode >> 8) & 0xf;
2655 int dest_afunc = (params->alphaMode >> 12) & 0xf;
2656 int alpha_func = (params->alphaMode >> 1) & 7;
2657 int a_ref = params->alphaMode >> 24;
2658 int depth_op = (params->fbzMode >> 5) & 7;
2659 int dither = params->fbzMode & FBZ_DITHER;*/
2660 int texels;
2661 int c;
2662 uint8_t (*voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y);
2663 int y_diff = SLI_ENABLED ? 2 : 1;
2664
2665 if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH ||
2666 (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL)
2667 texels = 1;
2668 else
2669 texels = 2;
2670
2671 state->clamp_s[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPS;
2672 state->clamp_t[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPT;
2673 state->clamp_s[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPS;
2674 state->clamp_t[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPT;
2675 // int last_x;
2676 // pclog("voodoo_triangle : bottom-half %X %X %X %X %X %i %i %i %i\n", xstart, xend, dx1, dx2, dx2 * 36, xdir, y, yend, ydir);
2677
2678 for (c = 0; c <= LOD_MAX; c++)
2679 {
2680 state->tex[0][c] = &voodoo->texture_cache[0][params->tex_entry[0]].data[texture_offset[c]];
2681 state->tex[1][c] = &voodoo->texture_cache[1][params->tex_entry[1]].data[texture_offset[c]];
2682 }
2683
2684 state->tformat = params->tformat[0];
2685
2686 state->tex_w_mask[0] = params->tex_w_mask[0];
2687 state->tex_h_mask[0] = params->tex_h_mask[0];
2688 state->tex_shift[0] = params->tex_shift[0];
2689 state->tex_lod[0] = params->tex_lod[0];
2690 state->tex_w_mask[1] = params->tex_w_mask[1];
2691 state->tex_h_mask[1] = params->tex_h_mask[1];
2692 state->tex_shift[1] = params->tex_shift[1];
2693 state->tex_lod[1] = params->tex_lod[1];
2694
2695 if ((params->fbzMode & 1) && (ystart < params->clipLowY))
2696 {
2697 int dy = params->clipLowY - ystart;
2698
2699 state->base_r += params->dRdY*dy;
2700 state->base_g += params->dGdY*dy;
2701 state->base_b += params->dBdY*dy;
2702 state->base_a += params->dAdY*dy;
2703 state->base_z += params->dZdY*dy;
2704 state->tmu[0].base_s += params->tmu[0].dSdY*dy;
2705 state->tmu[0].base_t += params->tmu[0].dTdY*dy;
2706 state->tmu[0].base_w += params->tmu[0].dWdY*dy;
2707 state->tmu[1].base_s += params->tmu[1].dSdY*dy;
2708 state->tmu[1].base_t += params->tmu[1].dTdY*dy;
2709 state->tmu[1].base_w += params->tmu[1].dWdY*dy;
2710 state->base_w += params->dWdY*dy;
2711 state->xstart += state->dx1*dy;
2712 state->xend += state->dx2*dy;
2713
2714 ystart = params->clipLowY;
2715 }
2716
2717 if ((params->fbzMode & 1) && (yend >= params->clipHighY))
2718 yend = params->clipHighY-1;
2719
2720 state->y = ystart;
2721 // yend--;
2722
2723 if (SLI_ENABLED)
2724 {
2725 int test_y;
2726
2727 if (params->fbzMode & (1 << 17))
2728 test_y = (voodoo->v_disp-1) - state->y;
2729 else
2730 test_y = state->y;
2731
2732 if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (test_y & 1)) ||
2733 ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(test_y & 1)))
2734 {
2735 state->y++;
2736
2737 state->base_r += params->dRdY;
2738 state->base_g += params->dGdY;
2739 state->base_b += params->dBdY;
2740 state->base_a += params->dAdY;
2741 state->base_z += params->dZdY;
2742 state->tmu[0].base_s += params->tmu[0].dSdY;
2743 state->tmu[0].base_t += params->tmu[0].dTdY;
2744 state->tmu[0].base_w += params->tmu[0].dWdY;
2745 state->tmu[1].base_s += params->tmu[1].dSdY;
2746 state->tmu[1].base_t += params->tmu[1].dTdY;
2747 state->tmu[1].base_w += params->tmu[1].dWdY;
2748 state->base_w += params->dWdY;
2749 state->xstart += state->dx1;
2750 state->xend += state->dx2;
2751 }
2752 }
2753 #ifndef NO_CODEGEN
2754 if (voodoo->use_recompiler)
2755 voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even);
2756 else
2757 voodoo_draw = NULL;
2758 #endif
2759
2760 if (voodoo_output)
2761 pclog("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC);
2762 // pclog("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17));
2763
2764 for (; state->y < yend; state->y += y_diff)
2765 {
2766 int x, x2;
2767 int real_y = (state->y << 4) + 8;
2768 int start_x, start_x2;
2769 int dx;
2770 uint16_t *fb_mem, *aux_mem;
2771
2772 state->ir = state->base_r;
2773 state->ig = state->base_g;
2774 state->ib = state->base_b;
2775 state->ia = state->base_a;
2776 state->z = state->base_z;
2777 state->tmu0_s = state->tmu[0].base_s;
2778 state->tmu0_t = state->tmu[0].base_t;
2779 state->tmu0_w = state->tmu[0].base_w;
2780 state->tmu1_s = state->tmu[1].base_s;
2781 state->tmu1_t = state->tmu[1].base_t;
2782 state->tmu1_w = state->tmu[1].base_w;
2783 state->w = state->base_w;
2784
2785 x = (state->vertexAx << 12) + ((state->dxAC * (real_y - state->vertexAy)) >> 4);
2786
2787 if (real_y < state->vertexBy)
2788 x2 = (state->vertexAx << 12) + ((state->dxAB * (real_y - state->vertexAy)) >> 4);
2789 else
2790 x2 = (state->vertexBx << 12) + ((state->dxBC * (real_y - state->vertexBy)) >> 4);
2791
2792 if (params->fbzMode & (1 << 17))
2793 real_y = (voodoo->v_disp-1) - (real_y >> 4);
2794 else
2795 real_y >>= 4;
2796
2797 if (SLI_ENABLED)
2798 {
2799 if (((real_y >> 1) & voodoo->odd_even_mask) != odd_even)
2800 goto next_line;
2801 }
2802 else
2803 {
2804 if ((real_y & voodoo->odd_even_mask) != odd_even)
2805 goto next_line;
2806 }
2807
2808 start_x = x;
2809
2810 if (state->xdir > 0)
2811 x2 -= (1 << 16);
2812 else
2813 x -= (1 << 16);
2814 dx = ((x + 0x7000) >> 16) - (((state->vertexAx << 12) + 0x7000) >> 16);
2815 start_x2 = x + 0x7000;
2816 x = (x + 0x7000) >> 16;
2817 x2 = (x2 + 0x7000) >> 16;
2818
2819 if (voodoo_output)
2820 pclog("%03i:%03i : Ax=%08x start_x=%08x dSdX=%016llx dx=%08x s=%08x -> ", x, state->y, state->vertexAx << 8, start_x, params->tmu[0].dTdX, dx, state->tmu0_t);
2821
2822 state->ir += (params->dRdX * dx);
2823 state->ig += (params->dGdX * dx);
2824 state->ib += (params->dBdX * dx);
2825 state->ia += (params->dAdX * dx);
2826 state->z += (params->dZdX * dx);
2827 state->tmu0_s += (params->tmu[0].dSdX * dx);
2828 state->tmu0_t += (params->tmu[0].dTdX * dx);
2829 state->tmu0_w += (params->tmu[0].dWdX * dx);
2830 state->tmu1_s += (params->tmu[1].dSdX * dx);
2831 state->tmu1_t += (params->tmu[1].dTdX * dx);
2832 state->tmu1_w += (params->tmu[1].dWdX * dx);
2833 state->w += (params->dWdX * dx);
2834
2835 if (voodoo_output)
2836 pclog("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18+state->lod), (state->tmu0_t + (1 << (17+state->lod))) >> (18+state->lod));
2837
2838 if (params->fbzMode & 1)
2839 {
2840 if (state->xdir > 0)
2841 {
2842 if (x < params->clipLeft)
2843 {
2844 int dx = params->clipLeft - x;
2845
2846 state->ir += params->dRdX*dx;
2847 state->ig += params->dGdX*dx;
2848 state->ib += params->dBdX*dx;
2849 state->ia += params->dAdX*dx;
2850 state->z += params->dZdX*dx;
2851 state->tmu0_s += params->tmu[0].dSdX*dx;
2852 state->tmu0_t += params->tmu[0].dTdX*dx;
2853 state->tmu0_w += params->tmu[0].dWdX*dx;
2854 state->tmu1_s += params->tmu[1].dSdX*dx;
2855 state->tmu1_t += params->tmu[1].dTdX*dx;
2856 state->tmu1_w += params->tmu[1].dWdX*dx;
2857 state->w += params->dWdX*dx;
2858
2859 x = params->clipLeft;
2860 }
2861 if (x2 >= params->clipRight)
2862 x2 = params->clipRight-1;
2863 }
2864 else
2865 {
2866 if (x >= params->clipRight)
2867 {
2868 int dx = (params->clipRight-1) - x;
2869
2870 state->ir += params->dRdX*dx;
2871 state->ig += params->dGdX*dx;
2872 state->ib += params->dBdX*dx;
2873 state->ia += params->dAdX*dx;
2874 state->z += params->dZdX*dx;
2875 state->tmu0_s += params->tmu[0].dSdX*dx;
2876 state->tmu0_t += params->tmu[0].dTdX*dx;
2877 state->tmu0_w += params->tmu[0].dWdX*dx;
2878 state->tmu1_s += params->tmu[1].dSdX*dx;
2879 state->tmu1_t += params->tmu[1].dTdX*dx;
2880 state->tmu1_w += params->tmu[1].dWdX*dx;
2881 state->w += params->dWdX*dx;
2882
2883 x = params->clipRight-1;
2884 }
2885 if (x2 < params->clipLeft)
2886 x2 = params->clipLeft;
2887 }
2888 }
2889
2890 if (x2 < x && state->xdir > 0)
2891 goto next_line;
2892 if (x2 > x && state->xdir < 0)
2893 goto next_line;
2894
2895 if (SLI_ENABLED)
2896 {
2897 state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + ((real_y >> 1) * voodoo->row_width)];
2898 state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + ((real_y >> 1) * voodoo->row_width)) & voodoo->fb_mask];
2899 }
2900 else
2901 {
2902 state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + (real_y * voodoo->row_width)];
2903 state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (real_y * voodoo->row_width)) & voodoo->fb_mask];
2904 }
2905
2906 if (voodoo_output)
2907 pclog("%03i: x=%08x x2=%08x xstart=%08x xend=%08x dx=%08x start_x2=%08x\n", state->y, x, x2, state->xstart, state->xend, dx, start_x2);
2908
2909 state->pixel_count = 0;
2910 state->texel_count = 0;
2911 state->x = x;
2912 state->x2 = x2;
2913 #ifndef NO_CODEGEN
2914 if (voodoo->use_recompiler)
2915 {
2916 voodoo_draw(state, params, x, real_y);
2917 }
2918 else
2919 #endif
2920 do
2921 {
2922 start_x = x;
2923 state->x = x;
2924 voodoo->pixel_count[odd_even]++;
2925 voodoo->texel_count[odd_even] += texels;
2926 voodoo->fbiPixelsIn++;
2927
2928 if (voodoo_output)
2929 pclog(" X=%03i T=%08x\n", x, state->tmu0_t);
2930 // if (voodoo->fbzMode & FBZ_RGB_WMASK)
2931 {
2932 int update = 1;
2933 uint8_t cother_r, cother_g, cother_b, aother;
2934 uint8_t clocal_r, clocal_g, clocal_b, alocal;
2935 int src_r = 0, src_g = 0, src_b = 0, src_a = 0;
2936 int msel_r, msel_g, msel_b, msel_a;
2937 uint8_t dest_r, dest_g, dest_b, dest_a;
2938 uint16_t dat;
2939 int sel;
2940 int32_t new_depth, w_depth;
2941
2942 if (state->w & 0xffff00000000)
2943 w_depth = 0;
2944 else if (!(state->w & 0xffff0000))
2945 w_depth = 0xf001;
2946 else
2947 {
2948 int exp = voodoo_fls((uint16_t)((uint32_t)state->w >> 16));
2949 int mant = ((~(uint32_t)state->w >> (19 - exp))) & 0xfff;
2950 w_depth = (exp << 12) + mant + 1;
2951 if (w_depth > 0xffff)
2952 w_depth = 0xffff;
2953 }
2954
2955 // w_depth = CLAMP16(w_depth);
2956
2957 if (params->fbzMode & FBZ_W_BUFFER)
2958 new_depth = w_depth;
2959 else
2960 new_depth = CLAMP16(state->z >> 12);
2961
2962 if (params->fbzMode & FBZ_DEPTH_BIAS)
2963 new_depth = CLAMP16(new_depth + (int16_t)params->zaColor);
2964
2965 if (params->fbzMode & FBZ_DEPTH_ENABLE)
2966 {
2967 uint16_t old_depth = aux_mem[x];
2968
2969 DEPTH_TEST((params->fbzMode & FBZ_DEPTH_SOURCE) ? (params->zaColor & 0xffff) : new_depth);
2970 }
2971
2972 dat = fb_mem[x];
2973 dest_r = (dat >> 8) & 0xf8;
2974 dest_g = (dat >> 3) & 0xfc;
2975 dest_b = (dat << 3) & 0xf8;
2976 dest_r |= (dest_r >> 5);
2977 dest_g |= (dest_g >> 6);
2978 dest_b |= (dest_b >> 5);
2979 dest_a = 0xff;
2980
2981 if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED)
2982 {
2983 if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus)
2984 {
2985 /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/
2986 voodoo_tmu_fetch(voodoo, params, state, 0, x);
2987 }
2988 else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH)
2989 {
2990 /*TMU0 in pass-through mode, only sample TMU1*/
2991 voodoo_tmu_fetch(voodoo, params, state, 1, x);
2992
2993 state->tex_r[0] = state->tex_r[1];
2994 state->tex_g[0] = state->tex_g[1];
2995 state->tex_b[0] = state->tex_b[1];
2996 state->tex_a[0] = state->tex_a[1];
2997 }
2998 else
2999 {
3000 voodoo_tmu_fetch_and_blend(voodoo, params, state, x);
3001 }
3002
3003 if ((params->fbzMode & FBZ_CHROMAKEY) &&
3004 state->tex_r[0] == params->chromaKey_r &&
3005 state->tex_g[0] == params->chromaKey_g &&
3006 state->tex_b[0] == params->chromaKey_b)
3007 {
3008 voodoo->fbiChromaFail++;
3009 goto skip_pixel;
3010 }
3011 }
3012
3013 if (voodoo->trexInit1[0] & (1 << 18))
3014 {
3015 state->tex_r[0] = state->tex_g[0] = 0;
3016 state->tex_b[0] = voodoo->tmuConfig;
3017 }
3018
3019 if (cc_localselect_override)
3020 sel = (state->tex_a[0] & 0x80) ? 1 : 0;
3021 else
3022 sel = cc_localselect;
3023
3024 if (sel)
3025 {
3026 clocal_r = (params->color0 >> 16) & 0xff;
3027 clocal_g = (params->color0 >> 8) & 0xff;
3028 clocal_b = params->color0 & 0xff;
3029 }
3030 else
3031 {
3032 clocal_r = CLAMP(state->ir >> 12);
3033 clocal_g = CLAMP(state->ig >> 12);
3034 clocal_b = CLAMP(state->ib >> 12);
3035 }
3036
3037 switch (_rgb_sel)
3038 {
3039 case CC_LOCALSELECT_ITER_RGB: /*Iterated RGB*/
3040 cother_r = CLAMP(state->ir >> 12);
3041 cother_g = CLAMP(state->ig >> 12);
3042 cother_b = CLAMP(state->ib >> 12);
3043 break;
3044
3045 case CC_LOCALSELECT_TEX: /*TREX Color Output*/
3046 cother_r = state->tex_r[0];
3047 cother_g = state->tex_g[0];
3048 cother_b = state->tex_b[0];
3049 break;
3050
3051 case CC_LOCALSELECT_COLOR1: /*Color1 RGB*/
3052 cother_r = (params->color1 >> 16) & 0xff;
3053 cother_g = (params->color1 >> 8) & 0xff;
3054 cother_b = params->color1 & 0xff;
3055 break;
3056
3057 case CC_LOCALSELECT_LFB: /*Linear Frame Buffer*/
3058 cother_r = src_r;
3059 cother_g = src_g;
3060 cother_b = src_b;
3061 break;
3062 }
3063
3064 switch (cca_localselect)
3065 {
3066 case CCA_LOCALSELECT_ITER_A:
3067 alocal = CLAMP(state->ia >> 12);
3068 break;
3069
3070 case CCA_LOCALSELECT_COLOR0:
3071 alocal = (params->color0 >> 24) & 0xff;
3072 break;
3073
3074 case CCA_LOCALSELECT_ITER_Z:
3075 alocal = CLAMP(state->z >> 20);
3076 break;
3077
3078 default:
3079 fatal("Bad cca_localselect %i\n", cca_localselect);
3080 alocal = 0xff;
3081 break;
3082 }
3083
3084 switch (a_sel)
3085 {
3086 case A_SEL_ITER_A:
3087 aother = CLAMP(state->ia >> 12);
3088 break;
3089 case A_SEL_TEX:
3090 aother = state->tex_a[0];
3091 break;
3092 case A_SEL_COLOR1:
3093 aother = (params->color1 >> 24) & 0xff;
3094 break;
3095 default:
3096 fatal("Bad a_sel %i\n", a_sel);
3097 aother = 0;
3098 break;
3099 }
3100
3101 if (cc_zero_other)
3102 {
3103 src_r = 0;
3104 src_g = 0;
3105 src_b = 0;
3106 }
3107 else
3108 {
3109 src_r = cother_r;
3110 src_g = cother_g;
3111 src_b = cother_b;
3112 }
3113
3114 if (cca_zero_other)
3115 src_a = 0;
3116 else
3117 src_a = aother;
3118
3119 if (cc_sub_clocal)
3120 {
3121 src_r -= clocal_r;
3122 src_g -= clocal_g;
3123 src_b -= clocal_b;
3124 }
3125
3126 if (cca_sub_clocal)
3127 src_a -= alocal;
3128
3129 switch (cc_mselect)
3130 {
3131 case CC_MSELECT_ZERO:
3132 msel_r = 0;
3133 msel_g = 0;
3134 msel_b = 0;
3135 break;
3136 case CC_MSELECT_CLOCAL:
3137 msel_r = clocal_r;
3138 msel_g = clocal_g;
3139 msel_b = clocal_b;
3140 break;
3141 case CC_MSELECT_AOTHER:
3142 msel_r = aother;
3143 msel_g = aother;
3144 msel_b = aother;
3145 break;
3146 case CC_MSELECT_ALOCAL:
3147 msel_r = alocal;
3148 msel_g = alocal;
3149 msel_b = alocal;
3150 break;
3151 case CC_MSELECT_TEX:
3152 msel_r = state->tex_a[0];
3153 msel_g = state->tex_a[0];
3154 msel_b = state->tex_a[0];
3155 break;
3156 case CC_MSELECT_TEXRGB:
3157 msel_r = state->tex_r[0];
3158 msel_g = state->tex_g[0];
3159 msel_b = state->tex_b[0];
3160 break;
3161
3162 default:
3163 fatal("Bad cc_mselect %i\n", cc_mselect);
3164 msel_r = 0;
3165 msel_g = 0;
3166 msel_b = 0;
3167 break;
3168 }
3169
3170 switch (cca_mselect)
3171 {
3172 case CCA_MSELECT_ZERO:
3173 msel_a = 0;
3174 break;
3175 case CCA_MSELECT_ALOCAL:
3176 msel_a = alocal;
3177 break;
3178 case CCA_MSELECT_AOTHER:
3179 msel_a = aother;
3180 break;
3181 case CCA_MSELECT_ALOCAL2:
3182 msel_a = alocal;
3183 break;
3184 case CCA_MSELECT_TEX:
3185 msel_a = state->tex_a[0];
3186 break;
3187
3188 default:
3189 fatal("Bad cca_mselect %i\n", cca_mselect);
3190 msel_a = 0;
3191 break;
3192 }
3193
3194 if (!cc_reverse_blend)
3195 {
3196 msel_r ^= 0xff;
3197 msel_g ^= 0xff;
3198 msel_b ^= 0xff;
3199 }
3200 msel_r++;
3201 msel_g++;
3202 msel_b++;
3203
3204 if (!cca_reverse_blend)
3205 msel_a ^= 0xff;
3206 msel_a++;
3207
3208 src_r = (src_r * msel_r) >> 8;
3209 src_g = (src_g * msel_g) >> 8;
3210 src_b = (src_b * msel_b) >> 8;
3211 src_a = (src_a * msel_a) >> 8;
3212
3213 switch (cc_add)
3214 {
3215 case CC_ADD_CLOCAL:
3216 src_r += clocal_r;
3217 src_g += clocal_g;
3218 src_b += clocal_b;
3219 break;
3220 case CC_ADD_ALOCAL:
3221 src_r += alocal;
3222 src_g += alocal;
3223 src_b += alocal;
3224 break;
3225 case 0:
3226 break;
3227 default:
3228 fatal("Bad cc_add %i\n", cc_add);
3229 }
3230
3231 if (cca_add)
3232 src_a += alocal;
3233
3234 src_r = CLAMP(src_r);
3235 src_g = CLAMP(src_g);
3236 src_b = CLAMP(src_b);
3237 src_a = CLAMP(src_a);
3238
3239 if (cc_invert_output)
3240 {
3241 src_r ^= 0xff;
3242 src_g ^= 0xff;
3243 src_b ^= 0xff;
3244 }
3245 if (cca_invert_output)
3246 src_a ^= 0xff;
3247
3248 if (params->fogMode & FOG_ENABLE)
3249 APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w);
3250
3251 if (params->alphaMode & 1)
3252 ALPHA_TEST(src_a);
3253
3254 if (params->alphaMode & (1 << 4))
3255 ALPHA_BLEND(src_r, src_g, src_b, src_a);
3256
3257 if (update)
3258 {
3259 if (dither)
3260 {
3261 if (dither2x2)
3262 {
3263 src_r = dither_rb2x2[src_r][real_y & 1][x & 1];
3264 src_g = dither_g2x2[src_g][real_y & 1][x & 1];
3265 src_b = dither_rb2x2[src_b][real_y & 1][x & 1];
3266 }
3267 else
3268 {
3269 src_r = dither_rb[src_r][real_y & 3][x & 3];
3270 src_g = dither_g[src_g][real_y & 3][x & 3];
3271 src_b = dither_rb[src_b][real_y & 3][x & 3];
3272 }
3273 }
3274 else
3275 {
3276 src_r >>= 3;
3277 src_g >>= 2;
3278 src_b >>= 3;
3279 }
3280
3281 if (params->fbzMode & FBZ_RGB_WMASK)
3282 fb_mem[x] = src_b | (src_g << 5) | (src_r << 11);
3283
3284 if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE))
3285 aux_mem[x] = new_depth;
3286 }
3287 }
3288 voodoo_output &= ~2;
3289 voodoo->fbiPixelsOut++;
3290 skip_pixel:
3291 if (state->xdir > 0)
3292 {
3293 state->ir += params->dRdX;
3294 state->ig += params->dGdX;
3295 state->ib += params->dBdX;
3296 state->ia += params->dAdX;
3297 state->z += params->dZdX;
3298 state->tmu0_s += params->tmu[0].dSdX;
3299 state->tmu0_t += params->tmu[0].dTdX;
3300 state->tmu0_w += params->tmu[0].dWdX;
3301 state->tmu1_s += params->tmu[1].dSdX;
3302 state->tmu1_t += params->tmu[1].dTdX;
3303 state->tmu1_w += params->tmu[1].dWdX;
3304 state->w += params->dWdX;
3305 }
3306 else
3307 {
3308 state->ir -= params->dRdX;
3309 state->ig -= params->dGdX;
3310 state->ib -= params->dBdX;
3311 state->ia -= params->dAdX;
3312 state->z -= params->dZdX;
3313 state->tmu0_s -= params->tmu[0].dSdX;
3314 state->tmu0_t -= params->tmu[0].dTdX;
3315 state->tmu0_w -= params->tmu[0].dWdX;
3316 state->tmu1_s -= params->tmu[1].dSdX;
3317 state->tmu1_t -= params->tmu[1].dTdX;
3318 state->tmu1_w -= params->tmu[1].dWdX;
3319 state->w -= params->dWdX;
3320 }
3321
3322 x += state->xdir;
3323 } while (start_x != x2);
3324
3325 voodoo->pixel_count[odd_even] += state->pixel_count;
3326 voodoo->texel_count[odd_even] += state->texel_count;
3327 voodoo->fbiPixelsIn += state->pixel_count;
3328
3329 if (voodoo->params.draw_offset == voodoo->params.front_offset)
3330 voodoo->dirty_line[real_y >> 1] = 1;
3331 next_line:
3332 if (SLI_ENABLED)
3333 {
3334 state->base_r += params->dRdY;
3335 state->base_g += params->dGdY;
3336 state->base_b += params->dBdY;
3337 state->base_a += params->dAdY;
3338 state->base_z += params->dZdY;
3339 state->tmu[0].base_s += params->tmu[0].dSdY;
3340 state->tmu[0].base_t += params->tmu[0].dTdY;
3341 state->tmu[0].base_w += params->tmu[0].dWdY;
3342 state->tmu[1].base_s += params->tmu[1].dSdY;
3343 state->tmu[1].base_t += params->tmu[1].dTdY;
3344 state->tmu[1].base_w += params->tmu[1].dWdY;
3345 state->base_w += params->dWdY;
3346 state->xstart += state->dx1;
3347 state->xend += state->dx2;
3348 }
3349 state->base_r += params->dRdY;
3350 state->base_g += params->dGdY;
3351 state->base_b += params->dBdY;
3352 state->base_a += params->dAdY;
3353 state->base_z += params->dZdY;
3354 state->tmu[0].base_s += params->tmu[0].dSdY;
3355 state->tmu[0].base_t += params->tmu[0].dTdY;
3356 state->tmu[0].base_w += params->tmu[0].dWdY;
3357 state->tmu[1].base_s += params->tmu[1].dSdY;
3358 state->tmu[1].base_t += params->tmu[1].dTdY;
3359 state->tmu[1].base_w += params->tmu[1].dWdY;
3360 state->base_w += params->dWdY;
3361 state->xstart += state->dx1;
3362 state->xend += state->dx2;
3363 }
3364
3365 voodoo->texture_cache[0][params->tex_entry[0]].refcount_r[odd_even]++;
3366 voodoo->texture_cache[1][params->tex_entry[1]].refcount_r[odd_even]++;
3367 }
3368
voodoo_triangle(voodoo_t * voodoo,voodoo_params_t * params,int odd_even)3369 static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even)
3370 {
3371 voodoo_state_t state;
3372 int vertexAy_adjusted;
3373 int vertexCy_adjusted;
3374 int dx, dy;
3375
3376 uint64_t tempdx, tempdy;
3377 uint64_t tempLOD;
3378 int LOD;
3379 int lodbias;
3380
3381 voodoo->tri_count++;
3382
3383 dx = 8 - (params->vertexAx & 0xf);
3384 if ((params->vertexAx & 0xf) > 8)
3385 dx += 16;
3386 dy = 8 - (params->vertexAy & 0xf);
3387 if ((params->vertexAy & 0xf) > 8)
3388 dy += 16;
3389
3390 /* pclog("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i,%i %08x %08x %08x,%08x tex=%i,%i fogMode=%08x\n", odd_even, voodoo->params_read_idx[odd_even], voodoo->params_read_idx[odd_even] & PARAM_MASK, (float)params->vertexAx / 16.0, (float)params->vertexAy / 16.0,
3391 (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0,
3392 (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0,
3393 (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0,
3394 (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[1] : 0, params->fbzColorPath, params->alphaMode, params->textureMode[0],params->textureMode[1], params->tex_entry[0],params->tex_entry[1], params->fogMode);*/
3395
3396 state.base_r = params->startR;
3397 state.base_g = params->startG;
3398 state.base_b = params->startB;
3399 state.base_a = params->startA;
3400 state.base_z = params->startZ;
3401 state.tmu[0].base_s = params->tmu[0].startS;
3402 state.tmu[0].base_t = params->tmu[0].startT;
3403 state.tmu[0].base_w = params->tmu[0].startW;
3404 state.tmu[1].base_s = params->tmu[1].startS;
3405 state.tmu[1].base_t = params->tmu[1].startT;
3406 state.tmu[1].base_w = params->tmu[1].startW;
3407 state.base_w = params->startW;
3408
3409 if (params->fbzColorPath & FBZ_PARAM_ADJUST)
3410 {
3411 state.base_r += (dx*params->dRdX + dy*params->dRdY) >> 4;
3412 state.base_g += (dx*params->dGdX + dy*params->dGdY) >> 4;
3413 state.base_b += (dx*params->dBdX + dy*params->dBdY) >> 4;
3414 state.base_a += (dx*params->dAdX + dy*params->dAdY) >> 4;
3415 state.base_z += (dx*params->dZdX + dy*params->dZdY) >> 4;
3416 state.tmu[0].base_s += (dx*params->tmu[0].dSdX + dy*params->tmu[0].dSdY) >> 4;
3417 state.tmu[0].base_t += (dx*params->tmu[0].dTdX + dy*params->tmu[0].dTdY) >> 4;
3418 state.tmu[0].base_w += (dx*params->tmu[0].dWdX + dy*params->tmu[0].dWdY) >> 4;
3419 state.tmu[1].base_s += (dx*params->tmu[1].dSdX + dy*params->tmu[1].dSdY) >> 4;
3420 state.tmu[1].base_t += (dx*params->tmu[1].dTdX + dy*params->tmu[1].dTdY) >> 4;
3421 state.tmu[1].base_w += (dx*params->tmu[1].dWdX + dy*params->tmu[1].dWdY) >> 4;
3422 state.base_w += (dx*params->dWdX + dy*params->dWdY) >> 4;
3423 }
3424
3425 tris++;
3426
3427 state.vertexAy = params->vertexAy & ~0xffff0000;
3428 if (state.vertexAy & 0x8000)
3429 state.vertexAy |= 0xffff0000;
3430 state.vertexBy = params->vertexBy & ~0xffff0000;
3431 if (state.vertexBy & 0x8000)
3432 state.vertexBy |= 0xffff0000;
3433 state.vertexCy = params->vertexCy & ~0xffff0000;
3434 if (state.vertexCy & 0x8000)
3435 state.vertexCy |= 0xffff0000;
3436
3437 state.vertexAx = params->vertexAx & ~0xffff0000;
3438 if (state.vertexAx & 0x8000)
3439 state.vertexAx |= 0xffff0000;
3440 state.vertexBx = params->vertexBx & ~0xffff0000;
3441 if (state.vertexBx & 0x8000)
3442 state.vertexBx |= 0xffff0000;
3443 state.vertexCx = params->vertexCx & ~0xffff0000;
3444 if (state.vertexCx & 0x8000)
3445 state.vertexCx |= 0xffff0000;
3446
3447 vertexAy_adjusted = (state.vertexAy+7) >> 4;
3448 vertexCy_adjusted = (state.vertexCy+7) >> 4;
3449
3450 if (state.vertexBy - state.vertexAy)
3451 state.dxAB = (int)((((int64_t)state.vertexBx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexBy - state.vertexAy);
3452 else
3453 state.dxAB = 0;
3454 if (state.vertexCy - state.vertexAy)
3455 state.dxAC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexCy - state.vertexAy);
3456 else
3457 state.dxAC = 0;
3458 if (state.vertexCy - state.vertexBy)
3459 state.dxBC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexBx << 12)) << 4) / (int)(state.vertexCy - state.vertexBy);
3460 else
3461 state.dxBC = 0;
3462
3463 state.lod_min[0] = (params->tLOD[0] & 0x3f) << 6;
3464 state.lod_max[0] = ((params->tLOD[0] >> 6) & 0x3f) << 6;
3465 if (state.lod_max[0] > 0x800)
3466 state.lod_max[0] = 0x800;
3467 state.lod_min[1] = (params->tLOD[1] & 0x3f) << 6;
3468 state.lod_max[1] = ((params->tLOD[1] >> 6) & 0x3f) << 6;
3469 if (state.lod_max[1] > 0x800)
3470 state.lod_max[1] = 0x800;
3471
3472 state.xstart = state.xend = state.vertexAx << 8;
3473 state.xdir = params->sign ? -1 : 1;
3474
3475 state.y = (state.vertexAy + 8) >> 4;
3476 state.ydir = 1;
3477
3478
3479 tempdx = (params->tmu[0].dSdX >> 14) * (params->tmu[0].dSdX >> 14) + (params->tmu[0].dTdX >> 14) * (params->tmu[0].dTdX >> 14);
3480 tempdy = (params->tmu[0].dSdY >> 14) * (params->tmu[0].dSdY >> 14) + (params->tmu[0].dTdY >> 14) * (params->tmu[0].dTdY >> 14);
3481
3482 if (tempdx > tempdy)
3483 tempLOD = tempdx;
3484 else
3485 tempLOD = tempdy;
3486
3487 LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256);
3488 LOD >>= 2;
3489
3490 lodbias = (params->tLOD[0] >> 12) & 0x3f;
3491 if (lodbias & 0x20)
3492 lodbias |= ~0x3f;
3493 state.tmu[0].lod = LOD + (lodbias << 6);
3494
3495
3496 tempdx = (params->tmu[1].dSdX >> 14) * (params->tmu[1].dSdX >> 14) + (params->tmu[1].dTdX >> 14) * (params->tmu[1].dTdX >> 14);
3497 tempdy = (params->tmu[1].dSdY >> 14) * (params->tmu[1].dSdY >> 14) + (params->tmu[1].dTdY >> 14) * (params->tmu[1].dTdY >> 14);
3498
3499 if (tempdx > tempdy)
3500 tempLOD = tempdx;
3501 else
3502 tempLOD = tempdy;
3503
3504 LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256);
3505 LOD >>= 2;
3506
3507 lodbias = (params->tLOD[1] >> 12) & 0x3f;
3508 if (lodbias & 0x20)
3509 lodbias |= ~0x3f;
3510 state.tmu[1].lod = LOD + (lodbias << 6);
3511
3512
3513 voodoo_half_triangle(voodoo, params, &state, vertexAy_adjusted, vertexCy_adjusted, odd_even);
3514 }
3515
wake_render_thread(voodoo_t * voodoo)3516 static inline void wake_render_thread(voodoo_t *voodoo)
3517 {
3518 thread_set_event(voodoo->wake_render_thread[0]); /*Wake up render thread if moving from idle*/
3519 if (voodoo->render_threads == 2)
3520 thread_set_event(voodoo->wake_render_thread[1]); /*Wake up render thread if moving from idle*/
3521 }
3522
wait_for_render_thread_idle(voodoo_t * voodoo)3523 static inline void wait_for_render_thread_idle(voodoo_t *voodoo)
3524 {
3525 while (!PARAM_EMPTY_1 || (voodoo->render_threads == 2 && !PARAM_EMPTY_2) || voodoo->render_voodoo_busy[0] || (voodoo->render_threads == 2 && voodoo->render_voodoo_busy[1]))
3526 {
3527 wake_render_thread(voodoo);
3528 if (!PARAM_EMPTY_1 || voodoo->render_voodoo_busy[0])
3529 thread_wait_event(voodoo->render_not_full_event[0], 1);
3530 if (voodoo->render_threads == 2 && (!PARAM_EMPTY_2 || voodoo->render_voodoo_busy[1]))
3531 thread_wait_event(voodoo->render_not_full_event[1], 1);
3532 }
3533 }
3534
render_thread(void * param,int odd_even)3535 static void render_thread(void *param, int odd_even)
3536 {
3537 voodoo_t *voodoo = (voodoo_t *)param;
3538
3539 while (1)
3540 {
3541 thread_set_event(voodoo->render_not_full_event[odd_even]);
3542 thread_wait_event(voodoo->wake_render_thread[odd_even], -1);
3543 thread_reset_event(voodoo->wake_render_thread[odd_even]);
3544 voodoo->render_voodoo_busy[odd_even] = 1;
3545
3546 while (!(odd_even ? PARAM_EMPTY_2 : PARAM_EMPTY_1))
3547 {
3548 uint64_t start_time = timer_read();
3549 uint64_t end_time;
3550 voodoo_params_t *params = &voodoo->params_buffer[voodoo->params_read_idx[odd_even] & PARAM_MASK];
3551
3552 voodoo_triangle(voodoo, params, odd_even);
3553
3554 voodoo->params_read_idx[odd_even]++;
3555
3556 if ((odd_even ? PARAM_ENTRIES_2 : PARAM_ENTRIES_1) > (PARAM_SIZE - 10))
3557 thread_set_event(voodoo->render_not_full_event[odd_even]);
3558
3559 end_time = timer_read();
3560 voodoo->render_time[odd_even] += end_time - start_time;
3561 }
3562
3563 voodoo->render_voodoo_busy[odd_even] = 0;
3564 }
3565 }
3566
render_thread_1(void * param)3567 static void render_thread_1(void *param)
3568 {
3569 render_thread(param, 0);
3570 }
render_thread_2(void * param)3571 static void render_thread_2(void *param)
3572 {
3573 render_thread(param, 1);
3574 }
3575
queue_triangle(voodoo_t * voodoo,voodoo_params_t * params)3576 static inline void queue_triangle(voodoo_t *voodoo, voodoo_params_t *params)
3577 {
3578 voodoo_params_t *params_new = &voodoo->params_buffer[voodoo->params_write_idx & PARAM_MASK];
3579
3580 while (PARAM_FULL_1 || (voodoo->render_threads == 2 && PARAM_FULL_2))
3581 {
3582 thread_reset_event(voodoo->render_not_full_event[0]);
3583 if (voodoo->render_threads == 2)
3584 thread_reset_event(voodoo->render_not_full_event[1]);
3585 if (PARAM_FULL_1)
3586 {
3587 thread_wait_event(voodoo->render_not_full_event[0], -1); /*Wait for room in ringbuffer*/
3588 }
3589 if (voodoo->render_threads == 2 && PARAM_FULL_2)
3590 {
3591 thread_wait_event(voodoo->render_not_full_event[1], -1); /*Wait for room in ringbuffer*/
3592 }
3593 }
3594
3595 use_texture(voodoo, params, 0);
3596 if (voodoo->dual_tmus)
3597 use_texture(voodoo, params, 1);
3598
3599 memcpy(params_new, params, sizeof(voodoo_params_t));
3600
3601 voodoo->params_write_idx++;
3602
3603 if (PARAM_ENTRIES_1 < 4 || (voodoo->render_threads == 2 && PARAM_ENTRIES_2 < 4))
3604 wake_render_thread(voodoo);
3605 }
3606
voodoo_fastfill(voodoo_t * voodoo,voodoo_params_t * params)3607 static void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params)
3608 {
3609 int y;
3610 int low_y, high_y;
3611
3612 if (params->fbzMode & (1 << 17))
3613 {
3614 high_y = voodoo->v_disp - params->clipLowY;
3615 low_y = voodoo->v_disp - params->clipHighY;
3616 }
3617 else
3618 {
3619 low_y = params->clipLowY;
3620 high_y = params->clipHighY;
3621 }
3622
3623 if (params->fbzMode & FBZ_RGB_WMASK)
3624 {
3625 int r, g, b;
3626 uint16_t col;
3627
3628 r = ((params->color1 >> 16) >> 3) & 0x1f;
3629 g = ((params->color1 >> 8) >> 2) & 0x3f;
3630 b = (params->color1 >> 3) & 0x1f;
3631 col = b | (g << 5) | (r << 11);
3632
3633 if (SLI_ENABLED)
3634 {
3635 for (y = low_y; y < high_y; y += 2)
3636 {
3637 uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
3638 int x;
3639
3640 for (x = params->clipLeft; x < params->clipRight; x++)
3641 cbuf[x] = col;
3642 }
3643 }
3644 else
3645 {
3646 for (y = low_y; y < high_y; y++)
3647 {
3648 uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + y*voodoo->row_width) & voodoo->fb_mask];
3649 int x;
3650
3651 for (x = params->clipLeft; x < params->clipRight; x++)
3652 cbuf[x] = col;
3653 }
3654 }
3655 }
3656 if (params->fbzMode & FBZ_DEPTH_WMASK)
3657 {
3658 if (SLI_ENABLED)
3659 {
3660 for (y = low_y; y < high_y; y += 2)
3661 {
3662 uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask];
3663 int x;
3664
3665 for (x = params->clipLeft; x < params->clipRight; x++)
3666 abuf[x] = params->zaColor & 0xffff;
3667 }
3668 }
3669 else
3670 {
3671 for (y = low_y; y < high_y; y++)
3672 {
3673 uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + y*voodoo->row_width) & voodoo->fb_mask];
3674 int x;
3675
3676 for (x = params->clipLeft; x < params->clipRight; x++)
3677 abuf[x] = params->zaColor & 0xffff;
3678 }
3679 }
3680 }
3681 }
3682
3683 enum
3684 {
3685 SETUPMODE_RGB = (1 << 0),
3686 SETUPMODE_ALPHA = (1 << 1),
3687 SETUPMODE_Z = (1 << 2),
3688 SETUPMODE_Wb = (1 << 3),
3689 SETUPMODE_W0 = (1 << 4),
3690 SETUPMODE_S0_T0 = (1 << 5),
3691 SETUPMODE_W1 = (1 << 6),
3692 SETUPMODE_S1_T1 = (1 << 7),
3693
3694 SETUPMODE_STRIP_MODE = (1 << 16),
3695 SETUPMODE_CULLING_ENABLE = (1 << 17),
3696 SETUPMODE_CULLING_SIGN = (1 << 18),
3697 SETUPMODE_DISABLE_PINGPONG = (1 << 19)
3698 };
3699
triangle_setup(voodoo_t * voodoo)3700 static void triangle_setup(voodoo_t *voodoo)
3701 {
3702 float dxAB, dxBC, dyAB, dyBC;
3703 float area;
3704 int va = 0, vb = 1, vc = 2;
3705 int reverse_cull = 0;
3706
3707 if (voodoo->verts[0].sVy < voodoo->verts[1].sVy)
3708 {
3709 if (voodoo->verts[1].sVy < voodoo->verts[2].sVy)
3710 {
3711 /* V1>V0, V2>V1, V2>V1>V0*/
3712 va = 0; /*OK*/
3713 vb = 1;
3714 vc = 2;
3715 }
3716 else
3717 {
3718 /* V1>V0, V1>V2*/
3719 if (voodoo->verts[0].sVy < voodoo->verts[2].sVy)
3720 {
3721 /* V1>V0, V1>V2, V2>V0, V1>V2>V0*/
3722 va = 0;
3723 vb = 2;
3724 vc = 1;
3725 reverse_cull = 1;
3726 }
3727 else
3728 {
3729 /* V1>V0, V1>V2, V0>V2, V1>V0>V2*/
3730 va = 2;
3731 vb = 0;
3732 vc = 1;
3733 }
3734 }
3735 }
3736 else
3737 {
3738 if (voodoo->verts[1].sVy < voodoo->verts[2].sVy)
3739 {
3740 /* V0>V1, V2>V1*/
3741 if (voodoo->verts[0].sVy < voodoo->verts[2].sVy)
3742 {
3743 /* V0>V1, V2>V1, V2>V0, V2>V0>V1*/
3744 va = 1;
3745 vb = 0;
3746 vc = 2;
3747 reverse_cull = 1;
3748 }
3749 else
3750 {
3751 /* V0>V1, V2>V1, V0>V2, V0>V2>V1*/
3752 va = 1;
3753 vb = 2;
3754 vc = 0;
3755 }
3756 }
3757 else
3758 {
3759 /*V0>V1>V2*/
3760 va = 2;
3761 vb = 1;
3762 vc = 0;
3763 reverse_cull = 1;
3764 }
3765 }
3766
3767 dxAB = voodoo->verts[va].sVx - voodoo->verts[vb].sVx;
3768 dxBC = voodoo->verts[vb].sVx - voodoo->verts[vc].sVx;
3769 dyAB = voodoo->verts[va].sVy - voodoo->verts[vb].sVy;
3770 dyBC = voodoo->verts[vb].sVy - voodoo->verts[vc].sVy;
3771
3772 area = dxAB * dyBC - dxBC * dyAB;
3773
3774 if (area == 0.0)
3775 {
3776 if ((voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) &&
3777 !(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG))
3778 voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN;
3779
3780 return;
3781 }
3782
3783 dxAB /= area;
3784 dxBC /= area;
3785 dyAB /= area;
3786 dyBC /= area;
3787
3788 if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE)
3789 {
3790 int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN;
3791 int sign = (area < 0.0);
3792
3793 if (!(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG))
3794 voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN;
3795
3796 if (reverse_cull)
3797 sign = !sign;
3798
3799 if (cull_sign && sign)
3800 return;
3801 if (!cull_sign && !sign)
3802 return;
3803 }
3804
3805 voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(voodoo->verts[va].sVx * 16.0f) & 0xffff);
3806 voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(voodoo->verts[va].sVy * 16.0f) & 0xffff);
3807 voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(voodoo->verts[vb].sVx * 16.0f) & 0xffff);
3808 voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(voodoo->verts[vb].sVy * 16.0f) & 0xffff);
3809 voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(voodoo->verts[vc].sVx * 16.0f) & 0xffff);
3810 voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(voodoo->verts[vc].sVy * 16.0f) & 0xffff);
3811
3812 if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy)
3813 fatal("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy);
3814
3815 if (voodoo->sSetupMode & SETUPMODE_RGB)
3816 {
3817 voodoo->params.startR = (int32_t)(voodoo->verts[va].sRed * 4096.0f);
3818 voodoo->params.dRdX = (int32_t)(((voodoo->verts[va].sRed - voodoo->verts[vb].sRed) * dyBC - (voodoo->verts[vb].sRed - voodoo->verts[vc].sRed) * dyAB) * 4096.0f);
3819 voodoo->params.dRdY = (int32_t)(((voodoo->verts[vb].sRed - voodoo->verts[vc].sRed) * dxAB - (voodoo->verts[va].sRed - voodoo->verts[vb].sRed) * dxBC) * 4096.0f);
3820 voodoo->params.startG = (int32_t)(voodoo->verts[va].sGreen * 4096.0f);
3821 voodoo->params.dGdX = (int32_t)(((voodoo->verts[va].sGreen - voodoo->verts[vb].sGreen) * dyBC - (voodoo->verts[vb].sGreen - voodoo->verts[vc].sGreen) * dyAB) * 4096.0f);
3822 voodoo->params.dGdY = (int32_t)(((voodoo->verts[vb].sGreen - voodoo->verts[vc].sGreen) * dxAB - (voodoo->verts[va].sGreen - voodoo->verts[vb].sGreen) * dxBC) * 4096.0f);
3823 voodoo->params.startB = (int32_t)(voodoo->verts[va].sBlue * 4096.0f);
3824 voodoo->params.dBdX = (int32_t)(((voodoo->verts[va].sBlue - voodoo->verts[vb].sBlue) * dyBC - (voodoo->verts[vb].sBlue - voodoo->verts[vc].sBlue) * dyAB) * 4096.0f);
3825 voodoo->params.dBdY = (int32_t)(((voodoo->verts[vb].sBlue - voodoo->verts[vc].sBlue) * dxAB - (voodoo->verts[va].sBlue - voodoo->verts[vb].sBlue) * dxBC) * 4096.0f);
3826 }
3827 if (voodoo->sSetupMode & SETUPMODE_ALPHA)
3828 {
3829 voodoo->params.startA = (int32_t)(voodoo->verts[va].sAlpha * 4096.0f);
3830 voodoo->params.dAdX = (int32_t)(((voodoo->verts[va].sAlpha - voodoo->verts[vb].sAlpha) * dyBC - (voodoo->verts[vb].sAlpha - voodoo->verts[vc].sAlpha) * dyAB) * 4096.0f);
3831 voodoo->params.dAdY = (int32_t)(((voodoo->verts[vb].sAlpha - voodoo->verts[vc].sAlpha) * dxAB - (voodoo->verts[va].sAlpha - voodoo->verts[vb].sAlpha) * dxBC) * 4096.0f);
3832 }
3833 if (voodoo->sSetupMode & SETUPMODE_Z)
3834 {
3835 voodoo->params.startZ = (int32_t)(voodoo->verts[va].sVz * 4096.0f);
3836 voodoo->params.dZdX = (int32_t)(((voodoo->verts[va].sVz - voodoo->verts[vb].sVz) * dyBC - (voodoo->verts[vb].sVz - voodoo->verts[vc].sVz) * dyAB) * 4096.0f);
3837 voodoo->params.dZdY = (int32_t)(((voodoo->verts[vb].sVz - voodoo->verts[vc].sVz) * dxAB - (voodoo->verts[va].sVz - voodoo->verts[vb].sVz) * dxBC) * 4096.0f);
3838 }
3839 if (voodoo->sSetupMode & SETUPMODE_Wb)
3840 {
3841 voodoo->params.startW = (int64_t)(voodoo->verts[va].sWb * 4294967296.0f);
3842 voodoo->params.dWdX = (int64_t)(((voodoo->verts[va].sWb - voodoo->verts[vb].sWb) * dyBC - (voodoo->verts[vb].sWb - voodoo->verts[vc].sWb) * dyAB) * 4294967296.0f);
3843 voodoo->params.dWdY = (int64_t)(((voodoo->verts[vb].sWb - voodoo->verts[vc].sWb) * dxAB - (voodoo->verts[va].sWb - voodoo->verts[vb].sWb) * dxBC) * 4294967296.0f);
3844 voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW;
3845 voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX;
3846 voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY;
3847 }
3848 if (voodoo->sSetupMode & SETUPMODE_W0)
3849 {
3850 voodoo->params.tmu[0].startW = (int64_t)(voodoo->verts[va].sW0 * 4294967296.0f);
3851 voodoo->params.tmu[0].dWdX = (int64_t)(((voodoo->verts[va].sW0 - voodoo->verts[vb].sW0) * dyBC - (voodoo->verts[vb].sW0 - voodoo->verts[vc].sW0) * dyAB) * 4294967296.0f);
3852 voodoo->params.tmu[0].dWdY = (int64_t)(((voodoo->verts[vb].sW0 - voodoo->verts[vc].sW0) * dxAB - (voodoo->verts[va].sW0 - voodoo->verts[vb].sW0) * dxBC) * 4294967296.0f);
3853 voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW;
3854 voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX;
3855 voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY;
3856 }
3857 if (voodoo->sSetupMode & SETUPMODE_S0_T0)
3858 {
3859 voodoo->params.tmu[0].startS = (int64_t)(voodoo->verts[va].sS0 * 4294967296.0f);
3860 voodoo->params.tmu[0].dSdX = (int64_t)(((voodoo->verts[va].sS0 - voodoo->verts[vb].sS0) * dyBC - (voodoo->verts[vb].sS0 - voodoo->verts[vc].sS0) * dyAB) * 4294967296.0f);
3861 voodoo->params.tmu[0].dSdY = (int64_t)(((voodoo->verts[vb].sS0 - voodoo->verts[vc].sS0) * dxAB - (voodoo->verts[va].sS0 - voodoo->verts[vb].sS0) * dxBC) * 4294967296.0f);
3862 voodoo->params.tmu[0].startT = (int64_t)(voodoo->verts[va].sT0 * 4294967296.0f);
3863 voodoo->params.tmu[0].dTdX = (int64_t)(((voodoo->verts[va].sT0 - voodoo->verts[vb].sT0) * dyBC - (voodoo->verts[vb].sT0 - voodoo->verts[vc].sT0) * dyAB) * 4294967296.0f);
3864 voodoo->params.tmu[0].dTdY = (int64_t)(((voodoo->verts[vb].sT0 - voodoo->verts[vc].sT0) * dxAB - (voodoo->verts[va].sT0 - voodoo->verts[vb].sT0) * dxBC) * 4294967296.0f);
3865 voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS;
3866 voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX;
3867 voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY;
3868 voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT;
3869 voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX;
3870 voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY;
3871 }
3872 if (voodoo->sSetupMode & SETUPMODE_W1)
3873 {
3874 voodoo->params.tmu[1].startW = (int64_t)(voodoo->verts[va].sW1 * 4294967296.0f);
3875 voodoo->params.tmu[1].dWdX = (int64_t)(((voodoo->verts[va].sW1 - voodoo->verts[vb].sW1) * dyBC - (voodoo->verts[vb].sW1 - voodoo->verts[vc].sW1) * dyAB) * 4294967296.0f);
3876 voodoo->params.tmu[1].dWdY = (int64_t)(((voodoo->verts[vb].sW1 - voodoo->verts[vc].sW1) * dxAB - (voodoo->verts[va].sW1 - voodoo->verts[vb].sW1) * dxBC) * 4294967296.0f);
3877 }
3878 if (voodoo->sSetupMode & SETUPMODE_S1_T1)
3879 {
3880 voodoo->params.tmu[1].startS = (int64_t)(voodoo->verts[va].sS1 * 4294967296.0f);
3881 voodoo->params.tmu[1].dSdX = (int64_t)(((voodoo->verts[va].sS1 - voodoo->verts[vb].sS1) * dyBC - (voodoo->verts[vb].sS1 - voodoo->verts[vc].sS1) * dyAB) * 4294967296.0f);
3882 voodoo->params.tmu[1].dSdY = (int64_t)(((voodoo->verts[vb].sS1 - voodoo->verts[vc].sS1) * dxAB - (voodoo->verts[va].sS1 - voodoo->verts[vb].sS1) * dxBC) * 4294967296.0f);
3883 voodoo->params.tmu[1].startT = (int64_t)(voodoo->verts[va].sT1 * 4294967296.0f);
3884 voodoo->params.tmu[1].dTdX = (int64_t)(((voodoo->verts[va].sT1 - voodoo->verts[vb].sT1) * dyBC - (voodoo->verts[vb].sT1 - voodoo->verts[vc].sT1) * dyAB) * 4294967296.0f);
3885 voodoo->params.tmu[1].dTdY = (int64_t)(((voodoo->verts[vb].sT1 - voodoo->verts[vc].sT1) * dxAB - (voodoo->verts[va].sT1 - voodoo->verts[vb].sT1) * dxBC) * 4294967296.0f);
3886 }
3887
3888 voodoo->params.sign = (area < 0.0);
3889
3890 if (voodoo->ncc_dirty[0])
3891 voodoo_update_ncc(voodoo, 0);
3892 if (voodoo->ncc_dirty[1])
3893 voodoo_update_ncc(voodoo, 1);
3894 voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
3895
3896 queue_triangle(voodoo, &voodoo->params);
3897 }
3898
3899 enum
3900 {
3901 BLIT_COMMAND_SCREEN_TO_SCREEN = 0,
3902 BLIT_COMMAND_CPU_TO_SCREEN = 1,
3903 BLIT_COMMAND_RECT_FILL = 2,
3904 BLIT_COMMAND_SGRAM_FILL = 3
3905 };
3906
3907 enum
3908 {
3909 BLIT_SRC_1BPP = (0 << 3),
3910 BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3),
3911 BLIT_SRC_16BPP = (2 << 3),
3912 BLIT_SRC_24BPP = (3 << 3),
3913 BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3),
3914 BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3)
3915 };
3916
3917 enum
3918 {
3919 BLIT_SRC_RGB_ARGB = (0 << 6),
3920 BLIT_SRC_RGB_ABGR = (1 << 6),
3921 BLIT_SRC_RGB_RGBA = (2 << 6),
3922 BLIT_SRC_RGB_BGRA = (3 << 6)
3923 };
3924
3925 enum
3926 {
3927 BLIT_COMMAND_MASK = 7,
3928 BLIT_SRC_FORMAT = (7 << 3),
3929 BLIT_SRC_RGB_FORMAT = (3 << 6),
3930 BLIT_SRC_CHROMA = (1 << 10),
3931 BLIT_DST_CHROMA = (1 << 12),
3932 BLIT_CLIPPING_ENABLED = (1 << 16)
3933 };
3934
3935 enum
3936 {
3937 BLIT_ROP_DST_PASS = (1 << 0),
3938 BLIT_ROP_SRC_PASS = (1 << 1)
3939 };
3940
3941 #define MIX(src_dat, dst_dat, rop) \
3942 switch (rop) \
3943 { \
3944 case 0x0: dst_dat = 0; break; \
3945 case 0x1: dst_dat = ~(src_dat | dst_dat); break; \
3946 case 0x2: dst_dat = ~src_dat & dst_dat; break; \
3947 case 0x3: dst_dat = ~src_dat; break; \
3948 case 0x4: dst_dat = src_dat & ~dst_dat; break; \
3949 case 0x5: dst_dat = ~dst_dat; break; \
3950 case 0x6: dst_dat = src_dat ^ dst_dat; break; \
3951 case 0x7: dst_dat = ~(src_dat & dst_dat); break; \
3952 case 0x8: dst_dat = src_dat & dst_dat; break; \
3953 case 0x9: dst_dat = ~(src_dat ^ dst_dat); break; \
3954 case 0xa: dst_dat = dst_dat; break; \
3955 case 0xb: dst_dat = ~src_dat | dst_dat; break; \
3956 case 0xc: dst_dat = src_dat; break; \
3957 case 0xd: dst_dat = src_dat | ~dst_dat; break; \
3958 case 0xe: dst_dat = src_dat | dst_dat; break; \
3959 case 0xf: dst_dat = 0xffff; break; \
3960 }
3961
blit_start(voodoo_t * voodoo)3962 static void blit_start(voodoo_t *voodoo)
3963 {
3964 uint64_t dat64;
3965 int size_x = ABS(voodoo->bltSizeX), size_y = ABS(voodoo->bltSizeY);
3966 int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1;
3967 int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1;
3968 int dst_x;
3969 int src_y = voodoo->bltSrcY & 0x7ff, dst_y = voodoo->bltDstY & 0x7ff;
3970 int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32*2) : (voodoo->bltSrcXYStride & 0xff8);
3971 int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8);
3972 uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8);
3973 uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
3974 int x, y;
3975
3976 /* pclog("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n",
3977 voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/
3978
3979 wait_for_render_thread_idle(voodoo);
3980
3981 switch (voodoo->bltCommand & BLIT_COMMAND_MASK)
3982 {
3983 case BLIT_COMMAND_SCREEN_TO_SCREEN:
3984 for (y = 0; y <= size_y; y++)
3985 {
3986 uint16_t *src = (uint16_t *)&voodoo->fb_mem[src_base_addr + src_y*src_stride];
3987 uint16_t *dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride];
3988 int src_x = voodoo->bltSrcX, dst_x = voodoo->bltDstX;
3989
3990 for (x = 0; x <= size_x; x++)
3991 {
3992 uint16_t src_dat = src[src_x];
3993 uint16_t dst_dat = dst[dst_x];
3994 int rop = 0;
3995
3996 if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
3997 {
3998 if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight ||
3999 dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
4000 goto skip_pixel_blit;
4001 }
4002
4003 if (voodoo->bltCommand & BLIT_SRC_CHROMA)
4004 {
4005 int r = (src_dat >> 11);
4006 int g = (src_dat >> 5) & 0x3f;
4007 int b = src_dat & 0x1f;
4008
4009 if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR &&
4010 g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG &&
4011 b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
4012 rop |= BLIT_ROP_SRC_PASS;
4013 }
4014 if (voodoo->bltCommand & BLIT_DST_CHROMA)
4015 {
4016 int r = (dst_dat >> 11);
4017 int g = (dst_dat >> 5) & 0x3f;
4018 int b = dst_dat & 0x1f;
4019
4020 if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR &&
4021 g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG &&
4022 b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
4023 rop |= BLIT_ROP_DST_PASS;
4024 }
4025
4026 MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
4027
4028 dst[dst_x] = dst_dat;
4029 skip_pixel_blit:
4030 src_x += x_dir;
4031 dst_x += x_dir;
4032 }
4033
4034 src_y += y_dir;
4035 dst_y += y_dir;
4036 }
4037 break;
4038
4039 case BLIT_COMMAND_CPU_TO_SCREEN:
4040 voodoo->blt.dst_x = voodoo->bltDstX;
4041 voodoo->blt.dst_y = voodoo->bltDstY;
4042 voodoo->blt.cur_x = 0;
4043 voodoo->blt.size_x = size_x;
4044 voodoo->blt.size_y = size_y;
4045 voodoo->blt.x_dir = x_dir;
4046 voodoo->blt.y_dir = y_dir;
4047 voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8);
4048 break;
4049
4050 case BLIT_COMMAND_RECT_FILL:
4051 for (y = 0; y <= size_y; y++)
4052 {
4053 uint16_t *dst;
4054 int dst_x = voodoo->bltDstX;
4055
4056 if (SLI_ENABLED)
4057 {
4058 if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) ||
4059 ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
4060 goto skip_line_fill;
4061 dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride];
4062 }
4063 else
4064 dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride];
4065
4066 for (x = 0; x <= size_x; x++)
4067 {
4068 if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
4069 {
4070 if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight ||
4071 dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY)
4072 goto skip_pixel_fill;
4073 }
4074
4075 dst[dst_x] = voodoo->bltColorFg;
4076 skip_pixel_fill:
4077 dst_x += x_dir;
4078 }
4079 skip_line_fill:
4080 dst_y += y_dir;
4081 }
4082 break;
4083
4084 case BLIT_COMMAND_SGRAM_FILL:
4085 /*32x32 tiles - 2kb*/
4086 dst_y = voodoo->bltDstY & 0x3ff;
4087 size_x = voodoo->bltSizeX & 0x1ff; //512*8 = 4kb
4088 size_y = voodoo->bltSizeY & 0x3ff;
4089
4090 dat64 = voodoo->bltColorFg | ((uint64_t)voodoo->bltColorFg << 16) |
4091 ((uint64_t)voodoo->bltColorFg << 32) | ((uint64_t)voodoo->bltColorFg << 48);
4092
4093 for (y = 0; y <= size_y; y++)
4094 {
4095 uint64_t *dst;
4096
4097 /*This may be wrong*/
4098 if (!y)
4099 {
4100 dst_x = voodoo->bltDstX & 0x1ff;
4101 size_x = 511 - dst_x;
4102 }
4103 else if (y < size_y)
4104 {
4105 dst_x = 0;
4106 size_x = 511;
4107 }
4108 else
4109 {
4110 dst_x = 0;
4111 size_x = voodoo->bltSizeX & 0x1ff;
4112 }
4113
4114 dst = (uint64_t *)&voodoo->fb_mem[(dst_y*512*8 + dst_x*8) & voodoo->fb_mask];
4115
4116 for (x = 0; x <= size_x; x++)
4117 dst[x] = dat64;
4118
4119 dst_y++;
4120 }
4121 break;
4122
4123 default:
4124 fatal("bad blit command %08x\n", voodoo->bltCommand);
4125 }
4126 }
4127
blit_data(voodoo_t * voodoo,uint32_t data)4128 static void blit_data(voodoo_t *voodoo, uint32_t data)
4129 {
4130 int src_bits = 32;
4131 uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8);
4132 uint32_t addr;
4133 uint16_t *dst;
4134
4135 if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN)
4136 return;
4137
4138 if (SLI_ENABLED)
4139 {
4140 addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride;
4141 dst = (uint16_t *)&voodoo->fb_mem[addr];
4142 }
4143 else
4144 {
4145 addr = base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride;
4146 dst = (uint16_t *)&voodoo->fb_mem[addr];
4147 }
4148
4149 if (addr >= voodoo->front_offset && voodoo->row_width)
4150 {
4151 int y = (addr - voodoo->front_offset) / voodoo->row_width;
4152 if (y < voodoo->v_disp)
4153 voodoo->dirty_line[y] = 2;
4154 }
4155
4156 while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x)
4157 {
4158 int r = 0, g = 0, b = 0;
4159 uint16_t src_dat = 0, dst_dat;
4160 int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x);
4161 int rop = 0;
4162
4163 switch (voodoo->bltCommand & BLIT_SRC_FORMAT)
4164 {
4165 case BLIT_SRC_1BPP: case BLIT_SRC_1BPP_BYTE_PACKED:
4166 src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg;
4167 data >>= 1;
4168 src_bits--;
4169 break;
4170 case BLIT_SRC_16BPP:
4171 switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT)
4172 {
4173 case BLIT_SRC_RGB_ARGB: case BLIT_SRC_RGB_RGBA:
4174 src_dat = data & 0xffff;
4175 break;
4176 case BLIT_SRC_RGB_ABGR: case BLIT_SRC_RGB_BGRA:
4177 src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11);
4178 break;
4179 }
4180 data >>= 16;
4181 src_bits -= 16;
4182 break;
4183 case BLIT_SRC_24BPP: case BLIT_SRC_24BPP_DITHER_2X2: case BLIT_SRC_24BPP_DITHER_4X4:
4184 switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT)
4185 {
4186 case BLIT_SRC_RGB_ARGB:
4187 r = (data >> 16) & 0xff;
4188 g = (data >> 8) & 0xff;
4189 b = data & 0xff;
4190 break;
4191 case BLIT_SRC_RGB_ABGR:
4192 r = data & 0xff;
4193 g = (data >> 8) & 0xff;
4194 b = (data >> 16) & 0xff;
4195 break;
4196 case BLIT_SRC_RGB_RGBA:
4197 r = (data >> 24) & 0xff;
4198 g = (data >> 16) & 0xff;
4199 b = (data >> 8) & 0xff;
4200 break;
4201 case BLIT_SRC_RGB_BGRA:
4202 r = (data >> 8) & 0xff;
4203 g = (data >> 16) & 0xff;
4204 b = (data >> 24) & 0xff;
4205 break;
4206 }
4207 switch (voodoo->bltCommand & BLIT_SRC_FORMAT)
4208 {
4209 case BLIT_SRC_24BPP:
4210 src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
4211 break;
4212 case BLIT_SRC_24BPP_DITHER_2X2:
4213 r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1];
4214 g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1];
4215 b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1];
4216 src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
4217 break;
4218 case BLIT_SRC_24BPP_DITHER_4X4:
4219 r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3];
4220 g = dither_g[g][voodoo->blt.dst_y & 3][x & 3];
4221 b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3];
4222 src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8);
4223 break;
4224 }
4225 src_bits = 0;
4226 break;
4227 }
4228
4229 if (SLI_ENABLED)
4230 {
4231 if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) ||
4232 ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1)))
4233 goto skip_pixel;
4234 }
4235
4236 if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED)
4237 {
4238 if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight ||
4239 voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY)
4240 goto skip_pixel;
4241 }
4242
4243 dst_dat = dst[x];
4244
4245 if (voodoo->bltCommand & BLIT_SRC_CHROMA)
4246 {
4247 r = (src_dat >> 11);
4248 g = (src_dat >> 5) & 0x3f;
4249 b = src_dat & 0x1f;
4250
4251 if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR &&
4252 g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG &&
4253 b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB)
4254 rop |= BLIT_ROP_SRC_PASS;
4255 }
4256 if (voodoo->bltCommand & BLIT_DST_CHROMA)
4257 {
4258 r = (dst_dat >> 11);
4259 g = (dst_dat >> 5) & 0x3f;
4260 b = dst_dat & 0x1f;
4261
4262 if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR &&
4263 g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG &&
4264 b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB)
4265 rop |= BLIT_ROP_DST_PASS;
4266 }
4267
4268 MIX(src_dat, dst_dat, voodoo->bltRop[rop]);
4269
4270 dst[x] = dst_dat;
4271
4272 skip_pixel:
4273 voodoo->blt.cur_x++;
4274 }
4275
4276 if (voodoo->blt.cur_x > voodoo->blt.size_x)
4277 {
4278 voodoo->blt.size_y--;
4279 if (voodoo->blt.size_y >= 0)
4280 {
4281 voodoo->blt.cur_x = 0;
4282 voodoo->blt.dst_y += voodoo->blt.y_dir;
4283 }
4284 }
4285 }
4286
4287 enum
4288 {
4289 CHIP_FBI = 0x1,
4290 CHIP_TREX0 = 0x2,
4291 CHIP_TREX1 = 0x4,
4292 CHIP_TREX2 = 0x8
4293 };
4294
wait_for_swap_complete(voodoo_t * voodoo)4295 static void wait_for_swap_complete(voodoo_t *voodoo)
4296 {
4297 while (voodoo->swap_pending)
4298 {
4299 thread_wait_event(voodoo->wake_fifo_thread, -1);
4300 thread_reset_event(voodoo->wake_fifo_thread);
4301 if ((voodoo->swap_pending && voodoo->flush) || FIFO_ENTRIES >= 65536)
4302 {
4303 /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/
4304 memset(voodoo->dirty_line, 1, 1024);
4305 voodoo->front_offset = voodoo->params.front_offset;
4306 if (voodoo->swap_count > 0)
4307 voodoo->swap_count--;
4308 voodoo->swap_pending = 0;
4309 break;
4310 }
4311 }
4312 }
4313
voodoo_reg_writel(uint32_t addr,uint32_t val,void * p)4314 static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
4315 {
4316 voodoo_t *voodoo = (voodoo_t *)p;
4317 union
4318 {
4319 uint32_t i;
4320 float f;
4321 } tempif;
4322 int ad21 = addr & (1 << 21);
4323 int chip = (addr >> 10) & 0xf;
4324 if (!chip)
4325 chip = 0xf;
4326
4327 tempif.i = val;
4328 //pclog("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip);
4329 addr &= 0x3fc;
4330
4331 if ((voodoo->fbiInit3 & FBIINIT3_REMAP) && addr < 0x100 && ad21)
4332 addr |= 0x400;
4333 switch (addr)
4334 {
4335 case SST_swapbufferCMD:
4336 // pclog(" start swap buffer command\n");
4337
4338 if (TRIPLE_BUFFER)
4339 {
4340 voodoo->disp_buffer = (voodoo->disp_buffer + 1) % 3;
4341 voodoo->draw_buffer = (voodoo->draw_buffer + 1) % 3;
4342 }
4343 else
4344 {
4345 voodoo->disp_buffer = !voodoo->disp_buffer;
4346 voodoo->draw_buffer = !voodoo->draw_buffer;
4347 }
4348 voodoo_recalc(voodoo);
4349
4350 voodoo->params.swapbufferCMD = val;
4351
4352 pclog("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0);
4353 // voodoo->front_offset = params->front_offset;
4354 wait_for_render_thread_idle(voodoo);
4355 if (!(val & 1))
4356 {
4357 memset(voodoo->dirty_line, 1, 1024);
4358 voodoo->front_offset = voodoo->params.front_offset;
4359 if (voodoo->swap_count > 0)
4360 voodoo->swap_count--;
4361 }
4362 else if (TRIPLE_BUFFER)
4363 {
4364 if (voodoo->swap_pending)
4365 wait_for_swap_complete(voodoo);
4366
4367 voodoo->swap_interval = (val >> 1) & 0xff;
4368 voodoo->swap_offset = voodoo->params.front_offset;
4369 voodoo->swap_pending = 1;
4370 }
4371 else
4372 {
4373 voodoo->swap_interval = (val >> 1) & 0xff;
4374 voodoo->swap_offset = voodoo->params.front_offset;
4375 voodoo->swap_pending = 1;
4376
4377 wait_for_swap_complete(voodoo);
4378 }
4379 voodoo->cmd_read++;
4380 break;
4381
4382 case SST_vertexAx: case SST_remap_vertexAx:
4383 voodoo->params.vertexAx = val & 0xffff;
4384 break;
4385 case SST_vertexAy: case SST_remap_vertexAy:
4386 voodoo->params.vertexAy = val & 0xffff;
4387 break;
4388 case SST_vertexBx: case SST_remap_vertexBx:
4389 voodoo->params.vertexBx = val & 0xffff;
4390 break;
4391 case SST_vertexBy: case SST_remap_vertexBy:
4392 voodoo->params.vertexBy = val & 0xffff;
4393 break;
4394 case SST_vertexCx: case SST_remap_vertexCx:
4395 voodoo->params.vertexCx = val & 0xffff;
4396 break;
4397 case SST_vertexCy: case SST_remap_vertexCy:
4398 voodoo->params.vertexCy = val & 0xffff;
4399 break;
4400
4401 case SST_startR: case SST_remap_startR:
4402 voodoo->params.startR = val & 0xffffff;
4403 break;
4404 case SST_startG: case SST_remap_startG:
4405 voodoo->params.startG = val & 0xffffff;
4406 break;
4407 case SST_startB: case SST_remap_startB:
4408 voodoo->params.startB = val & 0xffffff;
4409 break;
4410 case SST_startZ: case SST_remap_startZ:
4411 voodoo->params.startZ = val;
4412 break;
4413 case SST_startA: case SST_remap_startA:
4414 voodoo->params.startA = val & 0xffffff;
4415 break;
4416 case SST_startS: case SST_remap_startS:
4417 if (chip & CHIP_TREX0)
4418 voodoo->params.tmu[0].startS = ((int64_t)(int32_t)val) << 14;
4419 if (chip & CHIP_TREX1)
4420 voodoo->params.tmu[1].startS = ((int64_t)(int32_t)val) << 14;
4421 break;
4422 case SST_startT: case SST_remap_startT:
4423 if (chip & CHIP_TREX0)
4424 voodoo->params.tmu[0].startT = ((int64_t)(int32_t)val) << 14;
4425 if (chip & CHIP_TREX1)
4426 voodoo->params.tmu[1].startT = ((int64_t)(int32_t)val) << 14;
4427 break;
4428 case SST_startW: case SST_remap_startW:
4429 if (chip & CHIP_FBI)
4430 voodoo->params.startW = (int64_t)(int32_t)val << 2;
4431 if (chip & CHIP_TREX0)
4432 voodoo->params.tmu[0].startW = (int64_t)(int32_t)val << 2;
4433 if (chip & CHIP_TREX1)
4434 voodoo->params.tmu[1].startW = (int64_t)(int32_t)val << 2;
4435 break;
4436
4437 case SST_dRdX: case SST_remap_dRdX:
4438 voodoo->params.dRdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
4439 break;
4440 case SST_dGdX: case SST_remap_dGdX:
4441 voodoo->params.dGdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
4442 break;
4443 case SST_dBdX: case SST_remap_dBdX:
4444 voodoo->params.dBdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
4445 break;
4446 case SST_dZdX: case SST_remap_dZdX:
4447 voodoo->params.dZdX = val;
4448 break;
4449 case SST_dAdX: case SST_remap_dAdX:
4450 voodoo->params.dAdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
4451 break;
4452 case SST_dSdX: case SST_remap_dSdX:
4453 if (chip & CHIP_TREX0)
4454 voodoo->params.tmu[0].dSdX = ((int64_t)(int32_t)val) << 14;
4455 if (chip & CHIP_TREX1)
4456 voodoo->params.tmu[1].dSdX = ((int64_t)(int32_t)val) << 14;
4457 break;
4458 case SST_dTdX: case SST_remap_dTdX:
4459 if (chip & CHIP_TREX0)
4460 voodoo->params.tmu[0].dTdX = ((int64_t)(int32_t)val) << 14;
4461 if (chip & CHIP_TREX1)
4462 voodoo->params.tmu[1].dTdX = ((int64_t)(int32_t)val) << 14;
4463 break;
4464 case SST_dWdX: case SST_remap_dWdX:
4465 if (chip & CHIP_TREX0)
4466 voodoo->params.tmu[0].dWdX = (int64_t)(int32_t)val << 2;
4467 if (chip & CHIP_TREX1)
4468 voodoo->params.tmu[1].dWdX = (int64_t)(int32_t)val << 2;
4469 if (chip & CHIP_FBI)
4470 voodoo->params.dWdX = (int64_t)(int32_t)val << 2;
4471 break;
4472
4473 case SST_dRdY: case SST_remap_dRdY:
4474 voodoo->params.dRdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
4475 break;
4476 case SST_dGdY: case SST_remap_dGdY:
4477 voodoo->params.dGdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
4478 break;
4479 case SST_dBdY: case SST_remap_dBdY:
4480 voodoo->params.dBdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
4481 break;
4482 case SST_dZdY: case SST_remap_dZdY:
4483 voodoo->params.dZdY = val;
4484 break;
4485 case SST_dAdY: case SST_remap_dAdY:
4486 voodoo->params.dAdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0);
4487 break;
4488 case SST_dSdY: case SST_remap_dSdY:
4489 if (chip & CHIP_TREX0)
4490 voodoo->params.tmu[0].dSdY = ((int64_t)(int32_t)val) << 14;
4491 if (chip & CHIP_TREX1)
4492 voodoo->params.tmu[1].dSdY = ((int64_t)(int32_t)val) << 14;
4493 break;
4494 case SST_dTdY: case SST_remap_dTdY:
4495 if (chip & CHIP_TREX0)
4496 voodoo->params.tmu[0].dTdY = ((int64_t)(int32_t)val) << 14;
4497 if (chip & CHIP_TREX1)
4498 voodoo->params.tmu[1].dTdY = ((int64_t)(int32_t)val) << 14;
4499 break;
4500 case SST_dWdY: case SST_remap_dWdY:
4501 if (chip & CHIP_TREX0)
4502 voodoo->params.tmu[0].dWdY = (int64_t)(int32_t)val << 2;
4503 if (chip & CHIP_TREX1)
4504 voodoo->params.tmu[1].dWdY = (int64_t)(int32_t)val << 2;
4505 if (chip & CHIP_FBI)
4506 voodoo->params.dWdY = (int64_t)(int32_t)val << 2;
4507 break;
4508
4509 case SST_triangleCMD: case SST_remap_triangleCMD:
4510 voodoo->params.sign = val & (1 << 31);
4511
4512 if (voodoo->ncc_dirty[0])
4513 voodoo_update_ncc(voodoo, 0);
4514 if (voodoo->ncc_dirty[1])
4515 voodoo_update_ncc(voodoo, 1);
4516 voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
4517
4518 queue_triangle(voodoo, &voodoo->params);
4519
4520 voodoo->cmd_read++;
4521 break;
4522
4523 case SST_fvertexAx: case SST_remap_fvertexAx:
4524 voodoo->fvertexAx.i = val;
4525 voodoo->params.vertexAx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAx.f * 16.0f) & 0xffff;
4526 break;
4527 case SST_fvertexAy: case SST_remap_fvertexAy:
4528 voodoo->fvertexAy.i = val;
4529 voodoo->params.vertexAy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAy.f * 16.0f) & 0xffff;
4530 break;
4531 case SST_fvertexBx: case SST_remap_fvertexBx:
4532 voodoo->fvertexBx.i = val;
4533 voodoo->params.vertexBx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBx.f * 16.0f) & 0xffff;
4534 break;
4535 case SST_fvertexBy: case SST_remap_fvertexBy:
4536 voodoo->fvertexBy.i = val;
4537 voodoo->params.vertexBy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBy.f * 16.0f) & 0xffff;
4538 break;
4539 case SST_fvertexCx: case SST_remap_fvertexCx:
4540 voodoo->fvertexCx.i = val;
4541 voodoo->params.vertexCx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCx.f * 16.0f) & 0xffff;
4542 break;
4543 case SST_fvertexCy: case SST_remap_fvertexCy:
4544 voodoo->fvertexCy.i = val;
4545 voodoo->params.vertexCy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCy.f * 16.0f) & 0xffff;
4546 break;
4547
4548 case SST_fstartR: case SST_remap_fstartR:
4549 tempif.i = val;
4550 voodoo->params.startR = (int32_t)(tempif.f * 4096.0f);
4551 break;
4552 case SST_fstartG: case SST_remap_fstartG:
4553 tempif.i = val;
4554 voodoo->params.startG = (int32_t)(tempif.f * 4096.0f);
4555 break;
4556 case SST_fstartB: case SST_remap_fstartB:
4557 tempif.i = val;
4558 voodoo->params.startB = (int32_t)(tempif.f * 4096.0f);
4559 break;
4560 case SST_fstartZ: case SST_remap_fstartZ:
4561 tempif.i = val;
4562 voodoo->params.startZ = (int32_t)(tempif.f * 4096.0f);
4563 break;
4564 case SST_fstartA: case SST_remap_fstartA:
4565 tempif.i = val;
4566 voodoo->params.startA = (int32_t)(tempif.f * 4096.0f);
4567 break;
4568 case SST_fstartS: case SST_remap_fstartS:
4569 tempif.i = val;
4570 if (chip & CHIP_TREX0)
4571 voodoo->params.tmu[0].startS = (int64_t)(tempif.f * 4294967296.0f);
4572 if (chip & CHIP_TREX1)
4573 voodoo->params.tmu[1].startS = (int64_t)(tempif.f * 4294967296.0f);
4574 break;
4575 case SST_fstartT: case SST_remap_fstartT:
4576 tempif.i = val;
4577 if (chip & CHIP_TREX0)
4578 voodoo->params.tmu[0].startT = (int64_t)(tempif.f * 4294967296.0f);
4579 if (chip & CHIP_TREX1)
4580 voodoo->params.tmu[1].startT = (int64_t)(tempif.f * 4294967296.0f);
4581 break;
4582 case SST_fstartW: case SST_remap_fstartW:
4583 tempif.i = val;
4584 if (chip & CHIP_TREX0)
4585 voodoo->params.tmu[0].startW = (int64_t)(tempif.f * 4294967296.0f);
4586 if (chip & CHIP_TREX1)
4587 voodoo->params.tmu[1].startW = (int64_t)(tempif.f * 4294967296.0f);
4588 if (chip & CHIP_FBI)
4589 voodoo->params.startW = (int64_t)(tempif.f * 4294967296.0f);
4590 break;
4591
4592 case SST_fdRdX: case SST_remap_fdRdX:
4593 tempif.i = val;
4594 voodoo->params.dRdX = (int32_t)(tempif.f * 4096.0f);
4595 break;
4596 case SST_fdGdX: case SST_remap_fdGdX:
4597 tempif.i = val;
4598 voodoo->params.dGdX = (int32_t)(tempif.f * 4096.0f);
4599 break;
4600 case SST_fdBdX: case SST_remap_fdBdX:
4601 tempif.i = val;
4602 voodoo->params.dBdX = (int32_t)(tempif.f * 4096.0f);
4603 break;
4604 case SST_fdZdX: case SST_remap_fdZdX:
4605 tempif.i = val;
4606 voodoo->params.dZdX = (int32_t)(tempif.f * 4096.0f);
4607 break;
4608 case SST_fdAdX: case SST_remap_fdAdX:
4609 tempif.i = val;
4610 voodoo->params.dAdX = (int32_t)(tempif.f * 4096.0f);
4611 break;
4612 case SST_fdSdX: case SST_remap_fdSdX:
4613 tempif.i = val;
4614 if (chip & CHIP_TREX0)
4615 voodoo->params.tmu[0].dSdX = (int64_t)(tempif.f * 4294967296.0f);
4616 if (chip & CHIP_TREX1)
4617 voodoo->params.tmu[1].dSdX = (int64_t)(tempif.f * 4294967296.0f);
4618 break;
4619 case SST_fdTdX: case SST_remap_fdTdX:
4620 tempif.i = val;
4621 if (chip & CHIP_TREX0)
4622 voodoo->params.tmu[0].dTdX = (int64_t)(tempif.f * 4294967296.0f);
4623 if (chip & CHIP_TREX1)
4624 voodoo->params.tmu[1].dTdX = (int64_t)(tempif.f * 4294967296.0f);
4625 break;
4626 case SST_fdWdX: case SST_remap_fdWdX:
4627 tempif.i = val;
4628 if (chip & CHIP_TREX0)
4629 voodoo->params.tmu[0].dWdX = (int64_t)(tempif.f * 4294967296.0f);
4630 if (chip & CHIP_TREX1)
4631 voodoo->params.tmu[1].dWdX = (int64_t)(tempif.f * 4294967296.0f);
4632 if (chip & CHIP_FBI)
4633 voodoo->params.dWdX = (int64_t)(tempif.f * 4294967296.0f);
4634 break;
4635
4636 case SST_fdRdY: case SST_remap_fdRdY:
4637 tempif.i = val;
4638 voodoo->params.dRdY = (int32_t)(tempif.f * 4096.0f);
4639 break;
4640 case SST_fdGdY: case SST_remap_fdGdY:
4641 tempif.i = val;
4642 voodoo->params.dGdY = (int32_t)(tempif.f * 4096.0f);
4643 break;
4644 case SST_fdBdY: case SST_remap_fdBdY:
4645 tempif.i = val;
4646 voodoo->params.dBdY = (int32_t)(tempif.f * 4096.0f);
4647 break;
4648 case SST_fdZdY: case SST_remap_fdZdY:
4649 tempif.i = val;
4650 voodoo->params.dZdY = (int32_t)(tempif.f * 4096.0f);
4651 break;
4652 case SST_fdAdY: case SST_remap_fdAdY:
4653 tempif.i = val;
4654 voodoo->params.dAdY = (int32_t)(tempif.f * 4096.0f);
4655 break;
4656 case SST_fdSdY: case SST_remap_fdSdY:
4657 tempif.i = val;
4658 if (chip & CHIP_TREX0)
4659 voodoo->params.tmu[0].dSdY = (int64_t)(tempif.f * 4294967296.0f);
4660 if (chip & CHIP_TREX1)
4661 voodoo->params.tmu[1].dSdY = (int64_t)(tempif.f * 4294967296.0f);
4662 break;
4663 case SST_fdTdY: case SST_remap_fdTdY:
4664 tempif.i = val;
4665 if (chip & CHIP_TREX0)
4666 voodoo->params.tmu[0].dTdY = (int64_t)(tempif.f * 4294967296.0f);
4667 if (chip & CHIP_TREX1)
4668 voodoo->params.tmu[1].dTdY = (int64_t)(tempif.f * 4294967296.0f);
4669 break;
4670 case SST_fdWdY: case SST_remap_fdWdY:
4671 tempif.i = val;
4672 if (chip & CHIP_TREX0)
4673 voodoo->params.tmu[0].dWdY = (int64_t)(tempif.f * 4294967296.0f);
4674 if (chip & CHIP_TREX1)
4675 voodoo->params.tmu[1].dWdY = (int64_t)(tempif.f * 4294967296.0f);
4676 if (chip & CHIP_FBI)
4677 voodoo->params.dWdY = (int64_t)(tempif.f * 4294967296.0f);
4678 break;
4679
4680 case SST_ftriangleCMD:
4681 voodoo->params.sign = val & (1 << 31);
4682
4683 if (voodoo->ncc_dirty[0])
4684 voodoo_update_ncc(voodoo, 0);
4685 if (voodoo->ncc_dirty[1])
4686 voodoo_update_ncc(voodoo, 1);
4687 voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0;
4688
4689 queue_triangle(voodoo, &voodoo->params);
4690
4691 voodoo->cmd_read++;
4692 break;
4693
4694 case SST_fbzColorPath:
4695 voodoo->params.fbzColorPath = val;
4696 voodoo->rgb_sel = val & 3;
4697 break;
4698
4699 case SST_fogMode:
4700 voodoo->params.fogMode = val;
4701 break;
4702 case SST_alphaMode:
4703 voodoo->params.alphaMode = val;
4704 break;
4705 case SST_fbzMode:
4706 voodoo->params.fbzMode = val;
4707 voodoo_recalc(voodoo);
4708 break;
4709 case SST_lfbMode:
4710 voodoo->lfbMode = val;
4711 voodoo_recalc(voodoo);
4712 break;
4713
4714 case SST_clipLeftRight:
4715 if (voodoo->type >= VOODOO_2)
4716 {
4717 voodoo->params.clipRight = val & 0xfff;
4718 voodoo->params.clipLeft = (val >> 16) & 0xfff;
4719 }
4720 else
4721 {
4722 voodoo->params.clipRight = val & 0x3ff;
4723 voodoo->params.clipLeft = (val >> 16) & 0x3ff;
4724 }
4725 break;
4726 case SST_clipLowYHighY:
4727 if (voodoo->type >= VOODOO_2)
4728 {
4729 voodoo->params.clipHighY = val & 0xfff;
4730 voodoo->params.clipLowY = (val >> 16) & 0xfff;
4731 }
4732 else
4733 {
4734 voodoo->params.clipHighY = val & 0x3ff;
4735 voodoo->params.clipLowY = (val >> 16) & 0x3ff;
4736 }
4737 break;
4738
4739 case SST_nopCMD:
4740 voodoo->cmd_read++;
4741 voodoo->fbiPixelsIn = 0;
4742 voodoo->fbiChromaFail = 0;
4743 voodoo->fbiZFuncFail = 0;
4744 voodoo->fbiAFuncFail = 0;
4745 voodoo->fbiPixelsOut = 0;
4746 break;
4747 case SST_fastfillCMD:
4748 wait_for_render_thread_idle(voodoo);
4749 voodoo_fastfill(voodoo, &voodoo->params);
4750 voodoo->cmd_read++;
4751 break;
4752
4753 case SST_fogColor:
4754 voodoo->params.fogColor.r = (val >> 16) & 0xff;
4755 voodoo->params.fogColor.g = (val >> 8) & 0xff;
4756 voodoo->params.fogColor.b = val & 0xff;
4757 break;
4758
4759 case SST_zaColor:
4760 voodoo->params.zaColor = val;
4761 break;
4762 case SST_chromaKey:
4763 voodoo->params.chromaKey_r = (val >> 16) & 0xff;
4764 voodoo->params.chromaKey_g = (val >> 8) & 0xff;
4765 voodoo->params.chromaKey_b = val & 0xff;
4766 voodoo->params.chromaKey = val & 0xffffff;
4767 break;
4768 case SST_stipple:
4769 voodoo->params.stipple = val;
4770 break;
4771 case SST_color0:
4772 voodoo->params.color0 = val;
4773 break;
4774 case SST_color1:
4775 voodoo->params.color1 = val;
4776 break;
4777
4778 case SST_fogTable00: case SST_fogTable01: case SST_fogTable02: case SST_fogTable03:
4779 case SST_fogTable04: case SST_fogTable05: case SST_fogTable06: case SST_fogTable07:
4780 case SST_fogTable08: case SST_fogTable09: case SST_fogTable0a: case SST_fogTable0b:
4781 case SST_fogTable0c: case SST_fogTable0d: case SST_fogTable0e: case SST_fogTable0f:
4782 case SST_fogTable10: case SST_fogTable11: case SST_fogTable12: case SST_fogTable13:
4783 case SST_fogTable14: case SST_fogTable15: case SST_fogTable16: case SST_fogTable17:
4784 case SST_fogTable18: case SST_fogTable19: case SST_fogTable1a: case SST_fogTable1b:
4785 case SST_fogTable1c: case SST_fogTable1d: case SST_fogTable1e: case SST_fogTable1f:
4786 addr = (addr - SST_fogTable00) >> 1;
4787 voodoo->params.fogTable[addr].dfog = val & 0xff;
4788 voodoo->params.fogTable[addr].fog = (val >> 8) & 0xff;
4789 voodoo->params.fogTable[addr+1].dfog = (val >> 16) & 0xff;
4790 voodoo->params.fogTable[addr+1].fog = (val >> 24) & 0xff;
4791 break;
4792
4793 case SST_clutData:
4794 voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff;
4795 voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff;
4796 voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff;
4797 if (val & 0x20000000)
4798 {
4799 voodoo->clutData[(val >> 24) & 0x3f].b = 255;
4800 voodoo->clutData[(val >> 24) & 0x3f].g = 255;
4801 voodoo->clutData[(val >> 24) & 0x3f].r = 255;
4802 }
4803 voodoo->clutData_dirty = 1;
4804 break;
4805
4806 case SST_sSetupMode:
4807 voodoo->sSetupMode = val;
4808 break;
4809 case SST_sVx:
4810 tempif.i = val;
4811 voodoo->verts[3].sVx = tempif.f;
4812 // pclog("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f);
4813 break;
4814 case SST_sVy:
4815 tempif.i = val;
4816 voodoo->verts[3].sVy = tempif.f;
4817 // pclog("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f);
4818 break;
4819 case SST_sARGB:
4820 voodoo->verts[3].sBlue = (float)(val & 0xff);
4821 voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff);
4822 voodoo->verts[3].sRed = (float)((val >> 16) & 0xff);
4823 voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff);
4824 break;
4825 case SST_sRed:
4826 tempif.i = val;
4827 voodoo->verts[3].sRed = tempif.f;
4828 break;
4829 case SST_sGreen:
4830 tempif.i = val;
4831 voodoo->verts[3].sGreen = tempif.f;
4832 break;
4833 case SST_sBlue:
4834 tempif.i = val;
4835 voodoo->verts[3].sBlue = tempif.f;
4836 break;
4837 case SST_sAlpha:
4838 tempif.i = val;
4839 voodoo->verts[3].sAlpha = tempif.f;
4840 break;
4841 case SST_sVz:
4842 tempif.i = val;
4843 voodoo->verts[3].sVz = tempif.f;
4844 break;
4845 case SST_sWb:
4846 tempif.i = val;
4847 voodoo->verts[3].sWb = tempif.f;
4848 break;
4849 case SST_sW0:
4850 tempif.i = val;
4851 voodoo->verts[3].sW0 = tempif.f;
4852 break;
4853 case SST_sS0:
4854 tempif.i = val;
4855 voodoo->verts[3].sS0 = tempif.f;
4856 break;
4857 case SST_sT0:
4858 tempif.i = val;
4859 voodoo->verts[3].sT0 = tempif.f;
4860 break;
4861 case SST_sW1:
4862 tempif.i = val;
4863 voodoo->verts[3].sW1 = tempif.f;
4864 break;
4865 case SST_sS1:
4866 tempif.i = val;
4867 voodoo->verts[3].sS1 = tempif.f;
4868 break;
4869 case SST_sT1:
4870 tempif.i = val;
4871 voodoo->verts[3].sT1 = tempif.f;
4872 break;
4873
4874 case SST_sBeginTriCMD:
4875 // pclog("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx);
4876 voodoo->verts[0] = voodoo->verts[3];
4877 voodoo->vertex_num = 1;
4878 voodoo->num_verticies = 1;
4879 break;
4880 case SST_sDrawTriCMD:
4881 // pclog("sDrawTriCMD %i %i %i\n", voodoo->num_verticies, voodoo->vertex_num, voodoo->sSetupMode & SETUPMODE_STRIP_MODE);
4882 if (voodoo->vertex_num == 3)
4883 voodoo->vertex_num = (voodoo->sSetupMode & SETUPMODE_STRIP_MODE) ? 1 : 0;
4884 voodoo->verts[voodoo->vertex_num] = voodoo->verts[3];
4885
4886 voodoo->num_verticies++;
4887 voodoo->vertex_num++;
4888 if (voodoo->num_verticies == 3)
4889 {
4890 // pclog("triangle_setup\n");
4891 triangle_setup(voodoo);
4892
4893 voodoo->num_verticies = 2;
4894 }
4895 if (voodoo->vertex_num == 4)
4896 fatal("sDrawTriCMD overflow\n");
4897 break;
4898
4899 case SST_bltSrcBaseAddr:
4900 voodoo->bltSrcBaseAddr = val & 0x3fffff;
4901 break;
4902 case SST_bltDstBaseAddr:
4903 // pclog("Write bltDstBaseAddr %08x\n", val);
4904 voodoo->bltDstBaseAddr = val & 0x3fffff;
4905 break;
4906 case SST_bltXYStrides:
4907 voodoo->bltSrcXYStride = val & 0xfff;
4908 voodoo->bltDstXYStride = (val >> 16) & 0xfff;
4909 // pclog("Write bltXYStrides %08x\n", val);
4910 break;
4911 case SST_bltSrcChromaRange:
4912 voodoo->bltSrcChromaRange = val;
4913 voodoo->bltSrcChromaMinB = val & 0x1f;
4914 voodoo->bltSrcChromaMinG = (val >> 5) & 0x3f;
4915 voodoo->bltSrcChromaMinR = (val >> 11) & 0x1f;
4916 voodoo->bltSrcChromaMaxB = (val >> 16) & 0x1f;
4917 voodoo->bltSrcChromaMaxG = (val >> 21) & 0x3f;
4918 voodoo->bltSrcChromaMaxR = (val >> 27) & 0x1f;
4919 break;
4920 case SST_bltDstChromaRange:
4921 voodoo->bltDstChromaRange = val;
4922 voodoo->bltDstChromaMinB = val & 0x1f;
4923 voodoo->bltDstChromaMinG = (val >> 5) & 0x3f;
4924 voodoo->bltDstChromaMinR = (val >> 11) & 0x1f;
4925 voodoo->bltDstChromaMaxB = (val >> 16) & 0x1f;
4926 voodoo->bltDstChromaMaxG = (val >> 21) & 0x3f;
4927 voodoo->bltDstChromaMaxR = (val >> 27) & 0x1f;
4928 break;
4929 case SST_bltClipX:
4930 voodoo->bltClipRight = val & 0xfff;
4931 voodoo->bltClipLeft = (val >> 16) & 0xfff;
4932 break;
4933 case SST_bltClipY:
4934 voodoo->bltClipHighY = val & 0xfff;
4935 voodoo->bltClipLowY = (val >> 16) & 0xfff;
4936 break;
4937
4938 case SST_bltSrcXY:
4939 voodoo->bltSrcX = val & 0x7ff;
4940 voodoo->bltSrcY = (val >> 16) & 0x7ff;
4941 break;
4942 case SST_bltDstXY:
4943 // pclog("Write bltDstXY %08x\n", val);
4944 voodoo->bltDstX = val & 0x7ff;
4945 voodoo->bltDstY = (val >> 16) & 0x7ff;
4946 if (val & (1 << 31))
4947 blit_start(voodoo);
4948 break;
4949 case SST_bltSize:
4950 // pclog("Write bltSize %08x\n", val);
4951 voodoo->bltSizeX = val & 0xfff;
4952 if (voodoo->bltSizeX & 0x800)
4953 voodoo->bltSizeX |= 0xfffff000;
4954 voodoo->bltSizeY = (val >> 16) & 0xfff;
4955 if (voodoo->bltSizeY & 0x800)
4956 voodoo->bltSizeY |= 0xfffff000;
4957 if (val & (1 << 31))
4958 blit_start(voodoo);
4959 break;
4960 case SST_bltRop:
4961 voodoo->bltRop[0] = val & 0xf;
4962 voodoo->bltRop[1] = (val >> 4) & 0xf;
4963 voodoo->bltRop[2] = (val >> 8) & 0xf;
4964 voodoo->bltRop[3] = (val >> 12) & 0xf;
4965 break;
4966 case SST_bltColor:
4967 // pclog("Write bltColor %08x\n", val);
4968 voodoo->bltColorFg = val & 0xffff;
4969 voodoo->bltColorBg = (val >> 16) & 0xffff;
4970 break;
4971
4972 case SST_bltCommand:
4973 voodoo->bltCommand = val;
4974 // pclog("Write bltCommand %08x\n", val);
4975 if (val & (1 << 31))
4976 blit_start(voodoo);
4977 break;
4978 case SST_bltData:
4979 blit_data(voodoo, val);
4980 break;
4981
4982 case SST_textureMode:
4983 if (chip & CHIP_TREX0)
4984 {
4985 voodoo->params.textureMode[0] = val;
4986 voodoo->params.tformat[0] = (val >> 8) & 0xf;
4987 }
4988 if (chip & CHIP_TREX1)
4989 {
4990 voodoo->params.textureMode[1] = val;
4991 voodoo->params.tformat[1] = (val >> 8) & 0xf;
4992 }
4993 break;
4994 case SST_tLOD:
4995 if (chip & CHIP_TREX0)
4996 {
4997 voodoo->params.tLOD[0] = val;
4998 voodoo_recalc_tex(voodoo, 0);
4999 }
5000 if (chip & CHIP_TREX1)
5001 {
5002 voodoo->params.tLOD[1] = val;
5003 voodoo_recalc_tex(voodoo, 1);
5004 }
5005 break;
5006 case SST_tDetail:
5007 if (chip & CHIP_TREX0)
5008 {
5009 voodoo->params.detail_max[0] = val & 0xff;
5010 voodoo->params.detail_bias[0] = (val >> 8) & 0x3f;
5011 voodoo->params.detail_scale[0] = (val >> 14) & 7;
5012 }
5013 if (chip & CHIP_TREX1)
5014 {
5015 voodoo->params.detail_max[1] = val & 0xff;
5016 voodoo->params.detail_bias[1] = (val >> 8) & 0x3f;
5017 voodoo->params.detail_scale[1] = (val >> 14) & 7;
5018 }
5019 break;
5020 case SST_texBaseAddr:
5021 if (chip & CHIP_TREX0)
5022 {
5023 voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3;
5024 voodoo_recalc_tex(voodoo, 0);
5025 }
5026 if (chip & CHIP_TREX1)
5027 {
5028 voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3;
5029 voodoo_recalc_tex(voodoo, 1);
5030 }
5031 break;
5032 case SST_texBaseAddr1:
5033 if (chip & CHIP_TREX0)
5034 {
5035 voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3;
5036 voodoo_recalc_tex(voodoo, 0);
5037 }
5038 if (chip & CHIP_TREX1)
5039 {
5040 voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3;
5041 voodoo_recalc_tex(voodoo, 1);
5042 }
5043 break;
5044 case SST_texBaseAddr2:
5045 if (chip & CHIP_TREX0)
5046 {
5047 voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3;
5048 voodoo_recalc_tex(voodoo, 0);
5049 }
5050 if (chip & CHIP_TREX1)
5051 {
5052 voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3;
5053 voodoo_recalc_tex(voodoo, 1);
5054 }
5055 break;
5056 case SST_texBaseAddr38:
5057 if (chip & CHIP_TREX0)
5058 {
5059 voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3;
5060 voodoo_recalc_tex(voodoo, 0);
5061 }
5062 if (chip & CHIP_TREX1)
5063 {
5064 voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3;
5065 voodoo_recalc_tex(voodoo, 1);
5066 }
5067 break;
5068
5069 case SST_trexInit1:
5070 if (chip & CHIP_TREX0)
5071 voodoo->trexInit1[0] = val;
5072 if (chip & CHIP_TREX1)
5073 voodoo->trexInit1[1] = val;
5074 break;
5075
5076 case SST_nccTable0_Y0:
5077 if (chip & CHIP_TREX0)
5078 {
5079 voodoo->nccTable[0][0].y[0] = val;
5080 voodoo->ncc_dirty[0] = 1;
5081 }
5082 if (chip & CHIP_TREX1)
5083 {
5084 voodoo->nccTable[1][0].y[0] = val;
5085 voodoo->ncc_dirty[1] = 1;
5086 }
5087 break;
5088 case SST_nccTable0_Y1:
5089 if (chip & CHIP_TREX0)
5090 {
5091 voodoo->nccTable[0][0].y[1] = val;
5092 voodoo->ncc_dirty[0] = 1;
5093 }
5094 if (chip & CHIP_TREX1)
5095 {
5096 voodoo->nccTable[1][0].y[1] = val;
5097 voodoo->ncc_dirty[1] = 1;
5098 }
5099 break;
5100 case SST_nccTable0_Y2:
5101 if (chip & CHIP_TREX0)
5102 {
5103 voodoo->nccTable[0][0].y[2] = val;
5104 voodoo->ncc_dirty[0] = 1;
5105 }
5106 if (chip & CHIP_TREX1)
5107 {
5108 voodoo->nccTable[1][0].y[2] = val;
5109 voodoo->ncc_dirty[1] = 1;
5110 }
5111 break;
5112 case SST_nccTable0_Y3:
5113 if (chip & CHIP_TREX0)
5114 {
5115 voodoo->nccTable[0][0].y[3] = val;
5116 voodoo->ncc_dirty[0] = 1;
5117 }
5118 if (chip & CHIP_TREX1)
5119 {
5120 voodoo->nccTable[1][0].y[3] = val;
5121 voodoo->ncc_dirty[1] = 1;
5122 }
5123 break;
5124
5125 case SST_nccTable0_I0:
5126 if (!(val & (1 << 31)))
5127 {
5128 if (chip & CHIP_TREX0)
5129 {
5130 voodoo->nccTable[0][0].i[0] = val;
5131 voodoo->ncc_dirty[0] = 1;
5132 }
5133 if (chip & CHIP_TREX1)
5134 {
5135 voodoo->nccTable[1][0].i[0] = val;
5136 voodoo->ncc_dirty[1] = 1;
5137 }
5138 break;
5139 }
5140 case SST_nccTable0_I2:
5141 if (!(val & (1 << 31)))
5142 {
5143 if (chip & CHIP_TREX0)
5144 {
5145 voodoo->nccTable[0][0].i[2] = val;
5146 voodoo->ncc_dirty[0] = 1;
5147 }
5148 if (chip & CHIP_TREX1)
5149 {
5150 voodoo->nccTable[1][0].i[2] = val;
5151 voodoo->ncc_dirty[1] = 1;
5152 }
5153 break;
5154 }
5155 case SST_nccTable0_Q0:
5156 if (!(val & (1 << 31)))
5157 {
5158 if (chip & CHIP_TREX0)
5159 {
5160 voodoo->nccTable[0][0].q[0] = val;
5161 voodoo->ncc_dirty[0] = 1;
5162 }
5163 if (chip & CHIP_TREX1)
5164 {
5165 voodoo->nccTable[1][0].q[0] = val;
5166 voodoo->ncc_dirty[1] = 1;
5167 }
5168 break;
5169 }
5170 case SST_nccTable0_Q2:
5171 if (!(val & (1 << 31)))
5172 {
5173 if (chip & CHIP_TREX0)
5174 {
5175 voodoo->nccTable[0][0].i[2] = val;
5176 voodoo->ncc_dirty[0] = 1;
5177 }
5178 if (chip & CHIP_TREX1)
5179 {
5180 voodoo->nccTable[1][0].i[2] = val;
5181 voodoo->ncc_dirty[1] = 1;
5182 }
5183 break;
5184 }
5185 if (val & (1 << 31))
5186 {
5187 int p = (val >> 23) & 0xfe;
5188 if (chip & CHIP_TREX0)
5189 {
5190 voodoo->palette[0][p].u = val | 0xff000000;
5191 voodoo->palette_dirty[0] = 1;
5192 }
5193 if (chip & CHIP_TREX1)
5194 {
5195 voodoo->palette[1][p].u = val | 0xff000000;
5196 voodoo->palette_dirty[1] = 1;
5197 }
5198 }
5199 break;
5200
5201 case SST_nccTable0_I1:
5202 if (!(val & (1 << 31)))
5203 {
5204 if (chip & CHIP_TREX0)
5205 {
5206 voodoo->nccTable[0][0].i[1] = val;
5207 voodoo->ncc_dirty[0] = 1;
5208 }
5209 if (chip & CHIP_TREX1)
5210 {
5211 voodoo->nccTable[1][0].i[1] = val;
5212 voodoo->ncc_dirty[1] = 1;
5213 }
5214 break;
5215 }
5216 case SST_nccTable0_I3:
5217 if (!(val & (1 << 31)))
5218 {
5219 if (chip & CHIP_TREX0)
5220 {
5221 voodoo->nccTable[0][0].i[3] = val;
5222 voodoo->ncc_dirty[0] = 1;
5223 }
5224 if (chip & CHIP_TREX1)
5225 {
5226 voodoo->nccTable[1][0].i[3] = val;
5227 voodoo->ncc_dirty[1] = 1;
5228 }
5229 break;
5230 }
5231 case SST_nccTable0_Q1:
5232 if (!(val & (1 << 31)))
5233 {
5234 if (chip & CHIP_TREX0)
5235 {
5236 voodoo->nccTable[0][0].q[1] = val;
5237 voodoo->ncc_dirty[0] = 1;
5238 }
5239 if (chip & CHIP_TREX1)
5240 {
5241 voodoo->nccTable[1][0].q[1] = val;
5242 voodoo->ncc_dirty[1] = 1;
5243 }
5244 break;
5245 }
5246 case SST_nccTable0_Q3:
5247 if (!(val & (1 << 31)))
5248 {
5249 if (chip & CHIP_TREX0)
5250 {
5251 voodoo->nccTable[0][0].q[3] = val;
5252 voodoo->ncc_dirty[0] = 1;
5253 }
5254 if (chip & CHIP_TREX1)
5255 {
5256 voodoo->nccTable[1][0].q[3] = val;
5257 voodoo->ncc_dirty[1] = 1;
5258 }
5259 break;
5260 }
5261 if (val & (1 << 31))
5262 {
5263 int p = ((val >> 23) & 0xfe) | 0x01;
5264 if (chip & CHIP_TREX0)
5265 {
5266 voodoo->palette[0][p].u = val | 0xff000000;
5267 voodoo->palette_dirty[0] = 1;
5268 }
5269 if (chip & CHIP_TREX1)
5270 {
5271 voodoo->palette[1][p].u = val | 0xff000000;
5272 voodoo->palette_dirty[1] = 1;
5273 }
5274 }
5275 break;
5276
5277 case SST_nccTable1_Y0:
5278 if (chip & CHIP_TREX0)
5279 {
5280 voodoo->nccTable[0][1].y[0] = val;
5281 voodoo->ncc_dirty[0] = 1;
5282 }
5283 if (chip & CHIP_TREX1)
5284 {
5285 voodoo->nccTable[1][1].y[0] = val;
5286 voodoo->ncc_dirty[1] = 1;
5287 }
5288 break;
5289 case SST_nccTable1_Y1:
5290 if (chip & CHIP_TREX0)
5291 {
5292 voodoo->nccTable[0][1].y[1] = val;
5293 voodoo->ncc_dirty[0] = 1;
5294 }
5295 if (chip & CHIP_TREX1)
5296 {
5297 voodoo->nccTable[1][1].y[1] = val;
5298 voodoo->ncc_dirty[1] = 1;
5299 }
5300 break;
5301 case SST_nccTable1_Y2:
5302 if (chip & CHIP_TREX0)
5303 {
5304 voodoo->nccTable[0][1].y[2] = val;
5305 voodoo->ncc_dirty[0] = 1;
5306 }
5307 if (chip & CHIP_TREX1)
5308 {
5309 voodoo->nccTable[1][1].y[2] = val;
5310 voodoo->ncc_dirty[1] = 1;
5311 }
5312 break;
5313 case SST_nccTable1_Y3:
5314 if (chip & CHIP_TREX0)
5315 {
5316 voodoo->nccTable[0][1].y[3] = val;
5317 voodoo->ncc_dirty[0] = 1;
5318 }
5319 if (chip & CHIP_TREX1)
5320 {
5321 voodoo->nccTable[1][1].y[3] = val;
5322 voodoo->ncc_dirty[1] = 1;
5323 }
5324 break;
5325 case SST_nccTable1_I0:
5326 if (chip & CHIP_TREX0)
5327 {
5328 voodoo->nccTable[0][1].i[0] = val;
5329 voodoo->ncc_dirty[0] = 1;
5330 }
5331 if (chip & CHIP_TREX1)
5332 {
5333 voodoo->nccTable[1][1].i[0] = val;
5334 voodoo->ncc_dirty[1] = 1;
5335 }
5336 break;
5337 case SST_nccTable1_I1:
5338 if (chip & CHIP_TREX0)
5339 {
5340 voodoo->nccTable[0][1].i[1] = val;
5341 voodoo->ncc_dirty[0] = 1;
5342 }
5343 if (chip & CHIP_TREX1)
5344 {
5345 voodoo->nccTable[1][1].i[1] = val;
5346 voodoo->ncc_dirty[1] = 1;
5347 }
5348 break;
5349 case SST_nccTable1_I2:
5350 if (chip & CHIP_TREX0)
5351 {
5352 voodoo->nccTable[0][1].i[2] = val;
5353 voodoo->ncc_dirty[0] = 1;
5354 }
5355 if (chip & CHIP_TREX1)
5356 {
5357 voodoo->nccTable[1][1].i[2] = val;
5358 voodoo->ncc_dirty[1] = 1;
5359 }
5360 break;
5361 case SST_nccTable1_I3:
5362 if (chip & CHIP_TREX0)
5363 {
5364 voodoo->nccTable[0][1].i[3] = val;
5365 voodoo->ncc_dirty[0] = 1;
5366 }
5367 if (chip & CHIP_TREX1)
5368 {
5369 voodoo->nccTable[1][1].i[3] = val;
5370 voodoo->ncc_dirty[1] = 1;
5371 }
5372 break;
5373 case SST_nccTable1_Q0:
5374 if (chip & CHIP_TREX0)
5375 {
5376 voodoo->nccTable[0][1].q[0] = val;
5377 voodoo->ncc_dirty[0] = 1;
5378 }
5379 if (chip & CHIP_TREX1)
5380 {
5381 voodoo->nccTable[1][1].q[0] = val;
5382 voodoo->ncc_dirty[1] = 1;
5383 }
5384 break;
5385 case SST_nccTable1_Q1:
5386 if (chip & CHIP_TREX0)
5387 {
5388 voodoo->nccTable[0][1].q[1] = val;
5389 voodoo->ncc_dirty[0] = 1;
5390 }
5391 if (chip & CHIP_TREX1)
5392 {
5393 voodoo->nccTable[1][1].q[1] = val;
5394 voodoo->ncc_dirty[1] = 1;
5395 }
5396 break;
5397 case SST_nccTable1_Q2:
5398 if (chip & CHIP_TREX0)
5399 {
5400 voodoo->nccTable[0][1].q[2] = val;
5401 voodoo->ncc_dirty[0] = 1;
5402 }
5403 if (chip & CHIP_TREX1)
5404 {
5405 voodoo->nccTable[1][1].q[2] = val;
5406 voodoo->ncc_dirty[1] = 1;
5407 }
5408 break;
5409 case SST_nccTable1_Q3:
5410 if (chip & CHIP_TREX0)
5411 {
5412 voodoo->nccTable[0][1].q[3] = val;
5413 voodoo->ncc_dirty[0] = 1;
5414 }
5415 if (chip & CHIP_TREX1)
5416 {
5417 voodoo->nccTable[1][1].q[3] = val;
5418 voodoo->ncc_dirty[1] = 1;
5419 }
5420 break;
5421
5422 case SST_userIntrCMD:
5423 fatal("userIntrCMD write %08x from FIFO\n", val);
5424 break;
5425 }
5426 }
5427
5428
voodoo_fb_readw(uint32_t addr,void * p)5429 static uint16_t voodoo_fb_readw(uint32_t addr, void *p)
5430 {
5431 voodoo_t *voodoo = (voodoo_t *)p;
5432 int x, y;
5433 uint32_t read_addr;
5434 uint16_t temp;
5435
5436 x = (addr >> 1) & 0x3ff;
5437 y = (addr >> 11) & 0x3ff;
5438
5439 if (SLI_ENABLED)
5440 {
5441 voodoo_set_t *set = voodoo->set;
5442
5443 if (y & 1)
5444 voodoo = set->voodoos[1];
5445 else
5446 voodoo = set->voodoos[0];
5447
5448 y >>= 1;
5449 }
5450
5451 read_addr = voodoo->fb_read_offset + (x << 1) + (y * voodoo->row_width);
5452
5453 if (read_addr > voodoo->fb_mask)
5454 return 0xffff;
5455
5456 temp = *(uint16_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
5457
5458 // pclog("voodoo_fb_readw : %08X %08X %i %i %08X %08X %08x:%08x %i\n", addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++);
5459 return temp;
5460 }
voodoo_fb_readl(uint32_t addr,void * p)5461 static uint32_t voodoo_fb_readl(uint32_t addr, void *p)
5462 {
5463 voodoo_t *voodoo = (voodoo_t *)p;
5464 int x, y;
5465 uint32_t read_addr;
5466 uint32_t temp;
5467
5468 x = addr & 0x7fe;
5469 y = (addr >> 11) & 0x3ff;
5470
5471 if (SLI_ENABLED)
5472 {
5473 voodoo_set_t *set = voodoo->set;
5474
5475 if (y & 1)
5476 voodoo = set->voodoos[1];
5477 else
5478 voodoo = set->voodoos[0];
5479
5480 y >>= 1;
5481 }
5482
5483 read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width);
5484
5485 if (read_addr > voodoo->fb_mask)
5486 return 0xffffffff;
5487
5488 temp = *(uint32_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]);
5489
5490 // pclog("voodoo_fb_readl : %08X %08x %08X x=%i y=%i %08X %08X %08x:%08x %i ro=%08x rw=%i\n", addr, read_addr, temp, x, y, read_addr, *(uint32_t *)(&voodoo->fb_mem[4]), cs, pc, fb_reads++, voodoo->fb_read_offset, voodoo->row_width);
5491 return temp;
5492 }
5493
do_dither(voodoo_params_t * params,rgba8_t col,int x,int y)5494 static inline uint16_t do_dither(voodoo_params_t *params, rgba8_t col, int x, int y)
5495 {
5496 int r, g, b;
5497
5498 if (dither)
5499 {
5500 if (dither2x2)
5501 {
5502 r = dither_rb2x2[col.r][y & 1][x & 1];
5503 g = dither_g2x2[col.g][y & 1][x & 1];
5504 b = dither_rb2x2[col.b][y & 1][x & 1];
5505 }
5506 else
5507 {
5508 r = dither_rb[col.r][y & 3][x & 3];
5509 g = dither_g[col.g][y & 3][x & 3];
5510 b = dither_rb[col.b][y & 3][x & 3];
5511 }
5512 }
5513 else
5514 {
5515 r = col.r >> 3;
5516 g = col.g >> 2;
5517 b = col.b >> 3;
5518 }
5519
5520 return b | (g << 5) | (r << 11);
5521 }
5522
voodoo_fb_writew(uint32_t addr,uint16_t val,void * p)5523 static void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p)
5524 {
5525 voodoo_t *voodoo = (voodoo_t *)p;
5526 voodoo_params_t *params = &voodoo->params;
5527 int x, y;
5528 uint32_t write_addr, write_addr_aux;
5529 rgba8_t colour_data;
5530 uint16_t depth_data;
5531 uint8_t alpha_data;
5532 int write_mask = 0;
5533
5534 colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0;
5535
5536 depth_data = voodoo->params.zaColor & 0xffff;
5537 alpha_data = voodoo->params.zaColor >> 24;
5538
5539 // while (!RB_EMPTY)
5540 // thread_reset_event(voodoo->not_full_event);
5541
5542 // pclog("voodoo_fb_writew : %08X %04X\n", addr, val);
5543
5544
5545 switch (voodoo->lfbMode & LFB_FORMAT_MASK)
5546 {
5547 case LFB_FORMAT_RGB565:
5548 colour_data = rgb565[val];
5549 alpha_data = 0xff;
5550 write_mask = LFB_WRITE_COLOUR;
5551 break;
5552 case LFB_FORMAT_RGB555:
5553 colour_data = argb1555[val];
5554 alpha_data = 0xff;
5555 write_mask = LFB_WRITE_COLOUR;
5556 break;
5557 case LFB_FORMAT_ARGB1555:
5558 colour_data = argb1555[val];
5559 alpha_data = colour_data.a;
5560 write_mask = LFB_WRITE_COLOUR;
5561 break;
5562 case LFB_FORMAT_DEPTH:
5563 depth_data = val;
5564 write_mask = LFB_WRITE_DEPTH;
5565 break;
5566
5567 default:
5568 fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode);
5569 }
5570
5571 x = addr & 0x7fe;
5572 y = (addr >> 11) & 0x3ff;
5573
5574 if (SLI_ENABLED)
5575 {
5576 if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) ||
5577 ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
5578 return;
5579 y >>= 1;
5580 }
5581
5582
5583 if (voodoo->fb_write_offset == voodoo->params.front_offset)
5584 voodoo->dirty_line[y] = 1;
5585
5586 write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
5587 write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
5588
5589 // pclog("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr);
5590
5591 if (voodoo->lfbMode & 0x100)
5592 {
5593 {
5594 rgba8_t write_data = colour_data;
5595 uint16_t new_depth = depth_data;
5596
5597 if (params->fbzMode & FBZ_DEPTH_ENABLE)
5598 {
5599 uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
5600
5601 DEPTH_TEST(new_depth);
5602 }
5603
5604 if ((params->fbzMode & FBZ_CHROMAKEY) &&
5605 write_data.r == params->chromaKey_r &&
5606 write_data.g == params->chromaKey_g &&
5607 write_data.b == params->chromaKey_b)
5608 goto skip_pixel;
5609
5610 if (params->fogMode & FOG_ENABLE)
5611 {
5612 int32_t z = new_depth << 12;
5613 int64_t w_depth = (int64_t)(int32_t)new_depth;
5614 int32_t ia = alpha_data << 12;
5615
5616 APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
5617 }
5618
5619 if (params->alphaMode & 1)
5620 ALPHA_TEST(alpha_data);
5621
5622 if (params->alphaMode & (1 << 4))
5623 {
5624 uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
5625 int dest_r, dest_g, dest_b, dest_a;
5626
5627 dest_r = (dat >> 8) & 0xf8;
5628 dest_g = (dat >> 3) & 0xfc;
5629 dest_b = (dat << 3) & 0xf8;
5630 dest_r |= (dest_r >> 5);
5631 dest_g |= (dest_g >> 6);
5632 dest_b |= (dest_b >> 5);
5633 dest_a = 0xff;
5634
5635 ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data);
5636 }
5637
5638 if (params->fbzMode & FBZ_RGB_WMASK)
5639 *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y);
5640 if (params->fbzMode & FBZ_DEPTH_WMASK)
5641 *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
5642
5643 skip_pixel:
5644 x = x;
5645 }
5646 }
5647 else
5648 {
5649 if (write_mask & LFB_WRITE_COLOUR)
5650 *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y);
5651 if (write_mask & LFB_WRITE_DEPTH)
5652 *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data;
5653 }
5654 }
5655
5656
voodoo_fb_writel(uint32_t addr,uint32_t val,void * p)5657 static void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p)
5658 {
5659 voodoo_t *voodoo = (voodoo_t *)p;
5660 voodoo_params_t *params = &voodoo->params;
5661 int x, y;
5662 uint32_t write_addr, write_addr_aux;
5663 rgba8_t colour_data[2];
5664 uint16_t depth_data[2];
5665 uint8_t alpha_data[2];
5666 int write_mask = 0, count = 1;
5667
5668 depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff;
5669 alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24;
5670 // while (!RB_EMPTY)
5671 // thread_reset_event(voodoo->not_full_event);
5672
5673 // pclog("voodoo_fb_writel : %08X %08X\n", addr, val);
5674
5675 switch (voodoo->lfbMode & LFB_FORMAT_MASK)
5676 {
5677 case LFB_FORMAT_RGB565:
5678 colour_data[0] = rgb565[val & 0xffff];
5679 colour_data[1] = rgb565[val >> 16];
5680 write_mask = LFB_WRITE_COLOUR;
5681 count = 2;
5682 break;
5683 case LFB_FORMAT_RGB555:
5684 colour_data[0] = argb1555[val & 0xffff];
5685 colour_data[1] = argb1555[val >> 16];
5686 write_mask = LFB_WRITE_COLOUR;
5687 count = 2;
5688 break;
5689 case LFB_FORMAT_ARGB1555:
5690 colour_data[0] = argb1555[val & 0xffff];
5691 alpha_data[0] = colour_data[0].a;
5692 colour_data[1] = argb1555[val >> 16];
5693 alpha_data[1] = colour_data[1].a;
5694 write_mask = LFB_WRITE_COLOUR;
5695 count = 2;
5696 break;
5697
5698 case LFB_FORMAT_ARGB8888:
5699 colour_data[0].b = val & 0xff;
5700 colour_data[0].g = (val >> 8) & 0xff;
5701 colour_data[0].r = (val >> 16) & 0xff;
5702 alpha_data[0] = (val >> 24) & 0xff;
5703 write_mask = LFB_WRITE_COLOUR;
5704 addr >>= 1;
5705 break;
5706
5707 case LFB_FORMAT_DEPTH:
5708 depth_data[0] = val;
5709 depth_data[1] = val >> 16;
5710 write_mask = LFB_WRITE_DEPTH;
5711 count = 2;
5712 break;
5713
5714 default:
5715 fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode);
5716 }
5717
5718 x = addr & 0x7fe;
5719 y = (addr >> 11) & 0x3ff;
5720
5721 if (SLI_ENABLED)
5722 {
5723 if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) ||
5724 ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1)))
5725 return;
5726 y >>= 1;
5727 }
5728
5729 if (voodoo->fb_write_offset == voodoo->params.front_offset)
5730 voodoo->dirty_line[y] = 1;
5731
5732 write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width);
5733 write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width);
5734
5735 // pclog("fb_writel %08x x=%i y=%i rw=%i %08x wo=%08x\n", addr, x, y, voodoo->row_width, write_addr, voodoo->fb_write_offset);
5736
5737 if (voodoo->lfbMode & 0x100)
5738 {
5739 int c;
5740
5741 for (c = 0; c < count; c++)
5742 {
5743 rgba8_t write_data = colour_data[c];
5744 uint16_t new_depth = depth_data[c];
5745
5746 if (params->fbzMode & FBZ_DEPTH_ENABLE)
5747 {
5748 uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]);
5749
5750 DEPTH_TEST(new_depth);
5751 }
5752
5753 if ((params->fbzMode & FBZ_CHROMAKEY) &&
5754 write_data.r == params->chromaKey_r &&
5755 write_data.g == params->chromaKey_g &&
5756 write_data.b == params->chromaKey_b)
5757 goto skip_pixel;
5758
5759 if (params->fogMode & FOG_ENABLE)
5760 {
5761 int32_t z = new_depth << 12;
5762 int64_t w_depth = new_depth;
5763 int32_t ia = alpha_data[c] << 12;
5764
5765 APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth);
5766 }
5767
5768 if (params->alphaMode & 1)
5769 ALPHA_TEST(alpha_data[c]);
5770
5771 if (params->alphaMode & (1 << 4))
5772 {
5773 uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]);
5774 int dest_r, dest_g, dest_b, dest_a;
5775
5776 dest_r = (dat >> 8) & 0xf8;
5777 dest_g = (dat >> 3) & 0xfc;
5778 dest_b = (dat << 3) & 0xf8;
5779 dest_r |= (dest_r >> 5);
5780 dest_g |= (dest_g >> 6);
5781 dest_b |= (dest_b >> 5);
5782 dest_a = 0xff;
5783
5784 ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]);
5785 }
5786
5787 if (params->fbzMode & FBZ_RGB_WMASK)
5788 *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y);
5789 if (params->fbzMode & FBZ_DEPTH_WMASK)
5790 *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth;
5791
5792 skip_pixel:
5793 write_addr += 2;
5794 write_addr_aux += 2;
5795 }
5796 }
5797 else
5798 {
5799 int c;
5800
5801 for (c = 0; c < count; c++)
5802 {
5803 if (write_mask & LFB_WRITE_COLOUR)
5804 *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y);
5805 if (write_mask & LFB_WRITE_DEPTH)
5806 *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c];
5807
5808 write_addr += 2;
5809 write_addr_aux += 2;
5810 }
5811 }
5812 }
5813
voodoo_tex_writel(uint32_t addr,uint32_t val,void * p)5814 static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p)
5815 {
5816 int lod, s, t;
5817 voodoo_t *voodoo = (voodoo_t *)p;
5818 int tmu;
5819
5820 if (addr & 0x400000)
5821 return; /*TREX != 0*/
5822
5823 tmu = (addr & 0x200000) ? 1 : 0;
5824
5825 if (tmu && !voodoo->dual_tmus)
5826 return;
5827
5828 // pclog("voodoo_tex_writel : %08X %08X %i\n", addr, val, voodoo->params.tformat);
5829
5830 lod = (addr >> 17) & 0xf;
5831 t = (addr >> 9) & 0xff;
5832 if (voodoo->params.tformat[tmu] & 8)
5833 s = (addr >> 1) & 0xfe;
5834 else
5835 {
5836 if (voodoo->params.textureMode[tmu] & (1 << 31))
5837 s = addr & 0xfc;
5838 else
5839 s = (addr >> 1) & 0xfc;
5840 }
5841
5842 if (lod > LOD_MAX)
5843 return;
5844
5845 // if (addr >= 0x200000)
5846 // return;
5847
5848 if (voodoo->params.tformat[tmu] & 8)
5849 addr = voodoo->params.tex_base[tmu][lod] + s*2 + (t << voodoo->params.tex_shift[tmu][lod])*2;
5850 else
5851 addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]);
5852 if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
5853 {
5854 // pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
5855 flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu);
5856 }
5857 *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val;
5858 }
5859
5860 #define WAKE_DELAY (TIMER_USEC * 100)
wake_fifo_thread(voodoo_t * voodoo)5861 static inline void wake_fifo_thread(voodoo_t *voodoo)
5862 {
5863 if (!voodoo->wake_timer)
5864 {
5865 /*Don't wake FIFO thread immediately - if we do that it will probably
5866 process one word and go back to sleep, requiring it to be woken on
5867 almost every write. Instead, wait a short while so that the CPU
5868 emulation writes more data so we have more batched-up work.*/
5869 timer_process();
5870 voodoo->wake_timer = WAKE_DELAY;
5871 timer_update_outstanding();
5872 }
5873 }
5874
wake_fifo_thread_now(voodoo_t * voodoo)5875 static inline void wake_fifo_thread_now(voodoo_t *voodoo)
5876 {
5877 thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
5878 }
5879
voodoo_wake_timer(void * p)5880 static void voodoo_wake_timer(void *p)
5881 {
5882 voodoo_t *voodoo = (voodoo_t *)p;
5883
5884 voodoo->wake_timer = 0;
5885
5886 thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
5887 }
5888
queue_command(voodoo_t * voodoo,uint32_t addr_type,uint32_t val)5889 static inline void queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val)
5890 {
5891 fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK];
5892
5893 while (FIFO_FULL)
5894 {
5895 thread_reset_event(voodoo->fifo_not_full_event);
5896 if (FIFO_FULL)
5897 {
5898 thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/
5899 if (FIFO_FULL)
5900 wake_fifo_thread_now(voodoo);
5901 }
5902 }
5903
5904 fifo->val = val;
5905 fifo->addr_type = addr_type;
5906
5907 voodoo->fifo_write_idx++;
5908
5909 if (FIFO_ENTRIES > 0xe000)
5910 wake_fifo_thread(voodoo);
5911 }
5912
voodoo_readw(uint32_t addr,void * p)5913 static uint16_t voodoo_readw(uint32_t addr, void *p)
5914 {
5915 voodoo_t *voodoo = (voodoo_t *)p;
5916
5917 addr &= 0xffffff;
5918
5919 cycles -= voodoo->read_time;
5920
5921 if ((addr & 0xc00000) == 0x400000) /*Framebuffer*/
5922 {
5923 if (SLI_ENABLED)
5924 {
5925 voodoo_set_t *set = voodoo->set;
5926 int y = (addr >> 11) & 0x3ff;
5927
5928 if (y & 1)
5929 voodoo = set->voodoos[1];
5930 else
5931 voodoo = set->voodoos[0];
5932 }
5933
5934 voodoo->flush = 1;
5935 while (!FIFO_EMPTY)
5936 {
5937 wake_fifo_thread_now(voodoo);
5938 thread_wait_event(voodoo->fifo_not_full_event, 1);
5939 }
5940 wait_for_render_thread_idle(voodoo);
5941 voodoo->flush = 0;
5942
5943 return voodoo_fb_readw(addr, voodoo);
5944 }
5945
5946 return 0xffff;
5947 }
5948
voodoo_flush(voodoo_t * voodoo)5949 static void voodoo_flush(voodoo_t *voodoo)
5950 {
5951 voodoo->flush = 1;
5952 while (!FIFO_EMPTY)
5953 {
5954 wake_fifo_thread_now(voodoo);
5955 thread_wait_event(voodoo->fifo_not_full_event, 1);
5956 }
5957 wait_for_render_thread_idle(voodoo);
5958 voodoo->flush = 0;
5959 }
5960
wake_fifo_threads(voodoo_set_t * set,voodoo_t * voodoo)5961 static void wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo)
5962 {
5963 wake_fifo_thread(voodoo);
5964 if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo)
5965 wake_fifo_thread(set->voodoos[1]);
5966 }
5967
voodoo_readl(uint32_t addr,void * p)5968 static uint32_t voodoo_readl(uint32_t addr, void *p)
5969 {
5970 voodoo_t *voodoo = (voodoo_t *)p;
5971 uint32_t temp;
5972 int fifo_size;
5973 voodoo->rd_count++;
5974 addr &= 0xffffff;
5975
5976 cycles -= voodoo->read_time;
5977
5978 if (addr & 0x800000) /*Texture*/
5979 {
5980 }
5981 else if (addr & 0x400000) /*Framebuffer*/
5982 {
5983 if (SLI_ENABLED)
5984 {
5985 voodoo_set_t *set = voodoo->set;
5986 int y = (addr >> 11) & 0x3ff;
5987
5988 if (y & 1)
5989 voodoo = set->voodoos[1];
5990 else
5991 voodoo = set->voodoos[0];
5992 }
5993
5994 voodoo->flush = 1;
5995 while (!FIFO_EMPTY)
5996 {
5997 wake_fifo_thread_now(voodoo);
5998 thread_wait_event(voodoo->fifo_not_full_event, 1);
5999 }
6000 wait_for_render_thread_idle(voodoo);
6001 voodoo->flush = 0;
6002
6003 temp = voodoo_fb_readl(addr, voodoo);
6004 }
6005 else switch (addr & 0x3fc)
6006 {
6007 case SST_status:
6008 {
6009 int fifo_entries = FIFO_ENTRIES;
6010 int swap_count = voodoo->swap_count;
6011 int written = voodoo->cmd_written + voodoo->cmd_written_fifo;
6012 int busy = (written - voodoo->cmd_read) || (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr);
6013
6014 if (SLI_ENABLED && voodoo->type != VOODOO_2)
6015 {
6016 voodoo_t *voodoo_other = (voodoo == voodoo->set->voodoos[0]) ? voodoo->set->voodoos[1] : voodoo->set->voodoos[0];
6017 int other_written = voodoo_other->cmd_written + voodoo_other->cmd_written_fifo;
6018
6019 if (voodoo_other->swap_count > swap_count)
6020 swap_count = voodoo_other->swap_count;
6021 if ((voodoo_other->fifo_write_idx - voodoo_other->fifo_read_idx) > fifo_entries)
6022 fifo_entries = voodoo_other->fifo_write_idx - voodoo_other->fifo_read_idx;
6023 if ((other_written - voodoo_other->cmd_read) ||
6024 (voodoo_other->cmdfifo_depth_rd != voodoo_other->cmdfifo_depth_wr))
6025 busy = 1;
6026 if (!voodoo_other->voodoo_busy)
6027 wake_fifo_thread(voodoo_other);
6028 }
6029
6030 fifo_size = 0xffff - fifo_entries;
6031 temp = fifo_size << 12;
6032 if (fifo_size < 0x40)
6033 temp |= fifo_size;
6034 else
6035 temp |= 0x3f;
6036 if (swap_count < 7)
6037 temp |= (swap_count << 28);
6038 else
6039 temp |= (7 << 28);
6040 if (!voodoo->v_retrace)
6041 temp |= 0x40;
6042
6043 if (busy)
6044 temp |= 0x380; /*Busy*/
6045
6046 if (!voodoo->voodoo_busy)
6047 wake_fifo_thread(voodoo);
6048 }
6049 break;
6050
6051 case SST_fbzColorPath:
6052 voodoo_flush(voodoo);
6053 temp = voodoo->params.fbzColorPath;
6054 break;
6055 case SST_fogMode:
6056 voodoo_flush(voodoo);
6057 temp = voodoo->params.fogMode;
6058 break;
6059 case SST_alphaMode:
6060 voodoo_flush(voodoo);
6061 temp = voodoo->params.alphaMode;
6062 break;
6063 case SST_fbzMode:
6064 voodoo_flush(voodoo);
6065 temp = voodoo->params.fbzMode;
6066 break;
6067 case SST_lfbMode:
6068 voodoo_flush(voodoo);
6069 temp = voodoo->lfbMode;
6070 break;
6071 case SST_clipLeftRight:
6072 voodoo_flush(voodoo);
6073 temp = voodoo->params.clipRight | (voodoo->params.clipLeft << 16);
6074 break;
6075 case SST_clipLowYHighY:
6076 voodoo_flush(voodoo);
6077 temp = voodoo->params.clipHighY | (voodoo->params.clipLowY << 16);
6078 break;
6079
6080 case SST_stipple:
6081 voodoo_flush(voodoo);
6082 temp = voodoo->params.stipple;
6083 break;
6084 case SST_color0:
6085 voodoo_flush(voodoo);
6086 temp = voodoo->params.color0;
6087 break;
6088 case SST_color1:
6089 voodoo_flush(voodoo);
6090 temp = voodoo->params.color1;
6091 break;
6092
6093 case SST_fbiPixelsIn:
6094 temp = voodoo->fbiPixelsIn & 0xffffff;
6095 break;
6096 case SST_fbiChromaFail:
6097 temp = voodoo->fbiChromaFail & 0xffffff;
6098 break;
6099 case SST_fbiZFuncFail:
6100 temp = voodoo->fbiZFuncFail & 0xffffff;
6101 break;
6102 case SST_fbiAFuncFail:
6103 temp = voodoo->fbiAFuncFail & 0xffffff;
6104 break;
6105 case SST_fbiPixelsOut:
6106 temp = voodoo->fbiPixelsOut & 0xffffff;
6107 break;
6108
6109 case SST_fbiInit4:
6110 temp = voodoo->fbiInit4;
6111 break;
6112 case SST_fbiInit0:
6113 temp = voodoo->fbiInit0;
6114 break;
6115 case SST_fbiInit1:
6116 temp = voodoo->fbiInit1;
6117 break;
6118 case SST_fbiInit2:
6119 if (voodoo->initEnable & 0x04)
6120 temp = voodoo->dac_readdata;
6121 else
6122 temp = voodoo->fbiInit2;
6123 break;
6124 case SST_fbiInit3:
6125 temp = voodoo->fbiInit3 | (1 << 10) | (2 << 8);
6126 break;
6127
6128 case SST_vRetrace:
6129 timer_clock();
6130 temp = voodoo->line & 0x1fff;
6131 break;
6132 case SST_hvRetrace:
6133 timer_clock();
6134 temp = voodoo->line & 0x1fff;
6135 temp |= ((((voodoo->line_time - voodoo->timer_count) * voodoo->h_total) / voodoo->timer_count) << 16) & 0x7ff0000;
6136 break;
6137
6138 case SST_fbiInit5:
6139 temp = voodoo->fbiInit5 & ~0x1ff;
6140 break;
6141 case SST_fbiInit6:
6142 temp = voodoo->fbiInit6;
6143 break;
6144 case SST_fbiInit7:
6145 temp = voodoo->fbiInit7 & ~0xff;
6146 break;
6147
6148 case SST_cmdFifoBaseAddr:
6149 temp = voodoo->cmdfifo_base >> 12;
6150 temp |= (voodoo->cmdfifo_end >> 12) << 16;
6151 break;
6152
6153 case SST_cmdFifoRdPtr:
6154 temp = voodoo->cmdfifo_rp;
6155 break;
6156 case SST_cmdFifoAMin:
6157 temp = voodoo->cmdfifo_amin;
6158 break;
6159 case SST_cmdFifoAMax:
6160 temp = voodoo->cmdfifo_amax;
6161 break;
6162 case SST_cmdFifoDepth:
6163 temp = voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd;
6164 break;
6165
6166 default:
6167 fatal("voodoo_readl : bad addr %08X\n", addr);
6168 temp = 0xffffffff;
6169 }
6170
6171 return temp;
6172 }
6173
voodoo_writew(uint32_t addr,uint16_t val,void * p)6174 static void voodoo_writew(uint32_t addr, uint16_t val, void *p)
6175 {
6176 voodoo_t *voodoo = (voodoo_t *)p;
6177 voodoo->wr_count++;
6178 addr &= 0xffffff;
6179
6180 if (addr == voodoo->last_write_addr+4)
6181 cycles -= voodoo->burst_time;
6182 else
6183 cycles -= voodoo->write_time;
6184 voodoo->last_write_addr = addr;
6185
6186 if ((addr & 0xc00000) == 0x400000) /*Framebuffer*/
6187 queue_command(voodoo, addr | FIFO_WRITEW_FB, val);
6188 }
6189
voodoo_pixelclock_update(voodoo_t * voodoo)6190 static void voodoo_pixelclock_update(voodoo_t *voodoo)
6191 {
6192 int m = (voodoo->dac_pll_regs[0] & 0x7f) + 2;
6193 int n1 = ((voodoo->dac_pll_regs[0] >> 8) & 0x1f) + 2;
6194 int n2 = ((voodoo->dac_pll_regs[0] >> 13) & 0x07);
6195 float t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
6196 double clock_const;
6197 int line_length;
6198
6199 if ((voodoo->dac_data[6] & 0xf0) == 0x20 ||
6200 (voodoo->dac_data[6] & 0xf0) == 0x60 ||
6201 (voodoo->dac_data[6] & 0xf0) == 0x70)
6202 t /= 2.0f;
6203
6204 line_length = (voodoo->hSync & 0xff) + ((voodoo->hSync >> 16) & 0x3ff);
6205
6206 // pclog("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length);
6207
6208 voodoo->pixel_clock = t;
6209
6210 clock_const = cpuclock / t;
6211 voodoo->line_time = (int)((double)line_length * clock_const * (double)(1 << TIMER_SHIFT));
6212 }
6213
voodoo_writel(uint32_t addr,uint32_t val,void * p)6214 static void voodoo_writel(uint32_t addr, uint32_t val, void *p)
6215 {
6216 voodoo_t *voodoo = (voodoo_t *)p;
6217
6218 voodoo->wr_count++;
6219
6220 addr &= 0xffffff;
6221
6222 if (addr == voodoo->last_write_addr+4)
6223 cycles -= voodoo->burst_time;
6224 else
6225 cycles -= voodoo->write_time;
6226 voodoo->last_write_addr = addr;
6227
6228 if (addr & 0x800000) /*Texture*/
6229 {
6230 voodoo->tex_count++;
6231 queue_command(voodoo, addr | FIFO_WRITEL_TEX, val);
6232 }
6233 else if (addr & 0x400000) /*Framebuffer*/
6234 {
6235 queue_command(voodoo, addr | FIFO_WRITEL_FB, val);
6236 }
6237 else if ((addr & 0x200000) && (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE))
6238 {
6239 // pclog("Write CMDFIFO %08x(%08x) %08x %08x\n", addr, voodoo->cmdfifo_base + (addr & 0x3fffc), val, (voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask);
6240 *(uint32_t *)&voodoo->fb_mem[(voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask] = val;
6241 voodoo->cmdfifo_depth_wr++;
6242 if ((voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd) < 20)
6243 wake_fifo_thread(voodoo);
6244 }
6245 else switch (addr & 0x3fc)
6246 {
6247 case SST_intrCtrl:
6248 fatal("intrCtrl write %08x\n", val);
6249 break;
6250
6251 case SST_userIntrCMD:
6252 fatal("userIntrCMD write %08x\n", val);
6253 break;
6254
6255 case SST_swapbufferCMD:
6256 voodoo->cmd_written++;
6257 voodoo->swap_count++;
6258 if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
6259 return;
6260 queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
6261 if (!voodoo->voodoo_busy)
6262 wake_fifo_threads(voodoo->set, voodoo);
6263 break;
6264 case SST_triangleCMD:
6265 if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
6266 return;
6267 voodoo->cmd_written++;
6268 queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
6269 if (!voodoo->voodoo_busy)
6270 wake_fifo_threads(voodoo->set, voodoo);
6271 break;
6272 case SST_ftriangleCMD:
6273 if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
6274 return;
6275 voodoo->cmd_written++;
6276 queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
6277 if (!voodoo->voodoo_busy)
6278 wake_fifo_threads(voodoo->set, voodoo);
6279 break;
6280 case SST_fastfillCMD:
6281 if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
6282 return;
6283 voodoo->cmd_written++;
6284 queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
6285 if (!voodoo->voodoo_busy)
6286 wake_fifo_threads(voodoo->set, voodoo);
6287 break;
6288 case SST_nopCMD:
6289 if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
6290 return;
6291 voodoo->cmd_written++;
6292 queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
6293 if (!voodoo->voodoo_busy)
6294 wake_fifo_threads(voodoo->set, voodoo);
6295 break;
6296
6297 case SST_fbiInit4:
6298 if (voodoo->initEnable & 0x01)
6299 {
6300 voodoo->fbiInit4 = val;
6301 voodoo->read_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit4 & 1) ? 2 : 1);
6302 // pclog("fbiInit4 write %08x - read_time=%i\n", val, voodoo->read_time);
6303 }
6304 break;
6305 case SST_backPorch:
6306 voodoo->backPorch = val;
6307 break;
6308 case SST_videoDimensions:
6309 voodoo->videoDimensions = val;
6310 voodoo->h_disp = (val & 0xfff) + 1;
6311 voodoo->v_disp = (val >> 16) & 0xfff;
6312 break;
6313 case SST_fbiInit0:
6314 if (voodoo->initEnable & 0x01)
6315 {
6316 voodoo->fbiInit0 = val;
6317 if (voodoo->set->nr_cards == 2)
6318 svga_set_override(voodoo->svga, (voodoo->set->voodoos[0]->fbiInit0 | voodoo->set->voodoos[1]->fbiInit0) & 1);
6319 else
6320 svga_set_override(voodoo->svga, val & 1);
6321 if (val & FBIINIT0_GRAPHICS_RESET)
6322 {
6323 /*Reset display/draw buffer selection. This may not actually
6324 happen here on a real Voodoo*/
6325 voodoo->disp_buffer = 0;
6326 voodoo->draw_buffer = 1;
6327 voodoo_recalc(voodoo);
6328 voodoo->front_offset = voodoo->params.front_offset;
6329 }
6330 }
6331 break;
6332 case SST_fbiInit1:
6333 if (voodoo->initEnable & 0x01)
6334 {
6335 if ((voodoo->fbiInit1 & FBIINIT1_VIDEO_RESET) && !(val & FBIINIT1_VIDEO_RESET))
6336 {
6337 voodoo->line = 0;
6338 voodoo->swap_count = 0;
6339 voodoo->retrace_count = 0;
6340 }
6341 voodoo->fbiInit1 = (val & ~5) | (voodoo->fbiInit1 & 5);
6342 voodoo->write_time = pci_nonburst_time + pci_burst_time * ((voodoo->fbiInit1 & 2) ? 1 : 0);
6343 voodoo->burst_time = pci_burst_time * ((voodoo->fbiInit1 & 2) ? 2 : 1);
6344 // pclog("fbiInit1 write %08x - write_time=%i burst_time=%i\n", val, voodoo->write_time, voodoo->burst_time);
6345 }
6346 break;
6347 case SST_fbiInit2:
6348 if (voodoo->initEnable & 0x01)
6349 {
6350 voodoo->fbiInit2 = val;
6351 voodoo_recalc(voodoo);
6352 }
6353 break;
6354 case SST_fbiInit3:
6355 if (voodoo->initEnable & 0x01)
6356 voodoo->fbiInit3 = val;
6357 break;
6358
6359 case SST_hSync:
6360 voodoo->hSync = val;
6361 voodoo->h_total = (val & 0xffff) + (val >> 16);
6362 voodoo_pixelclock_update(voodoo);
6363 break;
6364 case SST_vSync:
6365 voodoo->vSync = val;
6366 voodoo->v_total = (val & 0xffff) + (val >> 16);
6367 break;
6368
6369 case SST_clutData:
6370 voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff;
6371 voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff;
6372 voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff;
6373 if (val & 0x20000000)
6374 {
6375 voodoo->clutData[(val >> 24) & 0x3f].b = 255;
6376 voodoo->clutData[(val >> 24) & 0x3f].g = 255;
6377 voodoo->clutData[(val >> 24) & 0x3f].r = 255;
6378 }
6379 voodoo->clutData_dirty = 1;
6380 break;
6381
6382 case SST_dacData:
6383 voodoo->dac_reg = (val >> 8) & 7;
6384 voodoo->dac_readdata = 0xff;
6385 if (val & 0x800)
6386 {
6387 // pclog(" dacData read %i %02X\n", voodoo->dac_reg, voodoo->dac_data[7]);
6388 if (voodoo->dac_reg == 5)
6389 {
6390 switch (voodoo->dac_data[7])
6391 {
6392 case 0x01: voodoo->dac_readdata = 0x55; break;
6393 case 0x07: voodoo->dac_readdata = 0x71; break;
6394 case 0x0b: voodoo->dac_readdata = 0x79; break;
6395 }
6396 }
6397 else
6398 voodoo->dac_readdata = voodoo->dac_data[voodoo->dac_readdata & 7];
6399 }
6400 else
6401 {
6402 if (voodoo->dac_reg == 5)
6403 {
6404 if (!voodoo->dac_reg_ff)
6405 voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] = (voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] & 0xff00) | val;
6406 else
6407 voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] = (voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf] & 0xff) | (val << 8);
6408 // pclog("Write PLL reg %x %04x\n", voodoo->dac_data[4] & 0xf, voodoo->dac_pll_regs[voodoo->dac_data[4] & 0xf]);
6409 voodoo->dac_reg_ff = !voodoo->dac_reg_ff;
6410 if (!voodoo->dac_reg_ff)
6411 voodoo->dac_data[4]++;
6412
6413 }
6414 else
6415 {
6416 voodoo->dac_data[voodoo->dac_reg] = val & 0xff;
6417 voodoo->dac_reg_ff = 0;
6418 }
6419 voodoo_pixelclock_update(voodoo);
6420 }
6421 break;
6422
6423 case SST_scrFilter:
6424 if (voodoo->initEnable & 0x01)
6425 {
6426 voodoo->scrfilterEnabled = 1;
6427 voodoo->scrfilterThreshold = val; /* update the threshold values and generate a new lookup table if necessary */
6428
6429 if (val < 1)
6430 voodoo->scrfilterEnabled = 0;
6431 voodoo_threshold_check(voodoo);
6432 pclog("Voodoo Filter: %06x\n", val);
6433 }
6434 break;
6435
6436 case SST_fbiInit5:
6437 if (voodoo->initEnable & 0x01)
6438 voodoo->fbiInit5 = (val & ~0x41e6) | (voodoo->fbiInit5 & 0x41e6);
6439 break;
6440 case SST_fbiInit6:
6441 if (voodoo->initEnable & 0x01)
6442 voodoo->fbiInit6 = val;
6443 break;
6444 case SST_fbiInit7:
6445 if (voodoo->initEnable & 0x01)
6446 voodoo->fbiInit7 = val;
6447 break;
6448
6449 case SST_cmdFifoBaseAddr:
6450 voodoo->cmdfifo_base = (val & 0x3ff) << 12;
6451 voodoo->cmdfifo_end = ((val >> 16) & 0x3ff) << 12;
6452 // pclog("CMDFIFO base=%08x end=%08x\n", voodoo->cmdfifo_base, voodoo->cmdfifo_end);
6453 break;
6454
6455 case SST_cmdFifoRdPtr:
6456 voodoo->cmdfifo_rp = val;
6457 break;
6458 case SST_cmdFifoAMin:
6459 voodoo->cmdfifo_amin = val;
6460 break;
6461 case SST_cmdFifoAMax:
6462 voodoo->cmdfifo_amax = val;
6463 break;
6464 case SST_cmdFifoDepth:
6465 voodoo->cmdfifo_depth_rd = 0;
6466 voodoo->cmdfifo_depth_wr = val & 0xffff;
6467 break;
6468
6469 default:
6470 if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)
6471 {
6472 pclog("Unknown register write in CMDFIFO mode %08x %08x\n", addr, val);
6473 }
6474 else
6475 {
6476 queue_command(voodoo, addr | FIFO_WRITEL_REG, val);
6477 }
6478 break;
6479 }
6480 }
6481
voodoo_snoop_readw(uint32_t addr,void * p)6482 static uint16_t voodoo_snoop_readw(uint32_t addr, void *p)
6483 {
6484 voodoo_set_t *set = (voodoo_set_t *)p;
6485
6486 return voodoo_readw(addr, set->voodoos[0]);
6487 }
voodoo_snoop_readl(uint32_t addr,void * p)6488 static uint32_t voodoo_snoop_readl(uint32_t addr, void *p)
6489 {
6490 voodoo_set_t *set = (voodoo_set_t *)p;
6491
6492 return voodoo_readl(addr, set->voodoos[0]);
6493 }
6494
voodoo_snoop_writew(uint32_t addr,uint16_t val,void * p)6495 static void voodoo_snoop_writew(uint32_t addr, uint16_t val, void *p)
6496 {
6497 voodoo_set_t *set = (voodoo_set_t *)p;
6498
6499 voodoo_writew(addr, val, set->voodoos[0]);
6500 voodoo_writew(addr, val, set->voodoos[1]);
6501 }
voodoo_snoop_writel(uint32_t addr,uint32_t val,void * p)6502 static void voodoo_snoop_writel(uint32_t addr, uint32_t val, void *p)
6503 {
6504 voodoo_set_t *set = (voodoo_set_t *)p;
6505
6506 voodoo_writel(addr, val, set->voodoos[0]);
6507 voodoo_writel(addr, val, set->voodoos[1]);
6508 }
6509
cmdfifo_get(voodoo_t * voodoo)6510 static uint32_t cmdfifo_get(voodoo_t *voodoo)
6511 {
6512 uint32_t val;
6513
6514 while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr)
6515 {
6516 thread_wait_event(voodoo->wake_fifo_thread, -1);
6517 thread_reset_event(voodoo->wake_fifo_thread);
6518 }
6519
6520 val = *(uint32_t *)&voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask];
6521
6522 voodoo->cmdfifo_depth_rd++;
6523 voodoo->cmdfifo_rp += 4;
6524
6525 // pclog(" CMDFIFO get %08x\n", val);
6526 return val;
6527 }
6528
cmdfifo_get_f(voodoo_t * voodoo)6529 static inline float cmdfifo_get_f(voodoo_t *voodoo)
6530 {
6531 union
6532 {
6533 uint32_t i;
6534 float f;
6535 } tempif;
6536
6537 tempif.i = cmdfifo_get(voodoo);
6538 return tempif.f;
6539 }
6540
6541 enum
6542 {
6543 CMDFIFO3_PC_MASK_RGB = (1 << 10),
6544 CMDFIFO3_PC_MASK_ALPHA = (1 << 11),
6545 CMDFIFO3_PC_MASK_Z = (1 << 12),
6546 CMDFIFO3_PC_MASK_Wb = (1 << 13),
6547 CMDFIFO3_PC_MASK_W0 = (1 << 14),
6548 CMDFIFO3_PC_MASK_S0_T0 = (1 << 15),
6549 CMDFIFO3_PC_MASK_W1 = (1 << 16),
6550 CMDFIFO3_PC_MASK_S1_T1 = (1 << 17),
6551
6552 CMDFIFO3_PC = (1 << 28)
6553 };
6554
fifo_thread(void * param)6555 static void fifo_thread(void *param)
6556 {
6557 voodoo_t *voodoo = (voodoo_t *)param;
6558
6559 while (1)
6560 {
6561 thread_set_event(voodoo->fifo_not_full_event);
6562 thread_wait_event(voodoo->wake_fifo_thread, -1);
6563 thread_reset_event(voodoo->wake_fifo_thread);
6564 voodoo->voodoo_busy = 1;
6565 while (!FIFO_EMPTY)
6566 {
6567 uint64_t start_time = timer_read();
6568 uint64_t end_time;
6569 fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
6570
6571 switch (fifo->addr_type & FIFO_TYPE)
6572 {
6573 case FIFO_WRITEL_REG:
6574 voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
6575 break;
6576 case FIFO_WRITEW_FB:
6577 wait_for_render_thread_idle(voodoo);
6578 voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
6579 break;
6580 case FIFO_WRITEL_FB:
6581 wait_for_render_thread_idle(voodoo);
6582 voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
6583 break;
6584 case FIFO_WRITEL_TEX:
6585 if (!(fifo->addr_type & 0x400000))
6586 voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo);
6587 break;
6588 }
6589 voodoo->fifo_read_idx++;
6590 fifo->addr_type = FIFO_INVALID;
6591
6592 if (FIFO_ENTRIES > 0xe000)
6593 thread_set_event(voodoo->fifo_not_full_event);
6594
6595 end_time = timer_read();
6596 voodoo->time += end_time - start_time;
6597 }
6598
6599 while (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr)
6600 {
6601 uint64_t start_time = timer_read();
6602 uint64_t end_time;
6603 uint32_t header = cmdfifo_get(voodoo);
6604 uint32_t addr;
6605 uint32_t mask;
6606 int smode;
6607 int num;
6608 int num_verticies;
6609 int v_num;
6610
6611 // pclog(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp);
6612
6613 switch (header & 7)
6614 {
6615 case 0:
6616 // pclog("CMDFIFO0\n");
6617 switch ((header >> 3) & 7)
6618 {
6619 case 0: /*NOP*/
6620 break;
6621
6622 case 3: /*JMP local frame buffer*/
6623 voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc;
6624 // pclog("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header);
6625 break;
6626
6627 default:
6628 fatal("Bad CMDFIFO0 %08x\n", header);
6629 }
6630 break;
6631
6632 case 1:
6633 num = header >> 16;
6634 addr = (header & 0x7ff8) >> 1;
6635 // pclog("CMDFIFO1 addr=%08x\n",addr);
6636 while (num--)
6637 {
6638 uint32_t val = cmdfifo_get(voodoo);
6639 if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
6640 (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
6641 voodoo->cmd_written_fifo++;
6642
6643 voodoo_reg_writel(addr, val, voodoo);
6644
6645 if (header & (1 << 15))
6646 addr += 4;
6647 }
6648 break;
6649
6650 case 3:
6651 num = (header >> 29) & 7;
6652 mask = header;//(header >> 10) & 0xff;
6653 smode = (header >> 22) & 0xf;
6654 voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo);
6655 num_verticies = (header >> 6) & 0xf;
6656 v_num = 0;
6657 if (((header >> 3) & 7) == 2)
6658 v_num = 1;
6659 // pclog("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff);
6660 // pclog("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7);
6661
6662 while (num_verticies--)
6663 {
6664 voodoo->verts[3].sVx = cmdfifo_get_f(voodoo);
6665 voodoo->verts[3].sVy = cmdfifo_get_f(voodoo);
6666 if (mask & CMDFIFO3_PC_MASK_RGB)
6667 {
6668 if (header & CMDFIFO3_PC)
6669 {
6670 uint32_t val = cmdfifo_get(voodoo);
6671 voodoo->verts[3].sBlue = (float)(val & 0xff);
6672 voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff);
6673 voodoo->verts[3].sRed = (float)((val >> 16) & 0xff);
6674 voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff);
6675 }
6676 else
6677 {
6678 voodoo->verts[3].sRed = cmdfifo_get_f(voodoo);
6679 voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo);
6680 voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo);
6681 }
6682 }
6683 if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC))
6684 voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo);
6685 if (mask & CMDFIFO3_PC_MASK_Z)
6686 voodoo->verts[3].sVz = cmdfifo_get_f(voodoo);
6687 if (mask & CMDFIFO3_PC_MASK_Wb)
6688 voodoo->verts[3].sWb = cmdfifo_get_f(voodoo);
6689 if (mask & CMDFIFO3_PC_MASK_W0)
6690 voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo);
6691 if (mask & CMDFIFO3_PC_MASK_S0_T0)
6692 {
6693 voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo);
6694 voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo);
6695 }
6696 if (mask & CMDFIFO3_PC_MASK_W1)
6697 voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo);
6698 if (mask & CMDFIFO3_PC_MASK_S1_T1)
6699 {
6700 voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo);
6701 voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo);
6702 }
6703 if (v_num)
6704 voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo);
6705 else
6706 voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo);
6707 v_num++;
6708 if (v_num == 3 && ((header >> 3) & 7) == 0)
6709 v_num = 0;
6710 }
6711 break;
6712
6713 case 4:
6714 num = (header >> 29) & 7;
6715 mask = (header >> 15) & 0x3fff;
6716 addr = (header & 0x7ff8) >> 1;
6717 // pclog("CMDFIFO4 addr=%08x\n",addr);
6718 while (mask)
6719 {
6720 if (mask & 1)
6721 {
6722 uint32_t val = cmdfifo_get(voodoo);
6723 if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
6724 (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
6725 voodoo->cmd_written_fifo++;
6726
6727 voodoo_reg_writel(addr, val, voodoo);
6728 }
6729
6730 addr += 4;
6731 mask >>= 1;
6732 }
6733 while (num--)
6734 cmdfifo_get(voodoo);
6735 break;
6736
6737 case 5:
6738 if (header & 0x3fc0000)
6739 fatal("CMDFIFO packet 5 has byte disables set %08x\n", header);
6740 num = (header >> 3) & 0x7ffff;
6741 addr = cmdfifo_get(voodoo) & 0xffffff;
6742 // pclog("CMDFIFO5 addr=%08x num=%i\n", addr, num);
6743 switch (header >> 30)
6744 {
6745 case 2: /*Framebuffer*/
6746 while (num--)
6747 {
6748 uint32_t val = cmdfifo_get(voodoo);
6749 voodoo_fb_writel(addr, val, voodoo);
6750 addr += 4;
6751 }
6752 break;
6753 case 3: /*Texture*/
6754 while (num--)
6755 {
6756 uint32_t val = cmdfifo_get(voodoo);
6757 voodoo_tex_writel(addr, val, voodoo);
6758 addr += 4;
6759 }
6760 break;
6761
6762 default:
6763 fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp);
6764 }
6765 break;
6766
6767 default:
6768 pclog("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
6769 }
6770
6771 end_time = timer_read();
6772 voodoo->time += end_time - start_time;
6773 }
6774 voodoo->voodoo_busy = 0;
6775 }
6776 }
6777
voodoo_recalcmapping(voodoo_set_t * set)6778 static void voodoo_recalcmapping(voodoo_set_t *set)
6779 {
6780 if (set->nr_cards == 2)
6781 {
6782 if (set->voodoos[0]->pci_enable && set->voodoos[0]->memBaseAddr)
6783 {
6784 if (set->voodoos[0]->type == VOODOO_2 && set->voodoos[1]->initEnable & (1 << 23))
6785 {
6786 pclog("voodoo_recalcmapping (pri) with snoop : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr);
6787 mem_mapping_disable(&set->voodoos[0]->mapping);
6788 mem_mapping_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000);
6789 }
6790 else if (set->voodoos[1]->pci_enable && (set->voodoos[0]->memBaseAddr == set->voodoos[1]->memBaseAddr))
6791 {
6792 pclog("voodoo_recalcmapping (pri) (sec) same addr : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr);
6793 mem_mapping_disable(&set->voodoos[0]->mapping);
6794 mem_mapping_disable(&set->voodoos[1]->mapping);
6795 mem_mapping_set_addr(&set->snoop_mapping, set->voodoos[0]->memBaseAddr, 0x01000000);
6796 return;
6797 }
6798 else
6799 {
6800 pclog("voodoo_recalcmapping (pri) : memBaseAddr %08X\n", set->voodoos[0]->memBaseAddr);
6801 mem_mapping_disable(&set->snoop_mapping);
6802 mem_mapping_set_addr(&set->voodoos[0]->mapping, set->voodoos[0]->memBaseAddr, 0x01000000);
6803 }
6804 }
6805 else
6806 {
6807 pclog("voodoo_recalcmapping (pri) : disabled\n");
6808 mem_mapping_disable(&set->voodoos[0]->mapping);
6809 }
6810
6811 if (set->voodoos[1]->pci_enable && set->voodoos[1]->memBaseAddr)
6812 {
6813 pclog("voodoo_recalcmapping (sec) : memBaseAddr %08X\n", set->voodoos[1]->memBaseAddr);
6814 mem_mapping_set_addr(&set->voodoos[1]->mapping, set->voodoos[1]->memBaseAddr, 0x01000000);
6815 }
6816 else
6817 {
6818 pclog("voodoo_recalcmapping (sec) : disabled\n");
6819 mem_mapping_disable(&set->voodoos[1]->mapping);
6820 }
6821 }
6822 else
6823 {
6824 voodoo_t *voodoo = set->voodoos[0];
6825
6826 if (voodoo->pci_enable && voodoo->memBaseAddr)
6827 {
6828 pclog("voodoo_recalcmapping : memBaseAddr %08X\n", voodoo->memBaseAddr);
6829 mem_mapping_set_addr(&voodoo->mapping, voodoo->memBaseAddr, 0x01000000);
6830 }
6831 else
6832 {
6833 pclog("voodoo_recalcmapping : disabled\n");
6834 mem_mapping_disable(&voodoo->mapping);
6835 }
6836 }
6837 }
6838
voodoo_pci_read(int func,int addr,void * p)6839 uint8_t voodoo_pci_read(int func, int addr, void *p)
6840 {
6841 voodoo_t *voodoo = (voodoo_t *)p;
6842
6843 if (func)
6844 return 0;
6845
6846 // pclog("Voodoo PCI read %08X PC=%08x\n", addr, cpu_state.pc);
6847
6848 switch (addr)
6849 {
6850 case 0x00: return 0x1a; /*3dfx*/
6851 case 0x01: return 0x12;
6852
6853 case 0x02:
6854 if (voodoo->type == VOODOO_2)
6855 return 0x02; /*Voodoo 2*/
6856 else
6857 return 0x01; /*SST-1 (Voodoo Graphics)*/
6858 case 0x03: return 0x00;
6859
6860 case 0x04: return voodoo->pci_enable ? 0x02 : 0x00; /*Respond to memory accesses*/
6861
6862 case 0x08: return 2; /*Revision ID*/
6863 case 0x09: return 0; /*Programming interface*/
6864 case 0x0a: return 0;
6865 case 0x0b: return 0x04;
6866
6867 case 0x10: return 0x00; /*memBaseAddr*/
6868 case 0x11: return 0x00;
6869 case 0x12: return 0x00;
6870 case 0x13: return voodoo->memBaseAddr >> 24;
6871
6872 case 0x40:
6873 return voodoo->initEnable & 0xff;
6874 case 0x41:
6875 if (voodoo->type == VOODOO_2)
6876 return 0x50 | ((voodoo->initEnable >> 8) & 0x0f);
6877 return (voodoo->initEnable >> 8) & 0x0f;
6878 case 0x42:
6879 return (voodoo->initEnable >> 16) & 0xff;
6880 case 0x43:
6881 return (voodoo->initEnable >> 24) & 0xff;
6882 }
6883 return 0;
6884 }
6885
voodoo_pci_write(int func,int addr,uint8_t val,void * p)6886 void voodoo_pci_write(int func, int addr, uint8_t val, void *p)
6887 {
6888 voodoo_t *voodoo = (voodoo_t *)p;
6889
6890 if (func)
6891 return;
6892
6893 // pclog("Voodoo PCI write %04X %02X PC=%08x\n", addr, val, cpu_state.pc);
6894
6895 switch (addr)
6896 {
6897 case 0x04:
6898 voodoo->pci_enable = val & 2;
6899 voodoo_recalcmapping(voodoo->set);
6900 break;
6901
6902 case 0x13:
6903 voodoo->memBaseAddr = val << 24;
6904 voodoo_recalcmapping(voodoo->set);
6905 break;
6906
6907 case 0x40:
6908 voodoo->initEnable = (voodoo->initEnable & ~0x000000ff) | val;
6909 break;
6910 case 0x41:
6911 voodoo->initEnable = (voodoo->initEnable & ~0x0000ff00) | (val << 8);
6912 break;
6913 case 0x42:
6914 voodoo->initEnable = (voodoo->initEnable & ~0x00ff0000) | (val << 16);
6915 voodoo_recalcmapping(voodoo->set);
6916 break;
6917 case 0x43:
6918 voodoo->initEnable = (voodoo->initEnable & ~0xff000000) | (val << 24);
6919 voodoo_recalcmapping(voodoo->set);
6920 break;
6921 }
6922 }
6923
voodoo_calc_clutData(voodoo_t * voodoo)6924 static void voodoo_calc_clutData(voodoo_t *voodoo)
6925 {
6926 int c;
6927
6928 for (c = 0; c < 256; c++)
6929 {
6930 voodoo->clutData256[c].r = (voodoo->clutData[c >> 3].r*(8-(c & 7)) +
6931 voodoo->clutData[(c >> 3)+1].r*(c & 7)) >> 3;
6932 voodoo->clutData256[c].g = (voodoo->clutData[c >> 3].g*(8-(c & 7)) +
6933 voodoo->clutData[(c >> 3)+1].g*(c & 7)) >> 3;
6934 voodoo->clutData256[c].b = (voodoo->clutData[c >> 3].b*(8-(c & 7)) +
6935 voodoo->clutData[(c >> 3)+1].b*(c & 7)) >> 3;
6936 }
6937
6938 for (c = 0; c < 65536; c++)
6939 {
6940 int r = (c >> 8) & 0xf8;
6941 int g = (c >> 3) & 0xfc;
6942 int b = (c << 3) & 0xf8;
6943 // r |= (r >> 5);
6944 // g |= (g >> 6);
6945 // b |= (b >> 5);
6946
6947 voodoo->video_16to32[c] = (voodoo->clutData256[r].r << 16) | (voodoo->clutData256[g].g << 8) | voodoo->clutData256[b].b;
6948 }
6949 }
6950
6951
6952
6953 #define FILTDIV 256
6954
6955 static int FILTCAP, FILTCAPG, FILTCAPB = 0; /* color filter threshold values */
6956
voodoo_generate_filter_v1(voodoo_t * voodoo)6957 static void voodoo_generate_filter_v1(voodoo_t *voodoo)
6958 {
6959 int g, h;
6960 float difference, diffg, diffb;
6961 float thiscol, thiscolg, thiscolb, lined;
6962 float fcr, fcg, fcb;
6963
6964 fcr = FILTCAP * 5;
6965 fcg = FILTCAPG * 6;
6966 fcb = FILTCAPB * 5;
6967
6968 for (g=0;g<FILTDIV;g++) // pixel 1
6969 {
6970 for (h=0;h<FILTDIV;h++) // pixel 2
6971 {
6972 difference = (float)(h - g);
6973 diffg = difference;
6974 diffb = difference;
6975
6976 thiscol = thiscolg = thiscolb = g;
6977
6978 if (difference > FILTCAP)
6979 difference = FILTCAP;
6980 if (difference < -FILTCAP)
6981 difference = -FILTCAP;
6982
6983 if (diffg > FILTCAPG)
6984 diffg = FILTCAPG;
6985 if (diffg < -FILTCAPG)
6986 diffg = -FILTCAPG;
6987
6988 if (diffb > FILTCAPB)
6989 diffb = FILTCAPB;
6990 if (diffb < -FILTCAPB)
6991 diffb = -FILTCAPB;
6992
6993 // hack - to make it not bleed onto black
6994 //if (g == 0){
6995 //difference = diffg = diffb = 0;
6996 //}
6997
6998 if ((difference < fcr) || (-difference > -fcr))
6999 thiscol = g + (difference / 2);
7000 if ((diffg < fcg) || (-diffg > -fcg))
7001 thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */
7002 if ((diffb < fcb) || (-diffb > -fcb))
7003 thiscolb = g + (diffb / 2);
7004
7005 if (thiscol < 0)
7006 thiscol = 0;
7007 if (thiscol > FILTDIV-1)
7008 thiscol = FILTDIV-1;
7009
7010 if (thiscolg < 0)
7011 thiscolg = 0;
7012 if (thiscolg > FILTDIV-1)
7013 thiscolg = FILTDIV-1;
7014
7015 if (thiscolb < 0)
7016 thiscolb = 0;
7017 if (thiscolb > FILTDIV-1)
7018 thiscolb = FILTDIV-1;
7019
7020 voodoo->thefilter[g][h] = thiscol;
7021 voodoo->thefilterg[g][h] = thiscolg;
7022 voodoo->thefilterb[g][h] = thiscolb;
7023 }
7024
7025 lined = g + 4;
7026 if (lined > 255)
7027 lined = 255;
7028 voodoo->purpleline[g][0] = lined;
7029 voodoo->purpleline[g][2] = lined;
7030
7031 lined = g + 0;
7032 if (lined > 255)
7033 lined = 255;
7034 voodoo->purpleline[g][1] = lined;
7035 }
7036 }
7037
voodoo_generate_filter_v2(voodoo_t * voodoo)7038 static void voodoo_generate_filter_v2(voodoo_t *voodoo)
7039 {
7040 int g, h;
7041 float difference;
7042 float thiscol, thiscolg, thiscolb, lined;
7043 float clr, clg, clb = 0;
7044 float fcr, fcg, fcb = 0;
7045
7046 // pre-clamping
7047
7048 fcr = FILTCAP;
7049 fcg = FILTCAPG;
7050 fcb = FILTCAPB;
7051
7052 if (fcr > 32) fcr = 32;
7053 if (fcg > 32) fcg = 32;
7054 if (fcb > 32) fcb = 32;
7055
7056 for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into
7057 {
7058 for (h=0;h<256;h++) // pixel 2 - our main pixel
7059 {
7060 float avg;
7061 float avgdiff;
7062
7063 difference = (float)(g - h);
7064 avg = (float)((g + g + g + g + h) / 5);
7065 avgdiff = avg - (float)((g + h + h + h + h) / 5);
7066 if (avgdiff < 0) avgdiff *= -1;
7067 if (difference < 0) difference *= -1;
7068
7069 thiscol = thiscolg = thiscolb = g;
7070
7071 // try lighten
7072 if (h > g)
7073 {
7074 clr = clg = clb = avgdiff;
7075
7076 if (clr>fcr) clr=fcr;
7077 if (clg>fcg) clg=fcg;
7078 if (clb>fcb) clb=fcb;
7079
7080
7081 thiscol = g + clr;
7082 thiscolg = g + clg;
7083 thiscolb = g + clb;
7084
7085 if (thiscol>g+FILTCAP)
7086 thiscol=g+FILTCAP;
7087 if (thiscolg>g+FILTCAPG)
7088 thiscolg=g+FILTCAPG;
7089 if (thiscolb>g+FILTCAPB)
7090 thiscolb=g+FILTCAPB;
7091
7092
7093 if (thiscol>g+avgdiff)
7094 thiscol=g+avgdiff;
7095 if (thiscolg>g+avgdiff)
7096 thiscolg=g+avgdiff;
7097 if (thiscolb>g+avgdiff)
7098 thiscolb=g+avgdiff;
7099
7100 }
7101
7102 if (difference > FILTCAP)
7103 thiscol = g;
7104 if (difference > FILTCAPG)
7105 thiscolg = g;
7106 if (difference > FILTCAPB)
7107 thiscolb = g;
7108
7109 // clamp
7110 if (thiscol < 0) thiscol = 0;
7111 if (thiscolg < 0) thiscolg = 0;
7112 if (thiscolb < 0) thiscolb = 0;
7113
7114 if (thiscol > 255) thiscol = 255;
7115 if (thiscolg > 255) thiscolg = 255;
7116 if (thiscolb > 255) thiscolb = 255;
7117
7118 // add to the table
7119 voodoo->thefilter[g][h] = (thiscol);
7120 voodoo->thefilterg[g][h] = (thiscolg);
7121 voodoo->thefilterb[g][h] = (thiscolb);
7122
7123 // debug the ones that don't give us much of a difference
7124 //if (difference < FILTCAP)
7125 //pclog("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb);
7126 }
7127
7128 lined = g + 3;
7129 if (lined > 255)
7130 lined = 255;
7131 voodoo->purpleline[g][0] = lined;
7132 voodoo->purpleline[g][1] = 0;
7133 voodoo->purpleline[g][2] = lined;
7134 }
7135 }
7136
voodoo_threshold_check(voodoo_t * voodoo)7137 static void voodoo_threshold_check(voodoo_t *voodoo)
7138 {
7139 int r, g, b;
7140
7141 if (!voodoo->scrfilterEnabled)
7142 return; /* considered disabled; don't check and generate */
7143
7144 /* Check for changes, to generate anew table */
7145 if (voodoo->scrfilterThreshold != voodoo->scrfilterThresholdOld)
7146 {
7147 r = (voodoo->scrfilterThreshold >> 16) & 0xFF;
7148 g = (voodoo->scrfilterThreshold >> 8 ) & 0xFF;
7149 b = voodoo->scrfilterThreshold & 0xFF;
7150
7151 FILTCAP = r;
7152 FILTCAPG = g;
7153 FILTCAPB = b;
7154
7155 pclog("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b);
7156
7157 voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold;
7158
7159 if (voodoo->type == VOODOO_2)
7160 voodoo_generate_filter_v2(voodoo);
7161 else
7162 voodoo_generate_filter_v1(voodoo);
7163 }
7164 }
7165
voodoo_filterline_v1(voodoo_t * voodoo,uint8_t * fil,int column,uint16_t * src,int line)7166 static void voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line)
7167 {
7168 int x;
7169
7170 // Scratchpad for avoiding feedback streaks
7171 uint8_t fil3[(voodoo->h_disp) * 3];
7172
7173 /* 16 to 32-bit */
7174 for (x=0; x<column;x++)
7175 {
7176 fil[x*3] = ((src[x] & 31) << 3);
7177 fil[x*3+1] = (((src[x] >> 5) & 63) << 2);
7178 fil[x*3+2] = (((src[x] >> 11) & 31) << 3);
7179
7180 // Copy to our scratchpads
7181 fil3[x*3+0] = fil[x*3+0];
7182 fil3[x*3+1] = fil[x*3+1];
7183 fil3[x*3+2] = fil[x*3+2];
7184 }
7185
7186
7187 /* lines */
7188
7189 if (line & 1)
7190 {
7191 for (x=0; x<column;x++)
7192 {
7193 fil[x*3] = voodoo->purpleline[fil[x*3]][0];
7194 fil[x*3+1] = voodoo->purpleline[fil[x*3+1]][1];
7195 fil[x*3+2] = voodoo->purpleline[fil[x*3+2]][2];
7196 }
7197 }
7198
7199
7200 /* filtering time */
7201
7202 for (x=1; x<column;x++)
7203 {
7204 fil3[(x)*3] = voodoo->thefilterb[fil[x*3]][fil[ (x-1) *3]];
7205 fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]];
7206 fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]];
7207 }
7208
7209 for (x=1; x<column;x++)
7210 {
7211 fil[(x)*3] = voodoo->thefilterb[fil3[x*3]][fil3[ (x-1) *3]];
7212 fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x-1) *3+1]];
7213 fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x-1) *3+2]];
7214 }
7215
7216 for (x=1; x<column;x++)
7217 {
7218 fil3[(x)*3] = voodoo->thefilterb[fil[x*3]][fil[ (x-1) *3]];
7219 fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]];
7220 fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]];
7221 }
7222
7223 for (x=0; x<column-1;x++)
7224 {
7225 fil[(x)*3] = voodoo->thefilterb[fil3[x*3]][fil3[ (x+1) *3]];
7226 fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x+1) *3+1]];
7227 fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x+1) *3+2]];
7228 }
7229 }
7230
7231
voodoo_filterline_v2(voodoo_t * voodoo,uint8_t * fil,int column,uint16_t * src,int line)7232 static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line)
7233 {
7234 int x;
7235
7236 // Scratchpad for blending filter
7237 uint8_t fil3[(voodoo->h_disp) * 3];
7238
7239 /* 16 to 32-bit */
7240 for (x=0; x<column;x++)
7241 {
7242 // Blank scratchpads
7243 fil3[x*3+0] = fil[x*3+0] = ((src[x] & 31) << 3);
7244 fil3[x*3+1] = fil[x*3+1] = (((src[x] >> 5) & 63) << 2);
7245 fil3[x*3+2] = fil[x*3+2] = (((src[x] >> 11) & 31) << 3);
7246 }
7247
7248 /* filtering time */
7249
7250 for (x=1; x<column-3;x++)
7251 {
7252 fil3[(x+3)*3] = voodoo->thefilterb [((src[x+3] & 31) << 3)] [((src[x] & 31) << 3)];
7253 fil3[(x+3)*3+1] = voodoo->thefilterg [(((src[x+3] >> 5) & 63) << 2)] [(((src[x] >> 5) & 63) << 2)];
7254 fil3[(x+3)*3+2] = voodoo->thefilter [(((src[x+3] >> 11) & 31) << 3)] [(((src[x] >> 11) & 31) << 3)];
7255
7256 fil[(x+2)*3] = voodoo->thefilterb [fil3[(x+2)*3]][((src[x] & 31) << 3)];
7257 fil[(x+2)*3+1] = voodoo->thefilterg [fil3[(x+2)*3+1]][(((src[x] >> 5) & 63) << 2)];
7258 fil[(x+2)*3+2] = voodoo->thefilter [fil3[(x+2)*3+2]][(((src[x] >> 11) & 31) << 3)];
7259
7260 fil3[(x+1)*3] = voodoo->thefilterb [fil[(x+1)*3]][((src[x] & 31) << 3)];
7261 fil3[(x+1)*3+1] = voodoo->thefilterg [fil[(x+1)*3+1]][(((src[x] >> 5) & 63) << 2)];
7262 fil3[(x+1)*3+2] = voodoo->thefilter [fil[(x+1)*3+2]][(((src[x] >> 11) & 31) << 3)];
7263
7264 fil[(x-1)*3] = voodoo->thefilterb [fil3[(x-1)*3]][((src[x] & 31) << 3)];
7265 fil[(x-1)*3+1] = voodoo->thefilterg [fil3[(x-1)*3+1]][(((src[x] >> 5) & 63) << 2)];
7266 fil[(x-1)*3+2] = voodoo->thefilter [fil3[(x-1)*3+2]][(((src[x] >> 11) & 31) << 3)];
7267 }
7268
7269 // unroll for edge cases
7270
7271 fil3[(column-3)*3] = voodoo->thefilterb [((src[column-3] & 31) << 3)] [((src[column] & 31) << 3)];
7272 fil3[(column-3)*3+1] = voodoo->thefilterg [(((src[column-3] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
7273 fil3[(column-3)*3+2] = voodoo->thefilter [(((src[column-3] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
7274
7275 fil3[(column-2)*3] = voodoo->thefilterb [((src[column-2] & 31) << 3)] [((src[column] & 31) << 3)];
7276 fil3[(column-2)*3+1] = voodoo->thefilterg [(((src[column-2] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
7277 fil3[(column-2)*3+2] = voodoo->thefilter [(((src[column-2] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
7278
7279 fil3[(column-1)*3] = voodoo->thefilterb [((src[column-1] & 31) << 3)] [((src[column] & 31) << 3)];
7280 fil3[(column-1)*3+1] = voodoo->thefilterg [(((src[column-1] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)];
7281 fil3[(column-1)*3+2] = voodoo->thefilter [(((src[column-1] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)];
7282
7283 fil[(column-2)*3] = voodoo->thefilterb [fil3[(column-2)*3]][((src[column] & 31) << 3)];
7284 fil[(column-2)*3+1] = voodoo->thefilterg [fil3[(column-2)*3+1]][(((src[column] >> 5) & 63) << 2)];
7285 fil[(column-2)*3+2] = voodoo->thefilter [fil3[(column-2)*3+2]][(((src[column] >> 11) & 31) << 3)];
7286
7287 fil[(column-1)*3] = voodoo->thefilterb [fil3[(column-1)*3]][((src[column] & 31) << 3)];
7288 fil[(column-1)*3+1] = voodoo->thefilterg [fil3[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)];
7289 fil[(column-1)*3+2] = voodoo->thefilter [fil3[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)];
7290
7291 fil3[(column-1)*3] = voodoo->thefilterb [fil[(column-1)*3]][((src[column] & 31) << 3)];
7292 fil3[(column-1)*3+1] = voodoo->thefilterg [fil[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)];
7293 fil3[(column-1)*3+2] = voodoo->thefilter [fil[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)];
7294 }
7295
voodoo_callback(void * p)7296 void voodoo_callback(void *p)
7297 {
7298 voodoo_t *voodoo = (voodoo_t *)p;
7299
7300 if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS)
7301 {
7302 if (voodoo->line < voodoo->v_disp)
7303 {
7304 voodoo_t *draw_voodoo;
7305 int draw_line;
7306
7307 if (SLI_ENABLED)
7308 {
7309 if (voodoo == voodoo->set->voodoos[1])
7310 goto skip_draw;
7311
7312 if (((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) ? 1 : 0) == (voodoo->line & 1))
7313 draw_voodoo = voodoo;
7314 else
7315 draw_voodoo = voodoo->set->voodoos[1];
7316 draw_line = voodoo->line >> 1;
7317 }
7318 else
7319 {
7320 if (!(voodoo->fbiInit0 & 1))
7321 goto skip_draw;
7322 draw_voodoo = voodoo;
7323 draw_line = voodoo->line;
7324 }
7325
7326 if (draw_voodoo->dirty_line[draw_line])
7327 {
7328 uint32_t *p = &((uint32_t *)buffer32->line[voodoo->line])[32];
7329 uint16_t *src = (uint16_t *)&draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line*draw_voodoo->row_width];
7330 int x;
7331
7332 draw_voodoo->dirty_line[draw_line] = 0;
7333
7334 if (voodoo->line < voodoo->dirty_line_low)
7335 {
7336 voodoo->dirty_line_low = voodoo->line;
7337 video_wait_for_buffer();
7338 }
7339 if (voodoo->line > voodoo->dirty_line_high)
7340 voodoo->dirty_line_high = voodoo->line;
7341
7342 if (voodoo->scrfilter && voodoo->scrfilterEnabled)
7343 {
7344 uint8_t fil[(voodoo->h_disp) * 3]; /* interleaved 24-bit RGB */
7345
7346 if (voodoo->type == VOODOO_2)
7347 voodoo_filterline_v2(voodoo, fil, voodoo->h_disp, src, voodoo->line);
7348 else
7349 voodoo_filterline_v1(voodoo, fil, voodoo->h_disp, src, voodoo->line);
7350
7351 for (x = 0; x < voodoo->h_disp; x++)
7352 {
7353 p[x] = (voodoo->clutData256[fil[x*3]].b << 0 | voodoo->clutData256[fil[x*3+1]].g << 8 | voodoo->clutData256[fil[x*3+2]].r << 16);
7354 }
7355 }
7356 else
7357 {
7358 for (x = 0; x < voodoo->h_disp; x++)
7359 {
7360 p[x] = draw_voodoo->video_16to32[src[x]];
7361 }
7362 }
7363 }
7364 }
7365 }
7366 skip_draw:
7367 if (voodoo->line == voodoo->v_disp)
7368 {
7369 // pclog("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending);
7370 voodoo->retrace_count++;
7371 if (SLI_ENABLED && (voodoo->fbiInit2 & FBIINIT2_SWAP_ALGORITHM_MASK) == FBIINIT2_SWAP_ALGORITHM_SLI_SYNC)
7372 {
7373 if (voodoo == voodoo->set->voodoos[0])
7374 {
7375 voodoo_t *voodoo_1 = voodoo->set->voodoos[1];
7376
7377 /*Only swap if both Voodoos are waiting for buffer swap*/
7378 if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval) &&
7379 voodoo_1->swap_pending && (voodoo_1->retrace_count > voodoo_1->swap_interval))
7380 {
7381 memset(voodoo->dirty_line, 1, 1024);
7382 voodoo->retrace_count = 0;
7383 voodoo->front_offset = voodoo->swap_offset;
7384 if (voodoo->swap_count > 0)
7385 voodoo->swap_count--;
7386 voodoo->swap_pending = 0;
7387
7388 memset(voodoo_1->dirty_line, 1, 1024);
7389 voodoo_1->retrace_count = 0;
7390 voodoo_1->front_offset = voodoo_1->swap_offset;
7391 if (voodoo_1->swap_count > 0)
7392 voodoo_1->swap_count--;
7393 voodoo_1->swap_pending = 0;
7394
7395 thread_set_event(voodoo->wake_fifo_thread);
7396 thread_set_event(voodoo_1->wake_fifo_thread);
7397
7398 voodoo->frame_count++;
7399 voodoo_1->frame_count++;
7400 }
7401 }
7402 }
7403 else
7404 {
7405 if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval))
7406 {
7407 memset(voodoo->dirty_line, 1, 1024);
7408 voodoo->retrace_count = 0;
7409 voodoo->front_offset = voodoo->swap_offset;
7410 if (voodoo->swap_count > 0)
7411 voodoo->swap_count--;
7412 voodoo->swap_pending = 0;
7413 thread_set_event(voodoo->wake_fifo_thread);
7414 voodoo->frame_count++;
7415 }
7416 }
7417 voodoo->v_retrace = 1;
7418 }
7419 voodoo->line++;
7420
7421 if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS)
7422 {
7423 if (voodoo->line == voodoo->v_disp)
7424 {
7425 if (voodoo->dirty_line_high > voodoo->dirty_line_low)
7426 svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga);
7427 if (voodoo->clutData_dirty)
7428 {
7429 voodoo->clutData_dirty = 0;
7430 voodoo_calc_clutData(voodoo);
7431 }
7432 voodoo->dirty_line_high = -1;
7433 voodoo->dirty_line_low = 2000;
7434 }
7435 }
7436
7437 if (voodoo->line >= voodoo->v_total)
7438 {
7439 voodoo->line = 0;
7440 voodoo->v_retrace = 0;
7441 }
7442 if (voodoo->line_time)
7443 voodoo->timer_count += voodoo->line_time;
7444 else
7445 voodoo->timer_count += TIMER_USEC * 32;
7446 }
7447
voodoo_add_status_info(char * s,int max_len,void * p)7448 static void voodoo_add_status_info(char *s, int max_len, void *p)
7449 {
7450 voodoo_set_t *voodoo_set = (voodoo_set_t *)p;
7451 voodoo_t *voodoo = voodoo_set->voodoos[0];
7452 voodoo_t *voodoo_slave = voodoo_set->voodoos[1];
7453 char temps[512], temps2[256];
7454 int pixel_count_current[2];
7455 int pixel_count_total;
7456 int texel_count_current[2];
7457 int texel_count_total;
7458 int render_time[2];
7459 uint64_t new_time = timer_read();
7460 uint64_t status_diff = new_time - status_time;
7461 status_time = new_time;
7462
7463 if (!status_diff)
7464 status_diff = 1;
7465
7466 svga_add_status_info(s, max_len, &voodoo->svga);
7467
7468 pixel_count_current[0] = voodoo->pixel_count[0];
7469 pixel_count_current[1] = voodoo->pixel_count[1];
7470 texel_count_current[0] = voodoo->texel_count[0];
7471 texel_count_current[1] = voodoo->texel_count[1];
7472 render_time[0] = voodoo->render_time[0];
7473 render_time[1] = voodoo->render_time[1];
7474 if (voodoo_set->nr_cards == 2)
7475 {
7476 pixel_count_current[0] += voodoo_slave->pixel_count[0];
7477 pixel_count_current[1] += voodoo_slave->pixel_count[1];
7478 texel_count_current[0] += voodoo_slave->texel_count[0];
7479 texel_count_current[1] += voodoo_slave->texel_count[1];
7480 render_time[0] = (render_time[0] + voodoo_slave->render_time[0]) / 2;
7481 render_time[1] = (render_time[1] + voodoo_slave->render_time[1]) / 2;
7482 }
7483 pixel_count_total = (pixel_count_current[0] + pixel_count_current[1]) - (voodoo->pixel_count_old[0] + voodoo->pixel_count_old[1]);
7484 texel_count_total = (texel_count_current[0] + texel_count_current[1]) - (voodoo->texel_count_old[0] + voodoo->texel_count_old[1]);
7485 sprintf(temps, "%f Mpixels/sec (%f)\n%f Mtexels/sec (%f)\n%f ktris/sec\n%f%% CPU (%f%% real)\n%d frames/sec (%i)\n%f%% CPU (%f%% real)\n"/*%d reads/sec\n%d write/sec\n%d tex/sec\n*/,
7486 (double)pixel_count_total/1000000.0,
7487 ((double)pixel_count_total/1000000.0) / ((double)render_time[0] / status_diff),
7488 (double)texel_count_total/1000000.0,
7489 ((double)texel_count_total/1000000.0) / ((double)render_time[0] / status_diff),
7490 (double)voodoo->tri_count/1000.0, ((double)voodoo->time * 100.0) / timer_freq, ((double)voodoo->time * 100.0) / status_diff, voodoo->frame_count, voodoo_recomp,
7491 ((double)voodoo->render_time[0] * 100.0) / timer_freq, ((double)voodoo->render_time[0] * 100.0) / status_diff);
7492 if (voodoo->render_threads == 2)
7493 {
7494 sprintf(temps2, "%f%% CPU (%f%% real)\n",
7495 ((double)voodoo->render_time[1] * 100.0) / timer_freq, ((double)voodoo->render_time[1] * 100.0) / status_diff);
7496 strncat(temps, temps2, sizeof(temps)-1);
7497 }
7498 if (voodoo_set->nr_cards == 2)
7499 {
7500 sprintf(temps2, "%f%% CPU (%f%% real)\n",
7501 ((double)voodoo_slave->render_time[0] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[0] * 100.0) / status_diff);
7502 strncat(temps, temps2, sizeof(temps)-1);
7503
7504 if (voodoo_slave->render_threads == 2)
7505 {
7506 sprintf(temps2, "%f%% CPU (%f%% real)\n",
7507 ((double)voodoo_slave->render_time[1] * 100.0) / timer_freq, ((double)voodoo_slave->render_time[1] * 100.0) / status_diff);
7508 strncat(temps, temps2, sizeof(temps)-1);
7509 }
7510 }
7511 strncat(s, temps, max_len);
7512
7513 voodoo->pixel_count_old[0] = pixel_count_current[0];
7514 voodoo->pixel_count_old[1] = pixel_count_current[1];
7515 voodoo->texel_count_old[0] = texel_count_current[0];
7516 voodoo->texel_count_old[1] = texel_count_current[1];
7517 voodoo->tri_count = voodoo->frame_count = 0;
7518 voodoo->rd_count = voodoo->wr_count = voodoo->tex_count = 0;
7519 voodoo->time = 0;
7520 voodoo->render_time[0] = voodoo->render_time[1] = 0;
7521 if (voodoo_set->nr_cards == 2)
7522 {
7523 voodoo_slave->pixel_count_old[0] = pixel_count_current[0];
7524 voodoo_slave->pixel_count_old[1] = pixel_count_current[1];
7525 voodoo_slave->texel_count_old[0] = texel_count_current[0];
7526 voodoo_slave->texel_count_old[1] = texel_count_current[1];
7527 voodoo_slave->tri_count = voodoo_slave->frame_count = 0;
7528 voodoo_slave->rd_count = voodoo_slave->wr_count = voodoo_slave->tex_count = 0;
7529 voodoo_slave->time = 0;
7530 voodoo_slave->render_time[0] = voodoo_slave->render_time[1] = 0;
7531 }
7532 voodoo_recomp = 0;
7533 }
7534
voodoo_speed_changed(void * p)7535 static void voodoo_speed_changed(void *p)
7536 {
7537 voodoo_set_t *voodoo_set = (voodoo_set_t *)p;
7538
7539 voodoo_pixelclock_update(voodoo_set->voodoos[0]);
7540 voodoo_set->voodoos[0]->read_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit4 & 1) ? 2 : 1);
7541 voodoo_set->voodoos[0]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 1 : 0);
7542 voodoo_set->voodoos[0]->burst_time = pci_burst_time * ((voodoo_set->voodoos[0]->fbiInit1 & 2) ? 2 : 1);
7543 if (voodoo_set->nr_cards == 2)
7544 {
7545 voodoo_pixelclock_update(voodoo_set->voodoos[1]);
7546 voodoo_set->voodoos[1]->read_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit4 & 1) ? 2 : 1);
7547 voodoo_set->voodoos[1]->write_time = pci_nonburst_time + pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 1 : 0);
7548 voodoo_set->voodoos[1]->burst_time = pci_burst_time * ((voodoo_set->voodoos[1]->fbiInit1 & 2) ? 2 : 1);
7549 }
7550 // pclog("Voodoo read_time=%i write_time=%i burst_time=%i %08x %08x\n", voodoo->read_time, voodoo->write_time, voodoo->burst_time, voodoo->fbiInit1, voodoo->fbiInit4);
7551 }
7552
voodoo_card_init()7553 void *voodoo_card_init()
7554 {
7555 int c;
7556 voodoo_t *voodoo = malloc(sizeof(voodoo_t));
7557 memset(voodoo, 0, sizeof(voodoo_t));
7558
7559 voodoo->bilinear_enabled = device_get_config_int("bilinear");
7560 voodoo->scrfilter = device_get_config_int("dacfilter");
7561 voodoo->texture_size = device_get_config_int("texture_memory");
7562 voodoo->texture_mask = (voodoo->texture_size << 20) - 1;
7563 voodoo->fb_size = device_get_config_int("framebuffer_memory");
7564 voodoo->fb_mask = (voodoo->fb_size << 20) - 1;
7565 voodoo->render_threads = device_get_config_int("render_threads");
7566 voodoo->odd_even_mask = voodoo->render_threads - 1;
7567 #ifndef NO_CODEGEN
7568 voodoo->use_recompiler = device_get_config_int("recompiler");
7569 #endif
7570 voodoo->type = device_get_config_int("type");
7571 switch (voodoo->type)
7572 {
7573 case VOODOO_1:
7574 voodoo->dual_tmus = 0;
7575 break;
7576 case VOODOO_SB50:
7577 voodoo->dual_tmus = 1;
7578 break;
7579 case VOODOO_2:
7580 voodoo->dual_tmus = 1;
7581 break;
7582 }
7583
7584 if (voodoo->type == VOODOO_2) /*generate filter lookup tables*/
7585 voodoo_generate_filter_v2(voodoo);
7586 else
7587 voodoo_generate_filter_v1(voodoo);
7588
7589 pci_add(voodoo_pci_read, voodoo_pci_write, voodoo);
7590
7591 mem_mapping_add(&voodoo->mapping, 0, 0, NULL, voodoo_readw, voodoo_readl, NULL, voodoo_writew, voodoo_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo);
7592
7593 voodoo->fb_mem = malloc(4 * 1024 * 1024);
7594 voodoo->tex_mem[0] = malloc(voodoo->texture_size * 1024 * 1024);
7595 if (voodoo->dual_tmus)
7596 voodoo->tex_mem[1] = malloc(voodoo->texture_size * 1024 * 1024);
7597 voodoo->tex_mem_w[0] = (uint16_t *)voodoo->tex_mem[0];
7598 voodoo->tex_mem_w[1] = (uint16_t *)voodoo->tex_mem[1];
7599
7600 for (c = 0; c < TEX_CACHE_MAX; c++)
7601 {
7602 voodoo->texture_cache[0][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4);
7603 voodoo->texture_cache[0][c].base = -1; /*invalid*/
7604 voodoo->texture_cache[0][c].refcount = 0;
7605 if (voodoo->dual_tmus)
7606 {
7607 voodoo->texture_cache[1][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4);
7608 voodoo->texture_cache[1][c].base = -1; /*invalid*/
7609 voodoo->texture_cache[1][c].refcount = 0;
7610 }
7611 }
7612
7613 timer_add(voodoo_callback, &voodoo->timer_count, TIMER_ALWAYS_ENABLED, voodoo);
7614
7615 voodoo->svga = svga_get_pri();
7616 voodoo->fbiInit0 = 0;
7617
7618 voodoo->wake_fifo_thread = thread_create_event();
7619 voodoo->wake_render_thread[0] = thread_create_event();
7620 voodoo->wake_render_thread[1] = thread_create_event();
7621 voodoo->wake_main_thread = thread_create_event();
7622 voodoo->fifo_not_full_event = thread_create_event();
7623 voodoo->render_not_full_event[0] = thread_create_event();
7624 voodoo->render_not_full_event[1] = thread_create_event();
7625 voodoo->fifo_thread = thread_create(fifo_thread, voodoo);
7626 voodoo->render_thread[0] = thread_create(render_thread_1, voodoo);
7627 if (voodoo->render_threads == 2)
7628 voodoo->render_thread[1] = thread_create(render_thread_2, voodoo);
7629
7630 timer_add(voodoo_wake_timer, &voodoo->wake_timer, &voodoo->wake_timer, (void *)voodoo);
7631
7632 for (c = 0; c < 0x100; c++)
7633 {
7634 rgb332[c].r = c & 0xe0;
7635 rgb332[c].g = (c << 3) & 0xe0;
7636 rgb332[c].b = (c << 6) & 0xc0;
7637 rgb332[c].r = rgb332[c].r | (rgb332[c].r >> 3) | (rgb332[c].r >> 6);
7638 rgb332[c].g = rgb332[c].g | (rgb332[c].g >> 3) | (rgb332[c].g >> 6);
7639 rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 2);
7640 rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 4);
7641 rgb332[c].a = 0xff;
7642
7643 ai44[c].a = (c & 0xf0) | ((c & 0xf0) >> 4);
7644 ai44[c].r = (c & 0x0f) | ((c & 0x0f) << 4);
7645 ai44[c].g = ai44[c].b = ai44[c].r;
7646 }
7647
7648 for (c = 0; c < 0x10000; c++)
7649 {
7650 rgb565[c].r = (c >> 8) & 0xf8;
7651 rgb565[c].g = (c >> 3) & 0xfc;
7652 rgb565[c].b = (c << 3) & 0xf8;
7653 rgb565[c].r |= (rgb565[c].r >> 5);
7654 rgb565[c].g |= (rgb565[c].g >> 6);
7655 rgb565[c].b |= (rgb565[c].b >> 5);
7656 rgb565[c].a = 0xff;
7657
7658 argb1555[c].r = (c >> 7) & 0xf8;
7659 argb1555[c].g = (c >> 2) & 0xf8;
7660 argb1555[c].b = (c << 3) & 0xf8;
7661 argb1555[c].r |= (argb1555[c].r >> 5);
7662 argb1555[c].g |= (argb1555[c].g >> 5);
7663 argb1555[c].b |= (argb1555[c].b >> 5);
7664 argb1555[c].a = (c & 0x8000) ? 0xff : 0;
7665
7666 argb4444[c].a = (c >> 8) & 0xf0;
7667 argb4444[c].r = (c >> 4) & 0xf0;
7668 argb4444[c].g = c & 0xf0;
7669 argb4444[c].b = (c << 4) & 0xf0;
7670 argb4444[c].a |= (argb4444[c].a >> 4);
7671 argb4444[c].r |= (argb4444[c].r >> 4);
7672 argb4444[c].g |= (argb4444[c].g >> 4);
7673 argb4444[c].b |= (argb4444[c].b >> 4);
7674
7675 ai88[c].a = (c >> 8);
7676 ai88[c].r = c & 0xff;
7677 ai88[c].g = c & 0xff;
7678 ai88[c].b = c & 0xff;
7679 }
7680 #ifndef NO_CODEGEN
7681 voodoo_codegen_init(voodoo);
7682 #endif
7683
7684 voodoo->disp_buffer = 0;
7685 voodoo->draw_buffer = 1;
7686
7687 return voodoo;
7688 }
7689
voodoo_init()7690 void *voodoo_init()
7691 {
7692 voodoo_set_t *voodoo_set = malloc(sizeof(voodoo_set_t));
7693 uint32_t tmuConfig = 1;
7694 int type;
7695 memset(voodoo_set, 0, sizeof(voodoo_set_t));
7696
7697 type = device_get_config_int("type");
7698
7699 voodoo_set->nr_cards = device_get_config_int("sli") ? 2 : 1;
7700 voodoo_set->voodoos[0] = voodoo_card_init();
7701 voodoo_set->voodoos[0]->set = voodoo_set;
7702 if (voodoo_set->nr_cards == 2)
7703 {
7704 voodoo_set->voodoos[1] = voodoo_card_init();
7705
7706 voodoo_set->voodoos[1]->set = voodoo_set;
7707
7708 if (type == VOODOO_2)
7709 {
7710 voodoo_set->voodoos[0]->fbiInit5 |= FBIINIT5_MULTI_CVG;
7711 voodoo_set->voodoos[1]->fbiInit5 |= FBIINIT5_MULTI_CVG;
7712 }
7713 else
7714 {
7715 voodoo_set->voodoos[0]->fbiInit1 |= FBIINIT1_MULTI_SST;
7716 voodoo_set->voodoos[1]->fbiInit1 |= FBIINIT1_MULTI_SST;
7717 }
7718 }
7719
7720 switch (type)
7721 {
7722 case VOODOO_1:
7723 if (voodoo_set->nr_cards == 2)
7724 tmuConfig = 1 | (3 << 3);
7725 else
7726 tmuConfig = 1;
7727 break;
7728 case VOODOO_SB50:
7729 if (voodoo_set->nr_cards == 2)
7730 tmuConfig = 1 | (3 << 3) | (3 << 6) | (2 << 9);
7731 else
7732 tmuConfig = 1 | (3 << 6);
7733 break;
7734 case VOODOO_2:
7735 tmuConfig = 1 | (3 << 6);
7736 break;
7737 }
7738
7739 voodoo_set->voodoos[0]->tmuConfig = tmuConfig;
7740 if (voodoo_set->nr_cards == 2)
7741 voodoo_set->voodoos[1]->tmuConfig = tmuConfig;
7742
7743 mem_mapping_add(&voodoo_set->snoop_mapping, 0, 0, NULL, voodoo_snoop_readw, voodoo_snoop_readl, NULL, voodoo_snoop_writew, voodoo_snoop_writel, NULL, MEM_MAPPING_EXTERNAL, voodoo_set);
7744
7745 return voodoo_set;
7746 }
7747
voodoo_card_close(voodoo_t * voodoo)7748 void voodoo_card_close(voodoo_t *voodoo)
7749 {
7750 #ifndef RELEASE_BUILD
7751 FILE *f;
7752 #endif
7753 int c;
7754
7755 #ifndef RELEASE_BUILD
7756 f = romfopen("texram.dmp", "wb");
7757 fwrite(voodoo->tex_mem[0], voodoo->texture_size*1024*1024, 1, f);
7758 fclose(f);
7759 if (voodoo->dual_tmus)
7760 {
7761 f = romfopen("texram2.dmp", "wb");
7762 fwrite(voodoo->tex_mem[1], voodoo->texture_size*1024*1024, 1, f);
7763 fclose(f);
7764 }
7765 #endif
7766
7767 thread_kill(voodoo->fifo_thread);
7768 thread_kill(voodoo->render_thread[0]);
7769 if (voodoo->render_threads == 2)
7770 thread_kill(voodoo->render_thread[1]);
7771 thread_destroy_event(voodoo->fifo_not_full_event);
7772 thread_destroy_event(voodoo->wake_main_thread);
7773 thread_destroy_event(voodoo->wake_fifo_thread);
7774 thread_destroy_event(voodoo->wake_render_thread[0]);
7775 thread_destroy_event(voodoo->wake_render_thread[1]);
7776 thread_destroy_event(voodoo->render_not_full_event[0]);
7777 thread_destroy_event(voodoo->render_not_full_event[1]);
7778
7779 for (c = 0; c < TEX_CACHE_MAX; c++)
7780 {
7781 if (voodoo->dual_tmus)
7782 free(voodoo->texture_cache[1][c].data);
7783 free(voodoo->texture_cache[0][c].data);
7784 }
7785 #ifndef NO_CODEGEN
7786 voodoo_codegen_close(voodoo);
7787 #endif
7788 free(voodoo->fb_mem);
7789 if (voodoo->dual_tmus)
7790 free(voodoo->tex_mem[1]);
7791 free(voodoo->tex_mem[0]);
7792 free(voodoo);
7793 }
7794
voodoo_close(void * p)7795 void voodoo_close(void *p)
7796 {
7797 voodoo_set_t *voodoo_set = (voodoo_set_t *)p;
7798
7799 if (voodoo_set->nr_cards == 2)
7800 voodoo_card_close(voodoo_set->voodoos[1]);
7801 voodoo_card_close(voodoo_set->voodoos[0]);
7802
7803 free(voodoo_set);
7804 }
7805
7806 static device_config_t voodoo_config[] =
7807 {
7808 {
7809 .name = "type",
7810 .description = "Voodoo type",
7811 .type = CONFIG_SELECTION,
7812 .selection =
7813 {
7814 {
7815 .description = "Voodoo Graphics",
7816 .value = VOODOO_1
7817 },
7818 {
7819 .description = "Obsidian SB50 + Amethyst (2 TMUs)",
7820 .value = VOODOO_SB50
7821 },
7822 {
7823 .description = "Voodoo 2",
7824 .value = VOODOO_2
7825 },
7826 {
7827 .description = ""
7828 }
7829 },
7830 .default_int = 0
7831 },
7832 {
7833 .name = "framebuffer_memory",
7834 .description = "Framebuffer memory size",
7835 .type = CONFIG_SELECTION,
7836 .selection =
7837 {
7838 {
7839 .description = "2 MB",
7840 .value = 2
7841 },
7842 {
7843 .description = "4 MB",
7844 .value = 4
7845 },
7846 {
7847 .description = ""
7848 }
7849 },
7850 .default_int = 2
7851 },
7852 {
7853 .name = "texture_memory",
7854 .description = "Texture memory size",
7855 .type = CONFIG_SELECTION,
7856 .selection =
7857 {
7858 {
7859 .description = "2 MB",
7860 .value = 2
7861 },
7862 {
7863 .description = "4 MB",
7864 .value = 4
7865 },
7866 {
7867 .description = ""
7868 }
7869 },
7870 .default_int = 2
7871 },
7872 {
7873 .name = "bilinear",
7874 .description = "Bilinear filtering",
7875 .type = CONFIG_BINARY,
7876 .default_int = 1
7877 },
7878 {
7879 .name = "dacfilter",
7880 .description = "Screen Filter",
7881 .type = CONFIG_BINARY,
7882 .default_int = 0
7883 },
7884 {
7885 .name = "render_threads",
7886 .description = "Render threads",
7887 .type = CONFIG_SELECTION,
7888 .selection =
7889 {
7890 {
7891 .description = "1",
7892 .value = 1
7893 },
7894 {
7895 .description = "2",
7896 .value = 2
7897 },
7898 {
7899 .description = ""
7900 }
7901 },
7902 .default_int = 2
7903 },
7904 {
7905 .name = "sli",
7906 .description = "SLI",
7907 .type = CONFIG_BINARY,
7908 .default_int = 0
7909 },
7910 #ifndef NO_CODEGEN
7911 {
7912 .name = "recompiler",
7913 .description = "Recompiler",
7914 .type = CONFIG_BINARY,
7915 .default_int = 1
7916 },
7917 #endif
7918 {
7919 .type = -1
7920 }
7921 };
7922
7923 device_t voodoo_device =
7924 {
7925 "3DFX Voodoo Graphics",
7926 DEVICE_PCI,
7927 voodoo_init,
7928 voodoo_close,
7929 NULL,
7930 voodoo_speed_changed,
7931 NULL,
7932 voodoo_add_status_info,
7933 voodoo_config
7934 };
7935