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