Statistics
| Branch: | Revision:

root / hw / vga.c @ 9da8ba18

History | View | Annotate | Download (36.7 kB)

1 e89f66ec bellard
/*
2 e89f66ec bellard
 * QEMU VGA Emulator. An S3 86c968 is emulated
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 <stdlib.h>
25 e89f66ec bellard
#include <stdio.h>
26 e89f66ec bellard
#include <stdarg.h>
27 e89f66ec bellard
#include <string.h>
28 e89f66ec bellard
#include <getopt.h>
29 e89f66ec bellard
#include <inttypes.h>
30 e89f66ec bellard
#include <unistd.h>
31 e89f66ec bellard
#include <sys/mman.h>
32 e89f66ec bellard
#include <fcntl.h>
33 e89f66ec bellard
#include <signal.h>
34 e89f66ec bellard
#include <time.h>
35 e89f66ec bellard
#include <sys/time.h>
36 e89f66ec bellard
#include <malloc.h>
37 e89f66ec bellard
#include <termios.h>
38 e89f66ec bellard
#include <sys/poll.h>
39 e89f66ec bellard
#include <errno.h>
40 e89f66ec bellard
#include <sys/wait.h>
41 e89f66ec bellard
#include <netinet/in.h>
42 e89f66ec bellard
43 e89f66ec bellard
#include "cpu-i386.h"
44 e89f66ec bellard
#include "exec.h"
45 e89f66ec bellard
46 e89f66ec bellard
#include "vl.h"
47 e89f66ec bellard
48 e89f66ec bellard
#define NO_THUNK_TYPE_SIZE
49 e89f66ec bellard
#include "thunk.h"
50 e89f66ec bellard
51 e89f66ec bellard
//#define DEBUG_VGA
52 17b0018b bellard
//#define DEBUG_VGA_MEM
53 e89f66ec bellard
54 e89f66ec bellard
#define MSR_COLOR_EMULATION 0x01
55 e89f66ec bellard
#define MSR_PAGE_SELECT     0x20
56 e89f66ec bellard
57 e89f66ec bellard
#define ST01_V_RETRACE      0x08
58 e89f66ec bellard
#define ST01_DISP_ENABLE    0x01
59 e89f66ec bellard
60 e89f66ec bellard
typedef struct VGAState {
61 e89f66ec bellard
    uint8_t *vram_ptr;
62 e89f66ec bellard
    unsigned long vram_offset;
63 e89f66ec bellard
    unsigned int vram_size;
64 e89f66ec bellard
    uint32_t latch;
65 e89f66ec bellard
    uint8_t sr_index;
66 e89f66ec bellard
    uint8_t sr[8];
67 e89f66ec bellard
    uint8_t gr_index;
68 e89f66ec bellard
    uint8_t gr[16];
69 e89f66ec bellard
    uint8_t ar_index;
70 e89f66ec bellard
    uint8_t ar[21];
71 e89f66ec bellard
    int ar_flip_flop;
72 e89f66ec bellard
    uint8_t cr_index;
73 e89f66ec bellard
    uint8_t cr[256]; /* CRT registers */
74 e89f66ec bellard
    uint8_t msr; /* Misc Output Register */
75 e89f66ec bellard
    uint8_t fcr; /* Feature Control Register */
76 e89f66ec bellard
    uint8_t st00; /* status 0 */
77 e89f66ec bellard
    uint8_t st01; /* status 1 */
78 e89f66ec bellard
    uint8_t dac_state;
79 e89f66ec bellard
    uint8_t dac_sub_index;
80 e89f66ec bellard
    uint8_t dac_read_index;
81 e89f66ec bellard
    uint8_t dac_write_index;
82 e89f66ec bellard
    uint8_t dac_cache[3]; /* used when writing */
83 e89f66ec bellard
    uint8_t palette[768];
84 e89f66ec bellard
85 e89f66ec bellard
    /* display refresh support */
86 e89f66ec bellard
    DisplayState *ds;
87 e89f66ec bellard
    uint32_t font_offsets[2];
88 e89f66ec bellard
    int graphic_mode;
89 17b0018b bellard
    uint8_t shift_control;
90 17b0018b bellard
    uint8_t double_scan;
91 e89f66ec bellard
    uint32_t line_offset;
92 e89f66ec bellard
    uint32_t line_compare;
93 e89f66ec bellard
    uint32_t start_addr;
94 e89f66ec bellard
    uint8_t last_cw, last_ch;
95 e89f66ec bellard
    uint32_t last_width, last_height;
96 e89f66ec bellard
    uint8_t cursor_start, cursor_end;
97 e89f66ec bellard
    uint32_t cursor_offset;
98 17b0018b bellard
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
99 39cf7803 bellard
    /* tell for each page if it has been updated since the last time */
100 e89f66ec bellard
    uint8_t vram_updated[VGA_RAM_SIZE / 4096];
101 e89f66ec bellard
    uint32_t last_palette[256];
102 17b0018b bellard
#define CH_ATTR_SIZE (160 * 100)
103 e89f66ec bellard
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
104 e89f66ec bellard
} VGAState;
105 e89f66ec bellard
106 e89f66ec bellard
/* force some bits to zero */
107 e89f66ec bellard
static const uint8_t sr_mask[8] = {
108 e89f66ec bellard
    (uint8_t)~0xfc,
109 e89f66ec bellard
    (uint8_t)~0xc2,
110 e89f66ec bellard
    (uint8_t)~0xf0,
111 e89f66ec bellard
    (uint8_t)~0xc0,
112 e89f66ec bellard
    (uint8_t)~0xf1,
113 e89f66ec bellard
    (uint8_t)~0xff,
114 e89f66ec bellard
    (uint8_t)~0xff,
115 e89f66ec bellard
    (uint8_t)~0x00,
116 e89f66ec bellard
};
117 e89f66ec bellard
118 e89f66ec bellard
static const uint8_t gr_mask[16] = {
119 e89f66ec bellard
    (uint8_t)~0xf0, /* 0x00 */
120 e89f66ec bellard
    (uint8_t)~0xf0, /* 0x01 */
121 e89f66ec bellard
    (uint8_t)~0xf0, /* 0x02 */
122 e89f66ec bellard
    (uint8_t)~0xe0, /* 0x03 */
123 e89f66ec bellard
    (uint8_t)~0xfc, /* 0x04 */
124 e89f66ec bellard
    (uint8_t)~0x84, /* 0x05 */
125 e89f66ec bellard
    (uint8_t)~0xf0, /* 0x06 */
126 e89f66ec bellard
    (uint8_t)~0xf0, /* 0x07 */
127 e89f66ec bellard
    (uint8_t)~0x00, /* 0x08 */
128 e89f66ec bellard
    (uint8_t)~0xff, /* 0x09 */
129 e89f66ec bellard
    (uint8_t)~0xff, /* 0x0a */
130 e89f66ec bellard
    (uint8_t)~0xff, /* 0x0b */
131 e89f66ec bellard
    (uint8_t)~0xff, /* 0x0c */
132 e89f66ec bellard
    (uint8_t)~0xff, /* 0x0d */
133 e89f66ec bellard
    (uint8_t)~0xff, /* 0x0e */
134 e89f66ec bellard
    (uint8_t)~0xff, /* 0x0f */
135 e89f66ec bellard
};
136 e89f66ec bellard
137 e89f66ec bellard
#define cbswap_32(__x) \
138 e89f66ec bellard
((uint32_t)( \
139 e89f66ec bellard
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
140 e89f66ec bellard
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
141 e89f66ec bellard
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
142 e89f66ec bellard
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
143 e89f66ec bellard
144 e89f66ec bellard
#ifdef WORD_BIGENDIAN
145 e89f66ec bellard
#define PAT(x) cbswap_32(x)
146 e89f66ec bellard
#else
147 e89f66ec bellard
#define PAT(x) (x)
148 e89f66ec bellard
#endif
149 e89f66ec bellard
150 e89f66ec bellard
static const uint32_t mask16[16] = {
151 e89f66ec bellard
    PAT(0x00000000),
152 e89f66ec bellard
    PAT(0x000000ff),
153 e89f66ec bellard
    PAT(0x0000ff00),
154 e89f66ec bellard
    PAT(0x0000ffff),
155 e89f66ec bellard
    PAT(0x00ff0000),
156 e89f66ec bellard
    PAT(0x00ff00ff),
157 e89f66ec bellard
    PAT(0x00ffff00),
158 e89f66ec bellard
    PAT(0x00ffffff),
159 e89f66ec bellard
    PAT(0xff000000),
160 e89f66ec bellard
    PAT(0xff0000ff),
161 e89f66ec bellard
    PAT(0xff00ff00),
162 e89f66ec bellard
    PAT(0xff00ffff),
163 e89f66ec bellard
    PAT(0xffff0000),
164 e89f66ec bellard
    PAT(0xffff00ff),
165 e89f66ec bellard
    PAT(0xffffff00),
166 e89f66ec bellard
    PAT(0xffffffff),
167 e89f66ec bellard
};
168 e89f66ec bellard
169 e89f66ec bellard
#undef PAT
170 e89f66ec bellard
171 e89f66ec bellard
#ifdef WORD_BIGENDIAN
172 e89f66ec bellard
#define PAT(x) (x)
173 e89f66ec bellard
#else
174 e89f66ec bellard
#define PAT(x) cbswap_32(x)
175 e89f66ec bellard
#endif
176 e89f66ec bellard
177 e89f66ec bellard
static const uint32_t dmask16[16] = {
178 e89f66ec bellard
    PAT(0x00000000),
179 e89f66ec bellard
    PAT(0x000000ff),
180 e89f66ec bellard
    PAT(0x0000ff00),
181 e89f66ec bellard
    PAT(0x0000ffff),
182 e89f66ec bellard
    PAT(0x00ff0000),
183 e89f66ec bellard
    PAT(0x00ff00ff),
184 e89f66ec bellard
    PAT(0x00ffff00),
185 e89f66ec bellard
    PAT(0x00ffffff),
186 e89f66ec bellard
    PAT(0xff000000),
187 e89f66ec bellard
    PAT(0xff0000ff),
188 e89f66ec bellard
    PAT(0xff00ff00),
189 e89f66ec bellard
    PAT(0xff00ffff),
190 e89f66ec bellard
    PAT(0xffff0000),
191 e89f66ec bellard
    PAT(0xffff00ff),
192 e89f66ec bellard
    PAT(0xffffff00),
193 e89f66ec bellard
    PAT(0xffffffff),
194 e89f66ec bellard
};
195 e89f66ec bellard
196 e89f66ec bellard
static const uint32_t dmask4[4] = {
197 e89f66ec bellard
    PAT(0x00000000),
198 e89f66ec bellard
    PAT(0x0000ffff),
199 e89f66ec bellard
    PAT(0xffff0000),
200 e89f66ec bellard
    PAT(0xffffffff),
201 e89f66ec bellard
};
202 e89f66ec bellard
203 e89f66ec bellard
static uint32_t expand4[256];
204 e89f66ec bellard
static uint16_t expand2[256];
205 17b0018b bellard
static uint8_t expand4to8[16];
206 e89f66ec bellard
207 e89f66ec bellard
VGAState vga_state;
208 e89f66ec bellard
int vga_io_memory;
209 e89f66ec bellard
210 e89f66ec bellard
static uint32_t vga_ioport_read(CPUX86State *env, uint32_t addr)
211 e89f66ec bellard
{
212 e89f66ec bellard
    VGAState *s = &vga_state;
213 e89f66ec bellard
    int val, index;
214 e89f66ec bellard
215 e89f66ec bellard
    /* check port range access depending on color/monochrome mode */
216 e89f66ec bellard
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
217 e89f66ec bellard
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
218 e89f66ec bellard
        val = 0xff;
219 e89f66ec bellard
    } else {
220 e89f66ec bellard
        switch(addr) {
221 e89f66ec bellard
        case 0x3c0:
222 e89f66ec bellard
            if (s->ar_flip_flop == 0) {
223 e89f66ec bellard
                val = s->ar_index;
224 e89f66ec bellard
            } else {
225 e89f66ec bellard
                val = 0;
226 e89f66ec bellard
            }
227 e89f66ec bellard
            break;
228 e89f66ec bellard
        case 0x3c1:
229 e89f66ec bellard
            index = s->ar_index & 0x1f;
230 e89f66ec bellard
            if (index < 21) 
231 e89f66ec bellard
                val = s->ar[index];
232 e89f66ec bellard
            else
233 e89f66ec bellard
                val = 0;
234 e89f66ec bellard
            break;
235 e89f66ec bellard
        case 0x3c2:
236 e89f66ec bellard
            val = s->st00;
237 e89f66ec bellard
            break;
238 e89f66ec bellard
        case 0x3c4:
239 e89f66ec bellard
            val = s->sr_index;
240 e89f66ec bellard
            break;
241 e89f66ec bellard
        case 0x3c5:
242 e89f66ec bellard
            val = s->sr[s->sr_index];
243 e89f66ec bellard
            break;
244 e89f66ec bellard
        case 0x3c7:
245 e89f66ec bellard
            val = s->dac_state;
246 e89f66ec bellard
            break;
247 e89f66ec bellard
        case 0x3c9:
248 e89f66ec bellard
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
249 e89f66ec bellard
            if (++s->dac_sub_index == 3) {
250 e89f66ec bellard
                s->dac_sub_index = 0;
251 e89f66ec bellard
                s->dac_read_index++;
252 e89f66ec bellard
            }
253 e89f66ec bellard
            break;
254 e89f66ec bellard
        case 0x3ca:
255 e89f66ec bellard
            val = s->fcr;
256 e89f66ec bellard
            break;
257 e89f66ec bellard
        case 0x3cc:
258 e89f66ec bellard
            val = s->msr;
259 e89f66ec bellard
            break;
260 e89f66ec bellard
        case 0x3ce:
261 e89f66ec bellard
            val = s->gr_index;
262 e89f66ec bellard
            break;
263 e89f66ec bellard
        case 0x3cf:
264 e89f66ec bellard
            val = s->gr[s->gr_index];
265 e89f66ec bellard
            break;
266 e89f66ec bellard
        case 0x3b4:
267 e89f66ec bellard
        case 0x3d4:
268 e89f66ec bellard
            val = s->cr_index;
269 e89f66ec bellard
            break;
270 e89f66ec bellard
        case 0x3b5:
271 e89f66ec bellard
        case 0x3d5:
272 e89f66ec bellard
            val = s->cr[s->cr_index];
273 e89f66ec bellard
            break;
274 e89f66ec bellard
        case 0x3ba:
275 e89f66ec bellard
        case 0x3da:
276 e89f66ec bellard
            /* just toggle to fool polling */
277 e89f66ec bellard
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
278 e89f66ec bellard
            val = s->st01;
279 e89f66ec bellard
            s->ar_flip_flop = 0;
280 e89f66ec bellard
            break;
281 e89f66ec bellard
        default:
282 e89f66ec bellard
            val = 0x00;
283 e89f66ec bellard
            break;
284 e89f66ec bellard
        }
285 e89f66ec bellard
    }
286 e89f66ec bellard
#ifdef DEBUG_VGA
287 e89f66ec bellard
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
288 e89f66ec bellard
#endif
289 e89f66ec bellard
    return val;
290 e89f66ec bellard
}
291 e89f66ec bellard
292 e89f66ec bellard
static void vga_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
293 e89f66ec bellard
{
294 e89f66ec bellard
    VGAState *s = &vga_state;
295 e89f66ec bellard
    int index, v;
296 e89f66ec bellard
297 e89f66ec bellard
    /* check port range access depending on color/monochrome mode */
298 e89f66ec bellard
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
299 e89f66ec bellard
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
300 e89f66ec bellard
        return;
301 e89f66ec bellard
302 e89f66ec bellard
#ifdef DEBUG_VGA
303 e89f66ec bellard
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
304 e89f66ec bellard
#endif
305 e89f66ec bellard
306 e89f66ec bellard
    switch(addr) {
307 e89f66ec bellard
    case 0x3c0:
308 e89f66ec bellard
        if (s->ar_flip_flop == 0) {
309 e89f66ec bellard
            val &= 0x3f;
310 e89f66ec bellard
            s->ar_index = val;
311 e89f66ec bellard
        } else {
312 e89f66ec bellard
            index = s->ar_index & 0x1f;
313 e89f66ec bellard
            switch(index) {
314 e89f66ec bellard
            case 0x00 ... 0x0f:
315 e89f66ec bellard
                s->ar[index] = val & 0x3f;
316 e89f66ec bellard
                break;
317 e89f66ec bellard
            case 0x10:
318 e89f66ec bellard
                s->ar[index] = val & ~0x10;
319 e89f66ec bellard
                break;
320 e89f66ec bellard
            case 0x11:
321 e89f66ec bellard
                s->ar[index] = val;
322 e89f66ec bellard
                break;
323 e89f66ec bellard
            case 0x12:
324 e89f66ec bellard
                s->ar[index] = val & ~0xc0;
325 e89f66ec bellard
                break;
326 e89f66ec bellard
            case 0x13:
327 e89f66ec bellard
                s->ar[index] = val & ~0xf0;
328 e89f66ec bellard
                break;
329 e89f66ec bellard
            case 0x14:
330 e89f66ec bellard
                s->ar[index] = val & ~0xf0;
331 e89f66ec bellard
                break;
332 e89f66ec bellard
            default:
333 e89f66ec bellard
                break;
334 e89f66ec bellard
            }
335 e89f66ec bellard
        }
336 e89f66ec bellard
        s->ar_flip_flop ^= 1;
337 e89f66ec bellard
        break;
338 e89f66ec bellard
    case 0x3c2:
339 e89f66ec bellard
        s->msr = val & ~0x10;
340 e89f66ec bellard
        break;
341 e89f66ec bellard
    case 0x3c4:
342 e89f66ec bellard
        s->sr_index = val & 7;
343 e89f66ec bellard
        break;
344 e89f66ec bellard
    case 0x3c5:
345 e89f66ec bellard
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
346 e89f66ec bellard
        break;
347 e89f66ec bellard
    case 0x3c7:
348 e89f66ec bellard
        s->dac_read_index = val;
349 e89f66ec bellard
        s->dac_sub_index = 0;
350 e89f66ec bellard
        s->dac_state = 3;
351 e89f66ec bellard
        break;
352 e89f66ec bellard
    case 0x3c8:
353 e89f66ec bellard
        s->dac_write_index = val;
354 e89f66ec bellard
        s->dac_sub_index = 0;
355 e89f66ec bellard
        s->dac_state = 0;
356 e89f66ec bellard
        break;
357 e89f66ec bellard
    case 0x3c9:
358 e89f66ec bellard
        s->dac_cache[s->dac_sub_index] = val;
359 e89f66ec bellard
        if (++s->dac_sub_index == 3) {
360 e89f66ec bellard
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
361 e89f66ec bellard
            s->dac_sub_index = 0;
362 e89f66ec bellard
            s->dac_write_index++;
363 e89f66ec bellard
        }
364 e89f66ec bellard
        break;
365 e89f66ec bellard
    case 0x3ce:
366 e89f66ec bellard
        s->gr_index = val & 0x0f;
367 e89f66ec bellard
        break;
368 e89f66ec bellard
    case 0x3cf:
369 e89f66ec bellard
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
370 e89f66ec bellard
        break;
371 e89f66ec bellard
    case 0x3b4:
372 e89f66ec bellard
    case 0x3d4:
373 e89f66ec bellard
        s->cr_index = val;
374 e89f66ec bellard
        break;
375 e89f66ec bellard
    case 0x3b5:
376 e89f66ec bellard
    case 0x3d5:
377 e89f66ec bellard
        /* handle CR0-7 protection */
378 e89f66ec bellard
        if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
379 e89f66ec bellard
            /* can always write bit 4 of CR7 */
380 e89f66ec bellard
            if (s->cr_index == 7)
381 e89f66ec bellard
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
382 e89f66ec bellard
            return;
383 e89f66ec bellard
        }
384 e89f66ec bellard
        switch(s->cr_index) {
385 e89f66ec bellard
        case 0x01: /* horizontal display end */
386 e89f66ec bellard
        case 0x07:
387 e89f66ec bellard
        case 0x09:
388 e89f66ec bellard
        case 0x0c:
389 e89f66ec bellard
        case 0x0d:
390 e89f66ec bellard
        case 0x12: /* veritcal display end */
391 e89f66ec bellard
            s->cr[s->cr_index] = val;
392 e89f66ec bellard
            break;
393 e89f66ec bellard
394 e89f66ec bellard
            /* S3 registers */
395 e89f66ec bellard
        case 0x2d:
396 e89f66ec bellard
        case 0x2e:
397 e89f66ec bellard
        case 0x2f:
398 e89f66ec bellard
        case 0x30:
399 e89f66ec bellard
            /* chip ID, cannot write */
400 e89f66ec bellard
            break;
401 e89f66ec bellard
        case 0x31:
402 e89f66ec bellard
            /* update start address */
403 e89f66ec bellard
            s->cr[s->cr_index] = val;
404 e89f66ec bellard
            v = (val >> 4) & 3;
405 e89f66ec bellard
            s->cr[0x69] = (s->cr[69] & ~0x03) | v;
406 e89f66ec bellard
            break;
407 e89f66ec bellard
        case 0x51:
408 e89f66ec bellard
            /* update start address */
409 e89f66ec bellard
            s->cr[s->cr_index] = val;
410 e89f66ec bellard
            v = val & 3;
411 e89f66ec bellard
            s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
412 e89f66ec bellard
            break;
413 e89f66ec bellard
        default:
414 e89f66ec bellard
            s->cr[s->cr_index] = val;
415 e89f66ec bellard
            break;
416 e89f66ec bellard
        }
417 e89f66ec bellard
        break;
418 e89f66ec bellard
    case 0x3ba:
419 e89f66ec bellard
    case 0x3da:
420 e89f66ec bellard
        s->fcr = val & 0x10;
421 e89f66ec bellard
        break;
422 e89f66ec bellard
    }
423 e89f66ec bellard
}
424 e89f66ec bellard
425 e89f66ec bellard
/* called for accesses between 0xa0000 and 0xc0000 */
426 e89f66ec bellard
static uint32_t vga_mem_readb(uint32_t addr)
427 e89f66ec bellard
{
428 e89f66ec bellard
    VGAState *s = &vga_state;
429 e89f66ec bellard
    int memory_map_mode, plane;
430 e89f66ec bellard
    uint32_t ret;
431 e89f66ec bellard
    
432 e89f66ec bellard
    /* convert to VGA memory offset */
433 e89f66ec bellard
    memory_map_mode = (s->gr[6] >> 2) & 3;
434 e89f66ec bellard
    switch(memory_map_mode) {
435 e89f66ec bellard
    case 0:
436 e89f66ec bellard
        addr -= 0xa0000;
437 e89f66ec bellard
        break;
438 e89f66ec bellard
    case 1:
439 e89f66ec bellard
        addr -= 0xa0000;
440 e89f66ec bellard
        if (addr >= 0x10000)
441 e89f66ec bellard
            return 0xff;
442 e89f66ec bellard
        break;
443 e89f66ec bellard
    case 2:
444 e89f66ec bellard
        addr -= 0xb0000;
445 e89f66ec bellard
        if (addr >= 0x8000)
446 e89f66ec bellard
            return 0xff;
447 e89f66ec bellard
        break;
448 e89f66ec bellard
    default:
449 e89f66ec bellard
    case 3:
450 e89f66ec bellard
        addr -= 0xb8000;
451 e89f66ec bellard
        break;
452 e89f66ec bellard
    }
453 e89f66ec bellard
    
454 e89f66ec bellard
    if (s->sr[4] & 0x08) {
455 e89f66ec bellard
        /* chain 4 mode : simplest access */
456 e89f66ec bellard
        ret = s->vram_ptr[addr];
457 e89f66ec bellard
    } else if (s->gr[5] & 0x10) {
458 e89f66ec bellard
        /* odd/even mode (aka text mode mapping) */
459 e89f66ec bellard
        plane = (s->gr[4] & 2) | (addr & 1);
460 e89f66ec bellard
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
461 e89f66ec bellard
    } else {
462 e89f66ec bellard
        /* standard VGA latched access */
463 e89f66ec bellard
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
464 e89f66ec bellard
465 e89f66ec bellard
        if (!(s->gr[5] & 0x08)) {
466 e89f66ec bellard
            /* read mode 0 */
467 e89f66ec bellard
            plane = s->gr[4];
468 e89f66ec bellard
#ifdef WORD_BIGENDIAN
469 e89f66ec bellard
            ret = (s->latch >> (24 - (plane * 8))) & 0xff;
470 e89f66ec bellard
#else
471 e89f66ec bellard
            ret = (s->latch >> (plane * 8)) & 0xff;
472 e89f66ec bellard
#endif
473 e89f66ec bellard
        } else {
474 e89f66ec bellard
            /* read mode 1 */
475 e89f66ec bellard
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
476 e89f66ec bellard
            ret |= ret >> 16;
477 e89f66ec bellard
            ret |= ret >> 8;
478 e89f66ec bellard
            ret = (~ret) & 0xff;
479 e89f66ec bellard
        }
480 e89f66ec bellard
    }
481 e89f66ec bellard
    return ret;
482 e89f66ec bellard
}
483 e89f66ec bellard
484 e89f66ec bellard
static uint32_t vga_mem_readw(uint32_t addr)
485 e89f66ec bellard
{
486 e89f66ec bellard
    uint32_t v;
487 e89f66ec bellard
    v = vga_mem_readb(addr);
488 e89f66ec bellard
    v |= vga_mem_readb(addr + 1) << 8;
489 e89f66ec bellard
    return v;
490 e89f66ec bellard
}
491 e89f66ec bellard
492 e89f66ec bellard
static uint32_t vga_mem_readl(uint32_t addr)
493 e89f66ec bellard
{
494 e89f66ec bellard
    uint32_t v;
495 e89f66ec bellard
    v = vga_mem_readb(addr);
496 e89f66ec bellard
    v |= vga_mem_readb(addr + 1) << 8;
497 e89f66ec bellard
    v |= vga_mem_readb(addr + 2) << 16;
498 e89f66ec bellard
    v |= vga_mem_readb(addr + 3) << 24;
499 e89f66ec bellard
    return v;
500 e89f66ec bellard
}
501 e89f66ec bellard
502 e89f66ec bellard
503 e89f66ec bellard
/* called for accesses between 0xa0000 and 0xc0000 */
504 e89f66ec bellard
void vga_mem_writeb(uint32_t addr, uint32_t val)
505 e89f66ec bellard
{
506 e89f66ec bellard
    VGAState *s = &vga_state;
507 e89f66ec bellard
    int memory_map_mode, plane, write_mode, b, func_select;
508 e89f66ec bellard
    uint32_t write_mask, bit_mask, set_mask;
509 e89f66ec bellard
510 17b0018b bellard
#ifdef DEBUG_VGA_MEM
511 e89f66ec bellard
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
512 e89f66ec bellard
#endif
513 e89f66ec bellard
    /* convert to VGA memory offset */
514 e89f66ec bellard
    memory_map_mode = (s->gr[6] >> 2) & 3;
515 e89f66ec bellard
    switch(memory_map_mode) {
516 e89f66ec bellard
    case 0:
517 e89f66ec bellard
        addr -= 0xa0000;
518 e89f66ec bellard
        break;
519 e89f66ec bellard
    case 1:
520 e89f66ec bellard
        addr -= 0xa0000;
521 e89f66ec bellard
        if (addr >= 0x10000)
522 e89f66ec bellard
            return;
523 e89f66ec bellard
        break;
524 e89f66ec bellard
    case 2:
525 e89f66ec bellard
        addr -= 0xb0000;
526 e89f66ec bellard
        if (addr >= 0x8000)
527 e89f66ec bellard
            return;
528 e89f66ec bellard
        break;
529 e89f66ec bellard
    default:
530 e89f66ec bellard
    case 3:
531 e89f66ec bellard
        addr -= 0xb8000;
532 e89f66ec bellard
        break;
533 e89f66ec bellard
    }
534 e89f66ec bellard
    
535 e89f66ec bellard
    if (s->sr[4] & 0x08) {
536 e89f66ec bellard
        /* chain 4 mode : simplest access */
537 e89f66ec bellard
        plane = addr & 3;
538 e89f66ec bellard
        if (s->sr[2] & (1 << plane)) {
539 e89f66ec bellard
            s->vram_ptr[addr] = val;
540 17b0018b bellard
#ifdef DEBUG_VGA_MEM
541 e89f66ec bellard
            printf("vga: chain4: [0x%x]\n", addr);
542 e89f66ec bellard
#endif
543 e89f66ec bellard
            s->vram_updated[addr >> 12] = 1;
544 e89f66ec bellard
        }
545 e89f66ec bellard
    } else if (s->gr[5] & 0x10) {
546 e89f66ec bellard
        /* odd/even mode (aka text mode mapping) */
547 e89f66ec bellard
        plane = (s->gr[4] & 2) | (addr & 1);
548 e89f66ec bellard
        if (s->sr[2] & (1 << plane)) {
549 e89f66ec bellard
            addr = ((addr & ~1) << 1) | plane;
550 e89f66ec bellard
            s->vram_ptr[addr] = val;
551 17b0018b bellard
#ifdef DEBUG_VGA_MEM
552 e89f66ec bellard
            printf("vga: odd/even: [0x%x]\n", addr);
553 e89f66ec bellard
#endif
554 e89f66ec bellard
            s->vram_updated[addr >> 12] = 1;
555 e89f66ec bellard
        }
556 e89f66ec bellard
    } else {
557 e89f66ec bellard
        /* standard VGA latched access */
558 e89f66ec bellard
        write_mode = s->gr[5] & 3;
559 e89f66ec bellard
        switch(write_mode) {
560 e89f66ec bellard
        default:
561 e89f66ec bellard
        case 0:
562 e89f66ec bellard
            /* rotate */
563 e89f66ec bellard
            b = s->gr[3] & 7;
564 e89f66ec bellard
            val = ((val >> b) | (val << (8 - b))) & 0xff;
565 e89f66ec bellard
            val |= val << 8;
566 e89f66ec bellard
            val |= val << 16;
567 e89f66ec bellard
568 e89f66ec bellard
            /* apply set/reset mask */
569 e89f66ec bellard
            set_mask = mask16[s->gr[1]];
570 e89f66ec bellard
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
571 e89f66ec bellard
            bit_mask = s->gr[8];
572 e89f66ec bellard
            break;
573 e89f66ec bellard
        case 1:
574 e89f66ec bellard
            val = s->latch;
575 e89f66ec bellard
            goto do_write;
576 e89f66ec bellard
        case 2:
577 e89f66ec bellard
            val = mask16[val & 0x0f];
578 e89f66ec bellard
            bit_mask = s->gr[8];
579 e89f66ec bellard
            break;
580 e89f66ec bellard
        case 3:
581 e89f66ec bellard
            /* rotate */
582 e89f66ec bellard
            b = s->gr[3] & 7;
583 e89f66ec bellard
            val = ((val >> b) | (val << (8 - b)));
584 e89f66ec bellard
585 e89f66ec bellard
            bit_mask = s->gr[8] & val;
586 e89f66ec bellard
            val = mask16[s->gr[0]];
587 e89f66ec bellard
            break;
588 e89f66ec bellard
        }
589 e89f66ec bellard
590 e89f66ec bellard
        /* apply logical operation */
591 e89f66ec bellard
        func_select = s->gr[3] >> 3;
592 e89f66ec bellard
        switch(func_select) {
593 e89f66ec bellard
        case 0:
594 e89f66ec bellard
        default:
595 e89f66ec bellard
            /* nothing to do */
596 e89f66ec bellard
            break;
597 e89f66ec bellard
        case 1:
598 e89f66ec bellard
            /* and */
599 e89f66ec bellard
            val &= s->latch;
600 e89f66ec bellard
            break;
601 e89f66ec bellard
        case 2:
602 e89f66ec bellard
            /* or */
603 e89f66ec bellard
            val |= s->latch;
604 e89f66ec bellard
            break;
605 e89f66ec bellard
        case 3:
606 e89f66ec bellard
            /* xor */
607 e89f66ec bellard
            val ^= s->latch;
608 e89f66ec bellard
            break;
609 e89f66ec bellard
        }
610 e89f66ec bellard
611 e89f66ec bellard
        /* apply bit mask */
612 e89f66ec bellard
        bit_mask |= bit_mask << 8;
613 e89f66ec bellard
        bit_mask |= bit_mask << 16;
614 e89f66ec bellard
        val = (val & bit_mask) | (s->latch & ~bit_mask);
615 e89f66ec bellard
616 e89f66ec bellard
    do_write:
617 e89f66ec bellard
        /* mask data according to sr[2] */
618 e89f66ec bellard
        write_mask = mask16[s->sr[2]];
619 e89f66ec bellard
        ((uint32_t *)s->vram_ptr)[addr] = 
620 e89f66ec bellard
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
621 e89f66ec bellard
            (val & write_mask);
622 17b0018b bellard
#ifdef DEBUG_VGA_MEM
623 e89f66ec bellard
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
624 e89f66ec bellard
                   addr * 4, write_mask, val);
625 e89f66ec bellard
#endif
626 e89f66ec bellard
        s->vram_updated[addr >> 10] = 1;
627 e89f66ec bellard
    }
628 e89f66ec bellard
}
629 e89f66ec bellard
630 e89f66ec bellard
void vga_mem_writew(uint32_t addr, uint32_t val)
631 e89f66ec bellard
{
632 e89f66ec bellard
    vga_mem_writeb(addr, val & 0xff);
633 e89f66ec bellard
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff);
634 e89f66ec bellard
}
635 e89f66ec bellard
636 e89f66ec bellard
void vga_mem_writel(uint32_t addr, uint32_t val)
637 e89f66ec bellard
{
638 e89f66ec bellard
    vga_mem_writeb(addr, val & 0xff);
639 e89f66ec bellard
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff);
640 e89f66ec bellard
    vga_mem_writeb(addr + 2, (val >> 16) & 0xff);
641 e89f66ec bellard
    vga_mem_writeb(addr + 3, (val >> 24) & 0xff);
642 e89f66ec bellard
}
643 e89f66ec bellard
644 e89f66ec bellard
#ifdef WORD_BIGENDIAN
645 e89f66ec bellard
#define BIG 1
646 e89f66ec bellard
#else
647 e89f66ec bellard
#define BIG 0
648 e89f66ec bellard
#endif
649 e89f66ec bellard
650 e89f66ec bellard
#ifdef WORDS_BIGENDIAN
651 e89f66ec bellard
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
652 e89f66ec bellard
#else
653 e89f66ec bellard
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
654 e89f66ec bellard
#endif
655 e89f66ec bellard
656 e89f66ec bellard
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
657 e89f66ec bellard
                             const uint8_t *font_ptr, int h,
658 e89f66ec bellard
                             uint32_t fgcol, uint32_t bgcol);
659 e89f66ec bellard
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
660 e89f66ec bellard
                                  const uint8_t *font_ptr, int h, 
661 e89f66ec bellard
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
662 e89f66ec bellard
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
663 e89f66ec bellard
                                const uint8_t *s, int width);
664 e89f66ec bellard
665 e89f66ec bellard
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
666 e89f66ec bellard
{
667 e89f66ec bellard
    /* XXX: TODO */
668 e89f66ec bellard
    return 0;
669 e89f66ec bellard
}
670 e89f66ec bellard
671 e89f66ec bellard
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
672 e89f66ec bellard
{
673 e89f66ec bellard
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
674 e89f66ec bellard
}
675 e89f66ec bellard
676 e89f66ec bellard
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
677 e89f66ec bellard
{
678 e89f66ec bellard
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
679 e89f66ec bellard
}
680 e89f66ec bellard
681 e89f66ec bellard
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
682 e89f66ec bellard
{
683 e89f66ec bellard
    return (r << 16) | (g << 8) | b;
684 e89f66ec bellard
}
685 e89f66ec bellard
686 e89f66ec bellard
#define DEPTH 8
687 e89f66ec bellard
#include "vga_template.h"
688 e89f66ec bellard
689 e89f66ec bellard
#define DEPTH 15
690 e89f66ec bellard
#include "vga_template.h"
691 e89f66ec bellard
692 e89f66ec bellard
#define DEPTH 16
693 e89f66ec bellard
#include "vga_template.h"
694 e89f66ec bellard
695 e89f66ec bellard
#define DEPTH 32
696 e89f66ec bellard
#include "vga_template.h"
697 e89f66ec bellard
698 e89f66ec bellard
static inline int c6_to_8(int v)
699 e89f66ec bellard
{
700 e89f66ec bellard
    int b;
701 e89f66ec bellard
    v &= 0x3f;
702 e89f66ec bellard
    b = v & 1;
703 e89f66ec bellard
    return (v << 2) | (b << 1) | b;
704 e89f66ec bellard
}
705 e89f66ec bellard
706 17b0018b bellard
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
707 17b0018b bellard
{
708 17b0018b bellard
    unsigned int col;
709 17b0018b bellard
    col = rgb_to_pixel8(r, g, b);
710 17b0018b bellard
    col |= col << 8;
711 17b0018b bellard
    col |= col << 16;
712 17b0018b bellard
    return col;
713 17b0018b bellard
}
714 17b0018b bellard
715 17b0018b bellard
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
716 17b0018b bellard
{
717 17b0018b bellard
    unsigned int col;
718 17b0018b bellard
    col = rgb_to_pixel15(r, g, b);
719 17b0018b bellard
    col |= col << 16;
720 17b0018b bellard
    return col;
721 17b0018b bellard
}
722 17b0018b bellard
723 17b0018b bellard
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
724 17b0018b bellard
{
725 17b0018b bellard
    unsigned int col;
726 17b0018b bellard
    col = rgb_to_pixel16(r, g, b);
727 17b0018b bellard
    col |= col << 16;
728 17b0018b bellard
    return col;
729 17b0018b bellard
}
730 17b0018b bellard
731 17b0018b bellard
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
732 17b0018b bellard
{
733 17b0018b bellard
    unsigned int col;
734 17b0018b bellard
    col = rgb_to_pixel32(r, g, b);
735 17b0018b bellard
    return col;
736 17b0018b bellard
}
737 17b0018b bellard
738 e89f66ec bellard
/* return true if the palette was modified */
739 e89f66ec bellard
static int update_palette16(VGAState *s)
740 e89f66ec bellard
{
741 17b0018b bellard
    int full_update, i;
742 e89f66ec bellard
    uint32_t v, col, *palette;
743 e89f66ec bellard
744 e89f66ec bellard
    full_update = 0;
745 e89f66ec bellard
    palette = s->last_palette;
746 e89f66ec bellard
    for(i = 0; i < 16; i++) {
747 e89f66ec bellard
        v = s->ar[i];
748 e89f66ec bellard
        if (s->ar[0x10] & 0x80)
749 e89f66ec bellard
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
750 e89f66ec bellard
        else
751 e89f66ec bellard
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
752 e89f66ec bellard
        v = v * 3;
753 17b0018b bellard
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
754 17b0018b bellard
                              c6_to_8(s->palette[v + 1]), 
755 17b0018b bellard
                              c6_to_8(s->palette[v + 2]));
756 17b0018b bellard
        if (col != palette[i]) {
757 17b0018b bellard
            full_update = 1;
758 17b0018b bellard
            palette[i] = col;
759 e89f66ec bellard
        }
760 17b0018b bellard
    }
761 17b0018b bellard
    return full_update;
762 17b0018b bellard
}
763 17b0018b bellard
764 17b0018b bellard
/* return true if the palette was modified */
765 17b0018b bellard
static int update_palette256(VGAState *s)
766 17b0018b bellard
{
767 17b0018b bellard
    int full_update, i;
768 17b0018b bellard
    uint32_t v, col, *palette;
769 17b0018b bellard
770 17b0018b bellard
    full_update = 0;
771 17b0018b bellard
    palette = s->last_palette;
772 17b0018b bellard
    v = 0;
773 17b0018b bellard
    for(i = 0; i < 256; i++) {
774 17b0018b bellard
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
775 17b0018b bellard
                              c6_to_8(s->palette[v + 1]), 
776 17b0018b bellard
                              c6_to_8(s->palette[v + 2]));
777 e89f66ec bellard
        if (col != palette[i]) {
778 e89f66ec bellard
            full_update = 1;
779 e89f66ec bellard
            palette[i] = col;
780 e89f66ec bellard
        }
781 17b0018b bellard
        v += 3;
782 e89f66ec bellard
    }
783 e89f66ec bellard
    return full_update;
784 e89f66ec bellard
}
785 e89f66ec bellard
786 e89f66ec bellard
/* update start_addr and line_offset. Return TRUE if modified */
787 e89f66ec bellard
static int update_basic_params(VGAState *s)
788 e89f66ec bellard
{
789 e89f66ec bellard
    int full_update;
790 e89f66ec bellard
    uint32_t start_addr, line_offset, line_compare, v;
791 e89f66ec bellard
    
792 e89f66ec bellard
    full_update = 0;
793 e89f66ec bellard
    /* compute line_offset in bytes */
794 e89f66ec bellard
    v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
795 e89f66ec bellard
    if (v == 0)
796 e89f66ec bellard
        v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
797 e89f66ec bellard
    line_offset = s->cr[0x13] | (v << 8);
798 e89f66ec bellard
    line_offset <<= 3;
799 39cf7803 bellard
800 e89f66ec bellard
    /* starting address */
801 e89f66ec bellard
    start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
802 e89f66ec bellard
    start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
803 e89f66ec bellard
804 e89f66ec bellard
    /* line compare */
805 e89f66ec bellard
    line_compare = s->cr[0x18] | 
806 e89f66ec bellard
        ((s->cr[0x07] & 0x10) << 4) |
807 e89f66ec bellard
        ((s->cr[0x09] & 0x40) << 3);
808 e89f66ec bellard
809 e89f66ec bellard
    if (line_offset != s->line_offset ||
810 e89f66ec bellard
        start_addr != s->start_addr ||
811 e89f66ec bellard
        line_compare != s->line_compare) {
812 e89f66ec bellard
        s->line_offset = line_offset;
813 e89f66ec bellard
        s->start_addr = start_addr;
814 e89f66ec bellard
        s->line_compare = line_compare;
815 e89f66ec bellard
        full_update = 1;
816 e89f66ec bellard
    }
817 e89f66ec bellard
    return full_update;
818 e89f66ec bellard
}
819 e89f66ec bellard
820 e89f66ec bellard
static inline int get_depth_index(int depth)
821 e89f66ec bellard
{
822 e89f66ec bellard
    switch(depth) {
823 e89f66ec bellard
    default:
824 e89f66ec bellard
    case 8:
825 e89f66ec bellard
        return 0;
826 e89f66ec bellard
    case 15:
827 e89f66ec bellard
        return 1;
828 e89f66ec bellard
    case 16:
829 e89f66ec bellard
        return 2;
830 e89f66ec bellard
    case 32:
831 e89f66ec bellard
        return 3;
832 e89f66ec bellard
    }
833 e89f66ec bellard
}
834 e89f66ec bellard
835 e89f66ec bellard
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
836 e89f66ec bellard
    vga_draw_glyph8_8,
837 e89f66ec bellard
    vga_draw_glyph8_16,
838 e89f66ec bellard
    vga_draw_glyph8_16,
839 e89f66ec bellard
    vga_draw_glyph8_32,
840 e89f66ec bellard
};
841 e89f66ec bellard
842 17b0018b bellard
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
843 17b0018b bellard
    vga_draw_glyph16_8,
844 17b0018b bellard
    vga_draw_glyph16_16,
845 17b0018b bellard
    vga_draw_glyph16_16,
846 17b0018b bellard
    vga_draw_glyph16_32,
847 17b0018b bellard
};
848 17b0018b bellard
849 e89f66ec bellard
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
850 e89f66ec bellard
    vga_draw_glyph9_8,
851 e89f66ec bellard
    vga_draw_glyph9_16,
852 e89f66ec bellard
    vga_draw_glyph9_16,
853 e89f66ec bellard
    vga_draw_glyph9_32,
854 e89f66ec bellard
};
855 e89f66ec bellard
    
856 e89f66ec bellard
static const uint8_t cursor_glyph[32 * 4] = {
857 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
858 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
859 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
860 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
861 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
862 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
863 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
864 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
865 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
866 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
867 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
868 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
869 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
870 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
871 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
872 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
873 e89f66ec bellard
};    
874 e89f66ec bellard
875 e89f66ec bellard
/* 
876 e89f66ec bellard
 * Text mode update 
877 e89f66ec bellard
 * Missing:
878 e89f66ec bellard
 * - double scan
879 e89f66ec bellard
 * - double width 
880 e89f66ec bellard
 * - underline
881 e89f66ec bellard
 * - flashing
882 e89f66ec bellard
 */
883 e89f66ec bellard
static void vga_draw_text(VGAState *s, int full_update)
884 e89f66ec bellard
{
885 e89f66ec bellard
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
886 e89f66ec bellard
    int cx_min, cx_max, linesize, x_incr;
887 e89f66ec bellard
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
888 e89f66ec bellard
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
889 e89f66ec bellard
    const uint8_t *font_ptr, *font_base[2];
890 e89f66ec bellard
    int dup9, line_offset, depth_index;
891 e89f66ec bellard
    uint32_t *palette;
892 e89f66ec bellard
    uint32_t *ch_attr_ptr;
893 e89f66ec bellard
    vga_draw_glyph8_func *vga_draw_glyph8;
894 e89f66ec bellard
    vga_draw_glyph9_func *vga_draw_glyph9;
895 e89f66ec bellard
896 e89f66ec bellard
    full_update |= update_palette16(s);
897 e89f66ec bellard
    palette = s->last_palette;
898 e89f66ec bellard
    
899 e89f66ec bellard
    /* compute font data address (in plane 2) */
900 e89f66ec bellard
    v = s->sr[3];
901 e89f66ec bellard
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
902 e89f66ec bellard
    if (offset != s->font_offsets[0]) {
903 e89f66ec bellard
        s->font_offsets[0] = offset;
904 e89f66ec bellard
        full_update = 1;
905 e89f66ec bellard
    }
906 e89f66ec bellard
    font_base[0] = s->vram_ptr + offset;
907 e89f66ec bellard
908 e89f66ec bellard
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
909 e89f66ec bellard
    font_base[1] = s->vram_ptr + offset;
910 e89f66ec bellard
    if (offset != s->font_offsets[1]) {
911 e89f66ec bellard
        s->font_offsets[1] = offset;
912 e89f66ec bellard
        full_update = 1;
913 e89f66ec bellard
    }
914 e89f66ec bellard
915 e89f66ec bellard
    full_update |= update_basic_params(s);
916 e89f66ec bellard
917 e89f66ec bellard
    line_offset = s->line_offset;
918 e89f66ec bellard
    s1 = s->vram_ptr + (s->start_addr * 4);
919 e89f66ec bellard
920 e89f66ec bellard
    /* total width & height */
921 e89f66ec bellard
    cheight = (s->cr[9] & 0x1f) + 1;
922 e89f66ec bellard
    cw = 8;
923 e89f66ec bellard
    if (s->sr[1] & 0x01)
924 e89f66ec bellard
        cw = 9;
925 17b0018b bellard
    if (s->sr[1] & 0x08)
926 17b0018b bellard
        cw = 16; /* NOTE: no 18 pixel wide */
927 e89f66ec bellard
    x_incr = cw * ((s->ds->depth + 7) >> 3);
928 e89f66ec bellard
    width = (s->cr[0x01] + 1);
929 17b0018b bellard
    if (s->cr[0x06] == 100) {
930 17b0018b bellard
        /* ugly hack for CGA 160x100x16 - explain me the logic */
931 17b0018b bellard
        height = 100;
932 17b0018b bellard
    } else {
933 17b0018b bellard
        height = s->cr[0x12] | 
934 17b0018b bellard
            ((s->cr[0x07] & 0x02) << 7) | 
935 17b0018b bellard
            ((s->cr[0x07] & 0x40) << 3);
936 17b0018b bellard
        height = (height + 1) / cheight;
937 17b0018b bellard
    }
938 e89f66ec bellard
    if (width != s->last_width || height != s->last_height ||
939 e89f66ec bellard
        cw != s->last_cw || cw != s->last_cw) {
940 e89f66ec bellard
        dpy_resize(s->ds, width * cw, height * cheight);
941 e89f66ec bellard
        s->last_width = width;
942 e89f66ec bellard
        s->last_height = height;
943 e89f66ec bellard
        s->last_ch = cheight;
944 e89f66ec bellard
        s->last_cw = cw;
945 e89f66ec bellard
        full_update = 1;
946 e89f66ec bellard
    }
947 e89f66ec bellard
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
948 e89f66ec bellard
    if (cursor_offset != s->cursor_offset ||
949 e89f66ec bellard
        s->cr[0xa] != s->cursor_start ||
950 e89f66ec bellard
        s->cr[0xb] != s->cursor_end) {
951 e89f66ec bellard
      /* if the cursor position changed, we update the old and new
952 e89f66ec bellard
         chars */
953 e89f66ec bellard
        if (s->cursor_offset < CH_ATTR_SIZE)
954 e89f66ec bellard
            s->last_ch_attr[s->cursor_offset] = -1;
955 e89f66ec bellard
        if (cursor_offset < CH_ATTR_SIZE)
956 e89f66ec bellard
            s->last_ch_attr[cursor_offset] = -1;
957 e89f66ec bellard
        s->cursor_offset = cursor_offset;
958 e89f66ec bellard
        s->cursor_start = s->cr[0xa];
959 e89f66ec bellard
        s->cursor_end = s->cr[0xb];
960 e89f66ec bellard
    }
961 39cf7803 bellard
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
962 e89f66ec bellard
    
963 e89f66ec bellard
    depth_index = get_depth_index(s->ds->depth);
964 17b0018b bellard
    if (cw == 16)
965 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
966 17b0018b bellard
    else
967 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
968 e89f66ec bellard
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
969 e89f66ec bellard
    
970 e89f66ec bellard
    dest = s->ds->data;
971 e89f66ec bellard
    linesize = s->ds->linesize;
972 e89f66ec bellard
    ch_attr_ptr = s->last_ch_attr;
973 e89f66ec bellard
    for(cy = 0; cy < height; cy++) {
974 e89f66ec bellard
        d1 = dest;
975 e89f66ec bellard
        src = s1;
976 e89f66ec bellard
        cx_min = width;
977 e89f66ec bellard
        cx_max = -1;
978 e89f66ec bellard
        for(cx = 0; cx < width; cx++) {
979 e89f66ec bellard
            ch_attr = *(uint16_t *)src;
980 e89f66ec bellard
            if (full_update || ch_attr != *ch_attr_ptr) {
981 e89f66ec bellard
                if (cx < cx_min)
982 e89f66ec bellard
                    cx_min = cx;
983 e89f66ec bellard
                if (cx > cx_max)
984 e89f66ec bellard
                    cx_max = cx;
985 e89f66ec bellard
                *ch_attr_ptr = ch_attr;
986 e89f66ec bellard
#ifdef WORDS_BIGENDIAN
987 e89f66ec bellard
                ch = ch_attr >> 8;
988 e89f66ec bellard
                cattr = ch_attr & 0xff;
989 e89f66ec bellard
#else
990 e89f66ec bellard
                ch = ch_attr & 0xff;
991 e89f66ec bellard
                cattr = ch_attr >> 8;
992 e89f66ec bellard
#endif
993 e89f66ec bellard
                font_ptr = font_base[(cattr >> 3) & 1];
994 e89f66ec bellard
                font_ptr += 32 * 4 * ch;
995 e89f66ec bellard
                bgcol = palette[cattr >> 4];
996 e89f66ec bellard
                fgcol = palette[cattr & 0x0f];
997 17b0018b bellard
                if (cw != 9) {
998 e89f66ec bellard
                    vga_draw_glyph8(d1, linesize, 
999 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol);
1000 e89f66ec bellard
                } else {
1001 e89f66ec bellard
                    dup9 = 0;
1002 e89f66ec bellard
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1003 e89f66ec bellard
                        dup9 = 1;
1004 e89f66ec bellard
                    vga_draw_glyph9(d1, linesize, 
1005 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1006 e89f66ec bellard
                }
1007 e89f66ec bellard
                if (src == cursor_ptr &&
1008 e89f66ec bellard
                    !(s->cr[0x0a] & 0x20)) {
1009 e89f66ec bellard
                    int line_start, line_last, h;
1010 e89f66ec bellard
                    /* draw the cursor */
1011 e89f66ec bellard
                    line_start = s->cr[0x0a] & 0x1f;
1012 e89f66ec bellard
                    line_last = s->cr[0x0b] & 0x1f;
1013 e89f66ec bellard
                    /* XXX: check that */
1014 e89f66ec bellard
                    if (line_last > cheight - 1)
1015 e89f66ec bellard
                        line_last = cheight - 1;
1016 e89f66ec bellard
                    if (line_last >= line_start && line_start < cheight) {
1017 e89f66ec bellard
                        h = line_last - line_start + 1;
1018 e89f66ec bellard
                        d = d1 + linesize * line_start;
1019 17b0018b bellard
                        if (cw != 9) {
1020 e89f66ec bellard
                            vga_draw_glyph8(d, linesize, 
1021 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol);
1022 e89f66ec bellard
                        } else {
1023 e89f66ec bellard
                            vga_draw_glyph9(d, linesize, 
1024 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol, 1);
1025 e89f66ec bellard
                        }
1026 e89f66ec bellard
                    }
1027 e89f66ec bellard
                }
1028 e89f66ec bellard
            }
1029 e89f66ec bellard
            d1 += x_incr;
1030 e89f66ec bellard
            src += 4;
1031 e89f66ec bellard
            ch_attr_ptr++;
1032 e89f66ec bellard
        }
1033 e89f66ec bellard
        if (cx_max != -1) {
1034 e89f66ec bellard
            dpy_update(s->ds, cx_min * cw, cy * cheight, 
1035 e89f66ec bellard
                       (cx_max - cx_min + 1) * cw, cheight);
1036 e89f66ec bellard
        }
1037 e89f66ec bellard
        dest += linesize * cheight;
1038 e89f66ec bellard
        s1 += line_offset;
1039 e89f66ec bellard
    }
1040 e89f66ec bellard
}
1041 e89f66ec bellard
1042 17b0018b bellard
enum {
1043 17b0018b bellard
    VGA_DRAW_LINE2,
1044 17b0018b bellard
    VGA_DRAW_LINE2D2,
1045 17b0018b bellard
    VGA_DRAW_LINE4,
1046 17b0018b bellard
    VGA_DRAW_LINE4D2,
1047 17b0018b bellard
    VGA_DRAW_LINE8D2,
1048 17b0018b bellard
    VGA_DRAW_LINE8,
1049 17b0018b bellard
    VGA_DRAW_LINE15,
1050 17b0018b bellard
    VGA_DRAW_LINE16,
1051 17b0018b bellard
    VGA_DRAW_LINE32,
1052 17b0018b bellard
    VGA_DRAW_LINE_NB,
1053 17b0018b bellard
};
1054 17b0018b bellard
1055 17b0018b bellard
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1056 e89f66ec bellard
    vga_draw_line2_8,
1057 e89f66ec bellard
    vga_draw_line2_16,
1058 e89f66ec bellard
    vga_draw_line2_16,
1059 e89f66ec bellard
    vga_draw_line2_32,
1060 e89f66ec bellard
1061 17b0018b bellard
    vga_draw_line2d2_8,
1062 17b0018b bellard
    vga_draw_line2d2_16,
1063 17b0018b bellard
    vga_draw_line2d2_16,
1064 17b0018b bellard
    vga_draw_line2d2_32,
1065 17b0018b bellard
1066 e89f66ec bellard
    vga_draw_line4_8,
1067 e89f66ec bellard
    vga_draw_line4_16,
1068 e89f66ec bellard
    vga_draw_line4_16,
1069 e89f66ec bellard
    vga_draw_line4_32,
1070 e89f66ec bellard
1071 17b0018b bellard
    vga_draw_line4d2_8,
1072 17b0018b bellard
    vga_draw_line4d2_16,
1073 17b0018b bellard
    vga_draw_line4d2_16,
1074 17b0018b bellard
    vga_draw_line4d2_32,
1075 17b0018b bellard
1076 17b0018b bellard
    vga_draw_line8d2_8,
1077 17b0018b bellard
    vga_draw_line8d2_16,
1078 17b0018b bellard
    vga_draw_line8d2_16,
1079 17b0018b bellard
    vga_draw_line8d2_32,
1080 17b0018b bellard
1081 e89f66ec bellard
    vga_draw_line8_8,
1082 e89f66ec bellard
    vga_draw_line8_16,
1083 e89f66ec bellard
    vga_draw_line8_16,
1084 e89f66ec bellard
    vga_draw_line8_32,
1085 e89f66ec bellard
1086 e89f66ec bellard
    vga_draw_line15_8,
1087 e89f66ec bellard
    vga_draw_line15_15,
1088 e89f66ec bellard
    vga_draw_line15_16,
1089 e89f66ec bellard
    vga_draw_line15_32,
1090 e89f66ec bellard
1091 e89f66ec bellard
    vga_draw_line16_8,
1092 e89f66ec bellard
    vga_draw_line16_15,
1093 e89f66ec bellard
    vga_draw_line16_16,
1094 e89f66ec bellard
    vga_draw_line16_32,
1095 e89f66ec bellard
1096 e89f66ec bellard
    vga_draw_line32_8,
1097 e89f66ec bellard
    vga_draw_line32_15,
1098 e89f66ec bellard
    vga_draw_line32_16,
1099 e89f66ec bellard
    vga_draw_line32_32,
1100 e89f66ec bellard
};
1101 e89f66ec bellard
1102 e89f66ec bellard
/* 
1103 e89f66ec bellard
 * graphic modes
1104 e89f66ec bellard
 * Missing:
1105 e89f66ec bellard
 * - double scan
1106 e89f66ec bellard
 * - double width 
1107 e89f66ec bellard
 */
1108 e89f66ec bellard
static void vga_draw_graphic(VGAState *s, int full_update)
1109 e89f66ec bellard
{
1110 17b0018b bellard
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1111 39cf7803 bellard
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1112 17b0018b bellard
    int disp_width;
1113 e89f66ec bellard
    uint8_t *d;
1114 39cf7803 bellard
    uint32_t v, addr1, addr;
1115 e89f66ec bellard
    vga_draw_line_func *vga_draw_line;
1116 17b0018b bellard
    
1117 e89f66ec bellard
    full_update |= update_basic_params(s);
1118 e89f66ec bellard
1119 39cf7803 bellard
    width = (s->cr[0x01] + 1) * 8;
1120 e89f66ec bellard
    height = s->cr[0x12] | 
1121 e89f66ec bellard
        ((s->cr[0x07] & 0x02) << 7) | 
1122 e89f66ec bellard
        ((s->cr[0x07] & 0x40) << 3);
1123 e89f66ec bellard
    height = (height + 1);
1124 17b0018b bellard
    disp_width = width;
1125 17b0018b bellard
    
1126 e89f66ec bellard
    shift_control = (s->gr[0x05] >> 5) & 3;
1127 9da8ba18 bellard
    if (shift_control > 1)
1128 9da8ba18 bellard
        double_scan = ((s->cr[0x09] & 0x1f) != 0);
1129 9da8ba18 bellard
    else
1130 9da8ba18 bellard
        double_scan = (s->cr[0x09] & 0x80);
1131 17b0018b bellard
    if (shift_control != s->shift_control ||
1132 17b0018b bellard
        double_scan != s->double_scan) {
1133 e89f66ec bellard
        full_update = 1;
1134 e89f66ec bellard
        s->shift_control = shift_control;
1135 17b0018b bellard
        s->double_scan = double_scan;
1136 e89f66ec bellard
    }
1137 e89f66ec bellard
    
1138 17b0018b bellard
    if (shift_control == 0) {
1139 17b0018b bellard
        full_update |= update_palette16(s);
1140 17b0018b bellard
        if (s->sr[0x01] & 8) {
1141 17b0018b bellard
            v = VGA_DRAW_LINE4D2;
1142 17b0018b bellard
            disp_width <<= 1;
1143 17b0018b bellard
        } else {
1144 17b0018b bellard
            v = VGA_DRAW_LINE4;
1145 17b0018b bellard
        }
1146 17b0018b bellard
    } else if (shift_control == 1) {
1147 17b0018b bellard
        full_update |= update_palette16(s);
1148 17b0018b bellard
        if (s->sr[0x01] & 8) {
1149 17b0018b bellard
            v = VGA_DRAW_LINE2D2;
1150 17b0018b bellard
            disp_width <<= 1;
1151 17b0018b bellard
        } else {
1152 17b0018b bellard
            v = VGA_DRAW_LINE2;
1153 17b0018b bellard
        }
1154 17b0018b bellard
    } else {
1155 17b0018b bellard
        full_update |= update_palette256(s);
1156 17b0018b bellard
        v = VGA_DRAW_LINE8D2;
1157 17b0018b bellard
    }
1158 e89f66ec bellard
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1159 17b0018b bellard
1160 17b0018b bellard
    if (disp_width != s->last_width ||
1161 17b0018b bellard
        height != s->last_height) {
1162 17b0018b bellard
        dpy_resize(s->ds, disp_width, height);
1163 17b0018b bellard
        s->last_width = disp_width;
1164 17b0018b bellard
        s->last_height = height;
1165 17b0018b bellard
        full_update = 1;
1166 17b0018b bellard
    }
1167 17b0018b bellard
1168 e89f66ec bellard
    line_offset = s->line_offset;
1169 17b0018b bellard
#if 0
1170 17b0018b bellard
    printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1171 17b0018b bellard
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1172 17b0018b bellard
#endif
1173 e89f66ec bellard
    addr1 = (s->start_addr * 4);
1174 39cf7803 bellard
    bwidth = width * 4;
1175 39cf7803 bellard
    y_start = -1;
1176 e89f66ec bellard
    page_min = 0x7fffffff;
1177 e89f66ec bellard
    page_max = -1;
1178 e89f66ec bellard
    d = s->ds->data;
1179 e89f66ec bellard
    linesize = s->ds->linesize;
1180 17b0018b bellard
    y1 = 0;
1181 e89f66ec bellard
    for(y = 0; y < height; y++) {
1182 e89f66ec bellard
        addr = addr1;
1183 39cf7803 bellard
        if (!(s->cr[0x17] & 1)) {
1184 17b0018b bellard
            int shift;
1185 e89f66ec bellard
            /* CGA compatibility handling */
1186 17b0018b bellard
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1187 17b0018b bellard
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1188 e89f66ec bellard
        }
1189 39cf7803 bellard
        if (!(s->cr[0x17] & 2)) {
1190 17b0018b bellard
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1191 e89f66ec bellard
        }
1192 e89f66ec bellard
        page0 = addr >> 12;
1193 39cf7803 bellard
        page1 = (addr + bwidth - 1) >> 12;
1194 e89f66ec bellard
        update = full_update | s->vram_updated[page0] | s->vram_updated[page1];
1195 39cf7803 bellard
        if ((page1 - page0) > 1) {
1196 39cf7803 bellard
            /* if wide line, can use another page */
1197 39cf7803 bellard
            update |= s->vram_updated[page0 + 1];
1198 39cf7803 bellard
        }
1199 e89f66ec bellard
        if (update) {
1200 39cf7803 bellard
            if (y_start < 0)
1201 39cf7803 bellard
                y_start = y;
1202 e89f66ec bellard
            if (page0 < page_min)
1203 e89f66ec bellard
                page_min = page0;
1204 e89f66ec bellard
            if (page1 > page_max)
1205 e89f66ec bellard
                page_max = page1;
1206 e89f66ec bellard
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1207 39cf7803 bellard
        } else {
1208 39cf7803 bellard
            if (y_start >= 0) {
1209 39cf7803 bellard
                /* flush to display */
1210 39cf7803 bellard
                dpy_update(s->ds, 0, y_start, 
1211 17b0018b bellard
                           disp_width, y - y_start);
1212 39cf7803 bellard
                y_start = -1;
1213 39cf7803 bellard
            }
1214 e89f66ec bellard
        }
1215 17b0018b bellard
        if (!double_scan || (y & 1) != 0) {
1216 17b0018b bellard
            if (y1 == s->line_compare) {
1217 17b0018b bellard
                addr1 = 0;
1218 17b0018b bellard
            } else {
1219 17b0018b bellard
                mask = (s->cr[0x17] & 3) ^ 3;
1220 17b0018b bellard
                if ((y1 & mask) == mask)
1221 17b0018b bellard
                    addr1 += line_offset; 
1222 17b0018b bellard
            }
1223 17b0018b bellard
            y1++;
1224 e89f66ec bellard
        }
1225 e89f66ec bellard
        d += linesize;
1226 e89f66ec bellard
    }
1227 39cf7803 bellard
    if (y_start >= 0) {
1228 39cf7803 bellard
        /* flush to display */
1229 39cf7803 bellard
        dpy_update(s->ds, 0, y_start, 
1230 17b0018b bellard
                   disp_width, y - y_start);
1231 39cf7803 bellard
    }
1232 e89f66ec bellard
    /* reset modified pages */
1233 e89f66ec bellard
    if (page_max != -1) {
1234 e89f66ec bellard
        memset(s->vram_updated + page_min, 0, page_max - page_min + 1);
1235 e89f66ec bellard
    }
1236 e89f66ec bellard
}
1237 e89f66ec bellard
1238 e89f66ec bellard
/* draw text terminal (very limited, just for simple boot debug
1239 e89f66ec bellard
   messages) */
1240 e89f66ec bellard
static int last_cursor_pos;
1241 e89f66ec bellard
1242 e89f66ec bellard
void vga_draw_dumb(VGAState *s)
1243 e89f66ec bellard
{
1244 e89f66ec bellard
    int c, i, cursor_pos, eol;
1245 e89f66ec bellard
1246 e89f66ec bellard
    cursor_pos = s->cr[0x0f] | (s->cr[0x0e] << 8);
1247 e89f66ec bellard
    eol = 0;
1248 e89f66ec bellard
    for(i = last_cursor_pos; i < cursor_pos; i++) {
1249 e89f66ec bellard
        /* XXX: should use vga RAM */
1250 e89f66ec bellard
        c = phys_ram_base[0xb8000 + (i) * 2];
1251 e89f66ec bellard
        if (c >= ' ') {
1252 e89f66ec bellard
            putchar(c);
1253 e89f66ec bellard
            eol = 0;
1254 e89f66ec bellard
        } else {
1255 e89f66ec bellard
            if (!eol)
1256 e89f66ec bellard
                putchar('\n');
1257 e89f66ec bellard
            eol = 1;
1258 e89f66ec bellard
        }
1259 e89f66ec bellard
    }
1260 e89f66ec bellard
    fflush(stdout);
1261 e89f66ec bellard
    last_cursor_pos = cursor_pos;
1262 e89f66ec bellard
}
1263 e89f66ec bellard
1264 e89f66ec bellard
void vga_update_display(void)
1265 e89f66ec bellard
{
1266 e89f66ec bellard
    VGAState *s = &vga_state;
1267 e89f66ec bellard
    int full_update, graphic_mode;
1268 e89f66ec bellard
1269 e89f66ec bellard
    if (s->ds->depth == 0) {
1270 e89f66ec bellard
        vga_draw_dumb(s);
1271 e89f66ec bellard
    } else {
1272 e89f66ec bellard
        full_update = 0;
1273 e89f66ec bellard
        graphic_mode = s->gr[6] & 1;
1274 e89f66ec bellard
        if (graphic_mode != s->graphic_mode) {
1275 e89f66ec bellard
            s->graphic_mode = graphic_mode;
1276 e89f66ec bellard
            full_update = 1;
1277 e89f66ec bellard
        }
1278 e89f66ec bellard
        if (graphic_mode)
1279 e89f66ec bellard
            vga_draw_graphic(s, full_update);
1280 e89f66ec bellard
        else
1281 e89f66ec bellard
            vga_draw_text(s, full_update);
1282 e89f66ec bellard
    }
1283 e89f66ec bellard
}
1284 e89f66ec bellard
1285 e89f66ec bellard
void vga_reset(VGAState *s)
1286 e89f66ec bellard
{
1287 e89f66ec bellard
    memset(s, 0, sizeof(VGAState));
1288 e89f66ec bellard
    /* chip ID for 8c968 */
1289 e89f66ec bellard
    s->cr[0x2d] = 0x88;
1290 e89f66ec bellard
    s->cr[0x2e] = 0xb0;
1291 e89f66ec bellard
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1292 e89f66ec bellard
    s->cr[0x30] = 0xe1;
1293 e89f66ec bellard
    s->graphic_mode = -1; /* force full update */
1294 e89f66ec bellard
}
1295 e89f66ec bellard
1296 e89f66ec bellard
CPUReadMemoryFunc *vga_mem_read[3] = {
1297 e89f66ec bellard
    vga_mem_readb,
1298 e89f66ec bellard
    vga_mem_readw,
1299 e89f66ec bellard
    vga_mem_readl,
1300 e89f66ec bellard
};
1301 e89f66ec bellard
1302 e89f66ec bellard
CPUWriteMemoryFunc *vga_mem_write[3] = {
1303 e89f66ec bellard
    vga_mem_writeb,
1304 e89f66ec bellard
    vga_mem_writew,
1305 e89f66ec bellard
    vga_mem_writel,
1306 e89f66ec bellard
};
1307 e89f66ec bellard
1308 e89f66ec bellard
int vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
1309 e89f66ec bellard
             unsigned long vga_ram_offset, int vga_ram_size)
1310 e89f66ec bellard
{
1311 e89f66ec bellard
    VGAState *s = &vga_state;
1312 17b0018b bellard
    int i, j, v, b;
1313 e89f66ec bellard
1314 e89f66ec bellard
    for(i = 0;i < 256; i++) {
1315 e89f66ec bellard
        v = 0;
1316 e89f66ec bellard
        for(j = 0; j < 8; j++) {
1317 e89f66ec bellard
            v |= ((i >> j) & 1) << (j * 4);
1318 e89f66ec bellard
        }
1319 e89f66ec bellard
        expand4[i] = v;
1320 e89f66ec bellard
1321 e89f66ec bellard
        v = 0;
1322 e89f66ec bellard
        for(j = 0; j < 4; j++) {
1323 e89f66ec bellard
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1324 e89f66ec bellard
        }
1325 e89f66ec bellard
        expand2[i] = v;
1326 e89f66ec bellard
    }
1327 17b0018b bellard
    for(i = 0; i < 16; i++) {
1328 17b0018b bellard
        v = 0;
1329 17b0018b bellard
        for(j = 0; j < 4; j++) {
1330 17b0018b bellard
            b = ((i >> j) & 1);
1331 17b0018b bellard
            v |= b << (2 * j);
1332 17b0018b bellard
            v |= b << (2 * j + 1);
1333 17b0018b bellard
        }
1334 17b0018b bellard
        expand4to8[i] = v;
1335 17b0018b bellard
    }
1336 e89f66ec bellard
1337 e89f66ec bellard
    vga_reset(s);
1338 e89f66ec bellard
1339 17b0018b bellard
    switch(ds->depth) {
1340 17b0018b bellard
    case 8:
1341 17b0018b bellard
        s->rgb_to_pixel = rgb_to_pixel8_dup;
1342 17b0018b bellard
        break;
1343 17b0018b bellard
    case 15:
1344 17b0018b bellard
        s->rgb_to_pixel = rgb_to_pixel15_dup;
1345 17b0018b bellard
        break;
1346 17b0018b bellard
    default:
1347 17b0018b bellard
    case 16:
1348 17b0018b bellard
        s->rgb_to_pixel = rgb_to_pixel16_dup;
1349 17b0018b bellard
        break;
1350 17b0018b bellard
    case 32:
1351 17b0018b bellard
        s->rgb_to_pixel = rgb_to_pixel32_dup;
1352 17b0018b bellard
        break;
1353 17b0018b bellard
    }
1354 17b0018b bellard
1355 e89f66ec bellard
    s->vram_ptr = vga_ram_base;
1356 e89f66ec bellard
    s->vram_offset = vga_ram_offset;
1357 e89f66ec bellard
    s->vram_size = vga_ram_size;
1358 e89f66ec bellard
    s->ds = ds;
1359 e89f66ec bellard
1360 e89f66ec bellard
    register_ioport_write(0x3c0, 16, vga_ioport_write, 1);
1361 e89f66ec bellard
1362 e89f66ec bellard
    register_ioport_write(0x3b4, 2, vga_ioport_write, 1);
1363 e89f66ec bellard
    register_ioport_write(0x3d4, 2, vga_ioport_write, 1);
1364 e89f66ec bellard
    register_ioport_write(0x3ba, 1, vga_ioport_write, 1);
1365 e89f66ec bellard
    register_ioport_write(0x3da, 1, vga_ioport_write, 1);
1366 e89f66ec bellard
1367 e89f66ec bellard
    register_ioport_read(0x3c0, 16, vga_ioport_read, 1);
1368 e89f66ec bellard
1369 e89f66ec bellard
    register_ioport_read(0x3b4, 2, vga_ioport_read, 1);
1370 e89f66ec bellard
    register_ioport_read(0x3d4, 2, vga_ioport_read, 1);
1371 e89f66ec bellard
    register_ioport_read(0x3ba, 1, vga_ioport_read, 1);
1372 e89f66ec bellard
    register_ioport_read(0x3da, 1, vga_ioport_read, 1);
1373 e89f66ec bellard
1374 e89f66ec bellard
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1375 e89f66ec bellard
    cpu_register_physical_memory(0xa0000, 0x20000, vga_io_memory);
1376 e89f66ec bellard
    return 0;
1377 e89f66ec bellard
}