Skip to content

Commit

Permalink
MGA: Implement gamma correction for 24+ bpp modes
Browse files Browse the repository at this point in the history
  • Loading branch information
Cacodemon345 committed Dec 23, 2023
1 parent 708a700 commit 70d6d59
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 33 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 @@ -268,6 +268,9 @@ typedef struct svga_t {
/* Pointer to monitor */
monitor_t *monitor;

/* Enable LUT mapping of >= 24 bpp modes. */
int lut_map;

void * dev8514;
void * xga;
} svga_t;
Expand Down
3 changes: 3 additions & 0 deletions src/include/86box/video.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ using atomic_int = std::atomic_int;

#define makecol(r, g, b) ((b) | ((g) << 8) | ((r) << 16))
#define makecol32(r, g, b) ((b) | ((g) << 8) | ((r) << 16))
#define getcolr(color) (((color) >> 16) & 0xFF)
#define getcolg(color) (((color) >> 8) & 0xFF)
#define getcolb(color) ((color) & 0xFF)

enum {
VID_NONE = 0,
Expand Down
2 changes: 2 additions & 0 deletions src/video/vid_mga.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,7 @@ mystique_recalctimings(svga_t *svga)
svga->hdisp = (svga->crtc[1] + 1) << 3;
svga->hdisp_time = svga->hdisp;
svga->rowoffset = svga->crtc[0x13] | ((mystique->crtcext_regs[0] & CRTCX_R0_OFFSET_MASK) << 4);
svga->lut_map = 1;

if (mystique->pci_regs[0x41] & (OPTION_INTERLEAVE >> 8)) {
svga->rowoffset <<= 1;
Expand Down Expand Up @@ -992,6 +993,7 @@ mystique_recalctimings(svga_t *svga)
} else {
svga->packed_chain4 = 0;
svga->line_compare = NULL;
svga->lut_map = 0;
if (mystique->type >= MGA_1064SG)
svga->bpp = 8;
else
Expand Down
80 changes: 47 additions & 33 deletions src/video/vid_svga_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@
#include <86box/vid_svga_render.h>
#include <86box/vid_svga_render_remap.h>

static inline uint32_t
lookup_lut_ram(svga_t* svga, uint32_t val)
{
if (!svga->lut_map)
return val;

uint8_t r = getcolr(svga->pallook[getcolr(val)]);
uint8_t g = getcolg(svga->pallook[getcolg(val)]);
uint8_t b = getcolb(svga->pallook[getcolb(val)]);
return makecol32(r, g, b) | (val & 0xFF000000);
}

#define lookup_lut(val) lookup_lut_ram(svga, val)

void
svga_render_null(svga_t *svga)
{
Expand Down Expand Up @@ -1422,7 +1436,7 @@ svga_render_24bpp_lowres(svga_t *svga)
fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 3;
svga->ma &= svga->vram_display_mask;
svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = fg;
svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = lookup_lut(fg);
}
}
} else {
Expand All @@ -1441,10 +1455,10 @@ svga_render_24bpp_lowres(svga_t *svga)
dat1 = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
dat2 = *(uint32_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);

p[0] = p[1] = dat0 & 0xffffff;
p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16);
p[6] = p[7] = dat2 >> 8;
p[0] = p[1] = lookup_lut(dat0 & 0xffffff);
p[2] = p[3] = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8));
p[4] = p[5] = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16));
p[6] = p[7] = lookup_lut(dat2 >> 8);

svga->ma += 12;
}
Expand All @@ -1457,10 +1471,10 @@ svga_render_24bpp_lowres(svga_t *svga)
addr = svga->remap_func(svga, svga->ma + 8);
dat2 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);

p[0] = p[1] = dat0 & 0xffffff;
p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16);
p[6] = p[7] = dat2 >> 8;
p[0] = p[1] = lookup_lut(dat0 & 0xffffff);
p[2] = p[3] = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8));
p[4] = p[5] = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16));
p[6] = p[7] = lookup_lut(dat2 >> 8);

svga->ma += 12;
}
Expand Down Expand Up @@ -1495,16 +1509,16 @@ svga_render_24bpp_highres(svga_t *svga)

for (x = 0; x <= (svga->hdisp + svga->scrollcache); x += 4) {
dat = *(uint32_t *) (&svga->vram[svga->ma & svga->vram_display_mask]);
p[x] = dat & 0xffffff;
p[x] = lookup_lut(dat & 0xffffff);

dat = *(uint32_t *) (&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
p[x + 1] = dat & 0xffffff;
p[x + 1] = lookup_lut(dat & 0xffffff);

dat = *(uint32_t *) (&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
p[x + 2] = dat & 0xffffff;
p[x + 2] = lookup_lut(dat & 0xffffff);

dat = *(uint32_t *) (&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
p[x + 3] = dat & 0xffffff;
p[x + 3] = lookup_lut(dat & 0xffffff);

svga->ma += 12;
}
Expand All @@ -1526,10 +1540,10 @@ svga_render_24bpp_highres(svga_t *svga)
dat1 = *(uint32_t *) (&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
dat2 = *(uint32_t *) (&svga->vram[(svga->ma + 8) & svga->vram_display_mask]);

*p++ = dat0 & 0xffffff;
*p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
*p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16);
*p++ = dat2 >> 8;
*p++ = lookup_lut(dat0 & 0xffffff);
*p++ = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8));
*p++ = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16));
*p++ = lookup_lut(dat2 >> 8);

svga->ma += 12;
}
Expand All @@ -1542,10 +1556,10 @@ svga_render_24bpp_highres(svga_t *svga)
addr = svga->remap_func(svga, svga->ma + 8);
dat2 = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);

*p++ = dat0 & 0xffffff;
*p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8);
*p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16);
*p++ = dat2 >> 8;
*p++ = lookup_lut(dat0 & 0xffffff);
*p++ = lookup_lut((dat0 >> 24) | ((dat1 & 0xffff) << 8));
*p++ = lookup_lut((dat1 >> 16) | ((dat2 & 0xff) << 16));
*p++ = lookup_lut(dat2 >> 8);

svga->ma += 12;
}
Expand Down Expand Up @@ -1577,7 +1591,7 @@ svga_render_32bpp_lowres(svga_t *svga)
dat = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = dat;
svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + svga->x_add] = svga->monitor->target_buffer->line[svga->displine + svga->y_add][(x << 1) + 1 + svga->x_add] = lookup_lut(dat);
}
}
} else {
Expand All @@ -1593,16 +1607,16 @@ svga_render_32bpp_lowres(svga_t *svga)
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
*p++ = dat & 0xffffff;
*p++ = dat & 0xffffff;
*p++ = lookup_lut(dat & 0xffffff);
*p++ = lookup_lut(dat & 0xffffff);
}
svga->ma += (x * 4);
} else {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = dat & 0xffffff;
*p++ = dat & 0xffffff;
*p++ = lookup_lut(dat & 0xffffff);
*p++ = lookup_lut(dat & 0xffffff);
svga->ma += 4;
}
svga->ma &= svga->vram_display_mask;
Expand Down Expand Up @@ -1633,7 +1647,7 @@ svga_render_32bpp_highres(svga_t *svga)

for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
p[x] = dat & 0xffffff;
p[x] = lookup_lut(dat & 0xffffff);
}
svga->ma += 4;
svga->ma &= svga->vram_display_mask;
Expand All @@ -1651,14 +1665,14 @@ svga_render_32bpp_highres(svga_t *svga)
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
*p++ = dat & 0xffffff;
*p++ = lookup_lut(dat & 0xffffff);
}
svga->ma += (x * 4);
} else {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = dat & 0xffffff;
*p++ = lookup_lut(dat & 0xffffff);

svga->ma += 4;
}
Expand Down Expand Up @@ -1692,14 +1706,14 @@ svga_render_ABGR8888_highres(svga_t *svga)
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
*p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
*p++ = lookup_lut(((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16));
}
svga->ma += x * 4;
} else {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
*p++ = lookup_lut(((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16));

svga->ma += 4;
}
Expand Down Expand Up @@ -1732,14 +1746,14 @@ svga_render_RGBA8888_highres(svga_t *svga)
if (!svga->remap_required) {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
dat = *(uint32_t *) (&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
*p++ = dat >> 8;
*p++ = lookup_lut(dat >> 8);
}
svga->ma += (x * 4);
} else {
for (x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
addr = svga->remap_func(svga, svga->ma);
dat = *(uint32_t *) (&svga->vram[addr & svga->vram_display_mask]);
*p++ = dat >> 8;
*p++ = lookup_lut(dat >> 8);

svga->ma += 4;
}
Expand Down

0 comments on commit 70d6d59

Please sign in to comment.