Video features and fixes:

Added the Mach8 and Mach32 ISA/VLB/PCI cards (initial implementation and MCA coming soon for the Mach32) and their corresponding EEPROM's.
Added INMOS XGA ISA card and updated the SVGA core to reflect its mapping as well as the Mach8/32 mapping when in 8514 monitor mode.
Mark the XGA button as already checked and locked when a standalone XGA BIOS card is present like the INMOS one. (QT only)
Same concept as above, but applies to the Mach8 and 32 for the 8514 option as well. (QT only)
This commit is contained in:
TC1995
2023-07-14 23:38:04 +02:00
parent 7efcef82d0
commit cb06b9e78f
15 changed files with 6648 additions and 283 deletions

View File

@@ -18,7 +18,7 @@ add_library(vid OBJECT agpgart.c video.c vid_table.c vid_cga.c vid_cga_comp.c
vid_incolor.c vid_colorplus.c vid_genius.c vid_pgc.c vid_im1024.c
vid_sigma.c vid_wy700.c vid_ega.c vid_ega_render.c vid_svga.c vid_8514a.c
vid_svga_render.c vid_ddc.c vid_vga.c vid_ati_eeprom.c vid_ati18800.c
vid_ati28800.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.c
vid_ati28800.c vid_ati_mach8.c vid_ati_mach64.c vid_ati68860_ramdac.c vid_bt48x_ramdac.c
vid_av9194.c vid_icd2061.c vid_ics2494.c vid_ics2595.c vid_cl54xx.c
vid_et3000.c vid_et4000.c vid_sc1148x_ramdac.c vid_sc1502x_ramdac.c
vid_et4000w32.c vid_stg_ramdac.c vid_ht216.c vid_oak_oti.c vid_paradise.c

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,26 @@ ati_eeprom_load(ati_eeprom_t *eeprom, char *fn, int type)
fclose(f);
}
void
ati_eeprom_load_mach8(ati_eeprom_t *eeprom, char *fn)
{
FILE *f;
int size;
eeprom->type = 0;
strncpy(eeprom->fn, fn, sizeof(eeprom->fn) - 1);
f = nvr_fopen(eeprom->fn, "rb");
size = 128;
if (!f) { /*The ATI Graphics Ultra bios expects an immediate write to nvram if none is present at boot time otherwise
it would hang the machine.*/
memset(eeprom->data, 0, size);
f = nvr_fopen(eeprom->fn, "wb");
fwrite(eeprom->data, 1, size, f);
}
if (fread(eeprom->data, 1, size, f) != size)
memset(eeprom->data, 0, size);
fclose(f);
}
void
ati_eeprom_save(ati_eeprom_t *eeprom)
{

5568
src/video/vid_ati_mach8.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -41,6 +41,7 @@
#include <86box/video.h>
#include <86box/vid_svga.h>
#include <86box/vid_svga_render.h>
#include <86box/vid_xga_device.h>
void svga_doblit(int wx, int wy, svga_t *svga);
@@ -131,7 +132,7 @@ svga_out(uint16_t addr, uint8_t val, void *p)
if (svga->attraddr < 16)
svga->fullchange = svga->monitor->mon_changeframecount;
if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10) {
for (uint8_t c = 0; c < 16; c++) {
for (int c = 0; c < 16; c++) {
if (svga->attrregs[0x10] & 0x80) {
svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4);
} else {
@@ -165,6 +166,12 @@ svga_out(uint16_t addr, uint8_t val, void *p)
io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p);
svga_recalctimings(svga);
break;
case 0x3c3:
if (xga_enabled) {
svga->xga.on = (val & 0x01) ? 0 : 1;
vga_on = !svga->xga.on;
}
break;
case 0x3c4:
svga->seqaddr = val;
break;
@@ -407,7 +414,7 @@ svga_set_ramdac_type(svga_t *svga, int type)
if (svga->ramdac_type != type) {
svga->ramdac_type = type;
for (uint16_t c = 0; c < 256; c++) {
for (int c = 0; c < 256; c++) {
if (svga->ramdac_type == RAMDAC_8BIT)
svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b);
else
@@ -583,8 +590,14 @@ svga_recalctimings(svga_t *svga)
svga->recalctimings_ex(svga);
}
} else {
if (ibm8514_enabled)
ibm8514_recalctimings(svga);
if (ibm8514_enabled) {
if (svga->dev8514.local) {
if (svga->recalctimings_ex) {
svga->recalctimings_ex(svga);
}
} else
ibm8514_recalctimings(svga);
}
if (xga_enabled)
xga_recalctimings(svga);
}
@@ -597,8 +610,13 @@ svga_recalctimings(svga_t *svga)
crtcconst = svga->clock * svga->char_width;
disptime = svga->htotal;
_dispontime = svga->hdisp_time;
if (ibm8514_on && !svga->dev8514.local) {
disptime = svga->dev8514.h_total;
_dispontime = svga->dev8514.h_disp;
} else {
disptime = svga->htotal;
_dispontime = svga->hdisp_time;
}
if (svga->seqregs[1] & 8) {
disptime *= 2;
@@ -678,16 +696,20 @@ void
svga_poll(void *p)
{
svga_t *svga = (svga_t *) p;
ibm8514_t *dev = &svga->dev8514;
uint32_t x;
uint32_t blink_delay;
int wx;
int wy;
int ret;
int old_ma;
int linecountff = 0;
if (!vga_on && ibm8514_enabled && ibm8514_on) {
ibm8514_poll(&svga->dev8514, svga);
return;
if (!dev->local) {
ibm8514_poll(dev, svga);
return;
}
} else if (!vga_on && xga_enabled && svga->xga.on) {
xga_poll(&svga->xga, svga);
return;
@@ -695,22 +717,22 @@ svga_poll(void *p)
if (!svga->linepos) {
if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena) {
svga->hwcursor_on = svga->hwcursor.cur_ysize - svga->hwcursor_latch.yoff;
svga->hwcursor_on = svga->hwcursor_latch.cur_ysize - svga->hwcursor_latch.yoff;
svga->hwcursor_oddeven = 0;
}
if (svga->displine == (svga->hwcursor_latch.y + 1) && svga->hwcursor_latch.ena && svga->interlace) {
svga->hwcursor_on = svga->hwcursor.cur_ysize - (svga->hwcursor_latch.yoff + 1);
svga->hwcursor_on = svga->hwcursor_latch.cur_ysize - (svga->hwcursor_latch.yoff + 1);
svga->hwcursor_oddeven = 1;
}
if (svga->displine == svga->dac_hwcursor_latch.y && svga->dac_hwcursor_latch.ena) {
svga->dac_hwcursor_on = svga->dac_hwcursor.cur_ysize - svga->dac_hwcursor_latch.yoff;
svga->dac_hwcursor_on = svga->dac_hwcursor_latch.cur_ysize - svga->dac_hwcursor_latch.yoff;
svga->dac_hwcursor_oddeven = 0;
}
if (svga->displine == (svga->dac_hwcursor_latch.y + 1) && svga->dac_hwcursor_latch.ena && svga->interlace) {
svga->dac_hwcursor_on = svga->dac_hwcursor.cur_ysize - (svga->dac_hwcursor_latch.yoff + 1);
svga->dac_hwcursor_on = svga->dac_hwcursor_latch.cur_ysize - (svga->dac_hwcursor_latch.yoff + 1);
svga->dac_hwcursor_oddeven = 1;
}
@@ -783,8 +805,14 @@ svga_poll(void *p)
if ((svga->sc == (svga->crtc[11] & 31)) || (svga->sc == svga->rowcount))
svga->con = 0;
if (svga->dispon) {
if (svga->linedbl && !svga->linecountff) {
svga->linecountff = 1;
/*Real IBM 8514/A or compatibility mode doesn't have linedbl, so skip those.*/
if (dev->local && ibm8514_on) {
svga->linedbl = 0;
svga->linecountff = 0;
linecountff = 1;
}
if (svga->linedbl && !svga->linecountff && !linecountff) {
svga->linecountff = 1;
svga->ma = svga->maback;
} else if (svga->sc == svga->rowcount) {
svga->linecountff = 0;
@@ -793,23 +821,24 @@ svga_poll(void *p)
svga->maback += (svga->rowoffset << 3);
if (svga->interlace)
svga->maback += (svga->rowoffset << 3);
svga->maback &= svga->vram_display_mask;
svga->ma = svga->maback;
} else {
svga->linecountff = 0;
svga->sc++;
svga->sc &= 31;
svga->sc &= 0x1f;
svga->ma = svga->maback;
}
}
svga->hsync_divisor = !svga->hsync_divisor;
svga->hsync_divisor ^= 1;
if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
return;
svga->vc++;
svga->vc &= 2047;
svga->vc &= 0x7ff;
if (svga->vc == svga->split) {
ret = 1;
@@ -835,6 +864,7 @@ svga_poll(void *p)
if (svga->vc == svga->dispend) {
if (svga->vblank_start)
svga->vblank_start(svga);
svga->dispon = 0;
blink_delay = (svga->crtc[11] & 0x60) >> 5;
if (svga->crtc[10] & 0x20)
@@ -846,6 +876,7 @@ svga_poll(void *p)
if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15))
svga->fullchange = 2;
svga->blink = (svga->blink + 1) & 0x7f;
for (x = 0; x < ((svga->vram_mask + 1) >> 12); x++) {
@@ -888,12 +919,18 @@ svga_poll(void *p)
svga->monitor->mon_changeframecount = svga->interlace ? 3 : 2;
svga->vslines = 0;
if (svga->interlace && svga->oddeven)
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5);
else
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5);
if ((dev->local && vga_on) || !dev->local) {
if (svga->interlace && svga->oddeven)
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5);
else
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5);
} else if (dev->local && ibm8514_on) {
if (svga->interlace && svga->oddeven)
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1);
else
svga->ma = svga->maback = svga->ma_latch;
}
svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj;
svga->ma = (svga->ma << 2);
svga->maback = (svga->maback << 2);
svga->ca = (svga->ca << 2);
@@ -958,9 +995,9 @@ svga_init(const device_t *info, svga_t *svga, void *p, int memsize,
svga->monitor_index = monitor_index_global;
svga->monitor = &monitors[svga->monitor_index];
for (uint16_t c = 0; c < 256; c++) {
for (int c = 0; c < 256; c++) {
e = c;
for (uint8_t d = 0; d < 8; d++) {
for (int d = 0; d < 8; d++) {
svga_rotate[d][c] = e;
e = (e >> 1) | ((e & 1) ? 0x80 : 0);
}
@@ -1100,7 +1137,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p)
if (!linear) {
if (xga_enabled) {
if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl == 1)) {
if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl >= 1)) {
if (val == 0xa5) { /*Memory size test of XGA*/
svga->xga.test = val;
svga->xga.a5_test = 1;
@@ -1108,7 +1145,7 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p)
} else if (val == 0x5a) {
svga->xga.test = val;
return;
} else if (val == 0x12 || val == 0x34) {
} else if ((val == 0x12) || (val == 0x34)) {
addr += svga->xga.write_bank;
svga->xga.vram[addr & svga->xga.vram_mask] = val;
svga->xga.linear_endian_reverse = 1;
@@ -1145,10 +1182,18 @@ svga_write_common(uint32_t addr, uint8_t val, uint8_t linear, void *p)
if (addr & 1)
writemask2 <<= 1;
addr &= ~1;
addr <<= 2;
} else
addr <<= 2;
if (linear && ibm8514_on && (svga->adv_flags & FLAG_ATI)) {
addr &= svga->vram_mask;
} else
addr <<= 2;
} else {
if (linear && ibm8514_on && (svga->adv_flags & FLAG_ATI)) {
writemask2 = 1 << (addr & 3);
addr &= ~3;
addr &= svga->vram_mask;
} else
addr <<= 2;
}
addr &= svga->decode_mask;
if (svga->translate_address)
@@ -1303,7 +1348,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
if (!linear) {
if (xga_enabled) {
if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl == 1)) {
if (((svga->xga.op_mode & 7) >= 4) && (svga->xga.aperture_cntl >= 1)) {
if (svga->xga.test == 0xa5) { /*Memory size test of XGA*/
svga->xga.on = 1;
vga_on = !svga->xga.on;
@@ -1312,7 +1357,7 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
svga->xga.on = 1;
vga_on = !svga->xga.on;
return svga->xga.test;
} else if (addr == 0xa0000 || addr == 0xa0010) {
} else if ((addr == 0xa0000) || (addr == 0xa0010)) {
addr += svga->xga.read_bank;
return svga->xga.vram[addr & svga->xga.vram_mask];
}
@@ -1354,11 +1399,24 @@ svga_read_common(uint32_t addr, uint8_t linear, void *p)
} else if (svga->chain2_read) {
readplane = (readplane & 2) | (addr & 1);
addr &= ~1;
addr <<= 2;
} else
addr <<= 2;
if (linear && ibm8514_on && (svga->adv_flags & FLAG_ATI))
addr &= svga->vram_mask;
else
addr <<= 2;
} else {
if (linear && ibm8514_on && (svga->adv_flags & FLAG_ATI)) {
addr &= svga->decode_mask;
if (addr >= svga->vram_max)
return 0xff;
latch_addr = (addr & svga->vram_mask) & ~3;
for (uint8_t i = 0; i < count; i++)
svga->latch.b[i] = svga->vram[latch_addr | i];
return svga->vram[addr & svga->vram_mask];
} else
addr <<= 2;
}
addr &= svga->decode_mask;
if (svga->translate_address) {
latch_addr = svga->translate_address(latch_addr, p);
addr = svga->translate_address(addr, p);

View File

@@ -36,6 +36,7 @@
#include <86box/vid_ega.h>
#include <86box/vid_colorplus.h>
#include <86box/vid_mda.h>
#include <86box/vid_xga_device.h>
typedef struct {
const device_t *device;
@@ -79,6 +80,8 @@ video_cards[] = {
{ &vid_none_device },
{ &vid_internal_device },
{ &atiega_device },
{ &mach8_isa_device, VIDEO_FLAG_TYPE_8514 },
{ &mach32_isa_device, VIDEO_FLAG_TYPE_8514 },
{ &mach64gx_isa_device },
{ &ati28800k_device },
{ &ati18800_vga88_device },
@@ -112,6 +115,7 @@ video_cards[] = {
{ &hercules_device, VIDEO_FLAG_TYPE_MDA },
{ &herculesplus_device, VIDEO_FLAG_TYPE_MDA },
{ &incolor_device },
{ &inmos_isa_device, VIDEO_FLAG_TYPE_XGA },
{ &im1024_device },
{ &iskra_ega_device },
{ &et4000_kasan_isa_device },
@@ -154,6 +158,7 @@ video_cards[] = {
{ &gd5428_mca_device },
{ &et4000_mca_device },
{ &radius_svga_multiview_mca_device },
{ &mach32_pci_device, VIDEO_FLAG_TYPE_8514 },
{ &mach64gx_pci_device },
{ &mach64vt2_device },
{ &et4000w32p_videomagic_revb_pci_device },
@@ -211,6 +216,7 @@ video_cards[] = {
{ &voodoo_3_1000_device },
{ &voodoo_3_2000_device },
{ &voodoo_3_3000_device },
{ &mach32_vlb_device, VIDEO_FLAG_TYPE_8514 },
{ &mach64gx_vlb_device },
{ &et4000w32i_vlb_device },
{ &et4000w32p_videomagic_revb_vlb_device },
@@ -431,3 +437,15 @@ video_is_ega_vga(void)
{
return (video_get_type() == VIDEO_FLAG_TYPE_SPECIAL);
}
int
video_is_8514(void)
{
return (video_get_type() == VIDEO_FLAG_TYPE_8514);
}
int
video_is_xga(void)
{
return (video_get_type() == VIDEO_FLAG_TYPE_XGA);
}

View File

@@ -37,6 +37,7 @@
#define XGA_BIOS_PATH "roms/video/xga/XGA_37F9576_Ver200.BIN"
#define XGA2_BIOS_PATH "roms/video/xga/xga2_v300.bin"
#define INMOS_XGA_BIOS_PATH "roms/video/xga/InMOS XGA - Fairchild NM27C256Q-150.BIN"
static video_timings_t timing_xga_isa = { .type = VIDEO_ISA, .write_b = 3, .write_w = 3, .write_l = 6, .read_b = 5, .read_w = 5, .read_l = 10 };
static video_timings_t timing_xga_mca = { .type = VIDEO_MCA, .write_b = 4, .write_w = 5, .write_l = 10, .read_b = 5, .read_w = 5, .read_l = 10 };
@@ -44,16 +45,86 @@ static video_timings_t timing_xga_mca = { .type = VIDEO_MCA, .write_b = 4, .writ
static void xga_ext_outb(uint16_t addr, uint8_t val, void *p);
static uint8_t xga_ext_inb(uint16_t addr, void *p);
int xga_has_vga = 0;
void
svga_xga_out(uint16_t addr, uint8_t val, void *p)
{
svga_t *svga = (svga_t *)p;
uint8_t old;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr) {
case 0x3D4:
svga->crtcreg = val & 0x3f;
return;
case 0x3D5:
if (svga->crtcreg & 0x20)
return;
if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
return;
if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
val = (svga->crtc[7] & ~0x10) | (val & 0x10);
old = svga->crtc[svga->crtcreg];
svga->crtc[svga->crtcreg] = val;
if (old != val) {
if (svga->crtcreg < 0xe || svga->crtcreg > 0x10) {
if ((svga->crtcreg == 0xc) || (svga->crtcreg == 0xd)) {
svga->fullchange = 3;
svga->ma_latch = ((svga->crtc[0xc] << 8) | svga->crtc[0xd]) + ((svga->crtc[8] & 0x60) >> 5);
} else {
svga->fullchange = changeframecount;
svga_recalctimings(svga);
}
}
}
break;
}
svga_out(addr, val, svga);
}
uint8_t
svga_xga_in(uint16_t addr, void *p)
{
svga_t *svga = (svga_t *)p;
uint8_t temp;
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
addr ^= 0x60;
switch (addr) {
case 0x3D4:
temp = svga->crtcreg;
break;
case 0x3D5:
if (svga->crtcreg & 0x20)
temp = 0xff;
else
temp = svga->crtc[svga->crtcreg];
break;
default:
temp = svga_in(addr, svga);
break;
}
return temp;
}
void
xga_updatemapping(svga_t *svga)
{
xga_t *xga = &svga->xga;
//pclog("OpMode = %x, linear base = %08x, aperture cntl = %d, opmodereset1 = %d, access mode = %x, map = %x.\n", xga->op_mode, xga->linear_base, xga->aperture_cntl, xga->op_mode_reset, xga->access_mode, svga->gdcreg[6] & 0x0c);
//pclog("OpMode = %x, linear base = %08x, aperture cntl = %d, access mode = %x, map = %x, endian reverse = %d, a5test = %d, XGA on = %d.\n", xga->op_mode, xga->linear_base, xga->aperture_cntl, xga->access_mode, svga->gdcreg[6] & 0x0c, xga->linear_endian_reverse, xga->a5_test, xga->on);
if (((xga->op_mode & 7) >= 4) || ((xga->op_mode & 7) == 0)) {
if (xga->aperture_cntl == 1) {
if ((xga->aperture_cntl == 1) || (xga->aperture_cntl == 2)) {
mem_mapping_disable(&svga->mapping);
mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000);
if (xga->aperture_cntl == 1)
mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000);
else
mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000);
mem_mapping_enable(&xga->video_mapping);
xga->banked_mask = 0xffff;
if (!xga->linear_endian_reverse)
@@ -63,38 +134,23 @@ xga_updatemapping(svga_t *svga)
mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000);
mem_mapping_enable(&xga->video_mapping);
xga->banked_mask = 0xffff;
if (xga->pos_regs[4] & 1)
mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000);
else if (xga->base_addr_1mb)
if (xga->base_addr_1mb)
mem_mapping_set_addr(&xga->linear_mapping, xga->base_addr_1mb, 0x100000);
else
mem_mapping_set_addr(&xga->linear_mapping, xga->linear_base, 0x400000);
if (((xga->op_mode & 7) == 4) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test && xga->on)
xga->linear_endian_reverse = 1;
else if (((xga->op_mode & 7) == 0) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test && !xga->on)
else if (((xga->op_mode & 7) == 0) && ((svga->gdcreg[6] & 0x0c) == 0x0c) && !xga->a5_test && !xga->on) {
xga->linear_endian_reverse = 1;
xga->on = 0;
vga_on = !xga->on;
} else {
mem_mapping_disable(&svga->mapping);
mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000);
mem_mapping_enable(&xga->video_mapping);
xga->banked_mask = 0xffff;
mem_mapping_disable(&xga->linear_mapping);
}
if (xga->a5_test && (xga->access_mode & 8) && !xga->linear_endian_reverse) {
xga->on = 0;
vga_on = !xga->on;
}
}
} else {
xga->on = 0;
vga_on = !xga->on;
mem_mapping_disable(&svga->mapping);
if (xga->aperture_cntl == 2)
mem_mapping_set_addr(&xga->video_mapping, 0xb0000, 0x10000);
else
mem_mapping_set_addr(&xga->video_mapping, 0xa0000, 0x10000);
mem_mapping_enable(&xga->video_mapping);
xga->banked_mask = 0xffff;
mem_mapping_disable(&xga->linear_mapping);
//pclog("XGA opmode (not extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, xga->disp_cntl_2 & 7, xga->aperture_cntl);
//pclog("XGA opmode (extended) = %d, disp mode = %d, aperture = %d.\n", xga->op_mode & 7, xga->disp_cntl_2 & 7, xga->aperture_cntl);
}
//pclog("VGA on = %d.\n", vga_on);
}
void
@@ -126,19 +182,19 @@ xga_recalctimings(svga_t *svga)
xga->ma_latch = xga->disp_start_addr;
switch (xga->clk_sel_1 & 0x0c) {
switch ((xga->clk_sel_1 >> 2) & 3) {
case 0:
if (xga->clk_sel_2 & 0x80) {
svga->clock = (cpuclock * (double) (1ULL << 32)) / 41539000.0;
svga->clock = (cpuclock * (double) (1ull << 32)) / 41539000.0;
} else {
svga->clock = (cpuclock * (double) (1ULL << 32)) / 25175000.0;
svga->clock = (cpuclock * (double) (1ull << 32)) / 25175000.0;
}
break;
case 4:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 28322000.0;
case 1:
svga->clock = (cpuclock * (double) (1ull << 32)) / 28322000.0;
break;
case 0x0c:
svga->clock = (cpuclock * (double) (1ULL << 32)) / 44900000.0;
case 3:
svga->clock = (cpuclock * (double) (1ull << 32)) / 44900000.0;
break;
}
}
@@ -309,7 +365,7 @@ xga_ext_out_reg(xga_t *xga, svga_t *svga, uint8_t idx, uint8_t val)
if ((xga->sprite_pos >= 0) && (xga->sprite_pos <= 16)) {
if ((xga->op_mode & 7) >= 5)
xga->cursor_data_on = 1;
else if (xga->sprite_pos >= 1)
else if ((xga->sprite_pos >= 1) || ((xga->disp_cntl_2 & 7) > 3))
xga->cursor_data_on = 1;
else if (xga->aperture_cntl == 0) {
if (xga->linear_endian_reverse && !(xga->access_mode & 8))
@@ -474,7 +530,10 @@ xga_ext_inb(uint16_t addr, void *p)
case 0x0f:
switch (xga->regs_idx) {
case 4:
ret = (xga->bus & DEVICE_MCA) ? 1 : 0;
if (xga->bus & DEVICE_MCA)
ret = 0x01; /*32-bit MCA*/
else
ret = 0x10; /*16-bit ISA*/
break;
case 0x10:
ret = xga->htotal & 0xff;
@@ -653,6 +712,16 @@ xga_ext_inb(uint16_t addr, void *p)
ret = xga->clk_sel_2;
break;
case 0x74:
if (xga->bus & DEVICE_MCA)
ret = xga->regs[xga->regs_idx];
else {
ret = (xga->dma_channel << 1);
if (xga->dma_channel)
ret |= 1;
}
break;
default:
ret = xga->regs[xga->regs_idx];
break;
@@ -678,15 +747,35 @@ xga_ext_inb(uint16_t addr, void *p)
dat = xga->vram[(addr + 1) & (xga->vram_mask - 1)] & 0xff; \
dat |= (xga->vram[(addr) & (xga->vram_mask - 1)] << 8);
#define READL(addr, dat) \
dat = *(uint32_t *) &xga->vram[(addr) & (xga->vram_mask)];
#define READL_REVERSE(addr, dat) \
dat = xga->vram[(addr + 3) & (xga->vram_mask - 3)] & 0xff; \
dat |= (xga->vram[(addr + 2) & (xga->vram_mask - 3)] << 8); \
dat |= (xga->vram[(addr + 1) & (xga->vram_mask - 3)] << 16); \
dat |= (xga->vram[(addr) & (xga->vram_mask - 3)] << 24);
#define WRITEW(addr, dat) \
*(uint16_t *) &xga->vram[((addr)) & (xga->vram_mask)] = dat; \
xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount;
#define WRITEL(addr, dat) \
*(uint32_t *) &xga->vram[((addr)) & (xga->vram_mask)] = dat; \
xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount;
#define WRITEW_REVERSE(addr, dat) \
xga->vram[((addr + 1)) & (xga->vram_mask - 1)] = dat & 0xff; \
xga->vram[((addr)) & (xga->vram_mask - 1)] = dat >> 8; \
xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount;
#define WRITEL_REVERSE(addr, dat) \
xga->vram[((addr + 3)) & (xga->vram_mask - 3)] = dat & 0xff; \
xga->vram[((addr + 2)) & (xga->vram_mask - 3)] = dat >> 8; \
xga->vram[((addr + 1)) & (xga->vram_mask - 3)] = dat >> 16; \
xga->vram[((addr)) & (xga->vram_mask - 3)] = dat >> 24; \
xga->changedvram[(((addr)) & (xga->vram_mask)) >> 12] = svga->monitor->mon_changeframecount;
#define ROP(mix, d, s) \
{ \
switch ((mix) ? (xga->accel.frgd_mix & 0x1f) : (xga->accel.bkgd_mix & 0x1f)) { \
@@ -859,6 +948,23 @@ xga_accel_read_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, int
byte = mem_readw_phys(addr);
}
return byte;
case 5: /*24-bit*/
addr += (y * (width << 2));
addr += (x << 2);
if (!skip) {
if ((xga->accel.px_map_format[map] & 8)) {
if (xga->linear_endian_reverse) {
READL(addr, byte);
} else {
READL_REVERSE(addr, byte);
}
} else {
READL(addr, byte);
}
} else {
byte = mem_readl_phys(addr);
}
return byte;
}
return 0;
@@ -936,6 +1042,22 @@ xga_accel_write_map_pixel(svga_t *svga, int x, int y, int map, uint32_t base, ui
}
mem_writew_phys(addr, pixel);
break;
case 5: /*24-bit*/
addr += (y * (width) << 2);
addr += (x << 2);
if (!skip) {
if ((xga->accel.px_map_format[map] & 8)) {
if (xga->linear_endian_reverse) {
WRITEL(addr, pixel);
} else {
WRITEL_REVERSE(addr, pixel);
}
} else {
WRITEL(addr, pixel);
}
}
mem_writel_phys(addr, pixel);
break;
}
}
@@ -1447,6 +1569,10 @@ xga_mem_write(uint32_t addr, uint32_t val, xga_t *xga, svga_t *svga, int len)
if (addr >= 0x1800) {
switch (addr & 0x7f) {
case 0x11:
xga->accel.control = val;
break;
case 0x12:
xga->accel.px_map_idx = val & 3;
break;
@@ -1923,11 +2049,21 @@ xga_mem_read(uint32_t addr, xga_t *xga, svga_t *svga)
uint8_t temp = 0;
addr &= 0x1fff;
if (addr < 0x1800) {
temp = xga->bios_rom.rom[addr];
if (!xga_has_vga)
temp = xga->bios_rom.rom[addr];
else
temp = xga->vga_bios_rom.rom[addr];
} else {
switch (addr & 0x7f) {
case 0x11:
temp = xga->accel.control;
if (xga->accel.control & 0x08)
temp |= 0x10;
else
temp &= ~0x10;
break;
case 0x20:
temp = xga->accel.bres_err_term & 0xff;
break;
@@ -2092,8 +2228,9 @@ xga_render_overscan_left(xga_t *xga, svga_t *svga)
if (svga->scrblank || (xga->h_disp == 0))
return;
uint32_t *line_ptr = svga->monitor->target_buffer->line[xga->displine + svga->y_add];
for (int i = 0; i < svga->x_add; i++)
buffer32->line[xga->displine + svga->y_add][i] = svga->overscan_color;
*line_ptr++ = svga->overscan_color;
}
static void
@@ -2107,9 +2244,10 @@ xga_render_overscan_right(xga_t *xga, svga_t *svga)
if (svga->scrblank || (xga->h_disp == 0))
return;
right = (overscan_x >> 1);
uint32_t *line_ptr = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add + xga->h_disp];
right = (overscan_x >> 1);
for (int i = 0; i < right; i++)
buffer32->line[xga->displine + svga->y_add][svga->x_add + xga->h_disp + i] = svga->overscan_color;
*line_ptr++ = svga->overscan_color;
}
static void
@@ -2122,7 +2260,7 @@ xga_render_8bpp(xga_t *xga, svga_t *svga)
return;
if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[xga->displine + svga->y_add][svga->x_add];
p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add];
if (xga->firstline_draw == 2000)
xga->firstline_draw = xga->displine;
@@ -2159,7 +2297,7 @@ xga_render_16bpp(xga_t *xga, svga_t *svga)
return;
if (xga->changedvram[xga->ma >> 12] || xga->changedvram[(xga->ma >> 12) + 1] || svga->fullchange) {
p = &buffer32->line[xga->displine + svga->y_add][svga->x_add];
p = &svga->monitor->target_buffer->line[xga->displine + svga->y_add][svga->x_add];
if (xga->firstline_draw == 2000)
xga->firstline_draw = xga->displine;
@@ -2524,7 +2662,7 @@ xga_poll(xga_t *xga, svga_t *svga)
}
xga->vc++;
xga->vc &= 2047;
xga->vc &= 0x7ff;
if (xga->vc == xga->split) {
if (xga->interlace && xga->oddeven)
@@ -2683,8 +2821,149 @@ static uint8_t
xga_pos_in(uint16_t addr, void *priv)
{
svga_t *svga = (svga_t *) priv;
xga_t *xga = &svga->xga;
uint8_t ret;
return (xga_mca_read(addr, svga));
if (xga_has_vga) {
switch (addr) {
case 0x0100:
case 0x0101:
if (xga->instance_isa == xga->instance_num)
ret = xga->pos_regs[addr & 7];
else
ret = 0xff;
break;
case 0x0102:
case 0x0105:
ret = xga->pos_regs[addr & 7];
break;
case 0x0106:
ret = xga->pos_idx >> 8;
break;
case 0x0107:
ret = xga->pos_idx & 0xff;
break;
case 0x0103:
if (!(xga->pos_idx & 3)) {
ret = xga->pos_regs[3];
} else
ret = 0;
//pclog("POS IDX for 0103 = %d, ret = %02x.\n", xga->pos_idx & 3, ret);
break;
case 0x0104:
switch (xga->pos_idx & 3) {
case 0:
ret = xga->pos_regs[4];
break;
case 1:
ret = xga->pos_regs[0];
break;
case 2:
ret = xga->pos_regs[1];
break;
case 3:
ret = 0;
break;
}
//pclog("POS IDX for 0104 = %d, ret = %02x.\n", xga->pos_idx & 3, ret);
break;
case 0x0108:
case 0x0109:
case 0x010a:
case 0x010b:
case 0x010c:
case 0x010d:
case 0x010e:
case 0x010f:
xga->instance_num = addr & 7;
if (xga->instance_isa == xga->instance_num)
ret = xga->instance_isa;
else
ret = 0;
ret |= xga->isa_pos_enable;
break;
}
} else {
switch (addr) {
case 0x0100:
case 0x0101:
ret = xga->pos_regs[addr & 7];
break;
case 0x0103:
ret = xga->pos_regs[3] | 7;
ret |= (xga->dma_channel << 3);
break;
case 0x0102:
case 0x0104:
case 0x0105:
case 0x0106:
case 0x0107:
ret = (xga_mca_read(addr, svga));
break;
case 0x0108:
case 0x0109:
case 0x010a:
case 0x010b:
case 0x010c:
case 0x010d:
case 0x010e:
case 0x010f:
xga->instance_num = addr & 7;
if (xga->instance_isa == xga->instance_num)
ret = xga->instance_isa;
else
ret = 0;
ret |= xga->isa_pos_enable;
break;
}
}
return ret;
}
static void
xga_pos_out(uint16_t addr, uint8_t val, void *priv)
{
svga_t *svga = (svga_t *) priv;
xga_t *xga = &svga->xga;
if (xga_has_vga) {
switch (addr) {
case 0x0106:
xga->pos_idx = (xga->pos_idx & 0x00ff) | (val << 8);
break;
case 0x0107:
xga->pos_idx = (xga->pos_idx & 0xff00) | (val);
//pclog("POS IDX Write = %04x.\n", xga->pos_idx);
break;
case 0x0108:
case 0x0109:
case 0x010a:
case 0x010b:
case 0x010c:
case 0x010d:
case 0x010e:
case 0x010f:
xga->instance_num = addr & 7;
xga->isa_pos_enable = val & 0x08;
break;
}
} else {
switch (addr) {
case 0x0108:
case 0x0109:
case 0x010a:
case 0x010b:
case 0x010c:
case 0x010d:
case 0x010e:
case 0x010f:
xga->instance_num = addr & 7;
xga->isa_pos_enable = val & 0x08;
break;
}
}
}
static void
@@ -2700,7 +2979,10 @@ static void
uint32_t temp;
uint8_t *rom = NULL;
xga->ext_mem_addr = device_get_config_hex16("ext_mem_addr");
xga->instance_isa = device_get_config_int("instance");
xga->type = device_get_config_int("type");
xga->dma_channel = device_get_config_int("dma");
xga->bus = info->flags;
xga->vram_size = (1024 << 10);
@@ -2739,12 +3021,16 @@ static void
xga->rom_addr = 0;
rom_init(&xga->bios_rom, xga->type ? XGA2_BIOS_PATH : XGA_BIOS_PATH, 0xc0000, 0x2000, 0x1fff, 0, MEM_MAPPING_EXTERNAL);
} else {
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_isa);
xga->pos_regs[2] = 1 | 0x0c | 0xf0;
if (xga_has_vga) {
rom_init(&xga->vga_bios_rom, INMOS_XGA_BIOS_PATH, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
} else
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_xga_isa);
xga->pos_regs[2] = 1 | (xga->instance_isa << 1) | xga->ext_mem_addr;
xga->instance = (xga->pos_regs[2] & 0x0e) >> 1;
xga->pos_regs[4] = 1 | 2;
xga->linear_base = ((xga->pos_regs[4] & 0xfe) * 0x1000000) + (xga->instance << 22);
xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000);
xga->rom_addr = 0xc0000 + (((xga->pos_regs[2] & 0xf0) >> 4) * 0x2000);
}
mem_mapping_add(&xga->video_mapping, 0, 0, xga_readb, xga_readw, xga_readl,
@@ -2755,7 +3041,7 @@ static void
NULL, MEM_MAPPING_EXTERNAL, svga);
mem_mapping_add(&xga->memio_mapping, 0, 0, xga_memio_readb, xga_memio_readw, xga_memio_readl,
xga_memio_writeb, xga_memio_writew, xga_memio_writel,
xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga);
xga_has_vga ? xga->vga_bios_rom.rom : xga->bios_rom.rom, MEM_MAPPING_EXTERNAL, svga);
mem_mapping_disable(&xga->video_mapping);
mem_mapping_disable(&xga->linear_mapping);
@@ -2768,13 +3054,41 @@ static void
mca_add(xga_mca_read, xga_mca_write, xga_mca_feedb, xga_mca_reset, svga);
} else {
io_sethandler(0x0100, 0x0008, xga_pos_in, NULL, NULL, NULL, NULL, NULL, svga);
if (xga_has_vga)
io_sethandler(0x0106, 0x0002, NULL, NULL, NULL, xga_pos_out, NULL, NULL, svga);
io_sethandler(0x2100 + (xga->instance << 4), 0x0010, xga_ext_inb, NULL, NULL, xga_ext_outb, NULL, NULL, svga);
io_sethandler(0x0108, 0x0008, xga_pos_in, NULL, NULL, xga_pos_out, NULL, NULL, svga);
mem_mapping_set_addr(&xga->memio_mapping, xga->rom_addr + 0x1c00 + (xga->instance * 0x80), 0x80);
}
return svga;
}
static void
*
svga_xga_init(const device_t *info)
{
svga_t *svga = malloc(sizeof(svga_t));
memset(svga, 0, sizeof(svga_t));
video_inform(VIDEO_FLAG_TYPE_XGA, &timing_xga_isa);
svga_init(info, svga, svga, 1 << 18, /*256kB*/
NULL,
svga_xga_in, svga_xga_out,
NULL,
NULL);
io_sethandler(0x03c0, 0x0020, svga_xga_in, NULL, NULL, svga_xga_out, NULL, NULL, svga);
svga->bpp = 8;
svga->miscout = 1;
xga_has_vga = 1;
xga_enabled = 1;
return xga_init(info);
}
static void
xga_close(void *p)
{
@@ -2793,6 +3107,12 @@ xga_available(void)
return rom_present(XGA_BIOS_PATH) && rom_present(XGA2_BIOS_PATH);
}
static int
inmos_xga_available(void)
{
return rom_present(INMOS_XGA_BIOS_PATH);
}
static void
xga_speed_changed(void *p)
{
@@ -2809,7 +3129,7 @@ xga_force_redraw(void *p)
svga->fullchange = svga->monitor->mon_changeframecount;
}
static const device_config_t xga_configuration[] = {
static const device_config_t xga_mca_configuration[] = {
// clang-format off
{
.name = "type",
@@ -2835,6 +3155,91 @@ static const device_config_t xga_configuration[] = {
// clang-format on
};
static const device_config_t xga_isa_configuration[] = {
// clang-format off
{
.name = "type",
.description = "XGA type",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{
.description = "XGA-1",
.value = 0
},
{
.description = "XGA-2",
.value = 1
},
{ .description = "" }
}
},
{
.name = "instance",
.description = "Instance",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 6,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "0 (2100h-210Fh)", .value = 0 },
{ .description = "1 (2110h-211Fh)", .value = 1 },
{ .description = "2 (2120h-212Fh)", .value = 2 },
{ .description = "3 (2130h-213Fh)", .value = 3 },
{ .description = "4 (2140h-214Fh)", .value = 4 },
{ .description = "5 (2150h-215Fh)", .value = 5 },
{ .description = "6 (2160h-216Fh)", .value = 6 },
{ .description = "7 (2170h-217Fh)", .value = 7 },
{ .description = "" }
},
},
{
.name = "ext_mem_addr",
.description = "MMIO address",
.type = CONFIG_HEX16,
.default_string = "",
.default_int = 0x00f0,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "C800h", .value = 0x0040 },
{ .description = "CA00h", .value = 0x0050 },
{ .description = "CC00h", .value = 0x0060 },
{ .description = "CE00h", .value = 0x0070 },
{ .description = "D000h", .value = 0x0080 },
{ .description = "D200h", .value = 0x0090 },
{ .description = "D400h", .value = 0x00a0 },
{ .description = "D600h", .value = 0x00b0 },
{ .description = "D800h", .value = 0x00c0 },
{ .description = "DA00h", .value = 0x00d0 },
{ .description = "DC00h", .value = 0x00e0 },
{ .description = "DE00h", .value = 0x00f0 },
{ .description = "" }
},
},
{
.name = "dma",
.description = "DMA channel",
.type = CONFIG_SELECTION,
.default_string = "",
.default_int = 7,
.file_filter = "",
.spinner = { 0 },
.selection = {
{ .description = "Disabled", .value = 0 },
{ .description = "DMA 6", .value = 6 },
{ .description = "DMA 7", .value = 7 },
{ .description = "" }
},
},
{ .name = "", .description = "", .type = CONFIG_END }
// clang-format on
};
const device_t xga_device = {
.name = "XGA (MCA)",
.internal_name = "xga_mca",
@@ -2846,7 +3251,7 @@ const device_t xga_device = {
{ .available = xga_available },
.speed_changed = xga_speed_changed,
.force_redraw = xga_force_redraw,
.config = xga_configuration
.config = xga_mca_configuration
};
const device_t xga_isa_device = {
@@ -2860,13 +3265,27 @@ const device_t xga_isa_device = {
{ .available = xga_available },
.speed_changed = xga_speed_changed,
.force_redraw = xga_force_redraw,
.config = xga_configuration
.config = xga_isa_configuration
};
const device_t inmos_isa_device = {
.name = "INMOS XGA (ISA)",
.internal_name = "inmos_xga_isa",
.flags = DEVICE_ISA | DEVICE_AT,
.local = 0,
.init = svga_xga_init,
.close = xga_close,
.reset = xga_reset,
{ .available = inmos_xga_available },
.speed_changed = xga_speed_changed,
.force_redraw = xga_force_redraw,
.config = xga_isa_configuration
};
void
xga_device_add(void)
{
if (!xga_enabled)
if (!xga_enabled || (xga_has_vga && xga_enabled))
return;
if (machine_has_bus(machine, MACHINE_BUS_MCA))