⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vga.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        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 + -