From patchwork Mon Sep 10 01:27:44 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Ogilvie X-Patchwork-Id: 182776 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id BC5462C009F for ; Mon, 10 Sep 2012 11:40:12 +1000 (EST) Received: from localhost ([::1]:32815 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TAsor-00069z-Ce for incoming@patchwork.ozlabs.org; Sun, 09 Sep 2012 21:29:45 -0400 Received: from eggs.gnu.org ([208.118.235.92]:56076) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TAsoF-000429-Jn for qemu-devel@nongnu.org; Sun, 09 Sep 2012 21:29:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TAsoD-0003BW-UZ for qemu-devel@nongnu.org; Sun, 09 Sep 2012 21:29:07 -0400 Received: from qmta15.emeryville.ca.mail.comcast.net ([76.96.27.228]:46063) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TAsoD-0003BG-Kl for qemu-devel@nongnu.org; Sun, 09 Sep 2012 21:29:05 -0400 Received: from omta17.emeryville.ca.mail.comcast.net ([76.96.30.73]) by qmta15.emeryville.ca.mail.comcast.net with comcast id xDGa1j0061afHeLAFDV4P6; Mon, 10 Sep 2012 01:29:04 +0000 Received: from mmogilvi.homeip.net ([24.9.53.136]) by omta17.emeryville.ca.mail.comcast.net with comcast id xDV31j00W2wKXRC8dDV4X1; Mon, 10 Sep 2012 01:29:04 +0000 Received: by mmogilvi.homeip.net (Postfix, from userid 501) id 9A10D1E9601B; Sun, 9 Sep 2012 19:29:03 -0600 (MDT) From: Matthew Ogilvie To: qemu-devel@nongnu.org Date: Sun, 9 Sep 2012 19:27:44 -0600 Message-Id: <1347240466-6152-5-git-send-email-mmogilvi_qemu@miniinfo.net> X-Mailer: git-send-email 1.7.10.2.484.gcd07cc5 In-Reply-To: <1347240466-6152-1-git-send-email-mmogilvi_qemu@miniinfo.net> References: <1347240466-6152-1-git-send-email-mmogilvi_qemu@miniinfo.net> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 76.96.27.228 Cc: Matthew Ogilvie Subject: [Qemu-devel] [PATCH v5 4/6] vga: add some optional CGA compatibility hacks X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch adds some optional compatibility hacks (default disabled) to allow Microport UNIX to function under qemu. I've tried to structure it to be easy to add more hacks for other old CGA programs, if anyone ever needs them. Microport UNIX System V/386 v 2.1 (ca 1987) tries to program the CGA registers directly with neither the assistance of BIOS, nor with proper handling of EGA/VGA-only registers. Note that it didn't work on real VGA hardware, either (although in that case, the most obvious problems seemed to be out-of-range hsync and/or vsync signalling, rather than the issues in this patch). Eventually real MDA and/or CGA support might provide an alternative to this patch, although a hybrid approach like this patch might still be useful in marginal cases. Signed-off-by: Matthew Ogilvie --- hw/pc.h | 4 ++++ hw/vga.c | 37 +++++++++++++++++++++++++++++-------- qemu-options.hx | 19 +++++++++++++++++++ vl.c | 23 +++++++++++++++++++++++ 4 files changed, 75 insertions(+), 8 deletions(-) diff --git a/hw/pc.h b/hw/pc.h index e4db071..37e2f87 100644 --- a/hw/pc.h +++ b/hw/pc.h @@ -176,6 +176,10 @@ enum vga_retrace_method { extern enum vga_retrace_method vga_retrace_method; +#define VGA_CGA_HACK_PALETTE_BLANKING (1<<0) +#define VGA_CGA_HACK_FONT_HEIGHT (1<<1) +extern int vga_cga_hacks; + static inline DeviceState *isa_vga_init(ISABus *bus) { ISADevice *dev; diff --git a/hw/vga.c b/hw/vga.c index f82ced8..fb08dc0 100644 --- a/hw/vga.c +++ b/hw/vga.c @@ -547,14 +547,31 @@ void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); #endif /* handle CR0-7 protection */ - if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) && - s->cr_index <= VGA_CRTC_OVERFLOW) { - /* can always write bit 4 of CR7 */ - if (s->cr_index == VGA_CRTC_OVERFLOW) { - s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) | - (val & 0x10); + if (s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) { + if (s->cr_index <= VGA_CRTC_OVERFLOW) { + /* can always write bit 4 of CR7 */ + if (s->cr_index == VGA_CRTC_OVERFLOW) { + s->cr[VGA_CRTC_OVERFLOW] = + (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) | (val & 0x10); + } + return; + } else if ((vga_cga_hacks & VGA_CGA_HACK_FONT_HEIGHT) && + !(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) { + /* extra CGA compatibility hacks (not in standard VGA) */ + if (s->cr_index == VGA_CRTC_MAX_SCAN && + val == 7 && + (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { + return; + } else if (s->cr_index == VGA_CRTC_CURSOR_START && + val == 6 && + (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { + val = 0xd; + } else if (s->cr_index == VGA_CRTC_CURSOR_END && + val == 7 && + (s->cr[VGA_CRTC_MAX_SCAN] & 0xf) == 0xf) { + val = 0xe; + } } - return; } s->cr[s->cr_index] = val; @@ -1886,7 +1903,11 @@ static void vga_update_display(void *opaque) /* nothing to do */ } else { full_update = 0; - if (!(s->ar_index & 0x20)) { + if (!(s->ar_index & 0x20) && + /* extra CGA compatibility hacks (not in standard VGA) */ + (!(vga_cga_hacks & VGA_CGA_HACK_PALETTE_BLANKING) || + s->ar_index != 0 || + !s->ar_flip_flop)) { graphic_mode = GMODE_BLANK; } else { graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE; diff --git a/qemu-options.hx b/qemu-options.hx index 3e8085d..68925f3 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -975,6 +975,25 @@ Valid optional properties are @item retrace=dumb|precise Select dumb (default) or precise VGA retrace logic, useful for some DOS games/demos. +@item cga_hacks=@var{hack1}[+@var{hack2}[+...]] +Enable various extra CGA compatibility hacks for programs that are +trying to directly set CGA modes without BIOS assistance nor +real knowledge of EGA/VGA. These might only work with -vga std. +Valid hacks are +@table @option +@item palette_blanking +Wait to blank the screen until palette registers seem to actually be +modified, instead of blanking it as soon as the palette address bit (0x10) +of the attribute address register (0x3c0) is cleared. +@item font_height +Ignore attempts to change the VGA font height (index 9), +cursor start (index 10), and cursor end (index 11) of the CRTC control +registers (0x3d5) if trying to set them to the default for CGA fonts +instead of VGA fonts. +@item all +Enable all CGA hacks. More CGA hacks may be added in future versions +of qemu. +@end table @end table ETEXI diff --git a/vl.c b/vl.c index febfd62..16d04a2 100644 --- a/vl.c +++ b/vl.c @@ -179,6 +179,7 @@ int main(int argc, char **argv) static const char *data_dir; const char *bios_name = NULL; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; +int vga_cga_hacks = 0; DisplayType display_type = DT_DEFAULT; int display_remote = 0; const char* keyboard_layout = NULL; @@ -1748,6 +1749,28 @@ static void select_vgahw (const char *p) else if (strstart(opts, "precise", &nextopt)) vga_retrace_method = VGA_RETRACE_PRECISE; else goto invalid_vga; + } else if (strstart(opts, ",cga_hacks=", &nextopt)) { + opts = nextopt; + while (*opts) { + if (strstart(opts, "all", &nextopt)) { + opts = nextopt; + vga_cga_hacks |= ~0; + } else if (strstart(opts, "palette_blanking", &nextopt)) { + opts = nextopt; + vga_cga_hacks |= VGA_CGA_HACK_PALETTE_BLANKING; + } else if (strstart(opts, "font_height", &nextopt)) { + opts = nextopt; + vga_cga_hacks |= VGA_CGA_HACK_FONT_HEIGHT; + } else { + break; + } + + if (*opts == '+') { + opts++; + } else { + break; + } + } } else goto invalid_vga; opts = nextopt; }