vga: sort-of implement word and double-word access modes

Jazz Jackrabbit has a very unusual VGA setup, where it uses odd/even mode
with 256-color graphics.  Probably, it wants to use fast VRAM-to-VRAM
copies without having to store 4 copies of the sprites as needed in mode
X, one for each mod-4 alignment; odd/even mode simplifies the code a
lot if it's okay to place on a 160-pixels horizontal grid.

At the same time, because it wants to use double buffering (a la "mode X")
it uses byte mode, not word mode as is the case in text modes.  In order
to implement the combination of odd/even mode (plane number comes from
bit 0 of the address) and byte mode (use all bytes of VRAM, whereas word
mode only uses bytes 0, 2, 4,... on each of the four planes), we need
to separate the effect on the plane number from the effect on the address.

Implementing the modes properly is a mess in QEMU, because it would
change the layout of VRAM and break migration.  As an approximation,
shift right when the CPU accesses memory instead of shifting left when
the CRT controller reads it.  A hack is needed in order to write font data
properly (see comment in the code), but it works well enough for the game.

Because doubleword and chain4 modes are now independent, chain4 does not
assert anymore that the address is in range.  Instead it just returns
all ones and discards writes, like other modes.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2014-12-29 14:56:24 +01:00
parent 3f83435042
commit 435262605f
2 changed files with 69 additions and 24 deletions

View file

@ -100,7 +100,9 @@
/* VGA CRT controller bit masks */
#define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */
#define VGA_CR14_DW 0x40
#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80
#define VGA_CR17_WORD_BYTE 0x40
/* VGA attribute controller register indices */
#define VGA_ATC_PALETTE0 0x00
@ -154,6 +156,8 @@
#define VGA_GFX_BIT_MASK 0x08
/* VGA graphics controller bit masks */
#define VGA_GR05_HOST_ODD_EVEN 0x10
#define VGA_GR06_GRAPHICS_MODE 0x01
#define VGA_GR06_CHAIN_ODD_EVEN 0x02
#endif /* HW_VGA_REGS_H */