diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index ad5f36f..a59347f 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -10,1079 +10,30 @@ #include "video.h" #include "vid_svga.h" #include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_blitter.h" +#include "vid_voodoo_display.h" #include "vid_voodoo_dither.h" +#include "vid_voodoo_fb.h" +#include "vid_voodoo_fifo.h" +#include "vid_voodoo_reg.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" +#include "vid_voodoo_texture.h" -#ifdef MIN -#undef MIN -#endif -#ifdef CLAMP -#undef CLAMP -#endif -#define MIN(a, b) ((a) < (b) ? (a) : (b)) +rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000]; -#define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x))) -#define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x))) -#define LOD_MAX 8 - -#define TEX_DIRTY_SHIFT 10 - -#define TEX_CACHE_MAX 64 - -enum -{ - VOODOO_1 = 0, - VOODOO_SB50 = 1, - VOODOO_2 = 2 -}; - -static uint32_t texture_offset[LOD_MAX+3] = -{ - 0, - 256*256, - 256*256 + 128*128, - 256*256 + 128*128 + 64*64, - 256*256 + 128*128 + 64*64 + 32*32, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1, - 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1 + 1 -}; - -static int tris = 0; +int tris = 0; static uint64_t status_time = 0; -typedef union int_float -{ - uint32_t i; - float f; -} int_float; -typedef struct rgb_t -{ - uint8_t b, g, r; - uint8_t pad; -} rgb_t; -typedef struct rgba8_t -{ - uint8_t b, g, r, a; -} rgba8_t; - -typedef union rgba_u -{ - struct - { - uint8_t b, g, r, a; - } rgba; - uint32_t u; -} rgba_u; - -#define FIFO_SIZE 65536 -#define FIFO_MASK (FIFO_SIZE - 1) -#define FIFO_ENTRY_SIZE (1 << 31) - -#define FIFO_ENTRIES (voodoo->fifo_write_idx - voodoo->fifo_read_idx) -#define FIFO_FULL ((voodoo->fifo_write_idx - voodoo->fifo_read_idx) >= FIFO_SIZE-4) -#define FIFO_EMPTY (voodoo->fifo_read_idx == voodoo->fifo_write_idx) - -#define FIFO_TYPE 0xff000000 -#define FIFO_ADDR 0x00ffffff - -enum -{ - FIFO_INVALID = (0x00 << 24), - FIFO_WRITEL_REG = (0x01 << 24), - FIFO_WRITEW_FB = (0x02 << 24), - FIFO_WRITEL_FB = (0x03 << 24), - FIFO_WRITEL_TEX = (0x04 << 24) -}; - -#define PARAM_SIZE 1024 -#define PARAM_MASK (PARAM_SIZE - 1) -#define PARAM_ENTRY_SIZE (1 << 31) - -#define PARAM_ENTRIES_1 (voodoo->params_write_idx - voodoo->params_read_idx[0]) -#define PARAM_ENTRIES_2 (voodoo->params_write_idx - voodoo->params_read_idx[1]) -#define PARAM_FULL_1 ((voodoo->params_write_idx - voodoo->params_read_idx[0]) >= PARAM_SIZE) -#define PARAM_FULL_2 ((voodoo->params_write_idx - voodoo->params_read_idx[1]) >= PARAM_SIZE) -#define PARAM_EMPTY_1 (voodoo->params_read_idx[0] == voodoo->params_write_idx) -#define PARAM_EMPTY_2 (voodoo->params_read_idx[1] == voodoo->params_write_idx) - -typedef struct -{ - uint32_t addr_type; - uint32_t val; -} fifo_entry_t; - -static rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000]; - -typedef struct voodoo_params_t -{ - int command; - - int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy; - - uint32_t startR, startG, startB, startZ, startA; - - int32_t dBdX, dGdX, dRdX, dAdX, dZdX; - - int32_t dBdY, dGdY, dRdY, dAdY, dZdY; - - int64_t startW, dWdX, dWdY; - - struct - { - int64_t startS, startT, startW, p1; - int64_t dSdX, dTdX, dWdX, p2; - int64_t dSdY, dTdY, dWdY, p3; - } tmu[2]; - - uint32_t color0, color1; - - uint32_t fbzMode; - uint32_t fbzColorPath; - - uint32_t fogMode; - rgb_t fogColor; - struct - { - uint8_t fog, dfog; - } fogTable[64]; - - uint32_t alphaMode; - - uint32_t zaColor; - - int chromaKey_r, chromaKey_g, chromaKey_b; - uint32_t chromaKey; - - uint32_t textureMode[2]; - uint32_t tLOD[2]; - - uint32_t texBaseAddr[2], texBaseAddr1[2], texBaseAddr2[2], texBaseAddr38[2]; - - uint32_t tex_base[2][LOD_MAX+2]; - uint32_t tex_end[2][LOD_MAX+2]; - int tex_width[2]; - int tex_w_mask[2][LOD_MAX+2]; - int tex_w_nmask[2][LOD_MAX+2]; - int tex_h_mask[2][LOD_MAX+2]; - int tex_shift[2][LOD_MAX+2]; - int tex_lod[2][LOD_MAX+2]; - int tex_entry[2]; - int detail_max[2], detail_bias[2], detail_scale[2]; - - uint32_t draw_offset, aux_offset; - - int tformat[2]; - - int clipLeft, clipRight, clipLowY, clipHighY; - - int sign; - - uint32_t front_offset; - - uint32_t swapbufferCMD; - - uint32_t stipple; -} voodoo_params_t; - -typedef struct texture_t -{ - uint32_t base; - uint32_t tLOD; - volatile int refcount, refcount_r[2]; - int is16; - uint32_t palette_checksum; - uint32_t addr_start[4], addr_end[4]; - uint32_t *data; -} texture_t; - -typedef struct vert_t -{ - float sVx, sVy; - float sRed, sGreen, sBlue, sAlpha; - float sVz, sWb; - float sW0, sS0, sT0; - float sW1, sS1, sT1; -} vert_t; - -typedef struct voodoo_t -{ - mem_mapping_t mapping; - - int pci_enable; - - uint8_t dac_data[8]; - int dac_reg, dac_reg_ff; - uint8_t dac_readdata; - uint16_t dac_pll_regs[16]; - - float pixel_clock; - uint64_t line_time; - - voodoo_params_t params; - - uint32_t fbiInit0, fbiInit1, fbiInit2, fbiInit3, fbiInit4; - uint32_t fbiInit5, fbiInit6, fbiInit7; /*Voodoo 2*/ - - uint32_t initEnable; - - uint32_t lfbMode; - - uint32_t memBaseAddr; - - int_float fvertexAx, fvertexAy, fvertexBx, fvertexBy, fvertexCx, fvertexCy; - - uint32_t front_offset, back_offset; - - uint32_t fb_read_offset, fb_write_offset; - - int row_width; - int block_width; - - uint8_t *fb_mem, *tex_mem[2]; - uint16_t *tex_mem_w[2]; - - int rgb_sel; - - uint32_t trexInit1[2]; - - uint32_t tmuConfig; - - int swap_count; - - int disp_buffer, draw_buffer; - pc_timer_t timer; - - int line; - svga_t *svga; - - uint32_t backPorch; - uint32_t videoDimensions; - uint32_t hSync, vSync; - - int h_total, v_total, v_disp; - int h_disp; - int v_retrace; - - struct - { - uint32_t y[4], i[4], q[4]; - } nccTable[2][2]; - - rgba_u palette[2][256]; - - rgba_u ncc_lookup[2][2][256]; - int ncc_dirty[2]; - - thread_t *fifo_thread; - thread_t *render_thread[2]; - event_t *wake_fifo_thread; - event_t *wake_main_thread; - event_t *fifo_not_full_event; - event_t *render_not_full_event[2]; - event_t *wake_render_thread[2]; - - int voodoo_busy; - int render_voodoo_busy[2]; - - int render_threads; - int odd_even_mask; - - int pixel_count[2], texel_count[2], tri_count, frame_count; - int pixel_count_old[2], texel_count_old[2]; - int wr_count, rd_count, tex_count; - - int retrace_count; - int swap_interval; - uint32_t swap_offset; - int swap_pending; - - int bilinear_enabled; - - int fb_size; - uint32_t fb_mask; - - int texture_size; - uint32_t texture_mask; - - int dual_tmus; - int type; - - fifo_entry_t fifo[FIFO_SIZE]; - volatile int fifo_read_idx, fifo_write_idx; - volatile int cmd_read, cmd_written, cmd_written_fifo; - - voodoo_params_t params_buffer[PARAM_SIZE]; - volatile int params_read_idx[2], params_write_idx; - - uint32_t cmdfifo_base, cmdfifo_end; - int cmdfifo_rp; - volatile int cmdfifo_depth_rd, cmdfifo_depth_wr; - uint32_t cmdfifo_amin, cmdfifo_amax; - - uint32_t sSetupMode; - vert_t verts[4]; - int vertex_num; - int num_verticies; - - int flush; - - int scrfilter; - int scrfilterEnabled; - int scrfilterThreshold; - int scrfilterThresholdOld; - - uint32_t last_write_addr; - - uint32_t fbiPixelsIn; - uint32_t fbiChromaFail; - uint32_t fbiZFuncFail; - uint32_t fbiAFuncFail; - uint32_t fbiPixelsOut; - - uint32_t bltSrcBaseAddr; - uint32_t bltDstBaseAddr; - int bltSrcXYStride, bltDstXYStride; - uint32_t bltSrcChromaRange, bltDstChromaRange; - int bltSrcChromaMinR, bltSrcChromaMinG, bltSrcChromaMinB; - int bltSrcChromaMaxR, bltSrcChromaMaxG, bltSrcChromaMaxB; - int bltDstChromaMinR, bltDstChromaMinG, bltDstChromaMinB; - int bltDstChromaMaxR, bltDstChromaMaxG, bltDstChromaMaxB; - - int bltClipRight, bltClipLeft; - int bltClipHighY, bltClipLowY; - - int bltSrcX, bltSrcY; - int bltDstX, bltDstY; - int bltSizeX, bltSizeY; - int bltRop[4]; - uint16_t bltColorFg, bltColorBg; - - uint32_t bltCommand; - - struct - { - int dst_x, dst_y; - int cur_x; - int size_x, size_y; - int x_dir, y_dir; - int dst_stride; - } blt; - - rgb_t clutData[33]; - int clutData_dirty; - rgb_t clutData256[256]; - uint32_t video_16to32[0x10000]; - - uint8_t dirty_line[1024]; - int dirty_line_low, dirty_line_high; - - int fb_write_buffer, fb_draw_buffer; - int buffer_cutoff; - - int read_time, write_time, burst_time; - - pc_timer_t wake_timer; - - uint8_t thefilter[256][256]; // pixel filter, feeding from one or two - uint8_t thefilterg[256][256]; // for green - uint8_t thefilterb[256][256]; // for blue - - /* the voodoo adds purple lines for some reason */ - uint16_t purpleline[256][3]; - - texture_t texture_cache[2][TEX_CACHE_MAX]; - uint8_t texture_present[2][4096]; - int texture_last_removed; - - uint32_t palette_checksum[2]; - int palette_dirty[2]; - - uint64_t time; - int render_time[2]; - - int use_recompiler; - void *codegen_data; - - struct voodoo_set_t *set; -} voodoo_t; - -typedef struct voodoo_set_t -{ - voodoo_t *voodoos[2]; - - mem_mapping_t snoop_mapping; - - int nr_cards; -} voodoo_set_t; - -static inline void wait_for_render_thread_idle(voodoo_t *voodoo); - -enum -{ - SST_status = 0x000, - SST_intrCtrl = 0x004, - - SST_vertexAx = 0x008, - SST_vertexAy = 0x00c, - SST_vertexBx = 0x010, - SST_vertexBy = 0x014, - SST_vertexCx = 0x018, - SST_vertexCy = 0x01c, - - SST_startR = 0x0020, - SST_startG = 0x0024, - SST_startB = 0x0028, - SST_startZ = 0x002c, - SST_startA = 0x0030, - SST_startS = 0x0034, - SST_startT = 0x0038, - SST_startW = 0x003c, - - SST_dRdX = 0x0040, - SST_dGdX = 0x0044, - SST_dBdX = 0x0048, - SST_dZdX = 0x004c, - SST_dAdX = 0x0050, - SST_dSdX = 0x0054, - SST_dTdX = 0x0058, - SST_dWdX = 0x005c, - - SST_dRdY = 0x0060, - SST_dGdY = 0x0064, - SST_dBdY = 0x0068, - SST_dZdY = 0x006c, - SST_dAdY = 0x0070, - SST_dSdY = 0x0074, - SST_dTdY = 0x0078, - SST_dWdY = 0x007c, - - SST_triangleCMD = 0x0080, - - SST_fvertexAx = 0x088, - SST_fvertexAy = 0x08c, - SST_fvertexBx = 0x090, - SST_fvertexBy = 0x094, - SST_fvertexCx = 0x098, - SST_fvertexCy = 0x09c, - - SST_fstartR = 0x00a0, - SST_fstartG = 0x00a4, - SST_fstartB = 0x00a8, - SST_fstartZ = 0x00ac, - SST_fstartA = 0x00b0, - SST_fstartS = 0x00b4, - SST_fstartT = 0x00b8, - SST_fstartW = 0x00bc, - - SST_fdRdX = 0x00c0, - SST_fdGdX = 0x00c4, - SST_fdBdX = 0x00c8, - SST_fdZdX = 0x00cc, - SST_fdAdX = 0x00d0, - SST_fdSdX = 0x00d4, - SST_fdTdX = 0x00d8, - SST_fdWdX = 0x00dc, - - SST_fdRdY = 0x00e0, - SST_fdGdY = 0x00e4, - SST_fdBdY = 0x00e8, - SST_fdZdY = 0x00ec, - SST_fdAdY = 0x00f0, - SST_fdSdY = 0x00f4, - SST_fdTdY = 0x00f8, - SST_fdWdY = 0x00fc, - - SST_ftriangleCMD = 0x0100, - - SST_fbzColorPath = 0x104, - SST_fogMode = 0x108, - - SST_alphaMode = 0x10c, - SST_fbzMode = 0x110, - SST_lfbMode = 0x114, - - SST_clipLeftRight = 0x118, - SST_clipLowYHighY = 0x11c, - - SST_nopCMD = 0x120, - SST_fastfillCMD = 0x124, - SST_swapbufferCMD = 0x128, - - SST_fogColor = 0x12c, - SST_zaColor = 0x130, - SST_chromaKey = 0x134, - - SST_userIntrCMD = 0x13c, - SST_stipple = 0x140, - SST_color0 = 0x144, - SST_color1 = 0x148, - - SST_fbiPixelsIn = 0x14c, - SST_fbiChromaFail = 0x150, - SST_fbiZFuncFail = 0x154, - SST_fbiAFuncFail = 0x158, - SST_fbiPixelsOut = 0x15c, - - SST_fogTable00 = 0x160, - SST_fogTable01 = 0x164, - SST_fogTable02 = 0x168, - SST_fogTable03 = 0x16c, - SST_fogTable04 = 0x170, - SST_fogTable05 = 0x174, - SST_fogTable06 = 0x178, - SST_fogTable07 = 0x17c, - SST_fogTable08 = 0x180, - SST_fogTable09 = 0x184, - SST_fogTable0a = 0x188, - SST_fogTable0b = 0x18c, - SST_fogTable0c = 0x190, - SST_fogTable0d = 0x194, - SST_fogTable0e = 0x198, - SST_fogTable0f = 0x19c, - SST_fogTable10 = 0x1a0, - SST_fogTable11 = 0x1a4, - SST_fogTable12 = 0x1a8, - SST_fogTable13 = 0x1ac, - SST_fogTable14 = 0x1b0, - SST_fogTable15 = 0x1b4, - SST_fogTable16 = 0x1b8, - SST_fogTable17 = 0x1bc, - SST_fogTable18 = 0x1c0, - SST_fogTable19 = 0x1c4, - SST_fogTable1a = 0x1c8, - SST_fogTable1b = 0x1cc, - SST_fogTable1c = 0x1d0, - SST_fogTable1d = 0x1d4, - SST_fogTable1e = 0x1d8, - SST_fogTable1f = 0x1dc, - - SST_cmdFifoBaseAddr = 0x1e0, - SST_cmdFifoBump = 0x1e4, - SST_cmdFifoRdPtr = 0x1e8, - SST_cmdFifoAMin = 0x1ec, - SST_cmdFifoAMax = 0x1f0, - SST_cmdFifoDepth = 0x1f4, - SST_cmdFifoHoles = 0x1f8, - - SST_fbiInit4 = 0x200, - SST_vRetrace = 0x204, - SST_backPorch = 0x208, - SST_videoDimensions = 0x20c, - SST_fbiInit0 = 0x210, - SST_fbiInit1 = 0x214, - SST_fbiInit2 = 0x218, - SST_fbiInit3 = 0x21c, - SST_hSync = 0x220, - SST_vSync = 0x224, - SST_clutData = 0x228, - SST_dacData = 0x22c, - - SST_scrFilter = 0x230, - - SST_hvRetrace = 0x240, - SST_fbiInit5 = 0x244, - SST_fbiInit6 = 0x248, - SST_fbiInit7 = 0x24c, - - SST_sSetupMode = 0x260, - SST_sVx = 0x264, - SST_sVy = 0x268, - SST_sARGB = 0x26c, - SST_sRed = 0x270, - SST_sGreen = 0x274, - SST_sBlue = 0x278, - SST_sAlpha = 0x27c, - SST_sVz = 0x280, - SST_sWb = 0x284, - SST_sW0 = 0x288, - SST_sS0 = 0x28c, - SST_sT0 = 0x290, - SST_sW1 = 0x294, - SST_sS1 = 0x298, - SST_sT1 = 0x29c, - - SST_sDrawTriCMD = 0x2a0, - SST_sBeginTriCMD = 0x2a4, - - SST_bltSrcBaseAddr = 0x2c0, - SST_bltDstBaseAddr = 0x2c4, - SST_bltXYStrides = 0x2c8, - SST_bltSrcChromaRange = 0x2cc, - SST_bltDstChromaRange = 0x2d0, - SST_bltClipX = 0x2d4, - SST_bltClipY = 0x2d8, - - SST_bltSrcXY = 0x2e0, - SST_bltDstXY = 0x2e4, - SST_bltSize = 0x2e8, - SST_bltRop = 0x2ec, - SST_bltColor = 0x2f0, - - SST_bltCommand = 0x2f8, - SST_bltData = 0x2fc, - - SST_textureMode = 0x300, - SST_tLOD = 0x304, - SST_tDetail = 0x308, - SST_texBaseAddr = 0x30c, - SST_texBaseAddr1 = 0x310, - SST_texBaseAddr2 = 0x314, - SST_texBaseAddr38 = 0x318, - - SST_trexInit1 = 0x320, - - SST_nccTable0_Y0 = 0x324, - SST_nccTable0_Y1 = 0x328, - SST_nccTable0_Y2 = 0x32c, - SST_nccTable0_Y3 = 0x330, - SST_nccTable0_I0 = 0x334, - SST_nccTable0_I1 = 0x338, - SST_nccTable0_I2 = 0x33c, - SST_nccTable0_I3 = 0x340, - SST_nccTable0_Q0 = 0x344, - SST_nccTable0_Q1 = 0x348, - SST_nccTable0_Q2 = 0x34c, - SST_nccTable0_Q3 = 0x350, - - SST_nccTable1_Y0 = 0x354, - SST_nccTable1_Y1 = 0x358, - SST_nccTable1_Y2 = 0x35c, - SST_nccTable1_Y3 = 0x360, - SST_nccTable1_I0 = 0x364, - SST_nccTable1_I1 = 0x368, - SST_nccTable1_I2 = 0x36c, - SST_nccTable1_I3 = 0x370, - SST_nccTable1_Q0 = 0x374, - SST_nccTable1_Q1 = 0x378, - SST_nccTable1_Q2 = 0x37c, - SST_nccTable1_Q3 = 0x380, - - SST_remap_status = 0x000 | 0x400, - - SST_remap_vertexAx = 0x008 | 0x400, - SST_remap_vertexAy = 0x00c | 0x400, - SST_remap_vertexBx = 0x010 | 0x400, - SST_remap_vertexBy = 0x014 | 0x400, - SST_remap_vertexCx = 0x018 | 0x400, - SST_remap_vertexCy = 0x01c | 0x400, - - SST_remap_startR = 0x0020 | 0x400, - SST_remap_startG = 0x002c | 0x400, - SST_remap_startB = 0x0038 | 0x400, - SST_remap_startZ = 0x0044 | 0x400, - SST_remap_startA = 0x0050 | 0x400, - SST_remap_startS = 0x005c | 0x400, - SST_remap_startT = 0x0068 | 0x400, - SST_remap_startW = 0x0074 | 0x400, - - SST_remap_dRdX = 0x0024 | 0x400, - SST_remap_dGdX = 0x0030 | 0x400, - SST_remap_dBdX = 0x003c | 0x400, - SST_remap_dZdX = 0x0048 | 0x400, - SST_remap_dAdX = 0x0054 | 0x400, - SST_remap_dSdX = 0x0060 | 0x400, - SST_remap_dTdX = 0x006c | 0x400, - SST_remap_dWdX = 0x0078 | 0x400, - - SST_remap_dRdY = 0x0028 | 0x400, - SST_remap_dGdY = 0x0034 | 0x400, - SST_remap_dBdY = 0x0040 | 0x400, - SST_remap_dZdY = 0x004c | 0x400, - SST_remap_dAdY = 0x0058 | 0x400, - SST_remap_dSdY = 0x0064 | 0x400, - SST_remap_dTdY = 0x0070 | 0x400, - SST_remap_dWdY = 0x007c | 0x400, - - SST_remap_triangleCMD = 0x0080 | 0x400, - - SST_remap_fvertexAx = 0x088 | 0x400, - SST_remap_fvertexAy = 0x08c | 0x400, - SST_remap_fvertexBx = 0x090 | 0x400, - SST_remap_fvertexBy = 0x094 | 0x400, - SST_remap_fvertexCx = 0x098 | 0x400, - SST_remap_fvertexCy = 0x09c | 0x400, - - SST_remap_fstartR = 0x00a0 | 0x400, - SST_remap_fstartG = 0x00ac | 0x400, - SST_remap_fstartB = 0x00b8 | 0x400, - SST_remap_fstartZ = 0x00c4 | 0x400, - SST_remap_fstartA = 0x00d0 | 0x400, - SST_remap_fstartS = 0x00dc | 0x400, - SST_remap_fstartT = 0x00e8 | 0x400, - SST_remap_fstartW = 0x00f4 | 0x400, - - SST_remap_fdRdX = 0x00a4 | 0x400, - SST_remap_fdGdX = 0x00b0 | 0x400, - SST_remap_fdBdX = 0x00bc | 0x400, - SST_remap_fdZdX = 0x00c8 | 0x400, - SST_remap_fdAdX = 0x00d4 | 0x400, - SST_remap_fdSdX = 0x00e0 | 0x400, - SST_remap_fdTdX = 0x00ec | 0x400, - SST_remap_fdWdX = 0x00f8 | 0x400, - - SST_remap_fdRdY = 0x00a8 | 0x400, - SST_remap_fdGdY = 0x00b4 | 0x400, - SST_remap_fdBdY = 0x00c0 | 0x400, - SST_remap_fdZdY = 0x00cc | 0x400, - SST_remap_fdAdY = 0x00d8 | 0x400, - SST_remap_fdSdY = 0x00e4 | 0x400, - SST_remap_fdTdY = 0x00f0 | 0x400, - SST_remap_fdWdY = 0x00fc | 0x400, -}; - -enum -{ - LFB_WRITE_FRONT = 0x0000, - LFB_WRITE_BACK = 0x0010, - LFB_WRITE_MASK = 0x0030 -}; - -enum -{ - LFB_READ_FRONT = 0x0000, - LFB_READ_BACK = 0x0040, - LFB_READ_AUX = 0x0080, - LFB_READ_MASK = 0x00c0 -}; - -enum -{ - LFB_FORMAT_RGB565 = 0, - LFB_FORMAT_RGB555 = 1, - LFB_FORMAT_ARGB1555 = 2, - LFB_FORMAT_ARGB8888 = 5, - LFB_FORMAT_DEPTH = 15, - LFB_FORMAT_MASK = 15 -}; - -enum -{ - LFB_WRITE_COLOUR = 1, - LFB_WRITE_DEPTH = 2 -}; - -enum -{ - FBZ_CHROMAKEY = (1 << 1), - FBZ_W_BUFFER = (1 << 3), - FBZ_DEPTH_ENABLE = (1 << 4), - - FBZ_DITHER = (1 << 8), - FBZ_RGB_WMASK = (1 << 9), - FBZ_DEPTH_WMASK = (1 << 10), - FBZ_DITHER_2x2 = (1 << 11), - - FBZ_DRAW_FRONT = 0x0000, - FBZ_DRAW_BACK = 0x4000, - FBZ_DRAW_MASK = 0xc000, - - FBZ_DEPTH_BIAS = (1 << 16), - - FBZ_DEPTH_SOURCE = (1 << 20), - - FBZ_PARAM_ADJUST = (1 << 26) -}; - -enum -{ - TEX_RGB332 = 0x0, - TEX_Y4I2Q2 = 0x1, - TEX_A8 = 0x2, - TEX_I8 = 0x3, - TEX_AI8 = 0x4, - TEX_PAL8 = 0x5, - TEX_APAL8 = 0x6, - TEX_ARGB8332 = 0x8, - TEX_A8Y4I2Q2 = 0x9, - TEX_R5G6B5 = 0xa, - TEX_ARGB1555 = 0xb, - TEX_ARGB4444 = 0xc, - TEX_A8I8 = 0xd, - TEX_APAL88 = 0xe -}; - -enum -{ - TEXTUREMODE_NCC_SEL = (1 << 5), - TEXTUREMODE_TCLAMPS = (1 << 6), - TEXTUREMODE_TCLAMPT = (1 << 7), - TEXTUREMODE_TRILINEAR = (1 << 30) -}; - -enum -{ - FBIINIT0_VGA_PASS = 1, - FBIINIT0_GRAPHICS_RESET = (1 << 1) -}; - -enum -{ - FBIINIT1_MULTI_SST = (1 << 2), /*Voodoo Graphics only*/ - FBIINIT1_VIDEO_RESET = (1 << 8), - FBIINIT1_SLI_ENABLE = (1 << 23) -}; - -enum -{ - FBIINIT2_SWAP_ALGORITHM_MASK = (3 << 9) -}; - -enum -{ - FBIINIT2_SWAP_ALGORITHM_DAC_VSYNC = (0 << 9), - FBIINIT2_SWAP_ALGORITHM_DAC_DATA = (1 << 9), - FBIINIT2_SWAP_ALGORITHM_PCI_FIFO_STALL = (2 << 9), - FBIINIT2_SWAP_ALGORITHM_SLI_SYNC = (3 << 9) -}; - -enum -{ - FBIINIT3_REMAP = 1 -}; - -enum -{ - FBIINIT5_MULTI_CVG = (1 << 14) -}; - -enum -{ - FBIINIT7_CMDFIFO_ENABLE = (1 << 8) -}; - -enum -{ - CC_LOCALSELECT_ITER_RGB = 0, - CC_LOCALSELECT_TEX = 1, - CC_LOCALSELECT_COLOR1 = 2, - CC_LOCALSELECT_LFB = 3 -}; - -enum -{ - CCA_LOCALSELECT_ITER_A = 0, - CCA_LOCALSELECT_COLOR0 = 1, - CCA_LOCALSELECT_ITER_Z = 2 -}; - -enum -{ - C_SEL_ITER_RGB = 0, - C_SEL_TEX = 1, - C_SEL_COLOR1 = 2, - C_SEL_LFB = 3 -}; - -enum -{ - A_SEL_ITER_A = 0, - A_SEL_TEX = 1, - A_SEL_COLOR1 = 2, - A_SEL_LFB = 3 -}; - -enum -{ - CC_MSELECT_ZERO = 0, - CC_MSELECT_CLOCAL = 1, - CC_MSELECT_AOTHER = 2, - CC_MSELECT_ALOCAL = 3, - CC_MSELECT_TEX = 4, - CC_MSELECT_TEXRGB = 5 -}; - -enum -{ - CCA_MSELECT_ZERO = 0, - CCA_MSELECT_ALOCAL = 1, - CCA_MSELECT_AOTHER = 2, - CCA_MSELECT_ALOCAL2 = 3, - CCA_MSELECT_TEX = 4 -}; - -enum -{ - TC_MSELECT_ZERO = 0, - TC_MSELECT_CLOCAL = 1, - TC_MSELECT_AOTHER = 2, - TC_MSELECT_ALOCAL = 3, - TC_MSELECT_DETAIL = 4, - TC_MSELECT_LOD_FRAC = 5 -}; - -enum -{ - TCA_MSELECT_ZERO = 0, - TCA_MSELECT_CLOCAL = 1, - TCA_MSELECT_AOTHER = 2, - TCA_MSELECT_ALOCAL = 3, - TCA_MSELECT_DETAIL = 4, - TCA_MSELECT_LOD_FRAC = 5 -}; - -enum -{ - CC_ADD_CLOCAL = 1, - CC_ADD_ALOCAL = 2 -}; - -enum -{ - CCA_ADD_CLOCAL = 1, - CCA_ADD_ALOCAL = 2 -}; - -enum -{ - AFUNC_AZERO = 0x0, - AFUNC_ASRC_ALPHA = 0x1, - AFUNC_A_COLOR = 0x2, - AFUNC_ADST_ALPHA = 0x3, - AFUNC_AONE = 0x4, - AFUNC_AOMSRC_ALPHA = 0x5, - AFUNC_AOM_COLOR = 0x6, - AFUNC_AOMDST_ALPHA = 0x7, - AFUNC_ASATURATE = 0xf -}; - -enum -{ - AFUNC_ACOLORBEFOREFOG = 0xf -}; - -enum -{ - AFUNC_NEVER = 0, - AFUNC_LESSTHAN = 1, - AFUNC_EQUAL = 2, - AFUNC_LESSTHANEQUAL = 3, - AFUNC_GREATERTHAN = 4, - AFUNC_NOTEQUAL = 5, - AFUNC_GREATERTHANEQUAL = 6, - AFUNC_ALWAYS = 7 -}; - -enum -{ - DEPTHOP_NEVER = 0, - DEPTHOP_LESSTHAN = 1, - DEPTHOP_EQUAL = 2, - DEPTHOP_LESSTHANEQUAL = 3, - DEPTHOP_GREATERTHAN = 4, - DEPTHOP_NOTEQUAL = 5, - DEPTHOP_GREATERTHANEQUAL = 6, - DEPTHOP_ALWAYS = 7 -}; - -enum -{ - FOG_ENABLE = 0x01, - FOG_ADD = 0x02, - FOG_MULT = 0x04, - FOG_ALPHA = 0x08, - FOG_Z = 0x10, - FOG_W = 0x18, - FOG_CONSTANT = 0x20 -}; - -enum -{ - LOD_ODD = (1 << 18), - LOD_SPLIT = (1 << 19), - LOD_S_IS_WIDER = (1 << 20), - LOD_TMULTIBASEADDR = (1 << 24), - LOD_TMIRROR_S = (1 << 28), - LOD_TMIRROR_T = (1 << 29) -}; -enum -{ - CMD_INVALID = 0, - CMD_DRAWTRIANGLE, - CMD_FASTFILL, - CMD_SWAPBUF -}; - -enum -{ - FBZCP_TEXTURE_ENABLED = (1 << 27) -}; - -enum -{ - BLTCMD_SRC_TILED = (1 << 14), - BLTCMD_DST_TILED = (1 << 15) -}; - -enum -{ - INITENABLE_SLI_MASTER_SLAVE = (1 << 11) -}; - -#define TEXTUREMODE_MASK 0x3ffff000 -#define TEXTUREMODE_PASSTHROUGH 0 - -#define TEXTUREMODE_LOCAL_MASK 0x00643000 -#define TEXTUREMODE_LOCAL 0x00241000 - -static void voodoo_threshold_check(voodoo_t *voodoo); - -static void voodoo_update_ncc(voodoo_t *voodoo, int tmu) -{ - int tbl; - - for (tbl = 0; tbl < 2; tbl++) - { - int col; - - for (col = 0; col < 256; col++) - { - int y = (col >> 4), i = (col >> 2) & 3, q = col & 3; - int i_r, i_g, i_b; - int q_r, q_g, q_b; - - y = (voodoo->nccTable[tmu][tbl].y[y >> 2] >> ((y & 3) * 8)) & 0xff; - - i_r = (voodoo->nccTable[tmu][tbl].i[i] >> 18) & 0x1ff; - if (i_r & 0x100) - i_r |= 0xfffffe00; - i_g = (voodoo->nccTable[tmu][tbl].i[i] >> 9) & 0x1ff; - if (i_g & 0x100) - i_g |= 0xfffffe00; - i_b = voodoo->nccTable[tmu][tbl].i[i] & 0x1ff; - if (i_b & 0x100) - i_b |= 0xfffffe00; - - q_r = (voodoo->nccTable[tmu][tbl].q[q] >> 18) & 0x1ff; - if (q_r & 0x100) - q_r |= 0xfffffe00; - q_g = (voodoo->nccTable[tmu][tbl].q[q] >> 9) & 0x1ff; - if (q_g & 0x100) - q_g |= 0xfffffe00; - q_b = voodoo->nccTable[tmu][tbl].q[q] & 0x1ff; - if (q_b & 0x100) - q_b |= 0xfffffe00; - - voodoo->ncc_lookup[tmu][tbl][col].rgba.r = CLAMP(y + i_r + q_r); - voodoo->ncc_lookup[tmu][tbl][col].rgba.g = CLAMP(y + i_g + q_g); - voodoo->ncc_lookup[tmu][tbl][col].rgba.b = CLAMP(y + i_b + q_b); - voodoo->ncc_lookup[tmu][tbl][col].rgba.a = 0xff; - } - } -} - -#define SLI_ENABLED (voodoo->fbiInit1 & FBIINIT1_SLI_ENABLE) -#define TRIPLE_BUFFER ((voodoo->fbiInit2 & 0x10) || (voodoo->fbiInit5 & 0x600) == 0x400) -static void voodoo_recalc(voodoo_t *voodoo) +void voodoo_recalc(voodoo_t *voodoo) { uint32_t buffer_offset = ((voodoo->fbiInit2 >> 11) & 511) * 4096; - + voodoo->params.front_offset = voodoo->disp_buffer*buffer_offset; voodoo->back_offset = voodoo->draw_buffer*buffer_offset; @@ -1124,7 +75,7 @@ static void voodoo_recalc(voodoo_t *voodoo) default: fatal("voodoo_recalc : unknown lfb source\n"); } - + switch (voodoo->params.fbzMode & FBZ_DRAW_MASK) { case FBZ_DRAW_FRONT: @@ -1139,7 +90,7 @@ static void voodoo_recalc(voodoo_t *voodoo) default: fatal("voodoo_recalc : unknown draw buffer\n"); } - + voodoo->block_width = ((voodoo->fbiInit1 >> 4) & 15) * 2; if (voodoo->fbiInit6 & (1 << 30)) voodoo->block_width += 1; @@ -1151,4769 +102,6 @@ static void voodoo_recalc(voodoo_t *voodoo) 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);*/ } -static void voodoo_recalc_tex(voodoo_t *voodoo, int tmu) -{ - int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; - int width = 256, height = 256; - int shift = 8; - int lod; - uint32_t base = voodoo->params.texBaseAddr[tmu]; - uint32_t offset = 0; - int tex_lod = 0; - - if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER) - height >>= aspect; - else - { - width >>= aspect; - shift -= aspect; - } - - if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD)) - { - width >>= 1; - height >>= 1; - shift--; - tex_lod++; - if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR) - base = voodoo->params.texBaseAddr1[tmu]; - } - - for (lod = 0; lod <= LOD_MAX+1; lod++) - { - if (!width) - width = 1; - if (!height) - height = 1; - if (shift < 0) - shift = 0; - voodoo->params.tex_base[tmu][lod] = base + offset; - if (voodoo->params.tformat[tmu] & 8) - voodoo->params.tex_end[tmu][lod] = base + offset + (width * height * 2); - else - voodoo->params.tex_end[tmu][lod] = base + offset + (width * height); - voodoo->params.tex_w_mask[tmu][lod] = width - 1; - voodoo->params.tex_w_nmask[tmu][lod] = ~(width - 1); - voodoo->params.tex_h_mask[tmu][lod] = height - 1; - voodoo->params.tex_shift[tmu][lod] = shift; - voodoo->params.tex_lod[tmu][lod] = tex_lod; - - if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) || ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD))) - { - if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0) - { - if (voodoo->params.tformat[tmu] & 8) - offset += width * height * 2; - else - offset += width * height; - - if (voodoo->params.tLOD[tmu] & LOD_SPLIT) - { - width >>= 2; - height >>= 2; - shift -= 2; - tex_lod += 2; - } - else - { - width >>= 1; - height >>= 1; - shift--; - tex_lod++; - } - - if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR) - { - switch (tex_lod) - { - case 0: - base = voodoo->params.texBaseAddr[tmu]; - break; - case 1: - base = voodoo->params.texBaseAddr1[tmu]; - break; - case 2: - base = voodoo->params.texBaseAddr2[tmu]; - break; - default: - base = voodoo->params.texBaseAddr38[tmu]; - break; - } - } - } - } - } - - voodoo->params.tex_width[tmu] = width; -} - -#define makergba(r, g, b, a) ((b) | ((g) << 8) | ((r) << 16) | ((a) << 24)) - -static void use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu) -{ - int c, d; - int lod; - int lod_min, lod_max; - uint32_t addr = 0, addr_end; - uint32_t palette_checksum; - - lod_min = (params->tLOD[tmu] >> 2) & 15; - lod_max = (params->tLOD[tmu] >> 8) & 15; - - if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88) - { - if (voodoo->palette_dirty[tmu]) - { - palette_checksum = 0; - - for (c = 0; c < 256; c++) - palette_checksum ^= voodoo->palette[tmu][c].u; - - voodoo->palette_checksum[tmu] = palette_checksum; - voodoo->palette_dirty[tmu] = 0; - } - else - palette_checksum = voodoo->palette_checksum[tmu]; - } - else - palette_checksum = 0; - - if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)) - addr = params->texBaseAddr1[tmu]; - else - addr = params->texBaseAddr[tmu]; - - /*Try to find texture in cache*/ - for (c = 0; c < TEX_CACHE_MAX; c++) - { - if (voodoo->texture_cache[tmu][c].base == addr && - voodoo->texture_cache[tmu][c].tLOD == (params->tLOD[tmu] & 0xf00fff) && - voodoo->texture_cache[tmu][c].palette_checksum == palette_checksum) - { - params->tex_entry[tmu] = c; - voodoo->texture_cache[tmu][c].refcount++; - return; - } - } - - /*Texture not found, search for unused texture*/ - do - { - for (c = 0; c < TEX_CACHE_MAX; c++) - { - voodoo->texture_last_removed++; - voodoo->texture_last_removed &= (TEX_CACHE_MAX-1); - if (voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[0] && - (voodoo->render_threads == 1 || voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[1])) - break; - } - if (c == TEX_CACHE_MAX) - wait_for_render_thread_idle(voodoo); - } while (c == TEX_CACHE_MAX); - if (c == TEX_CACHE_MAX) - fatal("Texture cache full!\n"); - - c = voodoo->texture_last_removed; - - - if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)) - voodoo->texture_cache[tmu][c].base = params->texBaseAddr1[tmu]; - else - voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu]; - voodoo->texture_cache[tmu][c].tLOD = params->tLOD[tmu] & 0xf00fff; - - lod_min = (params->tLOD[tmu] >> 2) & 15; - lod_max = (params->tLOD[tmu] >> 8) & 15; -// 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); - lod_min = MIN(lod_min, 8); - lod_max = MIN(lod_max, 8); - for (lod = lod_min; lod <= lod_max; lod++) - { - uint32_t *base = &voodoo->texture_cache[tmu][c].data[texture_offset[lod]]; - uint32_t tex_addr = params->tex_base[tmu][lod] & voodoo->texture_mask; - int x, y; - int shift = 8 - params->tex_lod[tmu][lod]; - rgba_u *pal; - - //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]); - - - switch (params->tformat[tmu]) - { - case TEX_RGB332: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(rgb332[dat].r, rgb332[dat].g, rgb332[dat].b, 0xff); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_Y4I2Q2: - pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_A8: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(dat, dat, dat, dat); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_I8: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(dat, dat, dat, 0xff); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_AI8: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba((dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0xf0) | ((dat >> 4) & 0x0f)); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_PAL8: - pal = voodoo->palette[tmu]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_APAL8: - pal = voodoo->palette[tmu]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; - - int r = ((pal[dat].rgba.r & 3) << 6) | ((pal[dat].rgba.g & 0xf0) >> 2) | (pal[dat].rgba.r & 3); - int g = ((pal[dat].rgba.g & 0xf) << 4) | ((pal[dat].rgba.b & 0xc0) >> 4) | ((pal[dat].rgba.g & 0xf) >> 2); - int b = ((pal[dat].rgba.b & 0x3f) << 2) | ((pal[dat].rgba.b & 0x30) >> 4); - int a = (pal[dat].rgba.r & 0xfc) | ((pal[dat].rgba.r & 0xc0) >> 6); - - base[x] = makergba(r, g, b, a); - } - tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); - base += (1 << shift); - } - break; - - case TEX_ARGB8332: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(rgb332[dat & 0xff].r, rgb332[dat & 0xff].g, rgb332[dat & 0xff].b, dat >> 8); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_A8Y4I2Q2: - pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_R5G6B5: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(rgb565[dat].r, rgb565[dat].g, rgb565[dat].b, 0xff); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_ARGB1555: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(argb1555[dat].r, argb1555[dat].g, argb1555[dat].b, argb1555[dat].a); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_ARGB4444: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(argb4444[dat].r, argb4444[dat].g, argb4444[dat].b, argb4444[dat].a); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_A8I8: - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(dat & 0xff, dat & 0xff, dat & 0xff, dat >> 8); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - case TEX_APAL88: - pal = voodoo->palette[tmu]; - for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) - { - for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) - { - uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; - - base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8); - } - tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); - base += (1 << shift); - } - break; - - default: - fatal("Unknown texture format %i\n", params->tformat[tmu]); - } - } - - voodoo->texture_cache[tmu][c].is16 = voodoo->params.tformat[tmu] & 8; - - if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88) - voodoo->texture_cache[tmu][c].palette_checksum = palette_checksum; - else - voodoo->texture_cache[tmu][c].palette_checksum = 0; - - if (lod_min == 0) - { - voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->params.tex_base[tmu][0]; - voodoo->texture_cache[tmu][c].addr_end[0] = voodoo->params.tex_end[tmu][0]; - } - else - voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->texture_cache[tmu][c].addr_end[0] = 0; - - if (lod_min <= 1 && lod_max >= 1) - { - voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->params.tex_base[tmu][1]; - voodoo->texture_cache[tmu][c].addr_end[1] = voodoo->params.tex_end[tmu][1]; - } - else - voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->texture_cache[tmu][c].addr_end[1] = 0; - - if (lod_min <= 2 && lod_max >= 2) - { - voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->params.tex_base[tmu][2]; - voodoo->texture_cache[tmu][c].addr_end[2] = voodoo->params.tex_end[tmu][2]; - } - else - voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->texture_cache[tmu][c].addr_end[2] = 0; - - if (lod_max >= 3) - { - voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->params.tex_base[tmu][(lod_min > 3) ? lod_min : 3]; - voodoo->texture_cache[tmu][c].addr_end[3] = voodoo->params.tex_end[tmu][(lod_max < 8) ? lod_max : 8]; - } - else - voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->texture_cache[tmu][c].addr_end[3] = 0; - - - for (d = 0; d < 4; d++) - { - addr = voodoo->texture_cache[tmu][c].addr_start[d]; - addr_end = voodoo->texture_cache[tmu][c].addr_end[d]; - - if (addr_end != 0) - { - for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT)) - voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; - } - } - - params->tex_entry[tmu] = c; - voodoo->texture_cache[tmu][c].refcount++; -} - -static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu) -{ - int wait_for_idle = 0; - int c; - - memset(voodoo->texture_present[tmu], 0, sizeof(voodoo->texture_present[0])); -// pclog("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present)); - for (c = 0; c < TEX_CACHE_MAX; c++) - { - if (voodoo->texture_cache[tmu][c].base != -1) - { - int d; - - for (d = 0; d < 4; d++) - { - int addr_start = voodoo->texture_cache[tmu][c].addr_start[d]; - int addr_end = voodoo->texture_cache[tmu][c].addr_end[d]; - - if (addr_end != 0) - { - int addr_start_masked = addr_start & voodoo->texture_mask & ~0x3ff; - int addr_end_masked = ((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff; - - if (addr_end_masked < addr_start_masked) - addr_end_masked = voodoo->texture_mask+1; - if (dirty_addr >= addr_start_masked && dirty_addr < addr_end_masked) - { -// pclog(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base); - - if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] || - (voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1])) - wait_for_idle = 1; - - voodoo->texture_cache[tmu][c].base = -1; - } - else - { - for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT)) - voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; - } - } - } - } - } - if (wait_for_idle) - wait_for_render_thread_idle(voodoo); -} - -typedef struct voodoo_state_t -{ - int xstart, xend, xdir; - uint32_t base_r, base_g, base_b, base_a, base_z; - struct - { - int64_t base_s, base_t, base_w; - int lod; - } tmu[2]; - int64_t base_w; - int lod; - int lod_min[2], lod_max[2]; - int dx1, dx2; - int y, yend, ydir; - int32_t dxAB, dxAC, dxBC; - int tex_b[2], tex_g[2], tex_r[2], tex_a[2]; - int tex_s, tex_t; - int clamp_s[2], clamp_t[2]; - - int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy; - - uint32_t *tex[2][LOD_MAX+1]; - int tformat; - - int *tex_w_mask[2]; - int *tex_h_mask[2]; - int *tex_shift[2]; - int *tex_lod[2]; - - uint16_t *fb_mem, *aux_mem; - - int32_t ib, ig, ir, ia; - int32_t z; - - int32_t new_depth; - - int64_t tmu0_s, tmu0_t; - int64_t tmu0_w; - int64_t tmu1_s, tmu1_t; - int64_t tmu1_w; - int64_t w; - - int pixel_count, texel_count; - int x, x2; - - uint32_t w_depth; - - float log_temp; - uint32_t ebp_store; - uint32_t texBaseAddr; - - int lod_frac[2]; -} voodoo_state_t; - -static int voodoo_output = 0; - -static uint8_t logtable[256] = -{ - 0x00,0x01,0x02,0x04,0x05,0x07,0x08,0x09,0x0b,0x0c,0x0e,0x0f,0x10,0x12,0x13,0x15, - 0x16,0x17,0x19,0x1a,0x1b,0x1d,0x1e,0x1f,0x21,0x22,0x23,0x25,0x26,0x27,0x28,0x2a, - 0x2b,0x2c,0x2e,0x2f,0x30,0x31,0x33,0x34,0x35,0x36,0x38,0x39,0x3a,0x3b,0x3d,0x3e, - 0x3f,0x40,0x41,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x50,0x51, - 0x52,0x53,0x54,0x55,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x60,0x61,0x62,0x63, - 0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74, - 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x83,0x84,0x85, - 0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94, - 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa2,0xa3, - 0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xad,0xae,0xaf,0xb0,0xb1,0xb2, - 0xb3,0xb4,0xb5,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbc,0xbd,0xbe,0xbf,0xc0, - 0xc1,0xc2,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xcd, - 0xce,0xcf,0xd0,0xd1,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd6,0xd7,0xd8,0xd9,0xda,0xda, - 0xdb,0xdc,0xdd,0xde,0xde,0xdf,0xe0,0xe1,0xe1,0xe2,0xe3,0xe4,0xe5,0xe5,0xe6,0xe7, - 0xe8,0xe8,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3, - 0xf4,0xf5,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xfa,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff -}; - -static inline int fastlog(uint64_t val) -{ - uint64_t oldval = val; - int exp = 63; - int frac; - - if (!val || val & (1ULL << 63)) - return 0x80000000; - - if (!(val & 0xffffffff00000000)) - { - exp -= 32; - val <<= 32; - } - if (!(val & 0xffff000000000000)) - { - exp -= 16; - val <<= 16; - } - if (!(val & 0xff00000000000000)) - { - exp -= 8; - val <<= 8; - } - if (!(val & 0xf000000000000000)) - { - exp -= 4; - val <<= 4; - } - if (!(val & 0xc000000000000000)) - { - exp -= 2; - val <<= 2; - } - if (!(val & 0x8000000000000000)) - { - exp -= 1; - val <<= 1; - } - - if (exp >= 8) - frac = (oldval >> (exp - 8)) & 0xff; - else - frac = (oldval << (8 - exp)) & 0xff; - - return (exp << 8) | logtable[frac]; -} - -static inline int voodoo_fls(uint16_t val) -{ - int num = 0; - -//pclog("fls(%04x) = ", val); - if (!(val & 0xff00)) - { - num += 8; - val <<= 8; - } - if (!(val & 0xf000)) - { - num += 4; - val <<= 4; - } - if (!(val & 0xc000)) - { - num += 2; - val <<= 2; - } - if (!(val & 0x8000)) - { - num += 1; - val <<= 1; - } -//pclog("%i %04x\n", num, val); - return num; -} - -typedef struct voodoo_texture_state_t -{ - int s, t; - int w_mask, h_mask; - int tex_shift; -} voodoo_texture_state_t; - -static inline void tex_read(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int tmu) -{ - uint32_t dat; - - if (texture_state->s & ~texture_state->w_mask) - { - if (state->clamp_s[tmu]) - { - if (texture_state->s < 0) - texture_state->s = 0; - if (texture_state->s > texture_state->w_mask) - texture_state->s = texture_state->w_mask; - } - else - texture_state->s &= texture_state->w_mask; - } - if (texture_state->t & ~texture_state->h_mask) - { - if (state->clamp_t[tmu]) - { - if (texture_state->t < 0) - texture_state->t = 0; - if (texture_state->t > texture_state->h_mask) - texture_state->t = texture_state->h_mask; - } - else - texture_state->t &= texture_state->h_mask; - } - - dat = state->tex[tmu][state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)]; - - state->tex_b[tmu] = dat & 0xff; - state->tex_g[tmu] = (dat >> 8) & 0xff; - state->tex_r[tmu] = (dat >> 16) & 0xff; - state->tex_a[tmu] = (dat >> 24) & 0xff; -} - -#define LOW4(x) ((x & 0x0f) | ((x & 0x0f) << 4)) -#define HIGH4(x) ((x & 0xf0) | ((x & 0xf0) >> 4)) - -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) -{ - rgba_u dat[4]; - - if (((s | (s + 1)) & ~texture_state->w_mask) || ((t | (t + 1)) & ~texture_state->h_mask)) - { - int c; - for (c = 0; c < 4; c++) - { - int _s = s + (c & 1); - int _t = t + ((c & 2) >> 1); - - if (_s & ~texture_state->w_mask) - { - if (state->clamp_s[tmu]) - { - if (_s < 0) - _s = 0; - if (_s > texture_state->w_mask) - _s = texture_state->w_mask; - } - else - _s &= texture_state->w_mask; - } - if (_t & ~texture_state->h_mask) - { - if (state->clamp_t[tmu]) - { - if (_t < 0) - _t = 0; - if (_t > texture_state->h_mask) - _t = texture_state->h_mask; - } - else - _t &= texture_state->h_mask; - } - dat[c].u = state->tex[tmu][state->lod][_s + (_t << texture_state->tex_shift)]; - } - } - else - { - dat[0].u = state->tex[tmu][state->lod][s + (t << texture_state->tex_shift)]; - dat[1].u = state->tex[tmu][state->lod][s + 1 + (t << texture_state->tex_shift)]; - dat[2].u = state->tex[tmu][state->lod][s + ((t + 1) << texture_state->tex_shift)]; - dat[3].u = state->tex[tmu][state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)]; - } - - 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; - 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; - 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; - 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; -} - -static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x) -{ - voodoo_texture_state_t texture_state; - int d[4]; - int s, t; - int tex_lod = state->tex_lod[tmu][state->lod]; - - texture_state.w_mask = state->tex_w_mask[tmu][state->lod]; - texture_state.h_mask = state->tex_h_mask[tmu][state->lod]; - texture_state.tex_shift = 8 - tex_lod; - - if (params->tLOD[tmu] & LOD_TMIRROR_S) - { - if (state->tex_s & 0x1000) - state->tex_s = ~state->tex_s; - } - if (params->tLOD[tmu] & LOD_TMIRROR_T) - { - if (state->tex_t & 0x1000) - state->tex_t = ~state->tex_t; - } - - if (voodoo->bilinear_enabled && params->textureMode[tmu] & 6) - { - int _ds, dt; - - state->tex_s -= 1 << (3+tex_lod); - state->tex_t -= 1 << (3+tex_lod); - - s = state->tex_s >> tex_lod; - t = state->tex_t >> tex_lod; - - _ds = s & 0xf; - dt = t & 0xf; - - s >>= 4; - t >>= 4; -//if (x == 80) -//if (voodoo_output) -// pclog("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, _ds, dt); - d[0] = (16 - _ds) * (16 - dt); - d[1] = _ds * (16 - dt); - d[2] = (16 - _ds) * dt; - d[3] = _ds * dt; - -// texture_state.s = s; -// texture_state.t = t; - tex_read_4(state, &texture_state, s, t, d, tmu, x); - - -/* 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; - 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; - 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; - 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;*/ -/* state->tex_r = tex_samples[0].r; - state->tex_g = tex_samples[0].g; - state->tex_b = tex_samples[0].b; - state->tex_a = tex_samples[0].a;*/ - } - else - { - // rgba_t tex_samples; - // voodoo_texture_state_t texture_state; -// int s = state->tex_s >> (18+state->lod); -// int t = state->tex_t >> (18+state->lod); - // int s, t; - -// state->tex_s -= 1 << (17+state->lod); -// state->tex_t -= 1 << (17+state->lod); - - s = state->tex_s >> (4+tex_lod); - t = state->tex_t >> (4+tex_lod); - - texture_state.s = s; - texture_state.t = t; - tex_read(state, &texture_state, tmu); - -/* state->tex_r = tex_samples[0].rgba.r; - state->tex_g = tex_samples[0].rgba.g; - state->tex_b = tex_samples[0].rgba.b; - state->tex_a = tex_samples[0].rgba.a;*/ - } -} - -static inline void voodoo_tmu_fetch(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x) -{ - if (params->textureMode[tmu] & 1) - { - int64_t _w = 0; - - if (tmu) - { - if (state->tmu1_w) - _w = (int64_t)((1ULL << 48) / state->tmu1_w); - state->tex_s = (int32_t)(((((state->tmu1_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); - state->tex_t = (int32_t)(((((state->tmu1_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); - } - else - { - if (state->tmu0_w) - _w = (int64_t)((1ULL << 48) / state->tmu0_w); - state->tex_s = (int32_t)(((((state->tmu0_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); - state->tex_t = (int32_t)(((((state->tmu0_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); - } - - state->lod = state->tmu[tmu].lod + (fastlog(_w) - (19 << 8)); - } - else - { - if (tmu) - { - state->tex_s = (int32_t)(state->tmu1_s >> (14+14)); - state->tex_t = (int32_t)(state->tmu1_t >> (14+14)); - } - else - { - state->tex_s = (int32_t)(state->tmu0_s >> (14+14)); - state->tex_t = (int32_t)(state->tmu0_t >> (14+14)); - } - state->lod = state->tmu[tmu].lod; - } - - if (state->lod < state->lod_min[tmu]) - state->lod = state->lod_min[tmu]; - else if (state->lod > state->lod_max[tmu]) - state->lod = state->lod_max[tmu]; - state->lod_frac[tmu] = state->lod & 0xff; - state->lod >>= 8; - - voodoo_get_texture(voodoo, params, state, tmu, x); -} - -#define DEPTH_TEST(comp_depth) \ - do \ - { \ - switch (depth_op) \ - { \ - case DEPTHOP_NEVER: \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - case DEPTHOP_LESSTHAN: \ - if (!(comp_depth < old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_EQUAL: \ - if (!(comp_depth == old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_LESSTHANEQUAL: \ - if (!(comp_depth <= old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_GREATERTHAN: \ - if (!(comp_depth > old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_NOTEQUAL: \ - if (!(comp_depth != old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_GREATERTHANEQUAL: \ - if (!(comp_depth >= old_depth)) \ - { \ - voodoo->fbiZFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case DEPTHOP_ALWAYS: \ - break; \ - } \ - } while (0) - -#define APPLY_FOG(src_r, src_g, src_b, z, ia, w) \ - do \ - { \ - if (params->fogMode & FOG_CONSTANT) \ - { \ - src_r += params->fogColor.r; \ - src_g += params->fogColor.g; \ - src_b += params->fogColor.b; \ - } \ - else \ - { \ - int fog_r, fog_g, fog_b, fog_a = 0; \ - int fog_idx; \ - \ - if (!(params->fogMode & FOG_ADD)) \ - { \ - fog_r = params->fogColor.r; \ - fog_g = params->fogColor.g; \ - fog_b = params->fogColor.b; \ - } \ - else \ - fog_r = fog_g = fog_b = 0; \ - \ - if (!(params->fogMode & FOG_MULT)) \ - { \ - fog_r -= src_r; \ - fog_g -= src_g; \ - fog_b -= src_b; \ - } \ - \ - switch (params->fogMode & (FOG_Z|FOG_ALPHA)) \ - { \ - case 0: \ - fog_idx = (w_depth >> 10) & 0x3f; \ - \ - fog_a = params->fogTable[fog_idx].fog; \ - fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; \ - break; \ - case FOG_Z: \ - fog_a = (z >> 20) & 0xff; \ - break; \ - case FOG_ALPHA: \ - fog_a = CLAMP(ia >> 12); \ - break; \ - case FOG_W: \ - fog_a = CLAMP((w >> 32) & 0xff); \ - break; \ - } \ - fog_a++; \ - \ - fog_r = (fog_r * fog_a) >> 8; \ - fog_g = (fog_g * fog_a) >> 8; \ - fog_b = (fog_b * fog_a) >> 8; \ - \ - if (params->fogMode & FOG_MULT) \ - { \ - src_r = fog_r; \ - src_g = fog_g; \ - src_b = fog_b; \ - } \ - else \ - { \ - src_r += fog_r; \ - src_g += fog_g; \ - src_b += fog_b; \ - } \ - } \ - \ - src_r = CLAMP(src_r); \ - src_g = CLAMP(src_g); \ - src_b = CLAMP(src_b); \ - } while (0) - -#define ALPHA_TEST(src_a) \ - do \ - { \ - switch (alpha_func) \ - { \ - case AFUNC_NEVER: \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - case AFUNC_LESSTHAN: \ - if (!(src_a < a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_EQUAL: \ - if (!(src_a == a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_LESSTHANEQUAL: \ - if (!(src_a <= a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_GREATERTHAN: \ - if (!(src_a > a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_NOTEQUAL: \ - if (!(src_a != a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_GREATERTHANEQUAL: \ - if (!(src_a >= a_ref)) \ - { \ - voodoo->fbiAFuncFail++; \ - goto skip_pixel; \ - } \ - break; \ - case AFUNC_ALWAYS: \ - break; \ - } \ - } while (0) - -#define ALPHA_BLEND(src_r, src_g, src_b, src_a) \ - do \ - { \ - int _a; \ - int newdest_r = 0, newdest_g = 0, newdest_b = 0; \ - \ - switch (dest_afunc) \ - { \ - case AFUNC_AZERO: \ - newdest_r = newdest_g = newdest_b = 0; \ - break; \ - case AFUNC_ASRC_ALPHA: \ - newdest_r = (dest_r * src_a) / 255; \ - newdest_g = (dest_g * src_a) / 255; \ - newdest_b = (dest_b * src_a) / 255; \ - break; \ - case AFUNC_A_COLOR: \ - newdest_r = (dest_r * src_r) / 255; \ - newdest_g = (dest_g * src_g) / 255; \ - newdest_b = (dest_b * src_b) / 255; \ - break; \ - case AFUNC_ADST_ALPHA: \ - newdest_r = (dest_r * dest_a) / 255; \ - newdest_g = (dest_g * dest_a) / 255; \ - newdest_b = (dest_b * dest_a) / 255; \ - break; \ - case AFUNC_AONE: \ - newdest_r = dest_r; \ - newdest_g = dest_g; \ - newdest_b = dest_b; \ - break; \ - case AFUNC_AOMSRC_ALPHA: \ - newdest_r = (dest_r * (255-src_a)) / 255; \ - newdest_g = (dest_g * (255-src_a)) / 255; \ - newdest_b = (dest_b * (255-src_a)) / 255; \ - break; \ - case AFUNC_AOM_COLOR: \ - newdest_r = (dest_r * (255-src_r)) / 255; \ - newdest_g = (dest_g * (255-src_g)) / 255; \ - newdest_b = (dest_b * (255-src_b)) / 255; \ - break; \ - case AFUNC_AOMDST_ALPHA: \ - newdest_r = (dest_r * (255-dest_a)) / 255; \ - newdest_g = (dest_g * (255-dest_a)) / 255; \ - newdest_b = (dest_b * (255-dest_a)) / 255; \ - break; \ - case AFUNC_ASATURATE: \ - _a = MIN(src_a, 1-dest_a); \ - newdest_r = (dest_r * _a) / 255; \ - newdest_g = (dest_g * _a) / 255; \ - newdest_b = (dest_b * _a) / 255; \ - break; \ - } \ - \ - switch (src_afunc) \ - { \ - case AFUNC_AZERO: \ - src_r = src_g = src_b = 0; \ - break; \ - case AFUNC_ASRC_ALPHA: \ - src_r = (src_r * src_a) / 255; \ - src_g = (src_g * src_a) / 255; \ - src_b = (src_b * src_a) / 255; \ - break; \ - case AFUNC_A_COLOR: \ - src_r = (src_r * dest_r) / 255; \ - src_g = (src_g * dest_g) / 255; \ - src_b = (src_b * dest_b) / 255; \ - break; \ - case AFUNC_ADST_ALPHA: \ - src_r = (src_r * dest_a) / 255; \ - src_g = (src_g * dest_a) / 255; \ - src_b = (src_b * dest_a) / 255; \ - break; \ - case AFUNC_AONE: \ - break; \ - case AFUNC_AOMSRC_ALPHA: \ - src_r = (src_r * (255-src_a)) / 255; \ - src_g = (src_g * (255-src_a)) / 255; \ - src_b = (src_b * (255-src_a)) / 255; \ - break; \ - case AFUNC_AOM_COLOR: \ - src_r = (src_r * (255-dest_r)) / 255; \ - src_g = (src_g * (255-dest_g)) / 255; \ - src_b = (src_b * (255-dest_b)) / 255; \ - break; \ - case AFUNC_AOMDST_ALPHA: \ - src_r = (src_r * (255-dest_a)) / 255; \ - src_g = (src_g * (255-dest_a)) / 255; \ - src_b = (src_b * (255-dest_a)) / 255; \ - break; \ - case AFUNC_ACOLORBEFOREFOG: \ - fatal("AFUNC_ACOLORBEFOREFOG\n"); \ - break; \ - } \ - \ - src_r += newdest_r; \ - src_g += newdest_g; \ - src_b += newdest_b; \ - \ - src_r = CLAMP(src_r); \ - src_g = CLAMP(src_g); \ - src_b = CLAMP(src_b); \ - } while(0) - - -#define _rgb_sel ( params->fbzColorPath & 3) -#define a_sel ( (params->fbzColorPath >> 2) & 3) -#define cc_localselect ( params->fbzColorPath & (1 << 4)) -#define cca_localselect ( (params->fbzColorPath >> 5) & 3) -#define cc_localselect_override ( params->fbzColorPath & (1 << 7)) -#define cc_zero_other ( params->fbzColorPath & (1 << 8)) -#define cc_sub_clocal ( params->fbzColorPath & (1 << 9)) -#define cc_mselect ( (params->fbzColorPath >> 10) & 7) -#define cc_reverse_blend ( params->fbzColorPath & (1 << 13)) -#define cc_add ( (params->fbzColorPath >> 14) & 3) -#define cc_add_alocal ( params->fbzColorPath & (1 << 15)) -#define cc_invert_output ( params->fbzColorPath & (1 << 16)) -#define cca_zero_other ( params->fbzColorPath & (1 << 17)) -#define cca_sub_clocal ( params->fbzColorPath & (1 << 18)) -#define cca_mselect ( (params->fbzColorPath >> 19) & 7) -#define cca_reverse_blend ( params->fbzColorPath & (1 << 22)) -#define cca_add ( (params->fbzColorPath >> 23) & 3) -#define cca_invert_output ( params->fbzColorPath & (1 << 25)) -#define tc_zero_other (params->textureMode[0] & (1 << 12)) -#define tc_sub_clocal (params->textureMode[0] & (1 << 13)) -#define tc_mselect ((params->textureMode[0] >> 14) & 7) -#define tc_reverse_blend (params->textureMode[0] & (1 << 17)) -#define tc_add_clocal (params->textureMode[0] & (1 << 18)) -#define tc_add_alocal (params->textureMode[0] & (1 << 19)) -#define tc_invert_output (params->textureMode[0] & (1 << 20)) -#define tca_zero_other (params->textureMode[0] & (1 << 21)) -#define tca_sub_clocal (params->textureMode[0] & (1 << 22)) -#define tca_mselect ((params->textureMode[0] >> 23) & 7) -#define tca_reverse_blend (params->textureMode[0] & (1 << 26)) -#define tca_add_clocal (params->textureMode[0] & (1 << 27)) -#define tca_add_alocal (params->textureMode[0] & (1 << 28)) -#define tca_invert_output (params->textureMode[0] & (1 << 29)) - -#define tc_sub_clocal_1 (params->textureMode[1] & (1 << 13)) -#define tc_mselect_1 ((params->textureMode[1] >> 14) & 7) -#define tc_reverse_blend_1 (params->textureMode[1] & (1 << 17)) -#define tc_add_clocal_1 (params->textureMode[1] & (1 << 18)) -#define tc_add_alocal_1 (params->textureMode[1] & (1 << 19)) -#define tca_sub_clocal_1 (params->textureMode[1] & (1 << 22)) -#define tca_mselect_1 ((params->textureMode[1] >> 23) & 7) -#define tca_reverse_blend_1 (params->textureMode[1] & (1 << 26)) -#define tca_add_clocal_1 (params->textureMode[1] & (1 << 27)) -#define tca_add_alocal_1 (params->textureMode[1] & (1 << 28)) - -#define src_afunc ( (params->alphaMode >> 8) & 0xf) -#define dest_afunc ( (params->alphaMode >> 12) & 0xf) -#define alpha_func ( (params->alphaMode >> 1) & 7) -#define a_ref ( params->alphaMode >> 24) -#define depth_op ( (params->fbzMode >> 5) & 7) -#define dither ( params->fbzMode & FBZ_DITHER) -#define dither2x2 (params->fbzMode & FBZ_DITHER_2x2) - -/*Perform texture fetch and blending for both TMUs*/ -static inline void voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int x) -{ - int r,g,b,a; - int c_reverse, a_reverse; -// int c_reverse1, a_reverse1; - int factor_r = 0, factor_g = 0, factor_b = 0, factor_a = 0; - - voodoo_tmu_fetch(voodoo, params, state, 1, x); - - if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && (state->lod & 1)) - { - c_reverse = tc_reverse_blend; - a_reverse = tca_reverse_blend; - } - else - { - c_reverse = !tc_reverse_blend; - a_reverse = !tca_reverse_blend; - } -/* c_reverse1 = c_reverse; - a_reverse1 = a_reverse;*/ - if (tc_sub_clocal_1) - { - switch (tc_mselect_1) - { - case TC_MSELECT_ZERO: - factor_r = factor_g = factor_b = 0; - break; - case TC_MSELECT_CLOCAL: - factor_r = state->tex_r[1]; - factor_g = state->tex_g[1]; - factor_b = state->tex_b[1]; - break; - case TC_MSELECT_AOTHER: - factor_r = factor_g = factor_b = 0; - break; - case TC_MSELECT_ALOCAL: - factor_r = factor_g = factor_b = state->tex_a[1]; - break; - case TC_MSELECT_DETAIL: - factor_r = (params->detail_bias[1] - state->lod) << params->detail_scale[1]; - if (factor_r > params->detail_max[1]) - factor_r = params->detail_max[1]; - factor_g = factor_b = factor_r; - break; - case TC_MSELECT_LOD_FRAC: - factor_r = factor_g = factor_b = state->lod_frac[1]; - break; - } - if (!c_reverse) - { - r = (-state->tex_r[1] * (factor_r + 1)) >> 8; - g = (-state->tex_g[1] * (factor_g + 1)) >> 8; - b = (-state->tex_b[1] * (factor_b + 1)) >> 8; - } - else - { - r = (-state->tex_r[1] * ((factor_r^0xff) + 1)) >> 8; - g = (-state->tex_g[1] * ((factor_g^0xff) + 1)) >> 8; - b = (-state->tex_b[1] * ((factor_b^0xff) + 1)) >> 8; - } - if (tc_add_clocal_1) - { - r += state->tex_r[1]; - g += state->tex_g[1]; - b += state->tex_b[1]; - } - else if (tc_add_alocal_1) - { - r += state->tex_a[1]; - g += state->tex_a[1]; - b += state->tex_a[1]; - } - state->tex_r[1] = CLAMP(r); - state->tex_g[1] = CLAMP(g); - state->tex_b[1] = CLAMP(b); - } - if (tca_sub_clocal_1) - { - switch (tca_mselect_1) - { - case TCA_MSELECT_ZERO: - factor_a = 0; - break; - case TCA_MSELECT_CLOCAL: - factor_a = state->tex_a[1]; - break; - case TCA_MSELECT_AOTHER: - factor_a = 0; - break; - case TCA_MSELECT_ALOCAL: - factor_a = state->tex_a[1]; - break; - case TCA_MSELECT_DETAIL: - factor_a = (params->detail_bias[1] - state->lod) << params->detail_scale[1]; - if (factor_a > params->detail_max[1]) - factor_a = params->detail_max[1]; - break; - case TCA_MSELECT_LOD_FRAC: - factor_a = state->lod_frac[1]; - break; - } - if (!a_reverse) - a = (-state->tex_a[1] * ((factor_a ^ 0xff) + 1)) >> 8; - else - a = (-state->tex_a[1] * (factor_a + 1)) >> 8; - if (tca_add_clocal_1 || tca_add_alocal_1) - a += state->tex_a[1]; - state->tex_a[1] = CLAMP(a); - } - - - voodoo_tmu_fetch(voodoo, params, state, 0, x); - - if ((params->textureMode[0] & TEXTUREMODE_TRILINEAR) && (state->lod & 1)) - { - c_reverse = tc_reverse_blend; - a_reverse = tca_reverse_blend; - } - else - { - c_reverse = !tc_reverse_blend; - a_reverse = !tca_reverse_blend; - } - - if (!tc_zero_other) - { - r = state->tex_r[1]; - g = state->tex_g[1]; - b = state->tex_b[1]; - } - else - r = g = b = 0; - if (tc_sub_clocal) - { - r -= state->tex_r[0]; - g -= state->tex_g[0]; - b -= state->tex_b[0]; - } - switch (tc_mselect) - { - case TC_MSELECT_ZERO: - factor_r = factor_g = factor_b = 0; - break; - case TC_MSELECT_CLOCAL: - factor_r = state->tex_r[0]; - factor_g = state->tex_g[0]; - factor_b = state->tex_b[0]; - break; - case TC_MSELECT_AOTHER: - factor_r = factor_g = factor_b = state->tex_a[1]; - break; - case TC_MSELECT_ALOCAL: - factor_r = factor_g = factor_b = state->tex_a[0]; - break; - case TC_MSELECT_DETAIL: - factor_r = (params->detail_bias[0] - state->lod) << params->detail_scale[0]; - if (factor_r > params->detail_max[0]) - factor_r = params->detail_max[0]; - factor_g = factor_b = factor_r; - break; - case TC_MSELECT_LOD_FRAC: - factor_r = factor_g = factor_b = state->lod_frac[0]; - break; - } - if (!c_reverse) - { - r = (r * (factor_r + 1)) >> 8; - g = (g * (factor_g + 1)) >> 8; - b = (b * (factor_b + 1)) >> 8; - } - else - { - r = (r * ((factor_r^0xff) + 1)) >> 8; - g = (g * ((factor_g^0xff) + 1)) >> 8; - b = (b * ((factor_b^0xff) + 1)) >> 8; - } - if (tc_add_clocal) - { - r += state->tex_r[0]; - g += state->tex_g[0]; - b += state->tex_b[0]; - } - else if (tc_add_alocal) - { - r += state->tex_a[0]; - g += state->tex_a[0]; - b += state->tex_a[0]; - } - - if (!tca_zero_other) - a = state->tex_a[1]; - else - a = 0; - if (tca_sub_clocal) - a -= state->tex_a[0]; - switch (tca_mselect) - { - case TCA_MSELECT_ZERO: - factor_a = 0; - break; - case TCA_MSELECT_CLOCAL: - factor_a = state->tex_a[0]; - break; - case TCA_MSELECT_AOTHER: - factor_a = state->tex_a[1]; - break; - case TCA_MSELECT_ALOCAL: - factor_a = state->tex_a[0]; - break; - case TCA_MSELECT_DETAIL: - factor_a = (params->detail_bias[0] - state->lod) << params->detail_scale[0]; - if (factor_a > params->detail_max[0]) - factor_a = params->detail_max[0]; - break; - case TCA_MSELECT_LOD_FRAC: - factor_a = state->lod_frac[0]; - break; - } - if (a_reverse) - a = (a * ((factor_a ^ 0xff) + 1)) >> 8; - else - a = (a * (factor_a + 1)) >> 8; - if (tca_add_clocal || tca_add_alocal) - a += state->tex_a[0]; - - - state->tex_r[0] = CLAMP(r); - state->tex_g[0] = CLAMP(g); - state->tex_b[0] = CLAMP(b); - state->tex_a[0] = CLAMP(a); - - if (tc_invert_output) - { - state->tex_r[0] ^= 0xff; - state->tex_g[0] ^= 0xff; - state->tex_b[0] ^= 0xff; - } - if (tca_invert_output) - state->tex_a[0] ^= 0xff; -} - -#if (defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__) -#include "vid_voodoo_codegen_x86.h" -#elif (defined __amd64__) -#include "vid_voodoo_codegen_x86-64.h" -#else -#define NO_CODEGEN -static int voodoo_recomp = 0; -#endif - -static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even) -{ -/* int rgb_sel = params->fbzColorPath & 3; - int a_sel = (params->fbzColorPath >> 2) & 3; - int cc_localselect = params->fbzColorPath & (1 << 4); - int cca_localselect = (params->fbzColorPath >> 5) & 3; - int cc_localselect_override = params->fbzColorPath & (1 << 7); - int cc_zero_other = params->fbzColorPath & (1 << 8); - int cc_sub_clocal = params->fbzColorPath & (1 << 9); - int cc_mselect = (params->fbzColorPath >> 10) & 7; - int cc_reverse_blend = params->fbzColorPath & (1 << 13); - int cc_add = (params->fbzColorPath >> 14) & 3; - int cc_add_alocal = params->fbzColorPath & (1 << 15); - int cc_invert_output = params->fbzColorPath & (1 << 16); - int cca_zero_other = params->fbzColorPath & (1 << 17); - int cca_sub_clocal = params->fbzColorPath & (1 << 18); - int cca_mselect = (params->fbzColorPath >> 19) & 7; - int cca_reverse_blend = params->fbzColorPath & (1 << 22); - int cca_add = (params->fbzColorPath >> 23) & 3; - int cca_invert_output = params->fbzColorPath & (1 << 25); - int src_afunc = (params->alphaMode >> 8) & 0xf; - int dest_afunc = (params->alphaMode >> 12) & 0xf; - int alpha_func = (params->alphaMode >> 1) & 7; - int a_ref = params->alphaMode >> 24; - int depth_op = (params->fbzMode >> 5) & 7; - int dither = params->fbzMode & FBZ_DITHER;*/ - int texels; - int c; -#ifndef NO_CODEGEN - uint8_t (*voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y); -#endif - int y_diff = SLI_ENABLED ? 2 : 1; - - if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || - (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) - texels = 1; - else - texels = 2; - - state->clamp_s[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPS; - state->clamp_t[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPT; - state->clamp_s[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPS; - state->clamp_t[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPT; -// int last_x; -// 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); - - for (c = 0; c <= LOD_MAX; c++) - { - state->tex[0][c] = &voodoo->texture_cache[0][params->tex_entry[0]].data[texture_offset[c]]; - state->tex[1][c] = &voodoo->texture_cache[1][params->tex_entry[1]].data[texture_offset[c]]; - } - - state->tformat = params->tformat[0]; - - state->tex_w_mask[0] = params->tex_w_mask[0]; - state->tex_h_mask[0] = params->tex_h_mask[0]; - state->tex_shift[0] = params->tex_shift[0]; - state->tex_lod[0] = params->tex_lod[0]; - state->tex_w_mask[1] = params->tex_w_mask[1]; - state->tex_h_mask[1] = params->tex_h_mask[1]; - state->tex_shift[1] = params->tex_shift[1]; - state->tex_lod[1] = params->tex_lod[1]; - - if ((params->fbzMode & 1) && (ystart < params->clipLowY)) - { - int dy = params->clipLowY - ystart; - - state->base_r += params->dRdY*dy; - state->base_g += params->dGdY*dy; - state->base_b += params->dBdY*dy; - state->base_a += params->dAdY*dy; - state->base_z += params->dZdY*dy; - state->tmu[0].base_s += params->tmu[0].dSdY*dy; - state->tmu[0].base_t += params->tmu[0].dTdY*dy; - state->tmu[0].base_w += params->tmu[0].dWdY*dy; - state->tmu[1].base_s += params->tmu[1].dSdY*dy; - state->tmu[1].base_t += params->tmu[1].dTdY*dy; - state->tmu[1].base_w += params->tmu[1].dWdY*dy; - state->base_w += params->dWdY*dy; - state->xstart += state->dx1*dy; - state->xend += state->dx2*dy; - - ystart = params->clipLowY; - } - - if ((params->fbzMode & 1) && (yend >= params->clipHighY)) - yend = params->clipHighY-1; - - state->y = ystart; -// yend--; - - if (SLI_ENABLED) - { - int test_y; - - if (params->fbzMode & (1 << 17)) - test_y = (voodoo->v_disp-1) - state->y; - else - test_y = state->y; - - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (test_y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(test_y & 1))) - { - state->y++; - - state->base_r += params->dRdY; - state->base_g += params->dGdY; - state->base_b += params->dBdY; - state->base_a += params->dAdY; - state->base_z += params->dZdY; - state->tmu[0].base_s += params->tmu[0].dSdY; - state->tmu[0].base_t += params->tmu[0].dTdY; - state->tmu[0].base_w += params->tmu[0].dWdY; - state->tmu[1].base_s += params->tmu[1].dSdY; - state->tmu[1].base_t += params->tmu[1].dTdY; - state->tmu[1].base_w += params->tmu[1].dWdY; - state->base_w += params->dWdY; - state->xstart += state->dx1; - state->xend += state->dx2; - } - } -#ifndef NO_CODEGEN - if (voodoo->use_recompiler) - voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even); - else - voodoo_draw = NULL; -#endif - - if (voodoo_output) - pclog("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC); -// pclog("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17)); - - for (; state->y < yend; state->y += y_diff) - { - int x, x2; - int real_y = (state->y << 4) + 8; - int start_x, start_x2; - int dx; - uint16_t *fb_mem, *aux_mem; - - state->ir = state->base_r; - state->ig = state->base_g; - state->ib = state->base_b; - state->ia = state->base_a; - state->z = state->base_z; - state->tmu0_s = state->tmu[0].base_s; - state->tmu0_t = state->tmu[0].base_t; - state->tmu0_w = state->tmu[0].base_w; - state->tmu1_s = state->tmu[1].base_s; - state->tmu1_t = state->tmu[1].base_t; - state->tmu1_w = state->tmu[1].base_w; - state->w = state->base_w; - - x = (state->vertexAx << 12) + ((state->dxAC * (real_y - state->vertexAy)) >> 4); - - if (real_y < state->vertexBy) - x2 = (state->vertexAx << 12) + ((state->dxAB * (real_y - state->vertexAy)) >> 4); - else - x2 = (state->vertexBx << 12) + ((state->dxBC * (real_y - state->vertexBy)) >> 4); - - if (params->fbzMode & (1 << 17)) - real_y = (voodoo->v_disp-1) - (real_y >> 4); - else - real_y >>= 4; - - if (SLI_ENABLED) - { - if (((real_y >> 1) & voodoo->odd_even_mask) != odd_even) - goto next_line; - } - else - { - if ((real_y & voodoo->odd_even_mask) != odd_even) - goto next_line; - } - - start_x = x; - - if (state->xdir > 0) - x2 -= (1 << 16); - else - x -= (1 << 16); - dx = ((x + 0x7000) >> 16) - (((state->vertexAx << 12) + 0x7000) >> 16); - start_x2 = x + 0x7000; - x = (x + 0x7000) >> 16; - x2 = (x2 + 0x7000) >> 16; - - if (voodoo_output) - 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); - - state->ir += (params->dRdX * dx); - state->ig += (params->dGdX * dx); - state->ib += (params->dBdX * dx); - state->ia += (params->dAdX * dx); - state->z += (params->dZdX * dx); - state->tmu0_s += (params->tmu[0].dSdX * dx); - state->tmu0_t += (params->tmu[0].dTdX * dx); - state->tmu0_w += (params->tmu[0].dWdX * dx); - state->tmu1_s += (params->tmu[1].dSdX * dx); - state->tmu1_t += (params->tmu[1].dTdX * dx); - state->tmu1_w += (params->tmu[1].dWdX * dx); - state->w += (params->dWdX * dx); - - if (voodoo_output) - pclog("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18+state->lod), (state->tmu0_t + (1 << (17+state->lod))) >> (18+state->lod)); - - if (params->fbzMode & 1) - { - if (state->xdir > 0) - { - if (x < params->clipLeft) - { - int dx = params->clipLeft - x; - - state->ir += params->dRdX*dx; - state->ig += params->dGdX*dx; - state->ib += params->dBdX*dx; - state->ia += params->dAdX*dx; - state->z += params->dZdX*dx; - state->tmu0_s += params->tmu[0].dSdX*dx; - state->tmu0_t += params->tmu[0].dTdX*dx; - state->tmu0_w += params->tmu[0].dWdX*dx; - state->tmu1_s += params->tmu[1].dSdX*dx; - state->tmu1_t += params->tmu[1].dTdX*dx; - state->tmu1_w += params->tmu[1].dWdX*dx; - state->w += params->dWdX*dx; - - x = params->clipLeft; - } - if (x2 >= params->clipRight) - x2 = params->clipRight-1; - } - else - { - if (x >= params->clipRight) - { - int dx = (params->clipRight-1) - x; - - state->ir += params->dRdX*dx; - state->ig += params->dGdX*dx; - state->ib += params->dBdX*dx; - state->ia += params->dAdX*dx; - state->z += params->dZdX*dx; - state->tmu0_s += params->tmu[0].dSdX*dx; - state->tmu0_t += params->tmu[0].dTdX*dx; - state->tmu0_w += params->tmu[0].dWdX*dx; - state->tmu1_s += params->tmu[1].dSdX*dx; - state->tmu1_t += params->tmu[1].dTdX*dx; - state->tmu1_w += params->tmu[1].dWdX*dx; - state->w += params->dWdX*dx; - - x = params->clipRight-1; - } - if (x2 < params->clipLeft) - x2 = params->clipLeft; - } - } - - if (x2 < x && state->xdir > 0) - goto next_line; - if (x2 > x && state->xdir < 0) - goto next_line; - - if (SLI_ENABLED) - { - state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + ((real_y >> 1) * voodoo->row_width)]; - state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + ((real_y >> 1) * voodoo->row_width)) & voodoo->fb_mask]; - } - else - { - state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + (real_y * voodoo->row_width)]; - state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (real_y * voodoo->row_width)) & voodoo->fb_mask]; - } - - if (voodoo_output) - 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); - - state->pixel_count = 0; - state->texel_count = 0; - state->x = x; - state->x2 = x2; -#ifndef NO_CODEGEN - if (voodoo->use_recompiler) - { - voodoo_draw(state, params, x, real_y); - } - else -#endif - do - { - start_x = x; - state->x = x; - voodoo->pixel_count[odd_even]++; - voodoo->texel_count[odd_even] += texels; - voodoo->fbiPixelsIn++; - - if (voodoo_output) - pclog(" X=%03i T=%08x\n", x, state->tmu0_t); -// if (voodoo->fbzMode & FBZ_RGB_WMASK) - { - int update = 1; - uint8_t cother_r, cother_g, cother_b, aother; - uint8_t clocal_r, clocal_g, clocal_b, alocal; - int src_r = 0, src_g = 0, src_b = 0, src_a = 0; - int msel_r, msel_g, msel_b, msel_a; - uint8_t dest_r, dest_g, dest_b, dest_a; - uint16_t dat; - int sel; - int32_t new_depth, w_depth; - - if (state->w & 0xffff00000000) - w_depth = 0; - else if (!(state->w & 0xffff0000)) - w_depth = 0xf001; - else - { - int exp = voodoo_fls((uint16_t)((uint32_t)state->w >> 16)); - int mant = ((~(uint32_t)state->w >> (19 - exp))) & 0xfff; - w_depth = (exp << 12) + mant + 1; - if (w_depth > 0xffff) - w_depth = 0xffff; - } - -// w_depth = CLAMP16(w_depth); - - if (params->fbzMode & FBZ_W_BUFFER) - new_depth = w_depth; - else - new_depth = CLAMP16(state->z >> 12); - - if (params->fbzMode & FBZ_DEPTH_BIAS) - new_depth = CLAMP16(new_depth + (int16_t)params->zaColor); - - if (params->fbzMode & FBZ_DEPTH_ENABLE) - { - uint16_t old_depth = aux_mem[x]; - - DEPTH_TEST((params->fbzMode & FBZ_DEPTH_SOURCE) ? (params->zaColor & 0xffff) : new_depth); - } - - dat = fb_mem[x]; - dest_r = (dat >> 8) & 0xf8; - dest_g = (dat >> 3) & 0xfc; - dest_b = (dat << 3) & 0xf8; - dest_r |= (dest_r >> 5); - dest_g |= (dest_g >> 6); - dest_b |= (dest_b >> 5); - dest_a = 0xff; - - if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) - { - if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) - { - /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/ - voodoo_tmu_fetch(voodoo, params, state, 0, x); - } - else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH) - { - /*TMU0 in pass-through mode, only sample TMU1*/ - voodoo_tmu_fetch(voodoo, params, state, 1, x); - - state->tex_r[0] = state->tex_r[1]; - state->tex_g[0] = state->tex_g[1]; - state->tex_b[0] = state->tex_b[1]; - state->tex_a[0] = state->tex_a[1]; - } - else - { - voodoo_tmu_fetch_and_blend(voodoo, params, state, x); - } - - if ((params->fbzMode & FBZ_CHROMAKEY) && - state->tex_r[0] == params->chromaKey_r && - state->tex_g[0] == params->chromaKey_g && - state->tex_b[0] == params->chromaKey_b) - { - voodoo->fbiChromaFail++; - goto skip_pixel; - } - } - - if (voodoo->trexInit1[0] & (1 << 18)) - { - state->tex_r[0] = state->tex_g[0] = 0; - state->tex_b[0] = voodoo->tmuConfig; - } - - if (cc_localselect_override) - sel = (state->tex_a[0] & 0x80) ? 1 : 0; - else - sel = cc_localselect; - - if (sel) - { - clocal_r = (params->color0 >> 16) & 0xff; - clocal_g = (params->color0 >> 8) & 0xff; - clocal_b = params->color0 & 0xff; - } - else - { - clocal_r = CLAMP(state->ir >> 12); - clocal_g = CLAMP(state->ig >> 12); - clocal_b = CLAMP(state->ib >> 12); - } - - switch (_rgb_sel) - { - case CC_LOCALSELECT_ITER_RGB: /*Iterated RGB*/ - cother_r = CLAMP(state->ir >> 12); - cother_g = CLAMP(state->ig >> 12); - cother_b = CLAMP(state->ib >> 12); - break; - - case CC_LOCALSELECT_TEX: /*TREX Color Output*/ - cother_r = state->tex_r[0]; - cother_g = state->tex_g[0]; - cother_b = state->tex_b[0]; - break; - - case CC_LOCALSELECT_COLOR1: /*Color1 RGB*/ - cother_r = (params->color1 >> 16) & 0xff; - cother_g = (params->color1 >> 8) & 0xff; - cother_b = params->color1 & 0xff; - break; - - case CC_LOCALSELECT_LFB: /*Linear Frame Buffer*/ - cother_r = src_r; - cother_g = src_g; - cother_b = src_b; - break; - } - - switch (cca_localselect) - { - case CCA_LOCALSELECT_ITER_A: - alocal = CLAMP(state->ia >> 12); - break; - - case CCA_LOCALSELECT_COLOR0: - alocal = (params->color0 >> 24) & 0xff; - break; - - case CCA_LOCALSELECT_ITER_Z: - alocal = CLAMP(state->z >> 20); - break; - - default: - fatal("Bad cca_localselect %i\n", cca_localselect); - alocal = 0xff; - break; - } - - switch (a_sel) - { - case A_SEL_ITER_A: - aother = CLAMP(state->ia >> 12); - break; - case A_SEL_TEX: - aother = state->tex_a[0]; - break; - case A_SEL_COLOR1: - aother = (params->color1 >> 24) & 0xff; - break; - default: - fatal("Bad a_sel %i\n", a_sel); - aother = 0; - break; - } - - if (cc_zero_other) - { - src_r = 0; - src_g = 0; - src_b = 0; - } - else - { - src_r = cother_r; - src_g = cother_g; - src_b = cother_b; - } - - if (cca_zero_other) - src_a = 0; - else - src_a = aother; - - if (cc_sub_clocal) - { - src_r -= clocal_r; - src_g -= clocal_g; - src_b -= clocal_b; - } - - if (cca_sub_clocal) - src_a -= alocal; - - switch (cc_mselect) - { - case CC_MSELECT_ZERO: - msel_r = 0; - msel_g = 0; - msel_b = 0; - break; - case CC_MSELECT_CLOCAL: - msel_r = clocal_r; - msel_g = clocal_g; - msel_b = clocal_b; - break; - case CC_MSELECT_AOTHER: - msel_r = aother; - msel_g = aother; - msel_b = aother; - break; - case CC_MSELECT_ALOCAL: - msel_r = alocal; - msel_g = alocal; - msel_b = alocal; - break; - case CC_MSELECT_TEX: - msel_r = state->tex_a[0]; - msel_g = state->tex_a[0]; - msel_b = state->tex_a[0]; - break; - case CC_MSELECT_TEXRGB: - msel_r = state->tex_r[0]; - msel_g = state->tex_g[0]; - msel_b = state->tex_b[0]; - break; - - default: - fatal("Bad cc_mselect %i\n", cc_mselect); - msel_r = 0; - msel_g = 0; - msel_b = 0; - break; - } - - switch (cca_mselect) - { - case CCA_MSELECT_ZERO: - msel_a = 0; - break; - case CCA_MSELECT_ALOCAL: - msel_a = alocal; - break; - case CCA_MSELECT_AOTHER: - msel_a = aother; - break; - case CCA_MSELECT_ALOCAL2: - msel_a = alocal; - break; - case CCA_MSELECT_TEX: - msel_a = state->tex_a[0]; - break; - - default: - fatal("Bad cca_mselect %i\n", cca_mselect); - msel_a = 0; - break; - } - - if (!cc_reverse_blend) - { - msel_r ^= 0xff; - msel_g ^= 0xff; - msel_b ^= 0xff; - } - msel_r++; - msel_g++; - msel_b++; - - if (!cca_reverse_blend) - msel_a ^= 0xff; - msel_a++; - - src_r = (src_r * msel_r) >> 8; - src_g = (src_g * msel_g) >> 8; - src_b = (src_b * msel_b) >> 8; - src_a = (src_a * msel_a) >> 8; - - switch (cc_add) - { - case CC_ADD_CLOCAL: - src_r += clocal_r; - src_g += clocal_g; - src_b += clocal_b; - break; - case CC_ADD_ALOCAL: - src_r += alocal; - src_g += alocal; - src_b += alocal; - break; - case 0: - break; - default: - fatal("Bad cc_add %i\n", cc_add); - } - - if (cca_add) - src_a += alocal; - - src_r = CLAMP(src_r); - src_g = CLAMP(src_g); - src_b = CLAMP(src_b); - src_a = CLAMP(src_a); - - if (cc_invert_output) - { - src_r ^= 0xff; - src_g ^= 0xff; - src_b ^= 0xff; - } - if (cca_invert_output) - src_a ^= 0xff; - - if (params->fogMode & FOG_ENABLE) - APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w); - - if (params->alphaMode & 1) - ALPHA_TEST(src_a); - - if (params->alphaMode & (1 << 4)) - ALPHA_BLEND(src_r, src_g, src_b, src_a); - - if (update) - { - if (dither) - { - if (dither2x2) - { - src_r = dither_rb2x2[src_r][real_y & 1][x & 1]; - src_g = dither_g2x2[src_g][real_y & 1][x & 1]; - src_b = dither_rb2x2[src_b][real_y & 1][x & 1]; - } - else - { - src_r = dither_rb[src_r][real_y & 3][x & 3]; - src_g = dither_g[src_g][real_y & 3][x & 3]; - src_b = dither_rb[src_b][real_y & 3][x & 3]; - } - } - else - { - src_r >>= 3; - src_g >>= 2; - src_b >>= 3; - } - - if (params->fbzMode & FBZ_RGB_WMASK) - fb_mem[x] = src_b | (src_g << 5) | (src_r << 11); - - if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) - aux_mem[x] = new_depth; - } - } - voodoo_output &= ~2; - voodoo->fbiPixelsOut++; -skip_pixel: - if (state->xdir > 0) - { - state->ir += params->dRdX; - state->ig += params->dGdX; - state->ib += params->dBdX; - state->ia += params->dAdX; - state->z += params->dZdX; - state->tmu0_s += params->tmu[0].dSdX; - state->tmu0_t += params->tmu[0].dTdX; - state->tmu0_w += params->tmu[0].dWdX; - state->tmu1_s += params->tmu[1].dSdX; - state->tmu1_t += params->tmu[1].dTdX; - state->tmu1_w += params->tmu[1].dWdX; - state->w += params->dWdX; - } - else - { - state->ir -= params->dRdX; - state->ig -= params->dGdX; - state->ib -= params->dBdX; - state->ia -= params->dAdX; - state->z -= params->dZdX; - state->tmu0_s -= params->tmu[0].dSdX; - state->tmu0_t -= params->tmu[0].dTdX; - state->tmu0_w -= params->tmu[0].dWdX; - state->tmu1_s -= params->tmu[1].dSdX; - state->tmu1_t -= params->tmu[1].dTdX; - state->tmu1_w -= params->tmu[1].dWdX; - state->w -= params->dWdX; - } - - x += state->xdir; - } while (start_x != x2); - - voodoo->pixel_count[odd_even] += state->pixel_count; - voodoo->texel_count[odd_even] += state->texel_count; - voodoo->fbiPixelsIn += state->pixel_count; - - if (voodoo->params.draw_offset == voodoo->params.front_offset) - voodoo->dirty_line[real_y >> 1] = 1; -next_line: - if (SLI_ENABLED) - { - state->base_r += params->dRdY; - state->base_g += params->dGdY; - state->base_b += params->dBdY; - state->base_a += params->dAdY; - state->base_z += params->dZdY; - state->tmu[0].base_s += params->tmu[0].dSdY; - state->tmu[0].base_t += params->tmu[0].dTdY; - state->tmu[0].base_w += params->tmu[0].dWdY; - state->tmu[1].base_s += params->tmu[1].dSdY; - state->tmu[1].base_t += params->tmu[1].dTdY; - state->tmu[1].base_w += params->tmu[1].dWdY; - state->base_w += params->dWdY; - state->xstart += state->dx1; - state->xend += state->dx2; - } - state->base_r += params->dRdY; - state->base_g += params->dGdY; - state->base_b += params->dBdY; - state->base_a += params->dAdY; - state->base_z += params->dZdY; - state->tmu[0].base_s += params->tmu[0].dSdY; - state->tmu[0].base_t += params->tmu[0].dTdY; - state->tmu[0].base_w += params->tmu[0].dWdY; - state->tmu[1].base_s += params->tmu[1].dSdY; - state->tmu[1].base_t += params->tmu[1].dTdY; - state->tmu[1].base_w += params->tmu[1].dWdY; - state->base_w += params->dWdY; - state->xstart += state->dx1; - state->xend += state->dx2; - } - - voodoo->texture_cache[0][params->tex_entry[0]].refcount_r[odd_even]++; - voodoo->texture_cache[1][params->tex_entry[1]].refcount_r[odd_even]++; -} - -static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even) -{ - voodoo_state_t state; - int vertexAy_adjusted; - int vertexCy_adjusted; - int dx, dy; - - uint64_t tempdx, tempdy; - uint64_t tempLOD; - int LOD; - int lodbias; - - voodoo->tri_count++; - - dx = 8 - (params->vertexAx & 0xf); - if ((params->vertexAx & 0xf) > 8) - dx += 16; - dy = 8 - (params->vertexAy & 0xf); - if ((params->vertexAy & 0xf) > 8) - dy += 16; - -/* 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, - (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0, - (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0, - (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0, - (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);*/ - - state.base_r = params->startR; - state.base_g = params->startG; - state.base_b = params->startB; - state.base_a = params->startA; - state.base_z = params->startZ; - state.tmu[0].base_s = params->tmu[0].startS; - state.tmu[0].base_t = params->tmu[0].startT; - state.tmu[0].base_w = params->tmu[0].startW; - state.tmu[1].base_s = params->tmu[1].startS; - state.tmu[1].base_t = params->tmu[1].startT; - state.tmu[1].base_w = params->tmu[1].startW; - state.base_w = params->startW; - - if (params->fbzColorPath & FBZ_PARAM_ADJUST) - { - state.base_r += (dx*params->dRdX + dy*params->dRdY) >> 4; - state.base_g += (dx*params->dGdX + dy*params->dGdY) >> 4; - state.base_b += (dx*params->dBdX + dy*params->dBdY) >> 4; - state.base_a += (dx*params->dAdX + dy*params->dAdY) >> 4; - state.base_z += (dx*params->dZdX + dy*params->dZdY) >> 4; - state.tmu[0].base_s += (dx*params->tmu[0].dSdX + dy*params->tmu[0].dSdY) >> 4; - state.tmu[0].base_t += (dx*params->tmu[0].dTdX + dy*params->tmu[0].dTdY) >> 4; - state.tmu[0].base_w += (dx*params->tmu[0].dWdX + dy*params->tmu[0].dWdY) >> 4; - state.tmu[1].base_s += (dx*params->tmu[1].dSdX + dy*params->tmu[1].dSdY) >> 4; - state.tmu[1].base_t += (dx*params->tmu[1].dTdX + dy*params->tmu[1].dTdY) >> 4; - state.tmu[1].base_w += (dx*params->tmu[1].dWdX + dy*params->tmu[1].dWdY) >> 4; - state.base_w += (dx*params->dWdX + dy*params->dWdY) >> 4; - } - - tris++; - - state.vertexAy = params->vertexAy & ~0xffff0000; - if (state.vertexAy & 0x8000) - state.vertexAy |= 0xffff0000; - state.vertexBy = params->vertexBy & ~0xffff0000; - if (state.vertexBy & 0x8000) - state.vertexBy |= 0xffff0000; - state.vertexCy = params->vertexCy & ~0xffff0000; - if (state.vertexCy & 0x8000) - state.vertexCy |= 0xffff0000; - - state.vertexAx = params->vertexAx & ~0xffff0000; - if (state.vertexAx & 0x8000) - state.vertexAx |= 0xffff0000; - state.vertexBx = params->vertexBx & ~0xffff0000; - if (state.vertexBx & 0x8000) - state.vertexBx |= 0xffff0000; - state.vertexCx = params->vertexCx & ~0xffff0000; - if (state.vertexCx & 0x8000) - state.vertexCx |= 0xffff0000; - - vertexAy_adjusted = (state.vertexAy+7) >> 4; - vertexCy_adjusted = (state.vertexCy+7) >> 4; - - if (state.vertexBy - state.vertexAy) - state.dxAB = (int)((((int64_t)state.vertexBx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexBy - state.vertexAy); - else - state.dxAB = 0; - if (state.vertexCy - state.vertexAy) - state.dxAC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexCy - state.vertexAy); - else - state.dxAC = 0; - if (state.vertexCy - state.vertexBy) - state.dxBC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexBx << 12)) << 4) / (int)(state.vertexCy - state.vertexBy); - else - state.dxBC = 0; - - state.lod_min[0] = (params->tLOD[0] & 0x3f) << 6; - state.lod_max[0] = ((params->tLOD[0] >> 6) & 0x3f) << 6; - if (state.lod_max[0] > 0x800) - state.lod_max[0] = 0x800; - state.lod_min[1] = (params->tLOD[1] & 0x3f) << 6; - state.lod_max[1] = ((params->tLOD[1] >> 6) & 0x3f) << 6; - if (state.lod_max[1] > 0x800) - state.lod_max[1] = 0x800; - - state.xstart = state.xend = state.vertexAx << 8; - state.xdir = params->sign ? -1 : 1; - - state.y = (state.vertexAy + 8) >> 4; - state.ydir = 1; - - - tempdx = (params->tmu[0].dSdX >> 14) * (params->tmu[0].dSdX >> 14) + (params->tmu[0].dTdX >> 14) * (params->tmu[0].dTdX >> 14); - tempdy = (params->tmu[0].dSdY >> 14) * (params->tmu[0].dSdY >> 14) + (params->tmu[0].dTdY >> 14) * (params->tmu[0].dTdY >> 14); - - if (tempdx > tempdy) - tempLOD = tempdx; - else - tempLOD = tempdy; - - LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256); - LOD >>= 2; - - lodbias = (params->tLOD[0] >> 12) & 0x3f; - if (lodbias & 0x20) - lodbias |= ~0x3f; - state.tmu[0].lod = LOD + (lodbias << 6); - - - tempdx = (params->tmu[1].dSdX >> 14) * (params->tmu[1].dSdX >> 14) + (params->tmu[1].dTdX >> 14) * (params->tmu[1].dTdX >> 14); - tempdy = (params->tmu[1].dSdY >> 14) * (params->tmu[1].dSdY >> 14) + (params->tmu[1].dTdY >> 14) * (params->tmu[1].dTdY >> 14); - - if (tempdx > tempdy) - tempLOD = tempdx; - else - tempLOD = tempdy; - - LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256); - LOD >>= 2; - - lodbias = (params->tLOD[1] >> 12) & 0x3f; - if (lodbias & 0x20) - lodbias |= ~0x3f; - state.tmu[1].lod = LOD + (lodbias << 6); - - - voodoo_half_triangle(voodoo, params, &state, vertexAy_adjusted, vertexCy_adjusted, odd_even); -} - -static inline void wake_render_thread(voodoo_t *voodoo) -{ - thread_set_event(voodoo->wake_render_thread[0]); /*Wake up render thread if moving from idle*/ - if (voodoo->render_threads == 2) - thread_set_event(voodoo->wake_render_thread[1]); /*Wake up render thread if moving from idle*/ -} - -static inline void wait_for_render_thread_idle(voodoo_t *voodoo) -{ - 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])) - { - wake_render_thread(voodoo); - if (!PARAM_EMPTY_1 || voodoo->render_voodoo_busy[0]) - thread_wait_event(voodoo->render_not_full_event[0], 1); - if (voodoo->render_threads == 2 && (!PARAM_EMPTY_2 || voodoo->render_voodoo_busy[1])) - thread_wait_event(voodoo->render_not_full_event[1], 1); - } -} - -static void render_thread(void *param, int odd_even) -{ - voodoo_t *voodoo = (voodoo_t *)param; - - while (1) - { - thread_set_event(voodoo->render_not_full_event[odd_even]); - thread_wait_event(voodoo->wake_render_thread[odd_even], -1); - thread_reset_event(voodoo->wake_render_thread[odd_even]); - voodoo->render_voodoo_busy[odd_even] = 1; - - while (!(odd_even ? PARAM_EMPTY_2 : PARAM_EMPTY_1)) - { - uint64_t start_time = timer_read(); - uint64_t end_time; - voodoo_params_t *params = &voodoo->params_buffer[voodoo->params_read_idx[odd_even] & PARAM_MASK]; - - voodoo_triangle(voodoo, params, odd_even); - - voodoo->params_read_idx[odd_even]++; - - if ((odd_even ? PARAM_ENTRIES_2 : PARAM_ENTRIES_1) > (PARAM_SIZE - 10)) - thread_set_event(voodoo->render_not_full_event[odd_even]); - - end_time = timer_read(); - voodoo->render_time[odd_even] += end_time - start_time; - } - - voodoo->render_voodoo_busy[odd_even] = 0; - } -} - -static void render_thread_1(void *param) -{ - render_thread(param, 0); -} -static void render_thread_2(void *param) -{ - render_thread(param, 1); -} - -static inline void queue_triangle(voodoo_t *voodoo, voodoo_params_t *params) -{ - voodoo_params_t *params_new = &voodoo->params_buffer[voodoo->params_write_idx & PARAM_MASK]; - - while (PARAM_FULL_1 || (voodoo->render_threads == 2 && PARAM_FULL_2)) - { - thread_reset_event(voodoo->render_not_full_event[0]); - if (voodoo->render_threads == 2) - thread_reset_event(voodoo->render_not_full_event[1]); - if (PARAM_FULL_1) - { - thread_wait_event(voodoo->render_not_full_event[0], -1); /*Wait for room in ringbuffer*/ - } - if (voodoo->render_threads == 2 && PARAM_FULL_2) - { - thread_wait_event(voodoo->render_not_full_event[1], -1); /*Wait for room in ringbuffer*/ - } - } - - use_texture(voodoo, params, 0); - if (voodoo->dual_tmus) - use_texture(voodoo, params, 1); - - memcpy(params_new, params, sizeof(voodoo_params_t)); - - voodoo->params_write_idx++; - - if (PARAM_ENTRIES_1 < 4 || (voodoo->render_threads == 2 && PARAM_ENTRIES_2 < 4)) - wake_render_thread(voodoo); -} - -static void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params) -{ - int y; - int low_y, high_y; - - if (params->fbzMode & (1 << 17)) - { - high_y = voodoo->v_disp - params->clipLowY; - low_y = voodoo->v_disp - params->clipHighY; - } - else - { - low_y = params->clipLowY; - high_y = params->clipHighY; - } - - if (params->fbzMode & FBZ_RGB_WMASK) - { - int r, g, b; - uint16_t col; - - r = ((params->color1 >> 16) >> 3) & 0x1f; - g = ((params->color1 >> 8) >> 2) & 0x3f; - b = (params->color1 >> 3) & 0x1f; - col = b | (g << 5) | (r << 11); - - if (SLI_ENABLED) - { - for (y = low_y; y < high_y; y += 2) - { - uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask]; - int x; - - for (x = params->clipLeft; x < params->clipRight; x++) - cbuf[x] = col; - } - } - else - { - for (y = low_y; y < high_y; y++) - { - uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + y*voodoo->row_width) & voodoo->fb_mask]; - int x; - - for (x = params->clipLeft; x < params->clipRight; x++) - cbuf[x] = col; - } - } - } - if (params->fbzMode & FBZ_DEPTH_WMASK) - { - if (SLI_ENABLED) - { - for (y = low_y; y < high_y; y += 2) - { - uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask]; - int x; - - for (x = params->clipLeft; x < params->clipRight; x++) - abuf[x] = params->zaColor & 0xffff; - } - } - else - { - for (y = low_y; y < high_y; y++) - { - uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + y*voodoo->row_width) & voodoo->fb_mask]; - int x; - - for (x = params->clipLeft; x < params->clipRight; x++) - abuf[x] = params->zaColor & 0xffff; - } - } - } -} - -enum -{ - SETUPMODE_RGB = (1 << 0), - SETUPMODE_ALPHA = (1 << 1), - SETUPMODE_Z = (1 << 2), - SETUPMODE_Wb = (1 << 3), - SETUPMODE_W0 = (1 << 4), - SETUPMODE_S0_T0 = (1 << 5), - SETUPMODE_W1 = (1 << 6), - SETUPMODE_S1_T1 = (1 << 7), - - SETUPMODE_STRIP_MODE = (1 << 16), - SETUPMODE_CULLING_ENABLE = (1 << 17), - SETUPMODE_CULLING_SIGN = (1 << 18), - SETUPMODE_DISABLE_PINGPONG = (1 << 19) -}; - -static void triangle_setup(voodoo_t *voodoo) -{ - float dxAB, dxBC, dyAB, dyBC; - float area; - int va = 0, vb = 1, vc = 2; - int reverse_cull = 0; - vert_t verts[3]; - - verts[0] = voodoo->verts[0]; - verts[1] = voodoo->verts[1]; - verts[2] = voodoo->verts[2]; - - if (verts[0].sVy < verts[1].sVy) - { - if (verts[1].sVy < verts[2].sVy) - { - /* V1>V0, V2>V1, V2>V1>V0*/ - va = 0; /*OK*/ - vb = 1; - vc = 2; - } - else - { - /* V1>V0, V1>V2*/ - if (verts[0].sVy < verts[2].sVy) - { - /* V1>V0, V1>V2, V2>V0, V1>V2>V0*/ - va = 0; - vb = 2; - vc = 1; - reverse_cull = 1; - } - else - { - /* V1>V0, V1>V2, V0>V2, V1>V0>V2*/ - va = 2; - vb = 0; - vc = 1; - } - } - } - else - { - if (verts[1].sVy < verts[2].sVy) - { - /* V0>V1, V2>V1*/ - if (verts[0].sVy < verts[2].sVy) - { - /* V0>V1, V2>V1, V2>V0, V2>V0>V1*/ - va = 1; - vb = 0; - vc = 2; - reverse_cull = 1; - } - else - { - /* V0>V1, V2>V1, V0>V2, V0>V2>V1*/ - va = 1; - vb = 2; - vc = 0; - } - } - else - { - /*V0>V1>V2*/ - va = 2; - vb = 1; - vc = 0; - reverse_cull = 1; - } - } - - dxAB = verts[va].sVx - verts[vb].sVx; - dxBC = verts[vb].sVx - verts[vc].sVx; - dyAB = verts[va].sVy - verts[vb].sVy; - dyBC = verts[vb].sVy - verts[vc].sVy; - - area = dxAB * dyBC - dxBC * dyAB; - - if (area == 0.0) - { - if ((voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) && - !(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG)) - voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN; - - return; - } - - dxAB /= area; - dxBC /= area; - dyAB /= area; - dyBC /= area; - - if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) - { - int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN; - int sign = (area < 0.0); - - if (!(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG)) - voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN; - - if (reverse_cull) - sign = !sign; - - if (cull_sign && sign) - return; - if (!cull_sign && !sign) - return; - } - - voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(verts[va].sVx * 16.0f) & 0xffff); - voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(verts[va].sVy * 16.0f) & 0xffff); - voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(verts[vb].sVx * 16.0f) & 0xffff); - voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(verts[vb].sVy * 16.0f) & 0xffff); - voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(verts[vc].sVx * 16.0f) & 0xffff); - voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(verts[vc].sVy * 16.0f) & 0xffff); - - if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy) - fatal("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy); - - if (voodoo->sSetupMode & SETUPMODE_RGB) - { - voodoo->params.startR = (int32_t)(verts[va].sRed * 4096.0f); - voodoo->params.dRdX = (int32_t)(((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f); - voodoo->params.dRdY = (int32_t)(((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f); - voodoo->params.startG = (int32_t)(verts[va].sGreen * 4096.0f); - voodoo->params.dGdX = (int32_t)(((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f); - voodoo->params.dGdY = (int32_t)(((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f); - voodoo->params.startB = (int32_t)(verts[va].sBlue * 4096.0f); - voodoo->params.dBdX = (int32_t)(((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f); - voodoo->params.dBdY = (int32_t)(((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f); - } - if (voodoo->sSetupMode & SETUPMODE_ALPHA) - { - voodoo->params.startA = (int32_t)(verts[va].sAlpha * 4096.0f); - voodoo->params.dAdX = (int32_t)(((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f); - voodoo->params.dAdY = (int32_t)(((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f); - } - if (voodoo->sSetupMode & SETUPMODE_Z) - { - voodoo->params.startZ = (int32_t)(verts[va].sVz * 4096.0f); - voodoo->params.dZdX = (int32_t)(((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f); - voodoo->params.dZdY = (int32_t)(((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f); - } - if (voodoo->sSetupMode & SETUPMODE_Wb) - { - voodoo->params.startW = (int64_t)(verts[va].sWb * 4294967296.0f); - voodoo->params.dWdX = (int64_t)(((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f); - voodoo->params.dWdY = (int64_t)(((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f); - voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW; - voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX; - voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY; - } - if (voodoo->sSetupMode & SETUPMODE_W0) - { - voodoo->params.tmu[0].startW = (int64_t)(verts[va].sW0 * 4294967296.0f); - voodoo->params.tmu[0].dWdX = (int64_t)(((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dWdY = (int64_t)(((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f); - voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW; - voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX; - voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY; - } - if (voodoo->sSetupMode & SETUPMODE_S0_T0) - { - voodoo->params.tmu[0].startS = (int64_t)(verts[va].sS0 * 4294967296.0f); - voodoo->params.tmu[0].dSdX = (int64_t)(((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dSdY = (int64_t)(((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f); - voodoo->params.tmu[0].startT = (int64_t)(verts[va].sT0 * 4294967296.0f); - voodoo->params.tmu[0].dTdX = (int64_t)(((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f); - voodoo->params.tmu[0].dTdY = (int64_t)(((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f); - voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS; - voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX; - voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY; - voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT; - voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX; - voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY; - } - if (voodoo->sSetupMode & SETUPMODE_W1) - { - voodoo->params.tmu[1].startW = (int64_t)(verts[va].sW1 * 4294967296.0f); - voodoo->params.tmu[1].dWdX = (int64_t)(((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dWdY = (int64_t)(((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f); - } - if (voodoo->sSetupMode & SETUPMODE_S1_T1) - { - voodoo->params.tmu[1].startS = (int64_t)(verts[va].sS1 * 4294967296.0f); - voodoo->params.tmu[1].dSdX = (int64_t)(((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dSdY = (int64_t)(((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f); - voodoo->params.tmu[1].startT = (int64_t)(verts[va].sT1 * 4294967296.0f); - voodoo->params.tmu[1].dTdX = (int64_t)(((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f); - voodoo->params.tmu[1].dTdY = (int64_t)(((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f); - } - - voodoo->params.sign = (area < 0.0); - - if (voodoo->ncc_dirty[0]) - voodoo_update_ncc(voodoo, 0); - if (voodoo->ncc_dirty[1]) - voodoo_update_ncc(voodoo, 1); - voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; - - queue_triangle(voodoo, &voodoo->params); -} - -enum -{ - BLIT_COMMAND_SCREEN_TO_SCREEN = 0, - BLIT_COMMAND_CPU_TO_SCREEN = 1, - BLIT_COMMAND_RECT_FILL = 2, - BLIT_COMMAND_SGRAM_FILL = 3 -}; - -enum -{ - BLIT_SRC_1BPP = (0 << 3), - BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3), - BLIT_SRC_16BPP = (2 << 3), - BLIT_SRC_24BPP = (3 << 3), - BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3), - BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3) -}; - -enum -{ - BLIT_SRC_RGB_ARGB = (0 << 6), - BLIT_SRC_RGB_ABGR = (1 << 6), - BLIT_SRC_RGB_RGBA = (2 << 6), - BLIT_SRC_RGB_BGRA = (3 << 6) -}; - -enum -{ - BLIT_COMMAND_MASK = 7, - BLIT_SRC_FORMAT = (7 << 3), - BLIT_SRC_RGB_FORMAT = (3 << 6), - BLIT_SRC_CHROMA = (1 << 10), - BLIT_DST_CHROMA = (1 << 12), - BLIT_CLIPPING_ENABLED = (1 << 16) -}; - -enum -{ - BLIT_ROP_DST_PASS = (1 << 0), - BLIT_ROP_SRC_PASS = (1 << 1) -}; - -#define MIX(src_dat, dst_dat, rop) \ - switch (rop) \ - { \ - case 0x0: dst_dat = 0; break; \ - case 0x1: dst_dat = ~(src_dat | dst_dat); break; \ - case 0x2: dst_dat = ~src_dat & dst_dat; break; \ - case 0x3: dst_dat = ~src_dat; break; \ - case 0x4: dst_dat = src_dat & ~dst_dat; break; \ - case 0x5: dst_dat = ~dst_dat; break; \ - case 0x6: dst_dat = src_dat ^ dst_dat; break; \ - case 0x7: dst_dat = ~(src_dat & dst_dat); break; \ - case 0x8: dst_dat = src_dat & dst_dat; break; \ - case 0x9: dst_dat = ~(src_dat ^ dst_dat); break; \ - case 0xa: dst_dat = dst_dat; break; \ - case 0xb: dst_dat = ~src_dat | dst_dat; break; \ - case 0xc: dst_dat = src_dat; break; \ - case 0xd: dst_dat = src_dat | ~dst_dat; break; \ - case 0xe: dst_dat = src_dat | dst_dat; break; \ - case 0xf: dst_dat = 0xffff; break; \ - } - -static void blit_start(voodoo_t *voodoo) -{ - uint64_t dat64; - int size_x = ABS(voodoo->bltSizeX), size_y = ABS(voodoo->bltSizeY); - int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1; - int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1; - int dst_x; - int src_y = voodoo->bltSrcY & 0x7ff, dst_y = voodoo->bltDstY & 0x7ff; - int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32*2) : (voodoo->bltSrcXYStride & 0xff8); - int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8); - uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8); - uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); - int x, y; - -/* pclog("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n", - voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/ - - wait_for_render_thread_idle(voodoo); - - switch (voodoo->bltCommand & BLIT_COMMAND_MASK) - { - case BLIT_COMMAND_SCREEN_TO_SCREEN: - for (y = 0; y <= size_y; y++) - { - uint16_t *src = (uint16_t *)&voodoo->fb_mem[src_base_addr + src_y*src_stride]; - uint16_t *dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride]; - int src_x = voodoo->bltSrcX, dst_x = voodoo->bltDstX; - - for (x = 0; x <= size_x; x++) - { - uint16_t src_dat = src[src_x]; - uint16_t dst_dat = dst[dst_x]; - int rop = 0; - - if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) - { - if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || - dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY) - goto skip_pixel_blit; - } - - if (voodoo->bltCommand & BLIT_SRC_CHROMA) - { - int r = (src_dat >> 11); - int g = (src_dat >> 5) & 0x3f; - int b = src_dat & 0x1f; - - if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && - g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && - b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB) - rop |= BLIT_ROP_SRC_PASS; - } - if (voodoo->bltCommand & BLIT_DST_CHROMA) - { - int r = (dst_dat >> 11); - int g = (dst_dat >> 5) & 0x3f; - int b = dst_dat & 0x1f; - - if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && - g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && - b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB) - rop |= BLIT_ROP_DST_PASS; - } - - MIX(src_dat, dst_dat, voodoo->bltRop[rop]); - - dst[dst_x] = dst_dat; -skip_pixel_blit: - src_x += x_dir; - dst_x += x_dir; - } - - src_y += y_dir; - dst_y += y_dir; - } - break; - - case BLIT_COMMAND_CPU_TO_SCREEN: - voodoo->blt.dst_x = voodoo->bltDstX; - voodoo->blt.dst_y = voodoo->bltDstY; - voodoo->blt.cur_x = 0; - voodoo->blt.size_x = size_x; - voodoo->blt.size_y = size_y; - voodoo->blt.x_dir = x_dir; - voodoo->blt.y_dir = y_dir; - voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8); - break; - - case BLIT_COMMAND_RECT_FILL: - for (y = 0; y <= size_y; y++) - { - uint16_t *dst; - int dst_x = voodoo->bltDstX; - - if (SLI_ENABLED) - { - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1))) - goto skip_line_fill; - dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride]; - } - else - dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride]; - - for (x = 0; x <= size_x; x++) - { - if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) - { - if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || - dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY) - goto skip_pixel_fill; - } - - dst[dst_x] = voodoo->bltColorFg; -skip_pixel_fill: - dst_x += x_dir; - } -skip_line_fill: - dst_y += y_dir; - } - break; - - case BLIT_COMMAND_SGRAM_FILL: - /*32x32 tiles - 2kb*/ - dst_y = voodoo->bltDstY & 0x3ff; - size_x = voodoo->bltSizeX & 0x1ff; //512*8 = 4kb - size_y = voodoo->bltSizeY & 0x3ff; - - dat64 = voodoo->bltColorFg | ((uint64_t)voodoo->bltColorFg << 16) | - ((uint64_t)voodoo->bltColorFg << 32) | ((uint64_t)voodoo->bltColorFg << 48); - - for (y = 0; y <= size_y; y++) - { - uint64_t *dst; - - /*This may be wrong*/ - if (!y) - { - dst_x = voodoo->bltDstX & 0x1ff; - size_x = 511 - dst_x; - } - else if (y < size_y) - { - dst_x = 0; - size_x = 511; - } - else - { - dst_x = 0; - size_x = voodoo->bltSizeX & 0x1ff; - } - - dst = (uint64_t *)&voodoo->fb_mem[(dst_y*512*8 + dst_x*8) & voodoo->fb_mask]; - - for (x = 0; x <= size_x; x++) - dst[x] = dat64; - - dst_y++; - } - break; - - default: - fatal("bad blit command %08x\n", voodoo->bltCommand); - } -} - -static void blit_data(voodoo_t *voodoo, uint32_t data) -{ - int src_bits = 32; - uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); - uint32_t addr; - uint16_t *dst; - - if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN) - return; - - if (SLI_ENABLED) - { - addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride; - dst = (uint16_t *)&voodoo->fb_mem[addr]; - } - else - { - addr = base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride; - dst = (uint16_t *)&voodoo->fb_mem[addr]; - } - - if (addr >= voodoo->front_offset && voodoo->row_width) - { - int y = (addr - voodoo->front_offset) / voodoo->row_width; - if (y < voodoo->v_disp) - voodoo->dirty_line[y] = 2; - } - - while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x) - { - int r = 0, g = 0, b = 0; - uint16_t src_dat = 0, dst_dat; - int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x); - int rop = 0; - - switch (voodoo->bltCommand & BLIT_SRC_FORMAT) - { - case BLIT_SRC_1BPP: case BLIT_SRC_1BPP_BYTE_PACKED: - src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg; - data >>= 1; - src_bits--; - break; - case BLIT_SRC_16BPP: - switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) - { - case BLIT_SRC_RGB_ARGB: case BLIT_SRC_RGB_RGBA: - src_dat = data & 0xffff; - break; - case BLIT_SRC_RGB_ABGR: case BLIT_SRC_RGB_BGRA: - src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11); - break; - } - data >>= 16; - src_bits -= 16; - break; - case BLIT_SRC_24BPP: case BLIT_SRC_24BPP_DITHER_2X2: case BLIT_SRC_24BPP_DITHER_4X4: - switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) - { - case BLIT_SRC_RGB_ARGB: - r = (data >> 16) & 0xff; - g = (data >> 8) & 0xff; - b = data & 0xff; - break; - case BLIT_SRC_RGB_ABGR: - r = data & 0xff; - g = (data >> 8) & 0xff; - b = (data >> 16) & 0xff; - break; - case BLIT_SRC_RGB_RGBA: - r = (data >> 24) & 0xff; - g = (data >> 16) & 0xff; - b = (data >> 8) & 0xff; - break; - case BLIT_SRC_RGB_BGRA: - r = (data >> 8) & 0xff; - g = (data >> 16) & 0xff; - b = (data >> 24) & 0xff; - break; - } - switch (voodoo->bltCommand & BLIT_SRC_FORMAT) - { - case BLIT_SRC_24BPP: - src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); - break; - case BLIT_SRC_24BPP_DITHER_2X2: - r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1]; - g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1]; - b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1]; - src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); - break; - case BLIT_SRC_24BPP_DITHER_4X4: - r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3]; - g = dither_g[g][voodoo->blt.dst_y & 3][x & 3]; - b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3]; - src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); - break; - } - src_bits = 0; - break; - } - - if (SLI_ENABLED) - { - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1))) - goto skip_pixel; - } - - if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) - { - if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight || - voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY) - goto skip_pixel; - } - - dst_dat = dst[x]; - - if (voodoo->bltCommand & BLIT_SRC_CHROMA) - { - r = (src_dat >> 11); - g = (src_dat >> 5) & 0x3f; - b = src_dat & 0x1f; - - if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && - g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && - b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB) - rop |= BLIT_ROP_SRC_PASS; - } - if (voodoo->bltCommand & BLIT_DST_CHROMA) - { - r = (dst_dat >> 11); - g = (dst_dat >> 5) & 0x3f; - b = dst_dat & 0x1f; - - if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && - g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && - b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB) - rop |= BLIT_ROP_DST_PASS; - } - - MIX(src_dat, dst_dat, voodoo->bltRop[rop]); - - dst[x] = dst_dat; - -skip_pixel: - voodoo->blt.cur_x++; - } - - if (voodoo->blt.cur_x > voodoo->blt.size_x) - { - voodoo->blt.size_y--; - if (voodoo->blt.size_y >= 0) - { - voodoo->blt.cur_x = 0; - voodoo->blt.dst_y += voodoo->blt.y_dir; - } - } -} - -enum -{ - CHIP_FBI = 0x1, - CHIP_TREX0 = 0x2, - CHIP_TREX1 = 0x4, - CHIP_TREX2 = 0x8 -}; - -static void wait_for_swap_complete(voodoo_t *voodoo) -{ - while (voodoo->swap_pending) - { - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); - if ((voodoo->swap_pending && voodoo->flush) || FIFO_FULL) - { - /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/ - memset(voodoo->dirty_line, 1, 1024); - voodoo->front_offset = voodoo->params.front_offset; - if (voodoo->swap_count > 0) - voodoo->swap_count--; - voodoo->swap_pending = 0; - break; - } - } -} - -static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - union - { - uint32_t i; - float f; - } tempif; - int ad21 = addr & (1 << 21); - int chip = (addr >> 10) & 0xf; - if (!chip) - chip = 0xf; - - tempif.i = val; -//pclog("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip); - addr &= 0x3fc; - - if ((voodoo->fbiInit3 & FBIINIT3_REMAP) && addr < 0x100 && ad21) - addr |= 0x400; - switch (addr) - { - case SST_swapbufferCMD: -// pclog(" start swap buffer command\n"); - - if (TRIPLE_BUFFER) - { - voodoo->disp_buffer = (voodoo->disp_buffer + 1) % 3; - voodoo->draw_buffer = (voodoo->draw_buffer + 1) % 3; - } - else - { - voodoo->disp_buffer = !voodoo->disp_buffer; - voodoo->draw_buffer = !voodoo->draw_buffer; - } - voodoo_recalc(voodoo); - - voodoo->params.swapbufferCMD = val; - - pclog("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0); -// voodoo->front_offset = params->front_offset; - wait_for_render_thread_idle(voodoo); - if (!(val & 1)) - { - memset(voodoo->dirty_line, 1, 1024); - voodoo->front_offset = voodoo->params.front_offset; - if (voodoo->swap_count > 0) - voodoo->swap_count--; - } - else if (TRIPLE_BUFFER) - { - if (voodoo->swap_pending) - wait_for_swap_complete(voodoo); - - voodoo->swap_interval = (val >> 1) & 0xff; - voodoo->swap_offset = voodoo->params.front_offset; - voodoo->swap_pending = 1; - } - else - { - voodoo->swap_interval = (val >> 1) & 0xff; - voodoo->swap_offset = voodoo->params.front_offset; - voodoo->swap_pending = 1; - - wait_for_swap_complete(voodoo); - } - voodoo->cmd_read++; - break; - - case SST_vertexAx: case SST_remap_vertexAx: - voodoo->params.vertexAx = val & 0xffff; - break; - case SST_vertexAy: case SST_remap_vertexAy: - voodoo->params.vertexAy = val & 0xffff; - break; - case SST_vertexBx: case SST_remap_vertexBx: - voodoo->params.vertexBx = val & 0xffff; - break; - case SST_vertexBy: case SST_remap_vertexBy: - voodoo->params.vertexBy = val & 0xffff; - break; - case SST_vertexCx: case SST_remap_vertexCx: - voodoo->params.vertexCx = val & 0xffff; - break; - case SST_vertexCy: case SST_remap_vertexCy: - voodoo->params.vertexCy = val & 0xffff; - break; - - case SST_startR: case SST_remap_startR: - voodoo->params.startR = val & 0xffffff; - break; - case SST_startG: case SST_remap_startG: - voodoo->params.startG = val & 0xffffff; - break; - case SST_startB: case SST_remap_startB: - voodoo->params.startB = val & 0xffffff; - break; - case SST_startZ: case SST_remap_startZ: - voodoo->params.startZ = val; - break; - case SST_startA: case SST_remap_startA: - voodoo->params.startA = val & 0xffffff; - break; - case SST_startS: case SST_remap_startS: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startS = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startS = ((int64_t)(int32_t)val) << 14; - break; - case SST_startT: case SST_remap_startT: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startT = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startT = ((int64_t)(int32_t)val) << 14; - break; - case SST_startW: case SST_remap_startW: - if (chip & CHIP_FBI) - voodoo->params.startW = (int64_t)(int32_t)val << 2; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startW = (int64_t)(int32_t)val << 2; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startW = (int64_t)(int32_t)val << 2; - break; - - case SST_dRdX: case SST_remap_dRdX: - voodoo->params.dRdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dGdX: case SST_remap_dGdX: - voodoo->params.dGdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dBdX: case SST_remap_dBdX: - voodoo->params.dBdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dZdX: case SST_remap_dZdX: - voodoo->params.dZdX = val; - break; - case SST_dAdX: case SST_remap_dAdX: - voodoo->params.dAdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dSdX: case SST_remap_dSdX: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dSdX = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dSdX = ((int64_t)(int32_t)val) << 14; - break; - case SST_dTdX: case SST_remap_dTdX: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dTdX = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dTdX = ((int64_t)(int32_t)val) << 14; - break; - case SST_dWdX: case SST_remap_dWdX: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dWdX = (int64_t)(int32_t)val << 2; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dWdX = (int64_t)(int32_t)val << 2; - if (chip & CHIP_FBI) - voodoo->params.dWdX = (int64_t)(int32_t)val << 2; - break; - - case SST_dRdY: case SST_remap_dRdY: - voodoo->params.dRdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dGdY: case SST_remap_dGdY: - voodoo->params.dGdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dBdY: case SST_remap_dBdY: - voodoo->params.dBdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dZdY: case SST_remap_dZdY: - voodoo->params.dZdY = val; - break; - case SST_dAdY: case SST_remap_dAdY: - voodoo->params.dAdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); - break; - case SST_dSdY: case SST_remap_dSdY: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dSdY = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dSdY = ((int64_t)(int32_t)val) << 14; - break; - case SST_dTdY: case SST_remap_dTdY: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dTdY = ((int64_t)(int32_t)val) << 14; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dTdY = ((int64_t)(int32_t)val) << 14; - break; - case SST_dWdY: case SST_remap_dWdY: - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dWdY = (int64_t)(int32_t)val << 2; - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dWdY = (int64_t)(int32_t)val << 2; - if (chip & CHIP_FBI) - voodoo->params.dWdY = (int64_t)(int32_t)val << 2; - break; - - case SST_triangleCMD: case SST_remap_triangleCMD: - voodoo->params.sign = val & (1 << 31); - - if (voodoo->ncc_dirty[0]) - voodoo_update_ncc(voodoo, 0); - if (voodoo->ncc_dirty[1]) - voodoo_update_ncc(voodoo, 1); - voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; - - queue_triangle(voodoo, &voodoo->params); - - voodoo->cmd_read++; - break; - - case SST_fvertexAx: case SST_remap_fvertexAx: - voodoo->fvertexAx.i = val; - voodoo->params.vertexAx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAx.f * 16.0f) & 0xffff; - break; - case SST_fvertexAy: case SST_remap_fvertexAy: - voodoo->fvertexAy.i = val; - voodoo->params.vertexAy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAy.f * 16.0f) & 0xffff; - break; - case SST_fvertexBx: case SST_remap_fvertexBx: - voodoo->fvertexBx.i = val; - voodoo->params.vertexBx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBx.f * 16.0f) & 0xffff; - break; - case SST_fvertexBy: case SST_remap_fvertexBy: - voodoo->fvertexBy.i = val; - voodoo->params.vertexBy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBy.f * 16.0f) & 0xffff; - break; - case SST_fvertexCx: case SST_remap_fvertexCx: - voodoo->fvertexCx.i = val; - voodoo->params.vertexCx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCx.f * 16.0f) & 0xffff; - break; - case SST_fvertexCy: case SST_remap_fvertexCy: - voodoo->fvertexCy.i = val; - voodoo->params.vertexCy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCy.f * 16.0f) & 0xffff; - break; - - case SST_fstartR: case SST_remap_fstartR: - tempif.i = val; - voodoo->params.startR = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartG: case SST_remap_fstartG: - tempif.i = val; - voodoo->params.startG = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartB: case SST_remap_fstartB: - tempif.i = val; - voodoo->params.startB = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartZ: case SST_remap_fstartZ: - tempif.i = val; - voodoo->params.startZ = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartA: case SST_remap_fstartA: - tempif.i = val; - voodoo->params.startA = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fstartS: case SST_remap_fstartS: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startS = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startS = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fstartT: case SST_remap_fstartT: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startT = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startT = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fstartW: case SST_remap_fstartW: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].startW = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].startW = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_FBI) - voodoo->params.startW = (int64_t)(tempif.f * 4294967296.0f); - break; - - case SST_fdRdX: case SST_remap_fdRdX: - tempif.i = val; - voodoo->params.dRdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdGdX: case SST_remap_fdGdX: - tempif.i = val; - voodoo->params.dGdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdBdX: case SST_remap_fdBdX: - tempif.i = val; - voodoo->params.dBdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdZdX: case SST_remap_fdZdX: - tempif.i = val; - voodoo->params.dZdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdAdX: case SST_remap_fdAdX: - tempif.i = val; - voodoo->params.dAdX = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdSdX: case SST_remap_fdSdX: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dSdX = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dSdX = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fdTdX: case SST_remap_fdTdX: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dTdX = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dTdX = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fdWdX: case SST_remap_fdWdX: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dWdX = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dWdX = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_FBI) - voodoo->params.dWdX = (int64_t)(tempif.f * 4294967296.0f); - break; - - case SST_fdRdY: case SST_remap_fdRdY: - tempif.i = val; - voodoo->params.dRdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdGdY: case SST_remap_fdGdY: - tempif.i = val; - voodoo->params.dGdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdBdY: case SST_remap_fdBdY: - tempif.i = val; - voodoo->params.dBdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdZdY: case SST_remap_fdZdY: - tempif.i = val; - voodoo->params.dZdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdAdY: case SST_remap_fdAdY: - tempif.i = val; - voodoo->params.dAdY = (int32_t)(tempif.f * 4096.0f); - break; - case SST_fdSdY: case SST_remap_fdSdY: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dSdY = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dSdY = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fdTdY: case SST_remap_fdTdY: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dTdY = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dTdY = (int64_t)(tempif.f * 4294967296.0f); - break; - case SST_fdWdY: case SST_remap_fdWdY: - tempif.i = val; - if (chip & CHIP_TREX0) - voodoo->params.tmu[0].dWdY = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_TREX1) - voodoo->params.tmu[1].dWdY = (int64_t)(tempif.f * 4294967296.0f); - if (chip & CHIP_FBI) - voodoo->params.dWdY = (int64_t)(tempif.f * 4294967296.0f); - break; - - case SST_ftriangleCMD: - voodoo->params.sign = val & (1 << 31); - - if (voodoo->ncc_dirty[0]) - voodoo_update_ncc(voodoo, 0); - if (voodoo->ncc_dirty[1]) - voodoo_update_ncc(voodoo, 1); - voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; - - queue_triangle(voodoo, &voodoo->params); - - voodoo->cmd_read++; - break; - - case SST_fbzColorPath: - voodoo->params.fbzColorPath = val; - voodoo->rgb_sel = val & 3; - break; - - case SST_fogMode: - voodoo->params.fogMode = val; - break; - case SST_alphaMode: - voodoo->params.alphaMode = val; - break; - case SST_fbzMode: - voodoo->params.fbzMode = val; - voodoo_recalc(voodoo); - break; - case SST_lfbMode: - voodoo->lfbMode = val; - voodoo_recalc(voodoo); - break; - - case SST_clipLeftRight: - if (voodoo->type >= VOODOO_2) - { - voodoo->params.clipRight = val & 0xfff; - voodoo->params.clipLeft = (val >> 16) & 0xfff; - } - else - { - voodoo->params.clipRight = val & 0x3ff; - voodoo->params.clipLeft = (val >> 16) & 0x3ff; - } - break; - case SST_clipLowYHighY: - if (voodoo->type >= VOODOO_2) - { - voodoo->params.clipHighY = val & 0xfff; - voodoo->params.clipLowY = (val >> 16) & 0xfff; - } - else - { - voodoo->params.clipHighY = val & 0x3ff; - voodoo->params.clipLowY = (val >> 16) & 0x3ff; - } - break; - - case SST_nopCMD: - voodoo->cmd_read++; - voodoo->fbiPixelsIn = 0; - voodoo->fbiChromaFail = 0; - voodoo->fbiZFuncFail = 0; - voodoo->fbiAFuncFail = 0; - voodoo->fbiPixelsOut = 0; - break; - case SST_fastfillCMD: - wait_for_render_thread_idle(voodoo); - voodoo_fastfill(voodoo, &voodoo->params); - voodoo->cmd_read++; - break; - - case SST_fogColor: - voodoo->params.fogColor.r = (val >> 16) & 0xff; - voodoo->params.fogColor.g = (val >> 8) & 0xff; - voodoo->params.fogColor.b = val & 0xff; - break; - - case SST_zaColor: - voodoo->params.zaColor = val; - break; - case SST_chromaKey: - voodoo->params.chromaKey_r = (val >> 16) & 0xff; - voodoo->params.chromaKey_g = (val >> 8) & 0xff; - voodoo->params.chromaKey_b = val & 0xff; - voodoo->params.chromaKey = val & 0xffffff; - break; - case SST_stipple: - voodoo->params.stipple = val; - break; - case SST_color0: - voodoo->params.color0 = val; - break; - case SST_color1: - voodoo->params.color1 = val; - break; - - case SST_fogTable00: case SST_fogTable01: case SST_fogTable02: case SST_fogTable03: - case SST_fogTable04: case SST_fogTable05: case SST_fogTable06: case SST_fogTable07: - case SST_fogTable08: case SST_fogTable09: case SST_fogTable0a: case SST_fogTable0b: - case SST_fogTable0c: case SST_fogTable0d: case SST_fogTable0e: case SST_fogTable0f: - case SST_fogTable10: case SST_fogTable11: case SST_fogTable12: case SST_fogTable13: - case SST_fogTable14: case SST_fogTable15: case SST_fogTable16: case SST_fogTable17: - case SST_fogTable18: case SST_fogTable19: case SST_fogTable1a: case SST_fogTable1b: - case SST_fogTable1c: case SST_fogTable1d: case SST_fogTable1e: case SST_fogTable1f: - addr = (addr - SST_fogTable00) >> 1; - voodoo->params.fogTable[addr].dfog = val & 0xff; - voodoo->params.fogTable[addr].fog = (val >> 8) & 0xff; - voodoo->params.fogTable[addr+1].dfog = (val >> 16) & 0xff; - voodoo->params.fogTable[addr+1].fog = (val >> 24) & 0xff; - break; - - case SST_clutData: - voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff; - voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff; - voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff; - if (val & 0x20000000) - { - voodoo->clutData[(val >> 24) & 0x3f].b = 255; - voodoo->clutData[(val >> 24) & 0x3f].g = 255; - voodoo->clutData[(val >> 24) & 0x3f].r = 255; - } - voodoo->clutData_dirty = 1; - break; - - case SST_sSetupMode: - voodoo->sSetupMode = val; - break; - case SST_sVx: - tempif.i = val; - voodoo->verts[3].sVx = tempif.f; -// pclog("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f); - break; - case SST_sVy: - tempif.i = val; - voodoo->verts[3].sVy = tempif.f; -// pclog("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f); - break; - case SST_sARGB: - voodoo->verts[3].sBlue = (float)(val & 0xff); - voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff); - voodoo->verts[3].sRed = (float)((val >> 16) & 0xff); - voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff); - break; - case SST_sRed: - tempif.i = val; - voodoo->verts[3].sRed = tempif.f; - break; - case SST_sGreen: - tempif.i = val; - voodoo->verts[3].sGreen = tempif.f; - break; - case SST_sBlue: - tempif.i = val; - voodoo->verts[3].sBlue = tempif.f; - break; - case SST_sAlpha: - tempif.i = val; - voodoo->verts[3].sAlpha = tempif.f; - break; - case SST_sVz: - tempif.i = val; - voodoo->verts[3].sVz = tempif.f; - break; - case SST_sWb: - tempif.i = val; - voodoo->verts[3].sWb = tempif.f; - break; - case SST_sW0: - tempif.i = val; - voodoo->verts[3].sW0 = tempif.f; - break; - case SST_sS0: - tempif.i = val; - voodoo->verts[3].sS0 = tempif.f; - break; - case SST_sT0: - tempif.i = val; - voodoo->verts[3].sT0 = tempif.f; - break; - case SST_sW1: - tempif.i = val; - voodoo->verts[3].sW1 = tempif.f; - break; - case SST_sS1: - tempif.i = val; - voodoo->verts[3].sS1 = tempif.f; - break; - case SST_sT1: - tempif.i = val; - voodoo->verts[3].sT1 = tempif.f; - break; - - case SST_sBeginTriCMD: -// pclog("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx); - voodoo->verts[0] = voodoo->verts[3]; - voodoo->vertex_num = 1; - voodoo->num_verticies = 1; - break; - case SST_sDrawTriCMD: -// pclog("sDrawTriCMD %i %i %i\n", voodoo->num_verticies, voodoo->vertex_num, voodoo->sSetupMode & SETUPMODE_STRIP_MODE); - if (voodoo->vertex_num == 3) - voodoo->vertex_num = (voodoo->sSetupMode & SETUPMODE_STRIP_MODE) ? 1 : 0; - voodoo->verts[voodoo->vertex_num] = voodoo->verts[3]; - - voodoo->num_verticies++; - voodoo->vertex_num++; - if (voodoo->num_verticies == 3) - { -// pclog("triangle_setup\n"); - triangle_setup(voodoo); - - voodoo->num_verticies = 2; - } - if (voodoo->vertex_num == 4) - fatal("sDrawTriCMD overflow\n"); - break; - - case SST_bltSrcBaseAddr: - voodoo->bltSrcBaseAddr = val & 0x3fffff; - break; - case SST_bltDstBaseAddr: -// pclog("Write bltDstBaseAddr %08x\n", val); - voodoo->bltDstBaseAddr = val & 0x3fffff; - break; - case SST_bltXYStrides: - voodoo->bltSrcXYStride = val & 0xfff; - voodoo->bltDstXYStride = (val >> 16) & 0xfff; -// pclog("Write bltXYStrides %08x\n", val); - break; - case SST_bltSrcChromaRange: - voodoo->bltSrcChromaRange = val; - voodoo->bltSrcChromaMinB = val & 0x1f; - voodoo->bltSrcChromaMinG = (val >> 5) & 0x3f; - voodoo->bltSrcChromaMinR = (val >> 11) & 0x1f; - voodoo->bltSrcChromaMaxB = (val >> 16) & 0x1f; - voodoo->bltSrcChromaMaxG = (val >> 21) & 0x3f; - voodoo->bltSrcChromaMaxR = (val >> 27) & 0x1f; - break; - case SST_bltDstChromaRange: - voodoo->bltDstChromaRange = val; - voodoo->bltDstChromaMinB = val & 0x1f; - voodoo->bltDstChromaMinG = (val >> 5) & 0x3f; - voodoo->bltDstChromaMinR = (val >> 11) & 0x1f; - voodoo->bltDstChromaMaxB = (val >> 16) & 0x1f; - voodoo->bltDstChromaMaxG = (val >> 21) & 0x3f; - voodoo->bltDstChromaMaxR = (val >> 27) & 0x1f; - break; - case SST_bltClipX: - voodoo->bltClipRight = val & 0xfff; - voodoo->bltClipLeft = (val >> 16) & 0xfff; - break; - case SST_bltClipY: - voodoo->bltClipHighY = val & 0xfff; - voodoo->bltClipLowY = (val >> 16) & 0xfff; - break; - - case SST_bltSrcXY: - voodoo->bltSrcX = val & 0x7ff; - voodoo->bltSrcY = (val >> 16) & 0x7ff; - break; - case SST_bltDstXY: -// pclog("Write bltDstXY %08x\n", val); - voodoo->bltDstX = val & 0x7ff; - voodoo->bltDstY = (val >> 16) & 0x7ff; - if (val & (1 << 31)) - blit_start(voodoo); - break; - case SST_bltSize: -// pclog("Write bltSize %08x\n", val); - voodoo->bltSizeX = val & 0xfff; - if (voodoo->bltSizeX & 0x800) - voodoo->bltSizeX |= 0xfffff000; - voodoo->bltSizeY = (val >> 16) & 0xfff; - if (voodoo->bltSizeY & 0x800) - voodoo->bltSizeY |= 0xfffff000; - if (val & (1 << 31)) - blit_start(voodoo); - break; - case SST_bltRop: - voodoo->bltRop[0] = val & 0xf; - voodoo->bltRop[1] = (val >> 4) & 0xf; - voodoo->bltRop[2] = (val >> 8) & 0xf; - voodoo->bltRop[3] = (val >> 12) & 0xf; - break; - case SST_bltColor: -// pclog("Write bltColor %08x\n", val); - voodoo->bltColorFg = val & 0xffff; - voodoo->bltColorBg = (val >> 16) & 0xffff; - break; - - case SST_bltCommand: - voodoo->bltCommand = val; -// pclog("Write bltCommand %08x\n", val); - if (val & (1 << 31)) - blit_start(voodoo); - break; - case SST_bltData: - blit_data(voodoo, val); - break; - - case SST_textureMode: - if (chip & CHIP_TREX0) - { - voodoo->params.textureMode[0] = val; - voodoo->params.tformat[0] = (val >> 8) & 0xf; - } - if (chip & CHIP_TREX1) - { - voodoo->params.textureMode[1] = val; - voodoo->params.tformat[1] = (val >> 8) & 0xf; - } - break; - case SST_tLOD: - if (chip & CHIP_TREX0) - { - voodoo->params.tLOD[0] = val; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - voodoo->params.tLOD[1] = val; - voodoo_recalc_tex(voodoo, 1); - } - break; - case SST_tDetail: - if (chip & CHIP_TREX0) - { - voodoo->params.detail_max[0] = val & 0xff; - voodoo->params.detail_bias[0] = (val >> 8) & 0x3f; - voodoo->params.detail_scale[0] = (val >> 14) & 7; - } - if (chip & CHIP_TREX1) - { - voodoo->params.detail_max[1] = val & 0xff; - voodoo->params.detail_bias[1] = (val >> 8) & 0x3f; - voodoo->params.detail_scale[1] = (val >> 14) & 7; - } - break; - case SST_texBaseAddr: - if (chip & CHIP_TREX0) - { - voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 1); - } - break; - case SST_texBaseAddr1: - if (chip & CHIP_TREX0) - { - voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 1); - } - break; - case SST_texBaseAddr2: - if (chip & CHIP_TREX0) - { - voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 1); - } - break; - case SST_texBaseAddr38: - if (chip & CHIP_TREX0) - { - voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 0); - } - if (chip & CHIP_TREX1) - { - voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3; - voodoo_recalc_tex(voodoo, 1); - } - break; - - case SST_trexInit1: - if (chip & CHIP_TREX0) - voodoo->trexInit1[0] = val; - if (chip & CHIP_TREX1) - voodoo->trexInit1[1] = val; - break; - - case SST_nccTable0_Y0: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].y[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].y[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable0_Y1: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].y[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].y[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable0_Y2: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].y[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].y[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable0_Y3: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].y[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].y[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - - case SST_nccTable0_I0: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_I2: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_Q0: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].q[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].q[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_Q2: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - if (val & (1 << 31)) - { - int p = (val >> 23) & 0xfe; - if (chip & CHIP_TREX0) - { - voodoo->palette[0][p].u = val | 0xff000000; - voodoo->palette_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->palette[1][p].u = val | 0xff000000; - voodoo->palette_dirty[1] = 1; - } - } - break; - - case SST_nccTable0_I1: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_I3: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].i[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].i[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_Q1: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].q[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].q[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - case SST_nccTable0_Q3: - if (!(val & (1 << 31))) - { - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][0].q[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][0].q[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - } - if (val & (1 << 31)) - { - int p = ((val >> 23) & 0xfe) | 0x01; - if (chip & CHIP_TREX0) - { - voodoo->palette[0][p].u = val | 0xff000000; - voodoo->palette_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->palette[1][p].u = val | 0xff000000; - voodoo->palette_dirty[1] = 1; - } - } - break; - - case SST_nccTable1_Y0: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].y[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].y[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Y1: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].y[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].y[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Y2: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].y[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].y[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Y3: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].y[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].y[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_I0: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].i[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].i[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_I1: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].i[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].i[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_I2: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].i[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].i[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_I3: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].i[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].i[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Q0: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].q[0] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].q[0] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Q1: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].q[1] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].q[1] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Q2: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].q[2] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].q[2] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - case SST_nccTable1_Q3: - if (chip & CHIP_TREX0) - { - voodoo->nccTable[0][1].q[3] = val; - voodoo->ncc_dirty[0] = 1; - } - if (chip & CHIP_TREX1) - { - voodoo->nccTable[1][1].q[3] = val; - voodoo->ncc_dirty[1] = 1; - } - break; - - case SST_userIntrCMD: - fatal("userIntrCMD write %08x from FIFO\n", val); - break; - } -} - - -static uint16_t voodoo_fb_readw(uint32_t addr, void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - int x, y; - uint32_t read_addr; - uint16_t temp; - - x = (addr >> 1) & 0x3ff; - y = (addr >> 11) & 0x3ff; - - if (SLI_ENABLED) - { - voodoo_set_t *set = voodoo->set; - - if (y & 1) - voodoo = set->voodoos[1]; - else - voodoo = set->voodoos[0]; - - y >>= 1; - } - - read_addr = voodoo->fb_read_offset + (x << 1) + (y * voodoo->row_width); - - if (read_addr > voodoo->fb_mask) - return 0xffff; - - temp = *(uint16_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]); - -// 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++); - return temp; -} -static uint32_t voodoo_fb_readl(uint32_t addr, void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - int x, y; - uint32_t read_addr; - uint32_t temp; - - x = addr & 0x7fe; - y = (addr >> 11) & 0x3ff; - - if (SLI_ENABLED) - { - voodoo_set_t *set = voodoo->set; - - if (y & 1) - voodoo = set->voodoos[1]; - else - voodoo = set->voodoos[0]; - - y >>= 1; - } - - read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width); - - if (read_addr > voodoo->fb_mask) - return 0xffffffff; - - temp = *(uint32_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]); - -// 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); - return temp; -} - -static inline uint16_t do_dither(voodoo_params_t *params, rgba8_t col, int x, int y) -{ - int r, g, b; - - if (dither) - { - if (dither2x2) - { - r = dither_rb2x2[col.r][y & 1][x & 1]; - g = dither_g2x2[col.g][y & 1][x & 1]; - b = dither_rb2x2[col.b][y & 1][x & 1]; - } - else - { - r = dither_rb[col.r][y & 3][x & 3]; - g = dither_g[col.g][y & 3][x & 3]; - b = dither_rb[col.b][y & 3][x & 3]; - } - } - else - { - r = col.r >> 3; - g = col.g >> 2; - b = col.b >> 3; - } - - return b | (g << 5) | (r << 11); -} - -static void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - voodoo_params_t *params = &voodoo->params; - int x, y; - uint32_t write_addr, write_addr_aux; - rgba8_t colour_data; - uint16_t depth_data; - uint8_t alpha_data; - int write_mask = 0; - - colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0; - - depth_data = voodoo->params.zaColor & 0xffff; - alpha_data = voodoo->params.zaColor >> 24; - -// while (!RB_EMPTY) -// thread_reset_event(voodoo->not_full_event); - -// pclog("voodoo_fb_writew : %08X %04X\n", addr, val); - - - switch (voodoo->lfbMode & LFB_FORMAT_MASK) - { - case LFB_FORMAT_RGB565: - colour_data = rgb565[val]; - alpha_data = 0xff; - write_mask = LFB_WRITE_COLOUR; - break; - case LFB_FORMAT_RGB555: - colour_data = argb1555[val]; - alpha_data = 0xff; - write_mask = LFB_WRITE_COLOUR; - break; - case LFB_FORMAT_ARGB1555: - colour_data = argb1555[val]; - alpha_data = colour_data.a; - write_mask = LFB_WRITE_COLOUR; - break; - case LFB_FORMAT_DEPTH: - depth_data = val; - write_mask = LFB_WRITE_DEPTH; - break; - - default: - fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode); - } - - x = addr & 0x7fe; - y = (addr >> 11) & 0x3ff; - - if (SLI_ENABLED) - { - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1))) - return; - y >>= 1; - } - - - if (voodoo->fb_write_offset == voodoo->params.front_offset) - voodoo->dirty_line[y] = 1; - - write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); - write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); - -// pclog("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr); - - if (voodoo->lfbMode & 0x100) - { - { - rgba8_t write_data = colour_data; - uint16_t new_depth = depth_data; - - if (params->fbzMode & FBZ_DEPTH_ENABLE) - { - uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); - - DEPTH_TEST(new_depth); - } - - if ((params->fbzMode & FBZ_CHROMAKEY) && - write_data.r == params->chromaKey_r && - write_data.g == params->chromaKey_g && - write_data.b == params->chromaKey_b) - goto skip_pixel; - - if (params->fogMode & FOG_ENABLE) - { - int32_t z = new_depth << 12; - int64_t w_depth = (int64_t)(int32_t)new_depth; - int32_t ia = alpha_data << 12; - - APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth); - } - - if (params->alphaMode & 1) - ALPHA_TEST(alpha_data); - - if (params->alphaMode & (1 << 4)) - { - uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]); - int dest_r, dest_g, dest_b, dest_a; - - dest_r = (dat >> 8) & 0xf8; - dest_g = (dat >> 3) & 0xfc; - dest_b = (dat << 3) & 0xf8; - dest_r |= (dest_r >> 5); - dest_g |= (dest_g >> 6); - dest_b |= (dest_b >> 5); - dest_a = 0xff; - - ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data); - } - - if (params->fbzMode & FBZ_RGB_WMASK) - *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y); - if (params->fbzMode & FBZ_DEPTH_WMASK) - *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth; - -skip_pixel: - x = x; - } - } - else - { - if (write_mask & LFB_WRITE_COLOUR) - *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y); - if (write_mask & LFB_WRITE_DEPTH) - *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data; - } -} - - -static void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - voodoo_params_t *params = &voodoo->params; - int x, y; - uint32_t write_addr, write_addr_aux; - rgba8_t colour_data[2]; - uint16_t depth_data[2]; - uint8_t alpha_data[2]; - int write_mask = 0, count = 1; - - depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff; - alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24; -// while (!RB_EMPTY) -// thread_reset_event(voodoo->not_full_event); - -// pclog("voodoo_fb_writel : %08X %08X\n", addr, val); - - switch (voodoo->lfbMode & LFB_FORMAT_MASK) - { - case LFB_FORMAT_RGB565: - colour_data[0] = rgb565[val & 0xffff]; - colour_data[1] = rgb565[val >> 16]; - write_mask = LFB_WRITE_COLOUR; - count = 2; - break; - case LFB_FORMAT_RGB555: - colour_data[0] = argb1555[val & 0xffff]; - colour_data[1] = argb1555[val >> 16]; - write_mask = LFB_WRITE_COLOUR; - count = 2; - break; - case LFB_FORMAT_ARGB1555: - colour_data[0] = argb1555[val & 0xffff]; - alpha_data[0] = colour_data[0].a; - colour_data[1] = argb1555[val >> 16]; - alpha_data[1] = colour_data[1].a; - write_mask = LFB_WRITE_COLOUR; - count = 2; - break; - - case LFB_FORMAT_ARGB8888: - colour_data[0].b = val & 0xff; - colour_data[0].g = (val >> 8) & 0xff; - colour_data[0].r = (val >> 16) & 0xff; - alpha_data[0] = (val >> 24) & 0xff; - write_mask = LFB_WRITE_COLOUR; - addr >>= 1; - break; - - case LFB_FORMAT_DEPTH: - depth_data[0] = val; - depth_data[1] = val >> 16; - write_mask = LFB_WRITE_DEPTH; - count = 2; - break; - - default: - fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode); - } - - x = addr & 0x7fe; - y = (addr >> 11) & 0x3ff; - - if (SLI_ENABLED) - { - if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || - ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1))) - return; - y >>= 1; - } - - if (voodoo->fb_write_offset == voodoo->params.front_offset) - voodoo->dirty_line[y] = 1; - - write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); - write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); - -// 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); - - if (voodoo->lfbMode & 0x100) - { - int c; - - for (c = 0; c < count; c++) - { - rgba8_t write_data = colour_data[c]; - uint16_t new_depth = depth_data[c]; - - if (params->fbzMode & FBZ_DEPTH_ENABLE) - { - uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); - - DEPTH_TEST(new_depth); - } - - if ((params->fbzMode & FBZ_CHROMAKEY) && - write_data.r == params->chromaKey_r && - write_data.g == params->chromaKey_g && - write_data.b == params->chromaKey_b) - goto skip_pixel; - - if (params->fogMode & FOG_ENABLE) - { - int32_t z = new_depth << 12; - int64_t w_depth = new_depth; - int32_t ia = alpha_data[c] << 12; - - APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth); - } - - if (params->alphaMode & 1) - ALPHA_TEST(alpha_data[c]); - - if (params->alphaMode & (1 << 4)) - { - uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]); - int dest_r, dest_g, dest_b, dest_a; - - dest_r = (dat >> 8) & 0xf8; - dest_g = (dat >> 3) & 0xfc; - dest_b = (dat << 3) & 0xf8; - dest_r |= (dest_r >> 5); - dest_g |= (dest_g >> 6); - dest_b |= (dest_b >> 5); - dest_a = 0xff; - - ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]); - } - - if (params->fbzMode & FBZ_RGB_WMASK) - *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y); - if (params->fbzMode & FBZ_DEPTH_WMASK) - *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth; - -skip_pixel: - write_addr += 2; - write_addr_aux += 2; - } - } - else - { - int c; - - for (c = 0; c < count; c++) - { - if (write_mask & LFB_WRITE_COLOUR) - *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); - if (write_mask & LFB_WRITE_DEPTH) - *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c]; - - write_addr += 2; - write_addr_aux += 2; - } - } -} - -static void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) -{ - int lod, s, t; - voodoo_t *voodoo = (voodoo_t *)p; - int tmu; - - if (addr & 0x400000) - return; /*TREX != 0*/ - - tmu = (addr & 0x200000) ? 1 : 0; - - if (tmu && !voodoo->dual_tmus) - return; - -// pclog("voodoo_tex_writel : %08X %08X %i\n", addr, val, voodoo->params.tformat); - - lod = (addr >> 17) & 0xf; - t = (addr >> 9) & 0xff; - if (voodoo->params.tformat[tmu] & 8) - s = (addr >> 1) & 0xfe; - else - { - if (voodoo->params.textureMode[tmu] & (1 << 31)) - s = addr & 0xfc; - else - s = (addr >> 1) & 0xfc; - } - - if (lod > LOD_MAX) - return; - -// if (addr >= 0x200000) -// return; - - if (voodoo->params.tformat[tmu] & 8) - addr = voodoo->params.tex_base[tmu][lod] + s*2 + (t << voodoo->params.tex_shift[tmu][lod])*2; - else - addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]); - if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) - { -// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); - flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu); - } - *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val; -} - -#define WAKE_DELAY (TIMER_USEC * 100) -static inline void wake_fifo_thread(voodoo_t *voodoo) -{ - if (!timer_is_enabled(&voodoo->wake_timer)) - { - /*Don't wake FIFO thread immediately - if we do that it will probably - process one word and go back to sleep, requiring it to be woken on - almost every write. Instead, wait a short while so that the CPU - emulation writes more data so we have more batched-up work.*/ - timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY); - } -} - -static inline void wake_fifo_thread_now(voodoo_t *voodoo) -{ - thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -static void voodoo_wake_timer(void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - - thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ -} - -static inline void queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val) -{ - fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK]; - - while (FIFO_FULL) - { - thread_reset_event(voodoo->fifo_not_full_event); - if (FIFO_FULL) - { - thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/ - if (FIFO_FULL) - wake_fifo_thread_now(voodoo); - } - } - - fifo->val = val; - fifo->addr_type = addr_type; - - voodoo->fifo_write_idx++; - - if (FIFO_ENTRIES > 0xe000) - wake_fifo_thread(voodoo); -} static uint16_t voodoo_readw(uint32_t addr, void *p) { @@ -5939,10 +127,10 @@ static uint16_t voodoo_readw(uint32_t addr, void *p) voodoo->flush = 1; while (!FIFO_EMPTY) { - wake_fifo_thread_now(voodoo); + voodoo_wake_fifo_thread_now(voodoo); thread_wait_event(voodoo->fifo_not_full_event, 1); } - wait_for_render_thread_idle(voodoo); + voodoo_wait_for_render_thread_idle(voodoo); voodoo->flush = 0; return voodoo_fb_readw(addr, voodoo); @@ -5951,24 +139,6 @@ static uint16_t voodoo_readw(uint32_t addr, void *p) return 0xffff; } -static void voodoo_flush(voodoo_t *voodoo) -{ - voodoo->flush = 1; - while (!FIFO_EMPTY) - { - wake_fifo_thread_now(voodoo); - thread_wait_event(voodoo->fifo_not_full_event, 1); - } - wait_for_render_thread_idle(voodoo); - voodoo->flush = 0; -} - -static void wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo) -{ - wake_fifo_thread(voodoo); - if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo) - wake_fifo_thread(set->voodoos[1]); -} static uint32_t voodoo_readl(uint32_t addr, void *p) { @@ -5999,10 +169,10 @@ static uint32_t voodoo_readl(uint32_t addr, void *p) voodoo->flush = 1; while (!FIFO_EMPTY) { - wake_fifo_thread_now(voodoo); + voodoo_wake_fifo_thread_now(voodoo); thread_wait_event(voodoo->fifo_not_full_event, 1); } - wait_for_render_thread_idle(voodoo); + voodoo_wait_for_render_thread_idle(voodoo); voodoo->flush = 0; temp = voodoo_fb_readl(addr, voodoo); @@ -6029,7 +199,7 @@ static uint32_t voodoo_readl(uint32_t addr, void *p) (voodoo_other->cmdfifo_depth_rd != voodoo_other->cmdfifo_depth_wr)) busy = 1; if (!voodoo_other->voodoo_busy) - wake_fifo_thread(voodoo_other); + voodoo_wake_fifo_thread(voodoo_other); } fifo_size = 0xffff - fifo_entries; @@ -6049,7 +219,7 @@ static uint32_t voodoo_readl(uint32_t addr, void *p) temp |= 0x380; /*Busy*/ if (!voodoo->voodoo_busy) - wake_fifo_thread(voodoo); + voodoo_wake_fifo_thread(voodoo); } break; @@ -6194,31 +364,7 @@ static void voodoo_writew(uint32_t addr, uint16_t val, void *p) cycles -= voodoo->write_time; if ((addr & 0xc00000) == 0x400000) /*Framebuffer*/ - queue_command(voodoo, addr | FIFO_WRITEW_FB, val); -} - -static void voodoo_pixelclock_update(voodoo_t *voodoo) -{ - int m = (voodoo->dac_pll_regs[0] & 0x7f) + 2; - int n1 = ((voodoo->dac_pll_regs[0] >> 8) & 0x1f) + 2; - int n2 = ((voodoo->dac_pll_regs[0] >> 13) & 0x07); - float t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); - double clock_const; - int line_length; - - if ((voodoo->dac_data[6] & 0xf0) == 0x20 || - (voodoo->dac_data[6] & 0xf0) == 0x60 || - (voodoo->dac_data[6] & 0xf0) == 0x70) - t /= 2.0f; - - line_length = (voodoo->hSync & 0xff) + ((voodoo->hSync >> 16) & 0x3ff); - -// pclog("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length); - - voodoo->pixel_clock = t; - - clock_const = cpuclock / t; - voodoo->line_time = (uint64_t)((double)line_length * clock_const * (double)(1ull << 32)); + voodoo_queue_command(voodoo, addr | FIFO_WRITEW_FB, val); } static void voodoo_writel(uint32_t addr, uint32_t val, void *p) @@ -6238,11 +384,11 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) if (addr & 0x800000) /*Texture*/ { voodoo->tex_count++; - queue_command(voodoo, addr | FIFO_WRITEL_TEX, val); + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_TEX, val); } else if (addr & 0x400000) /*Framebuffer*/ { - queue_command(voodoo, addr | FIFO_WRITEL_FB, val); + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_FB, val); } else if ((addr & 0x200000) && (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE)) { @@ -6250,7 +396,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) *(uint32_t *)&voodoo->fb_mem[(voodoo->cmdfifo_base + (addr & 0x3fffc)) & voodoo->fb_mask] = val; voodoo->cmdfifo_depth_wr++; if ((voodoo->cmdfifo_depth_wr - voodoo->cmdfifo_depth_rd) < 20) - wake_fifo_thread(voodoo); + voodoo_wake_fifo_thread(voodoo); } else switch (addr & 0x3fc) { @@ -6267,41 +413,41 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) voodoo->swap_count++; if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) return; - queue_command(voodoo, addr | FIFO_WRITEL_REG, val); + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; case SST_triangleCMD: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) return; voodoo->cmd_written++; - queue_command(voodoo, addr | FIFO_WRITEL_REG, val); + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; case SST_ftriangleCMD: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) return; voodoo->cmd_written++; - queue_command(voodoo, addr | FIFO_WRITEL_REG, val); + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; case SST_fastfillCMD: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) return; voodoo->cmd_written++; - queue_command(voodoo, addr | FIFO_WRITEL_REG, val); + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; case SST_nopCMD: if (voodoo->fbiInit7 & FBIINIT7_CMDFIFO_ENABLE) return; voodoo->cmd_written++; - queue_command(voodoo, addr | FIFO_WRITEL_REG, val); + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); if (!voodoo->voodoo_busy) - wake_fifo_threads(voodoo->set, voodoo); + voodoo_wake_fifo_threads(voodoo->set, voodoo); break; case SST_fbiInit4: @@ -6483,7 +629,7 @@ static void voodoo_writel(uint32_t addr, uint32_t val, void *p) } else { - queue_command(voodoo, addr | FIFO_WRITEL_REG, val); + voodoo_queue_command(voodoo, addr | FIFO_WRITEL_REG, val); } break; } @@ -6517,296 +663,6 @@ static void voodoo_snoop_writel(uint32_t addr, uint32_t val, void *p) voodoo_writel(addr, val, set->voodoos[1]); } -static uint32_t cmdfifo_get(voodoo_t *voodoo) -{ - uint32_t val; - - while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr) - { - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); - } - - val = *(uint32_t *)&voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; - - voodoo->cmdfifo_depth_rd++; - voodoo->cmdfifo_rp += 4; - -// pclog(" CMDFIFO get %08x\n", val); - return val; -} - -static inline float cmdfifo_get_f(voodoo_t *voodoo) -{ - union - { - uint32_t i; - float f; - } tempif; - - tempif.i = cmdfifo_get(voodoo); - return tempif.f; -} - -enum -{ - CMDFIFO3_PC_MASK_RGB = (1 << 10), - CMDFIFO3_PC_MASK_ALPHA = (1 << 11), - CMDFIFO3_PC_MASK_Z = (1 << 12), - CMDFIFO3_PC_MASK_Wb = (1 << 13), - CMDFIFO3_PC_MASK_W0 = (1 << 14), - CMDFIFO3_PC_MASK_S0_T0 = (1 << 15), - CMDFIFO3_PC_MASK_W1 = (1 << 16), - CMDFIFO3_PC_MASK_S1_T1 = (1 << 17), - - CMDFIFO3_PC = (1 << 28) -}; - -static void fifo_thread(void *param) -{ - voodoo_t *voodoo = (voodoo_t *)param; - - while (1) - { - thread_set_event(voodoo->fifo_not_full_event); - thread_wait_event(voodoo->wake_fifo_thread, -1); - thread_reset_event(voodoo->wake_fifo_thread); - voodoo->voodoo_busy = 1; - while (!FIFO_EMPTY) - { - uint64_t start_time = timer_read(); - uint64_t end_time; - fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - - switch (fifo->addr_type & FIFO_TYPE) - { - case FIFO_WRITEL_REG: - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_REG) - { - voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - case FIFO_WRITEW_FB: - wait_for_render_thread_idle(voodoo); - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEW_FB) - { - voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - case FIFO_WRITEL_FB: - wait_for_render_thread_idle(voodoo); - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_FB) - { - voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - case FIFO_WRITEL_TEX: - while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_TEX) - { - if (!(fifo->addr_type & 0x400000)) - voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); - fifo->addr_type = FIFO_INVALID; - voodoo->fifo_read_idx++; - fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; - } - break; - } - - if (FIFO_ENTRIES > 0xe000) - thread_set_event(voodoo->fifo_not_full_event); - - end_time = timer_read(); - voodoo->time += end_time - start_time; - } - - while (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) - { - uint64_t start_time = timer_read(); - uint64_t end_time; - uint32_t header = cmdfifo_get(voodoo); - uint32_t addr; - uint32_t mask; - int smode; - int num; - int num_verticies; - int v_num; - -// pclog(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp); - - switch (header & 7) - { - case 0: -// pclog("CMDFIFO0\n"); - switch ((header >> 3) & 7) - { - case 0: /*NOP*/ - break; - - case 3: /*JMP local frame buffer*/ - voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; -// pclog("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); - break; - - default: - fatal("Bad CMDFIFO0 %08x\n", header); - } - break; - - case 1: - num = header >> 16; - addr = (header & 0x7ff8) >> 1; -// pclog("CMDFIFO1 addr=%08x\n",addr); - while (num--) - { - uint32_t val = cmdfifo_get(voodoo); - if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || - (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) - voodoo->cmd_written_fifo++; - - voodoo_reg_writel(addr, val, voodoo); - - if (header & (1 << 15)) - addr += 4; - } - break; - - case 3: - num = (header >> 29) & 7; - mask = header;//(header >> 10) & 0xff; - smode = (header >> 22) & 0xf; - voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo); - num_verticies = (header >> 6) & 0xf; - v_num = 0; - if (((header >> 3) & 7) == 2) - v_num = 1; -// pclog("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff); -// pclog("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7); - - while (num_verticies--) - { - voodoo->verts[3].sVx = cmdfifo_get_f(voodoo); - voodoo->verts[3].sVy = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_RGB) - { - if (header & CMDFIFO3_PC) - { - uint32_t val = cmdfifo_get(voodoo); - voodoo->verts[3].sBlue = (float)(val & 0xff); - voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff); - voodoo->verts[3].sRed = (float)((val >> 16) & 0xff); - voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff); - } - else - { - voodoo->verts[3].sRed = cmdfifo_get_f(voodoo); - voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo); - voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo); - } - } - if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC)) - voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_Z) - voodoo->verts[3].sVz = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_Wb) - voodoo->verts[3].sWb = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_W0) - voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_S0_T0) - { - voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo); - voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo); - } - if (mask & CMDFIFO3_PC_MASK_W1) - voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo); - if (mask & CMDFIFO3_PC_MASK_S1_T1) - { - voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo); - voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo); - } - if (v_num) - voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo); - else - voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo); - v_num++; - if (v_num == 3 && ((header >> 3) & 7) == 0) - v_num = 0; - } - break; - - case 4: - num = (header >> 29) & 7; - mask = (header >> 15) & 0x3fff; - addr = (header & 0x7ff8) >> 1; -// pclog("CMDFIFO4 addr=%08x\n",addr); - while (mask) - { - if (mask & 1) - { - uint32_t val = cmdfifo_get(voodoo); - if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || - (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) - voodoo->cmd_written_fifo++; - - voodoo_reg_writel(addr, val, voodoo); - } - - addr += 4; - mask >>= 1; - } - while (num--) - cmdfifo_get(voodoo); - break; - - case 5: - if (header & 0x3fc0000) - fatal("CMDFIFO packet 5 has byte disables set %08x\n", header); - num = (header >> 3) & 0x7ffff; - addr = cmdfifo_get(voodoo) & 0xffffff; -// pclog("CMDFIFO5 addr=%08x num=%i\n", addr, num); - switch (header >> 30) - { - case 2: /*Framebuffer*/ - while (num--) - { - uint32_t val = cmdfifo_get(voodoo); - voodoo_fb_writel(addr, val, voodoo); - addr += 4; - } - break; - case 3: /*Texture*/ - while (num--) - { - uint32_t val = cmdfifo_get(voodoo); - voodoo_tex_writel(addr, val, voodoo); - addr += 4; - } - break; - - default: - fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp); - } - break; - - default: - pclog("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); - } - - end_time = timer_read(); - voodoo->time += end_time - start_time; - } - voodoo->voodoo_busy = 0; - } -} - static void voodoo_recalcmapping(voodoo_set_t *set) { if (set->nr_cards == 2) @@ -6953,529 +809,6 @@ void voodoo_pci_write(int func, int addr, uint8_t val, void *p) } } -static void voodoo_calc_clutData(voodoo_t *voodoo) -{ - int c; - - for (c = 0; c < 256; c++) - { - voodoo->clutData256[c].r = (voodoo->clutData[c >> 3].r*(8-(c & 7)) + - voodoo->clutData[(c >> 3)+1].r*(c & 7)) >> 3; - voodoo->clutData256[c].g = (voodoo->clutData[c >> 3].g*(8-(c & 7)) + - voodoo->clutData[(c >> 3)+1].g*(c & 7)) >> 3; - voodoo->clutData256[c].b = (voodoo->clutData[c >> 3].b*(8-(c & 7)) + - voodoo->clutData[(c >> 3)+1].b*(c & 7)) >> 3; - } - - for (c = 0; c < 65536; c++) - { - int r = (c >> 8) & 0xf8; - int g = (c >> 3) & 0xfc; - int b = (c << 3) & 0xf8; -// r |= (r >> 5); -// g |= (g >> 6); -// b |= (b >> 5); - - voodoo->video_16to32[c] = (voodoo->clutData256[r].r << 16) | (voodoo->clutData256[g].g << 8) | voodoo->clutData256[b].b; - } -} - - - -#define FILTDIV 256 - -static int FILTCAP, FILTCAPG, FILTCAPB = 0; /* color filter threshold values */ - -static void voodoo_generate_filter_v1(voodoo_t *voodoo) -{ - int g, h; - float difference, diffg, diffb; - float thiscol, thiscolg, thiscolb, lined; - float fcr, fcg, fcb; - - fcr = FILTCAP * 5; - fcg = FILTCAPG * 6; - fcb = FILTCAPB * 5; - - for (g=0;g FILTCAP) - difference = FILTCAP; - if (difference < -FILTCAP) - difference = -FILTCAP; - - if (diffg > FILTCAPG) - diffg = FILTCAPG; - if (diffg < -FILTCAPG) - diffg = -FILTCAPG; - - if (diffb > FILTCAPB) - diffb = FILTCAPB; - if (diffb < -FILTCAPB) - diffb = -FILTCAPB; - - // hack - to make it not bleed onto black - //if (g == 0){ - //difference = diffg = diffb = 0; - //} - - if ((difference < fcr) || (-difference > -fcr)) - thiscol = g + (difference / 2); - if ((diffg < fcg) || (-diffg > -fcg)) - thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */ - if ((diffb < fcb) || (-diffb > -fcb)) - thiscolb = g + (diffb / 2); - - if (thiscol < 0) - thiscol = 0; - if (thiscol > FILTDIV-1) - thiscol = FILTDIV-1; - - if (thiscolg < 0) - thiscolg = 0; - if (thiscolg > FILTDIV-1) - thiscolg = FILTDIV-1; - - if (thiscolb < 0) - thiscolb = 0; - if (thiscolb > FILTDIV-1) - thiscolb = FILTDIV-1; - - voodoo->thefilter[g][h] = thiscol; - voodoo->thefilterg[g][h] = thiscolg; - voodoo->thefilterb[g][h] = thiscolb; - } - - lined = g + 4; - if (lined > 255) - lined = 255; - voodoo->purpleline[g][0] = lined; - voodoo->purpleline[g][2] = lined; - - lined = g + 0; - if (lined > 255) - lined = 255; - voodoo->purpleline[g][1] = lined; - } -} - -static void voodoo_generate_filter_v2(voodoo_t *voodoo) -{ - int g, h; - float difference; - float thiscol, thiscolg, thiscolb, lined; - float clr, clg, clb = 0; - float fcr, fcg, fcb = 0; - - // pre-clamping - - fcr = FILTCAP; - fcg = FILTCAPG; - fcb = FILTCAPB; - - if (fcr > 32) fcr = 32; - if (fcg > 32) fcg = 32; - if (fcb > 32) fcb = 32; - - for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into - { - for (h=0;h<256;h++) // pixel 2 - our main pixel - { - float avg; - float avgdiff; - - difference = (float)(g - h); - avg = (float)((g + g + g + g + h) / 5); - avgdiff = avg - (float)((g + h + h + h + h) / 5); - if (avgdiff < 0) avgdiff *= -1; - if (difference < 0) difference *= -1; - - thiscol = thiscolg = thiscolb = g; - - // try lighten - if (h > g) - { - clr = clg = clb = avgdiff; - - if (clr>fcr) clr=fcr; - if (clg>fcg) clg=fcg; - if (clb>fcb) clb=fcb; - - - thiscol = g + clr; - thiscolg = g + clg; - thiscolb = g + clb; - - if (thiscol>g+FILTCAP) - thiscol=g+FILTCAP; - if (thiscolg>g+FILTCAPG) - thiscolg=g+FILTCAPG; - if (thiscolb>g+FILTCAPB) - thiscolb=g+FILTCAPB; - - - if (thiscol>g+avgdiff) - thiscol=g+avgdiff; - if (thiscolg>g+avgdiff) - thiscolg=g+avgdiff; - if (thiscolb>g+avgdiff) - thiscolb=g+avgdiff; - - } - - if (difference > FILTCAP) - thiscol = g; - if (difference > FILTCAPG) - thiscolg = g; - if (difference > FILTCAPB) - thiscolb = g; - - // clamp - if (thiscol < 0) thiscol = 0; - if (thiscolg < 0) thiscolg = 0; - if (thiscolb < 0) thiscolb = 0; - - if (thiscol > 255) thiscol = 255; - if (thiscolg > 255) thiscolg = 255; - if (thiscolb > 255) thiscolb = 255; - - // add to the table - voodoo->thefilter[g][h] = (thiscol); - voodoo->thefilterg[g][h] = (thiscolg); - voodoo->thefilterb[g][h] = (thiscolb); - - // debug the ones that don't give us much of a difference - //if (difference < FILTCAP) - //pclog("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb); - } - - lined = g + 3; - if (lined > 255) - lined = 255; - voodoo->purpleline[g][0] = lined; - voodoo->purpleline[g][1] = 0; - voodoo->purpleline[g][2] = lined; - } -} - -static void voodoo_threshold_check(voodoo_t *voodoo) -{ - int r, g, b; - - if (!voodoo->scrfilterEnabled) - return; /* considered disabled; don't check and generate */ - - /* Check for changes, to generate anew table */ - if (voodoo->scrfilterThreshold != voodoo->scrfilterThresholdOld) - { - r = (voodoo->scrfilterThreshold >> 16) & 0xFF; - g = (voodoo->scrfilterThreshold >> 8 ) & 0xFF; - b = voodoo->scrfilterThreshold & 0xFF; - - FILTCAP = r; - FILTCAPG = g; - FILTCAPB = b; - - pclog("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b); - - voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold; - - if (voodoo->type == VOODOO_2) - voodoo_generate_filter_v2(voodoo); - else - voodoo_generate_filter_v1(voodoo); - } -} - -static void voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) -{ - int x; - - // Scratchpad for avoiding feedback streaks - uint8_t fil3[(voodoo->h_disp) * 3]; - - /* 16 to 32-bit */ - for (x=0; x> 5) & 63) << 2); - fil[x*3+2] = (((src[x] >> 11) & 31) << 3); - - // Copy to our scratchpads - fil3[x*3+0] = fil[x*3+0]; - fil3[x*3+1] = fil[x*3+1]; - fil3[x*3+2] = fil[x*3+2]; - } - - - /* lines */ - - if (line & 1) - { - for (x=0; xpurpleline[fil[x*3]][0]; - fil[x*3+1] = voodoo->purpleline[fil[x*3+1]][1]; - fil[x*3+2] = voodoo->purpleline[fil[x*3+2]][2]; - } - } - - - /* filtering time */ - - for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; - fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; - fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; - } - - for (x=1; xthefilterb[fil3[x*3]][fil3[ (x-1) *3]]; - fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x-1) *3+1]]; - fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x-1) *3+2]]; - } - - for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; - fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; - fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; - } - - for (x=0; xthefilterb[fil3[x*3]][fil3[ (x+1) *3]]; - fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x+1) *3+1]]; - fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x+1) *3+2]]; - } -} - - -static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) -{ - int x; - - // Scratchpad for blending filter - uint8_t fil3[(voodoo->h_disp) * 3]; - - /* 16 to 32-bit */ - for (x=0; x> 5) & 63) << 2); - fil3[x*3+2] = fil[x*3+2] = (((src[x] >> 11) & 31) << 3); - } - - /* filtering time */ - - for (x=1; xthefilterb [((src[x+3] & 31) << 3)] [((src[x] & 31) << 3)]; - fil3[(x+3)*3+1] = voodoo->thefilterg [(((src[x+3] >> 5) & 63) << 2)] [(((src[x] >> 5) & 63) << 2)]; - fil3[(x+3)*3+2] = voodoo->thefilter [(((src[x+3] >> 11) & 31) << 3)] [(((src[x] >> 11) & 31) << 3)]; - - fil[(x+2)*3] = voodoo->thefilterb [fil3[(x+2)*3]][((src[x] & 31) << 3)]; - fil[(x+2)*3+1] = voodoo->thefilterg [fil3[(x+2)*3+1]][(((src[x] >> 5) & 63) << 2)]; - fil[(x+2)*3+2] = voodoo->thefilter [fil3[(x+2)*3+2]][(((src[x] >> 11) & 31) << 3)]; - - fil3[(x+1)*3] = voodoo->thefilterb [fil[(x+1)*3]][((src[x] & 31) << 3)]; - fil3[(x+1)*3+1] = voodoo->thefilterg [fil[(x+1)*3+1]][(((src[x] >> 5) & 63) << 2)]; - fil3[(x+1)*3+2] = voodoo->thefilter [fil[(x+1)*3+2]][(((src[x] >> 11) & 31) << 3)]; - - fil[(x-1)*3] = voodoo->thefilterb [fil3[(x-1)*3]][((src[x] & 31) << 3)]; - fil[(x-1)*3+1] = voodoo->thefilterg [fil3[(x-1)*3+1]][(((src[x] >> 5) & 63) << 2)]; - fil[(x-1)*3+2] = voodoo->thefilter [fil3[(x-1)*3+2]][(((src[x] >> 11) & 31) << 3)]; - } - - // unroll for edge cases - - fil3[(column-3)*3] = voodoo->thefilterb [((src[column-3] & 31) << 3)] [((src[column] & 31) << 3)]; - fil3[(column-3)*3+1] = voodoo->thefilterg [(((src[column-3] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; - fil3[(column-3)*3+2] = voodoo->thefilter [(((src[column-3] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; - - fil3[(column-2)*3] = voodoo->thefilterb [((src[column-2] & 31) << 3)] [((src[column] & 31) << 3)]; - fil3[(column-2)*3+1] = voodoo->thefilterg [(((src[column-2] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; - fil3[(column-2)*3+2] = voodoo->thefilter [(((src[column-2] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; - - fil3[(column-1)*3] = voodoo->thefilterb [((src[column-1] & 31) << 3)] [((src[column] & 31) << 3)]; - fil3[(column-1)*3+1] = voodoo->thefilterg [(((src[column-1] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; - fil3[(column-1)*3+2] = voodoo->thefilter [(((src[column-1] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; - - fil[(column-2)*3] = voodoo->thefilterb [fil3[(column-2)*3]][((src[column] & 31) << 3)]; - fil[(column-2)*3+1] = voodoo->thefilterg [fil3[(column-2)*3+1]][(((src[column] >> 5) & 63) << 2)]; - fil[(column-2)*3+2] = voodoo->thefilter [fil3[(column-2)*3+2]][(((src[column] >> 11) & 31) << 3)]; - - fil[(column-1)*3] = voodoo->thefilterb [fil3[(column-1)*3]][((src[column] & 31) << 3)]; - fil[(column-1)*3+1] = voodoo->thefilterg [fil3[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)]; - fil[(column-1)*3+2] = voodoo->thefilter [fil3[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)]; - - fil3[(column-1)*3] = voodoo->thefilterb [fil[(column-1)*3]][((src[column] & 31) << 3)]; - fil3[(column-1)*3+1] = voodoo->thefilterg [fil[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)]; - fil3[(column-1)*3+2] = voodoo->thefilter [fil[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)]; -} - -void voodoo_callback(void *p) -{ - voodoo_t *voodoo = (voodoo_t *)p; - - if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) - { - if (voodoo->line < voodoo->v_disp) - { - voodoo_t *draw_voodoo; - int draw_line; - - if (SLI_ENABLED) - { - if (voodoo == voodoo->set->voodoos[1]) - goto skip_draw; - - if (((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) ? 1 : 0) == (voodoo->line & 1)) - draw_voodoo = voodoo; - else - draw_voodoo = voodoo->set->voodoos[1]; - draw_line = voodoo->line >> 1; - } - else - { - if (!(voodoo->fbiInit0 & 1)) - goto skip_draw; - draw_voodoo = voodoo; - draw_line = voodoo->line; - } - - if (draw_voodoo->dirty_line[draw_line]) - { - uint32_t *p = &((uint32_t *)buffer32->line[voodoo->line])[32]; - uint16_t *src = (uint16_t *)&draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line*draw_voodoo->row_width]; - int x; - - draw_voodoo->dirty_line[draw_line] = 0; - - if (voodoo->line < voodoo->dirty_line_low) - { - voodoo->dirty_line_low = voodoo->line; - video_wait_for_buffer(); - } - if (voodoo->line > voodoo->dirty_line_high) - voodoo->dirty_line_high = voodoo->line; - - if (voodoo->scrfilter && voodoo->scrfilterEnabled) - { - uint8_t fil[(voodoo->h_disp) * 3]; /* interleaved 24-bit RGB */ - - if (voodoo->type == VOODOO_2) - voodoo_filterline_v2(voodoo, fil, voodoo->h_disp, src, voodoo->line); - else - voodoo_filterline_v1(voodoo, fil, voodoo->h_disp, src, voodoo->line); - - for (x = 0; x < voodoo->h_disp; x++) - { - 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); - } - } - else - { - for (x = 0; x < voodoo->h_disp; x++) - { - p[x] = draw_voodoo->video_16to32[src[x]]; - } - } - } - } - } -skip_draw: - if (voodoo->line == voodoo->v_disp) - { -// pclog("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending); - voodoo->retrace_count++; - if (SLI_ENABLED && (voodoo->fbiInit2 & FBIINIT2_SWAP_ALGORITHM_MASK) == FBIINIT2_SWAP_ALGORITHM_SLI_SYNC) - { - if (voodoo == voodoo->set->voodoos[0]) - { - voodoo_t *voodoo_1 = voodoo->set->voodoos[1]; - - /*Only swap if both Voodoos are waiting for buffer swap*/ - if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval) && - voodoo_1->swap_pending && (voodoo_1->retrace_count > voodoo_1->swap_interval)) - { - memset(voodoo->dirty_line, 1, 1024); - voodoo->retrace_count = 0; - voodoo->front_offset = voodoo->swap_offset; - if (voodoo->swap_count > 0) - voodoo->swap_count--; - voodoo->swap_pending = 0; - - memset(voodoo_1->dirty_line, 1, 1024); - voodoo_1->retrace_count = 0; - voodoo_1->front_offset = voodoo_1->swap_offset; - if (voodoo_1->swap_count > 0) - voodoo_1->swap_count--; - voodoo_1->swap_pending = 0; - - thread_set_event(voodoo->wake_fifo_thread); - thread_set_event(voodoo_1->wake_fifo_thread); - - voodoo->frame_count++; - voodoo_1->frame_count++; - } - } - } - else - { - if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval)) - { - memset(voodoo->dirty_line, 1, 1024); - voodoo->retrace_count = 0; - voodoo->front_offset = voodoo->swap_offset; - if (voodoo->swap_count > 0) - voodoo->swap_count--; - voodoo->swap_pending = 0; - thread_set_event(voodoo->wake_fifo_thread); - voodoo->frame_count++; - } - } - voodoo->v_retrace = 1; - } - voodoo->line++; - - if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) - { - if (voodoo->line == voodoo->v_disp) - { - if (voodoo->dirty_line_high > voodoo->dirty_line_low) - svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); - if (voodoo->clutData_dirty) - { - voodoo->clutData_dirty = 0; - voodoo_calc_clutData(voodoo); - } - voodoo->dirty_line_high = -1; - voodoo->dirty_line_low = 2000; - } - } - - if (voodoo->line >= voodoo->v_total) - { - voodoo->line = 0; - voodoo->v_retrace = 0; - } - if (voodoo->line_time) - timer_advance_u64(&voodoo->timer, voodoo->line_time); - else - timer_advance_u64(&voodoo->timer, TIMER_USEC * 32); -} static void voodoo_add_status_info(char *s, int max_len, void *p) { @@ -7652,10 +985,10 @@ void *voodoo_card_init() voodoo->fifo_not_full_event = thread_create_event(); voodoo->render_not_full_event[0] = thread_create_event(); voodoo->render_not_full_event[1] = thread_create_event(); - voodoo->fifo_thread = thread_create(fifo_thread, voodoo); - voodoo->render_thread[0] = thread_create(render_thread_1, voodoo); + voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo); + voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo); if (voodoo->render_threads == 2) - voodoo->render_thread[1] = thread_create(render_thread_2, voodoo); + voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo); timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *)voodoo, 0); diff --git a/src/vid_voodoo_blitter.c b/src/vid_voodoo_blitter.c new file mode 100644 index 0000000..f9b7538 --- /dev/null +++ b/src/vid_voodoo_blitter.c @@ -0,0 +1,479 @@ +#include +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "thread.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_blitter.h" +#include "vid_voodoo_dither.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" + +enum +{ + BLIT_COMMAND_SCREEN_TO_SCREEN = 0, + BLIT_COMMAND_CPU_TO_SCREEN = 1, + BLIT_COMMAND_RECT_FILL = 2, + BLIT_COMMAND_SGRAM_FILL = 3 +}; + +enum +{ + BLIT_SRC_1BPP = (0 << 3), + BLIT_SRC_1BPP_BYTE_PACKED = (1 << 3), + BLIT_SRC_16BPP = (2 << 3), + BLIT_SRC_24BPP = (3 << 3), + BLIT_SRC_24BPP_DITHER_2X2 = (4 << 3), + BLIT_SRC_24BPP_DITHER_4X4 = (5 << 3) +}; + +enum +{ + BLIT_SRC_RGB_ARGB = (0 << 6), + BLIT_SRC_RGB_ABGR = (1 << 6), + BLIT_SRC_RGB_RGBA = (2 << 6), + BLIT_SRC_RGB_BGRA = (3 << 6) +}; + +enum +{ + BLIT_COMMAND_MASK = 7, + BLIT_SRC_FORMAT = (7 << 3), + BLIT_SRC_RGB_FORMAT = (3 << 6), + BLIT_SRC_CHROMA = (1 << 10), + BLIT_DST_CHROMA = (1 << 12), + BLIT_CLIPPING_ENABLED = (1 << 16) +}; + +enum +{ + BLIT_ROP_DST_PASS = (1 << 0), + BLIT_ROP_SRC_PASS = (1 << 1) +}; + +#define MIX(src_dat, dst_dat, rop) \ + switch (rop) \ + { \ + case 0x0: dst_dat = 0; break; \ + case 0x1: dst_dat = ~(src_dat | dst_dat); break; \ + case 0x2: dst_dat = ~src_dat & dst_dat; break; \ + case 0x3: dst_dat = ~src_dat; break; \ + case 0x4: dst_dat = src_dat & ~dst_dat; break; \ + case 0x5: dst_dat = ~dst_dat; break; \ + case 0x6: dst_dat = src_dat ^ dst_dat; break; \ + case 0x7: dst_dat = ~(src_dat & dst_dat); break; \ + case 0x8: dst_dat = src_dat & dst_dat; break; \ + case 0x9: dst_dat = ~(src_dat ^ dst_dat); break; \ + case 0xa: dst_dat = dst_dat; break; \ + case 0xb: dst_dat = ~src_dat | dst_dat; break; \ + case 0xc: dst_dat = src_dat; break; \ + case 0xd: dst_dat = src_dat | ~dst_dat; break; \ + case 0xe: dst_dat = src_dat | dst_dat; break; \ + case 0xf: dst_dat = 0xffff; break; \ + } + +void voodoo_v2_blit_start(voodoo_t *voodoo) +{ + uint64_t dat64; + int size_x = ABS(voodoo->bltSizeX), size_y = ABS(voodoo->bltSizeY); + int x_dir = (voodoo->bltSizeX > 0) ? 1 : -1; + int y_dir = (voodoo->bltSizeY > 0) ? 1 : -1; + int dst_x; + int src_y = voodoo->bltSrcY & 0x7ff, dst_y = voodoo->bltDstY & 0x7ff; + int src_stride = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcXYStride & 0x3f) * 32*2) : (voodoo->bltSrcXYStride & 0xff8); + int dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8); + uint32_t src_base_addr = (voodoo->bltCommand & BLTCMD_SRC_TILED) ? ((voodoo->bltSrcBaseAddr & 0x3ff) << 12) : (voodoo->bltSrcBaseAddr & 0x3ffff8); + uint32_t dst_base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); + int x, y; + +/* pclog("blit_start: command=%08x srcX=%i srcY=%i dstX=%i dstY=%i sizeX=%i sizeY=%i color=%04x,%04x\n", + voodoo->bltCommand, voodoo->bltSrcX, voodoo->bltSrcY, voodoo->bltDstX, voodoo->bltDstY, voodoo->bltSizeX, voodoo->bltSizeY, voodoo->bltColorFg, voodoo->bltColorBg);*/ + + voodoo_wait_for_render_thread_idle(voodoo); + + switch (voodoo->bltCommand & BLIT_COMMAND_MASK) + { + case BLIT_COMMAND_SCREEN_TO_SCREEN: + for (y = 0; y <= size_y; y++) + { + uint16_t *src = (uint16_t *)&voodoo->fb_mem[src_base_addr + src_y*src_stride]; + uint16_t *dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride]; + int src_x = voodoo->bltSrcX, dst_x = voodoo->bltDstX; + + for (x = 0; x <= size_x; x++) + { + uint16_t src_dat = src[src_x]; + uint16_t dst_dat = dst[dst_x]; + int rop = 0; + + if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) + { + if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || + dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY) + goto skip_pixel_blit; + } + + if (voodoo->bltCommand & BLIT_SRC_CHROMA) + { + int r = (src_dat >> 11); + int g = (src_dat >> 5) & 0x3f; + int b = src_dat & 0x1f; + + if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && + g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && + b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB) + rop |= BLIT_ROP_SRC_PASS; + } + if (voodoo->bltCommand & BLIT_DST_CHROMA) + { + int r = (dst_dat >> 11); + int g = (dst_dat >> 5) & 0x3f; + int b = dst_dat & 0x1f; + + if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && + g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && + b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB) + rop |= BLIT_ROP_DST_PASS; + } + + MIX(src_dat, dst_dat, voodoo->bltRop[rop]); + + dst[dst_x] = dst_dat; +skip_pixel_blit: + src_x += x_dir; + dst_x += x_dir; + } + + src_y += y_dir; + dst_y += y_dir; + } + break; + + case BLIT_COMMAND_CPU_TO_SCREEN: + voodoo->blt.dst_x = voodoo->bltDstX; + voodoo->blt.dst_y = voodoo->bltDstY; + voodoo->blt.cur_x = 0; + voodoo->blt.size_x = size_x; + voodoo->blt.size_y = size_y; + voodoo->blt.x_dir = x_dir; + voodoo->blt.y_dir = y_dir; + voodoo->blt.dst_stride = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstXYStride & 0x3f) * 32*2) : (voodoo->bltDstXYStride & 0xff8); + break; + + case BLIT_COMMAND_RECT_FILL: + for (y = 0; y <= size_y; y++) + { + uint16_t *dst; + int dst_x = voodoo->bltDstX; + + if (SLI_ENABLED) + { + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || + ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1))) + goto skip_line_fill; + dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + (dst_y >> 1) * dst_stride]; + } + else + dst = (uint16_t *)&voodoo->fb_mem[dst_base_addr + dst_y*dst_stride]; + + for (x = 0; x <= size_x; x++) + { + if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) + { + if (dst_x < voodoo->bltClipLeft || dst_x >= voodoo->bltClipRight || + dst_y < voodoo->bltClipLowY || dst_y >= voodoo->bltClipHighY) + goto skip_pixel_fill; + } + + dst[dst_x] = voodoo->bltColorFg; +skip_pixel_fill: + dst_x += x_dir; + } +skip_line_fill: + dst_y += y_dir; + } + break; + + case BLIT_COMMAND_SGRAM_FILL: + /*32x32 tiles - 2kb*/ + dst_y = voodoo->bltDstY & 0x3ff; + size_x = voodoo->bltSizeX & 0x1ff; //512*8 = 4kb + size_y = voodoo->bltSizeY & 0x3ff; + + dat64 = voodoo->bltColorFg | ((uint64_t)voodoo->bltColorFg << 16) | + ((uint64_t)voodoo->bltColorFg << 32) | ((uint64_t)voodoo->bltColorFg << 48); + + for (y = 0; y <= size_y; y++) + { + uint64_t *dst; + + /*This may be wrong*/ + if (!y) + { + dst_x = voodoo->bltDstX & 0x1ff; + size_x = 511 - dst_x; + } + else if (y < size_y) + { + dst_x = 0; + size_x = 511; + } + else + { + dst_x = 0; + size_x = voodoo->bltSizeX & 0x1ff; + } + + dst = (uint64_t *)&voodoo->fb_mem[(dst_y*512*8 + dst_x*8) & voodoo->fb_mask]; + + for (x = 0; x <= size_x; x++) + dst[x] = dat64; + + dst_y++; + } + break; + + default: + fatal("bad blit command %08x\n", voodoo->bltCommand); + } +} + +void voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data) +{ + int src_bits = 32; + uint32_t base_addr = (voodoo->bltCommand & BLTCMD_DST_TILED) ? ((voodoo->bltDstBaseAddr & 0x3ff) << 12) : (voodoo->bltDstBaseAddr & 0x3ffff8); + uint32_t addr; + uint16_t *dst; + + if ((voodoo->bltCommand & BLIT_COMMAND_MASK) != BLIT_COMMAND_CPU_TO_SCREEN) + return; + + if (SLI_ENABLED) + { + addr = base_addr + (voodoo->blt.dst_y >> 1) * voodoo->blt.dst_stride; + dst = (uint16_t *)&voodoo->fb_mem[addr]; + } + else + { + addr = base_addr + voodoo->blt.dst_y*voodoo->blt.dst_stride; + dst = (uint16_t *)&voodoo->fb_mem[addr]; + } + + if (addr >= voodoo->front_offset && voodoo->row_width) + { + int y = (addr - voodoo->front_offset) / voodoo->row_width; + if (y < voodoo->v_disp) + voodoo->dirty_line[y] = 2; + } + + while (src_bits && voodoo->blt.cur_x <= voodoo->blt.size_x) + { + int r = 0, g = 0, b = 0; + uint16_t src_dat = 0, dst_dat; + int x = (voodoo->blt.x_dir > 0) ? (voodoo->blt.dst_x + voodoo->blt.cur_x) : (voodoo->blt.dst_x - voodoo->blt.cur_x); + int rop = 0; + + switch (voodoo->bltCommand & BLIT_SRC_FORMAT) + { + case BLIT_SRC_1BPP: case BLIT_SRC_1BPP_BYTE_PACKED: + src_dat = (data & 1) ? voodoo->bltColorFg : voodoo->bltColorBg; + data >>= 1; + src_bits--; + break; + case BLIT_SRC_16BPP: + switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) + { + case BLIT_SRC_RGB_ARGB: case BLIT_SRC_RGB_RGBA: + src_dat = data & 0xffff; + break; + case BLIT_SRC_RGB_ABGR: case BLIT_SRC_RGB_BGRA: + src_dat = ((data & 0xf800) >> 11) | (data & 0x07c0) | ((data & 0x0038) << 11); + break; + } + data >>= 16; + src_bits -= 16; + break; + case BLIT_SRC_24BPP: case BLIT_SRC_24BPP_DITHER_2X2: case BLIT_SRC_24BPP_DITHER_4X4: + switch (voodoo->bltCommand & BLIT_SRC_RGB_FORMAT) + { + case BLIT_SRC_RGB_ARGB: + r = (data >> 16) & 0xff; + g = (data >> 8) & 0xff; + b = data & 0xff; + break; + case BLIT_SRC_RGB_ABGR: + r = data & 0xff; + g = (data >> 8) & 0xff; + b = (data >> 16) & 0xff; + break; + case BLIT_SRC_RGB_RGBA: + r = (data >> 24) & 0xff; + g = (data >> 16) & 0xff; + b = (data >> 8) & 0xff; + break; + case BLIT_SRC_RGB_BGRA: + r = (data >> 8) & 0xff; + g = (data >> 16) & 0xff; + b = (data >> 24) & 0xff; + break; + } + switch (voodoo->bltCommand & BLIT_SRC_FORMAT) + { + case BLIT_SRC_24BPP: + src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); + break; + case BLIT_SRC_24BPP_DITHER_2X2: + r = dither_rb2x2[r][voodoo->blt.dst_y & 1][x & 1]; + g = dither_g2x2[g][voodoo->blt.dst_y & 1][x & 1]; + b = dither_rb2x2[b][voodoo->blt.dst_y & 1][x & 1]; + src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); + break; + case BLIT_SRC_24BPP_DITHER_4X4: + r = dither_rb[r][voodoo->blt.dst_y & 3][x & 3]; + g = dither_g[g][voodoo->blt.dst_y & 3][x & 3]; + b = dither_rb[b][voodoo->blt.dst_y & 3][x & 3]; + src_dat = (b >> 3) | ((g & 0xfc) << 3) | ((r & 0xf8) << 8); + break; + } + src_bits = 0; + break; + } + + if (SLI_ENABLED) + { + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (voodoo->blt.dst_y & 1)) || + ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(voodoo->blt.dst_y & 1))) + goto skip_pixel; + } + + if (voodoo->bltCommand & BLIT_CLIPPING_ENABLED) + { + if (x < voodoo->bltClipLeft || x >= voodoo->bltClipRight || + voodoo->blt.dst_y < voodoo->bltClipLowY || voodoo->blt.dst_y >= voodoo->bltClipHighY) + goto skip_pixel; + } + + dst_dat = dst[x]; + + if (voodoo->bltCommand & BLIT_SRC_CHROMA) + { + r = (src_dat >> 11); + g = (src_dat >> 5) & 0x3f; + b = src_dat & 0x1f; + + if (r >= voodoo->bltSrcChromaMinR && r <= voodoo->bltSrcChromaMaxR && + g >= voodoo->bltSrcChromaMinG && g <= voodoo->bltSrcChromaMaxG && + b >= voodoo->bltSrcChromaMinB && b <= voodoo->bltSrcChromaMaxB) + rop |= BLIT_ROP_SRC_PASS; + } + if (voodoo->bltCommand & BLIT_DST_CHROMA) + { + r = (dst_dat >> 11); + g = (dst_dat >> 5) & 0x3f; + b = dst_dat & 0x1f; + + if (r >= voodoo->bltDstChromaMinR && r <= voodoo->bltDstChromaMaxR && + g >= voodoo->bltDstChromaMinG && g <= voodoo->bltDstChromaMaxG && + b >= voodoo->bltDstChromaMinB && b <= voodoo->bltDstChromaMaxB) + rop |= BLIT_ROP_DST_PASS; + } + + MIX(src_dat, dst_dat, voodoo->bltRop[rop]); + + dst[x] = dst_dat; + +skip_pixel: + voodoo->blt.cur_x++; + } + + if (voodoo->blt.cur_x > voodoo->blt.size_x) + { + voodoo->blt.size_y--; + if (voodoo->blt.size_y >= 0) + { + voodoo->blt.cur_x = 0; + voodoo->blt.dst_y += voodoo->blt.y_dir; + } + } +} + + +void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params) +{ + int y; + int low_y, high_y; + + if (params->fbzMode & (1 << 17)) + { + high_y = voodoo->v_disp - params->clipLowY; + low_y = voodoo->v_disp - params->clipHighY; + } + else + { + low_y = params->clipLowY; + high_y = params->clipHighY; + } + + if (params->fbzMode & FBZ_RGB_WMASK) + { + int r, g, b; + uint16_t col; + + r = ((params->color1 >> 16) >> 3) & 0x1f; + g = ((params->color1 >> 8) >> 2) & 0x3f; + b = (params->color1 >> 3) & 0x1f; + col = b | (g << 5) | (r << 11); + + if (SLI_ENABLED) + { + for (y = low_y; y < high_y; y += 2) + { + uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask]; + int x; + + for (x = params->clipLeft; x < params->clipRight; x++) + cbuf[x] = col; + } + } + else + { + for (y = low_y; y < high_y; y++) + { + uint16_t *cbuf = (uint16_t *)&voodoo->fb_mem[(params->draw_offset + y*voodoo->row_width) & voodoo->fb_mask]; + int x; + + for (x = params->clipLeft; x < params->clipRight; x++) + cbuf[x] = col; + } + } + } + if (params->fbzMode & FBZ_DEPTH_WMASK) + { + if (SLI_ENABLED) + { + for (y = low_y; y < high_y; y += 2) + { + uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (y >> 1) * voodoo->row_width) & voodoo->fb_mask]; + int x; + + for (x = params->clipLeft; x < params->clipRight; x++) + abuf[x] = params->zaColor & 0xffff; + } + } + else + { + for (y = low_y; y < high_y; y++) + { + uint16_t *abuf = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + y*voodoo->row_width) & voodoo->fb_mask]; + int x; + + for (x = params->clipLeft; x < params->clipRight; x++) + abuf[x] = params->zaColor & 0xffff; + } + } + } +} diff --git a/src/vid_voodoo_blitter.h b/src/vid_voodoo_blitter.h new file mode 100644 index 0000000..8d315df --- /dev/null +++ b/src/vid_voodoo_blitter.h @@ -0,0 +1,3 @@ +void voodoo_v2_blit_start(voodoo_t *voodoo); +void voodoo_v2_blit_data(voodoo_t *voodoo, uint32_t data); +void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params); diff --git a/src/vid_voodoo_codegen_x86-64.h b/src/vid_voodoo_codegen_x86-64.h index 8462479..4b5335b 100644 --- a/src/vid_voodoo_codegen_x86-64.h +++ b/src/vid_voodoo_codegen_x86-64.h @@ -3288,7 +3288,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo addbyte(0xC3); /*RET*/ } -static int voodoo_recomp = 0; +int voodoo_recomp = 0; static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even) { int c; @@ -3339,7 +3339,7 @@ voodoo_recomp++; return data->code_block; } -static void voodoo_codegen_init(voodoo_t *voodoo) +void voodoo_codegen_init(voodoo_t *voodoo) { int c; @@ -3371,7 +3371,7 @@ static void voodoo_codegen_init(voodoo_t *voodoo) xmm_00_ff_w[1] = _mm_set_epi32(0, 0, 0xff | (0xff << 16), 0xff | (0xff << 16)); } -static void voodoo_codegen_close(voodoo_t *voodoo) +void voodoo_codegen_close(voodoo_t *voodoo) { #if WIN64 VirtualFree(voodoo->codegen_data, 0, MEM_RELEASE); diff --git a/src/vid_voodoo_codegen_x86.h b/src/vid_voodoo_codegen_x86.h index b09ed0e..5d14b24 100644 --- a/src/vid_voodoo_codegen_x86.h +++ b/src/vid_voodoo_codegen_x86.h @@ -3227,7 +3227,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo if (params->textureMode[1] & TEXTUREMODE_TRILINEAR) cs = cs; } -static int voodoo_recomp = 0; +int voodoo_recomp = 0; static inline void *voodoo_get_block(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int odd_even) { @@ -3279,7 +3279,7 @@ voodoo_recomp++; return data->code_block; } -static void voodoo_codegen_init(voodoo_t *voodoo) +void voodoo_codegen_init(voodoo_t *voodoo) { int c; #if defined(__linux__) || defined(__APPLE__) @@ -3317,7 +3317,7 @@ static void voodoo_codegen_init(voodoo_t *voodoo) xmm_00_ff_w[1] = _mm_set_epi32(0, 0, 0xff | (0xff << 16), 0xff | (0xff << 16)); } -static void voodoo_codegen_close(voodoo_t *voodoo) +void voodoo_codegen_close(voodoo_t *voodoo) { #if defined WIN32 || defined _WIN32 || defined _WIN32 VirtualFree(voodoo->codegen_data, 0, MEM_RELEASE); diff --git a/src/vid_voodoo_common.h b/src/vid_voodoo_common.h new file mode 100644 index 0000000..093fccd --- /dev/null +++ b/src/vid_voodoo_common.h @@ -0,0 +1,399 @@ +#ifdef MIN +#undef MIN +#endif +#ifdef CLAMP +#undef CLAMP +#endif + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#define CLAMP(x) (((x) < 0) ? 0 : (((x) > 0xff) ? 0xff : (x))) +#define CLAMP16(x) (((x) < 0) ? 0 : (((x) > 0xffff) ? 0xffff : (x))) + + +#define LOD_MAX 8 + +#define TEX_DIRTY_SHIFT 10 + +#define TEX_CACHE_MAX 64 + +enum +{ + VOODOO_1 = 0, + VOODOO_SB50 = 1, + VOODOO_2 = 2 +}; + +typedef union int_float +{ + uint32_t i; + float f; +} int_float; + +typedef struct rgb_t +{ + uint8_t b, g, r; + uint8_t pad; +} rgb_t; +typedef struct rgba8_t +{ + uint8_t b, g, r, a; +} rgba8_t; + +typedef union rgba_u +{ + struct + { + uint8_t b, g, r, a; + } rgba; + uint32_t u; +} rgba_u; + +#define FIFO_SIZE 65536 +#define FIFO_MASK (FIFO_SIZE - 1) +#define FIFO_ENTRY_SIZE (1 << 31) + +#define FIFO_ENTRIES (voodoo->fifo_write_idx - voodoo->fifo_read_idx) +#define FIFO_FULL ((voodoo->fifo_write_idx - voodoo->fifo_read_idx) >= FIFO_SIZE-4) +#define FIFO_EMPTY (voodoo->fifo_read_idx == voodoo->fifo_write_idx) + +#define FIFO_TYPE 0xff000000 +#define FIFO_ADDR 0x00ffffff + +enum +{ + FIFO_INVALID = (0x00 << 24), + FIFO_WRITEL_REG = (0x01 << 24), + FIFO_WRITEW_FB = (0x02 << 24), + FIFO_WRITEL_FB = (0x03 << 24), + FIFO_WRITEL_TEX = (0x04 << 24) +}; + +#define PARAM_SIZE 1024 +#define PARAM_MASK (PARAM_SIZE - 1) +#define PARAM_ENTRY_SIZE (1 << 31) + +#define PARAM_ENTRIES_1 (voodoo->params_write_idx - voodoo->params_read_idx[0]) +#define PARAM_ENTRIES_2 (voodoo->params_write_idx - voodoo->params_read_idx[1]) +#define PARAM_FULL_1 ((voodoo->params_write_idx - voodoo->params_read_idx[0]) >= PARAM_SIZE) +#define PARAM_FULL_2 ((voodoo->params_write_idx - voodoo->params_read_idx[1]) >= PARAM_SIZE) +#define PARAM_EMPTY_1 (voodoo->params_read_idx[0] == voodoo->params_write_idx) +#define PARAM_EMPTY_2 (voodoo->params_read_idx[1] == voodoo->params_write_idx) + +typedef struct +{ + uint32_t addr_type; + uint32_t val; +} fifo_entry_t; + +typedef struct voodoo_params_t +{ + int command; + + int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy; + + uint32_t startR, startG, startB, startZ, startA; + + int32_t dBdX, dGdX, dRdX, dAdX, dZdX; + + int32_t dBdY, dGdY, dRdY, dAdY, dZdY; + + int64_t startW, dWdX, dWdY; + + struct + { + int64_t startS, startT, startW, p1; + int64_t dSdX, dTdX, dWdX, p2; + int64_t dSdY, dTdY, dWdY, p3; + } tmu[2]; + + uint32_t color0, color1; + + uint32_t fbzMode; + uint32_t fbzColorPath; + + uint32_t fogMode; + rgb_t fogColor; + struct + { + uint8_t fog, dfog; + } fogTable[64]; + + uint32_t alphaMode; + + uint32_t zaColor; + + int chromaKey_r, chromaKey_g, chromaKey_b; + uint32_t chromaKey; + + uint32_t textureMode[2]; + uint32_t tLOD[2]; + + uint32_t texBaseAddr[2], texBaseAddr1[2], texBaseAddr2[2], texBaseAddr38[2]; + + uint32_t tex_base[2][LOD_MAX+2]; + uint32_t tex_end[2][LOD_MAX+2]; + int tex_width[2]; + int tex_w_mask[2][LOD_MAX+2]; + int tex_w_nmask[2][LOD_MAX+2]; + int tex_h_mask[2][LOD_MAX+2]; + int tex_shift[2][LOD_MAX+2]; + int tex_lod[2][LOD_MAX+2]; + int tex_entry[2]; + int detail_max[2], detail_bias[2], detail_scale[2]; + + uint32_t draw_offset, aux_offset; + + int tformat[2]; + + int clipLeft, clipRight, clipLowY, clipHighY; + + int sign; + + uint32_t front_offset; + + uint32_t swapbufferCMD; + + uint32_t stipple; +} voodoo_params_t; + +typedef struct texture_t +{ + uint32_t base; + uint32_t tLOD; + volatile int refcount, refcount_r[2]; + int is16; + uint32_t palette_checksum; + uint32_t addr_start[4], addr_end[4]; + uint32_t *data; +} texture_t; + +typedef struct vert_t +{ + float sVx, sVy; + float sRed, sGreen, sBlue, sAlpha; + float sVz, sWb; + float sW0, sS0, sT0; + float sW1, sS1, sT1; +} vert_t; + +typedef struct voodoo_t +{ + mem_mapping_t mapping; + + int pci_enable; + + uint8_t dac_data[8]; + int dac_reg, dac_reg_ff; + uint8_t dac_readdata; + uint16_t dac_pll_regs[16]; + + float pixel_clock; + uint64_t line_time; + + voodoo_params_t params; + + uint32_t fbiInit0, fbiInit1, fbiInit2, fbiInit3, fbiInit4; + uint32_t fbiInit5, fbiInit6, fbiInit7; /*Voodoo 2*/ + + uint32_t initEnable; + + uint32_t lfbMode; + + uint32_t memBaseAddr; + + int_float fvertexAx, fvertexAy, fvertexBx, fvertexBy, fvertexCx, fvertexCy; + + uint32_t front_offset, back_offset; + + uint32_t fb_read_offset, fb_write_offset; + + int row_width; + int block_width; + + uint8_t *fb_mem, *tex_mem[2]; + uint16_t *tex_mem_w[2]; + + int rgb_sel; + + uint32_t trexInit1[2]; + + uint32_t tmuConfig; + + int swap_count; + + int disp_buffer, draw_buffer; + pc_timer_t timer; + + int line; + svga_t *svga; + + uint32_t backPorch; + uint32_t videoDimensions; + uint32_t hSync, vSync; + + int h_total, v_total, v_disp; + int h_disp; + int v_retrace; + + struct + { + uint32_t y[4], i[4], q[4]; + } nccTable[2][2]; + + rgba_u palette[2][256]; + + rgba_u ncc_lookup[2][2][256]; + int ncc_dirty[2]; + + thread_t *fifo_thread; + thread_t *render_thread[2]; + event_t *wake_fifo_thread; + event_t *wake_main_thread; + event_t *fifo_not_full_event; + event_t *render_not_full_event[2]; + event_t *wake_render_thread[2]; + + int voodoo_busy; + int render_voodoo_busy[2]; + + int render_threads; + int odd_even_mask; + + int pixel_count[2], texel_count[2], tri_count, frame_count; + int pixel_count_old[2], texel_count_old[2]; + int wr_count, rd_count, tex_count; + + int retrace_count; + int swap_interval; + uint32_t swap_offset; + int swap_pending; + + int bilinear_enabled; + + int fb_size; + uint32_t fb_mask; + + int texture_size; + uint32_t texture_mask; + + int dual_tmus; + int type; + + fifo_entry_t fifo[FIFO_SIZE]; + volatile int fifo_read_idx, fifo_write_idx; + volatile int cmd_read, cmd_written, cmd_written_fifo; + + voodoo_params_t params_buffer[PARAM_SIZE]; + volatile int params_read_idx[2], params_write_idx; + + uint32_t cmdfifo_base, cmdfifo_end; + int cmdfifo_rp; + volatile int cmdfifo_depth_rd, cmdfifo_depth_wr; + uint32_t cmdfifo_amin, cmdfifo_amax; + + uint32_t sSetupMode; + vert_t verts[4]; + int vertex_num; + int num_verticies; + + int flush; + + int scrfilter; + int scrfilterEnabled; + int scrfilterThreshold; + int scrfilterThresholdOld; + + uint32_t last_write_addr; + + uint32_t fbiPixelsIn; + uint32_t fbiChromaFail; + uint32_t fbiZFuncFail; + uint32_t fbiAFuncFail; + uint32_t fbiPixelsOut; + + uint32_t bltSrcBaseAddr; + uint32_t bltDstBaseAddr; + int bltSrcXYStride, bltDstXYStride; + uint32_t bltSrcChromaRange, bltDstChromaRange; + int bltSrcChromaMinR, bltSrcChromaMinG, bltSrcChromaMinB; + int bltSrcChromaMaxR, bltSrcChromaMaxG, bltSrcChromaMaxB; + int bltDstChromaMinR, bltDstChromaMinG, bltDstChromaMinB; + int bltDstChromaMaxR, bltDstChromaMaxG, bltDstChromaMaxB; + + int bltClipRight, bltClipLeft; + int bltClipHighY, bltClipLowY; + + int bltSrcX, bltSrcY; + int bltDstX, bltDstY; + int bltSizeX, bltSizeY; + int bltRop[4]; + uint16_t bltColorFg, bltColorBg; + + uint32_t bltCommand; + + struct + { + int dst_x, dst_y; + int cur_x; + int size_x, size_y; + int x_dir, y_dir; + int dst_stride; + } blt; + + rgb_t clutData[33]; + int clutData_dirty; + rgb_t clutData256[256]; + uint32_t video_16to32[0x10000]; + + uint8_t dirty_line[1024]; + int dirty_line_low, dirty_line_high; + + int fb_write_buffer, fb_draw_buffer; + int buffer_cutoff; + + int read_time, write_time, burst_time; + + pc_timer_t wake_timer; + + uint8_t thefilter[256][256]; // pixel filter, feeding from one or two + uint8_t thefilterg[256][256]; // for green + uint8_t thefilterb[256][256]; // for blue + + /* the voodoo adds purple lines for some reason */ + uint16_t purpleline[256][3]; + + texture_t texture_cache[2][TEX_CACHE_MAX]; + uint8_t texture_present[2][4096]; + int texture_last_removed; + + uint32_t palette_checksum[2]; + int palette_dirty[2]; + + uint64_t time; + int render_time[2]; + + int use_recompiler; + void *codegen_data; + + struct voodoo_set_t *set; +} voodoo_t; + +typedef struct voodoo_set_t +{ + voodoo_t *voodoos[2]; + + mem_mapping_t snoop_mapping; + + int nr_cards; +} voodoo_set_t; + + +extern rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000]; + + + + +void voodoo_recalc(voodoo_t *voodoo); +void voodoo_update_ncc(voodoo_t *voodoo, int tmu); + diff --git a/src/vid_voodoo_display.c b/src/vid_voodoo_display.c new file mode 100644 index 0000000..d643d5d --- /dev/null +++ b/src/vid_voodoo_display.c @@ -0,0 +1,603 @@ +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "thread.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_display.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" + +void voodoo_update_ncc(voodoo_t *voodoo, int tmu) +{ + int tbl; + + for (tbl = 0; tbl < 2; tbl++) + { + int col; + + for (col = 0; col < 256; col++) + { + int y = (col >> 4), i = (col >> 2) & 3, q = col & 3; + int i_r, i_g, i_b; + int q_r, q_g, q_b; + + y = (voodoo->nccTable[tmu][tbl].y[y >> 2] >> ((y & 3) * 8)) & 0xff; + + i_r = (voodoo->nccTable[tmu][tbl].i[i] >> 18) & 0x1ff; + if (i_r & 0x100) + i_r |= 0xfffffe00; + i_g = (voodoo->nccTable[tmu][tbl].i[i] >> 9) & 0x1ff; + if (i_g & 0x100) + i_g |= 0xfffffe00; + i_b = voodoo->nccTable[tmu][tbl].i[i] & 0x1ff; + if (i_b & 0x100) + i_b |= 0xfffffe00; + + q_r = (voodoo->nccTable[tmu][tbl].q[q] >> 18) & 0x1ff; + if (q_r & 0x100) + q_r |= 0xfffffe00; + q_g = (voodoo->nccTable[tmu][tbl].q[q] >> 9) & 0x1ff; + if (q_g & 0x100) + q_g |= 0xfffffe00; + q_b = voodoo->nccTable[tmu][tbl].q[q] & 0x1ff; + if (q_b & 0x100) + q_b |= 0xfffffe00; + + voodoo->ncc_lookup[tmu][tbl][col].rgba.r = CLAMP(y + i_r + q_r); + voodoo->ncc_lookup[tmu][tbl][col].rgba.g = CLAMP(y + i_g + q_g); + voodoo->ncc_lookup[tmu][tbl][col].rgba.b = CLAMP(y + i_b + q_b); + voodoo->ncc_lookup[tmu][tbl][col].rgba.a = 0xff; + } + } +} + +void voodoo_pixelclock_update(voodoo_t *voodoo) +{ + int m = (voodoo->dac_pll_regs[0] & 0x7f) + 2; + int n1 = ((voodoo->dac_pll_regs[0] >> 8) & 0x1f) + 2; + int n2 = ((voodoo->dac_pll_regs[0] >> 13) & 0x07); + float t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2); + double clock_const; + int line_length; + + if ((voodoo->dac_data[6] & 0xf0) == 0x20 || + (voodoo->dac_data[6] & 0xf0) == 0x60 || + (voodoo->dac_data[6] & 0xf0) == 0x70) + t /= 2.0f; + + line_length = (voodoo->hSync & 0xff) + ((voodoo->hSync >> 16) & 0x3ff); + +// pclog("Pixel clock %f MHz hsync %08x line_length %d\n", t, voodoo->hSync, line_length); + + voodoo->pixel_clock = t; + + clock_const = cpuclock / t; + voodoo->line_time = (uint64_t)((double)line_length * clock_const * (double)(1ull << 32)); +} + +static void voodoo_calc_clutData(voodoo_t *voodoo) +{ + int c; + + for (c = 0; c < 256; c++) + { + voodoo->clutData256[c].r = (voodoo->clutData[c >> 3].r*(8-(c & 7)) + + voodoo->clutData[(c >> 3)+1].r*(c & 7)) >> 3; + voodoo->clutData256[c].g = (voodoo->clutData[c >> 3].g*(8-(c & 7)) + + voodoo->clutData[(c >> 3)+1].g*(c & 7)) >> 3; + voodoo->clutData256[c].b = (voodoo->clutData[c >> 3].b*(8-(c & 7)) + + voodoo->clutData[(c >> 3)+1].b*(c & 7)) >> 3; + } + + for (c = 0; c < 65536; c++) + { + int r = (c >> 8) & 0xf8; + int g = (c >> 3) & 0xfc; + int b = (c << 3) & 0xf8; +// r |= (r >> 5); +// g |= (g >> 6); +// b |= (b >> 5); + + voodoo->video_16to32[c] = (voodoo->clutData256[r].r << 16) | (voodoo->clutData256[g].g << 8) | voodoo->clutData256[b].b; + } +} + + + +#define FILTDIV 256 + +static int FILTCAP, FILTCAPG, FILTCAPB = 0; /* color filter threshold values */ + +void voodoo_generate_filter_v1(voodoo_t *voodoo) +{ + int g, h; + float difference, diffg, diffb; + float thiscol, thiscolg, thiscolb, lined; + float fcr, fcg, fcb; + + fcr = FILTCAP * 5; + fcg = FILTCAPG * 6; + fcb = FILTCAPB * 5; + + for (g=0;g FILTCAP) + difference = FILTCAP; + if (difference < -FILTCAP) + difference = -FILTCAP; + + if (diffg > FILTCAPG) + diffg = FILTCAPG; + if (diffg < -FILTCAPG) + diffg = -FILTCAPG; + + if (diffb > FILTCAPB) + diffb = FILTCAPB; + if (diffb < -FILTCAPB) + diffb = -FILTCAPB; + + // hack - to make it not bleed onto black + //if (g == 0){ + //difference = diffg = diffb = 0; + //} + + if ((difference < fcr) || (-difference > -fcr)) + thiscol = g + (difference / 2); + if ((diffg < fcg) || (-diffg > -fcg)) + thiscolg = g + (diffg / 2); /* need these divides so we can actually undither! */ + if ((diffb < fcb) || (-diffb > -fcb)) + thiscolb = g + (diffb / 2); + + if (thiscol < 0) + thiscol = 0; + if (thiscol > FILTDIV-1) + thiscol = FILTDIV-1; + + if (thiscolg < 0) + thiscolg = 0; + if (thiscolg > FILTDIV-1) + thiscolg = FILTDIV-1; + + if (thiscolb < 0) + thiscolb = 0; + if (thiscolb > FILTDIV-1) + thiscolb = FILTDIV-1; + + voodoo->thefilter[g][h] = thiscol; + voodoo->thefilterg[g][h] = thiscolg; + voodoo->thefilterb[g][h] = thiscolb; + } + + lined = g + 4; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][0] = lined; + voodoo->purpleline[g][2] = lined; + + lined = g + 0; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][1] = lined; + } +} + +void voodoo_generate_filter_v2(voodoo_t *voodoo) +{ + int g, h; + float difference; + float thiscol, thiscolg, thiscolb, lined; + float clr, clg, clb = 0; + float fcr, fcg, fcb = 0; + + // pre-clamping + + fcr = FILTCAP; + fcg = FILTCAPG; + fcb = FILTCAPB; + + if (fcr > 32) fcr = 32; + if (fcg > 32) fcg = 32; + if (fcb > 32) fcb = 32; + + for (g=0;g<256;g++) // pixel 1 - our target pixel we want to bleed into + { + for (h=0;h<256;h++) // pixel 2 - our main pixel + { + float avg; + float avgdiff; + + difference = (float)(g - h); + avg = (float)((g + g + g + g + h) / 5); + avgdiff = avg - (float)((g + h + h + h + h) / 5); + if (avgdiff < 0) avgdiff *= -1; + if (difference < 0) difference *= -1; + + thiscol = thiscolg = thiscolb = g; + + // try lighten + if (h > g) + { + clr = clg = clb = avgdiff; + + if (clr>fcr) clr=fcr; + if (clg>fcg) clg=fcg; + if (clb>fcb) clb=fcb; + + + thiscol = g + clr; + thiscolg = g + clg; + thiscolb = g + clb; + + if (thiscol>g+FILTCAP) + thiscol=g+FILTCAP; + if (thiscolg>g+FILTCAPG) + thiscolg=g+FILTCAPG; + if (thiscolb>g+FILTCAPB) + thiscolb=g+FILTCAPB; + + + if (thiscol>g+avgdiff) + thiscol=g+avgdiff; + if (thiscolg>g+avgdiff) + thiscolg=g+avgdiff; + if (thiscolb>g+avgdiff) + thiscolb=g+avgdiff; + + } + + if (difference > FILTCAP) + thiscol = g; + if (difference > FILTCAPG) + thiscolg = g; + if (difference > FILTCAPB) + thiscolb = g; + + // clamp + if (thiscol < 0) thiscol = 0; + if (thiscolg < 0) thiscolg = 0; + if (thiscolb < 0) thiscolb = 0; + + if (thiscol > 255) thiscol = 255; + if (thiscolg > 255) thiscolg = 255; + if (thiscolb > 255) thiscolb = 255; + + // add to the table + voodoo->thefilter[g][h] = (thiscol); + voodoo->thefilterg[g][h] = (thiscolg); + voodoo->thefilterb[g][h] = (thiscolb); + + // debug the ones that don't give us much of a difference + //if (difference < FILTCAP) + //pclog("Voodoofilter: %ix%i - %f difference, %f average difference, R=%f, G=%f, B=%f\n", g, h, difference, avgdiff, thiscol, thiscolg, thiscolb); + } + + lined = g + 3; + if (lined > 255) + lined = 255; + voodoo->purpleline[g][0] = lined; + voodoo->purpleline[g][1] = 0; + voodoo->purpleline[g][2] = lined; + } +} + +void voodoo_threshold_check(voodoo_t *voodoo) +{ + int r, g, b; + + if (!voodoo->scrfilterEnabled) + return; /* considered disabled; don't check and generate */ + + /* Check for changes, to generate anew table */ + if (voodoo->scrfilterThreshold != voodoo->scrfilterThresholdOld) + { + r = (voodoo->scrfilterThreshold >> 16) & 0xFF; + g = (voodoo->scrfilterThreshold >> 8 ) & 0xFF; + b = voodoo->scrfilterThreshold & 0xFF; + + FILTCAP = r; + FILTCAPG = g; + FILTCAPB = b; + + pclog("Voodoo Filter Threshold Check: %06x - RED %i GREEN %i BLUE %i\n", voodoo->scrfilterThreshold, r, g, b); + + voodoo->scrfilterThresholdOld = voodoo->scrfilterThreshold; + + if (voodoo->type == VOODOO_2) + voodoo_generate_filter_v2(voodoo); + else + voodoo_generate_filter_v1(voodoo); + } +} + +static void voodoo_filterline_v1(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) +{ + int x; + + // Scratchpad for avoiding feedback streaks + uint8_t fil3[(voodoo->h_disp) * 3]; + + /* 16 to 32-bit */ + for (x=0; x> 5) & 63) << 2); + fil[x*3+2] = (((src[x] >> 11) & 31) << 3); + + // Copy to our scratchpads + fil3[x*3+0] = fil[x*3+0]; + fil3[x*3+1] = fil[x*3+1]; + fil3[x*3+2] = fil[x*3+2]; + } + + + /* lines */ + + if (line & 1) + { + for (x=0; xpurpleline[fil[x*3]][0]; + fil[x*3+1] = voodoo->purpleline[fil[x*3+1]][1]; + fil[x*3+2] = voodoo->purpleline[fil[x*3+2]][2]; + } + } + + + /* filtering time */ + + for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; + fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; + fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; + } + + for (x=1; xthefilterb[fil3[x*3]][fil3[ (x-1) *3]]; + fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x-1) *3+1]]; + fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x-1) *3+2]]; + } + + for (x=1; xthefilterb[fil[x*3]][fil[ (x-1) *3]]; + fil3[(x)*3+1] = voodoo->thefilterg[fil[x*3+1]][fil[ (x-1) *3+1]]; + fil3[(x)*3+2] = voodoo->thefilter[fil[x*3+2]][fil[ (x-1) *3+2]]; + } + + for (x=0; xthefilterb[fil3[x*3]][fil3[ (x+1) *3]]; + fil[(x)*3+1] = voodoo->thefilterg[fil3[x*3+1]][fil3[ (x+1) *3+1]]; + fil[(x)*3+2] = voodoo->thefilter[fil3[x*3+2]][fil3[ (x+1) *3+2]]; + } +} + + +static void voodoo_filterline_v2(voodoo_t *voodoo, uint8_t *fil, int column, uint16_t *src, int line) +{ + int x; + + // Scratchpad for blending filter + uint8_t fil3[(voodoo->h_disp) * 3]; + + /* 16 to 32-bit */ + for (x=0; x> 5) & 63) << 2); + fil3[x*3+2] = fil[x*3+2] = (((src[x] >> 11) & 31) << 3); + } + + /* filtering time */ + + for (x=1; xthefilterb [((src[x+3] & 31) << 3)] [((src[x] & 31) << 3)]; + fil3[(x+3)*3+1] = voodoo->thefilterg [(((src[x+3] >> 5) & 63) << 2)] [(((src[x] >> 5) & 63) << 2)]; + fil3[(x+3)*3+2] = voodoo->thefilter [(((src[x+3] >> 11) & 31) << 3)] [(((src[x] >> 11) & 31) << 3)]; + + fil[(x+2)*3] = voodoo->thefilterb [fil3[(x+2)*3]][((src[x] & 31) << 3)]; + fil[(x+2)*3+1] = voodoo->thefilterg [fil3[(x+2)*3+1]][(((src[x] >> 5) & 63) << 2)]; + fil[(x+2)*3+2] = voodoo->thefilter [fil3[(x+2)*3+2]][(((src[x] >> 11) & 31) << 3)]; + + fil3[(x+1)*3] = voodoo->thefilterb [fil[(x+1)*3]][((src[x] & 31) << 3)]; + fil3[(x+1)*3+1] = voodoo->thefilterg [fil[(x+1)*3+1]][(((src[x] >> 5) & 63) << 2)]; + fil3[(x+1)*3+2] = voodoo->thefilter [fil[(x+1)*3+2]][(((src[x] >> 11) & 31) << 3)]; + + fil[(x-1)*3] = voodoo->thefilterb [fil3[(x-1)*3]][((src[x] & 31) << 3)]; + fil[(x-1)*3+1] = voodoo->thefilterg [fil3[(x-1)*3+1]][(((src[x] >> 5) & 63) << 2)]; + fil[(x-1)*3+2] = voodoo->thefilter [fil3[(x-1)*3+2]][(((src[x] >> 11) & 31) << 3)]; + } + + // unroll for edge cases + + fil3[(column-3)*3] = voodoo->thefilterb [((src[column-3] & 31) << 3)] [((src[column] & 31) << 3)]; + fil3[(column-3)*3+1] = voodoo->thefilterg [(((src[column-3] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; + fil3[(column-3)*3+2] = voodoo->thefilter [(((src[column-3] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; + + fil3[(column-2)*3] = voodoo->thefilterb [((src[column-2] & 31) << 3)] [((src[column] & 31) << 3)]; + fil3[(column-2)*3+1] = voodoo->thefilterg [(((src[column-2] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; + fil3[(column-2)*3+2] = voodoo->thefilter [(((src[column-2] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; + + fil3[(column-1)*3] = voodoo->thefilterb [((src[column-1] & 31) << 3)] [((src[column] & 31) << 3)]; + fil3[(column-1)*3+1] = voodoo->thefilterg [(((src[column-1] >> 5) & 63) << 2)] [(((src[column] >> 5) & 63) << 2)]; + fil3[(column-1)*3+2] = voodoo->thefilter [(((src[column-1] >> 11) & 31) << 3)] [(((src[column] >> 11) & 31) << 3)]; + + fil[(column-2)*3] = voodoo->thefilterb [fil3[(column-2)*3]][((src[column] & 31) << 3)]; + fil[(column-2)*3+1] = voodoo->thefilterg [fil3[(column-2)*3+1]][(((src[column] >> 5) & 63) << 2)]; + fil[(column-2)*3+2] = voodoo->thefilter [fil3[(column-2)*3+2]][(((src[column] >> 11) & 31) << 3)]; + + fil[(column-1)*3] = voodoo->thefilterb [fil3[(column-1)*3]][((src[column] & 31) << 3)]; + fil[(column-1)*3+1] = voodoo->thefilterg [fil3[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)]; + fil[(column-1)*3+2] = voodoo->thefilter [fil3[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)]; + + fil3[(column-1)*3] = voodoo->thefilterb [fil[(column-1)*3]][((src[column] & 31) << 3)]; + fil3[(column-1)*3+1] = voodoo->thefilterg [fil[(column-1)*3+1]][(((src[column] >> 5) & 63) << 2)]; + fil3[(column-1)*3+2] = voodoo->thefilter [fil[(column-1)*3+2]][(((src[column] >> 11) & 31) << 3)]; +} + +void voodoo_callback(void *p) +{ + voodoo_t *voodoo = (voodoo_t *)p; + + if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) + { + if (voodoo->line < voodoo->v_disp) + { + voodoo_t *draw_voodoo; + int draw_line; + + if (SLI_ENABLED) + { + if (voodoo == voodoo->set->voodoos[1]) + goto skip_draw; + + if (((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) ? 1 : 0) == (voodoo->line & 1)) + draw_voodoo = voodoo; + else + draw_voodoo = voodoo->set->voodoos[1]; + draw_line = voodoo->line >> 1; + } + else + { + if (!(voodoo->fbiInit0 & 1)) + goto skip_draw; + draw_voodoo = voodoo; + draw_line = voodoo->line; + } + + if (draw_voodoo->dirty_line[draw_line]) + { + uint32_t *p = &((uint32_t *)buffer32->line[voodoo->line])[32]; + uint16_t *src = (uint16_t *)&draw_voodoo->fb_mem[draw_voodoo->front_offset + draw_line*draw_voodoo->row_width]; + int x; + + draw_voodoo->dirty_line[draw_line] = 0; + + if (voodoo->line < voodoo->dirty_line_low) + { + voodoo->dirty_line_low = voodoo->line; + video_wait_for_buffer(); + } + if (voodoo->line > voodoo->dirty_line_high) + voodoo->dirty_line_high = voodoo->line; + + if (voodoo->scrfilter && voodoo->scrfilterEnabled) + { + uint8_t fil[(voodoo->h_disp) * 3]; /* interleaved 24-bit RGB */ + + if (voodoo->type == VOODOO_2) + voodoo_filterline_v2(voodoo, fil, voodoo->h_disp, src, voodoo->line); + else + voodoo_filterline_v1(voodoo, fil, voodoo->h_disp, src, voodoo->line); + + for (x = 0; x < voodoo->h_disp; x++) + { + 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); + } + } + else + { + for (x = 0; x < voodoo->h_disp; x++) + { + p[x] = draw_voodoo->video_16to32[src[x]]; + } + } + } + } + } +skip_draw: + if (voodoo->line == voodoo->v_disp) + { +// pclog("retrace %i %i %08x %i\n", voodoo->retrace_count, voodoo->swap_interval, voodoo->swap_offset, voodoo->swap_pending); + voodoo->retrace_count++; + if (SLI_ENABLED && (voodoo->fbiInit2 & FBIINIT2_SWAP_ALGORITHM_MASK) == FBIINIT2_SWAP_ALGORITHM_SLI_SYNC) + { + if (voodoo == voodoo->set->voodoos[0]) + { + voodoo_t *voodoo_1 = voodoo->set->voodoos[1]; + + /*Only swap if both Voodoos are waiting for buffer swap*/ + if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval) && + voodoo_1->swap_pending && (voodoo_1->retrace_count > voodoo_1->swap_interval)) + { + memset(voodoo->dirty_line, 1, 1024); + voodoo->retrace_count = 0; + voodoo->front_offset = voodoo->swap_offset; + if (voodoo->swap_count > 0) + voodoo->swap_count--; + voodoo->swap_pending = 0; + + memset(voodoo_1->dirty_line, 1, 1024); + voodoo_1->retrace_count = 0; + voodoo_1->front_offset = voodoo_1->swap_offset; + if (voodoo_1->swap_count > 0) + voodoo_1->swap_count--; + voodoo_1->swap_pending = 0; + + thread_set_event(voodoo->wake_fifo_thread); + thread_set_event(voodoo_1->wake_fifo_thread); + + voodoo->frame_count++; + voodoo_1->frame_count++; + } + } + } + else + { + if (voodoo->swap_pending && (voodoo->retrace_count > voodoo->swap_interval)) + { + memset(voodoo->dirty_line, 1, 1024); + voodoo->retrace_count = 0; + voodoo->front_offset = voodoo->swap_offset; + if (voodoo->swap_count > 0) + voodoo->swap_count--; + voodoo->swap_pending = 0; + thread_set_event(voodoo->wake_fifo_thread); + voodoo->frame_count++; + } + } + voodoo->v_retrace = 1; + } + voodoo->line++; + + if (voodoo->fbiInit0 & FBIINIT0_VGA_PASS) + { + if (voodoo->line == voodoo->v_disp) + { + if (voodoo->dirty_line_high > voodoo->dirty_line_low) + svga_doblit(0, voodoo->v_disp, voodoo->h_disp, voodoo->v_disp-1, voodoo->svga); + if (voodoo->clutData_dirty) + { + voodoo->clutData_dirty = 0; + voodoo_calc_clutData(voodoo); + } + voodoo->dirty_line_high = -1; + voodoo->dirty_line_low = 2000; + } + } + + if (voodoo->line >= voodoo->v_total) + { + voodoo->line = 0; + voodoo->v_retrace = 0; + } + if (voodoo->line_time) + timer_advance_u64(&voodoo->timer, voodoo->line_time); + else + timer_advance_u64(&voodoo->timer, TIMER_USEC * 32); +} diff --git a/src/vid_voodoo_display.h b/src/vid_voodoo_display.h new file mode 100644 index 0000000..46cbc00 --- /dev/null +++ b/src/vid_voodoo_display.h @@ -0,0 +1,6 @@ +void voodoo_update_ncc(voodoo_t *voodoo, int tmu); +void voodoo_pixelclock_update(voodoo_t *voodoo); +void voodoo_generate_filter_v1(voodoo_t *voodoo); +void voodoo_generate_filter_v2(voodoo_t *voodoo); +void voodoo_threshold_check(voodoo_t *voodoo); +void voodoo_callback(void *p); diff --git a/src/vid_voodoo_dither.h b/src/vid_voodoo_dither.h index 7ec7471..daf26d5 100644 --- a/src/vid_voodoo_dither.h +++ b/src/vid_voodoo_dither.h @@ -1,4 +1,4 @@ -uint8_t dither_rb[256][4][4] = +static const uint8_t dither_rb[256][4][4] = { { {0, 0, 0, 0}, @@ -1538,7 +1538,7 @@ uint8_t dither_rb[256][4][4] = }, }; -uint8_t dither_g[256][4][4] = +static const uint8_t dither_g[256][4][4] = { { {0, 0, 0, 0}, @@ -3078,7 +3078,7 @@ uint8_t dither_g[256][4][4] = }, }; -uint8_t dither_rb2x2[256][2][2] = +static const uint8_t dither_rb2x2[256][2][2] = { { {0, 0}, @@ -4106,7 +4106,7 @@ uint8_t dither_rb2x2[256][2][2] = }, }; -uint8_t dither_g2x2[256][2][2] = +static const uint8_t dither_g2x2[256][2][2] = { { {0, 0}, diff --git a/src/vid_voodoo_fb.c b/src/vid_voodoo_fb.c new file mode 100644 index 0000000..39fa2ac --- /dev/null +++ b/src/vid_voodoo_fb.c @@ -0,0 +1,397 @@ +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "thread.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_dither.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" +#include "vid_voodoo_fb.h" + +uint16_t voodoo_fb_readw(uint32_t addr, void *p) +{ + voodoo_t *voodoo = (voodoo_t *)p; + int x, y; + uint32_t read_addr; + uint16_t temp; + + x = (addr >> 1) & 0x3ff; + y = (addr >> 11) & 0x3ff; + + if (SLI_ENABLED) + { + voodoo_set_t *set = voodoo->set; + + if (y & 1) + voodoo = set->voodoos[1]; + else + voodoo = set->voodoos[0]; + + y >>= 1; + } + + read_addr = voodoo->fb_read_offset + (x << 1) + (y * voodoo->row_width); + + if (read_addr > voodoo->fb_mask) + return 0xffff; + + temp = *(uint16_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]); + +// 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++); + return temp; +} +uint32_t voodoo_fb_readl(uint32_t addr, void *p) +{ + voodoo_t *voodoo = (voodoo_t *)p; + int x, y; + uint32_t read_addr; + uint32_t temp; + + x = addr & 0x7fe; + y = (addr >> 11) & 0x3ff; + + if (SLI_ENABLED) + { + voodoo_set_t *set = voodoo->set; + + if (y & 1) + voodoo = set->voodoos[1]; + else + voodoo = set->voodoos[0]; + + y >>= 1; + } + + read_addr = voodoo->fb_read_offset + x + (y * voodoo->row_width); + + if (read_addr > voodoo->fb_mask) + return 0xffffffff; + + temp = *(uint32_t *)(&voodoo->fb_mem[read_addr & voodoo->fb_mask]); + +// 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); + return temp; +} + +static inline uint16_t do_dither(voodoo_params_t *params, rgba8_t col, int x, int y) +{ + int r, g, b; + + if (dither) + { + if (dither2x2) + { + r = dither_rb2x2[col.r][y & 1][x & 1]; + g = dither_g2x2[col.g][y & 1][x & 1]; + b = dither_rb2x2[col.b][y & 1][x & 1]; + } + else + { + r = dither_rb[col.r][y & 3][x & 3]; + g = dither_g[col.g][y & 3][x & 3]; + b = dither_rb[col.b][y & 3][x & 3]; + } + } + else + { + r = col.r >> 3; + g = col.g >> 2; + b = col.b >> 3; + } + + return b | (g << 5) | (r << 11); +} + +void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p) +{ + voodoo_t *voodoo = (voodoo_t *)p; + voodoo_params_t *params = &voodoo->params; + int x, y; + uint32_t write_addr, write_addr_aux; + rgba8_t colour_data; + uint16_t depth_data; + uint8_t alpha_data; + int write_mask = 0; + + colour_data.r = colour_data.g = colour_data.b = colour_data.a = 0; + + depth_data = voodoo->params.zaColor & 0xffff; + alpha_data = voodoo->params.zaColor >> 24; + +// while (!RB_EMPTY) +// thread_reset_event(voodoo->not_full_event); + +// pclog("voodoo_fb_writew : %08X %04X\n", addr, val); + + + switch (voodoo->lfbMode & LFB_FORMAT_MASK) + { + case LFB_FORMAT_RGB565: + colour_data = rgb565[val]; + alpha_data = 0xff; + write_mask = LFB_WRITE_COLOUR; + break; + case LFB_FORMAT_RGB555: + colour_data = argb1555[val]; + alpha_data = 0xff; + write_mask = LFB_WRITE_COLOUR; + break; + case LFB_FORMAT_ARGB1555: + colour_data = argb1555[val]; + alpha_data = colour_data.a; + write_mask = LFB_WRITE_COLOUR; + break; + case LFB_FORMAT_DEPTH: + depth_data = val; + write_mask = LFB_WRITE_DEPTH; + break; + + default: + fatal("voodoo_fb_writew : bad LFB format %08X\n", voodoo->lfbMode); + } + + x = addr & 0x7fe; + y = (addr >> 11) & 0x3ff; + + if (SLI_ENABLED) + { + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || + ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1))) + return; + y >>= 1; + } + + + if (voodoo->fb_write_offset == voodoo->params.front_offset) + voodoo->dirty_line[y] = 1; + + write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); + write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); + +// pclog("fb_writew %08x %i %i %i %08x\n", addr, x, y, voodoo->row_width, write_addr); + + if (voodoo->lfbMode & 0x100) + { + { + rgba8_t write_data = colour_data; + uint16_t new_depth = depth_data; + + if (params->fbzMode & FBZ_DEPTH_ENABLE) + { + uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); + + DEPTH_TEST(new_depth); + } + + if ((params->fbzMode & FBZ_CHROMAKEY) && + write_data.r == params->chromaKey_r && + write_data.g == params->chromaKey_g && + write_data.b == params->chromaKey_b) + goto skip_pixel; + + if (params->fogMode & FOG_ENABLE) + { + int32_t z = new_depth << 12; + int64_t w_depth = (int64_t)(int32_t)new_depth; + int32_t ia = alpha_data << 12; + + APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth); + } + + if (params->alphaMode & 1) + ALPHA_TEST(alpha_data); + + if (params->alphaMode & (1 << 4)) + { + uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]); + int dest_r, dest_g, dest_b, dest_a; + + dest_r = (dat >> 8) & 0xf8; + dest_g = (dat >> 3) & 0xfc; + dest_b = (dat << 3) & 0xf8; + dest_r |= (dest_r >> 5); + dest_g |= (dest_g >> 6); + dest_b |= (dest_b >> 5); + dest_a = 0xff; + + ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data); + } + + if (params->fbzMode & FBZ_RGB_WMASK) + *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, x >> 1, y); + if (params->fbzMode & FBZ_DEPTH_WMASK) + *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth; + +skip_pixel: + x = x; + } + } + else + { + if (write_mask & LFB_WRITE_COLOUR) + *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data, x >> 1, y); + if (write_mask & LFB_WRITE_DEPTH) + *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data; + } +} + + +void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p) +{ + voodoo_t *voodoo = (voodoo_t *)p; + voodoo_params_t *params = &voodoo->params; + int x, y; + uint32_t write_addr, write_addr_aux; + rgba8_t colour_data[2]; + uint16_t depth_data[2]; + uint8_t alpha_data[2]; + int write_mask = 0, count = 1; + + depth_data[0] = depth_data[1] = voodoo->params.zaColor & 0xffff; + alpha_data[0] = alpha_data[1] = voodoo->params.zaColor >> 24; +// while (!RB_EMPTY) +// thread_reset_event(voodoo->not_full_event); + +// pclog("voodoo_fb_writel : %08X %08X\n", addr, val); + + switch (voodoo->lfbMode & LFB_FORMAT_MASK) + { + case LFB_FORMAT_RGB565: + colour_data[0] = rgb565[val & 0xffff]; + colour_data[1] = rgb565[val >> 16]; + write_mask = LFB_WRITE_COLOUR; + count = 2; + break; + case LFB_FORMAT_RGB555: + colour_data[0] = argb1555[val & 0xffff]; + colour_data[1] = argb1555[val >> 16]; + write_mask = LFB_WRITE_COLOUR; + count = 2; + break; + case LFB_FORMAT_ARGB1555: + colour_data[0] = argb1555[val & 0xffff]; + alpha_data[0] = colour_data[0].a; + colour_data[1] = argb1555[val >> 16]; + alpha_data[1] = colour_data[1].a; + write_mask = LFB_WRITE_COLOUR; + count = 2; + break; + + case LFB_FORMAT_ARGB8888: + colour_data[0].b = val & 0xff; + colour_data[0].g = (val >> 8) & 0xff; + colour_data[0].r = (val >> 16) & 0xff; + alpha_data[0] = (val >> 24) & 0xff; + write_mask = LFB_WRITE_COLOUR; + addr >>= 1; + break; + + case LFB_FORMAT_DEPTH: + depth_data[0] = val; + depth_data[1] = val >> 16; + write_mask = LFB_WRITE_DEPTH; + count = 2; + break; + + default: + fatal("voodoo_fb_writel : bad LFB format %08X\n", voodoo->lfbMode); + } + + x = addr & 0x7fe; + y = (addr >> 11) & 0x3ff; + + if (SLI_ENABLED) + { + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (y & 1)) || + ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(y & 1))) + return; + y >>= 1; + } + + if (voodoo->fb_write_offset == voodoo->params.front_offset) + voodoo->dirty_line[y] = 1; + + write_addr = voodoo->fb_write_offset + x + (y * voodoo->row_width); + write_addr_aux = voodoo->params.aux_offset + x + (y * voodoo->row_width); + +// 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); + + if (voodoo->lfbMode & 0x100) + { + int c; + + for (c = 0; c < count; c++) + { + rgba8_t write_data = colour_data[c]; + uint16_t new_depth = depth_data[c]; + + if (params->fbzMode & FBZ_DEPTH_ENABLE) + { + uint16_t old_depth = *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]); + + DEPTH_TEST(new_depth); + } + + if ((params->fbzMode & FBZ_CHROMAKEY) && + write_data.r == params->chromaKey_r && + write_data.g == params->chromaKey_g && + write_data.b == params->chromaKey_b) + goto skip_pixel; + + if (params->fogMode & FOG_ENABLE) + { + int32_t z = new_depth << 12; + int64_t w_depth = new_depth; + int32_t ia = alpha_data[c] << 12; + + APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia, w_depth); + } + + if (params->alphaMode & 1) + ALPHA_TEST(alpha_data[c]); + + if (params->alphaMode & (1 << 4)) + { + uint16_t dat = *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]); + int dest_r, dest_g, dest_b, dest_a; + + dest_r = (dat >> 8) & 0xf8; + dest_g = (dat >> 3) & 0xfc; + dest_b = (dat << 3) & 0xf8; + dest_r |= (dest_r >> 5); + dest_g |= (dest_g >> 6); + dest_b |= (dest_b >> 5); + dest_a = 0xff; + + ALPHA_BLEND(write_data.r, write_data.g, write_data.b, alpha_data[c]); + } + + if (params->fbzMode & FBZ_RGB_WMASK) + *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, write_data, (x >> 1) + c, y); + if (params->fbzMode & FBZ_DEPTH_WMASK) + *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = new_depth; + +skip_pixel: + write_addr += 2; + write_addr_aux += 2; + } + } + else + { + int c; + + for (c = 0; c < count; c++) + { + if (write_mask & LFB_WRITE_COLOUR) + *(uint16_t *)(&voodoo->fb_mem[write_addr & voodoo->fb_mask]) = do_dither(&voodoo->params, colour_data[c], (x >> 1) + c, y); + if (write_mask & LFB_WRITE_DEPTH) + *(uint16_t *)(&voodoo->fb_mem[write_addr_aux & voodoo->fb_mask]) = depth_data[c]; + + write_addr += 2; + write_addr_aux += 2; + } + } +} diff --git a/src/vid_voodoo_fb.h b/src/vid_voodoo_fb.h new file mode 100644 index 0000000..fcb2513 --- /dev/null +++ b/src/vid_voodoo_fb.h @@ -0,0 +1,4 @@ +uint16_t voodoo_fb_readw(uint32_t addr, void *p); +uint32_t voodoo_fb_readl(uint32_t addr, void *p); +void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p); +void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p); diff --git a/src/vid_voodoo_fifo.c b/src/vid_voodoo_fifo.c new file mode 100644 index 0000000..ccf112e --- /dev/null +++ b/src/vid_voodoo_fifo.c @@ -0,0 +1,394 @@ +#include +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "thread.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_fb.h" +#include "vid_voodoo_fifo.h" +#include "vid_voodoo_reg.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" +#include "vid_voodoo_texture.h" + +#define WAKE_DELAY (TIMER_USEC * 100) +void voodoo_wake_fifo_thread(voodoo_t *voodoo) +{ + if (!timer_is_enabled(&voodoo->wake_timer)) + { + /*Don't wake FIFO thread immediately - if we do that it will probably + process one word and go back to sleep, requiring it to be woken on + almost every write. Instead, wait a short while so that the CPU + emulation writes more data so we have more batched-up work.*/ + timer_set_delay_u64(&voodoo->wake_timer, WAKE_DELAY); + } +} + +void voodoo_wake_fifo_thread_now(voodoo_t *voodoo) +{ + thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + +void voodoo_wake_timer(void *p) +{ + voodoo_t *voodoo = (voodoo_t *)p; + + thread_set_event(voodoo->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/ +} + +void voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val) +{ + fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_write_idx & FIFO_MASK]; + + while (FIFO_FULL) + { + thread_reset_event(voodoo->fifo_not_full_event); + if (FIFO_FULL) + { + thread_wait_event(voodoo->fifo_not_full_event, 1); /*Wait for room in ringbuffer*/ + if (FIFO_FULL) + voodoo_wake_fifo_thread_now(voodoo); + } + } + + fifo->val = val; + fifo->addr_type = addr_type; + + voodoo->fifo_write_idx++; + + if (FIFO_ENTRIES > 0xe000) + voodoo_wake_fifo_thread(voodoo); +} + +void voodoo_flush(voodoo_t *voodoo) +{ + voodoo->flush = 1; + while (!FIFO_EMPTY) + { + voodoo_wake_fifo_thread_now(voodoo); + thread_wait_event(voodoo->fifo_not_full_event, 1); + } + voodoo_wait_for_render_thread_idle(voodoo); + voodoo->flush = 0; +} + +void voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo) +{ + voodoo_wake_fifo_thread(voodoo); + if (SLI_ENABLED && voodoo->type != VOODOO_2 && set->voodoos[0] == voodoo) + voodoo_wake_fifo_thread(set->voodoos[1]); +} + +void voodoo_wait_for_swap_complete(voodoo_t *voodoo) +{ + while (voodoo->swap_pending) + { + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); + if ((voodoo->swap_pending && voodoo->flush) || FIFO_FULL) + { + /*Main thread is waiting for FIFO to empty, so skip vsync wait and just swap*/ + memset(voodoo->dirty_line, 1, 1024); + voodoo->front_offset = voodoo->params.front_offset; + if (voodoo->swap_count > 0) + voodoo->swap_count--; + voodoo->swap_pending = 0; + break; + } + } +} + + +static uint32_t cmdfifo_get(voodoo_t *voodoo) +{ + uint32_t val; + + while (voodoo->cmdfifo_depth_rd == voodoo->cmdfifo_depth_wr) + { + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); + } + + val = *(uint32_t *)&voodoo->fb_mem[voodoo->cmdfifo_rp & voodoo->fb_mask]; + + voodoo->cmdfifo_depth_rd++; + voodoo->cmdfifo_rp += 4; + +// pclog(" CMDFIFO get %08x\n", val); + return val; +} + +static inline float cmdfifo_get_f(voodoo_t *voodoo) +{ + union + { + uint32_t i; + float f; + } tempif; + + tempif.i = cmdfifo_get(voodoo); + return tempif.f; +} + +enum +{ + CMDFIFO3_PC_MASK_RGB = (1 << 10), + CMDFIFO3_PC_MASK_ALPHA = (1 << 11), + CMDFIFO3_PC_MASK_Z = (1 << 12), + CMDFIFO3_PC_MASK_Wb = (1 << 13), + CMDFIFO3_PC_MASK_W0 = (1 << 14), + CMDFIFO3_PC_MASK_S0_T0 = (1 << 15), + CMDFIFO3_PC_MASK_W1 = (1 << 16), + CMDFIFO3_PC_MASK_S1_T1 = (1 << 17), + + CMDFIFO3_PC = (1 << 28) +}; + +void voodoo_fifo_thread(void *param) +{ + voodoo_t *voodoo = (voodoo_t *)param; + + while (1) + { + thread_set_event(voodoo->fifo_not_full_event); + thread_wait_event(voodoo->wake_fifo_thread, -1); + thread_reset_event(voodoo->wake_fifo_thread); + voodoo->voodoo_busy = 1; + while (!FIFO_EMPTY) + { + uint64_t start_time = timer_read(); + uint64_t end_time; + fifo_entry_t *fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + + switch (fifo->addr_type & FIFO_TYPE) + { + case FIFO_WRITEL_REG: + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_REG) + { + voodoo_reg_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + case FIFO_WRITEW_FB: + voodoo_wait_for_render_thread_idle(voodoo); + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEW_FB) + { + voodoo_fb_writew(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + case FIFO_WRITEL_FB: + voodoo_wait_for_render_thread_idle(voodoo); + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_FB) + { + voodoo_fb_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + case FIFO_WRITEL_TEX: + while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_TEX) + { + if (!(fifo->addr_type & 0x400000)) + voodoo_tex_writel(fifo->addr_type & FIFO_ADDR, fifo->val, voodoo); + fifo->addr_type = FIFO_INVALID; + voodoo->fifo_read_idx++; + fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK]; + } + break; + } + + if (FIFO_ENTRIES > 0xe000) + thread_set_event(voodoo->fifo_not_full_event); + + end_time = timer_read(); + voodoo->time += end_time - start_time; + } + + while (voodoo->cmdfifo_depth_rd != voodoo->cmdfifo_depth_wr) + { + uint64_t start_time = timer_read(); + uint64_t end_time; + uint32_t header = cmdfifo_get(voodoo); + uint32_t addr; + uint32_t mask; + int smode; + int num; + int num_verticies; + int v_num; + +// pclog(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp); + + switch (header & 7) + { + case 0: +// pclog("CMDFIFO0\n"); + switch ((header >> 3) & 7) + { + case 0: /*NOP*/ + break; + + case 3: /*JMP local frame buffer*/ + voodoo->cmdfifo_rp = (header >> 4) & 0xfffffc; +// pclog("JMP to %08x %04x\n", voodoo->cmdfifo_rp, header); + break; + + default: + fatal("Bad CMDFIFO0 %08x\n", header); + } + break; + + case 1: + num = header >> 16; + addr = (header & 0x7ff8) >> 1; +// pclog("CMDFIFO1 addr=%08x\n",addr); + while (num--) + { + uint32_t val = cmdfifo_get(voodoo); + if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || + (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) + voodoo->cmd_written_fifo++; + + voodoo_reg_writel(addr, val, voodoo); + + if (header & (1 << 15)) + addr += 4; + } + break; + + case 3: + num = (header >> 29) & 7; + mask = header;//(header >> 10) & 0xff; + smode = (header >> 22) & 0xf; + voodoo_reg_writel(SST_sSetupMode, ((header >> 10) & 0xff) | (smode << 16), voodoo); + num_verticies = (header >> 6) & 0xf; + v_num = 0; + if (((header >> 3) & 7) == 2) + v_num = 1; +// pclog("CMDFIFO3: num=%i verts=%i mask=%02x\n", num, num_verticies, (header >> 10) & 0xff); +// pclog("CMDFIFO3 %02x %i\n", (header >> 10), (header >> 3) & 7); + + while (num_verticies--) + { + voodoo->verts[3].sVx = cmdfifo_get_f(voodoo); + voodoo->verts[3].sVy = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_RGB) + { + if (header & CMDFIFO3_PC) + { + uint32_t val = cmdfifo_get(voodoo); + voodoo->verts[3].sBlue = (float)(val & 0xff); + voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff); + voodoo->verts[3].sRed = (float)((val >> 16) & 0xff); + voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff); + } + else + { + voodoo->verts[3].sRed = cmdfifo_get_f(voodoo); + voodoo->verts[3].sGreen = cmdfifo_get_f(voodoo); + voodoo->verts[3].sBlue = cmdfifo_get_f(voodoo); + } + } + if ((mask & CMDFIFO3_PC_MASK_ALPHA) && !(header & CMDFIFO3_PC)) + voodoo->verts[3].sAlpha = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_Z) + voodoo->verts[3].sVz = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_Wb) + voodoo->verts[3].sWb = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_W0) + voodoo->verts[3].sW0 = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_S0_T0) + { + voodoo->verts[3].sS0 = cmdfifo_get_f(voodoo); + voodoo->verts[3].sT0 = cmdfifo_get_f(voodoo); + } + if (mask & CMDFIFO3_PC_MASK_W1) + voodoo->verts[3].sW1 = cmdfifo_get_f(voodoo); + if (mask & CMDFIFO3_PC_MASK_S1_T1) + { + voodoo->verts[3].sS1 = cmdfifo_get_f(voodoo); + voodoo->verts[3].sT1 = cmdfifo_get_f(voodoo); + } + if (v_num) + voodoo_reg_writel(SST_sDrawTriCMD, 0, voodoo); + else + voodoo_reg_writel(SST_sBeginTriCMD, 0, voodoo); + v_num++; + if (v_num == 3 && ((header >> 3) & 7) == 0) + v_num = 0; + } + break; + + case 4: + num = (header >> 29) & 7; + mask = (header >> 15) & 0x3fff; + addr = (header & 0x7ff8) >> 1; +// pclog("CMDFIFO4 addr=%08x\n",addr); + while (mask) + { + if (mask & 1) + { + uint32_t val = cmdfifo_get(voodoo); + if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD || + (addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD) + voodoo->cmd_written_fifo++; + + voodoo_reg_writel(addr, val, voodoo); + } + + addr += 4; + mask >>= 1; + } + while (num--) + cmdfifo_get(voodoo); + break; + + case 5: + if (header & 0x3fc0000) + fatal("CMDFIFO packet 5 has byte disables set %08x\n", header); + num = (header >> 3) & 0x7ffff; + addr = cmdfifo_get(voodoo) & 0xffffff; +// pclog("CMDFIFO5 addr=%08x num=%i\n", addr, num); + switch (header >> 30) + { + case 2: /*Framebuffer*/ + while (num--) + { + uint32_t val = cmdfifo_get(voodoo); + voodoo_fb_writel(addr, val, voodoo); + addr += 4; + } + break; + case 3: /*Texture*/ + while (num--) + { + uint32_t val = cmdfifo_get(voodoo); + voodoo_tex_writel(addr, val, voodoo); + addr += 4; + } + break; + + default: + fatal("CMDFIFO packet 5 bad space %08x %08x\n", header, voodoo->cmdfifo_rp); + } + break; + + default: + pclog("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp); + } + + end_time = timer_read(); + voodoo->time += end_time - start_time; + } + voodoo->voodoo_busy = 0; + } +} diff --git a/src/vid_voodoo_fifo.h b/src/vid_voodoo_fifo.h new file mode 100644 index 0000000..c1caeba --- /dev/null +++ b/src/vid_voodoo_fifo.h @@ -0,0 +1,8 @@ +void voodoo_wake_fifo_thread(voodoo_t *voodoo); +void voodoo_wake_fifo_thread_now(voodoo_t *voodoo); +void voodoo_wake_timer(void *p); +void voodoo_queue_command(voodoo_t *voodoo, uint32_t addr_type, uint32_t val); +void voodoo_flush(voodoo_t *voodoo); +void voodoo_wake_fifo_threads(voodoo_set_t *set, voodoo_t *voodoo); +void voodoo_wait_for_swap_complete(voodoo_t *voodoo); +void voodoo_fifo_thread(void *param); diff --git a/src/vid_voodoo_reg.c b/src/vid_voodoo_reg.c new file mode 100644 index 0000000..52557f1 --- /dev/null +++ b/src/vid_voodoo_reg.c @@ -0,0 +1,1140 @@ +#include +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "thread.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_blitter.h" +#include "vid_voodoo_dither.h" +#include "vid_voodoo_fifo.h" +#include "vid_voodoo_reg.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" +#include "vid_voodoo_setup.h" +#include "vid_voodoo_texture.h" + +enum +{ + CHIP_FBI = 0x1, + CHIP_TREX0 = 0x2, + CHIP_TREX1 = 0x4, + CHIP_TREX2 = 0x8 +}; + +void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) +{ + voodoo_t *voodoo = (voodoo_t *)p; + union + { + uint32_t i; + float f; + } tempif; + int ad21 = addr & (1 << 21); + int chip = (addr >> 10) & 0xf; + if (!chip) + chip = 0xf; + + tempif.i = val; +//pclog("voodoo_reg_write_l: addr=%08x val=%08x(%f) chip=%x\n", addr, val, tempif.f, chip); + addr &= 0x3fc; + + if ((voodoo->fbiInit3 & FBIINIT3_REMAP) && addr < 0x100 && ad21) + addr |= 0x400; + switch (addr) + { + case SST_swapbufferCMD: +// pclog(" start swap buffer command\n"); + + if (TRIPLE_BUFFER) + { + voodoo->disp_buffer = (voodoo->disp_buffer + 1) % 3; + voodoo->draw_buffer = (voodoo->draw_buffer + 1) % 3; + } + else + { + voodoo->disp_buffer = !voodoo->disp_buffer; + voodoo->draw_buffer = !voodoo->draw_buffer; + } + voodoo_recalc(voodoo); + + voodoo->params.swapbufferCMD = val; + + pclog("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0); +// voodoo->front_offset = params->front_offset; + voodoo_wait_for_render_thread_idle(voodoo); + if (!(val & 1)) + { + memset(voodoo->dirty_line, 1, 1024); + voodoo->front_offset = voodoo->params.front_offset; + if (voodoo->swap_count > 0) + voodoo->swap_count--; + } + else if (TRIPLE_BUFFER) + { + if (voodoo->swap_pending) + voodoo_wait_for_swap_complete(voodoo); + + voodoo->swap_interval = (val >> 1) & 0xff; + voodoo->swap_offset = voodoo->params.front_offset; + voodoo->swap_pending = 1; + } + else + { + voodoo->swap_interval = (val >> 1) & 0xff; + voodoo->swap_offset = voodoo->params.front_offset; + voodoo->swap_pending = 1; + + voodoo_wait_for_swap_complete(voodoo); + } + voodoo->cmd_read++; + break; + + case SST_vertexAx: case SST_remap_vertexAx: + voodoo->params.vertexAx = val & 0xffff; + break; + case SST_vertexAy: case SST_remap_vertexAy: + voodoo->params.vertexAy = val & 0xffff; + break; + case SST_vertexBx: case SST_remap_vertexBx: + voodoo->params.vertexBx = val & 0xffff; + break; + case SST_vertexBy: case SST_remap_vertexBy: + voodoo->params.vertexBy = val & 0xffff; + break; + case SST_vertexCx: case SST_remap_vertexCx: + voodoo->params.vertexCx = val & 0xffff; + break; + case SST_vertexCy: case SST_remap_vertexCy: + voodoo->params.vertexCy = val & 0xffff; + break; + + case SST_startR: case SST_remap_startR: + voodoo->params.startR = val & 0xffffff; + break; + case SST_startG: case SST_remap_startG: + voodoo->params.startG = val & 0xffffff; + break; + case SST_startB: case SST_remap_startB: + voodoo->params.startB = val & 0xffffff; + break; + case SST_startZ: case SST_remap_startZ: + voodoo->params.startZ = val; + break; + case SST_startA: case SST_remap_startA: + voodoo->params.startA = val & 0xffffff; + break; + case SST_startS: case SST_remap_startS: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startS = ((int64_t)(int32_t)val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startS = ((int64_t)(int32_t)val) << 14; + break; + case SST_startT: case SST_remap_startT: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startT = ((int64_t)(int32_t)val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startT = ((int64_t)(int32_t)val) << 14; + break; + case SST_startW: case SST_remap_startW: + if (chip & CHIP_FBI) + voodoo->params.startW = (int64_t)(int32_t)val << 2; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startW = (int64_t)(int32_t)val << 2; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startW = (int64_t)(int32_t)val << 2; + break; + + case SST_dRdX: case SST_remap_dRdX: + voodoo->params.dRdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dGdX: case SST_remap_dGdX: + voodoo->params.dGdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dBdX: case SST_remap_dBdX: + voodoo->params.dBdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dZdX: case SST_remap_dZdX: + voodoo->params.dZdX = val; + break; + case SST_dAdX: case SST_remap_dAdX: + voodoo->params.dAdX = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dSdX: case SST_remap_dSdX: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dSdX = ((int64_t)(int32_t)val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dSdX = ((int64_t)(int32_t)val) << 14; + break; + case SST_dTdX: case SST_remap_dTdX: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dTdX = ((int64_t)(int32_t)val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dTdX = ((int64_t)(int32_t)val) << 14; + break; + case SST_dWdX: case SST_remap_dWdX: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dWdX = (int64_t)(int32_t)val << 2; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dWdX = (int64_t)(int32_t)val << 2; + if (chip & CHIP_FBI) + voodoo->params.dWdX = (int64_t)(int32_t)val << 2; + break; + + case SST_dRdY: case SST_remap_dRdY: + voodoo->params.dRdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dGdY: case SST_remap_dGdY: + voodoo->params.dGdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dBdY: case SST_remap_dBdY: + voodoo->params.dBdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dZdY: case SST_remap_dZdY: + voodoo->params.dZdY = val; + break; + case SST_dAdY: case SST_remap_dAdY: + voodoo->params.dAdY = (val & 0xffffff) | ((val & 0x800000) ? 0xff000000 : 0); + break; + case SST_dSdY: case SST_remap_dSdY: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dSdY = ((int64_t)(int32_t)val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dSdY = ((int64_t)(int32_t)val) << 14; + break; + case SST_dTdY: case SST_remap_dTdY: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dTdY = ((int64_t)(int32_t)val) << 14; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dTdY = ((int64_t)(int32_t)val) << 14; + break; + case SST_dWdY: case SST_remap_dWdY: + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dWdY = (int64_t)(int32_t)val << 2; + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dWdY = (int64_t)(int32_t)val << 2; + if (chip & CHIP_FBI) + voodoo->params.dWdY = (int64_t)(int32_t)val << 2; + break; + + case SST_triangleCMD: case SST_remap_triangleCMD: + voodoo->params.sign = val & (1 << 31); + + if (voodoo->ncc_dirty[0]) + voodoo_update_ncc(voodoo, 0); + if (voodoo->ncc_dirty[1]) + voodoo_update_ncc(voodoo, 1); + voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; + + voodoo_queue_triangle(voodoo, &voodoo->params); + + voodoo->cmd_read++; + break; + + case SST_fvertexAx: case SST_remap_fvertexAx: + voodoo->fvertexAx.i = val; + voodoo->params.vertexAx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAx.f * 16.0f) & 0xffff; + break; + case SST_fvertexAy: case SST_remap_fvertexAy: + voodoo->fvertexAy.i = val; + voodoo->params.vertexAy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexAy.f * 16.0f) & 0xffff; + break; + case SST_fvertexBx: case SST_remap_fvertexBx: + voodoo->fvertexBx.i = val; + voodoo->params.vertexBx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBx.f * 16.0f) & 0xffff; + break; + case SST_fvertexBy: case SST_remap_fvertexBy: + voodoo->fvertexBy.i = val; + voodoo->params.vertexBy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexBy.f * 16.0f) & 0xffff; + break; + case SST_fvertexCx: case SST_remap_fvertexCx: + voodoo->fvertexCx.i = val; + voodoo->params.vertexCx = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCx.f * 16.0f) & 0xffff; + break; + case SST_fvertexCy: case SST_remap_fvertexCy: + voodoo->fvertexCy.i = val; + voodoo->params.vertexCy = (int32_t)(int16_t)(int32_t)(voodoo->fvertexCy.f * 16.0f) & 0xffff; + break; + + case SST_fstartR: case SST_remap_fstartR: + tempif.i = val; + voodoo->params.startR = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fstartG: case SST_remap_fstartG: + tempif.i = val; + voodoo->params.startG = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fstartB: case SST_remap_fstartB: + tempif.i = val; + voodoo->params.startB = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fstartZ: case SST_remap_fstartZ: + tempif.i = val; + voodoo->params.startZ = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fstartA: case SST_remap_fstartA: + tempif.i = val; + voodoo->params.startA = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fstartS: case SST_remap_fstartS: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startS = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startS = (int64_t)(tempif.f * 4294967296.0f); + break; + case SST_fstartT: case SST_remap_fstartT: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startT = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startT = (int64_t)(tempif.f * 4294967296.0f); + break; + case SST_fstartW: case SST_remap_fstartW: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].startW = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].startW = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_FBI) + voodoo->params.startW = (int64_t)(tempif.f * 4294967296.0f); + break; + + case SST_fdRdX: case SST_remap_fdRdX: + tempif.i = val; + voodoo->params.dRdX = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdGdX: case SST_remap_fdGdX: + tempif.i = val; + voodoo->params.dGdX = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdBdX: case SST_remap_fdBdX: + tempif.i = val; + voodoo->params.dBdX = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdZdX: case SST_remap_fdZdX: + tempif.i = val; + voodoo->params.dZdX = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdAdX: case SST_remap_fdAdX: + tempif.i = val; + voodoo->params.dAdX = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdSdX: case SST_remap_fdSdX: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dSdX = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dSdX = (int64_t)(tempif.f * 4294967296.0f); + break; + case SST_fdTdX: case SST_remap_fdTdX: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dTdX = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dTdX = (int64_t)(tempif.f * 4294967296.0f); + break; + case SST_fdWdX: case SST_remap_fdWdX: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dWdX = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dWdX = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_FBI) + voodoo->params.dWdX = (int64_t)(tempif.f * 4294967296.0f); + break; + + case SST_fdRdY: case SST_remap_fdRdY: + tempif.i = val; + voodoo->params.dRdY = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdGdY: case SST_remap_fdGdY: + tempif.i = val; + voodoo->params.dGdY = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdBdY: case SST_remap_fdBdY: + tempif.i = val; + voodoo->params.dBdY = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdZdY: case SST_remap_fdZdY: + tempif.i = val; + voodoo->params.dZdY = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdAdY: case SST_remap_fdAdY: + tempif.i = val; + voodoo->params.dAdY = (int32_t)(tempif.f * 4096.0f); + break; + case SST_fdSdY: case SST_remap_fdSdY: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dSdY = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dSdY = (int64_t)(tempif.f * 4294967296.0f); + break; + case SST_fdTdY: case SST_remap_fdTdY: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dTdY = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dTdY = (int64_t)(tempif.f * 4294967296.0f); + break; + case SST_fdWdY: case SST_remap_fdWdY: + tempif.i = val; + if (chip & CHIP_TREX0) + voodoo->params.tmu[0].dWdY = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_TREX1) + voodoo->params.tmu[1].dWdY = (int64_t)(tempif.f * 4294967296.0f); + if (chip & CHIP_FBI) + voodoo->params.dWdY = (int64_t)(tempif.f * 4294967296.0f); + break; + + case SST_ftriangleCMD: + voodoo->params.sign = val & (1 << 31); + + if (voodoo->ncc_dirty[0]) + voodoo_update_ncc(voodoo, 0); + if (voodoo->ncc_dirty[1]) + voodoo_update_ncc(voodoo, 1); + voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; + + voodoo_queue_triangle(voodoo, &voodoo->params); + + voodoo->cmd_read++; + break; + + case SST_fbzColorPath: + voodoo->params.fbzColorPath = val; + voodoo->rgb_sel = val & 3; + break; + + case SST_fogMode: + voodoo->params.fogMode = val; + break; + case SST_alphaMode: + voodoo->params.alphaMode = val; + break; + case SST_fbzMode: + voodoo->params.fbzMode = val; + voodoo_recalc(voodoo); + break; + case SST_lfbMode: + voodoo->lfbMode = val; + voodoo_recalc(voodoo); + break; + + case SST_clipLeftRight: + if (voodoo->type >= VOODOO_2) + { + voodoo->params.clipRight = val & 0xfff; + voodoo->params.clipLeft = (val >> 16) & 0xfff; + } + else + { + voodoo->params.clipRight = val & 0x3ff; + voodoo->params.clipLeft = (val >> 16) & 0x3ff; + } + break; + case SST_clipLowYHighY: + if (voodoo->type >= VOODOO_2) + { + voodoo->params.clipHighY = val & 0xfff; + voodoo->params.clipLowY = (val >> 16) & 0xfff; + } + else + { + voodoo->params.clipHighY = val & 0x3ff; + voodoo->params.clipLowY = (val >> 16) & 0x3ff; + } + break; + + case SST_nopCMD: + voodoo->cmd_read++; + voodoo->fbiPixelsIn = 0; + voodoo->fbiChromaFail = 0; + voodoo->fbiZFuncFail = 0; + voodoo->fbiAFuncFail = 0; + voodoo->fbiPixelsOut = 0; + break; + case SST_fastfillCMD: + voodoo_wait_for_render_thread_idle(voodoo); + voodoo_fastfill(voodoo, &voodoo->params); + voodoo->cmd_read++; + break; + + case SST_fogColor: + voodoo->params.fogColor.r = (val >> 16) & 0xff; + voodoo->params.fogColor.g = (val >> 8) & 0xff; + voodoo->params.fogColor.b = val & 0xff; + break; + + case SST_zaColor: + voodoo->params.zaColor = val; + break; + case SST_chromaKey: + voodoo->params.chromaKey_r = (val >> 16) & 0xff; + voodoo->params.chromaKey_g = (val >> 8) & 0xff; + voodoo->params.chromaKey_b = val & 0xff; + voodoo->params.chromaKey = val & 0xffffff; + break; + case SST_stipple: + voodoo->params.stipple = val; + break; + case SST_color0: + voodoo->params.color0 = val; + break; + case SST_color1: + voodoo->params.color1 = val; + break; + + case SST_fogTable00: case SST_fogTable01: case SST_fogTable02: case SST_fogTable03: + case SST_fogTable04: case SST_fogTable05: case SST_fogTable06: case SST_fogTable07: + case SST_fogTable08: case SST_fogTable09: case SST_fogTable0a: case SST_fogTable0b: + case SST_fogTable0c: case SST_fogTable0d: case SST_fogTable0e: case SST_fogTable0f: + case SST_fogTable10: case SST_fogTable11: case SST_fogTable12: case SST_fogTable13: + case SST_fogTable14: case SST_fogTable15: case SST_fogTable16: case SST_fogTable17: + case SST_fogTable18: case SST_fogTable19: case SST_fogTable1a: case SST_fogTable1b: + case SST_fogTable1c: case SST_fogTable1d: case SST_fogTable1e: case SST_fogTable1f: + addr = (addr - SST_fogTable00) >> 1; + voodoo->params.fogTable[addr].dfog = val & 0xff; + voodoo->params.fogTable[addr].fog = (val >> 8) & 0xff; + voodoo->params.fogTable[addr+1].dfog = (val >> 16) & 0xff; + voodoo->params.fogTable[addr+1].fog = (val >> 24) & 0xff; + break; + + case SST_clutData: + voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff; + voodoo->clutData[(val >> 24) & 0x3f].g = (val >> 8) & 0xff; + voodoo->clutData[(val >> 24) & 0x3f].r = (val >> 16) & 0xff; + if (val & 0x20000000) + { + voodoo->clutData[(val >> 24) & 0x3f].b = 255; + voodoo->clutData[(val >> 24) & 0x3f].g = 255; + voodoo->clutData[(val >> 24) & 0x3f].r = 255; + } + voodoo->clutData_dirty = 1; + break; + + case SST_sSetupMode: + voodoo->sSetupMode = val; + break; + case SST_sVx: + tempif.i = val; + voodoo->verts[3].sVx = tempif.f; +// pclog("sVx[%i]=%f\n", voodoo->vertex_num, tempif.f); + break; + case SST_sVy: + tempif.i = val; + voodoo->verts[3].sVy = tempif.f; +// pclog("sVy[%i]=%f\n", voodoo->vertex_num, tempif.f); + break; + case SST_sARGB: + voodoo->verts[3].sBlue = (float)(val & 0xff); + voodoo->verts[3].sGreen = (float)((val >> 8) & 0xff); + voodoo->verts[3].sRed = (float)((val >> 16) & 0xff); + voodoo->verts[3].sAlpha = (float)((val >> 24) & 0xff); + break; + case SST_sRed: + tempif.i = val; + voodoo->verts[3].sRed = tempif.f; + break; + case SST_sGreen: + tempif.i = val; + voodoo->verts[3].sGreen = tempif.f; + break; + case SST_sBlue: + tempif.i = val; + voodoo->verts[3].sBlue = tempif.f; + break; + case SST_sAlpha: + tempif.i = val; + voodoo->verts[3].sAlpha = tempif.f; + break; + case SST_sVz: + tempif.i = val; + voodoo->verts[3].sVz = tempif.f; + break; + case SST_sWb: + tempif.i = val; + voodoo->verts[3].sWb = tempif.f; + break; + case SST_sW0: + tempif.i = val; + voodoo->verts[3].sW0 = tempif.f; + break; + case SST_sS0: + tempif.i = val; + voodoo->verts[3].sS0 = tempif.f; + break; + case SST_sT0: + tempif.i = val; + voodoo->verts[3].sT0 = tempif.f; + break; + case SST_sW1: + tempif.i = val; + voodoo->verts[3].sW1 = tempif.f; + break; + case SST_sS1: + tempif.i = val; + voodoo->verts[3].sS1 = tempif.f; + break; + case SST_sT1: + tempif.i = val; + voodoo->verts[3].sT1 = tempif.f; + break; + + case SST_sBeginTriCMD: +// pclog("sBeginTriCMD %i %f\n", voodoo->vertex_num, voodoo->verts[4].sVx); + voodoo->verts[0] = voodoo->verts[3]; + voodoo->vertex_num = 1; + voodoo->num_verticies = 1; + break; + case SST_sDrawTriCMD: +// pclog("sDrawTriCMD %i %i %i\n", voodoo->num_verticies, voodoo->vertex_num, voodoo->sSetupMode & SETUPMODE_STRIP_MODE); + if (voodoo->vertex_num == 3) + voodoo->vertex_num = (voodoo->sSetupMode & SETUPMODE_STRIP_MODE) ? 1 : 0; + voodoo->verts[voodoo->vertex_num] = voodoo->verts[3]; + + voodoo->num_verticies++; + voodoo->vertex_num++; + if (voodoo->num_verticies == 3) + { +// pclog("triangle_setup\n"); + voodoo_triangle_setup(voodoo); + + voodoo->num_verticies = 2; + } + if (voodoo->vertex_num == 4) + fatal("sDrawTriCMD overflow\n"); + break; + + case SST_bltSrcBaseAddr: + voodoo->bltSrcBaseAddr = val & 0x3fffff; + break; + case SST_bltDstBaseAddr: +// pclog("Write bltDstBaseAddr %08x\n", val); + voodoo->bltDstBaseAddr = val & 0x3fffff; + break; + case SST_bltXYStrides: + voodoo->bltSrcXYStride = val & 0xfff; + voodoo->bltDstXYStride = (val >> 16) & 0xfff; +// pclog("Write bltXYStrides %08x\n", val); + break; + case SST_bltSrcChromaRange: + voodoo->bltSrcChromaRange = val; + voodoo->bltSrcChromaMinB = val & 0x1f; + voodoo->bltSrcChromaMinG = (val >> 5) & 0x3f; + voodoo->bltSrcChromaMinR = (val >> 11) & 0x1f; + voodoo->bltSrcChromaMaxB = (val >> 16) & 0x1f; + voodoo->bltSrcChromaMaxG = (val >> 21) & 0x3f; + voodoo->bltSrcChromaMaxR = (val >> 27) & 0x1f; + break; + case SST_bltDstChromaRange: + voodoo->bltDstChromaRange = val; + voodoo->bltDstChromaMinB = val & 0x1f; + voodoo->bltDstChromaMinG = (val >> 5) & 0x3f; + voodoo->bltDstChromaMinR = (val >> 11) & 0x1f; + voodoo->bltDstChromaMaxB = (val >> 16) & 0x1f; + voodoo->bltDstChromaMaxG = (val >> 21) & 0x3f; + voodoo->bltDstChromaMaxR = (val >> 27) & 0x1f; + break; + case SST_bltClipX: + voodoo->bltClipRight = val & 0xfff; + voodoo->bltClipLeft = (val >> 16) & 0xfff; + break; + case SST_bltClipY: + voodoo->bltClipHighY = val & 0xfff; + voodoo->bltClipLowY = (val >> 16) & 0xfff; + break; + + case SST_bltSrcXY: + voodoo->bltSrcX = val & 0x7ff; + voodoo->bltSrcY = (val >> 16) & 0x7ff; + break; + case SST_bltDstXY: +// pclog("Write bltDstXY %08x\n", val); + voodoo->bltDstX = val & 0x7ff; + voodoo->bltDstY = (val >> 16) & 0x7ff; + if (val & (1 << 31)) + voodoo_v2_blit_start(voodoo); + break; + case SST_bltSize: +// pclog("Write bltSize %08x\n", val); + voodoo->bltSizeX = val & 0xfff; + if (voodoo->bltSizeX & 0x800) + voodoo->bltSizeX |= 0xfffff000; + voodoo->bltSizeY = (val >> 16) & 0xfff; + if (voodoo->bltSizeY & 0x800) + voodoo->bltSizeY |= 0xfffff000; + if (val & (1 << 31)) + voodoo_v2_blit_start(voodoo); + break; + case SST_bltRop: + voodoo->bltRop[0] = val & 0xf; + voodoo->bltRop[1] = (val >> 4) & 0xf; + voodoo->bltRop[2] = (val >> 8) & 0xf; + voodoo->bltRop[3] = (val >> 12) & 0xf; + break; + case SST_bltColor: +// pclog("Write bltColor %08x\n", val); + voodoo->bltColorFg = val & 0xffff; + voodoo->bltColorBg = (val >> 16) & 0xffff; + break; + + case SST_bltCommand: + voodoo->bltCommand = val; +// pclog("Write bltCommand %08x\n", val); + if (val & (1 << 31)) + voodoo_v2_blit_start(voodoo); + break; + case SST_bltData: + voodoo_v2_blit_data(voodoo, val); + break; + + case SST_textureMode: + if (chip & CHIP_TREX0) + { + voodoo->params.textureMode[0] = val; + voodoo->params.tformat[0] = (val >> 8) & 0xf; + } + if (chip & CHIP_TREX1) + { + voodoo->params.textureMode[1] = val; + voodoo->params.tformat[1] = (val >> 8) & 0xf; + } + break; + case SST_tLOD: + if (chip & CHIP_TREX0) + { + voodoo->params.tLOD[0] = val; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) + { + voodoo->params.tLOD[1] = val; + voodoo_recalc_tex(voodoo, 1); + } + break; + case SST_tDetail: + if (chip & CHIP_TREX0) + { + voodoo->params.detail_max[0] = val & 0xff; + voodoo->params.detail_bias[0] = (val >> 8) & 0x3f; + voodoo->params.detail_scale[0] = (val >> 14) & 7; + } + if (chip & CHIP_TREX1) + { + voodoo->params.detail_max[1] = val & 0xff; + voodoo->params.detail_bias[1] = (val >> 8) & 0x3f; + voodoo->params.detail_scale[1] = (val >> 14) & 7; + } + break; + case SST_texBaseAddr: + if (chip & CHIP_TREX0) + { + voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) + { + voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 1); + } + break; + case SST_texBaseAddr1: + if (chip & CHIP_TREX0) + { + voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) + { + voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 1); + } + break; + case SST_texBaseAddr2: + if (chip & CHIP_TREX0) + { + voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) + { + voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 1); + } + break; + case SST_texBaseAddr38: + if (chip & CHIP_TREX0) + { + voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 0); + } + if (chip & CHIP_TREX1) + { + voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3; + voodoo_recalc_tex(voodoo, 1); + } + break; + + case SST_trexInit1: + if (chip & CHIP_TREX0) + voodoo->trexInit1[0] = val; + if (chip & CHIP_TREX1) + voodoo->trexInit1[1] = val; + break; + + case SST_nccTable0_Y0: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].y[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].y[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable0_Y1: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].y[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].y[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable0_Y2: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].y[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].y[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable0_Y3: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].y[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].y[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + + case SST_nccTable0_I0: + if (!(val & (1 << 31))) + { + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].i[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].i[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + case SST_nccTable0_I2: + if (!(val & (1 << 31))) + { + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].i[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].i[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + case SST_nccTable0_Q0: + if (!(val & (1 << 31))) + { + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].q[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].q[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + case SST_nccTable0_Q2: + if (!(val & (1 << 31))) + { + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].i[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].i[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + if (val & (1 << 31)) + { + int p = (val >> 23) & 0xfe; + if (chip & CHIP_TREX0) + { + voodoo->palette[0][p].u = val | 0xff000000; + voodoo->palette_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->palette[1][p].u = val | 0xff000000; + voodoo->palette_dirty[1] = 1; + } + } + break; + + case SST_nccTable0_I1: + if (!(val & (1 << 31))) + { + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].i[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].i[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + case SST_nccTable0_I3: + if (!(val & (1 << 31))) + { + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].i[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].i[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + case SST_nccTable0_Q1: + if (!(val & (1 << 31))) + { + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].q[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].q[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + case SST_nccTable0_Q3: + if (!(val & (1 << 31))) + { + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][0].q[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][0].q[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + } + if (val & (1 << 31)) + { + int p = ((val >> 23) & 0xfe) | 0x01; + if (chip & CHIP_TREX0) + { + voodoo->palette[0][p].u = val | 0xff000000; + voodoo->palette_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->palette[1][p].u = val | 0xff000000; + voodoo->palette_dirty[1] = 1; + } + } + break; + + case SST_nccTable1_Y0: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].y[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].y[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Y1: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].y[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].y[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Y2: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].y[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].y[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Y3: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].y[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].y[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_I0: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].i[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].i[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_I1: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].i[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].i[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_I2: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].i[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].i[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_I3: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].i[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].i[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Q0: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].q[0] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].q[0] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Q1: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].q[1] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].q[1] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Q2: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].q[2] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].q[2] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + case SST_nccTable1_Q3: + if (chip & CHIP_TREX0) + { + voodoo->nccTable[0][1].q[3] = val; + voodoo->ncc_dirty[0] = 1; + } + if (chip & CHIP_TREX1) + { + voodoo->nccTable[1][1].q[3] = val; + voodoo->ncc_dirty[1] = 1; + } + break; + + case SST_userIntrCMD: + fatal("userIntrCMD write %08x from FIFO\n", val); + break; + } +} diff --git a/src/vid_voodoo_reg.h b/src/vid_voodoo_reg.h new file mode 100644 index 0000000..f3a9418 --- /dev/null +++ b/src/vid_voodoo_reg.h @@ -0,0 +1 @@ +void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p); diff --git a/src/vid_voodoo_regs.h b/src/vid_voodoo_regs.h new file mode 100644 index 0000000..e065a71 --- /dev/null +++ b/src/vid_voodoo_regs.h @@ -0,0 +1,680 @@ +enum +{ + SST_status = 0x000, + SST_intrCtrl = 0x004, + + SST_vertexAx = 0x008, + SST_vertexAy = 0x00c, + SST_vertexBx = 0x010, + SST_vertexBy = 0x014, + SST_vertexCx = 0x018, + SST_vertexCy = 0x01c, + + SST_startR = 0x0020, + SST_startG = 0x0024, + SST_startB = 0x0028, + SST_startZ = 0x002c, + SST_startA = 0x0030, + SST_startS = 0x0034, + SST_startT = 0x0038, + SST_startW = 0x003c, + + SST_dRdX = 0x0040, + SST_dGdX = 0x0044, + SST_dBdX = 0x0048, + SST_dZdX = 0x004c, + SST_dAdX = 0x0050, + SST_dSdX = 0x0054, + SST_dTdX = 0x0058, + SST_dWdX = 0x005c, + + SST_dRdY = 0x0060, + SST_dGdY = 0x0064, + SST_dBdY = 0x0068, + SST_dZdY = 0x006c, + SST_dAdY = 0x0070, + SST_dSdY = 0x0074, + SST_dTdY = 0x0078, + SST_dWdY = 0x007c, + + SST_triangleCMD = 0x0080, + + SST_fvertexAx = 0x088, + SST_fvertexAy = 0x08c, + SST_fvertexBx = 0x090, + SST_fvertexBy = 0x094, + SST_fvertexCx = 0x098, + SST_fvertexCy = 0x09c, + + SST_fstartR = 0x00a0, + SST_fstartG = 0x00a4, + SST_fstartB = 0x00a8, + SST_fstartZ = 0x00ac, + SST_fstartA = 0x00b0, + SST_fstartS = 0x00b4, + SST_fstartT = 0x00b8, + SST_fstartW = 0x00bc, + + SST_fdRdX = 0x00c0, + SST_fdGdX = 0x00c4, + SST_fdBdX = 0x00c8, + SST_fdZdX = 0x00cc, + SST_fdAdX = 0x00d0, + SST_fdSdX = 0x00d4, + SST_fdTdX = 0x00d8, + SST_fdWdX = 0x00dc, + + SST_fdRdY = 0x00e0, + SST_fdGdY = 0x00e4, + SST_fdBdY = 0x00e8, + SST_fdZdY = 0x00ec, + SST_fdAdY = 0x00f0, + SST_fdSdY = 0x00f4, + SST_fdTdY = 0x00f8, + SST_fdWdY = 0x00fc, + + SST_ftriangleCMD = 0x0100, + + SST_fbzColorPath = 0x104, + SST_fogMode = 0x108, + + SST_alphaMode = 0x10c, + SST_fbzMode = 0x110, + SST_lfbMode = 0x114, + + SST_clipLeftRight = 0x118, + SST_clipLowYHighY = 0x11c, + + SST_nopCMD = 0x120, + SST_fastfillCMD = 0x124, + SST_swapbufferCMD = 0x128, + + SST_fogColor = 0x12c, + SST_zaColor = 0x130, + SST_chromaKey = 0x134, + + SST_userIntrCMD = 0x13c, + SST_stipple = 0x140, + SST_color0 = 0x144, + SST_color1 = 0x148, + + SST_fbiPixelsIn = 0x14c, + SST_fbiChromaFail = 0x150, + SST_fbiZFuncFail = 0x154, + SST_fbiAFuncFail = 0x158, + SST_fbiPixelsOut = 0x15c, + + SST_fogTable00 = 0x160, + SST_fogTable01 = 0x164, + SST_fogTable02 = 0x168, + SST_fogTable03 = 0x16c, + SST_fogTable04 = 0x170, + SST_fogTable05 = 0x174, + SST_fogTable06 = 0x178, + SST_fogTable07 = 0x17c, + SST_fogTable08 = 0x180, + SST_fogTable09 = 0x184, + SST_fogTable0a = 0x188, + SST_fogTable0b = 0x18c, + SST_fogTable0c = 0x190, + SST_fogTable0d = 0x194, + SST_fogTable0e = 0x198, + SST_fogTable0f = 0x19c, + SST_fogTable10 = 0x1a0, + SST_fogTable11 = 0x1a4, + SST_fogTable12 = 0x1a8, + SST_fogTable13 = 0x1ac, + SST_fogTable14 = 0x1b0, + SST_fogTable15 = 0x1b4, + SST_fogTable16 = 0x1b8, + SST_fogTable17 = 0x1bc, + SST_fogTable18 = 0x1c0, + SST_fogTable19 = 0x1c4, + SST_fogTable1a = 0x1c8, + SST_fogTable1b = 0x1cc, + SST_fogTable1c = 0x1d0, + SST_fogTable1d = 0x1d4, + SST_fogTable1e = 0x1d8, + SST_fogTable1f = 0x1dc, + + SST_cmdFifoBaseAddr = 0x1e0, + SST_cmdFifoBump = 0x1e4, + SST_cmdFifoRdPtr = 0x1e8, + SST_cmdFifoAMin = 0x1ec, + SST_cmdFifoAMax = 0x1f0, + SST_cmdFifoDepth = 0x1f4, + SST_cmdFifoHoles = 0x1f8, + + SST_fbiInit4 = 0x200, + SST_vRetrace = 0x204, + SST_backPorch = 0x208, + SST_videoDimensions = 0x20c, + SST_fbiInit0 = 0x210, + SST_fbiInit1 = 0x214, + SST_fbiInit2 = 0x218, + SST_fbiInit3 = 0x21c, + SST_hSync = 0x220, + SST_vSync = 0x224, + SST_clutData = 0x228, + SST_dacData = 0x22c, + + SST_scrFilter = 0x230, + + SST_hvRetrace = 0x240, + SST_fbiInit5 = 0x244, + SST_fbiInit6 = 0x248, + SST_fbiInit7 = 0x24c, + + SST_sSetupMode = 0x260, + SST_sVx = 0x264, + SST_sVy = 0x268, + SST_sARGB = 0x26c, + SST_sRed = 0x270, + SST_sGreen = 0x274, + SST_sBlue = 0x278, + SST_sAlpha = 0x27c, + SST_sVz = 0x280, + SST_sWb = 0x284, + SST_sW0 = 0x288, + SST_sS0 = 0x28c, + SST_sT0 = 0x290, + SST_sW1 = 0x294, + SST_sS1 = 0x298, + SST_sT1 = 0x29c, + + SST_sDrawTriCMD = 0x2a0, + SST_sBeginTriCMD = 0x2a4, + + SST_bltSrcBaseAddr = 0x2c0, + SST_bltDstBaseAddr = 0x2c4, + SST_bltXYStrides = 0x2c8, + SST_bltSrcChromaRange = 0x2cc, + SST_bltDstChromaRange = 0x2d0, + SST_bltClipX = 0x2d4, + SST_bltClipY = 0x2d8, + + SST_bltSrcXY = 0x2e0, + SST_bltDstXY = 0x2e4, + SST_bltSize = 0x2e8, + SST_bltRop = 0x2ec, + SST_bltColor = 0x2f0, + + SST_bltCommand = 0x2f8, + SST_bltData = 0x2fc, + + SST_textureMode = 0x300, + SST_tLOD = 0x304, + SST_tDetail = 0x308, + SST_texBaseAddr = 0x30c, + SST_texBaseAddr1 = 0x310, + SST_texBaseAddr2 = 0x314, + SST_texBaseAddr38 = 0x318, + + SST_trexInit1 = 0x320, + + SST_nccTable0_Y0 = 0x324, + SST_nccTable0_Y1 = 0x328, + SST_nccTable0_Y2 = 0x32c, + SST_nccTable0_Y3 = 0x330, + SST_nccTable0_I0 = 0x334, + SST_nccTable0_I1 = 0x338, + SST_nccTable0_I2 = 0x33c, + SST_nccTable0_I3 = 0x340, + SST_nccTable0_Q0 = 0x344, + SST_nccTable0_Q1 = 0x348, + SST_nccTable0_Q2 = 0x34c, + SST_nccTable0_Q3 = 0x350, + + SST_nccTable1_Y0 = 0x354, + SST_nccTable1_Y1 = 0x358, + SST_nccTable1_Y2 = 0x35c, + SST_nccTable1_Y3 = 0x360, + SST_nccTable1_I0 = 0x364, + SST_nccTable1_I1 = 0x368, + SST_nccTable1_I2 = 0x36c, + SST_nccTable1_I3 = 0x370, + SST_nccTable1_Q0 = 0x374, + SST_nccTable1_Q1 = 0x378, + SST_nccTable1_Q2 = 0x37c, + SST_nccTable1_Q3 = 0x380, + + SST_remap_status = 0x000 | 0x400, + + SST_remap_vertexAx = 0x008 | 0x400, + SST_remap_vertexAy = 0x00c | 0x400, + SST_remap_vertexBx = 0x010 | 0x400, + SST_remap_vertexBy = 0x014 | 0x400, + SST_remap_vertexCx = 0x018 | 0x400, + SST_remap_vertexCy = 0x01c | 0x400, + + SST_remap_startR = 0x0020 | 0x400, + SST_remap_startG = 0x002c | 0x400, + SST_remap_startB = 0x0038 | 0x400, + SST_remap_startZ = 0x0044 | 0x400, + SST_remap_startA = 0x0050 | 0x400, + SST_remap_startS = 0x005c | 0x400, + SST_remap_startT = 0x0068 | 0x400, + SST_remap_startW = 0x0074 | 0x400, + + SST_remap_dRdX = 0x0024 | 0x400, + SST_remap_dGdX = 0x0030 | 0x400, + SST_remap_dBdX = 0x003c | 0x400, + SST_remap_dZdX = 0x0048 | 0x400, + SST_remap_dAdX = 0x0054 | 0x400, + SST_remap_dSdX = 0x0060 | 0x400, + SST_remap_dTdX = 0x006c | 0x400, + SST_remap_dWdX = 0x0078 | 0x400, + + SST_remap_dRdY = 0x0028 | 0x400, + SST_remap_dGdY = 0x0034 | 0x400, + SST_remap_dBdY = 0x0040 | 0x400, + SST_remap_dZdY = 0x004c | 0x400, + SST_remap_dAdY = 0x0058 | 0x400, + SST_remap_dSdY = 0x0064 | 0x400, + SST_remap_dTdY = 0x0070 | 0x400, + SST_remap_dWdY = 0x007c | 0x400, + + SST_remap_triangleCMD = 0x0080 | 0x400, + + SST_remap_fvertexAx = 0x088 | 0x400, + SST_remap_fvertexAy = 0x08c | 0x400, + SST_remap_fvertexBx = 0x090 | 0x400, + SST_remap_fvertexBy = 0x094 | 0x400, + SST_remap_fvertexCx = 0x098 | 0x400, + SST_remap_fvertexCy = 0x09c | 0x400, + + SST_remap_fstartR = 0x00a0 | 0x400, + SST_remap_fstartG = 0x00ac | 0x400, + SST_remap_fstartB = 0x00b8 | 0x400, + SST_remap_fstartZ = 0x00c4 | 0x400, + SST_remap_fstartA = 0x00d0 | 0x400, + SST_remap_fstartS = 0x00dc | 0x400, + SST_remap_fstartT = 0x00e8 | 0x400, + SST_remap_fstartW = 0x00f4 | 0x400, + + SST_remap_fdRdX = 0x00a4 | 0x400, + SST_remap_fdGdX = 0x00b0 | 0x400, + SST_remap_fdBdX = 0x00bc | 0x400, + SST_remap_fdZdX = 0x00c8 | 0x400, + SST_remap_fdAdX = 0x00d4 | 0x400, + SST_remap_fdSdX = 0x00e0 | 0x400, + SST_remap_fdTdX = 0x00ec | 0x400, + SST_remap_fdWdX = 0x00f8 | 0x400, + + SST_remap_fdRdY = 0x00a8 | 0x400, + SST_remap_fdGdY = 0x00b4 | 0x400, + SST_remap_fdBdY = 0x00c0 | 0x400, + SST_remap_fdZdY = 0x00cc | 0x400, + SST_remap_fdAdY = 0x00d8 | 0x400, + SST_remap_fdSdY = 0x00e4 | 0x400, + SST_remap_fdTdY = 0x00f0 | 0x400, + SST_remap_fdWdY = 0x00fc | 0x400, +}; + +enum +{ + LFB_WRITE_FRONT = 0x0000, + LFB_WRITE_BACK = 0x0010, + LFB_WRITE_MASK = 0x0030 +}; + +enum +{ + LFB_READ_FRONT = 0x0000, + LFB_READ_BACK = 0x0040, + LFB_READ_AUX = 0x0080, + LFB_READ_MASK = 0x00c0 +}; + +enum +{ + LFB_FORMAT_RGB565 = 0, + LFB_FORMAT_RGB555 = 1, + LFB_FORMAT_ARGB1555 = 2, + LFB_FORMAT_ARGB8888 = 5, + LFB_FORMAT_DEPTH = 15, + LFB_FORMAT_MASK = 15 +}; + +enum +{ + LFB_WRITE_COLOUR = 1, + LFB_WRITE_DEPTH = 2 +}; + +enum +{ + FBZ_CHROMAKEY = (1 << 1), + FBZ_W_BUFFER = (1 << 3), + FBZ_DEPTH_ENABLE = (1 << 4), + + FBZ_DITHER = (1 << 8), + FBZ_RGB_WMASK = (1 << 9), + FBZ_DEPTH_WMASK = (1 << 10), + FBZ_DITHER_2x2 = (1 << 11), + + FBZ_DRAW_FRONT = 0x0000, + FBZ_DRAW_BACK = 0x4000, + FBZ_DRAW_MASK = 0xc000, + + FBZ_DEPTH_BIAS = (1 << 16), + + FBZ_DEPTH_SOURCE = (1 << 20), + + FBZ_PARAM_ADJUST = (1 << 26) +}; + +enum +{ + TEX_RGB332 = 0x0, + TEX_Y4I2Q2 = 0x1, + TEX_A8 = 0x2, + TEX_I8 = 0x3, + TEX_AI8 = 0x4, + TEX_PAL8 = 0x5, + TEX_APAL8 = 0x6, + TEX_ARGB8332 = 0x8, + TEX_A8Y4I2Q2 = 0x9, + TEX_R5G6B5 = 0xa, + TEX_ARGB1555 = 0xb, + TEX_ARGB4444 = 0xc, + TEX_A8I8 = 0xd, + TEX_APAL88 = 0xe +}; + +enum +{ + TEXTUREMODE_NCC_SEL = (1 << 5), + TEXTUREMODE_TCLAMPS = (1 << 6), + TEXTUREMODE_TCLAMPT = (1 << 7), + TEXTUREMODE_TRILINEAR = (1 << 30) +}; + +enum +{ + FBIINIT0_VGA_PASS = 1, + FBIINIT0_GRAPHICS_RESET = (1 << 1) +}; + +enum +{ + FBIINIT1_MULTI_SST = (1 << 2), /*Voodoo Graphics only*/ + FBIINIT1_VIDEO_RESET = (1 << 8), + FBIINIT1_SLI_ENABLE = (1 << 23) +}; + +enum +{ + FBIINIT2_SWAP_ALGORITHM_MASK = (3 << 9) +}; + +enum +{ + FBIINIT2_SWAP_ALGORITHM_DAC_VSYNC = (0 << 9), + FBIINIT2_SWAP_ALGORITHM_DAC_DATA = (1 << 9), + FBIINIT2_SWAP_ALGORITHM_PCI_FIFO_STALL = (2 << 9), + FBIINIT2_SWAP_ALGORITHM_SLI_SYNC = (3 << 9) +}; + +enum +{ + FBIINIT3_REMAP = 1 +}; + +enum +{ + FBIINIT5_MULTI_CVG = (1 << 14) +}; + +enum +{ + FBIINIT7_CMDFIFO_ENABLE = (1 << 8) +}; + +enum +{ + CC_LOCALSELECT_ITER_RGB = 0, + CC_LOCALSELECT_TEX = 1, + CC_LOCALSELECT_COLOR1 = 2, + CC_LOCALSELECT_LFB = 3 +}; + +enum +{ + CCA_LOCALSELECT_ITER_A = 0, + CCA_LOCALSELECT_COLOR0 = 1, + CCA_LOCALSELECT_ITER_Z = 2 +}; + +enum +{ + C_SEL_ITER_RGB = 0, + C_SEL_TEX = 1, + C_SEL_COLOR1 = 2, + C_SEL_LFB = 3 +}; + +enum +{ + A_SEL_ITER_A = 0, + A_SEL_TEX = 1, + A_SEL_COLOR1 = 2, + A_SEL_LFB = 3 +}; + +enum +{ + CC_MSELECT_ZERO = 0, + CC_MSELECT_CLOCAL = 1, + CC_MSELECT_AOTHER = 2, + CC_MSELECT_ALOCAL = 3, + CC_MSELECT_TEX = 4, + CC_MSELECT_TEXRGB = 5 +}; + +enum +{ + CCA_MSELECT_ZERO = 0, + CCA_MSELECT_ALOCAL = 1, + CCA_MSELECT_AOTHER = 2, + CCA_MSELECT_ALOCAL2 = 3, + CCA_MSELECT_TEX = 4 +}; + +enum +{ + TC_MSELECT_ZERO = 0, + TC_MSELECT_CLOCAL = 1, + TC_MSELECT_AOTHER = 2, + TC_MSELECT_ALOCAL = 3, + TC_MSELECT_DETAIL = 4, + TC_MSELECT_LOD_FRAC = 5 +}; + +enum +{ + TCA_MSELECT_ZERO = 0, + TCA_MSELECT_CLOCAL = 1, + TCA_MSELECT_AOTHER = 2, + TCA_MSELECT_ALOCAL = 3, + TCA_MSELECT_DETAIL = 4, + TCA_MSELECT_LOD_FRAC = 5 +}; + +enum +{ + CC_ADD_CLOCAL = 1, + CC_ADD_ALOCAL = 2 +}; + +enum +{ + CCA_ADD_CLOCAL = 1, + CCA_ADD_ALOCAL = 2 +}; + +enum +{ + AFUNC_AZERO = 0x0, + AFUNC_ASRC_ALPHA = 0x1, + AFUNC_A_COLOR = 0x2, + AFUNC_ADST_ALPHA = 0x3, + AFUNC_AONE = 0x4, + AFUNC_AOMSRC_ALPHA = 0x5, + AFUNC_AOM_COLOR = 0x6, + AFUNC_AOMDST_ALPHA = 0x7, + AFUNC_ASATURATE = 0xf +}; + +enum +{ + AFUNC_ACOLORBEFOREFOG = 0xf +}; + +enum +{ + AFUNC_NEVER = 0, + AFUNC_LESSTHAN = 1, + AFUNC_EQUAL = 2, + AFUNC_LESSTHANEQUAL = 3, + AFUNC_GREATERTHAN = 4, + AFUNC_NOTEQUAL = 5, + AFUNC_GREATERTHANEQUAL = 6, + AFUNC_ALWAYS = 7 +}; + +enum +{ + DEPTHOP_NEVER = 0, + DEPTHOP_LESSTHAN = 1, + DEPTHOP_EQUAL = 2, + DEPTHOP_LESSTHANEQUAL = 3, + DEPTHOP_GREATERTHAN = 4, + DEPTHOP_NOTEQUAL = 5, + DEPTHOP_GREATERTHANEQUAL = 6, + DEPTHOP_ALWAYS = 7 +}; + +enum +{ + FOG_ENABLE = 0x01, + FOG_ADD = 0x02, + FOG_MULT = 0x04, + FOG_ALPHA = 0x08, + FOG_Z = 0x10, + FOG_W = 0x18, + FOG_CONSTANT = 0x20 +}; + +enum +{ + LOD_ODD = (1 << 18), + LOD_SPLIT = (1 << 19), + LOD_S_IS_WIDER = (1 << 20), + LOD_TMULTIBASEADDR = (1 << 24), + LOD_TMIRROR_S = (1 << 28), + LOD_TMIRROR_T = (1 << 29) +}; +enum +{ + CMD_INVALID = 0, + CMD_DRAWTRIANGLE, + CMD_FASTFILL, + CMD_SWAPBUF +}; + +enum +{ + FBZCP_TEXTURE_ENABLED = (1 << 27) +}; + +enum +{ + BLTCMD_SRC_TILED = (1 << 14), + BLTCMD_DST_TILED = (1 << 15) +}; + +enum +{ + INITENABLE_SLI_MASTER_SLAVE = (1 << 11) +}; + +enum +{ + SETUPMODE_RGB = (1 << 0), + SETUPMODE_ALPHA = (1 << 1), + SETUPMODE_Z = (1 << 2), + SETUPMODE_Wb = (1 << 3), + SETUPMODE_W0 = (1 << 4), + SETUPMODE_S0_T0 = (1 << 5), + SETUPMODE_W1 = (1 << 6), + SETUPMODE_S1_T1 = (1 << 7), + + SETUPMODE_STRIP_MODE = (1 << 16), + SETUPMODE_CULLING_ENABLE = (1 << 17), + SETUPMODE_CULLING_SIGN = (1 << 18), + SETUPMODE_DISABLE_PINGPONG = (1 << 19) +}; + +#define TEXTUREMODE_MASK 0x3ffff000 +#define TEXTUREMODE_PASSTHROUGH 0 + +#define TEXTUREMODE_LOCAL_MASK 0x00643000 +#define TEXTUREMODE_LOCAL 0x00241000 + + +#define SLI_ENABLED (voodoo->fbiInit1 & FBIINIT1_SLI_ENABLE) +#define TRIPLE_BUFFER ((voodoo->fbiInit2 & 0x10) || (voodoo->fbiInit5 & 0x600) == 0x400) + + +#define _rgb_sel ( params->fbzColorPath & 3) +#define a_sel ( (params->fbzColorPath >> 2) & 3) +#define cc_localselect ( params->fbzColorPath & (1 << 4)) +#define cca_localselect ( (params->fbzColorPath >> 5) & 3) +#define cc_localselect_override ( params->fbzColorPath & (1 << 7)) +#define cc_zero_other ( params->fbzColorPath & (1 << 8)) +#define cc_sub_clocal ( params->fbzColorPath & (1 << 9)) +#define cc_mselect ( (params->fbzColorPath >> 10) & 7) +#define cc_reverse_blend ( params->fbzColorPath & (1 << 13)) +#define cc_add ( (params->fbzColorPath >> 14) & 3) +#define cc_add_alocal ( params->fbzColorPath & (1 << 15)) +#define cc_invert_output ( params->fbzColorPath & (1 << 16)) +#define cca_zero_other ( params->fbzColorPath & (1 << 17)) +#define cca_sub_clocal ( params->fbzColorPath & (1 << 18)) +#define cca_mselect ( (params->fbzColorPath >> 19) & 7) +#define cca_reverse_blend ( params->fbzColorPath & (1 << 22)) +#define cca_add ( (params->fbzColorPath >> 23) & 3) +#define cca_invert_output ( params->fbzColorPath & (1 << 25)) +#define tc_zero_other (params->textureMode[0] & (1 << 12)) +#define tc_sub_clocal (params->textureMode[0] & (1 << 13)) +#define tc_mselect ((params->textureMode[0] >> 14) & 7) +#define tc_reverse_blend (params->textureMode[0] & (1 << 17)) +#define tc_add_clocal (params->textureMode[0] & (1 << 18)) +#define tc_add_alocal (params->textureMode[0] & (1 << 19)) +#define tc_invert_output (params->textureMode[0] & (1 << 20)) +#define tca_zero_other (params->textureMode[0] & (1 << 21)) +#define tca_sub_clocal (params->textureMode[0] & (1 << 22)) +#define tca_mselect ((params->textureMode[0] >> 23) & 7) +#define tca_reverse_blend (params->textureMode[0] & (1 << 26)) +#define tca_add_clocal (params->textureMode[0] & (1 << 27)) +#define tca_add_alocal (params->textureMode[0] & (1 << 28)) +#define tca_invert_output (params->textureMode[0] & (1 << 29)) + +#define tc_sub_clocal_1 (params->textureMode[1] & (1 << 13)) +#define tc_mselect_1 ((params->textureMode[1] >> 14) & 7) +#define tc_reverse_blend_1 (params->textureMode[1] & (1 << 17)) +#define tc_add_clocal_1 (params->textureMode[1] & (1 << 18)) +#define tc_add_alocal_1 (params->textureMode[1] & (1 << 19)) +#define tca_sub_clocal_1 (params->textureMode[1] & (1 << 22)) +#define tca_mselect_1 ((params->textureMode[1] >> 23) & 7) +#define tca_reverse_blend_1 (params->textureMode[1] & (1 << 26)) +#define tca_add_clocal_1 (params->textureMode[1] & (1 << 27)) +#define tca_add_alocal_1 (params->textureMode[1] & (1 << 28)) + +#define src_afunc ( (params->alphaMode >> 8) & 0xf) +#define dest_afunc ( (params->alphaMode >> 12) & 0xf) +#define alpha_func ( (params->alphaMode >> 1) & 7) +#define a_ref ( params->alphaMode >> 24) +#define depth_op ( (params->fbzMode >> 5) & 7) +#define dither ( params->fbzMode & FBZ_DITHER) +#define dither2x2 (params->fbzMode & FBZ_DITHER_2x2) diff --git a/src/vid_voodoo_render.c b/src/vid_voodoo_render.c new file mode 100644 index 0000000..641e8e2 --- /dev/null +++ b/src/vid_voodoo_render.c @@ -0,0 +1,1608 @@ +#include +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "thread.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_dither.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" +#include "vid_voodoo_texture.h" + +typedef struct voodoo_state_t +{ + int xstart, xend, xdir; + uint32_t base_r, base_g, base_b, base_a, base_z; + struct + { + int64_t base_s, base_t, base_w; + int lod; + } tmu[2]; + int64_t base_w; + int lod; + int lod_min[2], lod_max[2]; + int dx1, dx2; + int y, yend, ydir; + int32_t dxAB, dxAC, dxBC; + int tex_b[2], tex_g[2], tex_r[2], tex_a[2]; + int tex_s, tex_t; + int clamp_s[2], clamp_t[2]; + + int32_t vertexAx, vertexAy, vertexBx, vertexBy, vertexCx, vertexCy; + + uint32_t *tex[2][LOD_MAX+1]; + int tformat; + + int *tex_w_mask[2]; + int *tex_h_mask[2]; + int *tex_shift[2]; + int *tex_lod[2]; + + uint16_t *fb_mem, *aux_mem; + + int32_t ib, ig, ir, ia; + int32_t z; + + int32_t new_depth; + + int64_t tmu0_s, tmu0_t; + int64_t tmu0_w; + int64_t tmu1_s, tmu1_t; + int64_t tmu1_w; + int64_t w; + + int pixel_count, texel_count; + int x, x2; + + uint32_t w_depth; + + float log_temp; + uint32_t ebp_store; + uint32_t texBaseAddr; + + int lod_frac[2]; +} voodoo_state_t; + +static int voodoo_output = 0; + +static uint8_t logtable[256] = +{ + 0x00,0x01,0x02,0x04,0x05,0x07,0x08,0x09,0x0b,0x0c,0x0e,0x0f,0x10,0x12,0x13,0x15, + 0x16,0x17,0x19,0x1a,0x1b,0x1d,0x1e,0x1f,0x21,0x22,0x23,0x25,0x26,0x27,0x28,0x2a, + 0x2b,0x2c,0x2e,0x2f,0x30,0x31,0x33,0x34,0x35,0x36,0x38,0x39,0x3a,0x3b,0x3d,0x3e, + 0x3f,0x40,0x41,0x43,0x44,0x45,0x46,0x47,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x50,0x51, + 0x52,0x53,0x54,0x55,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x60,0x61,0x62,0x63, + 0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74, + 0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x83,0x84,0x85, + 0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94, + 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa2,0xa3, + 0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xad,0xae,0xaf,0xb0,0xb1,0xb2, + 0xb3,0xb4,0xb5,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbc,0xbd,0xbe,0xbf,0xc0, + 0xc1,0xc2,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xcd, + 0xce,0xcf,0xd0,0xd1,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd6,0xd7,0xd8,0xd9,0xda,0xda, + 0xdb,0xdc,0xdd,0xde,0xde,0xdf,0xe0,0xe1,0xe1,0xe2,0xe3,0xe4,0xe5,0xe5,0xe6,0xe7, + 0xe8,0xe8,0xe9,0xea,0xeb,0xeb,0xec,0xed,0xee,0xef,0xef,0xf0,0xf1,0xf2,0xf2,0xf3, + 0xf4,0xf5,0xf5,0xf6,0xf7,0xf7,0xf8,0xf9,0xfa,0xfa,0xfb,0xfc,0xfd,0xfd,0xfe,0xff +}; + +static inline int fastlog(uint64_t val) +{ + uint64_t oldval = val; + int exp = 63; + int frac; + + if (!val || val & (1ULL << 63)) + return 0x80000000; + + if (!(val & 0xffffffff00000000)) + { + exp -= 32; + val <<= 32; + } + if (!(val & 0xffff000000000000)) + { + exp -= 16; + val <<= 16; + } + if (!(val & 0xff00000000000000)) + { + exp -= 8; + val <<= 8; + } + if (!(val & 0xf000000000000000)) + { + exp -= 4; + val <<= 4; + } + if (!(val & 0xc000000000000000)) + { + exp -= 2; + val <<= 2; + } + if (!(val & 0x8000000000000000)) + { + exp -= 1; + val <<= 1; + } + + if (exp >= 8) + frac = (oldval >> (exp - 8)) & 0xff; + else + frac = (oldval << (8 - exp)) & 0xff; + + return (exp << 8) | logtable[frac]; +} + +static inline int voodoo_fls(uint16_t val) +{ + int num = 0; + +//pclog("fls(%04x) = ", val); + if (!(val & 0xff00)) + { + num += 8; + val <<= 8; + } + if (!(val & 0xf000)) + { + num += 4; + val <<= 4; + } + if (!(val & 0xc000)) + { + num += 2; + val <<= 2; + } + if (!(val & 0x8000)) + { + num += 1; + val <<= 1; + } +//pclog("%i %04x\n", num, val); + return num; +} + +typedef struct voodoo_texture_state_t +{ + int s, t; + int w_mask, h_mask; + int tex_shift; +} voodoo_texture_state_t; + +static inline void tex_read(voodoo_state_t *state, voodoo_texture_state_t *texture_state, int tmu) +{ + uint32_t dat; + + if (texture_state->s & ~texture_state->w_mask) + { + if (state->clamp_s[tmu]) + { + if (texture_state->s < 0) + texture_state->s = 0; + if (texture_state->s > texture_state->w_mask) + texture_state->s = texture_state->w_mask; + } + else + texture_state->s &= texture_state->w_mask; + } + if (texture_state->t & ~texture_state->h_mask) + { + if (state->clamp_t[tmu]) + { + if (texture_state->t < 0) + texture_state->t = 0; + if (texture_state->t > texture_state->h_mask) + texture_state->t = texture_state->h_mask; + } + else + texture_state->t &= texture_state->h_mask; + } + + dat = state->tex[tmu][state->lod][texture_state->s + (texture_state->t << texture_state->tex_shift)]; + + state->tex_b[tmu] = dat & 0xff; + state->tex_g[tmu] = (dat >> 8) & 0xff; + state->tex_r[tmu] = (dat >> 16) & 0xff; + state->tex_a[tmu] = (dat >> 24) & 0xff; +} + +#define LOW4(x) ((x & 0x0f) | ((x & 0x0f) << 4)) +#define HIGH4(x) ((x & 0xf0) | ((x & 0xf0) >> 4)) + +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) +{ + rgba_u dat[4]; + + if (((s | (s + 1)) & ~texture_state->w_mask) || ((t | (t + 1)) & ~texture_state->h_mask)) + { + int c; + for (c = 0; c < 4; c++) + { + int _s = s + (c & 1); + int _t = t + ((c & 2) >> 1); + + if (_s & ~texture_state->w_mask) + { + if (state->clamp_s[tmu]) + { + if (_s < 0) + _s = 0; + if (_s > texture_state->w_mask) + _s = texture_state->w_mask; + } + else + _s &= texture_state->w_mask; + } + if (_t & ~texture_state->h_mask) + { + if (state->clamp_t[tmu]) + { + if (_t < 0) + _t = 0; + if (_t > texture_state->h_mask) + _t = texture_state->h_mask; + } + else + _t &= texture_state->h_mask; + } + dat[c].u = state->tex[tmu][state->lod][_s + (_t << texture_state->tex_shift)]; + } + } + else + { + dat[0].u = state->tex[tmu][state->lod][s + (t << texture_state->tex_shift)]; + dat[1].u = state->tex[tmu][state->lod][s + 1 + (t << texture_state->tex_shift)]; + dat[2].u = state->tex[tmu][state->lod][s + ((t + 1) << texture_state->tex_shift)]; + dat[3].u = state->tex[tmu][state->lod][s + 1 + ((t + 1) << texture_state->tex_shift)]; + } + + 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; + 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; + 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; + 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; +} + +static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x) +{ + voodoo_texture_state_t texture_state; + int d[4]; + int s, t; + int tex_lod = state->tex_lod[tmu][state->lod]; + + texture_state.w_mask = state->tex_w_mask[tmu][state->lod]; + texture_state.h_mask = state->tex_h_mask[tmu][state->lod]; + texture_state.tex_shift = 8 - tex_lod; + + if (params->tLOD[tmu] & LOD_TMIRROR_S) + { + if (state->tex_s & 0x1000) + state->tex_s = ~state->tex_s; + } + if (params->tLOD[tmu] & LOD_TMIRROR_T) + { + if (state->tex_t & 0x1000) + state->tex_t = ~state->tex_t; + } + + if (voodoo->bilinear_enabled && params->textureMode[tmu] & 6) + { + int _ds, dt; + + state->tex_s -= 1 << (3+tex_lod); + state->tex_t -= 1 << (3+tex_lod); + + s = state->tex_s >> tex_lod; + t = state->tex_t >> tex_lod; + + _ds = s & 0xf; + dt = t & 0xf; + + s >>= 4; + t >>= 4; +//if (x == 80) +//if (voodoo_output) +// pclog("s=%08x t=%08x _ds=%02x _dt=%02x\n", s, t, _ds, dt); + d[0] = (16 - _ds) * (16 - dt); + d[1] = _ds * (16 - dt); + d[2] = (16 - _ds) * dt; + d[3] = _ds * dt; + +// texture_state.s = s; +// texture_state.t = t; + tex_read_4(state, &texture_state, s, t, d, tmu, x); + + +/* 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; + 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; + 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; + 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;*/ +/* state->tex_r = tex_samples[0].r; + state->tex_g = tex_samples[0].g; + state->tex_b = tex_samples[0].b; + state->tex_a = tex_samples[0].a;*/ + } + else + { + // rgba_t tex_samples; + // voodoo_texture_state_t texture_state; +// int s = state->tex_s >> (18+state->lod); +// int t = state->tex_t >> (18+state->lod); + // int s, t; + +// state->tex_s -= 1 << (17+state->lod); +// state->tex_t -= 1 << (17+state->lod); + + s = state->tex_s >> (4+tex_lod); + t = state->tex_t >> (4+tex_lod); + + texture_state.s = s; + texture_state.t = t; + tex_read(state, &texture_state, tmu); + +/* state->tex_r = tex_samples[0].rgba.r; + state->tex_g = tex_samples[0].rgba.g; + state->tex_b = tex_samples[0].rgba.b; + state->tex_a = tex_samples[0].rgba.a;*/ + } +} + +static inline void voodoo_tmu_fetch(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int tmu, int x) +{ + if (params->textureMode[tmu] & 1) + { + int64_t _w = 0; + + if (tmu) + { + if (state->tmu1_w) + _w = (int64_t)((1ULL << 48) / state->tmu1_w); + state->tex_s = (int32_t)(((((state->tmu1_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + state->tex_t = (int32_t)(((((state->tmu1_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + } + else + { + if (state->tmu0_w) + _w = (int64_t)((1ULL << 48) / state->tmu0_w); + state->tex_s = (int32_t)(((((state->tmu0_s + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + state->tex_t = (int32_t)(((((state->tmu0_t + (1 << 13)) >> 14) * _w) + (1 << 29)) >> 30); + } + + state->lod = state->tmu[tmu].lod + (fastlog(_w) - (19 << 8)); + } + else + { + if (tmu) + { + state->tex_s = (int32_t)(state->tmu1_s >> (14+14)); + state->tex_t = (int32_t)(state->tmu1_t >> (14+14)); + } + else + { + state->tex_s = (int32_t)(state->tmu0_s >> (14+14)); + state->tex_t = (int32_t)(state->tmu0_t >> (14+14)); + } + state->lod = state->tmu[tmu].lod; + } + + if (state->lod < state->lod_min[tmu]) + state->lod = state->lod_min[tmu]; + else if (state->lod > state->lod_max[tmu]) + state->lod = state->lod_max[tmu]; + state->lod_frac[tmu] = state->lod & 0xff; + state->lod >>= 8; + + voodoo_get_texture(voodoo, params, state, tmu, x); +} + + +/*Perform texture fetch and blending for both TMUs*/ +static inline void voodoo_tmu_fetch_and_blend(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int x) +{ + int r,g,b,a; + int c_reverse, a_reverse; +// int c_reverse1, a_reverse1; + int factor_r = 0, factor_g = 0, factor_b = 0, factor_a = 0; + + voodoo_tmu_fetch(voodoo, params, state, 1, x); + + if ((params->textureMode[1] & TEXTUREMODE_TRILINEAR) && (state->lod & 1)) + { + c_reverse = tc_reverse_blend; + a_reverse = tca_reverse_blend; + } + else + { + c_reverse = !tc_reverse_blend; + a_reverse = !tca_reverse_blend; + } +/* c_reverse1 = c_reverse; + a_reverse1 = a_reverse;*/ + if (tc_sub_clocal_1) + { + switch (tc_mselect_1) + { + case TC_MSELECT_ZERO: + factor_r = factor_g = factor_b = 0; + break; + case TC_MSELECT_CLOCAL: + factor_r = state->tex_r[1]; + factor_g = state->tex_g[1]; + factor_b = state->tex_b[1]; + break; + case TC_MSELECT_AOTHER: + factor_r = factor_g = factor_b = 0; + break; + case TC_MSELECT_ALOCAL: + factor_r = factor_g = factor_b = state->tex_a[1]; + break; + case TC_MSELECT_DETAIL: + factor_r = (params->detail_bias[1] - state->lod) << params->detail_scale[1]; + if (factor_r > params->detail_max[1]) + factor_r = params->detail_max[1]; + factor_g = factor_b = factor_r; + break; + case TC_MSELECT_LOD_FRAC: + factor_r = factor_g = factor_b = state->lod_frac[1]; + break; + } + if (!c_reverse) + { + r = (-state->tex_r[1] * (factor_r + 1)) >> 8; + g = (-state->tex_g[1] * (factor_g + 1)) >> 8; + b = (-state->tex_b[1] * (factor_b + 1)) >> 8; + } + else + { + r = (-state->tex_r[1] * ((factor_r^0xff) + 1)) >> 8; + g = (-state->tex_g[1] * ((factor_g^0xff) + 1)) >> 8; + b = (-state->tex_b[1] * ((factor_b^0xff) + 1)) >> 8; + } + if (tc_add_clocal_1) + { + r += state->tex_r[1]; + g += state->tex_g[1]; + b += state->tex_b[1]; + } + else if (tc_add_alocal_1) + { + r += state->tex_a[1]; + g += state->tex_a[1]; + b += state->tex_a[1]; + } + state->tex_r[1] = CLAMP(r); + state->tex_g[1] = CLAMP(g); + state->tex_b[1] = CLAMP(b); + } + if (tca_sub_clocal_1) + { + switch (tca_mselect_1) + { + case TCA_MSELECT_ZERO: + factor_a = 0; + break; + case TCA_MSELECT_CLOCAL: + factor_a = state->tex_a[1]; + break; + case TCA_MSELECT_AOTHER: + factor_a = 0; + break; + case TCA_MSELECT_ALOCAL: + factor_a = state->tex_a[1]; + break; + case TCA_MSELECT_DETAIL: + factor_a = (params->detail_bias[1] - state->lod) << params->detail_scale[1]; + if (factor_a > params->detail_max[1]) + factor_a = params->detail_max[1]; + break; + case TCA_MSELECT_LOD_FRAC: + factor_a = state->lod_frac[1]; + break; + } + if (!a_reverse) + a = (-state->tex_a[1] * ((factor_a ^ 0xff) + 1)) >> 8; + else + a = (-state->tex_a[1] * (factor_a + 1)) >> 8; + if (tca_add_clocal_1 || tca_add_alocal_1) + a += state->tex_a[1]; + state->tex_a[1] = CLAMP(a); + } + + + voodoo_tmu_fetch(voodoo, params, state, 0, x); + + if ((params->textureMode[0] & TEXTUREMODE_TRILINEAR) && (state->lod & 1)) + { + c_reverse = tc_reverse_blend; + a_reverse = tca_reverse_blend; + } + else + { + c_reverse = !tc_reverse_blend; + a_reverse = !tca_reverse_blend; + } + + if (!tc_zero_other) + { + r = state->tex_r[1]; + g = state->tex_g[1]; + b = state->tex_b[1]; + } + else + r = g = b = 0; + if (tc_sub_clocal) + { + r -= state->tex_r[0]; + g -= state->tex_g[0]; + b -= state->tex_b[0]; + } + switch (tc_mselect) + { + case TC_MSELECT_ZERO: + factor_r = factor_g = factor_b = 0; + break; + case TC_MSELECT_CLOCAL: + factor_r = state->tex_r[0]; + factor_g = state->tex_g[0]; + factor_b = state->tex_b[0]; + break; + case TC_MSELECT_AOTHER: + factor_r = factor_g = factor_b = state->tex_a[1]; + break; + case TC_MSELECT_ALOCAL: + factor_r = factor_g = factor_b = state->tex_a[0]; + break; + case TC_MSELECT_DETAIL: + factor_r = (params->detail_bias[0] - state->lod) << params->detail_scale[0]; + if (factor_r > params->detail_max[0]) + factor_r = params->detail_max[0]; + factor_g = factor_b = factor_r; + break; + case TC_MSELECT_LOD_FRAC: + factor_r = factor_g = factor_b = state->lod_frac[0]; + break; + } + if (!c_reverse) + { + r = (r * (factor_r + 1)) >> 8; + g = (g * (factor_g + 1)) >> 8; + b = (b * (factor_b + 1)) >> 8; + } + else + { + r = (r * ((factor_r^0xff) + 1)) >> 8; + g = (g * ((factor_g^0xff) + 1)) >> 8; + b = (b * ((factor_b^0xff) + 1)) >> 8; + } + if (tc_add_clocal) + { + r += state->tex_r[0]; + g += state->tex_g[0]; + b += state->tex_b[0]; + } + else if (tc_add_alocal) + { + r += state->tex_a[0]; + g += state->tex_a[0]; + b += state->tex_a[0]; + } + + if (!tca_zero_other) + a = state->tex_a[1]; + else + a = 0; + if (tca_sub_clocal) + a -= state->tex_a[0]; + switch (tca_mselect) + { + case TCA_MSELECT_ZERO: + factor_a = 0; + break; + case TCA_MSELECT_CLOCAL: + factor_a = state->tex_a[0]; + break; + case TCA_MSELECT_AOTHER: + factor_a = state->tex_a[1]; + break; + case TCA_MSELECT_ALOCAL: + factor_a = state->tex_a[0]; + break; + case TCA_MSELECT_DETAIL: + factor_a = (params->detail_bias[0] - state->lod) << params->detail_scale[0]; + if (factor_a > params->detail_max[0]) + factor_a = params->detail_max[0]; + break; + case TCA_MSELECT_LOD_FRAC: + factor_a = state->lod_frac[0]; + break; + } + if (a_reverse) + a = (a * ((factor_a ^ 0xff) + 1)) >> 8; + else + a = (a * (factor_a + 1)) >> 8; + if (tca_add_clocal || tca_add_alocal) + a += state->tex_a[0]; + + + state->tex_r[0] = CLAMP(r); + state->tex_g[0] = CLAMP(g); + state->tex_b[0] = CLAMP(b); + state->tex_a[0] = CLAMP(a); + + if (tc_invert_output) + { + state->tex_r[0] ^= 0xff; + state->tex_g[0] ^= 0xff; + state->tex_b[0] ^= 0xff; + } + if (tca_invert_output) + state->tex_a[0] ^= 0xff; +} + +#if (defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__) +#include "vid_voodoo_codegen_x86.h" +#elif (defined __amd64__) +#include "vid_voodoo_codegen_x86-64.h" +#else +int voodoo_recomp = 0; +#endif + +static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int ystart, int yend, int odd_even) +{ +/* int rgb_sel = params->fbzColorPath & 3; + int a_sel = (params->fbzColorPath >> 2) & 3; + int cc_localselect = params->fbzColorPath & (1 << 4); + int cca_localselect = (params->fbzColorPath >> 5) & 3; + int cc_localselect_override = params->fbzColorPath & (1 << 7); + int cc_zero_other = params->fbzColorPath & (1 << 8); + int cc_sub_clocal = params->fbzColorPath & (1 << 9); + int cc_mselect = (params->fbzColorPath >> 10) & 7; + int cc_reverse_blend = params->fbzColorPath & (1 << 13); + int cc_add = (params->fbzColorPath >> 14) & 3; + int cc_add_alocal = params->fbzColorPath & (1 << 15); + int cc_invert_output = params->fbzColorPath & (1 << 16); + int cca_zero_other = params->fbzColorPath & (1 << 17); + int cca_sub_clocal = params->fbzColorPath & (1 << 18); + int cca_mselect = (params->fbzColorPath >> 19) & 7; + int cca_reverse_blend = params->fbzColorPath & (1 << 22); + int cca_add = (params->fbzColorPath >> 23) & 3; + int cca_invert_output = params->fbzColorPath & (1 << 25); + int src_afunc = (params->alphaMode >> 8) & 0xf; + int dest_afunc = (params->alphaMode >> 12) & 0xf; + int alpha_func = (params->alphaMode >> 1) & 7; + int a_ref = params->alphaMode >> 24; + int depth_op = (params->fbzMode >> 5) & 7; + int dither = params->fbzMode & FBZ_DITHER;*/ + int texels; + int c; +#ifndef NO_CODEGEN + uint8_t (*voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y); +#endif + int y_diff = SLI_ENABLED ? 2 : 1; + + if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || + (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) + texels = 1; + else + texels = 2; + + state->clamp_s[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPS; + state->clamp_t[0] = params->textureMode[0] & TEXTUREMODE_TCLAMPT; + state->clamp_s[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPS; + state->clamp_t[1] = params->textureMode[1] & TEXTUREMODE_TCLAMPT; +// int last_x; +// 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); + + for (c = 0; c <= LOD_MAX; c++) + { + state->tex[0][c] = &voodoo->texture_cache[0][params->tex_entry[0]].data[texture_offset[c]]; + state->tex[1][c] = &voodoo->texture_cache[1][params->tex_entry[1]].data[texture_offset[c]]; + } + + state->tformat = params->tformat[0]; + + state->tex_w_mask[0] = params->tex_w_mask[0]; + state->tex_h_mask[0] = params->tex_h_mask[0]; + state->tex_shift[0] = params->tex_shift[0]; + state->tex_lod[0] = params->tex_lod[0]; + state->tex_w_mask[1] = params->tex_w_mask[1]; + state->tex_h_mask[1] = params->tex_h_mask[1]; + state->tex_shift[1] = params->tex_shift[1]; + state->tex_lod[1] = params->tex_lod[1]; + + if ((params->fbzMode & 1) && (ystart < params->clipLowY)) + { + int dy = params->clipLowY - ystart; + + state->base_r += params->dRdY*dy; + state->base_g += params->dGdY*dy; + state->base_b += params->dBdY*dy; + state->base_a += params->dAdY*dy; + state->base_z += params->dZdY*dy; + state->tmu[0].base_s += params->tmu[0].dSdY*dy; + state->tmu[0].base_t += params->tmu[0].dTdY*dy; + state->tmu[0].base_w += params->tmu[0].dWdY*dy; + state->tmu[1].base_s += params->tmu[1].dSdY*dy; + state->tmu[1].base_t += params->tmu[1].dTdY*dy; + state->tmu[1].base_w += params->tmu[1].dWdY*dy; + state->base_w += params->dWdY*dy; + state->xstart += state->dx1*dy; + state->xend += state->dx2*dy; + + ystart = params->clipLowY; + } + + if ((params->fbzMode & 1) && (yend >= params->clipHighY)) + yend = params->clipHighY-1; + + state->y = ystart; +// yend--; + + if (SLI_ENABLED) + { + int test_y; + + if (params->fbzMode & (1 << 17)) + test_y = (voodoo->v_disp-1) - state->y; + else + test_y = state->y; + + if ((!(voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && (test_y & 1)) || + ((voodoo->initEnable & INITENABLE_SLI_MASTER_SLAVE) && !(test_y & 1))) + { + state->y++; + + state->base_r += params->dRdY; + state->base_g += params->dGdY; + state->base_b += params->dBdY; + state->base_a += params->dAdY; + state->base_z += params->dZdY; + state->tmu[0].base_s += params->tmu[0].dSdY; + state->tmu[0].base_t += params->tmu[0].dTdY; + state->tmu[0].base_w += params->tmu[0].dWdY; + state->tmu[1].base_s += params->tmu[1].dSdY; + state->tmu[1].base_t += params->tmu[1].dTdY; + state->tmu[1].base_w += params->tmu[1].dWdY; + state->base_w += params->dWdY; + state->xstart += state->dx1; + state->xend += state->dx2; + } + } +#ifndef NO_CODEGEN + if (voodoo->use_recompiler) + voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even); + else + voodoo_draw = NULL; +#endif + + if (voodoo_output) + pclog("dxAB=%08x dxBC=%08x dxAC=%08x\n", state->dxAB, state->dxBC, state->dxAC); +// pclog("Start %i %i\n", ystart, voodoo->fbzMode & (1 << 17)); + + for (; state->y < yend; state->y += y_diff) + { + int x, x2; + int real_y = (state->y << 4) + 8; + int start_x, start_x2; + int dx; + uint16_t *fb_mem, *aux_mem; + + state->ir = state->base_r; + state->ig = state->base_g; + state->ib = state->base_b; + state->ia = state->base_a; + state->z = state->base_z; + state->tmu0_s = state->tmu[0].base_s; + state->tmu0_t = state->tmu[0].base_t; + state->tmu0_w = state->tmu[0].base_w; + state->tmu1_s = state->tmu[1].base_s; + state->tmu1_t = state->tmu[1].base_t; + state->tmu1_w = state->tmu[1].base_w; + state->w = state->base_w; + + x = (state->vertexAx << 12) + ((state->dxAC * (real_y - state->vertexAy)) >> 4); + + if (real_y < state->vertexBy) + x2 = (state->vertexAx << 12) + ((state->dxAB * (real_y - state->vertexAy)) >> 4); + else + x2 = (state->vertexBx << 12) + ((state->dxBC * (real_y - state->vertexBy)) >> 4); + + if (params->fbzMode & (1 << 17)) + real_y = (voodoo->v_disp-1) - (real_y >> 4); + else + real_y >>= 4; + + if (SLI_ENABLED) + { + if (((real_y >> 1) & voodoo->odd_even_mask) != odd_even) + goto next_line; + } + else + { + if ((real_y & voodoo->odd_even_mask) != odd_even) + goto next_line; + } + + start_x = x; + + if (state->xdir > 0) + x2 -= (1 << 16); + else + x -= (1 << 16); + dx = ((x + 0x7000) >> 16) - (((state->vertexAx << 12) + 0x7000) >> 16); + start_x2 = x + 0x7000; + x = (x + 0x7000) >> 16; + x2 = (x2 + 0x7000) >> 16; + + if (voodoo_output) + 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); + + state->ir += (params->dRdX * dx); + state->ig += (params->dGdX * dx); + state->ib += (params->dBdX * dx); + state->ia += (params->dAdX * dx); + state->z += (params->dZdX * dx); + state->tmu0_s += (params->tmu[0].dSdX * dx); + state->tmu0_t += (params->tmu[0].dTdX * dx); + state->tmu0_w += (params->tmu[0].dWdX * dx); + state->tmu1_s += (params->tmu[1].dSdX * dx); + state->tmu1_t += (params->tmu[1].dTdX * dx); + state->tmu1_w += (params->tmu[1].dWdX * dx); + state->w += (params->dWdX * dx); + + if (voodoo_output) + pclog("%08llx %lli %lli\n", state->tmu0_t, state->tmu0_t >> (18+state->lod), (state->tmu0_t + (1 << (17+state->lod))) >> (18+state->lod)); + + if (params->fbzMode & 1) + { + if (state->xdir > 0) + { + if (x < params->clipLeft) + { + int dx = params->clipLeft - x; + + state->ir += params->dRdX*dx; + state->ig += params->dGdX*dx; + state->ib += params->dBdX*dx; + state->ia += params->dAdX*dx; + state->z += params->dZdX*dx; + state->tmu0_s += params->tmu[0].dSdX*dx; + state->tmu0_t += params->tmu[0].dTdX*dx; + state->tmu0_w += params->tmu[0].dWdX*dx; + state->tmu1_s += params->tmu[1].dSdX*dx; + state->tmu1_t += params->tmu[1].dTdX*dx; + state->tmu1_w += params->tmu[1].dWdX*dx; + state->w += params->dWdX*dx; + + x = params->clipLeft; + } + if (x2 >= params->clipRight) + x2 = params->clipRight-1; + } + else + { + if (x >= params->clipRight) + { + int dx = (params->clipRight-1) - x; + + state->ir += params->dRdX*dx; + state->ig += params->dGdX*dx; + state->ib += params->dBdX*dx; + state->ia += params->dAdX*dx; + state->z += params->dZdX*dx; + state->tmu0_s += params->tmu[0].dSdX*dx; + state->tmu0_t += params->tmu[0].dTdX*dx; + state->tmu0_w += params->tmu[0].dWdX*dx; + state->tmu1_s += params->tmu[1].dSdX*dx; + state->tmu1_t += params->tmu[1].dTdX*dx; + state->tmu1_w += params->tmu[1].dWdX*dx; + state->w += params->dWdX*dx; + + x = params->clipRight-1; + } + if (x2 < params->clipLeft) + x2 = params->clipLeft; + } + } + + if (x2 < x && state->xdir > 0) + goto next_line; + if (x2 > x && state->xdir < 0) + goto next_line; + + if (SLI_ENABLED) + { + state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + ((real_y >> 1) * voodoo->row_width)]; + state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + ((real_y >> 1) * voodoo->row_width)) & voodoo->fb_mask]; + } + else + { + state->fb_mem = fb_mem = (uint16_t *)&voodoo->fb_mem[params->draw_offset + (real_y * voodoo->row_width)]; + state->aux_mem = aux_mem = (uint16_t *)&voodoo->fb_mem[(params->aux_offset + (real_y * voodoo->row_width)) & voodoo->fb_mask]; + } + + if (voodoo_output) + 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); + + state->pixel_count = 0; + state->texel_count = 0; + state->x = x; + state->x2 = x2; +#ifndef NO_CODEGEN + if (voodoo->use_recompiler) + { + voodoo_draw(state, params, x, real_y); + } + else +#endif + do + { + start_x = x; + state->x = x; + voodoo->pixel_count[odd_even]++; + voodoo->texel_count[odd_even] += texels; + voodoo->fbiPixelsIn++; + + if (voodoo_output) + pclog(" X=%03i T=%08x\n", x, state->tmu0_t); +// if (voodoo->fbzMode & FBZ_RGB_WMASK) + { + int update = 1; + uint8_t cother_r, cother_g, cother_b, aother; + uint8_t clocal_r, clocal_g, clocal_b, alocal; + int src_r = 0, src_g = 0, src_b = 0, src_a = 0; + int msel_r, msel_g, msel_b, msel_a; + uint8_t dest_r, dest_g, dest_b, dest_a; + uint16_t dat; + int sel; + int32_t new_depth, w_depth; + + if (state->w & 0xffff00000000) + w_depth = 0; + else if (!(state->w & 0xffff0000)) + w_depth = 0xf001; + else + { + int exp = voodoo_fls((uint16_t)((uint32_t)state->w >> 16)); + int mant = ((~(uint32_t)state->w >> (19 - exp))) & 0xfff; + w_depth = (exp << 12) + mant + 1; + if (w_depth > 0xffff) + w_depth = 0xffff; + } + +// w_depth = CLAMP16(w_depth); + + if (params->fbzMode & FBZ_W_BUFFER) + new_depth = w_depth; + else + new_depth = CLAMP16(state->z >> 12); + + if (params->fbzMode & FBZ_DEPTH_BIAS) + new_depth = CLAMP16(new_depth + (int16_t)params->zaColor); + + if (params->fbzMode & FBZ_DEPTH_ENABLE) + { + uint16_t old_depth = aux_mem[x]; + + DEPTH_TEST((params->fbzMode & FBZ_DEPTH_SOURCE) ? (params->zaColor & 0xffff) : new_depth); + } + + dat = fb_mem[x]; + dest_r = (dat >> 8) & 0xf8; + dest_g = (dat >> 3) & 0xfc; + dest_b = (dat << 3) & 0xf8; + dest_r |= (dest_r >> 5); + dest_g |= (dest_g >> 6); + dest_b |= (dest_b >> 5); + dest_a = 0xff; + + if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) + { + if ((params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL || !voodoo->dual_tmus) + { + /*TMU0 only sampling local colour or only one TMU, only sample TMU0*/ + voodoo_tmu_fetch(voodoo, params, state, 0, x); + } + else if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH) + { + /*TMU0 in pass-through mode, only sample TMU1*/ + voodoo_tmu_fetch(voodoo, params, state, 1, x); + + state->tex_r[0] = state->tex_r[1]; + state->tex_g[0] = state->tex_g[1]; + state->tex_b[0] = state->tex_b[1]; + state->tex_a[0] = state->tex_a[1]; + } + else + { + voodoo_tmu_fetch_and_blend(voodoo, params, state, x); + } + + if ((params->fbzMode & FBZ_CHROMAKEY) && + state->tex_r[0] == params->chromaKey_r && + state->tex_g[0] == params->chromaKey_g && + state->tex_b[0] == params->chromaKey_b) + { + voodoo->fbiChromaFail++; + goto skip_pixel; + } + } + + if (voodoo->trexInit1[0] & (1 << 18)) + { + state->tex_r[0] = state->tex_g[0] = 0; + state->tex_b[0] = voodoo->tmuConfig; + } + + if (cc_localselect_override) + sel = (state->tex_a[0] & 0x80) ? 1 : 0; + else + sel = cc_localselect; + + if (sel) + { + clocal_r = (params->color0 >> 16) & 0xff; + clocal_g = (params->color0 >> 8) & 0xff; + clocal_b = params->color0 & 0xff; + } + else + { + clocal_r = CLAMP(state->ir >> 12); + clocal_g = CLAMP(state->ig >> 12); + clocal_b = CLAMP(state->ib >> 12); + } + + switch (_rgb_sel) + { + case CC_LOCALSELECT_ITER_RGB: /*Iterated RGB*/ + cother_r = CLAMP(state->ir >> 12); + cother_g = CLAMP(state->ig >> 12); + cother_b = CLAMP(state->ib >> 12); + break; + + case CC_LOCALSELECT_TEX: /*TREX Color Output*/ + cother_r = state->tex_r[0]; + cother_g = state->tex_g[0]; + cother_b = state->tex_b[0]; + break; + + case CC_LOCALSELECT_COLOR1: /*Color1 RGB*/ + cother_r = (params->color1 >> 16) & 0xff; + cother_g = (params->color1 >> 8) & 0xff; + cother_b = params->color1 & 0xff; + break; + + case CC_LOCALSELECT_LFB: /*Linear Frame Buffer*/ + cother_r = src_r; + cother_g = src_g; + cother_b = src_b; + break; + } + + switch (cca_localselect) + { + case CCA_LOCALSELECT_ITER_A: + alocal = CLAMP(state->ia >> 12); + break; + + case CCA_LOCALSELECT_COLOR0: + alocal = (params->color0 >> 24) & 0xff; + break; + + case CCA_LOCALSELECT_ITER_Z: + alocal = CLAMP(state->z >> 20); + break; + + default: + fatal("Bad cca_localselect %i\n", cca_localselect); + alocal = 0xff; + break; + } + + switch (a_sel) + { + case A_SEL_ITER_A: + aother = CLAMP(state->ia >> 12); + break; + case A_SEL_TEX: + aother = state->tex_a[0]; + break; + case A_SEL_COLOR1: + aother = (params->color1 >> 24) & 0xff; + break; + default: + fatal("Bad a_sel %i\n", a_sel); + aother = 0; + break; + } + + if (cc_zero_other) + { + src_r = 0; + src_g = 0; + src_b = 0; + } + else + { + src_r = cother_r; + src_g = cother_g; + src_b = cother_b; + } + + if (cca_zero_other) + src_a = 0; + else + src_a = aother; + + if (cc_sub_clocal) + { + src_r -= clocal_r; + src_g -= clocal_g; + src_b -= clocal_b; + } + + if (cca_sub_clocal) + src_a -= alocal; + + switch (cc_mselect) + { + case CC_MSELECT_ZERO: + msel_r = 0; + msel_g = 0; + msel_b = 0; + break; + case CC_MSELECT_CLOCAL: + msel_r = clocal_r; + msel_g = clocal_g; + msel_b = clocal_b; + break; + case CC_MSELECT_AOTHER: + msel_r = aother; + msel_g = aother; + msel_b = aother; + break; + case CC_MSELECT_ALOCAL: + msel_r = alocal; + msel_g = alocal; + msel_b = alocal; + break; + case CC_MSELECT_TEX: + msel_r = state->tex_a[0]; + msel_g = state->tex_a[0]; + msel_b = state->tex_a[0]; + break; + case CC_MSELECT_TEXRGB: + msel_r = state->tex_r[0]; + msel_g = state->tex_g[0]; + msel_b = state->tex_b[0]; + break; + + default: + fatal("Bad cc_mselect %i\n", cc_mselect); + msel_r = 0; + msel_g = 0; + msel_b = 0; + break; + } + + switch (cca_mselect) + { + case CCA_MSELECT_ZERO: + msel_a = 0; + break; + case CCA_MSELECT_ALOCAL: + msel_a = alocal; + break; + case CCA_MSELECT_AOTHER: + msel_a = aother; + break; + case CCA_MSELECT_ALOCAL2: + msel_a = alocal; + break; + case CCA_MSELECT_TEX: + msel_a = state->tex_a[0]; + break; + + default: + fatal("Bad cca_mselect %i\n", cca_mselect); + msel_a = 0; + break; + } + + if (!cc_reverse_blend) + { + msel_r ^= 0xff; + msel_g ^= 0xff; + msel_b ^= 0xff; + } + msel_r++; + msel_g++; + msel_b++; + + if (!cca_reverse_blend) + msel_a ^= 0xff; + msel_a++; + + src_r = (src_r * msel_r) >> 8; + src_g = (src_g * msel_g) >> 8; + src_b = (src_b * msel_b) >> 8; + src_a = (src_a * msel_a) >> 8; + + switch (cc_add) + { + case CC_ADD_CLOCAL: + src_r += clocal_r; + src_g += clocal_g; + src_b += clocal_b; + break; + case CC_ADD_ALOCAL: + src_r += alocal; + src_g += alocal; + src_b += alocal; + break; + case 0: + break; + default: + fatal("Bad cc_add %i\n", cc_add); + } + + if (cca_add) + src_a += alocal; + + src_r = CLAMP(src_r); + src_g = CLAMP(src_g); + src_b = CLAMP(src_b); + src_a = CLAMP(src_a); + + if (cc_invert_output) + { + src_r ^= 0xff; + src_g ^= 0xff; + src_b ^= 0xff; + } + if (cca_invert_output) + src_a ^= 0xff; + + if (params->fogMode & FOG_ENABLE) + APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w); + + if (params->alphaMode & 1) + ALPHA_TEST(src_a); + + if (params->alphaMode & (1 << 4)) + ALPHA_BLEND(src_r, src_g, src_b, src_a); + + if (update) + { + if (dither) + { + if (dither2x2) + { + src_r = dither_rb2x2[src_r][real_y & 1][x & 1]; + src_g = dither_g2x2[src_g][real_y & 1][x & 1]; + src_b = dither_rb2x2[src_b][real_y & 1][x & 1]; + } + else + { + src_r = dither_rb[src_r][real_y & 3][x & 3]; + src_g = dither_g[src_g][real_y & 3][x & 3]; + src_b = dither_rb[src_b][real_y & 3][x & 3]; + } + } + else + { + src_r >>= 3; + src_g >>= 2; + src_b >>= 3; + } + + if (params->fbzMode & FBZ_RGB_WMASK) + fb_mem[x] = src_b | (src_g << 5) | (src_r << 11); + + if ((params->fbzMode & (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) == (FBZ_DEPTH_WMASK | FBZ_DEPTH_ENABLE)) + aux_mem[x] = new_depth; + } + } + voodoo_output &= ~2; + voodoo->fbiPixelsOut++; +skip_pixel: + if (state->xdir > 0) + { + state->ir += params->dRdX; + state->ig += params->dGdX; + state->ib += params->dBdX; + state->ia += params->dAdX; + state->z += params->dZdX; + state->tmu0_s += params->tmu[0].dSdX; + state->tmu0_t += params->tmu[0].dTdX; + state->tmu0_w += params->tmu[0].dWdX; + state->tmu1_s += params->tmu[1].dSdX; + state->tmu1_t += params->tmu[1].dTdX; + state->tmu1_w += params->tmu[1].dWdX; + state->w += params->dWdX; + } + else + { + state->ir -= params->dRdX; + state->ig -= params->dGdX; + state->ib -= params->dBdX; + state->ia -= params->dAdX; + state->z -= params->dZdX; + state->tmu0_s -= params->tmu[0].dSdX; + state->tmu0_t -= params->tmu[0].dTdX; + state->tmu0_w -= params->tmu[0].dWdX; + state->tmu1_s -= params->tmu[1].dSdX; + state->tmu1_t -= params->tmu[1].dTdX; + state->tmu1_w -= params->tmu[1].dWdX; + state->w -= params->dWdX; + } + + x += state->xdir; + } while (start_x != x2); + + voodoo->pixel_count[odd_even] += state->pixel_count; + voodoo->texel_count[odd_even] += state->texel_count; + voodoo->fbiPixelsIn += state->pixel_count; + + if (voodoo->params.draw_offset == voodoo->params.front_offset) + voodoo->dirty_line[real_y >> 1] = 1; +next_line: + if (SLI_ENABLED) + { + state->base_r += params->dRdY; + state->base_g += params->dGdY; + state->base_b += params->dBdY; + state->base_a += params->dAdY; + state->base_z += params->dZdY; + state->tmu[0].base_s += params->tmu[0].dSdY; + state->tmu[0].base_t += params->tmu[0].dTdY; + state->tmu[0].base_w += params->tmu[0].dWdY; + state->tmu[1].base_s += params->tmu[1].dSdY; + state->tmu[1].base_t += params->tmu[1].dTdY; + state->tmu[1].base_w += params->tmu[1].dWdY; + state->base_w += params->dWdY; + state->xstart += state->dx1; + state->xend += state->dx2; + } + state->base_r += params->dRdY; + state->base_g += params->dGdY; + state->base_b += params->dBdY; + state->base_a += params->dAdY; + state->base_z += params->dZdY; + state->tmu[0].base_s += params->tmu[0].dSdY; + state->tmu[0].base_t += params->tmu[0].dTdY; + state->tmu[0].base_w += params->tmu[0].dWdY; + state->tmu[1].base_s += params->tmu[1].dSdY; + state->tmu[1].base_t += params->tmu[1].dTdY; + state->tmu[1].base_w += params->tmu[1].dWdY; + state->base_w += params->dWdY; + state->xstart += state->dx1; + state->xend += state->dx2; + } + + voodoo->texture_cache[0][params->tex_entry[0]].refcount_r[odd_even]++; + voodoo->texture_cache[1][params->tex_entry[1]].refcount_r[odd_even]++; +} + +void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_even) +{ + voodoo_state_t state; + int vertexAy_adjusted; + int vertexCy_adjusted; + int dx, dy; + + uint64_t tempdx, tempdy; + uint64_t tempLOD; + int LOD; + int lodbias; + + voodoo->tri_count++; + + dx = 8 - (params->vertexAx & 0xf); + if ((params->vertexAx & 0xf) > 8) + dx += 16; + dy = 8 - (params->vertexAy & 0xf); + if ((params->vertexAy & 0xf) > 8) + dy += 16; + +/* 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, + (float)params->vertexBx / 16.0, (float)params->vertexBy / 16.0, + (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0, + (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat[0] : 0, + (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);*/ + + state.base_r = params->startR; + state.base_g = params->startG; + state.base_b = params->startB; + state.base_a = params->startA; + state.base_z = params->startZ; + state.tmu[0].base_s = params->tmu[0].startS; + state.tmu[0].base_t = params->tmu[0].startT; + state.tmu[0].base_w = params->tmu[0].startW; + state.tmu[1].base_s = params->tmu[1].startS; + state.tmu[1].base_t = params->tmu[1].startT; + state.tmu[1].base_w = params->tmu[1].startW; + state.base_w = params->startW; + + if (params->fbzColorPath & FBZ_PARAM_ADJUST) + { + state.base_r += (dx*params->dRdX + dy*params->dRdY) >> 4; + state.base_g += (dx*params->dGdX + dy*params->dGdY) >> 4; + state.base_b += (dx*params->dBdX + dy*params->dBdY) >> 4; + state.base_a += (dx*params->dAdX + dy*params->dAdY) >> 4; + state.base_z += (dx*params->dZdX + dy*params->dZdY) >> 4; + state.tmu[0].base_s += (dx*params->tmu[0].dSdX + dy*params->tmu[0].dSdY) >> 4; + state.tmu[0].base_t += (dx*params->tmu[0].dTdX + dy*params->tmu[0].dTdY) >> 4; + state.tmu[0].base_w += (dx*params->tmu[0].dWdX + dy*params->tmu[0].dWdY) >> 4; + state.tmu[1].base_s += (dx*params->tmu[1].dSdX + dy*params->tmu[1].dSdY) >> 4; + state.tmu[1].base_t += (dx*params->tmu[1].dTdX + dy*params->tmu[1].dTdY) >> 4; + state.tmu[1].base_w += (dx*params->tmu[1].dWdX + dy*params->tmu[1].dWdY) >> 4; + state.base_w += (dx*params->dWdX + dy*params->dWdY) >> 4; + } + + tris++; + + state.vertexAy = params->vertexAy & ~0xffff0000; + if (state.vertexAy & 0x8000) + state.vertexAy |= 0xffff0000; + state.vertexBy = params->vertexBy & ~0xffff0000; + if (state.vertexBy & 0x8000) + state.vertexBy |= 0xffff0000; + state.vertexCy = params->vertexCy & ~0xffff0000; + if (state.vertexCy & 0x8000) + state.vertexCy |= 0xffff0000; + + state.vertexAx = params->vertexAx & ~0xffff0000; + if (state.vertexAx & 0x8000) + state.vertexAx |= 0xffff0000; + state.vertexBx = params->vertexBx & ~0xffff0000; + if (state.vertexBx & 0x8000) + state.vertexBx |= 0xffff0000; + state.vertexCx = params->vertexCx & ~0xffff0000; + if (state.vertexCx & 0x8000) + state.vertexCx |= 0xffff0000; + + vertexAy_adjusted = (state.vertexAy+7) >> 4; + vertexCy_adjusted = (state.vertexCy+7) >> 4; + + if (state.vertexBy - state.vertexAy) + state.dxAB = (int)((((int64_t)state.vertexBx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexBy - state.vertexAy); + else + state.dxAB = 0; + if (state.vertexCy - state.vertexAy) + state.dxAC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexAx << 12)) << 4) / (int)(state.vertexCy - state.vertexAy); + else + state.dxAC = 0; + if (state.vertexCy - state.vertexBy) + state.dxBC = (int)((((int64_t)state.vertexCx << 12) - ((int64_t)state.vertexBx << 12)) << 4) / (int)(state.vertexCy - state.vertexBy); + else + state.dxBC = 0; + + state.lod_min[0] = (params->tLOD[0] & 0x3f) << 6; + state.lod_max[0] = ((params->tLOD[0] >> 6) & 0x3f) << 6; + if (state.lod_max[0] > 0x800) + state.lod_max[0] = 0x800; + state.lod_min[1] = (params->tLOD[1] & 0x3f) << 6; + state.lod_max[1] = ((params->tLOD[1] >> 6) & 0x3f) << 6; + if (state.lod_max[1] > 0x800) + state.lod_max[1] = 0x800; + + state.xstart = state.xend = state.vertexAx << 8; + state.xdir = params->sign ? -1 : 1; + + state.y = (state.vertexAy + 8) >> 4; + state.ydir = 1; + + + tempdx = (params->tmu[0].dSdX >> 14) * (params->tmu[0].dSdX >> 14) + (params->tmu[0].dTdX >> 14) * (params->tmu[0].dTdX >> 14); + tempdy = (params->tmu[0].dSdY >> 14) * (params->tmu[0].dSdY >> 14) + (params->tmu[0].dTdY >> 14) * (params->tmu[0].dTdY >> 14); + + if (tempdx > tempdy) + tempLOD = tempdx; + else + tempLOD = tempdy; + + LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256); + LOD >>= 2; + + lodbias = (params->tLOD[0] >> 12) & 0x3f; + if (lodbias & 0x20) + lodbias |= ~0x3f; + state.tmu[0].lod = LOD + (lodbias << 6); + + + tempdx = (params->tmu[1].dSdX >> 14) * (params->tmu[1].dSdX >> 14) + (params->tmu[1].dTdX >> 14) * (params->tmu[1].dTdX >> 14); + tempdy = (params->tmu[1].dSdY >> 14) * (params->tmu[1].dSdY >> 14) + (params->tmu[1].dTdY >> 14) * (params->tmu[1].dTdY >> 14); + + if (tempdx > tempdy) + tempLOD = tempdx; + else + tempLOD = tempdy; + + LOD = (int)(log2((double)tempLOD / (double)(1ULL << 36)) * 256); + LOD >>= 2; + + lodbias = (params->tLOD[1] >> 12) & 0x3f; + if (lodbias & 0x20) + lodbias |= ~0x3f; + state.tmu[1].lod = LOD + (lodbias << 6); + + + voodoo_half_triangle(voodoo, params, &state, vertexAy_adjusted, vertexCy_adjusted, odd_even); +} + + +static void render_thread(void *param, int odd_even) +{ + voodoo_t *voodoo = (voodoo_t *)param; + + while (1) + { + thread_set_event(voodoo->render_not_full_event[odd_even]); + thread_wait_event(voodoo->wake_render_thread[odd_even], -1); + thread_reset_event(voodoo->wake_render_thread[odd_even]); + voodoo->render_voodoo_busy[odd_even] = 1; + + while (!(odd_even ? PARAM_EMPTY_2 : PARAM_EMPTY_1)) + { + uint64_t start_time = timer_read(); + uint64_t end_time; + voodoo_params_t *params = &voodoo->params_buffer[voodoo->params_read_idx[odd_even] & PARAM_MASK]; + + voodoo_triangle(voodoo, params, odd_even); + + voodoo->params_read_idx[odd_even]++; + + if ((odd_even ? PARAM_ENTRIES_2 : PARAM_ENTRIES_1) > (PARAM_SIZE - 10)) + thread_set_event(voodoo->render_not_full_event[odd_even]); + + end_time = timer_read(); + voodoo->render_time[odd_even] += end_time - start_time; + } + + voodoo->render_voodoo_busy[odd_even] = 0; + } +} + +void voodoo_render_thread_1(void *param) +{ + render_thread(param, 0); +} +void voodoo_render_thread_2(void *param) +{ + render_thread(param, 1); +} + +void voodoo_queue_triangle(voodoo_t *voodoo, voodoo_params_t *params) +{ + voodoo_params_t *params_new = &voodoo->params_buffer[voodoo->params_write_idx & PARAM_MASK]; + + while (PARAM_FULL_1 || (voodoo->render_threads == 2 && PARAM_FULL_2)) + { + thread_reset_event(voodoo->render_not_full_event[0]); + if (voodoo->render_threads == 2) + thread_reset_event(voodoo->render_not_full_event[1]); + if (PARAM_FULL_1) + { + thread_wait_event(voodoo->render_not_full_event[0], -1); /*Wait for room in ringbuffer*/ + } + if (voodoo->render_threads == 2 && PARAM_FULL_2) + { + thread_wait_event(voodoo->render_not_full_event[1], -1); /*Wait for room in ringbuffer*/ + } + } + + voodoo_use_texture(voodoo, params, 0); + if (voodoo->dual_tmus) + voodoo_use_texture(voodoo, params, 1); + + memcpy(params_new, params, sizeof(voodoo_params_t)); + + voodoo->params_write_idx++; + + if (PARAM_ENTRIES_1 < 4 || (voodoo->render_threads == 2 && PARAM_ENTRIES_2 < 4)) + voodoo_wake_render_thread(voodoo); +} diff --git a/src/vid_voodoo_render.h b/src/vid_voodoo_render.h new file mode 100644 index 0000000..ec8a551 --- /dev/null +++ b/src/vid_voodoo_render.h @@ -0,0 +1,324 @@ +#if !(defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__) +#define NO_CODEGEN +#endif + +#ifndef NO_CODEGEN +void voodoo_codegen_init(voodoo_t *voodoo); +void voodoo_codegen_close(voodoo_t *voodoo); +#endif + +#define DEPTH_TEST(comp_depth) \ + do \ + { \ + switch (depth_op) \ + { \ + case DEPTHOP_NEVER: \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + case DEPTHOP_LESSTHAN: \ + if (!(comp_depth < old_depth)) \ + { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_EQUAL: \ + if (!(comp_depth == old_depth)) \ + { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_LESSTHANEQUAL: \ + if (!(comp_depth <= old_depth)) \ + { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_GREATERTHAN: \ + if (!(comp_depth > old_depth)) \ + { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_NOTEQUAL: \ + if (!(comp_depth != old_depth)) \ + { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_GREATERTHANEQUAL: \ + if (!(comp_depth >= old_depth)) \ + { \ + voodoo->fbiZFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case DEPTHOP_ALWAYS: \ + break; \ + } \ + } while (0) + +#define APPLY_FOG(src_r, src_g, src_b, z, ia, w) \ + do \ + { \ + if (params->fogMode & FOG_CONSTANT) \ + { \ + src_r += params->fogColor.r; \ + src_g += params->fogColor.g; \ + src_b += params->fogColor.b; \ + } \ + else \ + { \ + int fog_r, fog_g, fog_b, fog_a = 0; \ + int fog_idx; \ + \ + if (!(params->fogMode & FOG_ADD)) \ + { \ + fog_r = params->fogColor.r; \ + fog_g = params->fogColor.g; \ + fog_b = params->fogColor.b; \ + } \ + else \ + fog_r = fog_g = fog_b = 0; \ + \ + if (!(params->fogMode & FOG_MULT)) \ + { \ + fog_r -= src_r; \ + fog_g -= src_g; \ + fog_b -= src_b; \ + } \ + \ + switch (params->fogMode & (FOG_Z|FOG_ALPHA)) \ + { \ + case 0: \ + fog_idx = (w_depth >> 10) & 0x3f; \ + \ + fog_a = params->fogTable[fog_idx].fog; \ + fog_a += (params->fogTable[fog_idx].dfog * ((w_depth >> 2) & 0xff)) >> 10; \ + break; \ + case FOG_Z: \ + fog_a = (z >> 20) & 0xff; \ + break; \ + case FOG_ALPHA: \ + fog_a = CLAMP(ia >> 12); \ + break; \ + case FOG_W: \ + fog_a = CLAMP((w >> 32) & 0xff); \ + break; \ + } \ + fog_a++; \ + \ + fog_r = (fog_r * fog_a) >> 8; \ + fog_g = (fog_g * fog_a) >> 8; \ + fog_b = (fog_b * fog_a) >> 8; \ + \ + if (params->fogMode & FOG_MULT) \ + { \ + src_r = fog_r; \ + src_g = fog_g; \ + src_b = fog_b; \ + } \ + else \ + { \ + src_r += fog_r; \ + src_g += fog_g; \ + src_b += fog_b; \ + } \ + } \ + \ + src_r = CLAMP(src_r); \ + src_g = CLAMP(src_g); \ + src_b = CLAMP(src_b); \ + } while (0) + +#define ALPHA_TEST(src_a) \ + do \ + { \ + switch (alpha_func) \ + { \ + case AFUNC_NEVER: \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + case AFUNC_LESSTHAN: \ + if (!(src_a < a_ref)) \ + { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_EQUAL: \ + if (!(src_a == a_ref)) \ + { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_LESSTHANEQUAL: \ + if (!(src_a <= a_ref)) \ + { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_GREATERTHAN: \ + if (!(src_a > a_ref)) \ + { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_NOTEQUAL: \ + if (!(src_a != a_ref)) \ + { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_GREATERTHANEQUAL: \ + if (!(src_a >= a_ref)) \ + { \ + voodoo->fbiAFuncFail++; \ + goto skip_pixel; \ + } \ + break; \ + case AFUNC_ALWAYS: \ + break; \ + } \ + } while (0) + +#define ALPHA_BLEND(src_r, src_g, src_b, src_a) \ + do \ + { \ + int _a; \ + int newdest_r = 0, newdest_g = 0, newdest_b = 0; \ + \ + switch (dest_afunc) \ + { \ + case AFUNC_AZERO: \ + newdest_r = newdest_g = newdest_b = 0; \ + break; \ + case AFUNC_ASRC_ALPHA: \ + newdest_r = (dest_r * src_a) / 255; \ + newdest_g = (dest_g * src_a) / 255; \ + newdest_b = (dest_b * src_a) / 255; \ + break; \ + case AFUNC_A_COLOR: \ + newdest_r = (dest_r * src_r) / 255; \ + newdest_g = (dest_g * src_g) / 255; \ + newdest_b = (dest_b * src_b) / 255; \ + break; \ + case AFUNC_ADST_ALPHA: \ + newdest_r = (dest_r * dest_a) / 255; \ + newdest_g = (dest_g * dest_a) / 255; \ + newdest_b = (dest_b * dest_a) / 255; \ + break; \ + case AFUNC_AONE: \ + newdest_r = dest_r; \ + newdest_g = dest_g; \ + newdest_b = dest_b; \ + break; \ + case AFUNC_AOMSRC_ALPHA: \ + newdest_r = (dest_r * (255-src_a)) / 255; \ + newdest_g = (dest_g * (255-src_a)) / 255; \ + newdest_b = (dest_b * (255-src_a)) / 255; \ + break; \ + case AFUNC_AOM_COLOR: \ + newdest_r = (dest_r * (255-src_r)) / 255; \ + newdest_g = (dest_g * (255-src_g)) / 255; \ + newdest_b = (dest_b * (255-src_b)) / 255; \ + break; \ + case AFUNC_AOMDST_ALPHA: \ + newdest_r = (dest_r * (255-dest_a)) / 255; \ + newdest_g = (dest_g * (255-dest_a)) / 255; \ + newdest_b = (dest_b * (255-dest_a)) / 255; \ + break; \ + case AFUNC_ASATURATE: \ + _a = MIN(src_a, 1-dest_a); \ + newdest_r = (dest_r * _a) / 255; \ + newdest_g = (dest_g * _a) / 255; \ + newdest_b = (dest_b * _a) / 255; \ + break; \ + } \ + \ + switch (src_afunc) \ + { \ + case AFUNC_AZERO: \ + src_r = src_g = src_b = 0; \ + break; \ + case AFUNC_ASRC_ALPHA: \ + src_r = (src_r * src_a) / 255; \ + src_g = (src_g * src_a) / 255; \ + src_b = (src_b * src_a) / 255; \ + break; \ + case AFUNC_A_COLOR: \ + src_r = (src_r * dest_r) / 255; \ + src_g = (src_g * dest_g) / 255; \ + src_b = (src_b * dest_b) / 255; \ + break; \ + case AFUNC_ADST_ALPHA: \ + src_r = (src_r * dest_a) / 255; \ + src_g = (src_g * dest_a) / 255; \ + src_b = (src_b * dest_a) / 255; \ + break; \ + case AFUNC_AONE: \ + break; \ + case AFUNC_AOMSRC_ALPHA: \ + src_r = (src_r * (255-src_a)) / 255; \ + src_g = (src_g * (255-src_a)) / 255; \ + src_b = (src_b * (255-src_a)) / 255; \ + break; \ + case AFUNC_AOM_COLOR: \ + src_r = (src_r * (255-dest_r)) / 255; \ + src_g = (src_g * (255-dest_g)) / 255; \ + src_b = (src_b * (255-dest_b)) / 255; \ + break; \ + case AFUNC_AOMDST_ALPHA: \ + src_r = (src_r * (255-dest_a)) / 255; \ + src_g = (src_g * (255-dest_a)) / 255; \ + src_b = (src_b * (255-dest_a)) / 255; \ + break; \ + case AFUNC_ACOLORBEFOREFOG: \ + fatal("AFUNC_ACOLORBEFOREFOG\n"); \ + break; \ + } \ + \ + src_r += newdest_r; \ + src_g += newdest_g; \ + src_b += newdest_b; \ + \ + src_r = CLAMP(src_r); \ + src_g = CLAMP(src_g); \ + src_b = CLAMP(src_b); \ + } while(0) + + + +void voodoo_render_thread_1(void *param); +void voodoo_render_thread_2(void *param); +void voodoo_queue_triangle(voodoo_t *voodoo, voodoo_params_t *params); + +extern int voodoo_recomp; +extern int tris; + +static inline void voodoo_wake_render_thread(voodoo_t *voodoo) +{ + thread_set_event(voodoo->wake_render_thread[0]); /*Wake up render thread if moving from idle*/ + if (voodoo->render_threads == 2) + thread_set_event(voodoo->wake_render_thread[1]); /*Wake up render thread if moving from idle*/ +} + +static inline void voodoo_wait_for_render_thread_idle(voodoo_t *voodoo) +{ + 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])) + { + voodoo_wake_render_thread(voodoo); + if (!PARAM_EMPTY_1 || voodoo->render_voodoo_busy[0]) + thread_wait_event(voodoo->render_not_full_event[0], 1); + if (voodoo->render_threads == 2 && (!PARAM_EMPTY_2 || voodoo->render_voodoo_busy[1])) + thread_wait_event(voodoo->render_not_full_event[1], 1); + } +} diff --git a/src/vid_voodoo_setup.c b/src/vid_voodoo_setup.c new file mode 100644 index 0000000..f3fe076 --- /dev/null +++ b/src/vid_voodoo_setup.c @@ -0,0 +1,215 @@ +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "thread.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" +#include "vid_voodoo_setup.h" + +void voodoo_triangle_setup(voodoo_t *voodoo) +{ + float dxAB, dxBC, dyAB, dyBC; + float area; + int va = 0, vb = 1, vc = 2; + int reverse_cull = 0; + vert_t verts[3]; + + verts[0] = voodoo->verts[0]; + verts[1] = voodoo->verts[1]; + verts[2] = voodoo->verts[2]; + + if (verts[0].sVy < verts[1].sVy) + { + if (verts[1].sVy < verts[2].sVy) + { + /* V1>V0, V2>V1, V2>V1>V0*/ + va = 0; /*OK*/ + vb = 1; + vc = 2; + } + else + { + /* V1>V0, V1>V2*/ + if (verts[0].sVy < verts[2].sVy) + { + /* V1>V0, V1>V2, V2>V0, V1>V2>V0*/ + va = 0; + vb = 2; + vc = 1; + reverse_cull = 1; + } + else + { + /* V1>V0, V1>V2, V0>V2, V1>V0>V2*/ + va = 2; + vb = 0; + vc = 1; + } + } + } + else + { + if (verts[1].sVy < verts[2].sVy) + { + /* V0>V1, V2>V1*/ + if (verts[0].sVy < verts[2].sVy) + { + /* V0>V1, V2>V1, V2>V0, V2>V0>V1*/ + va = 1; + vb = 0; + vc = 2; + reverse_cull = 1; + } + else + { + /* V0>V1, V2>V1, V0>V2, V0>V2>V1*/ + va = 1; + vb = 2; + vc = 0; + } + } + else + { + /*V0>V1>V2*/ + va = 2; + vb = 1; + vc = 0; + reverse_cull = 1; + } + } + + dxAB = verts[va].sVx - verts[vb].sVx; + dxBC = verts[vb].sVx - verts[vc].sVx; + dyAB = verts[va].sVy - verts[vb].sVy; + dyBC = verts[vb].sVy - verts[vc].sVy; + + area = dxAB * dyBC - dxBC * dyAB; + + if (area == 0.0) + { + if ((voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) && + !(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG)) + voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN; + + return; + } + + dxAB /= area; + dxBC /= area; + dyAB /= area; + dyBC /= area; + + if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) + { + int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN; + int sign = (area < 0.0); + + if (!(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG)) + voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN; + + if (reverse_cull) + sign = !sign; + + if (cull_sign && sign) + return; + if (!cull_sign && !sign) + return; + } + + voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(verts[va].sVx * 16.0f) & 0xffff); + voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(verts[va].sVy * 16.0f) & 0xffff); + voodoo->params.vertexBx = (int32_t)(int16_t)((int32_t)(verts[vb].sVx * 16.0f) & 0xffff); + voodoo->params.vertexBy = (int32_t)(int16_t)((int32_t)(verts[vb].sVy * 16.0f) & 0xffff); + voodoo->params.vertexCx = (int32_t)(int16_t)((int32_t)(verts[vc].sVx * 16.0f) & 0xffff); + voodoo->params.vertexCy = (int32_t)(int16_t)((int32_t)(verts[vc].sVy * 16.0f) & 0xffff); + + if (voodoo->params.vertexAy > voodoo->params.vertexBy || voodoo->params.vertexBy > voodoo->params.vertexCy) + fatal("triangle_setup wrong order %d %d %d\n", voodoo->params.vertexAy, voodoo->params.vertexBy, voodoo->params.vertexCy); + + if (voodoo->sSetupMode & SETUPMODE_RGB) + { + voodoo->params.startR = (int32_t)(verts[va].sRed * 4096.0f); + voodoo->params.dRdX = (int32_t)(((verts[va].sRed - verts[vb].sRed) * dyBC - (verts[vb].sRed - verts[vc].sRed) * dyAB) * 4096.0f); + voodoo->params.dRdY = (int32_t)(((verts[vb].sRed - verts[vc].sRed) * dxAB - (verts[va].sRed - verts[vb].sRed) * dxBC) * 4096.0f); + voodoo->params.startG = (int32_t)(verts[va].sGreen * 4096.0f); + voodoo->params.dGdX = (int32_t)(((verts[va].sGreen - verts[vb].sGreen) * dyBC - (verts[vb].sGreen - verts[vc].sGreen) * dyAB) * 4096.0f); + voodoo->params.dGdY = (int32_t)(((verts[vb].sGreen - verts[vc].sGreen) * dxAB - (verts[va].sGreen - verts[vb].sGreen) * dxBC) * 4096.0f); + voodoo->params.startB = (int32_t)(verts[va].sBlue * 4096.0f); + voodoo->params.dBdX = (int32_t)(((verts[va].sBlue - verts[vb].sBlue) * dyBC - (verts[vb].sBlue - verts[vc].sBlue) * dyAB) * 4096.0f); + voodoo->params.dBdY = (int32_t)(((verts[vb].sBlue - verts[vc].sBlue) * dxAB - (verts[va].sBlue - verts[vb].sBlue) * dxBC) * 4096.0f); + } + if (voodoo->sSetupMode & SETUPMODE_ALPHA) + { + voodoo->params.startA = (int32_t)(verts[va].sAlpha * 4096.0f); + voodoo->params.dAdX = (int32_t)(((verts[va].sAlpha - verts[vb].sAlpha) * dyBC - (verts[vb].sAlpha - verts[vc].sAlpha) * dyAB) * 4096.0f); + voodoo->params.dAdY = (int32_t)(((verts[vb].sAlpha - verts[vc].sAlpha) * dxAB - (verts[va].sAlpha - verts[vb].sAlpha) * dxBC) * 4096.0f); + } + if (voodoo->sSetupMode & SETUPMODE_Z) + { + voodoo->params.startZ = (int32_t)(verts[va].sVz * 4096.0f); + voodoo->params.dZdX = (int32_t)(((verts[va].sVz - verts[vb].sVz) * dyBC - (verts[vb].sVz - verts[vc].sVz) * dyAB) * 4096.0f); + voodoo->params.dZdY = (int32_t)(((verts[vb].sVz - verts[vc].sVz) * dxAB - (verts[va].sVz - verts[vb].sVz) * dxBC) * 4096.0f); + } + if (voodoo->sSetupMode & SETUPMODE_Wb) + { + voodoo->params.startW = (int64_t)(verts[va].sWb * 4294967296.0f); + voodoo->params.dWdX = (int64_t)(((verts[va].sWb - verts[vb].sWb) * dyBC - (verts[vb].sWb - verts[vc].sWb) * dyAB) * 4294967296.0f); + voodoo->params.dWdY = (int64_t)(((verts[vb].sWb - verts[vc].sWb) * dxAB - (verts[va].sWb - verts[vb].sWb) * dxBC) * 4294967296.0f); + voodoo->params.tmu[0].startW = voodoo->params.tmu[1].startW = voodoo->params.startW; + voodoo->params.tmu[0].dWdX = voodoo->params.tmu[1].dWdX = voodoo->params.dWdX; + voodoo->params.tmu[0].dWdY = voodoo->params.tmu[1].dWdY = voodoo->params.dWdY; + } + if (voodoo->sSetupMode & SETUPMODE_W0) + { + voodoo->params.tmu[0].startW = (int64_t)(verts[va].sW0 * 4294967296.0f); + voodoo->params.tmu[0].dWdX = (int64_t)(((verts[va].sW0 - verts[vb].sW0) * dyBC - (verts[vb].sW0 - verts[vc].sW0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dWdY = (int64_t)(((verts[vb].sW0 - verts[vc].sW0) * dxAB - (verts[va].sW0 - verts[vb].sW0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startW = voodoo->params.tmu[0].startW; + voodoo->params.tmu[1].dWdX = voodoo->params.tmu[0].dWdX; + voodoo->params.tmu[1].dWdY = voodoo->params.tmu[0].dWdY; + } + if (voodoo->sSetupMode & SETUPMODE_S0_T0) + { + voodoo->params.tmu[0].startS = (int64_t)(verts[va].sS0 * 4294967296.0f); + voodoo->params.tmu[0].dSdX = (int64_t)(((verts[va].sS0 - verts[vb].sS0) * dyBC - (verts[vb].sS0 - verts[vc].sS0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dSdY = (int64_t)(((verts[vb].sS0 - verts[vc].sS0) * dxAB - (verts[va].sS0 - verts[vb].sS0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[0].startT = (int64_t)(verts[va].sT0 * 4294967296.0f); + voodoo->params.tmu[0].dTdX = (int64_t)(((verts[va].sT0 - verts[vb].sT0) * dyBC - (verts[vb].sT0 - verts[vc].sT0) * dyAB) * 4294967296.0f); + voodoo->params.tmu[0].dTdY = (int64_t)(((verts[vb].sT0 - verts[vc].sT0) * dxAB - (verts[va].sT0 - verts[vb].sT0) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startS = voodoo->params.tmu[0].startS; + voodoo->params.tmu[1].dSdX = voodoo->params.tmu[0].dSdX; + voodoo->params.tmu[1].dSdY = voodoo->params.tmu[0].dSdY; + voodoo->params.tmu[1].startT = voodoo->params.tmu[0].startT; + voodoo->params.tmu[1].dTdX = voodoo->params.tmu[0].dTdX; + voodoo->params.tmu[1].dTdY = voodoo->params.tmu[0].dTdY; + } + if (voodoo->sSetupMode & SETUPMODE_W1) + { + voodoo->params.tmu[1].startW = (int64_t)(verts[va].sW1 * 4294967296.0f); + voodoo->params.tmu[1].dWdX = (int64_t)(((verts[va].sW1 - verts[vb].sW1) * dyBC - (verts[vb].sW1 - verts[vc].sW1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dWdY = (int64_t)(((verts[vb].sW1 - verts[vc].sW1) * dxAB - (verts[va].sW1 - verts[vb].sW1) * dxBC) * 4294967296.0f); + } + if (voodoo->sSetupMode & SETUPMODE_S1_T1) + { + voodoo->params.tmu[1].startS = (int64_t)(verts[va].sS1 * 4294967296.0f); + voodoo->params.tmu[1].dSdX = (int64_t)(((verts[va].sS1 - verts[vb].sS1) * dyBC - (verts[vb].sS1 - verts[vc].sS1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dSdY = (int64_t)(((verts[vb].sS1 - verts[vc].sS1) * dxAB - (verts[va].sS1 - verts[vb].sS1) * dxBC) * 4294967296.0f); + voodoo->params.tmu[1].startT = (int64_t)(verts[va].sT1 * 4294967296.0f); + voodoo->params.tmu[1].dTdX = (int64_t)(((verts[va].sT1 - verts[vb].sT1) * dyBC - (verts[vb].sT1 - verts[vc].sT1) * dyAB) * 4294967296.0f); + voodoo->params.tmu[1].dTdY = (int64_t)(((verts[vb].sT1 - verts[vc].sT1) * dxAB - (verts[va].sT1 - verts[vb].sT1) * dxBC) * 4294967296.0f); + } + + voodoo->params.sign = (area < 0.0); + + if (voodoo->ncc_dirty[0]) + voodoo_update_ncc(voodoo, 0); + if (voodoo->ncc_dirty[1]) + voodoo_update_ncc(voodoo, 1); + voodoo->ncc_dirty[0] = voodoo->ncc_dirty[1] = 0; + + voodoo_queue_triangle(voodoo, &voodoo->params); +} diff --git a/src/vid_voodoo_setup.h b/src/vid_voodoo_setup.h new file mode 100644 index 0000000..06d2f8d --- /dev/null +++ b/src/vid_voodoo_setup.h @@ -0,0 +1 @@ +void voodoo_triangle_setup(voodoo_t *voodoo); diff --git a/src/vid_voodoo_texture.c b/src/vid_voodoo_texture.c new file mode 100644 index 0000000..69bcbd3 --- /dev/null +++ b/src/vid_voodoo_texture.c @@ -0,0 +1,564 @@ +#include +#include +#include "ibm.h" +#include "device.h" +#include "mem.h" +#include "thread.h" +#include "video.h" +#include "vid_svga.h" +#include "vid_voodoo.h" +#include "vid_voodoo_common.h" +#include "vid_voodoo_dither.h" +#include "vid_voodoo_regs.h" +#include "vid_voodoo_render.h" +#include "vid_voodoo_texture.h" + +void voodoo_recalc_tex(voodoo_t *voodoo, int tmu) +{ + int aspect = (voodoo->params.tLOD[tmu] >> 21) & 3; + int width = 256, height = 256; + int shift = 8; + int lod; + uint32_t base = voodoo->params.texBaseAddr[tmu]; + uint32_t offset = 0; + int tex_lod = 0; + + if (voodoo->params.tLOD[tmu] & LOD_S_IS_WIDER) + height >>= aspect; + else + { + width >>= aspect; + shift -= aspect; + } + + if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD)) + { + width >>= 1; + height >>= 1; + shift--; + tex_lod++; + if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR) + base = voodoo->params.texBaseAddr1[tmu]; + } + + for (lod = 0; lod <= LOD_MAX+1; lod++) + { + if (!width) + width = 1; + if (!height) + height = 1; + if (shift < 0) + shift = 0; + voodoo->params.tex_base[tmu][lod] = base + offset; + if (voodoo->params.tformat[tmu] & 8) + voodoo->params.tex_end[tmu][lod] = base + offset + (width * height * 2); + else + voodoo->params.tex_end[tmu][lod] = base + offset + (width * height); + voodoo->params.tex_w_mask[tmu][lod] = width - 1; + voodoo->params.tex_w_nmask[tmu][lod] = ~(width - 1); + voodoo->params.tex_h_mask[tmu][lod] = height - 1; + voodoo->params.tex_shift[tmu][lod] = shift; + voodoo->params.tex_lod[tmu][lod] = tex_lod; + + if (!(voodoo->params.tLOD[tmu] & LOD_SPLIT) || ((lod & 1) && (voodoo->params.tLOD[tmu] & LOD_ODD)) || (!(lod & 1) && !(voodoo->params.tLOD[tmu] & LOD_ODD))) + { + if (!(voodoo->params.tLOD[tmu] & LOD_ODD) || lod != 0) + { + if (voodoo->params.tformat[tmu] & 8) + offset += width * height * 2; + else + offset += width * height; + + if (voodoo->params.tLOD[tmu] & LOD_SPLIT) + { + width >>= 2; + height >>= 2; + shift -= 2; + tex_lod += 2; + } + else + { + width >>= 1; + height >>= 1; + shift--; + tex_lod++; + } + + if (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR) + { + switch (tex_lod) + { + case 0: + base = voodoo->params.texBaseAddr[tmu]; + break; + case 1: + base = voodoo->params.texBaseAddr1[tmu]; + break; + case 2: + base = voodoo->params.texBaseAddr2[tmu]; + break; + default: + base = voodoo->params.texBaseAddr38[tmu]; + break; + } + } + } + } + } + + voodoo->params.tex_width[tmu] = width; +} + +#define makergba(r, g, b, a) ((b) | ((g) << 8) | ((r) << 16) | ((a) << 24)) + +void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu) +{ + int c, d; + int lod; + int lod_min, lod_max; + uint32_t addr = 0, addr_end; + uint32_t palette_checksum; + + lod_min = (params->tLOD[tmu] >> 2) & 15; + lod_max = (params->tLOD[tmu] >> 8) & 15; + + if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88) + { + if (voodoo->palette_dirty[tmu]) + { + palette_checksum = 0; + + for (c = 0; c < 256; c++) + palette_checksum ^= voodoo->palette[tmu][c].u; + + voodoo->palette_checksum[tmu] = palette_checksum; + voodoo->palette_dirty[tmu] = 0; + } + else + palette_checksum = voodoo->palette_checksum[tmu]; + } + else + palette_checksum = 0; + + if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)) + addr = params->texBaseAddr1[tmu]; + else + addr = params->texBaseAddr[tmu]; + + /*Try to find texture in cache*/ + for (c = 0; c < TEX_CACHE_MAX; c++) + { + if (voodoo->texture_cache[tmu][c].base == addr && + voodoo->texture_cache[tmu][c].tLOD == (params->tLOD[tmu] & 0xf00fff) && + voodoo->texture_cache[tmu][c].palette_checksum == palette_checksum) + { + params->tex_entry[tmu] = c; + voodoo->texture_cache[tmu][c].refcount++; + return; + } + } + + /*Texture not found, search for unused texture*/ + do + { + for (c = 0; c < TEX_CACHE_MAX; c++) + { + voodoo->texture_last_removed++; + voodoo->texture_last_removed &= (TEX_CACHE_MAX-1); + if (voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[0] && + (voodoo->render_threads == 1 || voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount == voodoo->texture_cache[tmu][voodoo->texture_last_removed].refcount_r[1])) + break; + } + if (c == TEX_CACHE_MAX) + voodoo_wait_for_render_thread_idle(voodoo); + } while (c == TEX_CACHE_MAX); + if (c == TEX_CACHE_MAX) + fatal("Texture cache full!\n"); + + c = voodoo->texture_last_removed; + + + if ((voodoo->params.tLOD[tmu] & LOD_SPLIT) && (voodoo->params.tLOD[tmu] & LOD_ODD) && (voodoo->params.tLOD[tmu] & LOD_TMULTIBASEADDR)) + voodoo->texture_cache[tmu][c].base = params->texBaseAddr1[tmu]; + else + voodoo->texture_cache[tmu][c].base = params->texBaseAddr[tmu]; + voodoo->texture_cache[tmu][c].tLOD = params->tLOD[tmu] & 0xf00fff; + + lod_min = (params->tLOD[tmu] >> 2) & 15; + lod_max = (params->tLOD[tmu] >> 8) & 15; +// 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); + lod_min = MIN(lod_min, 8); + lod_max = MIN(lod_max, 8); + for (lod = lod_min; lod <= lod_max; lod++) + { + uint32_t *base = &voodoo->texture_cache[tmu][c].data[texture_offset[lod]]; + uint32_t tex_addr = params->tex_base[tmu][lod] & voodoo->texture_mask; + int x, y; + int shift = 8 - params->tex_lod[tmu][lod]; + rgba_u *pal; + + //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]); + + + switch (params->tformat[tmu]) + { + case TEX_RGB332: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; + + base[x] = makergba(rgb332[dat].r, rgb332[dat].g, rgb332[dat].b, 0xff); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_Y4I2Q2: + pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; + + base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_A8: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; + + base[x] = makergba(dat, dat, dat, dat); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_I8: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; + + base[x] = makergba(dat, dat, dat, 0xff); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_AI8: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; + + base[x] = makergba((dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0x0f) | ((dat << 4) & 0xf0), (dat & 0xf0) | ((dat >> 4) & 0x0f)); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_PAL8: + pal = voodoo->palette[tmu]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; + + base[x] = makergba(pal[dat].rgba.r, pal[dat].rgba.g, pal[dat].rgba.b, 0xff); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_APAL8: + pal = voodoo->palette[tmu]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint8_t dat = voodoo->tex_mem[tmu][(tex_addr+x) & voodoo->texture_mask]; + + int r = ((pal[dat].rgba.r & 3) << 6) | ((pal[dat].rgba.g & 0xf0) >> 2) | (pal[dat].rgba.r & 3); + int g = ((pal[dat].rgba.g & 0xf) << 4) | ((pal[dat].rgba.b & 0xc0) >> 4) | ((pal[dat].rgba.g & 0xf) >> 2); + int b = ((pal[dat].rgba.b & 0x3f) << 2) | ((pal[dat].rgba.b & 0x30) >> 4); + int a = (pal[dat].rgba.r & 0xfc) | ((pal[dat].rgba.r & 0xc0) >> 6); + + base[x] = makergba(r, g, b, a); + } + tex_addr += (1 << voodoo->params.tex_shift[tmu][lod]); + base += (1 << shift); + } + break; + + case TEX_ARGB8332: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; + + base[x] = makergba(rgb332[dat & 0xff].r, rgb332[dat & 0xff].g, rgb332[dat & 0xff].b, dat >> 8); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); + base += (1 << shift); + } + break; + + case TEX_A8Y4I2Q2: + pal = voodoo->ncc_lookup[tmu][(voodoo->params.textureMode[tmu] & TEXTUREMODE_NCC_SEL) ? 1 : 0]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; + + base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); + base += (1 << shift); + } + break; + + case TEX_R5G6B5: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; + + base[x] = makergba(rgb565[dat].r, rgb565[dat].g, rgb565[dat].b, 0xff); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); + base += (1 << shift); + } + break; + + case TEX_ARGB1555: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; + + base[x] = makergba(argb1555[dat].r, argb1555[dat].g, argb1555[dat].b, argb1555[dat].a); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); + base += (1 << shift); + } + break; + + case TEX_ARGB4444: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; + + base[x] = makergba(argb4444[dat].r, argb4444[dat].g, argb4444[dat].b, argb4444[dat].a); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); + base += (1 << shift); + } + break; + + case TEX_A8I8: + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; + + base[x] = makergba(dat & 0xff, dat & 0xff, dat & 0xff, dat >> 8); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); + base += (1 << shift); + } + break; + + case TEX_APAL88: + pal = voodoo->palette[tmu]; + for (y = 0; y < voodoo->params.tex_h_mask[tmu][lod]+1; y++) + { + for (x = 0; x < voodoo->params.tex_w_mask[tmu][lod]+1; x++) + { + uint16_t dat = *(uint16_t *)&voodoo->tex_mem[tmu][(tex_addr + x*2) & voodoo->texture_mask]; + + base[x] = makergba(pal[dat & 0xff].rgba.r, pal[dat & 0xff].rgba.g, pal[dat & 0xff].rgba.b, dat >> 8); + } + tex_addr += (1 << (voodoo->params.tex_shift[tmu][lod]+1)); + base += (1 << shift); + } + break; + + default: + fatal("Unknown texture format %i\n", params->tformat[tmu]); + } + } + + voodoo->texture_cache[tmu][c].is16 = voodoo->params.tformat[tmu] & 8; + + if (params->tformat[tmu] == TEX_PAL8 || params->tformat[tmu] == TEX_APAL8 || params->tformat[tmu] == TEX_APAL88) + voodoo->texture_cache[tmu][c].palette_checksum = palette_checksum; + else + voodoo->texture_cache[tmu][c].palette_checksum = 0; + + if (lod_min == 0) + { + voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->params.tex_base[tmu][0]; + voodoo->texture_cache[tmu][c].addr_end[0] = voodoo->params.tex_end[tmu][0]; + } + else + voodoo->texture_cache[tmu][c].addr_start[0] = voodoo->texture_cache[tmu][c].addr_end[0] = 0; + + if (lod_min <= 1 && lod_max >= 1) + { + voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->params.tex_base[tmu][1]; + voodoo->texture_cache[tmu][c].addr_end[1] = voodoo->params.tex_end[tmu][1]; + } + else + voodoo->texture_cache[tmu][c].addr_start[1] = voodoo->texture_cache[tmu][c].addr_end[1] = 0; + + if (lod_min <= 2 && lod_max >= 2) + { + voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->params.tex_base[tmu][2]; + voodoo->texture_cache[tmu][c].addr_end[2] = voodoo->params.tex_end[tmu][2]; + } + else + voodoo->texture_cache[tmu][c].addr_start[2] = voodoo->texture_cache[tmu][c].addr_end[2] = 0; + + if (lod_max >= 3) + { + voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->params.tex_base[tmu][(lod_min > 3) ? lod_min : 3]; + voodoo->texture_cache[tmu][c].addr_end[3] = voodoo->params.tex_end[tmu][(lod_max < 8) ? lod_max : 8]; + } + else + voodoo->texture_cache[tmu][c].addr_start[3] = voodoo->texture_cache[tmu][c].addr_end[3] = 0; + + + for (d = 0; d < 4; d++) + { + addr = voodoo->texture_cache[tmu][c].addr_start[d]; + addr_end = voodoo->texture_cache[tmu][c].addr_end[d]; + + if (addr_end != 0) + { + for (; addr <= addr_end; addr += (1 << TEX_DIRTY_SHIFT)) + voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; + } + } + + params->tex_entry[tmu] = c; + voodoo->texture_cache[tmu][c].refcount++; +} + +static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu) +{ + int wait_for_idle = 0; + int c; + + memset(voodoo->texture_present[tmu], 0, sizeof(voodoo->texture_present[0])); +// pclog("Evict %08x %i\n", dirty_addr, sizeof(voodoo->texture_present)); + for (c = 0; c < TEX_CACHE_MAX; c++) + { + if (voodoo->texture_cache[tmu][c].base != -1) + { + int d; + + for (d = 0; d < 4; d++) + { + int addr_start = voodoo->texture_cache[tmu][c].addr_start[d]; + int addr_end = voodoo->texture_cache[tmu][c].addr_end[d]; + + if (addr_end != 0) + { + int addr_start_masked = addr_start & voodoo->texture_mask & ~0x3ff; + int addr_end_masked = ((addr_end & voodoo->texture_mask) + 0x3ff) & ~0x3ff; + + if (addr_end_masked < addr_start_masked) + addr_end_masked = voodoo->texture_mask+1; + if (dirty_addr >= addr_start_masked && dirty_addr < addr_end_masked) + { +// pclog(" Evict texture %i %08x\n", c, voodoo->texture_cache[tmu][c].base); + + if (voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[0] || + (voodoo->render_threads == 2 && voodoo->texture_cache[tmu][c].refcount != voodoo->texture_cache[tmu][c].refcount_r[1])) + wait_for_idle = 1; + + voodoo->texture_cache[tmu][c].base = -1; + } + else + { + for (; addr_start <= addr_end; addr_start += (1 << TEX_DIRTY_SHIFT)) + voodoo->texture_present[tmu][(addr_start & voodoo->texture_mask) >> TEX_DIRTY_SHIFT] = 1; + } + } + } + } + } + if (wait_for_idle) + voodoo_wait_for_render_thread_idle(voodoo); +} + +void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p) +{ + int lod, s, t; + voodoo_t *voodoo = (voodoo_t *)p; + int tmu; + + if (addr & 0x400000) + return; /*TREX != 0*/ + + tmu = (addr & 0x200000) ? 1 : 0; + + if (tmu && !voodoo->dual_tmus) + return; + +// pclog("voodoo_tex_writel : %08X %08X %i\n", addr, val, voodoo->params.tformat); + + lod = (addr >> 17) & 0xf; + t = (addr >> 9) & 0xff; + if (voodoo->params.tformat[tmu] & 8) + s = (addr >> 1) & 0xfe; + else + { + if (voodoo->params.textureMode[tmu] & (1 << 31)) + s = addr & 0xfc; + else + s = (addr >> 1) & 0xfc; + } + + if (lod > LOD_MAX) + return; + +// if (addr >= 0x200000) +// return; + + if (voodoo->params.tformat[tmu] & 8) + addr = voodoo->params.tex_base[tmu][lod] + s*2 + (t << voodoo->params.tex_shift[tmu][lod])*2; + else + addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]); + if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT]) + { +// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT); + flush_texture_cache(voodoo, addr & voodoo->texture_mask, tmu); + } + *(uint32_t *)(&voodoo->tex_mem[tmu][addr & voodoo->texture_mask]) = val; +} diff --git a/src/vid_voodoo_texture.h b/src/vid_voodoo_texture.h new file mode 100644 index 0000000..e744f17 --- /dev/null +++ b/src/vid_voodoo_texture.h @@ -0,0 +1,18 @@ +static const uint32_t texture_offset[LOD_MAX+3] = +{ + 0, + 256*256, + 256*256 + 128*128, + 256*256 + 128*128 + 64*64, + 256*256 + 128*128 + 64*64 + 32*32, + 256*256 + 128*128 + 64*64 + 32*32 + 16*16, + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8, + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4, + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2, + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1, + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2 + 1*1 + 1 +}; + +void voodoo_recalc_tex(voodoo_t *voodoo, int tmu); +void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu); +void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p);