From 5e0dd65738a018096dd8774ca0a370746c19c7cd Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 19 Aug 2025 23:52:54 +0600 Subject: [PATCH] Add color/chroma-keying to S3 Trio64V+ and Trio64V2/DX Clean up some TODOs in Voodoo 3/Banshee code --- src/video/vid_s3.c | 164 +++++++++++++++++++++++-- src/video/vid_s3_virge.c | 3 - src/video/vid_voodoo_banshee_blitter.c | 2 - 3 files changed, 156 insertions(+), 13 deletions(-) diff --git a/src/video/vid_s3.c b/src/video/vid_s3.c index 03b662b2e..3704df946 100644 --- a/src/video/vid_s3.c +++ b/src/video/vid_s3.c @@ -24,6 +24,7 @@ #include #include #include +#include #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 }; diff --git a/src/video/vid_s3_virge.c b/src/video/vid_s3_virge.c index 1291b9d59..a4b64cad8 100644 --- a/src/video/vid_s3_virge.c +++ b/src/video/vid_s3_virge.c @@ -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) { diff --git a/src/video/vid_voodoo_banshee_blitter.c b/src/video/vid_voodoo_banshee_blitter.c index cf2824bba..ad92d580f 100644 --- a/src/video/vid_voodoo_banshee_blitter.c +++ b/src/video/vid_voodoo_banshee_blitter.c @@ -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