📄 vga.c
字号:
s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f); }}static inline int cmp_vram(VGAState *s, int offset, int n){ long *vp, *sp; if (s->vram_shadow == NULL) return 1; vp = (long *)(s->vram_ptr + offset); sp = (long *)(s->vram_shadow + offset); while ((n -= sizeof(*vp)) >= 0) { if (*vp++ != *sp++) { memcpy(sp - 1, vp - 1, n + sizeof(*vp)); return 1; } } return 0;}#ifdef USE_SSE2#include <signal.h>#include <setjmp.h>#include <emmintrin.h>int sse2_ok = 1;static inline unsigned int cpuid_edx(unsigned int op){ unsigned int eax, edx;#ifdef __x86_64__#define __bx "rbx"#else#define __bx "ebx"#endif __asm__("push %%"__bx"; cpuid; pop %%"__bx : "=a" (eax), "=d" (edx) : "0" (op) : "cx");#undef __bx return edx;}jmp_buf sse_jbuf;void intr(int sig){ sse2_ok = 0; longjmp(sse_jbuf, 1);}void check_sse2(void){ /* Check 1: What does CPUID say? */ if ((cpuid_edx(1) & 0x4000000) == 0) { sse2_ok = 0; return; } /* Check 2: Can we use SSE2 in anger? */ signal(SIGILL, intr); if (setjmp(sse_jbuf) == 0) __asm__("xorps %xmm0,%xmm0\n");}int vram_dirty(VGAState *s, int offset, int n){ __m128i *sp, *vp; if (s->vram_shadow == NULL) return 1; if (sse2_ok == 0) return cmp_vram(s, offset, n); vp = (__m128i *)(s->vram_ptr + offset); sp = (__m128i *)(s->vram_shadow + offset); while ((n -= sizeof(*vp)) >= 0) { if (_mm_movemask_epi8(_mm_cmpeq_epi8(*sp, *vp)) != 0xffff) { while (n >= 0) { _mm_store_si128(sp++, _mm_load_si128(vp++)); n -= sizeof(*vp); } return 1; } sp++; vp++; } return 0;}#else /* !USE_SSE2 */int vram_dirty(VGAState *s, int offset, int n){ return cmp_vram(s, offset, n);}void check_sse2(void){}#endif /* !USE_SSE2 *//* * graphic modes */static void vga_draw_graphic(VGAState *s, int full_update){ int y1, y, update, linesize, y_start, double_scan, mask; int width, height, shift_control, line_offset, bwidth; ram_addr_t page0, page1; int disp_width, multi_scan, multi_run; uint8_t *d; uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line; ram_addr_t page_min, page_max; full_update |= update_basic_params(s); s->get_resolution(s, &width, &height); disp_width = width; shift_control = (s->gr[0x05] >> 5) & 3; double_scan = (s->cr[0x09] >> 7); if (shift_control != 1) { multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1; } else { /* in CGA modes, multi_scan is ignored */ /* XXX: is it correct ? */ multi_scan = double_scan; } multi_run = multi_scan; if (shift_control != s->shift_control || double_scan != s->double_scan) { full_update = 1; s->shift_control = shift_control; s->double_scan = double_scan; } if (shift_control == 0) { full_update |= update_palette16(s); if (s->sr[0x01] & 8) { v = VGA_DRAW_LINE4D2; disp_width <<= 1; } else { v = VGA_DRAW_LINE4; } } else if (shift_control == 1) { full_update |= update_palette16(s); if (s->sr[0x01] & 8) { v = VGA_DRAW_LINE2D2; disp_width <<= 1; } else { v = VGA_DRAW_LINE2; } } else { switch(s->get_bpp(s)) { default: case 0: full_update |= update_palette256(s); v = VGA_DRAW_LINE8D2; break; case 8: full_update |= update_palette256(s); v = VGA_DRAW_LINE8; break; case 15: v = VGA_DRAW_LINE15; break; case 16: v = VGA_DRAW_LINE16; break; case 24: v = VGA_DRAW_LINE24; break; case 32: v = VGA_DRAW_LINE32; break; } } vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; if (disp_width != s->last_width || height != s->last_height) { dpy_resize(s->ds, disp_width, height); s->last_scr_width = disp_width; s->last_scr_height = height; s->last_width = disp_width; s->last_height = height; full_update = 1; } if (s->cursor_invalidate) s->cursor_invalidate(s); line_offset = s->line_offset;#if 0 printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n", width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);#endif for (y = 0; y < s->vram_size; y += TARGET_PAGE_SIZE) if (vram_dirty(s, y, TARGET_PAGE_SIZE)) cpu_physical_memory_set_dirty(s->vram_offset + y); addr1 = (s->start_addr * 4); bwidth = width * 4; y_start = -1; page_min = 0; page_max = 0; d = s->ds->data; linesize = s->ds->linesize; y1 = 0; for(y = 0; y < height; y++) { addr = addr1; if (!(s->cr[0x17] & 1)) { int shift; /* CGA compatibility handling */ shift = 14 + ((s->cr[0x17] >> 6) & 1); addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift); } if (!(s->cr[0x17] & 2)) { addr = (addr & ~0x8000) | ((y1 & 2) << 14); } page0 = s->vram_offset + (addr & TARGET_PAGE_MASK); page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK); update = full_update | cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) | cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG); if ((page1 - page0) > TARGET_PAGE_SIZE) { /* if wide line, can use another page */ update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, VGA_DIRTY_FLAG); } /* explicit invalidation for the hardware cursor */ update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; if (update) { if (y_start < 0) y_start = y; if (page_min == 0 || page0 < page_min) page_min = page0; if (page_max == 0 || page1 > page_max) page_max = page1; vga_draw_line(s, d, s->vram_ptr + addr, width); if (s->cursor_draw_line) s->cursor_draw_line(s, d, y); } else { if (y_start >= 0) { /* flush to display */ dpy_update(s->ds, 0, y_start, disp_width, y - y_start); y_start = -1; } } if (!multi_run) { mask = (s->cr[0x17] & 3) ^ 3; if ((y1 & mask) == mask) addr1 += line_offset; y1++; multi_run = multi_scan; } else { multi_run--; } /* line compare acts on the displayed lines */ if (y == s->line_compare) addr1 = 0; d += linesize; } if (y_start >= 0) { /* flush to display */ dpy_update(s->ds, 0, y_start, disp_width, y - y_start); } /* reset modified pages */ if (page_max != -1) { cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE, VGA_DIRTY_FLAG); } memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);}static void vga_draw_blank(VGAState *s, int full_update){ int i, w, val; uint8_t *d; if (!full_update) return; if (s->last_scr_width <= 0 || s->last_scr_height <= 0) return; if (s->ds->depth == 8) val = s->rgb_to_pixel(0, 0, 0); else val = 0; w = s->last_scr_width * ((s->ds->depth + 7) >> 3); d = s->ds->data; for(i = 0; i < s->last_scr_height; i++) { memset(d, val, w); d += s->ds->linesize; } dpy_update(s->ds, 0, 0, s->last_scr_width, s->last_scr_height);}#define GMODE_TEXT 0#define GMODE_GRAPH 1#define GMODE_BLANK 2 static void vga_update_display(void *opaque){ VGAState *s = (VGAState *)opaque; int full_update, graphic_mode; if (s->ds->depth == 0) { /* nothing to do */ } else { s->rgb_to_pixel = rgb_to_pixel_dup_table[get_depth_index(s->ds)]; full_update = 0; if (!(s->ar_index & 0x20)) { graphic_mode = GMODE_BLANK; } else { graphic_mode = s->gr[6] & 1; } if (graphic_mode != s->graphic_mode) { s->graphic_mode = graphic_mode; full_update = 1; } switch(graphic_mode) { case GMODE_TEXT: vga_draw_text(s, full_update); break; case GMODE_GRAPH: vga_draw_graphic(s, full_update); break; case GMODE_BLANK: default: vga_draw_blank(s, full_update); break; } }}/* force a full display refresh */static void vga_invalidate_display(void *opaque){ VGAState *s = (VGAState *)opaque; s->last_width = -1; s->last_height = -1;}static void vga_reset(VGAState *s){ memset(s, 0, sizeof(VGAState)); s->graphic_mode = -1; /* force full update */}static CPUReadMemoryFunc *vga_mem_read[3] = { vga_mem_readb, vga_mem_readw, vga_mem_readl,};static CPUWriteMemoryFunc *vga_mem_write[3] = { vga_mem_writeb, vga_mem_writew, vga_mem_writel,};static void vga_save(QEMUFile *f, void *opaque){ VGAState *s = opaque; uint32_t vram_size;#ifdef CONFIG_BOCHS_VBE int i;#endif if (s->pci_dev) pci_device_save(s->pci_dev, f); qemu_put_be32s(f, &s->latch); qemu_put_8s(f, &s->sr_index); qemu_put_buffer(f, s->sr, 8); qemu_put_8s(f, &s->gr_index); qemu_put_buffer(f, s->gr, 16); qemu_put_8s(f, &s->ar_index); qemu_put_buffer(f, s->ar, 21); qemu_put_be32s(f, &s->ar_flip_flop); qemu_put_8s(f, &s->cr_index); qemu_put_buffer(f, s->cr, 256); qemu_put_8s(f, &s->msr); qemu_put_8s(f, &s->fcr); qemu_put_8s(f, &s->st00); qemu_put_8s(f, &s->st01); qemu_put_8s(f, &s->dac_state); qemu_put_8s(f, &s->dac_sub_index); qemu_put_8s(f, &s->dac_read_index); qemu_put_8s(f, &s->dac_write_index); qemu_put_buffer(f, s->dac_cache, 3); qemu_put_buffer(f, s->palette, 768); qemu_put_be32s(f, &s->bank_offset);#ifdef CONFIG_BOCHS_VBE qemu_put_byte(f, 1); qemu_put_be16s(f, &s->vbe_index); for(i = 0; i < VBE_DISPI_INDEX_NB; i++) qemu_put_be16s(f, &s->vbe_regs[i]); qemu_put_be32s(f, &s->vbe_start_addr); qemu_put_be32s(f, &s->vbe_line_offset); qemu_put_be32s(f, &s->vbe_bank_mask);#else qemu_put_byte(f, 0);#endif vram_size = s->vram_size; qemu_put_be32s(f, &vram_size); qemu_put_buffer(f, s->vram_ptr, s->vram_size); }static int vga_load(QEMUFile *f, void *opaque, int version_id){ VGAState *s = opaque; int is_vbe, ret; uint32_t vram_size;#ifdef CONFIG_BOCHS_VBE int i;#endif if (version_id > 3) return -EINVAL; if (s->pci_dev && version_id >= 2) { ret = pci_device_load(s->pci_dev, f); if (ret < 0) return ret; } qemu_get_be32s(f, &s->latch); qemu_get_8s(f, &s->sr_index); qemu_get_buffer(f, s->sr, 8); qemu_get_8s(f, &s->gr_index); qemu_get_buffer(f, s->gr, 16); qemu_get_8s(f, &s->ar_index); qemu_get_buffer(f, s->ar, 21); qemu_get_be32s(f, &s->ar_flip_flop); qemu_get_8s(f, &s->cr_index); qemu_get_buffer(f, s->cr, 256); qemu_get_8s(f, &s->msr); qemu_get_8s(f, &s->fcr); qemu_get_8s(f, &s->st00); qemu_get_8s(f, &s->st01); qemu_get_8s(f, &s->dac_state); qemu_get_8s(f, &s->dac_sub_index); qemu_get_8s(f, &s->dac_read_index); qemu_get_8s(f, &s->dac_write_index);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -