📄 cirrus_vga.c
字号:
blt_rop = s->gr[0x32];#ifdef DEBUG_BITBLT 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_width, s->cirrus_blt_height, s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, s->cirrus_blt_dstaddr, s->cirrus_blt_srcaddr, s->gr[0x2f]);#endif switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { case CIRRUS_BLTMODE_PIXELWIDTH8: s->cirrus_blt_pixelwidth = 1; break; case CIRRUS_BLTMODE_PIXELWIDTH16: s->cirrus_blt_pixelwidth = 2; break; case CIRRUS_BLTMODE_PIXELWIDTH24: s->cirrus_blt_pixelwidth = 3; break; case CIRRUS_BLTMODE_PIXELWIDTH32: s->cirrus_blt_pixelwidth = 4; break; default:#ifdef DEBUG_BITBLT printf("cirrus: bitblt - pixel width is unknown\n");#endif goto bitblt_ignore; } s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; if ((s-> cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {#ifdef DEBUG_BITBLT printf("cirrus: bitblt - memory-to-memory copy is requested\n");#endif goto bitblt_ignore; } if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | CIRRUS_BLTMODE_TRANSPARENTCOMP | CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) == (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { cirrus_bitblt_fgcol(s); cirrus_bitblt_solidfill(s, blt_rop); } else { if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND | CIRRUS_BLTMODE_PATTERNCOPY)) == CIRRUS_BLTMODE_COLOREXPAND) { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) cirrus_bitblt_bgcol(s); else cirrus_bitblt_fgcol(s); s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; } else { cirrus_bitblt_fgcol(s); cirrus_bitblt_bgcol(s); s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; } } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) cirrus_bitblt_bgcol(s); else cirrus_bitblt_fgcol(s); s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; } else { cirrus_bitblt_fgcol(s); cirrus_bitblt_bgcol(s); s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; } } else { s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; } } else { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]]; } else { s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]]; } } // setup bitblt engine. if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) { if (!cirrus_bitblt_cputovideo(s)) goto bitblt_ignore; } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) { if (!cirrus_bitblt_videotocpu(s)) goto bitblt_ignore; } else { if (!cirrus_bitblt_videotovideo(s)) goto bitblt_ignore; } } return; bitblt_ignore:; cirrus_bitblt_reset(s);}static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value){ unsigned old_value; old_value = s->gr[0x31]; s->gr[0x31] = reg_value; if (((old_value & CIRRUS_BLT_RESET) != 0) && ((reg_value & CIRRUS_BLT_RESET) == 0)) { cirrus_bitblt_reset(s); } else if (((old_value & CIRRUS_BLT_START) == 0) && ((reg_value & CIRRUS_BLT_START) != 0)) { cirrus_bitblt_start(s); }}/*************************************** * * basic parameters * ***************************************/static void cirrus_get_offsets(VGAState *s1, uint32_t *pline_offset, uint32_t *pstart_addr){ CirrusVGAState * s = (CirrusVGAState *)s1; uint32_t start_addr; uint32_t line_offset; line_offset = s->cr[0x13] | ((s->cr[0x1b] & 0x10) << 4); line_offset <<= 3; *pline_offset = line_offset; start_addr = (s->cr[0x0c] << 8) | s->cr[0x0d] | ((s->cr[0x1b] & 0x01) << 16) | ((s->cr[0x1b] & 0x0c) << 15) | ((s->cr[0x1d] & 0x80) << 12); *pstart_addr = start_addr;}static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s){ uint32_t ret = 16; switch (s->cirrus_hidden_dac_data & 0xf) { case 0: ret = 15; break; /* Sierra HiColor */ case 1: ret = 16; break; /* XGA HiColor */ default:#ifdef DEBUG_CIRRUS printf("cirrus: invalid DAC value %x in 16bpp\n", (s->cirrus_hidden_dac_data & 0xf));#endif ret = 15; /* XXX */ break; } return ret;}static int cirrus_get_bpp(VGAState *s1){ CirrusVGAState * s = (CirrusVGAState *)s1; uint32_t ret = 8; if ((s->sr[0x07] & 0x01) != 0) { /* Cirrus SVGA */ switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) { case CIRRUS_SR7_BPP_8: ret = 8; break; case CIRRUS_SR7_BPP_16_DOUBLEVCLK: ret = cirrus_get_bpp16_depth(s); break; case CIRRUS_SR7_BPP_24: ret = 24; break; case CIRRUS_SR7_BPP_16: ret = cirrus_get_bpp16_depth(s); break; case CIRRUS_SR7_BPP_32: ret = 32; break; default:#ifdef DEBUG_CIRRUS printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);#endif ret = 8; break; } } else { /* VGA */ ret = 0; } return ret;}static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight){ int width, height; width = (s->cr[0x01] + 1) * 8; height = s->cr[0x12] | ((s->cr[0x07] & 0x02) << 7) | ((s->cr[0x07] & 0x40) << 3); height = (height + 1); /* interlace support */ if (s->cr[0x1a] & 0x01) height = height * 2; *pwidth = width; *pheight = height;}/*************************************** * * bank memory * ***************************************/static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index){ unsigned offset; unsigned limit; if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */ offset = s->gr[0x09 + bank_index]; else /* single bank */ offset = s->gr[0x09]; if ((s->gr[0x0b] & 0x20) != 0) offset <<= 14; else offset <<= 12; if (s->real_vram_size <= offset) limit = 0; else limit = s->real_vram_size - offset; if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) { if (limit > 0x8000) { offset += 0x8000; limit -= 0x8000; } else { limit = 0; } } if (limit > 0) { s->cirrus_bank_base[bank_index] = offset; s->cirrus_bank_limit[bank_index] = limit; } else { s->cirrus_bank_base[bank_index] = 0; s->cirrus_bank_limit[bank_index] = 0; }}/*************************************** * * I/O access between 0x3c4-0x3c5 * ***************************************/static intcirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value){ switch (reg_index) { case 0x00: // Standard VGA case 0x01: // Standard VGA case 0x02: // Standard VGA case 0x03: // Standard VGA case 0x04: // Standard VGA return CIRRUS_HOOK_NOT_HANDLED; case 0x06: // Unlock Cirrus extensions *reg_value = s->sr[reg_index]; break; case 0x10: case 0x30: case 0x50: case 0x70: // Graphics Cursor X case 0x90: case 0xb0: case 0xd0: case 0xf0: // Graphics Cursor X *reg_value = s->sr[0x10]; break; case 0x11: case 0x31: case 0x51: case 0x71: // Graphics Cursor Y case 0x91: case 0xb1: case 0xd1: case 0xf1: // Graphics Cursor Y *reg_value = s->sr[0x11]; break; case 0x05: // ??? case 0x07: // Extended Sequencer Mode case 0x08: // EEPROM Control case 0x09: // Scratch Register 0 case 0x0a: // Scratch Register 1 case 0x0b: // VCLK 0 case 0x0c: // VCLK 1 case 0x0d: // VCLK 2 case 0x0e: // VCLK 3 case 0x0f: // DRAM Control case 0x12: // Graphics Cursor Attribute case 0x13: // Graphics Cursor Pattern Address 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: // Signal Generator Result case 0x1a: // Signal Generator Result case 0x1b: // VCLK 0 Denominator & Post case 0x1c: // VCLK 1 Denominator & Post case 0x1d: // VCLK 2 Denominator & Post case 0x1e: // VCLK 3 Denominator & Post case 0x1f: // BIOS Write Enable and MCLK select#ifdef DEBUG_CIRRUS printf("cirrus: handled inport sr_index %02x\n", reg_index);#endif *reg_value = s->sr[reg_index]; break; default:#ifdef DEBUG_CIRRUS printf("cirrus: inport sr_index %02x\n", reg_index);#endif *reg_value = 0xff; break; } return CIRRUS_HOOK_HANDLED;}static intcirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value){ switch (reg_index) { case 0x00: // Standard VGA case 0x01: // Standard VGA case 0x02: // Standard VGA case 0x03: // Standard VGA case 0x04: // Standard VGA return CIRRUS_HOOK_NOT_HANDLED; case 0x06: // Unlock Cirrus extensions reg_value &= 0x17; if (reg_value == 0x12) { s->sr[reg_index] = 0x12; } else { s->sr[reg_index] = 0x0f; } break; case 0x10: case 0x30: case 0x50: case 0x70: // Graphics Cursor X case 0x90: case 0xb0: case 0xd0: case 0xf0: // Graphics Cursor X s->sr[0x10] = reg_value; s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5); break; case 0x11: case 0x31: case 0x51: case 0x71: // Graphics Cursor Y case 0x91: case 0xb1: case 0xd1: case 0xf1: // Graphics Cursor Y s->sr[0x11] = reg_value; s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5); break; case 0x07: // Extended Sequencer Mode case 0x08: // EEPROM Control case 0x09: // Scratch Register 0 case 0x0a: // Scratch Register 1 case 0x0b: // VCLK 0 case 0x0c: // VCLK 1 case 0x0d: // VCLK 2 case 0x0e: // VCLK 3 case 0x0f: // DRAM Control case 0x12: // Graphics Cursor Attribute case 0x13: // Graphics Cursor Pattern Address case 0x14: // Scratch Register 2 case 0x15: // Scratch Register 3 case 0x16: // Performance Tuning Register case 0x18: // Signature Generator Control case 0x19: // Signature Generator Result case 0x1a: // Signature Generator Result case 0x1b: // VCLK 0 Denominator & Post case 0x1c: // VCLK 1 Denominator & Post case 0x1d: // VCLK 2 Denominator & Post case 0x1e: // VCLK 3 Denominator & Post case 0x1f: // BIOS Write Enable and MCLK select s->sr[reg_index] = reg_value;#ifdef DEBUG_CIRRUS printf("cirrus: handled outport sr_index %02x, sr_value %02x\n", 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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -