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 | +} | ... | ... |