📄 vga.c
字号:
s->line_compare = line_compare; full_update = 1; } return full_update;}static inline int get_depth_index(int depth){ switch(depth) { default: case 8: return 0; case 15: return 1; case 16: return 2; case 32: return 3; }}static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = { vga_draw_glyph8_8, vga_draw_glyph8_16, vga_draw_glyph8_16, vga_draw_glyph8_32,};static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = { vga_draw_glyph16_8, vga_draw_glyph16_16, vga_draw_glyph16_16, vga_draw_glyph16_32,};static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = { vga_draw_glyph9_8, vga_draw_glyph9_16, vga_draw_glyph9_16, vga_draw_glyph9_32,}; static const uint8_t cursor_glyph[32 * 4] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,}; /* * Text mode update * Missing: * - double scan * - double width * - underline * - flashing */static void vga_draw_text(VGAState *s, int full_update){ int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr; int cx_min, cx_max, linesize, x_incr; uint32_t offset, fgcol, bgcol, v, cursor_offset; uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr; const uint8_t *font_ptr, *font_base[2]; int dup9, line_offset, depth_index; uint32_t *palette; uint32_t *ch_attr_ptr; vga_draw_glyph8_func *vga_draw_glyph8; vga_draw_glyph9_func *vga_draw_glyph9; full_update |= update_palette16(s); palette = s->last_palette; /* compute font data address (in plane 2) */ v = s->sr[3]; offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2; if (offset != s->font_offsets[0]) { s->font_offsets[0] = offset; full_update = 1; } font_base[0] = s->vram_ptr + offset; offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2; font_base[1] = s->vram_ptr + offset; if (offset != s->font_offsets[1]) { s->font_offsets[1] = offset; full_update = 1; } if (s->plane_updated & (1 << 2)) { /* if the plane 2 was modified since the last display, it indicates the font may have been modified */ s->plane_updated = 0; full_update = 1; } full_update |= update_basic_params(s); line_offset = s->line_offset; s1 = s->vram_ptr + (s->start_addr * 4); /* total width & height */ cheight = (s->cr[9] & 0x1f) + 1; cw = 8; if (!(s->sr[1] & 0x01)) cw = 9; if (s->sr[1] & 0x08) cw = 16; /* NOTE: no 18 pixel wide */ x_incr = cw * ((s->ds->depth + 7) >> 3); width = (s->cr[0x01] + 1); if (s->cr[0x06] == 100) { /* ugly hack for CGA 160x100x16 - explain me the logic */ height = 100; } else { height = s->cr[0x12] | ((s->cr[0x07] & 0x02) << 7) | ((s->cr[0x07] & 0x40) << 3); height = (height + 1) / cheight; } if ((height * width) > CH_ATTR_SIZE) { /* better than nothing: exit if transient size is too big */ return; } if (width != s->last_width || height != s->last_height || cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; s->last_scr_height = height * cheight; dpy_resize(s->ds, s->last_scr_width, s->last_scr_height); s->last_width = width; s->last_height = height; s->last_ch = cheight; s->last_cw = cw; full_update = 1; } cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr; if (cursor_offset != s->cursor_offset || s->cr[0xa] != s->cursor_start || s->cr[0xb] != s->cursor_end) { /* if the cursor position changed, we update the old and new chars */ if (s->cursor_offset < CH_ATTR_SIZE) s->last_ch_attr[s->cursor_offset] = -1; if (cursor_offset < CH_ATTR_SIZE) s->last_ch_attr[cursor_offset] = -1; s->cursor_offset = cursor_offset; s->cursor_start = s->cr[0xa]; s->cursor_end = s->cr[0xb]; } cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4; depth_index = get_depth_index(s->ds->depth); if (cw == 16) vga_draw_glyph8 = vga_draw_glyph16_table[depth_index]; else vga_draw_glyph8 = vga_draw_glyph8_table[depth_index]; vga_draw_glyph9 = vga_draw_glyph9_table[depth_index]; dest = s->ds->data; linesize = s->ds->linesize; ch_attr_ptr = s->last_ch_attr; for(cy = 0; cy < height; cy++) { d1 = dest; src = s1; cx_min = width; cx_max = -1; for(cx = 0; cx < width; cx++) { ch_attr = *(uint16_t *)src; if (full_update || ch_attr != *ch_attr_ptr) { if (cx < cx_min) cx_min = cx; if (cx > cx_max) cx_max = cx; *ch_attr_ptr = ch_attr;#ifdef WORDS_BIGENDIAN ch = ch_attr >> 8; cattr = ch_attr & 0xff;#else ch = ch_attr & 0xff; cattr = ch_attr >> 8;#endif font_ptr = font_base[(cattr >> 3) & 1]; font_ptr += 32 * 4 * ch; bgcol = palette[cattr >> 4]; fgcol = palette[cattr & 0x0f]; if (cw != 9) { vga_draw_glyph8(d1, linesize, font_ptr, cheight, fgcol, bgcol); } else { dup9 = 0; if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04)) dup9 = 1; vga_draw_glyph9(d1, linesize, font_ptr, cheight, fgcol, bgcol, dup9); } if (src == cursor_ptr && !(s->cr[0x0a] & 0x20)) { int line_start, line_last, h; /* draw the cursor */ line_start = s->cr[0x0a] & 0x1f; line_last = s->cr[0x0b] & 0x1f; /* XXX: check that */ if (line_last > cheight - 1) line_last = cheight - 1; if (line_last >= line_start && line_start < cheight) { h = line_last - line_start + 1; d = d1 + linesize * line_start; if (cw != 9) { vga_draw_glyph8(d, linesize, cursor_glyph, h, fgcol, bgcol); } else { vga_draw_glyph9(d, linesize, cursor_glyph, h, fgcol, bgcol, 1); } } } } d1 += x_incr; src += 4; ch_attr_ptr++; } if (cx_max != -1) { dpy_update(s->ds, cx_min * cw, cy * cheight, (cx_max - cx_min + 1) * cw, cheight); } dest += linesize * cheight; s1 += line_offset; }}enum { VGA_DRAW_LINE2, VGA_DRAW_LINE2D2, VGA_DRAW_LINE4, VGA_DRAW_LINE4D2, VGA_DRAW_LINE8D2, VGA_DRAW_LINE8, VGA_DRAW_LINE15, VGA_DRAW_LINE16, VGA_DRAW_LINE24, VGA_DRAW_LINE32, VGA_DRAW_LINE_NB,};static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = { vga_draw_line2_8, vga_draw_line2_16, vga_draw_line2_16, vga_draw_line2_32, vga_draw_line2d2_8, vga_draw_line2d2_16, vga_draw_line2d2_16, vga_draw_line2d2_32, vga_draw_line4_8, vga_draw_line4_16, vga_draw_line4_16, vga_draw_line4_32, vga_draw_line4d2_8, vga_draw_line4d2_16, vga_draw_line4d2_16, vga_draw_line4d2_32, vga_draw_line8d2_8, vga_draw_line8d2_16, vga_draw_line8d2_16, vga_draw_line8d2_32, vga_draw_line8_8, vga_draw_line8_16, vga_draw_line8_16, vga_draw_line8_32, vga_draw_line15_8, vga_draw_line15_15, vga_draw_line15_16, vga_draw_line15_32, vga_draw_line16_8, vga_draw_line16_15, vga_draw_line16_16, vga_draw_line16_32, vga_draw_line24_8, vga_draw_line24_15, vga_draw_line24_16, vga_draw_line24_32, vga_draw_line32_8, vga_draw_line32_15, vga_draw_line32_16, vga_draw_line32_32,};static int vga_get_bpp(VGAState *s){ int ret;#ifdef CONFIG_BOCHS_VBE if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { ret = s->vbe_regs[VBE_DISPI_INDEX_BPP]; } else #endif { ret = 0; } return ret;}static void vga_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); *pwidth = width; *pheight = height;}void vga_invalidate_scanlines(VGAState *s, int y1, int y2){ int y; if (y1 >= VGA_MAX_HEIGHT) return; if (y2 >= VGA_MAX_HEIGHT) y2 = VGA_MAX_HEIGHT; for(y = y1; y < y2; y++) { s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f); }}/* * graphic modes */static void vga_draw_graphic(VGAState *s, int full_update){ int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask; int width, height, shift_control, line_offset, page0, page1, bwidth; int disp_width, multi_scan, multi_run; uint8_t *d; uint32_t v, addr1, addr; vga_draw_line_func *vga_draw_line; 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 * 4 + get_depth_index(s->ds->depth)]; 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 addr1 = (s->start_addr * 4); bwidth = width * 4; y_start = -1; page_min = 0x7fffffff; page_max = -1; 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -