Bochs/bochs/iodev/svga_cirrus.cc
Volker Ruppert a75d9f173d - mem_write: missing return statement added
- small fixes in bitblt functions (colorinvert, patterncopy)
2004-08-28 15:31:33 +00:00

3455 lines
109 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id: svga_cirrus.cc,v 1.4 2004-08-28 15:31:33 vruppert Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004 Makoto Suzuki (suzu)
// Volker Ruppert (vruppert)
// Robin Kay (komadori)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// limited PCI/ISA CLGD5446 support for Bochs
//
// there are still many unimplemented features:
//
// - 1bpp/4bpp
// - transparent compare not complete
// - some bitblt functions
// - ???
//
// some codes are copied from vga.cc and modified.
// some codes are ported from the cirrus emulation in qemu
// (http://savannah.nongnu.org/projects/qemu).
//
#define BX_PLUGGABLE
#include "iodev.h"
#if BX_SUPPORT_CLGD54XX
// Only reference the array if the tile numbers are within the bounds
// of the array. If out of bounds, do nothing.
#define SET_TILE_UPDATED(xtile,ytile,value) \
do { \
if (((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) \
BX_CIRRUS_THIS s.vga_tile_updated[(xtile)][(ytile)] = value; \
} while (0)
// Only reference the array if the tile numbers are within the bounds
// of the array. If out of bounds, return 1.
#define GET_TILE_UPDATED(xtile,ytile) \
((((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES))? \
BX_CIRRUS_THIS s.vga_tile_updated[(xtile)][(ytile)] \
: 1)
// Make colour
#define MAKE_COLOUR(red, red_shiftfrom, red_shiftto, red_mask, \
green, green_shiftfrom, green_shiftto, green_mask, \
blue, blue_shiftfrom, blue_shiftto, blue_mask) \
( \
((((red_shiftto) > (red_shiftfrom)) ? \
(red) << ((red_shiftto) - (red_shiftfrom)) : \
(red) >> ((red_shiftfrom) - (red_shiftto))) & \
(red_mask)) | \
((((green_shiftto) > (green_shiftfrom)) ? \
(green) << ((green_shiftto) - (green_shiftfrom)) : \
(green) >> ((green_shiftfrom) - (green_shiftto))) & \
(green_mask)) | \
((((blue_shiftto) > (blue_shiftfrom)) ? \
(blue) << ((blue_shiftto) - (blue_shiftfrom)) : \
(blue) >> ((blue_shiftfrom) - (blue_shiftto))) & \
(blue_mask)) \
)
#define LOG_THIS BX_CIRRUS_THIS
#if BX_USE_CIRRUS_SMF
#define VGA_READ(addr,len) bx_vga_c::read_handler(theSvga,addr,len)
#define VGA_WRITE(addr,val,len) bx_vga_c::write_handler(theSvga,addr,val,len)
#define SVGA_READ(addr,len) svga_read_handler(theSvga,addr,len)
#define SVGA_WRITE(addr,val,len) svga_write_handler(theSvga,addr,val,len)
#else
#define VGA_READ(addr,len) bx_vga_c::read(addr,len)
#define VGA_WRITE(addr,val,len) bx_vga_c::write(addr,val,len)
#define SVGA_READ(addr,len) svga_read(addr,len)
#define SVGA_WRITE(addr,val,len) svga_write(addr,val,len)
#endif // BX_USE_CIRRUS_SMF
#define ID_CLGD5428 (0x26<<2)
#define ID_CLGD5430 (0x28<<2)
#define ID_CLGD5434 (0x2A<<2)
#define ID_CLGD5446 (0x2E<<2)
// sequencer 0x07
#define CIRRUS_SR7_BPP_VGA 0x00
#define CIRRUS_SR7_BPP_SVGA 0x01
#define CIRRUS_SR7_BPP_MASK 0x0e
#define CIRRUS_SR7_BPP_8 0x00
#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02
#define CIRRUS_SR7_BPP_24 0x04
#define CIRRUS_SR7_BPP_16 0x06
#define CIRRUS_SR7_BPP_32 0x08
#define CIRRUS_SR7_ISAADDR_MASK 0xe0
// sequencer 0x0f
#define CIRRUS_MEMSIZE_512k 0x08
#define CIRRUS_MEMSIZE_1M 0x10
#define CIRRUS_MEMSIZE_2M 0x18
#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
// sequencer 0x12
#define CIRRUS_CURSOR_SHOW 0x01
#define CIRRUS_CURSOR_HIDDENPEL 0x02
#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear
// sequencer 0x17
#define CIRRUS_BUSTYPE_VLBFAST 0x10
#define CIRRUS_BUSTYPE_PCI 0x20
#define CIRRUS_BUSTYPE_VLBSLOW 0x30
#define CIRRUS_BUSTYPE_ISA 0x38
#define CIRRUS_MMIO_ENABLE 0x04
#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared.
#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
// control 0x0b
#define CIRRUS_BANKING_DUAL 0x01
#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k
// control 0x30
#define CIRRUS_BLTMODE_BACKWARDS 0x01
#define CIRRUS_BLTMODE_MEMSYSDEST 0x02
#define CIRRUS_BLTMODE_MEMSYSSRC 0x04
#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08
#define CIRRUS_BLTMODE_PATTERNCOPY 0x40
#define CIRRUS_BLTMODE_COLOREXPAND 0x80
#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30
#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00
#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10
#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
// control 0x31
#define CIRRUS_BLT_BUSY 0x01
#define CIRRUS_BLT_START 0x02
#define CIRRUS_BLT_RESET 0x04
#define CIRRUS_BLT_FIFOUSED 0x10
#define CIRRUS_BLT_AUTOSTART 0x80
// control 0x32
#define CIRRUS_ROP_0 0x00
#define CIRRUS_ROP_SRC_AND_DST 0x05
#define CIRRUS_ROP_NOP 0x06
#define CIRRUS_ROP_SRC_AND_NOTDST 0x09
#define CIRRUS_ROP_NOTDST 0x0b
#define CIRRUS_ROP_SRC 0x0d
#define CIRRUS_ROP_1 0x0e
#define CIRRUS_ROP_NOTSRC_AND_DST 0x50
#define CIRRUS_ROP_SRC_XOR_DST 0x59
#define CIRRUS_ROP_SRC_OR_DST 0x6d
#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90
#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95
#define CIRRUS_ROP_SRC_OR_NOTDST 0xad
#define CIRRUS_ROP_NOTSRC 0xd0
#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6
#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda
// control 0x33
#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04
#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02
#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
#define CLGD543x_MMIO_BLTBGCOLOR 0x00 // dword
#define CLGD543x_MMIO_BLTFGCOLOR 0x04 // dword
#define CLGD543x_MMIO_BLTWIDTH 0x08 // word
#define CLGD543x_MMIO_BLTHEIGHT 0x0a // word
#define CLGD543x_MMIO_BLTDESTPITCH 0x0c // word
#define CLGD543x_MMIO_BLTSRCPITCH 0x0e // word
#define CLGD543x_MMIO_BLTDESTADDR 0x10 // dword
#define CLGD543x_MMIO_BLTSRCADDR 0x14 // dword
#define CLGD543x_MMIO_BLTWRITEMASK 0x17 // byte
#define CLGD543x_MMIO_BLTMODE 0x18 // byte
#define CLGD543x_MMIO_BLTROP 0x1a // byte
#define CLGD543x_MMIO_BLTMODEEXT 0x1b // byte
#define CLGD543x_MMIO_BLTTRANSPARENTCOLOR 0x1c // word?
#define CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word?
#define CLGD543x_MMIO_BLTSTATUS 0x40 // byte
// PCI 0x00: vendor, 0x02: device
#define PCI_VENDOR_CIRRUS 0x1013
#define PCI_DEVICE_CLGD5430 0x00a0 // CLGD5430 or CLGD5440
#define PCI_DEVICE_CLGD5434 0x00a8
#define PCI_DEVICE_CLGD5436 0x00ac
#define PCI_DEVICE_CLGD5446 0x00b8
#define PCI_DEVICE_CLGD5462 0x00d0
#define PCI_DEVICE_CLGD5465 0x00d6
// PCI 0x04: command(word), 0x06(word): status
#define PCI_COMMAND_IOACCESS 0x0001
#define PCI_COMMAND_MEMACCESS 0x0002
#define PCI_COMMAND_BUSMASTER 0x0004
#define PCI_COMMAND_SPECIALCYCLE 0x0008
#define PCI_COMMAND_MEMWRITEINVALID 0x0010
#define PCI_COMMAND_PALETTESNOOPING 0x0020
#define PCI_COMMAND_PARITYDETECTION 0x0040
#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080
#define PCI_COMMAND_SERR 0x0100
#define PCI_COMMAND_BACKTOBACKTRANS 0x0200
// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
#define PCI_CLASS_BASE_DISPLAY 0x03
// PCI 0x08, 0x00ff0000
#define PCI_CLASS_SUB_VGA 0x00
// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
#define PCI_CLASS_HEADERTYPE_00h 0x00
// 0x10-0x3f (headertype 00h)
// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
#define PCI_MAP_MEM 0x0
#define PCI_MAP_IO 0x1
#define PCI_MAP_MEM_ADDR_MASK (~0xf)
#define PCI_MAP_IO_ADDR_MASK (~0x3)
#define PCI_MAP_MEMFLAGS_32BIT 0x0
#define PCI_MAP_MEMFLAGS_32BIT_1M 0x1
#define PCI_MAP_MEMFLAGS_64BIT 0x4
#define PCI_MAP_MEMFLAGS_CACHEABLE 0x8
// PCI 0x28: cardbus CIS pointer
// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
// PCI 0x30: expansion ROM base address
// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
// PCI 0x38: reserved
// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
// PCI 0x40-0xff: device dependent fields
// To implement the following stuffs, memory PnP is required!
// default PnP memory address (FIXME - can't relocate!)
#define CIRRUS_PNPMEM_BASE_ADDRESS 0xe0000000
#define CIRRUS_PNPMEM_SIZE CIRRUS_VIDEO_MEMORY_BYTES
// default PnP memory-mapped I/O address (FIXME - can't relocate!)
#define CIRRUS_PNPMMIO_BASE_ADDRESS (CIRRUS_PNPMEM_BASE_ADDRESS + CIRRUS_PNPMEM_SIZE)
#define CIRRUS_PNPMMIO_SIZE 0x1000
#define BX_MAX(a,b) ((a) > (b) ? (a) : (b))
#define BX_MIN(a,b) ((a) < (b) ? (a) : (b))
static bx_svga_cirrus_c *theSvga = NULL;
int
libvga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
{
theSvga = new bx_svga_cirrus_c ();
libvga_set_smf_pointer(theSvga);
bx_devices.pluginVgaDevice = theSvga;
BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSvga, BX_PLUGIN_VGA);
return(0); // Success
}
void
libvga_LTX_plugin_fini(void)
{
}
bx_svga_cirrus_c::bx_svga_cirrus_c(void) :
bx_vga_c ()
{
put("CLVGA");
vidmem = NULL;
tilemem = NULL;
}
bx_svga_cirrus_c::~bx_svga_cirrus_c()
{
if (vidmem != NULL) {
delete [] vidmem;
}
if (tilemem != NULL) {
delete [] tilemem;
}
}
void
bx_svga_cirrus_c::init(void)
{
// initialize VGA stuffs.
BX_CIRRUS_THIS bx_vga_c::init();
BX_CIRRUS_THIS bx_vga_c::init_iohandlers(
svga_read_handler, svga_write_handler);
BX_CIRRUS_THIS bx_vga_c::init_systemtimer(
svga_timer_handler);
// initialize SVGA stuffs.
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
BX_CIRRUS_THIS pci_enabled = DEV_is_pci_device("cirrus");
#endif
BX_CIRRUS_THIS svga_init_members();
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
if (BX_CIRRUS_THIS pci_enabled) {
BX_CIRRUS_THIS svga_init_pcihandlers();
}
#endif
}
void
bx_svga_cirrus_c::svga_init_members()
{
unsigned i;
// clear all registers.
BX_CIRRUS_THIS sequencer.index = CIRRUS_SEQENCER_MAX + 1;
for (i = 0; i <= CIRRUS_SEQENCER_MAX; i++)
BX_CIRRUS_THIS sequencer.reg[i] = 0x00;
BX_CIRRUS_THIS control.index = CIRRUS_CONTROL_MAX + 1;
for (i = 0; i <= CIRRUS_CONTROL_MAX; i++)
BX_CIRRUS_THIS control.reg[i] = 0x00;
BX_CIRRUS_THIS control.shadow_reg0 = 0x00;
BX_CIRRUS_THIS control.shadow_reg1 = 0x00;
BX_CIRRUS_THIS crtc.index = CIRRUS_CRTC_MAX + 1;
for (i = 0; i <= CIRRUS_CRTC_MAX; i++)
BX_CIRRUS_THIS crtc.reg[i] = 0x00;
BX_CIRRUS_THIS hidden_dac.lockindex = 0;
BX_CIRRUS_THIS hidden_dac.data = 0x00;
BX_CIRRUS_THIS svga_unlock_special = false;
BX_CIRRUS_THIS svga_needs_update_tile = true;
BX_CIRRUS_THIS svga_needs_update_dispentire = true;
BX_CIRRUS_THIS svga_needs_update_mode = false;
BX_CIRRUS_THIS svga_xres = 640;
BX_CIRRUS_THIS svga_yres = 480;
BX_CIRRUS_THIS svga_bpp = 8;
BX_CIRRUS_THIS svga_pitch = 640;
BX_CIRRUS_THIS bank_base[0] = 0;
BX_CIRRUS_THIS bank_base[1] = 0;
BX_CIRRUS_THIS bank_limit[0] = 0;
BX_CIRRUS_THIS bank_limit[1] = 0;
svga_reset_bitblt();
BX_CIRRUS_THIS hw_cursor.x = 0;
BX_CIRRUS_THIS hw_cursor.y = 0;
BX_CIRRUS_THIS hw_cursor.size = 0;
// memory allocation.
BX_CIRRUS_THIS vidmem = new Bit8u[CIRRUS_VIDEO_MEMORY_BYTES];
BX_CIRRUS_THIS tilemem = new Bit8u[X_TILESIZE * Y_TILESIZE * 4];
// set some registers.
BX_CIRRUS_THIS sequencer.reg[0x06] = 0x0f;
BX_CIRRUS_THIS sequencer.reg[0x07] = 0x00; // 0xf0:linearbase(0x00 if disabled)
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
if (BX_CIRRUS_THIS pci_enabled) {
BX_CIRRUS_THIS crtc.reg[0x27] = ID_CLGD5446;
BX_CIRRUS_THIS sequencer.reg[0x1F] = 0x2d; // MemClock
BX_CIRRUS_THIS control.reg[0x18] = 0x0f;
BX_CIRRUS_THIS sequencer.reg[0x0F] = 0x98;
BX_CIRRUS_THIS sequencer.reg[0x17] = CIRRUS_BUSTYPE_PCI;
BX_CIRRUS_THIS sequencer.reg[0x15] = 0x04; // memory size 4MB
BX_CIRRUS_THIS memsize = (4 << 20);
} else
#endif
{
BX_CIRRUS_THIS crtc.reg[0x27] = ID_CLGD5430;
BX_CIRRUS_THIS sequencer.reg[0x1F] = 0x22; // MemClock
BX_CIRRUS_THIS sequencer.reg[0x0F] = CIRRUS_MEMSIZE_2M;
BX_CIRRUS_THIS sequencer.reg[0x17] = CIRRUS_BUSTYPE_ISA;
BX_CIRRUS_THIS sequencer.reg[0x15] = 0x03; // memory size 2MB
BX_CIRRUS_THIS memsize = (2 << 20);
}
BX_CIRRUS_THIS hidden_dac.lockindex = 5;
BX_CIRRUS_THIS hidden_dac.data = 0;
memset(BX_CIRRUS_THIS vidmem, 0xff, CIRRUS_VIDEO_MEMORY_BYTES);
BX_CIRRUS_THIS disp_ptr = BX_CIRRUS_THIS vidmem;
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
if (BX_CIRRUS_THIS pci_enabled) {
// This should be done by the PCI BIOS
WriteHostDWordToLittleEndian(
&BX_CIRRUS_THIS pci_conf[0x10],
(PCI_MAP_MEM | PCI_MAP_MEMFLAGS_32BIT | PCI_MAP_MEMFLAGS_CACHEABLE |
CIRRUS_PNPMEM_BASE_ADDRESS));
WriteHostDWordToLittleEndian(
&BX_CIRRUS_THIS pci_conf[0x14],
(PCI_MAP_MEM | PCI_MAP_MEMFLAGS_32BIT |
CIRRUS_PNPMMIO_BASE_ADDRESS));
DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler,
cirrus_mem_write_handler,
&BX_CIRRUS_THIS pci_memaddr,
&BX_CIRRUS_THIS pci_conf[0x10],
CIRRUS_PNPMEM_SIZE);
DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler,
cirrus_mem_write_handler,
&BX_CIRRUS_THIS pci_mmioaddr,
&BX_CIRRUS_THIS pci_conf[0x14],
CIRRUS_PNPMMIO_SIZE);
}
#endif
}
void
bx_svga_cirrus_c::reset(unsigned type)
{
// reset VGA stuffs.
BX_CIRRUS_THIS bx_vga_c::reset(type);
// reset SVGA stuffs.
BX_CIRRUS_THIS svga_init_members();
}
void
bx_svga_cirrus_c::redraw_area(unsigned x0, unsigned y0,
unsigned width, unsigned height)
{
unsigned xi, yi, x1, y1, xmax, ymax;
if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
BX_CIRRUS_THIS bx_vga_c::redraw_area(x0,y0,width,height);
return;
}
if (BX_CIRRUS_THIS svga_needs_update_mode) {
return;
}
BX_CIRRUS_THIS svga_needs_update_tile = true;
x1 = x0 + width - 1;
y1 = y0 + height - 1;
xmax = BX_CIRRUS_THIS svga_xres;
ymax = BX_CIRRUS_THIS svga_yres;
for (yi=0; yi<ymax; yi+=Y_TILESIZE) {
for (xi=0; xi<xmax; xi+=X_TILESIZE) {
// is redraw rectangle outside x boundaries of this tile?
if (x1 < xi) continue;
if (x0 > (xi+X_TILESIZE-1)) continue;
// is redraw rectangle outside y boundaries of this tile?
if (y1 < yi) continue;
if (y0 > (yi+Y_TILESIZE-1)) continue;
unsigned xti = xi/X_TILESIZE;
unsigned yti = yi/Y_TILESIZE;
SET_TILE_UPDATED (xti, yti, 1);
}
}
}
void
bx_svga_cirrus_c::mem_write_mode4and5_8bpp(Bit8u mode, Bit32u offset, Bit8u value)
{
int x;
Bit8u val = value;
Bit8u *dst;
dst = BX_CIRRUS_THIS vidmem + offset;
for (x = 0; x < 8; x++) {
if (val & 0x80) {
*dst++ = BX_CIRRUS_THIS control.shadow_reg1;
} else if (mode == 5) {
*dst++ = BX_CIRRUS_THIS control.shadow_reg0;
}
val <<= 1;
}
}
void
bx_svga_cirrus_c::mem_write_mode4and5_16bpp(Bit8u mode, Bit32u offset, Bit8u value)
{
int x;
Bit8u val = value;
Bit8u *dst;
dst = BX_CIRRUS_THIS vidmem + offset;
for (x = 0; x < 8; x++) {
if (val & 0x80) {
*dst++ = BX_CIRRUS_THIS control.shadow_reg1;
*dst++ = BX_CIRRUS_THIS control.reg[0x11];
} else if (mode == 5) {
*dst++ = BX_CIRRUS_THIS control.shadow_reg0;
*dst++ = BX_CIRRUS_THIS control.reg[0x10];
}
val <<= 1;
}
}
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
bx_bool
bx_svga_cirrus_c::cirrus_mem_read_handler(unsigned long addr, unsigned long len,
void *data, void *param)
{
Bit8u *data_ptr;
#ifdef BX_LITTLE_ENDIAN
data_ptr = (Bit8u *) data;
#else // BX_BIG_ENDIAN
data_ptr = (Bit8u *) data + (len - 1);
#endif
for (unsigned i = 0; i < len; i++) {
*data_ptr = BX_CIRRUS_THIS mem_read(addr);
addr++;
#ifdef BX_LITTLE_ENDIAN
data_ptr++;
#else // BX_BIG_ENDIAN
data_ptr--;
#endif
}
return 1;
}
#endif
Bit8u
bx_svga_cirrus_c::mem_read(Bit32u addr)
{
if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
return BX_CIRRUS_THIS bx_vga_c::mem_read(addr);
}
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
if (BX_CIRRUS_THIS pci_enabled) {
if ((addr >= BX_CIRRUS_THIS pci_memaddr) &&
(addr < (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE - 256))) {
Bit8u *ptr;
Bit32u offset;
// video-to-cpu BLT
if (BX_CIRRUS_THIS bitblt.memdst_needed != 0) {
ptr = BX_CIRRUS_THIS bitblt.memdst_ptr;
if (ptr != BX_CIRRUS_THIS bitblt.memdst_endptr) {
BX_CIRRUS_THIS bitblt.memdst_ptr ++;
return *ptr;
}
if (!svga_asyncbitblt_next()) {
ptr = BX_CIRRUS_THIS bitblt.memdst_ptr;
BX_CIRRUS_THIS bitblt.memdst_ptr ++;
return *ptr;
}
}
ptr = BX_CIRRUS_THIS vidmem;
offset = addr - BX_CIRRUS_THIS pci_memaddr;
if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) {
offset <<= 4;
} else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) {
offset <<= 3;
}
return *(ptr + offset);
} else if ((addr >= (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE - 256)) &&
(addr < (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE))) {
Bit32u offset = addr - (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE - 256);
return svga_mmio_blt_read(offset & 0xff);
} else if ((addr >= BX_CIRRUS_THIS pci_mmioaddr) &&
(addr < (BX_CIRRUS_THIS pci_mmioaddr + CIRRUS_PNPMMIO_SIZE))) {
Bit32u offset;
offset = addr - BX_CIRRUS_THIS pci_mmioaddr;
if (offset >= 0x100) {
return svga_mmio_blt_read(offset - 0x100);
} else {
return svga_mmio_vga_read(offset);
}
}
}
#endif // BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
if (addr >= 0xA0000 && addr <= 0xAFFFF)
{
Bit32u bank;
Bit32u offset;
Bit8u *ptr;
// video-to-cpu BLT
if (BX_CIRRUS_THIS bitblt.memdst_needed != 0) {
ptr = BX_CIRRUS_THIS bitblt.memdst_ptr;
if (ptr != BX_CIRRUS_THIS bitblt.memdst_endptr) {
BX_CIRRUS_THIS bitblt.memdst_ptr ++;
return *ptr;
}
if (!svga_asyncbitblt_next()) {
ptr = BX_CIRRUS_THIS bitblt.memdst_ptr;
BX_CIRRUS_THIS bitblt.memdst_ptr ++;
return *ptr;
}
}
offset = addr & 0xffff;
bank = (offset >> 15);
offset &= 0x7fff;
if (offset < bank_limit[bank]) {
offset += bank_base[bank];
if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) {
offset <<= 4;
} else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) {
offset <<= 3;
}
offset &= (CIRRUS_VIDEO_MEMORY_BYTES - 1);
return *(BX_CIRRUS_THIS vidmem + offset);
}
else {
return 0xff;
}
}
else if (addr >= 0xB8000 && addr <= 0xBFFFF) {
// memory-mapped I/O.
Bit32u offset;
offset = addr - 0xb8000;
if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04)
return svga_mmio_blt_read(offset);
}
else {
BX_ERROR(("mem_read 0x%08x",addr));
}
return 0xff;
}
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
bx_bool
bx_svga_cirrus_c::cirrus_mem_write_handler(unsigned long addr, unsigned long len,
void *data, void *param)
{
Bit8u *data_ptr;
#ifdef BX_LITTLE_ENDIAN
data_ptr = (Bit8u *) data;
#else // BX_BIG_ENDIAN
data_ptr = (Bit8u *) data + (len - 1);
#endif
for (unsigned i = 0; i < len; i++) {
BX_CIRRUS_THIS mem_write(addr, *data_ptr);
addr++;
#ifdef BX_LITTLE_ENDIAN
data_ptr++;
#else // BX_BIG_ENDIAN
data_ptr--;
#endif
}
return 1;
}
#endif
void
bx_svga_cirrus_c::mem_write(Bit32u addr, Bit8u value)
{
if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
BX_CIRRUS_THIS bx_vga_c::mem_write(addr,value);
return;
}
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
if (BX_CIRRUS_THIS pci_enabled) {
if ((addr >= BX_CIRRUS_THIS pci_memaddr) &&
(addr < (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE - 256))) {
Bit32u offset;
Bit8u mode;
// cpu-to-video BLT
if (BX_CIRRUS_THIS bitblt.memsrc_needed != 0) {
*(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value);
if (bitblt.memsrc_ptr == BX_CIRRUS_THIS bitblt.memsrc_endptr) {
svga_asyncbitblt_next();
}
return;
}
offset = addr - BX_CIRRUS_THIS pci_memaddr;
// BX_DEBUG(("write offset 0x%08x,value 0x%02x",offset,value));
if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) {
offset <<= 4;
} else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) {
offset <<= 3;
}
mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07;
if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) {
*(BX_CIRRUS_THIS vidmem + offset) = value;
} else {
if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) {
mem_write_mode4and5_8bpp(mode, offset, value);
} else {
mem_write_mode4and5_16bpp(mode, offset, value);
}
}
BX_CIRRUS_THIS svga_needs_update_tile = true;
SET_TILE_UPDATED(((offset % BX_CIRRUS_THIS svga_pitch) / (BX_CIRRUS_THIS svga_bpp / 8)) / X_TILESIZE,
(offset / BX_CIRRUS_THIS svga_pitch) / Y_TILESIZE, 1);
return;
} else if ((addr >= (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE - 256)) &&
(addr < (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE))) {
Bit32u offset = addr - (BX_CIRRUS_THIS pci_memaddr + CIRRUS_PNPMEM_SIZE - 256);
svga_mmio_blt_write(offset & 0xff, value);
return;
} else if ((addr >= BX_CIRRUS_THIS pci_mmioaddr) &&
(addr < (BX_CIRRUS_THIS pci_mmioaddr + CIRRUS_PNPMMIO_SIZE))) {
// memory-mapped I/O.
Bit32u offset;
// BX_DEBUG(("write mmio 0x%08x",addr));
offset = addr - BX_CIRRUS_THIS pci_mmioaddr;
if (offset >= 0x100) {
svga_mmio_blt_write(offset - 0x100, value);
} else {
svga_mmio_vga_write(offset,value);
}
return;
}
}
#endif // BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
if (addr >= 0xA0000 && addr <= 0xAFFFF) {
Bit32u bank, offset;
Bit8u mode;
// cpu-to-video BLT
if (BX_CIRRUS_THIS bitblt.memsrc_needed != 0) {
*(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value);
if (BX_CIRRUS_THIS bitblt.memsrc_ptr == BX_CIRRUS_THIS bitblt.memsrc_endptr) {
svga_asyncbitblt_next();
}
return;
}
offset = addr & 0xffff;
bank = (offset >> 15);
offset &= 0x7fff;
if (offset < bank_limit[bank]) {
offset += bank_base[bank];
if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) {
offset <<= 4;
} else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) {
offset <<= 3;
}
offset &= (CIRRUS_VIDEO_MEMORY_BYTES - 1);
mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07;
if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) {
*(BX_CIRRUS_THIS vidmem + offset) = value;
} else {
if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) {
mem_write_mode4and5_8bpp(mode, offset, value);
} else {
mem_write_mode4and5_16bpp(mode, offset, value);
}
}
BX_CIRRUS_THIS svga_needs_update_tile = true;
SET_TILE_UPDATED(((offset % BX_CIRRUS_THIS svga_pitch) / (BX_CIRRUS_THIS svga_bpp / 8)) / X_TILESIZE,
(offset / BX_CIRRUS_THIS svga_pitch) / Y_TILESIZE, 1);
}
} else if (addr >= 0xB8000 && addr <= 0xBFFFF) {
// memory-mapped I/O.
Bit32u offset;
offset = addr - 0xb8000;
if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04) {
svga_mmio_blt_write(offset & 0xff, value);
}
}
else {
BX_ERROR(("mem_write 0x%08x, value 0x%02x",addr,value));
}
}
void
bx_svga_cirrus_c::get_text_snapshot(Bit8u **text_snapshot,
unsigned *txHeight, unsigned *txWidth)
{
BX_CIRRUS_THIS bx_vga_c::get_text_snapshot(text_snapshot,txHeight,txWidth);
}
void
bx_svga_cirrus_c::trigger_timer(void *this_ptr)
{
BX_CIRRUS_THIS timer_handler(this_ptr);
}
void
bx_svga_cirrus_c::set_update_interval (unsigned interval)
{
BX_INFO (("Changing timer interval to %d", interval));
BX_CIRRUS_THIS svga_timer_handler (theSvga);
bx_pc_system.activate_timer (BX_CIRRUS_THIS timer_id, interval, 1);
}
Bit8u
bx_svga_cirrus_c::get_actl_palette_idx(Bit8u index)
{
return BX_CIRRUS_THIS bx_vga_c::get_actl_palette_idx(index);
}
Bit32u
bx_svga_cirrus_c::svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len)
{
#if !BX_USE_CIRRUS_SMF
bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr;
return( class_ptr->svga_read(address, io_len) );
}
Bit32u
bx_svga_cirrus_c::svga_read(Bit32u address, unsigned io_len)
{
#else
UNUSED(this_ptr);
#endif // !BX_USE_CIRRUS_SMF
if ((io_len == 2) && ((address & 1) == 0)) {
Bit32u value;
value = (Bit32u)SVGA_READ(address,1);
value |= (Bit32u)SVGA_READ(address+1,1) << 8;
return value;
}
if (io_len != 1) {
BX_PANIC(("SVGA read: io_len != 1"));
}
switch (address) {
case 0x03b4: /* VGA: CRTC Index Register (monochrome emulation modes) */
case 0x03d4: /* VGA: CRTC Index Register (color emulation modes) */
return BX_CIRRUS_THIS crtc.index;
case 0x03b5: /* VGA: CRTC Registers (monochrome emulation modes) */
case 0x03d5: /* VGA: CRTC Registers (color emulation modes) */
if (BX_CIRRUS_THIS is_unlocked())
return BX_CIRRUS_THIS svga_read_crtc(address,BX_CIRRUS_THIS crtc.index);
break;
case 0x03c4: /* VGA: Sequencer Index Register */
return BX_CIRRUS_THIS sequencer.index;
case 0x03c5: /* VGA: Sequencer Registers */
if ((BX_CIRRUS_THIS sequencer.index == 0x06) ||
(BX_CIRRUS_THIS is_unlocked())) {
return BX_CIRRUS_THIS svga_read_sequencer(address,BX_CIRRUS_THIS sequencer.index);
}
break;
case 0x03c6: /* Hidden DAC */
if (BX_CIRRUS_THIS is_unlocked()) {
if ((++BX_CIRRUS_THIS hidden_dac.lockindex) == 5) {
BX_CIRRUS_THIS hidden_dac.lockindex = 0;
return BX_CIRRUS_THIS hidden_dac.data;
}
}
break;
case 0x03c8: /* PEL write address */
BX_CIRRUS_THIS hidden_dac.lockindex = 0;
break;
case 0x03c9: /* PEL Data Register, hiddem pel colors 00..0F */
if (BX_CIRRUS_THIS sequencer.reg[0x12] & CIRRUS_CURSOR_HIDDENPEL) {
Bit8u index = (BX_CIRRUS_THIS s.pel.read_data_register & 0x0f) * 3 +
BX_CIRRUS_THIS s.pel.read_data_cycle;
Bit8u retval = BX_CIRRUS_THIS hidden_dac.palette[index];
BX_CIRRUS_THIS s.pel.read_data_cycle ++;
if (BX_CIRRUS_THIS s.pel.read_data_cycle >= 3) {
BX_CIRRUS_THIS s.pel.read_data_cycle = 0;
BX_CIRRUS_THIS s.pel.read_data_register++;
}
return retval;
}
break;
case 0x03ce: /* VGA: Graphics Controller Index Register */
return BX_CIRRUS_THIS control.index;
case 0x03cf: /* VGA: Graphics Controller Registers */
if (BX_CIRRUS_THIS is_unlocked())
return BX_CIRRUS_THIS svga_read_control(address,BX_CIRRUS_THIS control.index);
break;
default:
break;
}
return VGA_READ(address,io_len);
}
void
bx_svga_cirrus_c::svga_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
{
#if !BX_USE_CIRRUS_SMF
bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr;
class_ptr->svga_write(address, value, io_len);
}
void
bx_svga_cirrus_c::svga_write(Bit32u address, Bit32u value, unsigned io_len)
{
#else
UNUSED(this_ptr);
#endif // !BX_USE_CIRRUS_SMF
if ((io_len == 2) && ((address & 1) == 0)) {
SVGA_WRITE(address,value & 0xff,1);
SVGA_WRITE(address+1,value >> 8,1);
return;
}
if (io_len != 1) {
BX_PANIC(("SVGA write: io_len != 1"));
}
switch (address) {
case 0x03b4: /* VGA: CRTC Index Register (monochrome emulation modes) */
case 0x03d4: /* VGA: CRTC Index Register (color emulation modes) */
BX_CIRRUS_THIS crtc.index = value & 0x7f;
break;
case 0x03b5: /* VGA: CRTC Registers (monochrome emulation modes) */
case 0x03d5: /* VGA: CRTC Registers (color emulation modes) */
if (BX_CIRRUS_THIS is_unlocked()) {
BX_CIRRUS_THIS svga_write_crtc(address,BX_CIRRUS_THIS crtc.index,value);
return;
}
break;
case 0x03c4: /* VGA: Sequencer Index Register */
BX_CIRRUS_THIS sequencer.index = value;
break;
case 0x03c5: /* VGA: Sequencer Registers */
if ((BX_CIRRUS_THIS sequencer.index == 0x06) ||
(BX_CIRRUS_THIS is_unlocked())) {
BX_CIRRUS_THIS svga_write_sequencer(address,BX_CIRRUS_THIS sequencer.index,value);
return;
}
break;
case 0x03c6: /* Hidden DAC */
if (BX_CIRRUS_THIS is_unlocked()) {
if (BX_CIRRUS_THIS hidden_dac.lockindex == 4) {
BX_CIRRUS_THIS hidden_dac.data = value;
}
BX_CIRRUS_THIS hidden_dac.lockindex = 0;
return;
}
break;
case 0x03c9: /* PEL Data Register, hidden pel colors 00..0F */
BX_CIRRUS_THIS svga_needs_update_dispentire = true;
if (BX_CIRRUS_THIS sequencer.reg[0x12] & CIRRUS_CURSOR_HIDDENPEL) {
Bit8u index = (BX_CIRRUS_THIS s.pel.write_data_register & 0x0f) * 3 +
BX_CIRRUS_THIS s.pel.write_data_cycle;
BX_CIRRUS_THIS hidden_dac.palette[index] = value;
BX_CIRRUS_THIS s.pel.write_data_cycle ++;
if (BX_CIRRUS_THIS s.pel.write_data_cycle >= 3) {
BX_CIRRUS_THIS s.pel.write_data_cycle = 0;
BX_CIRRUS_THIS s.pel.write_data_register++;
}
return;
}
break;
case 0x03ce: /* VGA: Graphics Controller Index Register */
BX_CIRRUS_THIS control.index = value;
break;
case 0x03cf: /* VGA: Graphics Controller Registers */
if (BX_CIRRUS_THIS is_unlocked()) {
BX_CIRRUS_THIS svga_write_control(address,BX_CIRRUS_THIS control.index,value);
return;
}
break;
default:
break;
}
VGA_WRITE(address,value,io_len);
}
void
bx_svga_cirrus_c::svga_timer_handler(void *this_ptr)
{
#if !BX_USE_CIRRUS_SMF
bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr;
class_ptr->svga_timer();
}
void
bx_svga_cirrus_c::svga_timer(void)
{
#else // !BX_USE_CIRRUS_SMF
UNUSED(this_ptr);
#endif // !BX_USE_CIRRUS_SMF
BX_CIRRUS_THIS svga_update();
bx_gui->flush();
}
void
bx_svga_cirrus_c::svga_modeupdate(void)
{
Bit32u iTopOffset, iHeight;
int width, iBpp, iDispBpp;
iTopOffset = (BX_CIRRUS_THIS crtc.reg[0x0c] << 8)
+ BX_CIRRUS_THIS crtc.reg[0x0d]
+ ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x01) << 16)
+ ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x0c) << 15)
+ ((BX_CIRRUS_THIS crtc.reg[0x1d] & 0x80) << 12);
iTopOffset <<= 2;
iHeight = 1 + BX_CIRRUS_THIS crtc.reg[0x12]
+ ((BX_CIRRUS_THIS crtc.reg[0x07] & 0x02) << 7)
+ ((BX_CIRRUS_THIS crtc.reg[0x07] & 0x40) << 3);
if ((BX_CIRRUS_THIS crtc.reg[0x1a] & 0x01) > 0) {
iHeight <<= 1;
}
width = (BX_CIRRUS_THIS crtc.reg[0x01] + 1) * 8;
iBpp = 8;
iDispBpp = 4;
if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x1) == CIRRUS_SR7_BPP_SVGA) {
switch (BX_CIRRUS_THIS sequencer.reg[0x07] & CIRRUS_SR7_BPP_MASK) {
case CIRRUS_SR7_BPP_8:
iBpp = 8;
iDispBpp = 8;
break;
case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
case CIRRUS_SR7_BPP_16:
iBpp = 16;
iDispBpp = (BX_CIRRUS_THIS hidden_dac.data & 0x1) ? 16 : 15;
break;
case CIRRUS_SR7_BPP_24:
iBpp = 24;
iDispBpp = 24;
break;
case CIRRUS_SR7_BPP_32:
iBpp = 32;
iDispBpp = 32;
break;
default:
BX_PANIC(("unknown bpp - seqencer.reg[0x07] = %02x",BX_CIRRUS_THIS sequencer.reg[0x07]));
break;
}
}
BX_INFO(("switched to %u x %u x %u",width,iHeight,iDispBpp));
BX_CIRRUS_THIS svga_xres = width;
BX_CIRRUS_THIS svga_yres = iHeight;
BX_CIRRUS_THIS svga_bpp = iBpp;
BX_CIRRUS_THIS svga_dispbpp = iDispBpp;
BX_CIRRUS_THIS disp_ptr = BX_CIRRUS_THIS vidmem + iTopOffset;
}
void
bx_svga_cirrus_c::draw_hardware_cursor(unsigned xc, unsigned yc, bx_svga_tileinfo_t *info)
{
if (BX_CIRRUS_THIS hw_cursor.size &&
(xc < BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size) &&
(xc+X_TILESIZE > BX_CIRRUS_THIS hw_cursor.x) &&
(yc < BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size) &&
(yc+Y_TILESIZE > BX_CIRRUS_THIS hw_cursor.y)) {
int i;
unsigned w, h, pitch, cx, cy, cx0, cy0, cx1, cy1;
Bit8u * tile_ptr, * tile_ptr2;
Bit8u * plane0_ptr, *plane0_ptr2;
Bit8u * plane1_ptr, *plane1_ptr2;
unsigned long fgcol, bgcol;
Bit64u plane0, plane1;
cx0 = BX_CIRRUS_THIS hw_cursor.x > xc ? BX_CIRRUS_THIS hw_cursor.x : xc;
cy0 = BX_CIRRUS_THIS hw_cursor.y > yc ? BX_CIRRUS_THIS hw_cursor.y : yc;
cx1 = BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size < xc+X_TILESIZE ? BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size : xc+X_TILESIZE;
cy1 = BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size < yc+Y_TILESIZE ? BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size : yc+Y_TILESIZE;
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h) +
info->pitch * (cy0 - yc) + (info->bpp / 8) * (cx0 - xc);
plane0_ptr = BX_CIRRUS_THIS vidmem + BX_CIRRUS_THIS memsize - 16384;
switch (BX_CIRRUS_THIS hw_cursor.size) {
case 32:
plane0_ptr += (BX_CIRRUS_THIS sequencer.reg[0x13] & 0x3f) * 256;
plane1_ptr = plane0_ptr + 128;
pitch = 4;
break;
case 64:
plane0_ptr += (BX_CIRRUS_THIS sequencer.reg[0x13] & 0x3c) * 256;
plane1_ptr = plane0_ptr + 8;
pitch = 16;
break;
default:
BX_ERROR(("unsupported hardware cursor size"));
return;
break;
}
fgcol = MAKE_COLOUR(
BX_CIRRUS_THIS hidden_dac.palette[45], 6, info->red_shift, info->red_mask,
BX_CIRRUS_THIS hidden_dac.palette[46], 6, info->green_shift, info->green_mask,
BX_CIRRUS_THIS hidden_dac.palette[47], 6, info->blue_shift, info->blue_mask);
bgcol = MAKE_COLOUR(
BX_CIRRUS_THIS hidden_dac.palette[0], 6, info->red_shift, info->red_mask,
BX_CIRRUS_THIS hidden_dac.palette[1], 6, info->green_shift, info->green_mask,
BX_CIRRUS_THIS hidden_dac.palette[2], 6, info->blue_shift, info->blue_mask);
plane0_ptr += pitch * (cy0 - BX_CIRRUS_THIS hw_cursor.y);
plane1_ptr += pitch * (cy0 - BX_CIRRUS_THIS hw_cursor.y);
for (cy=cy0; cy<cy1; cy++) {
tile_ptr2 = tile_ptr + (info->bpp/8) * (cx1 - cx0) - 1;
plane0_ptr2 = plane0_ptr;
plane1_ptr2 = plane1_ptr;
plane0 = plane1 = 0;
for (i=0; i<BX_CIRRUS_THIS hw_cursor.size; i+=8) {
plane0 = (plane0 << 8) | *(plane0_ptr2++);
plane1 = (plane1 << 8) | *(plane1_ptr2++);
}
plane0 >>= BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size - cx1;
plane1 >>= BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size - cx1;
for (cx=cx0; cx<cx1; cx++) {
if (plane0 & 1) {
if (plane1 & 1) {
if (info->is_little_endian) {
for (i=info->bpp-8; i>-8; i-=8) {
*(tile_ptr2--) = fgcol >> i;
}
}
else {
for (i=0; i<info->bpp; i+=8) {
*(tile_ptr2--) = fgcol >> i;
}
}
}
else {
for (i=0; i<info->bpp; i+=8) {
*(tile_ptr2--) ^= 0xff;
}
}
}
else {
if (plane1 & 1) {
if (info->is_little_endian) {
for (i=info->bpp-8; i>-8; i-=8) {
*(tile_ptr2--) = bgcol >> i;
}
}
else {
for (i=0; i<info->bpp; i+=8) {
*(tile_ptr2--) = bgcol >> i;
}
}
}
else {
tile_ptr2 -= (info->bpp/8);
}
}
plane0 >>= 1;
plane1 >>= 1;
}
tile_ptr += info->pitch;
plane0_ptr += pitch;
plane1_ptr += pitch;
}
}
}
void
bx_svga_cirrus_c::svga_update(void)
{
unsigned width, height, pitch;
/* skip screen update when the sequencer is in reset mode or video is disabled */
if (! BX_CIRRUS_THIS s.sequencer.reset1 ||
! BX_CIRRUS_THIS s.sequencer.reset2 ||
! BX_CIRRUS_THIS s.attribute_ctrl.video_enabled) {
return;
}
if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) {
if (BX_CIRRUS_THIS svga_needs_update_mode) {
BX_CIRRUS_THIS s.vga_mem_updated = 1;
BX_CIRRUS_THIS svga_needs_update_mode = false;
}
BX_CIRRUS_THIS bx_vga_c::update();
return;
}
else {
if (BX_CIRRUS_THIS svga_needs_update_mode) {
svga_modeupdate();
}
}
width = BX_CIRRUS_THIS svga_xres;
height = BX_CIRRUS_THIS svga_yres;
pitch = BX_CIRRUS_THIS svga_pitch;
if (BX_CIRRUS_THIS svga_needs_update_mode) {
width = BX_CIRRUS_THIS svga_xres;
height = BX_CIRRUS_THIS svga_yres;
bx_gui->dimension_update(width, height, 0, 0, BX_CIRRUS_THIS svga_dispbpp);
BX_CIRRUS_THIS svga_needs_update_mode = false;
BX_CIRRUS_THIS svga_needs_update_dispentire = true;
}
if (BX_CIRRUS_THIS svga_needs_update_dispentire) {
BX_CIRRUS_THIS redraw_area(0,0,width,height);
BX_CIRRUS_THIS svga_needs_update_dispentire = false;
}
if (!BX_CIRRUS_THIS svga_needs_update_tile) {
return;
}
BX_CIRRUS_THIS svga_needs_update_tile = false;
unsigned xc, yc, xti, yti;
unsigned r, c, w, h;
int i;
unsigned long red, green, blue, colour;
Bit8u * vid_ptr, * vid_ptr2;
Bit8u * tile_ptr, * tile_ptr2;
bx_svga_tileinfo_t info;
if (bx_gui->graphics_tile_info(&info)) {
if (info.is_indexed) {
switch (BX_CIRRUS_THIS svga_dispbpp) {
case 4:
case 15:
case 16:
case 24:
case 32:
BX_ERROR(("current guest pixel format is unsupported on indexed colour host displays"));
break;
case 8:
for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED (xti, yti)) {
vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + xc);
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
for (r=0; r<h; r++) {
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
colour = 0;
for (i=0; i<(int)BX_CIRRUS_THIS svga_bpp; i+=8) {
colour |= *(vid_ptr2++) << i;
}
if (info.is_little_endian) {
for (i=0; i<info.bpp; i+=8) {
*(tile_ptr2++) = colour >> i;
}
}
else {
for (i=info.bpp-8; i>-8; i-=8) {
*(tile_ptr2++) = colour >> i;
}
}
}
vid_ptr += pitch;
tile_ptr += info.pitch;
}
// FIXME? hardware cursor unsupported
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
SET_TILE_UPDATED (xti, yti, 0);
}
}
}
break;
}
}
else {
switch (BX_CIRRUS_THIS svga_dispbpp) {
case 4:
BX_ERROR(("cannot draw 4bpp SVGA"));
break;
case 8:
for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED (xti, yti)) {
vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + xc);
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
for (r=0; r<h; r++) {
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
colour = *(vid_ptr2++);
colour = MAKE_COLOUR(
BX_CIRRUS_THIS s.pel.data[colour].red, 6, info.red_shift, info.red_mask,
BX_CIRRUS_THIS s.pel.data[colour].green, 6, info.green_shift, info.green_mask,
BX_CIRRUS_THIS s.pel.data[colour].blue, 6, info.blue_shift, info.blue_mask);
if (info.is_little_endian) {
for (i=0; i<info.bpp; i+=8) {
*(tile_ptr2++) = colour >> i;
}
}
else {
for (i=info.bpp-8; i>-8; i-=8) {
*(tile_ptr2++) = colour >> i;
}
}
}
vid_ptr += pitch;
tile_ptr += info.pitch;
}
draw_hardware_cursor(xc, yc, &info);
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
SET_TILE_UPDATED (xti, yti, 0);
}
}
}
break;
case 15:
for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED (xti, yti)) {
vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + (xc<<1));
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
for (r=0; r<h; r++) {
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
colour = *(vid_ptr2++);
colour |= *(vid_ptr2++) << 8;
colour = MAKE_COLOUR(
colour & 0x001f, 5, info.blue_shift, info.blue_mask,
colour & 0x03e0, 10, info.green_shift, info.green_mask,
colour & 0x7c00, 15, info.red_shift, info.red_mask);
if (info.is_little_endian) {
for (i=0; i<info.bpp; i+=8) {
*(tile_ptr2++) = colour >> i;
}
}
else {
for (i=info.bpp-8; i>-8; i-=8) {
*(tile_ptr2++) = colour >> i;
}
}
}
vid_ptr += pitch;
tile_ptr += info.pitch;
}
draw_hardware_cursor(xc, yc, &info);
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
SET_TILE_UPDATED (xti, yti, 0);
}
}
}
break;
case 16:
for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED (xti, yti)) {
vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + (xc<<1));
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
for (r=0; r<h; r++) {
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
colour = *(vid_ptr2++);
colour |= *(vid_ptr2++) << 8;
colour = MAKE_COLOUR(
colour & 0x001f, 5, info.blue_shift, info.blue_mask,
colour & 0x07e0, 11, info.green_shift, info.green_mask,
colour & 0xf800, 16, info.red_shift, info.red_mask);
if (info.is_little_endian) {
for (i=0; i<info.bpp; i+=8) {
*(tile_ptr2++) = colour >> i;
}
}
else {
for (i=info.bpp-8; i>-8; i-=8) {
*(tile_ptr2++) = colour >> i;
}
}
}
vid_ptr += pitch;
tile_ptr += info.pitch;
}
draw_hardware_cursor(xc, yc, &info);
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
SET_TILE_UPDATED (xti, yti, 0);
}
}
}
break;
case 24:
for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED (xti, yti)) {
vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + 3*xc);
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
for (r=0; r<h; r++) {
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
blue = *(vid_ptr2++);
green = *(vid_ptr2++);
red = *(vid_ptr2++);
colour = MAKE_COLOUR(
red, 8, info.red_shift, info.red_mask,
green, 8, info.green_shift, info.green_mask,
blue, 8, info.blue_shift, info.blue_mask);
if (info.is_little_endian) {
for (i=0; i<info.bpp; i+=8) {
*(tile_ptr2++) = colour >> i;
}
}
else {
for (i=info.bpp-8; i>-8; i-=8) {
*(tile_ptr2++) = colour >> i;
}
}
}
vid_ptr += pitch;
tile_ptr += info.pitch;
}
draw_hardware_cursor(xc, yc, &info);
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
SET_TILE_UPDATED (xti, yti, 0);
}
}
}
break;
case 32:
for (yc=0, yti = 0; yc<height; yc+=Y_TILESIZE, yti++) {
for (xc=0, xti = 0; xc<width; xc+=X_TILESIZE, xti++) {
if (GET_TILE_UPDATED (xti, yti)) {
vid_ptr = BX_CIRRUS_THIS disp_ptr + (yc * pitch + (xc<<2));
tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
for (r=0; r<h; r++) {
vid_ptr2 = vid_ptr;
tile_ptr2 = tile_ptr;
for (c=0; c<w; c++) {
blue = *(vid_ptr2++);
green = *(vid_ptr2++);
red = *(vid_ptr2++);
vid_ptr2++;
colour = MAKE_COLOUR(
red, 8, info.red_shift, info.red_mask,
green, 8, info.green_shift, info.green_mask,
blue, 8, info.blue_shift, info.blue_mask);
if (info.is_little_endian) {
for (i=0; i<info.bpp; i+=8) {
*(tile_ptr2++) = colour >> i;
}
}
else {
for (i=info.bpp-8; i>-8; i-=8) {
*(tile_ptr2++) = colour >> i;
}
}
}
vid_ptr += pitch;
tile_ptr += info.pitch;
}
draw_hardware_cursor(xc, yc, &info);
bx_gui->graphics_tile_update_in_place(xc, yc, w, h);
SET_TILE_UPDATED (xti, yti, 0);
}
}
}
break;
}
}
}
else {
BX_PANIC(("cannot get svga tile info"));
}
}
void
bx_svga_cirrus_c::update_bank_ptr(Bit8u bank_index)
{
unsigned offset;
unsigned limit;
if (BX_CIRRUS_THIS banking_is_dual())
offset = BX_CIRRUS_THIS control.reg[0x09 + bank_index];
else
offset = BX_CIRRUS_THIS control.reg[0x09];
if (BX_CIRRUS_THIS banking_granularity_is_16k())
offset <<= 14;
else
offset <<= 12;
if (CIRRUS_VIDEO_MEMORY_BYTES <= offset) {
limit = 0;
BX_ERROR(("bank offset %08x is invalid",offset));
} else {
limit = CIRRUS_VIDEO_MEMORY_BYTES - offset;
}
if (!BX_CIRRUS_THIS banking_is_dual() && (bank_index != 0)) {
if (limit > 0x8000) {
offset += 0x8000;
limit -= 0x8000;
} else {
limit = 0;
}
}
if (limit > 0) {
BX_CIRRUS_THIS bank_base[bank_index] = offset;
BX_CIRRUS_THIS bank_limit[bank_index] = limit;
} else {
BX_CIRRUS_THIS bank_base[bank_index] = 0;
BX_CIRRUS_THIS bank_limit[bank_index] = 0;
}
}
Bit8u
bx_svga_cirrus_c::svga_read_crtc(Bit32u address, unsigned index)
{
switch (index) {
case 0x00: // VGA
case 0x01: // VGA
case 0x02: // VGA
case 0x03: // VGA
case 0x04: // VGA
case 0x05: // VGA
case 0x06: // VGA
case 0x07: // VGA
case 0x08: // VGA
case 0x09: // VGA
case 0x0a: // VGA
case 0x0b: // VGA
case 0x0c: // VGA
case 0x0d: // VGA
case 0x0e: // VGA
case 0x0f: // VGA
case 0x10: // VGA
case 0x11: // VGA
case 0x12: // VGA
case 0x13: // VGA
case 0x14: // VGA
case 0x15: // VGA
case 0x16: // VGA
case 0x17: // VGA
case 0x18: // VGA
break;
case 0x19:
case 0x1A:
case 0x1B:
case 0x1C:
case 0x1D:
case 0x22:
case 0x24:
case 0x25:
case 0x27:
break;
case 0x26:
return (BX_CIRRUS_THIS s.attribute_ctrl.address & 0x3f);
default:
BX_ERROR(("CRTC index 0x%02x is unknown(read)", index));
break;
}
if (index <= VGA_CRTC_MAX) {
return VGA_READ(address,1);
}
if (index <= CIRRUS_CRTC_MAX) {
return BX_CIRRUS_THIS crtc.reg[index];
}
return 0xff;
}
void
bx_svga_cirrus_c::svga_write_crtc(Bit32u address, unsigned index, Bit8u value)
{
BX_DEBUG(("crtc: index 0x%02x write 0x%02x", index, (unsigned)value));
bx_bool update_pitch = 0;
switch (index) {
case 0x00: // VGA
case 0x02: // VGA
case 0x03: // VGA
case 0x04: // VGA
case 0x05: // VGA
case 0x06: // VGA
case 0x08: // VGA
case 0x0a: // VGA
case 0x0b: // VGA
case 0x0e: // VGA
case 0x0f: // VGA
case 0x10: // VGA
case 0x11: // VGA
case 0x14: // VGA
case 0x15: // VGA
case 0x16: // VGA
case 0x17: // VGA
case 0x18: // VGA
break;
case 0x01: // VGA
case 0x07: // VGA
case 0x09: // VGA
case 0x0c: // VGA (display offset 0x00ff00)
case 0x0d: // VGA (display offset 0x0000ff)
case 0x12: // VGA
case 0x1A: // 0x01: interlaced video mode
case 0x1D: // 0x80: offset 0x080000 (>=CLGD5434)
BX_CIRRUS_THIS svga_needs_update_mode = true;
break;
case 0x13: // VGA
case 0x1B: // 0x01: offset 0x010000, 0x0c: offset 0x060000
update_pitch = 1;
break;
case 0x19:
case 0x1C:
break;
default:
BX_ERROR(("CRTC index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value));
return;
}
if (index <= CIRRUS_CRTC_MAX) {
BX_CIRRUS_THIS crtc.reg[index] = value;
}
if (index <= VGA_CRTC_MAX) {
VGA_WRITE(address,value,1);
}
if (update_pitch) {
BX_CIRRUS_THIS svga_pitch = (BX_CIRRUS_THIS crtc.reg[0x13] << 3) | ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x10) << 7);
BX_CIRRUS_THIS svga_needs_update_mode = true;
}
}
Bit8u
bx_svga_cirrus_c::svga_read_sequencer(Bit32u address, unsigned index)
{
switch (index) {
case 0x00: // VGA
case 0x01: // VGA
case 0x02: // VGA
case 0x03: // VGA
case 0x04: // VGA
break;
case 0x6: // cirrus unlock extensions
case 0x7: // cirrus extended sequencer mode
case 0xf: // cirrus dram control
case 0x12: // graphics cursor attribute
case 0x13: // graphics cursor pattern address offset
case 0x17: // configuration readback & extended control
break;
case 0x10: // cursor xpos << 5 (index & 0x3f)
case 0x30:
case 0x50:
case 0x70:
case 0x90:
case 0xb0:
case 0xd0:
case 0xf0:
return BX_CIRRUS_THIS sequencer.reg[0x10];
case 0x11: // cursor ypos << 5 (index & 0x3f)
case 0x31:
case 0x51:
case 0x71:
case 0x91:
case 0xb1:
case 0xd1:
case 0xf1:
return BX_CIRRUS_THIS sequencer.reg[0x11];
default:
BX_INFO (("sequencer index 0x%02x is unknown(read)", index));
break;
}
if (index <= VGA_SEQENCER_MAX) {
return VGA_READ(address,1);
}
if (index <= CIRRUS_SEQENCER_MAX) {
return BX_CIRRUS_THIS sequencer.reg[index];
}
return 0xff;
}
void
bx_svga_cirrus_c::svga_write_sequencer(Bit32u address, unsigned index, Bit8u value)
{
BX_DEBUG(("sequencer: index 0x%02x write 0x%02x", index, (unsigned)value));
bx_bool update_cursor = 0;
Bit16u x, y, size;
x = BX_CIRRUS_THIS hw_cursor.x;
y = BX_CIRRUS_THIS hw_cursor.y;
size = BX_CIRRUS_THIS hw_cursor.size;
switch (index) {
case 0x00: // VGA
case 0x02: // VGA
case 0x03: // VGA
break;
case 0x01: // VGA
case 0x04: // VGA
BX_CIRRUS_THIS svga_needs_update_mode = true;
break;
case 0x6: // cirrus unlock extensions
value &= 0x17;
if (value == 0x12) {
BX_CIRRUS_THIS svga_unlock_special = true;
BX_CIRRUS_THIS sequencer.reg[0x6] = 0x12;
}
else {
BX_CIRRUS_THIS svga_unlock_special = false;
BX_CIRRUS_THIS sequencer.reg[0x6] = 0x0f;
}
return;
case 0x7: // cirrus extended sequencer mode
if (value != BX_CIRRUS_THIS sequencer.reg[0x7]) {
BX_CIRRUS_THIS svga_needs_update_mode = true;
}
break;
case 0x08:
case 0x09:
case 0x0a: // cirrus scratch reg 1
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x1b:
case 0x1c:
case 0x1d:
case 0x1e:
break;
case 0x0f:
return;
case 0x10: // cursor xpos << 5 (index & 0x3f)
case 0x30:
case 0x50:
case 0x70:
case 0x90:
case 0xb0:
case 0xd0:
case 0xf0:
BX_CIRRUS_THIS sequencer.reg[0x10] = value;
x = BX_CIRRUS_THIS hw_cursor.x;
BX_CIRRUS_THIS hw_cursor.x = (value << 3) | (index >> 5);
update_cursor = 1;
break;
case 0x11: // cursor ypos << 5 (index & 0x3f)
case 0x31:
case 0x51:
case 0x71:
case 0x91:
case 0xb1:
case 0xd1:
case 0xf1:
BX_CIRRUS_THIS sequencer.reg[0x11] = value;
y = BX_CIRRUS_THIS hw_cursor.y;
BX_CIRRUS_THIS hw_cursor.y = (value << 3) | (index >> 5);
update_cursor = 1;
break;
case 0x12:
size = BX_CIRRUS_THIS hw_cursor.size;
if (value & CIRRUS_CURSOR_SHOW) {
if (value & CIRRUS_CURSOR_LARGE) {
BX_CIRRUS_THIS hw_cursor.size = 64;
}
else {
BX_CIRRUS_THIS hw_cursor.size = 32;
}
}
else {
BX_CIRRUS_THIS hw_cursor.size = 0;
}
update_cursor = 1;
break;
case 0x13:
update_cursor = 1;
break;
case 0x17:
value = (BX_CIRRUS_THIS sequencer.reg[0x17] & 0x38) | (value & 0xc7);
break;
default:
BX_INFO (("sequencer index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value));
break;
}
if (update_cursor) {
BX_CIRRUS_THIS redraw_area(x, y, size, size);
BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS hw_cursor.x, BX_CIRRUS_THIS hw_cursor.y, BX_CIRRUS_THIS hw_cursor.size, BX_CIRRUS_THIS hw_cursor.size);
}
if (index <= CIRRUS_SEQENCER_MAX) {
BX_CIRRUS_THIS sequencer.reg[index] = value;
}
if (index <= VGA_SEQENCER_MAX) {
VGA_WRITE(address,value,1);
}
}
Bit8u
bx_svga_cirrus_c::svga_read_control(Bit32u address, unsigned index)
{
switch (index) {
case 0x00: // VGA
return BX_CIRRUS_THIS control.shadow_reg0;
case 0x01: // VGA
return BX_CIRRUS_THIS control.shadow_reg1;
case 0x05: // VGA
return BX_CIRRUS_THIS control.reg[index];
case 0x02: // VGA
case 0x03: // VGA
case 0x04: // VGA
case 0x06: // VGA
case 0x07: // VGA
case 0x08: // VGA
break;
case 0x09: // bank offset #0
case 0x0A: // bank offset #1
case 0x0B:
break;
case 0x10: // BGCOLOR 0x0000ff00
case 0x11: // FGCOLOR 0x0000ff00
case 0x12: // BGCOLOR 0x00ff0000
case 0x13: // FGCOLOR 0x00ff0000
case 0x14: // BGCOLOR 0xff000000
case 0x15: // FGCOLOR 0xff000000
break;
case 0x20: // BLT WIDTH 0x0000ff
case 0x21: // BLT WIDTH 0x001f00
case 0x22: // BLT HEIGHT 0x0000ff
case 0x23: // BLT HEIGHT 0x001f00
case 0x24: // BLT DEST PITCH 0x0000ff
case 0x25: // BLT DEST PITCH 0x001f00
case 0x26: // BLT SRC PITCH 0x0000ff
case 0x27: // BLT SRC PITCH 0x001f00
case 0x28: // BLT DEST ADDR 0x0000ff
case 0x29: // BLT DEST ADDR 0x00ff00
case 0x2a: // BLT DEST ADDR 0x3f0000
case 0x2c: // BLT SRC ADDR 0x0000ff
case 0x2d: // BLT SRC ADDR 0x00ff00
case 0x2e: // BLT SRC ADDR 0x3f0000
case 0x2f: // BLT WRITE MASK
case 0x30: // BLT MODE
case 0x31: // BLT STATUS
case 0x32: // RASTER OP
case 0x33: // BLT MODE EXTENSION
case 0x34: // BLT TRANSPARENT COLOR 0x00ff
case 0x35: // BLT TRANSPARENT COLOR 0xff00
case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff
case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00
break;
default:
BX_INFO (("control index 0x%02x is unknown(read)", index));
break;
}
if (index <= VGA_CONTROL_MAX) {
return VGA_READ(address,1);
}
if (index <= CIRRUS_CONTROL_MAX) {
return BX_CIRRUS_THIS control.reg[index];
}
return 0xff;
}
void
bx_svga_cirrus_c::svga_write_control(Bit32u address, unsigned index, Bit8u value)
{
Bit8u old_value;
BX_DEBUG(("control: index 0x%02x write 0x%02x", index, (unsigned)value));
switch (index) {
case 0x00: // VGA
BX_CIRRUS_THIS control.shadow_reg0 = value;
break;
case 0x01: // VGA
BX_CIRRUS_THIS control.shadow_reg1 = value;
break;
case 0x02: // VGA
case 0x03: // VGA
case 0x04: // VGA
case 0x07: // VGA
case 0x08: // VGA
break;
case 0x05: // VGA
case 0x06: // VGA
BX_CIRRUS_THIS svga_needs_update_mode = true;
break;
case 0x09: // bank offset #0
case 0x0A: // bank offset #1
case 0x0B:
BX_CIRRUS_THIS control.reg[index] = value;
update_bank_ptr(0);
update_bank_ptr(1);
break;
case 0x10: // BGCOLOR 0x0000ff00
case 0x11: // FGCOLOR 0x0000ff00
case 0x12: // BGCOLOR 0x00ff0000
case 0x13: // FGCOLOR 0x00ff0000
case 0x14: // BGCOLOR 0xff000000
case 0x15: // FGCOLOR 0xff000000
break;
case 0x20: // BLT WIDTH 0x0000ff
break;
case 0x21: // BLT WIDTH 0x001f00
value &= 0x1f;
break;
case 0x22: // BLT HEIGHT 0x0000ff
break;
case 0x23: // BLT HEIGHT 0x001f00
value &= 0x1f;
break;
case 0x24: // BLT DEST PITCH 0x0000ff
break;
case 0x25: // BLT DEST PITCH 0x001f00
value &= 0x1f;
break;
case 0x26: // BLT SRC PITCH 0x0000ff
break;
case 0x27: // BLT SRC PITCH 0x001f00
value &= 0x1f;
break;
case 0x28: // BLT DEST ADDR 0x0000ff
break;
case 0x29: // BLT DEST ADDR 0x00ff00
break;
case 0x2a: // BLT DEST ADDR 0x3f0000
BX_CIRRUS_THIS control.reg[index] = value & 0x3f;
if (BX_CIRRUS_THIS control.reg[0x31] & CIRRUS_BLT_AUTOSTART) {
svga_bitblt();
}
return;
case 0x2c: // BLT SRC ADDR 0x0000ff
break;
case 0x2d: // BLT SRC ADDR 0x00ff00
break;
case 0x2e: // BLT SRC ADDR 0x3f0000
value &= 0x3f;
break;
case 0x2f: // BLT WRITE MASK
if (value & 0x80) {
BX_ERROR(("BLT WRITE MASK support is not complete (value = 0x%02x)", value));
}
break;
case 0x30: // BLT MODE
break;
case 0x31: // BLT STATUS/START
old_value = BX_CIRRUS_THIS control.reg[0x31];
BX_CIRRUS_THIS control.reg[0x31] = value;
if (((old_value & CIRRUS_BLT_RESET) != 0) &&
((value & CIRRUS_BLT_RESET) == 0)) {
svga_reset_bitblt();
}
else if (((old_value & CIRRUS_BLT_START) == 0) &&
((value & CIRRUS_BLT_START) != 0)) {
BX_CIRRUS_THIS control.reg[0x31] |= CIRRUS_BLT_BUSY;
svga_bitblt();
}
return;
case 0x32: // RASTER OP
case 0x33: // BLT MODE EXTENSION
break;
case 0x34: // BLT TRANSPARENT COLOR 0x00ff
case 0x35: // BLT TRANSPARENT COLOR 0xff00
case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff
case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00
default:
BX_INFO (("control index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value));
break;
}
if (index <= CIRRUS_CONTROL_MAX) {
BX_CIRRUS_THIS control.reg[index] = value;
}
if (index <= VGA_CONTROL_MAX) {
VGA_WRITE(address,value,1);
}
}
Bit8u
bx_svga_cirrus_c::svga_mmio_vga_read(Bit32u address)
{
Bit8u value = 0xff;
// bx_bool svga_unlock_special_old = BX_CIRRUS_THIS svga_unlock_special;
BX_DEBUG(("MMIO vga read - address 0x%04x, value 0x%02x",address,value));
// BX_CIRRUS_THIS svga_unlock_special = true;
#if BX_USE_CIRRUS_SMF
value = (Bit8u)svga_read_handler(theSvga,0x3c0+address,1);
#else // BX_USE_CIRRUS_SMF
value = (Bit8u)svga_read(0x3c0+address,1);
#endif // BX_USE_CIRRUS_SMF
// BX_CIRRUS_THIS svga_unlock_special = svga_unlock_special_old;
return value;
}
void
bx_svga_cirrus_c::svga_mmio_vga_write(Bit32u address,Bit8u value)
{
// bx_bool svga_unlock_special_old = BX_CIRRUS_THIS svga_unlock_special;
BX_DEBUG(("MMIO vga write - address 0x%04x, value 0x%02x",address,value));
// BX_CIRRUS_THIS svga_unlock_special = true;
#if BX_USE_CIRRUS_SMF
svga_write_handler(theSvga,0x3c0+address,value,1);
#else // BX_USE_CIRRUS_SMF
svga_write(0x3c0+address,value,1);
#endif // BX_USE_CIRRUS_SMF
/* switch (BX_CIRRUS_THIS sequencer.reg[0x06]) {
case 0x0f:
svga_unlock_special_old = false;
break;
case 0x12:
svga_unlock_special_old = true;
break;
}
BX_CIRRUS_THIS svga_unlock_special = svga_unlock_special_old;*/
}
Bit8u
bx_svga_cirrus_c::svga_mmio_blt_read(Bit32u address)
{
Bit8u value = 0xff;
switch (address) {
case (CLGD543x_MMIO_BLTBGCOLOR+0):
value = BX_CIRRUS_THIS control.shadow_reg0;
break;
case (CLGD543x_MMIO_BLTBGCOLOR+1):
value = svga_read_control(0x3cf,0x10);
break;
case (CLGD543x_MMIO_BLTBGCOLOR+2):
value = svga_read_control(0x3cf,0x12);
break;
case (CLGD543x_MMIO_BLTBGCOLOR+3):
value = svga_read_control(0x3cf,0x14);
break;
case (CLGD543x_MMIO_BLTFGCOLOR+0):
value = BX_CIRRUS_THIS control.shadow_reg1;
break;
case (CLGD543x_MMIO_BLTFGCOLOR+1):
value = svga_read_control(0x3cf,0x11);
break;
case (CLGD543x_MMIO_BLTFGCOLOR+2):
value = svga_read_control(0x3cf,0x13);
break;
case (CLGD543x_MMIO_BLTFGCOLOR+3):
value = svga_read_control(0x3cf,0x15);
break;
case (CLGD543x_MMIO_BLTWIDTH+0):
value = svga_read_control(0x3cf,0x20);
break;
case (CLGD543x_MMIO_BLTWIDTH+1):
value = svga_read_control(0x3cf,0x21);
break;
case (CLGD543x_MMIO_BLTHEIGHT+0):
value = svga_read_control(0x3cf,0x22);
break;
case (CLGD543x_MMIO_BLTHEIGHT+1):
value = svga_read_control(0x3cf,0x23);
break;
case (CLGD543x_MMIO_BLTDESTPITCH+0):
value = svga_read_control(0x3cf,0x24);
break;
case (CLGD543x_MMIO_BLTDESTPITCH+1):
value = svga_read_control(0x3cf,0x25);
break;
case (CLGD543x_MMIO_BLTSRCPITCH+0):
value = svga_read_control(0x3cf,0x26);
break;
case (CLGD543x_MMIO_BLTSRCPITCH+1):
value = svga_read_control(0x3cf,0x27);
break;
case (CLGD543x_MMIO_BLTDESTADDR+0):
value = svga_read_control(0x3cf,0x28);
break;
case (CLGD543x_MMIO_BLTDESTADDR+1):
value = svga_read_control(0x3cf,0x29);
break;
case (CLGD543x_MMIO_BLTDESTADDR+2):
value = svga_read_control(0x3cf,0x2a);
break;
case (CLGD543x_MMIO_BLTDESTADDR+3):
value = svga_read_control(0x3cf,0x2b);
break;
case (CLGD543x_MMIO_BLTSRCADDR+0):
value = svga_read_control(0x3cf,0x2c);
break;
case (CLGD543x_MMIO_BLTSRCADDR+1):
value = svga_read_control(0x3cf,0x2d);
break;
case (CLGD543x_MMIO_BLTSRCADDR+2):
value = svga_read_control(0x3cf,0x2e);
break;
case CLGD543x_MMIO_BLTWRITEMASK:
value = svga_read_control(0x3cf,0x2f);
break;
case CLGD543x_MMIO_BLTMODE:
value = svga_read_control(0x3cf,0x30);
break;
case CLGD543x_MMIO_BLTROP:
value = svga_read_control(0x3cf,0x32);
break;
case CLGD543x_MMIO_BLTMODEEXT:
value = svga_read_control(0x3cf,0x33);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+0):
value = svga_read_control(0x3cf,0x34);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+1):
value = svga_read_control(0x3cf,0x35);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+2):
BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR"));
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+3):
BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR"));
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+0):
value = svga_read_control(0x3cf,0x38);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+1):
value = svga_read_control(0x3cf,0x39);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+2):
BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK"));
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+3):
BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK"));
break;
case CLGD543x_MMIO_BLTSTATUS:
value = svga_read_control(0x3cf,0x31);
break;
default:
BX_ERROR(("MMIO blt read - address 0x%04x",address));
break;
}
BX_DEBUG(("MMIO blt read - address 0x%04x, value 0x%02x",address,value));
return value;
}
void
bx_svga_cirrus_c::svga_mmio_blt_write(Bit32u address,Bit8u value)
{
BX_DEBUG(("MMIO blt write - address 0x%04x, value 0x%02x",address,value));
switch (address) {
case (CLGD543x_MMIO_BLTBGCOLOR+0):
BX_CIRRUS_THIS control.shadow_reg0 = value;
break;
case (CLGD543x_MMIO_BLTBGCOLOR+1):
svga_write_control(0x3cf,0x10,value);
break;
case (CLGD543x_MMIO_BLTBGCOLOR+2):
svga_write_control(0x3cf,0x12,value);
break;
case (CLGD543x_MMIO_BLTBGCOLOR+3):
svga_write_control(0x3cf,0x14,value);
break;
case (CLGD543x_MMIO_BLTFGCOLOR+0):
BX_CIRRUS_THIS control.shadow_reg1 = value;
break;
case (CLGD543x_MMIO_BLTFGCOLOR+1):
svga_write_control(0x3cf,0x11,value);
break;
case (CLGD543x_MMIO_BLTFGCOLOR+2):
svga_write_control(0x3cf,0x13,value);
break;
case (CLGD543x_MMIO_BLTFGCOLOR+3):
svga_write_control(0x3cf,0x15,value);
break;
case (CLGD543x_MMIO_BLTWIDTH+0):
svga_write_control(0x3cf,0x20,value);
break;
case (CLGD543x_MMIO_BLTWIDTH+1):
svga_write_control(0x3cf,0x21,value);
break;
case (CLGD543x_MMIO_BLTHEIGHT+0):
svga_write_control(0x3cf,0x22,value);
break;
case (CLGD543x_MMIO_BLTHEIGHT+1):
svga_write_control(0x3cf,0x23,value);
break;
case (CLGD543x_MMIO_BLTDESTPITCH+0):
svga_write_control(0x3cf,0x24,value);
break;
case (CLGD543x_MMIO_BLTDESTPITCH+1):
svga_write_control(0x3cf,0x25,value);
break;
case (CLGD543x_MMIO_BLTSRCPITCH+0):
svga_write_control(0x3cf,0x26,value);
break;
case (CLGD543x_MMIO_BLTSRCPITCH+1):
svga_write_control(0x3cf,0x27,value);
break;
case (CLGD543x_MMIO_BLTDESTADDR+0):
svga_write_control(0x3cf,0x28,value);
break;
case (CLGD543x_MMIO_BLTDESTADDR+1):
svga_write_control(0x3cf,0x29,value);
break;
case (CLGD543x_MMIO_BLTDESTADDR+2):
svga_write_control(0x3cf,0x2a,value);
break;
case (CLGD543x_MMIO_BLTDESTADDR+3):
svga_write_control(0x3cf,0x2b,value);
break;
case (CLGD543x_MMIO_BLTSRCADDR+0):
svga_write_control(0x3cf,0x2c,value);
break;
case (CLGD543x_MMIO_BLTSRCADDR+1):
svga_write_control(0x3cf,0x2d,value);
break;
case (CLGD543x_MMIO_BLTSRCADDR+2):
svga_write_control(0x3cf,0x2e,value);
break;
case CLGD543x_MMIO_BLTWRITEMASK:
svga_write_control(0x3cf,0x2f,value);
break;
case CLGD543x_MMIO_BLTMODE:
svga_write_control(0x3cf,0x30,value);
break;
case CLGD543x_MMIO_BLTROP:
svga_write_control(0x3cf,0x32,value);
break;
case CLGD543x_MMIO_BLTMODEEXT:
svga_write_control(0x3cf,0x33,value);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+0):
svga_write_control(0x3cf,0x34,value);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+1):
svga_write_control(0x3cf,0x35,value);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+2):
BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR"));
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+3):
BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR"));
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+0):
svga_write_control(0x3cf,0x38,value);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+1):
svga_write_control(0x3cf,0x39,value);
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+2):
BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK"));
break;
case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+3):
BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK"));
break;
case CLGD543x_MMIO_BLTSTATUS:
svga_write_control(0x3cf,0x31,value);
break;
default:
BX_ERROR(("MMIO blt write - address 0x%04x, value 0x%02x",address,value));
break;
}
}
/////////////////////////////////////////////////////////////////////////
//
// PCI support
//
/////////////////////////////////////////////////////////////////////////
#if BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
void
bx_svga_cirrus_c::svga_init_pcihandlers(void)
{
int i;
// addresses
BX_CIRRUS_THIS pci_memaddr = CIRRUS_PNPMEM_BASE_ADDRESS;
BX_CIRRUS_THIS pci_mmioaddr = CIRRUS_PNPMMIO_BASE_ADDRESS;
Bit8u devfunc = 0x00;
DEV_register_pci_handlers(BX_CIRRUS_THIS_PTR,
pci_read_handler, pci_write_handler,
&devfunc, "cirrus", "PCI SVGA Cirrus");
for (i=0; i<256; i++) {
BX_CIRRUS_THIS pci_conf[i] = 0x0;
}
WriteHostWordToLittleEndian(
&BX_CIRRUS_THIS pci_conf[0x00], PCI_VENDOR_CIRRUS);
WriteHostWordToLittleEndian(
&BX_CIRRUS_THIS pci_conf[0x02], PCI_DEVICE_CLGD5446);
WriteHostWordToLittleEndian(
&BX_CIRRUS_THIS pci_conf[0x04],
(PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS));
BX_CIRRUS_THIS pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
BX_CIRRUS_THIS pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
BX_CIRRUS_THIS pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
}
Bit32u
bx_svga_cirrus_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len)
{
#if !BX_USE_CIRRUS_SMF
return ((bx_svga_cirrus_c *)this_ptr)->pci_read(address,io_len);
}
Bit32u
bx_svga_cirrus_c::pci_read(Bit8u address, unsigned io_len)
{
#endif // !BX_USE_CIRRUS_SMF
unsigned i;
Bit32u ret;
if (io_len > 4) {
BX_PANIC(("pci_read: io_len > 4!"));
return 0xffffffff;
}
if (((unsigned)address + io_len) > 256) {
BX_PANIC(("pci_read: (address + io_len) > 256!"));
return 0xffffffff;
}
ret = 0;
for (i = 0; i < io_len; i++) {
ret |= (Bit32u)(BX_CIRRUS_THIS pci_conf[address + i]) << (i*8);
}
BX_DEBUG(("pci_read: address 0x%02x, io_len 0x%02x, value 0x%x",
(unsigned)address, (unsigned)io_len, (unsigned)ret));
return ret;
}
void
bx_svga_cirrus_c::pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len)
{
#if !BX_USE_CIRRUS_SMF
((bx_svga_cirrus_c *)this_ptr)->pci_write(address,value,io_len);
}
void
bx_svga_cirrus_c::pci_write(Bit8u address, Bit32u value, unsigned io_len)
{
#endif // !BX_USE_CIRRUS_SMF
unsigned i;
unsigned write_addr;
Bit8u new_value, old_value;
bx_bool baseaddr0_change = 0;
bx_bool baseaddr1_change = 0;
BX_DEBUG(("pci_write: address 0x%02x, io_len 0x%02x, value 0x%x",
(unsigned)address, (unsigned)io_len, (unsigned)value));
if ((address > 0x17) && (address < 0x34))
return;
if (io_len <= 4) {
for (i = 0; i < io_len; i++) {
write_addr = address + i;
old_value = BX_CIRRUS_THIS pci_conf[write_addr];
new_value = (Bit8u)(value & 0xff);
switch (write_addr) {
case 0x04: // command bit0-7
new_value &= PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
new_value |= old_value & ~(PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS);
break;
case 0x05: // command bit8-15
new_value = old_value;
break;
case 0x06: // status bit0-7
new_value = old_value & (~new_value);
break;
case 0x07: // status bit8-15
new_value = old_value & (~new_value);
break;
case 0x10: case 0x11: case 0x12: case 0x13: // base address #0
baseaddr0_change = (old_value != new_value);
break;
case 0x14: case 0x15: case 0x16: case 0x17: // base address #1
baseaddr1_change = (old_value != new_value);
break;
// read-only.
case 0x00: case 0x01: // vendor
case 0x02: case 0x03: // device
case 0x08: // revision
case 0x09: case 0x0a: case 0x0b: // class
case 0x0e: // header type
case 0x0f: // built-in self test(unimplemented)
new_value = old_value;
break;
default:
break;
}
BX_CIRRUS_THIS pci_conf[write_addr] = new_value;
value >>= 8;
}
if (baseaddr0_change) {
DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler,
cirrus_mem_write_handler,
&BX_CIRRUS_THIS pci_memaddr,
&BX_CIRRUS_THIS pci_conf[0x10],
CIRRUS_PNPMEM_SIZE);
BX_INFO(("new pci_memaddr: 0x%04x", BX_CIRRUS_THIS pci_memaddr));
}
if (baseaddr1_change) {
DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler,
cirrus_mem_write_handler,
&BX_CIRRUS_THIS pci_mmioaddr,
&BX_CIRRUS_THIS pci_conf[0x14],
CIRRUS_PNPMMIO_SIZE);
BX_INFO(("new pci_mmioaddr = 0x%08x", BX_CIRRUS_THIS pci_mmioaddr));
}
}
}
#endif // BX_SUPPORT_PCI && BX_SUPPORT_CLGD54XX_PCI
/////////////////////////////////////////////////////////////////////////
//
// Bitblt.
//
/////////////////////////////////////////////////////////////////////////
void
bx_svga_cirrus_c::svga_reset_bitblt(void)
{
BX_CIRRUS_THIS control.reg[0x31] &= ~(CIRRUS_BLT_START|CIRRUS_BLT_BUSY|CIRRUS_BLT_FIFOUSED);
BX_CIRRUS_THIS bitblt.rop_handler = NULL;
BX_CIRRUS_THIS bitblt.src = NULL;
BX_CIRRUS_THIS bitblt.dst = NULL;
BX_CIRRUS_THIS bitblt.memsrc_ptr = NULL;
BX_CIRRUS_THIS bitblt.memsrc_endptr = NULL;
BX_CIRRUS_THIS bitblt.memsrc_needed = 0;
BX_CIRRUS_THIS bitblt.memdst_ptr = NULL;
BX_CIRRUS_THIS bitblt.memdst_endptr = NULL;
BX_CIRRUS_THIS bitblt.memdst_needed = 0;
}
void
bx_svga_cirrus_c::svga_bitblt()
{
Bit16u tmp16;
Bit32u tmp32;
Bit32u dstaddr;
Bit32u srcaddr;
Bit32u offset;
ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x20],tmp16);
BX_CIRRUS_THIS bitblt.bltwidth = ((int)tmp16 & (int)0x1fff) + 1;
ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x22],tmp16);
BX_CIRRUS_THIS bitblt.bltheight = ((int)tmp16 & (int)0x1fff) + 1;
ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x24],tmp16);
BX_CIRRUS_THIS bitblt.dstpitch = (int)tmp16 & (int)0x1fff;
ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x26],tmp16);
BX_CIRRUS_THIS bitblt.srcpitch = (int)tmp16 & (int)0x1fff;
ReadHostDWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x28],tmp32);
dstaddr = tmp32 & (Bit32u)0x003fffff;
ReadHostDWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x2c],tmp32);
srcaddr = tmp32 & (Bit32u)0x003fffff;
BX_CIRRUS_THIS bitblt.srcaddr = srcaddr;
BX_CIRRUS_THIS bitblt.bltmode = BX_CIRRUS_THIS control.reg[0x30];
BX_CIRRUS_THIS bitblt.bltmodeext = BX_CIRRUS_THIS control.reg[0x33];
BX_CIRRUS_THIS bitblt.bltrop = BX_CIRRUS_THIS control.reg[0x32];
BX_CIRRUS_THIS bitblt.async_xbytes = 0;
BX_CIRRUS_THIS bitblt.async_y = 0;
offset = dstaddr - (BX_CIRRUS_THIS disp_ptr - BX_CIRRUS_THIS vidmem);
BX_CIRRUS_THIS bitblt.pos_x = (offset % BX_CIRRUS_THIS bitblt.dstpitch) / (BX_CIRRUS_THIS svga_bpp >> 3);
BX_CIRRUS_THIS bitblt.pos_y = offset / BX_CIRRUS_THIS bitblt.dstpitch;
BX_INFO(("BLT: src:0x%08x,dst 0x%08x,block %ux%u,mode 0x%02x,ROP 0x%02x",
(unsigned)srcaddr,(unsigned)dstaddr,
(unsigned)BX_CIRRUS_THIS bitblt.bltwidth,(unsigned)BX_CIRRUS_THIS bitblt.bltheight,
(unsigned)BX_CIRRUS_THIS bitblt.bltmode,(unsigned)BX_CIRRUS_THIS bitblt.bltrop));
BX_INFO(("BLT: srcpitch:0x%08x,dstpitch 0x%08x,modeext 0x%02x",
(unsigned)BX_CIRRUS_THIS bitblt.srcpitch,
(unsigned)BX_CIRRUS_THIS bitblt.dstpitch,
(unsigned)BX_CIRRUS_THIS bitblt.bltmodeext));
BX_INFO(("BLT: dst x = %d, dst y = %d", BX_CIRRUS_THIS bitblt.pos_x, BX_CIRRUS_THIS bitblt.pos_y));
switch (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
case CIRRUS_BLTMODE_PIXELWIDTH8:
BX_CIRRUS_THIS bitblt.pixelwidth = 1;
break;
case CIRRUS_BLTMODE_PIXELWIDTH16:
BX_CIRRUS_THIS bitblt.pixelwidth = 2;
break;
case CIRRUS_BLTMODE_PIXELWIDTH24:
BX_CIRRUS_THIS bitblt.pixelwidth = 3;
break;
case CIRRUS_BLTMODE_PIXELWIDTH32:
BX_CIRRUS_THIS bitblt.pixelwidth = 4;
break;
default:
BX_PANIC(("unknown pixel width"));
goto ignoreblt;
}
BX_CIRRUS_THIS bitblt.bltwidth /= BX_CIRRUS_THIS bitblt.pixelwidth;
BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
if ((BX_CIRRUS_THIS bitblt.bltmode & (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_MEMSYSDEST))
== (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_MEMSYSDEST)) {
BX_ERROR(("BLT: memory-to-memory copy is requested, ROP %02x",
(unsigned)BX_CIRRUS_THIS bitblt.bltrop));
goto ignoreblt;
}
if ((BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
(BX_CIRRUS_THIS bitblt.bltmode & (CIRRUS_BLTMODE_MEMSYSDEST |
CIRRUS_BLTMODE_TRANSPARENTCOMP |
CIRRUS_BLTMODE_PATTERNCOPY |
CIRRUS_BLTMODE_COLOREXPAND)) ==
(CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
BX_CIRRUS_THIS bitblt.rop_handler = svga_get_fwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop);
BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS vidmem + dstaddr;
svga_solidfill();
} else {
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_BACKWARDS) {
BX_CIRRUS_THIS bitblt.dstpitch = -BX_CIRRUS_THIS bitblt.dstpitch;
BX_CIRRUS_THIS bitblt.srcpitch = -BX_CIRRUS_THIS bitblt.srcpitch;
BX_CIRRUS_THIS bitblt.rop_handler = svga_get_bkwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop);
}
else {
BX_CIRRUS_THIS bitblt.rop_handler = svga_get_fwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop);
}
// setup bitblt engine.
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_MEMSYSSRC) {
svga_setup_bitblt_cputovideo(dstaddr,srcaddr);
}
else if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_MEMSYSDEST) {
svga_setup_bitblt_videotocpu(dstaddr,srcaddr);
}
else {
svga_setup_bitblt_videotovideo(dstaddr,srcaddr);
}
return;
}
ignoreblt:
svga_reset_bitblt();
return;
}
void
bx_svga_cirrus_c::svga_setup_bitblt_cputovideo(Bit32u dstaddr,Bit32u srcaddr)
{
BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS vidmem + dstaddr;
BX_CIRRUS_THIS bitblt.src = NULL;
BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[0];
BX_CIRRUS_THIS bitblt.memsrc_endptr = &BX_CIRRUS_THIS bitblt.memsrc[0];
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) {
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
BX_CIRRUS_THIS bitblt.memsrc_needed = 8;
}
else {
BX_CIRRUS_THIS bitblt.memsrc_needed = 8 * 8 * BX_CIRRUS_THIS bitblt.pixelwidth;
}
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
BX_ERROR(("BLT: patterncopy: TRANSPARENTCOMP is not implemented"));
}
else {
BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_memsrc_static;
}
}
else {
BX_CIRRUS_THIS bitblt.memdst_bytesperline =
BX_CIRRUS_THIS bitblt.bltwidth * BX_CIRRUS_THIS bitblt.pixelwidth;
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
BX_CIRRUS_THIS bitblt.memsrc_bytesperline =
(BX_CIRRUS_THIS bitblt.bltwidth + 7) / 8;
}
else {
BX_CIRRUS_THIS bitblt.memsrc_bytesperline = BX_CIRRUS_THIS bitblt.memdst_bytesperline;
}
BX_CIRRUS_THIS bitblt.memsrc_needed =
BX_CIRRUS_THIS bitblt.memsrc_bytesperline * BX_CIRRUS_THIS bitblt.bltheight;
BX_CIRRUS_THIS bitblt.memsrc_needed = (BX_CIRRUS_THIS bitblt.memsrc_needed + 3) & (~3);
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_transp_memsrc_static;
}
else {
BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memsrc_static;
}
}
svga_asyncbitblt_next();
}
void
bx_svga_cirrus_c::svga_setup_bitblt_videotocpu(Bit32u dstaddr,Bit32u srcaddr)
{
BX_ERROR(("BLT: MEMSYSDEST is not implemented"));
BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_MEMSYSDEST;
#if 0
BX_CIRRUS_THIS bitblt.dst = NULL;
BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS vidmem + srcaddr;
BX_CIRRUS_THIS bitblt.memdst_ptr = &BX_CIRRUS_THIS bitblt.memdst[0];
BX_CIRRUS_THIS bitblt.memdst_endptr = &BX_CIRRUS_THIS bitblt.memdst[0];
BX_CIRRUS_THIS bitblt.memdst_needed =
BX_CIRRUS_THIS bitblt.bltwidth * BX_CIRRUS_THIS bitblt.pixelwidth * BX_CIRRUS_THIS bitblt.bltheight;
BX_CIRRUS_THIS bitblt.memdst_needed = (BX_CIRRUS_THIS bitblt.memdst_needed + 3) & (~3);
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) {
BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_memdst_static;
}
else {
BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memdst_static;
}
svga_asyncbitblt_next();
#endif
}
void
bx_svga_cirrus_c::svga_setup_bitblt_videotovideo(Bit32u dstaddr,Bit32u srcaddr)
{
BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS vidmem + dstaddr;
BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS vidmem + srcaddr;
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) {
BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_static;
}
else {
BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_static;
}
(*BX_CIRRUS_THIS bitblt.bitblt_ptr)();
svga_reset_bitblt();
BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS bitblt.pos_x, BX_CIRRUS_THIS bitblt.pos_y,
BX_CIRRUS_THIS bitblt.bltwidth, BX_CIRRUS_THIS bitblt.bltheight);
}
void
bx_svga_cirrus_c::svga_colorexpand(Bit8u *dst,const Bit8u *src,int count,int pixelwidth)
{
BX_DEBUG(("svga_cirrus: COLOR EXPAND"));
switch (pixelwidth) {
case 1:
svga_colorexpand_8(dst,src,count);
break;
case 2:
svga_colorexpand_16(dst,src,count);
break;
case 3:
svga_colorexpand_24(dst,src,count);
break;
case 4:
svga_colorexpand_32(dst,src,count);
break;
default:
BX_PANIC(("COLOREXPAND: unknown pixelwidth %u",(unsigned)pixelwidth));
break;
}
}
#if !BX_USE_CIRRUS_SMF
void
bx_svga_cirrus_c::svga_colorexpand_8_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count)
{
((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_8(dst,src,count);
}
void
bx_svga_cirrus_c::svga_colorexpand_16_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count)
{
((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_16(dst,src,count);
}
void
bx_svga_cirrus_c::svga_colorexpand_24_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count)
{
((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_24(dst,src,count);
}
void
bx_svga_cirrus_c::svga_colorexpand_32_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count)
{
((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_32(dst,src,count);
}
#endif // BX_USE_CIRRUS_SMF
void
bx_svga_cirrus_c::svga_colorexpand_8(Bit8u *dst,const Bit8u *src,int count)
{
int x;
Bit8u colors[2];
unsigned bits;
unsigned bitmask;
int srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
colors[0] = BX_CIRRUS_THIS control.shadow_reg0;
colors[1] = BX_CIRRUS_THIS control.shadow_reg1;
bitmask = 0x80 >> srcskipleft;
bits = *src++;
for (x = 0; x < count; x++) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++;
}
*dst++ = colors[!!(bits & bitmask)];
bitmask >>= 1;
}
}
void
bx_svga_cirrus_c::svga_colorexpand_16(Bit8u *dst,const Bit8u *src,int count)
{
int x;
Bit8u colors[2][2];
unsigned bits;
unsigned bitmask;
unsigned index;
int srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0;
colors[0][1] = BX_CIRRUS_THIS control.reg[0x10];
colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1;
colors[1][1] = BX_CIRRUS_THIS control.reg[0x11];
bitmask = 0x80 >> srcskipleft;
bits = *src++;
for (x = 0; x < count; x++) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++;
}
index = !!(bits & bitmask);
*dst++ = colors[index][0];
*dst++ = colors[index][1];
bitmask >>= 1;
}
}
void
bx_svga_cirrus_c::svga_colorexpand_24(Bit8u *dst,const Bit8u *src,int count)
{
int x;
Bit8u colors[2][3];
unsigned bits;
unsigned bitmask;
unsigned index;
int srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0;
colors[0][1] = BX_CIRRUS_THIS control.reg[0x10];
colors[0][2] = BX_CIRRUS_THIS control.reg[0x12];
colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1;
colors[1][1] = BX_CIRRUS_THIS control.reg[0x11];
colors[1][2] = BX_CIRRUS_THIS control.reg[0x13];
bitmask = 0x80 >> srcskipleft;
bits = *src++;
for (x = 0; x < count; x++) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++;
}
index = !!(bits & bitmask);
*dst++ = colors[index][0];
*dst++ = colors[index][1];
*dst++ = colors[index][2];
bitmask >>= 1;
}
}
void
bx_svga_cirrus_c::svga_colorexpand_32(Bit8u *dst,const Bit8u *src,int count)
{
int x;
Bit8u colors[2][4];
unsigned bits;
unsigned bitmask;
unsigned index;
int srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0;
colors[0][1] = BX_CIRRUS_THIS control.reg[0x10];
colors[0][2] = BX_CIRRUS_THIS control.reg[0x12];
colors[0][3] = BX_CIRRUS_THIS control.reg[0x14];
colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1;
colors[1][1] = BX_CIRRUS_THIS control.reg[0x11];
colors[1][2] = BX_CIRRUS_THIS control.reg[0x13];
colors[1][3] = BX_CIRRUS_THIS control.reg[0x15];
bitmask = 0x80 >> srcskipleft;
bits = *src++;
for (x = 0; x < count; x++) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++;
}
index = !!(bits & bitmask);
*dst++ = colors[index][0];
*dst++ = colors[index][1];
*dst++ = colors[index][2];
*dst++ = colors[index][3];
bitmask >>= 1;
}
}
#if !BX_USE_CIRRUS_SMF
void
bx_svga_cirrus_c::svga_patterncopy_static(void *this_ptr)
{
((bx_svga_cirrus_c *)this_ptr)->svga_patterncopy();
}
void
bx_svga_cirrus_c::svga_simplebitblt_static(void *this_ptr)
{
((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt();
}
void
bx_svga_cirrus_c::svga_patterncopy_memsrc_static(void *this_ptr)
{
((bx_svga_cirrus_c *)this_ptr)->svga_patterncopy_memsrc();
}
void
bx_svga_cirrus_c::svga_simplebitblt_memsrc_static(void *this_ptr)
{
((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt_memsrc();
}
void
bx_svga_cirrus_c::svga_simplebitblt_transp_memsrc_static(void *this_ptr)
{
((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt_transp_memsrc();
}
#endif // !BX_USE_CIRRUS_SMF
void
bx_svga_cirrus_c::svga_patterncopy()
{
Bit8u color[4];
Bit8u work_colorexp[256];
Bit8u *src, *dst;
Bit8u *dstc, *srcc;
int x,y, pattern_y;
int tilewidth;
int patternbytes = 8 * BX_CIRRUS_THIS bitblt.pixelwidth;
int bltbytes = BX_CIRRUS_THIS bitblt.bltwidth * BX_CIRRUS_THIS bitblt.pixelwidth;
unsigned bits, bits_xor, bitmask;
int srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
color[0] = BX_CIRRUS_THIS control.shadow_reg0;
color[1] = BX_CIRRUS_THIS control.reg[0x10];
color[2] = BX_CIRRUS_THIS control.reg[0x12];
color[3] = BX_CIRRUS_THIS control.reg[0x14];
bits_xor = 0xff;
} else {
color[0] = BX_CIRRUS_THIS control.shadow_reg1;
color[1] = BX_CIRRUS_THIS control.reg[0x11];
color[2] = BX_CIRRUS_THIS control.reg[0x13];
color[3] = BX_CIRRUS_THIS control.reg[0x15];
bits_xor = 0x00;
}
pattern_y = 0;
for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
dst = BX_CIRRUS_THIS bitblt.dst;
bitmask = 0x80 >> srcskipleft;
bits = BX_CIRRUS_THIS bitblt.src[pattern_y] ^ bits_xor;
for (x = 0; x < BX_CIRRUS_THIS bitblt.bltwidth; x++) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = BX_CIRRUS_THIS bitblt.src[pattern_y] ^ bits_xor;
}
if (bits & bitmask) {
(*BX_CIRRUS_THIS bitblt.rop_handler)(
dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
}
dst += BX_CIRRUS_THIS bitblt.pixelwidth;
bitmask >>= 1;
}
pattern_y = (pattern_y + 1) & 7;
BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
}
return;
} else {
svga_colorexpand(work_colorexp,BX_CIRRUS_THIS bitblt.src,8*8,BX_CIRRUS_THIS bitblt.pixelwidth);
BX_CIRRUS_THIS bitblt.src = work_colorexp;
BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_COLOREXPAND;
}
}
if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_PATTERNCOPY) {
BX_ERROR(("PATTERNCOPY: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
return;
}
BX_DEBUG(("svga_cirrus: PATTERN COPY"));
dst = BX_CIRRUS_THIS bitblt.dst;
pattern_y = BX_CIRRUS_THIS bitblt.srcaddr & 0x07;
src = (Bit8u *)BX_CIRRUS_THIS bitblt.src;
src -= (pattern_y * BX_CIRRUS_THIS bitblt.pixelwidth);
for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
srcc = src + pattern_y * patternbytes;
dstc = dst;
for (x = 0; x < bltbytes; x += patternbytes) {
tilewidth = BX_MIN(patternbytes,bltbytes - x);
(*BX_CIRRUS_THIS bitblt.rop_handler)(
dstc, srcc, 0, patternbytes,
tilewidth, 1);
dstc += patternbytes;
}
pattern_y = (pattern_y + 1) & 7;
dst += BX_CIRRUS_THIS bitblt.dstpitch;
}
}
void
bx_svga_cirrus_c::svga_simplebitblt()
{
Bit8u color[4];
Bit8u work_colorexp[2048];
int x, y;
Bit8u *dst;
unsigned bits, bits_xor, bitmask;
int srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
color[0] = BX_CIRRUS_THIS control.shadow_reg0;
color[1] = BX_CIRRUS_THIS control.reg[0x10];
color[2] = BX_CIRRUS_THIS control.reg[0x12];
color[3] = BX_CIRRUS_THIS control.reg[0x14];
bits_xor = 0xff;
} else {
color[0] = BX_CIRRUS_THIS control.shadow_reg1;
color[1] = BX_CIRRUS_THIS control.reg[0x11];
color[2] = BX_CIRRUS_THIS control.reg[0x13];
color[3] = BX_CIRRUS_THIS control.reg[0x15];
bits_xor = 0x00;
}
for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
dst = BX_CIRRUS_THIS bitblt.dst;
bitmask = 0x80 >> srcskipleft;
bits = *BX_CIRRUS_THIS bitblt.src++ ^ bits_xor;
for (x = 0; x < BX_CIRRUS_THIS bitblt.bltwidth; x++) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *BX_CIRRUS_THIS bitblt.src++ ^ bits_xor;
}
if (bits & bitmask) {
(*BX_CIRRUS_THIS bitblt.rop_handler)(
dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
}
dst += BX_CIRRUS_THIS bitblt.pixelwidth;
bitmask >>= 1;
}
BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
}
return;
} else {
for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
svga_colorexpand(work_colorexp,BX_CIRRUS_THIS bitblt.src,BX_CIRRUS_THIS bitblt.bltwidth,
BX_CIRRUS_THIS bitblt.pixelwidth);
(*BX_CIRRUS_THIS bitblt.rop_handler)(
BX_CIRRUS_THIS bitblt.dst, work_colorexp, 0, 0,
BX_CIRRUS_THIS bitblt.bltwidth * BX_CIRRUS_THIS bitblt.pixelwidth, 1);
BX_CIRRUS_THIS bitblt.src += ((BX_CIRRUS_THIS bitblt.bltwidth + 7) / 8);
BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
}
return;
}
}
if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_BACKWARDS) {
BX_ERROR(("SIMPLE BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
return;
}
BX_DEBUG(("svga_cirrus: BITBLT"));
(*BX_CIRRUS_THIS bitblt.rop_handler)(
BX_CIRRUS_THIS bitblt.dst, BX_CIRRUS_THIS bitblt.src,
BX_CIRRUS_THIS bitblt.dstpitch, BX_CIRRUS_THIS bitblt.srcpitch,
BX_CIRRUS_THIS bitblt.bltwidth * BX_CIRRUS_THIS bitblt.pixelwidth, BX_CIRRUS_THIS bitblt.bltheight
);
}
void
bx_svga_cirrus_c::svga_solidfill()
{
Bit8u color[4];
int x, y;
Bit8u *dst;
BX_DEBUG(("BLT: SOLIDFILL"));
color[0] = BX_CIRRUS_THIS control.shadow_reg1;
color[1] = BX_CIRRUS_THIS control.reg[0x11];
color[2] = BX_CIRRUS_THIS control.reg[0x13];
color[3] = BX_CIRRUS_THIS control.reg[0x15];
for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) {
dst = BX_CIRRUS_THIS bitblt.dst;
for (x = 0; x < BX_CIRRUS_THIS bitblt.bltwidth; x++) {
(*BX_CIRRUS_THIS bitblt.rop_handler)(
dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
dst += BX_CIRRUS_THIS bitblt.pixelwidth;
}
BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch;
}
BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS bitblt.pos_x, BX_CIRRUS_THIS bitblt.pos_y,
BX_CIRRUS_THIS bitblt.bltwidth, BX_CIRRUS_THIS bitblt.bltheight);
}
void
bx_svga_cirrus_c::svga_patterncopy_memsrc()
{
int srcavail = BX_CIRRUS_THIS bitblt.memsrc_ptr - &BX_CIRRUS_THIS bitblt.memsrc[0];
if (srcavail > 0) {
if (srcavail != BX_CIRRUS_THIS bitblt.memsrc_needed) {
BX_PANIC(("CIRRUS_BLT_CACHESIZE is too small"));
BX_CIRRUS_THIS bitblt.memsrc_needed = 0;
return;
}
BX_INFO(("svga_patterncopy_memsrc() - not tested"));
BX_CIRRUS_THIS bitblt.src = &BX_CIRRUS_THIS bitblt.memsrc[0];
svga_patterncopy();
BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS bitblt.pos_x, BX_CIRRUS_THIS bitblt.pos_y,
BX_CIRRUS_THIS bitblt.bltwidth, BX_CIRRUS_THIS bitblt.bltheight);
}
}
void
bx_svga_cirrus_c::svga_simplebitblt_memsrc()
{
Bit8u work_colorexp[256];
int srcavail = BX_CIRRUS_THIS bitblt.memsrc_ptr - &BX_CIRRUS_THIS bitblt.memsrc[0];
int bytesavail;
int bytesprocessed;
int total;
Bit8u *srcptr = &BX_CIRRUS_THIS bitblt.memsrc[0];
Bit8u *srccurptr;
int srccuravail;
BX_DEBUG(("svga_cirrus: BLT, cpu-to-video"));
total = 0;
while (1) {
bytesavail = BX_CIRRUS_THIS bitblt.memsrc_bytesperline - BX_CIRRUS_THIS bitblt.async_xbytes;
bytesavail = BX_MIN(bytesavail,srcavail);
if (bytesavail <= 0)
break;
bytesprocessed = bytesavail;
srccurptr = srcptr;
srccuravail = bytesavail;
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_COLOREXPAND) {
BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
return;
}
bytesprocessed = BX_MIN(256/32,bytesavail);
svga_colorexpand(work_colorexp,srcptr,bytesprocessed * 8,BX_CIRRUS_THIS bitblt.pixelwidth);
srccurptr = work_colorexp;
srccuravail = BX_MIN(
bytesprocessed * 8 * BX_CIRRUS_THIS bitblt.pixelwidth,
BX_CIRRUS_THIS bitblt.memdst_bytesperline - BX_CIRRUS_THIS bitblt.async_xbytes * 8 * BX_CIRRUS_THIS bitblt.pixelwidth);
}
else {
if (BX_CIRRUS_THIS bitblt.bltmode != 0) {
BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
return;
}
}
(*BX_CIRRUS_THIS bitblt.rop_handler)(
BX_CIRRUS_THIS bitblt.dst, srccurptr, 0, 0, srccuravail, 1);
BX_CIRRUS_THIS bitblt.dst += srccuravail;
total += bytesprocessed;
srcptr += ((bytesprocessed + 3) & ~3);
srcavail -= bytesprocessed;
BX_CIRRUS_THIS bitblt.async_xbytes += bytesprocessed;
if (BX_CIRRUS_THIS bitblt.async_xbytes >= BX_CIRRUS_THIS bitblt.memsrc_bytesperline) {
BX_CIRRUS_THIS bitblt.dst +=
BX_CIRRUS_THIS bitblt.dstpitch - BX_CIRRUS_THIS bitblt.memdst_bytesperline;
BX_CIRRUS_THIS bitblt.async_y ++;
BX_CIRRUS_THIS bitblt.async_xbytes = 0;
if (BX_CIRRUS_THIS bitblt.async_y >= BX_CIRRUS_THIS bitblt.bltheight) {
total += srcavail;
srcavail = 0;
break;
}
}
}
BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[total];
BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS bitblt.pos_x, BX_CIRRUS_THIS bitblt.pos_y,
BX_CIRRUS_THIS bitblt.bltwidth, BX_CIRRUS_THIS bitblt.bltheight);
}
void
bx_svga_cirrus_c::svga_simplebitblt_transp_memsrc()
{
Bit8u color[4];
int srcavail = BX_CIRRUS_THIS bitblt.memsrc_ptr - &BX_CIRRUS_THIS bitblt.memsrc[0];
int bytesavail;
int bytesprocessed;
int x, total;
Bit8u *srcptr = &BX_CIRRUS_THIS bitblt.memsrc[0];
Bit8u *dst, *src;
int srccuravail;
unsigned bits, bitmask;
int srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07;
BX_DEBUG(("BLT, cpu-to-video, transparent"));
color[0] = BX_CIRRUS_THIS control.shadow_reg1;
color[1] = BX_CIRRUS_THIS control.reg[0x11];
color[2] = BX_CIRRUS_THIS control.reg[0x13];
color[3] = BX_CIRRUS_THIS control.reg[0x15];
total = 0;
while (1) {
bytesavail = BX_CIRRUS_THIS bitblt.memsrc_bytesperline - BX_CIRRUS_THIS bitblt.async_xbytes;
bytesavail = BX_MIN(bytesavail,srcavail);
if (bytesavail <= 0)
break;
bytesprocessed = bytesavail;
if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) {
bytesprocessed = BX_MIN(256/32,bytesavail);
srccuravail = BX_MIN(
bytesprocessed * 8 * BX_CIRRUS_THIS bitblt.pixelwidth,
BX_CIRRUS_THIS bitblt.memdst_bytesperline - BX_CIRRUS_THIS bitblt.async_xbytes * 8 * BX_CIRRUS_THIS bitblt.pixelwidth);
src = srcptr;
dst = BX_CIRRUS_THIS bitblt.dst;
bitmask = 0x80 >> srcskipleft;
bits = *src++;
for (x = 0; x < bytesprocessed * 8; x++) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++;
}
if (bits & bitmask) {
(*BX_CIRRUS_THIS bitblt.rop_handler)(
dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1);
}
dst += BX_CIRRUS_THIS bitblt.pixelwidth;
bitmask >>= 1;
}
} else {
BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode));
return;
}
BX_CIRRUS_THIS bitblt.dst += srccuravail;
total += bytesprocessed;
srcptr += bytesprocessed;
srcavail -= bytesprocessed;
BX_CIRRUS_THIS bitblt.async_xbytes += bytesprocessed;
if (BX_CIRRUS_THIS bitblt.async_xbytes >= BX_CIRRUS_THIS bitblt.memsrc_bytesperline) {
BX_CIRRUS_THIS bitblt.dst +=
BX_CIRRUS_THIS bitblt.dstpitch - BX_CIRRUS_THIS bitblt.memdst_bytesperline;
BX_CIRRUS_THIS bitblt.async_y ++;
BX_CIRRUS_THIS bitblt.async_xbytes = 0;
if (BX_CIRRUS_THIS bitblt.async_y >= BX_CIRRUS_THIS bitblt.bltheight) {
total += srcavail;
srcavail = 0;
break;
}
}
}
BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[total];
BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS bitblt.pos_x, BX_CIRRUS_THIS bitblt.pos_y,
BX_CIRRUS_THIS bitblt.bltwidth, BX_CIRRUS_THIS bitblt.bltheight);
}
bx_bool // true if finished, false otherwise
bx_svga_cirrus_c::svga_asyncbitblt_next()
{
int count;
int avail;
if (BX_CIRRUS_THIS bitblt.bitblt_ptr == NULL) {
BX_PANIC(("svga_asyncbitblt_next: unexpected call"));
goto cleanup;
}
if (BX_CIRRUS_THIS bitblt.memdst_needed > 0) {
BX_CIRRUS_THIS bitblt.memdst_needed -= BX_CIRRUS_THIS bitblt.memdst_ptr - &BX_CIRRUS_THIS bitblt.memdst[0];
avail = BX_MIN(CIRRUS_BLT_CACHESIZE, BX_CIRRUS_THIS bitblt.memdst_needed);
BX_CIRRUS_THIS bitblt.memdst_ptr = &BX_CIRRUS_THIS bitblt.memdst[0];
BX_CIRRUS_THIS bitblt.memdst_endptr = &BX_CIRRUS_THIS bitblt.memdst[avail];
if (BX_CIRRUS_THIS bitblt.memsrc_needed <= 0 &&
BX_CIRRUS_THIS bitblt.memdst_needed <= 0) {
goto cleanup;
}
}
(*BX_CIRRUS_THIS bitblt.bitblt_ptr)();
if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) {
BX_CIRRUS_THIS bitblt.memsrc_needed -= BX_CIRRUS_THIS bitblt.memsrc_ptr - &BX_CIRRUS_THIS bitblt.memsrc[0];
count = BX_CIRRUS_THIS bitblt.memsrc_endptr - BX_CIRRUS_THIS bitblt.memsrc_ptr;
memmove(&BX_CIRRUS_THIS bitblt.memsrc[0], BX_CIRRUS_THIS bitblt.memsrc_ptr, count);
avail = BX_MIN(CIRRUS_BLT_CACHESIZE, BX_CIRRUS_THIS bitblt.memsrc_needed);
BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[count];
BX_CIRRUS_THIS bitblt.memsrc_endptr = &BX_CIRRUS_THIS bitblt.memsrc[avail];
if (BX_CIRRUS_THIS bitblt.memsrc_needed <= 0 &&
BX_CIRRUS_THIS bitblt.memdst_needed <= 0) {
goto cleanup;
}
}
return false;
cleanup:
svga_reset_bitblt();
return true;
}
/////////////////////////////////////////////////////////////////////////
//
// Raster operations.
//
/////////////////////////////////////////////////////////////////////////
#define IMPLEMENT_FORWARD_BITBLT(name,opline) \
static void \
bitblt_rop_fwd_##name( \
Bit8u *dst,const Bit8u *src, \
int dstpitch,int srcpitch, \
int bltwidth,int bltheight) \
{ \
int x,y; \
dstpitch -= bltwidth; \
srcpitch -= bltwidth; \
for (y = 0; y < bltheight; y++) { \
for (x = 0; x < bltwidth; x++) { \
opline; \
dst++; \
src++; \
} \
dst += dstpitch; \
src += srcpitch; \
} \
}
#define IMPLEMENT_BACKWARD_BITBLT(name,opline) \
static void \
bitblt_rop_bkwd_##name( \
Bit8u *dst,const Bit8u *src, \
int dstpitch,int srcpitch, \
int bltwidth,int bltheight) \
{ \
int x,y; \
dstpitch += bltwidth; \
srcpitch += bltwidth; \
for (y = 0; y < bltheight; y++) { \
for (x = 0; x < bltwidth; x++) { \
opline; \
dst--; \
src--; \
} \
dst += dstpitch; \
src += srcpitch; \
} \
}
IMPLEMENT_FORWARD_BITBLT(0, *dst = 0)
IMPLEMENT_FORWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
IMPLEMENT_FORWARD_BITBLT(nop, (void)0)
IMPLEMENT_FORWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
IMPLEMENT_FORWARD_BITBLT(notdst, *dst = ~(*dst))
IMPLEMENT_FORWARD_BITBLT(src, *dst = *src)
IMPLEMENT_FORWARD_BITBLT(1, *dst = 0xff)
IMPLEMENT_FORWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
IMPLEMENT_FORWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
IMPLEMENT_FORWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
IMPLEMENT_FORWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
IMPLEMENT_FORWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
IMPLEMENT_FORWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
IMPLEMENT_FORWARD_BITBLT(notsrc, *dst = (~(*src)))
IMPLEMENT_FORWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
IMPLEMENT_FORWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
IMPLEMENT_BACKWARD_BITBLT(0, *dst = 0)
IMPLEMENT_BACKWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst))
IMPLEMENT_BACKWARD_BITBLT(nop, (void)0)
IMPLEMENT_BACKWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst)))
IMPLEMENT_BACKWARD_BITBLT(notdst, *dst = ~(*dst))
IMPLEMENT_BACKWARD_BITBLT(src, *dst = *src)
IMPLEMENT_BACKWARD_BITBLT(1, *dst = 0xff)
IMPLEMENT_BACKWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst))
IMPLEMENT_BACKWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst))
IMPLEMENT_BACKWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst))
IMPLEMENT_BACKWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst)))
IMPLEMENT_BACKWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst)))
IMPLEMENT_BACKWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst)))
IMPLEMENT_BACKWARD_BITBLT(notsrc, *dst = (~(*src)))
IMPLEMENT_BACKWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst))
IMPLEMENT_BACKWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst)))
bx_cirrus_bitblt_rop_t
bx_svga_cirrus_c::svga_get_fwd_rop_handler(Bit8u rop)
{
bx_cirrus_bitblt_rop_t rop_handler = bitblt_rop_fwd_nop;
switch (rop)
{
case CIRRUS_ROP_0:
rop_handler = bitblt_rop_fwd_0;
break;
case CIRRUS_ROP_SRC_AND_DST:
rop_handler = bitblt_rop_fwd_src_and_dst;
break;
case CIRRUS_ROP_NOP:
rop_handler = bitblt_rop_fwd_nop;
break;
case CIRRUS_ROP_SRC_AND_NOTDST:
rop_handler = bitblt_rop_fwd_src_and_notdst;
break;
case CIRRUS_ROP_NOTDST:
rop_handler = bitblt_rop_fwd_notdst;
break;
case CIRRUS_ROP_SRC:
rop_handler = bitblt_rop_fwd_src;
break;
case CIRRUS_ROP_1:
rop_handler = bitblt_rop_fwd_1;
break;
case CIRRUS_ROP_NOTSRC_AND_DST:
rop_handler = bitblt_rop_fwd_notsrc_and_dst;
break;
case CIRRUS_ROP_SRC_XOR_DST:
rop_handler = bitblt_rop_fwd_src_xor_dst;
break;
case CIRRUS_ROP_SRC_OR_DST:
rop_handler = bitblt_rop_fwd_src_or_dst;
break;
case CIRRUS_ROP_NOTSRC_OR_NOTDST:
rop_handler = bitblt_rop_fwd_notsrc_or_notdst;
break;
case CIRRUS_ROP_SRC_NOTXOR_DST:
rop_handler = bitblt_rop_fwd_src_notxor_dst;
break;
case CIRRUS_ROP_SRC_OR_NOTDST:
rop_handler = bitblt_rop_fwd_src_or_notdst;
break;
case CIRRUS_ROP_NOTSRC:
rop_handler = bitblt_rop_fwd_notsrc;
break;
case CIRRUS_ROP_NOTSRC_OR_DST:
rop_handler = bitblt_rop_fwd_notsrc_or_dst;
break;
case CIRRUS_ROP_NOTSRC_AND_NOTDST:
rop_handler = bitblt_rop_fwd_notsrc_and_notdst;
break;
default:
BX_ERROR(("unknown ROP %02x",rop));
break;
}
return rop_handler;
}
bx_cirrus_bitblt_rop_t
bx_svga_cirrus_c::svga_get_bkwd_rop_handler(Bit8u rop)
{
bx_cirrus_bitblt_rop_t rop_handler = bitblt_rop_bkwd_nop;
switch (rop)
{
case CIRRUS_ROP_0:
rop_handler = bitblt_rop_bkwd_0;
break;
case CIRRUS_ROP_SRC_AND_DST:
rop_handler = bitblt_rop_bkwd_src_and_dst;
break;
case CIRRUS_ROP_NOP:
rop_handler = bitblt_rop_bkwd_nop;
break;
case CIRRUS_ROP_SRC_AND_NOTDST:
rop_handler = bitblt_rop_bkwd_src_and_notdst;
break;
case CIRRUS_ROP_NOTDST:
rop_handler = bitblt_rop_bkwd_notdst;
break;
case CIRRUS_ROP_SRC:
rop_handler = bitblt_rop_bkwd_src;
break;
case CIRRUS_ROP_1:
rop_handler = bitblt_rop_bkwd_1;
break;
case CIRRUS_ROP_NOTSRC_AND_DST:
rop_handler = bitblt_rop_bkwd_notsrc_and_dst;
break;
case CIRRUS_ROP_SRC_XOR_DST:
rop_handler = bitblt_rop_bkwd_src_xor_dst;
break;
case CIRRUS_ROP_SRC_OR_DST:
rop_handler = bitblt_rop_bkwd_src_or_dst;
break;
case CIRRUS_ROP_NOTSRC_OR_NOTDST:
rop_handler = bitblt_rop_bkwd_notsrc_or_notdst;
break;
case CIRRUS_ROP_SRC_NOTXOR_DST:
rop_handler = bitblt_rop_bkwd_src_notxor_dst;
break;
case CIRRUS_ROP_SRC_OR_NOTDST:
rop_handler = bitblt_rop_bkwd_src_or_notdst;
break;
case CIRRUS_ROP_NOTSRC:
rop_handler = bitblt_rop_bkwd_notsrc;
break;
case CIRRUS_ROP_NOTSRC_OR_DST:
rop_handler = bitblt_rop_bkwd_notsrc_or_dst;
break;
case CIRRUS_ROP_NOTSRC_AND_NOTDST:
rop_handler = bitblt_rop_bkwd_notsrc_and_notdst;
break;
default:
BX_ERROR(("unknown ROP %02x",rop));
break;
}
return rop_handler;
}
#endif // BX_SUPPORT_CLGD54XX