diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2014-12-30 22:42:06 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2024-01-18 10:43:14 +0100 |
commit | 3f83435042af241ea8773d04ef3726ce4146bfca (patch) | |
tree | e843167e964f5c7e513a569f1b22def455f82ba9 /hw/display/vga.c | |
parent | ae9d71a003c8cfd2f035c8f768341a40bcef8ed4 (diff) |
vga: use latches in odd/even mode too
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>
Diffstat (limited to 'hw/display/vga.c')
-rw-r--r-- | hw/display/vga.c | 38 |
1 files changed, 12 insertions, 26 deletions
diff --git a/hw/display/vga.c b/hw/display/vga.c index f89409f8f2..d1ef716642 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -825,15 +825,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; } @@ -886,11 +883,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 @@ -902,27 +900,15 @@ void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val) return; } + if ((sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_SEQ_MODE) == 0) { + mask &= (addr & 1) ? 0x0a : 0x05; + } + 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; + addr >>= 1; } - mask = sr(s, VGA_SEQ_PLANE_WRITE); - /* standard VGA latched access */ write_mode = s->gr[VGA_GFX_MODE] & 3; switch(write_mode) { |