Statistics
| Branch: | Revision:

root / hw / vga.c @ 334c0241

History | View | Annotate | Download (65.3 kB)

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