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