MGA: Implement gamma-correction for <= 16 bpp modes

This commit is contained in:
Cacodemon345
2023-12-25 15:24:52 +06:00
parent 278661c41c
commit 1bd4bbdfa1
4 changed files with 104 additions and 68 deletions

View File

@@ -271,6 +271,9 @@ typedef struct svga_t {
/* Enable LUT mapping of >= 24 bpp modes. */
int lut_map;
/* Return a 32 bpp color from a 15/16 bpp color. */
uint32_t (*conv_16to32)(struct svga_t *svga, uint16_t color, uint8_t bpp);
void * dev8514;
void * xga;
} svga_t;

View File

@@ -5728,6 +5728,31 @@ mystique_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
}
}
static uint32_t
mystique_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp)
{
mystique_t *mystique = (mystique_t*)svga->priv;
if (svga->lut_map) {
if (bpp == 15) {
if (mystique->xgenctrl & (1 << 2)) {
color &= 0x7FFF;
}
uint8_t b = getcolr(svga->pallook[(color & 0x1F) | (!!(color & 0x8000) >> 8)]);
uint8_t g = getcolg(svga->pallook[((color & 0x3E0) >> 5) | (!!(color & 0x8000) >> 8)]);
uint8_t r = getcolb(svga->pallook[((color & 0x7C00) >> 10) | (!!(color & 0x8000) >> 8)]);
return video_15to32[color] & 0xFF000000 | makecol(r, g, b);
} else {
uint8_t b = getcolr(svga->pallook[color & 0x1f]);
uint8_t g = getcolg(svga->pallook[(color & 0x7e0) >> 5]);
uint8_t r = getcolb(svga->pallook[(color & 0xf800) >> 11]);
return video_16to32[color] & 0xFF000000 | makecol(r, g, b);
}
}
return (bpp == 15) ? video_15to32[color] : video_16to32[color];
}
static void *
mystique_init(const device_t *info)
{
@@ -5852,6 +5877,7 @@ mystique_init(const device_t *info)
mystique->softrap_status_read = 1;
mystique->svga.vsync_callback = mystique_vsync_callback;
mystique->svga.conv_16to32 = mystique_conv_16to32;
mystique->i2c = i2c_gpio_init("i2c_mga");
mystique->i2c_ddc = i2c_gpio_init("ddc_mga");

View File

@@ -1102,6 +1102,12 @@ svga_poll(void *priv)
}
}
uint32_t
svga_conv_16to32(struct svga_t *svga, uint16_t color, uint8_t bpp)
{
return (bpp == 15) ? video_15to32[color] : video_16to32[color];
}
int
svga_init(const device_t *info, svga_t *svga, void *priv, int memsize,
void (*recalctimings_ex)(struct svga_t *svga),
@@ -1148,6 +1154,7 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize,
svga->video_out = video_out;
svga->hwcursor_draw = hwcursor_draw;
svga->overlay_draw = overlay_draw;
svga->conv_16to32 = svga_conv_16to32;
svga->hwcursor.cur_xsize = svga->hwcursor.cur_ysize = 32;

View File

@@ -1042,13 +1042,13 @@ svga_render_15bpp_lowres(svga_t *svga)
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x << 1] = p[(x << 1) + 1] = video_15to32[dat & 0xffff];
p[(x << 1) + 2] = p[(x << 1) + 3] = video_15to32[dat >> 16];
p[x << 1] = p[(x << 1) + 1] = svga->conv_16to32(svga, dat & 0xffff, 15);
p[(x << 1) + 2] = p[(x << 1) + 3] = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[(x << 1) + 4] = p[(x << 1) + 5] = video_15to32[dat & 0xffff];
p[(x << 1) + 6] = p[(x << 1) + 7] = video_15to32[dat >> 16];
p[(x << 1) + 4] = p[(x << 1) + 5] = svga->conv_16to32(svga, dat & 0xffff, 15);
p[(x << 1) + 6] = p[(x << 1) + 7] = svga->conv_16to32(svga, dat >> 16, 15);
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
@@ -1067,13 +1067,13 @@ svga_render_15bpp_lowres(svga_t *svga)
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
}
svga->ma += x << 1;
} else {
@@ -1081,8 +1081,8 @@ svga_render_15bpp_lowres(svga_t *svga)
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
svga->ma += 4;
}
}
@@ -1113,20 +1113,20 @@ svga_render_15bpp_highres(svga_t *svga)
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x] = video_15to32[dat & 0xffff];
p[x + 1] = video_15to32[dat >> 16];
p[x] = svga->conv_16to32(svga, dat & 0xffff, 15);
p[x + 1] = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[x + 2] = video_15to32[dat & 0xffff];
p[x + 3] = video_15to32[dat >> 16];
p[x + 2] = svga->conv_16to32(svga, dat & 0xffff, 15);
p[x + 3] = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
p[x + 4] = video_15to32[dat & 0xffff];
p[x + 5] = video_15to32[dat >> 16];
p[x + 4] = svga->conv_16to32(svga, dat & 0xffff, 15);
p[x + 5] = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
p[x + 6] = video_15to32[dat & 0xffff];
p[x + 7] = video_15to32[dat >> 16];
p[x + 6] = svga->conv_16to32(svga, dat & 0xffff, 15);
p[x + 7] = svga->conv_16to32(svga, dat >> 16, 15);
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
@@ -1144,20 +1144,20 @@ svga_render_15bpp_highres(svga_t *svga)
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
}
svga->ma += x << 1;
} else {
@@ -1165,8 +1165,8 @@ svga_render_15bpp_highres(svga_t *svga)
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = video_15to32[dat & 0xffff];
*p++ = video_15to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 15);
*p++ = svga->conv_16to32(svga, dat >> 16, 15);
svga->ma += 4;
}
}
@@ -1194,16 +1194,16 @@ svga_render_15bpp_mix_lowres(svga_t *svga)
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x << 1] = p[(x << 1) + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x << 1] = p[(x << 1) + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat >>= 16;
p[(x << 1) + 2] = p[(x << 1) + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[(x << 1) + 2] = p[(x << 1) + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[(x << 1) + 4] = p[(x << 1) + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[(x << 1) + 4] = p[(x << 1) + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat >>= 16;
p[(x << 1) + 6] = p[(x << 1) + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[(x << 1) + 6] = p[(x << 1) + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
@@ -1229,24 +1229,24 @@ svga_render_15bpp_mix_highres(svga_t *svga)
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat >>= 16;
p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x + 1] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x + 2] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat >>= 16;
p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x + 3] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
p[x + 4] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x + 4] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat >>= 16;
p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x + 5] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
p[x + 6] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x + 6] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
dat >>= 16;
p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : video_15to32[dat & 0xffff];
p[x + 7] = (dat & 0x00008000) ? svga->pallook[dat & 0xff] : svga->conv_16to32(svga, dat & 0xffff, 15);
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
@@ -1275,12 +1275,12 @@ svga_render_16bpp_lowres(svga_t *svga)
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x << 1] = p[(x << 1) + 1] = video_16to32[dat & 0xffff];
p[(x << 1) + 2] = p[(x << 1) + 3] = video_16to32[dat >> 16];
p[x << 1] = p[(x << 1) + 1] = svga->conv_16to32(svga, dat & 0xffff, 16);
p[(x << 1) + 2] = p[(x << 1) + 3] = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[(x << 1) + 4] = p[(x << 1) + 5] = video_16to32[dat & 0xffff];
p[(x << 1) + 6] = p[(x << 1) + 7] = video_16to32[dat >> 16];
p[(x << 1) + 4] = p[(x << 1) + 5] = svga->conv_16to32(svga, dat & 0xffff, 16);
p[(x << 1) + 6] = p[(x << 1) + 7] = svga->conv_16to32(svga, dat >> 16, 16);
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
@@ -1299,13 +1299,13 @@ svga_render_16bpp_lowres(svga_t *svga)
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
}
svga->ma += x << 1;
} else {
@@ -1313,8 +1313,8 @@ svga_render_16bpp_lowres(svga_t *svga)
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
}
svga->ma += 4;
}
@@ -1345,20 +1345,20 @@ svga_render_16bpp_highres(svga_t *svga)
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
uint32_t dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
p[x] = video_16to32[dat & 0xffff];
p[x + 1] = video_16to32[dat >> 16];
p[x] = svga->conv_16to32(svga, dat & 0xffff, 16);
p[x + 1] = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
p[x + 2] = video_16to32[dat & 0xffff];
p[x + 3] = video_16to32[dat >> 16];
p[x + 2] = svga->conv_16to32(svga, dat & 0xffff, 16);
p[x + 3] = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
p[x + 4] = video_16to32[dat & 0xffff];
p[x + 5] = video_16to32[dat >> 16];
p[x + 4] = svga->conv_16to32(svga, dat & 0xffff, 16);
p[x + 5] = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
p[x + 6] = video_16to32[dat & 0xffff];
p[x + 7] = video_16to32[dat >> 16];
p[x + 6] = svga->conv_16to32(svga, dat & 0xffff, 16);
p[x + 7] = svga->conv_16to32(svga, dat >> 16, 16);
}
svga->ma += x << 1;
svga->ma &= svga->vram_display_mask;
@@ -1376,20 +1376,20 @@ svga_render_16bpp_highres(svga_t *svga)
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 8) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
}
svga->ma += x << 1;
} else {
@@ -1397,8 +1397,8 @@ svga_render_16bpp_highres(svga_t *svga)
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = video_16to32[dat & 0xffff];
*p++ = video_16to32[dat >> 16];
*p++ = svga->conv_16to32(svga, dat & 0xffff, 16);
*p++ = svga->conv_16to32(svga, dat >> 16, 16);
svga->ma += 4;
}