Commit 17b0018b4200b674bfcb7c946fce89f0a5ffaa24
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 | ... | ... |