aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/pc.h4
-rw-r--r--hw/vga.c36
-rw-r--r--qemu-options.hx19
-rw-r--r--vl.c23
4 files changed, 74 insertions, 8 deletions
diff --git a/hw/pc.h b/hw/pc.h
index e4db0715b8..37e2f87583 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 f82ced8e66..a65fc26ab7 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,10 @@ 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 3e8085d463..0682338e9f 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 febfd62c37..16d04a2ee2 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;
}