2017-10-11 05:40:44 -04:00
|
|
|
/*
|
2023-01-06 15:36:05 -05:00
|
|
|
* 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.
|
2017-10-11 05:40:44 -04:00
|
|
|
*
|
2023-01-06 15:36:05 -05:00
|
|
|
* This file is part of the 86Box distribution.
|
2017-10-11 05:40:44 -04:00
|
|
|
*
|
2023-01-06 15:36:05 -05:00
|
|
|
* Hercules Plus emulation.
|
2017-10-11 05:40:44 -04:00
|
|
|
*
|
2020-03-25 00:46:02 +02:00
|
|
|
*
|
2017-10-11 05:40:44 -04:00
|
|
|
*
|
2023-01-06 15:36:29 -05:00
|
|
|
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
|
2023-01-06 15:36:05 -05:00
|
|
|
* Miran Grca, <mgrca8@gmail.com>
|
2017-10-11 05:40:44 -04:00
|
|
|
*
|
2023-01-06 15:36:05 -05:00
|
|
|
* Copyright 2008-2018 Sarah Walker.
|
|
|
|
|
* Copyright 2016-2018 Miran Grca.
|
2017-10-11 05:40:44 -04:00
|
|
|
*/
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdint.h>
|
2016-11-16 15:37:07 -06:00
|
|
|
#include <stdlib.h>
|
2018-10-10 22:21:55 +02:00
|
|
|
#include <string.h>
|
2017-09-25 04:31:20 -04:00
|
|
|
#include <wchar.h>
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/86box.h>
|
|
|
|
|
#include <86box/io.h>
|
|
|
|
|
#include <86box/lpt.h>
|
|
|
|
|
#include <86box/timer.h>
|
|
|
|
|
#include <86box/pit.h>
|
|
|
|
|
#include <86box/mem.h>
|
|
|
|
|
#include <86box/rom.h>
|
|
|
|
|
#include <86box/device.h>
|
|
|
|
|
#include <86box/video.h>
|
2016-11-16 15:37:07 -06:00
|
|
|
|
|
|
|
|
/* extended CRTC registers */
|
2022-08-31 19:19:29 -04:00
|
|
|
#define HERCULESPLUS_CRTC_XMODE 20 /* xMode register */
|
|
|
|
|
#define HERCULESPLUS_CRTC_UNDER 21 /* Underline */
|
|
|
|
|
#define HERCULESPLUS_CRTC_OVER 22 /* Overstrike */
|
2016-11-16 15:37:07 -06:00
|
|
|
|
|
|
|
|
/* character width */
|
2022-08-31 19:19:29 -04:00
|
|
|
#define HERCULESPLUS_CW ((dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL) ? 8 : 9)
|
2016-11-16 15:37:07 -06:00
|
|
|
|
|
|
|
|
/* mode control register */
|
2022-08-31 19:19:29 -04:00
|
|
|
#define HERCULESPLUS_CTRL_GRAPH 0x02
|
|
|
|
|
#define HERCULESPLUS_CTRL_ENABLE 0x08
|
|
|
|
|
#define HERCULESPLUS_CTRL_BLINK 0x20
|
|
|
|
|
#define HERCULESPLUS_CTRL_PAGE1 0x80
|
2016-11-16 15:37:07 -06:00
|
|
|
|
|
|
|
|
/* CRTC status register */
|
2022-08-31 19:19:29 -04:00
|
|
|
#define HERCULESPLUS_STATUS_HSYNC 0x01 /* horizontal sync */
|
2016-11-16 15:37:07 -06:00
|
|
|
#define HERCULESPLUS_STATUS_LIGHT 0x02
|
|
|
|
|
#define HERCULESPLUS_STATUS_VIDEO 0x08
|
2022-08-31 19:19:29 -04:00
|
|
|
#define HERCULESPLUS_STATUS_ID 0x10 /* Card identification */
|
|
|
|
|
#define HERCULESPLUS_STATUS_VSYNC 0x80 /* -vertical sync */
|
2016-11-16 15:37:07 -06:00
|
|
|
|
|
|
|
|
/* configuration switch register */
|
|
|
|
|
#define HERCULESPLUS_CTRL2_GRAPH 0x01
|
|
|
|
|
#define HERCULESPLUS_CTRL2_PAGE1 0x02
|
|
|
|
|
|
|
|
|
|
/* extended mode register */
|
|
|
|
|
#define HERCULESPLUS_XMODE_RAMFONT 0x01
|
|
|
|
|
#define HERCULESPLUS_XMODE_90COL 0x02
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
typedef struct {
|
2022-08-31 19:19:29 -04:00
|
|
|
mem_mapping_t mapping;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
uint8_t crtc[32];
|
|
|
|
|
int crtcreg;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
uint8_t ctrl, ctrl2, stat;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
uint64_t dispontime, dispofftime;
|
|
|
|
|
pc_timer_t timer;
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
int firstline, lastline;
|
2018-09-19 20:13:32 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
int linepos, displine;
|
|
|
|
|
int vc, sc;
|
|
|
|
|
uint16_t ma, maback;
|
|
|
|
|
int con, coff, cursoron;
|
|
|
|
|
int dispon, blink;
|
|
|
|
|
int vsynctime;
|
|
|
|
|
int vadj;
|
|
|
|
|
int monitor_index, prev_monitor_index;
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
int cols[256][2][2];
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
uint8_t *vram;
|
2016-11-16 15:37:07 -06:00
|
|
|
} herculesplus_t;
|
|
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
#define VIDEO_MONITOR_PROLOGUE() \
|
|
|
|
|
{ \
|
|
|
|
|
dev->prev_monitor_index = monitor_index_global; \
|
|
|
|
|
monitor_index_global = dev->monitor_index; \
|
|
|
|
|
}
|
|
|
|
|
#define VIDEO_MONITOR_EPILOGUE() \
|
|
|
|
|
{ \
|
|
|
|
|
monitor_index_global = dev->prev_monitor_index; \
|
|
|
|
|
}
|
2018-09-19 20:13:32 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
static video_timings_t timing_herculesplus = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
recalc_timings(herculesplus_t *dev)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2018-10-10 22:21:55 +02:00
|
|
|
double disptime;
|
|
|
|
|
double _dispontime, _dispofftime;
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
disptime = dev->crtc[0] + 1;
|
2018-10-10 22:21:55 +02:00
|
|
|
_dispontime = dev->crtc[1];
|
|
|
|
|
_dispofftime = disptime - _dispontime;
|
2022-08-31 19:19:29 -04:00
|
|
|
_dispontime *= HERCCONST;
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
_dispofftime *= HERCCONST;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
dev->dispontime = (uint64_t) (_dispontime);
|
|
|
|
|
dev->dispofftime = (uint64_t) (_dispofftime);
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
herculesplus_out(uint16_t port, uint8_t val, void *priv)
|
|
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_t *dev = (herculesplus_t *) priv;
|
|
|
|
|
uint8_t old;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
switch (port) {
|
2022-08-31 19:19:29 -04:00
|
|
|
case 0x3b0:
|
|
|
|
|
case 0x3b2:
|
|
|
|
|
case 0x3b4:
|
|
|
|
|
case 0x3b6:
|
|
|
|
|
dev->crtcreg = val & 31;
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 0x3b1:
|
|
|
|
|
case 0x3b3:
|
|
|
|
|
case 0x3b5:
|
|
|
|
|
case 0x3b7:
|
|
|
|
|
if (dev->crtcreg > 22)
|
|
|
|
|
return;
|
|
|
|
|
old = dev->crtc[dev->crtcreg];
|
|
|
|
|
dev->crtc[dev->crtcreg] = val;
|
|
|
|
|
if (dev->crtc[10] == 6 && dev->crtc[11] == 7) {
|
|
|
|
|
/*Fix for Generic Turbo XT BIOS,
|
|
|
|
|
*which sets up cursor registers wrong*/
|
|
|
|
|
dev->crtc[10] = 0xb;
|
|
|
|
|
dev->crtc[11] = 0xc;
|
|
|
|
|
}
|
|
|
|
|
if (old ^ val)
|
|
|
|
|
recalc_timings(dev);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 0x3b8:
|
|
|
|
|
old = dev->ctrl;
|
|
|
|
|
dev->ctrl = val;
|
|
|
|
|
if (old ^ val)
|
|
|
|
|
recalc_timings(dev);
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
case 0x3bf:
|
|
|
|
|
dev->ctrl2 = val;
|
|
|
|
|
if (val & 2)
|
|
|
|
|
mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x10000);
|
|
|
|
|
else
|
|
|
|
|
mem_mapping_set_addr(&dev->mapping, 0xb0000, 0x08000);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static uint8_t
|
|
|
|
|
herculesplus_in(uint16_t port, void *priv)
|
|
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_t *dev = (herculesplus_t *) priv;
|
|
|
|
|
uint8_t ret = 0xff;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
switch (port) {
|
2022-08-31 19:19:29 -04:00
|
|
|
case 0x3b0:
|
|
|
|
|
case 0x3b2:
|
|
|
|
|
case 0x3b4:
|
|
|
|
|
case 0x3b6:
|
|
|
|
|
ret = dev->crtcreg;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x3b1:
|
|
|
|
|
case 0x3b3:
|
|
|
|
|
case 0x3b5:
|
|
|
|
|
case 0x3b7:
|
|
|
|
|
if (dev->crtcreg <= 22)
|
|
|
|
|
ret = dev->crtc[dev->crtcreg];
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 0x3ba:
|
|
|
|
|
/* 0x10: Hercules Plus card identity */
|
|
|
|
|
ret = (dev->stat & 0xf) | ((dev->stat & 8) << 4) | 0x10;
|
|
|
|
|
break;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
return ret;
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
herculesplus_write(uint32_t addr, uint8_t val, void *priv)
|
|
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_t *dev = (herculesplus_t *) priv;
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
dev->vram[addr & 0xffff] = val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
|
herculesplus_read(uint32_t addr, void *priv)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_t *dev = (herculesplus_t *) priv;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
return dev->vram[addr & 0xffff];
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
draw_char_rom(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
unsigned ull, val, ifg, ibg;
|
2018-10-10 22:21:55 +02:00
|
|
|
const uint8_t *fnt;
|
2022-08-31 19:19:29 -04:00
|
|
|
int i, elg, blk;
|
|
|
|
|
int cw = HERCULESPLUS_CW;
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
blk = 0;
|
|
|
|
|
if (dev->ctrl & HERCULESPLUS_CTRL_BLINK) {
|
2022-08-31 19:19:29 -04:00
|
|
|
if (attr & 0x80)
|
|
|
|
|
blk = (dev->blink & 16);
|
|
|
|
|
attr &= 0x7f;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* MDA-compatible attributes */
|
|
|
|
|
ibg = 0;
|
|
|
|
|
ifg = 7;
|
2022-08-31 19:19:29 -04:00
|
|
|
if ((attr & 0x77) == 0x70) { /* Invert */
|
|
|
|
|
ifg = 0;
|
|
|
|
|
ibg = 7;
|
2022-02-20 02:26:27 -05:00
|
|
|
}
|
|
|
|
|
if (attr & 8)
|
2022-08-31 19:19:29 -04:00
|
|
|
ifg |= 8; /* High intensity FG */
|
2022-02-20 02:26:27 -05:00
|
|
|
if (attr & 0x80)
|
2022-08-31 19:19:29 -04:00
|
|
|
ibg |= 8; /* High intensity BG */
|
|
|
|
|
if ((attr & 0x77) == 0) /* Blank */
|
|
|
|
|
ifg = ibg;
|
2018-10-10 22:21:55 +02:00
|
|
|
ull = ((attr & 0x07) == 1) ? 13 : 0xffff;
|
|
|
|
|
|
2022-02-20 02:26:27 -05:00
|
|
|
if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL)
|
2022-08-31 19:19:29 -04:00
|
|
|
elg = 0;
|
|
|
|
|
else
|
|
|
|
|
elg = ((chr >= 0xc0) && (chr <= 0xdf));
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
fnt = &(fontdatm[chr][dev->sc]);
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
if (blk) {
|
2022-08-31 19:19:29 -04:00
|
|
|
val = 0x000; /* Blinking, draw all background */
|
|
|
|
|
} else if (dev->sc == ull) {
|
|
|
|
|
val = 0x1ff; /* Underscore, draw all foreground */
|
2018-10-10 22:21:55 +02:00
|
|
|
} else {
|
2022-08-31 19:19:29 -04:00
|
|
|
val = fnt[0] << 1;
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
if (elg)
|
|
|
|
|
val |= (val >> 1) & 1;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < cw; i++) {
|
2022-08-31 19:19:29 -04:00
|
|
|
buffer32->line[dev->displine][x * cw + i] = (val & 0x100) ? ifg : ibg;
|
|
|
|
|
val = val << 1;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
draw_char_ram4(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
unsigned ull, val, ibg, cfg;
|
2018-10-10 22:21:55 +02:00
|
|
|
const uint8_t *fnt;
|
2022-08-31 19:19:29 -04:00
|
|
|
int i, elg, blk;
|
|
|
|
|
int cw = HERCULESPLUS_CW;
|
|
|
|
|
int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
blk = 0;
|
|
|
|
|
if (blink) {
|
2022-08-31 19:19:29 -04:00
|
|
|
if (attr & 0x80)
|
|
|
|
|
blk = (dev->blink & 16);
|
|
|
|
|
attr &= 0x7f;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* MDA-compatible attributes */
|
|
|
|
|
ibg = 0;
|
2022-08-31 19:19:29 -04:00
|
|
|
if ((attr & 0x77) == 0x70) { /* Invert */
|
|
|
|
|
ibg = 7;
|
2022-02-20 02:26:27 -05:00
|
|
|
}
|
|
|
|
|
if (attr & 8)
|
2022-08-31 19:19:29 -04:00
|
|
|
if (attr & 0x80)
|
|
|
|
|
ibg |= 8; /* High intensity BG */
|
|
|
|
|
if ((attr & 0x77) == 0) /* Blank */
|
|
|
|
|
ull = ((attr & 0x07) == 1) ? 13 : 0xffff;
|
2022-02-20 02:26:27 -05:00
|
|
|
if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL)
|
2022-08-31 19:19:29 -04:00
|
|
|
elg = 0;
|
2022-02-20 02:26:27 -05:00
|
|
|
else
|
2022-08-31 19:19:29 -04:00
|
|
|
elg = ((chr >= 0xc0) && (chr <= 0xdf));
|
2018-10-10 22:21:55 +02:00
|
|
|
fnt = dev->vram + 0x4000 + 16 * chr + dev->sc;
|
|
|
|
|
|
|
|
|
|
if (blk) {
|
2022-08-31 19:19:29 -04:00
|
|
|
/* Blinking, draw all background */
|
|
|
|
|
val = 0x000;
|
2018-10-10 22:21:55 +02:00
|
|
|
} else if (dev->sc == ull) {
|
2022-08-31 19:19:29 -04:00
|
|
|
/* Underscore, draw all foreground */
|
|
|
|
|
val = 0x1ff;
|
2018-10-10 22:21:55 +02:00
|
|
|
} else {
|
2022-08-31 19:19:29 -04:00
|
|
|
val = fnt[0x00000] << 1;
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
if (elg)
|
|
|
|
|
val |= (val >> 1) & 1;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
for (i = 0; i < cw; i++) {
|
2022-08-31 19:19:29 -04:00
|
|
|
/* Generate pixel colour */
|
|
|
|
|
cfg = 0;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
/* cfg = colour of foreground pixels */
|
|
|
|
|
if ((attr & 0x77) == 0)
|
|
|
|
|
cfg = ibg; /* 'blank' attribute */
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
buffer32->line[dev->displine][x * cw + i] = dev->cols[attr][blink][cfg];
|
|
|
|
|
val = val << 1;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
draw_char_ram48(herculesplus_t *dev, int x, uint8_t chr, uint8_t attr)
|
|
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
int i, elg, blk, ul, ol, bld;
|
|
|
|
|
unsigned ull, oll, ulc = 0, olc = 0;
|
|
|
|
|
unsigned val, ibg, cfg;
|
2018-10-10 22:21:55 +02:00
|
|
|
const unsigned char *fnt;
|
2022-08-31 19:19:29 -04:00
|
|
|
int cw = HERCULESPLUS_CW;
|
|
|
|
|
int blink = dev->ctrl & HERCULESPLUS_CTRL_BLINK;
|
|
|
|
|
int font = (attr & 0x0F);
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
if (font >= 12)
|
|
|
|
|
font &= 7;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
blk = 0;
|
|
|
|
|
if (blink) {
|
2022-08-31 19:19:29 -04:00
|
|
|
if (attr & 0x40)
|
|
|
|
|
blk = (dev->blink & 16);
|
|
|
|
|
attr &= 0x7f;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* MDA-compatible attributes */
|
|
|
|
|
if (blink) {
|
2022-08-31 19:19:29 -04:00
|
|
|
ibg = (attr & 0x80) ? 8 : 0;
|
|
|
|
|
bld = 0;
|
|
|
|
|
ol = (attr & 0x20) ? 1 : 0;
|
|
|
|
|
ul = (attr & 0x10) ? 1 : 0;
|
2018-10-10 22:21:55 +02:00
|
|
|
} else {
|
2022-08-31 19:19:29 -04:00
|
|
|
bld = (attr & 0x80) ? 1 : 0;
|
|
|
|
|
ibg = (attr & 0x40) ? 0x0F : 0;
|
|
|
|
|
ol = (attr & 0x20) ? 1 : 0;
|
|
|
|
|
ul = (attr & 0x10) ? 1 : 0;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-20 02:26:27 -05:00
|
|
|
if (ul) {
|
2022-08-31 19:19:29 -04:00
|
|
|
ull = dev->crtc[HERCULESPLUS_CRTC_UNDER] & 0x0F;
|
|
|
|
|
ulc = (dev->crtc[HERCULESPLUS_CRTC_UNDER] >> 4) & 0x0F;
|
|
|
|
|
if (ulc == 0)
|
|
|
|
|
ulc = 7;
|
2018-10-10 22:21:55 +02:00
|
|
|
} else {
|
2022-08-31 19:19:29 -04:00
|
|
|
ull = 0xFFFF;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-20 02:26:27 -05:00
|
|
|
if (ol) {
|
2022-08-31 19:19:29 -04:00
|
|
|
oll = dev->crtc[HERCULESPLUS_CRTC_OVER] & 0x0F;
|
|
|
|
|
olc = (dev->crtc[HERCULESPLUS_CRTC_OVER] >> 4) & 0x0F;
|
|
|
|
|
if (olc == 0)
|
|
|
|
|
olc = 7;
|
2018-10-10 22:21:55 +02:00
|
|
|
} else {
|
2022-08-31 19:19:29 -04:00
|
|
|
oll = 0xFFFF;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
2022-02-20 02:26:27 -05:00
|
|
|
if (dev->crtc[HERCULESPLUS_CRTC_XMODE] & HERCULESPLUS_XMODE_90COL)
|
2022-08-31 19:19:29 -04:00
|
|
|
elg = 0;
|
2022-02-20 02:26:27 -05:00
|
|
|
else
|
2022-08-31 19:19:29 -04:00
|
|
|
elg = ((chr >= 0xc0) && (chr <= 0xdf));
|
2018-10-10 22:21:55 +02:00
|
|
|
fnt = dev->vram + 0x4000 + 16 * chr + 4096 * font + dev->sc;
|
|
|
|
|
|
|
|
|
|
if (blk) { /* Blinking, draw all background */
|
2022-08-31 19:19:29 -04:00
|
|
|
val = 0x000;
|
2018-10-10 22:21:55 +02:00
|
|
|
} else if (dev->sc == ull) {
|
2022-08-31 19:19:29 -04:00
|
|
|
/* Underscore, draw all foreground */
|
|
|
|
|
val = 0x1ff;
|
2018-10-10 22:21:55 +02:00
|
|
|
} else {
|
2022-08-31 19:19:29 -04:00
|
|
|
val = fnt[0x00000] << 1;
|
2022-02-20 02:26:27 -05:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
if (elg)
|
|
|
|
|
val |= (val >> 1) & 1;
|
|
|
|
|
if (bld)
|
|
|
|
|
val |= (val >> 1);
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < cw; i++) {
|
2022-08-31 19:19:29 -04:00
|
|
|
/* Generate pixel colour */
|
|
|
|
|
cfg = val & 0x100;
|
|
|
|
|
if (dev->sc == oll)
|
|
|
|
|
cfg = olc ^ ibg; /* Strikethrough */
|
|
|
|
|
else if (dev->sc == ull)
|
|
|
|
|
cfg = ulc ^ ibg; /* Underline */
|
|
|
|
|
else
|
|
|
|
|
cfg |= ibg;
|
|
|
|
|
|
|
|
|
|
buffer32->line[dev->displine][(x * cw) + i] = dev->cols[attr][blink][cfg];
|
|
|
|
|
val = val << 1;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
text_line(herculesplus_t *dev, uint16_t ca)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
int drawcursor;
|
|
|
|
|
int x, c;
|
|
|
|
|
uint8_t chr, attr;
|
2018-10-10 22:21:55 +02:00
|
|
|
uint32_t col;
|
|
|
|
|
|
|
|
|
|
for (x = 0; x < dev->crtc[1]; x++) {
|
2022-08-31 19:19:29 -04:00
|
|
|
if (dev->ctrl & 8) {
|
|
|
|
|
chr = dev->vram[(dev->ma << 1) & 0xfff];
|
|
|
|
|
attr = dev->vram[((dev->ma << 1) + 1) & 0xfff];
|
|
|
|
|
} else
|
|
|
|
|
chr = attr = 0;
|
|
|
|
|
|
|
|
|
|
drawcursor = ((dev->ma == ca) && dev->con && dev->cursoron);
|
|
|
|
|
|
|
|
|
|
switch (dev->crtc[HERCULESPLUS_CRTC_XMODE] & 5) {
|
|
|
|
|
case 0:
|
|
|
|
|
case 4: /* ROM font */
|
|
|
|
|
draw_char_rom(dev, x, chr, attr);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 1: /* 4k RAMfont */
|
|
|
|
|
draw_char_ram4(dev, x, chr, attr);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 5: /* 48k RAMfont */
|
|
|
|
|
draw_char_ram48(dev, x, chr, attr);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++dev->ma;
|
|
|
|
|
|
|
|
|
|
if (drawcursor) {
|
|
|
|
|
int cw = HERCULESPLUS_CW;
|
|
|
|
|
|
|
|
|
|
col = dev->cols[attr][0][1];
|
|
|
|
|
for (c = 0; c < cw; c++)
|
|
|
|
|
buffer32->line[dev->displine][x * cw + c] = col;
|
|
|
|
|
}
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
graphics_line(herculesplus_t *dev)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2018-10-10 22:21:55 +02:00
|
|
|
uint16_t ca;
|
2022-08-31 19:19:29 -04:00
|
|
|
int x, c, plane = 0;
|
2018-10-10 22:21:55 +02:00
|
|
|
uint16_t val;
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
/* Graphics mode. */
|
|
|
|
|
ca = (dev->sc & 3) * 0x2000;
|
|
|
|
|
if ((dev->ctrl & HERCULESPLUS_CTRL_PAGE1) && (dev->ctrl2 & HERCULESPLUS_CTRL2_PAGE1))
|
2022-08-31 19:19:29 -04:00
|
|
|
ca += 0x8000;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
for (x = 0; x < dev->crtc[1]; x++) {
|
2022-08-31 19:19:29 -04:00
|
|
|
if (dev->ctrl & 8)
|
|
|
|
|
val = (dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane] << 8)
|
|
|
|
|
| dev->vram[((dev->ma << 1) & 0x1fff) + ca + 0x10000 * plane + 1];
|
|
|
|
|
else
|
|
|
|
|
val = 0;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
dev->ma++;
|
|
|
|
|
for (c = 0; c < 16; c++) {
|
|
|
|
|
buffer32->line[dev->displine][(x << 4) + c] = (val & 0x8000) ? 7 : 0;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
val <<= 1;
|
|
|
|
|
}
|
2018-10-28 08:26:07 +01:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
for (c = 0; c < 16; c += 8)
|
|
|
|
|
video_blend((x << 4) + c, dev->displine);
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
herculesplus_poll(void *priv)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_t *dev = (herculesplus_t *) priv;
|
|
|
|
|
uint16_t ca = (dev->crtc[15] | (dev->crtc[14] << 8)) & 0x3fff;
|
|
|
|
|
int x, oldvc, oldsc;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-07-07 14:34:59 +06:00
|
|
|
VIDEO_MONITOR_PROLOGUE();
|
2022-08-31 19:19:29 -04:00
|
|
|
if (!dev->linepos) {
|
|
|
|
|
timer_advance_u64(&dev->timer, dev->dispofftime);
|
|
|
|
|
dev->stat |= 1;
|
|
|
|
|
dev->linepos = 1;
|
|
|
|
|
oldsc = dev->sc;
|
|
|
|
|
if ((dev->crtc[8] & 3) == 3)
|
|
|
|
|
dev->sc = (dev->sc << 1) & 7;
|
|
|
|
|
if (dev->dispon) {
|
|
|
|
|
if (dev->displine < dev->firstline) {
|
|
|
|
|
dev->firstline = dev->displine;
|
|
|
|
|
video_wait_for_buffer();
|
|
|
|
|
}
|
|
|
|
|
dev->lastline = dev->displine;
|
|
|
|
|
if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH))
|
|
|
|
|
graphics_line(dev);
|
|
|
|
|
else
|
|
|
|
|
text_line(dev, ca);
|
2022-10-30 17:00:02 +01:00
|
|
|
|
|
|
|
|
if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH))
|
|
|
|
|
x = dev->crtc[1] << 4;
|
|
|
|
|
else
|
|
|
|
|
x = dev->crtc[1] * 9;
|
|
|
|
|
|
|
|
|
|
video_process_8(x, dev->displine);
|
2022-08-31 19:19:29 -04:00
|
|
|
}
|
|
|
|
|
dev->sc = oldsc;
|
|
|
|
|
if (dev->vc == dev->crtc[7] && !dev->sc)
|
|
|
|
|
dev->stat |= 8;
|
|
|
|
|
dev->displine++;
|
|
|
|
|
if (dev->displine >= 500)
|
|
|
|
|
dev->displine = 0;
|
2018-10-10 22:21:55 +02:00
|
|
|
} else {
|
2022-08-31 19:19:29 -04:00
|
|
|
timer_advance_u64(&dev->timer, dev->dispontime);
|
|
|
|
|
if (dev->dispon)
|
|
|
|
|
dev->stat &= ~1;
|
|
|
|
|
dev->linepos = 0;
|
|
|
|
|
if (dev->vsynctime) {
|
|
|
|
|
dev->vsynctime--;
|
|
|
|
|
if (!dev->vsynctime)
|
|
|
|
|
dev->stat &= ~8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dev->sc == (dev->crtc[11] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[11] & 31) >> 1))) {
|
|
|
|
|
dev->con = 0;
|
|
|
|
|
dev->coff = 1;
|
|
|
|
|
}
|
|
|
|
|
if (dev->vadj) {
|
|
|
|
|
dev->sc++;
|
|
|
|
|
dev->sc &= 31;
|
|
|
|
|
dev->ma = dev->maback;
|
|
|
|
|
dev->vadj--;
|
|
|
|
|
if (!dev->vadj) {
|
|
|
|
|
dev->dispon = 1;
|
|
|
|
|
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
|
|
|
|
|
dev->sc = 0;
|
|
|
|
|
}
|
|
|
|
|
} else if (dev->sc == dev->crtc[9] || ((dev->crtc[8] & 3) == 3 && dev->sc == (dev->crtc[9] >> 1))) {
|
|
|
|
|
dev->maback = dev->ma;
|
|
|
|
|
dev->sc = 0;
|
|
|
|
|
oldvc = dev->vc;
|
|
|
|
|
dev->vc++;
|
|
|
|
|
dev->vc &= 127;
|
|
|
|
|
if (dev->vc == dev->crtc[6])
|
|
|
|
|
dev->dispon = 0;
|
|
|
|
|
if (oldvc == dev->crtc[4]) {
|
|
|
|
|
dev->vc = 0;
|
|
|
|
|
dev->vadj = dev->crtc[5];
|
|
|
|
|
if (!dev->vadj)
|
|
|
|
|
dev->dispon = 1;
|
|
|
|
|
if (!dev->vadj)
|
|
|
|
|
dev->ma = dev->maback = (dev->crtc[13] | (dev->crtc[12] << 8)) & 0x3fff;
|
|
|
|
|
if ((dev->crtc[10] & 0x60) == 0x20)
|
|
|
|
|
dev->cursoron = 0;
|
|
|
|
|
else
|
|
|
|
|
dev->cursoron = dev->blink & 16;
|
|
|
|
|
}
|
|
|
|
|
if (dev->vc == dev->crtc[7]) {
|
|
|
|
|
dev->dispon = 0;
|
|
|
|
|
dev->displine = 0;
|
|
|
|
|
dev->vsynctime = 16;
|
|
|
|
|
if (dev->crtc[7]) {
|
|
|
|
|
if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH))
|
|
|
|
|
x = dev->crtc[1] << 4;
|
|
|
|
|
else
|
|
|
|
|
x = dev->crtc[1] * 9;
|
|
|
|
|
dev->lastline++;
|
|
|
|
|
if ((dev->ctrl & 8) && ((x != xsize) || ((dev->lastline - dev->firstline) != ysize) || video_force_resize_get())) {
|
|
|
|
|
xsize = x;
|
|
|
|
|
ysize = dev->lastline - dev->firstline;
|
|
|
|
|
if (xsize < 64)
|
|
|
|
|
xsize = 656;
|
|
|
|
|
if (ysize < 32)
|
|
|
|
|
ysize = 200;
|
|
|
|
|
set_screen_size(xsize, ysize);
|
|
|
|
|
|
|
|
|
|
if (video_force_resize_get())
|
|
|
|
|
video_force_resize_set(0);
|
|
|
|
|
}
|
2022-10-30 17:00:02 +01:00
|
|
|
video_blit_memtoscreen(0, dev->firstline, xsize, dev->lastline - dev->firstline);
|
2022-08-31 19:19:29 -04:00
|
|
|
frames++;
|
|
|
|
|
if ((dev->ctrl & HERCULESPLUS_CTRL_GRAPH) && (dev->ctrl2 & HERCULESPLUS_CTRL2_GRAPH)) {
|
|
|
|
|
video_res_x = dev->crtc[1] * 16;
|
|
|
|
|
video_res_y = dev->crtc[6] * 4;
|
|
|
|
|
video_bpp = 1;
|
|
|
|
|
} else {
|
|
|
|
|
video_res_x = dev->crtc[1];
|
|
|
|
|
video_res_y = dev->crtc[6];
|
|
|
|
|
video_bpp = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
dev->firstline = 1000;
|
|
|
|
|
dev->lastline = 0;
|
|
|
|
|
dev->blink++;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
dev->sc++;
|
|
|
|
|
dev->sc &= 31;
|
|
|
|
|
dev->ma = dev->maback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((dev->sc == (dev->crtc[10] & 31) || ((dev->crtc[8] & 3) == 3 && dev->sc == ((dev->crtc[10] & 31) >> 1))))
|
|
|
|
|
dev->con = 1;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
2022-07-07 14:34:59 +06:00
|
|
|
|
|
|
|
|
VIDEO_MONITOR_EPILOGUE();
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void *
|
|
|
|
|
herculesplus_init(const device_t *info)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2018-10-10 22:21:55 +02:00
|
|
|
herculesplus_t *dev;
|
2022-08-31 19:19:29 -04:00
|
|
|
int c;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
dev = (herculesplus_t *) malloc(sizeof(herculesplus_t));
|
2018-10-10 22:21:55 +02:00
|
|
|
memset(dev, 0, sizeof(herculesplus_t));
|
|
|
|
|
|
2022-08-31 19:19:29 -04:00
|
|
|
dev->vram = (uint8_t *) malloc(0x10000); /* 64k VRAM */
|
2022-07-07 14:34:59 +06:00
|
|
|
dev->monitor_index = monitor_index_global;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port;
Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX);
Finished the 586MC1;
Added 8087 emulation;
Moved Cyrix 6x86'es to the Dev branch;
Sanitized/cleaned up memregs.c/h and intel.c/h;
Split the chipsets from machines and sanitized Port 92 emulation;
Added support for the 15bpp mode to the Compaq ATI 28800;
Moved the MR 386DX and 486 machines to the Dev branch;
Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00;
Ported the new timer code from PCem;
Cleaned up the CPU table of unused stuff and better optimized its structure;
Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch;
Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem;
Added the AHA-1540A and the BusTek BT-542B;
Moved the Sumo SCSI-AT to the Dev branch;
Minor IDE, FDC, and floppy drive code clean-ups;
Made NCR 5380/53C400-based cards' BIOS address configurable;
Got rid of the legacy romset variable;
Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit;
Added the Amstead PPC512 per PCem patch by John Elliott;
Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages);
Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing;
Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem;
Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit;
Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement;
Amstrad MegaPC does now works correctly with non-internal graphics card;
The SLiRP code no longer casts a packed struct type to a non-packed struct type;
The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present;
The S3 Virge on BeOS is no longer broken (was broken by build #1591);
OS/2 2.0 build 6.167 now sees key presses again;
Xi8088 now work on CGA again;
86F images converted from either the old or new variants of the HxC MFM format now work correctly;
Hardware interrupts with a vector of 0xFF are now handled correctly;
OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct;
Fixed VNC keyboard input bugs;
Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver;
Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly;
Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4;
Compaq Portable now works with all graphics cards;
Fixed various MDSI Genius bugs;
Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly;
Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355;
OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400.
Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391.
Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389.
Fixed a minor IDE timing bug, fixes #388.
Fixed Toshiba T1000 RAM issues, fixes #379.
Fixed EGA/(S)VGA overscan border handling, fixes #378;
Got rid of the now long useless IDE channel 2 auto-removal, fixes #370;
Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366;
Ported the Unicode CD image file name fix from VARCem, fixes #365;
Fixed high density floppy disks on the Xi8088, fixes #359;
Fixed some bugs in the Hercules emulation, fixes #346, fixes #358;
Fixed the SCSI hard disk mode sense pages, fixes #356;
Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349;
Fixed bugs in the serial mouse emulation, fixes #344;
Compiled 86Box binaries now include all the required .DLL's, fixes #341;
Made some combo boxes in the Settings dialog slightly wider, fixes #276.
2019-09-20 14:02:30 +02:00
|
|
|
timer_add(&dev->timer, herculesplus_poll, dev, 1);
|
2018-10-10 22:21:55 +02:00
|
|
|
|
2022-07-07 14:34:59 +06:00
|
|
|
mem_mapping_add(&dev->mapping, 0xb0000, 0x08000,
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_read, NULL, NULL,
|
|
|
|
|
herculesplus_write, NULL, NULL,
|
|
|
|
|
dev->vram, MEM_MAPPING_EXTERNAL, dev);
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
io_sethandler(0x03b0, 16,
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_in, NULL, NULL, herculesplus_out, NULL, NULL, dev);
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
for (c = 0; c < 256; c++) {
|
2022-08-31 19:19:29 -04:00
|
|
|
dev->cols[c][0][0] = dev->cols[c][1][0] = dev->cols[c][1][1] = 16;
|
|
|
|
|
if (c & 8)
|
|
|
|
|
dev->cols[c][0][1] = 15 + 16;
|
|
|
|
|
else
|
|
|
|
|
dev->cols[c][0][1] = 7 + 16;
|
2018-10-10 22:21:55 +02:00
|
|
|
}
|
|
|
|
|
dev->cols[0x70][0][1] = 16;
|
2022-08-31 19:19:29 -04:00
|
|
|
dev->cols[0x70][0][0] = dev->cols[0x70][1][0] = dev->cols[0x70][1][1] = 16 + 15;
|
|
|
|
|
dev->cols[0xF0][0][1] = 16;
|
|
|
|
|
dev->cols[0xF0][0][0] = dev->cols[0xF0][1][0] = dev->cols[0xF0][1][1] = 16 + 15;
|
|
|
|
|
dev->cols[0x78][0][1] = 16 + 7;
|
|
|
|
|
dev->cols[0x78][0][0] = dev->cols[0x78][1][0] = dev->cols[0x78][1][1] = 16 + 15;
|
|
|
|
|
dev->cols[0xF8][0][1] = 16 + 7;
|
|
|
|
|
dev->cols[0xF8][0][0] = dev->cols[0xF8][1][0] = dev->cols[0xF8][1][1] = 16 + 15;
|
2018-10-10 22:21:55 +02:00
|
|
|
dev->cols[0x00][0][1] = dev->cols[0x00][1][1] = 16;
|
|
|
|
|
dev->cols[0x08][0][1] = dev->cols[0x08][1][1] = 16;
|
|
|
|
|
dev->cols[0x80][0][1] = dev->cols[0x80][1][1] = 16;
|
|
|
|
|
dev->cols[0x88][0][1] = dev->cols[0x88][1][1] = 16;
|
|
|
|
|
|
2018-10-28 08:26:07 +01:00
|
|
|
herc_blend = device_get_config_int("blend");
|
|
|
|
|
|
|
|
|
|
cga_palette = device_get_config_int("rgb_type") << 1;
|
|
|
|
|
if (cga_palette > 6)
|
2022-08-31 19:19:29 -04:00
|
|
|
cga_palette = 0;
|
2018-10-28 08:26:07 +01:00
|
|
|
cgapal_rebuild();
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
video_inform(VIDEO_FLAG_TYPE_MDA, &timing_herculesplus);
|
|
|
|
|
|
|
|
|
|
/* Force the LPT3 port to be enabled. */
|
|
|
|
|
lpt3_init(0x3BC);
|
|
|
|
|
|
|
|
|
|
return dev;
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
herculesplus_close(void *priv)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_t *dev = (herculesplus_t *) priv;
|
2016-11-16 15:37:07 -06:00
|
|
|
|
2018-10-11 10:34:12 +02:00
|
|
|
if (!dev)
|
2022-08-31 19:19:29 -04:00
|
|
|
return;
|
2018-10-11 10:34:12 +02:00
|
|
|
|
|
|
|
|
if (dev->vram)
|
2022-08-31 19:19:29 -04:00
|
|
|
free(dev->vram);
|
2018-10-11 10:34:12 +02:00
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
free(dev);
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
static void
|
|
|
|
|
speed_changed(void *priv)
|
2016-11-16 15:37:07 -06:00
|
|
|
{
|
2022-08-31 19:19:29 -04:00
|
|
|
herculesplus_t *dev = (herculesplus_t *) priv;
|
2018-10-10 22:21:55 +02:00
|
|
|
|
|
|
|
|
recalc_timings(dev);
|
2016-11-16 15:37:07 -06:00
|
|
|
}
|
|
|
|
|
|
2018-10-28 08:26:07 +01:00
|
|
|
static const device_config_t herculesplus_config[] = {
|
2022-08-31 19:19:29 -04:00
|
|
|
// clang-format off
|
2018-10-28 08:26:07 +01:00
|
|
|
{
|
2022-04-09 20:09:14 -04:00
|
|
|
.name = "rgb_type",
|
|
|
|
|
.description = "Display type",
|
|
|
|
|
.type = CONFIG_SELECTION,
|
|
|
|
|
.default_int = 0,
|
|
|
|
|
.selection = {
|
|
|
|
|
{
|
|
|
|
|
.description = "Default",
|
|
|
|
|
.value = 0
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.description = "Green",
|
|
|
|
|
.value = 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.description = "Amber",
|
|
|
|
|
.value = 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.description = "Gray",
|
|
|
|
|
.value = 3
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.description = ""
|
|
|
|
|
}
|
2022-02-26 23:31:28 -05:00
|
|
|
}
|
2018-10-28 08:26:07 +01:00
|
|
|
},
|
2022-04-09 20:09:14 -04:00
|
|
|
{
|
|
|
|
|
.name = "blend",
|
|
|
|
|
.description = "Blend",
|
|
|
|
|
.type = CONFIG_BINARY,
|
|
|
|
|
.default_int = 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.type = CONFIG_END
|
|
|
|
|
}
|
2022-11-19 08:49:04 -05:00
|
|
|
// clang-format on
|
2018-10-28 08:26:07 +01:00
|
|
|
};
|
|
|
|
|
|
2018-10-10 22:21:55 +02:00
|
|
|
const device_t herculesplus_device = {
|
2022-08-31 19:19:29 -04:00
|
|
|
.name = "Hercules Plus",
|
2022-03-13 21:43:45 -04:00
|
|
|
.internal_name = "hercules_plus",
|
2022-08-31 19:19:29 -04:00
|
|
|
.flags = DEVICE_ISA,
|
|
|
|
|
.local = 0,
|
|
|
|
|
.init = herculesplus_init,
|
|
|
|
|
.close = herculesplus_close,
|
|
|
|
|
.reset = NULL,
|
2022-03-13 21:43:45 -04:00
|
|
|
{ .available = NULL },
|
|
|
|
|
.speed_changed = speed_changed,
|
2022-08-31 19:19:29 -04:00
|
|
|
.force_redraw = NULL,
|
|
|
|
|
.config = herculesplus_config
|
2016-11-16 15:37:07 -06:00
|
|
|
};
|