Statistics
| Branch: | Revision:

root / hw / vga.c @ c5d6edc3

History | View | Annotate | Download (55.2 kB)

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