OpenGL support under Cygwin/SDL
[btb/d2x.git] / arch / dos_init.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/dos_init.c,v $
3  * $Revision: 1.3 $
4  * $Author: bradleyb $
5  * $Date: 2001-01-29 13:35:08 $
6  *
7  * Dos initialization
8  *
9  * $Log: not supported by cvs2svn $
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include <conf.h>
14 #endif
15
16 #include <stdio.h>
17 #include <string.h>
18 #ifdef __DJGPP__
19 #define _BORLAND_DOS_REGS 1
20 #endif
21 #include <dos.h>
22
23 #include "pstypes.h"
24 #include "inferno.h"
25 #include "text.h"
26 #include "console.h"
27 #include "args.h"
28 #include "error.h"
29
30 #include "joy.h"
31 #include "timer.h"
32 #include "key.h"
33 #include "mono.h"
34 #include "u_dpmi.h"
35 #include "mouse.h"
36
37 //added on 9/15/98 by Victor Rachels to add cd controls
38 //#include "bcd.h"
39 //end this section addition - Victor Rachels
40
41
42 void install_int3_handler(void);
43
44 #ifdef __WATCOMC__
45 int __far descent_critical_error_handler( unsigned deverr, unsigned errcode, unsigned far * devhdr );
46 #endif
47
48 #ifndef NDEBUG
49 #ifdef __WATCOMC__
50 void do_heap_check()
51 {
52         int heap_status;
53
54         heap_status = _heapset( 0xFF );
55         switch( heap_status )
56         {
57         case _HEAPBADBEGIN:
58                 mprintf((1, "ERROR - heap is damaged\n"));
59                 Int3();
60                 break;
61         case _HEAPBADNODE:
62                 mprintf((1, "ERROR - bad node in heap\n" ));
63                 Int3();
64                 break;
65         }
66 }
67 #endif
68 #endif
69
70
71
72 #ifdef VR_DEVICES
73 int is_3dbios_installed()
74 {
75         dpmi_real_regs rregs;
76         memset(&rregs,0,sizeof(dpmi_real_regs));
77         rregs.eax = 0x4ed0;
78         //rregs.ebx = 0x3d10;   
79         dpmi_real_int386x( 0x10, &rregs );
80         if ( (rregs.edx & 0xFFFF) != 0x3344 )
81                 return 0;
82         else
83                 return 1;
84 }
85 #endif
86
87 // Returns 1 if ok, 0 if failed...
88 int init_gameport()
89 {
90         union REGS regs;
91
92         memset(&regs,0,sizeof(regs));
93         regs.x.eax = 0x8400;
94         regs.x.edx = 0xF0;
95         int386( 0x15, &regs, &regs );
96         if ( ( regs.x.eax & 0xFFFF ) == 0x4753 /*'SG'*/ )
97                 return 1;
98         else
99                 return 0;
100 }
101
102 void check_dos_version()
103 {
104         int major, minor;
105         union REGS regs;
106
107         memset(&regs,0,sizeof(regs));
108         regs.x.eax = 0x3000;                                                    // Get MS-DOS Version Number
109         int386( 0x21, &regs, &regs );
110
111         major = regs.h.al;
112         minor = regs.h.ah;
113         
114         if ( major < 5 )        {
115                 printf( "Using MS-DOS version %d.%d\nThis is not compatable with Descent.", major, minor);
116                 exit(1);
117         }
118         //printf( "\nUsing MS-DOS %d.%d...\n", major, minor );
119 }
120
121 void dos_check_file_handles(int num_required)
122 {
123         int i, n;
124         FILE * fp[16];
125
126         if ( num_required > 16 )
127                 num_required = 16;
128
129         n = 0;  
130         for (i=0; i<16; i++ )
131                 fp[i] = NULL;
132         for (i=0; i<16; i++ )   {
133                 fp[i] = fopen( "nul", "wb" );
134                 if ( !fp[i] ) break;
135         }
136         n = i;
137         for (i=0; i<16; i++ )   {
138                 if (fp[i])
139                         fclose(fp[i]);
140         }
141         if ( n < num_required ) {
142                 printf( "\n%s\n", TXT_NOT_ENOUGH_HANDLES );
143                 printf( "------------------------\n" );
144                 printf( "%d/%d %s\n", n, num_required, TXT_HANDLES_1 );
145                 printf( "%s\n", TXT_HANDLES_2);
146                 printf( "%s\n", TXT_HANDLES_3);
147                 exit(1);
148         }
149 }
150
151 #define NEEDED_DOS_MEMORY                       ( 300*1024)             // 300 K
152 #define NEEDED_LINEAR_MEMORY                    (7680*1024)             // 7.5 MB
153 #define LOW_PHYSICAL_MEMORY_CUTOFF      (5*1024*1024)   // 5.0 MB
154 #define NEEDED_PHYSICAL_MEMORY          (2000*1024)             // 2000 KB
155
156 extern int piggy_low_memory;
157
158 void mem_int_to_string( int number, char *dest )
159 {
160         int i,l,c;
161         char buffer[20],*p;
162
163         sprintf( buffer, "%d", number );
164
165         l = strlen(buffer);
166         if (l<=3) {
167                 // Don't bother with less than 3 digits
168                 sprintf( dest, "%d", number );
169                 return;
170         }
171
172         c = l % 3;
173         p=dest;
174         for (i=0; i<l; i++ ) {
175                 if (c==0) {
176                         if (i) *p++=',';
177             c = 3;
178         }
179         c--;
180         *p++ = buffer[i];
181     }
182         *p++ = '\0';
183 }
184
185 void check_memory()
186 {
187         char text[32];
188
189         printf( "\n%s\n", TXT_AVAILABLE_MEMORY);
190         printf( "----------------\n" );
191         mem_int_to_string( dpmi_dos_memory/1024, text );
192         printf( "Conventional: %7s KB\n", text );
193         mem_int_to_string( dpmi_physical_memory/1024, text );
194         printf( "Extended:     %7s KB\n", text );
195         if ( dpmi_available_memory > dpmi_physical_memory )     {
196                 mem_int_to_string( (dpmi_available_memory-dpmi_physical_memory)/1024, text );
197         } else {
198                 mem_int_to_string( 0, text );
199         }
200         printf( "Virtual:      %7s KB\n", text );
201         printf( "\n" );
202
203         if ( dpmi_dos_memory < NEEDED_DOS_MEMORY )      {
204                 printf( "%d %s\n", NEEDED_DOS_MEMORY - dpmi_dos_memory, TXT_MEMORY_CONFIG );
205                 exit(1);
206         }
207
208         if ( dpmi_available_memory < NEEDED_LINEAR_MEMORY )     {
209                 if ( dpmi_virtual_memory )      {
210                         printf( "%d %s\n", NEEDED_LINEAR_MEMORY - dpmi_available_memory, TXT_RECONFIGURE_VMM );
211                 } else {
212                         printf( "%d %s\n", NEEDED_LINEAR_MEMORY - dpmi_available_memory, TXT_MORE_MEMORY );
213                         printf( "%s\n", TXT_MORE_MEMORY_2);
214                 }
215                 exit(1);
216         }
217
218         if ( dpmi_physical_memory < NEEDED_PHYSICAL_MEMORY )    {
219                 printf( "%d %s\n", NEEDED_PHYSICAL_MEMORY - dpmi_physical_memory, TXT_PHYSICAL_MEMORY );
220                 if ( dpmi_virtual_memory )      {       
221                         printf( "%s\n", TXT_PHYSICAL_MEMORY_2);
222                 }
223                 exit(1);
224         }
225
226         if ( dpmi_physical_memory < LOW_PHYSICAL_MEMORY_CUTOFF )        {
227                 piggy_low_memory = 1;
228         }
229 }
230
231 //NO_STACK_SIZE_CHECK uint * stack, *stack_ptr;
232 //NO_STACK_SIZE_CHECK int stack_size, unused_stack_space;
233 //NO_STACK_SIZE_CHECK int sil;
234 //NO_STACK_SIZE_CHECK 
235 //NO_STACK_SIZE_CHECK int main(int argc,char **argv)
236 //NO_STACK_SIZE_CHECK {
237 //NO_STACK_SIZE_CHECK   uint ret_value;
238 //NO_STACK_SIZE_CHECK   
239 //NO_STACK_SIZE_CHECK   unused_stack_space = 0;
240 //NO_STACK_SIZE_CHECK   stack = &ret_value;
241 //NO_STACK_SIZE_CHECK   stack_size = stackavail()/4;
242 //NO_STACK_SIZE_CHECK 
243 //NO_STACK_SIZE_CHECK   for ( sil=0; sil<stack_size; sil++ )    {
244 //NO_STACK_SIZE_CHECK           stack--;
245 //NO_STACK_SIZE_CHECK           *stack = 0xface0123;
246 //NO_STACK_SIZE_CHECK   }
247 //NO_STACK_SIZE_CHECK
248 //NO_STACK_SIZE_CHECK   ret_value = descent_main( argc, argv );         // Rename main to be descent_main
249 //NO_STACK_SIZE_CHECK 
250 //NO_STACK_SIZE_CHECK   for ( sil=0; sil<stack_size; sil++ )    {
251 //NO_STACK_SIZE_CHECK           if ( *stack == 0xface0123 )     
252 //NO_STACK_SIZE_CHECK                   unused_stack_space++;
253 //NO_STACK_SIZE_CHECK           stack++;
254 //NO_STACK_SIZE_CHECK   }
255 //NO_STACK_SIZE_CHECK 
256 //NO_STACK_SIZE_CHECK   mprintf(( 0, "Program used %d/%d stack space\n", (stack_size - unused_stack_space)*4, stack_size*4 ));
257 //NO_STACK_SIZE_CHECK   key_getch();
258 //NO_STACK_SIZE_CHECK 
259 //NO_STACK_SIZE_CHECK   return ret_value;
260 //NO_STACK_SIZE_CHECK }
261
262 extern int digi_timer_rate;
263
264 #ifdef __WATCOMC__
265 #pragma off (check_stack)
266 int __far descent_critical_error_handler(unsigned deverror, unsigned errcode, unsigned __far * devhdr )
267 {
268         devhdr = devhdr;
269         descent_critical_error++;
270         descent_critical_deverror = deverror;
271         descent_critical_errcode = errcode;
272         return _HARDERR_FAIL;
273 }
274 void chandler_end (void)  // dummy functions
275 {
276 }
277 #pragma on (check_stack)
278 #endif
279
280 void arch_init_start() {
281         // Initialize DPMI before anything else!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
282         // (To check memory size and availbabitliy and allocate some low DOS memory)
283         // adb: no TXT_... loaded yet
284         //if (Inferno_verbose) printf( "%s... ", TXT_INITIALIZING_DPMI);
285         con_printf(CON_VERBOSE, "Initializing DPMI services... ");
286         dpmi_init(1);             // Before anything
287         con_printf(CON_VERBOSE, "\n" );
288
289 #ifndef __GNUC__
290         con_printf(CON_VERBOSE, "\n%s...", TXT_INITIALIZING_CRIT);
291         if (!dpmi_lock_region((void near *)descent_critical_error_handler,(char *)chandler_end - (char near *)descent_critical_error_handler))  {
292                 Error( "Unable to lock critial error handler" );
293         }
294         if (!dpmi_lock_region(&descent_critical_error,sizeof(int)))     {
295                 Error( "Unable to lock critial error handler" );
296         }
297         if (!dpmi_lock_region(&descent_critical_deverror,sizeof(unsigned)))     {
298                 Error( "Unable to lock critial error handler" );
299         }
300         if (!dpmi_lock_region(&descent_critical_errcode,sizeof(unsigned)))      {
301                 Error( "Unable to lock critial error handler" );
302         }
303         _harderr((void *) descent_critical_error_handler );
304         //Above line modified by KRB, added (void *) cast
305         //for the compiler.
306 #endif
307 }
308
309 void arch_init() {
310         if ( !FindArg( "-nodoscheck" ))
311                 check_dos_version();
312         
313         if ( !FindArg( "-nofilecheck" ))
314                 dos_check_file_handles(5);
315
316         if ( !FindArg( "-nomemcheck" ))
317                 check_memory();
318
319         #ifndef NDEBUG
320                 minit();
321                 mopen( 0, 9, 1, 78, 15, "Debug Spew");
322                 mopen( 1, 2, 1, 78,  5, "Errors & Serious Warnings");
323         #endif
324
325 /*        if (!WVIDEO_running)
326                 mprintf((0,"WVIDEO_running = %d\n",WVIDEO_running));*/
327
328         //if (!WVIDEO_running) install_int3_handler();
329
330
331         con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_2);
332         timer_init();
333         timer_set_rate( digi_timer_rate );                      // Tell our timer how fast to go (120 Hz)
334         joy_set_timer_rate( digi_timer_rate );      // Tell joystick how fast timer is going
335
336         con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_3);
337         key_init();
338         if (!FindArg( "-nomouse" ))     {
339                 con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_4);
340                 if (FindArg( "-nocyberman" ))
341                         mouse_init(0);
342                 else
343                         mouse_init(1);
344         } else {
345                 con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_5);
346         }
347         if (!FindArg( "-nojoystick" ))  {
348                 con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_6);
349                 joy_init();
350                 if ( FindArg( "-joyslow" ))     {
351                         con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_7);
352                         joy_set_slow_reading(JOY_SLOW_READINGS);
353                 }
354                 if ( FindArg( "-joypolled" ))   {
355                         con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_8);
356                         joy_set_slow_reading(JOY_POLLED_READINGS);
357                 }
358                 if ( FindArg( "-joybios" ))     {
359                         con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_9);
360                         joy_set_slow_reading(JOY_BIOS_READINGS);
361                 }
362                 if ( FindArg( "-joynice" ))     {
363                         con_printf(CON_VERBOSE, "\n%s", "Using nice joystick poller..." );
364                         joy_set_slow_reading(JOY_FRIENDLY_READINGS);
365                 }
366                 if ( FindArg( "-gameport" ))    {
367                         if ( init_gameport() )  {                       
368                                 joy_set_slow_reading(JOY_BIOS_READINGS);
369                         } else {
370                                 Error( "\nCouldn't initialize the Notebook Gameport.\nMake sure the NG driver is loaded.\n" );
371                         }
372                 }
373         } else {
374                 con_printf(CON_VERBOSE, "\n%s", TXT_VERBOSE_10);
375         }
376         #if 0 // no divzero
377         if (Inferno_verbose) printf( "\n%s", TXT_VERBOSE_11);
378         div0_init(DM_ERROR);
379         #endif
380 }