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

1.1       root        1: /*
                      2:  * QEMU TCX Frame buffer
1.1.1.4 ! root        3:  *
1.1       root        4:  * Copyright (c) 2003-2005 Fabrice Bellard
1.1.1.4 ! root        5:  *
1.1       root        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:  */
1.1.1.4 ! root       24: #include "hw.h"
        !            25: #include "sun4m.h"
        !            26: #include "console.h"
        !            27: #include "pixel_ops.h"
1.1       root       28: 
                     29: #define MAXX 1024
                     30: #define MAXY 768
                     31: #define TCX_DAC_NREGS 16
1.1.1.4 ! root       32: #define TCX_THC_NREGS_8  0x081c
        !            33: #define TCX_THC_NREGS_24 0x1000
        !            34: #define TCX_TEC_NREGS    0x1000
1.1       root       35: 
                     36: typedef struct TCXState {
1.1.1.4 ! root       37:     target_phys_addr_t addr;
1.1       root       38:     DisplayState *ds;
                     39:     uint8_t *vram;
1.1.1.4 ! root       40:     uint32_t *vram24, *cplane;
        !            41:     ram_addr_t vram_offset, vram24_offset, cplane_offset;
        !            42:     uint16_t width, height, depth;
1.1       root       43:     uint8_t r[256], g[256], b[256];
1.1.1.3   root       44:     uint32_t palette[256];
1.1       root       45:     uint8_t dac_index, dac_state;
                     46: } TCXState;
                     47: 
1.1.1.2   root       48: static void tcx_screen_dump(void *opaque, const char *filename);
1.1.1.4 ! root       49: static void tcx24_screen_dump(void *opaque, const char *filename);
        !            50: static void tcx_invalidate_display(void *opaque);
        !            51: static void tcx24_invalidate_display(void *opaque);
1.1.1.3   root       52: 
                     53: static void update_palette_entries(TCXState *s, int start, int end)
                     54: {
                     55:     int i;
                     56:     for(i = start; i < end; i++) {
                     57:         switch(s->ds->depth) {
                     58:         default:
                     59:         case 8:
                     60:             s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
                     61:             break;
                     62:         case 15:
1.1.1.4 ! root       63:             if (s->ds->bgr)
        !            64:                 s->palette[i] = rgb_to_pixel15bgr(s->r[i], s->g[i], s->b[i]);
        !            65:             else
        !            66:                 s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root       67:             break;
                     68:         case 16:
1.1.1.4 ! root       69:             if (s->ds->bgr)
        !            70:                 s->palette[i] = rgb_to_pixel16bgr(s->r[i], s->g[i], s->b[i]);
        !            71:             else
        !            72:                 s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root       73:             break;
                     74:         case 32:
1.1.1.4 ! root       75:             if (s->ds->bgr)
        !            76:                 s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
        !            77:             else
        !            78:                 s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root       79:             break;
                     80:         }
                     81:     }
1.1.1.4 ! root       82:     if (s->depth == 24)
        !            83:         tcx24_invalidate_display(s);
        !            84:     else
        !            85:         tcx_invalidate_display(s);
1.1.1.3   root       86: }
                     87: 
1.1.1.4 ! root       88: static void tcx_draw_line32(TCXState *s1, uint8_t *d,
        !            89:                             const uint8_t *s, int width)
1.1       root       90: {
                     91:     int x;
                     92:     uint8_t val;
1.1.1.3   root       93:     uint32_t *p = (uint32_t *)d;
1.1       root       94: 
                     95:     for(x = 0; x < width; x++) {
1.1.1.4 ! root       96:         val = *s++;
1.1.1.3   root       97:         *p++ = s1->palette[val];
1.1       root       98:     }
                     99: }
                    100: 
1.1.1.4 ! root      101: static void tcx_draw_line16(TCXState *s1, uint8_t *d,
        !           102:                             const uint8_t *s, int width)
1.1       root      103: {
                    104:     int x;
                    105:     uint8_t val;
1.1.1.3   root      106:     uint16_t *p = (uint16_t *)d;
1.1       root      107: 
                    108:     for(x = 0; x < width; x++) {
1.1.1.4 ! root      109:         val = *s++;
1.1.1.3   root      110:         *p++ = s1->palette[val];
1.1       root      111:     }
                    112: }
                    113: 
1.1.1.4 ! root      114: static void tcx_draw_line8(TCXState *s1, uint8_t *d,
        !           115:                            const uint8_t *s, int width)
1.1       root      116: {
                    117:     int x;
                    118:     uint8_t val;
                    119: 
                    120:     for(x = 0; x < width; x++) {
1.1.1.4 ! root      121:         val = *s++;
1.1.1.3   root      122:         *d++ = s1->palette[val];
1.1       root      123:     }
                    124: }
                    125: 
1.1.1.4 ! root      126: static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
        !           127:                                      const uint8_t *s, int width,
        !           128:                                      const uint32_t *cplane,
        !           129:                                      const uint32_t *s24)
        !           130: {
        !           131:     int x;
        !           132:     uint8_t val;
        !           133:     uint32_t *p = (uint32_t *)d;
        !           134:     uint32_t dval;
        !           135: 
        !           136:     for(x = 0; x < width; x++, s++, s24++) {
        !           137:         if ((bswap32(*cplane++) & 0xff000000) == 0x03000000) { // 24-bit direct
        !           138:             dval = bswap32(*s24) & 0x00ffffff;
        !           139:         } else {
        !           140:             val = *s;
        !           141:             dval = s1->palette[val];
        !           142:         }
        !           143:         *p++ = dval;
        !           144:     }
        !           145: }
        !           146: 
        !           147: static inline int check_dirty(TCXState *ts, ram_addr_t page, ram_addr_t page24,
        !           148:                               ram_addr_t cpage)
        !           149: {
        !           150:     int ret;
        !           151:     unsigned int off;
        !           152: 
        !           153:     ret = cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG);
        !           154:     for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
        !           155:         ret |= cpu_physical_memory_get_dirty(page24 + off, VGA_DIRTY_FLAG);
        !           156:         ret |= cpu_physical_memory_get_dirty(cpage + off, VGA_DIRTY_FLAG);
        !           157:     }
        !           158:     return ret;
        !           159: }
        !           160: 
        !           161: static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
        !           162:                                ram_addr_t page_max, ram_addr_t page24,
        !           163:                               ram_addr_t cpage)
        !           164: {
        !           165:     cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
        !           166:                                     VGA_DIRTY_FLAG);
        !           167:     page_min -= ts->vram_offset;
        !           168:     page_max -= ts->vram_offset;
        !           169:     cpu_physical_memory_reset_dirty(page24 + page_min * 4,
        !           170:                                     page24 + page_max * 4 + TARGET_PAGE_SIZE,
        !           171:                                     VGA_DIRTY_FLAG);
        !           172:     cpu_physical_memory_reset_dirty(cpage + page_min * 4,
        !           173:                                     cpage + page_max * 4 + TARGET_PAGE_SIZE,
        !           174:                                     VGA_DIRTY_FLAG);
        !           175: }
        !           176: 
1.1       root      177: /* Fixed line length 1024 allows us to do nice tricks not possible on
                    178:    VGA... */
1.1.1.2   root      179: static void tcx_update_display(void *opaque)
1.1       root      180: {
                    181:     TCXState *ts = opaque;
1.1.1.3   root      182:     ram_addr_t page, page_min, page_max;
                    183:     int y, y_start, dd, ds;
1.1       root      184:     uint8_t *d, *s;
1.1.1.4 ! root      185:     void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
1.1       root      186: 
                    187:     if (ts->ds->depth == 0)
1.1.1.4 ! root      188:         return;
1.1       root      189:     page = ts->vram_offset;
                    190:     y_start = -1;
1.1.1.3   root      191:     page_min = 0xffffffff;
                    192:     page_max = 0;
1.1       root      193:     d = ts->ds->data;
                    194:     s = ts->vram;
                    195:     dd = ts->ds->linesize;
                    196:     ds = 1024;
                    197: 
                    198:     switch (ts->ds->depth) {
                    199:     case 32:
1.1.1.4 ! root      200:         f = tcx_draw_line32;
        !           201:         break;
1.1.1.3   root      202:     case 15:
                    203:     case 16:
1.1.1.4 ! root      204:         f = tcx_draw_line16;
        !           205:         break;
1.1       root      206:     default:
                    207:     case 8:
1.1.1.4 ! root      208:         f = tcx_draw_line8;
        !           209:         break;
1.1       root      210:     case 0:
1.1.1.4 ! root      211:         return;
1.1       root      212:     }
1.1.1.4 ! root      213: 
1.1       root      214:     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
1.1.1.4 ! root      215:         if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
        !           216:             if (y_start < 0)
1.1       root      217:                 y_start = y;
                    218:             if (page < page_min)
                    219:                 page_min = page;
                    220:             if (page > page_max)
                    221:                 page_max = page;
1.1.1.4 ! root      222:             f(ts, d, s, ts->width);
        !           223:             d += dd;
        !           224:             s += ds;
        !           225:             f(ts, d, s, ts->width);
        !           226:             d += dd;
        !           227:             s += ds;
        !           228:             f(ts, d, s, ts->width);
        !           229:             d += dd;
        !           230:             s += ds;
        !           231:             f(ts, d, s, ts->width);
        !           232:             d += dd;
        !           233:             s += ds;
        !           234:         } else {
1.1       root      235:             if (y_start >= 0) {
                    236:                 /* flush to display */
1.1.1.4 ! root      237:                 dpy_update(ts->ds, 0, y_start,
1.1       root      238:                            ts->width, y - y_start);
                    239:                 y_start = -1;
                    240:             }
1.1.1.4 ! root      241:             d += dd * 4;
        !           242:             s += ds * 4;
        !           243:         }
1.1       root      244:     }
                    245:     if (y_start >= 0) {
1.1.1.4 ! root      246:         /* flush to display */
        !           247:         dpy_update(ts->ds, 0, y_start,
        !           248:                    ts->width, y - y_start);
1.1       root      249:     }
                    250:     /* reset modified pages */
1.1.1.3   root      251:     if (page_min <= page_max) {
1.1       root      252:         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
                    253:                                         VGA_DIRTY_FLAG);
                    254:     }
                    255: }
                    256: 
1.1.1.4 ! root      257: static void tcx24_update_display(void *opaque)
        !           258: {
        !           259:     TCXState *ts = opaque;
        !           260:     ram_addr_t page, page_min, page_max, cpage, page24;
        !           261:     int y, y_start, dd, ds;
        !           262:     uint8_t *d, *s;
        !           263:     uint32_t *cptr, *s24;
        !           264: 
        !           265:     if (ts->ds->depth != 32)
        !           266:             return;
        !           267:     page = ts->vram_offset;
        !           268:     page24 = ts->vram24_offset;
        !           269:     cpage = ts->cplane_offset;
        !           270:     y_start = -1;
        !           271:     page_min = 0xffffffff;
        !           272:     page_max = 0;
        !           273:     d = ts->ds->data;
        !           274:     s = ts->vram;
        !           275:     s24 = ts->vram24;
        !           276:     cptr = ts->cplane;
        !           277:     dd = ts->ds->linesize;
        !           278:     ds = 1024;
        !           279: 
        !           280:     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
        !           281:             page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
        !           282:         if (check_dirty(ts, page, page24, cpage)) {
        !           283:             if (y_start < 0)
        !           284:                 y_start = y;
        !           285:             if (page < page_min)
        !           286:                 page_min = page;
        !           287:             if (page > page_max)
        !           288:                 page_max = page;
        !           289:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
        !           290:             d += dd;
        !           291:             s += ds;
        !           292:             cptr += ds;
        !           293:             s24 += ds;
        !           294:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
        !           295:             d += dd;
        !           296:             s += ds;
        !           297:             cptr += ds;
        !           298:             s24 += ds;
        !           299:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
        !           300:             d += dd;
        !           301:             s += ds;
        !           302:             cptr += ds;
        !           303:             s24 += ds;
        !           304:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
        !           305:             d += dd;
        !           306:             s += ds;
        !           307:             cptr += ds;
        !           308:             s24 += ds;
        !           309:         } else {
        !           310:             if (y_start >= 0) {
        !           311:                 /* flush to display */
        !           312:                 dpy_update(ts->ds, 0, y_start,
        !           313:                            ts->width, y - y_start);
        !           314:                 y_start = -1;
        !           315:             }
        !           316:             d += dd * 4;
        !           317:             s += ds * 4;
        !           318:             cptr += ds * 4;
        !           319:             s24 += ds * 4;
        !           320:         }
        !           321:     }
        !           322:     if (y_start >= 0) {
        !           323:         /* flush to display */
        !           324:         dpy_update(ts->ds, 0, y_start,
        !           325:                    ts->width, y - y_start);
        !           326:     }
        !           327:     /* reset modified pages */
        !           328:     if (page_min <= page_max) {
        !           329:         reset_dirty(ts, page_min, page_max, page24, cpage);
        !           330:     }
        !           331: }
        !           332: 
1.1.1.2   root      333: static void tcx_invalidate_display(void *opaque)
1.1       root      334: {
                    335:     TCXState *s = opaque;
                    336:     int i;
                    337: 
                    338:     for (i = 0; i < MAXX*MAXY; i += TARGET_PAGE_SIZE) {
1.1.1.4 ! root      339:         cpu_physical_memory_set_dirty(s->vram_offset + i);
        !           340:     }
        !           341: }
        !           342: 
        !           343: static void tcx24_invalidate_display(void *opaque)
        !           344: {
        !           345:     TCXState *s = opaque;
        !           346:     int i;
        !           347: 
        !           348:     tcx_invalidate_display(s);
        !           349:     for (i = 0; i < MAXX*MAXY * 4; i += TARGET_PAGE_SIZE) {
        !           350:         cpu_physical_memory_set_dirty(s->vram24_offset + i);
        !           351:         cpu_physical_memory_set_dirty(s->cplane_offset + i);
1.1       root      352:     }
                    353: }
                    354: 
                    355: static void tcx_save(QEMUFile *f, void *opaque)
                    356: {
                    357:     TCXState *s = opaque;
1.1.1.4 ! root      358: 
1.1       root      359:     qemu_put_be16s(f, (uint16_t *)&s->height);
                    360:     qemu_put_be16s(f, (uint16_t *)&s->width);
1.1.1.4 ! root      361:     qemu_put_be16s(f, (uint16_t *)&s->depth);
1.1       root      362:     qemu_put_buffer(f, s->r, 256);
                    363:     qemu_put_buffer(f, s->g, 256);
                    364:     qemu_put_buffer(f, s->b, 256);
                    365:     qemu_put_8s(f, &s->dac_index);
                    366:     qemu_put_8s(f, &s->dac_state);
                    367: }
                    368: 
                    369: static int tcx_load(QEMUFile *f, void *opaque, int version_id)
                    370: {
                    371:     TCXState *s = opaque;
1.1.1.4 ! root      372:     uint32_t dummy;
        !           373: 
        !           374:     if (version_id != 3 && version_id != 4)
1.1       root      375:         return -EINVAL;
                    376: 
1.1.1.4 ! root      377:     if (version_id == 3) {
        !           378:         qemu_get_be32s(f, (uint32_t *)&dummy);
        !           379:         qemu_get_be32s(f, (uint32_t *)&dummy);
        !           380:         qemu_get_be32s(f, (uint32_t *)&dummy);
        !           381:     }
1.1       root      382:     qemu_get_be16s(f, (uint16_t *)&s->height);
                    383:     qemu_get_be16s(f, (uint16_t *)&s->width);
1.1.1.4 ! root      384:     qemu_get_be16s(f, (uint16_t *)&s->depth);
1.1       root      385:     qemu_get_buffer(f, s->r, 256);
                    386:     qemu_get_buffer(f, s->g, 256);
                    387:     qemu_get_buffer(f, s->b, 256);
                    388:     qemu_get_8s(f, &s->dac_index);
                    389:     qemu_get_8s(f, &s->dac_state);
1.1.1.3   root      390:     update_palette_entries(s, 0, 256);
1.1.1.4 ! root      391:     if (s->depth == 24)
        !           392:         tcx24_invalidate_display(s);
        !           393:     else
        !           394:         tcx_invalidate_display(s);
        !           395: 
1.1       root      396:     return 0;
                    397: }
                    398: 
                    399: static void tcx_reset(void *opaque)
                    400: {
                    401:     TCXState *s = opaque;
                    402: 
                    403:     /* Initialize palette */
                    404:     memset(s->r, 0, 256);
                    405:     memset(s->g, 0, 256);
                    406:     memset(s->b, 0, 256);
                    407:     s->r[255] = s->g[255] = s->b[255] = 255;
1.1.1.3   root      408:     update_palette_entries(s, 0, 256);
1.1       root      409:     memset(s->vram, 0, MAXX*MAXY);
1.1.1.4 ! root      410:     cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset +
        !           411:                                     MAXX * MAXY * (1 + 4 + 4), VGA_DIRTY_FLAG);
1.1       root      412:     s->dac_index = 0;
                    413:     s->dac_state = 0;
                    414: }
                    415: 
                    416: static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr)
                    417: {
                    418:     return 0;
                    419: }
                    420: 
                    421: static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
                    422: {
                    423:     TCXState *s = opaque;
                    424:     uint32_t saddr;
                    425: 
                    426:     saddr = (addr & (TCX_DAC_NREGS - 1)) >> 2;
                    427:     switch (saddr) {
                    428:     case 0:
1.1.1.4 ! root      429:         s->dac_index = val >> 24;
        !           430:         s->dac_state = 0;
        !           431:         break;
1.1       root      432:     case 1:
1.1.1.4 ! root      433:         switch (s->dac_state) {
        !           434:         case 0:
        !           435:             s->r[s->dac_index] = val >> 24;
1.1.1.3   root      436:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4 ! root      437:             s->dac_state++;
        !           438:             break;
        !           439:         case 1:
        !           440:             s->g[s->dac_index] = val >> 24;
1.1.1.3   root      441:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4 ! root      442:             s->dac_state++;
        !           443:             break;
        !           444:         case 2:
        !           445:             s->b[s->dac_index] = val >> 24;
1.1.1.3   root      446:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4 ! root      447:             s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
        !           448:         default:
        !           449:             s->dac_state = 0;
        !           450:             break;
        !           451:         }
        !           452:         break;
1.1       root      453:     default:
1.1.1.4 ! root      454:         break;
1.1       root      455:     }
                    456:     return;
                    457: }
                    458: 
                    459: static CPUReadMemoryFunc *tcx_dac_read[3] = {
1.1.1.4 ! root      460:     NULL,
        !           461:     NULL,
1.1       root      462:     tcx_dac_readl,
                    463: };
                    464: 
                    465: static CPUWriteMemoryFunc *tcx_dac_write[3] = {
1.1.1.4 ! root      466:     NULL,
        !           467:     NULL,
1.1       root      468:     tcx_dac_writel,
                    469: };
                    470: 
1.1.1.4 ! root      471: static uint32_t tcx_dummy_readl(void *opaque, target_phys_addr_t addr)
        !           472: {
        !           473:     return 0;
        !           474: }
        !           475: 
        !           476: static void tcx_dummy_writel(void *opaque, target_phys_addr_t addr,
        !           477:                              uint32_t val)
        !           478: {
        !           479: }
        !           480: 
        !           481: static CPUReadMemoryFunc *tcx_dummy_read[3] = {
        !           482:     NULL,
        !           483:     NULL,
        !           484:     tcx_dummy_readl,
        !           485: };
        !           486: 
        !           487: static CPUWriteMemoryFunc *tcx_dummy_write[3] = {
        !           488:     NULL,
        !           489:     NULL,
        !           490:     tcx_dummy_writel,
        !           491: };
        !           492: 
        !           493: void tcx_init(DisplayState *ds, target_phys_addr_t addr, uint8_t *vram_base,
        !           494:               unsigned long vram_offset, int vram_size, int width, int height,
        !           495:               int depth)
1.1       root      496: {
                    497:     TCXState *s;
1.1.1.4 ! root      498:     int io_memory, dummy_memory;
        !           499:     int size;
1.1       root      500: 
                    501:     s = qemu_mallocz(sizeof(TCXState));
                    502:     if (!s)
1.1.1.2   root      503:         return;
1.1       root      504:     s->ds = ds;
                    505:     s->addr = addr;
                    506:     s->vram_offset = vram_offset;
                    507:     s->width = width;
                    508:     s->height = height;
1.1.1.4 ! root      509:     s->depth = depth;
        !           510: 
        !           511:     // 8-bit plane
        !           512:     s->vram = vram_base;
        !           513:     size = vram_size;
        !           514:     cpu_register_physical_memory(addr + 0x00800000ULL, size, vram_offset);
        !           515:     vram_offset += size;
        !           516:     vram_base += size;
1.1       root      517: 
                    518:     io_memory = cpu_register_io_memory(0, tcx_dac_read, tcx_dac_write, s);
1.1.1.4 ! root      519:     cpu_register_physical_memory(addr + 0x00200000ULL, TCX_DAC_NREGS, io_memory);
1.1       root      520: 
1.1.1.4 ! root      521:     dummy_memory = cpu_register_io_memory(0, tcx_dummy_read, tcx_dummy_write,
        !           522:                                           s);
        !           523:     cpu_register_physical_memory(addr + 0x00700000ULL, TCX_TEC_NREGS,
        !           524:                                  dummy_memory);
        !           525:     if (depth == 24) {
        !           526:         // 24-bit plane
        !           527:         size = vram_size * 4;
        !           528:         s->vram24 = (uint32_t *)vram_base;
        !           529:         s->vram24_offset = vram_offset;
        !           530:         cpu_register_physical_memory(addr + 0x02000000ULL, size, vram_offset);
        !           531:         vram_offset += size;
        !           532:         vram_base += size;
        !           533: 
        !           534:         // Control plane
        !           535:         size = vram_size * 4;
        !           536:         s->cplane = (uint32_t *)vram_base;
        !           537:         s->cplane_offset = vram_offset;
        !           538:         cpu_register_physical_memory(addr + 0x0a000000ULL, size, vram_offset);
        !           539:         graphic_console_init(s->ds, tcx24_update_display,
        !           540:                              tcx24_invalidate_display, tcx24_screen_dump, s);
        !           541:     } else {
        !           542:         cpu_register_physical_memory(addr + 0x00300000ULL, TCX_THC_NREGS_8,
        !           543:                                      dummy_memory);
        !           544:         graphic_console_init(s->ds, tcx_update_display, tcx_invalidate_display,
        !           545:                              tcx_screen_dump, s);
        !           546:     }
        !           547:     // NetBSD writes here even with 8-bit display
        !           548:     cpu_register_physical_memory(addr + 0x00301000ULL, TCX_THC_NREGS_24,
        !           549:                                  dummy_memory);
        !           550: 
        !           551:     register_savevm("tcx", addr, 4, tcx_save, tcx_load, s);
1.1       root      552:     qemu_register_reset(tcx_reset, s);
                    553:     tcx_reset(s);
                    554:     dpy_resize(s->ds, width, height);
                    555: }
                    556: 
1.1.1.2   root      557: static void tcx_screen_dump(void *opaque, const char *filename)
1.1       root      558: {
                    559:     TCXState *s = opaque;
                    560:     FILE *f;
                    561:     uint8_t *d, *d1, v;
                    562:     int y, x;
                    563: 
                    564:     f = fopen(filename, "wb");
                    565:     if (!f)
                    566:         return;
                    567:     fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
                    568:     d1 = s->vram;
                    569:     for(y = 0; y < s->height; y++) {
                    570:         d = d1;
                    571:         for(x = 0; x < s->width; x++) {
                    572:             v = *d;
                    573:             fputc(s->r[v], f);
                    574:             fputc(s->g[v], f);
                    575:             fputc(s->b[v], f);
                    576:             d++;
                    577:         }
                    578:         d1 += MAXX;
                    579:     }
                    580:     fclose(f);
                    581:     return;
                    582: }
                    583: 
1.1.1.4 ! root      584: static void tcx24_screen_dump(void *opaque, const char *filename)
        !           585: {
        !           586:     TCXState *s = opaque;
        !           587:     FILE *f;
        !           588:     uint8_t *d, *d1, v;
        !           589:     uint32_t *s24, *cptr, dval;
        !           590:     int y, x;
1.1       root      591: 
1.1.1.4 ! root      592:     f = fopen(filename, "wb");
        !           593:     if (!f)
        !           594:         return;
        !           595:     fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
        !           596:     d1 = s->vram;
        !           597:     s24 = s->vram24;
        !           598:     cptr = s->cplane;
        !           599:     for(y = 0; y < s->height; y++) {
        !           600:         d = d1;
        !           601:         for(x = 0; x < s->width; x++, d++, s24++) {
        !           602:             if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
        !           603:                 dval = *s24 & 0x00ffffff;
        !           604:                 fputc((dval >> 16) & 0xff, f);
        !           605:                 fputc((dval >> 8) & 0xff, f);
        !           606:                 fputc(dval & 0xff, f);
        !           607:             } else {
        !           608:                 v = *d;
        !           609:                 fputc(s->r[v], f);
        !           610:                 fputc(s->g[v], f);
        !           611:                 fputc(s->b[v], f);
        !           612:             }
        !           613:         }
        !           614:         d1 += MAXX;
        !           615:     }
        !           616:     fclose(f);
        !           617:     return;
        !           618: }

unix.superglobalmegacorp.com

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