From f6d6f0de9b5fad1ddeacde4d4729130fa8fd1b2d Mon Sep 17 00:00:00 2001 From: TomW Date: Tue, 12 Jan 2016 19:37:01 +0000 Subject: [PATCH] Added 3DFX recompiler for x86-32. 2-4x speedup over previous code. --- src/Makefile.mingw | 4 +- src/Makefile.mingw64 | 10 +- src/vid_voodoo.c | 281 ++- src/vid_voodoo_codegen_x86.h | 3725 ++++++++++++++++++++++++++++++++++ 4 files changed, 3914 insertions(+), 106 deletions(-) create mode 100644 src/vid_voodoo_codegen_x86.h diff --git a/src/Makefile.mingw b/src/Makefile.mingw index a68bb4c..e470a64 100644 --- a/src/Makefile.mingw +++ b/src/Makefile.mingw @@ -2,7 +2,7 @@ VPATH = . dosbox resid-fp CPP = g++.exe CC = gcc.exe WINDRES = windres.exe -CFLAGS = -O3 -march=i686 -fomit-frame-pointer +CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86.o compaq.o config.o cpu.o dac.o \ device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \ @@ -22,7 +22,7 @@ OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \ win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res FMOBJ = dbopl.o -SIDOBJ = convolve.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o +SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o LIBS = -mwindows -lwinmm -lalut -lopenal32 -lddraw -ldinput -ldxguid -ld3d9 -lstdc++ diff --git a/src/Makefile.mingw64 b/src/Makefile.mingw64 index 670f25f..83ef396 100644 --- a/src/Makefile.mingw64 +++ b/src/Makefile.mingw64 @@ -3,21 +3,21 @@ CPP = g++.exe CC = gcc.exe WINDRES = windres.exe CFLAGS = -O3 -fomit-frame-pointer -OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o \ +OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \ codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_pentium.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \ - device.o disc.o disc_fdi.o disc_img.o dma.o fdc.o fdc37c665.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \ + device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o headland.o i430lx.o i430fx.o \ i430vx.o ide.o intel.o intel_flash.o io.o jim.o keyboard.o keyboard_amstrad.o keyboard_at.o \ keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o model.o mouse.o mouse_ps2.o \ mouse_serial.o neat.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \ serial.o sis496.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_cms.o sound_dbopl.o \ - sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_resid.o \ + sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_pssj.o sound_resid.o \ sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \ - soundopenal.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ + soundopenal.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \ vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_ega.o vid_et4000.o \ vid_et4000w32.o vid_et4000w32i.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_mda.o \ vid_olivetti_m24.o vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \ vid_pcjr.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_stg_ramdac.o vid_svga.o \ - vid_svga_render.o vid_tandy.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ + vid_svga_render.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \ vid_vga.o vid_voodoo.o video.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \ win-ddraw-fs.o win-deviceconfig.o win-hdconf.o win-joystick.o win-keyboard.o win-midi.o win-mouse.o \ win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res diff --git a/src/vid_voodoo.c b/src/vid_voodoo.c index 9e5453b..8387c0c 100644 --- a/src/vid_voodoo.c +++ b/src/vid_voodoo.c @@ -1,4 +1,5 @@ #include +#include #include "ibm.h" #include "device.h" #include "mem.h" @@ -32,11 +33,12 @@ typedef union int_float typedef struct rgb_t { - uint8_t r, g, b; + uint8_t b, g, r; + uint8_t pad; } rgb_t; typedef struct rgba8_t { - uint8_t r, g, b, a; + uint8_t b, g, r, a; } rgba8_t; typedef union rgba_u @@ -85,7 +87,7 @@ typedef struct uint32_t val; } fifo_entry_t; -static rgba8_t rgb332[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000]; +static rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], argb4444[0x10000], ai88[0x10000]; typedef struct voodoo_params_t { @@ -95,17 +97,17 @@ typedef struct voodoo_params_t uint32_t startR, startG, startB, startZ, startA; - int32_t dRdX, dGdX, dBdX, dZdX, dAdX; + int32_t dBdX, dGdX, dRdX, dAdX, dZdX; - int32_t dRdY, dGdY, dBdY, dZdY, dAdY; + int32_t dBdY, dGdY, dRdY, dAdY, dZdY; int64_t startW, dWdX, dWdY; struct { - int64_t startS, dSdX, dSdY; - int64_t startT, dTdX, dTdY; - int64_t startW, dWdX, dWdY; + int64_t startS, startT, startW, p1; + int64_t dSdX, dTdX, dWdX, p2; + int64_t dSdY, dTdY, dWdY, p3; } tmu[1]; uint32_t color0, color1; @@ -125,6 +127,7 @@ typedef struct voodoo_params_t uint32_t zaColor; int chromaKey_r, chromaKey_g, chromaKey_b; + uint32_t chromaKey; uint32_t textureMode; uint32_t tLOD; @@ -134,6 +137,7 @@ typedef struct voodoo_params_t uint32_t tex_base[LOD_MAX+1]; int tex_width; int tex_w_mask[LOD_MAX+1]; + int tex_w_nmask[LOD_MAX+1]; int tex_h_mask[LOD_MAX+1]; int tex_shift[LOD_MAX+1]; @@ -282,6 +286,9 @@ typedef struct voodoo_t /* the voodoo adds purple lines for some reason */ uint16_t purpleline[1024]; + + int use_recompiler; + void *codegen_data; } voodoo_t; enum @@ -896,6 +903,7 @@ static void voodoo_recalc_tex(voodoo_t *voodoo) shift = 0; voodoo->params.tex_base[lod] = base; voodoo->params.tex_w_mask[lod] = width - 1; + voodoo->params.tex_w_nmask[lod] = ~(width - 1); voodoo->params.tex_h_mask[lod] = height - 1; voodoo->params.tex_shift[lod] = shift; // pclog("LOD%i base=%08x %i-%i %i,%i wm=%02x hm=%02x sh=%i\n", lod, base, lod_min, lod_max, width, height, voodoo->params.tex_w_mask[lod], voodoo->params.tex_h_mask[lod], voodoo->params.tex_shift[lod]); @@ -928,7 +936,7 @@ typedef struct voodoo_state_t int dx1, dx2; int y, yend, ydir; int32_t dxAB, dxAC, dxBC; - int tex_r, tex_g, tex_b, tex_a; + int tex_b, tex_g, tex_r, tex_a; int tex_s, tex_t; int clamp_s, clamp_t; @@ -943,6 +951,22 @@ typedef struct voodoo_state_t int *tex_w_mask; int *tex_h_mask; int *tex_shift; + + 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 w; + + int pixel_count; + int x, x2; + + uint32_t w_depth; } voodoo_state_t; static int voodoo_output = 0; @@ -1428,7 +1452,7 @@ static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, } \ } while (0) -#define APPLY_FOG(src_r, src_g, src_b) \ +#define APPLY_FOG(src_r, src_g, src_b, z, ia) \ do \ { \ if (params->fogMode & FOG_CONSTANT) \ @@ -1679,6 +1703,13 @@ static inline void voodoo_get_texture(voodoo_t *voodoo, voodoo_params_t *params, #define dither ( params->fbzMode & FBZ_DITHER) #define dither2x2 (params->fbzMode & FBZ_DITHER_2x2) +#if (defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__) +#include "vid_voodoo_codegen_x86.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; @@ -1706,6 +1737,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood int depth_op = (params->fbzMode >> 5) & 7; int dither = params->fbzMode & FBZ_DITHER;*/ int c; + uint8_t (*voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y); state->clamp_s = params->textureMode & TEXTUREMODE_TCLAMPS; state->clamp_t = params->textureMode & TEXTUREMODE_TCLAMPT; @@ -1748,26 +1780,33 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood state->y = ystart; // yend--; + +#ifndef NO_CODEGEN + if (voodoo->use_recompiler) + voodoo_draw = voodoo_get_block(voodoo, params, state, odd_even); +#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++) { - int x, x2;// = state->xstart, x2 = state->xend; + int x, x2; int real_y = (state->y << 4) + 8; int start_x, start_x2; int dx; - int32_t ir = state->base_r; - int32_t ig = state->base_g; - int32_t ib = state->base_b; - int32_t ia = state->base_a; - int32_t z = state->base_z; - int64_t tmu0_s = state->tmu[0].base_s; - int64_t tmu0_t = state->tmu[0].base_t; - int64_t tmu0_w = state->tmu[0].base_w; - int64_t w = state->base_w; 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->w = state->base_w; + x = (state->vertexAx << 12) + ((state->dxAC * (real_y - state->vertexAy)) >> 4); if (real_y < state->vertexBy) @@ -1795,20 +1834,20 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood 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, tmu0_t); + 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); - ir += (params->dRdX * dx); - ig += (params->dGdX * dx); - ib += (params->dBdX * dx); - ia += (params->dAdX * dx); - z += (params->dZdX * dx); - tmu0_s += (params->tmu[0].dSdX * dx); - tmu0_t += (params->tmu[0].dTdX * dx); - tmu0_w += (params->tmu[0].dWdX * dx); - w += (params->dWdX * dx); + 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->w += (params->dWdX * dx); if (voodoo_output) - pclog("%08llx %lli %lli\n", tmu0_t, tmu0_t >> (18+state->lod), (tmu0_t + (1 << 17+state->lod)) >> (18+state->lod)); + 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) { @@ -1818,15 +1857,15 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood { int dx = params->clipLeft - x; - ir += params->dRdX*dx; - ig += params->dGdX*dx; - ib += params->dBdX*dx; - ia += params->dAdX*dx; - z += params->dZdX*dx; - tmu0_s += params->tmu[0].dSdX*dx; - tmu0_t += params->tmu[0].dTdX*dx; - tmu0_w += params->tmu[0].dWdX*dx; - w += params->dWdX*dx; + 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->w += params->dWdX*dx; x = params->clipLeft; } @@ -1839,15 +1878,15 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood { int dx = params->clipRight - x; - ir += params->dRdX*dx; - ig += params->dGdX*dx; - ib += params->dBdX*dx; - ia += params->dAdX*dx; - z += params->dZdX*dx; - tmu0_s += params->tmu[0].dSdX*dx; - tmu0_t += params->tmu[0].dTdX*dx; - tmu0_w += params->tmu[0].dWdX*dx; - w += params->dWdX*dx; + 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->w += params->dWdX*dx; x = params->clipRight; } @@ -1861,19 +1900,30 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood if (x2 > x && state->xdir < 0) goto next_line; - fb_mem = &voodoo->fb_mem[params->draw_offset + (real_y * voodoo->row_width)]; - aux_mem = &voodoo->fb_mem[params->aux_offset + (real_y * voodoo->row_width)]; + state->fb_mem = fb_mem = &voodoo->fb_mem[params->draw_offset + (real_y * voodoo->row_width)]; + state->aux_mem = aux_mem = &voodoo->fb_mem[params->aux_offset + (real_y * voodoo->row_width)]; 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->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; voodoo->pixel_count[odd_even]++; voodoo->fbiPixelsIn++; if (voodoo_output) - pclog(" X=%03i T=%08x\n", x, tmu0_t); + pclog(" X=%03i T=%08x\n", x, state->tmu0_t); // if (voodoo->fbzMode & FBZ_RGB_WMASK) { int update = 1; @@ -1887,14 +1937,14 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood int sel; int32_t new_depth, w_depth; - if (w & 0xffff00000000) + if (state->w & 0xffff00000000) w_depth = 0; - else if (!(w & 0xffff0000)) + else if (!(state->w & 0xffff0000)) w_depth = 0xf001; else { - int exp = fls((uint16_t)((uint32_t)w >> 16)); - int mant = ((~(uint32_t)w >> (19 - exp))) & 0xfff; + int exp = 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; @@ -1905,7 +1955,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood if (params->fbzMode & FBZ_W_BUFFER) new_depth = w_depth; else - new_depth = CLAMP16(z >> 12); + new_depth = CLAMP16(state->z >> 12); if (params->fbzMode & FBZ_DEPTH_ENABLE) { @@ -1928,18 +1978,18 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood if (params->textureMode & 1) { int64_t _w = 0; - if (tmu0_w) - _w = (int64_t)((1ULL << 48) / tmu0_w); + if (state->tmu0_w) + _w = (int64_t)((1ULL << 48) / state->tmu0_w); - state->tex_s = (int32_t)(((tmu0_s >> 14) * _w) >> 30); - state->tex_t = (int32_t)(((tmu0_t >> 14) * _w) >> 30); + state->tex_s = (int32_t)(((state->tmu0_s >> 14) * _w) >> 30); + state->tex_t = (int32_t)(((state->tmu0_t >> 14) * _w) >> 30); // state->lod = state->tmu[0].lod + (int)(log2((double)_w / (double)(1 << 19)) * 256.0); state->lod = state->tmu[0].lod + (fastlog(_w) - (19 << 8)); } else { - state->tex_s = (int32_t)(tmu0_s >> (14+14)); - state->tex_t = (int32_t)(tmu0_t >> (14+14)); + state->tex_s = (int32_t)(state->tmu0_s >> (14+14)); + state->tex_t = (int32_t)(state->tmu0_t >> (14+14)); state->lod = state->tmu[0].lod; } @@ -1980,17 +2030,17 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood } else { - clocal_r = CLAMP(ir >> 12); - clocal_g = CLAMP(ig >> 12); - clocal_b = CLAMP(ib >> 12); + 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(ir >> 12); - cother_g = CLAMP(ig >> 12); - cother_b = CLAMP(ib >> 12); + 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*/ @@ -2015,7 +2065,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood switch (cca_localselect) { case CCA_LOCALSELECT_ITER_A: - alocal = CLAMP(ia >> 12); + alocal = CLAMP(state->ia >> 12); break; case CCA_LOCALSELECT_COLOR0: @@ -2023,7 +2073,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood break; case CCA_LOCALSELECT_ITER_Z: - alocal = CLAMP(z >> 20); + alocal = CLAMP(state->z >> 20); break; default: @@ -2034,7 +2084,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood switch (a_sel) { case A_SEL_ITER_A: - aother = CLAMP(ia >> 12); + aother = CLAMP(state->ia >> 12); break; case A_SEL_TEX: aother = state->tex_a; @@ -2184,7 +2234,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood src_a ^= 0xff; if (params->fogMode & FOG_ENABLE) - APPLY_FOG(src_r, src_g, src_b); + APPLY_FOG(src_r, src_g, src_b, state->z, state->ia); if (params->alphaMode & 1) ALPHA_TEST(src_a); @@ -2227,31 +2277,34 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood skip_pixel: if (state->xdir > 0) { - ir += params->dRdX; - ig += params->dGdX; - ib += params->dBdX; - ia += params->dAdX; - z += params->dZdX; - tmu0_s += params->tmu[0].dSdX; - tmu0_t += params->tmu[0].dTdX; - tmu0_w += params->tmu[0].dWdX; - w += params->dWdX; + 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->w += params->dWdX; } else { - ir -= params->dRdX; - ig -= params->dGdX; - ib -= params->dBdX; - ia -= params->dAdX; - z -= params->dZdX; - tmu0_s -= params->tmu[0].dSdX; - tmu0_t -= params->tmu[0].dTdX; - tmu0_w -= params->tmu[0].dWdX; - w -= params->dWdX; + 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->w -= params->dWdX; } x += state->xdir; } while (start_x != x2); + + voodoo->pixel_count[odd_even] += state->pixel_count; + voodoo->fbiPixelsIn += state->pixel_count; if (voodoo->params.draw_offset == voodoo->params.front_offset) voodoo->dirty_line[real_y] = 1; @@ -2292,9 +2345,10 @@ static void voodoo_triangle(voodoo_t *voodoo, voodoo_params_t *params, int odd_e if ((params->vertexAy & 0xf) > 8) dy += 16; -/* pclog("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i\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, +/* pclog("voodoo_triangle %i %i %i : vA %f, %f vB %f, %f vC %f, %f f %i %08x %08x %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->tformat);*/ + (float)params->vertexCx / 16.0, (float)params->vertexCy / 16.0, (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) ? params->tformat : 0, params->fbzColorPath, params->alphaMode, params->textureMode);*/ + state.base_r = params->startR; state.base_g = params->startG; state.base_b = params->startB; @@ -2960,6 +3014,7 @@ static void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p) 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_color0: @@ -3300,7 +3355,7 @@ static void voodoo_fb_writew(uint32_t addr, uint16_t val, void *p) int32_t w_depth = new_depth; int32_t ia = alpha_data << 12; - APPLY_FOG(write_data.r, write_data.g, write_data.b); + APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia); } if (params->alphaMode & 1) @@ -3441,7 +3496,7 @@ static void voodoo_fb_writel(uint32_t addr, uint32_t val, void *p) int32_t w_depth = new_depth; int32_t ia = alpha_data[c] << 12; - APPLY_FOG(write_data.r, write_data.g, write_data.b); + APPLY_FOG(write_data.r, write_data.g, write_data.b, z, ia); } if (params->alphaMode & 1) @@ -4227,7 +4282,10 @@ static void voodoo_add_status_info(char *s, int max_len, void *p) pixel_count_current[0] = voodoo->pixel_count[0]; pixel_count_current[1] = voodoo->pixel_count[1]; pixel_count_total = (pixel_count_current[0] + pixel_count_current[1]) - (voodoo->pixel_count_old[0] + voodoo->pixel_count_old[1]); - sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU (%f%% real)\n%d frames/sec\n%f%% CPU (%f%% real)\n%f%% CPU (%f%% real)\n"/*%d reads/sec\n%d write/sec\n%d tex/sec\n*/, (double)pixel_count_total/1000000.0, (double)voodoo->tri_count/1000.0, ((double)voodoo_time * 100.0) / timer_freq, ((double)voodoo_time * 100.0) / status_diff, voodoo->frame_count, + sprintf(temps, "%f Mpixels/sec (%f)\n%f ktris/sec\n%f%% CPU (%f%% real)\n%d frames/sec (%i)\n%f%% CPU (%f%% real)\n%f%% CPU (%f%% real)\n"/*%d reads/sec\n%d write/sec\n%d tex/sec\n*/, + (double)pixel_count_total/1000000.0, + ((double)pixel_count_total/1000000.0) / ((double)voodoo_render_time[0] / status_diff), + (double)voodoo->tri_count/1000.0, ((double)voodoo_time * 100.0) / timer_freq, ((double)voodoo_time * 100.0) / status_diff, voodoo->frame_count, voodoo_recomp, ((double)voodoo_render_time[0] * 100.0) / timer_freq, ((double)voodoo_render_time[0] * 100.0) / status_diff, ((double)voodoo_render_time[1] * 100.0) / timer_freq, ((double)voodoo_render_time[1] * 100.0) / status_diff); strncat(s, temps, max_len); @@ -4238,6 +4296,7 @@ static void voodoo_add_status_info(char *s, int max_len, void *p) voodoo->rd_count = voodoo->wr_count = voodoo->tex_count = 0; voodoo_time = 0; voodoo_render_time[0] = voodoo_render_time[1] = 0; + voodoo_recomp = 0; } static void voodoo_speed_changed(void *p) @@ -4261,7 +4320,9 @@ void *voodoo_init() voodoo->fb_mask = (voodoo->fb_size << 20) - 1; voodoo->render_threads = device_get_config_int("render_threads"); voodoo->odd_even_mask = voodoo->render_threads - 1; - +#ifndef NO_CODEGEN + voodoo->use_recompiler = device_get_config_int("recompiler"); +#endif voodoo_generate_filter(voodoo); /*generate filter lookup tables*/ pci_add(voodoo_pci_read, voodoo_pci_write, voodoo); @@ -4299,6 +4360,10 @@ void *voodoo_init() rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 2); rgb332[c].b = rgb332[c].b | (rgb332[c].b >> 4); rgb332[c].a = 0xff; + + ai44[c].a = (c & 0xf0) | ((c & 0xf0) >> 4); + ai44[c].r = (c & 0x0f) | ((c & 0x0f) << 4); + ai44[c].g = ai44[c].b = ai44[c].r; } for (c = 0; c < 0x10000; c++) @@ -4327,8 +4392,15 @@ void *voodoo_init() argb4444[c].r |= (argb4444[c].r >> 4); argb4444[c].g |= (argb4444[c].g >> 4); argb4444[c].b |= (argb4444[c].b >> 4); + + ai88[c].a = (c >> 8); + ai88[c].r = c & 0xff; + ai88[c].g = c & 0xff; + ai88[c].b = c & 0xff; } - +#ifndef NO_CODEGEN + voodoo_codegen_init(voodoo); +#endif return voodoo; } @@ -4341,6 +4413,7 @@ void voodoo_close(void *p) fwrite(voodoo->tex_mem, 2048*1024, 1, f); fclose(f); #endif + thread_kill(voodoo->fifo_thread); thread_kill(voodoo->render_thread[0]); if (voodoo->render_threads == 2) @@ -4352,7 +4425,9 @@ void voodoo_close(void *p) thread_destroy_event(voodoo->wake_render_thread[1]); thread_destroy_event(voodoo->render_not_full_event[0]); thread_destroy_event(voodoo->render_not_full_event[1]); - +#ifndef NO_CODEGEN + voodoo_codegen_close(voodoo); +#endif free(voodoo->fb_mem); free(voodoo->tex_mem); free(voodoo); @@ -4432,6 +4507,14 @@ static device_config_t voodoo_config[] = }, .default_int = 2 }, +#ifndef NO_CODEGEN + { + .name = "recompiler", + .description = "Recompiler", + .type = CONFIG_BINARY, + .default_int = 1 + }, +#endif { .type = -1 } diff --git a/src/vid_voodoo_codegen_x86.h b/src/vid_voodoo_codegen_x86.h new file mode 100644 index 0000000..83d0d00 --- /dev/null +++ b/src/vid_voodoo_codegen_x86.h @@ -0,0 +1,3725 @@ +/*Registers : + + alphaMode + fbzMode & 0x1f3fff + fbzColorPath +*/ + +#ifdef __linux__ +#include +#include +#endif +#if defined WIN32 || defined _WIN32 || defined _WIN32 +#define BITMAP windows_BITMAP +#include +#undef BITMAP +#endif + +#include + +#define BLOCK_NUM 8 +#define BLOCK_MASK (BLOCK_NUM-1) +#define BLOCK_SIZE 8192 + +typedef struct voodoo_x86_data_t +{ + uint8_t code_block[BLOCK_SIZE]; + int xdir; + uint32_t alphaMode; + uint32_t fbzMode; + uint32_t fogMode; + uint32_t fbzColorPath; + uint32_t textureMode; + uint32_t trexInit1; +} voodoo_x86_data_t; + +static voodoo_x86_data_t voodoo_x86_data[2][BLOCK_NUM]; + +static int last_block[2] = {0, 0}; +static int next_block_to_write[2] = {0, 0}; + +#define addbyte(val) \ + code_block[block_pos++] = val; \ + if (block_pos >= BLOCK_SIZE) \ + fatal("Over!\n") + +#define addword(val) \ + *(uint16_t *)&code_block[block_pos] = val; \ + block_pos += 2; \ + if (block_pos >= BLOCK_SIZE) \ + fatal("Over!\n") + +#define addlong(val) \ + *(uint32_t *)&code_block[block_pos] = val; \ + block_pos += 4; \ + if (block_pos >= BLOCK_SIZE) \ + fatal("Over!\n") + +#define addquad(val) \ + *(uint64_t *)&code_block[block_pos] = val; \ + block_pos += 8; \ + if (block_pos >= BLOCK_SIZE) \ + fatal("Over!\n") + + +static __m128i xmm_01_w;// = 0x0001000100010001ull; +static __m128i xmm_ff_w;// = 0x00ff00ff00ff00ffull; +static __m128i xmm_ff_b;// = 0x00000000ffffffffull; + +static uint32_t ebp_store2; +static uint32_t zero = 0; +static double const_1_48 = (double)(1ull << 4); +static float log_temp; + +static __m128i alookup[257], aminuslookup[256]; +static __m128i minus_254;// = 0xff02ff02ff02ff02ull; +static __m128i bilinear_lookup[256*4]; + +static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params, voodoo_state_t *state, int depthop) +{ + int block_pos = 0; + int z_skip_pos = 0; + int a_skip_pos = 0; + int chroma_skip_pos = 0; + int depth_jump_pos = 0; + int depth_jump_pos2 = 0; + int loop_jump_pos = 0; +// xmm_01_w = (__m128i)0x0001000100010001ull; +// xmm_ff_w = (__m128i)0x00ff00ff00ff00ffull; +// xmm_ff_b = (__m128i)0x00000000ffffffffull; + xmm_01_w = _mm_set_epi32(0, 0, 0x00010001, 0x00010001); + xmm_ff_w = _mm_set_epi32(0, 0, 0x00ff00ff, 0x00ff00ff); + xmm_ff_b = _mm_set_epi32(0, 0, 0, 0x00ffffff); + minus_254 = _mm_set_epi32(0, 0, 0xff02ff02, 0xff02ff02); +// *(uint64_t *)&const_1_48 = 0x45b0000000000000ull; +// block_pos = 0; +// voodoo_get_depth = &code_block[block_pos]; + /*W at (%esp+4) + Z at (%esp+12) + new_depth at (%esp+16)*/ +// if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depth_op == DEPTHOP_NEVER)) +// { +// addbyte(0xC3); /*RET*/ +// return; +// } + addbyte(0x55); /*PUSH EBP*/ + addbyte(0x57); /*PUSH EDI*/ + addbyte(0x56); /*PUSH ESI*/ + addbyte(0x53); /*PUSH EBX*/ + + addbyte(0x8b); /*MOV EDI, [ESP+4]*/ + addbyte(0x7c); + addbyte(0x24); + addbyte(4+16); + loop_jump_pos = block_pos; + addbyte(0x8b); /*MOV ESI, [ESP+8]*/ + addbyte(0x74); + addbyte(0x24); + addbyte(8+16); + addbyte(0x66); /*PXOR XMM2, XMM2*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xd2); + + if ((params->fbzMode & FBZ_W_BUFFER) || (params->fogMode & (FOG_ENABLE|FOG_CONSTANT|FOG_Z|FOG_ALPHA)) == FOG_ENABLE) + { + addbyte(0xb8); /*MOV new_depth, 0*/ + addlong(0); + addbyte(0x66); /*TEST w+4, 0xffff*/ + addbyte(0xf7); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w)+4); + addword(0xffff); + addbyte(0x75); /*JNZ got_depth*/ + depth_jump_pos = block_pos; + addbyte(0); +// addbyte(4+5+2+3+2+5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); + addbyte(0x8b); /*MOV EDX, w*/ + addbyte(0x97); + addlong(offsetof(voodoo_state_t, w)); + addbyte(0xb8); /*MOV new_depth, 0xf001*/ + addlong(0xf001); + addbyte(0x89); /*MOV EBX, EDX*/ + addbyte(0xd3); + addbyte(0xc1); /*SHR EDX, 16*/ + addbyte(0xea); + addbyte(16); + addbyte(0x74); /*JZ got_depth*/ + depth_jump_pos2 = block_pos; + addbyte(0); +// addbyte(5+5+3+2+2+2+/*3+*/3+2+6+4+5+2+3); + addbyte(0xb9); /*MOV ECX, 19*/ + addlong(19); + addbyte(0x0f); /*BSR EAX, EDX*/ + addbyte(0xbd); + addbyte(0xc2); + addbyte(0xba); /*MOV EDX, 15*/ + addlong(15); + addbyte(0xf7); /*NOT EBX*/ + addbyte(0xd3); + addbyte(0x29); /*SUB EDX, EAX - EDX = exp*/ + addbyte(0xc2); + addbyte(0x29); /*SUB ECX, EDX*/ + addbyte(0xd1); + addbyte(0xc1); /*SHL EDX, 12*/ + addbyte(0xe2); + addbyte(12); + addbyte(0xd3); /*SHR EBX, CL*/ + addbyte(0xeb); + addbyte(0x81); /*AND EBX, 0xfff - EBX = mant*/ + addbyte(0xe3); + addlong(0xfff); + addbyte(0x8d); /*LEA EAX, 1[EDX, EBX]*/ + addbyte(0x44); + addbyte(0x13); + addbyte(1); + addbyte(0xbb); /*MOV EBX, 0xffff*/ + addlong(0xffff); + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + addbyte(0x0f); /*CMOVA EAX, EBX*/ + addbyte(0x47); + addbyte(0xc3); + + if (depth_jump_pos) + *(uint8_t *)&code_block[depth_jump_pos] = (block_pos - depth_jump_pos) - 1; + if (depth_jump_pos) + *(uint8_t *)&code_block[depth_jump_pos2] = (block_pos - depth_jump_pos2) - 1; + + if ((params->fogMode & (FOG_ENABLE|FOG_CONSTANT|FOG_Z|FOG_ALPHA)) == FOG_ENABLE) + { + addbyte(0x89); /*MOV state->w_depth[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w_depth)); + } + } + if (!(params->fbzMode & FBZ_W_BUFFER)) + { + addbyte(0x8b); /*MOV EAX, z*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + addbyte(0xbb); /*MOV EBX, 0xffff*/ + addlong(0xffff); + addbyte(0x31); /*XOR ECX, ECX*/ + addbyte(0xc9); + addbyte(0xc1); /*SAR EAX, 12*/ + addbyte(0xf8); + addbyte(12); + addbyte(0x0f); /*CMOVS EAX, ECX*/ + addbyte(0x48); + addbyte(0xc1); + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + addbyte(0x0f); /*CMOVA EAX, EBX*/ + addbyte(0x47); + addbyte(0xc3); + } + + addbyte(0x89); /*MOV state->new_depth[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, new_depth)); + + if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop != DEPTHOP_ALWAYS) && (depthop != DEPTHOP_NEVER)) + { + addbyte(0x8b); /*MOV EBX, state->x[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x8b);/*MOV ECX, aux_mem[EDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, aux_mem)); + addbyte(0x0f); /*MOVZX EBX, [ECX+EBX*2]*/ + addbyte(0xb7); + addbyte(0x1c); + addbyte(0x59); + addbyte(0x39); /*CMP EAX, EBX*/ + addbyte(0xd8); + if (depthop == DEPTHOP_LESSTHAN) + { + addbyte(0x0f); /*JAE skip*/ + addbyte(0x83); + z_skip_pos = block_pos; + addlong(0); + } + else if (depthop == DEPTHOP_EQUAL) + { + addbyte(0x0f); /*JNE skip*/ + addbyte(0x85); + z_skip_pos = block_pos; + addlong(0); + } + else if (depthop == DEPTHOP_LESSTHANEQUAL) + { + addbyte(0x0f); /*JA skip*/ + addbyte(0x87); + z_skip_pos = block_pos; + addlong(0); + } + else if (depthop == DEPTHOP_GREATERTHAN) + { + addbyte(0x0f); /*JBE skip*/ + addbyte(0x86); + z_skip_pos = block_pos; + addlong(0); + } + else if (depthop == DEPTHOP_NOTEQUAL) + { + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + z_skip_pos = block_pos; + addlong(0); + } + else if (depthop == DEPTHOP_GREATERTHANEQUAL) + { + addbyte(0x0f); /*JB skip*/ + addbyte(0x82); + z_skip_pos = block_pos; + addlong(0); + } + else + fatal("Bad depth_op\n"); + } + else if ((params->fbzMode & FBZ_DEPTH_ENABLE) && (depthop == DEPTHOP_NEVER)) + { + addbyte(0xC3); /*RET*/ +// addbyte(0x30); /*XOR EAX, EAX*/ +// addbyte(0xc0); + } +// else +// { +// addbyte(0xb0); /*MOV AL, 1*/ +// addbyte(1); +// } + + +// voodoo_combine = &code_block[block_pos]; + /*XMM0 = colour*/ + /*XMM2 = 0 (for unpacking*/ + + /*EDI = state, ESI = params*/ + + if (params->textureMode & 1) + { + /*CVTSI2SSq XMM6, state->w*/ + /*MOVSS XMM7, const_1_48*/ + /*DIVSS XMM7, XMM6*/ + /*CVTSI2SSq XMM4, state->tmu0_s*/ + /*MULSS XMM7, const_1_44*/ + /*CVTSI2SSq XMM5, state->tmu0_t*/ + /*MULSS XMM4, XMM7*/ + /*CVTSS2SIq state->tex_s, XMM4*/ + /*MULSS XMM5, XMM7*/ + /*CVTSS2SIq state->tex_t, XMM5*/ + + addbyte(0xdf); /*FILDq state->tmu0_w*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, tmu0_w)); + addbyte(0xdd); /*FLDq const_1_48*/ + addbyte(0x05); + addlong(&const_1_48); + addbyte(0xde); /*FDIV ST(1)*/ + addbyte(0xf1); + addbyte(0xdf); /*FILDq state->tmu0_s*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, tmu0_s)); + addbyte(0xdf); /*FILDq state->tmu0_t*/ /*ST(0)=t, ST(1)=s, ST(2)=1/w*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, tmu0_t)); + addbyte(0xd9); /*FXCH ST(1)*/ /*ST(0)=s, ST(1)=t, ST(2)=1/w*/ + addbyte(0xc9); + addbyte(0xd8); /*FMUL ST(2)*/ /*ST(0)=s/w, ST(1)=t, ST(2)=1/w*/ + addbyte(0xca); + addbyte(0xd9); /*FXCH ST(1)*/ /*ST(0)=t, ST(1)=s/w, ST(2)=1/w*/ + addbyte(0xc9); + addbyte(0xd8); /*FMUL ST(2)*/ /*ST(0)=t/w, ST(1)=s/w, ST(2)=1/w*/ + addbyte(0xca); + addbyte(0xd9); /*FXCH ST(2)*/ /*ST(0)=1/w, ST(1)=s/w, ST(2)=t/w*/ + addbyte(0xca); + addbyte(0xd9); /*FSTPs log_temp*/ /*ST(0)=s/w, ST(1)=t/w*/ + addbyte(0x1d); + addlong(&log_temp); +// addbyte(0xdd); /*FSTP ST(0)*/ +// addbyte(0xd8); + addbyte(0xdf); /*FSITPq state->tex_s*/ + addbyte(0xbf); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0xa1); /*MOV EAX, log_temp*/ + addlong(&log_temp); + addbyte(0xdf); /*FSITPq state->tex_t*/ + addbyte(0xbf); + addlong(offsetof(voodoo_state_t, tex_t)); + addbyte(0xc1); /*SHR EAX, 23-8*/ + addbyte(0xe8); + addbyte(15); + addbyte(0x0f); /*MOVZX EBX, AL*/ + addbyte(0xb6); + addbyte(0xd8); + addbyte(0x25); /*AND EAX, 0xff00*/ + addlong(0xff00); + addbyte(0x2d); /*SUB EAX, (127-44)<<8*/ + addlong((127-44+19) << 8); + addbyte(0x0f); /*MOVZX EBX, logtable[EBX]*/ + addbyte(0xb6); + addbyte(0x9b); + addlong(logtable); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); +// addbyte(0x89); /*MOV state->lod_raw, EAX*/ +// addbyte(0x87); +// addlong(offsetof(voodoo_state_t, lod_raw)); + addbyte(0x03); /*ADD EAX, state->lod*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tmu[0].lod)); +/*HACK*/ +#if 0 + addbyte(0x8b); /*MOV EAX, state->lod_min*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min)); +#endif + addbyte(0x3b); /*CMP EAX, state->lod_min*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min)); + addbyte(0x0f); /*CMOVL EAX, state->lod_min*/ + addbyte(0x4c); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min)); + addbyte(0x3b); /*CMP EAX, state->lod_max*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_max)); + addbyte(0x0f); /*CMOVNL EAX, state->lod_max*/ + addbyte(0x4d); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_max)); + addbyte(0xc1); /*SHR EAX, 8*/ + addbyte(0xe8); + addbyte(8); + addbyte(0x89); /*MOV state->lod, EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + } + else + { + addbyte(0xf3); /*MOVQ XMM4, state->tmu0_s*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tmu0_s)); + addbyte(0xf3); /*MOVQ XMM5, state->tmu0_t*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, tmu0_t)); + addbyte(0x66); /*SHRQ XMM4, 28*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xd4); + addbyte(28); + addbyte(0x66); /*SHRQ XMM5, 28*/ + addbyte(0x0f); + addbyte(0x73); + addbyte(0xd5); + addbyte(28); + addbyte(0x66); /*MOVQ state->tex_s, XMM4*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0x66); /*MOVQ state->tex_t, XMM5*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, tex_t)); + addbyte(0x8b); /*MOV EAX, state->lod_min*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod_min)); + addbyte(0xc1); /*SHR EAX, 8*/ + addbyte(0xe8); + addbyte(8); + addbyte(0x89); /*MOV state->lod, EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, lod)); + } + + + if (voodoo->trexInit1 & (1 << 18)) + { +#if 0 + addbyte(0xc7); /*MOV state->tex_r, 0*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_r)); + addlong(0); + addbyte(0xc7); /*MOV state->tex_g, 0*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_g)); + addlong(0); + addbyte(0xc7); /*MOV state->tex_b, 1*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_b)); + addlong(1); +#endif + addbyte(0xb8); /*MOV EAX, 0x000001*/ + addlong(0x000001); + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + } + else if (params->fbzColorPath & FBZCP_TEXTURE_ENABLED) + { + if (voodoo->bilinear_enabled && (params->textureMode & 6)) + { + addbyte(0x8b); /*MOV ECX, state->lod[EDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xbd); /*MOV EBP, 1*/ + addlong(1); + addbyte(0x8a); /*MOV DL, params->tex_shift[ESI+ECX*4]*/ + addbyte(0x94); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_shift)); + addbyte(0xd3); /*SHL EBP, CL*/ + addbyte(0xe5); + addbyte(0x8b); /*MOV EAX, state->tex_s[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0xc1); /*SHL EBP, 3*/ + addbyte(0xe5); + addbyte(3); + addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_t)); + addbyte(0x29); /*SUB EAX, EBP*/ + addbyte(0xe8); + addbyte(0x29); /*SUB EBX, EBP*/ + addbyte(0xeb); + addbyte(0xd3); /*SAR EAX, CL*/ + addbyte(0xf8); + addbyte(0x80); /*SUB CL, 4*/ + addbyte(0xe9); + addbyte(4); + addbyte(0x89); /*MOV EBP, EAX*/ + addbyte(0xc5); + addbyte(0xd3); /*ROR EBX, CL*/ + addbyte(0xcb); + addbyte(0x83); /*AND EBP, 0xf*/ + addbyte(0xe5); + addbyte(0xf); + addbyte(0x89); /*MOV ECX, EBX*/ + addbyte(0xd9); + addbyte(0xc1); /*SAR EAX, 4*/ + addbyte(0xf8); + addbyte(4); + addbyte(0x81); /*AND ECX, 0xf0*/ + addbyte(0xe1); + addlong(0xf0); + addbyte(0xc1); /*SAR EBX, 8*/ + addbyte(0xfb); + addbyte(8); + addbyte(0x09); /*OR EBP, ECX*/ + addbyte(0xcd); + addbyte(0x8b); /*MOV ECX, state->lod[EDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0xc1); /*SHL EBP, 6*/ + addbyte(0xe5); + addbyte(6); + /*EAX = S, EBX = T, ECX = LOD, EDX = tex_shift, ESI=params, EDI=state, EBP = bilinear shift*/ + addbyte(0x8d); /*LEA ESI, [ESI+ECX*4]*/ + addbyte(0x34); + addbyte(0x8e); + addbyte(0x89); /*MOV ebp_store2, EBP*/ + addbyte(0x2d); + addlong(&ebp_store2); + addbyte(0x8b); /*MOV EBP, state->tex[EDI+ECX*4]*/ + addbyte(0xac); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, tex)); + addbyte(0x88); /*MOV CL, DL*/ + addbyte(0xd1); + addbyte(0x89); /*MOV EDX, EBX*/ + addbyte(0xda); + if (!state->clamp_s) + { + addbyte(0x23); /*AND EAX, params->tex_w_mask[ESI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, tex_w_mask)); + } + addbyte(0x83); /*ADD EDX, 1*/ + addbyte(0xc2); + addbyte(1); + if (state->clamp_t) + { + addbyte(0x0f); /*CMOVS EDX, zero*/ + addbyte(0x48); + addbyte(0x15); + addlong(&zero); + addbyte(0x3b); /*CMP EDX, params->tex_h_mask[ESI]*/ + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask)); + addbyte(0x0f); /*CMOVA EDX, params->tex_h_mask[ESI]*/ + addbyte(0x47); + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask)); + addbyte(0x85); /*TEST EBX,EBX*/ + addbyte(0xdb); + addbyte(0x0f); /*CMOVS EBX, zero*/ + addbyte(0x48); + addbyte(0x1d); + addlong(&zero); + addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask)); + addbyte(0x0f); /*CMOVA EBX, params->tex_h_mask[ESI]*/ + addbyte(0x47); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask)); + } + else + { + addbyte(0x23); /*AND EDX, params->tex_h_mask[ESI]*/ + addbyte(0x96); + addlong(offsetof(voodoo_params_t, tex_h_mask)); + addbyte(0x23); /*AND EBX, params->tex_h_mask[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, tex_h_mask)); + } + /*EAX = S, EBX = T0, EDX = T1*/ + addbyte(0xd3); /*SHL EBX, CL*/ + addbyte(0xe3); + addbyte(0xd3); /*SHL EDX, CL*/ + addbyte(0xe2); + if (state->tformat & 8) + { + addbyte(0x8d); /*LEA EBX,[EBP+EBX*2]*/ + addbyte(0x5c); + addbyte(0x5d); + addbyte(0); + addbyte(0x8d); /*LEA EDX,[EBP+EDX*2]*/ + addbyte(0x54); + addbyte(0x55); + addbyte(0); + } + else + { + addbyte(0x01); /*ADD EBX, EBP*/ + addbyte(0xeb); + addbyte(0x01); /*ADD EDX, EBP*/ + addbyte(0xea); + } + if (state->clamp_s) + { + addbyte(0x8b); /*MOV EBP, params->tex_w_mask[ESI]*/ + addbyte(0xae); + addlong(offsetof(voodoo_params_t, tex_w_mask)); + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x8b); /*MOV ebp_store2, ESI*/ + addbyte(0x35); + addlong(&ebp_store2); + addbyte(0x0f); /*CMOVS EAX, zero*/ + addbyte(0x48); + addbyte(0x05); + addlong(&zero); + addbyte(0x78); /*JS + - clamp on 0*/ + addbyte(2+3+2+ ((state->tformat & 8) ? (3+3+2) : (4+4+2))); + addbyte(0x3b); /*CMP EAX, EBP*/ + addbyte(0xc5); + addbyte(0x0f); /*CMOVAE EAX, EBP*/ + addbyte(0x43); + addbyte(0xc5); + addbyte(0x73); /*JAE + - clamp on +*/ + addbyte((state->tformat & 8) ? (3+3+2) : (4+4+2)); + } + else + { + addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI] - is S at texture edge (ie will wrap/clamp)?*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, tex_w_mask)); + addbyte(0x8b); /*MOV ebp_store2, ESI*/ + addbyte(0x35); + addlong(&ebp_store2); + addbyte(0x74); /*JE +*/ + addbyte((state->tformat & 8) ? (3+3+2) : (4+4+2)); + } + + if (state->tformat & 8) + { + addbyte(0x8b); /*MOV EDX,[EDX+EAX*2]*/ + addbyte(0x14); + addbyte(0x42); + addbyte(0x8b); /*MOV EAX,[EBX+EAX*2]*/ + addbyte(0x04); + addbyte(0x43); + } + else + { + addbyte(0x0f); /*MOVZX EDX,W[EDX+EAX]*/ + addbyte(0xb7); + addbyte(0x14); + addbyte(0x02); + addbyte(0x0f); /*MOVZX EAX,W[EBX+EAX]*/ + addbyte(0xb7); + addbyte(0x04); + addbyte(0x03); + } + + if (state->clamp_s) + { + addbyte(0xeb); /*JMP +*/ + addbyte((state->tformat & 8) ? (3+4+3+3+4+3) : (4+4+2+2)); + + /*S clamped - the two S coordinates are the same*/ + if (state->tformat & 8) + { + addbyte(0x8b); /*MOV ECX, [EDX+EAX*2]*/ + addbyte(0x0c); + addbyte(0x42); + addbyte(0x8b); /*MOV EDX, [EDX+EAX*2-2]*/ + addbyte(0x54); + addbyte(0x42); + addbyte(-2); + addbyte(0x66); /*MOV DX, CX*/ + addbyte(0x89); + addbyte(0xca); + addbyte(0x8b); /*MOV ECX, [EBX+EAX*2]*/ + addbyte(0x0c); + addbyte(0x43); + addbyte(0x8b); /*MOV EAX, [EBX+EAX*2-2]*/ + addbyte(0x44); + addbyte(0x43); + addbyte(-2); + addbyte(0x66); /*MOV AX, CX*/ + addbyte(0x89); + addbyte(0xc8); + } + else + { + addbyte(0x0f); /*MOVZX EDX,W[EDX+EAX]*/ + addbyte(0xb7); + addbyte(0x14); + addbyte(0x02); + addbyte(0x0f); /*MOVZX EAX,W[EBX+EAX]*/ + addbyte(0xb7); + addbyte(0x04); + addbyte(0x03); + addbyte(0x88); /*MOV DH, DL*/ + addbyte(0xd6); + addbyte(0x88); /*MOV AH, AL*/ + addbyte(0xc4); + } + } + else + { + addbyte(0xeb); /*JMP +*/ + addbyte((state->tformat & 8) ? (3+3+3+3+3+3) : (2+2+4+4+2+2)); + + /*S wrapped - the two S coordinates are not contiguous*/ + if (state->tformat & 8) + { + addbyte(0x8b); /*MOV ECX, [EDX+EAX*2]*/ + addbyte(0x0c); + addbyte(0x42); + addbyte(0x8b); /*MOV EDX, [EDX-2]*/ + addbyte(0x52); + addbyte(-2); + addbyte(0x66); /*MOV DX, CX*/ + addbyte(0x89); + addbyte(0xca); + addbyte(0x8b); /*MOV ECX, [EBX+EAX*2]*/ + addbyte(0x0c); + addbyte(0x43); + addbyte(0x8b); /*MOV EAX, [EBX-2]*/ + addbyte(0x43); + addbyte(-2); + addbyte(0x66); /*MOV AX, CX*/ + addbyte(0x89); + addbyte(0xc8); + } + else + { + addbyte(0x8a); /*MOV CL, [EDX]*/ + addbyte(0x0a); + addbyte(0x8a); /*MOV CH, [EBX]*/ + addbyte(0x2b); + addbyte(0x0f); /*MOVZX EDX,B[EDX+EAX]*/ + addbyte(0xb6); + addbyte(0x14); + addbyte(0x02); + addbyte(0x0f); /*MOVZX EAX,B[EBX+EAX]*/ + addbyte(0xb6); + addbyte(0x04); + addbyte(0x03); + addbyte(0x88); /*MOV DH, CL*/ + addbyte(0xce); + addbyte(0x88); /*MOV AH, CH*/ + addbyte(0xec); + } + } + + addbyte(0x81); /*ADD ESI, bilinear_lookup*/ + addbyte(0xc6); + addlong(bilinear_lookup); + + switch (state->tformat) + { + case TEX_RGB332: + addbyte(0x0f); /*MOVZX ECX, AL*/ + addbyte(0xb6); + addbyte(0xc8); + addbyte(0x66); /*MOVD XMM0, rgb332[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x8d); + addlong(rgb332); + addbyte(0x0f); /*MOVZX ECX, AH*/ + addbyte(0xb6); + addbyte(0xcc); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM1, rgb332[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x8d); + addlong(rgb332); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x0f); /*MOVZX ECX, DL*/ + addbyte(0xb6); + addbyte(0xca); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*MOVD XMM3, rgb332[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x1c); + addbyte(0x8d); + addlong(rgb332); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x0f); /*MOVZX ECX, DH*/ + addbyte(0xb6); + addbyte(0xce); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, rgb332[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x8d); + addlong(rgb332); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_Y4I2Q2: + addbyte(0x8b); /*MOV EBP, state->palette[EDI]*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, palette)); + addbyte(0x0f); /*MOVZX ECX, AL*/ + addbyte(0xb6); + addbyte(0xc8); + addbyte(0x66); /*MOVD XMM0, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x44); + addbyte(0x8d); + addbyte(0); + addbyte(0x0f); /*MOVZX ECX, AH*/ + addbyte(0xb6); + addbyte(0xcc); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM1, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x4c); + addbyte(0x8d); + addbyte(0); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x0f); /*MOVZX ECX, DL*/ + addbyte(0xb6); + addbyte(0xca); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*MOVD XMM3, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x5c); + addbyte(0x8d); + addbyte(0); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x0f); /*MOVZX ECX, DH*/ + addbyte(0xb6); + addbyte(0xce); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x4c); + addbyte(0x8d); + addbyte(0); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_A8: + addbyte(0x66); /*MOVZX CX, AH*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0xcc); + addbyte(0x66); /*MOVZX AX, AL*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0xc0); + addbyte(0x66); /*IMUL CX, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*IMUL AX, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0x06); + addbyte(0x66); /*MOVZX BX, DH*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0xde); + addbyte(0x66); /*MOVZX DX, DL*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0xd2); + addbyte(0x66); /*ADD AX, CX*/ + addbyte(0x01); + addbyte(0xc8); + addbyte(0x66); /*IMUL BX, bilinear_lookup[ESI]+0x30*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0x5e); + addbyte(0x30); + addbyte(0x66); /*IMUL DX, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0x56); + addbyte(0x20); + addbyte(0x66); /*ADD AX, BX*/ + addbyte(0x01); + addbyte(0xd8); + addbyte(0x66); /*ADD AX, DX*/ + addbyte(0x01); + addbyte(0xd0); + addbyte(0x88); /*MOV AL, AH*/ + addbyte(0xe0); + addbyte(0x66); /*MOV BX, AX*/ + addbyte(0x89); + addbyte(0xc3); + addbyte(0x0f); /*BSWAP EAX*/ + addbyte(0xc8); + addbyte(0x66); /*MOV AX, BX*/ + addbyte(0x89); + addbyte(0xd8); + break; + + case TEX_I8: + addbyte(0x66); /*MOVZX CX, AH*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0xcc); + addbyte(0x66); /*MOVZX AX, AL*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0xc0); + addbyte(0x66); /*IMUL CX, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*IMUL AX, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0x06); + addbyte(0x66); /*MOVZX BX, DH*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0xde); + addbyte(0x66); /*MOVZX DX, DL*/ + addbyte(0x0f); + addbyte(0xb6); + addbyte(0xd2); + addbyte(0x66); /*ADD AX, CX*/ + addbyte(0x01); + addbyte(0xc8); + addbyte(0x66); /*IMUL BX, bilinear_lookup[ESI]+0x30*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0x5e); + addbyte(0x30); + addbyte(0x66); /*IMUL DX, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xaf); + addbyte(0x56); + addbyte(0x20); + addbyte(0x66); /*ADD AX, BX*/ + addbyte(0x01); + addbyte(0xd8); + addbyte(0x66); /*ADD AX, DX*/ + addbyte(0x01); + addbyte(0xd0); + addbyte(0x88); /*MOV AL, AH*/ + addbyte(0xe0); + addbyte(0xc1); /*SHL EAX, 8*/ + addbyte(0xe0); + addbyte(8); + addbyte(0x88); /*MOV AL, AH*/ + addbyte(0xe0); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_AI8: + addbyte(0x0f); /*MOVZX ECX, AL*/ + addbyte(0xb6); + addbyte(0xc8); + addbyte(0x66); /*MOVD XMM0, ai44[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x8d); + addlong(ai44); + addbyte(0x0f); /*MOVZX ECX, AH*/ + addbyte(0xb6); + addbyte(0xcc); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM1, ai44[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x8d); + addlong(ai44); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x0f); /*MOVZX ECX, DL*/ + addbyte(0xb6); + addbyte(0xca); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*MOVD XMM3, ai44[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x1c); + addbyte(0x8d); + addlong(ai44); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x0f); /*MOVZX ECX, DH*/ + addbyte(0xb6); + addbyte(0xce); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, ai44[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x8d); + addlong(ai44); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + break; + + case TEX_PAL8: + addbyte(0x8b); /*MOV EBP, state->palette[EDI]*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, palette)); + addbyte(0x0f); /*MOVZX ECX, AL*/ + addbyte(0xb6); + addbyte(0xc8); + addbyte(0x66); /*MOVD XMM0, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x44); + addbyte(0x8d); + addbyte(0); + addbyte(0x0f); /*MOVZX ECX, AH*/ + addbyte(0xb6); + addbyte(0xcc); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM1, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x4c); + addbyte(0x8d); + addbyte(0); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x0f); /*MOVZX ECX, DL*/ + addbyte(0xb6); + addbyte(0xca); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*MOVD XMM3, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x5c); + addbyte(0x8d); + addbyte(0); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x0f); /*MOVZX ECX, DH*/ + addbyte(0xb6); + addbyte(0xce); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x4c); + addbyte(0x8d); + addbyte(0); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x30*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_R5G6B5: + addbyte(0x0f); /*MOVZX ECX, AX*/ + addbyte(0xb7); + addbyte(0xc8); + addbyte(0xc1); /*SHR EAX, 16*/ + addbyte(0xe8); + addbyte(16); + addbyte(0x66); /*MOVD XMM0, rgb565[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x8d); + addlong(rgb565); + addbyte(0x66); /*MOVD XMM1, rgb565[EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x85); + addlong(rgb565); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x0f); /*MOVZX ECX, DX*/ + addbyte(0xb7); + addbyte(0xca); + addbyte(0xc1); /*SHR EDX, 16*/ + addbyte(0xea); + addbyte(16); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*MOVD XMM3, rgb565[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x1c); + addbyte(0x8d); + addlong(rgb565); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, rgb565[EDX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x95); + addlong(rgb565); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x30*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_ARGB1555: + addbyte(0x0f); /*MOVZX ECX, AX*/ + addbyte(0xb7); + addbyte(0xc8); + addbyte(0xc1); /*SHR EAX, 16*/ + addbyte(0xe8); + addbyte(16); + addbyte(0x66); /*MOVD XMM0, argb1555[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x8d); + addlong(argb1555); + addbyte(0x66); /*MOVD XMM1, argb1555[EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x85); + addlong(argb1555); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x0f); /*MOVZX ECX, DX*/ + addbyte(0xb7); + addbyte(0xca); + addbyte(0xc1); /*SHR EDX, 16*/ + addbyte(0xea); + addbyte(16); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*MOVD XMM3, argb1555[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x1c); + addbyte(0x8d); + addlong(argb1555); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, argb1555[EDX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x95); + addlong(argb1555); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + break; + + case TEX_ARGB4444: + addbyte(0x0f); /*MOVZX ECX, AX*/ + addbyte(0xb7); + addbyte(0xc8); + addbyte(0xc1); /*SHR EAX, 16*/ + addbyte(0xe8); + addbyte(16); + addbyte(0x66); /*MOVD XMM0, argb4444[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x8d); + addlong(argb4444); + addbyte(0x66); /*MOVD XMM1, argb4444[EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x85); + addlong(argb4444); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x0f); /*MOVZX ECX, DX*/ + addbyte(0xb7); + addbyte(0xca); + addbyte(0xc1); /*SHR EDX, 16*/ + addbyte(0xea); + addbyte(16); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*MOVD XMM3, argb4444[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x1c); + addbyte(0x8d); + addlong(argb4444); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, argb4444[EDX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x95); + addlong(argb4444); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + break; + + case TEX_A8I8: + addbyte(0x0f); /*MOVZX ECX, AX*/ + addbyte(0xb7); + addbyte(0xc8); + addbyte(0xc1); /*SHR EAX, 16*/ + addbyte(0xe8); + addbyte(16); + addbyte(0x66); /*MOVD XMM0, ai88[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x04); + addbyte(0x8d); + addlong(ai88); + addbyte(0x66); /*MOVD XMM1, ai88[EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x85); + addlong(ai88); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x0f); /*MOVZX ECX, DX*/ + addbyte(0xb7); + addbyte(0xca); + addbyte(0xc1); /*SHR EDX, 16*/ + addbyte(0xea); + addbyte(16); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*MOVD XMM3, ai88[ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x1c); + addbyte(0x8d); + addlong(ai88); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, ai88[EDX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x0c); + addbyte(0x95); + addlong(ai88); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + break; + + case TEX_APAL88: + addbyte(0x8b); /*MOV EBP, state->palette[EDI]*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, palette)); + addbyte(0x0f); /*MOVZX ECX, AL*/ + addbyte(0xb6); + addbyte(0xc8); + addbyte(0x66); /*MOVD XMM0, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x44); + addbyte(0x8d); + addbyte(0); + addbyte(0x0f); /*MOVZX ECX, AH*/ + addbyte(0xb6); + addbyte(0xcc); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0xc1); /*SHR EAX, 16*/ + addbyte(0xe8); + addbyte(16); + addbyte(0x66); /*PINSRW XMM0, ECX, 3*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0xc1); + addbyte(3); + addbyte(0x0f); /*MOVZX ECX, AL*/ + addbyte(0xb6); + addbyte(0xc8); + addbyte(0x0f); /*MOVZX EAX, AH*/ + addbyte(0xb6); + addbyte(0xc4); + addbyte(0x66); /*MOVD XMM1, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x4c); + addbyte(0x8d); + addbyte(0); + addbyte(0x66); /*PMULLW XMM0, bilinear_lookup[ESI]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x06); + addbyte(0x0f); /*MOVZX ECX, DL*/ + addbyte(0xb6); + addbyte(0xca); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PINSRW XMM1, EAX, 3*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0xc8); + addbyte(3); + addbyte(0x66); /*MOVD XMM3, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x5c); + addbyte(0x8d); + addbyte(0); + addbyte(0x0f); /*MOVZX ECX, DH*/ + addbyte(0xb6); + addbyte(0xce); + addbyte(0xc1); /*SHR EDX, 16*/ + addbyte(0xea); + addbyte(16); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x10*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x10); + addbyte(0x66); /*PINSRW XMM3, ECX, 3*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0xd9); + addbyte(3); + addbyte(0x0f); /*MOVZX ECX, DL*/ + addbyte(0xb6); + addbyte(0xca); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*MOVD XMM1, [EBP+ECX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x4c); + addbyte(0x8d); + addbyte(0); + addbyte(0x0f); /*MOVZX ECX, DH*/ + addbyte(0xb6); + addbyte(0xce); + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + addbyte(0x66); /*PMULLW XMM3, bilinear_lookup[ESI]+0x20*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x5e); + addbyte(0x20); + addbyte(0x66); /*PINSR1 XMM1, ECX, 3*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0xc9); + addbyte(3); + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); + addbyte(0x66); /*PMULLW XMM1, bilinear_lookup[ESI]+0x30*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x4e); + addbyte(0x30); + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + break; + + default: + fatal("Unknown texture format %i\n", state->tformat); + } + + addbyte(0x8b); /*MOV ESI, [ESP+8]*/ + addbyte(0x74); + addbyte(0x24); + addbyte(8+16); /*CHECK!*/ + } + else + { + addbyte(0x8b); /*MOV ECX, state->lod[EDI]*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, lod)); + addbyte(0x8a); /*MOV DL, params->tex_shift[ESI+ECX*4]*/ + addbyte(0x94); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_shift)); + addbyte(0x8b); /*MOV EBP, state->tex[EDI+ECX*4]*/ + addbyte(0xac); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, tex)); + addbyte(0x80); /*ADD CL, 4*/ + addbyte(0xc1); + addbyte(4); + addbyte(0x8b); /*MOV EAX, state->tex_s[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_s)); + addbyte(0x8b); /*MOV EBX, state->tex_t[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_t)); + addbyte(0xd3); /*SHR EAX, CL*/ + addbyte(0xe8); + addbyte(0xd3); /*SHR EBX, CL*/ + addbyte(0xeb); + if (state->clamp_s) + { + addbyte(0x85); /*TEST EAX, EAX*/ + addbyte(0xc0); + addbyte(0x0f); /*CMOVS EAX, zero*/ + addbyte(0x48); + addbyte(0x05); + addlong(&zero); + addbyte(0x3b); /*CMP EAX, params->tex_w_mask[ESI+ECX*4]*/ + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask) - 0x10); + addbyte(0x0f); /*CMOVAE EAX, params->tex_w_mask[ESI+ECX*4]*/ + addbyte(0x43); + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask) - 0x10); + + } + else + { + addbyte(0x23); /*AND EAX, params->tex_w_mask-0x10[ESI+ECX*4]*/ + addbyte(0x84); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_w_mask) - 0x10); + } + if (state->clamp_t) + { + addbyte(0x85); /*TEST EBX, EBX*/ + addbyte(0xdb); + addbyte(0x0f); /*CMOVS EBX, zero*/ + addbyte(0x48); + addbyte(0x1d); + addlong(&zero); + addbyte(0x3b); /*CMP EBX, params->tex_h_mask[ESI+ECX*4]*/ + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask) - 0x10); + addbyte(0x0f); /*CMOVAE EBX, params->tex_h_mask[ESI+ECX*4]*/ + addbyte(0x43); + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask) - 0x10); + } + else + { + addbyte(0x23); /*AND EBX, params->tex_h_mask-0x10[ESI+ECX*4]*/ + addbyte(0x9c); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, tex_h_mask) - 0x10); + } + addbyte(0x88); /*MOV CL, DL*/ + addbyte(0xd1); + addbyte(0xd3); /*SHL EBX, CL*/ + addbyte(0xe3); + addbyte(0x01); /*ADD EBX, EAX*/ + addbyte(0xc3); + + if (state->tformat & 8) + { + addbyte(0x0f); /*MOVZX EAX,W[EBP+EBX*2]*/ + addbyte(0xb7); + addbyte(0x44); + addbyte(0x5d); + addbyte(0); + } + else + { + addbyte(0x0f); /*MOVZX EAX,B[EBP+EBX]*/ + addbyte(0xb6); + addbyte(0x44); + addbyte(0x1d); + addbyte(0); + } + + switch (state->tformat) + { + case TEX_RGB332: + addbyte(0x8b); /*MOV EAX, rgb332[EAX*4]*/ + addbyte(0x04); + addbyte(0x85); + addlong(rgb332); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_Y4I2Q2: + addbyte(0x8b); /*MOV EBP, state->palette[EDI]*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, palette)); + addbyte(0x8b); /*MOV EAX, [EBP+EAX*4]*/ + addbyte(0x44); + addbyte(0x85); + addbyte(0); +// addbyte(0x0f); /*BSWAP EAX*/ +// addbyte(0xc8); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_A8: + addbyte(0x88); /*MOV AH, AL*/ + addbyte(0xc4); + addbyte(0x66); /*MOV BX, AX*/ + addbyte(0x89); + addbyte(0xc3); + addbyte(0x0f); /*BSWAP EAX*/ + addbyte(0xc8); + addbyte(0x66); /*MOV AX, BX*/ + addbyte(0x89); + addbyte(0xd8); + break; + + case TEX_I8: + addbyte(0x88); /*MOV AH, AL*/ + addbyte(0xc4); + addbyte(0xc1); /*SHL EAX, 8*/ + addbyte(0xe0); + addbyte(8); + addbyte(0x88); /*MOV AL, AH*/ + addbyte(0xe0); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); +// addbyte(0x25); /*AND EAX, 0x00ffffff*/ +// addlong(0x00000000); + break; + + case TEX_AI8: + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x83); /*AND EAX, 0x0f*/ + addbyte(0xe0); + addbyte(0x0f); + addbyte(0x81); /*AND EBX, 0xf0*/ + addbyte(0xe3); + addlong(0xf0); + addbyte(0x89); /*MOV ECX, EAX*/ + addbyte(0xc1); + addbyte(0x89); /*MOV EDX, EBX*/ + addbyte(0xda); + addbyte(0xc1); /*SHL ECX, 4*/ + addbyte(0xe1); + addbyte(4); + addbyte(0xc1); /*SHR EDX, 4*/ + addbyte(0xe2); + addbyte(4); + addbyte(0x09); /*OR EAX, ECX*/ + addbyte(0xc8); + addbyte(0x09); /*OR EBX, EDX*/ + addbyte(0xd3); + addbyte(0x88); /*MOV AH, AL*/ + addbyte(0xc4); + addbyte(0xc1); /*SHL EBX, 24*/ + addbyte(0xe3); + addbyte(24); + addbyte(0xc1); /*SHL EAX, 8*/ + addbyte(0xe0); + addbyte(8); + addbyte(0x88); /*MOV AL, AH*/ + addbyte(0xe0); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + break; + + case TEX_PAL8: + addbyte(0x8b); /*MOV EBP, state->palette[EDI]*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, palette)); + addbyte(0x8b); /*MOV EAX, [EBP+EAX*4]*/ + addbyte(0x44); + addbyte(0x85); + addbyte(0); +// addbyte(0x0f); /*BSWAP EAX*/ +// addbyte(0xc8); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_R5G6B5: + addbyte(0x8b); /*MOV EAX, rgb565[EAX*4]*/ + addbyte(0x04); + addbyte(0x85); + addlong(rgb565); + addbyte(0x0d); /*OR EAX, 0xff000000*/ + addlong(0xff000000); + break; + + case TEX_ARGB1555: + addbyte(0x8b); /*MOV EAX, argb1555[EAX*4]*/ + addbyte(0x04); + addbyte(0x85); + addlong(argb1555); + break; + + case TEX_ARGB4444: + addbyte(0x8b); /*MOV EAX, argb4444[EAX*4]*/ + addbyte(0x04); + addbyte(0x85); + addlong(argb4444); + break; + + case TEX_A8I8: + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0xc1); /*SHL EAX, 16*/ + addbyte(0xe0); + addbyte(16); + addbyte(0x88); /*MOV AL, BL*/ + addbyte(0xd8); + addbyte(0x88); /*MOV AH, BL*/ + addbyte(0xdc); + break; + + case TEX_APAL88: + addbyte(0x8b); /*MOV EBP, state->palette[EDI]*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, palette)); + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x25); /*AND EAX, 0x000000ff*/ + addlong(0x000000ff); + addbyte(0x8b); /*MOV EAX, [EBP+EAX*4]*/ + addbyte(0x44); + addbyte(0x85); + addbyte(0); + addbyte(0xc1); /*SHL EBX, 16*/ + addbyte(0xe3); + addbyte(16); +// addbyte(0x0f); /*BSWAP EAX*/ +// addbyte(0xc8); + addbyte(0x81); /*AND EBX, 0xff000000*/ + addbyte(0xe3); + addlong(0xff000000); + addbyte(0x25); /*AND EAX, 0x00ffffff*/ + addlong(0x00ffffff); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + +// addbyte(0x25); /*AND EAX, 0x00ffffff*/ +// addlong(0x00000000); + break; + + default: + fatal("Unknown texture format %i\n", state->tformat); + } + } + if ((params->fbzMode & FBZ_CHROMAKEY)) + { + addbyte(0x8b); /*MOV EBX, params->chromaKey[ESI]*/ + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, chromaKey)); + addbyte(0x31); /*XOR EBX, EAX*/ + addbyte(0xc3); + addbyte(0x81); /*AND EBX, 0xffffff*/ + addbyte(0xe3); + addlong(0xffffff); + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + chroma_skip_pos = block_pos; + addlong(0); + } +#if 0 + addbyte(0x0f); /*MOVZX EBX, AL*/ + addbyte(0xb6); + addbyte(0xd8); + addbyte(0x89); /*MOV state->tex_b[EDI], EBX*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_b)); + addbyte(0x0f); /*MOVZX EBX, AH*/ + addbyte(0xb6); + addbyte(0xdc); + addbyte(0xc1); /*SHR EAX, 16*/ + addbyte(0xe8); + addbyte(16); + addbyte(0x89); /*MOV state->tex_g[EDI], EBX*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_g)); + addbyte(0x0f); /*MOVZX EBX, AL*/ + addbyte(0xb6); + addbyte(0xd8); + addbyte(0x89); /*MOV state->tex_r[EDI], EBX*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_r)); + addbyte(0x0f); /*MOVZX EBX, AH*/ + addbyte(0xb6); + addbyte(0xdc); + addbyte(0x89); /*MOV state->tex_a[EDI], EBX*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); +#endif +//#if 0 +// addbyte(0x89); /*MOV state->tex_out[EDI], EAX*/ +// addbyte(0x87); +// addlong(offsetof(voodoo_state_t, tex_out)); + addbyte(0x66); /*MOVD XMM0, EAX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xc0); + addbyte(0xc1); /*SHR EAX, 24*/ + addbyte(0xe8); + addbyte(24); + addbyte(0x89); /*MOV state->tex_a[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); +//#endif + } + + + if (params->alphaMode & ((1 << 0) | (1 << 4))) + { + /*EBX = a_other*/ + switch (a_sel) + { + case A_SEL_ITER_A: + addbyte(0x8b); /*MOV EBX, state->ia*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + addbyte(0xc1); /*SAR EBX, 12*/ + addbyte(0xfb); + addbyte(12); + addbyte(0x0f); /*CMOVS EBX, EAX*/ + addbyte(0x48); + addbyte(0xd8); + addbyte(0x39); /*CMP EBX, EDX*/ + addbyte(0xd3); + addbyte(0x0f); /*CMOVA EBX, EDX*/ + addbyte(0x47); + addbyte(0xda); + break; + case A_SEL_TEX: + addbyte(0x8b); /*MOV EBX, state->tex_a*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + break; + case A_SEL_COLOR1: + addbyte(0x0f); /*MOVZX EBX, params->color1+3*/ + addbyte(0xb6); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, color1)+3); + break; + default: + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + break; + } + /*ECX = a_local*/ + switch (cca_localselect) + { + case CCA_LOCALSELECT_ITER_A: + if (a_sel == A_SEL_ITER_A) + { + addbyte(0x89); /*MOV ECX, EBX*/ + addbyte(0xd9); + } + else + { + addbyte(0x8b); /*MOV ECX, state->ia*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + addbyte(0xc1);/*SAR ECX, 12*/ + addbyte(0xf9); + addbyte(12); + addbyte(0x0f); /*CMOVS ECX, EAX*/ + addbyte(0x48); + addbyte(0xc8); + addbyte(0x39); /*CMP ECX, EDX*/ + addbyte(0xd1); + addbyte(0x0f); /*CMOVA ECX, EDX*/ + addbyte(0x47); + addbyte(0xca); + } + break; + case CCA_LOCALSELECT_COLOR0: + addbyte(0x0f); /*MOVZX ECX, params->color0+3*/ + addbyte(0xb6); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0)+3); + break; + case CCA_LOCALSELECT_ITER_Z: + addbyte(0x8b); /*MOV ECX, state->z*/ + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, z)); + if (a_sel != A_SEL_ITER_A) + { + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + addbyte(0xba); /*MOV EDX, 0xff*/ + addlong(0xff); + } + addbyte(0xc1);/*SAR ECX, 20*/ + addbyte(0xf9); + addbyte(20); + addbyte(0x0f); /*CMOVS ECX, EAX*/ + addbyte(0x48); + addbyte(0xc8); + addbyte(0x39); /*CMP ECX, EDX*/ + addbyte(0xd1); + addbyte(0x0f); /*CMOVA ECX, EDX*/ + addbyte(0x47); + addbyte(0xca); + break; + + default: + addbyte(0xb9); /*MOV ECX, 0xff*/ + addlong(0xff); + break; + } + + if (cca_zero_other) + { + addbyte(0x31); /*XOR EDX, EDX*/ + addbyte(0xd2); + } + else + { + addbyte(0x89); /*MOV EDX, EBX*/ + addbyte(0xda); + } + + if (cca_sub_clocal) + { + addbyte(0x29); /*SUB EDX, ECX*/ + addbyte(0xca); + } + } + + if (cc_sub_clocal || cc_mselect == 1 || cc_add == 1) + { + /*XMM1 = local*/ + if (!cc_localselect_override) + { + if (cc_localselect) + { + addbyte(0x66); /*MOVD XMM1, params->color0*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0)); + } + else + { + addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM1, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe1); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc9); + addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc9); + } + } + else + { + addbyte(0xf6); /*TEST state->tex_a, 0x80*/ + addbyte(0x87); + addbyte(0x23); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(0x80); + addbyte(0x74);/*JZ !cc_localselect*/ + addbyte(8+2); + addbyte(0x66); /*MOVD XMM1, params->color0*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, color0)); + /*JMP +*/ + /*!cc_localselect:*/ + addbyte(0xf3); /*MOVDQU XMM1, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRAD XMM1, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe1); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc9); + addbyte(0x66); /*PACKUSWB XMM1, XMM1*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc9); + } + addbyte(0x66); /*PUNPCKLBW XMM1, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xca); + } + if (!cc_zero_other) + { + if (_rgb_sel == CC_LOCALSELECT_ITER_RGB) + { + addbyte(0xf3); /*MOVDQU XMM0, ib*/ /* ir, ig and ib must be in same dqword!*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0x66); /*PSRLD XMM0, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xd0); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + } + else if (_rgb_sel == CC_LOCALSELECT_TEX) + { +#if 0 + addbyte(0xf3); /*MOVDQU XMM0, state->tex_b*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_b)); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); +#endif + } + else if (_rgb_sel == CC_LOCALSELECT_COLOR1) + { + addbyte(0x66); /*MOVD XMM0, params->color1*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x86); + addlong(offsetof(voodoo_params_t, color1)); + } + else + { + /*MOVD XMM0, src_r*/ + } + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + if (cc_sub_clocal) + { + addbyte(0x66); /*PSUBW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc1); + } + } + else + { + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + if (cc_sub_clocal) + { + addbyte(0x66); /*PSUBW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xc1); + } + } + + if (params->alphaMode & ((1 << 0) | (1 << 4))) + { + if (!(cca_mselect == 0 && cca_reverse_blend == 0)) + { + switch (cca_mselect) + { + case CCA_MSELECT_ALOCAL: + addbyte(0x89); /*MOV EAX, ECX*/ + addbyte(0xc8); + break; + case CCA_MSELECT_AOTHER: + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + break; + case CCA_MSELECT_ALOCAL2: + addbyte(0x89); /*MOV EAX, ECX*/ + addbyte(0xc8); + break; + case CCA_MSELECT_TEX: + addbyte(0x0f); /*MOVZX EAX, state->tex_a*/ + addbyte(0xb6); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, tex_a)); + break; + + case CCA_MSELECT_ZERO: + default: + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + break; + } + if (!cca_reverse_blend) + { + addbyte(0x35); /*XOR EAX, 0xff*/ + addlong(0xff); + } + addbyte(0x83); /*ADD EAX, 1*/ + addbyte(0xc0); + addbyte(1); + addbyte(0x0f); /*IMUL EDX, EAX*/ + addbyte(0xaf); + addbyte(0xd0); + addbyte(0xc1); /*SHR EDX, 8*/ + addbyte(0xea); + addbyte(8); + } + } + + addbyte(0x31); /*XOR EAX, EAX*/ + addbyte(0xc0); + + if (!(cc_mselect == 0 && cc_reverse_blend == 0) && cc_mselect == CC_MSELECT_AOTHER) + { + /*Copy a_other to XMM3 before it gets modified*/ + addbyte(0x66); /*MOVD XMM3, EDX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xda); + addbyte(0xf2); /*PSHUFLW XMM3, XMM3, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xdb); + addbyte(0x00); + } + + if (cca_add && (params->alphaMode & ((1 << 0) | (1 << 4)))) + { + addbyte(0x01); /*ADD EDX, ECX*/ + addbyte(0xca); + } + + addbyte(0x85); /*TEST EDX, EDX*/ + addbyte(0xd2); + addbyte(0x0f); /*CMOVS EDX, EAX*/ + addbyte(0x48); + addbyte(0xd0); + addbyte(0xb8); /*MOV EAX, 0xff*/ + addlong(0xff); + addbyte(0x81); /*CMP EDX, 0xff*/ + addbyte(0xfa); + addlong(0xff); + addbyte(0x0f); /*CMOVA EDX, EAX*/ + addbyte(0x47); + addbyte(0xd0); + + if (cc_invert_output) + { + addbyte(0x81); /*XOR EDX, 0xff*/ + addbyte(0xf2); + addlong(0xff); + } + + if (!(cc_mselect == 0 && cc_reverse_blend == 0)) + { + switch (cc_mselect) + { + case CC_MSELECT_ZERO: + addbyte(0x66); /*PXOR XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xdb); + break; + case CC_MSELECT_CLOCAL: + addbyte(0xf3); /*MOV XMM3, XMM1*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xd9); + break; + case CC_MSELECT_ALOCAL: + addbyte(0x66); /*MOVD XMM3, ECX*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0xd9); + addbyte(0xf2); /*PSHUFLW XMM3, XMM3, 0*/ + addbyte(0x0f); + addbyte(0x70); + addbyte(0xdb); + addbyte(0x00); + break; + case CC_MSELECT_AOTHER: + /*Handled above*/ + break; + case CC_MSELECT_TEX: + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 0*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(0); + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 1*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(1); + addbyte(0x66); /*PINSRW XMM3, state->tex_a, 2*/ + addbyte(0x0f); + addbyte(0xc4); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tex_a)); + addbyte(2); + addbyte(0x66); /*PSRLD XMM3, 12*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xd3); + addbyte(12); + addbyte(0x66); /*PACKSSDW XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xdb); + addbyte(0x66); /*PACKUSWB XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xdb); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + break; + } + addbyte(0xf3); /*MOV XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe0); + if (!cc_reverse_blend) + { + addbyte(0x66); /*PXOR XMM3, 0xff*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0x1d); + addlong(&xmm_ff_w); + } + addbyte(0x66); /*PADDW XMM3, 1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x1d); + addlong(&xmm_01_w); + addbyte(0x66); /*PMULLW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc3); + addbyte(0x66); /*PMULHW XMM4, XMM3*/ + addbyte(0x0f); + addbyte(0xe5); + addbyte(0xe3); + addbyte(0x66); /*PUNPCKLWD XMM0, XMM4*/ + addbyte(0x0f); + addbyte(0x61); + addbyte(0xc4); + addbyte(0x66); /*PSRLD XMM0, 8*/ + addbyte(0x0f); + addbyte(0x72); + addbyte(0xe0); + addbyte(8); + addbyte(0x66); /*PACKSSDW XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x6b); + addbyte(0xc0); + } + + if (cc_add == 1) + { + addbyte(0x66); /*PADDW XMM0, XMM1*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc1); + } + + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + + if (cc_invert_output) + { + addbyte(0x66); /*PXOR XMM0, 0xff*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0x05); + addlong(&xmm_ff_b); + } +//#if 0 +// addbyte(0x66); /*MOVD state->out[EDI], XMM0*/ +// addbyte(0x0f); +// addbyte(0x7e); +// addbyte(0x87); +// addlong(offsetof(voodoo_state_t, out)); + if (params->fogMode & FOG_ENABLE) + { + if (params->fogMode & FOG_CONSTANT) + { + addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, fogColor)); + addbyte(0x66); /*PADDUSB XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xdc); + addbyte(0xc3); +/* 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; */ + + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + + if (!(params->fogMode & FOG_ADD)) + { + addbyte(0x66); /*MOVD XMM3, params->fogColor[ESI]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x9e); + addlong(offsetof(voodoo_params_t, fogColor)); + addbyte(0x66); /*PUNPCKLBW XMM3, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xda); + } + else + { + addbyte(0x66); /*PXOR XMM3, XMM3*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xdb); + } + + if (!(params->fogMode & FOG_MULT)) + { + addbyte(0x66); /*PSUBW XMM3, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xd8); + } + + /*Divide by 2 to prevent overflow on multiply*/ + addbyte(0x66); /*PSRAW XMM3, 1*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xe3); + addbyte(1); + + if (params->fogMode & FOG_Z) + { + addbyte(0x8b); /*MOV EAX, state->z[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + addbyte(0xc1); /*SHR EAX, 12*/ + addbyte(0xe8); + addbyte(12); + addbyte(0x25); /*AND EAX, 0xff*/ + addlong(0xff); +// fog_a = (z >> 20) & 0xff; + } + else if (params->fogMode & FOG_ALPHA) + { + addbyte(0x8b); /*MOV EAX, state->ia[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, ia)); + addbyte(0x31); /*XOR EBX, EBX*/ + addbyte(0xdb); + addbyte(0xc1); /*SAR EAX, 12*/ + addbyte(0xf8); + addbyte(12); + addbyte(0x0f); /*CMOVS EAX, EBX*/ + addbyte(0x48); + addbyte(0xc3); + addbyte(0xbb); /*MOV EBX, 0xff*/ + addlong(0xff); + addbyte(0x3d); /*CMP EAX, 0xff*/ + addlong(0xff); + addbyte(0x0f); /*CMOVAE EAX, EBX*/ + addbyte(0x43); + addbyte(0xc3); +// fog_a = CLAMP(ia >> 12); + } + else + { + addbyte(0x8b); /*MOV EBX, state->w_depth[EDI]*/ + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, w_depth)); + addbyte(0x89); /*MOV EAX, EBX*/ + addbyte(0xd8); + addbyte(0xc1); /*SHR EBX, 10*/ + addbyte(0xeb); + addbyte(10); + addbyte(0xc1); /*SHR EAX, 2*/ + addbyte(0xe8); + addbyte(2); + addbyte(0x83); /*AND EBX, 0x3f*/ + addbyte(0xe3); + addbyte(0x3f); + addbyte(0x25); /*AND EAX, 0xff*/ + addlong(0xff); + addbyte(0xf6); /*MUL params->fogTable+1[ESI+EBX*2]*/ + addbyte(0xa4); + addbyte(0x5e); + addlong(offsetof(voodoo_params_t, fogTable)+1); + addbyte(0x0f); /*MOVZX EBX, params->fogTable[ESI+EBX*2]*/ + addbyte(0xb6); + addbyte(0x9c); + addbyte(0x5e); + addlong(offsetof(voodoo_params_t, fogTable)); + addbyte(0xc1); /*SHR EAX, 10*/ + addbyte(0xe8); + addbyte(10); + addbyte(0x01); /*ADD EAX, EBX*/ + addbyte(0xd8); + +/* int 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;*/ + } + addbyte(0x01); /*ADD EAX, EAX*/ + addbyte(0xc0); +// fog_a++; + + addbyte(0x66); /*PMULLW XMM3, alookup+4[EAX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x1c); + addbyte(0xc5); + addlong(((uintptr_t)alookup) + 16); + addbyte(0x66); /*PSRAW XMM3, 7*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xe3); + addbyte(7); +/* 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) + { + addbyte(0xf3); /*MOV XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc3); + } + else + { + addbyte(0x66); /*PADDW XMM0, XMM3*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc3); +/* src_r += fog_r; + src_g += fog_g; + src_b += fog_b;*/ + } + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + } + +/* src_r = CLAMP(src_r); + src_g = CLAMP(src_g); + src_b = CLAMP(src_b);*/ + } + + if ((params->alphaMode & 1) && (alpha_func != AFUNC_NEVER) && (alpha_func != AFUNC_ALWAYS)) + { + addbyte(0x0f); /*MOVZX ECX, params->alphaMode+3*/ + addbyte(0xb6); + addbyte(0x8e); + addlong(offsetof(voodoo_params_t, alphaMode) + 3); + addbyte(0x39); /*CMP EDX, ECX*/ + addbyte(0xca); + + switch (alpha_func) + { + case AFUNC_LESSTHAN: + addbyte(0x0f); /*JAE skip*/ + addbyte(0x83); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_EQUAL: + addbyte(0x0f); /*JNE skip*/ + addbyte(0x85); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_LESSTHANEQUAL: + addbyte(0x0f); /*JA skip*/ + addbyte(0x87); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_GREATERTHAN: + addbyte(0x0f); /*JBE skip*/ + addbyte(0x86); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_NOTEQUAL: + addbyte(0x0f); /*JE skip*/ + addbyte(0x84); + a_skip_pos = block_pos; + addlong(0); + break; + case AFUNC_GREATERTHANEQUAL: + addbyte(0x0f); /*JB skip*/ + addbyte(0x82); + a_skip_pos = block_pos; + addlong(0); + break; + } + } + else if ((params->alphaMode & 1) && (alpha_func == AFUNC_NEVER)) + { + addbyte(0xC3); /*RET*/ + } + + if (params->alphaMode & (1 << 4)) + { + addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x)); + addbyte(0x8b); /*MOV EBP, fb_mem*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, fb_mem)); + addbyte(0x01); /*ADD EDX, EDX*/ + addbyte(0xd2); + addbyte(0x0f); /*MOVZX EAX, [EBP+EAX*2]*/ + addbyte(0xb7); + addbyte(0x44); + addbyte(0x45); + addbyte(0); + addbyte(0x66); /*PUNPCKLBW XMM0, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xc2); + addbyte(0x66); /*MOVD XMM4, rgb565[EAX*4]*/ + addbyte(0x0f); + addbyte(0x6e); + addbyte(0x24); + addbyte(0x85); + addlong(rgb565); + addbyte(0x66); /*PUNPCKLBW XMM4, XMM2*/ + addbyte(0x0f); + addbyte(0x60); + addbyte(0xe2); + addbyte(0xf3); /*MOV XMM6, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xf4); + + switch (dest_afunc) + { + case AFUNC_AZERO: + addbyte(0x66); /*PXOR XMM4, XMM4*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xe4); + break; + case AFUNC_ASRC_ALPHA: + addbyte(0x66); /*PMULLW XMM4, alookup[EDX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x24); + addbyte(0xd5); + addlong(alookup); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_A_COLOR: + addbyte(0x66); /*PMULLW XMM4, XMM0*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xe0); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_ADST_ALPHA: + break; + case AFUNC_AONE: + break; + case AFUNC_AOMSRC_ALPHA: + addbyte(0x66); /*PMULLW XMM4, aminuslookup[EDX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x24); + addbyte(0xd5); + addlong(aminuslookup); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_AOM_COLOR: + addbyte(0xf3); /*MOVQ XMM5, xmm_ff_w*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x2d); + addlong(&xmm_ff_w); + addbyte(0x66); /*PSUBW XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xe8); + addbyte(0x66); /*PMULLW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xe5); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + break; + case AFUNC_AOMDST_ALPHA: + addbyte(0x66); /*PXOR XMM4, XMM4*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xe4); + break; + case AFUNC_ASATURATE: + addbyte(0x66); /*PMULLW XMM4, minus_254*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x25); + addlong(&minus_254); + addbyte(0xf3); /*MOVQ XMM5, XMM4*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xec); + addbyte(0x66); /*PADDW XMM4, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x25); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM4, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xe5); + addbyte(0x66); /*PSRLW XMM4, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd4); + addbyte(8); + } + + switch (src_afunc) + { + case AFUNC_AZERO: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case AFUNC_ASRC_ALPHA: + addbyte(0x66); /*PMULLW XMM0, alookup[EDX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x04); + addbyte(0xd5); + addlong(alookup); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_A_COLOR: + addbyte(0x66); /*PMULLW XMM0, XMM6*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc6); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_ADST_ALPHA: + break; + case AFUNC_AONE: + break; + case AFUNC_AOMSRC_ALPHA: + addbyte(0x66); /*PMULLW XMM0, aminuslookup[EDX*8]*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0x04); + addbyte(0xd5); + addlong(aminuslookup); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_AOM_COLOR: + addbyte(0xf3); /*MOVQ XMM5, xmm_ff_w*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x2d); + addlong(&xmm_ff_w); + addbyte(0x66); /*PSUBW XMM5, XMM6*/ + addbyte(0x0f); + addbyte(0xf9); + addbyte(0xee); + addbyte(0x66); /*PMULLW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xd5); + addbyte(0xc5); + addbyte(0xf3); /*MOVQ XMM5, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xe8); + addbyte(0x66); /*PADDW XMM0, alookup[1*8]*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0x05); + addlong((uint32_t)alookup + 16); + addbyte(0x66); /*PSRLW XMM5, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd5); + addbyte(8); + addbyte(0x66); /*PADDW XMM0, XMM5*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc5); + addbyte(0x66); /*PSRLW XMM0, 8*/ + addbyte(0x0f); + addbyte(0x71); + addbyte(0xd0); + addbyte(8); + break; + case AFUNC_AOMDST_ALPHA: + addbyte(0x66); /*PXOR XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0xef); + addbyte(0xc0); + break; + case AFUNC_ACOLORBEFOREFOG: + break; + } + + addbyte(0x66); /*PADDW XMM0, XMM4*/ + addbyte(0x0f); + addbyte(0xfd); + addbyte(0xc4); + + addbyte(0x66); /*PACKUSWB XMM0, XMM0*/ + addbyte(0x0f); + addbyte(0x67); + addbyte(0xc0); + } +//#endif + +// addbyte(0x8b); /*MOV EDX, x (ESP+12)*/ +// addbyte(0x54); +// addbyte(0x24); +// addbyte(12); + + + addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ + addbyte(0x97); + addlong(offsetof(voodoo_state_t, x)); + + addbyte(0x66); /*MOV EAX, XMM0*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xc0); + + if (params->fbzMode & FBZ_RGB_WMASK) + { +// addbyte(0x89); /*MOV state->rgb_out[EDI], EAX*/ +// addbyte(0x87); +// addlong(offsetof(voodoo_state_t, rgb_out)); + + if (dither) + { + addbyte(0x8b); /*MOV ESI, real_y (ESP+16)*/ + addbyte(0x74); + addbyte(0x24); + addbyte(16+16); + addbyte(0x0f); /*MOVZX EBX, AH*/ /*G*/ + addbyte(0xb6); + addbyte(0xdc); + if (dither2x2) + { + addbyte(0x83); /*AND EDX, 1*/ + addbyte(0xe2); + addbyte(1); + addbyte(0x83); /*AND ESI, 1*/ + addbyte(0xe6); + addbyte(1); + addbyte(0xc1); /*SHL EBX, 2*/ + addbyte(0xe3); + addbyte(2); + } + else + { + addbyte(0x83); /*AND EDX, 3*/ + addbyte(0xe2); + addbyte(3); + addbyte(0x83); /*AND ESI, 3*/ + addbyte(0xe6); + addbyte(3); + addbyte(0xc1); /*SHL EBX, 4*/ + addbyte(0xe3); + addbyte(4); + } + addbyte(0x0f); /*MOVZX ECX, AL*/ /*R*/ + addbyte(0xb6); + addbyte(0xc8); + if (dither2x2) + { + addbyte(0xc1); /*SHR EAX, 14*/ + addbyte(0xe8); + addbyte(14); + addbyte(0x8d); /*LEA ESI, EDX+ESI*2*/ + addbyte(0x34); + addbyte(0x72); + } + else + { + addbyte(0xc1); /*SHR EAX, 12*/ + addbyte(0xe8); + addbyte(12); + addbyte(0x8d); /*LEA ESI, EDX+ESI*4*/ + addbyte(0x34); + addbyte(0xb2); + } + addbyte(0x8b); /*MOV EDX, state->x[EDI]*/ + addbyte(0x97); + addlong(offsetof(voodoo_state_t, x)); + if (dither2x2) + { + addbyte(0xc1); /*SHL ECX, 2*/ + addbyte(0xe1); + addbyte(2); + addbyte(0x25); /*AND EAX, 0x3fc*/ /*B*/ + addlong(0x3fc); + } + else + { + addbyte(0xc1); /*SHL ECX, 4*/ + addbyte(0xe1); + addbyte(4); + addbyte(0x25); /*AND EAX, 0xff0*/ /*B*/ + addlong(0xff0); + } + addbyte(0x0f); /*MOVZX EBX, dither_g[EBX+ESI]*/ + addbyte(0xb6); + addbyte(0x9c); + addbyte(0x33); + addlong(dither2x2 ? dither_g2x2 : dither_g); + addbyte(0x0f); /*MOVZX ECX, dither_rb[ECX+ESI]*/ + addbyte(0xb6); + addbyte(0x8c); + addbyte(0x31); + addlong(dither2x2 ? dither_rb2x2 : dither_rb); + addbyte(0x0f); /*MOVZX EAX, dither_rb[EAX+ESI]*/ + addbyte(0xb6); + addbyte(0x84); + addbyte(0x30); + addlong(dither2x2 ? dither_rb2x2 : dither_rb); + addbyte(0xc1); /*SHL EBX, 5*/ + addbyte(0xe3); + addbyte(5); + addbyte(0xc1); /*SHL EAX, 11*/ + addbyte(0xe0); + addbyte(11); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + addbyte(0x09); /*OR EAX, ECX*/ + addbyte(0xc8); + } + else + { + addbyte(0x89); /*MOV EBX, EAX*/ + addbyte(0xc3); + addbyte(0x0f); /*MOVZX ECX, AH*/ + addbyte(0xb6); + addbyte(0xcc); + addbyte(0xc1); /*SHR EAX, 3*/ + addbyte(0xe8); + addbyte(3); + addbyte(0xc1); /*SHR EBX, 8*/ + addbyte(0xeb); + addbyte(8); + addbyte(0xc1); /*SHL ECX, 3*/ + addbyte(0xe1); + addbyte(3); + addbyte(0x81); /*AND EAX, 0x001f*/ + addbyte(0xe0); + addlong(0x001f); + addbyte(0x81); /*AND EBX, 0xf800*/ + addbyte(0xe3); + addlong(0xf800); + addbyte(0x81); /*AND ECX, 0x07e0*/ + addbyte(0xe1); + addlong(0x07e0); + addbyte(0x09); /*OR EAX, EBX*/ + addbyte(0xd8); + addbyte(0x09); /*OR EAX, ECX*/ + addbyte(0xc8); + } + addbyte(0x8b); /*MOV ESI, fb_mem*/ + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, fb_mem)); + addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x56); + } + + if (params->fbzMode & FBZ_DEPTH_WMASK) + { + addbyte(0x66); /*MOV AX, new_depth*/ + addbyte(0x8b); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, new_depth)); + addbyte(0x8b); /*MOV ESI, aux_mem*/ + addbyte(0xb7); + addlong(offsetof(voodoo_state_t, aux_mem)); + addbyte(0x66); /*MOV [ESI+EDX*2], AX*/ + addbyte(0x89); + addbyte(0x04); + addbyte(0x56); + } + + if (z_skip_pos) + *(uint32_t *)&code_block[z_skip_pos] = (block_pos - z_skip_pos) - 4; + if (a_skip_pos) + *(uint32_t *)&code_block[a_skip_pos] = (block_pos - a_skip_pos) - 4; + if (chroma_skip_pos) + *(uint32_t *)&code_block[chroma_skip_pos] = (block_pos - chroma_skip_pos) - 4; + + + addbyte(0x8b); /*MOV ESI, [ESP+8]*/ + addbyte(0x74); + addbyte(0x24); + addbyte(8+16); + + addbyte(0xf3); /*MOVDQU XMM1, state->ib[EDI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0xf3); /*MOVDQU XMM3, state->tmu0_s[EDI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tmu0_s)); + addbyte(0xf3); /*MOVQ XMM4, state->tmu0_w[EDI]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tmu0_w)); + addbyte(0xf3); /*MOVDQU XMM0, params->dBdX[ESI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0x86); + addlong(offsetof(voodoo_params_t, dBdX)); + addbyte(0x8b); /*MOV EAX, params->dZdX[ESI]*/ + addbyte(0x86); + addlong(offsetof(voodoo_params_t, dZdX)); + addbyte(0xf3); /*MOVDQU XMM5, params->tmu[0].dSdX[ESI]*/ + addbyte(0x0f); + addbyte(0x6f); + addbyte(0xae); + addlong(offsetof(voodoo_params_t, tmu[0].dSdX)); + addbyte(0xf3); /*MOVQ XMM6, params->tmu[0].dWdX[ESI]*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xb6); + addlong(offsetof(voodoo_params_t, tmu[0].dWdX)); + + if (state->xdir > 0) + { + addbyte(0x66); /*PADDD XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xfe); + addbyte(0xc8); + } + else + { + addbyte(0x66); /*PSUBD XMM1, XMM0*/ + addbyte(0x0f); + addbyte(0xfa); + addbyte(0xc8); + } + + addbyte(0xf3); /*MOVQ XMM0, state->w*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w)); + addbyte(0xf3); /*MOVDQU state->ib, XMM1*/ + addbyte(0x0f); + addbyte(0x7f); + addbyte(0x8f); + addlong(offsetof(voodoo_state_t, ib)); + addbyte(0xf3); /*MOVQ XMM7, params->dWdX*/ + addbyte(0x0f); + addbyte(0x7e); + addbyte(0xbe); + addlong(offsetof(voodoo_params_t, dWdX)); + + if (state->xdir > 0) + { + addbyte(0x66); /*PADDQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xdd); + addbyte(0x66); /*PADDQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xe6); + addbyte(0x66); /*PADDQ XMM0, XMM7*/ + addbyte(0x0f); + addbyte(0xd4); + addbyte(0xc7); + addbyte(0x01); /*ADD state->z[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + } + else + { + addbyte(0x66); /*PSUBQ XMM3, XMM5*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xdd); + addbyte(0x66); /*PSUBQ XMM4, XMM6*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xe6); + addbyte(0x66); /*PSUBQ XMM0, XMM7*/ + addbyte(0x0f); + addbyte(0xfb); + addbyte(0xc7); + addbyte(0x29); /*SUB state->z[EDI], EAX*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, z)); + } + + addbyte(0xf3); /*MOVDQU state->tmu0_s, XMM3*/ + addbyte(0x0f); + addbyte(0x7f); + addbyte(0x9f); + addlong(offsetof(voodoo_state_t, tmu0_s)); + addbyte(0x66); /*MOVQ state->tmu0_w, XMM4*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0xa7); + addlong(offsetof(voodoo_state_t, tmu0_w)); + addbyte(0x66); /*MOVQ state->w, XMM0*/ + addbyte(0x0f); + addbyte(0xd6); + addbyte(0x87); + addlong(offsetof(voodoo_state_t, w)); + + addbyte(0x83); /*ADD state->pixel_count[EDI], 1*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, pixel_count)); + addbyte(1); + + addbyte(0x8b); /*MOV EAX, state->x[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x)); + + if (state->xdir > 0) + { + addbyte(0x83); /*ADD state->x[EDI], 1*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x)); + addbyte(1); + } + else + { + addbyte(0x83); /*SUB state->x[EDI], 1*/ + addbyte(0xaf); + addlong(offsetof(voodoo_state_t, x)); + addbyte(1); + } + + addbyte(0x3b); /*CMP EAX, state->x2[EDI]*/ + addbyte(0x87); + addlong(offsetof(voodoo_state_t, x2)); + addbyte(0x0f); /*JNZ loop_jump_pos*/ + addbyte(0x85); + addlong(loop_jump_pos - (block_pos + 4)); + + addbyte(0x5b); /*POP EBX*/ + addbyte(0x5e); /*POP ESI*/ + addbyte(0x5f); /*POP EDI*/ + addbyte(0x5d); /*POP EBP*/ + + addbyte(0xC3); /*RET*/ +} +static 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; + int b = last_block[odd_even]; + voodoo_x86_data_t *data; + + for (c = 0; c < 8; c++) + { + data = &voodoo_x86_data[odd_even][b]; + + if (state->xdir == data->xdir && + params->alphaMode == data->alphaMode && + params->fbzMode == data->fbzMode && + params->fogMode == data->fogMode && + params->fbzColorPath == data->fbzColorPath && + (voodoo->trexInit1 & (1 << 18)) == data->trexInit1 && + params->textureMode == data->textureMode) + { + last_block[odd_even] = b; + return data->code_block; + } + + b = (b + 1) & 7; + } +voodoo_recomp++; + data = &voodoo_x86_data[odd_even][next_block_to_write[odd_even]]; +// code_block = data->code_block; + + voodoo_generate(data->code_block, voodoo, params, state, depth_op); + + data->xdir = state->xdir; + data->alphaMode = params->alphaMode; + data->fbzMode = params->fbzMode; + data->fogMode = params->fogMode; + data->fbzColorPath = params->fbzColorPath; + data->trexInit1 = voodoo->trexInit1 & (1 << 18); + data->textureMode = params->textureMode; + + next_block_to_write[odd_even] = (next_block_to_write[odd_even] + 1) & 7; + + return data->code_block; +} + +static void voodoo_codegen_init(voodoo_t *voodoo) +{ + int c; +#ifdef __linux__ + void *start; + size_t len; + long pagesize = sysconf(_SC_PAGESIZE); + long pagemask = ~(pagesize - 1); +#endif + +#if defined WIN32 || defined _WIN32 || defined _WIN32 + voodoo->codegen_data = VirtualAlloc(NULL, sizeof(voodoo_x86_data_t) * BLOCK_NUM, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else + voodoo->codegen_data = malloc(sizeof(voodoo_x86_data_t) * BLOCK_NUM); +#endif + +#ifdef __linux__ + start = (void *)((long)voodoo->codegen_data & pagemask); + len = (sizeof(voodoo_x86_data_t) * BLOCK_NUM) + pagesize) & pagemask; + if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + { + perror("mprotect"); + exit(-1); + } +#endif + + for (c = 0; c < 256; c++) + { + int d[4]; + int _ds = c & 0xf; + int dt = c >> 4; + + alookup[c] = _mm_set_epi32(0, 0, c | (c << 16), c | (c << 16)); + aminuslookup[c] = _mm_set_epi32(0, 0, (255-c) | ((255-c) << 16), (255-c) | ((255-c) << 16)); + + d[0] = (16 - _ds) * (16 - dt); + d[1] = _ds * (16 - dt); + d[2] = (16 - _ds) * dt; + d[3] = _ds * dt; + + bilinear_lookup[c*4] = _mm_set_epi32(0, 0, d[0] | (d[0] << 16), d[0] | (d[0] << 16)); + bilinear_lookup[c*4 + 1] = _mm_set_epi32(0, 0, d[1] | (d[1] << 16), d[1] | (d[1] << 16)); + bilinear_lookup[c*4 + 2] = _mm_set_epi32(0, 0, d[2] | (d[2] << 16), d[2] | (d[2] << 16)); + bilinear_lookup[c*4 + 3] = _mm_set_epi32(0, 0, d[3] | (d[3] << 16), d[3] | (d[3] << 16)); + } + alookup[256] = _mm_set_epi32(0, 0, 256 | (256 << 16), 256 | (256 << 16)); +} + +static void voodoo_codegen_close(voodoo_t *voodoo) +{ +#if defined WIN32 || defined _WIN32 || defined _WIN32 + VirtualFree(voodoo->codegen_data, 0, MEM_RELEASE); +#else + free(voodoo->codegen_data); +#endif +}