Fix VGA screen dump
[qemu] / hw / vga.c
1 /*
2  * QEMU VGA Emulator.
3  *
4  * Copyright (c) 2003 Fabrice Bellard
5  *
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  */
24 #include "hw.h"
25 #include "console.h"
26 #include "pc.h"
27 #include "pci.h"
28 #include "vga_int.h"
29 #include "pixel_ops.h"
30 #include "qemu-timer.h"
31 #include "kvm.h"
32
33 //#define DEBUG_VGA
34 //#define DEBUG_VGA_MEM
35 //#define DEBUG_VGA_REG
36
37 //#define DEBUG_BOCHS_VBE
38
39 /* force some bits to zero */
40 const uint8_t sr_mask[8] = {
41     (uint8_t)~0xfc,
42     (uint8_t)~0xc2,
43     (uint8_t)~0xf0,
44     (uint8_t)~0xc0,
45     (uint8_t)~0xf1,
46     (uint8_t)~0xff,
47     (uint8_t)~0xff,
48     (uint8_t)~0x00,
49 };
50
51 const uint8_t gr_mask[16] = {
52     (uint8_t)~0xf0, /* 0x00 */
53     (uint8_t)~0xf0, /* 0x01 */
54     (uint8_t)~0xf0, /* 0x02 */
55     (uint8_t)~0xe0, /* 0x03 */
56     (uint8_t)~0xfc, /* 0x04 */
57     (uint8_t)~0x84, /* 0x05 */
58     (uint8_t)~0xf0, /* 0x06 */
59     (uint8_t)~0xf0, /* 0x07 */
60     (uint8_t)~0x00, /* 0x08 */
61     (uint8_t)~0xff, /* 0x09 */
62     (uint8_t)~0xff, /* 0x0a */
63     (uint8_t)~0xff, /* 0x0b */
64     (uint8_t)~0xff, /* 0x0c */
65     (uint8_t)~0xff, /* 0x0d */
66     (uint8_t)~0xff, /* 0x0e */
67     (uint8_t)~0xff, /* 0x0f */
68 };
69
70 #define cbswap_32(__x) \
71 ((uint32_t)( \
72                 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
73                 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
74                 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
75                 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
76
77 #ifdef WORDS_BIGENDIAN
78 #define PAT(x) cbswap_32(x)
79 #else
80 #define PAT(x) (x)
81 #endif
82
83 #ifdef WORDS_BIGENDIAN
84 #define BIG 1
85 #else
86 #define BIG 0
87 #endif
88
89 #ifdef WORDS_BIGENDIAN
90 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
91 #else
92 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
93 #endif
94
95 static const uint32_t mask16[16] = {
96     PAT(0x00000000),
97     PAT(0x000000ff),
98     PAT(0x0000ff00),
99     PAT(0x0000ffff),
100     PAT(0x00ff0000),
101     PAT(0x00ff00ff),
102     PAT(0x00ffff00),
103     PAT(0x00ffffff),
104     PAT(0xff000000),
105     PAT(0xff0000ff),
106     PAT(0xff00ff00),
107     PAT(0xff00ffff),
108     PAT(0xffff0000),
109     PAT(0xffff00ff),
110     PAT(0xffffff00),
111     PAT(0xffffffff),
112 };
113
114 #undef PAT
115
116 #ifdef WORDS_BIGENDIAN
117 #define PAT(x) (x)
118 #else
119 #define PAT(x) cbswap_32(x)
120 #endif
121
122 static const uint32_t dmask16[16] = {
123     PAT(0x00000000),
124     PAT(0x000000ff),
125     PAT(0x0000ff00),
126     PAT(0x0000ffff),
127     PAT(0x00ff0000),
128     PAT(0x00ff00ff),
129     PAT(0x00ffff00),
130     PAT(0x00ffffff),
131     PAT(0xff000000),
132     PAT(0xff0000ff),
133     PAT(0xff00ff00),
134     PAT(0xff00ffff),
135     PAT(0xffff0000),
136     PAT(0xffff00ff),
137     PAT(0xffffff00),
138     PAT(0xffffffff),
139 };
140
141 static const uint32_t dmask4[4] = {
142     PAT(0x00000000),
143     PAT(0x0000ffff),
144     PAT(0xffff0000),
145     PAT(0xffffffff),
146 };
147
148 static uint32_t expand4[256];
149 static uint16_t expand2[256];
150 static uint8_t expand4to8[16];
151
152 static void vga_screen_dump(void *opaque, const char *filename);
153
154 static void vga_dumb_update_retrace_info(VGAState *s)
155 {
156     (void) s;
157 }
158
159 static void vga_precise_update_retrace_info(VGAState *s)
160 {
161     int htotal_chars;
162     int hretr_start_char;
163     int hretr_skew_chars;
164     int hretr_end_char;
165
166     int vtotal_lines;
167     int vretr_start_line;
168     int vretr_end_line;
169
170     int div2, sldiv2, dots;
171     int clocking_mode;
172     int clock_sel;
173     const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
174     int64_t chars_per_sec;
175     struct vga_precise_retrace *r = &s->retrace_info.precise;
176
177     htotal_chars = s->cr[0x00] + 5;
178     hretr_start_char = s->cr[0x04];
179     hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
180     hretr_end_char = s->cr[0x05] & 0x1f;
181
182     vtotal_lines = (s->cr[0x06]
183                     | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
184         ;
185     vretr_start_line = s->cr[0x10]
186         | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
187         ;
188     vretr_end_line = s->cr[0x11] & 0xf;
189
190
191     div2 = (s->cr[0x17] >> 2) & 1;
192     sldiv2 = (s->cr[0x17] >> 3) & 1;
193
194     clocking_mode = (s->sr[0x01] >> 3) & 1;
195     clock_sel = (s->msr >> 2) & 3;
196     dots = (s->msr & 1) ? 8 : 9;
197
198     chars_per_sec = clk_hz[clock_sel] / dots;
199
200     htotal_chars <<= clocking_mode;
201
202     r->total_chars = vtotal_lines * htotal_chars;
203     if (r->freq) {
204         r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
205     } else {
206         r->ticks_per_char = ticks_per_sec / chars_per_sec;
207     }
208
209     r->vstart = vretr_start_line;
210     r->vend = r->vstart + vretr_end_line + 1;
211
212     r->hstart = hretr_start_char + hretr_skew_chars;
213     r->hend = r->hstart + hretr_end_char + 1;
214     r->htotal = htotal_chars;
215
216 #if 0
217     printf (
218         "hz=%f\n"
219         "htotal = %d\n"
220         "hretr_start = %d\n"
221         "hretr_skew = %d\n"
222         "hretr_end = %d\n"
223         "vtotal = %d\n"
224         "vretr_start = %d\n"
225         "vretr_end = %d\n"
226         "div2 = %d sldiv2 = %d\n"
227         "clocking_mode = %d\n"
228         "clock_sel = %d %d\n"
229         "dots = %d\n"
230         "ticks/char = %lld\n"
231         "\n",
232         (double) ticks_per_sec / (r->ticks_per_char * r->total_chars),
233         htotal_chars,
234         hretr_start_char,
235         hretr_skew_chars,
236         hretr_end_char,
237         vtotal_lines,
238         vretr_start_line,
239         vretr_end_line,
240         div2, sldiv2,
241         clocking_mode,
242         clock_sel,
243         clk_hz[clock_sel],
244         dots,
245         r->ticks_per_char
246         );
247 #endif
248 }
249
250 static uint8_t vga_precise_retrace(VGAState *s)
251 {
252     struct vga_precise_retrace *r = &s->retrace_info.precise;
253     uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
254
255     if (r->total_chars) {
256         int cur_line, cur_line_char, cur_char;
257         int64_t cur_tick;
258
259         cur_tick = qemu_get_clock(vm_clock);
260
261         cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
262         cur_line = cur_char / r->htotal;
263
264         if (cur_line >= r->vstart && cur_line <= r->vend) {
265             val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
266         } else {
267             cur_line_char = cur_char % r->htotal;
268             if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
269                 val |= ST01_DISP_ENABLE;
270             }
271         }
272
273         return val;
274     } else {
275         return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
276     }
277 }
278
279 static uint8_t vga_dumb_retrace(VGAState *s)
280 {
281     return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
282 }
283
284 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
285 {
286     VGAState *s = opaque;
287     int val, index;
288
289     /* check port range access depending on color/monochrome mode */
290     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
291         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
292         val = 0xff;
293     } else {
294         switch(addr) {
295         case 0x3c0:
296             if (s->ar_flip_flop == 0) {
297                 val = s->ar_index;
298             } else {
299                 val = 0;
300             }
301             break;
302         case 0x3c1:
303             index = s->ar_index & 0x1f;
304             if (index < 21)
305                 val = s->ar[index];
306             else
307                 val = 0;
308             break;
309         case 0x3c2:
310             val = s->st00;
311             break;
312         case 0x3c4:
313             val = s->sr_index;
314             break;
315         case 0x3c5:
316             val = s->sr[s->sr_index];
317 #ifdef DEBUG_VGA_REG
318             printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
319 #endif
320             break;
321         case 0x3c7:
322             val = s->dac_state;
323             break;
324         case 0x3c8:
325             val = s->dac_write_index;
326             break;
327         case 0x3c9:
328             val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
329             if (++s->dac_sub_index == 3) {
330                 s->dac_sub_index = 0;
331                 s->dac_read_index++;
332             }
333             break;
334         case 0x3ca:
335             val = s->fcr;
336             break;
337         case 0x3cc:
338             val = s->msr;
339             break;
340         case 0x3ce:
341             val = s->gr_index;
342             break;
343         case 0x3cf:
344             val = s->gr[s->gr_index];
345 #ifdef DEBUG_VGA_REG
346             printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
347 #endif
348             break;
349         case 0x3b4:
350         case 0x3d4:
351             val = s->cr_index;
352             break;
353         case 0x3b5:
354         case 0x3d5:
355             val = s->cr[s->cr_index];
356 #ifdef DEBUG_VGA_REG
357             printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
358 #endif
359             break;
360         case 0x3ba:
361         case 0x3da:
362             /* just toggle to fool polling */
363             val = s->st01 = s->retrace(s);
364             s->ar_flip_flop = 0;
365             break;
366         default:
367             val = 0x00;
368             break;
369         }
370     }
371 #if defined(DEBUG_VGA)
372     printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
373 #endif
374     return val;
375 }
376
377 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
378 {
379     VGAState *s = opaque;
380     int index;
381
382     /* check port range access depending on color/monochrome mode */
383     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
384         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
385         return;
386
387 #ifdef DEBUG_VGA
388     printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
389 #endif
390
391     switch(addr) {
392     case 0x3c0:
393         if (s->ar_flip_flop == 0) {
394             val &= 0x3f;
395             s->ar_index = val;
396         } else {
397             index = s->ar_index & 0x1f;
398             switch(index) {
399             case 0x00 ... 0x0f:
400                 s->ar[index] = val & 0x3f;
401                 break;
402             case 0x10:
403                 s->ar[index] = val & ~0x10;
404                 break;
405             case 0x11:
406                 s->ar[index] = val;
407                 break;
408             case 0x12:
409                 s->ar[index] = val & ~0xc0;
410                 break;
411             case 0x13:
412                 s->ar[index] = val & ~0xf0;
413                 break;
414             case 0x14:
415                 s->ar[index] = val & ~0xf0;
416                 break;
417             default:
418                 break;
419             }
420         }
421         s->ar_flip_flop ^= 1;
422         break;
423     case 0x3c2:
424         s->msr = val & ~0x10;
425         s->update_retrace_info(s);
426         break;
427     case 0x3c4:
428         s->sr_index = val & 7;
429         break;
430     case 0x3c5:
431 #ifdef DEBUG_VGA_REG
432         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
433 #endif
434         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
435         if (s->sr_index == 1) s->update_retrace_info(s);
436         break;
437     case 0x3c7:
438         s->dac_read_index = val;
439         s->dac_sub_index = 0;
440         s->dac_state = 3;
441         break;
442     case 0x3c8:
443         s->dac_write_index = val;
444         s->dac_sub_index = 0;
445         s->dac_state = 0;
446         break;
447     case 0x3c9:
448         s->dac_cache[s->dac_sub_index] = val;
449         if (++s->dac_sub_index == 3) {
450             memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
451             s->dac_sub_index = 0;
452             s->dac_write_index++;
453         }
454         break;
455     case 0x3ce:
456         s->gr_index = val & 0x0f;
457         break;
458     case 0x3cf:
459 #ifdef DEBUG_VGA_REG
460         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
461 #endif
462         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
463         break;
464     case 0x3b4:
465     case 0x3d4:
466         s->cr_index = val;
467         break;
468     case 0x3b5:
469     case 0x3d5:
470 #ifdef DEBUG_VGA_REG
471         printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
472 #endif
473         /* handle CR0-7 protection */
474         if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
475             /* can always write bit 4 of CR7 */
476             if (s->cr_index == 7)
477                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
478             return;
479         }
480         switch(s->cr_index) {
481         case 0x01: /* horizontal display end */
482         case 0x07:
483         case 0x09:
484         case 0x0c:
485         case 0x0d:
486         case 0x12: /* vertical display end */
487             s->cr[s->cr_index] = val;
488             break;
489         default:
490             s->cr[s->cr_index] = val;
491             break;
492         }
493
494         switch(s->cr_index) {
495         case 0x00:
496         case 0x04:
497         case 0x05:
498         case 0x06:
499         case 0x07:
500         case 0x11:
501         case 0x17:
502             s->update_retrace_info(s);
503             break;
504         }
505         break;
506     case 0x3ba:
507     case 0x3da:
508         s->fcr = val & 0x10;
509         break;
510     }
511 }
512
513 #ifdef CONFIG_BOCHS_VBE
514 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
515 {
516     VGAState *s = opaque;
517     uint32_t val;
518     val = s->vbe_index;
519     return val;
520 }
521
522 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
523 {
524     VGAState *s = opaque;
525     uint32_t val;
526
527     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
528         if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
529             switch(s->vbe_index) {
530                 /* XXX: do not hardcode ? */
531             case VBE_DISPI_INDEX_XRES:
532                 val = VBE_DISPI_MAX_XRES;
533                 break;
534             case VBE_DISPI_INDEX_YRES:
535                 val = VBE_DISPI_MAX_YRES;
536                 break;
537             case VBE_DISPI_INDEX_BPP:
538                 val = VBE_DISPI_MAX_BPP;
539                 break;
540             default:
541                 val = s->vbe_regs[s->vbe_index];
542                 break;
543             }
544         } else {
545             val = s->vbe_regs[s->vbe_index];
546         }
547     } else {
548         val = 0;
549     }
550 #ifdef DEBUG_BOCHS_VBE
551     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
552 #endif
553     return val;
554 }
555
556 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
557 {
558     VGAState *s = opaque;
559     s->vbe_index = val;
560 }
561
562 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
563 {
564     VGAState *s = opaque;
565
566     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
567 #ifdef DEBUG_BOCHS_VBE
568         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
569 #endif
570         switch(s->vbe_index) {
571         case VBE_DISPI_INDEX_ID:
572             if (val == VBE_DISPI_ID0 ||
573                 val == VBE_DISPI_ID1 ||
574                 val == VBE_DISPI_ID2 ||
575                 val == VBE_DISPI_ID3 ||
576                 val == VBE_DISPI_ID4) {
577                 s->vbe_regs[s->vbe_index] = val;
578             }
579             break;
580         case VBE_DISPI_INDEX_XRES:
581             if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
582                 s->vbe_regs[s->vbe_index] = val;
583             }
584             break;
585         case VBE_DISPI_INDEX_YRES:
586             if (val <= VBE_DISPI_MAX_YRES) {
587                 s->vbe_regs[s->vbe_index] = val;
588             }
589             break;
590         case VBE_DISPI_INDEX_BPP:
591             if (val == 0)
592                 val = 8;
593             if (val == 4 || val == 8 || val == 15 ||
594                 val == 16 || val == 24 || val == 32) {
595                 s->vbe_regs[s->vbe_index] = val;
596             }
597             break;
598         case VBE_DISPI_INDEX_BANK:
599             if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
600               val &= (s->vbe_bank_mask >> 2);
601             } else {
602               val &= s->vbe_bank_mask;
603             }
604             s->vbe_regs[s->vbe_index] = val;
605             s->bank_offset = (val << 16);
606             break;
607         case VBE_DISPI_INDEX_ENABLE:
608             if ((val & VBE_DISPI_ENABLED) &&
609                 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
610                 int h, shift_control;
611
612                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
613                     s->vbe_regs[VBE_DISPI_INDEX_XRES];
614                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
615                     s->vbe_regs[VBE_DISPI_INDEX_YRES];
616                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
617                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
618
619                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
620                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
621                 else
622                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
623                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
624                 s->vbe_start_addr = 0;
625
626                 /* clear the screen (should be done in BIOS) */
627                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
628                     memset(s->vram_ptr, 0,
629                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
630                 }
631
632                 /* we initialize the VGA graphic mode (should be done
633                    in BIOS) */
634                 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
635                 s->cr[0x17] |= 3; /* no CGA modes */
636                 s->cr[0x13] = s->vbe_line_offset >> 3;
637                 /* width */
638                 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
639                 /* height (only meaningful if < 1024) */
640                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
641                 s->cr[0x12] = h;
642                 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
643                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
644                 /* line compare to 1023 */
645                 s->cr[0x18] = 0xff;
646                 s->cr[0x07] |= 0x10;
647                 s->cr[0x09] |= 0x40;
648
649                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
650                     shift_control = 0;
651                     s->sr[0x01] &= ~8; /* no double line */
652                 } else {
653                     shift_control = 2;
654                     s->sr[4] |= 0x08; /* set chain 4 mode */
655                     s->sr[2] |= 0x0f; /* activate all planes */
656                 }
657                 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
658                 s->cr[0x09] &= ~0x9f; /* no double scan */
659             } else {
660                 /* XXX: the bios should do that */
661                 s->bank_offset = 0;
662             }
663             s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
664             s->vbe_regs[s->vbe_index] = val;
665             break;
666         case VBE_DISPI_INDEX_VIRT_WIDTH:
667             {
668                 int w, h, line_offset;
669
670                 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
671                     return;
672                 w = val;
673                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
674                     line_offset = w >> 1;
675                 else
676                     line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
677                 h = s->vram_size / line_offset;
678                 /* XXX: support weird bochs semantics ? */
679                 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
680                     return;
681                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
682                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
683                 s->vbe_line_offset = line_offset;
684             }
685             break;
686         case VBE_DISPI_INDEX_X_OFFSET:
687         case VBE_DISPI_INDEX_Y_OFFSET:
688             {
689                 int x;
690                 s->vbe_regs[s->vbe_index] = val;
691                 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
692                 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
693                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
694                     s->vbe_start_addr += x >> 1;
695                 else
696                     s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
697                 s->vbe_start_addr >>= 2;
698             }
699             break;
700         default:
701             break;
702         }
703     }
704 }
705 #endif
706
707 /* called for accesses between 0xa0000 and 0xc0000 */
708 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
709 {
710     VGAState *s = opaque;
711     int memory_map_mode, plane;
712     uint32_t ret;
713
714     /* convert to VGA memory offset */
715     memory_map_mode = (s->gr[6] >> 2) & 3;
716     addr &= 0x1ffff;
717     switch(memory_map_mode) {
718     case 0:
719         break;
720     case 1:
721         if (addr >= 0x10000)
722             return 0xff;
723         addr += s->bank_offset;
724         break;
725     case 2:
726         addr -= 0x10000;
727         if (addr >= 0x8000)
728             return 0xff;
729         break;
730     default:
731     case 3:
732         addr -= 0x18000;
733         if (addr >= 0x8000)
734             return 0xff;
735         break;
736     }
737
738     if (s->sr[4] & 0x08) {
739         /* chain 4 mode : simplest access */
740         ret = s->vram_ptr[addr];
741     } else if (s->gr[5] & 0x10) {
742         /* odd/even mode (aka text mode mapping) */
743         plane = (s->gr[4] & 2) | (addr & 1);
744         ret = s->vram_ptr[((addr & ~1) << 1) | plane];
745     } else {
746         /* standard VGA latched access */
747         s->latch = ((uint32_t *)s->vram_ptr)[addr];
748
749         if (!(s->gr[5] & 0x08)) {
750             /* read mode 0 */
751             plane = s->gr[4];
752             ret = GET_PLANE(s->latch, plane);
753         } else {
754             /* read mode 1 */
755             ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
756             ret |= ret >> 16;
757             ret |= ret >> 8;
758             ret = (~ret) & 0xff;
759         }
760     }
761     return ret;
762 }
763
764 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
765 {
766     uint32_t v;
767 #ifdef TARGET_WORDS_BIGENDIAN
768     v = vga_mem_readb(opaque, addr) << 8;
769     v |= vga_mem_readb(opaque, addr + 1);
770 #else
771     v = vga_mem_readb(opaque, addr);
772     v |= vga_mem_readb(opaque, addr + 1) << 8;
773 #endif
774     return v;
775 }
776
777 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
778 {
779     uint32_t v;
780 #ifdef TARGET_WORDS_BIGENDIAN
781     v = vga_mem_readb(opaque, addr) << 24;
782     v |= vga_mem_readb(opaque, addr + 1) << 16;
783     v |= vga_mem_readb(opaque, addr + 2) << 8;
784     v |= vga_mem_readb(opaque, addr + 3);
785 #else
786     v = vga_mem_readb(opaque, addr);
787     v |= vga_mem_readb(opaque, addr + 1) << 8;
788     v |= vga_mem_readb(opaque, addr + 2) << 16;
789     v |= vga_mem_readb(opaque, addr + 3) << 24;
790 #endif
791     return v;
792 }
793
794 /* called for accesses between 0xa0000 and 0xc0000 */
795 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
796 {
797     VGAState *s = opaque;
798     int memory_map_mode, plane, write_mode, b, func_select, mask;
799     uint32_t write_mask, bit_mask, set_mask;
800
801 #ifdef DEBUG_VGA_MEM
802     printf("vga: [0x%x] = 0x%02x\n", addr, val);
803 #endif
804     /* convert to VGA memory offset */
805     memory_map_mode = (s->gr[6] >> 2) & 3;
806     addr &= 0x1ffff;
807     switch(memory_map_mode) {
808     case 0:
809         break;
810     case 1:
811         if (addr >= 0x10000)
812             return;
813         addr += s->bank_offset;
814         break;
815     case 2:
816         addr -= 0x10000;
817         if (addr >= 0x8000)
818             return;
819         break;
820     default:
821     case 3:
822         addr -= 0x18000;
823         if (addr >= 0x8000)
824             return;
825         break;
826     }
827
828     if (s->sr[4] & 0x08) {
829         /* chain 4 mode : simplest access */
830         plane = addr & 3;
831         mask = (1 << plane);
832         if (s->sr[2] & mask) {
833             s->vram_ptr[addr] = val;
834 #ifdef DEBUG_VGA_MEM
835             printf("vga: chain4: [0x%x]\n", addr);
836 #endif
837             s->plane_updated |= mask; /* only used to detect font change */
838             cpu_physical_memory_set_dirty(s->vram_offset + addr);
839         }
840     } else if (s->gr[5] & 0x10) {
841         /* odd/even mode (aka text mode mapping) */
842         plane = (s->gr[4] & 2) | (addr & 1);
843         mask = (1 << plane);
844         if (s->sr[2] & mask) {
845             addr = ((addr & ~1) << 1) | plane;
846             s->vram_ptr[addr] = val;
847 #ifdef DEBUG_VGA_MEM
848             printf("vga: odd/even: [0x%x]\n", addr);
849 #endif
850             s->plane_updated |= mask; /* only used to detect font change */
851             cpu_physical_memory_set_dirty(s->vram_offset + addr);
852         }
853     } else {
854         /* standard VGA latched access */
855         write_mode = s->gr[5] & 3;
856         switch(write_mode) {
857         default:
858         case 0:
859             /* rotate */
860             b = s->gr[3] & 7;
861             val = ((val >> b) | (val << (8 - b))) & 0xff;
862             val |= val << 8;
863             val |= val << 16;
864
865             /* apply set/reset mask */
866             set_mask = mask16[s->gr[1]];
867             val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
868             bit_mask = s->gr[8];
869             break;
870         case 1:
871             val = s->latch;
872             goto do_write;
873         case 2:
874             val = mask16[val & 0x0f];
875             bit_mask = s->gr[8];
876             break;
877         case 3:
878             /* rotate */
879             b = s->gr[3] & 7;
880             val = (val >> b) | (val << (8 - b));
881
882             bit_mask = s->gr[8] & val;
883             val = mask16[s->gr[0]];
884             break;
885         }
886
887         /* apply logical operation */
888         func_select = s->gr[3] >> 3;
889         switch(func_select) {
890         case 0:
891         default:
892             /* nothing to do */
893             break;
894         case 1:
895             /* and */
896             val &= s->latch;
897             break;
898         case 2:
899             /* or */
900             val |= s->latch;
901             break;
902         case 3:
903             /* xor */
904             val ^= s->latch;
905             break;
906         }
907
908         /* apply bit mask */
909         bit_mask |= bit_mask << 8;
910         bit_mask |= bit_mask << 16;
911         val = (val & bit_mask) | (s->latch & ~bit_mask);
912
913     do_write:
914         /* mask data according to sr[2] */
915         mask = s->sr[2];
916         s->plane_updated |= mask; /* only used to detect font change */
917         write_mask = mask16[mask];
918         ((uint32_t *)s->vram_ptr)[addr] =
919             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
920             (val & write_mask);
921 #ifdef DEBUG_VGA_MEM
922             printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
923                    addr * 4, write_mask, val);
924 #endif
925             cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
926     }
927 }
928
929 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
930 {
931 #ifdef TARGET_WORDS_BIGENDIAN
932     vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
933     vga_mem_writeb(opaque, addr + 1, val & 0xff);
934 #else
935     vga_mem_writeb(opaque, addr, val & 0xff);
936     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
937 #endif
938 }
939
940 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
941 {
942 #ifdef TARGET_WORDS_BIGENDIAN
943     vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
944     vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
945     vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
946     vga_mem_writeb(opaque, addr + 3, val & 0xff);
947 #else
948     vga_mem_writeb(opaque, addr, val & 0xff);
949     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
950     vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
951     vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
952 #endif
953 }
954
955 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
956                              const uint8_t *font_ptr, int h,
957                              uint32_t fgcol, uint32_t bgcol);
958 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
959                                   const uint8_t *font_ptr, int h,
960                                   uint32_t fgcol, uint32_t bgcol, int dup9);
961 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
962                                 const uint8_t *s, int width);
963
964 #define DEPTH 8
965 #include "vga_template.h"
966
967 #define DEPTH 15
968 #include "vga_template.h"
969
970 #define BGR_FORMAT
971 #define DEPTH 15
972 #include "vga_template.h"
973
974 #define DEPTH 16
975 #include "vga_template.h"
976
977 #define BGR_FORMAT
978 #define DEPTH 16
979 #include "vga_template.h"
980
981 #define DEPTH 32
982 #include "vga_template.h"
983
984 #define BGR_FORMAT
985 #define DEPTH 32
986 #include "vga_template.h"
987
988 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
989 {
990     unsigned int col;
991     col = rgb_to_pixel8(r, g, b);
992     col |= col << 8;
993     col |= col << 16;
994     return col;
995 }
996
997 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
998 {
999     unsigned int col;
1000     col = rgb_to_pixel15(r, g, b);
1001     col |= col << 16;
1002     return col;
1003 }
1004
1005 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1006                                           unsigned int b)
1007 {
1008     unsigned int col;
1009     col = rgb_to_pixel15bgr(r, g, b);
1010     col |= col << 16;
1011     return col;
1012 }
1013
1014 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1015 {
1016     unsigned int col;
1017     col = rgb_to_pixel16(r, g, b);
1018     col |= col << 16;
1019     return col;
1020 }
1021
1022 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1023                                           unsigned int b)
1024 {
1025     unsigned int col;
1026     col = rgb_to_pixel16bgr(r, g, b);
1027     col |= col << 16;
1028     return col;
1029 }
1030
1031 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1032 {
1033     unsigned int col;
1034     col = rgb_to_pixel32(r, g, b);
1035     return col;
1036 }
1037
1038 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1039 {
1040     unsigned int col;
1041     col = rgb_to_pixel32bgr(r, g, b);
1042     return col;
1043 }
1044
1045 /* return true if the palette was modified */
1046 static int update_palette16(VGAState *s)
1047 {
1048     int full_update, i;
1049     uint32_t v, col, *palette;
1050
1051     full_update = 0;
1052     palette = s->last_palette;
1053     for(i = 0; i < 16; i++) {
1054         v = s->ar[i];
1055         if (s->ar[0x10] & 0x80)
1056             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1057         else
1058             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1059         v = v * 3;
1060         col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1061                               c6_to_8(s->palette[v + 1]),
1062                               c6_to_8(s->palette[v + 2]));
1063         if (col != palette[i]) {
1064             full_update = 1;
1065             palette[i] = col;
1066         }
1067     }
1068     return full_update;
1069 }
1070
1071 /* return true if the palette was modified */
1072 static int update_palette256(VGAState *s)
1073 {
1074     int full_update, i;
1075     uint32_t v, col, *palette;
1076
1077     full_update = 0;
1078     palette = s->last_palette;
1079     v = 0;
1080     for(i = 0; i < 256; i++) {
1081         if (s->dac_8bit) {
1082           col = s->rgb_to_pixel(s->palette[v],
1083                                 s->palette[v + 1],
1084                                 s->palette[v + 2]);
1085         } else {
1086           col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1087                                 c6_to_8(s->palette[v + 1]),
1088                                 c6_to_8(s->palette[v + 2]));
1089         }
1090         if (col != palette[i]) {
1091             full_update = 1;
1092             palette[i] = col;
1093         }
1094         v += 3;
1095     }
1096     return full_update;
1097 }
1098
1099 static void vga_get_offsets(VGAState *s,
1100                             uint32_t *pline_offset,
1101                             uint32_t *pstart_addr,
1102                             uint32_t *pline_compare)
1103 {
1104     uint32_t start_addr, line_offset, line_compare;
1105 #ifdef CONFIG_BOCHS_VBE
1106     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1107         line_offset = s->vbe_line_offset;
1108         start_addr = s->vbe_start_addr;
1109         line_compare = 65535;
1110     } else
1111 #endif
1112     {
1113         /* compute line_offset in bytes */
1114         line_offset = s->cr[0x13];
1115         line_offset <<= 3;
1116
1117         /* starting address */
1118         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1119
1120         /* line compare */
1121         line_compare = s->cr[0x18] |
1122             ((s->cr[0x07] & 0x10) << 4) |
1123             ((s->cr[0x09] & 0x40) << 3);
1124     }
1125     *pline_offset = line_offset;
1126     *pstart_addr = start_addr;
1127     *pline_compare = line_compare;
1128 }
1129
1130 /* update start_addr and line_offset. Return TRUE if modified */
1131 static int update_basic_params(VGAState *s)
1132 {
1133     int full_update;
1134     uint32_t start_addr, line_offset, line_compare;
1135
1136     full_update = 0;
1137
1138     s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1139
1140     if (line_offset != s->line_offset ||
1141         start_addr != s->start_addr ||
1142         line_compare != s->line_compare) {
1143         s->line_offset = line_offset;
1144         s->start_addr = start_addr;
1145         s->line_compare = line_compare;
1146         full_update = 1;
1147     }
1148     return full_update;
1149 }
1150
1151 #define NB_DEPTHS 7
1152
1153 static inline int get_depth_index(DisplayState *s)
1154 {
1155     switch(ds_get_bits_per_pixel(s)) {
1156     default:
1157     case 8:
1158         return 0;
1159     case 15:
1160         if (s->bgr)
1161             return 5;
1162         else
1163             return 1;
1164     case 16:
1165         if (s->bgr)
1166             return 6;
1167         else
1168             return 2;
1169     case 32:
1170         if (s->bgr)
1171             return 4;
1172         else
1173             return 3;
1174     }
1175 }
1176
1177 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1178     vga_draw_glyph8_8,
1179     vga_draw_glyph8_16,
1180     vga_draw_glyph8_16,
1181     vga_draw_glyph8_32,
1182     vga_draw_glyph8_32,
1183     vga_draw_glyph8_16,
1184     vga_draw_glyph8_16,
1185 };
1186
1187 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1188     vga_draw_glyph16_8,
1189     vga_draw_glyph16_16,
1190     vga_draw_glyph16_16,
1191     vga_draw_glyph16_32,
1192     vga_draw_glyph16_32,
1193     vga_draw_glyph16_16,
1194     vga_draw_glyph16_16,
1195 };
1196
1197 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1198     vga_draw_glyph9_8,
1199     vga_draw_glyph9_16,
1200     vga_draw_glyph9_16,
1201     vga_draw_glyph9_32,
1202     vga_draw_glyph9_32,
1203     vga_draw_glyph9_16,
1204     vga_draw_glyph9_16,
1205 };
1206
1207 static const uint8_t cursor_glyph[32 * 4] = {
1208     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1222     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1223     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1224 };
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
1255 /*
1256  * Text mode update
1257  * Missing:
1258  * - double scan
1259  * - double width
1260  * - underline
1261  * - flashing
1262  */
1263 static void vga_draw_text(VGAState *s, int full_update)
1264 {
1265     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1266     int cx_min, cx_max, linesize, x_incr;
1267     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1268     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1269     const uint8_t *font_ptr, *font_base[2];
1270     int dup9, line_offset, depth_index;
1271     uint32_t *palette;
1272     uint32_t *ch_attr_ptr;
1273     vga_draw_glyph8_func *vga_draw_glyph8;
1274     vga_draw_glyph9_func *vga_draw_glyph9;
1275
1276     vga_dirty_log_stop(s);
1277
1278     full_update |= update_palette16(s);
1279     palette = s->last_palette;
1280
1281     /* compute font data address (in plane 2) */
1282     v = s->sr[3];
1283     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1284     if (offset != s->font_offsets[0]) {
1285         s->font_offsets[0] = offset;
1286         full_update = 1;
1287     }
1288     font_base[0] = s->vram_ptr + offset;
1289
1290     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1291     font_base[1] = s->vram_ptr + offset;
1292     if (offset != s->font_offsets[1]) {
1293         s->font_offsets[1] = offset;
1294         full_update = 1;
1295     }
1296     if (s->plane_updated & (1 << 2)) {
1297         /* if the plane 2 was modified since the last display, it
1298            indicates the font may have been modified */
1299         s->plane_updated = 0;
1300         full_update = 1;
1301     }
1302     full_update |= update_basic_params(s);
1303
1304     line_offset = s->line_offset;
1305     s1 = s->vram_ptr + (s->start_addr * 4);
1306
1307     vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1308     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1309     if ((height * width) > CH_ATTR_SIZE) {
1310         /* better than nothing: exit if transient size is too big */
1311         return;
1312     }
1313
1314     if (width != s->last_width || height != s->last_height ||
1315         cw != s->last_cw || cheight != s->last_ch) {
1316         s->last_scr_width = width * cw;
1317         s->last_scr_height = height * cheight;
1318         qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height);
1319         s->last_width = width;
1320         s->last_height = height;
1321         s->last_ch = cheight;
1322         s->last_cw = cw;
1323         full_update = 1;
1324     }
1325     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1326     if (cursor_offset != s->cursor_offset ||
1327         s->cr[0xa] != s->cursor_start ||
1328         s->cr[0xb] != s->cursor_end) {
1329       /* if the cursor position changed, we update the old and new
1330          chars */
1331         if (s->cursor_offset < CH_ATTR_SIZE)
1332             s->last_ch_attr[s->cursor_offset] = -1;
1333         if (cursor_offset < CH_ATTR_SIZE)
1334             s->last_ch_attr[cursor_offset] = -1;
1335         s->cursor_offset = cursor_offset;
1336         s->cursor_start = s->cr[0xa];
1337         s->cursor_end = s->cr[0xb];
1338     }
1339     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1340
1341     depth_index = get_depth_index(s->ds);
1342     if (cw == 16)
1343         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1344     else
1345         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1346     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1347
1348     dest = ds_get_data(s->ds);
1349     linesize = ds_get_linesize(s->ds);
1350     ch_attr_ptr = s->last_ch_attr;
1351     for(cy = 0; cy < height; cy++) {
1352         d1 = dest;
1353         src = s1;
1354         cx_min = width;
1355         cx_max = -1;
1356         for(cx = 0; cx < width; cx++) {
1357             ch_attr = *(uint16_t *)src;
1358             if (full_update || ch_attr != *ch_attr_ptr) {
1359                 if (cx < cx_min)
1360                     cx_min = cx;
1361                 if (cx > cx_max)
1362                     cx_max = cx;
1363                 *ch_attr_ptr = ch_attr;
1364 #ifdef WORDS_BIGENDIAN
1365                 ch = ch_attr >> 8;
1366                 cattr = ch_attr & 0xff;
1367 #else
1368                 ch = ch_attr & 0xff;
1369                 cattr = ch_attr >> 8;
1370 #endif
1371                 font_ptr = font_base[(cattr >> 3) & 1];
1372                 font_ptr += 32 * 4 * ch;
1373                 bgcol = palette[cattr >> 4];
1374                 fgcol = palette[cattr & 0x0f];
1375                 if (cw != 9) {
1376                     vga_draw_glyph8(d1, linesize,
1377                                     font_ptr, cheight, fgcol, bgcol);
1378                 } else {
1379                     dup9 = 0;
1380                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1381                         dup9 = 1;
1382                     vga_draw_glyph9(d1, linesize,
1383                                     font_ptr, cheight, fgcol, bgcol, dup9);
1384                 }
1385                 if (src == cursor_ptr &&
1386                     !(s->cr[0x0a] & 0x20)) {
1387                     int line_start, line_last, h;
1388                     /* draw the cursor */
1389                     line_start = s->cr[0x0a] & 0x1f;
1390                     line_last = s->cr[0x0b] & 0x1f;
1391                     /* XXX: check that */
1392                     if (line_last > cheight - 1)
1393                         line_last = cheight - 1;
1394                     if (line_last >= line_start && line_start < cheight) {
1395                         h = line_last - line_start + 1;
1396                         d = d1 + linesize * line_start;
1397                         if (cw != 9) {
1398                             vga_draw_glyph8(d, linesize,
1399                                             cursor_glyph, h, fgcol, bgcol);
1400                         } else {
1401                             vga_draw_glyph9(d, linesize,
1402                                             cursor_glyph, h, fgcol, bgcol, 1);
1403                         }
1404                     }
1405                 }
1406             }
1407             d1 += x_incr;
1408             src += 4;
1409             ch_attr_ptr++;
1410         }
1411         if (cx_max != -1) {
1412             dpy_update(s->ds, cx_min * cw, cy * cheight,
1413                        (cx_max - cx_min + 1) * cw, cheight);
1414         }
1415         dest += linesize * cheight;
1416         s1 += line_offset;
1417     }
1418 }
1419
1420 enum {
1421     VGA_DRAW_LINE2,
1422     VGA_DRAW_LINE2D2,
1423     VGA_DRAW_LINE4,
1424     VGA_DRAW_LINE4D2,
1425     VGA_DRAW_LINE8D2,
1426     VGA_DRAW_LINE8,
1427     VGA_DRAW_LINE15,
1428     VGA_DRAW_LINE16,
1429     VGA_DRAW_LINE24,
1430     VGA_DRAW_LINE32,
1431     VGA_DRAW_LINE_NB,
1432 };
1433
1434 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1435     vga_draw_line2_8,
1436     vga_draw_line2_16,
1437     vga_draw_line2_16,
1438     vga_draw_line2_32,
1439     vga_draw_line2_32,
1440     vga_draw_line2_16,
1441     vga_draw_line2_16,
1442
1443     vga_draw_line2d2_8,
1444     vga_draw_line2d2_16,
1445     vga_draw_line2d2_16,
1446     vga_draw_line2d2_32,
1447     vga_draw_line2d2_32,
1448     vga_draw_line2d2_16,
1449     vga_draw_line2d2_16,
1450
1451     vga_draw_line4_8,
1452     vga_draw_line4_16,
1453     vga_draw_line4_16,
1454     vga_draw_line4_32,
1455     vga_draw_line4_32,
1456     vga_draw_line4_16,
1457     vga_draw_line4_16,
1458
1459     vga_draw_line4d2_8,
1460     vga_draw_line4d2_16,
1461     vga_draw_line4d2_16,
1462     vga_draw_line4d2_32,
1463     vga_draw_line4d2_32,
1464     vga_draw_line4d2_16,
1465     vga_draw_line4d2_16,
1466
1467     vga_draw_line8d2_8,
1468     vga_draw_line8d2_16,
1469     vga_draw_line8d2_16,
1470     vga_draw_line8d2_32,
1471     vga_draw_line8d2_32,
1472     vga_draw_line8d2_16,
1473     vga_draw_line8d2_16,
1474
1475     vga_draw_line8_8,
1476     vga_draw_line8_16,
1477     vga_draw_line8_16,
1478     vga_draw_line8_32,
1479     vga_draw_line8_32,
1480     vga_draw_line8_16,
1481     vga_draw_line8_16,
1482
1483     vga_draw_line15_8,
1484     vga_draw_line15_15,
1485     vga_draw_line15_16,
1486     vga_draw_line15_32,
1487     vga_draw_line15_32bgr,
1488     vga_draw_line15_15bgr,
1489     vga_draw_line15_16bgr,
1490
1491     vga_draw_line16_8,
1492     vga_draw_line16_15,
1493     vga_draw_line16_16,
1494     vga_draw_line16_32,
1495     vga_draw_line16_32bgr,
1496     vga_draw_line16_15bgr,
1497     vga_draw_line16_16bgr,
1498
1499     vga_draw_line24_8,
1500     vga_draw_line24_15,
1501     vga_draw_line24_16,
1502     vga_draw_line24_32,
1503     vga_draw_line24_32bgr,
1504     vga_draw_line24_15bgr,
1505     vga_draw_line24_16bgr,
1506
1507     vga_draw_line32_8,
1508     vga_draw_line32_15,
1509     vga_draw_line32_16,
1510     vga_draw_line32_32,
1511     vga_draw_line32_32bgr,
1512     vga_draw_line32_15bgr,
1513     vga_draw_line32_16bgr,
1514 };
1515
1516 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1517
1518 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1519     rgb_to_pixel8_dup,
1520     rgb_to_pixel15_dup,
1521     rgb_to_pixel16_dup,
1522     rgb_to_pixel32_dup,
1523     rgb_to_pixel32bgr_dup,
1524     rgb_to_pixel15bgr_dup,
1525     rgb_to_pixel16bgr_dup,
1526 };
1527
1528 static int vga_get_bpp(VGAState *s)
1529 {
1530     int ret;
1531 #ifdef CONFIG_BOCHS_VBE
1532     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1533         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1534     } else
1535 #endif
1536     {
1537         ret = 0;
1538     }
1539     return ret;
1540 }
1541
1542 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1543 {
1544     int width, height;
1545
1546 #ifdef CONFIG_BOCHS_VBE
1547     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1548         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1549         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1550     } else
1551 #endif
1552     {
1553         width = (s->cr[0x01] + 1) * 8;
1554         height = s->cr[0x12] |
1555             ((s->cr[0x07] & 0x02) << 7) |
1556             ((s->cr[0x07] & 0x40) << 3);
1557         height = (height + 1);
1558     }
1559     *pwidth = width;
1560     *pheight = height;
1561 }
1562
1563 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1564 {
1565     int y;
1566     if (y1 >= VGA_MAX_HEIGHT)
1567         return;
1568     if (y2 >= VGA_MAX_HEIGHT)
1569         y2 = VGA_MAX_HEIGHT;
1570     for(y = y1; y < y2; y++) {
1571         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1572     }
1573 }
1574
1575 static void vga_sync_dirty_bitmap(VGAState *s)
1576 {
1577     if (s->map_addr)
1578         cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1579
1580     if (s->lfb_vram_mapped) {
1581         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1582         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1583     }
1584     vga_dirty_log_start(s);
1585 }
1586
1587 /*
1588  * graphic modes
1589  */
1590 static void vga_draw_graphic(VGAState *s, int full_update)
1591 {
1592     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1593     int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
1594     int disp_width, multi_scan, multi_run;
1595     uint8_t *d;
1596     uint32_t v, addr1, addr;
1597     vga_draw_line_func *vga_draw_line;
1598
1599     full_update |= update_basic_params(s);
1600
1601     if (!full_update)
1602         vga_sync_dirty_bitmap(s);
1603
1604     s->get_resolution(s, &width, &height);
1605     disp_width = width;
1606
1607     shift_control = (s->gr[0x05] >> 5) & 3;
1608     double_scan = (s->cr[0x09] >> 7);
1609     if (shift_control != 1) {
1610         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1611     } else {
1612         /* in CGA modes, multi_scan is ignored */
1613         /* XXX: is it correct ? */
1614         multi_scan = double_scan;
1615     }
1616     multi_run = multi_scan;
1617     if (shift_control != s->shift_control ||
1618         double_scan != s->double_scan) {
1619         full_update = 1;
1620         s->shift_control = shift_control;
1621         s->double_scan = double_scan;
1622     }
1623
1624     if (shift_control == 0) {
1625         full_update |= update_palette16(s);
1626         if (s->sr[0x01] & 8) {
1627             v = VGA_DRAW_LINE4D2;
1628             disp_width <<= 1;
1629         } else {
1630             v = VGA_DRAW_LINE4;
1631         }
1632         bits = 4;
1633     } else if (shift_control == 1) {
1634         full_update |= update_palette16(s);
1635         if (s->sr[0x01] & 8) {
1636             v = VGA_DRAW_LINE2D2;
1637             disp_width <<= 1;
1638         } else {
1639             v = VGA_DRAW_LINE2;
1640         }
1641         bits = 4;
1642     } else {
1643         switch(s->get_bpp(s)) {
1644         default:
1645         case 0:
1646             full_update |= update_palette256(s);
1647             v = VGA_DRAW_LINE8D2;
1648             bits = 4;
1649             break;
1650         case 8:
1651             full_update |= update_palette256(s);
1652             v = VGA_DRAW_LINE8;
1653             bits = 8;
1654             break;
1655         case 15:
1656             v = VGA_DRAW_LINE15;
1657             bits = 16;
1658             break;
1659         case 16:
1660             v = VGA_DRAW_LINE16;
1661             bits = 16;
1662             break;
1663         case 24:
1664             v = VGA_DRAW_LINE24;
1665             bits = 24;
1666             break;
1667         case 32:
1668             v = VGA_DRAW_LINE32;
1669             bits = 32;
1670             break;
1671         }
1672     }
1673     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1674
1675     if (disp_width != s->last_width ||
1676         height != s->last_height) {
1677         qemu_console_resize(s->console, disp_width, height);
1678         s->last_scr_width = disp_width;
1679         s->last_scr_height = height;
1680         s->last_width = disp_width;
1681         s->last_height = height;
1682         full_update = 1;
1683     }
1684     if (s->cursor_invalidate)
1685         s->cursor_invalidate(s);
1686
1687     line_offset = s->line_offset;
1688 #if 0
1689     printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
1690            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1691 #endif
1692     addr1 = (s->start_addr * 4);
1693     bwidth = (width * bits + 7) / 8;
1694     y_start = -1;
1695     page_min = 0x7fffffff;
1696     page_max = -1;
1697     d = ds_get_data(s->ds);
1698     linesize = ds_get_linesize(s->ds);
1699     y1 = 0;
1700     for(y = 0; y < height; y++) {
1701         addr = addr1;
1702         if (!(s->cr[0x17] & 1)) {
1703             int shift;
1704             /* CGA compatibility handling */
1705             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1706             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1707         }
1708         if (!(s->cr[0x17] & 2)) {
1709             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1710         }
1711         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1712         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1713         update = full_update |
1714             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1715             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1716         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1717             /* if wide line, can use another page */
1718             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1719                                                     VGA_DIRTY_FLAG);
1720         }
1721         /* explicit invalidation for the hardware cursor */
1722         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1723         if (update) {
1724             if (y_start < 0)
1725                 y_start = y;
1726             if (page0 < page_min)
1727                 page_min = page0;
1728             if (page1 > page_max)
1729                 page_max = page1;
1730             vga_draw_line(s, d, s->vram_ptr + addr, width);
1731             if (s->cursor_draw_line)
1732                 s->cursor_draw_line(s, d, y);
1733         } else {
1734             if (y_start >= 0) {
1735                 /* flush to display */
1736                 dpy_update(s->ds, 0, y_start,
1737                            disp_width, y - y_start);
1738                 y_start = -1;
1739             }
1740         }
1741         if (!multi_run) {
1742             mask = (s->cr[0x17] & 3) ^ 3;
1743             if ((y1 & mask) == mask)
1744                 addr1 += line_offset;
1745             y1++;
1746             multi_run = multi_scan;
1747         } else {
1748             multi_run--;
1749         }
1750         /* line compare acts on the displayed lines */
1751         if (y == s->line_compare)
1752             addr1 = 0;
1753         d += linesize;
1754     }
1755     if (y_start >= 0) {
1756         /* flush to display */
1757         dpy_update(s->ds, 0, y_start,
1758                    disp_width, y - y_start);
1759     }
1760     /* reset modified pages */
1761     if (page_max != -1) {
1762         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1763                                         VGA_DIRTY_FLAG);
1764     }
1765     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1766 }
1767
1768 static void vga_draw_blank(VGAState *s, int full_update)
1769 {
1770     int i, w, val;
1771     uint8_t *d;
1772
1773     if (!full_update)
1774         return;
1775     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1776         return;
1777     vga_dirty_log_stop(s);
1778
1779     if (ds_get_bits_per_pixel(s->ds) == 8)
1780         val = s->rgb_to_pixel(0, 0, 0);
1781     else
1782         val = 0;
1783     w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1784     d = ds_get_data(s->ds);
1785     for(i = 0; i < s->last_scr_height; i++) {
1786         memset(d, val, w);
1787         d += ds_get_linesize(s->ds);
1788     }
1789     dpy_update(s->ds, 0, 0,
1790                s->last_scr_width, s->last_scr_height);
1791 }
1792
1793 #define GMODE_TEXT     0
1794 #define GMODE_GRAPH    1
1795 #define GMODE_BLANK 2
1796
1797 static void vga_update_display(void *opaque)
1798 {
1799     VGAState *s = (VGAState *)opaque;
1800     int full_update, graphic_mode;
1801
1802     if (ds_get_bits_per_pixel(s->ds) == 0) {
1803         /* nothing to do */
1804     } else {
1805         s->rgb_to_pixel =
1806             rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1807
1808         full_update = 0;
1809         if (!(s->ar_index & 0x20)) {
1810             graphic_mode = GMODE_BLANK;
1811         } else {
1812             graphic_mode = s->gr[6] & 1;
1813         }
1814         if (graphic_mode != s->graphic_mode) {
1815             s->graphic_mode = graphic_mode;
1816             full_update = 1;
1817         }
1818         switch(graphic_mode) {
1819         case GMODE_TEXT:
1820             vga_draw_text(s, full_update);
1821             break;
1822         case GMODE_GRAPH:
1823             vga_draw_graphic(s, full_update);
1824             break;
1825         case GMODE_BLANK:
1826         default:
1827             vga_draw_blank(s, full_update);
1828             break;
1829         }
1830     }
1831 }
1832
1833 /* force a full display refresh */
1834 static void vga_invalidate_display(void *opaque)
1835 {
1836     VGAState *s = (VGAState *)opaque;
1837
1838     s->last_width = -1;
1839     s->last_height = -1;
1840 }
1841
1842 static void vga_reset(void *opaque)
1843 {
1844     VGAState *s = (VGAState *) opaque;
1845
1846     s->lfb_addr = 0;
1847     s->lfb_end = 0;
1848     s->map_addr = 0;
1849     s->map_end = 0;
1850     s->lfb_vram_mapped = 0;
1851     s->bios_offset = 0;
1852     s->bios_size = 0;
1853     s->sr_index = 0;
1854     memset(s->sr, '\0', sizeof(s->sr));
1855     s->gr_index = 0;
1856     memset(s->gr, '\0', sizeof(s->gr));
1857     s->ar_index = 0;
1858     memset(s->ar, '\0', sizeof(s->ar));
1859     s->ar_flip_flop = 0;
1860     s->cr_index = 0;
1861     memset(s->cr, '\0', sizeof(s->cr));
1862     s->msr = 0;
1863     s->fcr = 0;
1864     s->st00 = 0;
1865     s->st01 = 0;
1866     s->dac_state = 0;
1867     s->dac_sub_index = 0;
1868     s->dac_read_index = 0;
1869     s->dac_write_index = 0;
1870     memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1871     s->dac_8bit = 0;
1872     memset(s->palette, '\0', sizeof(s->palette));
1873     s->bank_offset = 0;
1874 #ifdef CONFIG_BOCHS_VBE
1875     s->vbe_index = 0;
1876     memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1877     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1878     s->vbe_start_addr = 0;
1879     s->vbe_line_offset = 0;
1880     s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1881 #endif
1882     memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1883     s->graphic_mode = -1; /* force full update */
1884     s->shift_control = 0;
1885     s->double_scan = 0;
1886     s->line_offset = 0;
1887     s->line_compare = 0;
1888     s->start_addr = 0;
1889     s->plane_updated = 0;
1890     s->last_cw = 0;
1891     s->last_ch = 0;
1892     s->last_width = 0;
1893     s->last_height = 0;
1894     s->last_scr_width = 0;
1895     s->last_scr_height = 0;
1896     s->cursor_start = 0;
1897     s->cursor_end = 0;
1898     s->cursor_offset = 0;
1899     memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1900     memset(s->last_palette, '\0', sizeof(s->last_palette));
1901     memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1902     switch (vga_retrace_method) {
1903     case VGA_RETRACE_DUMB:
1904         break;
1905     case VGA_RETRACE_PRECISE:
1906         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1907         break;
1908     }
1909 }
1910
1911 #define TEXTMODE_X(x)   ((x) % width)
1912 #define TEXTMODE_Y(x)   ((x) / width)
1913 #define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
1914         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1915 /* relay text rendering to the display driver
1916  * instead of doing a full vga_update_display() */
1917 static void vga_update_text(void *opaque, console_ch_t *chardata)
1918 {
1919     VGAState *s = (VGAState *) opaque;
1920     int graphic_mode, i, cursor_offset, cursor_visible;
1921     int cw, cheight, width, height, size, c_min, c_max;
1922     uint32_t *src;
1923     console_ch_t *dst, val;
1924     char msg_buffer[80];
1925     int full_update = 0;
1926
1927     if (!(s->ar_index & 0x20)) {
1928         graphic_mode = GMODE_BLANK;
1929     } else {
1930         graphic_mode = s->gr[6] & 1;
1931     }
1932     if (graphic_mode != s->graphic_mode) {
1933         s->graphic_mode = graphic_mode;
1934         full_update = 1;
1935     }
1936     if (s->last_width == -1) {
1937         s->last_width = 0;
1938         full_update = 1;
1939     }
1940
1941     switch (graphic_mode) {
1942     case GMODE_TEXT:
1943         /* TODO: update palette */
1944         full_update |= update_basic_params(s);
1945
1946         /* total width & height */
1947         cheight = (s->cr[9] & 0x1f) + 1;
1948         cw = 8;
1949         if (!(s->sr[1] & 0x01))
1950             cw = 9;
1951         if (s->sr[1] & 0x08)
1952             cw = 16; /* NOTE: no 18 pixel wide */
1953         width = (s->cr[0x01] + 1);
1954         if (s->cr[0x06] == 100) {
1955             /* ugly hack for CGA 160x100x16 - explain me the logic */
1956             height = 100;
1957         } else {
1958             height = s->cr[0x12] | 
1959                 ((s->cr[0x07] & 0x02) << 7) | 
1960                 ((s->cr[0x07] & 0x40) << 3);
1961             height = (height + 1) / cheight;
1962         }
1963
1964         size = (height * width);
1965         if (size > CH_ATTR_SIZE) {
1966             if (!full_update)
1967                 return;
1968
1969             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1970                      width, height);
1971             break;
1972         }
1973
1974         if (width != s->last_width || height != s->last_height ||
1975             cw != s->last_cw || cheight != s->last_ch) {
1976             s->last_scr_width = width * cw;
1977             s->last_scr_height = height * cheight;
1978             qemu_console_resize(s->console, width, height);
1979             s->last_width = width;
1980             s->last_height = height;
1981             s->last_ch = cheight;
1982             s->last_cw = cw;
1983             full_update = 1;
1984         }
1985
1986         /* Update "hardware" cursor */
1987         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1988         if (cursor_offset != s->cursor_offset ||
1989             s->cr[0xa] != s->cursor_start ||
1990             s->cr[0xb] != s->cursor_end || full_update) {
1991             cursor_visible = !(s->cr[0xa] & 0x20);
1992             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1993                 dpy_cursor(s->ds,
1994                            TEXTMODE_X(cursor_offset),
1995                            TEXTMODE_Y(cursor_offset));
1996             else
1997                 dpy_cursor(s->ds, -1, -1);
1998             s->cursor_offset = cursor_offset;
1999             s->cursor_start = s->cr[0xa];
2000             s->cursor_end = s->cr[0xb];
2001         }
2002
2003         src = (uint32_t *) s->vram_ptr + s->start_addr;
2004         dst = chardata;
2005
2006         if (full_update) {
2007             for (i = 0; i < size; src ++, dst ++, i ++)
2008                 console_write_ch(dst, VMEM2CHTYPE(*src));
2009
2010             dpy_update(s->ds, 0, 0, width, height);
2011         } else {
2012             c_max = 0;
2013
2014             for (i = 0; i < size; src ++, dst ++, i ++) {
2015                 console_write_ch(&val, VMEM2CHTYPE(*src));
2016                 if (*dst != val) {
2017                     *dst = val;
2018                     c_max = i;
2019                     break;
2020                 }
2021             }
2022             c_min = i;
2023             for (; i < size; src ++, dst ++, i ++) {
2024                 console_write_ch(&val, VMEM2CHTYPE(*src));
2025                 if (*dst != val) {
2026                     *dst = val;
2027                     c_max = i;
2028                 }
2029             }
2030
2031             if (c_min <= c_max) {
2032                 i = TEXTMODE_Y(c_min);
2033                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2034             }
2035         }
2036
2037         return;
2038     case GMODE_GRAPH:
2039         if (!full_update)
2040             return;
2041
2042         s->get_resolution(s, &width, &height);
2043         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2044                  width, height);
2045         break;
2046     case GMODE_BLANK:
2047     default:
2048         if (!full_update)
2049             return;
2050
2051         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2052         break;
2053     }
2054
2055     /* Display a message */
2056     s->last_width = 60;
2057     s->last_height = height = 3;
2058     dpy_cursor(s->ds, -1, -1);
2059     qemu_console_resize(s->console, s->last_width, height);
2060
2061     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2062         console_write_ch(dst ++, ' ');
2063
2064     size = strlen(msg_buffer);
2065     width = (s->last_width - size) / 2;
2066     dst = chardata + s->last_width + width;
2067     for (i = 0; i < size; i ++)
2068         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2069
2070     dpy_update(s->ds, 0, 0, s->last_width, height);
2071 }
2072
2073 static CPUReadMemoryFunc *vga_mem_read[3] = {
2074     vga_mem_readb,
2075     vga_mem_readw,
2076     vga_mem_readl,
2077 };
2078
2079 static CPUWriteMemoryFunc *vga_mem_write[3] = {
2080     vga_mem_writeb,
2081     vga_mem_writew,
2082     vga_mem_writel,
2083 };
2084
2085 static void vga_save(QEMUFile *f, void *opaque)
2086 {
2087     VGAState *s = opaque;
2088     int i;
2089
2090     if (s->pci_dev)
2091         pci_device_save(s->pci_dev, f);
2092
2093     qemu_put_be32s(f, &s->latch);
2094     qemu_put_8s(f, &s->sr_index);
2095     qemu_put_buffer(f, s->sr, 8);
2096     qemu_put_8s(f, &s->gr_index);
2097     qemu_put_buffer(f, s->gr, 16);
2098     qemu_put_8s(f, &s->ar_index);
2099     qemu_put_buffer(f, s->ar, 21);
2100     qemu_put_be32(f, s->ar_flip_flop);
2101     qemu_put_8s(f, &s->cr_index);
2102     qemu_put_buffer(f, s->cr, 256);
2103     qemu_put_8s(f, &s->msr);
2104     qemu_put_8s(f, &s->fcr);
2105     qemu_put_byte(f, s->st00);
2106     qemu_put_8s(f, &s->st01);
2107
2108     qemu_put_8s(f, &s->dac_state);
2109     qemu_put_8s(f, &s->dac_sub_index);
2110     qemu_put_8s(f, &s->dac_read_index);
2111     qemu_put_8s(f, &s->dac_write_index);
2112     qemu_put_buffer(f, s->dac_cache, 3);
2113     qemu_put_buffer(f, s->palette, 768);
2114
2115     qemu_put_be32(f, s->bank_offset);
2116 #ifdef CONFIG_BOCHS_VBE
2117     qemu_put_byte(f, 1);
2118     qemu_put_be16s(f, &s->vbe_index);
2119     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2120         qemu_put_be16s(f, &s->vbe_regs[i]);
2121     qemu_put_be32s(f, &s->vbe_start_addr);
2122     qemu_put_be32s(f, &s->vbe_line_offset);
2123     qemu_put_be32s(f, &s->vbe_bank_mask);
2124 #else
2125     qemu_put_byte(f, 0);
2126 #endif
2127 }
2128
2129 static int vga_load(QEMUFile *f, void *opaque, int version_id)
2130 {
2131     VGAState *s = opaque;
2132     int is_vbe, i, ret;
2133
2134     if (version_id > 2)
2135         return -EINVAL;
2136
2137     if (s->pci_dev && version_id >= 2) {
2138         ret = pci_device_load(s->pci_dev, f);
2139         if (ret < 0)
2140             return ret;
2141     }
2142
2143     qemu_get_be32s(f, &s->latch);
2144     qemu_get_8s(f, &s->sr_index);
2145     qemu_get_buffer(f, s->sr, 8);
2146     qemu_get_8s(f, &s->gr_index);
2147     qemu_get_buffer(f, s->gr, 16);
2148     qemu_get_8s(f, &s->ar_index);
2149     qemu_get_buffer(f, s->ar, 21);
2150     s->ar_flip_flop=qemu_get_be32(f);
2151     qemu_get_8s(f, &s->cr_index);
2152     qemu_get_buffer(f, s->cr, 256);
2153     qemu_get_8s(f, &s->msr);
2154     qemu_get_8s(f, &s->fcr);
2155     qemu_get_8s(f, &s->st00);
2156     qemu_get_8s(f, &s->st01);
2157
2158     qemu_get_8s(f, &s->dac_state);
2159     qemu_get_8s(f, &s->dac_sub_index);
2160     qemu_get_8s(f, &s->dac_read_index);
2161     qemu_get_8s(f, &s->dac_write_index);
2162     qemu_get_buffer(f, s->dac_cache, 3);
2163     qemu_get_buffer(f, s->palette, 768);
2164
2165     s->bank_offset=qemu_get_be32(f);
2166     is_vbe = qemu_get_byte(f);
2167 #ifdef CONFIG_BOCHS_VBE
2168     if (!is_vbe)
2169         return -EINVAL;
2170     qemu_get_be16s(f, &s->vbe_index);
2171     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2172         qemu_get_be16s(f, &s->vbe_regs[i]);
2173     qemu_get_be32s(f, &s->vbe_start_addr);
2174     qemu_get_be32s(f, &s->vbe_line_offset);
2175     qemu_get_be32s(f, &s->vbe_bank_mask);
2176 #else
2177     if (is_vbe)
2178         return -EINVAL;
2179 #endif
2180
2181     /* force refresh */
2182     s->graphic_mode = -1;
2183     return 0;
2184 }
2185
2186 typedef struct PCIVGAState {
2187     PCIDevice dev;
2188     VGAState vga_state;
2189 } PCIVGAState;
2190
2191 void vga_dirty_log_start(VGAState *s)
2192 {
2193     if (kvm_enabled() && s->map_addr)
2194         kvm_log_start(s->map_addr, s->map_end - s->map_addr);
2195
2196     if (kvm_enabled() && s->lfb_vram_mapped) {
2197         kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
2198         kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
2199     }
2200 }
2201
2202 void vga_dirty_log_stop(VGAState *s)
2203 {
2204     if (kvm_enabled() && s->map_addr)
2205         kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
2206
2207     if (kvm_enabled() && s->lfb_vram_mapped) {
2208         kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
2209         kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
2210     }
2211 }
2212
2213 static void vga_map(PCIDevice *pci_dev, int region_num,
2214                     uint32_t addr, uint32_t size, int type)
2215 {
2216     PCIVGAState *d = (PCIVGAState *)pci_dev;
2217     VGAState *s = &d->vga_state;
2218     if (region_num == PCI_ROM_SLOT) {
2219         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2220     } else {
2221         cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2222     }
2223
2224     s->map_addr = addr;
2225     s->map_end = addr + VGA_RAM_SIZE;
2226
2227     vga_dirty_log_start(s);
2228 }
2229
2230 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
2231                      ram_addr_t vga_ram_offset, int vga_ram_size)
2232 {
2233     int i, j, v, b;
2234
2235     for(i = 0;i < 256; i++) {
2236         v = 0;
2237         for(j = 0; j < 8; j++) {
2238             v |= ((i >> j) & 1) << (j * 4);
2239         }
2240         expand4[i] = v;
2241
2242         v = 0;
2243         for(j = 0; j < 4; j++) {
2244             v |= ((i >> (2 * j)) & 3) << (j * 4);
2245         }
2246         expand2[i] = v;
2247     }
2248     for(i = 0; i < 16; i++) {
2249         v = 0;
2250         for(j = 0; j < 4; j++) {
2251             b = ((i >> j) & 1);
2252             v |= b << (2 * j);
2253             v |= b << (2 * j + 1);
2254         }
2255         expand4to8[i] = v;
2256     }
2257
2258     s->vram_ptr = vga_ram_base;
2259     s->vram_offset = vga_ram_offset;
2260     s->vram_size = vga_ram_size;
2261     s->ds = ds;
2262     s->get_bpp = vga_get_bpp;
2263     s->get_offsets = vga_get_offsets;
2264     s->get_resolution = vga_get_resolution;
2265     s->update = vga_update_display;
2266     s->invalidate = vga_invalidate_display;
2267     s->screen_dump = vga_screen_dump;
2268     s->text_update = vga_update_text;
2269     switch (vga_retrace_method) {
2270     case VGA_RETRACE_DUMB:
2271         s->retrace = vga_dumb_retrace;
2272         s->update_retrace_info = vga_dumb_update_retrace_info;
2273         break;
2274
2275     case VGA_RETRACE_PRECISE:
2276         s->retrace = vga_precise_retrace;
2277         s->update_retrace_info = vga_precise_update_retrace_info;
2278         break;
2279     }
2280     qemu_register_reset(vga_reset, s);
2281     vga_reset(s);
2282 }
2283
2284 /* used by both ISA and PCI */
2285 void vga_init(VGAState *s)
2286 {
2287     int vga_io_memory;
2288
2289     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2290
2291     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2292
2293     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2294     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2295     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2296     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2297
2298     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2299
2300     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2301     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2302     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2303     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2304     s->bank_offset = 0;
2305
2306 #ifdef CONFIG_BOCHS_VBE
2307 #if defined (TARGET_I386)
2308     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2309     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2310
2311     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2312     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2313
2314     /* old Bochs IO ports */
2315     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2316     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2317
2318     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2319     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2320 #else
2321     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2322     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2323
2324     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2325     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2326 #endif
2327 #endif /* CONFIG_BOCHS_VBE */
2328
2329     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2330     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2331                                  vga_io_memory);
2332     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2333 }
2334
2335 /* Memory mapped interface */
2336 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2337 {
2338     VGAState *s = opaque;
2339
2340     return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
2341 }
2342
2343 static void vga_mm_writeb (void *opaque,
2344                            target_phys_addr_t addr, uint32_t value)
2345 {
2346     VGAState *s = opaque;
2347
2348     vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
2349 }
2350
2351 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2352 {
2353     VGAState *s = opaque;
2354
2355     return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
2356 }
2357
2358 static void vga_mm_writew (void *opaque,
2359                            target_phys_addr_t addr, uint32_t value)
2360 {
2361     VGAState *s = opaque;
2362
2363     vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
2364 }
2365
2366 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2367 {
2368     VGAState *s = opaque;
2369
2370     return vga_ioport_read(s, addr >> s->it_shift);
2371 }
2372
2373 static void vga_mm_writel (void *opaque,
2374                            target_phys_addr_t addr, uint32_t value)
2375 {
2376     VGAState *s = opaque;
2377
2378     vga_ioport_write(s, addr >> s->it_shift, value);
2379 }
2380
2381 static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2382     &vga_mm_readb,
2383     &vga_mm_readw,
2384     &vga_mm_readl,
2385 };
2386
2387 static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2388     &vga_mm_writeb,
2389     &vga_mm_writew,
2390     &vga_mm_writel,
2391 };
2392
2393 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2394                         target_phys_addr_t ctrl_base, int it_shift)
2395 {
2396     int s_ioport_ctrl, vga_io_memory;
2397
2398     s->it_shift = it_shift;
2399     s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2400     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2401
2402     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2403
2404     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2405     s->bank_offset = 0;
2406     cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2407     qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
2408 }
2409
2410 int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
2411                  unsigned long vga_ram_offset, int vga_ram_size)
2412 {
2413     VGAState *s;
2414
2415     s = qemu_mallocz(sizeof(VGAState));
2416     if (!s)
2417         return -1;
2418
2419     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2420     vga_init(s);
2421
2422     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2423                                       s->screen_dump, s->text_update, s);
2424
2425 #ifdef CONFIG_BOCHS_VBE
2426     /* XXX: use optimized standard vga accesses */
2427     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2428                                  vga_ram_size, vga_ram_offset);
2429 #endif
2430     return 0;
2431 }
2432
2433 int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
2434                     unsigned long vga_ram_offset, int vga_ram_size,
2435                     target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2436                     int it_shift)
2437 {
2438     VGAState *s;
2439
2440     s = qemu_mallocz(sizeof(VGAState));
2441     if (!s)
2442         return -1;
2443
2444     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2445     vga_mm_init(s, vram_base, ctrl_base, it_shift);
2446
2447     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2448                                       s->screen_dump, s->text_update, s);
2449
2450 #ifdef CONFIG_BOCHS_VBE
2451     /* XXX: use optimized standard vga accesses */
2452     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2453                                  vga_ram_size, vga_ram_offset);
2454 #endif
2455     return 0;
2456 }
2457
2458 int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
2459                  unsigned long vga_ram_offset, int vga_ram_size,
2460                  unsigned long vga_bios_offset, int vga_bios_size)
2461 {
2462     PCIVGAState *d;
2463     VGAState *s;
2464     uint8_t *pci_conf;
2465
2466     d = (PCIVGAState *)pci_register_device(bus, "VGA",
2467                                            sizeof(PCIVGAState),
2468                                            -1, NULL, NULL);
2469     if (!d)
2470         return -1;
2471     s = &d->vga_state;
2472
2473     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2474     vga_init(s);
2475
2476     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2477                                       s->screen_dump, s->text_update, s);
2478
2479     s->pci_dev = &d->dev;
2480
2481     pci_conf = d->dev.config;
2482     pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2483     pci_conf[0x01] = 0x12;
2484     pci_conf[0x02] = 0x11;
2485     pci_conf[0x03] = 0x11;
2486     pci_conf[0x0a] = 0x00; // VGA controller
2487     pci_conf[0x0b] = 0x03;
2488     pci_conf[0x0e] = 0x00; // header_type
2489
2490     /* XXX: vga_ram_size must be a power of two */
2491     pci_register_io_region(&d->dev, 0, vga_ram_size,
2492                            PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2493     if (vga_bios_size != 0) {
2494         unsigned int bios_total_size;
2495         s->bios_offset = vga_bios_offset;
2496         s->bios_size = vga_bios_size;
2497         /* must be a power of two */
2498         bios_total_size = 1;
2499         while (bios_total_size < vga_bios_size)
2500             bios_total_size <<= 1;
2501         pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2502                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2503     }
2504     return 0;
2505 }
2506
2507 /********************************************************/
2508 /* vga screen dump */
2509
2510 static int vga_save_w, vga_save_h;
2511
2512 static void vga_save_dpy_update(DisplayState *s,
2513                                 int x, int y, int w, int h)
2514 {
2515 }
2516
2517 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2518 {
2519     s->linesize = w * 4;
2520     s->data = qemu_mallocz(h * s->linesize);
2521     vga_save_w = w;
2522     vga_save_h = h;
2523 }
2524
2525 static void vga_save_dpy_refresh(DisplayState *s)
2526 {
2527 }
2528
2529 int ppm_save(const char *filename, uint8_t *data,
2530              int w, int h, int linesize)
2531 {
2532     FILE *f;
2533     uint8_t *d, *d1;
2534     unsigned int v;
2535     int y, x;
2536
2537     f = fopen(filename, "wb");
2538     if (!f)
2539         return -1;
2540     fprintf(f, "P6\n%d %d\n%d\n",
2541             w, h, 255);
2542     d1 = data;
2543     for(y = 0; y < h; y++) {
2544         d = d1;
2545         for(x = 0; x < w; x++) {
2546             v = *(uint32_t *)d;
2547             fputc((v >> 16) & 0xff, f);
2548             fputc((v >> 8) & 0xff, f);
2549             fputc((v) & 0xff, f);
2550             d += 4;
2551         }
2552         d1 += linesize;
2553     }
2554     fclose(f);
2555     return 0;
2556 }
2557
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)
2580 {
2581     DisplayState *saved_ds, ds1, *ds = &ds1;
2582
2583     /* XXX: this is a little hackish */
2584     vga_invalidate_display(s);
2585     saved_ds = s->ds;
2586
2587     memset(ds, 0, sizeof(DisplayState));
2588     ds->dpy_update = vga_save_dpy_update;
2589     ds->dpy_resize = vga_save_dpy_resize;
2590     ds->dpy_refresh = vga_save_dpy_refresh;
2591     ds->depth = 32;
2592
2593     ds->linesize = w * sizeof(uint32_t);
2594     ds->data = qemu_mallocz(h * ds->linesize);
2595     s->ds = ds;
2596     s->graphic_mode = -1;
2597     vga_update_display(s);
2598     ppm_save(filename, ds->data, w, h, ds->linesize);
2599     qemu_free(ds->data);
2600     s->ds = saved_ds;
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 }