Skip to content

Commit

Permalink
MGA: Implement gamma-correction for <= 16 bpp modes
Browse files Browse the repository at this point in the history
  • Loading branch information
Cacodemon345 committed Dec 25, 2023
1 parent 278661c commit 1bd4bbd
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 68 deletions.
3 changes: 3 additions & 0 deletions src/include/86box/vid_svga.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
26 changes: 26 additions & 0 deletions src/video/vid_mga.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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");
Expand Down
7 changes: 7 additions & 0 deletions src/video/vid_svga.c
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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;

Expand Down
136 changes: 68 additions & 68 deletions src/video/vid_svga_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -1067,22 +1067,22 @@ 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 {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) {
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;
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -1144,29 +1144,29 @@ 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 {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) {
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;
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -1299,22 +1299,22 @@ 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 {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) {
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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -1376,29 +1376,29 @@ 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 {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 2) {
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;
}
Expand Down

0 comments on commit 1bd4bbd

Please sign in to comment.