1 /*
2 * Copyright (C) 2002-2015 The DOSBox Team
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19
20 #include <string.h>
21
22 #include "dosbox.h"
23 #include "mem.h"
24 #include "inout.h"
25 #include "int10.h"
26 #include "vga.h"
27
28 #define _EGA_HALF_CLOCK 0x0001
29 #define _EGA_LINE_DOUBLE 0x0002
30 #define _VGA_PIXEL_DOUBLE 0x0004
31
32 #define SEQ_REGS 0x05
33 #define GFX_REGS 0x09
34 #define ATT_REGS 0x15
35
36 VideoModeBlock ModeList_VGA[]={
37 /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
38 { 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
39 { 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
40 { 0x002 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
41 { 0x003 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
42 { 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
43 { 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
44 { 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE},
45 { 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
46
47 { 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE },
48 { 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE },
49 { 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },/*was EGA_2*/
50 { 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },
51 { 0x011 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */
52 { 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },
53 { 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 },
54
55 { 0x054 ,M_TEXT ,1056,344, 132,43, 8, 8, 1 ,0xB8000 ,0x4000, 160, 449, 132,344, 0 },
56 { 0x055 ,M_TEXT ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 160, 449, 132,400, 0 },
57
58 /* Alias of mode 101 */
59 { 0x069 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
60 /* Alias of mode 102 */
61 { 0x06A ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 ,0 },
62
63 /* Follow vesa 1.2 for first 0x20 */
64 { 0x100 ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 },
65 { 0x101 ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
66 { 0x102 ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 },
67 { 0x103 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 },
68 { 0x104 ,M_LIN4 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 },
69 { 0x105 ,M_LIN8 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 },
70 { 0x106 ,M_LIN4 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 },
71 { 0x107 ,M_LIN8 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 },
72
73 /* VESA text modes */
74 { 0x108 ,M_TEXT ,640 ,480, 80,60, 8, 8 ,2 ,0xB8000 ,0x4000, 100 ,525 ,80 ,480 ,0 },
75 { 0x109 ,M_TEXT ,1056,400, 132,25, 8, 16, 1 ,0xB8000 ,0x2000, 160, 449, 132,400, 0 },
76 { 0x10A ,M_TEXT ,1056,688, 132,43, 8, 8, 1 ,0xB8000 ,0x4000, 160, 449, 132,344, 0 },
77 { 0x10B ,M_TEXT ,1056,400, 132,50, 8, 8, 1 ,0xB8000 ,0x4000, 160, 449, 132,400, 0 },
78 { 0x10C ,M_TEXT ,1056,480, 132,60, 8, 8, 2 ,0xB8000 ,0x4000, 160, 531, 132,480, 0 },
79
80 /* VESA higher color modes */
81 { 0x10D ,M_LIN15 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
82 { 0x10E ,M_LIN16 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
83 { 0x10F ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
84 { 0x110 ,M_LIN15 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0 },
85 { 0x111 ,M_LIN16 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0 },
86 { 0x112 ,M_LIN32 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
87 { 0x113 ,M_LIN15 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0 },
88 { 0x114 ,M_LIN16 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,628 ,200,600 ,0 },
89 { 0x115 ,M_LIN32 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 },
90 { 0x116 ,M_LIN15 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0 },
91 { 0x117 ,M_LIN16 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,336 ,806 ,256,768 ,0 },
92 { 0x118 ,M_LIN32 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 },
93
94 /* those should be interlaced but ok */
95 //{ 0x119 ,M_LIN15 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0 },
96 //{ 0x11A ,M_LIN16 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,424 ,1066,320,1024,0 },
97
98 { 0x150 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
99 { 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
100 { 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE },
101 { 0x153 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _VGA_PIXEL_DOUBLE },
102
103 { 0x160 ,M_LIN15 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
104 { 0x161 ,M_LIN15 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 , _VGA_PIXEL_DOUBLE },
105 { 0x162 ,M_LIN15 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE },
106 { 0x165 ,M_LIN15 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 },
107
108 { 0x170 ,M_LIN16 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
109 { 0x171 ,M_LIN16 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 , _VGA_PIXEL_DOUBLE },
110 { 0x172 ,M_LIN16 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _VGA_PIXEL_DOUBLE },
111 { 0x175 ,M_LIN16 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 },
112
113 { 0x190 ,M_LIN32 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _VGA_PIXEL_DOUBLE | _EGA_LINE_DOUBLE },
114 { 0x191 ,M_LIN32 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,449 ,40 ,400 , _VGA_PIXEL_DOUBLE },
115 { 0x192 ,M_LIN32 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _VGA_PIXEL_DOUBLE },
116
117 /* S3 specific modes */
118 { 0x207 ,M_LIN8 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0 },
119 { 0x209 ,M_LIN15 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0 },
120 { 0x20A ,M_LIN16 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,364 ,948 ,288,864 ,0 },
121 //{ 0x20B ,M_LIN32 ,1152,864,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,182 ,948 ,144,864 ,0 },
122 { 0x213 ,M_LIN32 ,640 ,400,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 ,0 },
123
124 /* Some custom modes */
125 //{ 0x220 ,M_LIN32 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0x10000,212 ,1066,160,1024,0 },
126 // A nice 16:9 mode
127 { 0x222 ,M_LIN8 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0 },
128 { 0x223 ,M_LIN15 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,0 },
129 { 0x224 ,M_LIN16 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,264 ,525 ,212 ,480 ,0 },
130 { 0x225 ,M_LIN32 ,848 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,525 ,106 ,480 ,0 },
131
132 {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
133 };
134
135 VideoModeBlock ModeList_VGA_Text_200lines[]={
136 /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
137 { 0x000 ,M_TEXT ,320 ,200 ,40 ,25 ,8 , 8 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
138 { 0x001 ,M_TEXT ,320 ,200 ,40 ,25 ,8 , 8 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
139 { 0x002 ,M_TEXT ,640 ,200 ,80 ,25 ,8 , 8 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE },
140 { 0x003 ,M_TEXT ,640 ,200 ,80 ,25 ,8 , 8 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE }
141 };
142
143 VideoModeBlock ModeList_VGA_Text_350lines[]={
144 /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
145 { 0x000 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,350 ,_EGA_HALF_CLOCK },
146 { 0x001 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,350 ,_EGA_HALF_CLOCK },
147 { 0x002 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,350 ,0 },
148 { 0x003 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,350 ,0 },
149 { 0x007 ,M_TEXT ,720 ,350 ,80 ,25 ,9 ,14 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,350 ,0 }
150 };
151
152 VideoModeBlock ModeList_VGA_Tseng[]={
153 /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
154 { 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
155 { 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
156 { 0x002 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
157 { 0x003 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
158 { 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
159 { 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
160 { 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE},
161 { 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
162
163 { 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE },
164 { 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE },
165 { 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },/*was EGA_2*/
166 { 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },
167 { 0x011 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */
168 { 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },
169 { 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 },
170
171 { 0x018 ,M_TEXT ,1056 ,688, 132,44, 8, 8, 1 ,0xB0000 ,0x4000, 192, 800, 132, 704, 0 },
172 { 0x019 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 400, 0 },
173 { 0x01A ,M_TEXT ,1056 ,400, 132,28, 8, 16,1 ,0xB0000 ,0x2000, 192, 449, 132, 448, 0 },
174 { 0x022 ,M_TEXT ,1056 ,688, 132,44, 8, 8, 1 ,0xB8000 ,0x4000, 192, 800, 132, 704, 0 },
175 { 0x023 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 400, 0 },
176 { 0x024 ,M_TEXT ,1056 ,400, 132,28, 8, 16,1 ,0xB8000 ,0x2000, 192, 449, 132, 448, 0 },
177 { 0x025 ,M_LIN4 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 , 0 },
178 { 0x029 ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },
179 { 0x02D ,M_LIN8 ,640 ,350 ,80 ,21 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,350 , 0 },
180 { 0x02E ,M_LIN8 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , 0 },
181 { 0x02F ,M_LIN8 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , 0 },/* ET4000 only */
182 { 0x030 ,M_LIN8 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,663 ,100,600 , 0 },
183 { 0x036 ,M_LIN4 ,960 , 720,120,45 ,8 ,16 ,1 ,0xA0000 ,0xA000, 120 ,800 ,120,720 , 0 },/* STB only */
184 { 0x037 ,M_LIN4 ,1024, 768,128,48 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,800 ,128,768 , 0 },
185 { 0x038 ,M_LIN8 ,1024 ,768,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,128 ,800 ,128,768 , 0 },/* ET4000 only */
186 { 0x03D ,M_LIN4 ,1280,1024,160,64 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1152,160,1024, 0 },/* newer ET4000 */
187 { 0x03E ,M_LIN4 ,1280, 960,160,60 ,8 ,16 ,1 ,0xA0000 ,0xA000, 160 ,1024,160,960 , 0 },/* Definicon only */
188 { 0x06A ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },/* newer ET4000 */
189
190 {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
191 };
192
193 VideoModeBlock ModeList_VGA_Paradise[]={
194 /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
195 { 0x000 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
196 { 0x001 ,M_TEXT ,360 ,400 ,40 ,25 ,9 ,16 ,8 ,0xB8000 ,0x0800 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK },
197 { 0x002 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
198 { 0x003 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB8000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
199 { 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
200 { 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
201 { 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE},
202 { 0x007 ,M_TEXT ,720 ,400 ,80 ,25 ,9 ,16 ,8 ,0xB0000 ,0x1000 ,100 ,449 ,80 ,400 ,0 },
203
204 { 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,50 ,449 ,40 ,400 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE },
205 { 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,100 ,449 ,80 ,400 ,_EGA_LINE_DOUBLE },
206 { 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },/*was EGA_2*/
207 { 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,100 ,449 ,80 ,350 ,0 },
208 { 0x011 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },/*was EGA_2 */
209 { 0x012 ,M_EGA ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0xA000 ,100 ,525 ,80 ,480 ,0 },
210 { 0x013 ,M_VGA ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x2000 ,100 ,449 ,80 ,400 ,0 },
211
212 { 0x054 ,M_TEXT ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 },
213 { 0x055 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 },
214 { 0x056 ,M_TEXT ,1056 ,688, 132,43, 8, 9, 1, 0xB0000, 0x4000, 192, 720, 132,688, 0 },
215 { 0x057 ,M_TEXT ,1056 ,400, 132,25, 8, 16,1, 0xB0000, 0x2000, 192, 449, 132,400, 0 },
216 { 0x058 ,M_LIN4 ,800 , 600, 100,37, 8, 16,1, 0xA0000, 0xA000, 128 ,663 ,100,600, 0 },
217 { 0x05D ,M_LIN4 ,1024, 768, 128,48 ,8, 16,1, 0xA0000, 0x10000,128 ,800 ,128,768 ,0 }, // documented only on C00 upwards
218 { 0x05E ,M_LIN8 ,640 , 400, 80 ,25, 8, 16,1, 0xA0000, 0x10000,100 ,449 ,80 ,400, 0 },
219 { 0x05F ,M_LIN8 ,640 , 480, 80 ,30, 8, 16,1, 0xA0000, 0x10000,100 ,525 ,80 ,480, 0 },
220
221 {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
222 };
223
224
225 VideoModeBlock ModeList_EGA[]={
226 /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde special flags */
227 { 0x000 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,366 ,40 ,350 ,_EGA_HALF_CLOCK },
228 { 0x001 ,M_TEXT ,320 ,350 ,40 ,25 ,8 ,14 ,8 ,0xB8000 ,0x0800 ,50 ,366 ,40 ,350 ,_EGA_HALF_CLOCK },
229 { 0x002 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,96 ,366 ,80 ,350 ,0 },
230 { 0x003 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,8 ,0xB8000 ,0x1000 ,96 ,366 ,80 ,350 ,0 },
231 { 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,60 ,262 ,40 ,200 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
232 { 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,60 ,262 ,40 ,200 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE},
233 { 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,120 ,262 ,80 ,200 ,_EGA_LINE_DOUBLE},
234 { 0x007 ,M_TEXT ,720 ,350 ,80 ,25 ,9 ,14 ,8 ,0xB0000 ,0x1000 ,120 ,440 ,80 ,350 ,0 },
235
236 { 0x00D ,M_EGA ,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xA0000 ,0x2000 ,60 ,262 ,40 ,200 ,_EGA_HALF_CLOCK | _EGA_LINE_DOUBLE },
237 { 0x00E ,M_EGA ,640 ,200 ,80 ,25 ,8 ,8 ,4 ,0xA0000 ,0x4000 ,120 ,262 ,80 ,200 ,_EGA_LINE_DOUBLE },
238 { 0x00F ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,96 ,366 ,80 ,350 ,0 },/*was EGA_2*/
239 { 0x010 ,M_EGA ,640 ,350 ,80 ,25 ,8 ,14 ,2 ,0xA0000 ,0x8000 ,96 ,366 ,80 ,350 ,0 },
240
241 {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
242 };
243
244 VideoModeBlock ModeList_OTHER[]={
245 /* mode ,type ,sw ,sh ,tw ,th ,cw,ch ,pt,pstart ,plength,htot,vtot,hde,vde ,special flags */
246 { 0x000 ,M_TEXT ,320 ,400 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x0800 ,56 ,31 ,40 ,25 ,0 },
247 { 0x001 ,M_TEXT ,320 ,400 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x0800 ,56 ,31 ,40 ,25 ,0 },
248 { 0x002 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x1000 ,113 ,31 ,80 ,25 ,0 },
249 { 0x003 ,M_TEXT ,640 ,400 ,80 ,25 ,8 ,8 ,4 ,0xB8000 ,0x1000 ,113 ,31 ,80 ,25 ,0 },
250 { 0x004 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,56 ,127 ,40 ,100 ,0 },
251 { 0x005 ,M_CGA4 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,56 ,127 ,40 ,100 ,0 },
252 { 0x006 ,M_CGA2 ,640 ,200 ,80 ,25 ,8 ,8 ,1 ,0xB8000 ,0x4000 ,56 ,127 ,40 ,100 ,0 },
253 { 0x008 ,M_TANDY16,160 ,200 ,20 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,56 ,127 ,40 ,100 ,0 },
254 { 0x009 ,M_TANDY16,320 ,200 ,40 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 },
255 { 0x00A ,M_CGA4 ,640 ,200 ,80 ,25 ,8 ,8 ,8 ,0xB8000 ,0x2000 ,113 ,63 ,80 ,50 ,0 },
256 //{ 0x00E ,M_TANDY16,640 ,200 ,80 ,25 ,8 ,8 ,8 ,0xA0000 ,0x10000 ,113 ,256 ,80 ,200 ,0 },
257 {0xFFFF ,M_ERROR ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x00000 ,0x0000 ,0 ,0 ,0 ,0 ,0 },
258 };
259
260 VideoModeBlock Hercules_Mode=
261 { 0x007 ,M_TEXT ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xB0000 ,0x1000 ,97 ,25 ,80 ,25 ,0 };
262
263 static Bit8u text_palette[64][3]=
264 {
265 {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x2a,0x00},{0x2a,0x2a,0x2a},
266 {0x00,0x00,0x15},{0x00,0x00,0x3f},{0x00,0x2a,0x15},{0x00,0x2a,0x3f},{0x2a,0x00,0x15},{0x2a,0x00,0x3f},{0x2a,0x2a,0x15},{0x2a,0x2a,0x3f},
267 {0x00,0x15,0x00},{0x00,0x15,0x2a},{0x00,0x3f,0x00},{0x00,0x3f,0x2a},{0x2a,0x15,0x00},{0x2a,0x15,0x2a},{0x2a,0x3f,0x00},{0x2a,0x3f,0x2a},
268 {0x00,0x15,0x15},{0x00,0x15,0x3f},{0x00,0x3f,0x15},{0x00,0x3f,0x3f},{0x2a,0x15,0x15},{0x2a,0x15,0x3f},{0x2a,0x3f,0x15},{0x2a,0x3f,0x3f},
269 {0x15,0x00,0x00},{0x15,0x00,0x2a},{0x15,0x2a,0x00},{0x15,0x2a,0x2a},{0x3f,0x00,0x00},{0x3f,0x00,0x2a},{0x3f,0x2a,0x00},{0x3f,0x2a,0x2a},
270 {0x15,0x00,0x15},{0x15,0x00,0x3f},{0x15,0x2a,0x15},{0x15,0x2a,0x3f},{0x3f,0x00,0x15},{0x3f,0x00,0x3f},{0x3f,0x2a,0x15},{0x3f,0x2a,0x3f},
271 {0x15,0x15,0x00},{0x15,0x15,0x2a},{0x15,0x3f,0x00},{0x15,0x3f,0x2a},{0x3f,0x15,0x00},{0x3f,0x15,0x2a},{0x3f,0x3f,0x00},{0x3f,0x3f,0x2a},
272 {0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f}
273 };
274
275 static Bit8u mtext_palette[64][3]=
276 {
277 {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
278 {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
279 {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
280 {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},
281 {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
282 {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
283 {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
284 {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f}
285 };
286
287 static Bit8u mtext_s3_palette[64][3]=
288 {
289 {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
290 {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
291 {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
292 {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},
293 {0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},{0x00,0x00,0x00},
294 {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
295 {0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},{0x2a,0x2a,0x2a},
296 {0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f},{0x3f,0x3f,0x3f}
297 };
298
299 static Bit8u ega_palette[64][3]=
300 {
301 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
302 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
303 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
304 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
305 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
306 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
307 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
308 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}
309 };
310
311 static Bit8u cga_palette[16][3]=
312 {
313 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
314 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
315 };
316
317 static Bit8u cga_palette_2[64][3]=
318 {
319 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
320 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
321 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
322 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
323 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
324 {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
325 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
326 {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
327 };
328
329 static Bit8u vga_palette[248][3]=
330 {
331 {0x00,0x00,0x00},{0x00,0x00,0x2a},{0x00,0x2a,0x00},{0x00,0x2a,0x2a},{0x2a,0x00,0x00},{0x2a,0x00,0x2a},{0x2a,0x15,0x00},{0x2a,0x2a,0x2a},
332 {0x15,0x15,0x15},{0x15,0x15,0x3f},{0x15,0x3f,0x15},{0x15,0x3f,0x3f},{0x3f,0x15,0x15},{0x3f,0x15,0x3f},{0x3f,0x3f,0x15},{0x3f,0x3f,0x3f},
333 {0x00,0x00,0x00},{0x05,0x05,0x05},{0x08,0x08,0x08},{0x0b,0x0b,0x0b},{0x0e,0x0e,0x0e},{0x11,0x11,0x11},{0x14,0x14,0x14},{0x18,0x18,0x18},
334 {0x1c,0x1c,0x1c},{0x20,0x20,0x20},{0x24,0x24,0x24},{0x28,0x28,0x28},{0x2d,0x2d,0x2d},{0x32,0x32,0x32},{0x38,0x38,0x38},{0x3f,0x3f,0x3f},
335 {0x00,0x00,0x3f},{0x10,0x00,0x3f},{0x1f,0x00,0x3f},{0x2f,0x00,0x3f},{0x3f,0x00,0x3f},{0x3f,0x00,0x2f},{0x3f,0x00,0x1f},{0x3f,0x00,0x10},
336 {0x3f,0x00,0x00},{0x3f,0x10,0x00},{0x3f,0x1f,0x00},{0x3f,0x2f,0x00},{0x3f,0x3f,0x00},{0x2f,0x3f,0x00},{0x1f,0x3f,0x00},{0x10,0x3f,0x00},
337 {0x00,0x3f,0x00},{0x00,0x3f,0x10},{0x00,0x3f,0x1f},{0x00,0x3f,0x2f},{0x00,0x3f,0x3f},{0x00,0x2f,0x3f},{0x00,0x1f,0x3f},{0x00,0x10,0x3f},
338 {0x1f,0x1f,0x3f},{0x27,0x1f,0x3f},{0x2f,0x1f,0x3f},{0x37,0x1f,0x3f},{0x3f,0x1f,0x3f},{0x3f,0x1f,0x37},{0x3f,0x1f,0x2f},{0x3f,0x1f,0x27},
339
340 {0x3f,0x1f,0x1f},{0x3f,0x27,0x1f},{0x3f,0x2f,0x1f},{0x3f,0x37,0x1f},{0x3f,0x3f,0x1f},{0x37,0x3f,0x1f},{0x2f,0x3f,0x1f},{0x27,0x3f,0x1f},
341 {0x1f,0x3f,0x1f},{0x1f,0x3f,0x27},{0x1f,0x3f,0x2f},{0x1f,0x3f,0x37},{0x1f,0x3f,0x3f},{0x1f,0x37,0x3f},{0x1f,0x2f,0x3f},{0x1f,0x27,0x3f},
342 {0x2d,0x2d,0x3f},{0x31,0x2d,0x3f},{0x36,0x2d,0x3f},{0x3a,0x2d,0x3f},{0x3f,0x2d,0x3f},{0x3f,0x2d,0x3a},{0x3f,0x2d,0x36},{0x3f,0x2d,0x31},
343 {0x3f,0x2d,0x2d},{0x3f,0x31,0x2d},{0x3f,0x36,0x2d},{0x3f,0x3a,0x2d},{0x3f,0x3f,0x2d},{0x3a,0x3f,0x2d},{0x36,0x3f,0x2d},{0x31,0x3f,0x2d},
344 {0x2d,0x3f,0x2d},{0x2d,0x3f,0x31},{0x2d,0x3f,0x36},{0x2d,0x3f,0x3a},{0x2d,0x3f,0x3f},{0x2d,0x3a,0x3f},{0x2d,0x36,0x3f},{0x2d,0x31,0x3f},
345 {0x00,0x00,0x1c},{0x07,0x00,0x1c},{0x0e,0x00,0x1c},{0x15,0x00,0x1c},{0x1c,0x00,0x1c},{0x1c,0x00,0x15},{0x1c,0x00,0x0e},{0x1c,0x00,0x07},
346 {0x1c,0x00,0x00},{0x1c,0x07,0x00},{0x1c,0x0e,0x00},{0x1c,0x15,0x00},{0x1c,0x1c,0x00},{0x15,0x1c,0x00},{0x0e,0x1c,0x00},{0x07,0x1c,0x00},
347 {0x00,0x1c,0x00},{0x00,0x1c,0x07},{0x00,0x1c,0x0e},{0x00,0x1c,0x15},{0x00,0x1c,0x1c},{0x00,0x15,0x1c},{0x00,0x0e,0x1c},{0x00,0x07,0x1c},
348
349 {0x0e,0x0e,0x1c},{0x11,0x0e,0x1c},{0x15,0x0e,0x1c},{0x18,0x0e,0x1c},{0x1c,0x0e,0x1c},{0x1c,0x0e,0x18},{0x1c,0x0e,0x15},{0x1c,0x0e,0x11},
350 {0x1c,0x0e,0x0e},{0x1c,0x11,0x0e},{0x1c,0x15,0x0e},{0x1c,0x18,0x0e},{0x1c,0x1c,0x0e},{0x18,0x1c,0x0e},{0x15,0x1c,0x0e},{0x11,0x1c,0x0e},
351 {0x0e,0x1c,0x0e},{0x0e,0x1c,0x11},{0x0e,0x1c,0x15},{0x0e,0x1c,0x18},{0x0e,0x1c,0x1c},{0x0e,0x18,0x1c},{0x0e,0x15,0x1c},{0x0e,0x11,0x1c},
352 {0x14,0x14,0x1c},{0x16,0x14,0x1c},{0x18,0x14,0x1c},{0x1a,0x14,0x1c},{0x1c,0x14,0x1c},{0x1c,0x14,0x1a},{0x1c,0x14,0x18},{0x1c,0x14,0x16},
353 {0x1c,0x14,0x14},{0x1c,0x16,0x14},{0x1c,0x18,0x14},{0x1c,0x1a,0x14},{0x1c,0x1c,0x14},{0x1a,0x1c,0x14},{0x18,0x1c,0x14},{0x16,0x1c,0x14},
354 {0x14,0x1c,0x14},{0x14,0x1c,0x16},{0x14,0x1c,0x18},{0x14,0x1c,0x1a},{0x14,0x1c,0x1c},{0x14,0x1a,0x1c},{0x14,0x18,0x1c},{0x14,0x16,0x1c},
355 {0x00,0x00,0x10},{0x04,0x00,0x10},{0x08,0x00,0x10},{0x0c,0x00,0x10},{0x10,0x00,0x10},{0x10,0x00,0x0c},{0x10,0x00,0x08},{0x10,0x00,0x04},
356 {0x10,0x00,0x00},{0x10,0x04,0x00},{0x10,0x08,0x00},{0x10,0x0c,0x00},{0x10,0x10,0x00},{0x0c,0x10,0x00},{0x08,0x10,0x00},{0x04,0x10,0x00},
357
358 {0x00,0x10,0x00},{0x00,0x10,0x04},{0x00,0x10,0x08},{0x00,0x10,0x0c},{0x00,0x10,0x10},{0x00,0x0c,0x10},{0x00,0x08,0x10},{0x00,0x04,0x10},
359 {0x08,0x08,0x10},{0x0a,0x08,0x10},{0x0c,0x08,0x10},{0x0e,0x08,0x10},{0x10,0x08,0x10},{0x10,0x08,0x0e},{0x10,0x08,0x0c},{0x10,0x08,0x0a},
360 {0x10,0x08,0x08},{0x10,0x0a,0x08},{0x10,0x0c,0x08},{0x10,0x0e,0x08},{0x10,0x10,0x08},{0x0e,0x10,0x08},{0x0c,0x10,0x08},{0x0a,0x10,0x08},
361 {0x08,0x10,0x08},{0x08,0x10,0x0a},{0x08,0x10,0x0c},{0x08,0x10,0x0e},{0x08,0x10,0x10},{0x08,0x0e,0x10},{0x08,0x0c,0x10},{0x08,0x0a,0x10},
362 {0x0b,0x0b,0x10},{0x0c,0x0b,0x10},{0x0d,0x0b,0x10},{0x0f,0x0b,0x10},{0x10,0x0b,0x10},{0x10,0x0b,0x0f},{0x10,0x0b,0x0d},{0x10,0x0b,0x0c},
363 {0x10,0x0b,0x0b},{0x10,0x0c,0x0b},{0x10,0x0d,0x0b},{0x10,0x0f,0x0b},{0x10,0x10,0x0b},{0x0f,0x10,0x0b},{0x0d,0x10,0x0b},{0x0c,0x10,0x0b},
364 {0x0b,0x10,0x0b},{0x0b,0x10,0x0c},{0x0b,0x10,0x0d},{0x0b,0x10,0x0f},{0x0b,0x10,0x10},{0x0b,0x0f,0x10},{0x0b,0x0d,0x10},{0x0b,0x0c,0x10}
365 };
366 VideoModeBlock * CurMode;
367
SetCurMode(VideoModeBlock modeblock[],Bit16u mode)368 static bool SetCurMode(VideoModeBlock modeblock[],Bit16u mode) {
369 Bitu i=0;
370 while (modeblock[i].mode!=0xffff) {
371 if (modeblock[i].mode!=mode) i++;
372 else {
373 if ((!int10.vesa_oldvbe) || (ModeList_VGA[i].mode<0x120)) {
374 CurMode=&modeblock[i];
375 return true;
376 }
377 return false;
378 }
379 }
380 return false;
381 }
382
SetTextLines(void)383 static void SetTextLines(void) {
384 // check for scanline backwards compatibility (VESA text modes??)
385 switch (real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)&0x90) {
386 case 0x80: // 200 lines emulation
387 if (CurMode->mode <= 3) {
388 CurMode = &ModeList_VGA_Text_200lines[CurMode->mode];
389 } else if (CurMode->mode == 7) {
390 CurMode = &ModeList_VGA_Text_350lines[4];
391 }
392 break;
393 case 0x00: // 350 lines emulation
394 if (CurMode->mode <= 3) {
395 CurMode = &ModeList_VGA_Text_350lines[CurMode->mode];
396 } else if (CurMode->mode == 7) {
397 CurMode = &ModeList_VGA_Text_350lines[4];
398 }
399 break;
400 }
401 }
402
INT10_SetCurMode(void)403 void INT10_SetCurMode(void) {
404 Bit16u bios_mode=(Bit16u)real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE);
405 if (GCC_UNLIKELY(CurMode->mode!=bios_mode)) {
406 bool mode_changed=false;
407 switch (machine) {
408 case MCH_CGA:
409 if (bios_mode<7) mode_changed=SetCurMode(ModeList_OTHER,bios_mode);
410 break;
411 case TANDY_ARCH_CASE:
412 if (bios_mode!=7 && bios_mode<=0xa) mode_changed=SetCurMode(ModeList_OTHER,bios_mode);
413 break;
414 case MCH_HERC:
415 if (bios_mode<7) mode_changed=SetCurMode(ModeList_OTHER,bios_mode);
416 else if (bios_mode==7) {mode_changed=true;CurMode=&Hercules_Mode;}
417 break;
418 case MCH_EGA:
419 mode_changed=SetCurMode(ModeList_EGA,bios_mode);
420 break;
421 case VGA_ARCH_CASE:
422 switch (svgaCard) {
423 case SVGA_TsengET4K:
424 case SVGA_TsengET3K:
425 mode_changed=SetCurMode(ModeList_VGA_Tseng,bios_mode);
426 break;
427 case SVGA_ParadisePVGA1A:
428 mode_changed=SetCurMode(ModeList_VGA_Paradise,bios_mode);
429 break;
430 case SVGA_S3Trio:
431 if (bios_mode>=0x68 && CurMode->mode==(bios_mode+0x98)) break;
432 // fall-through
433 default:
434 mode_changed=SetCurMode(ModeList_VGA,bios_mode);
435 break;
436 }
437 if (mode_changed && CurMode->type==M_TEXT) SetTextLines();
438 break;
439 }
440 if (mode_changed) LOG(LOG_INT10,LOG_WARN)("BIOS video mode changed to %X",bios_mode);
441 }
442 }
443
FinishSetMode(bool clearmem)444 static void FinishSetMode(bool clearmem) {
445 /* Clear video memory if needs be */
446 if (clearmem) {
447 switch (CurMode->type) {
448 case M_TANDY16:
449 case M_CGA4:
450 if ((machine==MCH_PCJR) && (CurMode->mode >= 9)) {
451 // PCJR cannot access the full 32k at 0xb800
452 for (Bit16u ct=0;ct<16*1024;ct++) {
453 // 0x1800 is the last 32k block in 128k, as set in the CRTCPU_PAGE register
454 real_writew(0x1800,ct*2,0x0000);
455 }
456 break;
457 }
458 // fall-through
459 case M_CGA2:
460 for (Bit16u ct=0;ct<16*1024;ct++) {
461 real_writew( 0xb800,ct*2,0x0000);
462 }
463 break;
464 case M_TEXT: {
465 Bit16u seg = (CurMode->mode==7)?0xb000:0xb800;
466 for (Bit16u ct=0;ct<16*1024;ct++) real_writew(seg,ct*2,0x0720);
467 break;
468 }
469 case M_EGA:
470 case M_VGA:
471 case M_LIN8:
472 case M_LIN4:
473 case M_LIN15:
474 case M_LIN16:
475 case M_LIN32:
476 /* Hack we just access the memory directly */
477 memset(vga.mem.linear,0,vga.vmemsize);
478 memset(vga.fastmem, 0, vga.vmemsize<<1);
479 }
480 }
481 /* Setup the BIOS */
482 if (CurMode->mode<128) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,(Bit8u)CurMode->mode);
483 else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE,(Bit8u)(CurMode->mode-0x98)); //Looks like the s3 bios
484 real_writew(BIOSMEM_SEG,BIOSMEM_NB_COLS,(Bit16u)CurMode->twidth);
485 real_writew(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE,(Bit16u)CurMode->plength);
486 real_writew(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS,((CurMode->mode==7 )|| (CurMode->mode==0x0f)) ? 0x3b4 : 0x3d4);
487 real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,(Bit8u)(CurMode->theight-1));
488 real_writew(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT,(Bit16u)CurMode->cheight);
489 real_writeb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL,(0x60|(clearmem?0:0x80)));
490 real_writeb(BIOSMEM_SEG,BIOSMEM_SWITCHES,0x09);
491
492 // this is an index into the dcc table:
493 if (IS_VGA_ARCH) real_writeb(BIOSMEM_SEG,BIOSMEM_DCC_INDEX,0x0b);
494
495 // Set cursor shape
496 if (CurMode->type==M_TEXT) {
497 INT10_SetCursorShape(0x06,07);
498 }
499 // Set cursor pos for page 0..7
500 for (Bit8u ct=0;ct<8;ct++) INT10_SetCursorPos(0,0,ct);
501 // Set active page 0
502 INT10_SetActivePage(0);
503 /* Set some interrupt vectors */
504 if (CurMode->mode<=3 || CurMode->mode==7)
505 RealSetVec(0x43,int10.rom.font_8_first);
506 else {
507 switch (CurMode->cheight) {
508 case 8:RealSetVec(0x43,int10.rom.font_8_first);break;
509 case 14:RealSetVec(0x43,int10.rom.font_14);break;
510 case 16:RealSetVec(0x43,int10.rom.font_16);break;
511 }
512 }
513 }
514
INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem)515 bool INT10_SetVideoMode_OTHER(Bit16u mode,bool clearmem) {
516 switch (machine) {
517 case MCH_CGA:
518 if (mode>6) return false;
519 case TANDY_ARCH_CASE:
520 if (mode>0xa) return false;
521 if (mode==7) mode=0; // PCJR defaults to 0 on illegal mode 7
522 if (!SetCurMode(ModeList_OTHER,mode)) {
523 LOG(LOG_INT10,LOG_ERROR)("Trying to set illegal mode %X",mode);
524 return false;
525 }
526 break;
527 case MCH_HERC:
528 // Allow standard color modes if equipment word is not set to mono (Victory Road)
529 if ((real_readw(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE)&0x30)!=0x30 && mode<7) {
530 SetCurMode(ModeList_OTHER,mode);
531 FinishSetMode(clearmem);
532 return true;
533 }
534 CurMode=&Hercules_Mode;
535 mode=7; // in case the video parameter table is modified
536 break;
537 }
538 LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
539
540 /* Setup the VGA to the correct mode */
541 // VGA_SetMode(CurMode->type);
542 /* Setup the CRTC */
543 Bitu crtc_base=machine==MCH_HERC ? 0x3b4 : 0x3d4;
544 //Horizontal total
545 IO_WriteW(crtc_base,0x00 | (CurMode->htotal) << 8);
546 //Horizontal displayed
547 IO_WriteW(crtc_base,0x01 | (CurMode->hdispend) << 8);
548 //Horizontal sync position
549 IO_WriteW(crtc_base,0x02 | (CurMode->hdispend+1) << 8);
550 //Horizontal sync width, seems to be fixed to 0xa, for cga at least, hercules has 0xf
551 IO_WriteW(crtc_base,0x03 | (0xa) << 8);
552 ////Vertical total
553 IO_WriteW(crtc_base,0x04 | (CurMode->vtotal) << 8);
554 //Vertical total adjust, 6 for cga,hercules,tandy
555 IO_WriteW(crtc_base,0x05 | (6) << 8);
556 //Vertical displayed
557 IO_WriteW(crtc_base,0x06 | (CurMode->vdispend) << 8);
558 //Vertical sync position
559 IO_WriteW(crtc_base,0x07 | (CurMode->vdispend + ((CurMode->vtotal - CurMode->vdispend)/2)-1) << 8);
560 //Maximum scanline
561 Bit8u scanline,crtpage;
562 scanline=8;
563 switch(CurMode->type) {
564 case M_TEXT:
565 if (machine==MCH_HERC) scanline=14;
566 else scanline=8;
567 break;
568 case M_CGA2:
569 scanline=2;
570 break;
571 case M_CGA4:
572 if (CurMode->mode!=0xa) scanline=2;
573 else scanline=4;
574 break;
575 case M_TANDY16:
576 if (CurMode->mode!=0x9) scanline=2;
577 else scanline=4;
578 break;
579 }
580 IO_WriteW(crtc_base,0x09 | (scanline-1) << 8);
581 //Setup the CGA palette using VGA DAC palette
582 for (Bit8u ct=0;ct<16;ct++) VGA_DAC_SetEntry(ct,cga_palette[ct][0],cga_palette[ct][1],cga_palette[ct][2]);
583 //Setup the tandy palette
584 for (Bit8u ct=0;ct<16;ct++) VGA_DAC_CombineColor(ct,ct);
585 //Setup the special registers for each machine type
586 Bit8u mode_control_list[0xa+1]={
587 0x2c,0x28,0x2d,0x29, //0-3
588 0x2a,0x2e,0x1e,0x29, //4-7
589 0x2a,0x2b,0x3b //8-a
590 };
591 Bit8u mode_control_list_pcjr[0xa+1]={
592 0x0c,0x08,0x0d,0x09, //0-3
593 0x0a,0x0e,0x0e,0x09, //4-7
594 0x1a,0x1b,0x0b //8-a
595 };
596 Bit8u mode_control,color_select;
597 switch (machine) {
598 case MCH_HERC:
599 IO_WriteB(0x3b8,0x28); // TEXT mode and blinking characters
600
601 Herc_Palette();
602 VGA_DAC_CombineColor(0,0);
603 VGA_DAC_CombineColor(1,7);
604
605 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x29); // attribute controls blinking
606 break;
607 case MCH_CGA:
608 mode_control=mode_control_list[CurMode->mode];
609 if (CurMode->mode == 0x6) color_select=0x3f;
610 else color_select=0x30;
611 IO_WriteB(0x3d8,mode_control);
612 IO_WriteB(0x3d9,color_select);
613 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
614 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
615 break;
616 case MCH_TANDY:
617 /* Init some registers */
618 IO_WriteB(0x3da,0x1);IO_WriteB(0x3de,0xf); //Palette mask always 0xf
619 IO_WriteB(0x3da,0x2);IO_WriteB(0x3de,0x0); //black border
620 IO_WriteB(0x3da,0x3); //Tandy color overrides?
621 switch (CurMode->mode) {
622 case 0x8:
623 IO_WriteB(0x3de,0x14);break;
624 case 0x9:
625 IO_WriteB(0x3de,0x14);break;
626 case 0xa:
627 IO_WriteB(0x3de,0x0c);break;
628 default:
629 IO_WriteB(0x3de,0x0);break;
630 }
631 // write palette
632 for(Bitu i = 0; i < 16; i++) {
633 IO_WriteB(0x3da,i+0x10);
634 IO_WriteB(0x3de,i);
635 }
636 //Clear extended mapping
637 IO_WriteB(0x3da,0x5);
638 IO_WriteB(0x3de,0x0);
639 //Clear monitor mode
640 IO_WriteB(0x3da,0x8);
641 IO_WriteB(0x3de,0x0);
642 crtpage=(CurMode->mode>=0x9) ? 0xf6 : 0x3f;
643 IO_WriteB(0x3df,crtpage);
644 real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage);
645 mode_control=mode_control_list[CurMode->mode];
646 if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
647 else color_select=0x30;
648 IO_WriteB(0x3d8,mode_control);
649 IO_WriteB(0x3d9,color_select);
650 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
651 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
652 break;
653 case MCH_PCJR:
654 /* Init some registers */
655 IO_ReadB(0x3da);
656 IO_WriteB(0x3da,0x1);IO_WriteB(0x3da,0xf); //Palette mask always 0xf
657 IO_WriteB(0x3da,0x2);IO_WriteB(0x3da,0x0); //black border
658 IO_WriteB(0x3da,0x3);
659 if (CurMode->mode<=0x04) IO_WriteB(0x3da,0x02);
660 else if (CurMode->mode==0x06) IO_WriteB(0x3da,0x08);
661 else IO_WriteB(0x3da,0x00);
662
663 /* set CRT/Processor page register */
664 if (CurMode->mode<0x04) crtpage=0x3f;
665 else if (CurMode->mode>=0x09) crtpage=0xf6;
666 else crtpage=0x7f;
667 IO_WriteB(0x3df,crtpage);
668 real_writeb(BIOSMEM_SEG,BIOSMEM_CRTCPU_PAGE,crtpage);
669
670 mode_control=mode_control_list_pcjr[CurMode->mode];
671 IO_WriteB(0x3da,0x0);IO_WriteB(0x3da,mode_control);
672 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,mode_control);
673
674 if (CurMode->mode == 0x6 || CurMode->mode==0xa) color_select=0x3f;
675 else color_select=0x30;
676 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,color_select);
677 INT10_SetColorSelect(1);
678 INT10_SetBackgroundBorder(0);
679 break;
680 }
681
682 RealPt vparams = RealGetVec(0x1d);
683 if ((vparams != RealMake(0xf000,0xf0a4)) && (mode < 8)) {
684 // load crtc parameters from video params table
685 Bit16u crtc_block_index = 0;
686 if (mode < 2) crtc_block_index = 0;
687 else if (mode < 4) crtc_block_index = 1;
688 else if (mode < 7) crtc_block_index = 2;
689 else if (mode == 7) crtc_block_index = 3; // MDA mono mode; invalid for others
690 else if (mode < 9) crtc_block_index = 2;
691 else crtc_block_index = 3; // Tandy/PCjr modes
692
693 // init CRTC registers
694 for (Bit16u i = 0; i < 16; i++)
695 IO_WriteW(crtc_base, i | (real_readb(RealSeg(vparams),
696 RealOff(vparams) + i + crtc_block_index*16) << 8));
697 }
698 FinishSetMode(clearmem);
699 return true;
700 }
701
702
INT10_SetVideoMode(Bit16u mode)703 bool INT10_SetVideoMode(Bit16u mode) {
704 bool clearmem=true;Bitu i;
705 if (mode>=0x100) {
706 if ((mode & 0x4000) && int10.vesa_nolfb) return false;
707 if (mode & 0x8000) clearmem=false;
708 mode&=0xfff;
709 }
710 if ((mode<0x100) && (mode & 0x80)) {
711 clearmem=false;
712 mode-=0x80;
713 }
714 int10.vesa_setmode=0xffff;
715 LOG(LOG_INT10,LOG_NORMAL)("Set Video Mode %X",mode);
716 if (!IS_EGAVGA_ARCH) return INT10_SetVideoMode_OTHER(mode,clearmem);
717
718 /* First read mode setup settings from bios area */
719 // Bit8u video_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL);
720 // Bit8u vga_switches=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES);
721 Bit8u modeset_ctl=real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL);
722
723 if (IS_VGA_ARCH) {
724 if (svga.accepts_mode) {
725 if (!svga.accepts_mode(mode)) return false;
726 }
727
728 switch(svgaCard) {
729 case SVGA_TsengET4K:
730 case SVGA_TsengET3K:
731 if (!SetCurMode(ModeList_VGA_Tseng,mode)){
732 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
733 return false;
734 }
735 break;
736 case SVGA_ParadisePVGA1A:
737 if (!SetCurMode(ModeList_VGA_Paradise,mode)){
738 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
739 return false;
740 }
741 break;
742 default:
743 if (!SetCurMode(ModeList_VGA,mode)){
744 LOG(LOG_INT10,LOG_ERROR)("VGA:Trying to set illegal mode %X",mode);
745 return false;
746 }
747 }
748 if (CurMode->type==M_TEXT) SetTextLines();
749 } else {
750 if (!SetCurMode(ModeList_EGA,mode)){
751 LOG(LOG_INT10,LOG_ERROR)("EGA:Trying to set illegal mode %X",mode);
752 return false;
753 }
754 }
755
756 /* Setup the VGA to the correct mode */
757
758 Bit16u crtc_base;
759 bool mono_mode=(mode == 7) || (mode==0xf);
760 if (mono_mode) crtc_base=0x3b4;
761 else crtc_base=0x3d4;
762
763 if (IS_VGA_ARCH && (svgaCard == SVGA_S3Trio)) {
764 // Disable MMIO here so we can read / write memory
765 IO_Write(crtc_base,0x53);
766 IO_Write(crtc_base+1,0x0);
767 }
768
769 /* Setup MISC Output Register */
770 Bit8u misc_output=0x2 | (mono_mode ? 0x0 : 0x1);
771
772 if ((CurMode->type==M_TEXT) && (CurMode->cwidth==9)) {
773 // 28MHz (16MHz EGA) clock for 9-pixel wide chars
774 misc_output|=0x4;
775 }
776
777 switch (CurMode->vdispend) {
778 case 400:
779 misc_output|=0x60;
780 break;
781 case 480:
782 misc_output|=0xe0;
783 break;
784 case 350:
785 misc_output|=0xa0;
786 break;
787 default:
788 misc_output|=0x60;
789 }
790 IO_Write(0x3c2,misc_output); //Setup for 3b4 or 3d4
791
792 /* Program Sequencer */
793 Bit8u seq_data[SEQ_REGS];
794 memset(seq_data,0,SEQ_REGS);
795 seq_data[1]|=0x01; //8 dot fonts by default
796 if (CurMode->special & _EGA_HALF_CLOCK) seq_data[1]|=0x08; //Check for half clock
797 if ((machine==MCH_EGA) && (CurMode->special & _EGA_HALF_CLOCK)) seq_data[1]|=0x02;
798 seq_data[4]|=0x02; //More than 64kb
799 switch (CurMode->type) {
800 case M_TEXT:
801 if (CurMode->cwidth==9) seq_data[1] &= ~1;
802 seq_data[2]|=0x3; //Enable plane 0 and 1
803 seq_data[4]|=0x01; //Alpanumeric
804 if (IS_VGA_ARCH) seq_data[4]|=0x04; //odd/even enabled
805 break;
806 case M_CGA2:
807 seq_data[2]|=0xf; //Enable plane 0
808 if (machine==MCH_EGA) seq_data[4]|=0x04; //odd/even enabled
809 break;
810 case M_CGA4:
811 if (machine==MCH_EGA) seq_data[2]|=0x03; //Enable plane 0 and 1
812 break;
813 case M_LIN4:
814 case M_EGA:
815 seq_data[2]|=0xf; //Enable all planes for writing
816 if (machine==MCH_EGA) seq_data[4]|=0x04; //odd/even enabled
817 break;
818 case M_LIN8: //Seems to have the same reg layout from testing
819 case M_LIN15:
820 case M_LIN16:
821 case M_LIN32:
822 case M_VGA:
823 seq_data[2]|=0xf; //Enable all planes for writing
824 seq_data[4]|=0xc; //Graphics - odd/even - Chained
825 break;
826 }
827 for (Bit8u ct=0;ct<SEQ_REGS;ct++) {
828 IO_Write(0x3c4,ct);
829 IO_Write(0x3c5,seq_data[ct]);
830 }
831 vga.config.compatible_chain4 = true; // this may be changed by SVGA chipset emulation
832
833 /* Program CRTC */
834 /* First disable write protection */
835 IO_Write(crtc_base,0x11);
836 IO_Write(crtc_base+1,IO_Read(crtc_base+1)&0x7f);
837 /* Clear all the regs */
838 for (Bit8u ct=0x0;ct<=0x18;ct++) {
839 IO_Write(crtc_base,ct);IO_Write(crtc_base+1,0);
840 }
841 Bit8u overflow=0;Bit8u max_scanline=0;
842 Bit8u ver_overflow=0;Bit8u hor_overflow=0;
843 /* Horizontal Total */
844 IO_Write(crtc_base,0x00);IO_Write(crtc_base+1,(Bit8u)(CurMode->htotal-5));
845 hor_overflow|=((CurMode->htotal-5) & 0x100) >> 8;
846 /* Horizontal Display End */
847 IO_Write(crtc_base,0x01);IO_Write(crtc_base+1,(Bit8u)(CurMode->hdispend-1));
848 hor_overflow|=((CurMode->hdispend-1) & 0x100) >> 7;
849 /* Start horizontal Blanking */
850 IO_Write(crtc_base,0x02);IO_Write(crtc_base+1,(Bit8u)CurMode->hdispend);
851 hor_overflow|=((CurMode->hdispend) & 0x100) >> 6;
852 /* End horizontal Blanking */
853 Bitu blank_end=(CurMode->htotal-2) & 0x7f;
854 IO_Write(crtc_base,0x03);IO_Write(crtc_base+1,0x80|(blank_end & 0x1f));
855
856 /* Start Horizontal Retrace */
857 Bitu ret_start;
858 if ((CurMode->special & _EGA_HALF_CLOCK) && (CurMode->type!=M_CGA2)) ret_start = (CurMode->hdispend+3);
859 else if (CurMode->type==M_TEXT) ret_start = (CurMode->hdispend+5);
860 else ret_start = (CurMode->hdispend+4);
861 IO_Write(crtc_base,0x04);IO_Write(crtc_base+1,(Bit8u)ret_start);
862 hor_overflow|=(ret_start & 0x100) >> 4;
863
864 /* End Horizontal Retrace */
865 Bitu ret_end;
866 if (CurMode->special & _EGA_HALF_CLOCK) {
867 if (CurMode->type==M_CGA2) ret_end=0; // mode 6
868 else if (CurMode->special & _EGA_LINE_DOUBLE) ret_end = (CurMode->htotal-18) & 0x1f;
869 else ret_end = ((CurMode->htotal-18) & 0x1f) | 0x20; // mode 0&1 have 1 char sync delay
870 } else if (CurMode->type==M_TEXT) ret_end = (CurMode->htotal-3) & 0x1f;
871 else ret_end = (CurMode->htotal-4) & 0x1f;
872
873 IO_Write(crtc_base,0x05);IO_Write(crtc_base+1,(Bit8u)(ret_end | (blank_end & 0x20) << 2));
874
875 /* Vertical Total */
876 IO_Write(crtc_base,0x06);IO_Write(crtc_base+1,(Bit8u)(CurMode->vtotal-2));
877 overflow|=((CurMode->vtotal-2) & 0x100) >> 8;
878 overflow|=((CurMode->vtotal-2) & 0x200) >> 4;
879 ver_overflow|=((CurMode->vtotal-2) & 0x400) >> 10;
880
881 Bitu vretrace;
882 if (IS_VGA_ARCH) {
883 switch (CurMode->vdispend) {
884 case 400: vretrace=CurMode->vdispend+12;
885 break;
886 case 480: vretrace=CurMode->vdispend+10;
887 break;
888 case 350: vretrace=CurMode->vdispend+37;
889 break;
890 default: vretrace=CurMode->vdispend+12;
891 }
892 } else {
893 switch (CurMode->vdispend) {
894 case 350: vretrace=CurMode->vdispend;
895 break;
896 default: vretrace=CurMode->vdispend+24;
897 }
898 }
899
900 /* Vertical Retrace Start */
901 IO_Write(crtc_base,0x10);IO_Write(crtc_base+1,(Bit8u)vretrace);
902 overflow|=(vretrace & 0x100) >> 6;
903 overflow|=(vretrace & 0x200) >> 2;
904 ver_overflow|=(vretrace & 0x400) >> 6;
905
906 /* Vertical Retrace End */
907 IO_Write(crtc_base,0x11);IO_Write(crtc_base+1,(vretrace+2) & 0xF);
908
909 /* Vertical Display End */
910 IO_Write(crtc_base,0x12);IO_Write(crtc_base+1,(Bit8u)(CurMode->vdispend-1));
911 overflow|=((CurMode->vdispend-1) & 0x100) >> 7;
912 overflow|=((CurMode->vdispend-1) & 0x200) >> 3;
913 ver_overflow|=((CurMode->vdispend-1) & 0x400) >> 9;
914
915 Bitu vblank_trim;
916 if (IS_VGA_ARCH) {
917 switch (CurMode->vdispend) {
918 case 400: vblank_trim=6;
919 break;
920 case 480: vblank_trim=7;
921 break;
922 case 350: vblank_trim=5;
923 break;
924 default: vblank_trim=8;
925 }
926 } else {
927 switch (CurMode->vdispend) {
928 case 350: vblank_trim=0;
929 break;
930 default: vblank_trim=23;
931 }
932 }
933
934 /* Vertical Blank Start */
935 IO_Write(crtc_base,0x15);IO_Write(crtc_base+1,(Bit8u)(CurMode->vdispend+vblank_trim));
936 overflow|=((CurMode->vdispend+vblank_trim) & 0x100) >> 5;
937 max_scanline|=((CurMode->vdispend+vblank_trim) & 0x200) >> 4;
938 ver_overflow|=((CurMode->vdispend+vblank_trim) & 0x400) >> 8;
939
940 /* Vertical Blank End */
941 IO_Write(crtc_base,0x16);IO_Write(crtc_base+1,(Bit8u)(CurMode->vtotal-vblank_trim-2));
942
943 /* Line Compare */
944 Bitu line_compare=(CurMode->vtotal < 1024) ? 1023 : 2047;
945 IO_Write(crtc_base,0x18);IO_Write(crtc_base+1,line_compare&0xff);
946 overflow|=(line_compare & 0x100) >> 4;
947 max_scanline|=(line_compare & 0x200) >> 3;
948 ver_overflow|=(line_compare & 0x400) >> 4;
949 Bit8u underline=0;
950 /* Maximum scanline / Underline Location */
951 if (CurMode->special & _EGA_LINE_DOUBLE) {
952 if (machine!=MCH_EGA) max_scanline|=0x80;
953 }
954 switch (CurMode->type) {
955 case M_TEXT:
956 max_scanline|=CurMode->cheight-1;
957 underline=mono_mode ? CurMode->cheight-1 : 0x1f; // mode 7 uses underline position
958 break;
959 case M_VGA:
960 underline=0x40;
961 max_scanline|=1; //Vga doesn't use double line but this
962 break;
963 case M_LIN8:
964 case M_LIN15:
965 case M_LIN16:
966 case M_LIN32:
967 underline=0x60; //Seems to enable the every 4th clock on my s3
968 break;
969 case M_CGA2:
970 case M_CGA4:
971 max_scanline|=1;
972 break;
973 default:
974 if (CurMode->vdispend==350) underline=0x0f;
975 break;
976 }
977
978 IO_Write(crtc_base,0x09);IO_Write(crtc_base+1,max_scanline);
979 IO_Write(crtc_base,0x14);IO_Write(crtc_base+1,underline);
980
981 /* OverFlow */
982 IO_Write(crtc_base,0x07);IO_Write(crtc_base+1,overflow);
983
984 if (svgaCard == SVGA_S3Trio) {
985 /* Extended Horizontal Overflow */
986 IO_Write(crtc_base,0x5d);IO_Write(crtc_base+1,hor_overflow);
987 /* Extended Vertical Overflow */
988 IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow);
989 }
990
991 /* Offset Register */
992 Bitu offset;
993 switch (CurMode->type) {
994 case M_LIN8:
995 offset = CurMode->swidth/8;
996 break;
997 case M_LIN15:
998 case M_LIN16:
999 offset = 2 * CurMode->swidth/8;
1000 break;
1001 case M_LIN32:
1002 offset = 4 * CurMode->swidth/8;
1003 break;
1004 default:
1005 offset = CurMode->hdispend/2;
1006 }
1007 IO_Write(crtc_base,0x13);
1008 IO_Write(crtc_base + 1,offset & 0xff);
1009
1010 if (svgaCard == SVGA_S3Trio) {
1011 /* Extended System Control 2 Register */
1012 /* This register actually has more bits but only use the extended offset ones */
1013 IO_Write(crtc_base,0x51);
1014 IO_Write(crtc_base + 1,(Bit8u)((offset & 0x300) >> 4));
1015 /* Clear remaining bits of the display start */
1016 IO_Write(crtc_base,0x69);
1017 IO_Write(crtc_base + 1,0);
1018 /* Extended Vertical Overflow */
1019 IO_Write(crtc_base,0x5e);IO_Write(crtc_base+1,ver_overflow);
1020 }
1021
1022 /* Mode Control */
1023 Bit8u mode_control=0;
1024
1025 switch (CurMode->type) {
1026 case M_CGA2:
1027 mode_control=0xc2; // 0x06 sets address wrap.
1028 break;
1029 case M_CGA4:
1030 mode_control=0xa2;
1031 break;
1032 case M_LIN4:
1033 case M_EGA:
1034 if (CurMode->mode==0x11) // 0x11 also sets address wrap. thought maybe all 2 color modes did but 0x0f doesn't.
1035 mode_control=0xc3; // so.. 0x11 or 0x0f a one off?
1036 else {
1037 if (machine==MCH_EGA) {
1038 if (CurMode->special & _EGA_LINE_DOUBLE) mode_control=0xc3;
1039 else mode_control=0x8b;
1040 } else {
1041 mode_control=0xe3;
1042 }
1043 }
1044 break;
1045 case M_TEXT:
1046 case M_VGA:
1047 case M_LIN8:
1048 case M_LIN15:
1049 case M_LIN16:
1050 case M_LIN32:
1051 mode_control=0xa3;
1052 if (CurMode->special & _VGA_PIXEL_DOUBLE)
1053 mode_control |= 0x08;
1054 break;
1055 }
1056
1057 IO_Write(crtc_base,0x17);IO_Write(crtc_base+1,mode_control);
1058 /* Renable write protection */
1059 IO_Write(crtc_base,0x11);
1060 IO_Write(crtc_base+1,IO_Read(crtc_base+1)|0x80);
1061
1062 if (svgaCard == SVGA_S3Trio) {
1063 /* Setup the correct clock */
1064 if (CurMode->mode>=0x100) {
1065 if (CurMode->vdispend>480)
1066 misc_output|=0xc0; //480-line sync
1067 misc_output|=0x0c; //Select clock 3
1068 Bitu clock=CurMode->vtotal*8*CurMode->htotal*70;
1069 VGA_SetClock(3,clock/1000);
1070 }
1071 Bit8u misc_control_2;
1072 /* Setup Pixel format */
1073 switch (CurMode->type) {
1074 case M_LIN8:
1075 misc_control_2=0x00;
1076 break;
1077 case M_LIN15:
1078 misc_control_2=0x30;
1079 break;
1080 case M_LIN16:
1081 misc_control_2=0x50;
1082 break;
1083 case M_LIN32:
1084 misc_control_2=0xd0;
1085 break;
1086 default:
1087 misc_control_2=0x0;
1088 break;
1089 }
1090 IO_WriteB(crtc_base,0x67);IO_WriteB(crtc_base+1,misc_control_2);
1091 }
1092
1093 /* Write Misc Output */
1094 IO_Write(0x3c2,misc_output);
1095 /* Program Graphics controller */
1096 Bit8u gfx_data[GFX_REGS];
1097 memset(gfx_data,0,GFX_REGS);
1098 gfx_data[0x7]=0xf; /* Color don't care */
1099 gfx_data[0x8]=0xff; /* BitMask */
1100 switch (CurMode->type) {
1101 case M_TEXT:
1102 gfx_data[0x5]|=0x10; //Odd-Even Mode
1103 gfx_data[0x6]|=mono_mode ? 0x0a : 0x0e; //Either b800 or b000
1104 break;
1105 case M_LIN8:
1106 case M_LIN15:
1107 case M_LIN16:
1108 case M_LIN32:
1109 case M_VGA:
1110 gfx_data[0x5]|=0x40; //256 color mode
1111 gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
1112 break;
1113 case M_LIN4:
1114 case M_EGA:
1115 if (CurMode->mode == 0x0f)
1116 gfx_data[0x7]=0x05; // only planes 0 and 2 are used
1117 gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
1118 break;
1119 case M_CGA4:
1120 gfx_data[0x5]|=0x20; //CGA mode
1121 gfx_data[0x6]|=0x0f; //graphics mode at at 0xb800=0xbfff
1122 if (machine==MCH_EGA) gfx_data[0x5]|=0x10;
1123 break;
1124 case M_CGA2:
1125 if (machine==MCH_EGA) {
1126 gfx_data[0x6]|=0x0d; //graphics mode at at 0xb800=0xbfff
1127 } else {
1128 gfx_data[0x6]|=0x0f; //graphics mode at at 0xb800=0xbfff
1129 }
1130 break;
1131 }
1132 for (Bit8u ct=0;ct<GFX_REGS;ct++) {
1133 IO_Write(0x3ce,ct);
1134 IO_Write(0x3cf,gfx_data[ct]);
1135 }
1136 Bit8u att_data[ATT_REGS];
1137 memset(att_data,0,ATT_REGS);
1138 att_data[0x12]=0xf; //Always have all color planes enabled
1139 /* Program Attribute Controller */
1140 switch (CurMode->type) {
1141 case M_EGA:
1142 case M_LIN4:
1143 att_data[0x10]=0x01; //Color Graphics
1144 switch (CurMode->mode) {
1145 case 0x0f:
1146 att_data[0x12]=0x05; // planes 0 and 2 enabled
1147 att_data[0x10]|=0x0a; // monochrome and blinking
1148
1149 att_data[0x01]=0x08; // low-intensity
1150 att_data[0x04]=0x18; // blink-on case
1151 att_data[0x05]=0x18; // high-intensity
1152 att_data[0x09]=0x08; // low-intensity in blink-off case
1153 att_data[0x0d]=0x18; // high-intensity in blink-off
1154 break;
1155 case 0x11:
1156 for (i=1;i<16;i++) att_data[i]=0x3f;
1157 break;
1158 case 0x10:
1159 case 0x12:
1160 goto att_text16;
1161 default:
1162 if ( CurMode->type == M_LIN4 )
1163 goto att_text16;
1164 for (Bit8u ct=0;ct<8;ct++) {
1165 att_data[ct]=ct;
1166 att_data[ct+8]=ct+0x10;
1167 }
1168 break;
1169 }
1170 break;
1171 case M_TANDY16:
1172 att_data[0x10]=0x01; //Color Graphics
1173 for (Bit8u ct=0;ct<16;ct++) att_data[ct]=ct;
1174 break;
1175 case M_TEXT:
1176 if (CurMode->cwidth==9) {
1177 att_data[0x13]=0x08; //Pel panning on 8, although we don't have 9 dot text mode
1178 att_data[0x10]=0x0C; //Color Text with blinking, 9 Bit characters
1179 } else {
1180 att_data[0x13]=0x00;
1181 att_data[0x10]=0x08; //Color Text with blinking, 8 Bit characters
1182 }
1183 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
1184 att_text16:
1185 if (CurMode->mode==7) {
1186 att_data[0]=0x00;
1187 att_data[8]=0x10;
1188 for (i=1; i<8; i++) {
1189 att_data[i]=0x08;
1190 att_data[i+8]=0x18;
1191 }
1192 } else {
1193 for (Bit8u ct=0;ct<8;ct++) {
1194 att_data[ct]=ct;
1195 att_data[ct+8]=ct+0x38;
1196 }
1197 if (IS_VGA_ARCH) att_data[0x06]=0x14; //Odd Color 6 yellow/brown.
1198 }
1199 break;
1200 case M_CGA2:
1201 att_data[0x10]=0x01; //Color Graphics
1202 att_data[0]=0x0;
1203 for (i=1;i<0x10;i++) att_data[i]=0x17;
1204 att_data[0x12]=0x1; //Only enable 1 plane
1205 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x3f);
1206 break;
1207 case M_CGA4:
1208 att_data[0x10]=0x01; //Color Graphics
1209 att_data[0]=0x0;
1210 att_data[1]=0x13;
1211 att_data[2]=0x15;
1212 att_data[3]=0x17;
1213 att_data[4]=0x02;
1214 att_data[5]=0x04;
1215 att_data[6]=0x06;
1216 att_data[7]=0x07;
1217 for (Bit8u ct=0x8;ct<0x10;ct++)
1218 att_data[ct] = ct + 0x8;
1219 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAL,0x30);
1220 break;
1221 case M_VGA:
1222 case M_LIN8:
1223 case M_LIN15:
1224 case M_LIN16:
1225 case M_LIN32:
1226 for (Bit8u ct=0;ct<16;ct++) att_data[ct]=ct;
1227 att_data[0x10]=0x41; //Color Graphics 8-bit
1228 break;
1229 }
1230 IO_Read(mono_mode ? 0x3ba : 0x3da);
1231 if ((modeset_ctl & 8)==0) {
1232 for (Bit8u ct=0;ct<ATT_REGS;ct++) {
1233 IO_Write(0x3c0,ct);
1234 IO_Write(0x3c0,att_data[ct]);
1235 }
1236 vga.config.pel_panning = 0;
1237 IO_Write(0x3c0,0x20); IO_Write(0x3c0,0x00); //Disable palette access
1238 IO_Write(0x3c6,0xff); //Reset Pelmask
1239 /* Setup the DAC */
1240 IO_Write(0x3c8,0);
1241 switch (CurMode->type) {
1242 case M_EGA:
1243 if (CurMode->mode>0xf) {
1244 goto dac_text16;
1245 } else if (CurMode->mode==0xf) {
1246 for (i=0;i<64;i++) {
1247 IO_Write(0x3c9,mtext_s3_palette[i][0]);
1248 IO_Write(0x3c9,mtext_s3_palette[i][1]);
1249 IO_Write(0x3c9,mtext_s3_palette[i][2]);
1250 }
1251 } else {
1252 for (i=0;i<64;i++) {
1253 IO_Write(0x3c9,ega_palette[i][0]);
1254 IO_Write(0x3c9,ega_palette[i][1]);
1255 IO_Write(0x3c9,ega_palette[i][2]);
1256 }
1257 }
1258 break;
1259 case M_CGA2:
1260 case M_CGA4:
1261 case M_TANDY16:
1262 for (i=0;i<64;i++) {
1263 IO_Write(0x3c9,cga_palette_2[i][0]);
1264 IO_Write(0x3c9,cga_palette_2[i][1]);
1265 IO_Write(0x3c9,cga_palette_2[i][2]);
1266 }
1267 break;
1268 case M_TEXT:
1269 if (CurMode->mode==7) {
1270 if ((IS_VGA_ARCH) && (svgaCard == SVGA_S3Trio)) {
1271 for (i=0;i<64;i++) {
1272 IO_Write(0x3c9,mtext_s3_palette[i][0]);
1273 IO_Write(0x3c9,mtext_s3_palette[i][1]);
1274 IO_Write(0x3c9,mtext_s3_palette[i][2]);
1275 }
1276 } else {
1277 for (i=0;i<64;i++) {
1278 IO_Write(0x3c9,mtext_palette[i][0]);
1279 IO_Write(0x3c9,mtext_palette[i][1]);
1280 IO_Write(0x3c9,mtext_palette[i][2]);
1281 }
1282 }
1283 break;
1284 } //FALLTHROUGH!!!!
1285 case M_LIN4: //Added for CAD Software
1286 dac_text16:
1287 for (i=0;i<64;i++) {
1288 IO_Write(0x3c9,text_palette[i][0]);
1289 IO_Write(0x3c9,text_palette[i][1]);
1290 IO_Write(0x3c9,text_palette[i][2]);
1291 }
1292 break;
1293 case M_VGA:
1294 case M_LIN8:
1295 case M_LIN15:
1296 case M_LIN16:
1297 case M_LIN32:
1298 // IBM and clones use 248 default colors in the palette for 256-color mode.
1299 // The last 8 colors of the palette are only initialized to 0 at BIOS init.
1300 // Palette index is left at 0xf8 as on most clones, IBM leaves it at 0x10.
1301 for (i=0;i<248;i++) {
1302 IO_Write(0x3c9,vga_palette[i][0]);
1303 IO_Write(0x3c9,vga_palette[i][1]);
1304 IO_Write(0x3c9,vga_palette[i][2]);
1305 }
1306 break;
1307 }
1308 if (IS_VGA_ARCH) {
1309 /* check if gray scale summing is enabled */
1310 if (real_readb(BIOSMEM_SEG,BIOSMEM_MODESET_CTL) & 2) {
1311 INT10_PerformGrayScaleSumming(0,256);
1312 }
1313 }
1314 } else {
1315 for (Bit8u ct=0x10;ct<ATT_REGS;ct++) {
1316 if (ct==0x11) continue; // skip overscan register
1317 IO_Write(0x3c0,ct);
1318 IO_Write(0x3c0,att_data[ct]);
1319 }
1320 vga.config.pel_panning = 0;
1321 IO_Write(0x3c0,0x20); //Disable palette access
1322 }
1323 /* Write palette register data to dynamic save area if pointer is non-zero */
1324 RealPt vsavept=real_readd(BIOSMEM_SEG,BIOSMEM_VS_POINTER);
1325 RealPt dsapt=real_readd(RealSeg(vsavept),RealOff(vsavept)+4);
1326 if (dsapt) {
1327 for (Bit8u ct=0;ct<0x10;ct++) {
1328 real_writeb(RealSeg(dsapt),RealOff(dsapt)+ct,att_data[ct]);
1329 }
1330 real_writeb(RealSeg(dsapt),RealOff(dsapt)+0x10,0); // overscan
1331 }
1332 /* Setup some special stuff for different modes */
1333 Bit8u feature=real_readb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE);
1334 switch (CurMode->type) {
1335 case M_CGA2:
1336 feature=(feature&~0x30)|0x20;
1337 real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x1e);
1338 break;
1339 case M_CGA4:
1340 feature=(feature&~0x30)|0x20;
1341 if (CurMode->mode==4) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2a);
1342 else if (CurMode->mode==5) real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2e);
1343 else real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2);
1344 break;
1345 case M_TANDY16:
1346 feature=(feature&~0x30)|0x20;
1347 break;
1348 case M_TEXT:
1349 feature=(feature&~0x30)|0x20;
1350 switch (CurMode->mode) {
1351 case 0:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2c);break;
1352 case 1:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x28);break;
1353 case 2:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x2d);break;
1354 case 3:
1355 case 7:real_writeb(BIOSMEM_SEG,BIOSMEM_CURRENT_MSR,0x29);break;
1356 }
1357 break;
1358 case M_LIN4:
1359 case M_EGA:
1360 case M_VGA:
1361 feature=(feature&~0x30);
1362 break;
1363 }
1364 // disabled, has to be set in bios.cpp exclusively
1365 // real_writeb(BIOSMEM_SEG,BIOSMEM_INITIAL_MODE,feature);
1366
1367 if (svgaCard == SVGA_S3Trio) {
1368 /* Setup the CPU Window */
1369 IO_Write(crtc_base,0x6a);
1370 IO_Write(crtc_base+1,0);
1371 /* Setup the linear frame buffer */
1372 IO_Write(crtc_base,0x59);
1373 IO_Write(crtc_base+1,(Bit8u)((S3_LFB_BASE >> 24)&0xff));
1374 IO_Write(crtc_base,0x5a);
1375 IO_Write(crtc_base+1,(Bit8u)((S3_LFB_BASE >> 16)&0xff));
1376 IO_Write(crtc_base,0x6b); // BIOS scratchpad
1377 IO_Write(crtc_base+1,(Bit8u)((S3_LFB_BASE >> 24)&0xff));
1378
1379 /* Setup some remaining S3 registers */
1380 IO_Write(crtc_base,0x41); // BIOS scratchpad
1381 IO_Write(crtc_base+1,0x88);
1382 IO_Write(crtc_base,0x52); // extended BIOS scratchpad
1383 IO_Write(crtc_base+1,0x80);
1384
1385 IO_Write(0x3c4,0x15);
1386 IO_Write(0x3c5,0x03);
1387
1388 // Accellerator setup
1389 Bitu reg_50=S3_XGA_8BPP;
1390 switch (CurMode->type) {
1391 case M_LIN15:
1392 case M_LIN16: reg_50|=S3_XGA_16BPP; break;
1393 case M_LIN32: reg_50|=S3_XGA_32BPP; break;
1394 default: break;
1395 }
1396 switch(CurMode->swidth) {
1397 case 640: reg_50|=S3_XGA_640; break;
1398 case 800: reg_50|=S3_XGA_800; break;
1399 case 1024: reg_50|=S3_XGA_1024; break;
1400 case 1152: reg_50|=S3_XGA_1152; break;
1401 case 1280: reg_50|=S3_XGA_1280; break;
1402 default: break;
1403 }
1404 IO_WriteB(crtc_base,0x50); IO_WriteB(crtc_base+1,reg_50);
1405
1406 Bit8u reg_31, reg_3a;
1407 switch (CurMode->type) {
1408 case M_LIN15:
1409 case M_LIN16:
1410 case M_LIN32:
1411 reg_3a=0x15;
1412 break;
1413 case M_LIN8:
1414 // S3VBE20 does it this way. The other double pixel bit does not
1415 // seem to have an effect on the Trio64.
1416 if(CurMode->special&_VGA_PIXEL_DOUBLE) reg_3a=0x5;
1417 else reg_3a=0x15;
1418 break;
1419 default:
1420 reg_3a=5;
1421 break;
1422 };
1423
1424 switch (CurMode->type) {
1425 case M_LIN4: // <- Theres a discrepance with real hardware on this
1426 case M_LIN8:
1427 case M_LIN15:
1428 case M_LIN16:
1429 case M_LIN32:
1430 reg_31 = 9;
1431 break;
1432 default:
1433 reg_31 = 5;
1434 break;
1435 }
1436 IO_Write(crtc_base,0x3a);IO_Write(crtc_base+1,reg_3a);
1437 IO_Write(crtc_base,0x31);IO_Write(crtc_base+1,reg_31); //Enable banked memory and 256k+ access
1438 IO_Write(crtc_base,0x58);IO_Write(crtc_base+1,0x3); //Enable 8 mb of linear addressing
1439
1440 IO_Write(crtc_base,0x38);IO_Write(crtc_base+1,0x48); //Register lock 1
1441 IO_Write(crtc_base,0x39);IO_Write(crtc_base+1,0xa5); //Register lock 2
1442 } else if (svga.set_video_mode) {
1443 VGA_ModeExtraData modeData;
1444 modeData.ver_overflow = ver_overflow;
1445 modeData.hor_overflow = hor_overflow;
1446 modeData.offset = offset;
1447 modeData.modeNo = CurMode->mode;
1448 modeData.htotal = CurMode->htotal;
1449 modeData.vtotal = CurMode->vtotal;
1450 svga.set_video_mode(crtc_base, &modeData);
1451 }
1452
1453 FinishSetMode(clearmem);
1454
1455 /* Set vga attrib register into defined state */
1456 IO_Read(mono_mode ? 0x3ba : 0x3da);
1457 IO_Write(0x3c0,0x20);
1458
1459 /* Load text mode font */
1460 if (CurMode->type==M_TEXT) {
1461 INT10_ReloadFont();
1462 }
1463 return true;
1464 }
1465
VideoModeMemSize(Bitu mode)1466 Bitu VideoModeMemSize(Bitu mode) {
1467 if (!IS_VGA_ARCH)
1468 return 0;
1469
1470 VideoModeBlock* modelist = NULL;
1471
1472 switch (svgaCard) {
1473 case SVGA_TsengET4K:
1474 case SVGA_TsengET3K:
1475 modelist = ModeList_VGA_Tseng;
1476 break;
1477 case SVGA_ParadisePVGA1A:
1478 modelist = ModeList_VGA_Paradise;
1479 break;
1480 default:
1481 modelist = ModeList_VGA;
1482 break;
1483 }
1484
1485 VideoModeBlock* vmodeBlock = NULL;
1486 Bitu i=0;
1487 while (modelist[i].mode!=0xffff) {
1488 if (modelist[i].mode==mode) {
1489 vmodeBlock = &modelist[i];
1490 break;
1491 }
1492 i++;
1493 }
1494 if (!vmodeBlock)
1495 return 0;
1496
1497 switch(vmodeBlock->type) {
1498 case M_LIN4:
1499 return vmodeBlock->swidth*vmodeBlock->sheight/2;
1500 case M_LIN8:
1501 return vmodeBlock->swidth*vmodeBlock->sheight;
1502 case M_LIN15: case M_LIN16:
1503 return vmodeBlock->swidth*vmodeBlock->sheight*2;
1504 case M_LIN32:
1505 return vmodeBlock->swidth*vmodeBlock->sheight*4;
1506 case M_TEXT:
1507 return vmodeBlock->twidth*vmodeBlock->theight*2;
1508 }
1509 // Return 0 for all other types, those always fit in memory
1510 return 0;
1511 }
1512