STARTUP.CPP 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. /*
  2. ** Command & Conquer(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* $Header: F:\projects\c&c\vcs\code\startup.cpv 2.17 16 Oct 1995 16:48:12 JOE_BOSTIC $ */
  19. /***********************************************************************************************
  20. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  21. ***********************************************************************************************
  22. * *
  23. * Project Name : Command & Conquer *
  24. * *
  25. * File Name : STARTUP.CPP *
  26. * *
  27. * Programmer : Joe L. Bostic *
  28. * *
  29. * Start Date : October 3, 1994 *
  30. * *
  31. * Last Update : August 27, 1995 [JLB] *
  32. * *
  33. *---------------------------------------------------------------------------------------------*
  34. * Functions: *
  35. * Delete_Swap_Files -- Deletes previously existing swap files. *
  36. * Prog_End -- Cleans up library systems in prep for game exit. *
  37. * main -- Initial startup routine (preps library systems). *
  38. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  39. #include "function.h"
  40. #include <conio.h>
  41. #include <io.h>
  42. #include "ccdde.h"
  43. bool Read_Private_Config_Struct(char *profile, NewConfigType *config);
  44. void Delete_Swap_Files(void);
  45. void Print_Error_End_Exit(char *string);
  46. void Print_Error_Exit(char *string);
  47. WinTimerClass *WinTimer;
  48. extern void Create_Main_Window ( HANDLE instance , int command_show , int width , int height);
  49. extern bool ReadyToQuit;
  50. void Read_Setup_Options(RawFileClass *config_file);
  51. bool VideoBackBufferAllowed = true;
  52. void Check_From_WChat(char *wchat_name);
  53. bool SpawnedFromWChat = false;
  54. extern "C"{
  55. bool __cdecl Detect_MMX_Availability(void);
  56. void __cdecl Init_MMX(void);
  57. }
  58. #if (0)
  59. char WibbleBuffer[1024*1024];
  60. void CD_Test(void)
  61. {
  62. HANDLE handle;
  63. DWORD size;
  64. handle= CreateFile("e:\\scores.mix", GENERIC_READ, FILE_SHARE_READ,
  65. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  66. if (handle== INVALID_HANDLE_VALUE){
  67. return;
  68. }
  69. unsigned bytes_read;
  70. do{
  71. bytes_read = ReadFile (handle , WibbleBuffer , 1024*1024, &size, NULL);
  72. }while(size == 1024*1024);
  73. CloseHandle (handle);
  74. }
  75. #endif //(0)
  76. /***********************************************************************************************
  77. * main -- Initial startup routine (preps library systems). *
  78. * *
  79. * This is the routine that is first called when the program starts up. It basically *
  80. * handles the command line parsing and setting up library systems. *
  81. * *
  82. * INPUT: argc -- Number of command line arguments. *
  83. * *
  84. * argv -- Pointer to array of comman line argument strings. *
  85. * *
  86. * OUTPUT: Returns with execution failure code (if any). *
  87. * *
  88. * WARNINGS: none *
  89. * *
  90. * HISTORY: *
  91. * 03/20/1995 JLB : Created. *
  92. *=============================================================================================*/
  93. HINSTANCE ProgramInstance;
  94. extern BOOL CC95AlreadyRunning;
  95. void Move_Point(short &x, short &y, register DirType dir, unsigned short distance);
  96. void Check_Use_Compressed_Shapes (void);
  97. int PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , int command_show )
  98. {
  99. // Heap_Dump_Check( "first thing in main" );
  100. // malloc(1);
  101. CCDebugString ("C&C95 - Starting up.\n");
  102. //WindowsTimer = new WinTimerClass(60,FALSE);
  103. //CD_Test();
  104. /*
  105. ** These values return 0x47 if code is working correctly
  106. */
  107. // int temp = Desired_Facing256 (1070, 5419, 1408, 5504);
  108. /*
  109. ** If we are already running then switch to the existing process and exit
  110. */
  111. SpawnedFromWChat = false;
  112. if (CC95AlreadyRunning) { //Set in the DDEServer constructor
  113. //MessageBox (NULL, "Error - attempt to restart C&C95 when already running.", "Command & Conquer", MB_ICONEXCLAMATION|MB_OK);
  114. HWND ccwindow;
  115. ccwindow = FindWindow ("Command & Conquer", "Command & Conquer");
  116. if (ccwindow){
  117. SetForegroundWindow ( ccwindow );
  118. ShowWindow ( ccwindow, SW_RESTORE );
  119. }
  120. return (EXIT_SUCCESS);
  121. }
  122. DDSCAPS surface_capabilities;
  123. if (Ram_Free(MEM_NORMAL) < 5000000) {
  124. #ifdef GERMAN
  125. printf("Zuwenig Hauptspeicher verf�gbar.\n");
  126. #else
  127. #ifdef FRENCH
  128. printf("M‚moire vive (RAM) insuffisante.\n");
  129. #else
  130. printf("Insufficient RAM available.\n");
  131. #endif
  132. #endif
  133. return(EXIT_FAILURE);
  134. }
  135. //void *test_buffer = Alloc(20,MEM_NORMAL);
  136. //memset ((char*)test_buffer, 0, 21);
  137. //Free(test_buffer);
  138. int argc; //Command line argument count
  139. unsigned command_scan;
  140. char command_char;
  141. char * argv[20]; //Pointers to command line arguments
  142. char path_to_exe[280];
  143. ProgramInstance = instance;
  144. /*
  145. ** Get the full path to the .EXE
  146. */
  147. GetModuleFileName (instance, &path_to_exe[0], 280);
  148. /*
  149. ** First argument is supposed to be a pointer to the .EXE that is running
  150. **
  151. */
  152. argc=1; //Set argument count to 1
  153. argv[0]=&path_to_exe[0]; //Set 1st command line argument to point to full path
  154. /*
  155. ** Get pointers to command line arguments just like if we were in DOS
  156. **
  157. ** The command line we get is cr/zero? terminated.
  158. **
  159. */
  160. command_scan=0;
  161. do {
  162. /*
  163. ** Scan for non-space character on command line
  164. */
  165. do {
  166. command_char = *( command_line+command_scan++ );
  167. } while ( command_char==' ' );
  168. if ( command_char!=0 && command_char != 13 ){
  169. argv[argc++]=command_line+command_scan-1;
  170. /*
  171. ** Scan for space character on command line
  172. */
  173. do {
  174. command_char = *( command_line+command_scan++ );
  175. } while ( command_char!=' ' && command_char != 0 && command_char!=13 );
  176. *( command_line+command_scan-1 ) = 0;
  177. }
  178. } while ( command_char != 0 && command_char != 13 && argc<20 );
  179. /*
  180. ** Remember the current working directory and drive.
  181. */
  182. unsigned olddrive;
  183. char oldpath[PATH_MAX];
  184. getcwd(oldpath, sizeof(oldpath));
  185. _dos_getdrive(&olddrive);
  186. /*
  187. ** Change directory to the where the executable is located. Handle the
  188. ** case where there is no path attached to argv[0].
  189. */
  190. char drive[_MAX_DRIVE];
  191. char path[_MAX_PATH];
  192. unsigned drivecount;
  193. _splitpath(argv[0], drive, path, NULL, NULL);
  194. if (!drive[0]) {
  195. drive[0] = ('A' + olddrive)-1;
  196. }
  197. if (!path[0]) {
  198. strcpy(path, ".");
  199. }
  200. _dos_setdrive(toupper((drive[0])-'A')+1, &drivecount);
  201. if (path[strlen(path)-1] == '\\') {
  202. path[strlen(path)-1] = '\0';
  203. }
  204. chdir(path);
  205. #ifdef JAPANESE
  206. ForceEnglish = false;
  207. #endif
  208. if (Parse_Command_Line(argc, argv)) {
  209. WindowsTimer = new WinTimerClass(60,FALSE);
  210. int time_test = WindowsTimer->Get_System_Tick_Count();
  211. Sleep (1000);
  212. if (WindowsTimer->Get_System_Tick_Count() == time_test){
  213. #ifdef FRENCH
  214. MessageBox(0, "Error - L'horloge systŠme n'a pas pu s'initialiser en raison de l'instabilit‚ du sytŠme. Vous devez red‚marrer Windows.", "Command & Conquer" , MB_OK|MB_ICONSTOP);
  215. #else
  216. #ifdef GERMAN
  217. MessageBox(0, "Fehler - das Timer-System konnte aufgrund einer Instabilit„t des Systems nicht initialisiert werden. Bitte starten Sie Windows neu.", "Command & Conquer", MB_OK|MB_ICONSTOP);
  218. #else
  219. MessageBox(0, "Error - Timer system failed to start due to system instability. You need to restart Windows.", "Command & Conquer", MB_OK|MB_ICONSTOP);
  220. #endif //GERMAN
  221. #endif //FRENCH
  222. return(EXIT_FAILURE);
  223. }
  224. RawFileClass cfile("CONQUER.INI");
  225. #ifdef JAPANESE
  226. //////////////////////////////////////if(!ForceEnglish) KBLanguage = 1;
  227. #endif
  228. /*
  229. ** Check for existance of MMX support on the processor
  230. */
  231. if (Detect_MMX_Availability()){
  232. //MessageBox(NULL, "MMX extensions detected - enabling MMX support.", "Command & Conquer",MB_ICONEXCLAMATION|MB_OK);
  233. MMXAvailable = true;
  234. }
  235. /*
  236. ** If there is loads of memory then use uncompressed shapes
  237. */
  238. Check_Use_Compressed_Shapes();
  239. /*
  240. ** If there is not enough disk space free, dont allow the product to run.
  241. */
  242. if (Disk_Space_Available() < INIT_FREE_DISK_SPACE) {
  243. #ifdef GERMAN
  244. char disk_space_message [512];
  245. sprintf (disk_space_message, "Nicht genug Festplattenplatz f�r Command & Conquer.\nSie brauchen %d MByte freien Platz auf der Festplatte.", (INIT_FREE_DISK_SPACE) / (1024 * 1024));
  246. MessageBox(NULL, disk_space_message, "Command & Conquer", MB_ICONEXCLAMATION|MB_OK);
  247. if ( WindowsTimer )
  248. delete WindowsTimer;
  249. return (EXIT_FAILURE);
  250. #endif
  251. #ifdef FRENCH
  252. char disk_space_message [512];
  253. sprintf (disk_space_message, "Espace disque insuffisant pour lancer Command & Conquer.\nVous devez disposer de %d Mo d'espace disponsible sur disque dur.", (INIT_FREE_DISK_SPACE) / (1024 * 1024));
  254. MessageBox(NULL, disk_space_message, "Command & Conquer", MB_ICONEXCLAMATION|MB_OK);
  255. if ( WindowsTimer )
  256. delete WindowsTimer;
  257. return (EXIT_FAILURE);
  258. #endif
  259. #if !(FRENCH | GERMAN)
  260. int reply = MessageBox(NULL, "Warning - you are critically low on free disk space for virtual memory and save games. Do you want to play C&C anyway?", "Command & Conquer", MB_ICONQUESTION|MB_YESNO);
  261. if (reply == IDNO){
  262. if ( WindowsTimer )
  263. delete WindowsTimer;
  264. return (EXIT_FAILURE);
  265. }
  266. #endif
  267. }
  268. CDFileClass::Set_CD_Drive (CDList.Get_First_CD_Drive());
  269. if (cfile.Is_Available()) {
  270. #ifndef NOMEMCHECK
  271. char * cdata = (char *)Load_Alloc_Data(cfile);
  272. Read_Private_Config_Struct(cdata, &NewConfig);
  273. delete [] cdata;
  274. #else
  275. Read_Private_Config_Struct((char *)Load_Alloc_Data(cfile), &NewConfig);
  276. #endif
  277. Read_Setup_Options( &cfile );
  278. CCDebugString ("C&C95 - Creating main window.\n");
  279. Create_Main_Window( instance , command_show , ScreenWidth , ScreenHeight );
  280. CCDebugString ("C&C95 - Initialising audio.\n");
  281. SoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 );
  282. Palette = new(MEM_CLEAR) unsigned char[768];
  283. BOOL video_success = FALSE;
  284. CCDebugString ("C&C95 - Setting video mode.\n");
  285. /*
  286. ** Set 640x400 video mode. If its not available then try for 640x480
  287. */
  288. if (ScreenHeight == 400){
  289. if (Set_Video_Mode (MainWindow, ScreenWidth, ScreenHeight, 8)){
  290. video_success = TRUE;
  291. }else{
  292. if (Set_Video_Mode (MainWindow, ScreenWidth, 480, 8)){
  293. video_success = TRUE;
  294. ScreenHeight = 480;
  295. }
  296. }
  297. }else{
  298. if (Set_Video_Mode (MainWindow, ScreenWidth, ScreenHeight, 8)){
  299. video_success = TRUE;
  300. }
  301. }
  302. if (!video_success){
  303. CCDebugString ("C&C95 - Failed to set video mode.\n");
  304. MessageBox(MainWindow, Text_String(TXT_UNABLE_TO_SET_VIDEO_MODE), "Command & Conquer", MB_ICONEXCLAMATION|MB_OK);
  305. if (WindowsTimer) delete WindowsTimer;
  306. if (Palette) delete [] Palette;
  307. return (EXIT_FAILURE);
  308. }
  309. CCDebugString ("C&C95 - Initialising video surfaces.\n");
  310. if (ScreenWidth==320){
  311. VisiblePage.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
  312. ModeXBuff.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));
  313. } else {
  314. VisiblePage.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));
  315. /*
  316. ** Check that we really got a video memory page. Failure is fatal.
  317. */
  318. memset (&surface_capabilities, 0, sizeof(surface_capabilities));
  319. VisiblePage.Get_DD_Surface()->GetCaps(&surface_capabilities);
  320. if (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY){
  321. /*
  322. ** Aaaarrgghh!
  323. */
  324. CCDebugString ("C&C95 - Unable to allocate primary surface.\n");
  325. MessageBox(MainWindow, Text_String(TXT_UNABLE_TO_ALLOCATE_PRIMARY_VIDEO_BUFFER), "Command & Conquer", MB_ICONEXCLAMATION|MB_OK);
  326. if (WindowsTimer) delete WindowsTimer;
  327. if (Palette) delete [] Palette;
  328. return (EXIT_FAILURE);
  329. }
  330. /*
  331. ** If we have enough left then put the hidpage in video memory unless...
  332. **
  333. ** If there is no blitter then we will get better performance with a system
  334. ** memory hidpage
  335. **
  336. ** Use a system memory page if the user has specified it via the ccsetup program.
  337. */
  338. CCDebugString ("C&C95 - Allocating back buffer ");
  339. long video_memory = Get_Free_Video_Memory();
  340. unsigned video_capabilities = Get_Video_Hardware_Capabilities();
  341. if (video_memory < ScreenWidth*ScreenHeight ||
  342. (! (video_capabilities & VIDEO_BLITTER)) ||
  343. (video_capabilities & VIDEO_NO_HARDWARE_ASSIST) ||
  344. !VideoBackBufferAllowed){
  345. CCDebugString ("in system memory.\n");
  346. HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
  347. } else {
  348. //HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
  349. CCDebugString ("in video memory.\n");
  350. HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)GBC_VIDEOMEM);
  351. /*
  352. ** Make sure we really got a video memory hid page. If we didnt then things
  353. ** will run very slowly.
  354. */
  355. memset (&surface_capabilities, 0, sizeof(surface_capabilities));
  356. HiddenPage.Get_DD_Surface()->GetCaps(&surface_capabilities);
  357. if (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY){
  358. /*
  359. ** Oh dear, big trub. This must be an IBM Aptiva or something similarly cruddy.
  360. ** We must redo the Hidden Page as system memory.
  361. */
  362. AllSurfaces.Remove_DD_Surface(HiddenPage.Get_DD_Surface()); // Remove the old surface from the AllSurfaces list
  363. HiddenPage.Get_DD_Surface()->Release();
  364. HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
  365. }else{
  366. VisiblePage.Attach_DD_Surface(&HiddenPage);
  367. }
  368. }
  369. }
  370. ScreenHeight = 400;
  371. if (VisiblePage.Get_Height() == 480){
  372. SeenBuff.Attach(&VisiblePage,0, 40, 640, 400);
  373. HidPage.Attach(&HiddenPage, 0, 40, 640, 400);
  374. }else{
  375. SeenBuff.Attach(&VisiblePage,0, 0, 640, 400);
  376. HidPage.Attach(&HiddenPage, 0, 0, 640, 400);
  377. }
  378. CCDebugString ("C&C95 - Adjusting variables for resolution.\n");
  379. Options.Adjust_Variables_For_Resolution();
  380. CCDebugString ("C&C95 - Setting palette.\n");
  381. /////////Set_Palette(Palette);
  382. WindowList[0][WINDOWWIDTH] = SeenBuff.Get_Width() >> 3;
  383. WindowList[0][WINDOWHEIGHT] = SeenBuff.Get_Height();
  384. /*
  385. ** Install the memory error handler
  386. */
  387. Memory_Error = &Memory_Error_Handler;
  388. /*
  389. ** Initialise MMX support if its available
  390. */
  391. CCDebugString ("C&C95 - Entering MMX detection.\n");
  392. if (MMXAvailable){
  393. Init_MMX();
  394. }
  395. CCDebugString ("C&C95 - Creating mouse class.\n");
  396. WWMouse = new WWMouseClass(&SeenBuff, 32, 32);
  397. // MouseInstalled = Install_Mouse(32,24,320,200);
  398. MouseInstalled = TRUE;
  399. /*
  400. ** See if we should run the intro
  401. */
  402. CCDebugString ("C&C95 - Reading CONQUER.INI.\n");
  403. char *buffer = (char*)Alloc(64000 , MEM_NORMAL); //(char *)HidPage.Get_Buffer();
  404. cfile.Read(buffer, cfile.Size());
  405. buffer[cfile.Size()] = '\0';
  406. /*
  407. ** Check for forced intro movie run disabling. If the conquer
  408. ** configuration file says "no", then don't run the intro.
  409. */
  410. char tempbuff[5];
  411. WWGetPrivateProfileString("Intro", "PlayIntro", "Yes", tempbuff, 4, buffer);
  412. if ((stricmp(tempbuff, "No") == 0) || SpawnedFromWChat) {
  413. Special.IsFromInstall = false;
  414. }else{
  415. Special.IsFromInstall = true;
  416. }
  417. SlowPalette = WWGetPrivateProfileInt("Options", "SlowPalette", 1, buffer);
  418. #ifdef DEMO
  419. /*
  420. ** Check for override directory path for CD searches.
  421. */
  422. WWGetPrivateProfileString("CD", "Path", ".", OverridePath, sizeof(OverridePath), buffer);
  423. #endif
  424. /*
  425. ** Regardless of whether we should run it or not, here we're
  426. ** gonna change it to say "no" in the future.
  427. */
  428. WWWritePrivateProfileString("Intro", "PlayIntro", "No", buffer);
  429. cfile.Write(buffer, strlen(buffer));
  430. Free(buffer);
  431. CCDebugString ("C&C95 - Checking availability of C&CSPAWN.INI packet from WChat.\n");
  432. if (DDEServer.Get_MPlayer_Game_Info()){
  433. CCDebugString ("C&C95 - C&CSPAWN.INI packet available.\n");
  434. Check_From_WChat(NULL);
  435. }else{
  436. CCDebugString ("C&C95 - C&CSPAWN.INI packet not arrived yet.\n");
  437. //Check_From_WChat("C&CSPAWN.INI");
  438. //if (Special.IsFromWChat){
  439. // DDEServer.Disable();
  440. //}
  441. }
  442. /*
  443. ** If the intro is being run for the first time, then don't
  444. ** allow breaking out of it with the <ESC> key.
  445. */
  446. if (Special.IsFromInstall) {
  447. BreakoutAllowed = false;
  448. }
  449. Memory_Error_Exit = Print_Error_End_Exit;
  450. CCDebugString ("C&C95 - Entering main game.\n");
  451. Main_Game(argc, argv);
  452. VisiblePage.Clear();
  453. HiddenPage.Clear();
  454. // Set_Video_Mode(RESET_MODE);
  455. Memory_Error_Exit = Print_Error_Exit;
  456. CCDebugString ("C&C95 - About to exit.\n");
  457. ReadyToQuit = 1;
  458. PostMessage(MainWindow, WM_DESTROY, 0, 0);
  459. do
  460. {
  461. Keyboard::Check();
  462. }while (ReadyToQuit == 1);
  463. CCDebugString ("C&C95 - Returned from final message loop.\n");
  464. //Prog_End();
  465. //Invalidate_Cached_Icons();
  466. //VisiblePage.Un_Init();
  467. //HiddenPage.Un_Init();
  468. //AllSurfaces.Release();
  469. //Reset_Video_Mode();
  470. //Stop_Profiler();
  471. return (EXIT_SUCCESS);
  472. } else {
  473. #ifdef GERMAN
  474. puts("Bitte erst das SETUP-Programm starten.\n");
  475. #else
  476. #ifdef FRENCH
  477. puts("Lancez d'abord le programme de configuration SETUP.\n");
  478. #else
  479. puts("Run SETUP program first.");
  480. puts("\n");
  481. #endif
  482. Kbd.Get();
  483. #endif
  484. }
  485. // Remove_Keyboard_Interrupt();
  486. if (WindowsTimer){
  487. delete WindowsTimer;
  488. WindowsTimer = NULL;
  489. }
  490. if (Palette){
  491. delete [] Palette;
  492. Palette = NULL;
  493. }
  494. }
  495. /*
  496. ** Restore the current drive and directory.
  497. */
  498. #ifdef NOT_FOR_WIN95
  499. _dos_setdrive(olddrive, &drivecount);
  500. chdir(oldpath);
  501. #endif //NOT_FOR_WIN95
  502. return(EXIT_SUCCESS);
  503. }
  504. /***********************************************************************************************
  505. * Prog_End -- Cleans up library systems in prep for game exit. *
  506. * *
  507. * This routine should be called before the game terminates. It handles cleaning up *
  508. * library systems so that a graceful return to the host operating system is achieved. *
  509. * *
  510. * INPUT: none *
  511. * *
  512. * OUTPUT: none *
  513. * *
  514. * WARNINGS: none *
  515. * *
  516. * HISTORY: *
  517. * 03/20/1995 JLB : Created. *
  518. *=============================================================================================*/
  519. void __cdecl Prog_End(void)
  520. {
  521. #ifndef DEMO
  522. if (GameToPlay == GAME_MODEM || GameToPlay == GAME_NULL_MODEM) {
  523. NullModem.Change_IRQ_Priority(0);
  524. }
  525. #endif
  526. CCDebugString ("C&C95 - About to call Sound_End.\n");
  527. Sound_End();
  528. CCDebugString ("C&C95 - Returned from Sound_End.\n");
  529. if (WWMouse){
  530. CCDebugString ("C&C95 - Deleting mouse object.\n");
  531. delete WWMouse;
  532. WWMouse = NULL;
  533. }
  534. if (WindowsTimer){
  535. CCDebugString ("C&C95 - Deleting windows timer.\n");
  536. delete WindowsTimer;
  537. WindowsTimer = NULL;
  538. }
  539. if (Palette){
  540. CCDebugString ("C&C95 - Deleting palette object.\n");
  541. delete [] Palette;
  542. Palette = NULL;
  543. }
  544. }
  545. /***********************************************************************************************
  546. * Delete_Swap_Files -- Deletes previously existing swap files. *
  547. * *
  548. * This routine will scan through the current directory and delete any swap files it may *
  549. * find. This is used to clear out any left over swap files from previous runs (crashes) *
  550. * of the game. This routine presumes that it cannot delete the swap file that is created *
  551. * by the current run of the game. *
  552. * *
  553. * INPUT: none *
  554. * *
  555. * OUTPUT: none *
  556. * *
  557. * WARNINGS: none *
  558. * *
  559. * HISTORY: *
  560. * 08/27/1995 JLB : Created. *
  561. *=============================================================================================*/
  562. void Delete_Swap_Files(void)
  563. {
  564. struct find_t ff; // for _dos_findfirst
  565. if (!_dos_findfirst("*.SWP", _A_NORMAL, &ff)) {
  566. do {
  567. unlink(ff.name);
  568. } while(!_dos_findnext(&ff));
  569. }
  570. }
  571. void Print_Error_End_Exit(char *string)
  572. {
  573. printf( "%s\n", string );
  574. Get_Key();
  575. Prog_End();
  576. printf( "%s\n", string );
  577. exit(1);
  578. }
  579. void Print_Error_Exit(char *string)
  580. {
  581. printf( "%s\n", string );
  582. exit(1);
  583. }
  584. /***********************************************************************************************
  585. * Read_Setup_Options -- Read stuff in from the INI file that we need to know sooner *
  586. * *
  587. * *
  588. * *
  589. * INPUT: Nothing *
  590. * *
  591. * OUTPUT: Nothing *
  592. * *
  593. * WARNINGS: None *
  594. * *
  595. * HISTORY: *
  596. * 6/7/96 4:09PM ST : Created *
  597. *=============================================================================================*/
  598. void Read_Setup_Options( RawFileClass *config_file )
  599. {
  600. char *buffer = new char [config_file->Size()];
  601. if (config_file->Is_Available()){
  602. config_file->Read (buffer, config_file->Size());
  603. VideoBackBufferAllowed = WWGetPrivateProfileInt ("Options", "VideoBackBuffer", 1, buffer);
  604. AllowHardwareBlitFills = WWGetPrivateProfileInt ("Options", "HardwareFills", 1, buffer);
  605. ScreenHeight = WWGetPrivateProfileInt ("Options", "Resolution", 0, buffer) ? 480 : 400;
  606. IsV107 = WWGetPrivateProfileInt ("Options", "Compatibility", 0, buffer);
  607. /*
  608. ** See if an alternative socket number has been specified
  609. */
  610. int socket = WWGetPrivateProfileInt ("Options", "Socket", 0, buffer);
  611. if (socket >0 ){
  612. socket += 0x4000;
  613. if (socket >= 0x4000 && socket < 0x8000) {
  614. Ipx.Set_Socket (socket);
  615. }
  616. }
  617. /*
  618. ** See if a destination network has been specified
  619. */
  620. char netbuf [512];
  621. memset (netbuf, 0, sizeof (netbuf) );
  622. char *netptr = WWGetPrivateProfileString ("Options", "DestNet", NULL, netbuf, sizeof (netbuf), buffer);
  623. if (netptr && strlen (netbuf)){
  624. NetNumType net;
  625. NetNodeType node;
  626. /*
  627. ** Scan the string, pulling off each address piece
  628. */
  629. int i = 0;
  630. char * p = strtok(netbuf,".");
  631. int x;
  632. while (p) {
  633. sscanf(p,"%x",&x); // convert from hex string to int
  634. if (i < 4) {
  635. net[i] = (char)x; // fill NetNum
  636. } else {
  637. node[i-4] = (char)x; // fill NetNode
  638. }
  639. i++;
  640. p = strtok(NULL,".");
  641. }
  642. /*
  643. ** If all the address components were successfully read, fill in the
  644. ** BridgeNet with a broadcast address to the network across the bridge.
  645. */
  646. if (i >= 4) {
  647. IsBridge = 1;
  648. memset(node, 0xff, 6);
  649. BridgeNet = IPXAddressClass(net, node);
  650. }
  651. }
  652. }
  653. delete [] buffer;
  654. }