aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/vga.c113
1 files changed, 86 insertions, 27 deletions
diff --git a/hw/vga.c b/hw/vga.c
index 058a77cc72..80212070ea 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -1223,6 +1223,35 @@ static const uint8_t cursor_glyph[32 * 4] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
+static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
+ int *pcwidth, int *pcheight)
+{
+ int width, cwidth, height, cheight;
+
+ /* total width & height */
+ cheight = (s->cr[9] & 0x1f) + 1;
+ cwidth = 8;
+ if (!(s->sr[1] & 0x01))
+ cwidth = 9;
+ if (s->sr[1] & 0x08)
+ cwidth = 16; /* NOTE: no 18 pixel wide */
+ width = (s->cr[0x01] + 1);
+ if (s->cr[0x06] == 100) {
+ /* ugly hack for CGA 160x100x16 - explain me the logic */
+ height = 100;
+ } else {
+ height = s->cr[0x12] |
+ ((s->cr[0x07] & 0x02) << 7) |
+ ((s->cr[0x07] & 0x40) << 3);
+ height = (height + 1) / cheight;
+ }
+
+ *pwidth = width;
+ *pheight = height;
+ *pcwidth = cwidth;
+ *pcheight = cheight;
+}
+
/*
* Text mode update
* Missing:
@@ -1275,24 +1304,8 @@ static void vga_draw_text(VGAState *s, int full_update)
line_offset = s->line_offset;
s1 = s->vram_ptr + (s->start_addr * 4);
- /* total width & height */
- cheight = (s->cr[9] & 0x1f) + 1;
- cw = 8;
- if (!(s->sr[1] & 0x01))
- cw = 9;
- if (s->sr[1] & 0x08)
- cw = 16; /* NOTE: no 18 pixel wide */
+ vga_get_text_resolution(s, &width, &height, &cw, &cheight);
x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
- width = (s->cr[0x01] + 1);
- if (s->cr[0x06] == 100) {
- /* ugly hack for CGA 160x100x16 - explain me the logic */
- height = 100;
- } else {
- height = s->cr[0x12] |
- ((s->cr[0x07] & 0x02) << 7) |
- ((s->cr[0x07] & 0x40) << 3);
- height = (height + 1) / cheight;
- }
if ((height * width) > CH_ATTR_SIZE) {
/* better than nothing: exit if transient size is too big */
return;
@@ -2542,11 +2555,29 @@ int ppm_save(const char *filename, uint8_t *data,
return 0;
}
-/* save the vga display in a PPM image even if no display is
- available */
-static void vga_screen_dump(void *opaque, const char *filename)
+static void vga_screen_dump_blank(VGAState *s, const char *filename)
+{
+ FILE *f;
+ unsigned int y, x, w, h;
+
+ w = s->last_scr_width * sizeof(uint32_t);
+ h = s->last_scr_height;
+
+ f = fopen(filename, "wb");
+ if (!f)
+ return;
+ fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ fputc(0, f);
+ }
+ }
+ fclose(f);
+}
+
+static void vga_screen_dump_common(VGAState *s, const char *filename,
+ int w, int h)
{
- VGAState *s = (VGAState *)opaque;
DisplayState *saved_ds, ds1, *ds = &ds1;
/* XXX: this is a little hackish */
@@ -2559,14 +2590,42 @@ static void vga_screen_dump(void *opaque, const char *filename)
ds->dpy_refresh = vga_save_dpy_refresh;
ds->depth = 32;
+ ds->linesize = w * sizeof(uint32_t);
+ ds->data = qemu_mallocz(h * ds->linesize);
s->ds = ds;
s->graphic_mode = -1;
vga_update_display(s);
-
- if (ds_get_data(ds)) {
- ppm_save(filename, ds_get_data(ds), vga_save_w, vga_save_h,
- ds_get_linesize(s->ds));
- qemu_free(ds_get_data(ds));
- }
+ ppm_save(filename, ds->data, w, h, ds->linesize);
+ qemu_free(ds->data);
s->ds = saved_ds;
}
+
+static void vga_screen_dump_graphic(VGAState *s, const char *filename)
+{
+ int w, h;
+
+ s->get_resolution(s, &w, &h);
+ vga_screen_dump_common(s, filename, w, h);
+}
+
+static void vga_screen_dump_text(VGAState *s, const char *filename)
+{
+ int w, h, cwidth, cheight;
+
+ vga_get_text_resolution(s, &w, &h, &cwidth, &cheight);
+ vga_screen_dump_common(s, filename, w * cwidth, h * cheight);
+}
+
+/* save the vga display in a PPM image even if no display is
+ available */
+static void vga_screen_dump(void *opaque, const char *filename)
+{
+ VGAState *s = (VGAState *)opaque;
+
+ if (!(s->ar_index & 0x20))
+ vga_screen_dump_blank(s, filename);
+ else if (s->gr[6] & 1)
+ vga_screen_dump_graphic(s, filename);
+ else
+ vga_screen_dump_text(s, filename);
+}