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

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.6   root       24: 
1.1.1.4   root       25: #include "console.h"
                     26: #include "pixel_ops.h"
1.1.1.6   root       27: #include "sysbus.h"
                     28: #include "qdev-addr.h"
1.1       root       29: 
                     30: #define MAXX 1024
                     31: #define MAXY 768
                     32: #define TCX_DAC_NREGS 16
1.1.1.4   root       33: #define TCX_THC_NREGS_8  0x081c
                     34: #define TCX_THC_NREGS_24 0x1000
                     35: #define TCX_TEC_NREGS    0x1000
1.1       root       36: 
                     37: typedef struct TCXState {
1.1.1.6   root       38:     SysBusDevice busdev;
1.1.1.4   root       39:     target_phys_addr_t addr;
1.1       root       40:     DisplayState *ds;
                     41:     uint8_t *vram;
1.1.1.4   root       42:     uint32_t *vram24, *cplane;
1.1.1.10! root       43:     MemoryRegion vram_mem;
        !            44:     MemoryRegion vram_8bit;
        !            45:     MemoryRegion vram_24bit;
        !            46:     MemoryRegion vram_cplane;
        !            47:     MemoryRegion dac;
        !            48:     MemoryRegion tec;
        !            49:     MemoryRegion thc24;
        !            50:     MemoryRegion thc8;
        !            51:     ram_addr_t vram24_offset, cplane_offset;
1.1.1.6   root       52:     uint32_t vram_size;
1.1.1.3   root       53:     uint32_t palette[256];
1.1.1.10! root       54:     uint8_t r[256], g[256], b[256];
        !            55:     uint16_t width, height, depth;
1.1       root       56:     uint8_t dac_index, dac_state;
                     57: } TCXState;
                     58: 
1.1.1.2   root       59: static void tcx_screen_dump(void *opaque, const char *filename);
1.1.1.4   root       60: static void tcx24_screen_dump(void *opaque, const char *filename);
1.1.1.6   root       61: 
                     62: static void tcx_set_dirty(TCXState *s)
                     63: {
                     64:     unsigned int i;
                     65: 
                     66:     for (i = 0; i < MAXX * MAXY; i += TARGET_PAGE_SIZE) {
1.1.1.10! root       67:         memory_region_set_dirty(&s->vram_mem, i);
1.1.1.6   root       68:     }
                     69: }
                     70: 
                     71: static void tcx24_set_dirty(TCXState *s)
                     72: {
                     73:     unsigned int i;
                     74: 
                     75:     for (i = 0; i < MAXX * MAXY * 4; i += TARGET_PAGE_SIZE) {
1.1.1.10! root       76:         memory_region_set_dirty(&s->vram_mem, s->vram24_offset + i);
        !            77:         memory_region_set_dirty(&s->vram_mem, s->cplane_offset + i);
1.1.1.6   root       78:     }
                     79: }
1.1.1.3   root       80: 
                     81: static void update_palette_entries(TCXState *s, int start, int end)
                     82: {
                     83:     int i;
                     84:     for(i = start; i < end; i++) {
1.1.1.5   root       85:         switch(ds_get_bits_per_pixel(s->ds)) {
1.1.1.3   root       86:         default:
                     87:         case 8:
                     88:             s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
                     89:             break;
                     90:         case 15:
1.1.1.5   root       91:             s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root       92:             break;
                     93:         case 16:
1.1.1.5   root       94:             s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root       95:             break;
                     96:         case 32:
1.1.1.6   root       97:             if (is_surface_bgr(s->ds->surface))
                     98:                 s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
                     99:             else
                    100:                 s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
1.1.1.3   root      101:             break;
                    102:         }
                    103:     }
1.1.1.6   root      104:     if (s->depth == 24) {
                    105:         tcx24_set_dirty(s);
                    106:     } else {
                    107:         tcx_set_dirty(s);
                    108:     }
1.1.1.3   root      109: }
                    110: 
1.1.1.4   root      111: static void tcx_draw_line32(TCXState *s1, uint8_t *d,
                    112:                             const uint8_t *s, int width)
1.1       root      113: {
                    114:     int x;
                    115:     uint8_t val;
1.1.1.3   root      116:     uint32_t *p = (uint32_t *)d;
1.1       root      117: 
                    118:     for(x = 0; x < width; x++) {
1.1.1.4   root      119:         val = *s++;
1.1.1.3   root      120:         *p++ = s1->palette[val];
1.1       root      121:     }
                    122: }
                    123: 
1.1.1.4   root      124: static void tcx_draw_line16(TCXState *s1, uint8_t *d,
                    125:                             const uint8_t *s, int width)
1.1       root      126: {
                    127:     int x;
                    128:     uint8_t val;
1.1.1.3   root      129:     uint16_t *p = (uint16_t *)d;
1.1       root      130: 
                    131:     for(x = 0; x < width; x++) {
1.1.1.4   root      132:         val = *s++;
1.1.1.3   root      133:         *p++ = s1->palette[val];
1.1       root      134:     }
                    135: }
                    136: 
1.1.1.4   root      137: static void tcx_draw_line8(TCXState *s1, uint8_t *d,
                    138:                            const uint8_t *s, int width)
1.1       root      139: {
                    140:     int x;
                    141:     uint8_t val;
                    142: 
                    143:     for(x = 0; x < width; x++) {
1.1.1.4   root      144:         val = *s++;
1.1.1.3   root      145:         *d++ = s1->palette[val];
1.1       root      146:     }
                    147: }
                    148: 
1.1.1.5   root      149: /*
                    150:   XXX Could be much more optimal:
                    151:   * detect if line/page/whole screen is in 24 bit mode
                    152:   * if destination is also BGR, use memcpy
                    153:   */
1.1.1.4   root      154: static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
                    155:                                      const uint8_t *s, int width,
                    156:                                      const uint32_t *cplane,
                    157:                                      const uint32_t *s24)
                    158: {
1.1.1.6   root      159:     int x, bgr, r, g, b;
1.1.1.5   root      160:     uint8_t val, *p8;
1.1.1.4   root      161:     uint32_t *p = (uint32_t *)d;
                    162:     uint32_t dval;
                    163: 
1.1.1.6   root      164:     bgr = is_surface_bgr(s1->ds->surface);
1.1.1.4   root      165:     for(x = 0; x < width; x++, s++, s24++) {
1.1.1.5   root      166:         if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) {
                    167:             // 24-bit direct, BGR order
                    168:             p8 = (uint8_t *)s24;
                    169:             p8++;
                    170:             b = *p8++;
                    171:             g = *p8++;
1.1.1.8   root      172:             r = *p8;
1.1.1.6   root      173:             if (bgr)
                    174:                 dval = rgb_to_pixel32bgr(r, g, b);
                    175:             else
                    176:                 dval = rgb_to_pixel32(r, g, b);
1.1.1.4   root      177:         } else {
                    178:             val = *s;
                    179:             dval = s1->palette[val];
                    180:         }
                    181:         *p++ = dval;
                    182:     }
                    183: }
                    184: 
1.1.1.10! root      185: static inline int check_dirty(TCXState *s, ram_addr_t page, ram_addr_t page24,
1.1.1.4   root      186:                               ram_addr_t cpage)
                    187: {
                    188:     int ret;
                    189:     unsigned int off;
                    190: 
1.1.1.10! root      191:     ret = memory_region_get_dirty(&s->vram_mem, page, DIRTY_MEMORY_VGA);
1.1.1.4   root      192:     for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
1.1.1.10! root      193:         ret |= memory_region_get_dirty(&s->vram_mem, page24 + off,
        !           194:                                        DIRTY_MEMORY_VGA);
        !           195:         ret |= memory_region_get_dirty(&s->vram_mem, cpage + off,
        !           196:                                        DIRTY_MEMORY_VGA);
1.1.1.4   root      197:     }
                    198:     return ret;
                    199: }
                    200: 
                    201: static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
                    202:                                ram_addr_t page_max, ram_addr_t page24,
                    203:                               ram_addr_t cpage)
                    204: {
1.1.1.10! root      205:     memory_region_reset_dirty(&ts->vram_mem,
        !           206:                               page_min, page_max + TARGET_PAGE_SIZE,
        !           207:                               DIRTY_MEMORY_VGA);
        !           208:     memory_region_reset_dirty(&ts->vram_mem,
        !           209:                               page24 + page_min * 4,
        !           210:                               page24 + page_max * 4 + TARGET_PAGE_SIZE,
        !           211:                               DIRTY_MEMORY_VGA);
        !           212:     memory_region_reset_dirty(&ts->vram_mem,
        !           213:                               cpage + page_min * 4,
        !           214:                               cpage + page_max * 4 + TARGET_PAGE_SIZE,
        !           215:                               DIRTY_MEMORY_VGA);
1.1.1.4   root      216: }
                    217: 
1.1       root      218: /* Fixed line length 1024 allows us to do nice tricks not possible on
                    219:    VGA... */
1.1.1.2   root      220: static void tcx_update_display(void *opaque)
1.1       root      221: {
                    222:     TCXState *ts = opaque;
1.1.1.3   root      223:     ram_addr_t page, page_min, page_max;
                    224:     int y, y_start, dd, ds;
1.1       root      225:     uint8_t *d, *s;
1.1.1.4   root      226:     void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
1.1       root      227: 
1.1.1.5   root      228:     if (ds_get_bits_per_pixel(ts->ds) == 0)
1.1.1.4   root      229:         return;
1.1.1.10! root      230:     page = 0;
1.1       root      231:     y_start = -1;
1.1.1.6   root      232:     page_min = -1;
1.1.1.3   root      233:     page_max = 0;
1.1.1.5   root      234:     d = ds_get_data(ts->ds);
1.1       root      235:     s = ts->vram;
1.1.1.5   root      236:     dd = ds_get_linesize(ts->ds);
1.1       root      237:     ds = 1024;
                    238: 
1.1.1.5   root      239:     switch (ds_get_bits_per_pixel(ts->ds)) {
1.1       root      240:     case 32:
1.1.1.4   root      241:         f = tcx_draw_line32;
                    242:         break;
1.1.1.3   root      243:     case 15:
                    244:     case 16:
1.1.1.4   root      245:         f = tcx_draw_line16;
                    246:         break;
1.1       root      247:     default:
                    248:     case 8:
1.1.1.4   root      249:         f = tcx_draw_line8;
                    250:         break;
1.1       root      251:     case 0:
1.1.1.4   root      252:         return;
1.1       root      253:     }
1.1.1.4   root      254: 
1.1       root      255:     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
1.1.1.10! root      256:         if (memory_region_get_dirty(&ts->vram_mem, page, DIRTY_MEMORY_VGA)) {
1.1.1.4   root      257:             if (y_start < 0)
1.1       root      258:                 y_start = y;
                    259:             if (page < page_min)
                    260:                 page_min = page;
                    261:             if (page > page_max)
                    262:                 page_max = page;
1.1.1.4   root      263:             f(ts, d, s, ts->width);
                    264:             d += dd;
                    265:             s += ds;
                    266:             f(ts, d, s, ts->width);
                    267:             d += dd;
                    268:             s += ds;
                    269:             f(ts, d, s, ts->width);
                    270:             d += dd;
                    271:             s += ds;
                    272:             f(ts, d, s, ts->width);
                    273:             d += dd;
                    274:             s += ds;
                    275:         } else {
1.1       root      276:             if (y_start >= 0) {
                    277:                 /* flush to display */
1.1.1.4   root      278:                 dpy_update(ts->ds, 0, y_start,
1.1       root      279:                            ts->width, y - y_start);
                    280:                 y_start = -1;
                    281:             }
1.1.1.4   root      282:             d += dd * 4;
                    283:             s += ds * 4;
                    284:         }
1.1       root      285:     }
                    286:     if (y_start >= 0) {
1.1.1.4   root      287:         /* flush to display */
                    288:         dpy_update(ts->ds, 0, y_start,
                    289:                    ts->width, y - y_start);
1.1       root      290:     }
                    291:     /* reset modified pages */
1.1.1.6   root      292:     if (page_max >= page_min) {
1.1.1.10! root      293:         memory_region_reset_dirty(&ts->vram_mem,
        !           294:                                   page_min, page_max + TARGET_PAGE_SIZE,
        !           295:                                   DIRTY_MEMORY_VGA);
1.1       root      296:     }
                    297: }
                    298: 
1.1.1.4   root      299: static void tcx24_update_display(void *opaque)
                    300: {
                    301:     TCXState *ts = opaque;
                    302:     ram_addr_t page, page_min, page_max, cpage, page24;
                    303:     int y, y_start, dd, ds;
                    304:     uint8_t *d, *s;
                    305:     uint32_t *cptr, *s24;
                    306: 
1.1.1.5   root      307:     if (ds_get_bits_per_pixel(ts->ds) != 32)
1.1.1.4   root      308:             return;
1.1.1.10! root      309:     page = 0;
1.1.1.4   root      310:     page24 = ts->vram24_offset;
                    311:     cpage = ts->cplane_offset;
                    312:     y_start = -1;
1.1.1.6   root      313:     page_min = -1;
1.1.1.4   root      314:     page_max = 0;
1.1.1.5   root      315:     d = ds_get_data(ts->ds);
1.1.1.4   root      316:     s = ts->vram;
                    317:     s24 = ts->vram24;
                    318:     cptr = ts->cplane;
1.1.1.5   root      319:     dd = ds_get_linesize(ts->ds);
1.1.1.4   root      320:     ds = 1024;
                    321: 
                    322:     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
                    323:             page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
1.1.1.10! root      324:         if (check_dirty(ts, page, page24, cpage)) {
1.1.1.4   root      325:             if (y_start < 0)
                    326:                 y_start = y;
                    327:             if (page < page_min)
                    328:                 page_min = page;
                    329:             if (page > page_max)
                    330:                 page_max = page;
                    331:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
                    332:             d += dd;
                    333:             s += ds;
                    334:             cptr += ds;
                    335:             s24 += ds;
                    336:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
                    337:             d += dd;
                    338:             s += ds;
                    339:             cptr += ds;
                    340:             s24 += ds;
                    341:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
                    342:             d += dd;
                    343:             s += ds;
                    344:             cptr += ds;
                    345:             s24 += ds;
                    346:             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
                    347:             d += dd;
                    348:             s += ds;
                    349:             cptr += ds;
                    350:             s24 += ds;
                    351:         } else {
                    352:             if (y_start >= 0) {
                    353:                 /* flush to display */
                    354:                 dpy_update(ts->ds, 0, y_start,
                    355:                            ts->width, y - y_start);
                    356:                 y_start = -1;
                    357:             }
                    358:             d += dd * 4;
                    359:             s += ds * 4;
                    360:             cptr += ds * 4;
                    361:             s24 += ds * 4;
                    362:         }
                    363:     }
                    364:     if (y_start >= 0) {
                    365:         /* flush to display */
                    366:         dpy_update(ts->ds, 0, y_start,
                    367:                    ts->width, y - y_start);
                    368:     }
                    369:     /* reset modified pages */
1.1.1.6   root      370:     if (page_max >= page_min) {
1.1.1.4   root      371:         reset_dirty(ts, page_min, page_max, page24, cpage);
                    372:     }
                    373: }
                    374: 
1.1.1.2   root      375: static void tcx_invalidate_display(void *opaque)
1.1       root      376: {
                    377:     TCXState *s = opaque;
                    378: 
1.1.1.6   root      379:     tcx_set_dirty(s);
                    380:     qemu_console_resize(s->ds, s->width, s->height);
1.1.1.4   root      381: }
                    382: 
                    383: static void tcx24_invalidate_display(void *opaque)
                    384: {
                    385:     TCXState *s = opaque;
                    386: 
1.1.1.6   root      387:     tcx_set_dirty(s);
                    388:     tcx24_set_dirty(s);
                    389:     qemu_console_resize(s->ds, s->width, s->height);
1.1       root      390: }
                    391: 
1.1.1.7   root      392: static int vmstate_tcx_post_load(void *opaque, int version_id)
1.1       root      393: {
                    394:     TCXState *s = opaque;
1.1.1.4   root      395: 
1.1.1.3   root      396:     update_palette_entries(s, 0, 256);
1.1.1.6   root      397:     if (s->depth == 24) {
                    398:         tcx24_set_dirty(s);
                    399:     } else {
                    400:         tcx_set_dirty(s);
                    401:     }
1.1.1.4   root      402: 
1.1       root      403:     return 0;
                    404: }
                    405: 
1.1.1.7   root      406: static const VMStateDescription vmstate_tcx = {
                    407:     .name ="tcx",
                    408:     .version_id = 4,
                    409:     .minimum_version_id = 4,
                    410:     .minimum_version_id_old = 4,
                    411:     .post_load = vmstate_tcx_post_load,
                    412:     .fields      = (VMStateField []) {
                    413:         VMSTATE_UINT16(height, TCXState),
                    414:         VMSTATE_UINT16(width, TCXState),
                    415:         VMSTATE_UINT16(depth, TCXState),
                    416:         VMSTATE_BUFFER(r, TCXState),
                    417:         VMSTATE_BUFFER(g, TCXState),
                    418:         VMSTATE_BUFFER(b, TCXState),
                    419:         VMSTATE_UINT8(dac_index, TCXState),
                    420:         VMSTATE_UINT8(dac_state, TCXState),
                    421:         VMSTATE_END_OF_LIST()
                    422:     }
                    423: };
                    424: 
                    425: static void tcx_reset(DeviceState *d)
1.1       root      426: {
1.1.1.7   root      427:     TCXState *s = container_of(d, TCXState, busdev.qdev);
1.1       root      428: 
                    429:     /* Initialize palette */
                    430:     memset(s->r, 0, 256);
                    431:     memset(s->g, 0, 256);
                    432:     memset(s->b, 0, 256);
                    433:     s->r[255] = s->g[255] = s->b[255] = 255;
1.1.1.3   root      434:     update_palette_entries(s, 0, 256);
1.1       root      435:     memset(s->vram, 0, MAXX*MAXY);
1.1.1.10! root      436:     memory_region_reset_dirty(&s->vram_mem, 0, MAXX * MAXY * (1 + 4 + 4),
        !           437:                               DIRTY_MEMORY_VGA);
1.1       root      438:     s->dac_index = 0;
                    439:     s->dac_state = 0;
                    440: }
                    441: 
1.1.1.10! root      442: static uint64_t tcx_dac_readl(void *opaque, target_phys_addr_t addr,
        !           443:                               unsigned size)
1.1       root      444: {
                    445:     return 0;
                    446: }
                    447: 
1.1.1.10! root      448: static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint64_t val,
        !           449:                            unsigned size)
1.1       root      450: {
                    451:     TCXState *s = opaque;
                    452: 
1.1.1.5   root      453:     switch (addr) {
1.1       root      454:     case 0:
1.1.1.4   root      455:         s->dac_index = val >> 24;
                    456:         s->dac_state = 0;
                    457:         break;
1.1.1.5   root      458:     case 4:
1.1.1.4   root      459:         switch (s->dac_state) {
                    460:         case 0:
                    461:             s->r[s->dac_index] = val >> 24;
1.1.1.3   root      462:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4   root      463:             s->dac_state++;
                    464:             break;
                    465:         case 1:
                    466:             s->g[s->dac_index] = val >> 24;
1.1.1.3   root      467:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4   root      468:             s->dac_state++;
                    469:             break;
                    470:         case 2:
                    471:             s->b[s->dac_index] = val >> 24;
1.1.1.3   root      472:             update_palette_entries(s, s->dac_index, s->dac_index + 1);
1.1.1.4   root      473:             s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
                    474:         default:
                    475:             s->dac_state = 0;
                    476:             break;
                    477:         }
                    478:         break;
1.1       root      479:     default:
1.1.1.4   root      480:         break;
1.1       root      481:     }
                    482:     return;
                    483: }
                    484: 
1.1.1.10! root      485: static const MemoryRegionOps tcx_dac_ops = {
        !           486:     .read = tcx_dac_readl,
        !           487:     .write = tcx_dac_writel,
        !           488:     .endianness = DEVICE_NATIVE_ENDIAN,
        !           489:     .valid = {
        !           490:         .min_access_size = 4,
        !           491:         .max_access_size = 4,
        !           492:     },
1.1       root      493: };
                    494: 
1.1.1.10! root      495: static uint64_t dummy_readl(void *opaque, target_phys_addr_t addr,
        !           496:                             unsigned size)
1.1.1.4   root      497: {
                    498:     return 0;
                    499: }
                    500: 
1.1.1.10! root      501: static void dummy_writel(void *opaque, target_phys_addr_t addr,
        !           502:                          uint64_t val, unsigned size)
1.1.1.4   root      503: {
                    504: }
                    505: 
1.1.1.10! root      506: static const MemoryRegionOps dummy_ops = {
        !           507:     .read = dummy_readl,
        !           508:     .write = dummy_writel,
        !           509:     .endianness = DEVICE_NATIVE_ENDIAN,
        !           510:     .valid = {
        !           511:         .min_access_size = 4,
        !           512:         .max_access_size = 4,
        !           513:     },
1.1.1.4   root      514: };
                    515: 
1.1.1.7   root      516: static int tcx_init1(SysBusDevice *dev)
1.1.1.6   root      517: {
                    518:     TCXState *s = FROM_SYSBUS(TCXState, dev);
1.1.1.10! root      519:     ram_addr_t vram_offset = 0;
1.1.1.4   root      520:     int size;
1.1.1.6   root      521:     uint8_t *vram_base;
1.1       root      522: 
1.1.1.10! root      523:     memory_region_init_ram(&s->vram_mem, NULL, "tcx.vram",
        !           524:                            s->vram_size * (1 + 4 + 4));
        !           525:     vram_base = memory_region_get_ram_ptr(&s->vram_mem);
1.1.1.4   root      526: 
1.1.1.6   root      527:     /* 8-bit plane */
1.1.1.4   root      528:     s->vram = vram_base;
1.1.1.6   root      529:     size = s->vram_size;
1.1.1.10! root      530:     memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
        !           531:                              &s->vram_mem, vram_offset, size);
        !           532:     sysbus_init_mmio_region(dev, &s->vram_8bit);
1.1.1.4   root      533:     vram_offset += size;
                    534:     vram_base += size;
1.1       root      535: 
1.1.1.6   root      536:     /* DAC */
1.1.1.10! root      537:     memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS);
        !           538:     sysbus_init_mmio_region(dev, &s->dac);
1.1       root      539: 
1.1.1.6   root      540:     /* TEC (dummy) */
1.1.1.10! root      541:     memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
        !           542:     sysbus_init_mmio_region(dev, &s->tec);
1.1.1.6   root      543:     /* THC: NetBSD writes here even with 8-bit display: dummy */
1.1.1.10! root      544:     memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24",
        !           545:                           TCX_THC_NREGS_24);
        !           546:     sysbus_init_mmio_region(dev, &s->thc24);
1.1.1.6   root      547: 
                    548:     if (s->depth == 24) {
                    549:         /* 24-bit plane */
                    550:         size = s->vram_size * 4;
1.1.1.4   root      551:         s->vram24 = (uint32_t *)vram_base;
                    552:         s->vram24_offset = vram_offset;
1.1.1.10! root      553:         memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
        !           554:                                  &s->vram_mem, vram_offset, size);
        !           555:         sysbus_init_mmio_region(dev, &s->vram_24bit);
1.1.1.4   root      556:         vram_offset += size;
                    557:         vram_base += size;
                    558: 
1.1.1.6   root      559:         /* Control plane */
                    560:         size = s->vram_size * 4;
1.1.1.4   root      561:         s->cplane = (uint32_t *)vram_base;
                    562:         s->cplane_offset = vram_offset;
1.1.1.10! root      563:         memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
        !           564:                                  &s->vram_mem, vram_offset, size);
        !           565:         sysbus_init_mmio_region(dev, &s->vram_cplane);
1.1.1.6   root      566: 
1.1.1.5   root      567:         s->ds = graphic_console_init(tcx24_update_display,
                    568:                                      tcx24_invalidate_display,
                    569:                                      tcx24_screen_dump, NULL, s);
1.1.1.4   root      570:     } else {
1.1.1.6   root      571:         /* THC 8 bit (dummy) */
1.1.1.10! root      572:         memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
        !           573:                               TCX_THC_NREGS_8);
        !           574:         sysbus_init_mmio_region(dev, &s->thc8);
1.1.1.6   root      575: 
1.1.1.5   root      576:         s->ds = graphic_console_init(tcx_update_display,
                    577:                                      tcx_invalidate_display,
                    578:                                      tcx_screen_dump, NULL, s);
1.1.1.4   root      579:     }
                    580: 
1.1.1.6   root      581:     qemu_console_resize(s->ds, s->width, s->height);
1.1.1.7   root      582:     return 0;
1.1       root      583: }
                    584: 
1.1.1.2   root      585: static void tcx_screen_dump(void *opaque, const char *filename)
1.1       root      586: {
                    587:     TCXState *s = opaque;
                    588:     FILE *f;
                    589:     uint8_t *d, *d1, v;
                    590:     int y, x;
                    591: 
                    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:     for(y = 0; y < s->height; y++) {
                    598:         d = d1;
                    599:         for(x = 0; x < s->width; x++) {
                    600:             v = *d;
                    601:             fputc(s->r[v], f);
                    602:             fputc(s->g[v], f);
                    603:             fputc(s->b[v], f);
                    604:             d++;
                    605:         }
                    606:         d1 += MAXX;
                    607:     }
                    608:     fclose(f);
                    609:     return;
                    610: }
                    611: 
1.1.1.4   root      612: static void tcx24_screen_dump(void *opaque, const char *filename)
                    613: {
                    614:     TCXState *s = opaque;
                    615:     FILE *f;
                    616:     uint8_t *d, *d1, v;
                    617:     uint32_t *s24, *cptr, dval;
                    618:     int y, x;
1.1       root      619: 
1.1.1.4   root      620:     f = fopen(filename, "wb");
                    621:     if (!f)
                    622:         return;
                    623:     fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
                    624:     d1 = s->vram;
                    625:     s24 = s->vram24;
                    626:     cptr = s->cplane;
                    627:     for(y = 0; y < s->height; y++) {
                    628:         d = d1;
                    629:         for(x = 0; x < s->width; x++, d++, s24++) {
                    630:             if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
                    631:                 dval = *s24 & 0x00ffffff;
                    632:                 fputc((dval >> 16) & 0xff, f);
                    633:                 fputc((dval >> 8) & 0xff, f);
                    634:                 fputc(dval & 0xff, f);
                    635:             } else {
                    636:                 v = *d;
                    637:                 fputc(s->r[v], f);
                    638:                 fputc(s->g[v], f);
                    639:                 fputc(s->b[v], f);
                    640:             }
                    641:         }
                    642:         d1 += MAXX;
                    643:     }
                    644:     fclose(f);
                    645:     return;
                    646: }
1.1.1.6   root      647: 
                    648: static SysBusDeviceInfo tcx_info = {
                    649:     .init = tcx_init1,
                    650:     .qdev.name  = "SUNW,tcx",
                    651:     .qdev.size  = sizeof(TCXState),
1.1.1.7   root      652:     .qdev.reset = tcx_reset,
                    653:     .qdev.vmsd  = &vmstate_tcx,
1.1.1.6   root      654:     .qdev.props = (Property[]) {
1.1.1.7   root      655:         DEFINE_PROP_TADDR("addr",      TCXState, addr,      -1),
                    656:         DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
                    657:         DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
                    658:         DEFINE_PROP_UINT16("height",   TCXState, height,    -1),
                    659:         DEFINE_PROP_UINT16("depth",    TCXState, depth,     -1),
                    660:         DEFINE_PROP_END_OF_LIST(),
1.1.1.6   root      661:     }
                    662: };
                    663: 
                    664: static void tcx_register_devices(void)
                    665: {
                    666:     sysbus_register_withprop(&tcx_info);
                    667: }
                    668: 
                    669: device_init(tcx_register_devices)

unix.superglobalmegacorp.com

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