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,6 +49,7 @@
49 #include "thunk.h" 49 #include "thunk.h"
50 50
51 //#define DEBUG_VGA 51 //#define DEBUG_VGA
  52 +//#define DEBUG_VGA_MEM
52 53
53 #define MSR_COLOR_EMULATION 0x01 54 #define MSR_COLOR_EMULATION 0x01
54 #define MSR_PAGE_SELECT 0x20 55 #define MSR_PAGE_SELECT 0x20
@@ -85,7 +86,8 @@ typedef struct VGAState { @@ -85,7 +86,8 @@ typedef struct VGAState {
85 DisplayState *ds; 86 DisplayState *ds;
86 uint32_t font_offsets[2]; 87 uint32_t font_offsets[2];
87 int graphic_mode; 88 int graphic_mode;
88 - int shift_control; 89 + uint8_t shift_control;
  90 + uint8_t double_scan;
89 uint32_t line_offset; 91 uint32_t line_offset;
90 uint32_t line_compare; 92 uint32_t line_compare;
91 uint32_t start_addr; 93 uint32_t start_addr;
@@ -93,10 +95,11 @@ typedef struct VGAState { @@ -93,10 +95,11 @@ typedef struct VGAState {
93 uint32_t last_width, last_height; 95 uint32_t last_width, last_height;
94 uint8_t cursor_start, cursor_end; 96 uint8_t cursor_start, cursor_end;
95 uint32_t cursor_offset; 97 uint32_t cursor_offset;
  98 + unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
96 /* tell for each page if it has been updated since the last time */ 99 /* tell for each page if it has been updated since the last time */
97 uint8_t vram_updated[VGA_RAM_SIZE / 4096]; 100 uint8_t vram_updated[VGA_RAM_SIZE / 4096];
98 uint32_t last_palette[256]; 101 uint32_t last_palette[256];
99 -#define CH_ATTR_SIZE (132 * 60) 102 +#define CH_ATTR_SIZE (160 * 100)
100 uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ 103 uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
101 } VGAState; 104 } VGAState;
102 105
@@ -199,6 +202,7 @@ static const uint32_t dmask4[4] = { @@ -199,6 +202,7 @@ static const uint32_t dmask4[4] = {
199 202
200 static uint32_t expand4[256]; 203 static uint32_t expand4[256];
201 static uint16_t expand2[256]; 204 static uint16_t expand2[256];
  205 +static uint8_t expand4to8[16];
202 206
203 VGAState vga_state; 207 VGAState vga_state;
204 int vga_io_memory; 208 int vga_io_memory;
@@ -503,7 +507,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val) @@ -503,7 +507,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
503 int memory_map_mode, plane, write_mode, b, func_select; 507 int memory_map_mode, plane, write_mode, b, func_select;
504 uint32_t write_mask, bit_mask, set_mask; 508 uint32_t write_mask, bit_mask, set_mask;
505 509
506 -#ifdef DEBUG_VGA 510 +#ifdef DEBUG_VGA_MEM
507 printf("vga: [0x%x] = 0x%02x\n", addr, val); 511 printf("vga: [0x%x] = 0x%02x\n", addr, val);
508 #endif 512 #endif
509 /* convert to VGA memory offset */ 513 /* convert to VGA memory offset */
@@ -533,7 +537,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val) @@ -533,7 +537,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
533 plane = addr & 3; 537 plane = addr & 3;
534 if (s->sr[2] & (1 << plane)) { 538 if (s->sr[2] & (1 << plane)) {
535 s->vram_ptr[addr] = val; 539 s->vram_ptr[addr] = val;
536 -#ifdef DEBUG_VGA 540 +#ifdef DEBUG_VGA_MEM
537 printf("vga: chain4: [0x%x]\n", addr); 541 printf("vga: chain4: [0x%x]\n", addr);
538 #endif 542 #endif
539 s->vram_updated[addr >> 12] = 1; 543 s->vram_updated[addr >> 12] = 1;
@@ -544,7 +548,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val) @@ -544,7 +548,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
544 if (s->sr[2] & (1 << plane)) { 548 if (s->sr[2] & (1 << plane)) {
545 addr = ((addr & ~1) << 1) | plane; 549 addr = ((addr & ~1) << 1) | plane;
546 s->vram_ptr[addr] = val; 550 s->vram_ptr[addr] = val;
547 -#ifdef DEBUG_VGA 551 +#ifdef DEBUG_VGA_MEM
548 printf("vga: odd/even: [0x%x]\n", addr); 552 printf("vga: odd/even: [0x%x]\n", addr);
549 #endif 553 #endif
550 s->vram_updated[addr >> 12] = 1; 554 s->vram_updated[addr >> 12] = 1;
@@ -615,7 +619,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val) @@ -615,7 +619,7 @@ void vga_mem_writeb(uint32_t addr, uint32_t val)
615 ((uint32_t *)s->vram_ptr)[addr] = 619 ((uint32_t *)s->vram_ptr)[addr] =
616 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 620 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
617 (val & write_mask); 621 (val & write_mask);
618 -#ifdef DEBUG_VGA 622 +#ifdef DEBUG_VGA_MEM
619 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 623 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
620 addr * 4, write_mask, val); 624 addr * 4, write_mask, val);
621 #endif 625 #endif
@@ -699,28 +703,43 @@ static inline int c6_to_8(int v) @@ -699,28 +703,43 @@ static inline int c6_to_8(int v)
699 return (v << 2) | (b << 1) | b; 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 /* return true if the palette was modified */ 738 /* return true if the palette was modified */
703 static int update_palette16(VGAState *s) 739 static int update_palette16(VGAState *s)
704 { 740 {
705 - int full_update, i, depth; 741 + int full_update, i;
706 uint32_t v, col, *palette; 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 full_update = 0; 744 full_update = 0;
726 palette = s->last_palette; 745 palette = s->last_palette;
@@ -731,21 +750,35 @@ static int update_palette16(VGAState *s) @@ -731,21 +750,35 @@ static int update_palette16(VGAState *s)
731 else 750 else
732 v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f); 751 v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
733 v = v * 3; 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 if (col != palette[i]) { 777 if (col != palette[i]) {
746 full_update = 1; 778 full_update = 1;
747 palette[i] = col; 779 palette[i] = col;
748 } 780 }
  781 + v += 3;
749 } 782 }
750 return full_update; 783 return full_update;
751 } 784 }
@@ -806,6 +839,13 @@ static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = { @@ -806,6 +839,13 @@ static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
806 vga_draw_glyph8_32, 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 static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = { 849 static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
810 vga_draw_glyph9_8, 850 vga_draw_glyph9_8,
811 vga_draw_glyph9_16, 851 vga_draw_glyph9_16,
@@ -882,12 +922,19 @@ static void vga_draw_text(VGAState *s, int full_update) @@ -882,12 +922,19 @@ static void vga_draw_text(VGAState *s, int full_update)
882 cw = 8; 922 cw = 8;
883 if (s->sr[1] & 0x01) 923 if (s->sr[1] & 0x01)
884 cw = 9; 924 cw = 9;
  925 + if (s->sr[1] & 0x08)
  926 + cw = 16; /* NOTE: no 18 pixel wide */
885 x_incr = cw * ((s->ds->depth + 7) >> 3); 927 x_incr = cw * ((s->ds->depth + 7) >> 3);
886 width = (s->cr[0x01] + 1); 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 if (width != s->last_width || height != s->last_height || 938 if (width != s->last_width || height != s->last_height ||
892 cw != s->last_cw || cw != s->last_cw) { 939 cw != s->last_cw || cw != s->last_cw) {
893 dpy_resize(s->ds, width * cw, height * cheight); 940 dpy_resize(s->ds, width * cw, height * cheight);
@@ -914,7 +961,10 @@ static void vga_draw_text(VGAState *s, int full_update) @@ -914,7 +961,10 @@ static void vga_draw_text(VGAState *s, int full_update)
914 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4; 961 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
915 962
916 depth_index = get_depth_index(s->ds->depth); 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 vga_draw_glyph9 = vga_draw_glyph9_table[depth_index]; 968 vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
919 969
920 dest = s->ds->data; 970 dest = s->ds->data;
@@ -944,7 +994,7 @@ static void vga_draw_text(VGAState *s, int full_update) @@ -944,7 +994,7 @@ static void vga_draw_text(VGAState *s, int full_update)
944 font_ptr += 32 * 4 * ch; 994 font_ptr += 32 * 4 * ch;
945 bgcol = palette[cattr >> 4]; 995 bgcol = palette[cattr >> 4];
946 fgcol = palette[cattr & 0x0f]; 996 fgcol = palette[cattr & 0x0f];
947 - if (cw == 8) { 997 + if (cw != 9) {
948 vga_draw_glyph8(d1, linesize, 998 vga_draw_glyph8(d1, linesize,
949 font_ptr, cheight, fgcol, bgcol); 999 font_ptr, cheight, fgcol, bgcol);
950 } else { 1000 } else {
@@ -966,7 +1016,7 @@ static void vga_draw_text(VGAState *s, int full_update) @@ -966,7 +1016,7 @@ static void vga_draw_text(VGAState *s, int full_update)
966 if (line_last >= line_start && line_start < cheight) { 1016 if (line_last >= line_start && line_start < cheight) {
967 h = line_last - line_start + 1; 1017 h = line_last - line_start + 1;
968 d = d1 + linesize * line_start; 1018 d = d1 + linesize * line_start;
969 - if (cw == 8) { 1019 + if (cw != 9) {
970 vga_draw_glyph8(d, linesize, 1020 vga_draw_glyph8(d, linesize,
971 cursor_glyph, h, fgcol, bgcol); 1021 cursor_glyph, h, fgcol, bgcol);
972 } else { 1022 } else {
@@ -989,17 +1039,45 @@ static void vga_draw_text(VGAState *s, int full_update) @@ -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 vga_draw_line2_8, 1056 vga_draw_line2_8,
994 vga_draw_line2_16, 1057 vga_draw_line2_16,
995 vga_draw_line2_16, 1058 vga_draw_line2_16,
996 vga_draw_line2_32, 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 vga_draw_line4_8, 1066 vga_draw_line4_8,
999 vga_draw_line4_16, 1067 vga_draw_line4_16,
1000 vga_draw_line4_16, 1068 vga_draw_line4_16,
1001 vga_draw_line4_32, 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 vga_draw_line8_8, 1081 vga_draw_line8_8,
1004 vga_draw_line8_16, 1082 vga_draw_line8_16,
1005 vga_draw_line8_16, 1083 vga_draw_line8_16,
@@ -1029,14 +1107,13 @@ static vga_draw_line_func *vga_draw_line_table[4 * 6] = { @@ -1029,14 +1107,13 @@ static vga_draw_line_func *vga_draw_line_table[4 * 6] = {
1029 */ 1107 */
1030 static void vga_draw_graphic(VGAState *s, int full_update) 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 int width, height, shift_control, line_offset, page0, page1, bwidth; 1111 int width, height, shift_control, line_offset, page0, page1, bwidth;
  1112 + int disp_width;
1034 uint8_t *d; 1113 uint8_t *d;
1035 uint32_t v, addr1, addr; 1114 uint32_t v, addr1, addr;
1036 vga_draw_line_func *vga_draw_line; 1115 vga_draw_line_func *vga_draw_line;
1037 -  
1038 - full_update |= update_palette16(s);  
1039 - 1116 +
1040 full_update |= update_basic_params(s); 1117 full_update |= update_basic_params(s);
1041 1118
1042 width = (s->cr[0x01] + 1) * 8; 1119 width = (s->cr[0x01] + 1) * 8;
@@ -1044,30 +1121,53 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1044,30 +1121,53 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1044 ((s->cr[0x07] & 0x02) << 7) | 1121 ((s->cr[0x07] & 0x02) << 7) |
1045 ((s->cr[0x07] & 0x40) << 3); 1122 ((s->cr[0x07] & 0x40) << 3);
1046 height = (height + 1); 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 shift_control = (s->gr[0x05] >> 5) & 3; 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 full_update = 1; 1130 full_update = 1;
1059 s->shift_control = shift_control; 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 vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)]; 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 line_offset = s->line_offset; 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 addr1 = (s->start_addr * 4); 1171 addr1 = (s->start_addr * 4);
1072 bwidth = width * 4; 1172 bwidth = width * 4;
1073 y_start = -1; 1173 y_start = -1;
@@ -1075,14 +1175,17 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1075,14 +1175,17 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1075 page_max = -1; 1175 page_max = -1;
1076 d = s->ds->data; 1176 d = s->ds->data;
1077 linesize = s->ds->linesize; 1177 linesize = s->ds->linesize;
  1178 + y1 = 0;
1078 for(y = 0; y < height; y++) { 1179 for(y = 0; y < height; y++) {
1079 addr = addr1; 1180 addr = addr1;
1080 if (!(s->cr[0x17] & 1)) { 1181 if (!(s->cr[0x17] & 1)) {
  1182 + int shift;
1081 /* CGA compatibility handling */ 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 if (!(s->cr[0x17] & 2)) { 1187 if (!(s->cr[0x17] & 2)) {
1085 - addr = (addr & ~0x4000) | ((y & 2) << 13); 1188 + addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1086 } 1189 }
1087 page0 = addr >> 12; 1190 page0 = addr >> 12;
1088 page1 = (addr + bwidth - 1) >> 12; 1191 page1 = (addr + bwidth - 1) >> 12;
@@ -1103,21 +1206,26 @@ static void vga_draw_graphic(VGAState *s, int full_update) @@ -1103,21 +1206,26 @@ static void vga_draw_graphic(VGAState *s, int full_update)
1103 if (y_start >= 0) { 1206 if (y_start >= 0) {
1104 /* flush to display */ 1207 /* flush to display */
1105 dpy_update(s->ds, 0, y_start, 1208 dpy_update(s->ds, 0, y_start,
1106 - width, y - y_start); 1209 + disp_width, y - y_start);
1107 y_start = -1; 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 d += linesize; 1223 d += linesize;
1116 } 1224 }
1117 if (y_start >= 0) { 1225 if (y_start >= 0) {
1118 /* flush to display */ 1226 /* flush to display */
1119 dpy_update(s->ds, 0, y_start, 1227 dpy_update(s->ds, 0, y_start,
1120 - width, y - y_start); 1228 + disp_width, y - y_start);
1121 } 1229 }
1122 /* reset modified pages */ 1230 /* reset modified pages */
1123 if (page_max != -1) { 1231 if (page_max != -1) {
@@ -1199,7 +1307,7 @@ int vga_init(DisplayState *ds, uint8_t *vga_ram_base, @@ -1199,7 +1307,7 @@ int vga_init(DisplayState *ds, uint8_t *vga_ram_base,
1199 unsigned long vga_ram_offset, int vga_ram_size) 1307 unsigned long vga_ram_offset, int vga_ram_size)
1200 { 1308 {
1201 VGAState *s = &vga_state; 1309 VGAState *s = &vga_state;
1202 - int i, j, v; 1310 + int i, j, v, b;
1203 1311
1204 for(i = 0;i < 256; i++) { 1312 for(i = 0;i < 256; i++) {
1205 v = 0; 1313 v = 0;
@@ -1214,9 +1322,34 @@ int vga_init(DisplayState *ds, uint8_t *vga_ram_base, @@ -1214,9 +1322,34 @@ int vga_init(DisplayState *ds, uint8_t *vga_ram_base,
1214 } 1322 }
1215 expand2[i] = v; 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 vga_reset(s); 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 s->vram_ptr = vga_ram_base; 1353 s->vram_ptr = vga_ram_base;
1221 s->vram_offset = vga_ram_offset; 1354 s->vram_offset = vga_ram_offset;
1222 s->vram_size = vga_ram_size; 1355 s->vram_size = vga_ram_size;
hw/vga_template.h
@@ -37,15 +37,11 @@ @@ -37,15 +37,11 @@
37 37
38 #if DEPTH != 15 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 #if BPP == 1 45 #if BPP == 1
50 ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; 46 ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
51 ((uint32_t *)d)[3] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; 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,6 +60,38 @@ static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
64 ((uint32_t *)d)[6] = ((-(font_data >> 1) & 1) & xorcol) ^ bgcol; 60 ((uint32_t *)d)[6] = ((-(font_data >> 1) & 1) & xorcol) ^ bgcol;
65 ((uint32_t *)d)[7] = ((-(font_data >> 0) & 1) & xorcol) ^ bgcol; 61 ((uint32_t *)d)[7] = ((-(font_data >> 0) & 1) & xorcol) ^ bgcol;
66 #endif 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 font_ptr += 4; 95 font_ptr += 4;
68 d += linesize; 96 d += linesize;
69 } while (--h); 97 } while (--h);
@@ -151,6 +179,48 @@ static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d, @@ -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 * 16 color mode 225 * 16 color mode
156 */ 226 */
@@ -184,7 +254,62 @@ static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d, @@ -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 * XXX: add plane_mask support (never used in standard VGA modes) 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,6 +414,7 @@ static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d,
289 #endif 414 #endif
290 } 415 }
291 416
  417 +#undef PUT_PIXEL2
292 #undef DEPTH 418 #undef DEPTH
293 #undef BPP 419 #undef BPP
294 #undef PIXEL_TYPE 420 #undef PIXEL_TYPE