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

📄 tcx.c

📁 qemu虚拟机代码
💻 C
字号:
/* * QEMU TCX Frame buffer *  * Copyright (c) 2003-2005 Fabrice Bellard *  * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "vl.h"#define MAXX 1024#define MAXY 768#define TCX_DAC_NREGS 16typedef struct TCXState {    uint32_t addr;    DisplayState *ds;    uint8_t *vram;    unsigned long vram_offset;    uint16_t width, height;    uint8_t r[256], g[256], b[256];    uint8_t dac_index, dac_state;} TCXState;static void tcx_screen_dump(void *opaque, const char *filename);static void tcx_draw_line32(TCXState *s1, uint8_t *d, 			    const uint8_t *s, int width){    int x;    uint8_t val;    for(x = 0; x < width; x++) {	val = *s++;	*d++ = s1->b[val];	*d++ = s1->g[val];	*d++ = s1->r[val];	d++;    }}static void tcx_draw_line24(TCXState *s1, uint8_t *d, 			    const uint8_t *s, int width){    int x;    uint8_t val;    for(x = 0; x < width; x++) {	val = *s++;	*d++ = s1->b[val];	*d++ = s1->g[val];	*d++ = s1->r[val];    }}static void tcx_draw_line8(TCXState *s1, uint8_t *d, 			   const uint8_t *s, int width){    int x;    uint8_t val;    for(x = 0; x < width; x++) {	val = *s++;	/* XXX translate between palettes? */	*d++ = val;    }}/* Fixed line length 1024 allows us to do nice tricks not possible on   VGA... */static void tcx_update_display(void *opaque){    TCXState *ts = opaque;    uint32_t page;    int y, page_min, page_max, y_start, dd, ds;    uint8_t *d, *s;    void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);    if (ts->ds->depth == 0)	return;    page = ts->vram_offset;    y_start = -1;    page_min = 0x7fffffff;    page_max = -1;    d = ts->ds->data;    s = ts->vram;    dd = ts->ds->linesize;    ds = 1024;    switch (ts->ds->depth) {    case 32:	f = tcx_draw_line32;	break;    case 24:	f = tcx_draw_line24;	break;    default:    case 8:	f = tcx_draw_line8;	break;    case 0:	return;    }        for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {	if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {	    if (y_start < 0)                y_start = y;            if (page < page_min)                page_min = page;            if (page > page_max)                page_max = page;	    f(ts, d, s, ts->width);	    d += dd;	    s += ds;	    f(ts, d, s, ts->width);	    d += dd;	    s += ds;	    f(ts, d, s, ts->width);	    d += dd;	    s += ds;	    f(ts, d, s, ts->width);	    d += dd;	    s += ds;	} else {            if (y_start >= 0) {                /* flush to display */                dpy_update(ts->ds, 0, y_start,                            ts->width, y - y_start);                y_start = -1;            }	    d += dd * 4;	    s += ds * 4;	}    }    if (y_start >= 0) {	/* flush to display */	dpy_update(ts->ds, 0, y_start, 		   ts->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);    }}static void tcx_invalidate_display(void *opaque){    TCXState *s = opaque;    int i;    for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {	cpu_physical_memory_set_dirty(s->vram_offset + i);    }}static void tcx_save(QEMUFile *f, void *opaque){    TCXState *s = opaque;        qemu_put_be32s(f, (uint32_t *)&s->addr);    qemu_put_be32s(f, (uint32_t *)&s->vram);    qemu_put_be16s(f, (uint16_t *)&s->height);    qemu_put_be16s(f, (uint16_t *)&s->width);    qemu_put_buffer(f, s->r, 256);    qemu_put_buffer(f, s->g, 256);    qemu_put_buffer(f, s->b, 256);    qemu_put_8s(f, &s->dac_index);    qemu_put_8s(f, &s->dac_state);}static int tcx_load(QEMUFile *f, void *opaque, int version_id){    TCXState *s = opaque;        if (version_id != 1)        return -EINVAL;    qemu_get_be32s(f, (uint32_t *)&s->addr);    qemu_get_be32s(f, (uint32_t *)&s->vram);    qemu_get_be16s(f, (uint16_t *)&s->height);    qemu_get_be16s(f, (uint16_t *)&s->width);    qemu_get_buffer(f, s->r, 256);    qemu_get_buffer(f, s->g, 256);    qemu_get_buffer(f, s->b, 256);    qemu_get_8s(f, &s->dac_index);    qemu_get_8s(f, &s->dac_state);    return 0;}static void tcx_reset(void *opaque){    TCXState *s = opaque;    /* Initialize palette */    memset(s->r, 0, 256);    memset(s->g, 0, 256);    memset(s->b, 0, 256);    s->r[255] = s->g[255] = s->b[255] = 255;    memset(s->vram, 0, MAXX*MAXY);    cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY,                                    VGA_DIRTY_FLAG);    s->dac_index = 0;    s->dac_state = 0;}static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr){    return 0;}static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val){    TCXState *s = opaque;    uint32_t saddr;    saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2;    switch (saddr) {    case 0:	s->dac_index = val >> 24;	s->dac_state = 0;	break;    case 1:	switch (s->dac_state) {	case 0:	    s->r[s->dac_index] = val >> 24;	    s->dac_state++;	    break;	case 1:	    s->g[s->dac_index] = val >> 24;	    s->dac_state++;	    break;	case 2:	    s->b[s->dac_index] = val >> 24;	default:	    s->dac_state = 0;	    break;	}	break;    default:	break;    }    return;}static CPUReadMemoryFunc *tcx_dac_read[3] = {    tcx_dac_readl,    tcx_dac_readl,    tcx_dac_readl,};static CPUWriteMemoryFunc *tcx_dac_write[3] = {    tcx_dac_writel,    tcx_dac_writel,    tcx_dac_writel,};void tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,	      unsigned long vram_offset, int vram_size, int width, int height){    TCXState *s;    int io_memory;    s = qemu_mallocz(sizeof(TCXState));    if (!s)        return;    s->ds = ds;    s->addr = addr;    s->vram = vram_base;    s->vram_offset = vram_offset;    s->width = width;    s->height = height;    cpu_register_physical_memory(addr + 0x800000, vram_size, vram_offset);    io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);    cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory);    graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display,                         tcx_screen_dump, s);    register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);    qemu_register_reset(tcx_reset, s);    tcx_reset(s);    dpy_resize(s->ds, width, height);}static void tcx_screen_dump(void *opaque, const char *filename){    TCXState *s = opaque;    FILE *f;    uint8_t *d, *d1, v;    int y, x;    f = fopen(filename, "wb");    if (!f)        return;    fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);    d1 = s->vram;    for(y = 0; y < s->height; y++) {        d = d1;        for(x = 0; x < s->width; x++) {            v = *d;            fputc(s->r[v], f);            fputc(s->g[v], f);            fputc(s->b[v], f);            d++;        }        d1 += MAXX;    }    fclose(f);    return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -