Add color/chroma-keying to S3 Trio64V+ and Trio64V2/DX

Clean up some TODOs in Voodoo 3/Banshee code
This commit is contained in:
Cacodemon345
2025-08-19 23:52:54 +06:00
parent 1fa46aa0f7
commit 5e0dd65738
3 changed files with 156 additions and 13 deletions

View File

@@ -24,6 +24,7 @@
#include <math.h>
#include <wchar.h>
#include <stdatomic.h>
#include <stdbool.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
@@ -389,6 +390,8 @@ typedef struct s3_t {
int color_16bit;
atomic_int busy, force_busy;
bool color_key_enabled;
uint8_t thread_run, serialport;
void *i2c, *ddc;
@@ -2614,10 +2617,89 @@ s3_hwcursor_draw(svga_t *svga, int displine)
} \
} while (0)
static bool
s3_trio64v_colorkey(s3_t* s3, uint32_t x, uint32_t y)
{
svga_t* svga = &s3->svga;
uint8_t comp_r = 0, comp_g = 0, comp_b = 0;
uint8_t r = 0, g = 0, b = 0;
uint8_t bytes_per_pel = 1;
uint8_t shift = ((s3->streams.chroma_ctrl >> 24) & 7) ^ 7;
bool is15bpp = false;
uint32_t base_addr = svga->memaddr_latch;
uint32_t stride = s3->streams.pri_stride;
if (!s3->color_key_enabled)
return true;
if (y > 2048)
return true;
if (!(s3->streams.chroma_ctrl & (1 << 28))) {
return true;
}
comp_r = (s3->streams.chroma_ctrl >> 16) & 0xFF;
comp_g = (s3->streams.chroma_ctrl >> 8) & 0xFF;
comp_b = (s3->streams.chroma_ctrl) & 0xFF;
if (svga->render == svga_render_32bpp_highres) bytes_per_pel = 4;
if (svga->render == svga_render_24bpp_highres) bytes_per_pel = 3;
if (svga->render == svga_render_16bpp_highres) bytes_per_pel = 2;
if (svga->render == svga_render_15bpp_highres) { bytes_per_pel = 2; is15bpp = true; }
switch (bytes_per_pel) {
case 1: {
uint8_t index = svga->vram[(base_addr + (stride * y) + x * bytes_per_pel) & svga->vram_mask];
r = svga->vgapal[index].r << 2;
g = svga->vgapal[index].g << 2;
b = svga->vgapal[index].b << 2;
break;
}
case 2: {
uint16_t col = *(uint16_t*)&svga->vram[(base_addr + (stride * y) + x * bytes_per_pel) & svga->vram_mask];
if (is15bpp) {
r = ((col >> 10) & 0x1f) << 3;
g = ((col >> 5) & 0x1f) << 3;
b = (col & 0x1f) << 3;
} else {
r = ((col >> 11) & 0x1f) << 3;
g = ((col >> 5) & 0x3f) << 2;
b = (col & 0x1f) << 3;
}
break;
}
case 3: {
uint8_t *col = &svga->vram[(base_addr + (stride * y) + x * bytes_per_pel) & svga->vram_mask];
r = col[0];
g = col[1];
b = col[2];
break;
}
case 4: {
uint32_t col = *(uint32_t*)&svga->vram[(base_addr + (stride * y) + x * bytes_per_pel) & svga->vram_mask];
r = (col >> 16) & 0xFF;
g = (col >> 8) & 0xFF;
b = col & 0xFF;
break;
}
}
r >>= shift;
g >>= shift;
b >>= shift;
comp_r >>= shift;
comp_g >>= shift;
comp_b >>= shift;
return !!(r == comp_r && g == comp_g && b == comp_b);
}
static void
s3_trio64v_overlay_draw(svga_t *svga, int displine)
{
const s3_t *s3 = (s3_t *) svga->priv;
s3_t *s3 = (s3_t *) svga->priv;
int offset = (s3->streams.sec_x - s3->streams.pri_x) + 1;
int r[8];
int g[8];
@@ -2638,7 +2720,10 @@ s3_trio64v_overlay_draw(svga_t *svga, int displine)
OVERLAY_SAMPLE();
for (int x = 0; x < x_size; x++) {
*p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16);
if (s3_trio64v_colorkey(s3, offset + x, displine - svga->y_add))
*p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16);
else
p++;
svga->overlay_latch.h_acc += s3->streams.k1_horiz_scale;
if (svga->overlay_latch.h_acc >= 0) {
@@ -10181,6 +10266,7 @@ s3_init(const device_t *info)
s3_in, s3_out,
s3_hwcursor_draw,
s3_trio64v_overlay_draw);
s3->color_key_enabled = !!device_get_config_int("colorkey");
} else {
svga_init(info, svga, s3, vram_size,
s3_recalctimings,
@@ -10925,6 +11011,68 @@ static const device_config_t s3_phoenix_trio32_config[] = {
{ .name = "", .description = "", .type = CONFIG_END }
};
static const device_config_t s3_phoenix_trio32_v_config[] = {
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 2,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "512 KB", .value = 0 },
{ .description = "1 MB", .value = 1 },
{ .description = "2 MB", .value = 2 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "colorkey",
.description = "Video chroma-keying",
.type = CONFIG_BINARY,
.default_string = NULL,
.default_int = 1,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
};
static const device_config_t s3_trio64v_config[] = {
{
.name = "memory",
.description = "Memory size",
.type = CONFIG_SELECTION,
.default_string = NULL,
.default_int = 4,
.file_filter = NULL,
.spinner = { 0 },
.selection = {
{ .description = "1 MB", .value = 1 },
{ .description = "2 MB", .value = 2 },
{ .description = "4 MB", .value = 4 },
{ .description = "" }
},
.bios = { { 0 } }
},
{
.name = "colorkey",
.description = "Video chroma-keying",
.type = CONFIG_BINARY,
.default_string = NULL,
.default_int = 1,
.file_filter = NULL,
.spinner = { 0 },
.selection = { { 0 } },
.bios = { { 0 } }
},
{ .name = "", .description = "", .type = CONFIG_END }
};
static const device_config_t s3_standard_config[] = {
{
.name = "memory",
@@ -11529,7 +11677,7 @@ const device_t s3_stb_powergraph_64_video_vlb_device = {
.available = s3_stb_powergraph_64_video_available,
.speed_changed = s3_speed_changed,
.force_redraw = s3_force_redraw,
.config = s3_phoenix_trio32_config
.config = s3_phoenix_trio32_v_config
};
const device_t s3_phoenix_trio64vplus_onboard_pci_device = {
@@ -11543,7 +11691,7 @@ const device_t s3_phoenix_trio64vplus_onboard_pci_device = {
.available = NULL,
.speed_changed = s3_speed_changed,
.force_redraw = s3_force_redraw,
.config = s3_standard_config
.config = s3_trio64v_config
};
const device_t s3_phoenix_trio64vplus_pci_device = {
@@ -11557,7 +11705,7 @@ const device_t s3_phoenix_trio64vplus_pci_device = {
.available = s3_phoenix_trio64vplus_available,
.speed_changed = s3_speed_changed,
.force_redraw = s3_force_redraw,
.config = s3_standard_config
.config = s3_trio64v_config
};
const device_t s3_cardex_trio64vplus_pci_device = {
@@ -11571,7 +11719,7 @@ const device_t s3_cardex_trio64vplus_pci_device = {
.available = s3_cardex_trio64vplus_available,
.speed_changed = s3_speed_changed,
.force_redraw = s3_force_redraw,
.config = s3_standard_config
.config = s3_trio64v_config
};
const device_t s3_phoenix_vision864_vlb_device = {
@@ -11711,7 +11859,7 @@ const device_t s3_trio64v2_dx_pci_device = {
.available = s3_trio64v2_dx_available,
.speed_changed = s3_speed_changed,
.force_redraw = s3_force_redraw,
.config = s3_standard_config
.config = s3_trio64v_config
};
const device_t s3_trio64v2_dx_onboard_pci_device = {
@@ -11725,5 +11873,5 @@ const device_t s3_trio64v2_dx_onboard_pci_device = {
.available = NULL,
.speed_changed = s3_speed_changed,
.force_redraw = s3_force_redraw,
.config = s3_standard_config
.config = s3_trio64v_config
};

View File

@@ -4815,7 +4815,6 @@ s3_virge_colorkey(virge_t* virge, uint32_t x, uint32_t y)
uint32_t base_addr = svga->memaddr_latch;
uint32_t stride = (virge->chip < S3_VIRGEGX2) ? virge->streams.pri_stride : (svga->rowoffset << 3);
bool chroma_key = false;
bool color_key = false;
bool alpha_key = false;
@@ -4913,10 +4912,8 @@ s3_virge_colorkey(virge_t* virge, uint32_t x, uint32_t y)
if (virge->chip < S3_VIRGEGX2) {
color_key = true;
chroma_key = false;
} else {
color_key = ((virge->streams.chroma_ctrl >> 29) & 3) == 2;
chroma_key = ((virge->streams.chroma_ctrl >> 29) & 3) == 3;
}
if (color_key) {

View File

@@ -1,7 +1,5 @@
/*Current issues :
- missing screen->screen scaled blits with format conversion
- missing YUV blits (YUV -> 32-bit, 24-bit, or 16-bit RGB now done)
- missing linestyle
- missing wait for vsync
- missing reversible lines