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