Commit 4c5e8c5ce8a874880bc403ef153285f54dbbd960
1 parent
6fa724a3
Fix VGA screen dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6159 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
86 additions
and
27 deletions
hw/vga.c
| ... | ... | @@ -1223,6 +1223,35 @@ static const uint8_t cursor_glyph[32 * 4] = { |
| 1223 | 1223 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
| 1224 | 1224 | }; |
| 1225 | 1225 | |
| 1226 | +static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight, | |
| 1227 | + int *pcwidth, int *pcheight) | |
| 1228 | +{ | |
| 1229 | + int width, cwidth, height, cheight; | |
| 1230 | + | |
| 1231 | + /* total width & height */ | |
| 1232 | + cheight = (s->cr[9] & 0x1f) + 1; | |
| 1233 | + cwidth = 8; | |
| 1234 | + if (!(s->sr[1] & 0x01)) | |
| 1235 | + cwidth = 9; | |
| 1236 | + if (s->sr[1] & 0x08) | |
| 1237 | + cwidth = 16; /* NOTE: no 18 pixel wide */ | |
| 1238 | + width = (s->cr[0x01] + 1); | |
| 1239 | + if (s->cr[0x06] == 100) { | |
| 1240 | + /* ugly hack for CGA 160x100x16 - explain me the logic */ | |
| 1241 | + height = 100; | |
| 1242 | + } else { | |
| 1243 | + height = s->cr[0x12] | | |
| 1244 | + ((s->cr[0x07] & 0x02) << 7) | | |
| 1245 | + ((s->cr[0x07] & 0x40) << 3); | |
| 1246 | + height = (height + 1) / cheight; | |
| 1247 | + } | |
| 1248 | + | |
| 1249 | + *pwidth = width; | |
| 1250 | + *pheight = height; | |
| 1251 | + *pcwidth = cwidth; | |
| 1252 | + *pcheight = cheight; | |
| 1253 | +} | |
| 1254 | + | |
| 1226 | 1255 | /* |
| 1227 | 1256 | * Text mode update |
| 1228 | 1257 | * Missing: |
| ... | ... | @@ -1275,24 +1304,8 @@ static void vga_draw_text(VGAState *s, int full_update) |
| 1275 | 1304 | line_offset = s->line_offset; |
| 1276 | 1305 | s1 = s->vram_ptr + (s->start_addr * 4); |
| 1277 | 1306 | |
| 1278 | - /* total width & height */ | |
| 1279 | - cheight = (s->cr[9] & 0x1f) + 1; | |
| 1280 | - cw = 8; | |
| 1281 | - if (!(s->sr[1] & 0x01)) | |
| 1282 | - cw = 9; | |
| 1283 | - if (s->sr[1] & 0x08) | |
| 1284 | - cw = 16; /* NOTE: no 18 pixel wide */ | |
| 1307 | + vga_get_text_resolution(s, &width, &height, &cw, &cheight); | |
| 1285 | 1308 | x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3); |
| 1286 | - width = (s->cr[0x01] + 1); | |
| 1287 | - if (s->cr[0x06] == 100) { | |
| 1288 | - /* ugly hack for CGA 160x100x16 - explain me the logic */ | |
| 1289 | - height = 100; | |
| 1290 | - } else { | |
| 1291 | - height = s->cr[0x12] | | |
| 1292 | - ((s->cr[0x07] & 0x02) << 7) | | |
| 1293 | - ((s->cr[0x07] & 0x40) << 3); | |
| 1294 | - height = (height + 1) / cheight; | |
| 1295 | - } | |
| 1296 | 1309 | if ((height * width) > CH_ATTR_SIZE) { |
| 1297 | 1310 | /* better than nothing: exit if transient size is too big */ |
| 1298 | 1311 | return; |
| ... | ... | @@ -2542,11 +2555,29 @@ int ppm_save(const char *filename, uint8_t *data, |
| 2542 | 2555 | return 0; |
| 2543 | 2556 | } |
| 2544 | 2557 | |
| 2545 | -/* save the vga display in a PPM image even if no display is | |
| 2546 | - available */ | |
| 2547 | -static void vga_screen_dump(void *opaque, const char *filename) | |
| 2558 | +static void vga_screen_dump_blank(VGAState *s, const char *filename) | |
| 2559 | +{ | |
| 2560 | + FILE *f; | |
| 2561 | + unsigned int y, x, w, h; | |
| 2562 | + | |
| 2563 | + w = s->last_scr_width * sizeof(uint32_t); | |
| 2564 | + h = s->last_scr_height; | |
| 2565 | + | |
| 2566 | + f = fopen(filename, "wb"); | |
| 2567 | + if (!f) | |
| 2568 | + return; | |
| 2569 | + fprintf(f, "P6\n%d %d\n%d\n", w, h, 255); | |
| 2570 | + for (y = 0; y < h; y++) { | |
| 2571 | + for (x = 0; x < w; x++) { | |
| 2572 | + fputc(0, f); | |
| 2573 | + } | |
| 2574 | + } | |
| 2575 | + fclose(f); | |
| 2576 | +} | |
| 2577 | + | |
| 2578 | +static void vga_screen_dump_common(VGAState *s, const char *filename, | |
| 2579 | + int w, int h) | |
| 2548 | 2580 | { |
| 2549 | - VGAState *s = (VGAState *)opaque; | |
| 2550 | 2581 | DisplayState *saved_ds, ds1, *ds = &ds1; |
| 2551 | 2582 | |
| 2552 | 2583 | /* XXX: this is a little hackish */ |
| ... | ... | @@ -2559,14 +2590,42 @@ static void vga_screen_dump(void *opaque, const char *filename) |
| 2559 | 2590 | ds->dpy_refresh = vga_save_dpy_refresh; |
| 2560 | 2591 | ds->depth = 32; |
| 2561 | 2592 | |
| 2593 | + ds->linesize = w * sizeof(uint32_t); | |
| 2594 | + ds->data = qemu_mallocz(h * ds->linesize); | |
| 2562 | 2595 | s->ds = ds; |
| 2563 | 2596 | s->graphic_mode = -1; |
| 2564 | 2597 | vga_update_display(s); |
| 2565 | - | |
| 2566 | - if (ds_get_data(ds)) { | |
| 2567 | - ppm_save(filename, ds_get_data(ds), vga_save_w, vga_save_h, | |
| 2568 | - ds_get_linesize(s->ds)); | |
| 2569 | - qemu_free(ds_get_data(ds)); | |
| 2570 | - } | |
| 2598 | + ppm_save(filename, ds->data, w, h, ds->linesize); | |
| 2599 | + qemu_free(ds->data); | |
| 2571 | 2600 | s->ds = saved_ds; |
| 2572 | 2601 | } |
| 2602 | + | |
| 2603 | +static void vga_screen_dump_graphic(VGAState *s, const char *filename) | |
| 2604 | +{ | |
| 2605 | + int w, h; | |
| 2606 | + | |
| 2607 | + s->get_resolution(s, &w, &h); | |
| 2608 | + vga_screen_dump_common(s, filename, w, h); | |
| 2609 | +} | |
| 2610 | + | |
| 2611 | +static void vga_screen_dump_text(VGAState *s, const char *filename) | |
| 2612 | +{ | |
| 2613 | + int w, h, cwidth, cheight; | |
| 2614 | + | |
| 2615 | + vga_get_text_resolution(s, &w, &h, &cwidth, &cheight); | |
| 2616 | + vga_screen_dump_common(s, filename, w * cwidth, h * cheight); | |
| 2617 | +} | |
| 2618 | + | |
| 2619 | +/* save the vga display in a PPM image even if no display is | |
| 2620 | + available */ | |
| 2621 | +static void vga_screen_dump(void *opaque, const char *filename) | |
| 2622 | +{ | |
| 2623 | + VGAState *s = (VGAState *)opaque; | |
| 2624 | + | |
| 2625 | + if (!(s->ar_index & 0x20)) | |
| 2626 | + vga_screen_dump_blank(s, filename); | |
| 2627 | + else if (s->gr[6] & 1) | |
| 2628 | + vga_screen_dump_graphic(s, filename); | |
| 2629 | + else | |
| 2630 | + vga_screen_dump_text(s, filename); | |
| 2631 | +} | ... | ... |