b1e43730db93fc5bde9182eeed75a9357061f768
[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     0x03,
42     0x3d,
43     0x0f,
44     0x3f,
45     0x0e,
46     0x00,
47     0x00,
48     0xff,
49 };
50
51 const uint8_t gr_mask[16] = {
52     0x0f, /* 0x00 */
53     0x0f, /* 0x01 */
54     0x0f, /* 0x02 */
55     0x1f, /* 0x03 */
56     0x03, /* 0x04 */
57     0x7b, /* 0x05 */
58     0x0f, /* 0x06 */
59     0x0f, /* 0x07 */
60     0xff, /* 0x08 */
61     0x00, /* 0x09 */
62     0x00, /* 0x0a */
63     0x00, /* 0x0b */
64     0x00, /* 0x0c */
65     0x00, /* 0x0d */
66     0x00, /* 0x0e */
67     0x00, /* 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         return 1;
1161     case 16:
1162         return 2;
1163     case 32:
1164         if (is_surface_bgr(s->surface))
1165             return 4;
1166         else
1167             return 3;
1168     }
1169 }
1170
1171 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1172     vga_draw_glyph8_8,
1173     vga_draw_glyph8_16,
1174     vga_draw_glyph8_16,
1175     vga_draw_glyph8_32,
1176     vga_draw_glyph8_32,
1177     vga_draw_glyph8_16,
1178     vga_draw_glyph8_16,
1179 };
1180
1181 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1182     vga_draw_glyph16_8,
1183     vga_draw_glyph16_16,
1184     vga_draw_glyph16_16,
1185     vga_draw_glyph16_32,
1186     vga_draw_glyph16_32,
1187     vga_draw_glyph16_16,
1188     vga_draw_glyph16_16,
1189 };
1190
1191 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1192     vga_draw_glyph9_8,
1193     vga_draw_glyph9_16,
1194     vga_draw_glyph9_16,
1195     vga_draw_glyph9_32,
1196     vga_draw_glyph9_32,
1197     vga_draw_glyph9_16,
1198     vga_draw_glyph9_16,
1199 };
1200
1201 static const uint8_t cursor_glyph[32 * 4] = {
1202     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1203     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1204     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1205     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1206     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
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 };
1219
1220 static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
1221                                     int *pcwidth, int *pcheight)
1222 {
1223     int width, cwidth, height, cheight;
1224
1225     /* total width & height */
1226     cheight = (s->cr[9] & 0x1f) + 1;
1227     cwidth = 8;
1228     if (!(s->sr[1] & 0x01))
1229         cwidth = 9;
1230     if (s->sr[1] & 0x08)
1231         cwidth = 16; /* NOTE: no 18 pixel wide */
1232     width = (s->cr[0x01] + 1);
1233     if (s->cr[0x06] == 100) {
1234         /* ugly hack for CGA 160x100x16 - explain me the logic */
1235         height = 100;
1236     } else {
1237         height = s->cr[0x12] |
1238             ((s->cr[0x07] & 0x02) << 7) |
1239             ((s->cr[0x07] & 0x40) << 3);
1240         height = (height + 1) / cheight;
1241     }
1242
1243     *pwidth = width;
1244     *pheight = height;
1245     *pcwidth = cwidth;
1246     *pcheight = cheight;
1247 }
1248
1249 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1250
1251 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1252     rgb_to_pixel8_dup,
1253     rgb_to_pixel15_dup,
1254     rgb_to_pixel16_dup,
1255     rgb_to_pixel32_dup,
1256     rgb_to_pixel32bgr_dup,
1257     rgb_to_pixel15bgr_dup,
1258     rgb_to_pixel16bgr_dup,
1259 };
1260
1261 /*
1262  * Text mode update
1263  * Missing:
1264  * - double scan
1265  * - double width
1266  * - underline
1267  * - flashing
1268  */
1269 static void vga_draw_text(VGAState *s, int full_update)
1270 {
1271     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1272     int cx_min, cx_max, linesize, x_incr;
1273     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1274     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1275     const uint8_t *font_ptr, *font_base[2];
1276     int dup9, line_offset, depth_index;
1277     uint32_t *palette;
1278     uint32_t *ch_attr_ptr;
1279     vga_draw_glyph8_func *vga_draw_glyph8;
1280     vga_draw_glyph9_func *vga_draw_glyph9;
1281
1282     vga_dirty_log_stop(s);
1283
1284     /* compute font data address (in plane 2) */
1285     v = s->sr[3];
1286     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1287     if (offset != s->font_offsets[0]) {
1288         s->font_offsets[0] = offset;
1289         full_update = 1;
1290     }
1291     font_base[0] = s->vram_ptr + offset;
1292
1293     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1294     font_base[1] = s->vram_ptr + offset;
1295     if (offset != s->font_offsets[1]) {
1296         s->font_offsets[1] = offset;
1297         full_update = 1;
1298     }
1299     if (s->plane_updated & (1 << 2)) {
1300         /* if the plane 2 was modified since the last display, it
1301            indicates the font may have been modified */
1302         s->plane_updated = 0;
1303         full_update = 1;
1304     }
1305     full_update |= update_basic_params(s);
1306
1307     line_offset = s->line_offset;
1308     s1 = s->vram_ptr + (s->start_addr * 4);
1309
1310     vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1311     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1312     if ((height * width) > CH_ATTR_SIZE) {
1313         /* better than nothing: exit if transient size is too big */
1314         return;
1315     }
1316
1317     if (width != s->last_width || height != s->last_height ||
1318         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1319         s->last_scr_width = width * cw;
1320         s->last_scr_height = height * cheight;
1321         qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1322         s->last_depth = 0;
1323         s->last_width = width;
1324         s->last_height = height;
1325         s->last_ch = cheight;
1326         s->last_cw = cw;
1327         full_update = 1;
1328     }
1329     s->rgb_to_pixel =
1330         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1331     full_update |= update_palette16(s);
1332     palette = s->last_palette;
1333     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1334
1335     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1336     if (cursor_offset != s->cursor_offset ||
1337         s->cr[0xa] != s->cursor_start ||
1338         s->cr[0xb] != s->cursor_end) {
1339       /* if the cursor position changed, we update the old and new
1340          chars */
1341         if (s->cursor_offset < CH_ATTR_SIZE)
1342             s->last_ch_attr[s->cursor_offset] = -1;
1343         if (cursor_offset < CH_ATTR_SIZE)
1344             s->last_ch_attr[cursor_offset] = -1;
1345         s->cursor_offset = cursor_offset;
1346         s->cursor_start = s->cr[0xa];
1347         s->cursor_end = s->cr[0xb];
1348     }
1349     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1350
1351     depth_index = get_depth_index(s->ds);
1352     if (cw == 16)
1353         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1354     else
1355         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1356     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1357
1358     dest = ds_get_data(s->ds);
1359     linesize = ds_get_linesize(s->ds);
1360     ch_attr_ptr = s->last_ch_attr;
1361     for(cy = 0; cy < height; cy++) {
1362         d1 = dest;
1363         src = s1;
1364         cx_min = width;
1365         cx_max = -1;
1366         for(cx = 0; cx < width; cx++) {
1367             ch_attr = *(uint16_t *)src;
1368             if (full_update || ch_attr != *ch_attr_ptr) {
1369                 if (cx < cx_min)
1370                     cx_min = cx;
1371                 if (cx > cx_max)
1372                     cx_max = cx;
1373                 *ch_attr_ptr = ch_attr;
1374 #ifdef WORDS_BIGENDIAN
1375                 ch = ch_attr >> 8;
1376                 cattr = ch_attr & 0xff;
1377 #else
1378                 ch = ch_attr & 0xff;
1379                 cattr = ch_attr >> 8;
1380 #endif
1381                 font_ptr = font_base[(cattr >> 3) & 1];
1382                 font_ptr += 32 * 4 * ch;
1383                 bgcol = palette[cattr >> 4];
1384                 fgcol = palette[cattr & 0x0f];
1385                 if (cw != 9) {
1386                     vga_draw_glyph8(d1, linesize,
1387                                     font_ptr, cheight, fgcol, bgcol);
1388                 } else {
1389                     dup9 = 0;
1390                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1391                         dup9 = 1;
1392                     vga_draw_glyph9(d1, linesize,
1393                                     font_ptr, cheight, fgcol, bgcol, dup9);
1394                 }
1395                 if (src == cursor_ptr &&
1396                     !(s->cr[0x0a] & 0x20)) {
1397                     int line_start, line_last, h;
1398                     /* draw the cursor */
1399                     line_start = s->cr[0x0a] & 0x1f;
1400                     line_last = s->cr[0x0b] & 0x1f;
1401                     /* XXX: check that */
1402                     if (line_last > cheight - 1)
1403                         line_last = cheight - 1;
1404                     if (line_last >= line_start && line_start < cheight) {
1405                         h = line_last - line_start + 1;
1406                         d = d1 + linesize * line_start;
1407                         if (cw != 9) {
1408                             vga_draw_glyph8(d, linesize,
1409                                             cursor_glyph, h, fgcol, bgcol);
1410                         } else {
1411                             vga_draw_glyph9(d, linesize,
1412                                             cursor_glyph, h, fgcol, bgcol, 1);
1413                         }
1414                     }
1415                 }
1416             }
1417             d1 += x_incr;
1418             src += 4;
1419             ch_attr_ptr++;
1420         }
1421         if (cx_max != -1) {
1422             dpy_update(s->ds, cx_min * cw, cy * cheight,
1423                        (cx_max - cx_min + 1) * cw, cheight);
1424         }
1425         dest += linesize * cheight;
1426         s1 += line_offset;
1427     }
1428 }
1429
1430 enum {
1431     VGA_DRAW_LINE2,
1432     VGA_DRAW_LINE2D2,
1433     VGA_DRAW_LINE4,
1434     VGA_DRAW_LINE4D2,
1435     VGA_DRAW_LINE8D2,
1436     VGA_DRAW_LINE8,
1437     VGA_DRAW_LINE15,
1438     VGA_DRAW_LINE16,
1439     VGA_DRAW_LINE24,
1440     VGA_DRAW_LINE32,
1441     VGA_DRAW_LINE_NB,
1442 };
1443
1444 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1445     vga_draw_line2_8,
1446     vga_draw_line2_16,
1447     vga_draw_line2_16,
1448     vga_draw_line2_32,
1449     vga_draw_line2_32,
1450     vga_draw_line2_16,
1451     vga_draw_line2_16,
1452
1453     vga_draw_line2d2_8,
1454     vga_draw_line2d2_16,
1455     vga_draw_line2d2_16,
1456     vga_draw_line2d2_32,
1457     vga_draw_line2d2_32,
1458     vga_draw_line2d2_16,
1459     vga_draw_line2d2_16,
1460
1461     vga_draw_line4_8,
1462     vga_draw_line4_16,
1463     vga_draw_line4_16,
1464     vga_draw_line4_32,
1465     vga_draw_line4_32,
1466     vga_draw_line4_16,
1467     vga_draw_line4_16,
1468
1469     vga_draw_line4d2_8,
1470     vga_draw_line4d2_16,
1471     vga_draw_line4d2_16,
1472     vga_draw_line4d2_32,
1473     vga_draw_line4d2_32,
1474     vga_draw_line4d2_16,
1475     vga_draw_line4d2_16,
1476
1477     vga_draw_line8d2_8,
1478     vga_draw_line8d2_16,
1479     vga_draw_line8d2_16,
1480     vga_draw_line8d2_32,
1481     vga_draw_line8d2_32,
1482     vga_draw_line8d2_16,
1483     vga_draw_line8d2_16,
1484
1485     vga_draw_line8_8,
1486     vga_draw_line8_16,
1487     vga_draw_line8_16,
1488     vga_draw_line8_32,
1489     vga_draw_line8_32,
1490     vga_draw_line8_16,
1491     vga_draw_line8_16,
1492
1493     vga_draw_line15_8,
1494     vga_draw_line15_15,
1495     vga_draw_line15_16,
1496     vga_draw_line15_32,
1497     vga_draw_line15_32bgr,
1498     vga_draw_line15_15bgr,
1499     vga_draw_line15_16bgr,
1500
1501     vga_draw_line16_8,
1502     vga_draw_line16_15,
1503     vga_draw_line16_16,
1504     vga_draw_line16_32,
1505     vga_draw_line16_32bgr,
1506     vga_draw_line16_15bgr,
1507     vga_draw_line16_16bgr,
1508
1509     vga_draw_line24_8,
1510     vga_draw_line24_15,
1511     vga_draw_line24_16,
1512     vga_draw_line24_32,
1513     vga_draw_line24_32bgr,
1514     vga_draw_line24_15bgr,
1515     vga_draw_line24_16bgr,
1516
1517     vga_draw_line32_8,
1518     vga_draw_line32_15,
1519     vga_draw_line32_16,
1520     vga_draw_line32_32,
1521     vga_draw_line32_32bgr,
1522     vga_draw_line32_15bgr,
1523     vga_draw_line32_16bgr,
1524 };
1525
1526 static int vga_get_bpp(VGAState *s)
1527 {
1528     int ret;
1529 #ifdef CONFIG_BOCHS_VBE
1530     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1531         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1532     } else
1533 #endif
1534     {
1535         ret = 0;
1536     }
1537     return ret;
1538 }
1539
1540 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1541 {
1542     int width, height;
1543
1544 #ifdef CONFIG_BOCHS_VBE
1545     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1546         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1547         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1548     } else
1549 #endif
1550     {
1551         width = (s->cr[0x01] + 1) * 8;
1552         height = s->cr[0x12] |
1553             ((s->cr[0x07] & 0x02) << 7) |
1554             ((s->cr[0x07] & 0x40) << 3);
1555         height = (height + 1);
1556     }
1557     *pwidth = width;
1558     *pheight = height;
1559 }
1560
1561 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1562 {
1563     int y;
1564     if (y1 >= VGA_MAX_HEIGHT)
1565         return;
1566     if (y2 >= VGA_MAX_HEIGHT)
1567         y2 = VGA_MAX_HEIGHT;
1568     for(y = y1; y < y2; y++) {
1569         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1570     }
1571 }
1572
1573 static void vga_sync_dirty_bitmap(VGAState *s)
1574 {
1575     if (s->map_addr)
1576         cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1577
1578     if (s->lfb_vram_mapped) {
1579         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1580         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1581     }
1582     vga_dirty_log_start(s);
1583 }
1584
1585 /*
1586  * graphic modes
1587  */
1588 static void vga_draw_graphic(VGAState *s, int full_update)
1589 {
1590     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask, depth;
1591     int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
1592     int disp_width, multi_scan, multi_run;
1593     uint8_t *d;
1594     uint32_t v, addr1, addr;
1595     vga_draw_line_func *vga_draw_line;
1596
1597     full_update |= update_basic_params(s);
1598
1599     if (!full_update)
1600         vga_sync_dirty_bitmap(s);
1601
1602     s->get_resolution(s, &width, &height);
1603     disp_width = width;
1604
1605     shift_control = (s->gr[0x05] >> 5) & 3;
1606     double_scan = (s->cr[0x09] >> 7);
1607     if (shift_control != 1) {
1608         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1609     } else {
1610         /* in CGA modes, multi_scan is ignored */
1611         /* XXX: is it correct ? */
1612         multi_scan = double_scan;
1613     }
1614     multi_run = multi_scan;
1615     if (shift_control != s->shift_control ||
1616         double_scan != s->double_scan) {
1617         full_update = 1;
1618         s->shift_control = shift_control;
1619         s->double_scan = double_scan;
1620     }
1621
1622     if (shift_control == 0) {
1623         if (s->sr[0x01] & 8) {
1624             disp_width <<= 1;
1625         }
1626     } else if (shift_control == 1) {
1627         if (s->sr[0x01] & 8) {
1628             disp_width <<= 1;
1629         }
1630     }
1631
1632     depth = s->get_bpp(s);
1633     if (s->line_offset != s->last_line_offset ||
1634         disp_width != s->last_width ||
1635         height != s->last_height ||
1636         s->last_depth != depth) {
1637 #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1638         if (depth == 16 || depth == 32) {
1639 #else
1640         if (depth == 32) {
1641 #endif
1642             qemu_free_displaysurface(s->ds);
1643             s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1644                     s->line_offset,
1645                     s->vram_ptr + (s->start_addr * 4));
1646 #if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1647             s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1648 #endif
1649             dpy_resize(s->ds);
1650         } else {
1651             qemu_console_resize(s->ds, disp_width, height);
1652         }
1653         s->last_scr_width = disp_width;
1654         s->last_scr_height = height;
1655         s->last_width = disp_width;
1656         s->last_height = height;
1657         s->last_line_offset = s->line_offset;
1658         s->last_depth = depth;
1659         full_update = 1;
1660     } else if (is_buffer_shared(s->ds->surface) &&
1661                (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1662         s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1663         dpy_setdata(s->ds);
1664     }
1665
1666     s->rgb_to_pixel =
1667         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1668
1669     if (shift_control == 0) {
1670         full_update |= update_palette16(s);
1671         if (s->sr[0x01] & 8) {
1672             v = VGA_DRAW_LINE4D2;
1673         } else {
1674             v = VGA_DRAW_LINE4;
1675         }
1676         bits = 4;
1677     } else if (shift_control == 1) {
1678         full_update |= update_palette16(s);
1679         if (s->sr[0x01] & 8) {
1680             v = VGA_DRAW_LINE2D2;
1681         } else {
1682             v = VGA_DRAW_LINE2;
1683         }
1684         bits = 4;
1685     } else {
1686         switch(s->get_bpp(s)) {
1687         default:
1688         case 0:
1689             full_update |= update_palette256(s);
1690             v = VGA_DRAW_LINE8D2;
1691             bits = 4;
1692             break;
1693         case 8:
1694             full_update |= update_palette256(s);
1695             v = VGA_DRAW_LINE8;
1696             bits = 8;
1697             break;
1698         case 15:
1699             v = VGA_DRAW_LINE15;
1700             bits = 16;
1701             break;
1702         case 16:
1703             v = VGA_DRAW_LINE16;
1704             bits = 16;
1705             break;
1706         case 24:
1707             v = VGA_DRAW_LINE24;
1708             bits = 24;
1709             break;
1710         case 32:
1711             v = VGA_DRAW_LINE32;
1712             bits = 32;
1713             break;
1714         }
1715     }
1716     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1717
1718     if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1719         s->cursor_invalidate(s);
1720
1721     line_offset = s->line_offset;
1722 #if 0
1723     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",
1724            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1725 #endif
1726     addr1 = (s->start_addr * 4);
1727     bwidth = (width * bits + 7) / 8;
1728     y_start = -1;
1729     page_min = 0x7fffffff;
1730     page_max = -1;
1731     d = ds_get_data(s->ds);
1732     linesize = ds_get_linesize(s->ds);
1733     y1 = 0;
1734     for(y = 0; y < height; y++) {
1735         addr = addr1;
1736         if (!(s->cr[0x17] & 1)) {
1737             int shift;
1738             /* CGA compatibility handling */
1739             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1740             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1741         }
1742         if (!(s->cr[0x17] & 2)) {
1743             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1744         }
1745         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1746         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1747         update = full_update |
1748             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1749             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1750         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1751             /* if wide line, can use another page */
1752             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1753                                                     VGA_DIRTY_FLAG);
1754         }
1755         /* explicit invalidation for the hardware cursor */
1756         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1757         if (update) {
1758             if (y_start < 0)
1759                 y_start = y;
1760             if (page0 < page_min)
1761                 page_min = page0;
1762             if (page1 > page_max)
1763                 page_max = page1;
1764             if (!(is_buffer_shared(s->ds->surface))) {
1765                 vga_draw_line(s, d, s->vram_ptr + addr, width);
1766                 if (s->cursor_draw_line)
1767                     s->cursor_draw_line(s, d, y);
1768             }
1769         } else {
1770             if (y_start >= 0) {
1771                 /* flush to display */
1772                 dpy_update(s->ds, 0, y_start,
1773                            disp_width, y - y_start);
1774                 y_start = -1;
1775             }
1776         }
1777         if (!multi_run) {
1778             mask = (s->cr[0x17] & 3) ^ 3;
1779             if ((y1 & mask) == mask)
1780                 addr1 += line_offset;
1781             y1++;
1782             multi_run = multi_scan;
1783         } else {
1784             multi_run--;
1785         }
1786         /* line compare acts on the displayed lines */
1787         if (y == s->line_compare)
1788             addr1 = 0;
1789         d += linesize;
1790     }
1791     if (y_start >= 0) {
1792         /* flush to display */
1793         dpy_update(s->ds, 0, y_start,
1794                    disp_width, y - y_start);
1795     }
1796     /* reset modified pages */
1797     if (page_max != -1) {
1798         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1799                                         VGA_DIRTY_FLAG);
1800     }
1801     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1802 }
1803
1804 static void vga_draw_blank(VGAState *s, int full_update)
1805 {
1806     int i, w, val;
1807     uint8_t *d;
1808
1809     if (!full_update)
1810         return;
1811     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1812         return;
1813     vga_dirty_log_stop(s);
1814
1815     s->rgb_to_pixel =
1816         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1817     if (ds_get_bits_per_pixel(s->ds) == 8)
1818         val = s->rgb_to_pixel(0, 0, 0);
1819     else
1820         val = 0;
1821     w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1822     d = ds_get_data(s->ds);
1823     for(i = 0; i < s->last_scr_height; i++) {
1824         memset(d, val, w);
1825         d += ds_get_linesize(s->ds);
1826     }
1827     dpy_update(s->ds, 0, 0,
1828                s->last_scr_width, s->last_scr_height);
1829 }
1830
1831 #define GMODE_TEXT     0
1832 #define GMODE_GRAPH    1
1833 #define GMODE_BLANK 2
1834
1835 static void vga_update_display(void *opaque)
1836 {
1837     VGAState *s = (VGAState *)opaque;
1838     int full_update, graphic_mode;
1839
1840     if (ds_get_bits_per_pixel(s->ds) == 0) {
1841         /* nothing to do */
1842     } else {
1843         full_update = 0;
1844         if (!(s->ar_index & 0x20)) {
1845             graphic_mode = GMODE_BLANK;
1846         } else {
1847             graphic_mode = s->gr[6] & 1;
1848         }
1849         if (graphic_mode != s->graphic_mode) {
1850             s->graphic_mode = graphic_mode;
1851             full_update = 1;
1852         }
1853         switch(graphic_mode) {
1854         case GMODE_TEXT:
1855             vga_draw_text(s, full_update);
1856             break;
1857         case GMODE_GRAPH:
1858             vga_draw_graphic(s, full_update);
1859             break;
1860         case GMODE_BLANK:
1861         default:
1862             vga_draw_blank(s, full_update);
1863             break;
1864         }
1865     }
1866 }
1867
1868 /* force a full display refresh */
1869 static void vga_invalidate_display(void *opaque)
1870 {
1871     VGAState *s = (VGAState *)opaque;
1872
1873     s->last_width = -1;
1874     s->last_height = -1;
1875 }
1876
1877 void vga_reset(void *opaque)
1878 {
1879     VGAState *s = (VGAState *) opaque;
1880
1881     s->lfb_addr = 0;
1882     s->lfb_end = 0;
1883     s->map_addr = 0;
1884     s->map_end = 0;
1885     s->lfb_vram_mapped = 0;
1886     s->bios_offset = 0;
1887     s->bios_size = 0;
1888     s->sr_index = 0;
1889     memset(s->sr, '\0', sizeof(s->sr));
1890     s->gr_index = 0;
1891     memset(s->gr, '\0', sizeof(s->gr));
1892     s->ar_index = 0;
1893     memset(s->ar, '\0', sizeof(s->ar));
1894     s->ar_flip_flop = 0;
1895     s->cr_index = 0;
1896     memset(s->cr, '\0', sizeof(s->cr));
1897     s->msr = 0;
1898     s->fcr = 0;
1899     s->st00 = 0;
1900     s->st01 = 0;
1901     s->dac_state = 0;
1902     s->dac_sub_index = 0;
1903     s->dac_read_index = 0;
1904     s->dac_write_index = 0;
1905     memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1906     s->dac_8bit = 0;
1907     memset(s->palette, '\0', sizeof(s->palette));
1908     s->bank_offset = 0;
1909 #ifdef CONFIG_BOCHS_VBE
1910     s->vbe_index = 0;
1911     memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1912     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1913     s->vbe_start_addr = 0;
1914     s->vbe_line_offset = 0;
1915     s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1916 #endif
1917     memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1918     s->graphic_mode = -1; /* force full update */
1919     s->shift_control = 0;
1920     s->double_scan = 0;
1921     s->line_offset = 0;
1922     s->line_compare = 0;
1923     s->start_addr = 0;
1924     s->plane_updated = 0;
1925     s->last_cw = 0;
1926     s->last_ch = 0;
1927     s->last_width = 0;
1928     s->last_height = 0;
1929     s->last_scr_width = 0;
1930     s->last_scr_height = 0;
1931     s->cursor_start = 0;
1932     s->cursor_end = 0;
1933     s->cursor_offset = 0;
1934     memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1935     memset(s->last_palette, '\0', sizeof(s->last_palette));
1936     memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1937     switch (vga_retrace_method) {
1938     case VGA_RETRACE_DUMB:
1939         break;
1940     case VGA_RETRACE_PRECISE:
1941         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1942         break;
1943     }
1944 }
1945
1946 #define TEXTMODE_X(x)   ((x) % width)
1947 #define TEXTMODE_Y(x)   ((x) / width)
1948 #define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
1949         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1950 /* relay text rendering to the display driver
1951  * instead of doing a full vga_update_display() */
1952 static void vga_update_text(void *opaque, console_ch_t *chardata)
1953 {
1954     VGAState *s = (VGAState *) opaque;
1955     int graphic_mode, i, cursor_offset, cursor_visible;
1956     int cw, cheight, width, height, size, c_min, c_max;
1957     uint32_t *src;
1958     console_ch_t *dst, val;
1959     char msg_buffer[80];
1960     int full_update = 0;
1961
1962     if (!(s->ar_index & 0x20)) {
1963         graphic_mode = GMODE_BLANK;
1964     } else {
1965         graphic_mode = s->gr[6] & 1;
1966     }
1967     if (graphic_mode != s->graphic_mode) {
1968         s->graphic_mode = graphic_mode;
1969         full_update = 1;
1970     }
1971     if (s->last_width == -1) {
1972         s->last_width = 0;
1973         full_update = 1;
1974     }
1975
1976     switch (graphic_mode) {
1977     case GMODE_TEXT:
1978         /* TODO: update palette */
1979         full_update |= update_basic_params(s);
1980
1981         /* total width & height */
1982         cheight = (s->cr[9] & 0x1f) + 1;
1983         cw = 8;
1984         if (!(s->sr[1] & 0x01))
1985             cw = 9;
1986         if (s->sr[1] & 0x08)
1987             cw = 16; /* NOTE: no 18 pixel wide */
1988         width = (s->cr[0x01] + 1);
1989         if (s->cr[0x06] == 100) {
1990             /* ugly hack for CGA 160x100x16 - explain me the logic */
1991             height = 100;
1992         } else {
1993             height = s->cr[0x12] | 
1994                 ((s->cr[0x07] & 0x02) << 7) | 
1995                 ((s->cr[0x07] & 0x40) << 3);
1996             height = (height + 1) / cheight;
1997         }
1998
1999         size = (height * width);
2000         if (size > CH_ATTR_SIZE) {
2001             if (!full_update)
2002                 return;
2003
2004             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2005                      width, height);
2006             break;
2007         }
2008
2009         if (width != s->last_width || height != s->last_height ||
2010             cw != s->last_cw || cheight != s->last_ch) {
2011             s->last_scr_width = width * cw;
2012             s->last_scr_height = height * cheight;
2013             s->ds->surface->width = width;
2014             s->ds->surface->height = height;
2015             dpy_resize(s->ds);
2016             s->last_width = width;
2017             s->last_height = height;
2018             s->last_ch = cheight;
2019             s->last_cw = cw;
2020             full_update = 1;
2021         }
2022
2023         /* Update "hardware" cursor */
2024         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2025         if (cursor_offset != s->cursor_offset ||
2026             s->cr[0xa] != s->cursor_start ||
2027             s->cr[0xb] != s->cursor_end || full_update) {
2028             cursor_visible = !(s->cr[0xa] & 0x20);
2029             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2030                 dpy_cursor(s->ds,
2031                            TEXTMODE_X(cursor_offset),
2032                            TEXTMODE_Y(cursor_offset));
2033             else
2034                 dpy_cursor(s->ds, -1, -1);
2035             s->cursor_offset = cursor_offset;
2036             s->cursor_start = s->cr[0xa];
2037             s->cursor_end = s->cr[0xb];
2038         }
2039
2040         src = (uint32_t *) s->vram_ptr + s->start_addr;
2041         dst = chardata;
2042
2043         if (full_update) {
2044             for (i = 0; i < size; src ++, dst ++, i ++)
2045                 console_write_ch(dst, VMEM2CHTYPE(*src));
2046
2047             dpy_update(s->ds, 0, 0, width, height);
2048         } else {
2049             c_max = 0;
2050
2051             for (i = 0; i < size; src ++, dst ++, i ++) {
2052                 console_write_ch(&val, VMEM2CHTYPE(*src));
2053                 if (*dst != val) {
2054                     *dst = val;
2055                     c_max = i;
2056                     break;
2057                 }
2058             }
2059             c_min = i;
2060             for (; i < size; src ++, dst ++, i ++) {
2061                 console_write_ch(&val, VMEM2CHTYPE(*src));
2062                 if (*dst != val) {
2063                     *dst = val;
2064                     c_max = i;
2065                 }
2066             }
2067
2068             if (c_min <= c_max) {
2069                 i = TEXTMODE_Y(c_min);
2070                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2071             }
2072         }
2073
2074         return;
2075     case GMODE_GRAPH:
2076         if (!full_update)
2077             return;
2078
2079         s->get_resolution(s, &width, &height);
2080         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2081                  width, height);
2082         break;
2083     case GMODE_BLANK:
2084     default:
2085         if (!full_update)
2086             return;
2087
2088         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2089         break;
2090     }
2091
2092     /* Display a message */
2093     s->last_width = 60;
2094     s->last_height = height = 3;
2095     dpy_cursor(s->ds, -1, -1);
2096     s->ds->surface->width = s->last_width;
2097     s->ds->surface->height = height;
2098     dpy_resize(s->ds);
2099
2100     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2101         console_write_ch(dst ++, ' ');
2102
2103     size = strlen(msg_buffer);
2104     width = (s->last_width - size) / 2;
2105     dst = chardata + s->last_width + width;
2106     for (i = 0; i < size; i ++)
2107         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2108
2109     dpy_update(s->ds, 0, 0, s->last_width, height);
2110 }
2111
2112 static CPUReadMemoryFunc *vga_mem_read[3] = {
2113     vga_mem_readb,
2114     vga_mem_readw,
2115     vga_mem_readl,
2116 };
2117
2118 static CPUWriteMemoryFunc *vga_mem_write[3] = {
2119     vga_mem_writeb,
2120     vga_mem_writew,
2121     vga_mem_writel,
2122 };
2123
2124 static void vga_save(QEMUFile *f, void *opaque)
2125 {
2126     VGAState *s = opaque;
2127     int i;
2128
2129     if (s->pci_dev)
2130         pci_device_save(s->pci_dev, f);
2131
2132     qemu_put_be32s(f, &s->latch);
2133     qemu_put_8s(f, &s->sr_index);
2134     qemu_put_buffer(f, s->sr, 8);
2135     qemu_put_8s(f, &s->gr_index);
2136     qemu_put_buffer(f, s->gr, 16);
2137     qemu_put_8s(f, &s->ar_index);
2138     qemu_put_buffer(f, s->ar, 21);
2139     qemu_put_be32(f, s->ar_flip_flop);
2140     qemu_put_8s(f, &s->cr_index);
2141     qemu_put_buffer(f, s->cr, 256);
2142     qemu_put_8s(f, &s->msr);
2143     qemu_put_8s(f, &s->fcr);
2144     qemu_put_byte(f, s->st00);
2145     qemu_put_8s(f, &s->st01);
2146
2147     qemu_put_8s(f, &s->dac_state);
2148     qemu_put_8s(f, &s->dac_sub_index);
2149     qemu_put_8s(f, &s->dac_read_index);
2150     qemu_put_8s(f, &s->dac_write_index);
2151     qemu_put_buffer(f, s->dac_cache, 3);
2152     qemu_put_buffer(f, s->palette, 768);
2153
2154     qemu_put_be32(f, s->bank_offset);
2155 #ifdef CONFIG_BOCHS_VBE
2156     qemu_put_byte(f, 1);
2157     qemu_put_be16s(f, &s->vbe_index);
2158     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2159         qemu_put_be16s(f, &s->vbe_regs[i]);
2160     qemu_put_be32s(f, &s->vbe_start_addr);
2161     qemu_put_be32s(f, &s->vbe_line_offset);
2162     qemu_put_be32s(f, &s->vbe_bank_mask);
2163 #else
2164     qemu_put_byte(f, 0);
2165 #endif
2166 }
2167
2168 static int vga_load(QEMUFile *f, void *opaque, int version_id)
2169 {
2170     VGAState *s = opaque;
2171     int is_vbe, i, ret;
2172
2173     if (version_id > 2)
2174         return -EINVAL;
2175
2176     if (s->pci_dev && version_id >= 2) {
2177         ret = pci_device_load(s->pci_dev, f);
2178         if (ret < 0)
2179             return ret;
2180     }
2181
2182     qemu_get_be32s(f, &s->latch);
2183     qemu_get_8s(f, &s->sr_index);
2184     qemu_get_buffer(f, s->sr, 8);
2185     qemu_get_8s(f, &s->gr_index);
2186     qemu_get_buffer(f, s->gr, 16);
2187     qemu_get_8s(f, &s->ar_index);
2188     qemu_get_buffer(f, s->ar, 21);
2189     s->ar_flip_flop=qemu_get_be32(f);
2190     qemu_get_8s(f, &s->cr_index);
2191     qemu_get_buffer(f, s->cr, 256);
2192     qemu_get_8s(f, &s->msr);
2193     qemu_get_8s(f, &s->fcr);
2194     qemu_get_8s(f, &s->st00);
2195     qemu_get_8s(f, &s->st01);
2196
2197     qemu_get_8s(f, &s->dac_state);
2198     qemu_get_8s(f, &s->dac_sub_index);
2199     qemu_get_8s(f, &s->dac_read_index);
2200     qemu_get_8s(f, &s->dac_write_index);
2201     qemu_get_buffer(f, s->dac_cache, 3);
2202     qemu_get_buffer(f, s->palette, 768);
2203
2204     s->bank_offset=qemu_get_be32(f);
2205     is_vbe = qemu_get_byte(f);
2206 #ifdef CONFIG_BOCHS_VBE
2207     if (!is_vbe)
2208         return -EINVAL;
2209     qemu_get_be16s(f, &s->vbe_index);
2210     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2211         qemu_get_be16s(f, &s->vbe_regs[i]);
2212     qemu_get_be32s(f, &s->vbe_start_addr);
2213     qemu_get_be32s(f, &s->vbe_line_offset);
2214     qemu_get_be32s(f, &s->vbe_bank_mask);
2215 #else
2216     if (is_vbe)
2217         return -EINVAL;
2218 #endif
2219
2220     /* force refresh */
2221     s->graphic_mode = -1;
2222     return 0;
2223 }
2224
2225 typedef struct PCIVGAState {
2226     PCIDevice dev;
2227     VGAState vga_state;
2228 } PCIVGAState;
2229
2230 void vga_dirty_log_start(VGAState *s)
2231 {
2232     if (kvm_enabled() && s->map_addr)
2233         kvm_log_start(s->map_addr, s->map_end - s->map_addr);
2234
2235     if (kvm_enabled() && s->lfb_vram_mapped) {
2236         kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
2237         kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
2238     }
2239 }
2240
2241 void vga_dirty_log_stop(VGAState *s)
2242 {
2243     if (kvm_enabled() && s->map_addr)
2244         kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
2245
2246     if (kvm_enabled() && s->lfb_vram_mapped) {
2247         kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
2248         kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
2249     }
2250 }
2251
2252 static void vga_map(PCIDevice *pci_dev, int region_num,
2253                     uint32_t addr, uint32_t size, int type)
2254 {
2255     PCIVGAState *d = (PCIVGAState *)pci_dev;
2256     VGAState *s = &d->vga_state;
2257     if (region_num == PCI_ROM_SLOT) {
2258         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2259     } else {
2260         cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2261     }
2262
2263     s->map_addr = addr;
2264     s->map_end = addr + VGA_RAM_SIZE;
2265
2266     vga_dirty_log_start(s);
2267 }
2268
2269 void vga_common_init(VGAState *s, uint8_t *vga_ram_base,
2270                      ram_addr_t vga_ram_offset, int vga_ram_size)
2271 {
2272     int i, j, v, b;
2273
2274     for(i = 0;i < 256; i++) {
2275         v = 0;
2276         for(j = 0; j < 8; j++) {
2277             v |= ((i >> j) & 1) << (j * 4);
2278         }
2279         expand4[i] = v;
2280
2281         v = 0;
2282         for(j = 0; j < 4; j++) {
2283             v |= ((i >> (2 * j)) & 3) << (j * 4);
2284         }
2285         expand2[i] = v;
2286     }
2287     for(i = 0; i < 16; i++) {
2288         v = 0;
2289         for(j = 0; j < 4; j++) {
2290             b = ((i >> j) & 1);
2291             v |= b << (2 * j);
2292             v |= b << (2 * j + 1);
2293         }
2294         expand4to8[i] = v;
2295     }
2296
2297     s->vram_ptr = vga_ram_base;
2298     s->vram_offset = vga_ram_offset;
2299     s->vram_size = vga_ram_size;
2300     s->get_bpp = vga_get_bpp;
2301     s->get_offsets = vga_get_offsets;
2302     s->get_resolution = vga_get_resolution;
2303     s->update = vga_update_display;
2304     s->invalidate = vga_invalidate_display;
2305     s->screen_dump = vga_screen_dump;
2306     s->text_update = vga_update_text;
2307     switch (vga_retrace_method) {
2308     case VGA_RETRACE_DUMB:
2309         s->retrace = vga_dumb_retrace;
2310         s->update_retrace_info = vga_dumb_update_retrace_info;
2311         break;
2312
2313     case VGA_RETRACE_PRECISE:
2314         s->retrace = vga_precise_retrace;
2315         s->update_retrace_info = vga_precise_update_retrace_info;
2316         break;
2317     }
2318     vga_reset(s);
2319 }
2320
2321 /* used by both ISA and PCI */
2322 void vga_init(VGAState *s)
2323 {
2324     int vga_io_memory;
2325
2326     qemu_register_reset(vga_reset, s);
2327     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2328
2329     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2330
2331     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2332     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2333     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2334     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2335
2336     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2337
2338     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2339     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2340     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2341     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2342     s->bank_offset = 0;
2343
2344 #ifdef CONFIG_BOCHS_VBE
2345 #if defined (TARGET_I386)
2346     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2347     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2348
2349     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2350     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2351
2352     /* old Bochs IO ports */
2353     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2354     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2355
2356     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2357     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2358 #else
2359     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2360     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2361
2362     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2363     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2364 #endif
2365 #endif /* CONFIG_BOCHS_VBE */
2366
2367     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2368     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2369                                  vga_io_memory);
2370     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2371 }
2372
2373 /* Memory mapped interface */
2374 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2375 {
2376     VGAState *s = opaque;
2377
2378     return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
2379 }
2380
2381 static void vga_mm_writeb (void *opaque,
2382                            target_phys_addr_t addr, uint32_t value)
2383 {
2384     VGAState *s = opaque;
2385
2386     vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
2387 }
2388
2389 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2390 {
2391     VGAState *s = opaque;
2392
2393     return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
2394 }
2395
2396 static void vga_mm_writew (void *opaque,
2397                            target_phys_addr_t addr, uint32_t value)
2398 {
2399     VGAState *s = opaque;
2400
2401     vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
2402 }
2403
2404 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2405 {
2406     VGAState *s = opaque;
2407
2408     return vga_ioport_read(s, addr >> s->it_shift);
2409 }
2410
2411 static void vga_mm_writel (void *opaque,
2412                            target_phys_addr_t addr, uint32_t value)
2413 {
2414     VGAState *s = opaque;
2415
2416     vga_ioport_write(s, addr >> s->it_shift, value);
2417 }
2418
2419 static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2420     &vga_mm_readb,
2421     &vga_mm_readw,
2422     &vga_mm_readl,
2423 };
2424
2425 static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2426     &vga_mm_writeb,
2427     &vga_mm_writew,
2428     &vga_mm_writel,
2429 };
2430
2431 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2432                         target_phys_addr_t ctrl_base, int it_shift)
2433 {
2434     int s_ioport_ctrl, vga_io_memory;
2435
2436     s->it_shift = it_shift;
2437     s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2438     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2439
2440     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2441
2442     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2443     s->bank_offset = 0;
2444     cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2445     qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
2446 }
2447
2448 int isa_vga_init(uint8_t *vga_ram_base,
2449                  unsigned long vga_ram_offset, int vga_ram_size)
2450 {
2451     VGAState *s;
2452
2453     s = qemu_mallocz(sizeof(VGAState));
2454
2455     vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
2456     vga_init(s);
2457
2458     s->ds = graphic_console_init(s->update, s->invalidate,
2459                                  s->screen_dump, s->text_update, s);
2460
2461 #ifdef CONFIG_BOCHS_VBE
2462     /* XXX: use optimized standard vga accesses */
2463     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2464                                  vga_ram_size, vga_ram_offset);
2465 #endif
2466     return 0;
2467 }
2468
2469 int isa_vga_mm_init(uint8_t *vga_ram_base,
2470                     unsigned long vga_ram_offset, int vga_ram_size,
2471                     target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2472                     int it_shift)
2473 {
2474     VGAState *s;
2475
2476     s = qemu_mallocz(sizeof(VGAState));
2477
2478     vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
2479     vga_mm_init(s, vram_base, ctrl_base, it_shift);
2480
2481     s->ds = graphic_console_init(s->update, s->invalidate,
2482                                  s->screen_dump, s->text_update, s);
2483
2484 #ifdef CONFIG_BOCHS_VBE
2485     /* XXX: use optimized standard vga accesses */
2486     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2487                                  vga_ram_size, vga_ram_offset);
2488 #endif
2489     return 0;
2490 }
2491
2492 static void pci_vga_write_config(PCIDevice *d,
2493                                  uint32_t address, uint32_t val, int len)
2494 {
2495     PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
2496     VGAState *s = &pvs->vga_state;
2497
2498     vga_dirty_log_stop(s);
2499     pci_default_write_config(d, address, val, len);
2500     vga_dirty_log_start(s);
2501 }
2502
2503 int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base,
2504                  unsigned long vga_ram_offset, int vga_ram_size,
2505                  unsigned long vga_bios_offset, int vga_bios_size)
2506 {
2507     PCIVGAState *d;
2508     VGAState *s;
2509     uint8_t *pci_conf;
2510
2511     d = (PCIVGAState *)pci_register_device(bus, "VGA",
2512                                            sizeof(PCIVGAState),
2513                                            -1, NULL, pci_vga_write_config);
2514     if (!d)
2515         return -1;
2516     s = &d->vga_state;
2517
2518     vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
2519     vga_init(s);
2520
2521     s->ds = graphic_console_init(s->update, s->invalidate,
2522                                  s->screen_dump, s->text_update, s);
2523
2524     s->pci_dev = &d->dev;
2525
2526     pci_conf = d->dev.config;
2527     // dummy VGA (same as Bochs ID)
2528     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
2529     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
2530     pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
2531     pci_conf[0x0e] = 0x00; // header_type
2532
2533     /* XXX: vga_ram_size must be a power of two */
2534     pci_register_io_region(&d->dev, 0, vga_ram_size,
2535                            PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2536     if (vga_bios_size != 0) {
2537         unsigned int bios_total_size;
2538         s->bios_offset = vga_bios_offset;
2539         s->bios_size = vga_bios_size;
2540         /* must be a power of two */
2541         bios_total_size = 1;
2542         while (bios_total_size < vga_bios_size)
2543             bios_total_size <<= 1;
2544         pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2545                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2546     }
2547     return 0;
2548 }
2549
2550 /********************************************************/
2551 /* vga screen dump */
2552
2553 static void vga_save_dpy_update(DisplayState *s,
2554                                 int x, int y, int w, int h)
2555 {
2556 }
2557
2558 static void vga_save_dpy_resize(DisplayState *s)
2559 {
2560 }
2561
2562 static void vga_save_dpy_refresh(DisplayState *s)
2563 {
2564 }
2565
2566 int ppm_save(const char *filename, struct DisplaySurface *ds)
2567 {
2568     FILE *f;
2569     uint8_t *d, *d1;
2570     uint32_t v;
2571     int y, x;
2572     uint8_t r, g, b;
2573
2574     f = fopen(filename, "wb");
2575     if (!f)
2576         return -1;
2577     fprintf(f, "P6\n%d %d\n%d\n",
2578             ds->width, ds->height, 255);
2579     d1 = ds->data;
2580     for(y = 0; y < ds->height; y++) {
2581         d = d1;
2582         for(x = 0; x < ds->width; x++) {
2583             if (ds->pf.bits_per_pixel == 32)
2584                 v = *(uint32_t *)d;
2585             else
2586                 v = (uint32_t) (*(uint16_t *)d);
2587             r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2588                 (ds->pf.rmax + 1);
2589             g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2590                 (ds->pf.gmax + 1);
2591             b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2592                 (ds->pf.bmax + 1);
2593             fputc(r, f);
2594             fputc(g, f);
2595             fputc(b, f);
2596             d += ds->pf.bytes_per_pixel;
2597         }
2598         d1 += ds->linesize;
2599     }
2600     fclose(f);
2601     return 0;
2602 }
2603
2604 static void vga_screen_dump_blank(VGAState *s, const char *filename)
2605 {
2606     FILE *f;
2607     unsigned int y, x, w, h;
2608
2609     w = s->last_scr_width * sizeof(uint32_t);
2610     h = s->last_scr_height;
2611
2612     f = fopen(filename, "wb");
2613     if (!f)
2614         return;
2615     fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
2616     for (y = 0; y < h; y++) {
2617         for (x = 0; x < w; x++) {
2618             fputc(0, f);
2619         }
2620     }
2621     fclose(f);
2622 }
2623
2624 static void vga_screen_dump_common(VGAState *s, const char *filename,
2625                                    int w, int h)
2626 {
2627     DisplayState *saved_ds, ds1, *ds = &ds1;
2628     DisplayChangeListener dcl;
2629
2630     /* XXX: this is a little hackish */
2631     vga_invalidate_display(s);
2632     saved_ds = s->ds;
2633
2634     memset(ds, 0, sizeof(DisplayState));
2635     memset(&dcl, 0, sizeof(DisplayChangeListener));
2636     dcl.dpy_update = vga_save_dpy_update;
2637     dcl.dpy_resize = vga_save_dpy_resize;
2638     dcl.dpy_refresh = vga_save_dpy_refresh;
2639     register_displaychangelistener(ds, &dcl);
2640     ds->allocator = &default_allocator;
2641     ds->surface = qemu_create_displaysurface(ds, w, h);
2642
2643     s->ds = ds;
2644     s->graphic_mode = -1;
2645     vga_update_display(s);
2646
2647     ppm_save(filename, ds->surface);
2648
2649     qemu_free_displaysurface(ds);
2650     s->ds = saved_ds;
2651 }
2652
2653 static void vga_screen_dump_graphic(VGAState *s, const char *filename)
2654 {
2655     int w, h;
2656
2657     s->get_resolution(s, &w, &h);
2658     vga_screen_dump_common(s, filename, w, h);
2659 }
2660
2661 static void vga_screen_dump_text(VGAState *s, const char *filename)
2662 {
2663     int w, h, cwidth, cheight;
2664
2665     vga_get_text_resolution(s, &w, &h, &cwidth, &cheight);
2666     vga_screen_dump_common(s, filename, w * cwidth, h * cheight);
2667 }
2668
2669 /* save the vga display in a PPM image even if no display is
2670    available */
2671 static void vga_screen_dump(void *opaque, const char *filename)
2672 {
2673     VGAState *s = (VGAState *)opaque;
2674
2675     if (!(s->ar_index & 0x20))
2676         vga_screen_dump_blank(s, filename);
2677     else if (s->gr[6] & 1)
2678         vga_screen_dump_graphic(s, filename);
2679     else
2680         vga_screen_dump_text(s, filename);
2681 }