1 /*
2  *  Copyright (C) 2002-2010  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 /* $Id: vga.cpp,v 1.36 2009-05-27 09:15:41 qbix79 Exp $ */
20 
21 #include "dosbox.h"
22 //#include "setup.h"
23 #include "video.h"
24 #include "pic.h"
25 #include "vga.h"
26 
27 #include <string.h>
28 
29 VGA_Type vga;
30 SVGA_Driver svga;
31 
32 Bit32u CGA_2_Table[16];
33 Bit32u CGA_4_Table[256];
34 Bit32u CGA_4_HiRes_Table[256];
35 Bit32u CGA_16_Table[256];
36 Bit32u TXT_Font_Table[16];
37 Bit32u TXT_FG_Table[16];
38 Bit32u TXT_BG_Table[16];
39 Bit32u ExpandTable[256];
40 Bit32u Expand16Table[4][16];
41 Bit32u FillTable[16];
42 Bit32u ColorTable[16];
43 
VGA_SetModeNow(VGAModes mode)44 void VGA_SetModeNow(VGAModes mode) {
45 	if (vga.mode == mode) return;
46 	vga.mode=mode;
47 	VGA_SetupHandlers();
48 	VGA_StartResize(0);
49 }
50 
51 
VGA_SetMode(VGAModes mode)52 void VGA_SetMode(VGAModes mode) {
53 	if (vga.mode == mode) return;
54 	vga.mode=mode;
55 	VGA_SetupHandlers();
56 	VGA_StartResize();
57 }
58 
VGA_DetermineMode(void)59 void VGA_DetermineMode(void) {
60 	if (svga.determine_mode) {
61 		svga.determine_mode();
62 		return;
63 	}
64 	/* Test for VGA output active or direct color modes */
65 	switch (vga.s3.misc_control_2 >> 4) {
66 	case 0:
67 		if (vga.attr.mode_control & 1) { // graphics mode
68 			if (IS_VGA_ARCH && (vga.gfx.mode & 0x40)) {
69 				// access above 256k?
70 				if (vga.s3.reg_31 & 0x8) VGA_SetMode(M_LIN8);
71 				else VGA_SetMode(M_VGA);
72 			}
73 			else if (vga.gfx.mode & 0x20) VGA_SetMode(M_CGA4);
74 			else if ((vga.gfx.miscellaneous & 0x0c)==0x0c) VGA_SetMode(M_CGA2);
75 			else {
76 				// access above 256k?
77 				if (vga.s3.reg_31 & 0x8) VGA_SetMode(M_LIN4);
78 				else VGA_SetMode(M_EGA);
79 			}
80 		} else {
81 			VGA_SetMode(M_TEXT);
82 		}
83 		break;
84 	case 1:VGA_SetMode(M_LIN8);break;
85 	case 3:VGA_SetMode(M_LIN15);break;
86 	case 5:VGA_SetMode(M_LIN16);break;
87 	case 13:VGA_SetMode(M_LIN32);break;
88 	}
89 }
90 
VGA_StartResize(Bitu delay)91 void VGA_StartResize(Bitu delay /*=50*/) {
92 	if (!vga.draw.resizing) {
93 		vga.draw.resizing=true;
94 		if (vga.mode==M_ERROR) delay = 5;
95 		/* Start a resize after delay (default 50 ms) */
96 		if (delay==0) VGA_SetupDrawing(0);
97 		else PIC_AddEvent(VGA_SetupDrawing,(float)delay);
98 	}
99 }
100 
VGA_SetClock(Bitu which,Bitu target)101 void VGA_SetClock(Bitu which,Bitu target) {
102 	if (svga.set_clock) {
103 		svga.set_clock(which, target);
104 		return;
105 	}
106 	struct{
107 		Bitu n,m;
108 		Bits err;
109 	} best;
110 	best.err=target;
111 	best.m=1;
112 	best.n=1;
113 	Bitu n,r;
114 	Bits m;
115 
116 	for (r = 0; r <= 3; r++) {
117 		Bitu f_vco = target * (1 << r);
118 		if (MIN_VCO <= f_vco && f_vco < MAX_VCO) break;
119     }
120 	for (n=1;n<=31;n++) {
121 		m=(target * (n + 2) * (1 << r) + (S3_CLOCK_REF/2)) / S3_CLOCK_REF - 2;
122 		if (0 <= m && m <= 127)	{
123 			Bitu temp_target = S3_CLOCK(m,n,r);
124 			Bits err = target - temp_target;
125 			if (err < 0) err = -err;
126 			if (err < best.err) {
127 				best.err = err;
128 				best.m = m;
129 				best.n = n;
130 			}
131 		}
132     }
133 	/* Program the s3 clock chip */
134 	vga.s3.clk[which].m=best.m;
135 	vga.s3.clk[which].r=r;
136 	vga.s3.clk[which].n=best.n;
137 	VGA_StartResize();
138 }
139 
VGA_SetCGA2Table(Bit8u val0,Bit8u val1)140 void VGA_SetCGA2Table(Bit8u val0,Bit8u val1) {
141 	Bit8u total[2]={ val0,val1};
142 	for (Bitu i=0;i<16;i++) {
143 		CGA_2_Table[i]=
144 #ifdef WORDS_BIGENDIAN
145 			(total[(i >> 0) & 1] << 0  ) | (total[(i >> 1) & 1] << 8  ) |
146 			(total[(i >> 2) & 1] << 16 ) | (total[(i >> 3) & 1] << 24 );
147 #else
148 			(total[(i >> 3) & 1] << 0  ) | (total[(i >> 2) & 1] << 8  ) |
149 			(total[(i >> 1) & 1] << 16 ) | (total[(i >> 0) & 1] << 24 );
150 #endif
151 	}
152 }
153 
VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3)154 void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3) {
155 	Bit8u total[4]={ val0,val1,val2,val3};
156 	for (Bitu i=0;i<256;i++) {
157 		CGA_4_Table[i]=
158 #ifdef WORDS_BIGENDIAN
159 			(total[(i >> 0) & 3] << 0  ) | (total[(i >> 2) & 3] << 8  ) |
160 			(total[(i >> 4) & 3] << 16 ) | (total[(i >> 6) & 3] << 24 );
161 #else
162 			(total[(i >> 6) & 3] << 0  ) | (total[(i >> 4) & 3] << 8  ) |
163 			(total[(i >> 2) & 3] << 16 ) | (total[(i >> 0) & 3] << 24 );
164 #endif
165 		CGA_4_HiRes_Table[i]=
166 #ifdef WORDS_BIGENDIAN
167 			(total[((i >> 0) & 1) | ((i >> 3) & 2)] << 0  ) | (total[((i >> 1) & 1) | ((i >> 4) & 2)] << 8  ) |
168 			(total[((i >> 2) & 1) | ((i >> 5) & 2)] << 16 ) | (total[((i >> 3) & 1) | ((i >> 6) & 2)] << 24 );
169 #else
170 			(total[((i >> 3) & 1) | ((i >> 6) & 2)] << 0  ) | (total[((i >> 2) & 1) | ((i >> 5) & 2)] << 8  ) |
171 			(total[((i >> 1) & 1) | ((i >> 4) & 2)] << 16 ) | (total[((i >> 0) & 1) | ((i >> 3) & 2)] << 24 );
172 #endif
173 	}
174 }
175 
VGA_Init(Section * sec)176 void VGA_Init(Section* sec) {
177 //	Section_prop * section=static_cast<Section_prop *>(sec);
178 	vga.draw.resizing=false;
179 	vga.mode=M_ERROR;			//For first init
180 	SVGA_Setup_Driver();
181 	VGA_SetupMemory(sec);
182 	VGA_SetupMisc();
183 	VGA_SetupDAC();
184 	VGA_SetupGFX();
185 	VGA_SetupSEQ();
186 	VGA_SetupAttr();
187 	VGA_SetupOther();
188 	VGA_SetupXGA();
189 	VGA_SetClock(0,CLK_25);
190 	VGA_SetClock(1,CLK_28);
191 /* Generate tables */
192 	VGA_SetCGA2Table(0,1);
193 	VGA_SetCGA4Table(0,1,2,3);
194 	Bitu i,j;
195 	for (i=0;i<256;i++) {
196 		ExpandTable[i]=i | (i << 8)| (i <<16) | (i << 24);
197 	}
198 	for (i=0;i<16;i++) {
199 		TXT_FG_Table[i]=i | (i << 8)| (i <<16) | (i << 24);
200 		TXT_BG_Table[i]=i | (i << 8)| (i <<16) | (i << 24);
201 #ifdef WORDS_BIGENDIAN
202 		FillTable[i]=
203 			((i & 1) ? 0xff000000 : 0) |
204 			((i & 2) ? 0x00ff0000 : 0) |
205 			((i & 4) ? 0x0000ff00 : 0) |
206 			((i & 8) ? 0x000000ff : 0) ;
207 		TXT_Font_Table[i]=
208 			((i & 1) ? 0x000000ff : 0) |
209 			((i & 2) ? 0x0000ff00 : 0) |
210 			((i & 4) ? 0x00ff0000 : 0) |
211 			((i & 8) ? 0xff000000 : 0) ;
212 #else
213 		FillTable[i]=
214 			((i & 1) ? 0x000000ff : 0) |
215 			((i & 2) ? 0x0000ff00 : 0) |
216 			((i & 4) ? 0x00ff0000 : 0) |
217 			((i & 8) ? 0xff000000 : 0) ;
218 		TXT_Font_Table[i]=
219 			((i & 1) ? 0xff000000 : 0) |
220 			((i & 2) ? 0x00ff0000 : 0) |
221 			((i & 4) ? 0x0000ff00 : 0) |
222 			((i & 8) ? 0x000000ff : 0) ;
223 #endif
224 	}
225 	for (j=0;j<4;j++) {
226 		for (i=0;i<16;i++) {
227 #ifdef WORDS_BIGENDIAN
228 			Expand16Table[j][i] =
229 				((i & 1) ? 1 << j : 0) |
230 				((i & 2) ? 1 << (8 + j) : 0) |
231 				((i & 4) ? 1 << (16 + j) : 0) |
232 				((i & 8) ? 1 << (24 + j) : 0);
233 #else
234 			Expand16Table[j][i] =
235 				((i & 1) ? 1 << (24 + j) : 0) |
236 				((i & 2) ? 1 << (16 + j) : 0) |
237 				((i & 4) ? 1 << (8 + j) : 0) |
238 				((i & 8) ? 1 << j : 0);
239 #endif
240 		}
241 	}
242 }
243 
SVGA_Setup_Driver(void)244 void SVGA_Setup_Driver(void) {
245 	memset(&svga, 0, sizeof(SVGA_Driver));
246 
247 	switch(svgaCard) {
248 	case SVGA_S3Trio:
249 		SVGA_Setup_S3Trio();
250 		break;
251 	case SVGA_TsengET4K:
252 		SVGA_Setup_TsengET4K();
253 		break;
254 	case SVGA_TsengET3K:
255 		SVGA_Setup_TsengET3K();
256 		break;
257 	case SVGA_ParadisePVGA1A:
258 		SVGA_Setup_ParadisePVGA1A();
259 		break;
260 	default:
261 		vga.vmemsize = vga.vmemwrap = 256*1024;
262 		break;
263 	}
264 }
265