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