mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 09:58:19 -07:00
SVGA hskew
This commit is contained in:
@@ -1828,6 +1828,28 @@ gd54xx_recalctimings(svga_t *svga)
|
||||
}
|
||||
|
||||
svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff;
|
||||
|
||||
pclog("svga->crtc[0x1a] = %02X\n", svga->crtc[0x1a]);
|
||||
pclog("svga->crtc[0x1b] = %02X\n", svga->crtc[0x1b]);
|
||||
pclog("svga->crtc[0x1c] = %02X\n", svga->crtc[0x1c]);
|
||||
|
||||
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430)
|
||||
svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07);
|
||||
|
||||
if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) {
|
||||
/* Special blanking mode: the blank start and end become components of the window generator,
|
||||
and the actual blanking comes from the display enable signal. */
|
||||
/* Start blanking at the first character clock after the last active one. */
|
||||
svga->hblankstart = svga->crtc[1] + 1;
|
||||
svga->hblank_end_val = (svga->htotal + 6) & 0x3f;
|
||||
/* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */
|
||||
if (!svga->scrblank && svga->attr_palette_enable)
|
||||
svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8;
|
||||
/* No overscan in this mode. */
|
||||
svga->hblank_overscan = 0;
|
||||
/* Also make sure vertical blanking starts on display end. */
|
||||
svga->vblankstart = svga->dispend;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -55,17 +55,19 @@
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
#define ET4000_TYPE_TC6058AF 0 /* ISA ET4000AX (TC6058AF) */
|
||||
#define ET4000_TYPE_ISA 1 /* ISA ET4000AX */
|
||||
#define ET4000_TYPE_MCA 2 /* MCA ET4000AX */
|
||||
#define ET4000_TYPE_KOREAN 3 /* Korean ET4000 */
|
||||
#define ET4000_TYPE_TRIGEM 4 /* Trigem 286M ET4000 */
|
||||
#define ET4000_TYPE_KASAN 5 /* Kasan ET4000 */
|
||||
|
||||
#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN"
|
||||
#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin"
|
||||
#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom"
|
||||
#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin"
|
||||
#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom"
|
||||
#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN"
|
||||
#define TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.bin"
|
||||
#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin"
|
||||
#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom"
|
||||
#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin"
|
||||
#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom"
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
@@ -115,6 +117,7 @@ et4000_in(uint16_t addr, void *priv)
|
||||
{
|
||||
et4000_t *dev = (et4000_t *) priv;
|
||||
svga_t *svga = &dev->svga;
|
||||
uint8_t ret;
|
||||
|
||||
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
|
||||
addr ^= 0x60;
|
||||
@@ -138,7 +141,8 @@ et4000_in(uint16_t addr, void *priv)
|
||||
case 0x3c7:
|
||||
case 0x3c8:
|
||||
case 0x3c9:
|
||||
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
|
||||
if (dev->type >= ET4000_TYPE_ISA)
|
||||
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
|
||||
|
||||
case 0x3cd: /*Banking*/
|
||||
return dev->banking;
|
||||
@@ -149,6 +153,26 @@ et4000_in(uint16_t addr, void *priv)
|
||||
case 0x3d5:
|
||||
return svga->crtc[svga->crtcreg];
|
||||
|
||||
case 0x3da:
|
||||
svga->attrff = 0;
|
||||
|
||||
if (svga->cgastat & 0x01)
|
||||
svga->cgastat &= ~0x30;
|
||||
else
|
||||
svga->cgastat ^= 0x30;
|
||||
|
||||
ret = svga->cgastat;
|
||||
|
||||
if ((svga->fcr & 0x08) && svga->dispon)
|
||||
ret |= 0x08;
|
||||
|
||||
if (ret & 0x08)
|
||||
ret &= 0x7f;
|
||||
else
|
||||
ret |= 0x80;
|
||||
|
||||
return ret;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -225,12 +249,33 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
|
||||
addr ^= 0x60;
|
||||
|
||||
switch (addr) {
|
||||
case 0x3c5:
|
||||
if (svga->seqaddr == 4) {
|
||||
svga->seqregs[4] = val;
|
||||
|
||||
svga->chain2_write = !(val & 4);
|
||||
svga->chain4 = (svga->chain4 & ~8) | (val & 8);
|
||||
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8);
|
||||
return;
|
||||
} else if (svga->seqaddr == 0x0e) {
|
||||
svga->seqregs[0x0e] = val;
|
||||
svga->chain4 &= ~0x02;
|
||||
if (svga->gdcreg[5] & 0x40)
|
||||
svga->chain4 |= (svga->seqregs[0x0e] & 0x02);
|
||||
svga_recalctimings(svga);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3c6:
|
||||
case 0x3c7:
|
||||
case 0x3c8:
|
||||
case 0x3c9:
|
||||
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
|
||||
return;
|
||||
if (dev->type >= ET4000_TYPE_ISA) {
|
||||
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x3cd: /*Banking*/
|
||||
if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) {
|
||||
@@ -241,7 +286,11 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
|
||||
return;
|
||||
|
||||
case 0x3cf:
|
||||
if ((svga->gdcaddr & 15) == 6) {
|
||||
if ((svga->gdcaddr & 15) == 5) {
|
||||
svga->chain4 &= ~0x02;
|
||||
if (val & 0x40)
|
||||
svga->chain4 |= (svga->seqregs[0x0e] & 0x02);
|
||||
} else if ((svga->gdcaddr & 15) == 6) {
|
||||
if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) {
|
||||
svga->write_bank = (dev->banking & 0x0f) * 0x10000;
|
||||
svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000;
|
||||
@@ -418,7 +467,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
|
||||
if ((et4000->kasan_cfg_index - 0xF0) <= 16)
|
||||
et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
|
||||
io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
|
||||
et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1];
|
||||
io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
|
||||
@@ -465,7 +515,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv)
|
||||
case 4:
|
||||
case 5:
|
||||
if (et4000->kasan_cfg_regs[0] & 1) {
|
||||
et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
|
||||
if ((addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)) <= 4)
|
||||
et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
@@ -607,6 +658,19 @@ et4000_recalctimings(svga_t *svga)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40)) {
|
||||
svga->ma_latch <<= (1 << 0);
|
||||
svga->rowoffset <<= (1 << 0);
|
||||
svga->render = svga_render_8bpp_highres;
|
||||
}
|
||||
|
||||
if (dev->type == ET4000_TYPE_TC6058AF) {
|
||||
if (svga->render == svga_render_8bpp_lowres)
|
||||
svga->render = svga_render_8bpp_tseng_lowres;
|
||||
else if (svga->render == svga_render_8bpp_highres)
|
||||
svga->render = svga_render_8bpp_tseng_highres;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -666,6 +730,7 @@ et4000_init(const device_t *info)
|
||||
fn = BIOS_ROM_PATH;
|
||||
|
||||
switch (dev->type) {
|
||||
case ET4000_TYPE_TC6058AF: /* ISA ET4000AX (TC6058AF) */
|
||||
case ET4000_TYPE_ISA: /* ISA ET4000AX */
|
||||
dev->vram_size = device_get_config_int("memory") << 10;
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa);
|
||||
@@ -674,6 +739,8 @@ et4000_init(const device_t *info)
|
||||
NULL, NULL);
|
||||
io_sethandler(0x03c0, 32,
|
||||
et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev);
|
||||
if (dev->type == ET4000_TYPE_TC6058AF)
|
||||
fn = TC6058AF_BIOS_ROM_PATH;
|
||||
break;
|
||||
|
||||
case ET4000_TYPE_MCA: /* MCA ET4000AX */
|
||||
@@ -750,7 +817,8 @@ et4000_init(const device_t *info)
|
||||
break;
|
||||
}
|
||||
|
||||
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
|
||||
if (dev->type >= ET4000_TYPE_ISA)
|
||||
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
|
||||
|
||||
dev->vram_mask = dev->vram_size - 1;
|
||||
|
||||
@@ -790,6 +858,12 @@ et4000_force_redraw(void *priv)
|
||||
dev->svga.fullchange = changeframecount;
|
||||
}
|
||||
|
||||
static int
|
||||
et4000_tc6058af_available(void)
|
||||
{
|
||||
return rom_present(TC6058AF_BIOS_ROM_PATH);
|
||||
}
|
||||
|
||||
static int
|
||||
et4000_available(void)
|
||||
{
|
||||
@@ -808,6 +882,33 @@ et4000_kasan_available(void)
|
||||
return rom_present(KASAN_BIOS_ROM_PATH) && rom_present(KASAN_FONT_ROM_PATH);
|
||||
}
|
||||
|
||||
static const device_config_t et4000_tc6058af_config[] = {
|
||||
// clang-format off
|
||||
{
|
||||
.name = "memory",
|
||||
.description = "Memory size",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_int = 512,
|
||||
.selection = {
|
||||
{
|
||||
.description = "256 KB",
|
||||
.value = 256
|
||||
},
|
||||
{
|
||||
.description = "512 KB",
|
||||
.value = 512
|
||||
},
|
||||
{
|
||||
.description = ""
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.type = CONFIG_END
|
||||
}
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static const device_config_t et4000_config[] = {
|
||||
// clang-format off
|
||||
{
|
||||
@@ -839,6 +940,20 @@ static const device_config_t et4000_config[] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
const device_t et4000_tc6058af_isa_device = {
|
||||
.name = "Tseng Labs ET4000AX (TC6058AF) (ISA)",
|
||||
.internal_name = "et4000ax_tc6058af",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = et4000_init,
|
||||
.close = et4000_close,
|
||||
.reset = NULL,
|
||||
{ .available = et4000_tc6058af_available },
|
||||
.speed_changed = et4000_speed_changed,
|
||||
.force_redraw = et4000_force_redraw,
|
||||
.config = et4000_tc6058af_config
|
||||
};
|
||||
|
||||
const device_t et4000_isa_device = {
|
||||
.name = "Tseng Labs ET4000AX (ISA)",
|
||||
.internal_name = "et4000ax",
|
||||
|
||||
@@ -457,6 +457,7 @@ et4000w32p_recalctimings(svga_t *svga)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (svga->adv_flags & FLAG_NOSKEW) {
|
||||
/* On the Cardex ET4000/W32p-based cards, adjust text mode clocks by 1. */
|
||||
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /* Text mode */
|
||||
@@ -480,6 +481,7 @@ et4000w32p_recalctimings(svga_t *svga)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (et4000->type == ET4000W32) {
|
||||
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
|
||||
@@ -2561,6 +2563,9 @@ et4000w32p_pci_read(UNUSED(int func), int addr, void *priv)
|
||||
{
|
||||
et4000w32p_t *et4000 = (et4000w32p_t *) priv;
|
||||
|
||||
if (func > 0)
|
||||
return 0xff;
|
||||
|
||||
addr &= 0xff;
|
||||
|
||||
switch (addr) {
|
||||
@@ -2618,6 +2623,9 @@ et4000w32p_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
|
||||
et4000w32p_t *et4000 = (et4000w32p_t *) priv;
|
||||
svga_t *svga = &et4000->svga;
|
||||
|
||||
if (func > 0)
|
||||
return;
|
||||
|
||||
addr &= 0xff;
|
||||
|
||||
switch (addr) {
|
||||
|
||||
@@ -3038,6 +3038,8 @@ s3_recalctimings(svga_t *svga)
|
||||
s3_t *s3 = (s3_t *) svga->priv;
|
||||
int clk_sel = (svga->miscout >> 2) & 3;
|
||||
|
||||
svga->hdisp = svga->hdisp_old;
|
||||
|
||||
if (!svga->scrblank && svga->attr_palette_enable) {
|
||||
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
|
||||
if (svga->crtc[0x3a] & 0x10) { /*256+ color register*/
|
||||
@@ -3047,14 +3049,13 @@ s3_recalctimings(svga_t *svga)
|
||||
}
|
||||
|
||||
svga->ma_latch |= (s3->ma_ext << 16);
|
||||
if (s3->chip >= S3_86C928) {
|
||||
svga->hdisp = svga->hdisp_old;
|
||||
|
||||
if (s3->chip >= S3_86C928) {
|
||||
if (svga->crtc[0x5d] & 0x01)
|
||||
svga->htotal |= 0x100;
|
||||
if (svga->crtc[0x5d] & 0x02) {
|
||||
svga->hdisp_time |= 0x100;
|
||||
svga->hdisp |= 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8);
|
||||
svga->hdisp |= 0x100 * svga->dots_per_clock;
|
||||
}
|
||||
if (svga->crtc[0x5e] & 0x01)
|
||||
svga->vtotal |= 0x400;
|
||||
@@ -3072,7 +3073,8 @@ s3_recalctimings(svga_t *svga)
|
||||
svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4;
|
||||
else if (svga->crtc[0x43] & 0x04)
|
||||
svga->rowoffset |= 0x100;
|
||||
}
|
||||
} else if (svga->crtc[0x43] & 0x04)
|
||||
svga->rowoffset |= 0x100;
|
||||
if (!svga->rowoffset)
|
||||
svga->rowoffset = 0x100;
|
||||
|
||||
@@ -3341,6 +3343,30 @@ s3_recalctimings(svga_t *svga)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s3->chip >= S3_86C801) {
|
||||
if (!svga->scrblank && svga->attr_palette_enable && (svga->crtc[0x43] & 0x80)) {
|
||||
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
|
||||
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18);
|
||||
}
|
||||
|
||||
if (svga->crtc[0x5d] & 0x04)
|
||||
svga->hblankstart += 0x100;
|
||||
if (s3->chip >= S3_VISION964) {
|
||||
/* NOTE: The S3 Trio64V+ datasheet says this is bit 7, but then where is bit 6?
|
||||
The datasheets for the pre-Trio64V+ cards say +64, which implies bit 6,
|
||||
and, contrary to VGADOC, it also exists on Trio32, Trio64, Vision868,
|
||||
and Vision968. */
|
||||
#if 0
|
||||
pclog("svga->crtc[0x5d] = %02X\n", svga->crtc[0x5d]);
|
||||
#endif
|
||||
if (svga->crtc[0x5d] & 0x08)
|
||||
svga->hblank_ext = 0x40;
|
||||
svga->hblank_end_len = 0x00000040;
|
||||
}
|
||||
}
|
||||
|
||||
svga->hblank_overscan = !(svga->crtc[0x33] & 0x20);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -202,7 +202,7 @@ svga_out(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
case 4:
|
||||
svga->chain2_write = !(val & 4);
|
||||
svga->chain4 = val & 8;
|
||||
svga->chain4 = (svga->chain4 & ~8) | (val & 8);
|
||||
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && ((svga->chain4 && (svga->packed_chain4 || svga->force_old_addr)) || svga->fb_only) && !(svga->adv_flags & FLAG_ADDR_BY8);
|
||||
break;
|
||||
|
||||
@@ -307,6 +307,9 @@ svga_out(uint16_t addr, uint8_t val, void *priv)
|
||||
if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
|
||||
svga_recalctimings(svga);
|
||||
break;
|
||||
case 0x3da:
|
||||
svga->fcr = val;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -384,6 +387,9 @@ svga_in(uint16_t addr, void *priv)
|
||||
if (svga->adv_flags & FLAG_RAMDAC_SHIFT)
|
||||
ret >>= 2;
|
||||
break;
|
||||
case 0x3ca:
|
||||
ret = svga->fcr;
|
||||
break;
|
||||
case 0x3cc:
|
||||
ret = svga->miscout;
|
||||
break;
|
||||
@@ -420,6 +426,8 @@ svga_in(uint16_t addr, void *priv)
|
||||
|
||||
ret = svga->cgastat;
|
||||
|
||||
if ((svga->fcr & 0x08) && svga->dispon)
|
||||
ret |= 0x08;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -453,6 +461,14 @@ svga_recalctimings(svga_t *svga)
|
||||
double _dispontime;
|
||||
double _dispofftime;
|
||||
double disptime;
|
||||
#ifdef ENABLE_SVGA_LOG
|
||||
int vsyncend;
|
||||
int vblankend;
|
||||
int hdispstart;
|
||||
int hdispend;
|
||||
int hsyncstart;
|
||||
int hsyncend;
|
||||
#endif
|
||||
|
||||
svga->vtotal = svga->crtc[6];
|
||||
svga->dispend = svga->crtc[0x12];
|
||||
@@ -490,7 +506,7 @@ svga_recalctimings(svga_t *svga)
|
||||
svga->vblankstart |= 0x200;
|
||||
svga->vblankstart++;
|
||||
|
||||
svga->hdisp = svga->crtc[1] - ((svga->crtc[5] & 0x60) >> 5);
|
||||
svga->hdisp = svga->crtc[1] - ((svga->crtc[3] & 0x60) >> 5);
|
||||
svga->hdisp++;
|
||||
|
||||
svga->htotal = svga->crtc[0];
|
||||
@@ -513,20 +529,20 @@ svga_recalctimings(svga_t *svga)
|
||||
svga->hdisp_time = svga->hdisp;
|
||||
svga->render = svga_render_blank;
|
||||
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
|
||||
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
|
||||
if (svga->seqregs[1] & 8)
|
||||
svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
|
||||
else
|
||||
svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
|
||||
|
||||
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
|
||||
if (svga->seqregs[1] & 8) { /*40 column*/
|
||||
svga->render = svga_render_text_40;
|
||||
svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
|
||||
/* Character clock is off by 1 now in 40-line modes, on all cards. */
|
||||
svga->ma_latch--;
|
||||
svga->hdisp += (svga->seqregs[1] & 1) ? 16 : 18;
|
||||
} else {
|
||||
svga->render = svga_render_text_80;
|
||||
svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
|
||||
}
|
||||
svga->hdisp_old = svga->hdisp;
|
||||
} else {
|
||||
svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
|
||||
svga->hdisp_old = svga->hdisp;
|
||||
|
||||
switch (svga->gdcreg[5] & 0x60) {
|
||||
@@ -612,6 +628,26 @@ svga_recalctimings(svga_t *svga)
|
||||
} else
|
||||
svga->monitor->mon_overscan_x = 16;
|
||||
|
||||
svga->htotal = svga->crtc[0];
|
||||
svga->hblankstart = svga->crtc[4] + 1;
|
||||
svga->hblank_end_val = (svga->crtc[3] & 0x1f) | ((svga->crtc[5] & 0x80) ? 0x20 : 0x00);
|
||||
#if 0
|
||||
pclog("htotal = %i, hblankstart = %i, hblank_end_val = %02X\n", svga->htotal, svga->hblankstart, svga->hblank_end_val);
|
||||
#endif
|
||||
svga->hblank_end_len = 0x00000040;
|
||||
svga->hblank_overscan = 1;
|
||||
|
||||
if (!svga->scrblank && svga->attr_palette_enable) {
|
||||
/* TODO: In case of bug reports, disable 9-dots-wide character clocks in graphics modes. */
|
||||
if (svga->seqregs[1] & 8)
|
||||
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 16 : 18);
|
||||
else
|
||||
svga->dots_per_clock = ((svga->seqregs[1] & 1) ? 8 : 9);
|
||||
} else
|
||||
svga->dots_per_clock = 1;
|
||||
|
||||
/* Do svga->recalctimings_ex() here so that the above five variables can be
|
||||
updated by said function. */
|
||||
if (vga_on) {
|
||||
if (svga->recalctimings_ex) {
|
||||
svga->recalctimings_ex(svga);
|
||||
@@ -629,6 +665,20 @@ svga_recalctimings(svga_t *svga)
|
||||
xga_recalctimings(svga);
|
||||
}
|
||||
|
||||
svga->htotal += 6; /*+6 is required for Tyrian*/
|
||||
svga->hblankend = (svga->hblankstart & ~(svga->hblank_end_len - 1)) | svga->hblank_end_val;
|
||||
if (svga->hblankend <= svga->hblankstart)
|
||||
svga->hblankend += svga->hblank_end_len;
|
||||
svga->hblankend += svga->hblank_ext;
|
||||
|
||||
svga->hblank_sub = 0;
|
||||
if (svga->hblankend > svga->htotal) {
|
||||
svga->hblankend &= (svga->hblank_end_len - 1);
|
||||
svga->hblank_sub = svga->hblankend + svga->hblank_overscan;
|
||||
|
||||
svga->hdisp -= (svga->hblank_sub * svga->dots_per_clock);
|
||||
}
|
||||
|
||||
if (svga->hdisp >= 2048)
|
||||
svga->monitor->mon_overscan_x = 0;
|
||||
|
||||
@@ -640,6 +690,43 @@ svga_recalctimings(svga_t *svga)
|
||||
|
||||
crtcconst = svga->clock * svga->char_width;
|
||||
|
||||
#ifdef ENABLE_SVGA_LOG
|
||||
vsyncend = (svga->vsyncstart & 0xfffffff0) | (svga->crtc[0x11] & 0x0f);
|
||||
if (vsyncend <= svga->vsyncstart)
|
||||
vsyncend += 0x00000010;
|
||||
vblankend = (svga->vblankstart & 0xffffff80) | (svga->crtc[0x16] & 0x7f);
|
||||
if (vblankend <= svga->vblankstart)
|
||||
vblankend += 0x00000080;
|
||||
|
||||
hdispstart = ((svga->crtc[3] >> 5) & 3);
|
||||
hdispend = svga->crtc[1] + 1;
|
||||
hsyncstart = svga->crtc[4] + ((svga->crtc[5] >> 5) & 3) + 1;
|
||||
hsyncend = (hsyncstart & 0xffffffe0) | (svga->crtc[5] & 0x1f);
|
||||
if (hsyncend <= hsyncstart)
|
||||
hsyncend += 0x00000020;
|
||||
#endif
|
||||
|
||||
svga_log("Last scanline in the vertical period: %i\n"
|
||||
"First scanline after the last of active display: %i\n"
|
||||
"First scanline with vertical retrace asserted: %i\n"
|
||||
"First scanline after the last with vertical retrace asserted: %i\n"
|
||||
"First scanline of blanking: %i\n"
|
||||
"First scanline after the last of blanking: %i\n"
|
||||
"\n"
|
||||
"Last character in the horizontal period: %i\n"
|
||||
"First character of active display: %i\n"
|
||||
"First character after the last of active display: %i\n"
|
||||
"First character with horizontal retrace asserted: %i\n"
|
||||
"First character after the last with horizontal retrace asserted: %i\n"
|
||||
"First character of blanking: %i\n"
|
||||
"First character after the last of blanking: %i\n"
|
||||
"\n"
|
||||
"\n",
|
||||
svga->vtotal, svga->dispend, svga->vsyncstart, vsyncend,
|
||||
svga->vblankstart, vblankend,
|
||||
svga->htotal, hdispstart, hdispend, hsyncstart, hsyncend,
|
||||
svga->hblankstart, svga->hblankend);
|
||||
|
||||
if (ibm8514_on && !svga->dev8514.local) {
|
||||
disptime = svga->dev8514.h_total;
|
||||
_dispontime = svga->dev8514.h_disp;
|
||||
@@ -878,9 +965,9 @@ svga_poll(void *priv)
|
||||
|
||||
if (ret) {
|
||||
if (svga->interlace && svga->oddeven)
|
||||
svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[5] & 0x60) >> 5);
|
||||
svga->ma = svga->maback = (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
|
||||
else
|
||||
svga->ma = svga->maback = ((svga->crtc[5] & 0x60) >> 5);
|
||||
svga->ma = svga->maback = ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
|
||||
svga->ma = (svga->ma << 2);
|
||||
svga->maback = (svga->maback << 2);
|
||||
|
||||
@@ -951,9 +1038,9 @@ svga_poll(void *priv)
|
||||
|
||||
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);
|
||||
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1) + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
|
||||
else
|
||||
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5);
|
||||
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[3] & 0x60) >> 5) + svga->hblank_sub;
|
||||
} else if (dev->local && ibm8514_on) {
|
||||
if (svga->interlace && svga->oddeven)
|
||||
svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1);
|
||||
@@ -968,6 +1055,9 @@ svga_poll(void *priv)
|
||||
if (svga->vsync_callback)
|
||||
svga->vsync_callback(svga);
|
||||
}
|
||||
#if 0
|
||||
if (svga->vc == lines_num) {
|
||||
#endif
|
||||
if (svga->vc == svga->vtotal) {
|
||||
svga->vc = 0;
|
||||
svga->sc = 0;
|
||||
@@ -1090,7 +1180,8 @@ svga_init(const device_t *info, svga_t *svga, void *priv, int memsize,
|
||||
|
||||
svga->ramdac_type = RAMDAC_6BIT;
|
||||
|
||||
svga->map8 = svga->pallook;
|
||||
svga->map8 = svga->pallook;
|
||||
svga->hblank_overscan = 1; /* Do at least 1 character of overscan after horizontal blanking. */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -70,9 +70,20 @@ svga_render_blank(svga_t *svga)
|
||||
break;
|
||||
}
|
||||
|
||||
#if 0
|
||||
pclog("svga->displine = %i, svga->y_add = %i, svga->x_add = %i\n", svga->displine, svga->y_add, svga->x_add);
|
||||
#endif
|
||||
uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add];
|
||||
#if 0
|
||||
pclog("svga->hdisp = %i, svga->scrollcache = %i, char_width = %i, sizeof(uint32_t) = %i\n", svga->hdisp, svga->scrollcache, char_width, sizeof(uint32_t));
|
||||
#endif
|
||||
uint32_t line_width = (uint32_t) (svga->hdisp + svga->scrollcache) * char_width * sizeof(uint32_t);
|
||||
memset(line_ptr, 0, line_width);
|
||||
|
||||
#if 0
|
||||
pclog("line_width = %i\n", line_width);
|
||||
#endif
|
||||
if ((svga->hdisp + svga->scrollcache) > 0)
|
||||
memset(line_ptr, 0, line_width);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -81,7 +92,7 @@ svga_render_overscan_left(svga_t *svga)
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->scrblank || (svga->hdisp == 0))
|
||||
if (svga->scrblank || (svga->hdisp <= 0))
|
||||
return;
|
||||
|
||||
uint32_t *line_ptr = svga->monitor->target_buffer->line[svga->displine + svga->y_add];
|
||||
@@ -97,7 +108,7 @@ svga_render_overscan_right(svga_t *svga)
|
||||
if ((svga->displine + svga->y_add) < 0)
|
||||
return;
|
||||
|
||||
if (svga->scrblank || (svga->hdisp == 0))
|
||||
if (svga->scrblank || (svga->hdisp <= 0))
|
||||
return;
|
||||
|
||||
uint32_t *line_ptr = &svga->monitor->target_buffer->line[svga->displine + svga->y_add][svga->x_add + svga->hdisp];
|
||||
|
||||
@@ -148,6 +148,7 @@ video_cards[] = {
|
||||
{ &et4000k_isa_device },
|
||||
{ &et2000_device },
|
||||
{ &et3000_isa_device },
|
||||
{ &et4000_tc6058af_isa_device },
|
||||
{ &et4000_isa_device },
|
||||
{ &et4000w32_device },
|
||||
{ &et4000w32i_isa_device },
|
||||
|
||||
Reference in New Issue
Block a user