Statistics
| Branch: | Revision:

root / hw / vga.c @ 17b0018b

History | View | Annotate | Download (36.7 kB)

1
/*
2
 * QEMU VGA Emulator. An S3 86c968 is emulated
3
 * 
4
 * Copyright (c) 2003 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <getopt.h>
29
#include <inttypes.h>
30
#include <unistd.h>
31
#include <sys/mman.h>
32
#include <fcntl.h>
33
#include <signal.h>
34
#include <time.h>
35
#include <sys/time.h>
36
#include <malloc.h>
37
#include <termios.h>
38
#include <sys/poll.h>
39
#include <errno.h>
40
#include <sys/wait.h>
41
#include <netinet/in.h>
42

    
43
#include "cpu-i386.h"
44
#include "exec.h"
45

    
46
#include "vl.h"
47

    
48
#define NO_THUNK_TYPE_SIZE
49
#include "thunk.h"
50

    
51
//#define DEBUG_VGA
52
//#define DEBUG_VGA_MEM
53

    
54
#define MSR_COLOR_EMULATION 0x01
55
#define MSR_PAGE_SELECT     0x20
56

    
57
#define ST01_V_RETRACE      0x08
58
#define ST01_DISP_ENABLE    0x01
59

    
60
typedef struct VGAState {
61
    uint8_t *vram_ptr;
62
    unsigned long vram_offset;
63
    unsigned int vram_size;
64
    uint32_t latch;
65
    uint8_t sr_index;
66
    uint8_t sr[8];
67
    uint8_t gr_index;
68
    uint8_t gr[16];
69
    uint8_t ar_index;
70
    uint8_t ar[21];
71
    int ar_flip_flop;
72
    uint8_t cr_index;
73
    uint8_t cr[256]; /* CRT registers */
74
    uint8_t msr; /* Misc Output Register */
75
    uint8_t fcr; /* Feature Control Register */
76
    uint8_t st00; /* status 0 */
77
    uint8_t st01; /* status 1 */
78
    uint8_t dac_state;
79
    uint8_t dac_sub_index;
80
    uint8_t dac_read_index;
81
    uint8_t dac_write_index;
82
    uint8_t dac_cache[3]; /* used when writing */
83
    uint8_t palette[768];
84

    
85
    /* display refresh support */
86
    DisplayState *ds;
87
    uint32_t font_offsets[2];
88
    int graphic_mode;
89
    uint8_t shift_control;
90
    uint8_t double_scan;
91
    uint32_t line_offset;
92
    uint32_t line_compare;
93
    uint32_t start_addr;
94
    uint8_t last_cw, last_ch;
95
    uint32_t last_width, last_height;
96
    uint8_t cursor_start, cursor_end;
97
    uint32_t cursor_offset;
98
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
99
    /* tell for each page if it has been updated since the last time */
100
    uint8_t vram_updated[VGA_RAM_SIZE / 4096];
101
    uint32_t last_palette[256];
102
#define CH_ATTR_SIZE (160 * 100)
103
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
104
} VGAState;
105

    
106
/* force some bits to zero */
107
static const uint8_t sr_mask[8] = {
108
    (uint8_t)~0xfc,
109
    (uint8_t)~0xc2,
110
    (uint8_t)~0xf0,
111
    (uint8_t)~0xc0,
112
    (uint8_t)~0xf1,
113
    (uint8_t)~0xff,
114
    (uint8_t)~0xff,
115
    (uint8_t)~0x00,
116
};
117

    
118
static const uint8_t gr_mask[16] = {
119
    (uint8_t)~0xf0, /* 0x00 */
120
    (uint8_t)~0xf0, /* 0x01 */
121
    (uint8_t)~0xf0, /* 0x02 */
122
    (uint8_t)~0xe0, /* 0x03 */
123
    (uint8_t)~0xfc, /* 0x04 */
124
    (uint8_t)~0x84, /* 0x05 */
125
    (uint8_t)~0xf0, /* 0x06 */
126
    (uint8_t)~0xf0, /* 0x07 */
127
    (uint8_t)~0x00, /* 0x08 */
128
    (uint8_t)~0xff, /* 0x09 */
129
    (uint8_t)~0xff, /* 0x0a */
130
    (uint8_t)~0xff, /* 0x0b */
131
    (uint8_t)~0xff, /* 0x0c */
132
    (uint8_t)~0xff, /* 0x0d */
133
    (uint8_t)~0xff, /* 0x0e */
134
    (uint8_t)~0xff, /* 0x0f */
135
};
136

    
137
#define cbswap_32(__x) \
138
((uint32_t)( \
139
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
140
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
141
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
142
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
143

    
144
#ifdef WORD_BIGENDIAN
145
#define PAT(x) cbswap_32(x)
146
#else
147
#define PAT(x) (x)
148
#endif
149

    
150
static const uint32_t mask16[16] = {
151
    PAT(0x00000000),
152
    PAT(0x000000ff),
153
    PAT(0x0000ff00),
154
    PAT(0x0000ffff),
155
    PAT(0x00ff0000),
156
    PAT(0x00ff00ff),
157
    PAT(0x00ffff00),
158
    PAT(0x00ffffff),
159
    PAT(0xff000000),
160
    PAT(0xff0000ff),
161
    PAT(0xff00ff00),
162
    PAT(0xff00ffff),
163
    PAT(0xffff0000),
164
    PAT(0xffff00ff),
165
    PAT(0xffffff00),
166
    PAT(0xffffffff),
167
};
168

    
169
#undef PAT
170

    
171
#ifdef WORD_BIGENDIAN
172
#define PAT(x) (x)
173
#else
174
#define PAT(x) cbswap_32(x)
175
#endif
176

    
177
static const uint32_t dmask16[16] = {
178
    PAT(0x00000000),
179
    PAT(0x000000ff),
180
    PAT(0x0000ff00),
181
    PAT(0x0000ffff),
182
    PAT(0x00ff0000),
183
    PAT(0x00ff00ff),
184
    PAT(0x00ffff00),
185
    PAT(0x00ffffff),
186
    PAT(0xff000000),
187
    PAT(0xff0000ff),
188
    PAT(0xff00ff00),
189
    PAT(0xff00ffff),
190
    PAT(0xffff0000),
191
    PAT(0xffff00ff),
192
    PAT(0xffffff00),
193
    PAT(0xffffffff),
194
};
195

    
196
static const uint32_t dmask4[4] = {
197
    PAT(0x00000000),
198
    PAT(0x0000ffff),
199
    PAT(0xffff0000),
200
    PAT(0xffffffff),
201
};
202

    
203
static uint32_t expand4[256];
204
static uint16_t expand2[256];
205
static uint8_t expand4to8[16];
206

    
207
VGAState vga_state;
208
int vga_io_memory;
209

    
210
static uint32_t vga_ioport_read(CPUX86State *env, uint32_t addr)
211
{
212
    VGAState *s = &vga_state;
213
    int val, index;
214

    
215
    /* check port range access depending on color/monochrome mode */
216
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
217
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
218
        val = 0xff;
219
    } else {
220
        switch(addr) {
221
        case 0x3c0:
222
            if (s->ar_flip_flop == 0) {
223
                val = s->ar_index;
224
            } else {
225
                val = 0;
226
            }
227
            break;
228
        case 0x3c1:
229
            index = s->ar_index & 0x1f;
230
            if (index < 21) 
231
                val = s->ar[index];
232
            else
233
                val = 0;
234
            break;
235
        case 0x3c2:
236
            val = s->st00;
237
            break;
238
        case 0x3c4:
239
            val = s->sr_index;
240
            break;
241
        case 0x3c5:
242
            val = s->sr[s->sr_index];
243
            break;
244
        case 0x3c7:
245
            val = s->dac_state;
246
            break;
247
        case 0x3c9:
248
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
249
            if (++s->dac_sub_index == 3) {
250
                s->dac_sub_index = 0;
251
                s->dac_read_index++;
252
            }
253
            break;
254
        case 0x3ca:
255
            val = s->fcr;
256
            break;
257
        case 0x3cc:
258
            val = s->msr;
259
            break;
260
        case 0x3ce:
261
            val = s->gr_index;
262
            break;
263
        case 0x3cf:
264
            val = s->gr[s->gr_index];
265
            break;
266
        case 0x3b4:
267
        case 0x3d4:
268
            val = s->cr_index;
269
            break;
270
        case 0x3b5:
271
        case 0x3d5:
272
            val = s->cr[s->cr_index];
273
            break;
274
        case 0x3ba:
275
        case 0x3da:
276
            /* just toggle to fool polling */
277
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
278
            val = s->st01;
279
            s->ar_flip_flop = 0;
280
            break;
281
        default:
282
            val = 0x00;
283
            break;
284
        }
285
    }
286
#ifdef DEBUG_VGA
287
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
288
#endif
289
    return val;
290
}
291

    
292
static void vga_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
293
{
294
    VGAState *s = &vga_state;
295
    int index, v;
296

    
297
    /* check port range access depending on color/monochrome mode */
298
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
299
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
300
        return;
301

    
302
#ifdef DEBUG_VGA
303
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
304
#endif
305

    
306
    switch(addr) {
307
    case 0x3c0:
308
        if (s->ar_flip_flop == 0) {
309
            val &= 0x3f;
310
            s->ar_index = val;
311
        } else {
312
            index = s->ar_index & 0x1f;
313
            switch(index) {
314
            case 0x00 ... 0x0f:
315
                s->ar[index] = val & 0x3f;
316
                break;
317
            case 0x10:
318
                s->ar[index] = val & ~0x10;
319
                break;
320
            case 0x11:
321
                s->ar[index] = val;
322
                break;
323
            case 0x12:
324
                s->ar[index] = val & ~0xc0;
325
                break;
326
            case 0x13:
327
                s->ar[index] = val & ~0xf0;
328
                break;
329
            case 0x14:
330
                s->ar[index] = val & ~0xf0;
331
                break;
332
            default:
333
                break;
334
            }
335
        }
336
        s->ar_flip_flop ^= 1;
337
        break;
338
    case 0x3c2:
339
        s->msr = val & ~0x10;
340
        break;
341
    case 0x3c4:
342
        s->sr_index = val & 7;
343
        break;
344
    case 0x3c5:
345
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
346
        break;
347
    case 0x3c7:
348
        s->dac_read_index = val;
349
        s->dac_sub_index = 0;
350
        s->dac_state = 3;
351
        break;
352
    case 0x3c8:
353
        s->dac_write_index = val;
354
        s->dac_sub_index = 0;
355
        s->dac_state = 0;
356
        break;
357
    case 0x3c9:
358
        s->dac_cache[s->dac_sub_index] = val;
359
        if (++s->dac_sub_index == 3) {
360
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
361
            s->dac_sub_index = 0;
362
            s->dac_write_index++;
363
        }
364
        break;
365
    case 0x3ce:
366
        s->gr_index = val & 0x0f;
367
        break;
368
    case 0x3cf:
369
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
370
        break;
371
    case 0x3b4:
372
    case 0x3d4:
373
        s->cr_index = val;
374
        break;
375
    case 0x3b5:
376
    case 0x3d5:
377
        /* handle CR0-7 protection */
378
        if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
379
            /* can always write bit 4 of CR7 */
380
            if (s->cr_index == 7)
381
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
382
            return;
383
        }
384
        switch(s->cr_index) {
385
        case 0x01: /* horizontal display end */
386
        case 0x07:
387
        case 0x09:
388
        case 0x0c:
389
        case 0x0d:
390
        case 0x12: /* veritcal display end */
391
            s->cr[s->cr_index] = val;
392
            break;
393

    
394
            /* S3 registers */
395
        case 0x2d:
396
        case 0x2e:
397
        case 0x2f:
398
        case 0x30:
399
            /* chip ID, cannot write */
400
            break;
401
        case 0x31:
402
            /* update start address */
403
            s->cr[s->cr_index] = val;
404
            v = (val >> 4) & 3;
405
            s->cr[0x69] = (s->cr[69] & ~0x03) | v;
406
            break;
407
        case 0x51:
408
            /* update start address */
409
            s->cr[s->cr_index] = val;
410
            v = val & 3;
411
            s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
412
            break;
413
        default:
414
            s->cr[s->cr_index] = val;
415
            break;
416
        }
417
        break;
418
    case 0x3ba:
419
    case 0x3da:
420
        s->fcr = val & 0x10;
421
        break;
422
    }
423
}
424

    
425
/* called for accesses between 0xa0000 and 0xc0000 */
426
static uint32_t vga_mem_readb(uint32_t addr)
427
{
428
    VGAState *s = &vga_state;
429
    int memory_map_mode, plane;
430
    uint32_t ret;
431
    
432
    /* convert to VGA memory offset */
433
    memory_map_mode = (s->gr[6] >> 2) & 3;
434
    switch(memory_map_mode) {
435
    case 0:
436
        addr -= 0xa0000;
437
        break;
438
    case 1:
439
        addr -= 0xa0000;
440
        if (addr >= 0x10000)
441
            return 0xff;
442
        break;
443
    case 2:
444
        addr -= 0xb0000;
445
        if (addr >= 0x8000)
446
            return 0xff;
447
        break;
448
    default:
449
    case 3:
450
        addr -= 0xb8000;
451
        break;
452
    }
453
    
454
    if (s->sr[4] & 0x08) {
455
        /* chain 4 mode : simplest access */
456
        ret = s->vram_ptr[addr];
457
    } else if (s->gr[5] & 0x10) {
458
        /* odd/even mode (aka text mode mapping) */
459
        plane = (s->gr[4] & 2) | (addr & 1);
460
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
461
    } else {
462
        /* standard VGA latched access */
463
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
464

    
465
        if (!(s->gr[5] & 0x08)) {
466
            /* read mode 0 */
467
            plane = s->gr[4];
468
#ifdef WORD_BIGENDIAN
469
            ret = (s->latch >> (24 - (plane * 8))) & 0xff;
470
#else
471
            ret = (s->latch >> (plane * 8)) & 0xff;
472
#endif
473
        } else {
474
            /* read mode 1 */
475
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
476
            ret |= ret >> 16;
477
            ret |= ret >> 8;
478
            ret = (~ret) & 0xff;
479
        }
480
    }
481
    return ret;
482
}
483

    
484
static uint32_t vga_mem_readw(uint32_t addr)
485
{
486
    uint32_t v;
487
    v = vga_mem_readb(addr);
488
    v |= vga_mem_readb(addr + 1) << 8;
489
    return v;
490
}
491

    
492
static uint32_t vga_mem_readl(uint32_t addr)
493
{
494
    uint32_t v;
495
    v = vga_mem_readb(addr);
496
    v |= vga_mem_readb(addr + 1) << 8;
497
    v |= vga_mem_readb(addr + 2) << 16;
498
    v |= vga_mem_readb(addr + 3) << 24;
499
    return v;
500
}
501

    
502

    
503
/* called for accesses between 0xa0000 and 0xc0000 */
504
void vga_mem_writeb(uint32_t addr, uint32_t val)
505
{
506
    VGAState *s = &vga_state;
507
    int memory_map_mode, plane, write_mode, b, func_select;
508
    uint32_t write_mask, bit_mask, set_mask;
509

    
510
#ifdef DEBUG_VGA_MEM
511
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
512
#endif
513
    /* convert to VGA memory offset */
514
    memory_map_mode = (s->gr[6] >> 2) & 3;
515
    switch(memory_map_mode) {
516
    case 0:
517
        addr -= 0xa0000;
518
        break;
519
    case 1:
520
        addr -= 0xa0000;
521
        if (addr >= 0x10000)
522
            return;
523
        break;
524
    case 2:
525
        addr -= 0xb0000;
526
        if (addr >= 0x8000)
527
            return;
528
        break;
529
    default:
530
    case 3:
531
        addr -= 0xb8000;
532
        break;
533
    }
534
    
535
    if (s->sr[4] & 0x08) {
536
        /* chain 4 mode : simplest access */
537
        plane = addr & 3;
538
        if (s->sr[2] & (1 << plane)) {
539
            s->vram_ptr[addr] = val;
540
#ifdef DEBUG_VGA_MEM
541
            printf("vga: chain4: [0x%x]\n", addr);
542
#endif
543
            s->vram_updated[addr >> 12] = 1;
544
        }
545
    } else if (s->gr[5] & 0x10) {
546
        /* odd/even mode (aka text mode mapping) */
547
        plane = (s->gr[4] & 2) | (addr & 1);
548
        if (s->sr[2] & (1 << plane)) {
549
            addr = ((addr & ~1) << 1) | plane;
550
            s->vram_ptr[addr] = val;
551
#ifdef DEBUG_VGA_MEM
552
            printf("vga: odd/even: [0x%x]\n", addr);
553
#endif
554
            s->vram_updated[addr >> 12] = 1;
555
        }
556
    } else {
557
        /* standard VGA latched access */
558
        write_mode = s->gr[5] & 3;
559
        switch(write_mode) {
560
        default:
561
        case 0:
562
            /* rotate */
563
            b = s->gr[3] & 7;
564
            val = ((val >> b) | (val << (8 - b))) & 0xff;
565
            val |= val << 8;
566
            val |= val << 16;
567

    
568
            /* apply set/reset mask */
569
            set_mask = mask16[s->gr[1]];
570
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
571
            bit_mask = s->gr[8];
572
            break;
573
        case 1:
574
            val = s->latch;
575
            goto do_write;
576
        case 2:
577
            val = mask16[val & 0x0f];
578
            bit_mask = s->gr[8];
579
            break;
580
        case 3:
581
            /* rotate */
582
            b = s->gr[3] & 7;
583
            val = ((val >> b) | (val << (8 - b)));
584

    
585
            bit_mask = s->gr[8] & val;
586
            val = mask16[s->gr[0]];
587
            break;
588
        }
589

    
590
        /* apply logical operation */
591
        func_select = s->gr[3] >> 3;
592
        switch(func_select) {
593
        case 0:
594
        default:
595
            /* nothing to do */
596
            break;
597
        case 1:
598
            /* and */
599
            val &= s->latch;
600
            break;
601
        case 2:
602
            /* or */
603
            val |= s->latch;
604
            break;
605
        case 3:
606
            /* xor */
607
            val ^= s->latch;
608
            break;
609
        }
610

    
611
        /* apply bit mask */
612
        bit_mask |= bit_mask << 8;
613
        bit_mask |= bit_mask << 16;
614
        val = (val & bit_mask) | (s->latch & ~bit_mask);
615

    
616
    do_write:
617
        /* mask data according to sr[2] */
618
        write_mask = mask16[s->sr[2]];
619
        ((uint32_t *)s->vram_ptr)[addr] = 
620
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
621
            (val & write_mask);
622
#ifdef DEBUG_VGA_MEM
623
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
624
                   addr * 4, write_mask, val);
625
#endif
626
        s->vram_updated[addr >> 10] = 1;
627
    }
628
}
629

    
630
void vga_mem_writew(uint32_t addr, uint32_t val)
631
{
632
    vga_mem_writeb(addr, val & 0xff);
633
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff);
634
}
635

    
636
void vga_mem_writel(uint32_t addr, uint32_t val)
637
{
638
    vga_mem_writeb(addr, val & 0xff);
639
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff);
640
    vga_mem_writeb(addr + 2, (val >> 16) & 0xff);
641
    vga_mem_writeb(addr + 3, (val >> 24) & 0xff);
642
}
643

    
644
#ifdef WORD_BIGENDIAN
645
#define BIG 1
646
#else
647
#define BIG 0
648
#endif
649

    
650
#ifdef WORDS_BIGENDIAN
651
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
652
#else
653
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
654
#endif
655

    
656
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
657
                             const uint8_t *font_ptr, int h,
658
                             uint32_t fgcol, uint32_t bgcol);
659
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
660
                                  const uint8_t *font_ptr, int h, 
661
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
662
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
663
                                const uint8_t *s, int width);
664

    
665
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
666
{
667
    /* XXX: TODO */
668
    return 0;
669
}
670

    
671
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
672
{
673
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
674
}
675

    
676
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
677
{
678
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
679
}
680

    
681
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
682
{
683
    return (r << 16) | (g << 8) | b;
684
}
685

    
686
#define DEPTH 8
687
#include "vga_template.h"
688

    
689
#define DEPTH 15
690
#include "vga_template.h"
691

    
692
#define DEPTH 16
693
#include "vga_template.h"
694

    
695
#define DEPTH 32
696
#include "vga_template.h"
697

    
698
static inline int c6_to_8(int v)
699
{
700
    int b;
701
    v &= 0x3f;
702
    b = v & 1;
703
    return (v << 2) | (b << 1) | b;
704
}
705

    
706
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
707
{
708
    unsigned int col;
709
    col = rgb_to_pixel8(r, g, b);
710
    col |= col << 8;
711
    col |= col << 16;
712
    return col;
713
}
714

    
715
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
716
{
717
    unsigned int col;
718
    col = rgb_to_pixel15(r, g, b);
719
    col |= col << 16;
720
    return col;
721
}
722

    
723
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
724
{
725
    unsigned int col;
726
    col = rgb_to_pixel16(r, g, b);
727
    col |= col << 16;
728
    return col;
729
}
730

    
731
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
732
{
733
    unsigned int col;
734
    col = rgb_to_pixel32(r, g, b);
735
    return col;
736
}
737

    
738
/* return true if the palette was modified */
739
static int update_palette16(VGAState *s)
740
{
741
    int full_update, i;
742
    uint32_t v, col, *palette;
743

    
744
    full_update = 0;
745
    palette = s->last_palette;
746
    for(i = 0; i < 16; i++) {
747
        v = s->ar[i];
748
        if (s->ar[0x10] & 0x80)
749
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
750
        else
751
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
752
        v = v * 3;
753
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
754
                              c6_to_8(s->palette[v + 1]), 
755
                              c6_to_8(s->palette[v + 2]));
756
        if (col != palette[i]) {
757
            full_update = 1;
758
            palette[i] = col;
759
        }
760
    }
761
    return full_update;
762
}
763

    
764
/* return true if the palette was modified */
765
static int update_palette256(VGAState *s)
766
{
767
    int full_update, i;
768
    uint32_t v, col, *palette;
769

    
770
    full_update = 0;
771
    palette = s->last_palette;
772
    v = 0;
773
    for(i = 0; i < 256; i++) {
774
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
775
                              c6_to_8(s->palette[v + 1]), 
776
                              c6_to_8(s->palette[v + 2]));
777
        if (col != palette[i]) {
778
            full_update = 1;
779
            palette[i] = col;
780
        }
781
        v += 3;
782
    }
783
    return full_update;
784
}
785

    
786
/* update start_addr and line_offset. Return TRUE if modified */
787
static int update_basic_params(VGAState *s)
788
{
789
    int full_update;
790
    uint32_t start_addr, line_offset, line_compare, v;
791
    
792
    full_update = 0;
793
    /* compute line_offset in bytes */
794
    v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
795
    if (v == 0)
796
        v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
797
    line_offset = s->cr[0x13] | (v << 8);
798
    line_offset <<= 3;
799

    
800
    /* starting address */
801
    start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
802
    start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
803

    
804
    /* line compare */
805
    line_compare = s->cr[0x18] | 
806
        ((s->cr[0x07] & 0x10) << 4) |
807
        ((s->cr[0x09] & 0x40) << 3);
808

    
809
    if (line_offset != s->line_offset ||
810
        start_addr != s->start_addr ||
811
        line_compare != s->line_compare) {
812
        s->line_offset = line_offset;
813
        s->start_addr = start_addr;
814
        s->line_compare = line_compare;
815
        full_update = 1;
816
    }
817
    return full_update;
818
}
819

    
820
static inline int get_depth_index(int depth)
821
{
822
    switch(depth) {
823
    default:
824
    case 8:
825
        return 0;
826
    case 15:
827
        return 1;
828
    case 16:
829
        return 2;
830
    case 32:
831
        return 3;
832
    }
833
}
834

    
835
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
836
    vga_draw_glyph8_8,
837
    vga_draw_glyph8_16,
838
    vga_draw_glyph8_16,
839
    vga_draw_glyph8_32,
840
};
841

    
842
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
843
    vga_draw_glyph16_8,
844
    vga_draw_glyph16_16,
845
    vga_draw_glyph16_16,
846
    vga_draw_glyph16_32,
847
};
848

    
849
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
850
    vga_draw_glyph9_8,
851
    vga_draw_glyph9_16,
852
    vga_draw_glyph9_16,
853
    vga_draw_glyph9_32,
854
};
855
    
856
static const uint8_t cursor_glyph[32 * 4] = {
857
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
858
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
859
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
860
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
861
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
862
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
863
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
864
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
865
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
866
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
867
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
868
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
869
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
870
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
871
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
872
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
873
};    
874

    
875
/* 
876
 * Text mode update 
877
 * Missing:
878
 * - double scan
879
 * - double width 
880
 * - underline
881
 * - flashing
882
 */
883
static void vga_draw_text(VGAState *s, int full_update)
884
{
885
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
886
    int cx_min, cx_max, linesize, x_incr;
887
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
888
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
889
    const uint8_t *font_ptr, *font_base[2];
890
    int dup9, line_offset, depth_index;
891
    uint32_t *palette;
892
    uint32_t *ch_attr_ptr;
893
    vga_draw_glyph8_func *vga_draw_glyph8;
894
    vga_draw_glyph9_func *vga_draw_glyph9;
895

    
896
    full_update |= update_palette16(s);
897
    palette = s->last_palette;
898
    
899
    /* compute font data address (in plane 2) */
900
    v = s->sr[3];
901
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
902
    if (offset != s->font_offsets[0]) {
903
        s->font_offsets[0] = offset;
904
        full_update = 1;
905
    }
906
    font_base[0] = s->vram_ptr + offset;
907

    
908
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
909
    font_base[1] = s->vram_ptr + offset;
910
    if (offset != s->font_offsets[1]) {
911
        s->font_offsets[1] = offset;
912
        full_update = 1;
913
    }
914

    
915
    full_update |= update_basic_params(s);
916

    
917
    line_offset = s->line_offset;
918
    s1 = s->vram_ptr + (s->start_addr * 4);
919

    
920
    /* total width & height */
921
    cheight = (s->cr[9] & 0x1f) + 1;
922
    cw = 8;
923
    if (s->sr[1] & 0x01)
924
        cw = 9;
925
    if (s->sr[1] & 0x08)
926
        cw = 16; /* NOTE: no 18 pixel wide */
927
    x_incr = cw * ((s->ds->depth + 7) >> 3);
928
    width = (s->cr[0x01] + 1);
929
    if (s->cr[0x06] == 100) {
930
        /* ugly hack for CGA 160x100x16 - explain me the logic */
931
        height = 100;
932
    } else {
933
        height = s->cr[0x12] | 
934
            ((s->cr[0x07] & 0x02) << 7) | 
935
            ((s->cr[0x07] & 0x40) << 3);
936
        height = (height + 1) / cheight;
937
    }
938
    if (width != s->last_width || height != s->last_height ||
939
        cw != s->last_cw || cw != s->last_cw) {
940
        dpy_resize(s->ds, width * cw, height * cheight);
941
        s->last_width = width;
942
        s->last_height = height;
943
        s->last_ch = cheight;
944
        s->last_cw = cw;
945
        full_update = 1;
946
    }
947
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
948
    if (cursor_offset != s->cursor_offset ||
949
        s->cr[0xa] != s->cursor_start ||
950
        s->cr[0xb] != s->cursor_end) {
951
      /* if the cursor position changed, we update the old and new
952
         chars */
953
        if (s->cursor_offset < CH_ATTR_SIZE)
954
            s->last_ch_attr[s->cursor_offset] = -1;
955
        if (cursor_offset < CH_ATTR_SIZE)
956
            s->last_ch_attr[cursor_offset] = -1;
957
        s->cursor_offset = cursor_offset;
958
        s->cursor_start = s->cr[0xa];
959
        s->cursor_end = s->cr[0xb];
960
    }
961
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
962
    
963
    depth_index = get_depth_index(s->ds->depth);
964
    if (cw == 16)
965
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
966
    else
967
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
968
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
969
    
970
    dest = s->ds->data;
971
    linesize = s->ds->linesize;
972
    ch_attr_ptr = s->last_ch_attr;
973
    for(cy = 0; cy < height; cy++) {
974
        d1 = dest;
975
        src = s1;
976
        cx_min = width;
977
        cx_max = -1;
978
        for(cx = 0; cx < width; cx++) {
979
            ch_attr = *(uint16_t *)src;
980
            if (full_update || ch_attr != *ch_attr_ptr) {
981
                if (cx < cx_min)
982
                    cx_min = cx;
983
                if (cx > cx_max)
984
                    cx_max = cx;
985
                *ch_attr_ptr = ch_attr;
986
#ifdef WORDS_BIGENDIAN
987
                ch = ch_attr >> 8;
988
                cattr = ch_attr & 0xff;
989
#else
990
                ch = ch_attr & 0xff;
991
                cattr = ch_attr >> 8;
992
#endif
993
                font_ptr = font_base[(cattr >> 3) & 1];
994
                font_ptr += 32 * 4 * ch;
995
                bgcol = palette[cattr >> 4];
996
                fgcol = palette[cattr & 0x0f];
997
                if (cw != 9) {
998
                    vga_draw_glyph8(d1, linesize, 
999
                                    font_ptr, cheight, fgcol, bgcol);
1000
                } else {
1001
                    dup9 = 0;
1002
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1003
                        dup9 = 1;
1004
                    vga_draw_glyph9(d1, linesize, 
1005
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1006
                }
1007
                if (src == cursor_ptr &&
1008
                    !(s->cr[0x0a] & 0x20)) {
1009
                    int line_start, line_last, h;
1010
                    /* draw the cursor */
1011
                    line_start = s->cr[0x0a] & 0x1f;
1012
                    line_last = s->cr[0x0b] & 0x1f;
1013
                    /* XXX: check that */
1014
                    if (line_last > cheight - 1)
1015
                        line_last = cheight - 1;
1016
                    if (line_last >= line_start && line_start < cheight) {
1017
                        h = line_last - line_start + 1;
1018
                        d = d1 + linesize * line_start;
1019
                        if (cw != 9) {
1020
                            vga_draw_glyph8(d, linesize, 
1021
                                            cursor_glyph, h, fgcol, bgcol);
1022
                        } else {
1023
                            vga_draw_glyph9(d, linesize, 
1024
                                            cursor_glyph, h, fgcol, bgcol, 1);
1025
                        }
1026
                    }
1027
                }
1028
            }
1029
            d1 += x_incr;
1030
            src += 4;
1031
            ch_attr_ptr++;
1032
        }
1033
        if (cx_max != -1) {
1034
            dpy_update(s->ds, cx_min * cw, cy * cheight, 
1035
                       (cx_max - cx_min + 1) * cw, cheight);
1036
        }
1037
        dest += linesize * cheight;
1038
        s1 += line_offset;
1039
    }
1040
}
1041

    
1042
enum {
1043
    VGA_DRAW_LINE2,
1044
    VGA_DRAW_LINE2D2,
1045
    VGA_DRAW_LINE4,
1046
    VGA_DRAW_LINE4D2,
1047
    VGA_DRAW_LINE8D2,
1048
    VGA_DRAW_LINE8,
1049
    VGA_DRAW_LINE15,
1050
    VGA_DRAW_LINE16,
1051
    VGA_DRAW_LINE32,
1052
    VGA_DRAW_LINE_NB,
1053
};
1054

    
1055
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1056
    vga_draw_line2_8,
1057
    vga_draw_line2_16,
1058
    vga_draw_line2_16,
1059
    vga_draw_line2_32,
1060

    
1061
    vga_draw_line2d2_8,
1062
    vga_draw_line2d2_16,
1063
    vga_draw_line2d2_16,
1064
    vga_draw_line2d2_32,
1065

    
1066
    vga_draw_line4_8,
1067
    vga_draw_line4_16,
1068
    vga_draw_line4_16,
1069
    vga_draw_line4_32,
1070

    
1071
    vga_draw_line4d2_8,
1072
    vga_draw_line4d2_16,
1073
    vga_draw_line4d2_16,
1074
    vga_draw_line4d2_32,
1075

    
1076
    vga_draw_line8d2_8,
1077
    vga_draw_line8d2_16,
1078
    vga_draw_line8d2_16,
1079
    vga_draw_line8d2_32,
1080

    
1081
    vga_draw_line8_8,
1082
    vga_draw_line8_16,
1083
    vga_draw_line8_16,
1084
    vga_draw_line8_32,
1085

    
1086
    vga_draw_line15_8,
1087
    vga_draw_line15_15,
1088
    vga_draw_line15_16,
1089
    vga_draw_line15_32,
1090

    
1091
    vga_draw_line16_8,
1092
    vga_draw_line16_15,
1093
    vga_draw_line16_16,
1094
    vga_draw_line16_32,
1095

    
1096
    vga_draw_line32_8,
1097
    vga_draw_line32_15,
1098
    vga_draw_line32_16,
1099
    vga_draw_line32_32,
1100
};
1101

    
1102
/* 
1103
 * graphic modes
1104
 * Missing:
1105
 * - double scan
1106
 * - double width 
1107
 */
1108
static void vga_draw_graphic(VGAState *s, int full_update)
1109
{
1110
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1111
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1112
    int disp_width;
1113
    uint8_t *d;
1114
    uint32_t v, addr1, addr;
1115
    vga_draw_line_func *vga_draw_line;
1116
    
1117
    full_update |= update_basic_params(s);
1118

    
1119
    width = (s->cr[0x01] + 1) * 8;
1120
    height = s->cr[0x12] | 
1121
        ((s->cr[0x07] & 0x02) << 7) | 
1122
        ((s->cr[0x07] & 0x40) << 3);
1123
    height = (height + 1);
1124
    disp_width = width;
1125
    
1126
    shift_control = (s->gr[0x05] >> 5) & 3;
1127
    double_scan = (s->cr[0x09] & 0x80);
1128
    if (shift_control != s->shift_control ||
1129
        double_scan != s->double_scan) {
1130
        full_update = 1;
1131
        s->shift_control = shift_control;
1132
        s->double_scan = double_scan;
1133
    }
1134
    
1135
    if (shift_control == 0) {
1136
        full_update |= update_palette16(s);
1137
        if (s->sr[0x01] & 8) {
1138
            v = VGA_DRAW_LINE4D2;
1139
            disp_width <<= 1;
1140
        } else {
1141
            v = VGA_DRAW_LINE4;
1142
        }
1143
    } else if (shift_control == 1) {
1144
        full_update |= update_palette16(s);
1145
        if (s->sr[0x01] & 8) {
1146
            v = VGA_DRAW_LINE2D2;
1147
            disp_width <<= 1;
1148
        } else {
1149
            v = VGA_DRAW_LINE2;
1150
        }
1151
    } else {
1152
        full_update |= update_palette256(s);
1153
        v = VGA_DRAW_LINE8D2;
1154
        double_scan = 1; /* XXX: explain me why it is always activated */
1155
    }
1156
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1157

    
1158
    if (disp_width != s->last_width ||
1159
        height != s->last_height) {
1160
        dpy_resize(s->ds, disp_width, height);
1161
        s->last_width = disp_width;
1162
        s->last_height = height;
1163
        full_update = 1;
1164
    }
1165

    
1166
    line_offset = s->line_offset;
1167
#if 0
1168
    printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1169
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1170
#endif
1171
    addr1 = (s->start_addr * 4);
1172
    bwidth = width * 4;
1173
    y_start = -1;
1174
    page_min = 0x7fffffff;
1175
    page_max = -1;
1176
    d = s->ds->data;
1177
    linesize = s->ds->linesize;
1178
    y1 = 0;
1179
    for(y = 0; y < height; y++) {
1180
        addr = addr1;
1181
        if (!(s->cr[0x17] & 1)) {
1182
            int shift;
1183
            /* CGA compatibility handling */
1184
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1185
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1186
        }
1187
        if (!(s->cr[0x17] & 2)) {
1188
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1189
        }
1190
        page0 = addr >> 12;
1191
        page1 = (addr + bwidth - 1) >> 12;
1192
        update = full_update | s->vram_updated[page0] | s->vram_updated[page1];
1193
        if ((page1 - page0) > 1) {
1194
            /* if wide line, can use another page */
1195
            update |= s->vram_updated[page0 + 1];
1196
        }
1197
        if (update) {
1198
            if (y_start < 0)
1199
                y_start = y;
1200
            if (page0 < page_min)
1201
                page_min = page0;
1202
            if (page1 > page_max)
1203
                page_max = page1;
1204
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1205
        } else {
1206
            if (y_start >= 0) {
1207
                /* flush to display */
1208
                dpy_update(s->ds, 0, y_start, 
1209
                           disp_width, y - y_start);
1210
                y_start = -1;
1211
            }
1212
        }
1213
        if (!double_scan || (y & 1) != 0) {
1214
            if (y1 == s->line_compare) {
1215
                addr1 = 0;
1216
            } else {
1217
                mask = (s->cr[0x17] & 3) ^ 3;
1218
                if ((y1 & mask) == mask)
1219
                    addr1 += line_offset; 
1220
            }
1221
            y1++;
1222
        }
1223
        d += linesize;
1224
    }
1225
    if (y_start >= 0) {
1226
        /* flush to display */
1227
        dpy_update(s->ds, 0, y_start, 
1228
                   disp_width, y - y_start);
1229
    }
1230
    /* reset modified pages */
1231
    if (page_max != -1) {
1232
        memset(s->vram_updated + page_min, 0, page_max - page_min + 1);
1233
    }
1234
}
1235

    
1236
/* draw text terminal (very limited, just for simple boot debug
1237
   messages) */
1238
static int last_cursor_pos;
1239

    
1240
void vga_draw_dumb(VGAState *s)
1241
{
1242
    int c, i, cursor_pos, eol;
1243

    
1244
    cursor_pos = s->cr[0x0f] | (s->cr[0x0e] << 8);
1245
    eol = 0;
1246
    for(i = last_cursor_pos; i < cursor_pos; i++) {
1247
        /* XXX: should use vga RAM */
1248
        c = phys_ram_base[0xb8000 + (i) * 2];
1249
        if (c >= ' ') {
1250
            putchar(c);
1251
            eol = 0;
1252
        } else {
1253
            if (!eol)
1254
                putchar('\n');
1255
            eol = 1;
1256
        }
1257
    }
1258
    fflush(stdout);
1259
    last_cursor_pos = cursor_pos;
1260
}
1261

    
1262
void vga_update_display(void)
1263
{
1264
    VGAState *s = &vga_state;
1265
    int full_update, graphic_mode;
1266

    
1267
    if (s->ds->depth == 0) {
1268
        vga_draw_dumb(s);
1269
    } else {
1270
        full_update = 0;
1271
        graphic_mode = s->gr[6] & 1;
1272
        if (graphic_mode != s->graphic_mode) {
1273
            s->graphic_mode = graphic_mode;
1274
            full_update = 1;
1275
        }
1276
        if (graphic_mode)
1277
            vga_draw_graphic(s, full_update);
1278
        else
1279
            vga_draw_text(s, full_update);
1280
    }
1281
}
1282

    
1283
void vga_reset(VGAState *s)
1284
{
1285
    memset(s, 0, sizeof(VGAState));
1286
    /* chip ID for 8c968 */
1287
    s->cr[0x2d] = 0x88;
1288
    s->cr[0x2e] = 0xb0;
1289
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1290
    s->cr[0x30] = 0xe1;
1291
    s->graphic_mode = -1; /* force full update */
1292
}
1293

    
1294
CPUReadMemoryFunc *vga_mem_read[3] = {
1295
    vga_mem_readb,
1296
    vga_mem_readw,
1297
    vga_mem_readl,
1298
};
1299

    
1300
CPUWriteMemoryFunc *vga_mem_write[3] = {
1301
    vga_mem_writeb,
1302
    vga_mem_writew,
1303
    vga_mem_writel,
1304
};
1305

    
1306
int vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
1307
             unsigned long vga_ram_offset, int vga_ram_size)
1308
{
1309
    VGAState *s = &vga_state;
1310
    int i, j, v, b;
1311

    
1312
    for(i = 0;i < 256; i++) {
1313
        v = 0;
1314
        for(j = 0; j < 8; j++) {
1315
            v |= ((i >> j) & 1) << (j * 4);
1316
        }
1317
        expand4[i] = v;
1318

    
1319
        v = 0;
1320
        for(j = 0; j < 4; j++) {
1321
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1322
        }
1323
        expand2[i] = v;
1324
    }
1325
    for(i = 0; i < 16; i++) {
1326
        v = 0;
1327
        for(j = 0; j < 4; j++) {
1328
            b = ((i >> j) & 1);
1329
            v |= b << (2 * j);
1330
            v |= b << (2 * j + 1);
1331
        }
1332
        expand4to8[i] = v;
1333
    }
1334

    
1335
    vga_reset(s);
1336

    
1337
    switch(ds->depth) {
1338
    case 8:
1339
        s->rgb_to_pixel = rgb_to_pixel8_dup;
1340
        break;
1341
    case 15:
1342
        s->rgb_to_pixel = rgb_to_pixel15_dup;
1343
        break;
1344
    default:
1345
    case 16:
1346
        s->rgb_to_pixel = rgb_to_pixel16_dup;
1347
        break;
1348
    case 32:
1349
        s->rgb_to_pixel = rgb_to_pixel32_dup;
1350
        break;
1351
    }
1352

    
1353
    s->vram_ptr = vga_ram_base;
1354
    s->vram_offset = vga_ram_offset;
1355
    s->vram_size = vga_ram_size;
1356
    s->ds = ds;
1357

    
1358
    register_ioport_write(0x3c0, 16, vga_ioport_write, 1);
1359

    
1360
    register_ioport_write(0x3b4, 2, vga_ioport_write, 1);
1361
    register_ioport_write(0x3d4, 2, vga_ioport_write, 1);
1362
    register_ioport_write(0x3ba, 1, vga_ioport_write, 1);
1363
    register_ioport_write(0x3da, 1, vga_ioport_write, 1);
1364

    
1365
    register_ioport_read(0x3c0, 16, vga_ioport_read, 1);
1366

    
1367
    register_ioport_read(0x3b4, 2, vga_ioport_read, 1);
1368
    register_ioport_read(0x3d4, 2, vga_ioport_read, 1);
1369
    register_ioport_read(0x3ba, 1, vga_ioport_read, 1);
1370
    register_ioport_read(0x3da, 1, vga_ioport_read, 1);
1371

    
1372
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1373
    cpu_register_physical_memory(0xa0000, 0x20000, vga_io_memory);
1374
    return 0;
1375
}