Statistics
| Branch: | Revision:

root / hw / vga.c @ 546fa6ab

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