Added Voodoo Banshee emulation.

Known issues :
- Tiled framebuffer layout is not yet implemented. This causes horizontal
  offsets in some 2D 16bpp stuff (eg FMV in Tomb Raider 2, UI in Expendable)
- Fog is broken and currently disabled for Banshee
- Possibly at least 1 race in 2D blitter emulation
- A few things not yet emulated - overlay filters, some (rarely used) 2D
  blitter functions
This commit is contained in:
SarahW 2020-08-11 11:18:03 +01:00
commit 19a5dfa579
18 changed files with 3857 additions and 120 deletions

View file

@ -321,6 +321,7 @@ enum
GFX_CL_GD5428, /*Cirrus Logic CL-GD5428*/
GFX_IBM_GD5428, /*IBM 1MB SVGA Adapter/A*/
GFX_TVGA9000B, /*Trident TVGA9000B*/
GFX_BANSHEE,
GFX_MAX
};

View file

@ -667,36 +667,39 @@ void svga_poll(void *p)
svga->maback <<= 2;
svga->ca <<= 2;
svga->video_res_x = wx;
svga->video_res_y = wy + 1;
// pclog("%i %i %i\n", svga->video_res_x, svga->video_res_y, svga->lowres);
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) /*Text mode*/
if (!svga->video_res_override)
{
svga->video_res_x /= svga->char_width;
svga->video_res_y /= (svga->crtc[9] & 31) + 1;
svga->video_bpp = 0;
}
else
{
if (svga->crtc[9] & 0x80)
svga->video_res_y /= 2;
if (!(svga->crtc[0x17] & 2))
svga->video_res_y *= 4;
else if (!(svga->crtc[0x17] & 1))
svga->video_res_y *= 2;
svga->video_res_y /= (svga->crtc[9] & 31) + 1;
if (svga->render == svga_render_8bpp_lowres ||
svga->render == svga_render_15bpp_lowres ||
svga->render == svga_render_16bpp_lowres ||
svga->render == svga_render_24bpp_lowres ||
svga->render == svga_render_32bpp_lowres)
svga->video_res_x /= 2;
svga->video_res_x = wx;
svga->video_res_y = wy + 1;
switch (svga->gdcreg[5] & 0x60)
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) /*Text mode*/
{
case 0x00: svga->video_bpp = 4; break;
case 0x20: svga->video_bpp = 2; break;
case 0x40: case 0x60: svga->video_bpp = svga->bpp; break;
svga->video_res_x /= svga->char_width;
svga->video_res_y /= (svga->crtc[9] & 31) + 1;
svga->video_bpp = 0;
}
else
{
if (svga->crtc[9] & 0x80)
svga->video_res_y /= 2;
if (!(svga->crtc[0x17] & 2))
svga->video_res_y *= 4;
else if (!(svga->crtc[0x17] & 1))
svga->video_res_y *= 2;
svga->video_res_y /= (svga->crtc[9] & 31) + 1;
if (svga->render == svga_render_8bpp_lowres ||
svga->render == svga_render_15bpp_lowres ||
svga->render == svga_render_16bpp_lowres ||
svga->render == svga_render_24bpp_lowres ||
svga->render == svga_render_32bpp_lowres)
svga->video_res_x /= 2;
switch (svga->gdcreg[5] & 0x60)
{
case 0x00: svga->video_bpp = 4; break;
case 0x20: svga->video_bpp = 2; break;
case 0x40: case 0x60: svga->video_bpp = svga->bpp; break;
}
}
}
// if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2);
@ -767,7 +770,7 @@ int svga_init(svga_t *svga, void *p, int memsize,
svga->vram_display_mask = memsize - 1;
svga->vram_mask = memsize - 1;
svga->decode_mask = 0x7fffff;
svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x800000 >> 12);
svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x1000000 >> 12);
svga->recalctimings_ex = recalctimings_ex;
svga->video_in = video_in;
svga->video_out = video_out;

View file

@ -50,7 +50,7 @@ typedef struct svga_t
int set_reset_disabled;
uint8_t egapal[16];
uint32_t pallook[256];
uint32_t pallook[512];
PALETTE vgapal;
int ramdac_type;
@ -93,6 +93,8 @@ typedef struct svga_t
int fullchange;
int video_res_x, video_res_y, video_bpp;
int video_res_override; /*If clear then SVGA code will set above variables, if
set then card code will*/
int frames, fps;
struct

View file

@ -34,6 +34,9 @@ void voodoo_recalc(voodoo_t *voodoo)
{
uint32_t buffer_offset = ((voodoo->fbiInit2 >> 11) & 511) * 4096;
if (voodoo->type >= VOODOO_BANSHEE)
return;
voodoo->params.front_offset = voodoo->disp_buffer*buffer_offset;
voodoo->back_offset = voodoo->draw_buffer*buffer_offset;
@ -1050,6 +1053,114 @@ void *voodoo_card_init()
return voodoo;
}
void *voodoo_2d3d_card_init(int type)
{
int c;
voodoo_t *voodoo = malloc(sizeof(voodoo_t));
memset(voodoo, 0, sizeof(voodoo_t));
voodoo->bilinear_enabled = device_get_config_int("bilinear");
voodoo->scrfilter = 0;
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->type = type;
voodoo->dual_tmus = 0;
/*generate filter lookup tables*/
voodoo_generate_filter_v2(voodoo);
for (c = 0; c < TEX_CACHE_MAX; c++)
{
voodoo->texture_cache[0][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4);
voodoo->texture_cache[0][c].base = -1; /*invalid*/
voodoo->texture_cache[0][c].refcount = 0;
if (voodoo->dual_tmus)
{
voodoo->texture_cache[1][c].data = malloc((256*256 + 256*256 + 128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) * 4);
voodoo->texture_cache[1][c].base = -1; /*invalid*/
voodoo->texture_cache[1][c].refcount = 0;
}
}
timer_add(&voodoo->timer, voodoo_callback, voodoo, 1);
voodoo->fbiInit0 = 0;
voodoo->wake_fifo_thread = thread_create_event();
voodoo->wake_render_thread[0] = thread_create_event();
voodoo->wake_render_thread[1] = thread_create_event();
voodoo->wake_main_thread = thread_create_event();
voodoo->fifo_not_full_event = thread_create_event();
voodoo->render_not_full_event[0] = thread_create_event();
voodoo->render_not_full_event[1] = thread_create_event();
voodoo->fifo_thread = thread_create(voodoo_fifo_thread, voodoo);
voodoo->render_thread[0] = thread_create(voodoo_render_thread_1, voodoo);
if (voodoo->render_threads == 2)
voodoo->render_thread[1] = thread_create(voodoo_render_thread_2, voodoo);
timer_add(&voodoo->wake_timer, voodoo_wake_timer, (void *)voodoo, 0);
for (c = 0; c < 0x100; c++)
{
rgb332[c].r = c & 0xe0;
rgb332[c].g = (c << 3) & 0xe0;
rgb332[c].b = (c << 6) & 0xc0;
rgb332[c].r = rgb332[c].r | (rgb332[c].r >> 3) | (rgb332[c].r >> 6);
rgb332[c].g = rgb332[c].g | (rgb332[c].g >> 3) | (rgb332[c].g >> 6);
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++)
{
rgb565[c].r = (c >> 8) & 0xf8;
rgb565[c].g = (c >> 3) & 0xfc;
rgb565[c].b = (c << 3) & 0xf8;
rgb565[c].r |= (rgb565[c].r >> 5);
rgb565[c].g |= (rgb565[c].g >> 6);
rgb565[c].b |= (rgb565[c].b >> 5);
rgb565[c].a = 0xff;
argb1555[c].r = (c >> 7) & 0xf8;
argb1555[c].g = (c >> 2) & 0xf8;
argb1555[c].b = (c << 3) & 0xf8;
argb1555[c].r |= (argb1555[c].r >> 5);
argb1555[c].g |= (argb1555[c].g >> 5);
argb1555[c].b |= (argb1555[c].b >> 5);
argb1555[c].a = (c & 0x8000) ? 0xff : 0;
argb4444[c].a = (c >> 8) & 0xf0;
argb4444[c].r = (c >> 4) & 0xf0;
argb4444[c].g = c & 0xf0;
argb4444[c].b = (c << 4) & 0xf0;
argb4444[c].a |= (argb4444[c].a >> 4);
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
voodoo->disp_buffer = 0;
voodoo->draw_buffer = 1;
return voodoo;
}
void *voodoo_init()
{
voodoo_set_t *voodoo_set = malloc(sizeof(voodoo_set_t));
@ -1116,14 +1227,17 @@ void voodoo_card_close(voodoo_t *voodoo)
int c;
#ifndef RELEASE_BUILD
f = romfopen("texram.dmp", "wb");
fwrite(voodoo->tex_mem[0], voodoo->texture_size*1024*1024, 1, f);
fclose(f);
if (voodoo->dual_tmus)
if (voodoo->tex_mem[0])
{
f = romfopen("texram2.dmp", "wb");
fwrite(voodoo->tex_mem[1], voodoo->texture_size*1024*1024, 1, f);
f = romfopen("texram.dmp", "wb");
fwrite(voodoo->tex_mem[0], voodoo->texture_size*1024*1024, 1, f);
fclose(f);
if (voodoo->dual_tmus)
{
f = romfopen("texram2.dmp", "wb");
fwrite(voodoo->tex_mem[1], voodoo->texture_size*1024*1024, 1, f);
fclose(f);
}
}
#endif
@ -1148,10 +1262,13 @@ void voodoo_card_close(voodoo_t *voodoo)
#ifndef NO_CODEGEN
voodoo_codegen_close(voodoo);
#endif
free(voodoo->fb_mem);
if (voodoo->dual_tmus)
free(voodoo->tex_mem[1]);
free(voodoo->tex_mem[0]);
if (voodoo->type != VOODOO_BANSHEE && voodoo->fb_mem)
{
free(voodoo->fb_mem);
if (voodoo->dual_tmus)
free(voodoo->tex_mem[1]);
free(voodoo->tex_mem[0]);
}
free(voodoo);
}

1997
src/vid_voodoo_banshee.c Normal file

File diff suppressed because it is too large Load diff

3
src/vid_voodoo_banshee.h Normal file
View file

@ -0,0 +1,3 @@
extern device_t atrend_voodoo_banshee_device;
void banshee_set_overlay_addr(void *p, uint32_t addr);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
void voodoo_2d_reg_writel(voodoo_t *voodoo, uint32_t addr, uint32_t val);

View file

@ -2175,6 +2175,8 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
// addbyte(0x7e);
// addbyte(0x87);
// addlong(offsetof(voodoo_state_t, out));
if (voodoo->type != VOODOO_BANSHEE) /*HACK*/
{
if (params->fogMode & FOG_ENABLE)
{
if (params->fogMode & FOG_CONSTANT)
@ -2377,6 +2379,7 @@ static inline void voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo
src_g = CLAMP(src_g);
src_b = CLAMP(src_b);*/
}
}
if ((params->alphaMode & 1) && (alpha_func != AFUNC_NEVER) && (alpha_func != AFUNC_ALWAYS))
{

View file

@ -20,8 +20,9 @@
enum
{
VOODOO_1 = 0,
VOODOO_SB50 = 1,
VOODOO_2 = 2
VOODOO_SB50,
VOODOO_2,
VOODOO_BANSHEE
};
typedef union int_float
@ -62,11 +63,12 @@ typedef union rgba_u
enum
{
FIFO_INVALID = (0x00 << 24),
FIFO_WRITEL_REG = (0x01 << 24),
FIFO_WRITEW_FB = (0x02 << 24),
FIFO_WRITEL_FB = (0x03 << 24),
FIFO_WRITEL_TEX = (0x04 << 24)
FIFO_INVALID = (0x00 << 24),
FIFO_WRITEL_REG = (0x01 << 24),
FIFO_WRITEW_FB = (0x02 << 24),
FIFO_WRITEL_FB = (0x03 << 24),
FIFO_WRITEL_TEX = (0x04 << 24),
FIFO_WRITEL_2DREG = (0x05 << 24)
};
#define PARAM_SIZE 1024
@ -147,6 +149,7 @@ typedef struct voodoo_params_t
int tformat[2];
int clipLeft, clipRight, clipLowY, clipHighY;
int clipLeft1, clipRight1, clipLowY1, clipHighY1;
int sign;
@ -177,6 +180,12 @@ typedef struct vert_t
float sW1, sS1, sT1;
} vert_t;
typedef struct clip_t
{
int x_min, x_max;
int y_min, y_max;
} clip_t;
typedef struct voodoo_t
{
mem_mapping_t mapping;
@ -287,7 +296,7 @@ typedef struct voodoo_t
voodoo_params_t params_buffer[PARAM_SIZE];
volatile int params_read_idx[2], params_write_idx;
uint32_t cmdfifo_base, cmdfifo_end;
uint32_t cmdfifo_base, cmdfifo_end, cmdfifo_size;
int cmdfifo_rp;
volatile int cmdfifo_depth_rd, cmdfifo_depth_wr;
uint32_t cmdfifo_amin, cmdfifo_amax;
@ -296,6 +305,7 @@ typedef struct voodoo_t
vert_t verts[4];
int vertex_num;
int num_verticies;
int cull_pingpong;
int flush;
@ -332,6 +342,8 @@ typedef struct voodoo_t
uint32_t bltCommand;
uint32_t leftOverlayBuf;
struct
{
int dst_x, dst_y;
@ -341,6 +353,80 @@ typedef struct voodoo_t
int dst_stride;
} blt;
struct
{
uint32_t bresError0, bresError1;
uint32_t clip0Min, clip0Max;
uint32_t clip1Min, clip1Max;
uint32_t colorBack, colorFore;
uint32_t command, commandExtra;
uint32_t dstBaseAddr;
uint32_t dstFormat;
uint32_t dstSize;
uint32_t dstXY;
uint32_t rop;
uint32_t srcBaseAddr;
uint32_t srcFormat;
uint32_t srcSize;
uint32_t srcXY;
uint32_t colorPattern[64];
int bres_error_0, bres_error_1;
uint32_t colorPattern8[64], colorPattern16[64], colorPattern24[64];
int cur_x, cur_y;
uint32_t dstBaseAddr_tiled;
uint32_t dstColorkeyMin, dstColorkeyMax;
int dstSizeX, dstSizeY;
int dstX, dstY;
int dst_stride;
int patoff_x, patoff_y;
uint8_t rops[4];
uint32_t srcBaseAddr_tiled;
uint32_t srcColorkeyMin, srcColorkeyMax;
int srcSizeX, srcSizeY;
int srcX, srcY;
int src_stride;
int old_srcX;
/*Used for handling packed 24bpp host data*/
int host_data_remainder;
uint32_t old_host_data;
/*Polyfill coordinates*/
int lx[2], rx[2];
int ly[2], ry[2];
/*Polyfill state*/
int error[2];
int dx[2], dy[2];
int x_inc[2]; /*y_inc is always 1 for polyfill*/
int lx_cur, rx_cur;
clip_t clip[2];
uint8_t host_data[16384];
int host_data_count;
int host_data_size_src, host_data_size_dest;
int src_stride_src, src_stride_dest;
} banshee_blt;
struct
{
uint32_t vidOverlayStartCoords;
uint32_t vidOverlayEndScreenCoords;
uint32_t vidOverlayDudx, vidOverlayDudxOffsetSrcWidth;
uint32_t vidOverlayDvdy, vidOverlayDvdyOffset;
//uint32_t vidDesktopOverlayStride;
int start_x, start_y;
int end_x, end_y;
int size_x, size_y;
int overlay_bytes;
unsigned int src_y;
} overlay;
rgb_t clutData[33];
int clutData_dirty;
rgb_t clutData256[256];
@ -351,6 +437,9 @@ typedef struct voodoo_t
int fb_write_buffer, fb_draw_buffer;
int buffer_cutoff;
uint32_t tile_base, tile_stride;
int tile_stride_shift, tile_x;
int read_time, write_time, burst_time;
@ -364,7 +453,7 @@ typedef struct voodoo_t
uint16_t purpleline[256][3];
texture_t texture_cache[2][TEX_CACHE_MAX];
uint8_t texture_present[2][4096];
uint8_t texture_present[2][16384];
int texture_last_removed;
uint32_t palette_checksum[2];
@ -377,6 +466,11 @@ typedef struct voodoo_t
void *codegen_data;
struct voodoo_set_t *set;
uint8_t *vram, *changedvram;
void *p;
} voodoo_t;
typedef struct voodoo_set_t
@ -397,3 +491,5 @@ extern rgba8_t rgb332[0x100], ai44[0x100], rgb565[0x10000], argb1555[0x10000], a
void voodoo_recalc(voodoo_t *voodoo);
void voodoo_update_ncc(voodoo_t *voodoo, int tmu);
void *voodoo_2d3d_card_init(int type);
void voodoo_card_close(voodoo_t *voodoo);

View file

@ -8,6 +8,7 @@
#include "vid_svga.h"
#include "vid_voodoo.h"
#include "vid_voodoo_common.h"
#include "vid_voodoo_banshee_blitter.h"
#include "vid_voodoo_fb.h"
#include "vid_voodoo_fifo.h"
#include "vid_voodoo_reg.h"
@ -205,6 +206,18 @@ void voodoo_fifo_thread(void *param)
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
case FIFO_WRITEL_2DREG:
while ((fifo->addr_type & FIFO_TYPE) == FIFO_WRITEL_2DREG)
{
voodoo_2d_reg_writel(voodoo, fifo->addr_type & FIFO_ADDR, fifo->val);
fifo->addr_type = FIFO_INVALID;
voodoo->fifo_read_idx++;
fifo = &voodoo->fifo[voodoo->fifo_read_idx & FIFO_MASK];
}
break;
default:
fatal("Unknown fifo entry %08x\n", fifo->addr_type);
}
if (FIFO_ENTRIES > 0xe000)
@ -226,7 +239,7 @@ void voodoo_fifo_thread(void *param)
int num_verticies;
int v_num;
// pclog(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp);
// pclog(" CMDFIFO header %08x at %08x\n", header, voodoo->cmdfifo_rp);
switch (header & 7)
{
@ -254,17 +267,48 @@ void voodoo_fifo_thread(void *param)
while (num--)
{
uint32_t val = cmdfifo_get(voodoo);
if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
(addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
voodoo->cmd_written_fifo++;
if ((addr & (1 << 13)) && voodoo->type == VOODOO_BANSHEE)
{
// if (voodoo->type != VOODOO_BANSHEE)
// fatal("CMDFIFO1: Not Banshee\n");
// pclog("CMDFIFO1: write %08x %08x\n", addr, val);
voodoo_2d_reg_writel(voodoo, addr, val);
}
else
{
if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
(addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
voodoo->cmd_written_fifo++;
voodoo_reg_writel(addr, val, voodoo);
if (voodoo->type == VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD)
voodoo->cmd_written_fifo++;
voodoo_reg_writel(addr, val, voodoo);
}
if (header & (1 << 15))
addr += 4;
}
break;
case 2:
if (voodoo->type != VOODOO_BANSHEE)
fatal("CMDFIFO2: Not Banshee\n");
mask = (header >> 3);
addr = 8;
while (mask)
{
if (mask & 1)
{
uint32_t val = cmdfifo_get(voodoo);
voodoo_2d_reg_writel(voodoo, addr, val);
}
addr += 4;
mask >>= 1;
}
break;
case 3:
num = (header >> 29) & 7;
mask = header;//(header >> 10) & 0xff;
@ -338,11 +382,24 @@ void voodoo_fifo_thread(void *param)
if (mask & 1)
{
uint32_t val = cmdfifo_get(voodoo);
if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
(addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
voodoo->cmd_written_fifo++;
voodoo_reg_writel(addr, val, voodoo);
if ((addr & (1 << 13)) && voodoo->type == VOODOO_BANSHEE)
{
if (voodoo->type != VOODOO_BANSHEE)
fatal("CMDFIFO1: Not Banshee\n");
// pclog("CMDFIFO1: write %08x %08x\n", addr, val);
voodoo_2d_reg_writel(voodoo, addr, val);
}
else
{
if ((addr & 0x3ff) == SST_triangleCMD || (addr & 0x3ff) == SST_ftriangleCMD ||
(addr & 0x3ff) == SST_fastfillCMD || (addr & 0x3ff) == SST_nopCMD)
voodoo->cmd_written_fifo++;
if (voodoo->type == VOODOO_BANSHEE && (addr & 0x3ff) == SST_swapbufferCMD)
voodoo->cmd_written_fifo++;
voodoo_reg_writel(addr, val, voodoo);
}
}
addr += 4;
@ -353,13 +410,29 @@ void voodoo_fifo_thread(void *param)
break;
case 5:
if (header & 0x3fc0000)
fatal("CMDFIFO packet 5 has byte disables set %08x\n", header);
// if (header & 0x3fc00000)
// fatal("CMDFIFO packet 5 has byte disables set %08x\n", header);
num = (header >> 3) & 0x7ffff;
addr = cmdfifo_get(voodoo) & 0xffffff;
if (!num)
num = 1;
// pclog("CMDFIFO5 addr=%08x num=%i\n", addr, num);
switch (header >> 30)
{
case 0: /*Linear framebuffer (Banshee)*/
if (voodoo->texture_present[0][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
{
// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);
flush_texture_cache(voodoo, addr & voodoo->texture_mask, 0);
}
while (num--)
{
uint32_t val = cmdfifo_get(voodoo);
if (addr <= voodoo->fb_mask)
*(uint32_t *)&voodoo->fb_mem[addr] = val;
addr += 4;
}
break;
case 2: /*Framebuffer*/
while (num--)
{
@ -383,7 +456,7 @@ void voodoo_fifo_thread(void *param)
break;
default:
pclog("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
fatal("Bad CMDFIFO packet %08x %08x\n", header, voodoo->cmdfifo_rp);
}
end_time = timer_read();

View file

@ -8,6 +8,7 @@
#include "vid_svga.h"
#include "vid_voodoo.h"
#include "vid_voodoo_common.h"
#include "vid_voodoo_banshee.h"
#include "vid_voodoo_blitter.h"
#include "vid_voodoo_dither.h"
#include "vid_voodoo_fifo.h"
@ -47,7 +48,38 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
switch (addr)
{
case SST_swapbufferCMD:
// pclog(" start swap buffer command\n");
if (voodoo->type == VOODOO_BANSHEE)
{
// pclog("swapbufferCMD %08x %08x\n", val, voodoo->leftOverlayBuf);
voodoo_wait_for_render_thread_idle(voodoo);
if (!(val & 1))
{
banshee_set_overlay_addr(voodoo->p, voodoo->leftOverlayBuf);
if (voodoo->swap_count > 0)
voodoo->swap_count--;
voodoo->frame_count++;
}
else if (TRIPLE_BUFFER)
{
if (voodoo->swap_pending)
voodoo_wait_for_swap_complete(voodoo);
voodoo->swap_interval = (val >> 1) & 0xff;
voodoo->swap_offset = voodoo->leftOverlayBuf;
voodoo->swap_pending = 1;
}
else
{
voodoo->swap_interval = (val >> 1) & 0xff;
voodoo->swap_offset = voodoo->leftOverlayBuf;
voodoo->swap_pending = 1;
voodoo_wait_for_swap_complete(voodoo);
}
voodoo->cmd_read++;
break;
}
if (TRIPLE_BUFFER)
{
@ -63,7 +95,7 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
voodoo->params.swapbufferCMD = val;
pclog("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0);
// pclog("Swap buffer %08x %d %p %i\n", val, voodoo->swap_count, &voodoo->swap_count, (voodoo == voodoo->set->voodoos[1]) ? 1 : 0);
// voodoo->front_offset = params->front_offset;
voodoo_wait_for_render_thread_idle(voodoo);
if (!(val & 1))
@ -503,6 +535,52 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
voodoo->params.fogTable[addr+1].dfog = (val >> 16) & 0xff;
voodoo->params.fogTable[addr+1].fog = (val >> 24) & 0xff;
break;
case SST_clipLeftRight1:
if (voodoo->type == VOODOO_BANSHEE)
{
voodoo->params.clipRight1 = val & 0xfff;
voodoo->params.clipLeft1 = (val >> 16) & 0xfff;
}
break;
case SST_clipTopBottom1:
if (voodoo->type == VOODOO_BANSHEE)
{
voodoo->params.clipHighY1 = val & 0xfff;
voodoo->params.clipLowY1 = (val >> 16) & 0xfff;
}
break;
case SST_colBufferAddr:
if (voodoo->type == VOODOO_BANSHEE)
{
voodoo->params.draw_offset = val & 0xfffff0;
voodoo->fb_write_offset = voodoo->params.draw_offset;
// pclog("colorBufferAddr=%06x\n", voodoo->params.draw_offset);
}
break;
case SST_colBufferStride:
if (voodoo->type == VOODOO_BANSHEE)
{
if (val & (1 << 15))
{
voodoo->row_width = (val & 0x7f) * 128;
// pclog("colBufferStride = %i bytes, tiled\n", voodoo->row_width);
}
else
{
voodoo->row_width = val & 0x3fff;
// pclog("colBufferStride = %i bytes, linear\n", voodoo->row_width);
}
}
break;
case SST_auxBufferAddr:
if (voodoo->type == VOODOO_BANSHEE)
{
voodoo->params.aux_offset = val & 0xfffff0;
// pclog("auxBufferAddr=%06x\n", voodoo->params.aux_offset);
}
break;
case SST_clutData:
voodoo->clutData[(val >> 24) & 0x3f].b = val & 0xff;
@ -590,6 +668,7 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
voodoo->verts[0] = voodoo->verts[3];
voodoo->vertex_num = 1;
voodoo->num_verticies = 1;
voodoo->cull_pingpong = 0;
break;
case SST_sDrawTriCMD:
// pclog("sDrawTriCMD %i %i %i\n", voodoo->num_verticies, voodoo->vertex_num, voodoo->sSetupMode & SETUPMODE_STRIP_MODE);
@ -603,6 +682,7 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
{
// pclog("triangle_setup\n");
voodoo_triangle_setup(voodoo);
voodoo->cull_pingpong = !voodoo->cull_pingpong;
voodoo->num_verticies = 2;
}
@ -734,48 +814,73 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
case SST_texBaseAddr:
if (chip & CHIP_TREX0)
{
voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3;
if (voodoo->type == VOODOO_BANSHEE)
voodoo->params.texBaseAddr[0] = val & 0xfffff0;
else
voodoo->params.texBaseAddr[0] = (val & 0x7ffff) << 3;
// pclog("texBaseAddr = %08x %08x\n", voodoo->params.texBaseAddr[0], val);
voodoo_recalc_tex(voodoo, 0);
}
if (chip & CHIP_TREX1)
{
voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3;
if (voodoo->type == VOODOO_BANSHEE)
voodoo->params.texBaseAddr[1] = val & 0xfffff0;
else
voodoo->params.texBaseAddr[1] = (val & 0x7ffff) << 3;
voodoo_recalc_tex(voodoo, 1);
}
break;
case SST_texBaseAddr1:
if (chip & CHIP_TREX0)
{
voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3;
if (voodoo->type == VOODOO_BANSHEE)
voodoo->params.texBaseAddr1[0] = val & 0xfffff0;
else
voodoo->params.texBaseAddr1[0] = (val & 0x7ffff) << 3;
voodoo_recalc_tex(voodoo, 0);
}
if (chip & CHIP_TREX1)
{
voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3;
if (voodoo->type == VOODOO_BANSHEE)
voodoo->params.texBaseAddr1[1] = val & 0xfffff0;
else
voodoo->params.texBaseAddr1[1] = (val & 0x7ffff) << 3;
voodoo_recalc_tex(voodoo, 1);
}
break;
case SST_texBaseAddr2:
if (chip & CHIP_TREX0)
{
voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3;
if (voodoo->type == VOODOO_BANSHEE)
voodoo->params.texBaseAddr2[0] = val & 0xfffff0;
else
voodoo->params.texBaseAddr2[0] = (val & 0x7ffff) << 3;
voodoo_recalc_tex(voodoo, 0);
}
if (chip & CHIP_TREX1)
{
voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3;
if (voodoo->type == VOODOO_BANSHEE)
voodoo->params.texBaseAddr2[1] = val & 0xfffff0;
else
voodoo->params.texBaseAddr2[1] = (val & 0x7ffff) << 3;
voodoo_recalc_tex(voodoo, 1);
}
break;
case SST_texBaseAddr38:
if (chip & CHIP_TREX0)
{
voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3;
if (voodoo->type == VOODOO_BANSHEE)
voodoo->params.texBaseAddr38[0] = val & 0xfffff0;
else
voodoo->params.texBaseAddr38[0] = (val & 0x7ffff) << 3;
voodoo_recalc_tex(voodoo, 0);
}
if (chip & CHIP_TREX1)
{
voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3;
if (voodoo->type == VOODOO_BANSHEE)
voodoo->params.texBaseAddr38[1] = val & 0xfffff0;
else
voodoo->params.texBaseAddr38[1] = (val & 0x7ffff) << 3;
voodoo_recalc_tex(voodoo, 1);
}
break;
@ -1136,5 +1241,10 @@ void voodoo_reg_writel(uint32_t addr, uint32_t val, void *p)
case SST_userIntrCMD:
fatal("userIntrCMD write %08x from FIFO\n", val);
break;
case SST_leftOverlayBuf:
voodoo->leftOverlayBuf = val;
break;
}
}

View file

@ -144,6 +144,14 @@ enum
SST_cmdFifoAMax = 0x1f0,
SST_cmdFifoDepth = 0x1f4,
SST_cmdFifoHoles = 0x1f8,
SST_colBufferAddr = 0x1ec, /*Banshee*/
SST_colBufferStride = 0x1f0, /*Banshee*/
SST_auxBufferAddr = 0x1f4, /*Banshee*/
SST_auxBufferStride = 0x1f8, /*Banshee*/
SST_clipLeftRight1 = 0x200, /*Banshee*/
SST_clipTopBottom1 = 0x204, /*Banshee*/
SST_fbiInit4 = 0x200,
SST_vRetrace = 0x204,
@ -164,7 +172,10 @@ enum
SST_fbiInit5 = 0x244,
SST_fbiInit6 = 0x248,
SST_fbiInit7 = 0x24c,
SST_swapPending = 0x24c, /*Banshee*/
SST_leftOverlayBuf = 0x250, /*Banshee*/
SST_sSetupMode = 0x260,
SST_sVx = 0x264,
SST_sVy = 0x268,

View file

@ -1266,8 +1266,11 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood
if (cca_invert_output)
src_a ^= 0xff;
if (params->fogMode & FOG_ENABLE)
APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w);
if (voodoo->type != VOODOO_BANSHEE) /*HACK*/
{
if (params->fogMode & FOG_ENABLE)
APPLY_FOG(src_r, src_g, src_b, state->z, state->ia, state->w);
}
if (params->alphaMode & 1)
ALPHA_TEST(src_a);

View file

@ -15,7 +15,6 @@ void voodoo_triangle_setup(voodoo_t *voodoo)
float dxAB, dxBC, dyAB, dyBC;
float area;
int va = 0, vb = 1, vc = 2;
int reverse_cull = 0;
vert_t verts[3];
verts[0] = voodoo->verts[0];
@ -40,7 +39,6 @@ void voodoo_triangle_setup(voodoo_t *voodoo)
va = 0;
vb = 2;
vc = 1;
reverse_cull = 1;
}
else
{
@ -62,7 +60,6 @@ void voodoo_triangle_setup(voodoo_t *voodoo)
va = 1;
vb = 0;
vc = 2;
reverse_cull = 1;
}
else
{
@ -78,10 +75,35 @@ void voodoo_triangle_setup(voodoo_t *voodoo)
va = 2;
vb = 1;
vc = 0;
reverse_cull = 1;
}
}
dxAB = verts[0].sVx - verts[1].sVx;
dxBC = verts[1].sVx - verts[2].sVx;
dyAB = verts[0].sVy - verts[1].sVy;
dyBC = verts[1].sVy - verts[2].sVy;
area = dxAB * dyBC - dxBC * dyAB;
if (area == 0.0)
return;
if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE)
{
int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN;
int sign = (area < 0.0);
if ((voodoo->sSetupMode & (SETUPMODE_CULLING_ENABLE | SETUPMODE_DISABLE_PINGPONG))
== SETUPMODE_CULLING_ENABLE && voodoo->cull_pingpong)
cull_sign = !cull_sign;
if (cull_sign && sign)
return;
if (!cull_sign && !sign)
return;
}
dxAB = verts[va].sVx - verts[vb].sVx;
dxBC = verts[vb].sVx - verts[vc].sVx;
dyAB = verts[va].sVy - verts[vb].sVy;
@ -89,36 +111,12 @@ void voodoo_triangle_setup(voodoo_t *voodoo)
area = dxAB * dyBC - dxBC * dyAB;
if (area == 0.0)
{
if ((voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE) &&
!(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG))
voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN;
return;
}
dxAB /= area;
dxBC /= area;
dyAB /= area;
dyBC /= area;
if (voodoo->sSetupMode & SETUPMODE_CULLING_ENABLE)
{
int cull_sign = voodoo->sSetupMode & SETUPMODE_CULLING_SIGN;
int sign = (area < 0.0);
if (!(voodoo->sSetupMode & SETUPMODE_DISABLE_PINGPONG))
voodoo->sSetupMode ^= SETUPMODE_CULLING_SIGN;
if (reverse_cull)
sign = !sign;
if (cull_sign && sign)
return;
if (!cull_sign && !sign)
return;
}
voodoo->params.vertexAx = (int32_t)(int16_t)((int32_t)(verts[va].sVx * 16.0f) & 0xffff);
voodoo->params.vertexAy = (int32_t)(int16_t)((int32_t)(verts[va].sVy * 16.0f) & 0xffff);

View file

@ -157,7 +157,7 @@ void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
return;
}
}
/*Texture not found, search for unused texture*/
do
{
@ -469,7 +469,7 @@ void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu)
voodoo->texture_cache[tmu][c].refcount++;
}
static void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu)
void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu)
{
int wait_for_idle = 0;
int c;
@ -531,30 +531,41 @@ void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p)
if (tmu && !voodoo->dual_tmus)
return;
// pclog("voodoo_tex_writel : %08X %08X %i\n", addr, val, voodoo->params.tformat);
lod = (addr >> 17) & 0xf;
t = (addr >> 9) & 0xff;
if (voodoo->params.tformat[tmu] & 8)
s = (addr >> 1) & 0xfe;
else
if (voodoo->type != VOODOO_BANSHEE)
{
if (voodoo->params.textureMode[tmu] & (1 << 31))
s = addr & 0xfc;
if (!(voodoo->params.tformat[tmu] & 8) && voodoo->type == VOODOO_BANSHEE)
{
lod = (addr >> 16) & 0xf;
t = (addr >> 8) & 0xff;
}
else
s = (addr >> 1) & 0xfc;
{
lod = (addr >> 17) & 0xf;
t = (addr >> 9) & 0xff;
}
if (voodoo->params.tformat[tmu] & 8)
s = (addr >> 1) & 0xfe;
else
{
if ((voodoo->params.textureMode[tmu] & (1 << 31)) || voodoo->type == VOODOO_BANSHEE)
s = addr & 0xfc;
else
s = (addr >> 1) & 0xfc;
}
if (lod > LOD_MAX)
return;
// if (addr >= 0x200000)
// return;
if (voodoo->params.tformat[tmu] & 8)
addr = voodoo->params.tex_base[tmu][lod] + s*2 + (t << voodoo->params.tex_shift[tmu][lod])*2;
else
addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]);
}
if (lod > LOD_MAX)
return;
// if (addr >= 0x200000)
// return;
if (voodoo->params.tformat[tmu] & 8)
addr = voodoo->params.tex_base[tmu][lod] + s*2 + (t << voodoo->params.tex_shift[tmu][lod])*2;
else
addr = voodoo->params.tex_base[tmu][lod] + s + (t << voodoo->params.tex_shift[tmu][lod]);
addr = (addr & 0x1ffffc) + voodoo->params.tex_base[tmu][lod];
if (voodoo->texture_present[tmu][(addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT])
{
// pclog("texture_present at %08x %i\n", addr, (addr & voodoo->texture_mask) >> TEX_DIRTY_SHIFT);

View file

@ -16,3 +16,4 @@ static const uint32_t texture_offset[LOD_MAX+3] =
void voodoo_recalc_tex(voodoo_t *voodoo, int tmu);
void voodoo_use_texture(voodoo_t *voodoo, voodoo_params_t *params, int tmu);
void voodoo_tex_writel(uint32_t addr, uint32_t val, void *p);
void flush_texture_cache(voodoo_t *voodoo, uint32_t dirty_addr, int tmu);

View file

@ -50,6 +50,7 @@
#include "vid_wy700.h"
#include "vid_t3100e.h"
#include "vid_t1000.h"
#include "vid_voodoo_banshee.h"
enum
{
@ -82,6 +83,7 @@ typedef struct
static VIDEO_CARD video_cards[] =
{
{"A-Trend Helios 3D (Voodoo Banshee)", "banshee", &atrend_voodoo_banshee_device, GFX_BANSHEE, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
{"Acumos AVGA2 / Cirrus Logic CL-GD5402", "avga2", &avga2_device, GFX_AVGA2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_ISA, 3, 3, 6, 5, 5, 10}},
{"ATI Graphics Pro Turbo (Mach64 GX)", "mach64gx", &mach64gx_device, GFX_MACH64GX, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},
{"ATI Video Xpression (Mach64 VT2)", "mach64vt2", &mach64vt2_device, GFX_MACH64VT2, VIDEO_FLAG_TYPE_SPECIAL, {VIDEO_BUS, 2, 2, 1, 20, 20, 21}},