ViRGE S3D triangle rendering now uses worker thread.
Fixed clipping bug on ViRGE. Fixed status window crash.
This commit is contained in:
parent
67cb9e3781
commit
1c3d1039ff
22 changed files with 462 additions and 305 deletions
|
|
@ -95,18 +95,12 @@ char *device_add_status_info(char *s, int max_len)
|
|||
{
|
||||
int c;
|
||||
|
||||
s += strlen(s);
|
||||
|
||||
for (c = 0; c < 256; c++)
|
||||
{
|
||||
if (devices[c] != NULL)
|
||||
{
|
||||
if (devices[c]->add_status_info != NULL)
|
||||
{
|
||||
int len = devices[c]->add_status_info(s, max_len, device_priv[c]);
|
||||
s += len;
|
||||
max_len -= len;
|
||||
}
|
||||
devices[c]->add_status_info(s, max_len, device_priv[c]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ typedef struct device_t
|
|||
int (*available)();
|
||||
void (*speed_changed)(void *p);
|
||||
void (*force_redraw)(void *p);
|
||||
int (*add_status_info)(char *s, int max_len, void *p);
|
||||
void (*add_status_info)(char *s, int max_len, void *p);
|
||||
device_config_t *config;
|
||||
} device_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ void sb_speed_changed(void *p)
|
|||
sb_dsp_speed_changed(&sb->dsp);
|
||||
}
|
||||
|
||||
int sb_add_status_info(char *s, int max_len, void *p)
|
||||
void sb_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
sb_t *sb = (sb_t *)p;
|
||||
|
||||
|
|
|
|||
|
|
@ -910,10 +910,9 @@ void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r)
|
|||
*r = dsp->sbdatr;
|
||||
}
|
||||
|
||||
int sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp)
|
||||
void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp)
|
||||
{
|
||||
char temps[128];
|
||||
int cur_len = max_len;
|
||||
int len;
|
||||
int freq;
|
||||
|
||||
|
|
@ -967,15 +966,11 @@ int sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp)
|
|||
}
|
||||
else
|
||||
strcpy(temps, "SB playback stopped\n");
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
strncat(s, temps, max_len);
|
||||
|
||||
if ((dsp->sb_8_enable && dsp->sb_8_output) || (dsp->sb_16_enable && dsp->sb_16_output))
|
||||
{
|
||||
sprintf(temps, "SB playback frequency : %iHz\n", freq);
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
strncat(s, temps, max_len);
|
||||
}
|
||||
|
||||
return max_len - cur_len;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,4 +68,4 @@ void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r);
|
|||
|
||||
void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo);
|
||||
|
||||
int sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp);
|
||||
void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp);
|
||||
|
|
|
|||
|
|
@ -171,11 +171,11 @@ void ati18800_force_redraw(void *p)
|
|||
ati18800->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int ati18800_add_status_info(char *s, int max_len, void *p)
|
||||
void ati18800_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
ati18800_t *ati18800 = (ati18800_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &ati18800->svga);
|
||||
svga_add_status_info(s, max_len, &ati18800->svga);
|
||||
}
|
||||
|
||||
device_t ati18800_device =
|
||||
|
|
|
|||
|
|
@ -192,11 +192,11 @@ void ati28800_force_redraw(void *p)
|
|||
ati28800->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int ati28800_add_status_info(char *s, int max_len, void *p)
|
||||
void ati28800_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
ati28800_t *ati28800 = (ati28800_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &ati28800->svga);
|
||||
svga_add_status_info(s, max_len, &ati28800->svga);
|
||||
}
|
||||
|
||||
device_t ati28800_device =
|
||||
|
|
|
|||
|
|
@ -2278,10 +2278,9 @@ void mach64_force_redraw(void *p)
|
|||
mach64->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int mach64_add_status_info(char *s, int max_len, void *p)
|
||||
void mach64_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
mach64_t *mach64 = (mach64_t *)p;
|
||||
int cur_len = max_len;
|
||||
|
||||
if (((mach64->crtc_gen_cntl >> 24) & 3) == 3)
|
||||
{
|
||||
|
|
@ -2289,8 +2288,7 @@ int mach64_add_status_info(char *s, int max_len, void *p)
|
|||
char temps[128];
|
||||
int bpp = 4;
|
||||
|
||||
strncat(s, "Mach64 in native mode\n", cur_len);
|
||||
cur_len -= strlen("Mach64 in native mode\n");
|
||||
strncat(s, "Mach64 in native mode\n", max_len);
|
||||
|
||||
switch ((mach64->crtc_gen_cntl >> 8) & 7)
|
||||
{
|
||||
|
|
@ -2303,25 +2301,19 @@ int mach64_add_status_info(char *s, int max_len, void *p)
|
|||
}
|
||||
|
||||
sprintf(temps, "Mach64 colour depth : %i bpp\n", bpp);
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
strncat(s, temps, max_len);
|
||||
|
||||
sprintf(temps, "Mach64 resolution : %i x %i\n", svga->hdisp, svga->dispend);
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
strncat(s, temps, max_len);
|
||||
|
||||
sprintf(temps, "Mach64 refresh rate : %i Hz\n\n", svga->frames);
|
||||
svga->frames = 0;
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
|
||||
return max_len - cur_len;
|
||||
strncat(s, temps, max_len);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncat(s, "Mach64 in SVGA mode\n", cur_len);
|
||||
cur_len -= strlen("Mach64 in SVGA mode\n");
|
||||
return svga_add_status_info(s, cur_len, &mach64->svga);
|
||||
strncat(s, "Mach64 in SVGA mode\n", max_len);
|
||||
svga_add_status_info(s, max_len, &mach64->svga);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -870,11 +870,11 @@ void gd5429_force_redraw(void *p)
|
|||
gd5429->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int gd5429_add_status_info(char *s, int max_len, void *p)
|
||||
void gd5429_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
gd5429_t *gd5429 = (gd5429_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &gd5429->svga);
|
||||
svga_add_status_info(s, max_len, &gd5429->svga);
|
||||
}
|
||||
|
||||
device_t gd5429_device =
|
||||
|
|
|
|||
|
|
@ -174,11 +174,11 @@ void et4000_force_redraw(void *p)
|
|||
et4000->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int et4000_add_status_info(char *s, int max_len, void *p)
|
||||
void et4000_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
et4000_t *et4000 = (et4000_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &et4000->svga);
|
||||
svga_add_status_info(s, max_len, &et4000->svga);
|
||||
}
|
||||
|
||||
device_t et4000_device =
|
||||
|
|
|
|||
|
|
@ -1077,11 +1077,11 @@ void et4000w32p_force_redraw(void *p)
|
|||
et4000w32p->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int et4000w32p_add_status_info(char *s, int max_len, void *p)
|
||||
void et4000w32p_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
et4000w32p_t *et4000w32p = (et4000w32p_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &et4000w32p->svga);
|
||||
svga_add_status_info(s, max_len, &et4000w32p->svga);
|
||||
}
|
||||
|
||||
static device_config_t et4000w32p_config[] =
|
||||
|
|
|
|||
|
|
@ -187,11 +187,11 @@ void oti067_force_redraw(void *p)
|
|||
oti067->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int oti067_add_status_info(char *s, int max_len, void *p)
|
||||
void oti067_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
oti067_t *oti067 = (oti067_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &oti067->svga);
|
||||
svga_add_status_info(s, max_len, &oti067->svga);
|
||||
}
|
||||
|
||||
static device_config_t oti067_config[] =
|
||||
|
|
|
|||
|
|
@ -372,11 +372,11 @@ void paradise_force_redraw(void *p)
|
|||
paradise->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int paradise_add_status_info(char *s, int max_len, void *p)
|
||||
void paradise_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
paradise_t *paradise = (paradise_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, ¶dise->svga);
|
||||
svga_add_status_info(s, max_len, ¶dise->svga);
|
||||
}
|
||||
|
||||
device_t paradise_pvga1a_pc2086_device =
|
||||
|
|
|
|||
|
|
@ -2055,11 +2055,11 @@ void s3_force_redraw(void *p)
|
|||
s3->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int s3_add_status_info(char *s, int max_len, void *p)
|
||||
void s3_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
s3_t *s3 = (s3_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &s3->svga);
|
||||
svga_add_status_info(s, max_len, &s3->svga);
|
||||
}
|
||||
|
||||
static device_config_t s3_bahamas64_config[] =
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "mem.h"
|
||||
#include "pci.h"
|
||||
#include "rom.h"
|
||||
#include "thread.h"
|
||||
#include "video.h"
|
||||
#include "vid_s3_virge.h"
|
||||
#include "vid_svga.h"
|
||||
|
|
@ -13,7 +14,7 @@
|
|||
|
||||
static uint64_t virge_time = 0;
|
||||
static uint64_t status_time = 0;
|
||||
static int reg_writes = 0;
|
||||
static int reg_writes = 0, reg_reads = 0;
|
||||
|
||||
static int dither[4][4] =
|
||||
{
|
||||
|
|
@ -23,6 +24,54 @@ static int dither[4][4] =
|
|||
7, 3, 6, 2,
|
||||
};
|
||||
|
||||
#define RB_SIZE 256
|
||||
#define RB_MASK (RB_SIZE - 1)
|
||||
|
||||
#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx)
|
||||
#define RB_FULL (RB_ENTRIES == RB_SIZE)
|
||||
#define RB_EMPTY (!RB_ENTRIES)
|
||||
|
||||
typedef struct s3d_t
|
||||
{
|
||||
uint32_t cmd_set;
|
||||
int clip_l, clip_r, clip_t, clip_b;
|
||||
|
||||
uint32_t dest_base;
|
||||
uint32_t dest_str;
|
||||
|
||||
uint32_t z_base;
|
||||
uint32_t z_str;
|
||||
|
||||
uint32_t tex_base;
|
||||
uint32_t tex_bdr_clr;
|
||||
uint32_t tbv, tbu;
|
||||
int32_t TdVdX, TdUdX;
|
||||
int32_t TdVdY, TdUdY;
|
||||
uint32_t tus, tvs;
|
||||
|
||||
int32_t TdZdX, TdZdY;
|
||||
uint32_t tzs;
|
||||
|
||||
int32_t TdWdX, TdWdY;
|
||||
uint32_t tws;
|
||||
|
||||
int32_t TdDdX, TdDdY;
|
||||
uint32_t tds;
|
||||
|
||||
int16_t TdGdX, TdBdX, TdRdX, TdAdX;
|
||||
int16_t TdGdY, TdBdY, TdRdY, TdAdY;
|
||||
uint32_t tgs, tbs, trs, tas;
|
||||
|
||||
uint32_t TdXdY12;
|
||||
uint32_t txend12;
|
||||
uint32_t TdXdY01;
|
||||
uint32_t txend01;
|
||||
uint32_t TdXdY02;
|
||||
uint32_t txs;
|
||||
uint32_t tys;
|
||||
int ty01, ty12, tlr;
|
||||
} s3d_t;
|
||||
|
||||
typedef struct virge_t
|
||||
{
|
||||
mem_mapping_t linear_mapping;
|
||||
|
|
@ -51,6 +100,11 @@ typedef struct virge_t
|
|||
int memory_size;
|
||||
|
||||
int pixel_count, tri_count;
|
||||
|
||||
thread_t *render_thread;
|
||||
event_t *wake_render_thread;
|
||||
event_t *wake_main_thread;
|
||||
event_t *not_full_event;
|
||||
|
||||
struct
|
||||
{
|
||||
|
|
@ -86,41 +140,14 @@ typedef struct virge_t
|
|||
uint32_t pattern_8[8*8];
|
||||
uint32_t pattern_16[8*8];
|
||||
uint32_t pattern_32[8*8];
|
||||
|
||||
|
||||
uint32_t z_base;
|
||||
uint32_t z_str;
|
||||
|
||||
uint32_t tex_base;
|
||||
uint32_t tex_bdr_clr;
|
||||
uint32_t tbv, tbu;
|
||||
int32_t TdVdX, TdUdX;
|
||||
int32_t TdVdY, TdUdY;
|
||||
uint32_t tus, tvs;
|
||||
|
||||
int32_t TdZdX, TdZdY;
|
||||
uint32_t tzs;
|
||||
|
||||
int32_t TdWdX, TdWdY;
|
||||
uint32_t tws;
|
||||
|
||||
int32_t TdDdX, TdDdY;
|
||||
uint32_t tds;
|
||||
|
||||
int16_t TdGdX, TdBdX, TdRdX, TdAdX;
|
||||
int16_t TdGdY, TdBdY, TdRdY, TdAdY;
|
||||
uint32_t tgs, tbs, trs, tas;
|
||||
|
||||
uint32_t TdXdY12;
|
||||
uint32_t txend12;
|
||||
uint32_t TdXdY01;
|
||||
uint32_t txend01;
|
||||
uint32_t TdXdY02;
|
||||
uint32_t txs;
|
||||
uint32_t tys;
|
||||
int ty01, ty12, tlr;
|
||||
} s3d;
|
||||
|
||||
s3d_t s3d_tri;
|
||||
|
||||
s3d_t s3d_buffer[RB_SIZE];
|
||||
int s3d_read_idx, s3d_write_idx;
|
||||
int s3d_busy;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32_t pri_ctrl;
|
||||
|
|
@ -154,13 +181,13 @@ typedef struct virge_t
|
|||
} streams;
|
||||
} virge_t;
|
||||
|
||||
static void queue_triangle(virge_t *virge);
|
||||
|
||||
static void s3_virge_recalctimings(svga_t *svga);
|
||||
static void s3_virge_updatemapping(virge_t *virge);
|
||||
|
||||
static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat);
|
||||
|
||||
static void s3_virge_triangle(virge_t *virge);
|
||||
|
||||
static uint8_t s3_virge_mmio_read(uint32_t addr, void *p);
|
||||
static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p);
|
||||
static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p);
|
||||
|
|
@ -598,7 +625,7 @@ static void s3_virge_updatemapping(virge_t *virge)
|
|||
|
||||
static uint8_t s3_virge_mmio_read(uint32_t addr, void *p)
|
||||
{
|
||||
reg_writes++;
|
||||
reg_reads++;
|
||||
// pclog("New MMIO readb %08X\n", addr);
|
||||
switch (addr & 0xffff)
|
||||
{
|
||||
|
|
@ -620,7 +647,7 @@ static uint8_t s3_virge_mmio_read(uint32_t addr, void *p)
|
|||
}
|
||||
static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p)
|
||||
{
|
||||
reg_writes++;
|
||||
reg_reads++;
|
||||
// pclog("New MMIO readw %08X\n", addr);
|
||||
switch (addr & 0xfffe)
|
||||
{
|
||||
|
|
@ -633,7 +660,7 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p)
|
|||
{
|
||||
virge_t *virge = (virge_t *)p;
|
||||
uint32_t ret = 0xffffffff;
|
||||
reg_writes++;
|
||||
reg_reads++;
|
||||
// pclog("New MMIO readl %08X %04X(%08X):%08X ", addr, CS, cs, pc);
|
||||
switch (addr & 0xfffc)
|
||||
{
|
||||
|
|
@ -705,7 +732,11 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p)
|
|||
break;
|
||||
|
||||
case 0x8504:
|
||||
ret = (0x10 << 8) | (1 << 13);
|
||||
if (virge->s3d_busy)
|
||||
ret = (0x10 << 8);
|
||||
else
|
||||
ret = (0x10 << 8) | (1 << 13);
|
||||
// pclog("Read status %04x %i\n", ret, virge->s3d_busy);
|
||||
break;
|
||||
case 0xa4d4:
|
||||
ret = virge->s3d.src_base;
|
||||
|
|
@ -756,7 +787,7 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p)
|
|||
default:
|
||||
ret = s3_virge_mmio_read_w(addr, p) | (s3_virge_mmio_read_w(addr + 2, p) << 16);
|
||||
}
|
||||
// pclog("%02x\n", ret);
|
||||
// /*if ((addr & 0xfffc) != 0x8504) */pclog("%02x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p)
|
||||
|
|
@ -856,11 +887,13 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
virge->streams.blend_ctrl = val;
|
||||
break;
|
||||
case 0x81c0:
|
||||
// pclog("Write pri_fb0 %08x\n", val);
|
||||
virge->streams.pri_fb0 = val & 0x3fffff;
|
||||
s3_virge_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
case 0x81c4:
|
||||
// pclog("Write pri_fb1 %08x\n", val);
|
||||
virge->streams.pri_fb1 = val & 0x3fffff;
|
||||
s3_virge_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
|
|
@ -871,9 +904,10 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
case 0x81cc:
|
||||
pclog("Write buffer_ctrl %08x\n", val);
|
||||
// pclog("Write buffer_ctrl %08x\n", val);
|
||||
virge->streams.buffer_ctrl = val;
|
||||
s3_virge_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
break;
|
||||
case 0x81d0:
|
||||
virge->streams.sec_fb0 = val;
|
||||
|
|
@ -991,22 +1025,21 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
}
|
||||
break;
|
||||
|
||||
|
||||
case 0xa4d4: case 0xa8d4:
|
||||
virge->s3d.src_base = val & 0x3ffff8;
|
||||
break;
|
||||
case 0xa4d8: case 0xa8d8: case 0xb4d8:
|
||||
case 0xa4d8: case 0xa8d8:
|
||||
virge->s3d.dest_base = val & 0x3ffff8;
|
||||
break;
|
||||
case 0xa4dc: case 0xa8dc: case 0xb4dc:
|
||||
case 0xa4dc: case 0xa8dc:
|
||||
virge->s3d.clip_l = (val >> 16) & 0x7ff;
|
||||
virge->s3d.clip_r = val & 0x7ff;
|
||||
break;
|
||||
case 0xa4e0: case 0xa8e0: case 0xb4e0:
|
||||
case 0xa4e0: case 0xa8e0:
|
||||
virge->s3d.clip_t = (val >> 16) & 0x7ff;
|
||||
virge->s3d.clip_b = val & 0x7ff;
|
||||
break;
|
||||
case 0xa4e4: case 0xa8e4: case 0xb4e4:
|
||||
case 0xa4e4: case 0xa8e4:
|
||||
virge->s3d.dest_str = (val >> 16) & 0xff8;
|
||||
virge->s3d.src_str = val & 0xff8;
|
||||
break;
|
||||
|
|
@ -1068,125 +1101,151 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
break;
|
||||
|
||||
case 0xb4d4:
|
||||
virge->s3d.z_base = val & 0x3ffff8;
|
||||
virge->s3d_tri.z_base = val & 0x3ffff8;
|
||||
break;
|
||||
case 0xb4d8:
|
||||
virge->s3d_tri.dest_base = val & 0x3ffff8;
|
||||
break;
|
||||
case 0xb4dc:
|
||||
virge->s3d_tri.clip_l = (val >> 16) & 0x7ff;
|
||||
virge->s3d_tri.clip_r = val & 0x7ff;
|
||||
break;
|
||||
case 0xb4e0:
|
||||
virge->s3d_tri.clip_t = (val >> 16) & 0x7ff;
|
||||
virge->s3d_tri.clip_b = val & 0x7ff;
|
||||
break;
|
||||
case 0xb4e4:
|
||||
virge->s3d_tri.dest_str = (val >> 16) & 0xff8;
|
||||
virge->s3d.src_str = val & 0xff8;
|
||||
break;
|
||||
case 0xb4e8:
|
||||
virge->s3d.z_str = val & 0xff8;
|
||||
virge->s3d_tri.z_str = val & 0xff8;
|
||||
break;
|
||||
case 0xb4ec:
|
||||
virge->s3d.tex_base = val & 0x3ffff8;
|
||||
virge->s3d_tri.tex_base = val & 0x3ffff8;
|
||||
break;
|
||||
case 0xb4f0:
|
||||
virge->s3d.tex_bdr_clr = val & 0xffffff;
|
||||
virge->s3d_tri.tex_bdr_clr = val & 0xffffff;
|
||||
break;
|
||||
case 0xb500:
|
||||
virge->s3d.cmd_set = val;
|
||||
virge->s3d_tri.cmd_set = val;
|
||||
if (!(val & CMD_SET_AE))
|
||||
s3_virge_triangle(virge);
|
||||
queue_triangle(virge);
|
||||
/* {
|
||||
thread_set_event(virge->wake_render_thread);
|
||||
thread_wait_event(virge->wake_main_thread, -1);
|
||||
} */
|
||||
// s3_virge_triangle(virge);
|
||||
break;
|
||||
case 0xb504:
|
||||
virge->s3d.tbv = val & 0xfffff;
|
||||
virge->s3d_tri.tbv = val & 0xfffff;
|
||||
break;
|
||||
case 0xb508:
|
||||
virge->s3d.tbu = val & 0xfffff;
|
||||
virge->s3d_tri.tbu = val & 0xfffff;
|
||||
break;
|
||||
case 0xb50c:
|
||||
virge->s3d.TdWdX = val;
|
||||
virge->s3d_tri.TdWdX = val;
|
||||
break;
|
||||
case 0xb510:
|
||||
virge->s3d.TdWdY = val;
|
||||
virge->s3d_tri.TdWdY = val;
|
||||
break;
|
||||
case 0xb514:
|
||||
virge->s3d.tws = val;
|
||||
virge->s3d_tri.tws = val;
|
||||
break;
|
||||
case 0xb518:
|
||||
virge->s3d.TdDdX = val;
|
||||
virge->s3d_tri.TdDdX = val;
|
||||
break;
|
||||
case 0xb51c:
|
||||
virge->s3d.TdVdX = val;
|
||||
virge->s3d_tri.TdVdX = val;
|
||||
break;
|
||||
case 0xb520:
|
||||
virge->s3d.TdUdX = val;
|
||||
virge->s3d_tri.TdUdX = val;
|
||||
break;
|
||||
case 0xb524:
|
||||
virge->s3d.TdDdY = val;
|
||||
virge->s3d_tri.TdDdY = val;
|
||||
break;
|
||||
case 0xb528:
|
||||
virge->s3d.TdVdY = val;
|
||||
virge->s3d_tri.TdVdY = val;
|
||||
break;
|
||||
case 0xb52c:
|
||||
virge->s3d.TdUdY = val;
|
||||
virge->s3d_tri.TdUdY = val;
|
||||
break;
|
||||
case 0xb530:
|
||||
virge->s3d.tds = val;
|
||||
virge->s3d_tri.tds = val;
|
||||
break;
|
||||
case 0xb534:
|
||||
virge->s3d.tvs = val;
|
||||
virge->s3d_tri.tvs = val;
|
||||
break;
|
||||
case 0xb538:
|
||||
virge->s3d.tus = val;
|
||||
virge->s3d_tri.tus = val;
|
||||
break;
|
||||
case 0xb53c:
|
||||
virge->s3d.TdGdX = val >> 16;
|
||||
virge->s3d.TdBdX = val & 0xffff;
|
||||
virge->s3d_tri.TdGdX = val >> 16;
|
||||
virge->s3d_tri.TdBdX = val & 0xffff;
|
||||
break;
|
||||
case 0xb540:
|
||||
virge->s3d.TdAdX = val >> 16;
|
||||
virge->s3d.TdRdX = val & 0xffff;
|
||||
virge->s3d_tri.TdAdX = val >> 16;
|
||||
virge->s3d_tri.TdRdX = val & 0xffff;
|
||||
break;
|
||||
case 0xb544:
|
||||
virge->s3d.TdGdY = val >> 16;
|
||||
virge->s3d.TdBdY = val & 0xffff;
|
||||
virge->s3d_tri.TdGdY = val >> 16;
|
||||
virge->s3d_tri.TdBdY = val & 0xffff;
|
||||
break;
|
||||
case 0xb548:
|
||||
virge->s3d.TdAdY = val >> 16;
|
||||
virge->s3d.TdRdY = val & 0xffff;
|
||||
virge->s3d_tri.TdAdY = val >> 16;
|
||||
virge->s3d_tri.TdRdY = val & 0xffff;
|
||||
break;
|
||||
case 0xb54c:
|
||||
virge->s3d.tgs = (val >> 16) & 0xffff;
|
||||
virge->s3d.tbs = val & 0xffff;
|
||||
virge->s3d_tri.tgs = (val >> 16) & 0xffff;
|
||||
virge->s3d_tri.tbs = val & 0xffff;
|
||||
break;
|
||||
case 0xb550:
|
||||
virge->s3d.tas = (val >> 16) & 0xffff;
|
||||
virge->s3d.trs = val & 0xffff;
|
||||
virge->s3d_tri.tas = (val >> 16) & 0xffff;
|
||||
virge->s3d_tri.trs = val & 0xffff;
|
||||
break;
|
||||
|
||||
case 0xb554:
|
||||
virge->s3d.TdZdX = val;
|
||||
virge->s3d_tri.TdZdX = val;
|
||||
break;
|
||||
case 0xb558:
|
||||
virge->s3d.TdZdY = val;
|
||||
virge->s3d_tri.TdZdY = val;
|
||||
break;
|
||||
case 0xb55c:
|
||||
virge->s3d.tzs = val;
|
||||
virge->s3d_tri.tzs = val;
|
||||
break;
|
||||
case 0xb560:
|
||||
virge->s3d.TdXdY12 = val;
|
||||
virge->s3d_tri.TdXdY12 = val;
|
||||
break;
|
||||
case 0xb564:
|
||||
virge->s3d.txend12 = val;
|
||||
virge->s3d_tri.txend12 = val;
|
||||
break;
|
||||
case 0xb568:
|
||||
virge->s3d.TdXdY01 = val;
|
||||
virge->s3d_tri.TdXdY01 = val;
|
||||
break;
|
||||
case 0xb56c:
|
||||
virge->s3d.txend01 = val;
|
||||
virge->s3d_tri.txend01 = val;
|
||||
break;
|
||||
case 0xb570:
|
||||
virge->s3d.TdXdY02 = val;
|
||||
virge->s3d_tri.TdXdY02 = val;
|
||||
break;
|
||||
case 0xb574:
|
||||
virge->s3d.txs = val;
|
||||
virge->s3d_tri.txs = val;
|
||||
break;
|
||||
case 0xb578:
|
||||
virge->s3d.tys = val;
|
||||
virge->s3d_tri.tys = val;
|
||||
break;
|
||||
case 0xb57c:
|
||||
virge->s3d.ty01 = (val >> 16) & 0x7ff;
|
||||
virge->s3d.ty12 = val & 0x7ff;
|
||||
virge->s3d.tlr = val >> 31;
|
||||
if (virge->s3d.cmd_set & CMD_SET_AE)
|
||||
s3_virge_triangle(virge);
|
||||
virge->s3d_tri.ty01 = (val >> 16) & 0x7ff;
|
||||
virge->s3d_tri.ty12 = val & 0x7ff;
|
||||
virge->s3d_tri.tlr = val >> 31;
|
||||
if (virge->s3d_tri.cmd_set & CMD_SET_AE)
|
||||
queue_triangle(virge);
|
||||
/* {
|
||||
thread_set_event(virge->wake_render_thread);
|
||||
thread_wait_event(virge->wake_main_thread, -1);
|
||||
}*/
|
||||
|
||||
// s3_virge_triangle(virge);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1210,24 +1269,35 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
|
|||
|
||||
#define Z_READ(addr) *(uint16_t *)&vram[addr & 0x3fffff]
|
||||
|
||||
#define Z_WRITE(addr, val) if (!(virge->s3d.cmd_set & CMD_SET_ZB_MODE)) *(uint16_t *)&vram[addr & 0x3fffff] = val
|
||||
#define Z_WRITE(addr, val) if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) *(uint16_t *)&vram[addr & 0x3fffff] = val
|
||||
|
||||
#define CLIP(x, y) \
|
||||
do \
|
||||
{ \
|
||||
if ((virge->s3d.cmd_set & CMD_SET_HC) && \
|
||||
(x < virge->s3d.clip_l || \
|
||||
x > virge->s3d.clip_r || \
|
||||
y < virge->s3d.clip_t || \
|
||||
y > virge->s3d.clip_b)) \
|
||||
if ((virge->s3d.cmd_set & CMD_SET_HC) && \
|
||||
(x < virge->s3d.clip_l || \
|
||||
x > virge->s3d.clip_r || \
|
||||
y < virge->s3d.clip_t || \
|
||||
y > virge->s3d.clip_b)) \
|
||||
update = 0; \
|
||||
} while (0)
|
||||
|
||||
#define CLIP_3D(x, y) \
|
||||
do \
|
||||
{ \
|
||||
if ((s3d_tri->cmd_set & CMD_SET_HC) && \
|
||||
(x < s3d_tri->clip_l || \
|
||||
x > s3d_tri->clip_r || \
|
||||
y < s3d_tri->clip_t || \
|
||||
y > s3d_tri->clip_b)) \
|
||||
update = 0; \
|
||||
} while (0)
|
||||
|
||||
#define Z_CLIP(Zzb, Zs) \
|
||||
do \
|
||||
{ \
|
||||
if (!(virge->s3d.cmd_set & CMD_SET_ZB_MODE)) \
|
||||
switch ((virge->s3d.cmd_set >> 20) & 7) \
|
||||
if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \
|
||||
switch ((s3d_tri->cmd_set >> 20) & 7) \
|
||||
{ \
|
||||
case 0: update = 0; break; \
|
||||
case 1: if (Zs <= Zzb) update = 0; else Zzb = Zs; break; \
|
||||
|
|
@ -2208,51 +2278,53 @@ static void dest_pixel_lit_texture_modulate(s3d_state_t *state)
|
|||
state->dest_rgba.a = a;
|
||||
}
|
||||
|
||||
static void tri(virge_t *virge, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2)
|
||||
static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2)
|
||||
{
|
||||
uint8_t *vram = virge->svga.vram;
|
||||
|
||||
int x_dir = virge->s3d.tlr ? 1 : -1;
|
||||
int x_dir = s3d_tri->tlr ? 1 : -1;
|
||||
|
||||
int use_z = !(virge->s3d.cmd_set & CMD_SET_ZB_MODE);
|
||||
int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE);
|
||||
|
||||
int y_count = yc;
|
||||
|
||||
int bpp = (virge->s3d.cmd_set >> 2) & 7;
|
||||
int bpp = (s3d_tri->cmd_set >> 2) & 7;
|
||||
|
||||
uint32_t dest_offset, z_offset;
|
||||
|
||||
if (virge->s3d.cmd_set & CMD_SET_HC)
|
||||
if (s3d_tri->cmd_set & CMD_SET_HC)
|
||||
{
|
||||
if (state->y < virge->s3d.clip_t)
|
||||
if (state->y < s3d_tri->clip_t)
|
||||
return;
|
||||
if (state->y > virge->s3d.clip_b)
|
||||
if (state->y > s3d_tri->clip_b)
|
||||
{
|
||||
int diff_y = state->y - virge->s3d.clip_b;
|
||||
int diff_y = state->y - s3d_tri->clip_b;
|
||||
|
||||
if (diff_y > y_count)
|
||||
diff_y = y_count;
|
||||
|
||||
state->base_u += (virge->s3d.TdUdY * diff_y);
|
||||
state->base_v += (virge->s3d.TdVdY * diff_y);
|
||||
state->base_z += (virge->s3d.TdZdY * diff_y);
|
||||
state->base_r += (virge->s3d.TdRdY * diff_y);
|
||||
state->base_g += (virge->s3d.TdGdY * diff_y);
|
||||
state->base_b += (virge->s3d.TdBdY * diff_y);
|
||||
state->base_a += (virge->s3d.TdAdY * diff_y);
|
||||
state->base_d += (virge->s3d.TdDdY * diff_y);
|
||||
state->base_w += (virge->s3d.TdWdY * diff_y);
|
||||
state->base_u += (s3d_tri->TdUdY * diff_y);
|
||||
state->base_v += (s3d_tri->TdVdY * diff_y);
|
||||
state->base_z += (s3d_tri->TdZdY * diff_y);
|
||||
state->base_r += (s3d_tri->TdRdY * diff_y);
|
||||
state->base_g += (s3d_tri->TdGdY * diff_y);
|
||||
state->base_b += (s3d_tri->TdBdY * diff_y);
|
||||
state->base_a += (s3d_tri->TdAdY * diff_y);
|
||||
state->base_d += (s3d_tri->TdDdY * diff_y);
|
||||
state->base_w += (s3d_tri->TdWdY * diff_y);
|
||||
state->x1 += (dx1 * diff_y);
|
||||
state->x2 += (dx2 * diff_y);
|
||||
state->y -= diff_y;
|
||||
dest_offset -= virge->s3d.dest_str;
|
||||
z_offset -= virge->s3d.z_str;
|
||||
dest_offset -= s3d_tri->dest_str;
|
||||
z_offset -= s3d_tri->z_str;
|
||||
y_count -= diff_y;
|
||||
}
|
||||
if ((state->y - y_count) < s3d_tri->clip_t)
|
||||
y_count = state->y - s3d_tri->clip_t;
|
||||
}
|
||||
|
||||
dest_offset = virge->s3d.dest_base + (state->y * virge->s3d.dest_str);
|
||||
z_offset = virge->s3d.z_base + (state->y * virge->s3d.z_str);
|
||||
dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str);
|
||||
z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str);
|
||||
|
||||
for (; y_count > 0; y_count--)
|
||||
{
|
||||
|
|
@ -2273,68 +2345,68 @@ static void tri(virge_t *virge, s3d_state_t *state, int yc, int32_t dx1, int32_t
|
|||
int xz_offset = x_dir << 1;
|
||||
if (x_dir > 0)
|
||||
dx += 1;
|
||||
state->r = state->base_r + ((virge->s3d.TdRdX * dx) >> 5);
|
||||
state->g = state->base_g + ((virge->s3d.TdGdX * dx) >> 5);
|
||||
state->b = state->base_b + ((virge->s3d.TdBdX * dx) >> 5);
|
||||
state->a = state->base_a + ((virge->s3d.TdAdX * dx) >> 5);
|
||||
state->u = state->base_u + ((virge->s3d.TdUdX * dx) >> 5);
|
||||
state->v = state->base_v + ((virge->s3d.TdVdX * dx) >> 5);
|
||||
state->w = state->base_w + ((virge->s3d.TdWdX * dx) >> 5);
|
||||
state->d = state->base_d + ((virge->s3d.TdDdX * dx) >> 5);
|
||||
z += ((virge->s3d.TdZdX * dx) >> 5);
|
||||
state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5);
|
||||
state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5);
|
||||
state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5);
|
||||
state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5);
|
||||
state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5);
|
||||
state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5);
|
||||
state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5);
|
||||
state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5);
|
||||
z += ((s3d_tri->TdZdX * dx) >> 5);
|
||||
|
||||
// pclog("Draw Y=%i X=%i to XE=%i %i %08x %08x %08x %08x %08x %08x %08x %08x %i %08x\n", state->y, x, xe, dx, state->x1, state->x2, dx1, virge->s3d.TdWdX, state->u, state->v, virge->s3d.TdUdX, virge->s3d.TdUdY, dx, (virge->s3d.TdUdX * dx) >> 4);
|
||||
|
||||
if (virge->s3d.cmd_set & CMD_SET_HC)
|
||||
if (s3d_tri->cmd_set & CMD_SET_HC)
|
||||
{
|
||||
if (x_dir > 0)
|
||||
{
|
||||
if (x > virge->s3d.clip_r)
|
||||
if (x > s3d_tri->clip_r)
|
||||
goto tri_skip_line;
|
||||
if (xe < virge->s3d.clip_l)
|
||||
if (xe < s3d_tri->clip_l)
|
||||
goto tri_skip_line;
|
||||
if (xe > virge->s3d.clip_r)
|
||||
xe = virge->s3d.clip_r;
|
||||
if (x < virge->s3d.clip_l)
|
||||
if (xe > s3d_tri->clip_r)
|
||||
xe = s3d_tri->clip_r;
|
||||
if (x < s3d_tri->clip_l)
|
||||
{
|
||||
int diff_x = virge->s3d.clip_l - x;
|
||||
int diff_x = s3d_tri->clip_l - x;
|
||||
|
||||
z += (virge->s3d.TdZdX * diff_x);
|
||||
state->u += (virge->s3d.TdUdX * diff_x);
|
||||
state->v += (virge->s3d.TdVdX * diff_x);
|
||||
state->r += (virge->s3d.TdRdX * diff_x);
|
||||
state->g += (virge->s3d.TdGdX * diff_x);
|
||||
state->b += (virge->s3d.TdBdX * diff_x);
|
||||
state->a += (virge->s3d.TdAdX * diff_x);
|
||||
state->d += (virge->s3d.TdDdX * diff_x);
|
||||
state->w += (virge->s3d.TdWdX * diff_x);
|
||||
z += (s3d_tri->TdZdX * diff_x);
|
||||
state->u += (s3d_tri->TdUdX * diff_x);
|
||||
state->v += (s3d_tri->TdVdX * diff_x);
|
||||
state->r += (s3d_tri->TdRdX * diff_x);
|
||||
state->g += (s3d_tri->TdGdX * diff_x);
|
||||
state->b += (s3d_tri->TdBdX * diff_x);
|
||||
state->a += (s3d_tri->TdAdX * diff_x);
|
||||
state->d += (s3d_tri->TdDdX * diff_x);
|
||||
state->w += (s3d_tri->TdWdX * diff_x);
|
||||
|
||||
x = virge->s3d.clip_l;
|
||||
x = s3d_tri->clip_l;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x < virge->s3d.clip_l)
|
||||
if (x < s3d_tri->clip_l)
|
||||
goto tri_skip_line;
|
||||
if (xe > virge->s3d.clip_r)
|
||||
if (xe > s3d_tri->clip_r)
|
||||
goto tri_skip_line;
|
||||
if (xe < virge->s3d.clip_l)
|
||||
xe = virge->s3d.clip_l;
|
||||
if (x > virge->s3d.clip_r)
|
||||
if (xe < s3d_tri->clip_l)
|
||||
xe = s3d_tri->clip_l;
|
||||
if (x > s3d_tri->clip_r)
|
||||
{
|
||||
int diff_x = x - virge->s3d.clip_r;
|
||||
int diff_x = x - s3d_tri->clip_r;
|
||||
|
||||
z += (virge->s3d.TdZdX * diff_x);
|
||||
state->u += (virge->s3d.TdUdX * diff_x);
|
||||
state->v += (virge->s3d.TdVdX * diff_x);
|
||||
state->r += (virge->s3d.TdRdX * diff_x);
|
||||
state->g += (virge->s3d.TdGdX * diff_x);
|
||||
state->b += (virge->s3d.TdBdX * diff_x);
|
||||
state->a += (virge->s3d.TdAdX * diff_x);
|
||||
state->d += (virge->s3d.TdDdX * diff_x);
|
||||
state->w += (virge->s3d.TdWdX * diff_x);
|
||||
z += (s3d_tri->TdZdX * diff_x);
|
||||
state->u += (s3d_tri->TdUdX * diff_x);
|
||||
state->v += (s3d_tri->TdVdX * diff_x);
|
||||
state->r += (s3d_tri->TdRdX * diff_x);
|
||||
state->g += (s3d_tri->TdGdX * diff_x);
|
||||
state->b += (s3d_tri->TdBdX * diff_x);
|
||||
state->a += (s3d_tri->TdAdX * diff_x);
|
||||
state->d += (s3d_tri->TdDdX * diff_x);
|
||||
state->w += (s3d_tri->TdWdX * diff_x);
|
||||
|
||||
x = virge->s3d.clip_r;
|
||||
x = s3d_tri->clip_r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2362,7 +2434,7 @@ static void tri(virge_t *virge, s3d_state_t *state, int yc, int32_t dx1, int32_t
|
|||
|
||||
dest_pixel(state);
|
||||
|
||||
if (virge->s3d.cmd_set & CMD_SET_ABC_ENABLE)
|
||||
if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE)
|
||||
{
|
||||
uint32_t src_col;
|
||||
int src_r, src_g, src_b;
|
||||
|
|
@ -2404,19 +2476,19 @@ static void tri(virge_t *virge, s3d_state_t *state, int yc, int32_t dx1, int32_t
|
|||
break;
|
||||
}
|
||||
|
||||
if (use_z && (virge->s3d.cmd_set & CMD_SET_ZUP))
|
||||
if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP))
|
||||
Z_WRITE(z_addr, src_z);
|
||||
}
|
||||
|
||||
z += virge->s3d.TdZdX;
|
||||
state->u += virge->s3d.TdUdX;
|
||||
state->v += virge->s3d.TdVdX;
|
||||
state->r += virge->s3d.TdRdX;
|
||||
state->g += virge->s3d.TdGdX;
|
||||
state->b += virge->s3d.TdBdX;
|
||||
state->a += virge->s3d.TdAdX;
|
||||
state->d += virge->s3d.TdDdX;
|
||||
state->w += virge->s3d.TdWdX;
|
||||
z += s3d_tri->TdZdX;
|
||||
state->u += s3d_tri->TdUdX;
|
||||
state->v += s3d_tri->TdVdX;
|
||||
state->r += s3d_tri->TdRdX;
|
||||
state->g += s3d_tri->TdGdX;
|
||||
state->b += s3d_tri->TdBdX;
|
||||
state->a += s3d_tri->TdAdX;
|
||||
state->d += s3d_tri->TdDdX;
|
||||
state->w += s3d_tri->TdWdX;
|
||||
dest_addr += x_offset;
|
||||
z_addr += xz_offset;
|
||||
virge->pixel_count++;
|
||||
|
|
@ -2425,18 +2497,18 @@ static void tri(virge_t *virge, s3d_state_t *state, int yc, int32_t dx1, int32_t
|
|||
tri_skip_line:
|
||||
state->x1 += dx1;
|
||||
state->x2 += dx2;
|
||||
state->base_u += virge->s3d.TdUdY;
|
||||
state->base_v += virge->s3d.TdVdY;
|
||||
state->base_z += virge->s3d.TdZdY;
|
||||
state->base_r += virge->s3d.TdRdY;
|
||||
state->base_g += virge->s3d.TdGdY;
|
||||
state->base_b += virge->s3d.TdBdY;
|
||||
state->base_a += virge->s3d.TdAdY;
|
||||
state->base_d += virge->s3d.TdDdY;
|
||||
state->base_w += virge->s3d.TdWdY;
|
||||
state->base_u += s3d_tri->TdUdY;
|
||||
state->base_v += s3d_tri->TdVdY;
|
||||
state->base_z += s3d_tri->TdZdY;
|
||||
state->base_r += s3d_tri->TdRdY;
|
||||
state->base_g += s3d_tri->TdGdY;
|
||||
state->base_b += s3d_tri->TdBdY;
|
||||
state->base_a += s3d_tri->TdAdY;
|
||||
state->base_d += s3d_tri->TdDdY;
|
||||
state->base_w += s3d_tri->TdWdY;
|
||||
state->y--;
|
||||
dest_offset -= virge->s3d.dest_str;
|
||||
z_offset -= virge->s3d.z_str;
|
||||
dest_offset -= s3d_tri->dest_str;
|
||||
z_offset -= s3d_tri->z_str;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2452,7 +2524,7 @@ static int tex_size[8] =
|
|||
1*2
|
||||
};
|
||||
|
||||
static void s3_virge_triangle(virge_t *virge)
|
||||
static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri)
|
||||
{
|
||||
s3d_state_t state;
|
||||
|
||||
|
|
@ -2462,34 +2534,34 @@ static void s3_virge_triangle(virge_t *virge)
|
|||
uint64_t start_time = timer_read();
|
||||
uint64_t end_time;
|
||||
|
||||
state.tbu = virge->s3d.tbu << 11;
|
||||
state.tbv = virge->s3d.tbv << 11;
|
||||
state.tbu = s3d_tri->tbu << 11;
|
||||
state.tbv = s3d_tri->tbv << 11;
|
||||
|
||||
state.max_d = (virge->s3d.cmd_set >> 8) & 15;
|
||||
state.max_d = (s3d_tri->cmd_set >> 8) & 15;
|
||||
|
||||
state.tex_bdr_clr = virge->s3d.tex_bdr_clr;
|
||||
state.tex_bdr_clr = s3d_tri->tex_bdr_clr;
|
||||
|
||||
state.cmd_set = virge->s3d.cmd_set;
|
||||
state.cmd_set = s3d_tri->cmd_set;
|
||||
|
||||
state.base_u = virge->s3d.tus;
|
||||
state.base_v = virge->s3d.tvs;
|
||||
state.base_z = virge->s3d.tzs;
|
||||
state.base_r = (int32_t)virge->s3d.trs;
|
||||
state.base_g = (int32_t)virge->s3d.tgs;
|
||||
state.base_b = (int32_t)virge->s3d.tbs;
|
||||
state.base_a = (int32_t)virge->s3d.tas;
|
||||
state.base_d = virge->s3d.tds;
|
||||
state.base_w = virge->s3d.tws;
|
||||
state.base_u = s3d_tri->tus;
|
||||
state.base_v = s3d_tri->tvs;
|
||||
state.base_z = s3d_tri->tzs;
|
||||
state.base_r = (int32_t)s3d_tri->trs;
|
||||
state.base_g = (int32_t)s3d_tri->tgs;
|
||||
state.base_b = (int32_t)s3d_tri->tbs;
|
||||
state.base_a = (int32_t)s3d_tri->tas;
|
||||
state.base_d = s3d_tri->tds;
|
||||
state.base_w = s3d_tri->tws;
|
||||
|
||||
tex_base = virge->s3d.tex_base;
|
||||
tex_base = s3d_tri->tex_base;
|
||||
for (c = 9; c >= 0; c--)
|
||||
{
|
||||
state.texture[c] = (uint16_t *)&virge->svga.vram[tex_base];
|
||||
if (c <= state.max_d)
|
||||
tex_base += ((1 << (c*2)) * tex_size[(virge->s3d.cmd_set >> 5) & 7]) / 2;
|
||||
tex_base += ((1 << (c*2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2;
|
||||
}
|
||||
|
||||
switch ((virge->s3d.cmd_set >> 27) & 0xf)
|
||||
switch ((s3d_tri->cmd_set >> 27) & 0xf)
|
||||
{
|
||||
case 0:
|
||||
dest_pixel = dest_pixel_gouraud_shaded_triangle;
|
||||
|
|
@ -2497,7 +2569,7 @@ static void s3_virge_triangle(virge_t *virge)
|
|||
break;
|
||||
case 1:
|
||||
case 5:
|
||||
switch ((virge->s3d.cmd_set >> 15) & 0x3)
|
||||
switch ((s3d_tri->cmd_set >> 15) & 0x3)
|
||||
{
|
||||
case 0:
|
||||
dest_pixel = dest_pixel_lit_texture_reflection;
|
||||
|
|
@ -2512,7 +2584,7 @@ static void s3_virge_triangle(virge_t *virge)
|
|||
// pclog("dest_pixel_lit_texture_decal\n");
|
||||
break;
|
||||
default:
|
||||
pclog("bad triangle type %x\n", (virge->s3d.cmd_set >> 27) & 0xf);
|
||||
pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
|
@ -2522,11 +2594,11 @@ static void s3_virge_triangle(virge_t *virge)
|
|||
// pclog("dest_pixel_unlit_texture_triangle\n");
|
||||
break;
|
||||
default:
|
||||
pclog("bad triangle type %x\n", (virge->s3d.cmd_set >> 27) & 0xf);
|
||||
pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (((virge->s3d.cmd_set >> 12) & 7) | ((virge->s3d.cmd_set & (1 << 29)) ? 8 : 0))
|
||||
switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0))
|
||||
{
|
||||
case 0: case 1:
|
||||
tex_sample = tex_sample_mipmap;
|
||||
|
|
@ -2574,33 +2646,33 @@ static void s3_virge_triangle(virge_t *virge)
|
|||
break;
|
||||
}
|
||||
|
||||
switch ((virge->s3d.cmd_set >> 5) & 7)
|
||||
switch ((s3d_tri->cmd_set >> 5) & 7)
|
||||
{
|
||||
case 0:
|
||||
tex_read = (virge->s3d.cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap;
|
||||
tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap;
|
||||
break;
|
||||
case 1:
|
||||
tex_read = (virge->s3d.cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap;
|
||||
tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap;
|
||||
// pclog("tex_ARGB4444\n");
|
||||
break;
|
||||
case 2:
|
||||
tex_read = (virge->s3d.cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
|
||||
// pclog("tex_ARGB1555 %i\n", (virge->s3d.cmd_set >> 5) & 7);
|
||||
tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
|
||||
// pclog("tex_ARGB1555 %i\n", (s3d_tri->cmd_set >> 5) & 7);
|
||||
break;
|
||||
default:
|
||||
pclog("bad texture type %i\n", (virge->s3d.cmd_set >> 5) & 7);
|
||||
tex_read = (virge->s3d.cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
|
||||
pclog("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7);
|
||||
tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
|
||||
break;
|
||||
}
|
||||
|
||||
// pclog("Triangle %i %i,%i to %i,%i %08x\n", y, x1 >> 20, y, virge->s3d.txend01 >> 20, y - (virge->s3d.ty01 + virge->s3d.ty12), state.cmd_set);
|
||||
// pclog("Triangle %i %i,%i to %i,%i %08x\n", y, x1 >> 20, y, s3d_tri->txend01 >> 20, y - (s3d_tri->ty01 + s3d_tri->ty12), state.cmd_set);
|
||||
|
||||
state.y = virge->s3d.tys;
|
||||
state.x1 = virge->s3d.txs;
|
||||
state.x2 = virge->s3d.txend01;
|
||||
tri(virge, &state, virge->s3d.ty01, virge->s3d.TdXdY02, virge->s3d.TdXdY01);
|
||||
state.x2 = virge->s3d.txend12;
|
||||
tri(virge, &state, virge->s3d.ty12, virge->s3d.TdXdY02, virge->s3d.TdXdY12);
|
||||
state.y = s3d_tri->tys;
|
||||
state.x1 = s3d_tri->txs;
|
||||
state.x2 = s3d_tri->txend01;
|
||||
tri(virge, s3d_tri, &state, s3d_tri->ty01, s3d_tri->TdXdY02, s3d_tri->TdXdY01);
|
||||
state.x2 = s3d_tri->txend12;
|
||||
tri(virge, s3d_tri, &state, s3d_tri->ty12, s3d_tri->TdXdY02, s3d_tri->TdXdY12);
|
||||
|
||||
virge->tri_count++;
|
||||
|
||||
|
|
@ -2609,6 +2681,43 @@ static void s3_virge_triangle(virge_t *virge)
|
|||
virge_time += end_time - start_time;
|
||||
}
|
||||
|
||||
static void render_thread(void *param)
|
||||
{
|
||||
virge_t *virge = (virge_t *)param;
|
||||
|
||||
while (1)
|
||||
{
|
||||
thread_wait_event(virge->wake_render_thread, -1);
|
||||
thread_reset_event(virge->wake_render_thread);
|
||||
virge->s3d_busy = 1;
|
||||
while (!RB_EMPTY)
|
||||
{
|
||||
s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]);
|
||||
virge->s3d_read_idx++;
|
||||
|
||||
if (RB_ENTRIES == RB_SIZE - 1)
|
||||
thread_set_event(virge->not_full_event);
|
||||
}
|
||||
virge->s3d_busy = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void queue_triangle(virge_t *virge)
|
||||
{
|
||||
int c;
|
||||
// pclog("queue_triangle: read=%i write=%i RB_ENTRIES=%i RB_FULL=%i\n", virge->s3d_read_idx, virge->s3d_write_idx, RB_ENTRIES, RB_FULL);
|
||||
if (RB_FULL)
|
||||
{
|
||||
thread_reset_event(virge->not_full_event);
|
||||
if (RB_FULL)
|
||||
thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/
|
||||
}
|
||||
// pclog(" add at read=%i write=%i %i\n", virge->s3d_read_idx, virge->s3d_write_idx, virge->s3d_write_idx & RB_MASK);
|
||||
virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri;
|
||||
virge->s3d_write_idx++;
|
||||
if (!virge->s3d_busy)
|
||||
thread_set_event(virge->wake_render_thread); /*Wake up render thread if moving from idle*/
|
||||
}
|
||||
|
||||
static void s3_virge_hwcursor_draw(svga_t *svga, int displine)
|
||||
{
|
||||
|
|
@ -3098,6 +3207,11 @@ static void *s3_virge_init()
|
|||
virge->is_375 = 0;
|
||||
|
||||
pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
|
||||
|
||||
virge->wake_render_thread = thread_create_event();
|
||||
virge->wake_main_thread = thread_create_event();
|
||||
virge->not_full_event = thread_create_event();
|
||||
virge->render_thread = thread_create(render_thread, virge);
|
||||
|
||||
return virge;
|
||||
}
|
||||
|
|
@ -3186,6 +3300,11 @@ static void *s3_virge_375_init()
|
|||
|
||||
pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
|
||||
|
||||
virge->wake_render_thread = thread_create_event();
|
||||
virge->wake_main_thread = thread_create_event();
|
||||
virge->not_full_event = thread_create_event();
|
||||
virge->render_thread = thread_create(render_thread, virge);
|
||||
|
||||
return virge;
|
||||
}
|
||||
|
||||
|
|
@ -3196,6 +3315,11 @@ static void s3_virge_close(void *p)
|
|||
fwrite(virge->svga.vram, 4 << 20, 1, f);
|
||||
fclose(f);
|
||||
|
||||
thread_kill(virge->render_thread);
|
||||
thread_destroy_event(virge->not_full_event);
|
||||
thread_destroy_event(virge->wake_main_thread);
|
||||
thread_destroy_event(virge->wake_render_thread);
|
||||
|
||||
svga_close(&virge->svga);
|
||||
|
||||
free(virge);
|
||||
|
|
@ -3225,12 +3349,10 @@ static void s3_virge_force_redraw(void *p)
|
|||
virge->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
static int s3_virge_add_status_info(char *s, int max_len, void *p)
|
||||
static void s3_virge_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
virge_t *virge = (virge_t *)p;
|
||||
int cur_len;
|
||||
char temps[256];
|
||||
|
||||
uint64_t new_time = timer_read();
|
||||
uint64_t status_diff = new_time - status_time;
|
||||
status_time = new_time;
|
||||
|
|
@ -3238,15 +3360,14 @@ static int s3_virge_add_status_info(char *s, int max_len, void *p)
|
|||
if (!status_diff)
|
||||
status_diff = 1;
|
||||
|
||||
cur_len = svga_add_status_info(s, cur_len, &virge->svga);
|
||||
sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes);
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
svga_add_status_info(s, max_len, &virge->svga);
|
||||
sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes %i reads\n\n", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes, reg_reads);
|
||||
strncat(s, temps, max_len);
|
||||
|
||||
virge->pixel_count = virge->tri_count = 0;
|
||||
virge_time = 0;
|
||||
reg_reads = 0;
|
||||
reg_writes = 0;
|
||||
|
||||
return max_len - cur_len;
|
||||
}
|
||||
|
||||
static device_config_t s3_virge_config[] =
|
||||
|
|
|
|||
|
|
@ -1181,8 +1181,6 @@ void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
|
|||
void svga_writew(uint32_t addr, uint16_t val, void *p)
|
||||
{
|
||||
svga_t *svga = (svga_t *)p;
|
||||
if (!svga)
|
||||
exit(-1);
|
||||
if (!svga->fast)
|
||||
{
|
||||
svga_write(addr, val, p);
|
||||
|
|
@ -1363,30 +1361,23 @@ uint32_t svga_readl_linear(uint32_t addr, void *p)
|
|||
}
|
||||
|
||||
|
||||
int svga_add_status_info(char *s, int max_len, void *p)
|
||||
void svga_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
svga_t *svga = (svga_t *)p;
|
||||
char temps[128];
|
||||
int cur_len = max_len;
|
||||
|
||||
if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h)\n");
|
||||
else strcpy(temps, "SVGA unchained (possibly mode-X)\n");
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
strncat(s, temps, max_len);
|
||||
|
||||
if (!svga->video_bpp) strcpy(temps, "SVGA in text mode\n");
|
||||
else sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp);
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
strncat(s, temps, max_len);
|
||||
|
||||
sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y);
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
strncat(s, temps, max_len);
|
||||
|
||||
sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames);
|
||||
svga->frames = 0;
|
||||
strncat(s, temps, cur_len);
|
||||
cur_len -= strlen(temps);
|
||||
|
||||
return max_len - cur_len;
|
||||
strncat(s, temps, max_len);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ void svga_write_linear(uint32_t addr, uint8_t val, void *p);
|
|||
void svga_writew_linear(uint32_t addr, uint16_t val, void *p);
|
||||
void svga_writel_linear(uint32_t addr, uint32_t val, void *p);
|
||||
|
||||
int svga_add_status_info(char *s, int max_len, void *p);
|
||||
void svga_add_status_info(char *s, int max_len, void *p);
|
||||
|
||||
extern uint8_t svga_rotate[8][256];
|
||||
|
||||
|
|
|
|||
|
|
@ -1111,11 +1111,11 @@ void tgui_accel_write_fb_l(uint32_t addr, uint32_t val, void *p)
|
|||
tgui_accel_command(32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24), tgui);
|
||||
}
|
||||
|
||||
int tgui_add_status_info(char *s, int max_len, void *p)
|
||||
void tgui_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
tgui_t *tgui = (tgui_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &tgui->svga);
|
||||
svga_add_status_info(s, max_len, &tgui->svga);
|
||||
}
|
||||
|
||||
static device_config_t tgui9440_config[] =
|
||||
|
|
|
|||
|
|
@ -300,11 +300,11 @@ void tvga_force_redraw(void *p)
|
|||
tvga->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int tvga_add_status_info(char *s, int max_len, void *p)
|
||||
void tvga_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
tvga_t *tvga = (tvga_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &tvga->svga);
|
||||
svga_add_status_info(s, max_len, &tvga->svga);
|
||||
}
|
||||
|
||||
static device_config_t tvga_config[] =
|
||||
|
|
|
|||
|
|
@ -125,11 +125,11 @@ void vga_force_redraw(void *p)
|
|||
vga->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
int vga_add_status_info(char *s, int max_len, void *p)
|
||||
void vga_add_status_info(char *s, int max_len, void *p)
|
||||
{
|
||||
vga_t *vga = (vga_t *)p;
|
||||
|
||||
return svga_add_status_info(s, max_len, &vga->svga);
|
||||
svga_add_status_info(s, max_len, &vga->svga);
|
||||
}
|
||||
|
||||
device_t vga_device =
|
||||
|
|
|
|||
|
|
@ -13,10 +13,8 @@ HWND status_hwnd;
|
|||
int status_is_open = 0;
|
||||
|
||||
extern int sreadlnum, swritelnum, segareads, segawrites, scycles_lost;
|
||||
|
||||
static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
char s[256];
|
||||
char device_s[4096];
|
||||
switch (message)
|
||||
{
|
||||
|
|
@ -28,7 +26,7 @@ static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
"FPU speed : %f MFLOPS\n\n"
|
||||
"Cache misses (read) : %i/sec\n"
|
||||
"Cache misses (write) : %i/sec\n\n"
|
||||
"Video throughput (read) : %i bytes/sec\n\n"
|
||||
"Video throughput (read) : %i bytes/sec\n"
|
||||
"Video throughput (write) : %i bytes/sec\n\n"
|
||||
"Effective clockspeed : %iHz\n\n"
|
||||
"Timer 0 frequency : %fHz\n\n",
|
||||
|
|
@ -57,6 +55,7 @@ static BOOL CALLBACK status_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPAR
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
65
src/win.c
65
src/win.c
|
|
@ -21,6 +21,7 @@
|
|||
#include "model.h"
|
||||
#include "nvr.h"
|
||||
#include "sound.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "plat-midi.h"
|
||||
#include "plat-keyboard.h"
|
||||
|
|
@ -183,6 +184,70 @@ void mainthread(LPVOID param)
|
|||
}
|
||||
}
|
||||
|
||||
void *thread_create(void (*thread_rout)(void *param), void *param)
|
||||
{
|
||||
return (void *)_beginthread(thread_rout, 0, param);
|
||||
}
|
||||
|
||||
void thread_kill(void *handle)
|
||||
{
|
||||
TerminateThread(handle, 0);
|
||||
}
|
||||
|
||||
void thread_sleep(int t)
|
||||
{
|
||||
Sleep(t);
|
||||
}
|
||||
|
||||
typedef struct win_event_t
|
||||
{
|
||||
HANDLE handle;
|
||||
} win_event_t;
|
||||
|
||||
event_t *thread_create_event()
|
||||
{
|
||||
win_event_t *event = malloc(sizeof(win_event_t));
|
||||
|
||||
event->handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
return (event_t *)event;
|
||||
}
|
||||
|
||||
void thread_set_event(event_t *_event)
|
||||
{
|
||||
win_event_t *event = (win_event_t *)_event;
|
||||
|
||||
SetEvent(event->handle);
|
||||
}
|
||||
|
||||
void thread_reset_event(event_t *_event)
|
||||
{
|
||||
win_event_t *event = (win_event_t *)_event;
|
||||
|
||||
ResetEvent(event->handle);
|
||||
}
|
||||
|
||||
int thread_wait_event(event_t *_event, int timeout)
|
||||
{
|
||||
win_event_t *event = (win_event_t *)_event;
|
||||
|
||||
if (timeout == -1)
|
||||
timeout = INFINITE;
|
||||
|
||||
if (WaitForSingleObject(event->handle, timeout))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void thread_destroy_event(event_t *_event)
|
||||
{
|
||||
win_event_t *event = (win_event_t *)_event;
|
||||
|
||||
CloseHandle(event->handle);
|
||||
|
||||
free(event);
|
||||
}
|
||||
|
||||
static void initmenu(void)
|
||||
{
|
||||
int c;
|
||||
|
|
|
|||
Loading…
Reference in a new issue