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