Annotation of qemu/hw/tcx.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU TCX Frame buffer
        !             3:  * 
        !             4:  * Copyright (c) 2003-2005 Fabrice Bellard
        !             5:  * 
        !             6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             7:  * of this software and associated documentation files (the "Software"), to deal
        !             8:  * in the Software without restriction, including without limitation the rights
        !             9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            10:  * copies of the Software, and to permit persons to whom the Software is
        !            11:  * furnished to do so, subject to the following conditions:
        !            12:  *
        !            13:  * The above copyright notice and this permission notice shall be included in
        !            14:  * all copies or substantial portions of the Software.
        !            15:  *
        !            16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            22:  * THE SOFTWARE.
        !            23:  */
        !            24: #include "vl.h"
        !            25: 
        !            26: #define MAXX 1024
        !            27: #define MAXY 768
        !            28: #define TCX_DAC_NREGS 16
        !            29: 
        !            30: typedef struct TCXState {
        !            31:     uint32_t addr;
        !            32:     DisplayState *ds;
        !            33:     uint8_t *vram;
        !            34:     unsigned long vram_offset;
        !            35:     uint16_t width, height;
        !            36:     uint8_t r[256], g[256], b[256];
        !            37:     uint8_t dac_index, dac_state;
        !            38: } TCXState;
        !            39: 
        !            40: static void tcx_draw_line32(TCXState *s1, uint8_t *d, 
        !            41:                            const uint8_t *s, int width)
        !            42: {
        !            43:     int x;
        !            44:     uint8_t val;
        !            45: 
        !            46:     for(x = 0; x < width; x++) {
        !            47:        val = *s++;
        !            48:        *d++ = s1->b[val];
        !            49:        *d++ = s1->g[val];
        !            50:        *d++ = s1->r[val];
        !            51:        d++;
        !            52:     }
        !            53: }
        !            54: 
        !            55: static void tcx_draw_line24(TCXState *s1, uint8_t *d, 
        !            56:                            const uint8_t *s, int width)
        !            57: {
        !            58:     int x;
        !            59:     uint8_t val;
        !            60: 
        !            61:     for(x = 0; x < width; x++) {
        !            62:        val = *s++;
        !            63:        *d++ = s1->b[val];
        !            64:        *d++ = s1->g[val];
        !            65:        *d++ = s1->r[val];
        !            66:     }
        !            67: }
        !            68: 
        !            69: static void tcx_draw_line8(TCXState *s1, uint8_t *d, 
        !            70:                           const uint8_t *s, int width)
        !            71: {
        !            72:     int x;
        !            73:     uint8_t val;
        !            74: 
        !            75:     for(x = 0; x < width; x++) {
        !            76:        val = *s++;
        !            77:        /* XXX translate between palettes? */
        !            78:        *d++ = val;
        !            79:     }
        !            80: }
        !            81: 
        !            82: /* Fixed line length 1024 allows us to do nice tricks not possible on
        !            83:    VGA... */
        !            84: void tcx_update_display(void *opaque)
        !            85: {
        !            86:     TCXState *ts = opaque;
        !            87:     uint32_t page;
        !            88:     int y, page_min, page_max, y_start, dd, ds;
        !            89:     uint8_t *d, *s;
        !            90:     void (*f)(TCXState *s1, uint8_t *d, const uint8_t *s, int width);
        !            91: 
        !            92:     if (ts->ds->depth == 0)
        !            93:        return;
        !            94:     page = ts->vram_offset;
        !            95:     y_start = -1;
        !            96:     page_min = 0x7fffffff;
        !            97:     page_max = -1;
        !            98:     d = ts->ds->data;
        !            99:     s = ts->vram;
        !           100:     dd = ts->ds->linesize;
        !           101:     ds = 1024;
        !           102: 
        !           103:     switch (ts->ds->depth) {
        !           104:     case 32:
        !           105:        f = tcx_draw_line32;
        !           106:        break;
        !           107:     case 24:
        !           108:        f = tcx_draw_line24;
        !           109:        break;
        !           110:     default:
        !           111:     case 8:
        !           112:        f = tcx_draw_line8;
        !           113:        break;
        !           114:     case 0:
        !           115:        return;
        !           116:     }
        !           117:     
        !           118:     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
        !           119:        if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
        !           120:            if (y_start < 0)
        !           121:                 y_start = y;
        !           122:             if (page < page_min)
        !           123:                 page_min = page;
        !           124:             if (page > page_max)
        !           125:                 page_max = page;
        !           126:            f(ts, d, s, ts->width);
        !           127:            d += dd;
        !           128:            s += ds;
        !           129:            f(ts, d, s, ts->width);
        !           130:            d += dd;
        !           131:            s += ds;
        !           132:            f(ts, d, s, ts->width);
        !           133:            d += dd;
        !           134:            s += ds;
        !           135:            f(ts, d, s, ts->width);
        !           136:            d += dd;
        !           137:            s += ds;
        !           138:        } else {
        !           139:             if (y_start >= 0) {
        !           140:                 /* flush to display */
        !           141:                 dpy_update(ts->ds, 0, y_start, 
        !           142:                            ts->width, y - y_start);
        !           143:                 y_start = -1;
        !           144:             }
        !           145:            d += dd * 4;
        !           146:            s += ds * 4;
        !           147:        }
        !           148:     }
        !           149:     if (y_start >= 0) {
        !           150:        /* flush to display */
        !           151:        dpy_update(ts->ds, 0, y_start, 
        !           152:                   ts->width, y - y_start);
        !           153:     }
        !           154:     /* reset modified pages */
        !           155:     if (page_max != -1) {
        !           156:         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
        !           157:                                         VGA_DIRTY_FLAG);
        !           158:     }
        !           159: }
        !           160: 
        !           161: void tcx_invalidate_display(void *opaque)
        !           162: {
        !           163:     TCXState *s = opaque;
        !           164:     int i;
        !           165: 
        !           166:     for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
        !           167:        cpu_physical_memory_set_dirty(s->vram_offset + i);
        !           168:     }
        !           169: }
        !           170: 
        !           171: static void tcx_save(QEMUFile *f, void *opaque)
        !           172: {
        !           173:     TCXState *s = opaque;
        !           174:     
        !           175:     qemu_put_be32s(f, (uint32_t *)&s->addr);
        !           176:     qemu_put_be32s(f, (uint32_t *)&s->vram);
        !           177:     qemu_put_be16s(f, (uint16_t *)&s->height);
        !           178:     qemu_put_be16s(f, (uint16_t *)&s->width);
        !           179:     qemu_put_buffer(f, s->r, 256);
        !           180:     qemu_put_buffer(f, s->g, 256);
        !           181:     qemu_put_buffer(f, s->b, 256);
        !           182:     qemu_put_8s(f, &s->dac_index);
        !           183:     qemu_put_8s(f, &s->dac_state);
        !           184: }
        !           185: 
        !           186: static int tcx_load(QEMUFile *f, void *opaque, int version_id)
        !           187: {
        !           188:     TCXState *s = opaque;
        !           189:     
        !           190:     if (version_id != 1)
        !           191:         return -EINVAL;
        !           192: 
        !           193:     qemu_get_be32s(f, (uint32_t *)&s->addr);
        !           194:     qemu_get_be32s(f, (uint32_t *)&s->vram);
        !           195:     qemu_get_be16s(f, (uint16_t *)&s->height);
        !           196:     qemu_get_be16s(f, (uint16_t *)&s->width);
        !           197:     qemu_get_buffer(f, s->r, 256);
        !           198:     qemu_get_buffer(f, s->g, 256);
        !           199:     qemu_get_buffer(f, s->b, 256);
        !           200:     qemu_get_8s(f, &s->dac_index);
        !           201:     qemu_get_8s(f, &s->dac_state);
        !           202:     return 0;
        !           203: }
        !           204: 
        !           205: static void tcx_reset(void *opaque)
        !           206: {
        !           207:     TCXState *s = opaque;
        !           208: 
        !           209:     /* Initialize palette */
        !           210:     memset(s->r, 0, 256);
        !           211:     memset(s->g, 0, 256);
        !           212:     memset(s->b, 0, 256);
        !           213:     s->r[255] = s->g[255] = s->b[255] = 255;
        !           214:     memset(s->vram, 0, MAXX*MAXY);
        !           215:     cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset + MAXX*MAXY,
        !           216:                                     VGA_DIRTY_FLAG);
        !           217:     s->dac_index = 0;
        !           218:     s->dac_state = 0;
        !           219: }
        !           220: 
        !           221: static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr)
        !           222: {
        !           223:     return 0;
        !           224: }
        !           225: 
        !           226: static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
        !           227: {
        !           228:     TCXState *s = opaque;
        !           229:     uint32_t saddr;
        !           230: 
        !           231:     saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2;
        !           232:     switch (saddr) {
        !           233:     case 0:
        !           234:        s->dac_index = val >> 24;
        !           235:        s->dac_state = 0;
        !           236:        break;
        !           237:     case 1:
        !           238:        switch (s->dac_state) {
        !           239:        case 0:
        !           240:            s->r[s->dac_index] = val >> 24;
        !           241:            s->dac_state++;
        !           242:            break;
        !           243:        case 1:
        !           244:            s->g[s->dac_index] = val >> 24;
        !           245:            s->dac_state++;
        !           246:            break;
        !           247:        case 2:
        !           248:            s->b[s->dac_index] = val >> 24;
        !           249:        default:
        !           250:            s->dac_state = 0;
        !           251:            break;
        !           252:        }
        !           253:        break;
        !           254:     default:
        !           255:        break;
        !           256:     }
        !           257:     return;
        !           258: }
        !           259: 
        !           260: static CPUReadMemoryFunc *tcx_dac_read[3] = {
        !           261:     tcx_dac_readl,
        !           262:     tcx_dac_readl,
        !           263:     tcx_dac_readl,
        !           264: };
        !           265: 
        !           266: static CPUWriteMemoryFunc *tcx_dac_write[3] = {
        !           267:     tcx_dac_writel,
        !           268:     tcx_dac_writel,
        !           269:     tcx_dac_writel,
        !           270: };
        !           271: 
        !           272: void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base,
        !           273:               unsigned long vram_offset, int vram_size, int width, int height)
        !           274: {
        !           275:     TCXState *s;
        !           276:     int io_memory;
        !           277: 
        !           278:     s = qemu_mallocz(sizeof(TCXState));
        !           279:     if (!s)
        !           280:         return NULL;
        !           281:     s->ds = ds;
        !           282:     s->addr = addr;
        !           283:     s->vram = vram_base;
        !           284:     s->vram_offset = vram_offset;
        !           285:     s->width = width;
        !           286:     s->height = height;
        !           287: 
        !           288:     cpu_register_physical_memory(addr + 0x800000, vram_size, vram_offset);
        !           289:     io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);
        !           290:     cpu_register_physical_memory(addr + 0x200000, TCX_DAC_NREGS, io_memory);
        !           291: 
        !           292:     register_savevm("tcx", addr, 1, tcx_save, tcx_load, s);
        !           293:     qemu_register_reset(tcx_reset, s);
        !           294:     tcx_reset(s);
        !           295:     dpy_resize(s->ds, width, height);
        !           296:     return s;
        !           297: }
        !           298: 
        !           299: void tcx_screen_dump(void *opaque, const char *filename)
        !           300: {
        !           301:     TCXState *s = opaque;
        !           302:     FILE *f;
        !           303:     uint8_t *d, *d1, v;
        !           304:     int y, x;
        !           305: 
        !           306:     f = fopen(filename, "wb");
        !           307:     if (!f)
        !           308:         return;
        !           309:     fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
        !           310:     d1 = s->vram;
        !           311:     for(y = 0; y < s->height; y++) {
        !           312:         d = d1;
        !           313:         for(x = 0; x < s->width; x++) {
        !           314:             v = *d;
        !           315:             fputc(s->r[v], f);
        !           316:             fputc(s->g[v], f);
        !           317:             fputc(s->b[v], f);
        !           318:             d++;
        !           319:         }
        !           320:         d1 += MAXX;
        !           321:     }
        !           322:     fclose(f);
        !           323:     return;
        !           324: }
        !           325: 
        !           326: 
        !           327: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.