///////////////////////////////////////////////////////////////////////// // $Id: svga_cirrus.cc,v 1.2 2004-08-16 15:23:19 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 (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); } 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; cybpp/8) * (cx1 - cx0) - 1; plane0_ptr2 = plane0_ptr; plane1_ptr2 = plane1_ptr; plane0 = plane1 = 0; for (i=0; i>= 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; cxis_little_endian) { for (i=info->bpp-8; i>-8; i-=8) { *(tile_ptr2--) = fgcol >> i; } } else { for (i=0; ibpp; i+=8) { *(tile_ptr2--) = fgcol >> i; } } } else { for (i=0; ibpp; 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; ibpp; 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; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> 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; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> 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; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> 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; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> 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; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> 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; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> 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 { switch (BX_CIRRUS_THIS svga_bpp) { case 4: BX_ERROR(("cannot draw 4bpp SVGA")); break; case 8: for (yc=0, yti = 0; ycgraphics_tile_update(BX_CIRRUS_THIS tilemem, xc, yc); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 16: for (yc=0, yti = 0; ycgraphics_tile_update(BX_CIRRUS_THIS tilemem, xc, yc); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 24: for (yc=0, yti = 0; ycgraphics_tile_update(BX_CIRRUS_THIS tilemem, xc, yc); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 32: for (yc=0, yti = 0; ycgraphics_tile_update(BX_CIRRUS_THIS tilemem, xc, yc); SET_TILE_UPDATED (xti, yti, 0); } } } break; default: BX_PANIC(("unknown bpp %u",(unsigned)BX_CIRRUS_THIS svga_bpp)); break; } } } 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 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; if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { 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; 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, BX_CIRRUS_THIS bitblt.dstpitch, 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, 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) { 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; bitmask = 0x80 >> srcskipleft; bits = *BX_CIRRUS_THIS bitblt.src++; for (x = 0; x < BX_CIRRUS_THIS bitblt.bltwidth; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *BX_CIRRUS_THIS bitblt.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; } 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