Commit 17b0018b4200b674bfcb7c946fce89f0a5ffaa24

Authored by bellard
1 parent 39cf7803

Full VGA support, including old CGA modes, VGA planar and mode X


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@346 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 340 additions and 81 deletions
hw/vga.c
... ... @@ -49,6 +49,7 @@
49 49 #include "thunk.h"
50 50  
51 51 //#define DEBUG_VGA
  52 +//#define DEBUG_VGA_MEM
52 53  
53 54 #define MSR_COLOR_EMULATION 0x01
54 55 #define MSR_PAGE_SELECT 0x20
... ... @@ -85,7 +86,8 @@ typedef struct VGAState {
85 86 DisplayState *ds;
86 87 uint32_t font_offsets[2];
87 88 int graphic_mode;
88   - int shift_control;
  89 + uint8_t shift_control;
  90 + uint8_t double_scan;
89 91 uint32_t line_offset;
90 92 uint32_t line_compare;
91 93 uint32_t start_addr;
... ... @@ -93,10 +95,11 @@ typedef struct VGAState {
93 95 uint32_t last_width, last_height;
94 96 uint8_t cursor_start, cursor_end;
95 97 uint32_t cursor_offset;
  98 + unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
96 99 /* tell for each page if it has been updated since the last time */
97 100 uint8_t vram_updated[VGA_RAM_SIZE / 4096];
98 101 uint32_t last_palette[256];
99   -#define CH_ATTR_SIZE (132 * 60)
  102 +#define CH_ATTR_SIZE (160 * 100)
100 103 uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
101 104 } VGAState;
102 105  
... ... @@ -199,6 +202,7 @@ static const uint32_t dmask4[4] = {
199 202  
200 203 static uint32_t expand4[256];
201 204 static uint16_t expand2[256];
  205 +static uint8_t expand4to8[16];
202 206  
203 207 VGAState vga_state;
204 208 int vga_io_memory;
... ... @@ -503,7 +507,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
503 507 int memory_map_mode, plane, write_mode, b, func_select;
504 508 uint32_t write_mask, bit_mask, set_mask;
505 509  
506   -#ifdef DEBUG_VGA
  510 +#ifdef DEBUG_VGA_MEM
507 511 printf("vga: [0x%x] = 0x%02x\n", addr, val);
508 512 #endif
509 513 /* convert to VGA memory offset */
... ... @@ -533,7 +537,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
533 537 plane = addr & 3;
534 538 if (s->sr[2] & (1 << plane)) {
535 539 s->vram_ptr[addr] = val;
536   -#ifdef DEBUG_VGA
  540 +#ifdef DEBUG_VGA_MEM
537 541 printf("vga: chain4: [0x%x]\n", addr);
538 542 #endif
539 543 s->vram_updated[addr >> 12] = 1;
... ... @@ -544,7 +548,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
544 548 if (s->sr[2] & (1 << plane)) {
545 549 addr = ((addr & ~1) << 1) | plane;
546 550 s->vram_ptr[addr] = val;
547   -#ifdef DEBUG_VGA
  551 +#ifdef DEBUG_VGA_MEM
548 552 printf("vga: odd/even: [0x%x]\n", addr);
549 553 #endif
550 554 s->vram_updated[addr >> 12] = 1;
... ... @@ -615,7 +619,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
615 619 ((uint32_t *)s->vram_ptr)[addr] =
616 620 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
617 621 (val & write_mask);
618   -#ifdef DEBUG_VGA
  622 +#ifdef DEBUG_VGA_MEM
619 623 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
620 624 addr * 4, write_mask, val);
621 625 #endif
... ... @@ -699,28 +703,43 @@ static inline int c6_to_8(int v)
699 703 return (v << 2) | (b << 1) | b;
700 704 }
701 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 +
702 738 /* return true if the palette was modified */
703 739 static int update_palette16(VGAState *s)
704 740 {
705   - int full_update, i, depth;
  741 + int full_update, i;
706 742 uint32_t v, col, *palette;
707   - unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
708   - depth = s->ds->depth;
709   - switch(depth) {
710   - case 8:
711   - rgb_to_pixel = rgb_to_pixel8;
712   - break;
713   - case 15:
714   - rgb_to_pixel = rgb_to_pixel15;
715   - break;
716   - default:
717   - case 16:
718   - rgb_to_pixel = rgb_to_pixel16;
719   - break;
720   - case 32:
721   - rgb_to_pixel = rgb_to_pixel32;
722   - break;
723   - }
724 743  
725 744 full_update = 0;
726 745 palette = s->last_palette;
... ... @@ -731,21 +750,35 @@ static int update_palette16(VGAState *s)
731 750 else
732 751 v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
733 752 v = v * 3;
734   - col = rgb_to_pixel(c6_to_8(s->palette[v]),
735   - c6_to_8(s->palette[v + 1]),
736   - c6_to_8(s->palette[v + 2]));
737   -
738   - if (depth == 8) {
739   - col |= col << 8;
740   - col |= col << 16;
741   - } else if (depth <= 16) {
742   - col |= col << 16;
  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;
743 759 }
744   - // printf("%2d: %08x\n", i, col);
  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]));
745 777 if (col != palette[i]) {
746 778 full_update = 1;
747 779 palette[i] = col;
748 780 }
  781 + v += 3;
749 782 }
750 783 return full_update;
751 784 }
... ... @@ -806,6 +839,13 @@ static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
806 839 vga_draw_glyph8_32,
807 840 };
808 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 +
809 849 static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
810 850 vga_draw_glyph9_8,
811 851 vga_draw_glyph9_16,
... ... @@ -882,12 +922,19 @@ static void vga_draw_text(VGAState *s, int full_update)
882 922 cw = 8;
883 923 if (s->sr[1] & 0x01)
884 924 cw = 9;
  925 + if (s->sr[1] & 0x08)
  926 + cw = 16; /* NOTE: no 18 pixel wide */
885 927 x_incr = cw * ((s->ds->depth + 7) >> 3);
886 928 width = (s->cr[0x01] + 1);
887   - height = s->cr[0x12] |
888   - ((s->cr[0x07] & 0x02) << 7) |
889   - ((s->cr[0x07] & 0x40) << 3);
890   - height = (height + 1) / cheight;
  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 + }
891 938 if (width != s->last_width || height != s->last_height ||
892 939 cw != s->last_cw || cw != s->last_cw) {
893 940 dpy_resize(s->ds, width * cw, height * cheight);
... ... @@ -914,7 +961,10 @@ static void vga_draw_text(VGAState *s, int full_update)
914 961 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
915 962  
916 963 depth_index = get_depth_index(s->ds->depth);
917   - vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
  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];
918 968 vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
919 969  
920 970 dest = s->ds->data;
... ... @@ -944,7 +994,7 @@ static void vga_draw_text(VGAState *s, int full_update)
944 994 font_ptr += 32 * 4 * ch;
945 995 bgcol = palette[cattr >> 4];
946 996 fgcol = palette[cattr & 0x0f];
947   - if (cw == 8) {
  997 + if (cw != 9) {
948 998 vga_draw_glyph8(d1, linesize,
949 999 font_ptr, cheight, fgcol, bgcol);
950 1000 } else {
... ... @@ -966,7 +1016,7 @@ static void vga_draw_text(VGAState *s, int full_update)
966 1016 if (line_last >= line_start && line_start < cheight) {
967 1017 h = line_last - line_start + 1;
968 1018 d = d1 + linesize * line_start;
969   - if (cw == 8) {
  1019 + if (cw != 9) {
970 1020 vga_draw_glyph8(d, linesize,
971 1021 cursor_glyph, h, fgcol, bgcol);
972 1022 } else {
... ... @@ -989,17 +1039,45 @@ static void vga_draw_text(VGAState *s, int full_update)
989 1039 }
990 1040 }
991 1041  
992   -static vga_draw_line_func *vga_draw_line_table[4 * 6] = {
  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] = {
993 1056 vga_draw_line2_8,
994 1057 vga_draw_line2_16,
995 1058 vga_draw_line2_16,
996 1059 vga_draw_line2_32,
997 1060  
  1061 + vga_draw_line2d2_8,
  1062 + vga_draw_line2d2_16,
  1063 + vga_draw_line2d2_16,
  1064 + vga_draw_line2d2_32,
  1065 +
998 1066 vga_draw_line4_8,
999 1067 vga_draw_line4_16,
1000 1068 vga_draw_line4_16,
1001 1069 vga_draw_line4_32,
1002 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 +
1003 1081 vga_draw_line8_8,
1004 1082 vga_draw_line8_16,
1005 1083 vga_draw_line8_16,
... ... @@ -1029,14 +1107,13 @@ static vga_draw_line_func *vga_draw_line_table[4 * 6] = {
1029 1107 */
1030 1108 static void vga_draw_graphic(VGAState *s, int full_update)
1031 1109 {
1032   - int y, update, page_min, page_max, linesize, y_start;
  1110 + int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1033 1111 int width, height, shift_control, line_offset, page0, page1, bwidth;
  1112 + int disp_width;
1034 1113 uint8_t *d;
1035 1114 uint32_t v, addr1, addr;
1036 1115 vga_draw_line_func *vga_draw_line;
1037   -
1038   - full_update |= update_palette16(s);
1039   -
  1116 +
1040 1117 full_update |= update_basic_params(s);
1041 1118  
1042 1119 width = (s->cr[0x01] + 1) * 8;
... ... @@ -1044,30 +1121,53 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1044 1121 ((s->cr[0x07] & 0x02) << 7) |
1045 1122 ((s->cr[0x07] & 0x40) << 3);
1046 1123 height = (height + 1);
1047   -
1048   - if (width != s->last_width ||
1049   - height != s->last_height) {
1050   - dpy_resize(s->ds, width, height);
1051   - s->last_width = width;
1052   - s->last_height = height;
1053   - full_update = 1;
1054   - }
1055   -
  1124 + disp_width = width;
  1125 +
1056 1126 shift_control = (s->gr[0x05] >> 5) & 3;
1057   - if (shift_control != s->shift_control) {
  1127 + double_scan = (s->cr[0x09] & 0x80);
  1128 + if (shift_control != s->shift_control ||
  1129 + double_scan != s->double_scan) {
1058 1130 full_update = 1;
1059 1131 s->shift_control = shift_control;
  1132 + s->double_scan = double_scan;
1060 1133 }
1061 1134  
1062   - if (shift_control == 0)
1063   - v = 1; /* 4 bit/pixel */
1064   - else if (shift_control == 1)
1065   - v = 0; /* 2 bit/pixel */
1066   - else
1067   - v = 2; /* 8 bit/pixel */
  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 + }
1068 1156 vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1069   -
  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 +
1070 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
1071 1171 addr1 = (s->start_addr * 4);
1072 1172 bwidth = width * 4;
1073 1173 y_start = -1;
... ... @@ -1075,14 +1175,17 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1075 1175 page_max = -1;
1076 1176 d = s->ds->data;
1077 1177 linesize = s->ds->linesize;
  1178 + y1 = 0;
1078 1179 for(y = 0; y < height; y++) {
1079 1180 addr = addr1;
1080 1181 if (!(s->cr[0x17] & 1)) {
  1182 + int shift;
1081 1183 /* CGA compatibility handling */
1082   - addr = (addr & ~0x2000) | ((y & 1) << 13);
  1184 + shift = 14 + ((s->cr[0x17] >> 6) & 1);
  1185 + addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1083 1186 }
1084 1187 if (!(s->cr[0x17] & 2)) {
1085   - addr = (addr & ~0x4000) | ((y & 2) << 13);
  1188 + addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1086 1189 }
1087 1190 page0 = addr >> 12;
1088 1191 page1 = (addr + bwidth - 1) >> 12;
... ... @@ -1103,21 +1206,26 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1103 1206 if (y_start >= 0) {
1104 1207 /* flush to display */
1105 1208 dpy_update(s->ds, 0, y_start,
1106   - width, y - y_start);
  1209 + disp_width, y - y_start);
1107 1210 y_start = -1;
1108 1211 }
1109 1212 }
1110   - if (y == s->line_compare) {
1111   - addr1 = 0;
1112   - } else {
1113   - addr1 += line_offset;
  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++;
1114 1222 }
1115 1223 d += linesize;
1116 1224 }
1117 1225 if (y_start >= 0) {
1118 1226 /* flush to display */
1119 1227 dpy_update(s->ds, 0, y_start,
1120   - width, y - y_start);
  1228 + disp_width, y - y_start);
1121 1229 }
1122 1230 /* reset modified pages */
1123 1231 if (page_max != -1) {
... ... @@ -1199,7 +1307,7 @@ int vga_init(DisplayState *ds, uint8_t *vga_ram_base,
1199 1307 unsigned long vga_ram_offset, int vga_ram_size)
1200 1308 {
1201 1309 VGAState *s = &vga_state;
1202   - int i, j, v;
  1310 + int i, j, v, b;
1203 1311  
1204 1312 for(i = 0;i < 256; i++) {
1205 1313 v = 0;
... ... @@ -1214,9 +1322,34 @@ int vga_init(DisplayState *ds, uint8_t *vga_ram_base,
1214 1322 }
1215 1323 expand2[i] = v;
1216 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 + }
1217 1334  
1218 1335 vga_reset(s);
1219 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 +
1220 1353 s->vram_ptr = vga_ram_base;
1221 1354 s->vram_offset = vga_ram_offset;
1222 1355 s->vram_size = vga_ram_size;
... ...
hw/vga_template.h
... ... @@ -37,15 +37,11 @@
37 37  
38 38 #if DEPTH != 15
39 39  
40   -static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
41   - const uint8_t *font_ptr, int h,
42   - uint32_t fgcol, uint32_t bgcol)
  40 +static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
  41 + uint32_t font_data,
  42 + uint32_t xorcol,
  43 + uint32_t bgcol)
43 44 {
44   - uint32_t font_data, xorcol;
45   -
46   - xorcol = bgcol ^ fgcol;
47   - do {
48   - font_data = font_ptr[0];
49 45 #if BPP == 1
50 46 ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
51 47 ((uint32_t *)d)[3] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
... ... @@ -64,6 +60,38 @@ static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
64 60 ((uint32_t *)d)[6] = ((-(font_data >> 1) & 1) & xorcol) ^ bgcol;
65 61 ((uint32_t *)d)[7] = ((-(font_data >> 0) & 1) & xorcol) ^ bgcol;
66 62 #endif
  63 +}
  64 +
  65 +static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
  66 + const uint8_t *font_ptr, int h,
  67 + uint32_t fgcol, uint32_t bgcol)
  68 +{
  69 + uint32_t font_data, xorcol;
  70 +
  71 + xorcol = bgcol ^ fgcol;
  72 + do {
  73 + font_data = font_ptr[0];
  74 + glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
  75 + font_ptr += 4;
  76 + d += linesize;
  77 + } while (--h);
  78 +}
  79 +
  80 +static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
  81 + const uint8_t *font_ptr, int h,
  82 + uint32_t fgcol, uint32_t bgcol)
  83 +{
  84 + uint32_t font_data, xorcol;
  85 +
  86 + xorcol = bgcol ^ fgcol;
  87 + do {
  88 + font_data = font_ptr[0];
  89 + glue(vga_draw_glyph_line_, DEPTH)(d,
  90 + expand4to8[font_data >> 4],
  91 + xorcol, bgcol);
  92 + glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
  93 + expand4to8[font_data & 0x0f],
  94 + xorcol, bgcol);
67 95 font_ptr += 4;
68 96 d += linesize;
69 97 } while (--h);
... ... @@ -151,6 +179,48 @@ static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d,
151 179 }
152 180 }
153 181  
  182 +#if BPP == 1
  183 +#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
  184 +#elif BPP == 2
  185 +#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
  186 +#else
  187 +#define PUT_PIXEL2(d, n, v) \
  188 +((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
  189 +#endif
  190 +
  191 +/*
  192 + * 4 color mode, dup2 horizontal
  193 + */
  194 +static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d,
  195 + const uint8_t *s, int width)
  196 +{
  197 + uint32_t plane_mask, *palette, data, v;
  198 + int x;
  199 +
  200 + palette = s1->last_palette;
  201 + plane_mask = mask16[s1->ar[0x12] & 0xf];
  202 + width >>= 3;
  203 + for(x = 0; x < width; x++) {
  204 + data = ((uint32_t *)s)[0];
  205 + data &= plane_mask;
  206 + v = expand2[GET_PLANE(data, 0)];
  207 + v |= expand2[GET_PLANE(data, 2)] << 2;
  208 + PUT_PIXEL2(d, 0, palette[v >> 12]);
  209 + PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
  210 + PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
  211 + PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
  212 +
  213 + v = expand2[GET_PLANE(data, 1)];
  214 + v |= expand2[GET_PLANE(data, 3)] << 2;
  215 + PUT_PIXEL2(d, 4, palette[v >> 12]);
  216 + PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
  217 + PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
  218 + PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
  219 + d += BPP * 16;
  220 + s += 4;
  221 + }
  222 +}
  223 +
154 224 /*
155 225 * 16 color mode
156 226 */
... ... @@ -184,7 +254,62 @@ static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d,
184 254 }
185 255  
186 256 /*
187   - * 256 color mode
  257 + * 16 color mode, dup2 horizontal
  258 + */
  259 +static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d,
  260 + const uint8_t *s, int width)
  261 +{
  262 + uint32_t plane_mask, data, v, *palette;
  263 + int x;
  264 +
  265 + palette = s1->last_palette;
  266 + plane_mask = mask16[s1->ar[0x12] & 0xf];
  267 + width >>= 3;
  268 + for(x = 0; x < width; x++) {
  269 + data = ((uint32_t *)s)[0];
  270 + data &= plane_mask;
  271 + v = expand4[GET_PLANE(data, 0)];
  272 + v |= expand4[GET_PLANE(data, 1)] << 1;
  273 + v |= expand4[GET_PLANE(data, 2)] << 2;
  274 + v |= expand4[GET_PLANE(data, 3)] << 3;
  275 + PUT_PIXEL2(d, 0, palette[v >> 28]);
  276 + PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
  277 + PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
  278 + PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
  279 + PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
  280 + PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
  281 + PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
  282 + PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
  283 + d += BPP * 16;
  284 + s += 4;
  285 + }
  286 +}
  287 +
  288 +/*
  289 + * 256 color mode, double pixels
  290 + *
  291 + * XXX: add plane_mask support (never used in standard VGA modes)
  292 + */
  293 +static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d,
  294 + const uint8_t *s, int width)
  295 +{
  296 + uint32_t *palette;
  297 + int x;
  298 +
  299 + palette = s1->last_palette;
  300 + width >>= 3;
  301 + for(x = 0; x < width; x++) {
  302 + PUT_PIXEL2(d, 0, palette[s[0]]);
  303 + PUT_PIXEL2(d, 1, palette[s[1]]);
  304 + PUT_PIXEL2(d, 2, palette[s[2]]);
  305 + PUT_PIXEL2(d, 3, palette[s[3]]);
  306 + d += BPP * 8;
  307 + s += 4;
  308 + }
  309 +}
  310 +
  311 +/*
  312 + * standard 256 color mode
188 313 *
189 314 * XXX: add plane_mask support (never used in standard VGA modes)
190 315 */
... ... @@ -289,6 +414,7 @@ static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d,
289 414 #endif
290 415 }
291 416  
  417 +#undef PUT_PIXEL2
292 418 #undef DEPTH
293 419 #undef BPP
294 420 #undef PIXEL_TYPE
... ...