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