/*
* TODO:
- * - add support for WRITEMASK (GR2F)
+ * - destination write mask support not complete (bits 5..7)
* - optimize linear mappings
* - optimize bitblt functions
*/
uint8_t *cirrus_srcptr;
uint8_t *cirrus_srcptr_end;
uint32_t cirrus_srccounter;
- uint8_t *cirrus_dstptr;
- uint8_t *cirrus_dstptr_end;
- uint32_t cirrus_dstcounter;
/* hwcursor display state */
int last_hw_cursor_size;
int last_hw_cursor_x;
int last_hw_cursor_y_start;
int last_hw_cursor_y_end;
int real_vram_size; /* XXX: suppress that */
+ CPUWriteMemoryFunc **cirrus_linear_write;
} CirrusVGAState;
typedef struct PCICirrusVGAState {
***************************************/
-static void cirrus_bitblt_reset(CirrusVGAState * s);
+static void cirrus_bitblt_reset(CirrusVGAState *s);
+static void cirrus_update_memory_access(CirrusVGAState *s);
/***************************************
*
s->cirrus_srcptr = &s->cirrus_bltbuf[0];
s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
s->cirrus_srccounter = 0;
- s->cirrus_dstptr = &s->cirrus_bltbuf[0];
- s->cirrus_dstptr_end = &s->cirrus_bltbuf[0];
- s->cirrus_dstcounter = 0;
+ cirrus_update_memory_access(s);
}
static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
else
s->cirrus_blt_srcpitch = ((w + 7) >> 3);
} else {
- s->cirrus_blt_srcpitch = s->cirrus_blt_width;
+ /* always align input size to 32 bits */
+ s->cirrus_blt_srcpitch = (s->cirrus_blt_width + 3) & ~3;
}
s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
}
s->cirrus_srcptr = s->cirrus_bltbuf;
s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
+ cirrus_update_memory_access(s);
return 1;
}
blt_rop = s->gr[0x32];
#ifdef DEBUG_BITBLT
- printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spicth=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
+ printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spitch=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
blt_rop,
s->cirrus_blt_mode,
s->cirrus_blt_modeext,
s->cirrus_blt_srcpitch,
s->cirrus_blt_dstaddr,
s->cirrus_blt_srcaddr,
- s->sr[0x2f]);
+ s->gr[0x2f]);
#endif
switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
else
offset <<= 12;
- if (s->vram_size <= offset)
+ if (s->real_vram_size <= offset)
limit = 0;
else
- limit = s->vram_size - offset;
+ limit = s->real_vram_size - offset;
if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
if (limit > 0x8000) {
case 0x14: // Scratch Register 2
case 0x15: // Scratch Register 3
case 0x16: // Performance Tuning Register
- case 0x17: // Configuration Readback and Extended Control
case 0x18: // Signature Generator Control
case 0x19: // Signature Generator Result
case 0x1a: // Signature Generator Result
reg_index, reg_value);
#endif
break;
+ case 0x17: // Configuration Readback and Extended Control
+ s->sr[reg_index] = (s->sr[reg_index] & 0x38) | (reg_value & 0xc7);
+ cirrus_update_memory_access(s);
+ break;
default:
#ifdef DEBUG_CIRRUS
printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
return CIRRUS_HOOK_NOT_HANDLED;
case 0x05: // Standard VGA, Cirrus extended mode
s->gr[reg_index] = reg_value & 0x7f;
+ cirrus_update_memory_access(s);
break;
case 0x09: // bank offset #0
case 0x0A: // bank offset #1
+ s->gr[reg_index] = reg_value;
+ cirrus_update_bank_ptr(s, 0);
+ cirrus_update_bank_ptr(s, 1);
+ break;
case 0x0B:
s->gr[reg_index] = reg_value;
cirrus_update_bank_ptr(s, 0);
cirrus_update_bank_ptr(s, 1);
+ cirrus_update_memory_access(s);
break;
case 0x10: // BGCOLOR 0x0000ff00
case 0x11: // FGCOLOR 0x0000ff00
dst = s->vram_ptr + offset;
for (x = 0; x < 8; x++) {
if (val & 0x80) {
- *dst++ = s->cirrus_shadow_gr1;
+ *dst = s->cirrus_shadow_gr1;
} else if (mode == 5) {
- *dst++ = s->cirrus_shadow_gr0;
+ *dst = s->cirrus_shadow_gr0;
}
val <<= 1;
+ dst++;
}
cpu_physical_memory_set_dirty(s->vram_offset + offset);
cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
dst = s->vram_ptr + offset;
for (x = 0; x < 8; x++) {
if (val & 0x80) {
- *dst++ = s->cirrus_shadow_gr1;
- *dst++ = s->gr[0x11];
+ *dst = s->cirrus_shadow_gr1;
+ *(dst + 1) = s->gr[0x11];
} else if (mode == 5) {
- *dst++ = s->cirrus_shadow_gr0;
- *dst++ = s->gr[0x10];
+ *dst = s->cirrus_shadow_gr0;
+ *(dst + 1) = s->gr[0x10];
}
val <<= 1;
+ dst += 2;
}
cpu_physical_memory_set_dirty(s->vram_offset + offset);
cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
cirrus_linear_writel,
};
+static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ *(s->vram_ptr + addr) = val;
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
+static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val);
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
+static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val);
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
/***************************************
*
* system to screen memory access
cirrus_linear_bitblt_writel,
};
+/* Compute the memory access functions */
+static void cirrus_update_memory_access(CirrusVGAState *s)
+{
+ unsigned mode;
+
+ if ((s->sr[0x17] & 0x44) == 0x44) {
+ goto generic_io;
+ } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
+ goto generic_io;
+ } else {
+ if ((s->gr[0x0B] & 0x14) == 0x14) {
+ goto generic_io;
+ } else if (s->gr[0x0B] & 0x02) {
+ goto generic_io;
+ }
+
+ mode = s->gr[0x05] & 0x7;
+ if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
+ s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
+ s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
+ s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
+ } else {
+ generic_io:
+ s->cirrus_linear_write[0] = cirrus_linear_writeb;
+ s->cirrus_linear_write[1] = cirrus_linear_writew;
+ s->cirrus_linear_write[2] = cirrus_linear_writel;
+ }
+ }
+}
+
+
/* I/O ports */
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
#endif
/* handle CR0-7 protection */
- if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
+ if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
/* can always write bit 4 of CR7 */
if (s->cr_index == 7)
s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
s->cirrus_linear_io_addr =
cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
s);
+ s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr);
+
/* I/O handler for LFB */
s->cirrus_linear_bitblt_io_addr =
cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,