[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 7/8] vga: use latches in odd/even mode too
From: |
Paolo Bonzini |
Subject: |
[PATCH 7/8] vga: use latches in odd/even mode too |
Date: |
Sun, 31 Dec 2023 10:39:17 +0100 |
Jazz Jackrabbit uses odd/even mode with 256-color graphics. This is
probably so that it can do very fast blitting with a decent resolution
(two pixels, compared to four pixels for "regular" mode X).
Accesses still use all planes (reads go to the latches and the game uses
read mode 1 so that the CPU always gets 0xFF; writes use the plane mask
register because the game sets bit 2 of the sequencer's memory mode
register). For this to work, QEMU needs to use the code for latched
memory accesses in odd/even mode. The only difference between odd/even
mode and "regular" planar mode is how the plane is computed in read mode
0, and how the planes are masked if the aforementioned bit 2 is reset.
It is almost enough to fix the game. You also need to honor byte/word
mode selection, which is done in the next patch.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
hw/display/vga.c | 40 +++++++++++++---------------------------
1 file changed, 13 insertions(+), 27 deletions(-)
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 08ba5bb1118..731501cb7af 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -842,15 +842,12 @@ uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
if (s->gr[VGA_GFX_MODE] & 0x10) {
/* odd/even mode (aka text mode mapping) */
plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
- addr = ((addr & ~1) << 1) | plane;
- if (addr >= s->vram_size) {
- return 0xff;
- }
- return s->vram_ptr[addr];
+ addr >>= 1;
+ } else {
+ /* standard VGA latched access */
+ plane = s->gr[VGA_GFX_PLANE_READ];
}
- /* standard VGA latched access */
- plane = s->gr[VGA_GFX_PLANE_READ];
if (addr * sizeof(uint32_t) >= s->vram_size) {
return 0xff;
}
@@ -903,11 +900,12 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr,
uint32_t val)
break;
}
+ mask = sr(s, VGA_SEQ_PLANE_WRITE);
if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
/* chain 4 mode : simplest access */
plane = addr & 3;
- mask = (1 << plane);
- if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) {
+ mask &= (1 << plane);
+ if (mask) {
assert(addr < s->vram_size);
s->vram_ptr[addr] = val;
#ifdef DEBUG_VGA_MEM
@@ -919,26 +917,14 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr,
uint32_t val)
return;
}
- if (s->gr[VGA_GFX_MODE] & 0x10) {
- /* odd/even mode (aka text mode mapping) */
- plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
- mask = (1 << plane);
- if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) {
- addr = ((addr & ~1) << 1) | plane;
- if (addr >= s->vram_size) {
- return;
- }
- s->vram_ptr[addr] = val;
-#ifdef DEBUG_VGA_MEM
- printf("vga: odd/even: [0x" HWADDR_FMT_plx "]\n", addr);
-#endif
- s->plane_updated |= mask; /* only used to detect font change */
- memory_region_set_dirty(&s->vram, addr, 1);
- }
- return;
+ if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0) {
+ mask &= (addr & 1) ? 0x0a : 0x05;
}
- mask = sr(s, VGA_SEQ_PLANE_WRITE);
+ if (s->gr[VGA_GFX_MODE] & 0x10) {
+ /* odd/even mode (aka text mode mapping) */
+ addr >>= 1;
+ }
/* standard VGA latched access */
write_mode = s->gr[VGA_GFX_MODE] & 3;
--
2.43.0
- [PATCH 0/8] vga: improve emulation fidelity, Paolo Bonzini, 2023/12/31
- [PATCH 3/8] vga: mask addresses in non-VESA modes to 256k, Paolo Bonzini, 2023/12/31
- [PATCH 1/8] vga: remove unused macros, Paolo Bonzini, 2023/12/31
- [PATCH 7/8] vga: use latches in odd/even mode too,
Paolo Bonzini <=
- [PATCH 2/8] vga: introduce VGADisplayParams, Paolo Bonzini, 2023/12/31
- [PATCH 4/8] vga: implement horizontal pel panning in graphics modes, Paolo Bonzini, 2023/12/31
- [PATCH 5/8] vga: optimize horizontal pel panning in 256-color modes, Paolo Bonzini, 2023/12/31
- [PATCH 6/8] vga: reindent memory access code, Paolo Bonzini, 2023/12/31
- [PATCH 8/8] vga: sort-of implement word and double-word access modes, Paolo Bonzini, 2023/12/31