📄 cirrus_vga.c
字号:
ROP2(cirrus_patternfill_src_or_notdst), ROP2(cirrus_patternfill_notsrc), ROP2(cirrus_patternfill_notsrc_or_dst), ROP2(cirrus_patternfill_notsrc_and_notdst),};static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = { ROP2(cirrus_colorexpand_transp_0), ROP2(cirrus_colorexpand_transp_src_and_dst), ROP_NOP2(cirrus_bitblt_rop_nop), ROP2(cirrus_colorexpand_transp_src_and_notdst), ROP2(cirrus_colorexpand_transp_notdst), ROP2(cirrus_colorexpand_transp_src), ROP2(cirrus_colorexpand_transp_1), ROP2(cirrus_colorexpand_transp_notsrc_and_dst), ROP2(cirrus_colorexpand_transp_src_xor_dst), ROP2(cirrus_colorexpand_transp_src_or_dst), ROP2(cirrus_colorexpand_transp_notsrc_or_notdst), ROP2(cirrus_colorexpand_transp_src_notxor_dst), ROP2(cirrus_colorexpand_transp_src_or_notdst), ROP2(cirrus_colorexpand_transp_notsrc), ROP2(cirrus_colorexpand_transp_notsrc_or_dst), ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),};static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = { ROP2(cirrus_colorexpand_0), ROP2(cirrus_colorexpand_src_and_dst), ROP_NOP2(cirrus_bitblt_rop_nop), ROP2(cirrus_colorexpand_src_and_notdst), ROP2(cirrus_colorexpand_notdst), ROP2(cirrus_colorexpand_src), ROP2(cirrus_colorexpand_1), ROP2(cirrus_colorexpand_notsrc_and_dst), ROP2(cirrus_colorexpand_src_xor_dst), ROP2(cirrus_colorexpand_src_or_dst), ROP2(cirrus_colorexpand_notsrc_or_notdst), ROP2(cirrus_colorexpand_src_notxor_dst), ROP2(cirrus_colorexpand_src_or_notdst), ROP2(cirrus_colorexpand_notsrc), ROP2(cirrus_colorexpand_notsrc_or_dst), ROP2(cirrus_colorexpand_notsrc_and_notdst),};static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = { ROP2(cirrus_colorexpand_pattern_transp_0), ROP2(cirrus_colorexpand_pattern_transp_src_and_dst), ROP_NOP2(cirrus_bitblt_rop_nop), ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst), ROP2(cirrus_colorexpand_pattern_transp_notdst), ROP2(cirrus_colorexpand_pattern_transp_src), ROP2(cirrus_colorexpand_pattern_transp_1), ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst), ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst), ROP2(cirrus_colorexpand_pattern_transp_src_or_dst), ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst), ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst), ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst), ROP2(cirrus_colorexpand_pattern_transp_notsrc), ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst), ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst),};static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = { ROP2(cirrus_colorexpand_pattern_0), ROP2(cirrus_colorexpand_pattern_src_and_dst), ROP_NOP2(cirrus_bitblt_rop_nop), ROP2(cirrus_colorexpand_pattern_src_and_notdst), ROP2(cirrus_colorexpand_pattern_notdst), ROP2(cirrus_colorexpand_pattern_src), ROP2(cirrus_colorexpand_pattern_1), ROP2(cirrus_colorexpand_pattern_notsrc_and_dst), ROP2(cirrus_colorexpand_pattern_src_xor_dst), ROP2(cirrus_colorexpand_pattern_src_or_dst), ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst), ROP2(cirrus_colorexpand_pattern_src_notxor_dst), ROP2(cirrus_colorexpand_pattern_src_or_notdst), ROP2(cirrus_colorexpand_pattern_notsrc), ROP2(cirrus_colorexpand_pattern_notsrc_or_dst), ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst),};static const cirrus_fill_t cirrus_fill[16][4] = { ROP2(cirrus_fill_0), ROP2(cirrus_fill_src_and_dst), ROP_NOP2(cirrus_bitblt_fill_nop), ROP2(cirrus_fill_src_and_notdst), ROP2(cirrus_fill_notdst), ROP2(cirrus_fill_src), ROP2(cirrus_fill_1), ROP2(cirrus_fill_notsrc_and_dst), ROP2(cirrus_fill_src_xor_dst), ROP2(cirrus_fill_src_or_dst), ROP2(cirrus_fill_notsrc_or_notdst), ROP2(cirrus_fill_src_notxor_dst), ROP2(cirrus_fill_src_or_notdst), ROP2(cirrus_fill_notsrc), ROP2(cirrus_fill_notsrc_or_dst), ROP2(cirrus_fill_notsrc_and_notdst),};static inline void cirrus_bitblt_fgcol(CirrusVGAState *s){ unsigned int color; switch (s->cirrus_blt_pixelwidth) { case 1: s->cirrus_blt_fgcol = s->cirrus_shadow_gr1; break; case 2: color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8); s->cirrus_blt_fgcol = le16_to_cpu(color); break; case 3: s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | (s->gr[0x13] << 16); break; default: case 4: color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | (s->gr[0x13] << 16) | (s->gr[0x15] << 24); s->cirrus_blt_fgcol = le32_to_cpu(color); break; }}static inline void cirrus_bitblt_bgcol(CirrusVGAState *s){ unsigned int color; switch (s->cirrus_blt_pixelwidth) { case 1: s->cirrus_blt_bgcol = s->cirrus_shadow_gr0; break; case 2: color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8); s->cirrus_blt_bgcol = le16_to_cpu(color); break; case 3: s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) | (s->gr[0x12] << 16); break; default: case 4: color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) | (s->gr[0x12] << 16) | (s->gr[0x14] << 24); s->cirrus_blt_bgcol = le32_to_cpu(color); break; }}static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, int off_pitch, int bytesperline, int lines){ int y; int off_cur; int off_cur_end; for (y = 0; y < lines; y++) { off_cur = off_begin; off_cur_end = off_cur + bytesperline; off_cur &= TARGET_PAGE_MASK; while (off_cur < off_cur_end) { cpu_physical_memory_set_dirty(s->vram_offset + off_cur); off_cur += TARGET_PAGE_SIZE; } off_begin += off_pitch; }}static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, const uint8_t * src){ uint8_t *dst; dst = s->vram_ptr + s->cirrus_blt_dstaddr; (*s->cirrus_rop) (s, dst, src, s->cirrus_blt_dstpitch, 0, s->cirrus_blt_width, s->cirrus_blt_height); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_width, s->cirrus_blt_height); return 1;}/* fill */static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop){ cirrus_fill_t rop_func; rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_width, s->cirrus_blt_height); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_width, s->cirrus_blt_height); cirrus_bitblt_reset(s); return 1;}/*************************************** * * bitblt (video-to-video) * ***************************************/static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s){ return cirrus_bitblt_common_patterncopy(s, s->vram_ptr + (s->cirrus_blt_srcaddr & ~7));}static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h){ int sx, sy; int dx, dy; int width, height; int depth; int notify = 0; depth = s->get_bpp((VGAState *)s) / 8; s->get_resolution((VGAState *)s, &width, &height); /* extra x, y */ sx = (src % (width * depth)) / depth; sy = (src / (width * depth)); dx = (dst % (width *depth)) / depth; dy = (dst / (width * depth)); /* normalize width */ w /= depth; /* if we're doing a backward copy, we have to adjust our x/y to be the upper left corner (instead of the lower right corner) */ if (s->cirrus_blt_dstpitch < 0) { sx -= (s->cirrus_blt_width / depth) - 1; dx -= (s->cirrus_blt_width / depth) - 1; sy -= s->cirrus_blt_height - 1; dy -= s->cirrus_blt_height - 1; } /* are we in the visible portion of memory? */ if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 && (sx + w) <= width && (sy + h) <= height && (dx + w) <= width && (dy + h) <= height) { notify = 1; } /* make to sure only copy if it's a plain copy ROP */ if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src && *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src) notify = 0; /* we have to flush all pending changes so that the copy is generated at the appropriate moment in time */ if (notify) vga_hw_update(); (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr, s->vram_ptr + s->cirrus_blt_srcaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, s->cirrus_blt_width, s->cirrus_blt_height); if (notify) s->ds->dpy_copy(s->ds, sx, sy, dx, dy, s->cirrus_blt_width / depth, s->cirrus_blt_height); /* we don't have to notify the display that this portion has changed since dpy_copy implies this */ if (!notify) cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_width, s->cirrus_blt_height);}static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s){ if (s->ds->dpy_copy) { cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr, s->cirrus_blt_srcaddr - s->start_addr, s->cirrus_blt_width, s->cirrus_blt_height); } else { (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr, s->vram_ptr + s->cirrus_blt_srcaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, s->cirrus_blt_width, s->cirrus_blt_height); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, s->cirrus_blt_dstpitch, s->cirrus_blt_width, s->cirrus_blt_height); } return 1;}/*************************************** * * bitblt (cpu-to-video) * ***************************************/static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s){ int copy_count; uint8_t *end_ptr; if (s->cirrus_srccounter > 0) { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); the_end: s->cirrus_srccounter = 0; cirrus_bitblt_reset(s); } else { /* at least one scan line */ do { (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr, s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, s->cirrus_blt_width, 1); s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; s->cirrus_srccounter -= s->cirrus_blt_srcpitch; if (s->cirrus_srccounter <= 0) goto the_end; /* more bytes than needed can be transfered because of word alignment, so we keep them for the next line */ /* XXX: keep alignment to speed up transfer */ end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; copy_count = s->cirrus_srcptr_end - end_ptr; memmove(s->cirrus_bltbuf, end_ptr, copy_count); s->cirrus_srcptr = s->cirrus_bltbuf + copy_count; s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; } while (s->cirrus_srcptr >= s->cirrus_srcptr_end); } }}/*************************************** * * bitblt wrapper * ***************************************/static void cirrus_bitblt_reset(CirrusVGAState * s){ s->gr[0x31] &= ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED); s->cirrus_srcptr = &s->cirrus_bltbuf[0]; s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; s->cirrus_srccounter = 0; cirrus_update_memory_access(s);}static int cirrus_bitblt_cputovideo(CirrusVGAState * s){ int w; s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; s->cirrus_srcptr = &s->cirrus_bltbuf[0]; s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { s->cirrus_blt_srcpitch = 8; } else { /* XXX: check for 24 bpp */ s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth; } s->cirrus_srccounter = s->cirrus_blt_srcpitch; } else { if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth; if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) s->cirrus_blt_srcpitch = ((w + 31) >> 5); else s->cirrus_blt_srcpitch = ((w + 7) >> 3); } else { /* 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;}static int cirrus_bitblt_videotocpu(CirrusVGAState * s){ /* XXX */#ifdef DEBUG_BITBLT printf("cirrus: bitblt (video to cpu) is not implemented yet\n");#endif return 0;}static int cirrus_bitblt_videotovideo(CirrusVGAState * s){ int ret; if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { ret = cirrus_bitblt_videotovideo_patterncopy(s); } else { ret = cirrus_bitblt_videotovideo_copy(s); } if (ret) cirrus_bitblt_reset(s); return ret;}static void cirrus_bitblt_start(CirrusVGAState * s){ uint8_t blt_rop; s->gr[0x31] |= CIRRUS_BLT_BUSY; s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1; s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1; s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8)); s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8)); s->cirrus_blt_dstaddr = (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16)); s->cirrus_blt_srcaddr = (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16)); s->cirrus_blt_mode = s->gr[0x30]; s->cirrus_blt_modeext = s->gr[0x33];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -