Skip to content

Commit 2afbe3b

Browse files
authored
Merge pull request 86Box#4022 from 86Box/feature/svga-hskew
Merge feature/svga hskew into master.
2 parents 23039a3 + 553e58f commit 2afbe3b

15 files changed

+393
-42
lines changed

src/include/86box/vid_svga.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ typedef struct svga_t {
274274
/* Enable LUT mapping of >= 24 bpp modes. */
275275
int lut_map;
276276

277+
/* Override the horizontal blanking stuff. */
278+
int hoverride;
279+
277280
/* Return a 32 bpp color from a 15/16 bpp color. */
278281
uint32_t (*conv_16to32)(struct svga_t *svga, uint16_t color, uint8_t bpp);
279282

src/video/vid_ati28800.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ ati28800_out(uint16_t addr, uint8_t val, void *priv)
136136
if ((old ^ val) & 0x80)
137137
svga_recalctimings(svga);
138138
break;
139+
case 0xad:
140+
if ((old ^ val) & 0x0c)
141+
svga_recalctimings(svga);
142+
break;
139143
case 0xb0:
140144
if ((old ^ val) & 0x60)
141145
svga_recalctimings(svga);
@@ -403,7 +407,8 @@ ati28800_recalctimings(svga_t *svga)
403407
ati28800_t *ati28800 = (ati28800_t *) svga->priv;
404408
int clock_sel;
405409

406-
clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) | ((ati28800->regs[0xb9] & 2) << 1);
410+
clock_sel = ((svga->miscout >> 2) & 3) | ((ati28800->regs[0xbe] & 0x10) >> 1) |
411+
((ati28800->regs[0xb9] & 2) << 1);
407412

408413
if (ati28800->regs[0xa3] & 0x10)
409414
svga->ma_latch |= 0x10000;
@@ -443,7 +448,11 @@ ati28800_recalctimings(svga_t *svga)
443448
if (!svga->scrblank && (svga->crtc[0x17] & 0x80) && svga->attr_palette_enable) {
444449
if ((svga->gdcreg[6] & 1) || (svga->attrregs[0x10] & 1)) {
445450
svga->clock = (cpuclock * (double) (1ULL << 32)) / svga->getclock(clock_sel, svga->clock_gen);
446-
ati28800_log("SEQREG1 bit 3=%x. gdcreg5 bits 5-6=%02x, 4bit pel=%02x, planar 16color=%02x, apa mode=%02x, attregs10 bit 7=%02x.\n", svga->seqregs[1] & 8, svga->gdcreg[5] & 0x60, ati28800->regs[0xb3] & 0x40, ati28800->regs[0xac] & 0x40, ati28800->regs[0xb6] & 0x18, ati28800->svga.attrregs[0x10] & 0x80);
451+
ati28800_log("SEQREG1 bit 3=%x. gdcreg5 bits 5-6=%02x, 4bit pel=%02x, "
452+
"planar 16color=%02x, apa mode=%02x, attregs10 bit 7=%02x.\n",
453+
svga->seqregs[1] & 8, svga->gdcreg[5] & 0x60,
454+
ati28800->regs[0xb3] & 0x40, ati28800->regs[0xac] & 0x40,
455+
ati28800->regs[0xb6] & 0x18, ati28800->svga.attrregs[0x10] & 0x80);
447456
switch (svga->gdcreg[5] & 0x60) {
448457
case 0x00:
449458
if (svga->seqregs[1] & 8) /*Low res (320)*/
@@ -492,6 +501,9 @@ ati28800_recalctimings(svga_t *svga)
492501
}
493502
}
494503
}
504+
505+
if (ati28800->regs[0xad] & 0x08)
506+
svga->hblankstart = ((ati28800->regs[0x0d] >> 2) << 8) + svga->crtc[4] + 1;
495507
}
496508

497509
static void

src/video/vid_ati_mach64.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,7 @@ mach64_recalctimings(svga_t *svga)
510510
const mach64_t *mach64 = (mach64_t *) svga->priv;
511511

512512
if (((mach64->crtc_gen_cntl >> 24) & 3) == 3) {
513+
svga->hoverride = 1;
513514
svga->vtotal = (mach64->crtc_v_total_disp & 2047) + 1;
514515
svga->dispend = ((mach64->crtc_v_total_disp >> 16) & 2047) + 1;
515516
svga->htotal = (mach64->crtc_h_total_disp & 255) + 1;
@@ -566,6 +567,7 @@ mach64_recalctimings(svga_t *svga)
566567

567568
svga->vram_display_mask = mach64->vram_mask;
568569
} else {
570+
svga->hoverride = 0;
569571
svga->vram_display_mask = (mach64->regs[0x36] & 0x01) ? mach64->vram_mask : 0x3ffff;
570572
}
571573
}

src/video/vid_ati_mach8.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2841,6 +2841,9 @@ mach_recalctimings(svga_t *svga)
28412841
}
28422842
}
28432843
}
2844+
2845+
if (mach->regs[0xad] & 0x08)
2846+
svga->hblankstart = ((mach->regs[0x0d] >> 2) << 8) + svga->crtc[4] + 1;
28442847
}
28452848

28462849
static void

src/video/vid_cl54xx.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,28 @@ gd54xx_recalctimings(svga_t *svga)
19421942

19431943
svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd54xx->vram_mask : 0x3ffff;
19441944

1945+
if (svga->crtc[0x27] >= CIRRUS_ID_CLGD5430)
1946+
svga->htotal += ((svga->crtc[0x1c] >> 3) & 0x07);
1947+
1948+
if (svga->crtc[0x1b] & ((svga->crtc[0x27] >= CIRRUS_ID_CLGD5424) ? 0xa0 : 0x20)) {
1949+
/* Special blanking mode: the blank start and end become components of the window generator,
1950+
and the actual blanking comes from the display enable signal. */
1951+
/* Start blanking at the first character clock after the last active one. */
1952+
svga->hblankstart = svga->crtc[1] + 1;
1953+
svga->hblank_end_val = (svga->htotal + 5) & 0xff;
1954+
/* In this mode, the dots per clock are always 8 or 16, never 9 or 18. */
1955+
if (!svga->scrblank && svga->attr_palette_enable)
1956+
svga->dots_per_clock = (svga->seqregs[1] & 8) ? 16 : 8;
1957+
/* No overscan in this mode. */
1958+
svga->hblank_overscan = 0;
1959+
/* Also make sure vertical blanking starts on display end. */
1960+
svga->vblankstart = svga->dispend;
1961+
1962+
/* Account for horizontal overflow bits. */
1963+
svga->hblank_end_val += (svga->crtc[0x1a] & 0x30) << 2;
1964+
svga->hblank_end_len = 0x100;
1965+
}
1966+
19451967
if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) { /*Text mode*/
19461968
if (svga->seqregs[1] & 8) {
19471969
svga->render = svga_render_text_40;

src/video/vid_et4000.c

Lines changed: 129 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,19 @@
5555
#include <86box/plat_fallthrough.h>
5656
#include <86box/plat_unused.h>
5757

58+
#define ET4000_TYPE_TC6058AF 0 /* ISA ET4000AX (TC6058AF) */
5859
#define ET4000_TYPE_ISA 1 /* ISA ET4000AX */
5960
#define ET4000_TYPE_MCA 2 /* MCA ET4000AX */
6061
#define ET4000_TYPE_KOREAN 3 /* Korean ET4000 */
6162
#define ET4000_TYPE_TRIGEM 4 /* Trigem 286M ET4000 */
6263
#define ET4000_TYPE_KASAN 5 /* Kasan ET4000 */
6364

64-
#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN"
65-
#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin"
66-
#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom"
67-
#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin"
68-
#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom"
65+
#define BIOS_ROM_PATH "roms/video/et4000/ET4000.BIN"
66+
#define TC6058AF_BIOS_ROM_PATH "roms/video/et4000/Tseng_Labs_VGA-4000_BIOS_V1.1.bin"
67+
#define KOREAN_BIOS_ROM_PATH "roms/video/et4000/tgkorvga.bin"
68+
#define KOREAN_FONT_ROM_PATH "roms/video/et4000/tg_ksc5601.rom"
69+
#define KASAN_BIOS_ROM_PATH "roms/video/et4000/et4000_kasan16.bin"
70+
#define KASAN_FONT_ROM_PATH "roms/video/et4000/kasan_ksc5601.rom"
6971

7072
typedef struct {
7173
const char *name;
@@ -115,6 +117,7 @@ et4000_in(uint16_t addr, void *priv)
115117
{
116118
et4000_t *dev = (et4000_t *) priv;
117119
svga_t *svga = &dev->svga;
120+
uint8_t ret;
118121

119122
if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
120123
addr ^= 0x60;
@@ -138,7 +141,8 @@ et4000_in(uint16_t addr, void *priv)
138141
case 0x3c7:
139142
case 0x3c8:
140143
case 0x3c9:
141-
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
144+
if (dev->type >= ET4000_TYPE_ISA)
145+
return sc1502x_ramdac_in(addr, svga->ramdac, svga);
142146

143147
case 0x3cd: /*Banking*/
144148
return dev->banking;
@@ -149,6 +153,26 @@ et4000_in(uint16_t addr, void *priv)
149153
case 0x3d5:
150154
return svga->crtc[svga->crtcreg];
151155

156+
case 0x3da:
157+
svga->attrff = 0;
158+
159+
if (svga->cgastat & 0x01)
160+
svga->cgastat &= ~0x30;
161+
else
162+
svga->cgastat ^= 0x30;
163+
164+
ret = svga->cgastat;
165+
166+
if ((svga->fcr & 0x08) && svga->dispon)
167+
ret |= 0x08;
168+
169+
if (ret & 0x08)
170+
ret &= 0x7f;
171+
else
172+
ret |= 0x80;
173+
174+
return ret;
175+
152176
default:
153177
break;
154178
}
@@ -225,12 +249,33 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
225249
addr ^= 0x60;
226250

227251
switch (addr) {
252+
case 0x3c5:
253+
if (svga->seqaddr == 4) {
254+
svga->seqregs[4] = val;
255+
256+
svga->chain2_write = !(val & 4);
257+
svga->chain4 = (svga->chain4 & ~8) | (val & 8);
258+
svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4 && !(svga->adv_flags & FLAG_ADDR_BY8);
259+
return;
260+
} else if (svga->seqaddr == 0x0e) {
261+
svga->seqregs[0x0e] = val;
262+
svga->chain4 &= ~0x02;
263+
if (svga->gdcreg[5] & 0x40)
264+
svga->chain4 |= (svga->seqregs[0x0e] & 0x02);
265+
svga_recalctimings(svga);
266+
return;
267+
}
268+
break;
269+
228270
case 0x3c6:
229271
case 0x3c7:
230272
case 0x3c8:
231273
case 0x3c9:
232-
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
233-
return;
274+
if (dev->type >= ET4000_TYPE_ISA) {
275+
sc1502x_ramdac_out(addr, val, svga->ramdac, svga);
276+
return;
277+
}
278+
break;
234279

235280
case 0x3cd: /*Banking*/
236281
if (!(svga->crtc[0x36] & 0x10) && !(svga->gdcreg[6] & 0x08)) {
@@ -241,7 +286,11 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
241286
return;
242287

243288
case 0x3cf:
244-
if ((svga->gdcaddr & 15) == 6) {
289+
if ((svga->gdcaddr & 15) == 5) {
290+
svga->chain4 &= ~0x02;
291+
if (val & 0x40)
292+
svga->chain4 |= (svga->seqregs[0x0e] & 0x02);
293+
} else if ((svga->gdcaddr & 15) == 6) {
245294
if (!(svga->crtc[0x36] & 0x10) && !(val & 0x08)) {
246295
svga->write_bank = (dev->banking & 0x0f) * 0x10000;
247296
svga->read_bank = ((dev->banking >> 4) & 0x0f) * 0x10000;
@@ -418,7 +467,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv)
418467
break;
419468
case 1:
420469
case 2:
421-
et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
470+
if ((et4000->kasan_cfg_index - 0xF0) <= 16)
471+
et4000->kasan_cfg_regs[et4000->kasan_cfg_index - 0xF0] = val;
422472
io_removehandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
423473
et4000->kasan_access_addr = (et4000->kasan_cfg_regs[2] << 8) | et4000->kasan_cfg_regs[1];
424474
io_sethandler(et4000->kasan_access_addr, 0x0008, et4000_kasan_in, NULL, NULL, et4000_kasan_out, NULL, NULL, et4000);
@@ -463,7 +513,8 @@ et4000_kasan_out(uint16_t addr, uint8_t val, void *priv)
463513
case 4:
464514
case 5:
465515
if (et4000->kasan_cfg_regs[0] & 1) {
466-
et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
516+
if ((addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)) <= 4)
517+
et4000->kasan_font_data[addr - (((et4000->kasan_cfg_regs[2] << 8) | (et4000->kasan_cfg_regs[1])) + 3)] = val;
467518
}
468519
break;
469520
case 6:
@@ -562,6 +613,8 @@ et4000_recalctimings(svga_t *svga)
562613
svga->rowoffset = 0x100;
563614
if (svga->crtc[0x3f] & 1)
564615
svga->htotal += 256;
616+
if (svga->crtc[0x3f] & 0x04)
617+
svga->hblankstart += 0x100;
565618
if (svga->attrregs[0x16] & 0x20)
566619
svga->hdisp <<= 1;
567620

@@ -606,6 +659,19 @@ et4000_recalctimings(svga_t *svga)
606659
}
607660
}
608661

662+
if ((svga->seqregs[0x0e] & 0x02) && ((svga->gdcreg[5] & 0x60) >= 0x40)) {
663+
svga->ma_latch <<= (1 << 0);
664+
svga->rowoffset <<= (1 << 0);
665+
svga->render = svga_render_8bpp_highres;
666+
}
667+
668+
if (dev->type == ET4000_TYPE_TC6058AF) {
669+
if (svga->render == svga_render_8bpp_lowres)
670+
svga->render = svga_render_8bpp_tseng_lowres;
671+
else if (svga->render == svga_render_8bpp_highres)
672+
svga->render = svga_render_8bpp_tseng_highres;
673+
}
674+
609675
if ((svga->bpp == 8) && ((svga->gdcreg[5] & 0x60) >= 0x40)) {
610676
svga->map8 = svga->pallook;
611677
if (svga->lowres)
@@ -672,6 +738,7 @@ et4000_init(const device_t *info)
672738
fn = BIOS_ROM_PATH;
673739

674740
switch (dev->type) {
741+
case ET4000_TYPE_TC6058AF: /* ISA ET4000AX (TC6058AF) */
675742
case ET4000_TYPE_ISA: /* ISA ET4000AX */
676743
dev->vram_size = device_get_config_int("memory") << 10;
677744
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_et4000_isa);
@@ -680,6 +747,8 @@ et4000_init(const device_t *info)
680747
NULL, NULL);
681748
io_sethandler(0x03c0, 32,
682749
et4000_in, NULL, NULL, et4000_out, NULL, NULL, dev);
750+
if (dev->type == ET4000_TYPE_TC6058AF)
751+
fn = TC6058AF_BIOS_ROM_PATH;
683752
break;
684753

685754
case ET4000_TYPE_MCA: /* MCA ET4000AX */
@@ -759,7 +828,8 @@ et4000_init(const device_t *info)
759828
break;
760829
}
761830

762-
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
831+
if (dev->type >= ET4000_TYPE_ISA)
832+
dev->svga.ramdac = device_add(&sc1502x_ramdac_device);
763833

764834
dev->vram_mask = dev->vram_size - 1;
765835

@@ -799,6 +869,12 @@ et4000_force_redraw(void *priv)
799869
dev->svga.fullchange = changeframecount;
800870
}
801871

872+
static int
873+
et4000_tc6058af_available(void)
874+
{
875+
return rom_present(TC6058AF_BIOS_ROM_PATH);
876+
}
877+
802878
static int
803879
et4000_available(void)
804880
{
@@ -817,6 +893,33 @@ et4000_kasan_available(void)
817893
return rom_present(KASAN_BIOS_ROM_PATH) && rom_present(KASAN_FONT_ROM_PATH);
818894
}
819895

896+
static const device_config_t et4000_tc6058af_config[] = {
897+
// clang-format off
898+
{
899+
.name = "memory",
900+
.description = "Memory size",
901+
.type = CONFIG_SELECTION,
902+
.default_int = 512,
903+
.selection = {
904+
{
905+
.description = "256 KB",
906+
.value = 256
907+
},
908+
{
909+
.description = "512 KB",
910+
.value = 512
911+
},
912+
{
913+
.description = ""
914+
}
915+
}
916+
},
917+
{
918+
.type = CONFIG_END
919+
}
920+
// clang-format on
921+
};
922+
820923
static const device_config_t et4000_config[] = {
821924
// clang-format off
822925
{
@@ -848,6 +951,20 @@ static const device_config_t et4000_config[] = {
848951
// clang-format on
849952
};
850953

954+
const device_t et4000_tc6058af_isa_device = {
955+
.name = "Tseng Labs ET4000AX (TC6058AF) (ISA)",
956+
.internal_name = "et4000ax_tc6058af",
957+
.flags = DEVICE_ISA,
958+
.local = 0,
959+
.init = et4000_init,
960+
.close = et4000_close,
961+
.reset = NULL,
962+
{ .available = et4000_tc6058af_available },
963+
.speed_changed = et4000_speed_changed,
964+
.force_redraw = et4000_force_redraw,
965+
.config = et4000_tc6058af_config
966+
};
967+
851968
const device_t et4000_isa_device = {
852969
.name = "Tseng Labs ET4000AX (ISA)",
853970
.internal_name = "et4000ax",

0 commit comments

Comments
 (0)