]> 4ch.mooo.com Git - 16.git/blob - 16/v2/source/ENGINE/MODEINIT.C
wwww
[16.git] / 16 / v2 / source / ENGINE / MODEINIT.C
1 /*\r
2 Copyright (C) 1998 BJ Eirich (aka vecna)\r
3 This program is free software; you can redistribute it and/or\r
4 modify it under the terms of the GNU General Public License\r
5 as published by the Free Software Foundation; either version 2\r
6 of the License, or (at your option) any later version.\r
7 This program is distributed in the hope that it will be useful,\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
10 See the GNU General Public Lic\r
11 See the GNU General Public License for more details.\r
12 You should have received a copy of the GNU General Public License\r
13 along with this program; if not, write to the Free Software\r
14 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\r
15 */\r
16 \r
17 #include <dpmi.h>\r
18 #include <sys\nearptr.h>\r
19 #include "verge.h"\r
20 \r
21 void BIOS_SetVideoMode(int mode)\r
22 {\r
23   REGISTERS r;\r
24   SET_AX(r, mode);\r
25   INTERRUPT(0x10, r);\r
26 }\r
27 \r
28 // =============================== Mode 13h ===================================\r
29 \r
30 int Mode13hShutdown(int i)\r
31 {\r
32   if (i) BIOS_SetVideoMode(0x3);\r
33   free(screen);\r
34   return 0;\r
35 }\r
36 \r
37 void InitMode13h(void)\r
38 {\r
39   BIOS_SetVideoMode(0x13);\r
40 \r
41   DriverDesc = "320x200 (Mode 13h, linear)";\r
42   sx=320,   sy=200;\r
43   tx=20,    ty=13;\r
44   cx1=0,    cy1=0;\r
45   cx2=sx-1, cy2=sy-1;\r
46 \r
47   // setup function drivers\r
48   ShowPage=LFB_ShowPage;\r
49   ShutdownVideo=Mode13hShutdown;\r
50 \r
51   video=(byte *) 0xA0000 + __djgpp_conventional_base;\r
52   vscreen=(byte *) valloc(sx*sy, "vscreen", 0);\r
53   screen=vscreen;\r
54   memset(screen, 0, sx*sy);\r
55 }\r
56 \r
57 // ================================= Mode-X ==================================\r
58 \r
59 #define SEQU_ADDR       0x3c4\r
60 #define CRTC_ADDR       0x3d4\r
61 #define MISC_OUTPUT     0x3c2\r
62 \r
63 #define ATTRCON_ADDR    0x3c0\r
64 #define MISC_ADDR       0x3c2\r
65 #define VGAENABLE_ADDR  0x3c3\r
66 #define SEQ_ADDR        0x3c4\r
67 #define GRACON_ADDR     0x3ce\r
68 #define CRTC_ADDR       0x3d4\r
69 #define STATUS_ADDR     0x3da\r
70 \r
71 typedef struct\r
72 {\r
73   unsigned port;\r
74   byte index, value;\r
75 } Register;\r
76 \r
77 typedef Register *RegisterPtr;\r
78 \r
79 Register scr256x256[] =\r
80 {\r
81   { 0x3c2, 0x00, 0xe3},{ 0x3d4, 0x00, 0x5f},{ 0x3d4, 0x01, 0x3f},\r
82   { 0x3d4, 0x02, 0x40},{ 0x3d4, 0x03, 0x82},{ 0x3d4, 0x04, 0x4A},\r
83   { 0x3d4, 0x05, 0x9A},{ 0x3d4, 0x06, 0x23},{ 0x3d4, 0x07, 0xb2},\r
84   { 0x3d4, 0x08, 0x00},{ 0x3d4, 0x09, 0x61},{ 0x3d4, 0x10, 0x0a},\r
85   { 0x3d4, 0x11, 0xac},{ 0x3d4, 0x12, 0xff},{ 0x3d4, 0x13, 0x20},\r
86   { 0x3d4, 0x14, 0x40},{ 0x3d4, 0x15, 0x07},{ 0x3d4, 0x16, 0x1a},\r
87   { 0x3d4, 0x17, 0xa3},{ 0x3c4, 0x01, 0x01},{ 0x3c4, 0x04, 0x0e},\r
88   { 0x3ce, 0x05, 0x40},{ 0x3ce, 0x06, 0x05},{ 0x3c0, 0x10, 0x41},\r
89   { 0x3c0, 0x13, 0x00}\r
90 };\r
91 \r
92 // ================================= Code ====================================\r
93 \r
94 void plane(byte p)\r
95 {\r
96   int hi=1<<p;\r
97   outpw(0x03c4, (hi<<8)|0x02);\r
98 }\r
99 \r
100 int ModeXShutdown(int i)\r
101 {\r
102   if (i) BIOS_SetVideoMode(0x3);\r
103   vfree(screen);\r
104   return 0;\r
105 }\r
106 \r
107 int ModeXShowPage()\r
108 {\r
109   byte *s,*d;\r
110   int x,y,k;\r
111   int sx2;\r
112 \r
113   if (key[SCAN_ALT] && key[SCAN_X]) err("Exiting: ALT-X pressed.");\r
114   RenderGUI();\r
115   cpubyte=PFLIP;\r
116 \r
117   d=video;\r
118   sx2=sx>>2;\r
119 \r
120   for (y=0; y<sy; ++y,d+=sx2)\r
121   {\r
122     s=screen+(y*sx);\r
123     for (k=0; k<4; k++,s-=sx)\r
124     {\r
125       plane(k);\r
126       for (x=0; x<sx2; x++,s+=4)\r
127         d[x]=s[k];\r
128     }\r
129   }\r
130   cpubyte=ETC;\r
131   return 0;\r
132 }\r
133 \r
134 static void outReg(Register r)\r
135 {\r
136   switch (r.port)\r
137   {\r
138     // First handle special cases:\r
139 \r
140     case ATTRCON_ADDR:\r
141       // reset read/write flip-flop\r
142       inp(STATUS_ADDR);\r
143       // ensure VGA output is enabled\r
144       outp(ATTRCON_ADDR, r.index | 0x20);\r
145       outp(ATTRCON_ADDR, r.value);\r
146       break;\r
147 \r
148     case MISC_ADDR:\r
149     case VGAENABLE_ADDR:\r
150       //  directly to the port\r
151       outp(r.port, r.value);\r
152       break;\r
153 \r
154     case SEQ_ADDR:\r
155     case GRACON_ADDR:\r
156     case CRTC_ADDR:\r
157     default:\r
158       // index to port\r
159       outp(r.port, r.index);\r
160       // value to port+1\r
161       outp(r.port + 1, r.value);\r
162       break;\r
163   }\r
164 }\r
165 \r
166 // readyVgaRegs() does the initialization to make the VGA ready to\r
167 // accept any combination of configuration register settings.\r
168 //\r
169 // This involves enabling writes to index 0 to 7 of the CRT controller\r
170 // (port 0x3d4), by clearing the most significant bit (bit 7) of index\r
171 // 0x11.\r
172 \r
173 static void readyVgaRegs(void)\r
174 {\r
175   int v;\r
176 \r
177   outp(0x3d4, 0x11);\r
178   v = inp(0x3d5) & 0x7f;\r
179   outp(0x3d4, 0x11);\r
180   outp(0x3d5, v);\r
181 }\r
182 \r
183 // outRegArray sets n registers according to the array pointed to by r.\r
184 // First, indexes 0-7 of the CRT controller are enabled for writing.\r
185 \r
186 static void outRegArray(Register *r, int n)\r
187 {\r
188   readyVgaRegs();\r
189   while (n--)\r
190     outReg (*r++);\r
191 }\r
192 \r
193 void Set256x256()\r
194 {\r
195   DriverDesc = "256x256 (ModeX, planar)";\r
196 \r
197   outRegArray(scr256x256, sizeof(scr256x256) / sizeof (Register));\r
198 \r
199   sx=256,   sy=256;\r
200   tx=17,    ty=16;\r
201   cx1=0,    cy1=0;\r
202   cx2=sx-1, cy2=sy-1;\r
203 }\r
204 \r
205 void Set320x240()\r
206 { char in_byte;\r
207 \r
208   DriverDesc = "320x240 (ModeX, planar)";\r
209 \r
210   outpw(SEQU_ADDR, 0x0604);\r
211   memset((unsigned char *)0xA0000 + __djgpp_conventional_base,0,0x10000); // for clean mode switch\r
212   outpw(SEQU_ADDR, 0x0110);\r
213   outp(MISC_OUTPUT, 0xe3);\r
214   outpw(SEQU_ADDR, 0x0300);\r
215   outp(CRTC_ADDR, 0x11);\r
216   in_byte = inp((CRTC_ADDR+1));\r
217   in_byte = (in_byte && 0x7f);\r
218   outp((CRTC_ADDR+1), in_byte);\r
219   outpw(CRTC_ADDR, 0x0d06);\r
220   outpw(CRTC_ADDR, 0x3e07);\r
221   outpw(CRTC_ADDR, 0x4109);\r
222   outpw(CRTC_ADDR, 0xea10);\r
223   outpw(CRTC_ADDR, 0xac11);\r
224   outpw(CRTC_ADDR, 0xdf12);\r
225   outpw(CRTC_ADDR, 0x0014);\r
226   outpw(CRTC_ADDR, 0xe715);\r
227   outpw(CRTC_ADDR, 0x0616);\r
228   outpw(CRTC_ADDR, 0xe317);\r
229 \r
230   sx=320,   sy=240;\r
231   tx=20,    ty=15;\r
232   cx1=0,    cy1=0;\r
233   cx2=sx-1, cy2=sy-1;\r
234 }\r
235 \r
236 void Set360x240()\r
237 { char in_byte;\r
238 \r
239   DriverDesc = "360x240 (ModeX, planar)";\r
240 \r
241   outpw(SEQU_ADDR, 0x0604);\r
242   memset((unsigned char *)0xA0000 + __djgpp_conventional_base,0,0x10000); // for clean mode switch\r
243   outpw(SEQU_ADDR, 0x100);\r
244   outp(MISC_OUTPUT, 0xe7);\r
245   outpw(SEQU_ADDR, 0x300);\r
246   outp(CRTC_ADDR, 0x11);\r
247   in_byte = inp((CRTC_ADDR+1));\r
248   in_byte = (in_byte && 0x7f);\r
249   outp((CRTC_ADDR+1), in_byte);\r
250   outpw(CRTC_ADDR, 0x6b00);\r
251   outpw(CRTC_ADDR, 0x5901);\r
252   outpw(CRTC_ADDR, 0x5a02);\r
253   outpw(CRTC_ADDR, 0x8e03);\r
254   outpw(CRTC_ADDR, 0x5e04);\r
255   outpw(CRTC_ADDR, 0x8a05);\r
256   outpw(CRTC_ADDR, 0x0d06);\r
257   outpw(CRTC_ADDR, 0x3e07);\r
258   outpw(CRTC_ADDR, 0x4109);\r
259   outpw(CRTC_ADDR, 0xea10);\r
260   outpw(CRTC_ADDR, 0xac11);\r
261   outpw(CRTC_ADDR, 0xdf12);\r
262   outpw(CRTC_ADDR, 0x2d13);\r
263   outpw(CRTC_ADDR, 0x0014);\r
264   outpw(CRTC_ADDR, 0xe715);\r
265   outpw(CRTC_ADDR, 0x0616);\r
266   outpw(CRTC_ADDR, 0xe317);\r
267 \r
268   sx=360,   sy=240;\r
269   tx=23,    ty=15;\r
270   cx1=0,    cy1=0;\r
271   cx2=sx-1, cy2=sy-1;\r
272 }\r
273 \r
274 void InitModeX(int xres, int yres)\r
275 {\r
276   int found;\r
277 \r
278   BIOS_SetVideoMode(0x13);\r
279 \r
280   found=0;\r
281   if (xres==320 && yres==240) { Set320x240(); found=1; }\r
282   if (xres==360 && yres==240) { Set360x240(); found=1; }\r
283   if (xres==256 && yres==256) { Set256x256(); found=1; }\r
284 \r
285   if (!found)\r
286   {\r
287     // resolution not found, bitch...\r
288     err("Internal error: unknown ModeX resolution");\r
289   }\r
290   // resolution found..\r
291   else\r
292   {\r
293     ShowPage=LFB_ShowPage;\r
294     if (xres != 256 && yres != 256)\r
295       ShowPage=ModeXShowPage;\r
296     ShutdownVideo=ModeXShutdown;\r
297   }\r
298 \r
299   video=(byte *) 0xA0000 + __djgpp_conventional_base;\r
300   vscreen=(byte *) valloc(sx*sy, "vscreen", 0);\r
301   screen=vscreen;\r
302   memset(screen, 0, sx*sy);\r
303 }\r
304 \r
305 // ================================= VESA ====================================\r
306 \r
307 int VESAShutdown(int i)\r
308 {\r
309   if (i) BIOS_SetVideoMode(0x3);\r
310   free(screen);\r
311   return 0;\r
312 }\r
313 \r
314 void VESASetBank(int bank)\r
315 {\r
316   REGISTERS r;\r
317   SET_AX(r, 0x4f05);\r
318   SET_BX(r, 0);\r
319   SET_DX(r, bank);\r
320   INTERRUPT(0x10, r);\r
321 }\r
322 \r
323 int VESAShowPage(void)\r
324 {\r
325   byte *s,*d;\r
326   int y,bytes,bank;\r
327   int span;\r
328 \r
329   if (key[SCAN_ALT] && key[SCAN_X]) err("Exiting: ALT-X pressed.");\r
330   RenderGUI();\r
331   cpubyte=PFLIP;\r
332 \r
333   s=screen;\r
334   d=video;\r
335 \r
336   bank=0;\r
337   bytes=65536;\r
338   VESASetBank(bank++);\r
339 \r
340   // *** no padding exists now, can be rewritten smaller/faster - aen\r
341   for (y=sy; y; y--)\r
342   {\r
343     if (bytes >= sx)\r
344     { memcpy(d,s,sx);\r
345       bytes-=sx;\r
346       s+=sx;\r
347       d+=sx;\r
348     }\r
349     else\r
350     { memcpy(d,s,bytes);\r
351       s+=bytes;\r
352       span=sx-bytes;\r
353 \r
354       VESASetBank(bank++);\r
355       d=video;\r
356       bytes=65536;\r
357 \r
358       memcpy(d,s,span);\r
359       bytes-=span;\r
360       s+=span;\r
361       d+=span;\r
362     }\r
363   }\r
364   cpubyte=ETC;\r
365   return 0;\r
366 }\r
367 \r
368 void Set640x480()\r
369 {\r
370   REGISTERS r;\r
371 \r
372   DriverDesc = "640x480 (VESA, Banked)";\r
373 \r
374   SET_BX(r, 0x0101);\r
375   SET_AX(r, 0x4f02);\r
376   INTERRUPT(0x10, r);\r
377 \r
378   sx=640;  sy=480;\r
379   tx=40;   ty=30;\r
380   cx1=0;   cy1=0;\r
381   cx2=sx-1;cy2=sy-1;\r
382 }\r
383 \r
384 void InitVESA(int xres, int yres)\r
385 {\r
386   int found;\r
387 \r
388   found=0;\r
389   if (xres==640 && yres==480) { Set640x480(); found=1; }\r
390 \r
391   if (!found)\r
392     err("Internal error: unknown VESA resolution");\r
393 \r
394   // setup driver functions\r
395   ShowPage = VESAShowPage; // reassign for banked VESA video blt\r
396   ShutdownVideo = VESAShutdown;\r
397 \r
398   video=(byte *) 0xA0000 + __djgpp_conventional_base;\r
399   vscreen=(byte *) valloc(sx*sy, "vscreen", 0);\r
400   screen=vscreen;\r
401   memset(screen, 0, sx*sy);\r
402 }\r
403 \r
404 // ============================================================================\r
405 \r
406 int InitVideo(int xres, int yres)\r
407 {\r
408   int found;\r
409 \r
410   found=0;\r
411   if (xres==320 && yres==200) { InitMode13h(); found=1; }\r
412   if (xres==320 && yres==240) { InitModeX(xres,yres); found=1; }\r
413   if (xres==360 && yres==240) { InitModeX(xres,yres); found=1; }\r
414   if (xres==256 && yres==256) { InitModeX(xres,yres); found=1; }\r
415   if (xres==640 && yres==480) { InitVESA(xres,yres); found=1; }\r
416 \r
417   if (found)\r
418   {\r
419     tsx=xres; tsy=yres;\r
420     Logp("Sys: Initializing %s.", DriverDesc);\r
421     InitMouse(tsx, tsy);\r
422   }\r
423   else\r
424   {\r
425     InitMode13h();\r
426     tsx=320; tsy=200;\r
427     Logp("Unknown video mode %dx%d; defaulting to mode 13h.", xres, yres);\r
428     InitMouse(tsx, tsy);\r
429   }\r
430   LogDone();\r
431   return found;\r
432 }\r