Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
54 pj 1
/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen                    */
2
/*                                                                 */
3
/* This library is free software; you can redistribute it and/or   */
4
/* modify it without any restrictions. This library is distributed */
5
/* in the hope that it will be useful, but without any warranty.   */
6
 
7
/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
8
/* partially copyrighted (C) 1993 by Hartmut Schirmer */
9
 
10
/* 21 January 1995 - added vga_readscanline(), added support for   */
11
/* non 8-pixel aligned scanlines in 16 color mode. billr@rastergr.com */
12
#include <stdio.h>
13
#include "vga.h"
14
#include "libvga.h"
15
#include "driver.h"
16
 
17
/* used to decompose color value into bits (for fast scanline drawing) */
18
union bits {
19
    struct {
20
        unsigned char bit3;
21
        unsigned char bit2;
22
        unsigned char bit1;
23
        unsigned char bit0;
24
    } b;
25
    unsigned int i;
26
};
27
 
28
/* color decompositions */
29
static union bits color16[16] =
30
{
31
    {
32
        {0, 0, 0, 0}},
33
    {
34
        {0, 0, 0, 1}},
35
    {
36
        {0, 0, 1, 0}},
37
    {
38
        {0, 0, 1, 1}},
39
    {
40
        {0, 1, 0, 0}},
41
    {
42
        {0, 1, 0, 1}},
43
    {
44
        {0, 1, 1, 0}},
45
    {
46
        {0, 1, 1, 1}},
47
    {
48
        {1, 0, 0, 0}},
49
    {
50
        {1, 0, 0, 1}},
51
    {
52
        {1, 0, 1, 0}},
53
    {
54
        {1, 0, 1, 1}},
55
    {
56
        {1, 1, 0, 0}},
57
    {
58
        {1, 1, 0, 1}},
59
    {
60
        {1, 1, 1, 0}},
61
    {
62
        {1, 1, 1, 1}}};
63
 
64
/* mask for end points in plane buffer mode */
65
static unsigned char mask[8] =
66
{
67
    0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
68
/* display plane buffers (for fast scanline drawing) */
69
/* 256 bytes -> max 2048 pixel per line (2/16 colors) */
70
static unsigned char plane0[256];
71
static unsigned char plane1[256];
72
static unsigned char plane2[256];
73
static unsigned char plane3[256];
74
 
75
static inline void shifted_memcpy(void *dest_in, void *source_in, int len)
76
{
77
    int *dest = dest_in;
78
    int *source = source_in;
79
 
80
    len >>= 2;
81
 
82
    while (len--)
83
        *dest++ = (*source++ << 8);
84
}
85
 
86
/* RGB_swapped_memcopy returns the amount of bytes unhandled */
87
static inline int RGB_swapped_memcpy(char *dest, char *source, int len)
88
{
89
    int rest, tmp;
90
 
91
    tmp = len / 3;
92
    rest = len - 3 * tmp;
93
    len = tmp;
94
 
95
    while (len--) {
96
        *dest++ = source[2];
97
        *dest++ = source[1];
98
        *dest++ = source[0];
99
        source += 3;
100
    }
101
 
102
    return rest;
103
}
104
 
105
int vga_drawscanline(int line, unsigned char *colors)
106
{
107
    if ((CI.colors == 2) || (CI.colors > 256))
108
        return vga_drawscansegment(colors, 0, line, CI.xbytes);
109
    else
110
        return vga_drawscansegment(colors, 0, line, CI.xdim);
111
}
112
 
113
#ifdef LIBC_MEMCPY
114
#define MEMCPY memcpy
115
#else
116
void MEMCPY(unsigned char *dst, unsigned char *src, size_t n) {
117
    unsigned char *e;
118
    e=src+n;
119
    while(src<e) *(dst++)=*(src++);
120
}
121
#endif
122
 
123
int vga_drawscansegment(unsigned char *colors, int x, int y, int length)
124
{
125
    /* both length and x must divide with 8 */
126
    /*  no longer true (at least for 16 & 256 colors) */
127
 
128
    if (MODEX)
129
        goto modeX;
130
    switch (CI.colors) {
131
    case 16:
132
        {
133
            int i, j, k, first, last, page, l1, l2;
134
            int offset, eoffs, soffs, ioffs;
135
            union bits bytes;
136
            unsigned char *address;
137
 
138
            k = 0;
139
            soffs = ioffs = (x & 0x7);  /* starting offset into first byte */
140
            eoffs = (x + length) & 0x7;         /* ending offset into last byte */
141
            for (i = 0; i < length;) {
142
                bytes.i = 0;
143
                first = i;
144
                last = i + 8 - ioffs;
145
                if (last > length)
146
                    last = length;
147
                for (j = first; j < last; j++, i++)
148
                    bytes.i = (bytes.i << 1) | color16[colors[j]].i;
149
                plane0[k] = bytes.b.bit0;
150
                plane1[k] = bytes.b.bit1;
151
                plane2[k] = bytes.b.bit2;
152
                plane3[k++] = bytes.b.bit3;
153
                ioffs = 0;
154
            }
155
            if (eoffs) {
156
                /* fixup last byte */
157
                k--;
158
                bytes.i <<= (8 - eoffs);
159
                plane0[k] = bytes.b.bit0;
160
                plane1[k] = bytes.b.bit1;
161
                plane2[k] = bytes.b.bit2;
162
                plane3[k++] = bytes.b.bit3;
163
            }
164
            offset = (y * CI.xdim + x) / 8;
165
            vga_setpage((page = offset >> 16));
166
            l1 = 0x10000 - (offset &= 0xffff);
167
            /* k currently contains number of bytes to write */
168
            if (l1 > k)
169
                l1 = k;
170
            l2 = k - l1;
171
            /* make k the index of the last byte to write */
172
            k--;
173
 
174
            address = GM + offset;
175
 
176
            /* disable Set/Reset Register */
177
            __svgalib_outgra(0x01,0x00);
178
 
179
            /* write to all bits */
180
            __svgalib_outgra(0x08,0xff);
181
 
182
            /* select write map mask register */
183
            __svgalib_outseq(0x02,0x01);
184
 
185
            /* select read map mask register */
186
            __svgalib_outgra(0x04,0x00);
187
            if (soffs)
188
                plane0[0] |= *address & ~mask[soffs];
189
            if (eoffs && l2 == 0)
190
                plane0[k] |= *(address + l1 - 1) & mask[eoffs];
191
            MEMCPY(address, plane0, l1);
192
 
193
            /* write plane 1 */
194
            __svgalib_outseq(0x02,0x02);
195
            /* read plane 1 */
196
            __svgalib_outgra(0x04,0x01);
197
            if (soffs)
198
                plane1[0] |= *address & ~mask[soffs];
199
            if (eoffs && l2 == 0)
200
                plane1[k] |= *(address + l1 - 1) & mask[eoffs];
201
            MEMCPY(address, plane1, l1);
202
 
203
            /* write plane 2 */
204
            __svgalib_outseq(0x02,0x04);
205
            /* read plane 2 */
206
            __svgalib_outgra(0x04,0x02);
207
            if (soffs)
208
                plane2[0] |= *address & ~mask[soffs];
209
            if (eoffs && l2 == 0)
210
                plane2[k] |= *(address + l1 - 1) & mask[eoffs];
211
            MEMCPY(address, plane2, l1);
212
 
213
            /* write plane 3 */
214
            __svgalib_outseq(0x02,0x08);
215
            /* read plane 3 */
216
            __svgalib_outgra(0x04,0x03);
217
            if (soffs)
218
                plane3[0] |= *address & ~mask[soffs];
219
            if (eoffs && l2 == 0)
220
                plane3[k] |= *(address + l1 - 1) & mask[eoffs];
221
            MEMCPY(address, plane3, l1);
222
 
223
            if (l2 > 0) {
224
                vga_setpage(page + 1);
225
 
226
                /* write plane 0 */
227
                __svgalib_outseq(0x02,0x01);
228
                if (eoffs) {
229
                    /* read plane 0 */
230
                    __svgalib_outgra(0x04,0x00);
231
                    plane0[k] |= *(GM + l2 - 1) & mask[eoffs];
232
                }
233
                MEMCPY(GM, &plane0[l1], l2);
234
 
235
                /* write plane 1 */
236
                __svgalib_outseq(0x02,0x02);
237
                if (eoffs) {
238
                    /* read plane 1 */
239
                    __svgalib_outgra(0x04,0x01);
240
                    plane1[k] |= *(GM + l2 - 1) & mask[eoffs];
241
                }
242
                MEMCPY(GM, &plane1[l1], l2);
243
 
244
                /* write plane 2 */
245
                __svgalib_outseq(0x02,0x04);
246
                if (eoffs) {
247
                    /* read plane 2 */
248
                    __svgalib_outgra(0x04,0x02);
249
                    plane2[k] |= *(GM + l2 - 1) & mask[eoffs];
250
                }
251
                MEMCPY(GM, &plane2[l1], l2);
252
 
253
                /* write plane 3 */
254
                __svgalib_outseq(0x02,0x08);
255
                if (eoffs) {
256
                    /* read plane 3 */
257
                    __svgalib_outgra(0x04,0x03);
258
                    plane3[k] |= *(GM + l2 - 1) & mask[eoffs];
259
                }
260
                MEMCPY(GM, &plane3[l1], l2);
261
            }
262
            /* restore map mask register */
263
            __svgalib_outseq(0x02,0x0f);
264
 
265
            /* enable Set/Reset Register */
266
            __svgalib_outgra(0x01,0x0f);
267
        }
268
        break;
269
    case 2:
270
        {
271
            /* disable Set/Reset Register */
272
            __svgalib_outgra(0x01,0x00);
273
 
274
            /* write to all bits */
275
            __svgalib_outgra(0x08,0xff);
276
 
277
            /* write to all planes */
278
            __svgalib_outseq(0x02,0x0f);
279
 
280
            MEMCPY(GM + (y * CI.xdim + x) / 8, colors, length);
281
 
282
            /* restore map mask register */
283
            __svgalib_outseq(0x02,0x0f);
284
 
285
            /* enable Set/Reset Register */
286
            __svgalib_outgra(0x01,0x0f);
287
        }
288
        break;
289
    case 256:
290
        {
291
            switch (CM) {
292
            case G320x200x256:  /* linear addressing - easy and fast */
293
                MEMCPY(GM + (y * CI.xdim + x), colors, length);
294
                return 0;
295
            case G320x240x256:
296
            case G320x400x256:
297
            case G360x480x256:
298
            case G400x300x256X:
299
              modeX:
300
                {
301
                    int first, offset, pixel, plane;
302
 
303
                    for (plane = 0; plane < 4; plane++) {
304
                        /* select plane */
305
                        __svgalib_outseq(0x02,1 << plane );
306
 
307
                        pixel = ((4 - (x & 3) + plane) & 3);
308
                        first = (y * CI.xdim + x) / 4;
309
                        if((x & 3) + pixel > 3)
310
                            first++;
311
                        for (offset = first; pixel < length; offset++) {
312
                            *(GM+offset) = colors[pixel];
313
                            pixel += 4;
314
                        }
315
                    }
316
                }
317
                return 0;
318
            }
319
            {
320
                unsigned long offset;
321
                int segment, free;
322
 
323
              SegmentedCopy:
324
                offset = y * CI.xbytes + x;
325
                if (__svgalib_modeinfo_linearset & IS_LINEAR ) {
326
                    MEMCPY(LINEAR_POINTER+offset, colors, length);
327
                } else {
328
                    segment = offset >> 16;
329
                    free = ((segment + 1) << 16) - offset;
330
                    offset &= 0xFFFF;
331
 
332
                    if (free < length) {
333
                        vga_setpage(segment);
334
                        MEMCPY(GM + offset, colors, free);
335
                        vga_setpage(segment + 1);
336
                        MEMCPY(GM, colors + free, length - free);
337
                    } else {
338
                        vga_setpage(segment);
339
                        MEMCPY(GM + offset, colors, length);
340
                    }
341
                }
342
            }
343
        }
344
        break;
345
    case 32768:
346
    case 65536:
347
        x *= 2;
348
        goto SegmentedCopy;
349
    case 1 << 24:
350
        if (__svgalib_cur_info.bytesperpixel == 4) {
351
            x <<= 2;
352
            if (MODEFLAGS & RGB_MISORDERED) {
353
                unsigned long offset;
354
                int segment, free;
355
 
356
                offset = y * CI.xbytes + x;
357
                if (__svgalib_modeinfo_linearset & IS_LINEAR ) {
358
                    shifted_memcpy(LINEAR_POINTER+offset, colors, length);
359
                } else {
360
                    segment = offset >> 16;
361
                    free = ((segment + 1) << 16) - offset;
362
                    offset &= 0xFFFF;
363
 
364
                    if (free < length) {
365
                        vga_setpage(segment);
366
                        shifted_memcpy(GM + offset, colors, free);
367
                        vga_setpage(segment + 1);
368
                        shifted_memcpy(GM, colors + free, length - free);
369
                    } else {
370
                        vga_setpage(segment);
371
                        shifted_memcpy(GM + offset, colors, length);
372
                    }
373
                }
374
            } else {
375
                goto SegmentedCopy;
376
            }
377
            break;
378
        }
379
        x *= 3;
380
        if (MODEFLAGS & RGB_MISORDERED) {
381
            unsigned long offset;
382
            int segment, free;
383
 
384
            offset = y * CI.xbytes + x;
385
            if (__svgalib_modeinfo_linearset & IS_LINEAR ) {
386
                RGB_swapped_memcpy(LINEAR_POINTER+offset, colors, length);
387
            } else {
388
                segment = offset >> 16;
389
                free = ((segment + 1) << 16) - offset;
390
                offset &= 0xFFFF;
391
 
392
                if (free < length) {
393
                    int i;
394
 
395
                    vga_setpage(segment);
396
                    i = RGB_swapped_memcpy(GM + offset, colors, free);
397
                    colors += (free - i);
398
 
399
                    switch (i) {
400
                    case 2:
401
                        *(GM+0xfffe) = colors[2];
402
                        *(GM+0xffff) = colors[1];
403
                        break;
404
                    case 1:
405
                        *(GM+0xffff) = colors[2];
406
                        break;
407
                    }
408
 
409
                    vga_setpage(segment + 1);
410
 
411
                    switch (i) {
412
                    case 1:
413
                        *(GM+1) = colors[0];
414
                        *(GM)   = colors[1];
415
                        i = 3 - i;
416
                        free += i;
417
                        colors += 3;
418
                        break;
419
                    case 2:
420
                        *(GM) = colors[0];
421
                        i = 3 - i;
422
                        free += i;
423
                        colors += 3;
424
                        break;
425
                    }
426
 
427
                    RGB_swapped_memcpy(GM + i, colors, length - free);
428
                } else {
429
                    vga_setpage(segment);
430
                    RGB_swapped_memcpy(GM + offset, colors, length);
431
                }
432
            }
433
        } else {
434
            goto SegmentedCopy;
435
        }
436
    }
437
 
438
    return 0;
439
}
440
 
441
int vga_getscansegment(unsigned char *colors, int x, int y, int length)
442
{
443
 
444
    if (MODEX)
445
        goto modeX2;
446
    switch (CI.colors) {
447
    case 16:
448
        {
449
            int i, k, page, l1, l2;
450
            int offset, eoffs, soffs, nbytes, bit;
451
            unsigned char *address;
452
            unsigned char color;
453
            k = 0;
454
            soffs = (x & 0x7);  /* starting offset into first byte */
455
            eoffs = (x + length) & 0x7;         /* ending offset into last byte */
456
            offset = (y * CI.xdim + x) / 8;
457
            vga_setpage((page = offset >> 16));
458
            l1 = 0x10000 - (offset &= 0xffff);
459
            if (soffs)
460
                nbytes = (length - (8 - soffs)) / 8 + 1;
461
            else
462
                nbytes = length / 8;
463
            if (eoffs)
464
                nbytes++;
465
            if (l1 > nbytes)
466
                l1 = nbytes;
467
            l2 = nbytes - l1;
468
            address = GM + offset;
469
            /* disable Set/Reset Register */
470
            __svgalib_outgra(0x01,0x00);
471
            /* read plane 0 */
472
            __svgalib_outgra(0x04,0x00);
473
            memcpy(plane0, address, l1);
474
            /* read plane 1 */
475
            __svgalib_outgra(0x04,0x01);
476
            memcpy(plane1, address, l1);
477
            /* read plane 2 */
478
            __svgalib_outgra(0x04,0x02);
479
            memcpy(plane2, address, l1);
480
            /* read plane 3 */
481
            __svgalib_outgra(0x04,0x03);
482
            memcpy(plane3, address, l1);
483
            if (l2 > 0) {
484
                vga_setpage(page + 1);
485
                /* read plane 0 */
486
              __svgalib_outgra(0x04,0x00);
487
                memcpy(&plane0[l1], GM, l2);
488
                /* read plane 1 */
489
              __svgalib_outgra(0x04,0x01);
490
                memcpy(&plane1[l1], GM, l2);
491
                /* read plane 2 */
492
              __svgalib_outgra(0x04,0x02);
493
                memcpy(&plane2[l1], GM, l2);
494
                /* read plane 3 */
495
              __svgalib_outgra(0x04,0x03);
496
                memcpy(&plane3[l1], GM, l2);
497
            }
498
            /* enable Set/Reset Register */
499
            __svgalib_outgra(0x01,0x0f);
500
            k = 0;
501
            for (i = 0; i < length;) {
502
                for (bit = 7 - soffs; bit >= 0 && i < length; bit--, i++) {
503
                    color = (plane0[k] & (1 << bit) ? 1 : 0);
504
                    color |= (plane1[k] & (1 << bit) ? 1 : 0) << 1;
505
                    color |= (plane2[k] & (1 << bit) ? 1 : 0) << 2;
506
                    color |= (plane3[k] & (1 << bit) ? 1 : 0) << 3;
507
                    colors[i] = color;
508
                }
509
                k++;
510
                soffs = 0;
511
            }
512
        }
513
        break;
514
    case 2:
515
        {
516
            /* disable Set/Reset Register */
517
            __svgalib_outgra(0x01,0x00);
518
            /* read from plane 0 */
519
            __svgalib_outseq(0x04,0x00);
520
            memcpy(colors, GM + (y * CI.xdim + x) / 8, length);
521
            /* enable Set/Reset Register */
522
            __svgalib_outgra(0x01,0x0f);
523
        }
524
        break;
525
    case 256:
526
        {
527
            switch (CM) {
528
            case G320x200x256:  /* linear addressing - easy and fast */
529
                memcpy(colors, GM + y * CI.xdim + x, length);
530
                return 0;
531
            case G320x240x256:
532
            case G320x400x256:
533
            case G360x480x256:
534
            case G400x300x256X:
535
              modeX2:
536
                {
537
                    int first, offset, pixel, plane;
538
                    for (plane = 0; plane < 4; plane++) {
539
                        /* select plane */
540
                        __svgalib_outgra(0x04, plane);
541
                        pixel = ((4 - (x & 3) + plane) & 3);
542
                        first = (y * CI.xdim + x) / 4;
543
                        if((x & 3) + pixel > 3)
544
                            first++;
545
                        for (offset = first; pixel < length; offset++) {
546
                            colors[pixel] = gr_readb(offset);
547
                            pixel += 4;
548
                        }
549
                    }
550
                }
551
                return 0;
552
            }
553
            {
554
                unsigned long offset;
555
                int segment, free;
556
              SegmentedCopy2:
557
                offset = y * CI.xbytes + x;
558
                if (__svgalib_modeinfo_linearset & IS_LINEAR ) {
559
                    memcpy(colors, LINEAR_POINTER+offset, length);
560
                } else {
561
                    segment = offset >> 16;
562
                    free = ((segment + 1) << 16) - offset;
563
                    offset &= 0xFFFF;
564
                    if (free < length) {
565
                        vga_setpage(segment);
566
                        memcpy(colors, GM + offset, free);
567
                        vga_setpage(segment + 1);
568
                        memcpy(colors + free, GM, length - free);
569
                    } else {
570
                        vga_setpage(segment);
571
                        memcpy(colors, GM + offset, length);
572
                    }
573
                }
574
            }
575
        }
576
        break;
577
    case 32768:
578
    case 65536:
579
        x *= 2;
580
        goto SegmentedCopy2;
581
    case 1 << 24:
582
        if (__svgalib_cur_info.bytesperpixel == 4) {
583
                x<<=2;
584
        } else {
585
                x *= 3;
586
        }
587
        goto SegmentedCopy2;
588
    }
589
    return 0;
590
}