]> icculus.org git repositories - btb/d2x.git/blob - main/old/descentw.c
Fix crash if Num_walls=0
[btb/d2x.git] / main / old / descentw.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14
15 #pragma off (unreferenced)
16 static char rcsid[] = "$Id: descentw.c,v 1.1.1.1 2001-01-19 03:30:14 bradleyb Exp $";
17 #pragma on (unreferenced)
18
19 #include "desw.h"
20
21 #include <mmsystem.h>
22 #include <setjmp.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26
27
28 #include "winapp.h"
29 #include "error.h"
30 #include "gr.h"
31 #include "digi.h"
32 #include "key.h"
33 #include "inferno.h"
34 #include "gamepal.h"
35 #include "game.h"
36 #include "songs.h"
37 #include "mono.h"
38 #include "screens.h"
39 #include "config.h"
40 #include "newdemo.h"
41 #include "text.h"
42 #include "menu.h"
43 #include "vers_id.h"
44 #include "mvelibw.h"
45 #include "modem.h"
46 #include "cntrlcen.h"
47
48 #define D2_ICON 50
49
50 #define MIN_VIRTUAL_MEM_FREE            (16 * (1024*1024))
51 #define MIN_PHYSICAL_MEM_FREE           (16 * (1024*1024))
52 #define SOUND_22K_CUTOFF                        (16 *1024*1024)         // 8.0 MB
53
54
55 //      Globals --------------------------------------------------------------------
56
57 HWND                    _hAppWnd;                                               // Descent Window
58 HINSTANCE       _hAppInstance;
59 int                     _DDraw = 0;                                             // No DirectX
60 char                    *_OffscreenCanvasBits;          // Pointer to Offscreen Canvas Bits.
61 BOOL                    _AppActive = FALSE;                     // Is application active?
62 BOOL                    _AppPaused = FALSE;                     // Shall we run game?
63 BOOL                    _AppInit = FALSE;                               // Is application initialized?
64 BOOL                    _RedrawScreen=FALSE;                    // Shall we force a redraw of the screen?
65 SCREEN_CONTEXT _SCRContext;
66
67 HANDLE          hDescent2Mutex = NULL;          // handle to determine whether D2 is already running
68 HANDLE          hDescent2Mutex2 = NULL;
69
70 BOOL                    AllowActivates = FALSE;
71
72 //      HACK, to keep original CD audio vol.
73 DWORD CD_audio_desktop_vol = 0;
74 int CD_audio_desktop_dev = -1;
75
76 //      EXTERNS
77
78 int Platform_system=0;
79
80
81 extern int Mono_initialized;
82 extern int WinEnableInt3;
83 extern int DD_Emulation;
84 extern int Skip_briefing_screens;               // So we can skip the briefing 
85 extern int digi_system_initialized;
86 extern int framerate_on;
87 extern int Current_display_mode;
88 extern ubyte gr_palette_faded_out;
89 extern int piggy_low_memory;                            // FROM PIGGY.C!
90 extern RECT ViewportRect;
91 extern int Joystick_calibrating;
92
93 // Game State and other Variables ---------------------------------------------
94
95 static char                     WinErrorMessage[512];
96 static BOOL                     WinErrorTrap = FALSE;
97 static BOOL                     GameShutdown = FALSE;
98 //static BOOL                   GameInitialized = FALSE;
99 static BOOL                     WinEnableMovies = TRUE;
100
101
102 //      External Functions ---------------------------------------------------------
103
104 extern void grwin_gdi_realizepal(HDC hdc);
105 extern void grwin_cleanup_palette();
106
107 extern void GameLoop(int, int);
108 extern void game_setup(void);
109 extern void check_joystick_calibration();
110 extern void DDResizeViewport(void);
111 extern void SetWinMonoInfo(HWND hWnd, HINSTANCE hInstance);
112
113 extern void InitCD(char *arg);
114 extern void     InitVideo(void);
115 extern void     InitIO(void);
116 extern void     InitData(void);
117 extern void     InitSound(void);
118 extern void     InitNetwork(void);
119 extern void InitDescent(void);
120 extern void InitPilot(void);    
121
122
123 //      Function Prototypes --------------------------------------------------------
124
125 int RunGame(int argc, char *argv[]);
126 int RestoreGameSurfaces(void);
127 void ValidateSystem(void);
128 void MakeCodeWritable(void);
129 int ParseArgs(char *argv[], LPSTR lpCmdLine);
130 void WErrorCatch(char *message);
131
132 void DoRegisterCheck(void);
133
134 void AppExit();
135 void AppPaint(HWND hWnd, HDC hdc);
136 void AppSize(HWND hWnd);
137 void AppActivate(HWND hWnd, UINT wParam);
138 void AppQueryPalette(HWND hWnd);
139 void AppPaletteChange(HWND hWnd, UINT wParam);
140 void AppDisplayChange(HWND hWnd, int w, int h, int bpp);
141 BOOL AppHandleSystemKeys(UINT msg, UINT wParam, UINT lParam);
142
143 BOOL GameCheckMultiReactor();
144
145 LRESULT WINAPI _export DescentWndProc(HWND hWnd,UINT msg,UINT wParam,
146                                                                                                          LPARAM lParam);
147
148
149
150 // Initialization and Destruction
151 //      ----------------------------------------------------------------------------
152
153 BOOL AppInit(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
154 {
155 //      Create Application Window and Initialize WinG stuff.
156         WNDCLASS wc;
157
158 #ifdef RELEASE
159         WinEnableInt3=0;
160 #else
161         WinEnableInt3=1;
162 #endif
163
164 #ifndef NDEBUG
165         if (FindArg("-logfile")) loginit("descentw.log");
166 #endif
167
168         ValidateSystem();
169
170         if (!hPrev) {
171                 wc.hCursor                              = LoadCursor(NULL, IDC_ARROW);
172                 wc.hIcon                                        = LoadIcon(hInst, MAKEINTRESOURCE(D2_ICON));
173                 wc.lpszMenuName         = NULL;
174                 wc.lpszClassName                = "DescentWndClass";
175                 wc.hbrBackground                = (HBRUSH)GetStockObject(BLACK_BRUSH);
176                 wc.hInstance                    = hInst;
177                 wc.style                                        = CS_DBLCLKS;
178                 wc.lpfnWndProc                  = (WNDPROC)DescentWndProc;
179                 wc.cbWndExtra                   = 0;
180                 wc.cbClsExtra                   = 0;
181
182                 if (!RegisterClass(&wc)) return FALSE;
183         }
184
185 //      Arrgh, make entire code segment writable for now.
186 //      -codereadonly forces read only code (debug purposes)
187
188         if (!FindArg("-codereadonly")) 
189                 MakeCodeWritable();
190
191 #ifndef RELEASE
192         cinit();
193 #endif
194
195         atexit(AppExit);
196
197         _hAppInstance = hInst;
198         _hAppWnd = CreateWindowEx(WS_EX_APPWINDOW,
199                                         "DescentWndClass", 
200                                         WINAPP_NAME,
201                                         WS_POPUP | WS_SYSMENU | WS_BORDER,
202                                         0, 0,
203                                         GetSystemMetrics(SM_CXSCREEN),
204                                         GetSystemMetrics(SM_CYSCREEN),
205                                         NULL, 
206                                         NULL, 
207                                         hInst, 
208                                         NULL);
209
210         Assert(_hAppWnd != 0);
211
212         ShowWindow(_hAppWnd, SW_SHOWNORMAL);
213         UpdateWindow(_hAppWnd);
214
215 //      Tell Descent Libraries about Windows
216         HideCursorW();
217 //      LoadCursorWin(MOUSE_WAIT_CURSOR);
218 //      ShowCursorW();
219
220 #ifdef RELEASE
221 #ifndef NDEBUG 
222         if (FindArg("-monodebug")) Mono_initialized = 1;
223         else // link to below line!
224 #endif  
225         Mono_initialized = 0;
226 #else
227         Mono_initialized = 1;
228 #endif
229
230         minit();
231
232         SetLibraryWinInfo(_hAppWnd, _hAppInstance);
233
234         #ifndef NDEBUG
235                 mopen( 0, 9, 1, 78, 15, "Debug Spew");
236                 mopen( 1, 2, 1, 78,  5, "Errors & Serious Warnings");
237         #endif
238
239         return TRUE;
240 }
241
242
243 void AppExit()
244 {
245 //      HACK do this when the application is closing! restore the CD audio volume.
246         if (CD_audio_desktop_dev != -1) 
247                 auxSetVolume(CD_audio_desktop_dev, CD_audio_desktop_vol);
248
249         grwin_cleanup_palette();
250
251         LoadCursorWin(MOUSE_DEFAULT_CURSOR);
252         ShowCursorW();
253
254 #ifndef RELEASE
255         if (WinErrorTrap) {
256                 cprintf("\n\n%s", WinErrorMessage);
257                 cgetch();
258         }
259         else {
260                 CloseWindow(_hAppWnd);
261                 cprintf("\n\nDescent II for Win95 done...\n");
262                 cgetch();
263         }
264         cclose();
265 #else 
266         if (WinErrorTrap)
267                 MessageBox(NULL, WinErrorMessage, "Descent II error", MB_OK);
268 #endif
269
270 #ifndef NDEBUG
271         logclose();
272 #endif
273
274         if (hDescent2Mutex2) 
275                 CloseHandle(hDescent2Mutex2);
276
277         if (hDescent2Mutex) 
278                 CloseHandle(hDescent2Mutex);            // Destroy Mutex Object!
279 }
280
281 extern char CDROM_dir[30];
282
283 void DoRegisterCheck()
284 {
285         STARTUPINFO si;
286         PROCESS_INFORMATION pi;
287         BOOL flag;
288         char filename[64];
289
290         strcpy(filename, CDROM_dir);
291         strcat(filename, "regcard.exe");
292
293         memset(&si, 0, sizeof(si));
294         si.cb = sizeof(si);
295         si.dwFlags = STARTF_USESHOWWINDOW;
296         si.wShowWindow = SW_SHOW;
297
298         flag = CreateProcess(
299                         NULL,
300                         filename, NULL, NULL,
301                         FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL,
302                         &si, &pi);                      
303         if (flag) {
304                 DWORD dwval;
305                 dwval = WaitForInputIdle(pi.hProcess, INFINITE);
306
307                 while (WaitForSingleObject(pi.hProcess, 0) != WAIT_OBJECT_0)
308                 {
309                 }
310
311                 mprintf((1, "JOY.CPL process finished?\n"));
312                 ShowWindow(_hAppWnd, SW_MAXIMIZE);
313                 SetForegroundWindow(_hAppWnd);
314         }
315 }
316
317
318 //      Game -----------------------------------------------------------------------
319
320 char commandline_help[] = 
321                         "Command-line options (case is not significant):\n"
322                         "\n"
323                         " General Options:\n"
324                         "\n"
325                         "       -LowMem         Lower animation detail for better performance with low memory\n"
326                         "       -NoLowMem       Force high animation detail even when low memory\n"
327                         "       -Subtitles              Turn on movie subtitles (English-only)\n"
328                         "\n"
329                         " Input devices: -SpecialDevice\n"
330                         "\n"
331                         "       -IForce <n>     Use Immersion tactile feedback joystick on port <n>\n"
332                         "\n"
333                         " Sound & Music:\n"
334                         "\n"
335                         "       -NoSound        Turns off sound & music\n"
336                         "       -NoMusic                Disables music; sound effects remain enabled\n"
337                         "       -Sound22K       Use 22KHz sounds, even if machine has less than 16 MB\n"
338                         "       -Sound11K       Use 11KHz sounds, even if machine has more than 16 MB\n"
339                         "\n"
340                         " Network & Modem:\n"
341                         "\n"
342                         "       -CtsRts         Enables CTS/RTS handshaking during null-modem games\n"
343                         "       -NoNetwork      Disables network drivers\n"
344                         "       -NoSerial               Disables serial drivers\n"
345                         "       -Packets #      Specifies the packets per second where # is the number of packets\n"
346                         "       -Shortpackets   Turn on short packets\n"
347                         "       -Norankings     Disable multiplayer ranking system\n"
348                         "       -Noredunancy    suppresses duplicate messages such as \"You already have ....\"\n"
349                         "\n"
350                         "Diagnostic:\n"
351                         "       -emul           Certain video cards need this option in order to run game.\n"
352                         "       -ddemul         If -emul doesn't work, use this option.\n";
353
354 print_commandline_help()
355 {
356         ShowCursorW();
357         MessageBox(NULL, commandline_help, "Descent II Command-line Options", MB_OK);
358 }
359
360 int RunGame(int argc, char *argv[])
361 {
362         MSG msg;
363         int val;
364
365         setbuf(stdout, NULL);
366         error_init(WErrorCatch, NULL);
367
368 #ifndef RELEASE
369         if (FindArg("-stopwatch"))
370                 timer_init(1); 
371         else
372                 timer_init(0);
373 #else
374         timer_init(0);
375 #endif
376
377 //      InitArgs(argc, argv);
378
379         InitCD(argv[0]);
380         
381 #ifdef RELEASE
382         DoRegisterCheck();
383 #endif
384
385         InitVideo();
386         InitIO();
387         InitData();
388         InitSound();
389
390         if (!FindArg("-nonetwork"))
391                 InitNetwork();
392
393         if (!FindArg("-noserial"))
394                 serial_active = 1;
395
396         AllowActivates = TRUE;  
397
398         InitDescent();
399
400         InitPilot();    
401
402         if (Auto_demo)  {
403                 newdemo_start_playback("DESCENT.DEM");          
404                 if (Newdemo_state == ND_STATE_PLAYBACK )
405                         Function_mode = FMODE_GAME;
406         }
407
408 //      do this here because the demo code can do a longjmp when trying to
409 //              autostart a demo from the main menu, never having gone into the game
410         setjmp(LeaveGame);
411
412         while (Function_mode != FMODE_EXIT)
413         {
414                 val = DoMessageStuff(&msg);
415
416                 DDGRRESTORE;
417
418                 switch (Function_mode) 
419                 {
420                         case FMODE_MENU:
421                         {
422                                 set_screen_mode(SCREEN_MENU);
423                                 if (Auto_demo) {
424                                         DEFINE_SCREEN(NULL);
425                                         newdemo_start_playback(NULL);
426                                         if (Newdemo_state != ND_STATE_PLAYBACK) 
427                                                 Error("No demo files were found for autodemo mode!");
428                                 }
429                                 else {
430                                         DEFINE_SCREEN(Menu_pcx_name);
431                                         mprintf((1, "%s\n", Menu_pcx_name));
432                                         gr_palette_clear();
433                                         DoMenu();
434                                 }
435                                 break;
436                         }
437                         case FMODE_GAME:
438                         {
439                                 HideCursorW();
440                                 DEFINE_SCREEN(NULL);
441                                 game();
442                                 digi_reset();
443                                 digi_reset();
444                                 if ( Function_mode == FMODE_MENU )
445                                         songs_play_song( SONG_TITLE, 1 );
446                                 mprintf((0, "Function mode = %d\n", Function_mode));
447                         }
448                 }
449
450         }       
451
452         dd_gr_set_current_canvas(NULL);
453         dd_gr_clear_canvas(BM_XRGB(0,0,0));
454
455         WriteConfigFile();
456
457         return msg.wParam;
458 }
459
460
461 //      Window Message Functions 
462 //      ----------------------------------------------------------------------------
463
464 void AppPaint(HWND hWnd, HDC hdc)
465 {
466 //      grwin_gdi_realizepal(hdc);
467 }
468
469                                 
470 void AppSize(HWND hWnd)
471 {
472         if (IsIconic(hWnd)) {
473                 _AppPaused = TRUE;
474                 InvalidateRect(hWnd, NULL, TRUE);
475         }
476         else if (GetForegroundWindow() == hWnd) {
477                 _AppPaused = FALSE;
478         }
479           
480         DDResizeViewport();
481         mprintf((0, "Resized window (%d,%d,%d,%d).\n", ViewportRect.left, ViewportRect.top, ViewportRect.right, ViewportRect.bottom));  
482 }
483
484
485 void AppActivate(HWND hWnd, UINT wParam)
486 {
487         _AppActive = (BOOL)(wParam) && GetForegroundWindow()==hWnd && !IsIconic(hWnd);
488                         
489         if (_AppActive) {
490                 mprintf((0, "Descent II is gaining Window focus.\n"));
491                 cprintf("Descent II is gaining Window focus.\n");
492         }
493         else {
494                 mprintf((0, "Descent II is losing Window focus.\n"));
495                 cprintf("Descent II is losing Window focus.\n");
496         }
497
498 // Must now unpause if paused and app is active now.
499         mprintf((0, "AppActivate: Active: %d, Paused: %d\n", _AppActive, _AppPaused));
500
501         if (_AppActive && AllowActivates && !_AppPaused) 
502         {
503                 D2Restore();
504         }
505         else if (AllowActivates) {
506                 D2Shutdown();
507         }
508
509 }
510
511
512 void AppQueryPalette(HWND hWnd)
513 {
514 //      if (!_DDFullScreen && _lpDDPalette && _lpDDSPrimary) {
515 //              gr_palette_load(gr_palette);
516 //      }
517         mprintf((0, "QUERY PALETTE!\n"));
518 }
519
520
521 void AppCreate(HWND hWnd)
522 {
523         HMENU hMenu;
524
525 // Remove system menu components not good
526         hMenu = GetSystemMenu(hWnd, FALSE);
527         
528         RemoveMenu(hMenu, SC_SIZE, MF_BYCOMMAND);
529         RemoveMenu(hMenu, SC_MOVE, MF_BYCOMMAND);
530 }       
531
532
533 void AppPaletteChange(HWND hWnd, UINT wParam)
534 {
535         if ((HWND)wParam != hWnd) {
536                 if (!_DDFullScreen) {
537                         mprintf((0, "Palette changed!\n"));
538                         _AppPaused = TRUE;
539                         mprintf((0, "Descent 2 is paused.\n"));
540                 }       
541         }
542 }
543
544 //static LPDIRECTDRAWSURFACE Page0Buffer = 0;
545
546 void AppDisplayChange(HWND hWnd, int w, int h, int bpp)
547 {         
548 //      mprintf((0, "Windows feels a display change coming...\n"));
549 }
550
551
552 BOOL AppHandleSystemKeys(UINT msg, UINT wParam, UINT lParam)
553 {                
554 //      Intercept ALT keystrokes
555
556         if (msg == WM_SYSKEYUP) {
557                 mprintf((0,"ALT key down!"));
558         }
559
560         send_key_msg(msg, wParam, lParam);
561
562         if (wParam == VK_TAB || wParam == VK_ESCAPE) return FALSE;
563
564         return TRUE;
565 }
566
567
568 int RestoreGameSurfaces()
569 {
570         if (dd_VR_offscreen_buffer) {
571                 if (!dd_VR_offscreen_buffer->lpdds) return 1;
572                 if (IDirectDrawSurface_Restore(dd_VR_offscreen_buffer->lpdds) != DD_OK)  {
573                         mprintf((1, "Warning: Unable to restore dd_VR_offscreen_buffer!\n"));
574                         return 0;
575                 }
576                 mprintf((0, "Restored dd_VR_offscreen_buffer\n"));
577         }
578
579         return 1;
580 }
581
582
583 LRESULT WINAPI _export DescentWndProc(HWND hWnd,
584                                                                 UINT msg, 
585                                                                 UINT wParam,
586                                                                 LPARAM lParam)
587 {
588         //HANDLE h;
589         //static int nTimer = 0;
590
591         switch (msg)
592         {
593                 case WM_CREATE:
594                         AppCreate(hWnd);
595                         return 0;
596
597                 case WM_SYSCOMMAND:
598                         if((wParam&0xFFF0)==SC_SCREENSAVE || (wParam&0xFFF0)==SC_MONITORPOWER)
599             return 0;
600
601                         if ((wParam&0xfff0)== SC_KEYMENU && _AppActive) {
602                                 mprintf((0, "W32: Bypassing system menu.\n"));
603                                 return 0;
604                         }
605                         break;
606
607                 case WM_SIZE:
608                 case WM_MOVE:
609                         AppSize(hWnd);
610                         return 0;
611
612                 case WM_ACTIVATEAPP:                                    // Application is losing focus.
613                         AppActivate(hWnd, wParam);
614                         return 0;
615
616                 case WM_QUERYNEWPALETTE:
617                         AppQueryPalette(hWnd);
618                         break;
619
620                 case WM_PALETTECHANGED:
621                         AppPaletteChange(hWnd, wParam);
622                         break;
623
624                 case WM_DISPLAYCHANGE:                          // Screen Mode is changing.
625                         AppDisplayChange(hWnd, LOWORD(lParam), HIWORD(lParam), wParam);
626                         break;
627
628                 case WM_SYSKEYUP:
629                 case WM_SYSKEYDOWN:
630                         if (AppHandleSystemKeys(msg, wParam,lParam))
631                                 return 0;
632                         break;
633
634                 case WM_KEYDOWN:
635                 case WM_KEYUP:
636                         if (wParam == VK_SNAPSHOT) {
637                                 mprintf((0, "Capture screen begins...\n"));
638                                 save_screen_shot(0);
639                                 if (!clipboard_screenshot()) 
640                                         mprintf((1, "Failed to create clipboard screenshot!\n"));
641                         }
642 //              #ifndef NDEBUG
643 //                      if (msg == WM_KEYDOWN && wParam == 0x49) ipx_debug_hold_packets = 1;
644 //                      if (msg == WM_KEYUP && wParam == 0x49) ipx_debug_hold_packets = 0;
645 //              #endif
646                         send_key_msg(msg, wParam, lParam);
647                         break;
648         
649                 case WM_PAINT:
650 //                      hdc = BeginPaint(hWnd, &ps);                    
651 //                      AppPaint(hWnd, hdc);
652 //                      EndPaint(hWnd, &ps);
653 //                      return 0;
654                         break;
655
656                 case MM_JOY1MOVE:
657                 case MM_JOY1BUTTONDOWN:
658                 case MM_JOY1BUTTONUP:
659                         if (!_AppPaused && (_AppActive || !_DDFullScreen))      {
660                                 joy_handler_win(hWnd, msg, wParam, lParam);
661                         }
662                         break;                  
663
664                 case WM_DESTROY:
665                         mprintf((0, "Killing main window...\n"));
666                         PostQuitMessage(0);
667                         break;
668         }
669
670 //      digi_midi_debug();
671         mouse_win_callback(msg, wParam, lParam);
672         
673         return DefWindowProc(hWnd, msg, wParam, lParam);
674 }
675
676
677 static char *WinArgs[64];
678
679 //      Main Program
680 //      ----------------------------------------------------------------------------
681
682 int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, 
683                                                  int nCmdShow)
684 {
685         int retval = 1;
686         int argc;
687
688
689         argc = ParseArgs(WinArgs, szCmdLine);
690         InitArgs(argc, WinArgs);
691
692         if (FindArg( "-?" ) || FindArg( "-help" ) || FindArg( "?" ) ) {
693                 print_commandline_help();
694                 set_exit_message("");
695                 return(0);
696         }
697
698         if (AppInit(hInst, hPrev, szCmdLine, nCmdShow)) {
699                 retval = RunGame(argc, WinArgs);
700         }
701
702         return retval;
703 }
704
705
706
707 //      Low Level Routines
708 //      ----------------------------------------------------------------------------
709
710 static char *NoMovieArg = "-nomovies";
711 static char *PathArg = "descentw.exe";
712
713 int ParseArgs(char *argv[], LPSTR lpCmdLine)
714 {
715         int argc;
716         int i;
717
718         argc = 0;
719         i = 0;
720
721         argv[argc++] = PathArg;
722
723 //      while (lpCmdLine[i] == '-' || lpCmdLine[i] == '/' )
724
725         while (lpCmdLine[i])
726         {
727                 if (lpCmdLine[i] == ' ') i++;
728                 else {
729                         argv[argc++] = &lpCmdLine[i];
730
731                         while (lpCmdLine[i]!=' ' && lpCmdLine[i]!= 0) {
732                                 //mprintf((0, "%c", lpCmdLine[i]));
733                                 i++;
734                         }
735                         lpCmdLine[i++] = 0;
736 //                      mprintf((0, "Argument %s.\n", argv[argc-1]));
737                 }
738         }
739
740         if (!WinEnableMovies) 
741                 argv[argc++] = NoMovieArg;
742
743         return argc;
744 }
745                                         
746
747 extern void rls_stretch_scanline_asm();
748
749
750 void MakeCodeWritable(void)
751 {
752         typedef DWORD __stdcall translator(DWORD);
753
754         HMODULE         modCode;
755         BYTE            *pImageBase = 0;
756         DWORD           version;
757
758         modCode = GetModuleHandle(0);
759         version = GetVersion();
760
761 //      For Win32s we have to use undocumented features
762         if ((version < 0x80000000) || ((BYTE)version >=0x04)) {  
763         //       Win NT, Win95.
764                 pImageBase = (BYTE *)modCode;
765         }
766         else {
767                 MessageBox(NULL, "Descent II cannot run under Windows 3.x", "Descent II", MB_OK);
768                 exit(1);
769
770         }
771
772         if (pImageBase) {
773                 DWORD oldRights;
774                 //char buf[256];
775                 IMAGE_OPTIONAL_HEADER *pHeader = 
776                         (IMAGE_OPTIONAL_HEADER *)(pImageBase + ((IMAGE_DOS_HEADER *)pImageBase)->e_lfanew + 
777                                                                                          sizeof(IMAGE_NT_SIGNATURE) + sizeof(IMAGE_FILE_HEADER));
778
779 //@@            if (!VirtualProtect(pImageBase+pHeader->BaseOfCode, pHeader->SizeOfCode,
780 //@@                                                              PAGE_READWRITE, &oldRights))  {
781 //@@                            exit(1);
782 //@@            }
783
784                 if (!VirtualProtect(rls_stretch_scanline_asm, 4096*2, PAGE_READWRITE, &oldRights))  {
785                         MessageBox(NULL, "Unable to gain write access to requested page.", "Descent II Error", MB_OK);
786                         exit(1);
787                 }
788
789 //              wsprintf(buf, "Start:%x FN1:%x",(DWORD)pImageBase+pHeader->BaseOfCode, (DWORD)rls_stretch_scanline_asm);
790 //              MessageBox(NULL, buf, "Info", MB_OK);
791         }
792 }
793
794
795 void ValidateSystem()
796 {
797         DWORD version;
798
799         version = GetVersion();
800
801         if ((version < 0x80000000) || ((BYTE)version >=0x04)) {
802                 if ((version < 0x80000000)  && ((BYTE)version >= 0x04)) {
803                         Platform_system = WINNT_PLATFORM;
804                         DD_Emulation = 1;
805                 }        
806                 else Platform_system = WIN95_PLATFORM;
807         }
808         else {
809                 MessageBox(NULL, "Descent II will not run under Windows 3.x", "DESCENT II", MB_OK);
810                 exit(1);
811         }
812
813 //      Do the named mutex thingy.
814         {
815                 HANDLE hMutex, hMutex2;
816
817                 hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "BigRedStinksMutex");
818                 if (hMutex) {
819                         hMutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "BigRedSucksMutex");
820                         if (hMutex2) {
821                                 CloseHandle(hMutex2);
822                                 exit(1);                                // Don't even tell user he's trying to run a third copy
823                         }
824
825                         hDescent2Mutex2 = CreateMutex(NULL, FALSE, "BigRedSucksMutex");
826                         if (!hDescent2Mutex2) {
827                                 MessageBox(NULL, "Unable to create second mutex object.", "Descent II error", MB_OK);
828                                 exit(1);
829                         }
830                         MessageBox(NULL, "You may only run one instance of Descent II at a time.", 
831                                         "Descent II error", MB_OK);
832                         CloseHandle(hMutex);
833                         exit(1);
834                 }
835                 hDescent2Mutex = CreateMutex(NULL, FALSE, "BigRedStinksMutex");
836                 if (!hDescent2Mutex) {
837                         MessageBox(NULL, "Unable to create mutex object.", "Descent II error", MB_OK);
838                         exit(1);
839                 }
840         }
841 //      Do the Version ID thing for Beta testers
842 #if defined(RELEASE) && defined(VERSION_NAME) && !defined(NDEBUG)
843         { 
844                 char buf[256];
845
846                 sprintf(buf, "Descent II %s v%d.%d\n%s\n%s %s", VERSION_TYPE, Version_major, Version_minor,
847                                                                                                                         VERSION_NAME, __DATE__, __TIME__);
848                 MessageBox(NULL, buf, "Descent II beta information", MB_OK);
849         }
850 #endif
851
852 //      Super memory check
853         {
854                 MEMORYSTATUS memstat;
855                 int mem_free;
856
857                 memset(&memstat, 0, sizeof(memstat));
858                 memstat.dwLength = sizeof(memstat);
859                 GlobalMemoryStatus(&memstat);
860
861                 logentry("Memory: \n");
862                 logentry("  MemoryLoad     = %10d\n",memstat.dwMemoryLoad);
863                 logentry("  TotalPhys      = %10d\n",memstat.dwTotalPhys);
864                 logentry("  AvailPhys      = %10d\n",memstat.dwAvailPhys);
865                 logentry("  TotalPageFile  = %10d\n",memstat.dwTotalPageFile);
866                 logentry("  AvailPageFile  = %10d\n",memstat.dwAvailPageFile);
867                 logentry("  TotalVirtual   = %10d\n",memstat.dwTotalVirtual);
868                 logentry("  AvailVirtual   = %10d\n",memstat.dwAvailVirtual);
869
870                 mem_free = memstat.dwTotalPhys;
871 //              mem_free=100;
872 //              logentry("  mem_free       = %10d\n",mem_free);
873                 
874                 if ( mem_free < MIN_PHYSICAL_MEM_FREE) {
875                         logentry("Using low memory option.\n");
876                         piggy_low_memory = 1;
877                 }
878
879                 if ( memstat.dwAvailPageFile < MIN_VIRTUAL_MEM_FREE) {
880                         MessageBox(NULL, "Not enough virtual memory.\n You need at least 16MB of free drive space.\n", 
881                                                         "Descent II Error", MB_OK);
882                         exit(1);
883                 }
884
885                 if ( ((mem_free > SOUND_22K_CUTOFF) || FindArg("-sound22k")) && !FindArg("-sound11k") && !FindArg("-lowmem") ) {
886                         logentry("Using 22KHz sounds\n");
887                         digi_sample_rate = SAMPLE_RATE_22K;
888                 } else {
889                         logentry("Using 11KHz sounds\n");
890                         digi_sample_rate = SAMPLE_RATE_11K;
891                 }
892         }
893 }       
894
895
896 int DoMessageStuff(MSG *msg)
897 {
898
899         while(1)
900         {
901                 if (PeekMessage(msg, NULL, 0, 0, PM_REMOVE)) {
902                         if (msg->message == WM_QUIT) {
903                                 WriteConfigFile();
904                                 exit(0);
905                         }
906
907                         TranslateMessage(msg);
908                         DispatchMessage(msg);
909                 }
910                 else if (!_AppPaused && (_AppActive || !_DDFullScreen)) {
911                         break;
912                 } else {
913
914                         if ((Game_mode & GM_MULTI)) {
915                                 if (Control_center_destroyed) {
916                                         ShowWindow(_hAppWnd, SW_MAXIMIZE);
917                                         WinDelayIdle();
918                                         SetForegroundWindow(_hAppWnd);
919                                         WinDelayIdle();
920                                         _RedrawScreen = TRUE;
921                                 }
922                                 else if (multi_menu_poll() == -1) {
923                                         ShowWindow(_hAppWnd, SW_MAXIMIZE);
924                                         WinDelayIdle();
925
926                                         if (GetForegroundWindow() == _hAppWnd) {
927                                                 if (_AppPaused || !_AppActive) {
928                                                         mprintf((0, "Descent2 Daemon...Pause: %d, Active %d\n",_AppPaused, _AppActive)); 
929                                                         SetActiveWindow(_hAppWnd);
930                                                         _RedrawScreen = FALSE;
931                                                         break;
932                                                 }
933                                         }
934                                         else {
935                                                 SetForegroundWindow(_hAppWnd);
936                                                 WinDelayIdle();
937                                                 _RedrawScreen = FALSE;
938                                         }
939                                 }
940                         }
941                         else {
942                                 mprintf((0, "Waiting...Pause: %d, Active %d\n",_AppPaused, _AppActive)); 
943                                 WaitMessage();
944                         }
945                 }
946         }
947                 
948
949         return MSG_NORMAL;
950 }
951
952
953 void WinDelayIdle()
954 {
955         MSG msg;
956
957         mprintf((0, "Entering Idle message loop...\n"));
958
959         while (1)
960         {
961                 if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
962                         if (msg.message == WM_QUIT) {
963                                 WriteConfigFile();
964                                 exit(0);
965                         }
966
967                         mprintf((0, "Retreiving message(0x%x:0x%x,0x%x) in idle loop.\n",msg.message, msg.wParam, msg.lParam));
968
969                         TranslateMessage(&msg);
970                         DispatchMessage(&msg);
971
972                 }
973                 else break;
974         }
975 }
976
977
978 void WinDelay(int msecs)
979 {
980         int timeout;
981         MSG msg;
982
983
984         timeout = timeGetTime() + msecs;
985
986         while (timeout > timeGetTime())
987         {
988                 DoMessageStuff(&msg);
989                 if (msg.message == WM_QUIT) exit(0);
990         }
991 }
992
993
994 void    WErrorCatch(char *message)
995 {
996         mprintf((1, "Bye Bye: %s\n", message));
997
998         strcpy(WinErrorMessage, message);
999
1000         WinErrorTrap = 1;
1001
1002         logentry("%s", WinErrorMessage);
1003         CloseWindow(_hAppWnd);
1004 }
1005
1006
1007 //static BOOL CursorVisible = TRUE;
1008 static HANDLE CursorHandle = NULL;
1009
1010
1011 void LoadCursorWin(int cursor)
1012 {
1013         switch (cursor)
1014         {
1015                 case MOUSE_DEFAULT_CURSOR:
1016                         CursorHandle = LoadCursor(NULL, IDC_ARROW);
1017                         break;
1018                 
1019                 case MOUSE_WAIT_CURSOR: 
1020                         CursorHandle = LoadCursor(NULL, IDC_WAIT);
1021                         break;
1022                 
1023                 default:
1024                         CursorHandle = NULL;    
1025         }
1026
1027         SetCursor(CursorHandle);
1028 }
1029  
1030
1031 void HideCursorW()
1032 {                                        
1033         while (ShowCursor(FALSE) >=0);
1034 }
1035  
1036
1037 void ShowCursorW()
1038 {
1039         if (DD_Emulation) return;
1040         
1041         if (CursorHandle == NULL)
1042                 LoadCursorWin(MOUSE_DEFAULT_CURSOR);
1043
1044         while (ShowCursor(TRUE) < 0);
1045 }       
1046
1047
1048
1049 //      Descent 2 Shutdown and Restore functions
1050 //      ----------------------------------------------------------------------------
1051
1052 void SaveVideoState();
1053 void RestoreVideoState();
1054
1055 static int Saved_Game_window_w;
1056 static int Saved_Game_window_h;
1057 static int SavedScreenMode = 0;
1058
1059 extern int Digi_initialized;
1060 extern int Current_display_mode;
1061 extern BOOL WMVEPlaying, RMVEPlaying;
1062 extern int current_song_level;
1063
1064
1065 void RestoreScreenContext()
1066 {
1067         if ( _SCRContext.bkg_filename != NULL ) {
1068                 mprintf((0, "Loading background file...\n"));
1069                 nm_draw_background1( _SCRContext.bkg_filename );
1070         }
1071         gr_palette_load(gr_palette);
1072 }
1073
1074
1075 void D2Shutdown()
1076 {
1077         if (GameShutdown) return;
1078
1079         _AppPaused = TRUE;
1080
1081         if (!Joystick_calibrating) joy_stop_poll();
1082
1083         key_flush();
1084
1085         SaveVideoState();
1086
1087         songs_stop_all();
1088
1089         if (CD_audio_desktop_dev != -1) 
1090                 auxSetVolume(CD_audio_desktop_dev, CD_audio_desktop_vol);
1091
1092         if (Function_mode == FMODE_GAME && !(Game_mode &GM_MULTI)) {
1093                 stop_time();
1094         }
1095
1096         mprintf((0, "WMVE: %d, RMVE: %d\n", WMVEPlaying, RMVEPlaying));
1097
1098         if (WMVEPlaying) MovieShutdown();
1099         if (RMVEPlaying) MVE_rmHoldMovie();
1100
1101         if (!WMVEPlaying) digi_reset();
1102
1103         mprintf((0, "Descent 2 is asleep...\n"));
1104
1105         GameShutdown = TRUE;
1106 }
1107
1108
1109 void D2Restore()
1110 {
1111         if (!GameShutdown) return;
1112         
1113         if (!WMVEPlaying) digi_reset();
1114         if (WMVEPlaying) {
1115                 MovieRestore();
1116                 key_flush();
1117                 if (CD_audio_desktop_dev != -1) 
1118                         auxGetVolume(CD_audio_desktop_dev, &CD_audio_desktop_vol);
1119                 _AppPaused = FALSE;
1120                 goto EndD2Restore;
1121         }
1122         else if (RMVEPlaying) {
1123                 key_flush();
1124         //      if (_lpDD) RestoreVideoState();
1125                 dd_gr_init_screen();
1126                 W95DisplayMode = -1;
1127
1128                 if (SavedScreenMode != -1)  
1129                         set_screen_mode(SavedScreenMode);
1130
1131                 if (CD_audio_desktop_dev != -1) 
1132                         auxGetVolume(CD_audio_desktop_dev, &CD_audio_desktop_vol);
1133                 MVE_rmHoldMovie();
1134                 _RedrawScreen = TRUE;
1135                 _AppPaused = FALSE;
1136                 goto EndD2Restore;
1137         }
1138         else {
1139                 if (_lpDD) RestoreVideoState();
1140
1141                 if (CD_audio_desktop_dev != -1) 
1142                         auxGetVolume(CD_audio_desktop_dev, &CD_audio_desktop_vol);
1143                                                                                                                                                    
1144                 if (Function_mode == FMODE_MENU) songs_play_song(SONG_TITLE, 1);
1145                 if (Function_mode == FMODE_GAME) {
1146                         songs_play_level_song(current_song_level);
1147                 }
1148                 key_flush();
1149                 _AppPaused = FALSE;
1150
1151         }
1152
1153         if (Function_mode == FMODE_GAME && !(Game_mode & GM_MULTI)) start_time();
1154         else if (Function_mode == FMODE_MENU) 
1155                 keyd_time_when_last_pressed = timer_get_fixed_seconds();
1156
1157 EndD2Restore:
1158         if (!Joystick_calibrating) joy_start_poll();
1159         set_redbook_volume(Config_redbook_volume);
1160         mprintf((0, "...Descent 2 is awake!\n"));
1161         
1162         GameShutdown = FALSE;
1163 }
1164
1165
1166 void SaveVideoState()
1167 {
1168 // If in game mode, then restore window size
1169         if (Screen_mode == SCREEN_GAME) {
1170                 Saved_Game_window_w = Game_window_w;
1171                 Saved_Game_window_h = Game_window_h;
1172
1173         }               
1174
1175         SavedScreenMode = Screen_mode;
1176         Screen_mode = -1;
1177 }
1178
1179
1180 void RestoreVideoState()
1181 {
1182 //      Just reinitialize screen state.
1183         dd_gr_init_screen();
1184         W95DisplayMode = -1;
1185
1186
1187 // If in game mode, then restore window size
1188         if (SavedScreenMode != -1)  
1189                 set_screen_mode(SavedScreenMode);
1190                                                                                                                                         
1191         if (SavedScreenMode == SCREEN_GAME) {
1192                 Game_window_w = Saved_Game_window_w;
1193                 Game_window_h = Saved_Game_window_h;
1194                 init_cockpit();
1195         }
1196         if (Function_mode == FMODE_GAME) {
1197                 load_palette(Current_level_palette,1,1);
1198         }                               
1199
1200         _RedrawScreen = TRUE;
1201         RestoreScreenContext();
1202 }
1203
1204