Move components of video cards (external ramdacs and clock generators that could be paired with many cards) to their own folders. Reorganise video cmakelists
This commit is contained in:
338
src/video/ramdac/vid_ramdac_ati68860.c
Normal file
338
src/video/ramdac/vid_ramdac_ati68860.c
Normal file
@@ -0,0 +1,338 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* ATI 68860 RAMDAC emulation (for Mach64)
|
||||
*
|
||||
* ATI 68860/68880 Truecolor DACs:
|
||||
* REG08 (R/W):
|
||||
* bit 0-? Always 2 ??
|
||||
*
|
||||
* REG0A (R/W):
|
||||
* bit 0-? Always 1Dh ??
|
||||
*
|
||||
* REG0B (R/W): (GMR ?)
|
||||
* bit 0-7 Mode. 82h: 4bpp, 83h: 8bpp,
|
||||
* A0h: 15bpp, A1h: 16bpp, C0h: 24bpp,
|
||||
* E3h: 32bpp (80h for VGA modes ?)
|
||||
*
|
||||
* REG0C (R/W): Device Setup Register A
|
||||
* bit 0 Controls 6/8bit DAC. 0: 8bit DAC/LUT, 1: 6bit DAC/LUT
|
||||
* 2-3 Depends on Video memory (= VRAM width ?) .
|
||||
* 1: Less than 1Mb, 2: 1Mb, 3: > 1Mb
|
||||
* 5-6 Always set ?
|
||||
* 7 If set can remove "snow" in some cases
|
||||
* (A860_Delay_L ?) ??
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_8514a.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_svga_render.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct ati68860_ramdac_t {
|
||||
uint8_t regs[16];
|
||||
void (*render)(struct svga_t *svga);
|
||||
|
||||
int dac_addr;
|
||||
int dac_pos;
|
||||
int dac_r;
|
||||
int dac_g;
|
||||
PALETTE pal;
|
||||
uint32_t pallook[2];
|
||||
|
||||
int ramdac_type;
|
||||
} ati68860_ramdac_t;
|
||||
|
||||
void
|
||||
ati68860_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0:
|
||||
svga_out(0x3c8, val, svga);
|
||||
break;
|
||||
case 1:
|
||||
svga_out(0x3c9, val, svga);
|
||||
break;
|
||||
case 2:
|
||||
svga_out(0x3c6, val, svga);
|
||||
break;
|
||||
case 3:
|
||||
svga_out(0x3c7, val, svga);
|
||||
break;
|
||||
default:
|
||||
ramdac->regs[addr & 0xf] = val;
|
||||
switch (addr & 0xf) {
|
||||
case 0x4:
|
||||
ramdac->dac_addr = val;
|
||||
ramdac->dac_pos = 0;
|
||||
break;
|
||||
case 0x5:
|
||||
switch (ramdac->dac_pos) {
|
||||
case 0:
|
||||
ramdac->dac_r = val;
|
||||
ramdac->dac_pos++;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->dac_g = val;
|
||||
ramdac->dac_pos++;
|
||||
break;
|
||||
case 2:
|
||||
if (ramdac->dac_addr > 1)
|
||||
break;
|
||||
ramdac->pal[ramdac->dac_addr].r = ramdac->dac_r;
|
||||
ramdac->pal[ramdac->dac_addr].g = ramdac->dac_g;
|
||||
ramdac->pal[ramdac->dac_addr].b = val;
|
||||
if (ramdac->ramdac_type == RAMDAC_8BIT)
|
||||
ramdac->pallook[ramdac->dac_addr] = makecol32(ramdac->pal[ramdac->dac_addr].r,
|
||||
ramdac->pal[ramdac->dac_addr].g,
|
||||
ramdac->pal[ramdac->dac_addr].b);
|
||||
else
|
||||
ramdac->pallook[ramdac->dac_addr] = makecol32(video_6to8[ramdac->pal[ramdac->dac_addr].r & 0x3f],
|
||||
video_6to8[ramdac->pal[ramdac->dac_addr].g & 0x3f],
|
||||
video_6to8[ramdac->pal[ramdac->dac_addr].b & 0x3f]);
|
||||
ramdac->dac_pos = 0;
|
||||
ramdac->dac_addr = (ramdac->dac_addr + 1) & 255;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xb:
|
||||
switch (val) {
|
||||
case 0x82:
|
||||
ramdac->render = svga_render_4bpp_highres;
|
||||
break;
|
||||
case 0x83:
|
||||
/*FIXME*/
|
||||
ramdac->render = svga_render_8bpp_clone_highres;
|
||||
break;
|
||||
case 0xa0:
|
||||
case 0xb0:
|
||||
ramdac->render = svga_render_15bpp_highres;
|
||||
break;
|
||||
case 0xa1:
|
||||
case 0xb1:
|
||||
ramdac->render = svga_render_16bpp_highres;
|
||||
break;
|
||||
case 0xc0:
|
||||
case 0xd0:
|
||||
ramdac->render = svga_render_24bpp_highres;
|
||||
break;
|
||||
case 0xe2:
|
||||
case 0xf7:
|
||||
ramdac->render = svga_render_32bpp_highres;
|
||||
break;
|
||||
case 0xe3:
|
||||
ramdac->render = svga_render_ABGR8888_highres;
|
||||
break;
|
||||
case 0xf2:
|
||||
ramdac->render = svga_render_RGBA8888_highres;
|
||||
break;
|
||||
default:
|
||||
/*FIXME*/
|
||||
ramdac->render = svga_render_8bpp_clone_highres;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xc:
|
||||
svga_set_ramdac_type(svga, (val & 1) ? RAMDAC_6BIT : RAMDAC_8BIT);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ati68860_ramdac_in(uint16_t addr, void *priv, svga_t *svga)
|
||||
{
|
||||
const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
|
||||
uint8_t temp = 0;
|
||||
|
||||
switch (addr) {
|
||||
case 0:
|
||||
temp = svga_in(0x3c8, svga);
|
||||
break;
|
||||
case 1:
|
||||
temp = svga_in(0x3c9, svga);
|
||||
break;
|
||||
case 2:
|
||||
temp = svga_in(0x3c6, svga);
|
||||
break;
|
||||
case 3:
|
||||
temp = svga_in(0x3c7, svga);
|
||||
break;
|
||||
case 4:
|
||||
case 8:
|
||||
temp = 2;
|
||||
break;
|
||||
case 6:
|
||||
case 0xa:
|
||||
temp = 0x1d;
|
||||
break;
|
||||
case 0xf:
|
||||
temp = 0xd0;
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = ramdac->regs[addr & 0xf];
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void
|
||||
ati68860_set_ramdac_type(void *priv, int type)
|
||||
{
|
||||
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
|
||||
|
||||
if (ramdac->ramdac_type != type) {
|
||||
ramdac->ramdac_type = type;
|
||||
|
||||
for (uint8_t c = 0; c < 2; c++) {
|
||||
if (ramdac->ramdac_type == RAMDAC_8BIT)
|
||||
ramdac->pallook[c] = makecol32(ramdac->pal[c].r, ramdac->pal[c].g,
|
||||
ramdac->pal[c].b);
|
||||
else
|
||||
ramdac->pallook[c] = makecol32(video_6to8[ramdac->pal[c].r & 0x3f], video_6to8[ramdac->pal[c].g & 0x3f],
|
||||
video_6to8[ramdac->pal[c].b & 0x3f]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
ati68860_ramdac_init(UNUSED(const device_t *info))
|
||||
{
|
||||
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) malloc(sizeof(ati68860_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(ati68860_ramdac_t));
|
||||
|
||||
/*FIXME*/
|
||||
ramdac->render = svga_render_8bpp_clone_highres;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
void
|
||||
ati68860_ramdac_set_render(void *priv, svga_t *svga)
|
||||
{
|
||||
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
|
||||
|
||||
svga->render = ramdac->render;
|
||||
}
|
||||
|
||||
void
|
||||
ati68860_ramdac_set_pallook(void *priv, int i, uint32_t col)
|
||||
{
|
||||
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
|
||||
|
||||
ramdac->pallook[i] = col;
|
||||
}
|
||||
|
||||
void
|
||||
ati68860_hwcursor_draw(svga_t *svga, int displine)
|
||||
{
|
||||
const ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) svga->ramdac;
|
||||
int comb;
|
||||
int offset;
|
||||
int x_pos;
|
||||
int y_pos;
|
||||
int shift = 0;
|
||||
uint16_t dat;
|
||||
uint32_t col0 = ramdac->pallook[0];
|
||||
uint32_t col1 = ramdac->pallook[1];
|
||||
uint32_t *p;
|
||||
|
||||
offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff;
|
||||
if (svga->packed_4bpp)
|
||||
shift = 1;
|
||||
|
||||
for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += (8 >> shift)) {
|
||||
if (shift) {
|
||||
dat = svga->vram[(svga->dac_hwcursor_latch.addr) & svga->vram_mask] & 0x0f;
|
||||
dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 1) & svga->vram_mask] << 4);
|
||||
dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 2) & svga->vram_mask] << 8);
|
||||
dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 3) & svga->vram_mask] << 12);
|
||||
} else {
|
||||
dat = svga->vram[svga->dac_hwcursor_latch.addr & svga->vram_mask];
|
||||
dat |= (svga->vram[(svga->dac_hwcursor_latch.addr + 1) & svga->vram_mask] << 8);
|
||||
}
|
||||
for (int xx = 0; xx < (8 >> shift); xx++) {
|
||||
comb = (dat >> (xx << 1)) & 0x03;
|
||||
|
||||
y_pos = displine;
|
||||
x_pos = offset + svga->x_add;
|
||||
p = buffer32->line[y_pos];
|
||||
|
||||
if (offset >= svga->dac_hwcursor_latch.x) {
|
||||
switch (comb) {
|
||||
case 0:
|
||||
p[x_pos] = col0;
|
||||
break;
|
||||
case 1:
|
||||
p[x_pos] = col1;
|
||||
break;
|
||||
case 3:
|
||||
p[x_pos] ^= 0xffffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
svga->dac_hwcursor_latch.addr += 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ati68860_ramdac_close(void *priv)
|
||||
{
|
||||
ati68860_ramdac_t *ramdac = (ati68860_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t ati68860_ramdac_device = {
|
||||
.name = "ATI-68860 RAMDAC",
|
||||
.internal_name = "ati68860_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = ati68860_ramdac_init,
|
||||
.close = ati68860_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
167
src/video/ramdac/vid_ramdac_ati68875.c
Normal file
167
src/video/ramdac/vid_ramdac_ati68875.c
Normal file
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the Mach32-compatible ATI 68875 RAMDAC and clones.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: TheCollector1995.
|
||||
*
|
||||
* Copyright 2022-2023 TheCollector1995.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_svga_render.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct ati68875_ramdac_t {
|
||||
uint8_t gen_cntl;
|
||||
uint8_t in_clk_sel;
|
||||
uint8_t out_clk_sel;
|
||||
uint8_t mux_cntl;
|
||||
uint8_t palette_page_sel;
|
||||
uint8_t test_reg;
|
||||
} ati68875_ramdac_t;
|
||||
|
||||
void
|
||||
ati68875_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
|
||||
rs |= (!!rs2 << 2);
|
||||
rs |= (!!rs3 << 3);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
case 0x01: /* Palette Data Register (RS value = 0001) */
|
||||
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
|
||||
case 0x03:
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
case 0x08: /* General Control Register (RS value = 1000) */
|
||||
ramdac->gen_cntl = val;
|
||||
break;
|
||||
case 0x09: /* Input Clock Selection Register (RS value = 1001) */
|
||||
ramdac->in_clk_sel = val;
|
||||
break;
|
||||
case 0x0a: /* Output Clock Selection Register (RS value = 1010) */
|
||||
ramdac->out_clk_sel = val;
|
||||
break;
|
||||
case 0x0b: /* MUX Control Register (RS value = 1011) */
|
||||
ramdac->mux_cntl = val;
|
||||
break;
|
||||
case 0x0c: /* Palette Page Register (RS value = 1100) */
|
||||
ramdac->palette_page_sel = val;
|
||||
break;
|
||||
case 0x0e: /* Test Register (RS value = 1110) */
|
||||
ramdac->test_reg = val;
|
||||
break;
|
||||
case 0x0f: /* Reset State (RS value = 1111) */
|
||||
ramdac->mux_cntl = 0x2d;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ati68875_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga)
|
||||
{
|
||||
const ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
uint8_t temp = 0;
|
||||
|
||||
rs |= (!!rs2 << 2);
|
||||
rs |= (!!rs3 << 3);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
case 0x01: /* Palette Data Register (RS value = 0001) */
|
||||
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
|
||||
case 0x03:
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
case 0x08: /* General Control Register (RS value = 1000) */
|
||||
temp = ramdac->gen_cntl;
|
||||
break;
|
||||
case 0x09: /* Input Clock Selection Register (RS value = 1001) */
|
||||
temp = ramdac->in_clk_sel;
|
||||
break;
|
||||
case 0x0a: /* Output Clock Selection Register (RS value = 1010) */
|
||||
temp = ramdac->out_clk_sel;
|
||||
break;
|
||||
case 0x0b: /* MUX Control Register (RS value = 1011) */
|
||||
temp = ramdac->mux_cntl;
|
||||
break;
|
||||
case 0x0c: /* Palette Page Register (RS value = 1100) */
|
||||
temp = ramdac->palette_page_sel;
|
||||
break;
|
||||
case 0x0e: /* Test Register (RS value = 1110) */
|
||||
switch (ramdac->test_reg & 0x07) {
|
||||
case 0x03:
|
||||
temp = 0x75;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void *
|
||||
ati68875_ramdac_init(UNUSED(const device_t *info))
|
||||
{
|
||||
ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) malloc(sizeof(ati68875_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(ati68875_ramdac_t));
|
||||
|
||||
ramdac->mux_cntl = 0x2d;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
ati68875_ramdac_close(void *priv)
|
||||
{
|
||||
ati68875_ramdac_t *ramdac = (ati68875_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t ati68875_ramdac_device = {
|
||||
.name = "ATI 68875 RAMDAC",
|
||||
.internal_name = "ati68875_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = ati68875_ramdac_init,
|
||||
.close = ati68875_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
217
src/video/ramdac/vid_ramdac_att20c49x.c
Normal file
217
src/video/ramdac/vid_ramdac_att20c49x.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of a AT&T 20c490/491 and 492/493 RAMDAC.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
|
||||
typedef struct att49x_ramdac_t {
|
||||
int type;
|
||||
int state;
|
||||
uint8_t ctrl;
|
||||
} att49x_ramdac_t;
|
||||
|
||||
enum {
|
||||
ATT_490 = 0,
|
||||
ATT_491,
|
||||
ATT_492
|
||||
};
|
||||
|
||||
static void
|
||||
att49x_ramdac_control(uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv;
|
||||
ramdac->ctrl = val;
|
||||
switch ((ramdac->ctrl >> 5) & 7) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 6:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 7:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ramdac->type == ATT_490 || ramdac->type == ATT_491)
|
||||
svga_set_ramdac_type(svga, (val & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void
|
||||
att49x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
rs |= ((!!rs2) << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
svga_out(addr, val, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x02:
|
||||
switch (ramdac->state) {
|
||||
case 4:
|
||||
att49x_ramdac_control(val, ramdac, svga);
|
||||
break;
|
||||
default:
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x06:
|
||||
att49x_ramdac_control(val, ramdac, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
att49x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga)
|
||||
{
|
||||
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
rs |= ((!!rs2) << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
temp = svga_in(addr, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x02:
|
||||
switch (ramdac->state) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
temp = 0x00;
|
||||
ramdac->state++;
|
||||
break;
|
||||
case 4:
|
||||
temp = ramdac->ctrl;
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
ramdac->state++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x06:
|
||||
temp = ramdac->ctrl;
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void *
|
||||
att49x_ramdac_init(const device_t *info)
|
||||
{
|
||||
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) malloc(sizeof(att49x_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(att49x_ramdac_t));
|
||||
|
||||
ramdac->type = info->local;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
att49x_ramdac_close(void *priv)
|
||||
{
|
||||
att49x_ramdac_t *ramdac = (att49x_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t att490_ramdac_device = {
|
||||
.name = "AT&T 20c490 RAMDAC",
|
||||
.internal_name = "att490_ramdac",
|
||||
.flags = 0,
|
||||
.local = ATT_490,
|
||||
.init = att49x_ramdac_init,
|
||||
.close = att49x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t att491_ramdac_device = {
|
||||
.name = "AT&T 20c491 RAMDAC",
|
||||
.internal_name = "att491_ramdac",
|
||||
.flags = 0,
|
||||
.local = ATT_491,
|
||||
.init = att49x_ramdac_init,
|
||||
.close = att49x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t att492_ramdac_device = {
|
||||
.name = "AT&T 20c492 RAMDAC",
|
||||
.internal_name = "att492_ramdac",
|
||||
.flags = 0,
|
||||
.local = ATT_492,
|
||||
.init = att49x_ramdac_init,
|
||||
.close = att49x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
190
src/video/ramdac/vid_ramdac_att2xc498.c
Normal file
190
src/video/ramdac/vid_ramdac_att2xc498.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of a AT&T 2xc498 RAMDAC.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
|
||||
typedef struct att498_ramdac_t {
|
||||
int type;
|
||||
int state;
|
||||
int loop;
|
||||
uint8_t ctrl;
|
||||
} att498_ramdac_t;
|
||||
|
||||
static void
|
||||
att498_ramdac_control(uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
att498_ramdac_t *ramdac = (att498_ramdac_t *) priv;
|
||||
ramdac->ctrl = val;
|
||||
|
||||
if (val == 0xff)
|
||||
return;
|
||||
|
||||
switch ((ramdac->ctrl >> 4) & 0x0f) {
|
||||
default:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 1:
|
||||
if (ramdac->ctrl & 4)
|
||||
svga->bpp = 15;
|
||||
else
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 3:
|
||||
case 6:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 5:
|
||||
case 7:
|
||||
svga->bpp = 32;
|
||||
break;
|
||||
case 0x0e:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
}
|
||||
|
||||
svga_set_ramdac_type(svga, (ramdac->ctrl & 2) ? RAMDAC_8BIT : RAMDAC_6BIT);
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void
|
||||
att498_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
att498_ramdac_t *ramdac = (att498_ramdac_t *) priv;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
rs |= ((!!rs2) << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
svga_out(addr, val, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x02:
|
||||
switch (ramdac->state) {
|
||||
case 4:
|
||||
att498_ramdac_control(val, ramdac, svga);
|
||||
break;
|
||||
default:
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x06:
|
||||
att498_ramdac_control(val, ramdac, svga);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
att498_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga)
|
||||
{
|
||||
att498_ramdac_t *ramdac = (att498_ramdac_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
rs |= ((!!rs2) << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
temp = svga_in(addr, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x02:
|
||||
switch (ramdac->state) {
|
||||
case 4:
|
||||
temp = ramdac->ctrl;
|
||||
ramdac->state++;
|
||||
break;
|
||||
case 5:
|
||||
temp = 0x84;
|
||||
ramdac->state++;
|
||||
break;
|
||||
case 6:
|
||||
temp = ramdac->ctrl;
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
ramdac->state++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x06:
|
||||
temp = ramdac->ctrl;
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void *
|
||||
att498_ramdac_init(const device_t *info)
|
||||
{
|
||||
att498_ramdac_t *ramdac = (att498_ramdac_t *) malloc(sizeof(att498_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(att498_ramdac_t));
|
||||
|
||||
ramdac->type = info->local;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
att498_ramdac_close(void *priv)
|
||||
{
|
||||
att498_ramdac_t *ramdac = (att498_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t att498_ramdac_device = {
|
||||
.name = "AT&T 22c498 RAMDAC",
|
||||
.internal_name = "att498_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = att498_ramdac_init,
|
||||
.close = att498_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
161
src/video/ramdac/vid_ramdac_bt481.c
Normal file
161
src/video/ramdac/vid_ramdac_bt481.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the Brooktree BT481 true colour RAMDAC
|
||||
* family.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: TheCollector1995.
|
||||
*
|
||||
* Copyright 2024 TheCollector1995.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct bt481_ramdac_t {
|
||||
int state;
|
||||
uint8_t cmd;
|
||||
} bt481_ramdac_t;
|
||||
|
||||
static void
|
||||
bt481_ramdac_command(uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
bt481_ramdac_t *ramdac = (bt481_ramdac_t *) priv;
|
||||
ramdac->cmd = val;
|
||||
pclog("RAMDAC CMD=%02x.\n", val);
|
||||
switch ((ramdac->cmd >> 4) & 0x0f) {
|
||||
default:
|
||||
case 0x00:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x0a:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 0x09:
|
||||
case 0x0c:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
}
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void
|
||||
bt481_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
bt481_ramdac_t *ramdac = (bt481_ramdac_t *) priv;
|
||||
uint8_t rs = (addr & 0x03) | ((!!rs2) << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
case 0x07:
|
||||
svga_out(addr, val, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x02:
|
||||
pclog("RAMDAC Write State=%x.\n", ramdac->state);
|
||||
switch (ramdac->state) {
|
||||
case 4:
|
||||
bt481_ramdac_command(val, ramdac, svga);
|
||||
break;
|
||||
default:
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x06:
|
||||
bt481_ramdac_command(val, ramdac, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
bt481_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga)
|
||||
{
|
||||
bt481_ramdac_t * ramdac = (bt481_ramdac_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
uint8_t rs = (addr & 0x03) | ((!!rs2) << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 0x02:
|
||||
case 0x06:
|
||||
switch (ramdac->state) {
|
||||
case 4:
|
||||
temp = ramdac->cmd;
|
||||
break;
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
ramdac->state++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pclog("RAMDAC IN=%02x, ret=%02x.\n", rs, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void *
|
||||
bt481_ramdac_init(UNUSED(const device_t *info))
|
||||
{
|
||||
bt481_ramdac_t *ramdac = (bt481_ramdac_t *) malloc(sizeof(bt481_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(bt481_ramdac_t));
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
bt481_ramdac_close(void *priv)
|
||||
{
|
||||
bt481_ramdac_t *ramdac = (bt481_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t bt481_ramdac_device = {
|
||||
.name = "Brooktree Bt481 RAMDAC",
|
||||
.internal_name = "bt481_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = bt481_ramdac_init,
|
||||
.close = bt481_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
601
src/video/ramdac/vid_ramdac_bt48x.c
Normal file
601
src/video/ramdac/vid_ramdac_bt48x.c
Normal file
@@ -0,0 +1,601 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the Brooktree BT484-485A true colour RAMDAC
|
||||
* family.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* TheCollector1995,
|
||||
*
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2018 TheCollector1995.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
|
||||
typedef struct bt48x_ramdac_t {
|
||||
PALETTE extpal;
|
||||
uint32_t extpallook[256];
|
||||
uint8_t cursor32_data[256];
|
||||
uint8_t cursor64_data[1024];
|
||||
int hwc_y;
|
||||
int hwc_x;
|
||||
uint8_t cmd_r0;
|
||||
uint8_t cmd_r1;
|
||||
uint8_t cmd_r2;
|
||||
uint8_t cmd_r3;
|
||||
uint8_t cmd_r4;
|
||||
uint8_t status;
|
||||
uint8_t type;
|
||||
} bt48x_ramdac_t;
|
||||
|
||||
enum {
|
||||
BT484 = 0,
|
||||
ATT20C504,
|
||||
BT485,
|
||||
ATT20C505,
|
||||
BT485A
|
||||
};
|
||||
|
||||
static void
|
||||
bt48x_set_bpp(bt48x_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
if ((!(ramdac->cmd_r2 & 0x20)) || ((ramdac->type >= BT485A) && ((ramdac->cmd_r3 & 0x60) == 0x60)))
|
||||
svga->bpp = 8;
|
||||
else if ((ramdac->type >= BT485A) && ((ramdac->cmd_r3 & 0x60) == 0x40))
|
||||
svga->bpp = 24;
|
||||
else
|
||||
switch (ramdac->cmd_r1 & 0x60) {
|
||||
case 0x00:
|
||||
svga->bpp = 32;
|
||||
break;
|
||||
case 0x20:
|
||||
if (ramdac->cmd_r1 & 0x08)
|
||||
svga->bpp = 16;
|
||||
else
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 0x40:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 0x60:
|
||||
svga->bpp = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void
|
||||
bt48x_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv;
|
||||
uint32_t o32;
|
||||
uint8_t *cd;
|
||||
uint16_t index;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
uint16_t da_mask = 0x03ff;
|
||||
rs |= (!!rs2 << 2);
|
||||
rs |= (!!rs3 << 3);
|
||||
if (ramdac->type < BT485)
|
||||
da_mask = 0x00ff;
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
|
||||
case 0x03:
|
||||
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
|
||||
svga->dac_pos = 0;
|
||||
svga->dac_status = addr & 0x03;
|
||||
svga->dac_addr = val;
|
||||
if (ramdac->type >= BT485)
|
||||
svga->dac_addr |= ((ramdac->cmd_r3 & 0x03) << 8);
|
||||
if (svga->dac_status)
|
||||
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
|
||||
break;
|
||||
case 0x01: /* Palette Data Register (RS value = 0001) */
|
||||
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
|
||||
svga->dac_status = 0;
|
||||
svga->fullchange = changeframecount;
|
||||
switch (svga->dac_pos) {
|
||||
case 0:
|
||||
svga->dac_r = val;
|
||||
svga->dac_pos++;
|
||||
break;
|
||||
case 1:
|
||||
svga->dac_g = val;
|
||||
svga->dac_pos++;
|
||||
break;
|
||||
case 2:
|
||||
index = svga->dac_addr & 3;
|
||||
ramdac->extpal[index].r = svga->dac_r;
|
||||
ramdac->extpal[index].g = svga->dac_g;
|
||||
ramdac->extpal[index].b = val;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b);
|
||||
else
|
||||
ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]);
|
||||
|
||||
if (svga->ext_overscan && !index) {
|
||||
o32 = svga->overscan_color;
|
||||
svga->overscan_color = ramdac->extpallook[0];
|
||||
if (o32 != svga->overscan_color)
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
svga->dac_addr = (svga->dac_addr + 1) & 0xff;
|
||||
svga->dac_pos = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x06: /* Command Register 0 (RS value = 0110) */
|
||||
ramdac->cmd_r0 = val;
|
||||
svga->ramdac_type = (val & 0x02) ? RAMDAC_8BIT : RAMDAC_6BIT;
|
||||
break;
|
||||
case 0x08: /* Command Register 1 (RS value = 1000) */
|
||||
ramdac->cmd_r1 = val;
|
||||
bt48x_set_bpp(ramdac, svga);
|
||||
break;
|
||||
case 0x09: /* Command Register 2 (RS value = 1001) */
|
||||
ramdac->cmd_r2 = val;
|
||||
svga->dac_hwcursor.ena = !!(val & 0x03);
|
||||
bt48x_set_bpp(ramdac, svga);
|
||||
break;
|
||||
case 0x0a:
|
||||
if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) {
|
||||
switch (svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f)) {
|
||||
case 0x01:
|
||||
/* Command Register 3 (RS value = 1010) */
|
||||
ramdac->cmd_r3 = val;
|
||||
if (ramdac->type >= BT485A)
|
||||
bt48x_set_bpp(ramdac, svga);
|
||||
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = (val & 4) ? 64 : 32;
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
|
||||
svga->dac_addr = (svga->dac_addr & 0x00ff) | ((val & 0x03) << 8);
|
||||
svga_recalctimings(svga);
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x20:
|
||||
case 0x21:
|
||||
case 0x22:
|
||||
if (ramdac->type != BT485A)
|
||||
break;
|
||||
else if (svga->dac_addr == 2) {
|
||||
ramdac->cmd_r4 = val;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
|
||||
index = svga->dac_addr & da_mask;
|
||||
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64))
|
||||
cd = (uint8_t *) ramdac->cursor64_data;
|
||||
else {
|
||||
index &= 0xff;
|
||||
cd = (uint8_t *) ramdac->cursor32_data;
|
||||
}
|
||||
|
||||
cd[index] = val;
|
||||
|
||||
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
|
||||
break;
|
||||
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
|
||||
ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val;
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
|
||||
break;
|
||||
case 0x0d: /* Cursor X High Register (RS value = 1101) */
|
||||
ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8);
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
|
||||
break;
|
||||
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
|
||||
ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val;
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
|
||||
break;
|
||||
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
|
||||
ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8);
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
bt48x_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga)
|
||||
{
|
||||
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
const uint8_t *cd;
|
||||
uint16_t index;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
uint16_t da_mask = 0x03ff;
|
||||
rs |= (!!rs2 << 2);
|
||||
rs |= (!!rs3 << 3);
|
||||
if (ramdac->type < BT485)
|
||||
da_mask = 0x00ff;
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
case 0x01: /* Palette Data Register (RS value = 0001) */
|
||||
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
|
||||
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
case 0x03: /* Palette Read Index Register (RS value = 0011) */
|
||||
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
|
||||
temp = svga->dac_addr & 0xff;
|
||||
break;
|
||||
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
|
||||
index = (svga->dac_addr - 1) & 3;
|
||||
svga->dac_status = 3;
|
||||
switch (svga->dac_pos) {
|
||||
case 0:
|
||||
svga->dac_pos++;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
temp = ramdac->extpal[index].r;
|
||||
else
|
||||
temp = ramdac->extpal[index].r & 0x3f;
|
||||
break;
|
||||
case 1:
|
||||
svga->dac_pos++;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
temp = ramdac->extpal[index].g;
|
||||
else
|
||||
temp = ramdac->extpal[index].g & 0x3f;
|
||||
break;
|
||||
case 2:
|
||||
svga->dac_pos = 0;
|
||||
svga->dac_addr = svga->dac_addr + 1;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
temp = ramdac->extpal[index].b;
|
||||
else
|
||||
temp = ramdac->extpal[index].b & 0x3f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x06: /* Command Register 0 (RS value = 0110) */
|
||||
temp = ramdac->cmd_r0;
|
||||
break;
|
||||
case 0x08: /* Command Register 1 (RS value = 1000) */
|
||||
temp = ramdac->cmd_r1;
|
||||
break;
|
||||
case 0x09: /* Command Register 2 (RS value = 1001) */
|
||||
temp = ramdac->cmd_r2;
|
||||
break;
|
||||
case 0x0a:
|
||||
if ((ramdac->type >= BT485) && (ramdac->cmd_r0 & 0x80)) {
|
||||
switch (svga->dac_addr & ((ramdac->type >= BT485A) ? 0xff : 0x3f)) {
|
||||
default:
|
||||
case 0x00:
|
||||
temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00);
|
||||
break;
|
||||
case 0x01:
|
||||
temp = ramdac->cmd_r3 & 0xfc;
|
||||
temp |= (svga->dac_addr & 0x300) >> 8;
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x20:
|
||||
case 0x21:
|
||||
case 0x22:
|
||||
if (ramdac->type != BT485A)
|
||||
break;
|
||||
else if (svga->dac_addr == 2) {
|
||||
temp = ramdac->cmd_r4;
|
||||
break;
|
||||
} else {
|
||||
/* TODO: Red, Green, and Blue Signature Analysis Registers */
|
||||
temp = 0xff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
temp = ramdac->status | (svga->dac_status ? 0x04 : 0x00);
|
||||
break;
|
||||
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
|
||||
index = (svga->dac_addr - 1) & da_mask;
|
||||
if ((ramdac->type >= BT485) && (svga->dac_hwcursor.cur_xsize == 64))
|
||||
cd = (uint8_t *) ramdac->cursor64_data;
|
||||
else {
|
||||
index &= 0xff;
|
||||
cd = (uint8_t *) ramdac->cursor32_data;
|
||||
}
|
||||
|
||||
temp = cd[index];
|
||||
|
||||
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
|
||||
break;
|
||||
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
|
||||
temp = ramdac->hwc_x & 0xff;
|
||||
break;
|
||||
case 0x0d: /* Cursor X High Register (RS value = 1101) */
|
||||
temp = (ramdac->hwc_x >> 8) & 0xff;
|
||||
break;
|
||||
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
|
||||
temp = ramdac->hwc_y & 0xff;
|
||||
break;
|
||||
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
|
||||
temp = (ramdac->hwc_y >> 8) & 0xff;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void
|
||||
bt48x_recalctimings(void *priv, svga_t *svga)
|
||||
{
|
||||
const bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv;
|
||||
|
||||
svga->interlace = ramdac->cmd_r2 & 0x08;
|
||||
if (ramdac->cmd_r3 & 0x08)
|
||||
svga->hdisp *= 2; /* x2 clock multiplier */
|
||||
}
|
||||
|
||||
void
|
||||
bt48x_hwcursor_draw(svga_t *svga, int displine)
|
||||
{
|
||||
int comb;
|
||||
int b0;
|
||||
int b1;
|
||||
uint16_t dat[2];
|
||||
int offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff;
|
||||
int pitch;
|
||||
int bppl;
|
||||
int mode;
|
||||
int x_pos;
|
||||
int y_pos;
|
||||
uint32_t clr1;
|
||||
uint32_t clr2;
|
||||
uint32_t clr3;
|
||||
uint32_t *p;
|
||||
const uint8_t *cd;
|
||||
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) svga->ramdac;
|
||||
|
||||
clr1 = ramdac->extpallook[1];
|
||||
clr2 = ramdac->extpallook[2];
|
||||
clr3 = ramdac->extpallook[3];
|
||||
|
||||
/* The planes come in two parts, and each plane is 1bpp,
|
||||
so a 32x32 cursor has 4 bytes per line, and a 64x64
|
||||
cursor has 8 bytes per line. */
|
||||
pitch = (svga->dac_hwcursor_latch.cur_xsize >> 3); /* Bytes per line. */
|
||||
/* A 32x32 cursor has 128 bytes per line, and a 64x64
|
||||
cursor has 512 bytes per line. */
|
||||
bppl = (pitch * svga->dac_hwcursor_latch.cur_ysize); /* Bytes per plane. */
|
||||
mode = ramdac->cmd_r2 & 0x03;
|
||||
|
||||
if (svga->interlace && svga->dac_hwcursor_oddeven)
|
||||
svga->dac_hwcursor_latch.addr += pitch;
|
||||
|
||||
if (svga->dac_hwcursor_latch.cur_xsize == 64)
|
||||
cd = (uint8_t *) ramdac->cursor64_data;
|
||||
else
|
||||
cd = (uint8_t *) ramdac->cursor32_data;
|
||||
|
||||
for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += 16) {
|
||||
dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) | cd[svga->dac_hwcursor_latch.addr + 1];
|
||||
dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) | cd[svga->dac_hwcursor_latch.addr + bppl + 1];
|
||||
|
||||
for (uint8_t xx = 0; xx < 16; xx++) {
|
||||
b0 = (dat[0] >> (15 - xx)) & 1;
|
||||
b1 = (dat[1] >> (15 - xx)) & 1;
|
||||
comb = (b0 | (b1 << 1));
|
||||
|
||||
y_pos = displine;
|
||||
x_pos = (offset + svga->x_add) & 2047;
|
||||
p = buffer32->line[y_pos];
|
||||
|
||||
if (offset >= svga->dac_hwcursor_latch.x) {
|
||||
switch (mode) {
|
||||
case 1: /* Three Color */
|
||||
switch (comb) {
|
||||
case 1:
|
||||
p[x_pos] = clr1;
|
||||
break;
|
||||
case 2:
|
||||
p[x_pos] = clr2;
|
||||
break;
|
||||
case 3:
|
||||
p[x_pos] = clr3;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /* PM/Windows */
|
||||
switch (comb) {
|
||||
case 0:
|
||||
p[x_pos] = clr1;
|
||||
break;
|
||||
case 1:
|
||||
p[x_pos] = clr2;
|
||||
break;
|
||||
case 3:
|
||||
p[x_pos] ^= 0xffffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: /* X-Windows */
|
||||
switch (comb) {
|
||||
case 2:
|
||||
p[x_pos] = clr1;
|
||||
break;
|
||||
case 3:
|
||||
p[x_pos] = clr2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
svga->dac_hwcursor_latch.addr += 2;
|
||||
}
|
||||
|
||||
if (svga->interlace && !svga->dac_hwcursor_oddeven)
|
||||
svga->dac_hwcursor_latch.addr += pitch;
|
||||
}
|
||||
|
||||
void *
|
||||
bt48x_ramdac_init(const device_t *info)
|
||||
{
|
||||
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) malloc(sizeof(bt48x_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(bt48x_ramdac_t));
|
||||
|
||||
ramdac->type = info->local;
|
||||
|
||||
/* Set the RAM DAC status byte to the correct ID bits.
|
||||
|
||||
Both the BT484 and BT485 datasheets say this:
|
||||
SR7-SR6: These bits are identification values. SR7=0 and SR6=1.
|
||||
But all other sources seem to assume SR7=1 and SR6=0. */
|
||||
switch (ramdac->type) {
|
||||
case BT484:
|
||||
ramdac->status = 0x40;
|
||||
break;
|
||||
case ATT20C504:
|
||||
ramdac->status = 0x40;
|
||||
break;
|
||||
case BT485:
|
||||
ramdac->status = 0x60;
|
||||
break;
|
||||
case ATT20C505:
|
||||
ramdac->status = 0xd0;
|
||||
break;
|
||||
case BT485A:
|
||||
ramdac->status = 0x20;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
bt48x_ramdac_close(void *priv)
|
||||
{
|
||||
bt48x_ramdac_t *ramdac = (bt48x_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t bt484_ramdac_device = {
|
||||
.name = "Brooktree Bt484 RAMDAC",
|
||||
.internal_name = "bt484_ramdac",
|
||||
.flags = 0,
|
||||
.local = BT484,
|
||||
.init = bt48x_ramdac_init,
|
||||
.close = bt48x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t att20c504_ramdac_device = {
|
||||
.name = "AT&T 20c504 RAMDAC",
|
||||
.internal_name = "att20c504_ramdac",
|
||||
.flags = 0,
|
||||
.local = ATT20C504,
|
||||
.init = bt48x_ramdac_init,
|
||||
.close = bt48x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t bt485_ramdac_device = {
|
||||
.name = "Brooktree Bt485 RAMDAC",
|
||||
.internal_name = "bt485_ramdac",
|
||||
.flags = 0,
|
||||
.local = BT485,
|
||||
.init = bt48x_ramdac_init,
|
||||
.close = bt48x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t att20c505_ramdac_device = {
|
||||
.name = "AT&T 20c505 RAMDAC",
|
||||
.internal_name = "att20c505_ramdac",
|
||||
.flags = 0,
|
||||
.local = ATT20C505,
|
||||
.init = bt48x_ramdac_init,
|
||||
.close = bt48x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t bt485a_ramdac_device = {
|
||||
.name = "Brooktree Bt485A RAMDAC",
|
||||
.internal_name = "bt485a_ramdac",
|
||||
.flags = 0,
|
||||
.local = BT485A,
|
||||
.init = bt48x_ramdac_init,
|
||||
.close = bt48x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
989
src/video/ramdac/vid_ramdac_ibm_rgb528.c
Normal file
989
src/video/ramdac/vid_ramdac_ibm_rgb528.c
Normal file
@@ -0,0 +1,989 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the IBM RGB 528 true colour RAMDAC.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef union ibm_rgb528_pixel8_t {
|
||||
uint8_t pixel;
|
||||
struct {
|
||||
uint8_t b : 2;
|
||||
uint8_t g : 3;
|
||||
uint8_t r : 2;
|
||||
};
|
||||
} ibm_rgb528_pixel8_t;
|
||||
|
||||
typedef union ibm_rgb528_pixel16_t {
|
||||
uint16_t pixel;
|
||||
struct {
|
||||
uint16_t b_ : 5;
|
||||
uint16_t g_ : 6;
|
||||
uint16_t r_ : 5;
|
||||
};
|
||||
struct {
|
||||
uint16_t b : 5;
|
||||
uint16_t g : 5;
|
||||
uint16_t r : 5;
|
||||
uint16_t c : 1;
|
||||
};
|
||||
} ibm_rgb528_pixel16_t;
|
||||
|
||||
typedef union ibm_rgb528_pixel32_t {
|
||||
uint32_t pixel;
|
||||
struct {
|
||||
uint8_t b;
|
||||
uint8_t g;
|
||||
uint8_t r;
|
||||
uint8_t a;
|
||||
};
|
||||
} ibm_rgb528_pixel32_t;
|
||||
|
||||
typedef struct ibm_rgb528_ramdac_t {
|
||||
PALETTE extpal;
|
||||
uint32_t extpallook[256];
|
||||
uint8_t indexed_data[2048];
|
||||
uint8_t cursor32_data[256];
|
||||
uint8_t cursor64_data[1024];
|
||||
uint8_t palettes[3][256];
|
||||
ibm_rgb528_pixel32_t extra_pal[4];
|
||||
int16_t hwc_y;
|
||||
int16_t hwc_x;
|
||||
uint16_t index;
|
||||
uint16_t smlc_part;
|
||||
uint8_t cmd_r0;
|
||||
uint8_t cmd_r1;
|
||||
uint8_t cmd_r2;
|
||||
uint8_t cmd_r3;
|
||||
uint8_t cmd_r4;
|
||||
uint8_t status;
|
||||
uint8_t indx_cntl;
|
||||
uint8_t cursor_array;
|
||||
uint8_t cursor_hotspot_x;
|
||||
uint8_t cursor_hotspot_y;
|
||||
} ibm_rgb528_ramdac_t;
|
||||
|
||||
void
|
||||
ibm_rgb528_render_4bpp(svga_t *svga)
|
||||
{
|
||||
uint32_t *p;
|
||||
ibm_rgb528_pixel32_t dat_out;
|
||||
uint8_t dat;
|
||||
uint32_t dat32 = 0x00000000;
|
||||
uint64_t dat64 = 0x0000000000000000ULL;
|
||||
uint64_t dat642 = 0x0000000000000000ULL;
|
||||
const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac;
|
||||
uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6;
|
||||
uint8_t partition = (ramdac->indexed_data[0x07] & 0x0f) << 4;
|
||||
uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10;
|
||||
uint8_t swap_nib = ramdac->indexed_data[0x72] & 0x21;
|
||||
uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03;
|
||||
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
|
||||
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
|
||||
if (vram_size == 3) {
|
||||
if (!(x & 31)) {
|
||||
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
|
||||
dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]);
|
||||
if (swap_word) {
|
||||
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
|
||||
dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL);
|
||||
}
|
||||
}
|
||||
if (swap_nib)
|
||||
dat = (((x & 16) ? dat642 : dat64) >> ((x & 15) << 2)) & 0xf;
|
||||
else
|
||||
dat = (((x & 16) ? dat642 : dat64) >> (((x & 15) << 2) ^ 4)) & 0xf;
|
||||
} else if (vram_size == 1) {
|
||||
if (!(x & 15)) {
|
||||
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
|
||||
if (swap_word)
|
||||
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
|
||||
}
|
||||
if (swap_nib)
|
||||
dat = (dat64 >> ((x & 15) << 2)) & 0xf;
|
||||
else
|
||||
dat = (dat64 >> (((x & 15) << 2) ^ 4)) & 0xf;
|
||||
} else {
|
||||
if (!(x & 7))
|
||||
dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]);
|
||||
if (swap_nib)
|
||||
dat = (dat32 >> ((x & 7) << 2)) & 0xf;
|
||||
else
|
||||
dat = (dat32 >> (((x & 7) << 2) ^ 4)) & 0xf;
|
||||
}
|
||||
if (b8_dcol == 0x00) {
|
||||
dat_out.a = 0x00;
|
||||
dat_out.r = ramdac->palettes[0][partition | dat];
|
||||
dat_out.g = ramdac->palettes[1][partition | dat];
|
||||
dat_out.b = ramdac->palettes[2][partition | dat];
|
||||
} else
|
||||
dat_out.pixel = video_8togs[dat];
|
||||
if (svga->lowres) {
|
||||
p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff;
|
||||
} else
|
||||
p[x] = dat_out.pixel & 0xffffff;
|
||||
|
||||
if ((vram_size == 3) && ((x & 31) == 31))
|
||||
svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask;
|
||||
if ((vram_size == 1) && ((x & 15) == 15))
|
||||
svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask;
|
||||
else if ((!vram_size) && ((x & 7) == 7))
|
||||
svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ibm_rgb528_render_8bpp(svga_t *svga)
|
||||
{
|
||||
uint32_t *p;
|
||||
ibm_rgb528_pixel32_t dat_out;
|
||||
uint8_t dat;
|
||||
uint32_t dat32 = 0x00000000;
|
||||
uint64_t dat64 = 0x0000000000000000ULL;
|
||||
uint64_t dat642 = 0x0000000000000000ULL;
|
||||
const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac;
|
||||
uint8_t b8_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6;
|
||||
uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10;
|
||||
uint8_t vram_size = ramdac->indexed_data[0x70] & 0x03;
|
||||
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
|
||||
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
|
||||
if (vram_size == 3) {
|
||||
if (!(x & 15)) {
|
||||
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
|
||||
dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]);
|
||||
if (swap_word) {
|
||||
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
|
||||
dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL);
|
||||
}
|
||||
}
|
||||
dat = (((x & 8) ? dat642 : dat64) >> ((x & 7) << 3)) & 0xff;
|
||||
} else if (vram_size == 1) {
|
||||
if (!(x & 7)) {
|
||||
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
|
||||
if (swap_word)
|
||||
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
|
||||
}
|
||||
dat = (dat64 >> ((x & 7) << 3)) & 0xff;
|
||||
} else {
|
||||
if (!(x & 3))
|
||||
dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]);
|
||||
dat = (dat32 >> ((x & 3) << 3)) & 0xff;
|
||||
}
|
||||
if (b8_dcol == 0x00) {
|
||||
dat_out.a = 0x00;
|
||||
dat_out.r = ramdac->palettes[0][dat];
|
||||
dat_out.g = ramdac->palettes[1][dat];
|
||||
dat_out.b = ramdac->palettes[2][dat];
|
||||
} else
|
||||
dat_out.pixel = video_8togs[dat];
|
||||
if (svga->lowres) {
|
||||
p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff;
|
||||
} else
|
||||
p[x] = dat_out.pixel & 0xffffff;
|
||||
|
||||
if ((vram_size == 3) && ((x & 15) == 15))
|
||||
svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask;
|
||||
else if ((vram_size == 1) && ((x & 7) == 7))
|
||||
svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask;
|
||||
else if ((!vram_size) && ((x & 3) == 3))
|
||||
svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ibm_rgb528_render_15_16bpp(svga_t *svga)
|
||||
{
|
||||
uint32_t *p;
|
||||
ibm_rgb528_pixel16_t *dat_ex;
|
||||
ibm_rgb528_pixel32_t dat_out;
|
||||
uint16_t dat;
|
||||
uint32_t dat32 = 0x00000000;
|
||||
uint64_t dat64 = 0x0000000000000000ULL;
|
||||
uint64_t dat642 = 0x0000000000000000ULL;
|
||||
const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac;
|
||||
uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6;
|
||||
uint8_t by16_pol = ramdac->indexed_data[0x0c] & 0x20;
|
||||
uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02;
|
||||
uint8_t bspr_cnt = ramdac->indexed_data[0x0c] & 0x01;
|
||||
uint8_t partition = (ramdac->indexed_data[0x07] & 0x0e) << 4;
|
||||
uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80;
|
||||
uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80;
|
||||
uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10;
|
||||
uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01;
|
||||
uint8_t temp;
|
||||
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (b555_565 && (b16_dcol != 0x01))
|
||||
partition &= 0xc0;
|
||||
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
|
||||
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
|
||||
if (vram_size == 2) {
|
||||
if (!(x & 7)) {
|
||||
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
|
||||
dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]);
|
||||
if (swap_word) {
|
||||
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
|
||||
dat642 = (dat64 << 32ULL) | (dat642 >> 32ULL);
|
||||
}
|
||||
}
|
||||
dat = (((x & 4) ? dat642 : dat64) >> ((x & 3) << 4)) & 0xffff;
|
||||
} else if (vram_size == 1) {
|
||||
if (!(x & 3)) {
|
||||
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
|
||||
if (swap_word)
|
||||
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
|
||||
}
|
||||
dat = (dat64 >> ((x & 3) << 4)) & 0xffff;
|
||||
} else {
|
||||
if (!(x & 1))
|
||||
dat32 = *(uint32_t *) (&svga->vram[svga->memaddr]);
|
||||
dat = (dat32 >> ((x & 1) << 4)) & 0xffff;
|
||||
}
|
||||
dat_ex = (ibm_rgb528_pixel16_t *) &dat;
|
||||
if (b555_565 && (b16_dcol != 0x01)) {
|
||||
if (swaprb) {
|
||||
temp = dat_ex->r_;
|
||||
dat_ex->r_ = dat_ex->b_;
|
||||
dat_ex->b_ = temp;
|
||||
}
|
||||
if (b16_dcol == 0x00) {
|
||||
dat_out.a = 0x00;
|
||||
if (bspr_cnt) {
|
||||
dat_out.r = ramdac->palettes[0][partition | dat_ex->r_];
|
||||
dat_out.g = ramdac->palettes[1][partition | dat_ex->g_];
|
||||
dat_out.b = ramdac->palettes[2][partition | dat_ex->b_];
|
||||
} else {
|
||||
dat_out.r = ramdac->palettes[0][dat_ex->r_ << 3];
|
||||
dat_out.g = ramdac->palettes[1][dat_ex->g_ << 2];
|
||||
dat_out.b = ramdac->palettes[2][dat_ex->b_ << 3];
|
||||
}
|
||||
if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) {
|
||||
dat_out.r |= ((dat_out.r & 0xc0) >> 6);
|
||||
dat_out.g |= ((dat_out.g & 0xc0) >> 6);
|
||||
dat_out.b |= ((dat_out.b & 0xc0) >> 6);
|
||||
}
|
||||
} else
|
||||
dat_out.pixel = video_16to32[dat_ex->pixel];
|
||||
} else {
|
||||
if (swaprb) {
|
||||
temp = dat_ex->r;
|
||||
dat_ex->r = dat_ex->b;
|
||||
dat_ex->b = temp;
|
||||
}
|
||||
if (by16_pol)
|
||||
dat ^= 0x8000;
|
||||
if ((b16_dcol == 0x00) || ((b16_dcol == 0x01) && !(dat & 0x8000))) {
|
||||
dat_out.a = 0x00;
|
||||
if (bspr_cnt) {
|
||||
dat_out.r = ramdac->palettes[0][partition | dat_ex->r];
|
||||
dat_out.g = ramdac->palettes[1][partition | dat_ex->g];
|
||||
dat_out.b = ramdac->palettes[2][partition | dat_ex->b];
|
||||
} else {
|
||||
dat_out.r = ramdac->palettes[0][dat_ex->r << 3];
|
||||
dat_out.g = ramdac->palettes[1][dat_ex->g << 3];
|
||||
dat_out.b = ramdac->palettes[2][dat_ex->b << 3];
|
||||
}
|
||||
if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) {
|
||||
dat_out.r |= ((dat_out.r & 0xc0) >> 6);
|
||||
dat_out.g |= ((dat_out.g & 0xc0) >> 6);
|
||||
dat_out.b |= ((dat_out.b & 0xc0) >> 6);
|
||||
}
|
||||
} else
|
||||
dat_out.pixel = video_15to32[dat_ex->pixel & 0x7fff];
|
||||
}
|
||||
if (svga->lowres) {
|
||||
p[x << 1] = p[(x << 1) + 1] = dat_out.pixel & 0xffffff;
|
||||
} else
|
||||
p[x] = dat_out.pixel & 0xffffff;
|
||||
|
||||
if ((vram_size == 3) && ((x & 7) == 7))
|
||||
svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask;
|
||||
else if ((vram_size == 1) && ((x & 3) == 3))
|
||||
svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask;
|
||||
else if (!vram_size && ((x & 1) == 1))
|
||||
svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ibm_rgb528_render_24bpp(svga_t *svga)
|
||||
{
|
||||
uint32_t *p;
|
||||
ibm_rgb528_pixel32_t *dat_ex;
|
||||
uint32_t dat;
|
||||
uint64_t dat64[6];
|
||||
uint8_t *dat8 = (uint8_t *) dat64;
|
||||
const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac;
|
||||
uint8_t b24_dcol = ramdac->indexed_data[0x0d] & 0x01;
|
||||
uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80;
|
||||
uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10;
|
||||
uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01;
|
||||
uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80;
|
||||
uint8_t temp;
|
||||
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
|
||||
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
|
||||
dat_ex = (ibm_rgb528_pixel32_t *) &dat;
|
||||
if (vram_size == 3) {
|
||||
if ((x & 15) == 0) {
|
||||
dat64[0] = *(uint64_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]);
|
||||
dat64[1] = *(uint64_t *) (&svga->vram[(svga->memaddr + 8) & svga->vram_display_mask]);
|
||||
dat64[2] = *(uint64_t *) (&svga->vram[(svga->memaddr + 16) & svga->vram_display_mask]);
|
||||
dat64[3] = *(uint64_t *) (&svga->vram[(svga->memaddr + 24) & svga->vram_display_mask]);
|
||||
dat64[4] = *(uint64_t *) (&svga->vram[(svga->memaddr + 32) & svga->vram_display_mask]);
|
||||
dat64[5] = *(uint64_t *) (&svga->vram[(svga->memaddr + 40) & svga->vram_display_mask]);
|
||||
if (swap_word) {
|
||||
dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL);
|
||||
dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL);
|
||||
dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL);
|
||||
dat64[3] = (dat64[3] << 32ULL) | (dat64[3] >> 32ULL);
|
||||
dat64[4] = (dat64[4] << 32ULL) | (dat64[4] >> 32ULL);
|
||||
dat64[5] = (dat64[5] << 32ULL) | (dat64[5] >> 32ULL);
|
||||
}
|
||||
}
|
||||
dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[(x & 15) * 3]);
|
||||
} else if (vram_size == 1) {
|
||||
if ((x & 7) == 0) {
|
||||
dat64[0] = *(uint64_t *) (&svga->vram[svga->memaddr & svga->vram_display_mask]);
|
||||
dat64[1] = *(uint64_t *) (&svga->vram[(svga->memaddr + 8) & svga->vram_display_mask]);
|
||||
dat64[2] = *(uint64_t *) (&svga->vram[(svga->memaddr + 16) & svga->vram_display_mask]);
|
||||
if (swap_word) {
|
||||
dat64[0] = (dat64[0] << 32ULL) | (dat64[0] >> 32ULL);
|
||||
dat64[1] = (dat64[1] << 32ULL) | (dat64[1] >> 32ULL);
|
||||
dat64[2] = (dat64[2] << 32ULL) | (dat64[2] >> 32ULL);
|
||||
}
|
||||
}
|
||||
dat_ex = (ibm_rgb528_pixel32_t *) &(dat8[(x & 7) * 3]);
|
||||
} else
|
||||
dat = 0x00000000;
|
||||
if (swaprb) {
|
||||
temp = dat_ex->r;
|
||||
dat_ex->r = dat_ex->b;
|
||||
dat_ex->b = temp;
|
||||
}
|
||||
if (b24_dcol == 0x00) {
|
||||
dat_ex->a = 0x00;
|
||||
dat_ex->r = ramdac->palettes[0][dat_ex->r];
|
||||
dat_ex->g = ramdac->palettes[1][dat_ex->g];
|
||||
dat_ex->g = ramdac->palettes[2][dat_ex->b];
|
||||
if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) {
|
||||
dat_ex->r |= ((dat_ex->r & 0xc0) >> 6);
|
||||
dat_ex->g |= ((dat_ex->g & 0xc0) >> 6);
|
||||
dat_ex->b |= ((dat_ex->b & 0xc0) >> 6);
|
||||
}
|
||||
}
|
||||
if (svga->lowres) {
|
||||
p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff;
|
||||
} else
|
||||
p[x] = dat_ex->pixel & 0xffffff;
|
||||
|
||||
if ((vram_size == 3) && ((x & 15) == 15))
|
||||
svga->memaddr = (svga->memaddr + 48) & svga->vram_display_mask;
|
||||
else if ((vram_size == 1) && ((x & 7) == 7))
|
||||
svga->memaddr = (svga->memaddr + 24) & svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ibm_rgb528_render_32bpp(svga_t *svga)
|
||||
{
|
||||
uint32_t *p;
|
||||
ibm_rgb528_pixel32_t *dat_ex;
|
||||
uint32_t dat = 0x00000000;
|
||||
uint64_t dat64 = 0x0000000000000000ULL;
|
||||
uint64_t dat642 = 0x0000000000000000ULL;
|
||||
const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac;
|
||||
uint8_t b32_dcol = ramdac->indexed_data[0x0e] & 0x03;
|
||||
uint8_t by32_pol = ramdac->indexed_data[0x0e] & 0x04;
|
||||
uint8_t swaprb = ramdac->indexed_data[0x72] & 0x80;
|
||||
uint8_t swap_word = ramdac->indexed_data[0x72] & 0x10;
|
||||
uint8_t vram_size = ramdac->indexed_data[0x70] & 0x01;
|
||||
uint8_t b6bit_lin = ramdac->indexed_data[0x07] & 0x80;
|
||||
uint8_t temp;
|
||||
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->changedvram[svga->memaddr >> 12] || svga->changedvram[(svga->memaddr >> 12) + 1] || svga->changedvram[(svga->memaddr >> 12) + 2] || svga->fullchange) {
|
||||
p = &buffer32->line[svga->displine + svga->y_add][svga->x_add];
|
||||
|
||||
if (svga->firstline_draw == 2000)
|
||||
svga->firstline_draw = svga->displine;
|
||||
svga->lastline_draw = svga->displine;
|
||||
|
||||
for (int x = 0; x <= (svga->hdisp + svga->scrollcache); x++) {
|
||||
if (vram_size == 3) {
|
||||
if (!(x & 3)) {
|
||||
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
|
||||
dat642 = *(uint64_t *) (&svga->vram[svga->memaddr + 8]);
|
||||
if (swap_word) {
|
||||
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
|
||||
dat642 = (dat642 << 32ULL) | (dat642 >> 32ULL);
|
||||
}
|
||||
}
|
||||
dat = (((x & 2) ? dat642 : dat64) >> ((x & 1ULL) << 5ULL)) & 0xffffffff;
|
||||
} else if (vram_size == 1) {
|
||||
if (!(x & 1)) {
|
||||
dat64 = *(uint64_t *) (&svga->vram[svga->memaddr]);
|
||||
if (swap_word)
|
||||
dat64 = (dat64 << 32ULL) | (dat64 >> 32ULL);
|
||||
}
|
||||
dat = (dat64 >> ((x & 1ULL) << 5ULL)) & 0xffffffff;
|
||||
} else
|
||||
dat = *(uint32_t *) (&svga->vram[svga->memaddr]);
|
||||
dat_ex = (ibm_rgb528_pixel32_t *) &dat;
|
||||
if (swaprb) {
|
||||
temp = dat_ex->r;
|
||||
dat_ex->r = dat_ex->b;
|
||||
dat_ex->b = temp;
|
||||
}
|
||||
if ((b32_dcol < 0x03) && by32_pol)
|
||||
dat ^= 0x01000000;
|
||||
if ((b32_dcol == 0x00) || ((b32_dcol == 0x01) && !(dat & 0x01000000))) {
|
||||
dat_ex->a = 0x00;
|
||||
dat_ex->r = ramdac->palettes[0][dat_ex->r];
|
||||
dat_ex->g = ramdac->palettes[1][dat_ex->g];
|
||||
dat_ex->g = ramdac->palettes[2][dat_ex->b];
|
||||
if ((svga->ramdac_type != RAMDAC_8BIT) && !b6bit_lin) {
|
||||
dat_ex->r |= ((dat_ex->r & 0xc0) >> 6);
|
||||
dat_ex->g |= ((dat_ex->g & 0xc0) >> 6);
|
||||
dat_ex->b |= ((dat_ex->b & 0xc0) >> 6);
|
||||
}
|
||||
}
|
||||
if (svga->lowres) {
|
||||
p[x << 1] = p[(x << 1) + 1] = dat_ex->pixel & 0xffffff;
|
||||
} else
|
||||
p[x] = dat_ex->pixel & 0xffffff;
|
||||
|
||||
if ((vram_size == 3) && ((x & 3) == 3))
|
||||
svga->memaddr = (svga->memaddr + 16) & svga->vram_display_mask;
|
||||
else if ((vram_size == 1) && ((x & 1) == 1))
|
||||
svga->memaddr = (svga->memaddr + 8) & svga->vram_display_mask;
|
||||
else if (!vram_size)
|
||||
svga->memaddr = (svga->memaddr + 4) & svga->vram_display_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ibm_rgb528_set_bpp(ibm_rgb528_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
uint8_t b16_dcol = (ramdac->indexed_data[0x0c] & 0xc0) >> 6;
|
||||
uint8_t b555_565 = ramdac->indexed_data[0x0c] & 0x02;
|
||||
|
||||
if (ramdac->indexed_data[0x071] & 0x01)
|
||||
switch (ramdac->indexed_data[0x00a] & 0x07) {
|
||||
case 0x02:
|
||||
svga->bpp = 4;
|
||||
break;
|
||||
case 0x03:
|
||||
default:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 0x04:
|
||||
if (b555_565 && (b16_dcol != 0x01))
|
||||
svga->bpp = 16;
|
||||
else
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 0x05:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
case 0x06:
|
||||
svga->bpp = 32;
|
||||
break;
|
||||
}
|
||||
else
|
||||
svga->bpp = 8;
|
||||
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void
|
||||
ibm_rgb528_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv;
|
||||
uint16_t index;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
uint16_t da_mask = 0x03ff;
|
||||
uint8_t updt_cntl = (ramdac->indexed_data[0x30] & 0x08);
|
||||
rs |= (!!rs2 << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
case 0x03:
|
||||
svga->dac_pos = 0;
|
||||
svga->dac_status = addr & 0x03;
|
||||
svga->dac_addr = val;
|
||||
if (svga->dac_status)
|
||||
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
|
||||
break;
|
||||
case 0x01: /* Palette Data Register (RS value = 0001) */
|
||||
index = svga->dac_addr & 255;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
ramdac->palettes[svga->dac_pos][index] = val;
|
||||
else
|
||||
ramdac->palettes[svga->dac_pos][index] = (val & 0x3f) << 2;
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
case 0x04:
|
||||
ramdac->index = (ramdac->index & 0x0700) | val;
|
||||
if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff))
|
||||
ramdac->cursor_array = 1;
|
||||
break;
|
||||
case 0x05:
|
||||
ramdac->index = (ramdac->index & 0x00ff) | ((val & 0x07) << 0x08);
|
||||
if ((ramdac->index >= 0x0100) && (ramdac->index <= 0x04ff))
|
||||
ramdac->cursor_array = 1;
|
||||
break;
|
||||
case 0x06:
|
||||
if ((ramdac->index < 0x0100) || (ramdac->index > 0x04ff) || ramdac->cursor_array)
|
||||
ramdac->indexed_data[ramdac->index] = val;
|
||||
switch (ramdac->index) {
|
||||
case 0x00a:
|
||||
case 0x00c:
|
||||
ibm_rgb528_set_bpp(ramdac, svga);
|
||||
break;
|
||||
case 0x030:
|
||||
switch (val & 0xc0) {
|
||||
case 0x00:
|
||||
ramdac->smlc_part = 0x0100;
|
||||
break;
|
||||
case 0x40:
|
||||
ramdac->smlc_part = 0x0200;
|
||||
break;
|
||||
case 0x80:
|
||||
ramdac->smlc_part = 0x0300;
|
||||
break;
|
||||
case 0xc0:
|
||||
ramdac->smlc_part = 0x0400;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
svga->dac_hwcursor.addr = ramdac->smlc_part;
|
||||
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = (val & 0x04) ? 64 : 32;
|
||||
svga->dac_hwcursor.ena = ((val & 0x03) != 0x00);
|
||||
break;
|
||||
case 0x031:
|
||||
if (!updt_cntl)
|
||||
break;
|
||||
ramdac->hwc_x = (ramdac->hwc_x & 0xff00) | val;
|
||||
svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x;
|
||||
break;
|
||||
case 0x032:
|
||||
/* Sign-extend the sign bit (7) to the remaining bits (6-4). */
|
||||
val &= 0x8f;
|
||||
if (val & 0x80)
|
||||
val |= 0x70;
|
||||
ramdac->indexed_data[ramdac->index] = val;
|
||||
if (!updt_cntl)
|
||||
break;
|
||||
ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | (val << 8);
|
||||
svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x;
|
||||
break;
|
||||
case 0x033:
|
||||
if (!updt_cntl)
|
||||
break;
|
||||
ramdac->hwc_y = (ramdac->hwc_y & 0xff00) | val;
|
||||
svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y;
|
||||
break;
|
||||
case 0x034:
|
||||
/* Sign-extend the sign bit (7) to the remaining bits (6-4). */
|
||||
val &= 0x8f;
|
||||
if (val & 0x80)
|
||||
val |= 0x70;
|
||||
ramdac->indexed_data[ramdac->index] = val;
|
||||
if (updt_cntl) {
|
||||
ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | (val << 8);
|
||||
svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y;
|
||||
} else {
|
||||
ramdac->hwc_x = ramdac->indexed_data[0x031];
|
||||
ramdac->hwc_x |= (ramdac->indexed_data[0x032] << 8);
|
||||
ramdac->hwc_y = ramdac->indexed_data[0x033];
|
||||
ramdac->hwc_y |= (val << 8);
|
||||
svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x;
|
||||
svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y;
|
||||
}
|
||||
break;
|
||||
case 0x035:
|
||||
if (svga->dac_hwcursor.cur_xsize == 64)
|
||||
ramdac->cursor_hotspot_x = (val & 0x3f);
|
||||
else
|
||||
ramdac->cursor_hotspot_x = (val & 0x1f);
|
||||
svga->dac_hwcursor.x = ((int) ramdac->hwc_x) - ramdac->cursor_hotspot_x;
|
||||
break;
|
||||
case 0x036:
|
||||
if (svga->dac_hwcursor.cur_xsize == 64)
|
||||
ramdac->cursor_hotspot_y = (val & 0x3f);
|
||||
else
|
||||
ramdac->cursor_hotspot_y = (val & 0x1f);
|
||||
svga->dac_hwcursor.y = ((int) ramdac->hwc_y) - ramdac->cursor_hotspot_y;
|
||||
break;
|
||||
case 0x040:
|
||||
case 0x043:
|
||||
case 0x046:
|
||||
ramdac->extra_pal[(ramdac->index - 0x40) / 3].r = val;
|
||||
break;
|
||||
case 0x041:
|
||||
case 0x044:
|
||||
case 0x047:
|
||||
ramdac->extra_pal[(ramdac->index - 0x41) / 3].g = val;
|
||||
break;
|
||||
case 0x042:
|
||||
case 0x045:
|
||||
case 0x048:
|
||||
ramdac->extra_pal[(ramdac->index - 0x42) / 3].b = val;
|
||||
break;
|
||||
case 0x060:
|
||||
ramdac->extra_pal[3].r = val;
|
||||
break;
|
||||
case 0x061:
|
||||
ramdac->extra_pal[3].g = val;
|
||||
break;
|
||||
case 0x062:
|
||||
ramdac->extra_pal[3].b = val;
|
||||
break;
|
||||
case 0x071:
|
||||
svga->ramdac_type = (val & 0x04) ? RAMDAC_8BIT : RAMDAC_6BIT;
|
||||
ibm_rgb528_set_bpp(ramdac, svga);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ramdac->indx_cntl) {
|
||||
if (ramdac->index == 0x00ff)
|
||||
ramdac->cursor_array = 0;
|
||||
ramdac->index = (ramdac->index + 1) & 0x07ff;
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
ramdac->indx_cntl = val & 0x01;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ibm_rgb528_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga)
|
||||
{
|
||||
ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
uint8_t loc_read = (ramdac->indexed_data[0x30] & 0x10);
|
||||
rs |= (!!rs2 << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
case 0x01: /* Palette Data Register (RS value = 0001) */
|
||||
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
case 0x03: /* Palette Read Index Register (RS value = 0011) */
|
||||
temp = svga->dac_addr & 0xff;
|
||||
if (ramdac->indexed_data[0x070] & 0x20)
|
||||
temp = (temp & 0xfc) | svga->dac_status;
|
||||
break;
|
||||
case 0x04:
|
||||
temp = ramdac->index & 0xff;
|
||||
break;
|
||||
case 0x05:
|
||||
temp = ramdac->index >> 8;
|
||||
break;
|
||||
case 0x06:
|
||||
temp = ramdac->indexed_data[ramdac->index];
|
||||
switch (ramdac->index) {
|
||||
case 0x0000: /* Revision */
|
||||
temp = 0xe0;
|
||||
break;
|
||||
case 0x0001: /* ID */
|
||||
temp = 0x02;
|
||||
break;
|
||||
case 0x0031:
|
||||
if (loc_read)
|
||||
temp = ramdac->hwc_x & 0xff;
|
||||
break;
|
||||
case 0x0032:
|
||||
if (loc_read)
|
||||
temp = ramdac->hwc_x >> 8;
|
||||
break;
|
||||
case 0x0033:
|
||||
if (loc_read)
|
||||
temp = ramdac->hwc_y & 0xff;
|
||||
break;
|
||||
case 0x0034:
|
||||
if (loc_read)
|
||||
temp = ramdac->hwc_y >> 8;
|
||||
break;
|
||||
default:
|
||||
temp = ramdac->indexed_data[ramdac->index];
|
||||
break;
|
||||
}
|
||||
if (ramdac->indx_cntl) {
|
||||
if (ramdac->index == 0x00ff)
|
||||
ramdac->cursor_array = 0;
|
||||
ramdac->index = (ramdac->index + 1) & 0x07ff;
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
temp = ramdac->indx_cntl;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void
|
||||
ibm_rgb528_recalctimings(void *priv, svga_t *svga)
|
||||
{
|
||||
const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv;
|
||||
|
||||
svga->interlace = ramdac->indexed_data[0x071] & 0x20;
|
||||
|
||||
if (svga->scrblank || !svga->attr_palette_enable) {
|
||||
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
|
||||
if (((svga->gdcreg[5] & 0x60) == 0x40) || ((svga->gdcreg[5] & 0x60) == 0x60)) {
|
||||
if (ramdac->indexed_data[0x071] & 0x01) {
|
||||
switch (svga->bpp) {
|
||||
case 4:
|
||||
svga->render = ibm_rgb528_render_4bpp;
|
||||
break;
|
||||
case 8:
|
||||
svga->render = ibm_rgb528_render_8bpp;
|
||||
break;
|
||||
case 15:
|
||||
case 16:
|
||||
svga->render = ibm_rgb528_render_15_16bpp;
|
||||
break;
|
||||
case 24:
|
||||
svga->render = ibm_rgb528_render_24bpp;
|
||||
break;
|
||||
case 32:
|
||||
svga->render = ibm_rgb528_render_32bpp;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ibm_rgb528_hwcursor_draw(svga_t *svga, int displine)
|
||||
{
|
||||
uint8_t dat;
|
||||
uint8_t four_pixels = 0x00;
|
||||
int pitch;
|
||||
int x_pos;
|
||||
int y_pos;
|
||||
int offset = svga->dac_hwcursor_latch.x - svga->dac_hwcursor_latch.xoff;
|
||||
uint32_t *p;
|
||||
const ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) svga->ramdac;
|
||||
uint8_t pix_ordr = ramdac->indexed_data[0x30] & 0x20;
|
||||
uint8_t cursor_mode = ramdac->indexed_data[0x30] & 0x03;
|
||||
|
||||
/* The planes come in one part, and each plane is 2bpp,
|
||||
so a 32x32 cursor has 8 bytes per line, and a 64x64
|
||||
cursor has 16 bytes per line. */
|
||||
pitch = (svga->dac_hwcursor_latch.cur_xsize >> 2); /* Bytes per line. */
|
||||
|
||||
if ((ramdac->indexed_data[0x071] & 0x20) && svga->dac_hwcursor_oddeven)
|
||||
svga->dac_hwcursor_latch.addr += pitch;
|
||||
|
||||
y_pos = displine;
|
||||
x_pos = offset + svga->x_add;
|
||||
p = buffer32->line[y_pos];
|
||||
|
||||
for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x++) {
|
||||
if (!(x & 3))
|
||||
four_pixels = ramdac->indexed_data[svga->dac_hwcursor_latch.addr];
|
||||
|
||||
if (pix_ordr)
|
||||
dat = (four_pixels >> (((3 - x) & 3) << 1)) & 0x03;
|
||||
else
|
||||
dat = (four_pixels >> ((x & 3) << 1)) & 0x03;
|
||||
|
||||
x_pos = offset + svga->x_add + x;
|
||||
|
||||
switch (cursor_mode) {
|
||||
case 0x01:
|
||||
switch (dat) {
|
||||
case 0x01:
|
||||
/* Cursor Color 1 */
|
||||
p[x_pos] = ramdac->extra_pal[0].pixel;
|
||||
break;
|
||||
case 0x02:
|
||||
/* Cursor Color 2 */
|
||||
p[x_pos] = ramdac->extra_pal[1].pixel;
|
||||
break;
|
||||
case 0x03:
|
||||
/* Cursor Color 3 */
|
||||
p[x_pos] = ramdac->extra_pal[2].pixel;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
switch (dat) {
|
||||
case 0x00:
|
||||
/* Cursor Color 1 */
|
||||
p[x_pos] = ramdac->extra_pal[0].pixel;
|
||||
break;
|
||||
case 0x01:
|
||||
/* Cursor Color 2 */
|
||||
p[x_pos] = ramdac->extra_pal[1].pixel;
|
||||
break;
|
||||
case 0x03:
|
||||
/* Complement */
|
||||
p[x_pos] ^= 0xffffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
switch (dat) {
|
||||
case 0x02:
|
||||
/* Cursor Color 1 */
|
||||
p[x_pos] = ramdac->extra_pal[0].pixel;
|
||||
break;
|
||||
case 0x03:
|
||||
/* Cursor Color 2 */
|
||||
p[x_pos] = ramdac->extra_pal[1].pixel;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((x & 3) == 3)
|
||||
svga->dac_hwcursor_latch.addr++;
|
||||
}
|
||||
|
||||
if ((ramdac->indexed_data[0x071] & 0x20) && !svga->dac_hwcursor_oddeven)
|
||||
svga->dac_hwcursor_latch.addr += pitch;
|
||||
}
|
||||
|
||||
void *
|
||||
ibm_rgb528_ramdac_init(UNUSED(const device_t *info))
|
||||
{
|
||||
ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) malloc(sizeof(ibm_rgb528_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(ibm_rgb528_ramdac_t));
|
||||
|
||||
ramdac->smlc_part = 0x0100;
|
||||
|
||||
ramdac->indexed_data[0x0008] = 0x0001;
|
||||
ramdac->indexed_data[0x0015] = 0x0008;
|
||||
ramdac->indexed_data[0x0016] = 0x0041;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
ibm_rgb528_ramdac_close(void *priv)
|
||||
{
|
||||
ibm_rgb528_ramdac_t *ramdac = (ibm_rgb528_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t ibm_rgb528_ramdac_device = {
|
||||
.name = "IBM RGB528 RAMDAC",
|
||||
.internal_name = "ibm_rgb528_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = ibm_rgb528_ramdac_init,
|
||||
.close = ibm_rgb528_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
205
src/video/ramdac/vid_ramdac_sc1148x.c
Normal file
205
src/video/ramdac/vid_ramdac_sc1148x.c
Normal file
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of Sierra SC1148x RAMDACs and clones (e.g.: Winbond).
|
||||
*
|
||||
* Used by the S3 911 and 924 chips.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: TheCollector1995, <mariogplayer90@gmail.com>
|
||||
*
|
||||
* Copyright 2020 TheCollector1995.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
|
||||
typedef struct sc1148x_ramdac_t {
|
||||
int type;
|
||||
int state;
|
||||
int rs2;
|
||||
uint8_t ctrl;
|
||||
} sc1148x_ramdac_t;
|
||||
|
||||
void
|
||||
sc1148x_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) priv;
|
||||
uint8_t rs = (addr & 0x03) | ((!!rs2) << 2);
|
||||
int oldbpp = 0;
|
||||
|
||||
switch (rs) {
|
||||
case 2:
|
||||
case 6:
|
||||
switch (ramdac->state) {
|
||||
case 4:
|
||||
ramdac->state = 0;
|
||||
if (val == 0xff)
|
||||
break;
|
||||
ramdac->ctrl = val;
|
||||
ramdac->ctrl = (ramdac->ctrl & ~1) | ((((val >> 2) ^ val) & (val & 0x20)) >> 5);
|
||||
oldbpp = svga->bpp;
|
||||
switch (ramdac->type) {
|
||||
case 0: /* Sierra Mark 2 (11483)*/
|
||||
case 2: /* Sierra Mark 2 (11484)*/
|
||||
case 3: /* Sierra Mark 1 (11486)*/
|
||||
if (val & 0xa0) {
|
||||
svga->bpp = 15;
|
||||
} else if (val == 0x00)
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 1: /* Sierra Mark 3 (11487)*/
|
||||
if (val & 0xa0) {
|
||||
if (val & 0x40)
|
||||
svga->bpp = 16;
|
||||
else
|
||||
svga->bpp = 15;
|
||||
} else if (val == 0x00)
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (oldbpp != svga->bpp)
|
||||
svga_recalctimings(svga);
|
||||
return;
|
||||
default:
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ramdac->state = 0;
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
sc1148x_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga)
|
||||
{
|
||||
sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) priv;
|
||||
uint8_t ret = 0xff;
|
||||
uint8_t rs = (addr & 0x03) | ((!!rs2) << 2);
|
||||
|
||||
switch (rs) {
|
||||
case 2:
|
||||
case 6:
|
||||
switch (ramdac->state) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
ret = 0x00;
|
||||
ramdac->state++;
|
||||
break;
|
||||
case 4:
|
||||
ret = ramdac->ctrl;
|
||||
ret = (ret & ~0x18) | (svga->dac_mask & 0x18);
|
||||
break;
|
||||
default:
|
||||
ret = svga_in(addr, svga);
|
||||
ramdac->state++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = svga_in(addr, svga);
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *
|
||||
sc1148x_ramdac_init(const device_t *info)
|
||||
{
|
||||
sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) malloc(sizeof(sc1148x_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(sc1148x_ramdac_t));
|
||||
|
||||
ramdac->type = info->local;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
sc1148x_ramdac_close(void *priv)
|
||||
{
|
||||
sc1148x_ramdac_t *ramdac = (sc1148x_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t sc11483_ramdac_device = {
|
||||
.name = "Sierra SC11483 RAMDAC",
|
||||
.internal_name = "sc11483_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = sc1148x_ramdac_init,
|
||||
.close = sc1148x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t sc11487_ramdac_device = {
|
||||
.name = "Sierra SC11487 RAMDAC",
|
||||
.internal_name = "sc11487_ramdac",
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.init = sc1148x_ramdac_init,
|
||||
.close = sc1148x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t sc11484_nors2_ramdac_device = {
|
||||
.name = "Sierra SC11484 RAMDAC (no RS2 signal)",
|
||||
.internal_name = "sc11484_nors2_ramdac",
|
||||
.flags = 0,
|
||||
.local = 2,
|
||||
.init = sc1148x_ramdac_init,
|
||||
.close = sc1148x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t sc11486_ramdac_device = {
|
||||
.name = "Sierra SC11486 RAMDAC",
|
||||
.internal_name = "sc11486_ramdac",
|
||||
.flags = 0,
|
||||
.local = 3,
|
||||
.init = sc1148x_ramdac_init,
|
||||
.close = sc1148x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
256
src/video/ramdac/vid_ramdac_sc1502x.c
Normal file
256
src/video/ramdac/vid_ramdac_sc1502x.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of a Sierra SC1502X RAMDAC.
|
||||
*
|
||||
* Used by the TLIVESA1 driver for ET4000.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct sc1502x_ramdac_t {
|
||||
int state;
|
||||
uint8_t ctrl;
|
||||
uint8_t idx;
|
||||
uint8_t regs[256];
|
||||
uint32_t pixel_mask;
|
||||
uint8_t enable_ext;
|
||||
} sc1502x_ramdac_t;
|
||||
|
||||
static void
|
||||
sc1502x_ramdac_bpp(uint8_t val, sc1502x_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
int oldbpp = 0;
|
||||
if (val == 0xff)
|
||||
return;
|
||||
ramdac->ctrl = val;
|
||||
oldbpp = svga->bpp;
|
||||
switch ((val & 1) | ((val & 0xc0) >> 5)) {
|
||||
case 0:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
switch (val & 0x20) {
|
||||
case 0x00:
|
||||
svga->bpp = 32;
|
||||
break;
|
||||
case 0x20:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 6:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 7:
|
||||
if (val & 4) {
|
||||
switch (val & 0x20) {
|
||||
case 0x00:
|
||||
svga->bpp = 32;
|
||||
break;
|
||||
case 0x20:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (oldbpp != svga->bpp)
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void
|
||||
sc1502x_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3C6:
|
||||
if (ramdac->state == 0)
|
||||
ramdac->enable_ext = (val == 0x10);
|
||||
|
||||
if (ramdac->state == 4) {
|
||||
ramdac->state = 0;
|
||||
sc1502x_ramdac_bpp(val, ramdac, svga);
|
||||
return;
|
||||
}
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x3C7:
|
||||
if (ramdac->enable_ext) {
|
||||
ramdac->idx = val;
|
||||
return;
|
||||
}
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x3C8:
|
||||
if (ramdac->enable_ext) {
|
||||
switch (ramdac->idx) {
|
||||
case 8:
|
||||
ramdac->regs[ramdac->idx] = val;
|
||||
svga_set_ramdac_type(svga, (ramdac->regs[ramdac->idx] & 1) ? RAMDAC_8BIT : RAMDAC_6BIT);
|
||||
break;
|
||||
case 0x0d:
|
||||
ramdac->pixel_mask = val & svga->dac_mask;
|
||||
break;
|
||||
case 0x0e:
|
||||
ramdac->pixel_mask |= ((val & svga->dac_mask) << 8);
|
||||
break;
|
||||
case 0x0f:
|
||||
ramdac->pixel_mask |= ((val & svga->dac_mask) << 16);
|
||||
break;
|
||||
default:
|
||||
ramdac->regs[ramdac->idx] = val;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x3C9:
|
||||
if (ramdac->enable_ext)
|
||||
return;
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
sc1502x_ramdac_in(uint16_t addr, void *priv, svga_t *svga)
|
||||
{
|
||||
sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) priv;
|
||||
uint8_t temp = svga_in(addr, svga);
|
||||
|
||||
switch (addr) {
|
||||
case 0x3C6:
|
||||
if (ramdac->state == 4) {
|
||||
ramdac->state = 0;
|
||||
temp = ramdac->ctrl;
|
||||
break;
|
||||
}
|
||||
ramdac->state++;
|
||||
break;
|
||||
case 0x3C7:
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x3C8:
|
||||
if (ramdac->enable_ext) {
|
||||
switch (ramdac->idx) {
|
||||
case 9:
|
||||
temp = 0x53;
|
||||
break;
|
||||
case 0x0a:
|
||||
temp = 0x3a;
|
||||
break;
|
||||
case 0x0b:
|
||||
temp = 0xb1;
|
||||
break;
|
||||
case 0x0c:
|
||||
temp = 0x41;
|
||||
break;
|
||||
case 0x0d:
|
||||
temp = ramdac->pixel_mask & 0xff;
|
||||
break;
|
||||
case 0x0e:
|
||||
temp = ramdac->pixel_mask >> 8;
|
||||
break;
|
||||
case 0x0f:
|
||||
temp = ramdac->pixel_mask >> 16;
|
||||
break;
|
||||
default:
|
||||
temp = ramdac->regs[ramdac->idx];
|
||||
break;
|
||||
}
|
||||
} else
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
case 0x3C9:
|
||||
if (ramdac->enable_ext)
|
||||
temp = ramdac->idx;
|
||||
else
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void *
|
||||
sc1502x_ramdac_init(UNUSED(const device_t *info))
|
||||
{
|
||||
sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) malloc(sizeof(sc1502x_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(sc1502x_ramdac_t));
|
||||
|
||||
ramdac->ctrl = 0;
|
||||
ramdac->pixel_mask = 0xffffff;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
sc1502x_ramdac_close(void *priv)
|
||||
{
|
||||
sc1502x_ramdac_t *ramdac = (sc1502x_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t sc1502x_ramdac_device = {
|
||||
.name = "Sierra SC1502x RAMDAC",
|
||||
.internal_name = "sc1502x_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = sc1502x_ramdac_init,
|
||||
.close = sc1502x_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
362
src/video/ramdac/vid_ramdac_sdac.c
Normal file
362
src/video/ramdac/vid_ramdac_sdac.c
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* 87C716 'SDAC' true colour RAMDAC emulation.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
|
||||
enum {
|
||||
ICS_5300 = 0,
|
||||
ICS_5301,
|
||||
ICS_5340,
|
||||
ICS_5341,
|
||||
ICS_5342
|
||||
};
|
||||
|
||||
#define ICS_S3_MASK 7
|
||||
#define ICS_S3 8
|
||||
|
||||
#define S3_86C708 (ICS_5300 | ICS_S3)
|
||||
#define S3_86C716 (ICS_5342 | ICS_S3)
|
||||
|
||||
typedef struct sdac_ramdac_t {
|
||||
uint16_t regs[256];
|
||||
int magic_count;
|
||||
int windex;
|
||||
int rindex;
|
||||
int reg_ff;
|
||||
int rs2;
|
||||
uint8_t type;
|
||||
uint8_t command;
|
||||
} sdac_ramdac_t;
|
||||
|
||||
static void
|
||||
sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val)
|
||||
{
|
||||
ramdac->command = val;
|
||||
|
||||
switch (ramdac->type & ICS_S3_MASK) {
|
||||
case ICS_5300:
|
||||
case ICS_5301:
|
||||
switch (val >> 5) {
|
||||
default:
|
||||
case 0x00:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 0x01:
|
||||
case 0x04:
|
||||
case 0x05:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 0x03:
|
||||
case 0x06:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x07:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ICS_5340:
|
||||
case ICS_5341:
|
||||
case ICS_5342:
|
||||
switch (val >> 4) {
|
||||
default:
|
||||
case 0x00:
|
||||
case 0x01: /* This is actually 8bpp with two pixels read at a time. */
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
case 0x08:
|
||||
case 0x0a:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 0x05:
|
||||
case 0x06:
|
||||
case 0x0c:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x09:
|
||||
case 0x0e:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
case 0x07:
|
||||
svga->bpp = 32;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
static void
|
||||
sdac_reg_write(sdac_ramdac_t *ramdac, int reg, uint8_t val)
|
||||
{
|
||||
if ((reg >= 2 && reg <= 7) || (reg == 0xa) || (reg == 0xe)) {
|
||||
if (!ramdac->reg_ff)
|
||||
ramdac->regs[reg] = (ramdac->regs[reg] & 0xff00) | val;
|
||||
else
|
||||
ramdac->regs[reg] = (ramdac->regs[reg] & 0x00ff) | (val << 8);
|
||||
}
|
||||
ramdac->reg_ff = !ramdac->reg_ff;
|
||||
if (!ramdac->reg_ff)
|
||||
ramdac->windex++;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
sdac_reg_read(sdac_ramdac_t *ramdac, int reg)
|
||||
{
|
||||
uint8_t temp;
|
||||
|
||||
if (!ramdac->reg_ff)
|
||||
temp = ramdac->regs[reg] & 0xff;
|
||||
else
|
||||
temp = ramdac->regs[reg] >> 8;
|
||||
ramdac->reg_ff = !ramdac->reg_ff;
|
||||
if (!ramdac->reg_ff)
|
||||
ramdac->rindex++;
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void
|
||||
sdac_ramdac_out(uint16_t addr, int rs2, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
rs |= ((!!rs2) << 2);
|
||||
|
||||
if (rs != 0x02)
|
||||
ramdac->magic_count = 0;
|
||||
|
||||
switch (rs) {
|
||||
case 0x02:
|
||||
switch (ramdac->magic_count) {
|
||||
case 4:
|
||||
sdac_control_write(ramdac, svga, val);
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
default:
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
case 0x04:
|
||||
ramdac->windex = val;
|
||||
ramdac->reg_ff = 0;
|
||||
break;
|
||||
case 0x05:
|
||||
sdac_reg_write(ramdac, ramdac->windex & 0xff, val);
|
||||
break;
|
||||
case 0x06:
|
||||
sdac_control_write(ramdac, svga, val);
|
||||
break;
|
||||
case 0x07:
|
||||
ramdac->rindex = val;
|
||||
ramdac->reg_ff = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
sdac_ramdac_in(uint16_t addr, int rs2, void *priv, svga_t *svga)
|
||||
{
|
||||
sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
rs |= ((!!rs2) << 2);
|
||||
|
||||
if (rs != 0x02)
|
||||
ramdac->magic_count = 0;
|
||||
|
||||
switch (rs) {
|
||||
case 0x02:
|
||||
switch (ramdac->magic_count) {
|
||||
case 1:
|
||||
case 2:
|
||||
temp = 0x00;
|
||||
ramdac->magic_count++;
|
||||
break;
|
||||
case 3:
|
||||
temp = (ramdac->type & ICS_S3) ? 0x70 : 0x00;
|
||||
ramdac->magic_count++;
|
||||
break;
|
||||
case 4:
|
||||
temp = ramdac->command;
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
default:
|
||||
temp = svga_in(addr, svga);
|
||||
ramdac->magic_count++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x00:
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
case 0x04:
|
||||
temp = ramdac->windex;
|
||||
break;
|
||||
case 0x05:
|
||||
temp = sdac_reg_read(ramdac, ramdac->rindex & 0xff);
|
||||
break;
|
||||
case 0x06:
|
||||
temp = ramdac->command;
|
||||
break;
|
||||
case 0x07:
|
||||
temp = ramdac->rindex;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
float
|
||||
sdac_getclock(int clock, void *priv)
|
||||
{
|
||||
const sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv;
|
||||
float t;
|
||||
int m;
|
||||
int n1;
|
||||
int n2;
|
||||
|
||||
if (ramdac->regs[0xe] & (1 << 5))
|
||||
clock = ramdac->regs[0xe] & 7;
|
||||
|
||||
clock &= 7;
|
||||
|
||||
if (clock == 0)
|
||||
return 25175000.0;
|
||||
if (clock == 1)
|
||||
return 28322000.0;
|
||||
|
||||
m = (ramdac->regs[clock] & 0x7f) + 2;
|
||||
n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
|
||||
n2 = ((ramdac->regs[clock] >> 13) & 0x07);
|
||||
n2 = (1 << n2);
|
||||
t = (14318184.0f * (float) m) / (float) (n1 * n2);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void *
|
||||
sdac_ramdac_init(const device_t *info)
|
||||
{
|
||||
sdac_ramdac_t *ramdac = (sdac_ramdac_t *) malloc(sizeof(sdac_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(sdac_ramdac_t));
|
||||
|
||||
ramdac->type = info->local;
|
||||
|
||||
ramdac->regs[0] = 0x6128;
|
||||
ramdac->regs[1] = 0x623d;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
sdac_ramdac_close(void *priv)
|
||||
{
|
||||
sdac_ramdac_t *ramdac = (sdac_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t gendac_ramdac_device = {
|
||||
.name = "S3 GENDAC 86c708 RAMDAC",
|
||||
.internal_name = "gendac_ramdac",
|
||||
.flags = 0,
|
||||
.local = S3_86C708,
|
||||
.init = sdac_ramdac_init,
|
||||
.close = sdac_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t tseng_ics5301_ramdac_device = {
|
||||
.name = "Tseng ICS5301 GENDAC RAMDAC",
|
||||
.internal_name = "tseng_ics5301_ramdac",
|
||||
.flags = 0,
|
||||
.local = ICS_5301,
|
||||
.init = sdac_ramdac_init,
|
||||
.close = sdac_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t tseng_ics5341_ramdac_device = {
|
||||
.name = "Tseng ICS5341 GENDAC RAMDAC",
|
||||
.internal_name = "tseng_ics5341_ramdac",
|
||||
.flags = 0,
|
||||
.local = ICS_5341,
|
||||
.init = sdac_ramdac_init,
|
||||
.close = sdac_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t sdac_ramdac_device = {
|
||||
.name = "S3 SDAC 86c716 RAMDAC",
|
||||
.internal_name = "sdac_ramdac",
|
||||
.flags = 0,
|
||||
.local = S3_86C716,
|
||||
.init = sdac_ramdac_init,
|
||||
.close = sdac_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
270
src/video/ramdac/vid_ramdac_stg1702.c
Normal file
270
src/video/ramdac/vid_ramdac_stg1702.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* STG1702 true colour RAMDAC emulation.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct stg_ramdac_t {
|
||||
int magic_count, index;
|
||||
uint8_t regs[256];
|
||||
uint8_t command;
|
||||
} stg_ramdac_t;
|
||||
|
||||
static int stg_state_read[2][8] = {
|
||||
{1, 2, 3, 4, 0, 0, 0, 0},
|
||||
{ 1, 2, 3, 4, 5, 6, 7, 7}
|
||||
};
|
||||
static int stg_state_write[8] = { 0, 0, 0, 0, 0, 6, 7, 7 };
|
||||
|
||||
void
|
||||
stg_ramdac_set_bpp(svga_t *svga, stg_ramdac_t *ramdac)
|
||||
{
|
||||
if (ramdac->command & 0x8) {
|
||||
switch (ramdac->regs[3]) {
|
||||
default:
|
||||
case 0:
|
||||
case 5:
|
||||
case 7:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 8:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 3:
|
||||
case 6:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 4:
|
||||
case 9:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (ramdac->command >> 5) {
|
||||
default:
|
||||
case 0:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 5:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 6:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 7:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void
|
||||
stg_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
stg_ramdac_t *ramdac = (stg_ramdac_t *) priv;
|
||||
int didwrite;
|
||||
int old;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3c6:
|
||||
switch (ramdac->magic_count) {
|
||||
/* 0 = PEL mask register */
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
break;
|
||||
case 4: /* REG06 */
|
||||
old = ramdac->command;
|
||||
ramdac->command = val;
|
||||
if ((old ^ val) & 8)
|
||||
stg_ramdac_set_bpp(svga, ramdac);
|
||||
else {
|
||||
if ((old ^ val) & 0xE0)
|
||||
stg_ramdac_set_bpp(svga, ramdac);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
ramdac->index = (ramdac->index & 0xff00) | val;
|
||||
break;
|
||||
case 6:
|
||||
ramdac->index = (ramdac->index & 0xff) | (val << 8);
|
||||
break;
|
||||
case 7:
|
||||
if (ramdac->index < 0x100)
|
||||
ramdac->regs[ramdac->index] = val;
|
||||
if ((ramdac->index == 3) && (ramdac->command & 8))
|
||||
stg_ramdac_set_bpp(svga, ramdac);
|
||||
ramdac->index++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
didwrite = (ramdac->magic_count >= 4);
|
||||
ramdac->magic_count = stg_state_write[ramdac->magic_count & 7];
|
||||
if (didwrite)
|
||||
return;
|
||||
break;
|
||||
case 0x3c7:
|
||||
case 0x3c8:
|
||||
case 0x3c9:
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
stg_ramdac_in(uint16_t addr, void *priv, svga_t *svga)
|
||||
{
|
||||
stg_ramdac_t *ramdac = (stg_ramdac_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3c6:
|
||||
switch (ramdac->magic_count) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
temp = 0xff;
|
||||
break;
|
||||
case 4:
|
||||
temp = ramdac->command;
|
||||
break;
|
||||
case 5:
|
||||
temp = ramdac->index & 0xff;
|
||||
break;
|
||||
case 6:
|
||||
temp = ramdac->index >> 8;
|
||||
break;
|
||||
case 7:
|
||||
switch (ramdac->index) {
|
||||
case 0:
|
||||
temp = 0x44;
|
||||
break;
|
||||
case 1:
|
||||
temp = 0x03;
|
||||
break;
|
||||
case 7:
|
||||
temp = 0x88;
|
||||
break;
|
||||
default:
|
||||
if (ramdac->index < 0x100)
|
||||
temp = ramdac->regs[ramdac->index];
|
||||
else
|
||||
temp = 0xff;
|
||||
break;
|
||||
}
|
||||
ramdac->index++;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ramdac->magic_count = stg_state_read[(ramdac->command & 0x10) ? 1 : 0][ramdac->magic_count & 7];
|
||||
return temp;
|
||||
case 0x3c7:
|
||||
case 0x3c8:
|
||||
case 0x3c9:
|
||||
ramdac->magic_count = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
|
||||
float
|
||||
stg_getclock(int clock, void *priv)
|
||||
{
|
||||
stg_ramdac_t *ramdac = (stg_ramdac_t *) priv;
|
||||
float t;
|
||||
int m;
|
||||
int n;
|
||||
int n2;
|
||||
const uint16_t *c;
|
||||
|
||||
if (clock == 0)
|
||||
return 25175000.0;
|
||||
if (clock == 1)
|
||||
return 28322000.0;
|
||||
|
||||
clock ^= 1; /*Clocks 2 and 3 seem to be reversed*/
|
||||
c = (uint16_t *) &ramdac->regs[0x20 + (clock << 1)];
|
||||
m = (*c & 0xff) + 2; /* B+2 */
|
||||
n = ((*c >> 8) & 0x1f) + 2; /* N1+2 */
|
||||
n2 = ((*c >> 13) & 0x07); /* D */
|
||||
n2 = (1 << n2);
|
||||
t = (14318184.0f * (float) m) / (float) (n * n2);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static void *
|
||||
stg_ramdac_init(UNUSED(const device_t *info))
|
||||
{
|
||||
stg_ramdac_t *ramdac = (stg_ramdac_t *) malloc(sizeof(stg_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(stg_ramdac_t));
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
stg_ramdac_close(void *priv)
|
||||
{
|
||||
stg_ramdac_t *ramdac = (stg_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t stg_ramdac_device = {
|
||||
.name = "SGS-Thompson STG170x RAMDAC",
|
||||
.internal_name = "stg_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = stg_ramdac_init,
|
||||
.close = stg_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
136
src/video/ramdac/vid_ramdac_tkd8001.c
Normal file
136
src/video/ramdac/vid_ramdac_tkd8001.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Trident TKD8001 RAMDAC emulation.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
typedef struct tkd8001_ramdac_t {
|
||||
int state;
|
||||
uint8_t ctrl;
|
||||
} tkd8001_ramdac_t;
|
||||
|
||||
void
|
||||
tkd8001_ramdac_out(uint16_t addr, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3C6:
|
||||
if (ramdac->state == 4) {
|
||||
ramdac->state = 0;
|
||||
ramdac->ctrl = val;
|
||||
switch (val >> 5) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
svga->bpp = 8;
|
||||
break;
|
||||
case 5:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 6:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
case 7:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 0x3C7:
|
||||
case 0x3C8:
|
||||
case 0x3C9:
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
svga_out(addr, val, svga);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
tkd8001_ramdac_in(uint16_t addr, void *priv, svga_t *svga)
|
||||
{
|
||||
tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) priv;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3C6:
|
||||
if (ramdac->state == 4)
|
||||
return ramdac->ctrl;
|
||||
ramdac->state++;
|
||||
break;
|
||||
case 0x3C7:
|
||||
case 0x3C8:
|
||||
case 0x3C9:
|
||||
ramdac->state = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return svga_in(addr, svga);
|
||||
}
|
||||
|
||||
static void *
|
||||
tkd8001_ramdac_init(UNUSED(const device_t *info))
|
||||
{
|
||||
tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) malloc(sizeof(tkd8001_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(tkd8001_ramdac_t));
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
tkd8001_ramdac_close(void *priv)
|
||||
{
|
||||
tkd8001_ramdac_t *ramdac = (tkd8001_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t tkd8001_ramdac_device = {
|
||||
.name = "Trident TKD8001 RAMDAC",
|
||||
.internal_name = "tkd8001_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = tkd8001_ramdac_init,
|
||||
.close = tkd8001_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
740
src/video/ramdac/vid_ramdac_tvp3026.c
Normal file
740
src/video/ramdac/vid_ramdac_tvp3026.c
Normal file
@@ -0,0 +1,740 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Emulation of the Texas Instruments TVP3026 true colour RAMDAC
|
||||
* family.
|
||||
*
|
||||
*
|
||||
* TODO: Clock and other parts.
|
||||
*
|
||||
* Authors: TheCollector1995,
|
||||
*
|
||||
* Copyright 2021 TheCollector1995.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/video.h>
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
|
||||
typedef struct tvp3026_ramdac_t {
|
||||
PALETTE extpal;
|
||||
uint32_t extpallook[256];
|
||||
uint8_t cursor64_data[1024];
|
||||
int hwc_y;
|
||||
int hwc_x;
|
||||
uint8_t ind_idx;
|
||||
uint8_t dcc;
|
||||
uint8_t dc_init;
|
||||
uint8_t ccr;
|
||||
uint8_t true_color;
|
||||
uint8_t latch_cntl;
|
||||
uint8_t mcr;
|
||||
uint8_t ppr;
|
||||
uint8_t general_cntl;
|
||||
uint8_t mclk;
|
||||
uint8_t misc;
|
||||
uint8_t type;
|
||||
uint8_t mode;
|
||||
uint8_t pll_addr;
|
||||
uint8_t clock_sel;
|
||||
struct {
|
||||
uint8_t m;
|
||||
uint8_t n;
|
||||
uint8_t p;
|
||||
} pix, mem, loop;
|
||||
uint8_t gpio_cntl;
|
||||
uint8_t gpio_data;
|
||||
uint8_t (*gpio_read)(uint8_t cntl, void *priv);
|
||||
void (*gpio_write)(uint8_t cntl, uint8_t val, void *priv);
|
||||
void *gpio_priv;
|
||||
} tvp3026_ramdac_t;
|
||||
|
||||
static void
|
||||
tvp3026_set_bpp(tvp3026_ramdac_t *ramdac, svga_t *svga)
|
||||
{
|
||||
if (ramdac->true_color & 0x80) {
|
||||
if (ramdac->mcr & 0x08)
|
||||
svga->bpp = 8;
|
||||
else
|
||||
svga->bpp = 4;
|
||||
} else {
|
||||
switch (ramdac->true_color & 0x0f) {
|
||||
case 0x01:
|
||||
case 0x03:
|
||||
case 0x05:
|
||||
svga->bpp = 16;
|
||||
break;
|
||||
case 0x04:
|
||||
svga->bpp = 15;
|
||||
break;
|
||||
case 0x06:
|
||||
case 0x07:
|
||||
if (ramdac->true_color & 0x10)
|
||||
svga->bpp = 24;
|
||||
else
|
||||
svga->bpp = 32;
|
||||
break;
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
svga->bpp = 24;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
|
||||
void
|
||||
tvp3026_ramdac_out(uint16_t addr, int rs2, int rs3, uint8_t val, void *priv, svga_t *svga)
|
||||
{
|
||||
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv;
|
||||
uint32_t o32;
|
||||
uint8_t *cd;
|
||||
uint16_t index;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
uint16_t da_mask = 0x03ff;
|
||||
rs |= (!!rs2 << 2);
|
||||
rs |= (!!rs3 << 3);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
ramdac->ind_idx = val;
|
||||
fallthrough;
|
||||
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
|
||||
case 0x03:
|
||||
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
|
||||
svga->dac_pos = 0;
|
||||
svga->dac_status = addr & 0x03;
|
||||
svga->dac_addr = val;
|
||||
if (svga->dac_status)
|
||||
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
|
||||
break;
|
||||
case 0x01: /* Palette Data Register (RS value = 0001) */
|
||||
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
|
||||
svga_out(addr, val, svga);
|
||||
break;
|
||||
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
|
||||
svga->dac_status = 0;
|
||||
svga->fullchange = changeframecount;
|
||||
switch (svga->dac_pos) {
|
||||
case 0:
|
||||
svga->dac_r = val;
|
||||
svga->dac_pos++;
|
||||
break;
|
||||
case 1:
|
||||
svga->dac_g = val;
|
||||
svga->dac_pos++;
|
||||
break;
|
||||
case 2:
|
||||
index = svga->dac_addr & 3;
|
||||
ramdac->extpal[index].r = svga->dac_r;
|
||||
ramdac->extpal[index].g = svga->dac_g;
|
||||
ramdac->extpal[index].b = val;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
ramdac->extpallook[index] = makecol32(ramdac->extpal[index].r, ramdac->extpal[index].g, ramdac->extpal[index].b);
|
||||
else
|
||||
ramdac->extpallook[index] = makecol32(video_6to8[ramdac->extpal[index].r & 0x3f], video_6to8[ramdac->extpal[index].g & 0x3f], video_6to8[ramdac->extpal[index].b & 0x3f]);
|
||||
|
||||
if (svga->ext_overscan && !index) {
|
||||
o32 = svga->overscan_color;
|
||||
svga->overscan_color = ramdac->extpallook[0];
|
||||
if (o32 != svga->overscan_color)
|
||||
svga_recalctimings(svga);
|
||||
}
|
||||
svga->dac_addr = (svga->dac_addr + 1) & 0xff;
|
||||
svga->dac_pos = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x09: /* Direct Cursor Control (RS value = 1001) */
|
||||
ramdac->dcc = val;
|
||||
if (ramdac->ccr & 0x80) {
|
||||
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64;
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
|
||||
svga->dac_hwcursor.ena = !!(val & 0x03);
|
||||
ramdac->mode = val & 0x03;
|
||||
}
|
||||
break;
|
||||
case 0x0a: /* Indexed Data (RS value = 1010) */
|
||||
switch (ramdac->ind_idx) {
|
||||
case 0x06: /* Indirect Cursor Control */
|
||||
ramdac->ccr = val;
|
||||
if (!(ramdac->ccr & 0x80)) {
|
||||
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64;
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
|
||||
svga->dac_hwcursor.ena = !!(val & 0x03);
|
||||
ramdac->mode = val & 0x03;
|
||||
} else {
|
||||
svga->dac_hwcursor.cur_xsize = svga->dac_hwcursor.cur_ysize = 64;
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
|
||||
svga->dac_hwcursor.ena = !!(ramdac->dcc & 0x03);
|
||||
ramdac->mode = ramdac->dcc & 0x03;
|
||||
}
|
||||
break;
|
||||
case 0x0f: /* Latch Control */
|
||||
ramdac->latch_cntl = val;
|
||||
break;
|
||||
case 0x18: /* True Color Control */
|
||||
ramdac->true_color = val;
|
||||
tvp3026_set_bpp(ramdac, svga);
|
||||
break;
|
||||
case 0x19: /* Multiplex Control */
|
||||
ramdac->mcr = val;
|
||||
tvp3026_set_bpp(ramdac, svga);
|
||||
break;
|
||||
case 0x1a: /* Clock Selection */
|
||||
ramdac->clock_sel = val;
|
||||
break;
|
||||
case 0x1c: /* Palette-Page Register */
|
||||
ramdac->ppr = val;
|
||||
break;
|
||||
case 0x1d: /* General Control Register */
|
||||
ramdac->general_cntl = val;
|
||||
break;
|
||||
case 0x1e: /* Miscellaneous Control */
|
||||
ramdac->misc = val;
|
||||
svga->ramdac_type = (val & 0x08) ? RAMDAC_8BIT : RAMDAC_6BIT;
|
||||
break;
|
||||
case 0x2a: /* General-Purpose I/O Control */
|
||||
ramdac->gpio_cntl = val;
|
||||
if (ramdac->gpio_write)
|
||||
ramdac->gpio_write(ramdac->gpio_cntl, ramdac->gpio_data, ramdac->gpio_priv);
|
||||
break;
|
||||
case 0x2b: /* General-Purpose I/O Data */
|
||||
ramdac->gpio_data = val;
|
||||
if (ramdac->gpio_write)
|
||||
ramdac->gpio_write(ramdac->gpio_cntl, ramdac->gpio_data, ramdac->gpio_priv);
|
||||
break;
|
||||
case 0x2c: /* PLL Address */
|
||||
ramdac->pll_addr = val;
|
||||
break;
|
||||
case 0x2d: /* Pixel clock PLL data */
|
||||
switch (ramdac->pll_addr & 3) {
|
||||
case 0:
|
||||
ramdac->pix.n = val;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->pix.m = val;
|
||||
break;
|
||||
case 2:
|
||||
ramdac->pix.p = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ramdac->pll_addr = ((ramdac->pll_addr + 1) & 3) | (ramdac->pll_addr & 0xfc);
|
||||
break;
|
||||
case 0x2e: /* Memory Clock PLL Data */
|
||||
switch ((ramdac->pll_addr >> 2) & 3) {
|
||||
case 0:
|
||||
ramdac->mem.n = val;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->mem.m = val;
|
||||
break;
|
||||
case 2:
|
||||
ramdac->mem.p = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ramdac->pll_addr = ((ramdac->pll_addr + 4) & 0x0c) | (ramdac->pll_addr & 0xf3);
|
||||
break;
|
||||
case 0x2f: /* Loop Clock PLL Data */
|
||||
switch ((ramdac->pll_addr >> 4) & 3) {
|
||||
case 0:
|
||||
ramdac->loop.n = val;
|
||||
break;
|
||||
case 1:
|
||||
ramdac->loop.m = val;
|
||||
break;
|
||||
case 2:
|
||||
ramdac->loop.p = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ramdac->pll_addr = ((ramdac->pll_addr + 0x10) & 0x30) | (ramdac->pll_addr & 0xcf);
|
||||
break;
|
||||
case 0x39: /* MCLK/Loop Clock Control */
|
||||
ramdac->mclk = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
|
||||
index = (svga->dac_addr & da_mask) | ((ramdac->ccr & 0x0c) << 6);
|
||||
cd = (uint8_t *) ramdac->cursor64_data;
|
||||
cd[index] = val;
|
||||
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
|
||||
break;
|
||||
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
|
||||
ramdac->hwc_x = (ramdac->hwc_x & 0x0f00) | val;
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
|
||||
break;
|
||||
case 0x0d: /* Cursor X High Register (RS value = 1101) */
|
||||
ramdac->hwc_x = (ramdac->hwc_x & 0x00ff) | ((val & 0x0f) << 8);
|
||||
svga->dac_hwcursor.x = ramdac->hwc_x - svga->dac_hwcursor.cur_xsize;
|
||||
break;
|
||||
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
|
||||
ramdac->hwc_y = (ramdac->hwc_y & 0x0f00) | val;
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
|
||||
break;
|
||||
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
|
||||
ramdac->hwc_y = (ramdac->hwc_y & 0x00ff) | ((val & 0x0f) << 8);
|
||||
svga->dac_hwcursor.y = ramdac->hwc_y - svga->dac_hwcursor.cur_ysize;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
tvp3026_ramdac_in(uint16_t addr, int rs2, int rs3, void *priv, svga_t *svga)
|
||||
{
|
||||
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv;
|
||||
uint8_t temp = 0xff;
|
||||
const uint8_t *cd;
|
||||
uint16_t index;
|
||||
uint8_t rs = (addr & 0x03);
|
||||
uint16_t da_mask = 0x03ff;
|
||||
rs |= (!!rs2 << 2);
|
||||
rs |= (!!rs3 << 3);
|
||||
|
||||
switch (rs) {
|
||||
case 0x00: /* Palette Write Index Register (RS value = 0000) */
|
||||
case 0x01: /* Palette Data Register (RS value = 0001) */
|
||||
case 0x02: /* Pixel Read Mask Register (RS value = 0010) */
|
||||
case 0x04: /* Ext Palette Write Index Register (RS value = 0100) */
|
||||
temp = svga_in(addr, svga);
|
||||
break;
|
||||
case 0x03: /* Palette Read Index Register (RS value = 0011) */
|
||||
case 0x07: /* Ext Palette Read Index Register (RS value = 0111) */
|
||||
temp = svga->dac_addr & 0xff;
|
||||
break;
|
||||
case 0x05: /* Ext Palette Data Register (RS value = 0101) */
|
||||
index = (svga->dac_addr - 1) & 3;
|
||||
svga->dac_status = 3;
|
||||
switch (svga->dac_pos) {
|
||||
case 0:
|
||||
svga->dac_pos++;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
temp = ramdac->extpal[index].r;
|
||||
else
|
||||
temp = ramdac->extpal[index].r & 0x3f;
|
||||
break;
|
||||
case 1:
|
||||
svga->dac_pos++;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
temp = ramdac->extpal[index].g;
|
||||
else
|
||||
temp = ramdac->extpal[index].g & 0x3f;
|
||||
break;
|
||||
case 2:
|
||||
svga->dac_pos = 0;
|
||||
svga->dac_addr = svga->dac_addr + 1;
|
||||
if (svga->ramdac_type == RAMDAC_8BIT)
|
||||
temp = ramdac->extpal[index].b;
|
||||
else
|
||||
temp = ramdac->extpal[index].b & 0x3f;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x09: /* Direct Cursor Control (RS value = 1001) */
|
||||
temp = ramdac->dcc;
|
||||
break;
|
||||
case 0x0a: /* Indexed Data (RS value = 1010) */
|
||||
switch (ramdac->ind_idx) {
|
||||
case 0x01: /* Silicon Revision */
|
||||
temp = 0x00;
|
||||
break;
|
||||
case 0x06: /* Indirect Cursor Control */
|
||||
temp = ramdac->ccr;
|
||||
break;
|
||||
case 0x0f: /* Latch Control */
|
||||
temp = ramdac->latch_cntl;
|
||||
break;
|
||||
case 0x18: /* True Color Control */
|
||||
temp = ramdac->true_color;
|
||||
break;
|
||||
case 0x19: /* Multiplex Control */
|
||||
temp = ramdac->mcr;
|
||||
break;
|
||||
case 0x1a: /* Clock Selection */
|
||||
temp = ramdac->clock_sel;
|
||||
break;
|
||||
case 0x1c: /* Palette-Page Register */
|
||||
temp = ramdac->ppr;
|
||||
break;
|
||||
case 0x1d: /* General Control Register */
|
||||
temp = ramdac->general_cntl;
|
||||
break;
|
||||
case 0x1e: /* Miscellaneous Control */
|
||||
temp = ramdac->misc;
|
||||
break;
|
||||
case 0x2a: /* General-Purpose I/O Control */
|
||||
temp = ramdac->gpio_cntl;
|
||||
break;
|
||||
case 0x2b: /* General-Purpose I/O Data */
|
||||
if (ramdac->gpio_read) {
|
||||
temp = 0xe0 | (ramdac->gpio_cntl & 0x1f); /* keep upper bits untouched */
|
||||
ramdac->gpio_data = (ramdac->gpio_data & temp) | (ramdac->gpio_read(ramdac->gpio_cntl, ramdac->gpio_priv) & ~temp);
|
||||
}
|
||||
temp = ramdac->gpio_data;
|
||||
break;
|
||||
case 0x2c: /* PLL Address */
|
||||
temp = ramdac->pll_addr;
|
||||
break;
|
||||
case 0x2d: /* Pixel clock PLL data */
|
||||
switch (ramdac->pll_addr & 3) {
|
||||
case 0:
|
||||
temp = ramdac->pix.n;
|
||||
break;
|
||||
case 1:
|
||||
temp = ramdac->pix.m;
|
||||
break;
|
||||
case 2:
|
||||
temp = ramdac->pix.p;
|
||||
break;
|
||||
case 3:
|
||||
temp = 0x40; /*PLL locked to frequency*/
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2e: /* Memory Clock PLL Data */
|
||||
switch ((ramdac->pll_addr >> 2) & 3) {
|
||||
case 0:
|
||||
temp = ramdac->mem.n;
|
||||
break;
|
||||
case 1:
|
||||
temp = ramdac->mem.m;
|
||||
break;
|
||||
case 2:
|
||||
temp = ramdac->mem.p;
|
||||
break;
|
||||
case 3:
|
||||
temp = 0x40; /*PLL locked to frequency*/
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x2f: /* Loop Clock PLL Data */
|
||||
switch ((ramdac->pll_addr >> 4) & 3) {
|
||||
case 0:
|
||||
temp = ramdac->loop.n;
|
||||
break;
|
||||
case 1:
|
||||
temp = ramdac->loop.m;
|
||||
break;
|
||||
case 2:
|
||||
temp = ramdac->loop.p;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x39: /* MCLK/Loop Clock Control */
|
||||
temp = ramdac->mclk;
|
||||
break;
|
||||
case 0x3f: /* ID */
|
||||
temp = 0x26;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x0b: /* Cursor RAM Data Register (RS value = 1011) */
|
||||
index = ((svga->dac_addr - 1) & da_mask) | ((ramdac->ccr & 0x0c) << 6);
|
||||
cd = (uint8_t *) ramdac->cursor64_data;
|
||||
temp = cd[index];
|
||||
|
||||
svga->dac_addr = (svga->dac_addr + 1) & da_mask;
|
||||
break;
|
||||
case 0x0c: /* Cursor X Low Register (RS value = 1100) */
|
||||
temp = ramdac->hwc_x & 0xff;
|
||||
break;
|
||||
case 0x0d: /* Cursor X High Register (RS value = 1101) */
|
||||
temp = (ramdac->hwc_x >> 8) & 0xff;
|
||||
break;
|
||||
case 0x0e: /* Cursor Y Low Register (RS value = 1110) */
|
||||
temp = ramdac->hwc_y & 0xff;
|
||||
break;
|
||||
case 0x0f: /* Cursor Y High Register (RS value = 1111) */
|
||||
temp = (ramdac->hwc_y >> 8) & 0xff;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
void
|
||||
tvp3026_recalctimings(void *priv, svga_t *svga)
|
||||
{
|
||||
const tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv;
|
||||
|
||||
svga->interlace = !!(ramdac->ccr & 0x40);
|
||||
/* TODO: Figure out gamma correction for 15/16 bpp color. */
|
||||
svga->lut_map = !!((svga->bpp >= 15 && (svga->bpp != 24)) && (ramdac->true_color & 0xf0) != 0x00);
|
||||
|
||||
if (!(ramdac->clock_sel & 0x70)) {
|
||||
if (ramdac->mcr != 0x98) {
|
||||
svga->hdisp <<= 1;
|
||||
svga->dots_per_clock <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
tvp3026_conv_16to32(svga_t* svga, uint16_t color, uint8_t bpp)
|
||||
{
|
||||
uint32_t ret = 0x00000000;
|
||||
|
||||
if (svga->lut_map) {
|
||||
if (bpp == 15) {
|
||||
uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]);
|
||||
uint8_t g = getcolg(svga->pallook[(color & 0x3e0) >> 2]);
|
||||
uint8_t r = getcolb(svga->pallook[(color & 0x7c00) >> 7]);
|
||||
ret = (video_15to32[color] & 0xFF000000) | makecol(r, g, b);
|
||||
} else {
|
||||
uint8_t b = getcolr(svga->pallook[(color & 0x1f) << 3]);
|
||||
uint8_t g = getcolg(svga->pallook[(color & 0x7e0) >> 3]);
|
||||
uint8_t r = getcolb(svga->pallook[(color & 0xf800) >> 8]);
|
||||
ret = (video_16to32[color] & 0xFF000000) | makecol(r, g, b);
|
||||
}
|
||||
} else
|
||||
ret = (bpp == 15) ? video_15to32[color] : video_16to32[color];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
tvp3026_hwcursor_draw(svga_t *svga, int displine)
|
||||
{
|
||||
int comb;
|
||||
int b0;
|
||||
int b1;
|
||||
uint16_t dat[2];
|
||||
int offset = svga->dac_hwcursor_latch.x + svga->dac_hwcursor_latch.xoff;
|
||||
int pitch;
|
||||
int bppl;
|
||||
int mode;
|
||||
int x_pos;
|
||||
int y_pos;
|
||||
uint32_t clr1;
|
||||
uint32_t clr2;
|
||||
uint32_t clr3;
|
||||
uint32_t *p;
|
||||
const uint8_t *cd;
|
||||
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) svga->ramdac;
|
||||
|
||||
clr1 = ramdac->extpallook[1];
|
||||
clr2 = ramdac->extpallook[2];
|
||||
clr3 = ramdac->extpallook[3];
|
||||
|
||||
/* The planes come in two parts, and each plane is 1bpp,
|
||||
so a 32x32 cursor has 4 bytes per line, and a 64x64
|
||||
cursor has 8 bytes per line. */
|
||||
pitch = (svga->dac_hwcursor_latch.cur_xsize >> 3); /* Bytes per line. */
|
||||
/* A 32x32 cursor has 128 bytes per line, and a 64x64
|
||||
cursor has 512 bytes per line. */
|
||||
bppl = (pitch * svga->dac_hwcursor_latch.cur_ysize); /* Bytes per plane. */
|
||||
mode = ramdac->mode;
|
||||
|
||||
if (svga->interlace && svga->dac_hwcursor_oddeven)
|
||||
svga->dac_hwcursor_latch.addr += pitch;
|
||||
|
||||
cd = (uint8_t *) ramdac->cursor64_data;
|
||||
|
||||
for (int x = 0; x < svga->dac_hwcursor_latch.cur_xsize; x += 16) {
|
||||
dat[0] = (cd[svga->dac_hwcursor_latch.addr] << 8) | cd[svga->dac_hwcursor_latch.addr + 1];
|
||||
dat[1] = (cd[svga->dac_hwcursor_latch.addr + bppl] << 8) | cd[svga->dac_hwcursor_latch.addr + bppl + 1];
|
||||
|
||||
for (uint8_t xx = 0; xx < 16; xx++) {
|
||||
b0 = (dat[0] >> (15 - xx)) & 1;
|
||||
b1 = (dat[1] >> (15 - xx)) & 1;
|
||||
comb = (b0 | (b1 << 1));
|
||||
|
||||
y_pos = displine;
|
||||
x_pos = (offset + svga->x_add) & 2047;
|
||||
p = svga->monitor->target_buffer->line[y_pos];
|
||||
|
||||
if (offset >= svga->dac_hwcursor_latch.x) {
|
||||
switch (mode) {
|
||||
case 1: /* Three Color */
|
||||
switch (comb) {
|
||||
case 1:
|
||||
p[x_pos] = clr1;
|
||||
break;
|
||||
case 2:
|
||||
p[x_pos] = clr2;
|
||||
break;
|
||||
case 3:
|
||||
p[x_pos] = clr3;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: /* XGA */
|
||||
switch (comb) {
|
||||
case 0:
|
||||
p[x_pos] = clr1;
|
||||
break;
|
||||
case 1:
|
||||
p[x_pos] = clr2;
|
||||
break;
|
||||
case 3:
|
||||
p[x_pos] ^= 0xffffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3: /* X-Windows */
|
||||
switch (comb) {
|
||||
case 2:
|
||||
p[x_pos] = clr1;
|
||||
break;
|
||||
case 3:
|
||||
p[x_pos] = clr2;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
svga->dac_hwcursor_latch.addr += 2;
|
||||
}
|
||||
|
||||
if (svga->interlace && !svga->dac_hwcursor_oddeven)
|
||||
svga->dac_hwcursor_latch.addr += pitch;
|
||||
}
|
||||
|
||||
float
|
||||
tvp3026_getclock(int clock, void *priv)
|
||||
{
|
||||
const tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv;
|
||||
int n;
|
||||
int m;
|
||||
int pl;
|
||||
float f_vco;
|
||||
float f_pll;
|
||||
|
||||
if (clock == 0)
|
||||
return 25175000.0;
|
||||
if (clock == 1)
|
||||
return 28322000.0;
|
||||
|
||||
/*Fvco = 8 x Fref x (65 - M) / (65 - N)*/
|
||||
/*Fpll = Fvco / 2^P*/
|
||||
n = ramdac->pix.n & 0x3f;
|
||||
m = ramdac->pix.m & 0x3f;
|
||||
pl = ramdac->pix.p & 0x03;
|
||||
f_vco = 8.0f * 14318184 * (float) (65 - m) / (float) (65 - n);
|
||||
f_pll = f_vco / (float) (1 << pl);
|
||||
|
||||
return f_pll;
|
||||
}
|
||||
|
||||
void
|
||||
tvp3026_gpio(uint8_t (*read)(uint8_t cntl, void *priv),
|
||||
void (*write)(uint8_t cntl, uint8_t val, void *priv),
|
||||
void *cb_priv, void *priv)
|
||||
{
|
||||
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv;
|
||||
|
||||
ramdac->gpio_read = read;
|
||||
ramdac->gpio_write = write;
|
||||
ramdac->gpio_priv = cb_priv;
|
||||
}
|
||||
|
||||
void *
|
||||
tvp3026_ramdac_init(const device_t *info)
|
||||
{
|
||||
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) malloc(sizeof(tvp3026_ramdac_t));
|
||||
memset(ramdac, 0, sizeof(tvp3026_ramdac_t));
|
||||
|
||||
ramdac->type = info->local;
|
||||
|
||||
ramdac->latch_cntl = 0x06;
|
||||
ramdac->true_color = 0x80;
|
||||
ramdac->mcr = 0x98;
|
||||
ramdac->clock_sel = 0x07;
|
||||
ramdac->mclk = 0x18;
|
||||
|
||||
return ramdac;
|
||||
}
|
||||
|
||||
static void
|
||||
tvp3026_ramdac_close(void *priv)
|
||||
{
|
||||
tvp3026_ramdac_t *ramdac = (tvp3026_ramdac_t *) priv;
|
||||
|
||||
if (ramdac)
|
||||
free(ramdac);
|
||||
}
|
||||
|
||||
const device_t tvp3026_ramdac_device = {
|
||||
.name = "TI TVP3026 RAMDAC",
|
||||
.internal_name = "tvp3026_ramdac",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = tvp3026_ramdac_init,
|
||||
.close = tvp3026_ramdac_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
Reference in New Issue
Block a user