STARTUP.CPP 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /counterstrike/STARTUP.CPP 6 3/15/97 7:18p Steve_tall $ */
  15. /***********************************************************************************************
  16. *** 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 ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : STARTUP.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : October 3, 1994 *
  26. * *
  27. * Last Update : September 30, 1996 [JLB] *
  28. * *
  29. *---------------------------------------------------------------------------------------------*
  30. * Functions: *
  31. * Prog_End -- Cleans up library systems in prep for game exit. *
  32. * main -- Initial startup routine (preps library systems). *
  33. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  34. #include "function.h"
  35. #include <conio.h>
  36. #include <io.h>
  37. #ifdef WIN32
  38. #include "ccdde.h"
  39. #include "ipx95.h"
  40. #endif //WIN32
  41. #ifdef MCIMPEG // Denzil 6/15/98
  42. #include "mcimovie.h"
  43. #endif
  44. #ifdef WOLAPI_INTEGRATION
  45. //#include "WolDebug.h"
  46. #endif
  47. extern char RedAlertINI[_MAX_PATH];
  48. bool Read_Private_Config_Struct(FileClass & file, NewConfigType * config);
  49. void Print_Error_End_Exit(char * string);
  50. void Print_Error_Exit(char * string);
  51. #ifdef WIN32
  52. //WinTimerClass * WinTimer;
  53. extern void Create_Main_Window ( HANDLE instance , int command_show , int width , int height);
  54. extern bool RA95AlreadyRunning;
  55. HINSTANCE ProgramInstance;
  56. void Check_Use_Compressed_Shapes (void);
  57. void Read_Setup_Options(RawFileClass *config_file);
  58. bool VideoBackBufferAllowed = true;
  59. #else
  60. BOOL Init_Timer_System(unsigned int freq, int partial = FALSE);
  61. BOOL Remove_Timer_System(VOID);
  62. #endif //WIN32
  63. const char* Game_Registry_Key();
  64. #if (ENGLISH)
  65. #define WINDOW_NAME "Red Alert"
  66. #endif
  67. #if (FRENCH)
  68. #define WINDOW_NAME "Alerte Rouge"
  69. #endif
  70. #if (GERMAN)
  71. #define WINDOW_NAME "Alarmstufe Rot"
  72. #endif
  73. // Added. ST - 5/14/2019
  74. bool ProgEndCalled = false;
  75. extern "C"{
  76. extern char *BigShapeBufferStart;
  77. extern char *TheaterShapeBufferStart;
  78. extern BOOL UseBigShapeBuffer;
  79. extern bool IsTheaterShape;
  80. }
  81. extern void Free_Heaps(void);
  82. extern void DLL_Shutdown(void);
  83. BOOL WINAPI DllMain(HINSTANCE instance, unsigned int fdwReason, void *lpvReserved)
  84. {
  85. lpvReserved;
  86. switch (fdwReason) {
  87. case DLL_PROCESS_ATTACH:
  88. ProgramInstance = instance;
  89. break;
  90. case DLL_PROCESS_DETACH:
  91. if (WindowsTimer) {
  92. delete WindowsTimer;
  93. WindowsTimer = NULL;
  94. }
  95. /*
  96. ** Red Alert doesn't clean up memory. Do some of that here.
  97. */
  98. MFCD::Free_All();
  99. if (BigShapeBufferStart) {
  100. Free(BigShapeBufferStart);
  101. BigShapeBufferStart = NULL;
  102. }
  103. if (TheaterShapeBufferStart) {
  104. Free(TheaterShapeBufferStart);
  105. TheaterShapeBufferStart = NULL;
  106. }
  107. if (_ShapeBuffer) {
  108. delete [] _ShapeBuffer;
  109. _ShapeBuffer = NULL;
  110. }
  111. DLL_Shutdown();
  112. Free_Heaps();
  113. break;
  114. case DLL_THREAD_ATTACH:
  115. case DLL_THREAD_DETACH:
  116. break;
  117. }
  118. return true;
  119. }
  120. /***********************************************************************************************
  121. * main -- Initial startup routine (preps library systems). *
  122. * *
  123. * This is the routine that is first called when the program starts up. It basically *
  124. * handles the command line parsing and setting up library systems. *
  125. * *
  126. * INPUT: argc -- Number of command line arguments. *
  127. * *
  128. * argv -- Pointer to array of command line argument strings. *
  129. * *
  130. * OUTPUT: Returns with execution failure code (if any). *
  131. * *
  132. * WARNINGS: none *
  133. * *
  134. * HISTORY: *
  135. * 03/20/1995 JLB : Created. *
  136. *=============================================================================================*/
  137. #ifdef WIN32
  138. //int PASCAL WinMain(HINSTANCE, HINSTANCE, char *, int )
  139. //PG int PASCAL WinMain ( HINSTANCE instance , HINSTANCE , char * command_line , int command_show )
  140. int DLL_Startup(const char * command_line_in)
  141. #else //WIN32
  142. int main(int argc, char * argv[])
  143. #endif //WIN32
  144. {
  145. #ifdef WIN32
  146. RunningAsDLL = true;
  147. int command_show = SW_HIDE;
  148. HINSTANCE instance = ProgramInstance;
  149. char command_line[1024];
  150. strcpy(command_line, command_line_in);
  151. #ifndef MPEGMOVIE // Denzil 6/10/98
  152. //PG DDSCAPS surface_capabilities;
  153. #endif
  154. /*
  155. ** First thing to do is check if there is another instance of Red Alert already running
  156. ** and if so, switch to the existing instance and terminate ourselves.
  157. */
  158. SpawnedFromWChat = false;
  159. #if (0)//PG
  160. if (RA95AlreadyRunning) { //Set in the DDEServer constructor
  161. //MessageBox (NULL, "Error - attempt to restart Red Alert 95 when already running.", "Red Alert", MB_ICONEXCLAMATION|MB_OK);
  162. HWND ccwindow;
  163. ccwindow = FindWindow (WINDOW_NAME, WINDOW_NAME);
  164. if (ccwindow) {
  165. SetForegroundWindow ( ccwindow );
  166. ShowWindow ( ccwindow, SW_RESTORE );
  167. }
  168. return (EXIT_SUCCESS);
  169. }
  170. #endif
  171. #endif
  172. //printf("in program.\n");getch();
  173. //printf("ram free = %ld\n",Ram_Free(MEM_NORMAL));getch();
  174. #ifdef WIN32
  175. if (Ram_Free(MEM_NORMAL) < 7000000) {
  176. #else
  177. void *temp_mem = malloc (13*1024*1024);
  178. if (temp_mem) {
  179. free (temp_mem);
  180. }else{
  181. //if (Ram_Free(MEM_NORMAL) < 13000000) {
  182. // if (Ram_Free(MEM_NORMAL) < 3500000) {
  183. #endif
  184. printf (TEXT_NO_RAM);
  185. #ifndef WIN32
  186. printf (TEXT_USE_START_MENU);
  187. getch();
  188. #endif
  189. #if (0)
  190. /*
  191. ** Take a stab at finding out how much memory there is available.
  192. */
  193. for ( int mem = 13*1024*1024 ; mem >0 ; mem -=1024 ) {
  194. temp_mem = malloc (mem);
  195. if (temp_mem){
  196. free (temp_mem);
  197. printf ("Memory available: %d", mem);
  198. break;
  199. }
  200. }
  201. getch();
  202. #endif //(0)
  203. return(EXIT_FAILURE);
  204. }
  205. #ifdef WIN32
  206. if (strstr(command_line, "f:\\projects\\c&c0") != NULL ||
  207. strstr(command_line, "F:\\PROJECTS\\C&C0") != NULL) {
  208. MessageBox(0, "Playing off of the network is not allowed.", "Red Alert", MB_OK|MB_ICONSTOP);
  209. return(EXIT_FAILURE);
  210. }
  211. int argc; //Command line argument count
  212. unsigned command_scan;
  213. char command_char;
  214. char * argv[20]; //Pointers to command line arguments
  215. char path_to_exe[132];
  216. ProgramInstance = instance;
  217. /*
  218. ** Get the full path to the .EXE
  219. */
  220. GetModuleFileName (instance, &path_to_exe[0], 132);
  221. /*
  222. ** First argument is supposed to be a pointer to the .EXE that is running
  223. **
  224. */
  225. argc=1; //Set argument count to 1
  226. argv[0]=&path_to_exe[0]; //Set 1st command line argument to point to full path
  227. /*
  228. ** Get pointers to command line arguments just like if we were in DOS
  229. **
  230. ** The command line we get is cr/zero? terminated.
  231. **
  232. */
  233. command_scan=0;
  234. do {
  235. /*
  236. ** Scan for non-space character on command line
  237. */
  238. do {
  239. command_char = *( command_line+command_scan++ );
  240. } while ( command_char==' ' );
  241. if ( command_char!=0 && command_char != 13 ) {
  242. argv[argc++]=command_line+command_scan-1;
  243. /*
  244. ** Scan for space character on command line
  245. */
  246. bool in_quotes = false;
  247. do {
  248. command_char = *( command_line+command_scan++ );
  249. if (command_char == '"') {
  250. in_quotes = !in_quotes;
  251. }
  252. } while ( (in_quotes || command_char!=' ') && command_char != 0 && command_char!=13 );
  253. *( command_line+command_scan-1 ) = 0;
  254. }
  255. } while ( command_char != 0 && command_char != 13 && argc<20 );
  256. #endif //WIN32
  257. /*
  258. ** Remember the current working directory and drive.
  259. */
  260. #if (0)//PG
  261. unsigned olddrive;
  262. char oldpath[MAX_PATH];
  263. getcwd(oldpath, sizeof(oldpath));
  264. _dos_getdrive(&olddrive);
  265. /*
  266. ** Change directory to the where the executable is located. Handle the
  267. ** case where there is no path attached to argv[0].
  268. */
  269. char drive[_MAX_DRIVE];
  270. char path[_MAX_PATH];
  271. unsigned drivecount;
  272. _splitpath(argv[0], drive, path, NULL, NULL);
  273. if (!drive[0]) {
  274. drive[0] = ('A' + olddrive)-1;
  275. }
  276. if (!path[0]) {
  277. strcpy(path, ".");
  278. }
  279. _dos_setdrive(toupper((drive[0])-'A')+1, &drivecount);
  280. if (path[strlen(path)-1] == '\\') {
  281. path[strlen(path)-1] = '\0';
  282. }
  283. chdir(path);
  284. #endif
  285. #ifdef WOLAPI_INTEGRATION
  286. // Look for special wolapi install program, used after the patch to version 3, to install "Shared Internet Components".
  287. WIN32_FIND_DATA wfd;
  288. HANDLE hWOLSetupFile = FindFirstFile( "wolsetup.exe", &wfd );
  289. bool bWOLSetupFile = ( hWOLSetupFile != INVALID_HANDLE_VALUE );
  290. // if( bWOLSetupFile )
  291. // debugprint( "Found wolsetup.exe\n" );
  292. FindClose( hWOLSetupFile );
  293. // Look for special registry entry that tells us when the setup exe has done its thing.
  294. HKEY hKey;
  295. RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey );
  296. DWORD dwValue;
  297. DWORD dwBufSize = sizeof( DWORD );
  298. if( RegQueryValueEx( hKey, "WolapiInstallComplete", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) == ERROR_SUCCESS )
  299. {
  300. // debugprint( "Found WolapiInstallComplete in registry\n" );
  301. // Setup has finished. Delete the setup exe and remove reg key.
  302. if( bWOLSetupFile )
  303. {
  304. if( DeleteFile( "wolsetup.exe" ) )
  305. RegDeleteValue( hKey, "WolapiInstallComplete" );
  306. }
  307. else
  308. RegDeleteValue( hKey, "WolapiInstallComplete" );
  309. }
  310. RegCloseKey( hKey );
  311. // I've been having problems getting the patch to delete "conquer.eng", which is present in the game
  312. // directory for 1.08, but which must NOT be present for this version (Aftermath mix files provide the
  313. // string overrides that the 1.08 separate conquer.eng did before Aftermath).
  314. // Delete conquer.eng if it's found.
  315. if( FindFirstFile( "conquer.eng", &wfd ) != INVALID_HANDLE_VALUE )
  316. DeleteFile( "conquer.eng" );
  317. #endif
  318. if (Parse_Command_Line(argc, argv)) {
  319. #if(TEN)
  320. //
  321. // Only allow the TEN version of the game to run if the TEN
  322. // or AllowSoloPlayOptions arguments are specified.
  323. //
  324. if (Session.AllowSolo==0 && Session.Type != GAME_TEN) {
  325. #ifdef WIN32
  326. MessageBox(NULL, "Red Alert for TEN\n (c) 1996 Westwood Studios",
  327. "Red Alert", MB_OK);
  328. exit(0);
  329. #else
  330. printf("\n");
  331. printf(" Red Alert for TEN\n");
  332. printf(" (c) 1996 Westwood Studios\n");
  333. printf("\n");
  334. exit(0);
  335. #endif // WIN32
  336. }
  337. #endif // TEN
  338. #if(MPATH)
  339. //
  340. // Only allow the MPATH version of the game to run if the MPATH
  341. // or AllowSoloPlayOptions arguments are specified.
  342. //
  343. if (Session.AllowSolo==0 && Session.Type != GAME_MPATH) {
  344. #ifdef WIN32
  345. MessageBox(NULL, "Red Alert for MPATH\n (c) 1996 Westwood Studios",
  346. "Red Alert", MB_OK);
  347. exit(0);
  348. #else
  349. printf("\n");
  350. printf(" Red Alert for MPATH\n");
  351. printf(" (c) 1996 Westwood Studios\n");
  352. printf("\n");
  353. exit(0);
  354. #endif // WIN32
  355. }
  356. #endif // MPATH
  357. #ifdef WIN32
  358. WindowsTimer = new WinTimerClass(60, FALSE);
  359. #if (0)//PG
  360. int time_test = WindowsTimer->Get_System_Tick_Count();
  361. Sleep (1000);
  362. if (WindowsTimer->Get_System_Tick_Count() == time_test){
  363. MessageBox(0, TEXT_ERROR_TIMER, TEXT_SHORT_TITLE, MB_OK|MB_ICONSTOP);
  364. return(EXIT_FAILURE);
  365. }
  366. #endif
  367. #else //WIN32
  368. Init_Timer_System(60, true);
  369. #endif //WIN32
  370. ////////////////////////////////////////
  371. // The editor needs to load the Red Alert ini file from a different location than the real game. - 7/18/2019 JAS
  372. char* red_alert_file_path = nullptr;
  373. if (RunningFromEditor)
  374. {
  375. red_alert_file_path = RedAlertINI;
  376. }
  377. else
  378. {
  379. red_alert_file_path = CONFIG_FILE_NAME;
  380. }
  381. RawFileClass cfile(red_alert_file_path);
  382. //RawFileClass cfile(CONFIG_FILE_NAME);
  383. // end of change - 7/18/2019 JAS
  384. ////////////////////////////////////////
  385. #ifndef WIN32
  386. Install_Keyboard_Interrupt(Get_RM_Keyboard_Address(), Get_RM_Keyboard_Size());
  387. #endif //WIN32
  388. #ifdef NEVER
  389. Keyboard->IsLibrary = true;
  390. if (Debug_Flag) {
  391. Keyboard_Attributes_On(DEBUGINT);
  392. }
  393. #endif
  394. Keyboard = new KeyboardClass();
  395. #ifdef WIN32
  396. /*
  397. ** If there is loads of memory then use uncompressed shapes
  398. */
  399. Check_Use_Compressed_Shapes();
  400. #endif
  401. /*
  402. ** If there is not enough disk space free, don't allow the product to run.
  403. */
  404. if (Disk_Space_Available() < INIT_FREE_DISK_SPACE) {
  405. #ifdef WIN32
  406. #if (0)//PG
  407. char disk_space_message [512];
  408. sprintf(disk_space_message, TEXT_CRITICALLY_LOW); //PG , (INIT_FREE_DISK_SPACE) / (1024 * 1024));
  409. int reply = MessageBox(NULL, disk_space_message, TEXT_SHORT_TITLE, MB_ICONQUESTION|MB_YESNO);
  410. if (reply == IDNO) {
  411. if ( WindowsTimer )
  412. delete WindowsTimer;
  413. return (EXIT_FAILURE);
  414. }
  415. #endif
  416. #else
  417. printf(TEXT_INSUFFICIENT);
  418. printf(TEXT_MUST_HAVE, INIT_FREE_DISK_SPACE / (1024 * 1024));
  419. printf("\n");
  420. if (Keyboard) Keyboard->Get();
  421. // Keyboard::IsLibrary = false;
  422. Remove_Keyboard_Interrupt();
  423. Remove_Timer_System();
  424. return(EXIT_FAILURE);
  425. #endif
  426. }
  427. if (cfile.Is_Available()) {
  428. Read_Private_Config_Struct(cfile, &NewConfig);
  429. #ifdef WIN32
  430. /*
  431. ** Set the options as requested by the ccsetup program
  432. */
  433. Read_Setup_Options( &cfile );
  434. Create_Main_Window( instance , command_show , ScreenWidth , ScreenHeight );
  435. SoundOn = Audio_Init ( MainWindow , 16 , false , 11025*2 , 0 );
  436. #else //WIN32
  437. if (!Debug_Quiet) {
  438. Audio_Init(NewConfig.DigitCard,
  439. NewConfig.Port,
  440. NewConfig.IRQ,
  441. NewConfig.DMA,
  442. PLAYBACK_RATE_NORMAL,
  443. // (NewConfig.Speed) ? PLAYBACK_RATE_SLOW : PLAYBACK_RATE_NORMAL,
  444. NewConfig.BitsPerSample,
  445. // 4,
  446. (Get_CPU() < 5) ? 3 : 5,
  447. // (NewConfig.Speed) ? 3 : 5,
  448. NewConfig.Reverse);
  449. SoundOn = true;
  450. } else {
  451. Audio_Init(0, -1, -1, -1, PLAYBACK_RATE_NORMAL, 8, 5, false);
  452. }
  453. #endif //WIN32
  454. #ifdef WIN32
  455. #ifdef MPEGMOVIE // Denzil 6/10/98
  456. if (!InitDDraw())
  457. return (EXIT_FAILURE);
  458. #else
  459. BOOL video_success = FALSE;
  460. /*
  461. ** Set 640x400 video mode. If its not available then try for 640x480
  462. */
  463. if (ScreenHeight == 400) {
  464. if (Set_Video_Mode (MainWindow, ScreenWidth, ScreenHeight, 8)) {
  465. video_success = TRUE;
  466. } else {
  467. if (Set_Video_Mode (MainWindow, ScreenWidth, 480, 8)) {
  468. video_success = TRUE;
  469. ScreenHeight = 480;
  470. }
  471. }
  472. } else {
  473. if (Set_Video_Mode (MainWindow, ScreenWidth, ScreenHeight, 8)) {
  474. video_success = TRUE;
  475. }
  476. }
  477. if (!video_success) {
  478. MessageBox(MainWindow, TEXT_VIDEO_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);
  479. if (WindowsTimer) delete WindowsTimer;
  480. //if (Palette) delete Palette;
  481. return (EXIT_FAILURE);
  482. }
  483. if (ScreenWidth==320) {
  484. VisiblePage.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
  485. ModeXBuff.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));
  486. } else {
  487. #if (1) //ST - 1/3/2019 2:11PM
  488. VisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);
  489. HiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);
  490. #else
  491. VisiblePage.Init( ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));
  492. /*
  493. ** Check that we really got a video memory page. Failure is fatal.
  494. */
  495. memset (&surface_capabilities, 0, sizeof(surface_capabilities));
  496. VisiblePage.Get_DD_Surface()->GetCaps(&surface_capabilities);
  497. if (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY) {
  498. /*
  499. ** Aaaarrgghh!
  500. */
  501. WWDebugString(TEXT_DDRAW_ERROR);WWDebugString("\n");
  502. MessageBox(MainWindow, TEXT_DDRAW_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);
  503. if (WindowsTimer) delete WindowsTimer;
  504. return (EXIT_FAILURE);
  505. }
  506. /*
  507. ** If we have enough left then put the hidpage in video memory unless...
  508. **
  509. ** If there is no blitter then we will get better performance with a system
  510. ** memory hidpage
  511. **
  512. ** Use a system memory page if the user has specified it via the ccsetup program.
  513. */
  514. unsigned video_memory = Get_Free_Video_Memory();
  515. unsigned video_capabilities = Get_Video_Hardware_Capabilities();
  516. if (video_memory < (unsigned int)(ScreenWidth*ScreenHeight) ||
  517. (! (video_capabilities & VIDEO_BLITTER)) ||
  518. (video_capabilities & VIDEO_NO_HARDWARE_ASSIST) ||
  519. !VideoBackBufferAllowed) {
  520. HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
  521. } else {
  522. //HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
  523. HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)GBC_VIDEOMEM);
  524. /*
  525. ** Make sure we really got a video memory hid page. If we didnt then things
  526. ** will run very slowly.
  527. */
  528. memset (&surface_capabilities, 0, sizeof(surface_capabilities));
  529. HiddenPage.Get_DD_Surface()->GetCaps(&surface_capabilities);
  530. if (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY) {
  531. /*
  532. ** Oh dear, big trub. This must be an IBM Aptiva or something similarly cruddy.
  533. ** We must redo the Hidden Page as system memory.
  534. */
  535. AllSurfaces.Remove_DD_Surface(HiddenPage.Get_DD_Surface()); // Remove the old surface from the AllSurfaces list
  536. HiddenPage.Get_DD_Surface()->Release();
  537. HiddenPage.Init (ScreenWidth , ScreenHeight , NULL , 0 , (GBC_Enum)0);
  538. } else {
  539. VisiblePage.Attach_DD_Surface(&HiddenPage);
  540. }
  541. }
  542. #endif
  543. }
  544. ScreenHeight = 3072;
  545. if (VisiblePage.Get_Height() == 480) {
  546. SeenBuff.Attach(&VisiblePage, 0, 40, 3072, 3072);
  547. HidPage.Attach(&HiddenPage, 0, 40, 3072, 3072);
  548. } else {
  549. SeenBuff.Attach(&VisiblePage, 0, 0, 3072, 3072);
  550. HidPage.Attach(&HiddenPage, 0, 0, 3072, 3072);
  551. }
  552. #endif // MPEGMOVIE - Denzil 6/10/98
  553. Options.Adjust_Variables_For_Resolution();
  554. /*
  555. ** Install the memory error handler
  556. */
  557. Memory_Error = &Memory_Error_Handler;
  558. WindowList[0][WINDOWWIDTH] = SeenBuff.Get_Width();
  559. WindowList[0][WINDOWHEIGHT] = SeenBuff.Get_Height();
  560. WindowList[WINDOW_EDITOR][WINDOWWIDTH] = SeenBuff.Get_Width();
  561. WindowList[WINDOW_EDITOR][WINDOWHEIGHT]= SeenBuff.Get_Height();
  562. ////////////////////////////////////////
  563. // The editor needs to not start the mouse up. - 7/22/2019 JAS
  564. if (!RunningFromEditor)
  565. {
  566. WWMouse = new WWMouseClass(&SeenBuff, 48, 48);
  567. MouseInstalled = TRUE;
  568. }
  569. //PG CDFileClass::Set_CD_Drive (CDList.Get_First_CD_Drive());
  570. #else //WIN32
  571. Options.Adjust_Variables_For_Resolution();
  572. if (!Special.IsFromInstall) {
  573. BlackPalette.Set();
  574. // Set_Palette(Palette);
  575. Set_Video_Mode(MCGA_MODE);
  576. }
  577. MouseInstalled = Install_Mouse(32, 24, 320, 200);
  578. #endif //WIN32
  579. /*
  580. ** See if we should run the intro
  581. */
  582. INIClass ini;
  583. ini.Load(cfile);
  584. /*
  585. ** Check for forced intro movie run disabling. If the conquer
  586. ** configuration file says "no", then don't run the intro.
  587. ** Don't do this for TEN & MPath.
  588. */
  589. if (!Special.IsFromInstall && Session.Type != GAME_TEN &&
  590. Session.Type != GAME_MPATH) {
  591. Special.IsFromInstall = ini.Get_Bool("Intro", "PlayIntro", true);
  592. }
  593. SlowPalette = ini.Get_Bool("Options", "SlowPalette", false);
  594. /*
  595. ** Regardless of whether we should run it or not, here we're
  596. ** gonna change it to say "no" in the future.
  597. */
  598. if (Special.IsFromInstall) {
  599. BreakoutAllowed = true;
  600. // BreakoutAllowed = false;
  601. ini.Put_Bool("Intro", "PlayIntro", false);
  602. ini.Save(cfile);
  603. }
  604. #ifndef WOLAPI_INTEGRATION
  605. #ifdef WIN32
  606. /*
  607. ** If WChat has been trying to send us a game start packet then receive it and
  608. ** flag that we were spawned from WCHat so we dont play the into movie.
  609. */
  610. if (DDEServer.Get_MPlayer_Game_Info()){
  611. Check_From_WChat(NULL);
  612. }else{
  613. //Check_From_WChat("C&CSPAWN.INI");
  614. //if (Special.IsFromWChat){
  615. // DDEServer.Disable();
  616. //}
  617. }
  618. #endif //WIN32
  619. #endif
  620. /*
  621. ** If the intro is being run for the first time, then don't
  622. ** allow breaking out of it with the <ESC> key.
  623. */
  624. if (Special.IsFromInstall) {
  625. BreakoutAllowed = true;
  626. // BreakoutAllowed = false;
  627. }
  628. Memory_Error_Exit = Print_Error_End_Exit;
  629. Main_Game(argc, argv);
  630. if (RunningAsDLL) { //PG
  631. return (EXIT_SUCCESS);
  632. }
  633. #ifdef MPEGMOVIE // Denzil 6/15/98
  634. if (MpgSettings != NULL)
  635. delete MpgSettings;
  636. #ifdef MCIMPEG
  637. if (MciMovie != NULL)
  638. delete MciMovie;
  639. #endif
  640. #endif
  641. #ifdef WIN32
  642. VisiblePage.Clear();
  643. HiddenPage.Clear();
  644. #else //WIN32
  645. SeenPage.Clear();
  646. Set_Video_Mode(RESET_MODE);
  647. #endif //WIN32
  648. Memory_Error_Exit = Print_Error_Exit;
  649. #ifdef WIN32
  650. /*
  651. ** Flag that this is a clean shutdown (not killed with Ctrl-Alt-Del)
  652. */
  653. ReadyToQuit = 1;
  654. /*
  655. ** Post a message to our message handler to tell it to clean up.
  656. */
  657. PostMessage(MainWindow, WM_DESTROY, 0, 0);
  658. /*
  659. ** Wait until the message handler has dealt with the message
  660. */
  661. do
  662. {
  663. Keyboard->Check();
  664. }while (ReadyToQuit == 1);
  665. return (EXIT_SUCCESS);
  666. #else //WIN32
  667. Remove_Mouse();
  668. Sound_End();
  669. #endif //WIN32
  670. } else {
  671. if (!RunningFromEditor)
  672. {
  673. puts(TEXT_SETUP_FIRST);
  674. Keyboard->Get();
  675. }
  676. }
  677. #ifdef WIN32
  678. if (WindowsTimer) {
  679. delete WindowsTimer;
  680. WindowsTimer = NULL;
  681. }
  682. #else //WIN32
  683. Remove_Keyboard_Interrupt();
  684. Remove_Timer_System();
  685. #endif //WIN32
  686. }
  687. /*
  688. ** Restore the current drive and directory.
  689. */
  690. #ifndef WIN32
  691. _dos_setdrive(olddrive, &drivecount);
  692. chdir(oldpath);
  693. #endif //WIN32
  694. return(EXIT_SUCCESS);
  695. }
  696. /* Initialize DirectDraw and surfaces */
  697. bool InitDDraw(void)
  698. {
  699. VisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE | GBC_VIDEOMEM));
  700. HiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);
  701. VisiblePage.Attach_DD_Surface(&HiddenPage);
  702. SeenBuff.Attach(&VisiblePage, 0, 0, 3072, 3072);
  703. HidPage.Attach(&HiddenPage, 0, 0, 3072, 3072);
  704. #if (0)//PG
  705. DDSCAPS surface_capabilities;
  706. BOOL video_success = FALSE;
  707. /* Set 640x400 video mode. If its not available then try for 640x480 */
  708. if (ScreenHeight == 400)
  709. {
  710. if (Set_Video_Mode(MainWindow, ScreenWidth, ScreenHeight, 8))
  711. {
  712. video_success = TRUE;
  713. }
  714. else
  715. {
  716. if (Set_Video_Mode(MainWindow, ScreenWidth, 480, 8))
  717. {
  718. video_success = TRUE;
  719. ScreenHeight = 480;
  720. }
  721. }
  722. }
  723. else
  724. {
  725. if (Set_Video_Mode(MainWindow, ScreenWidth, ScreenHeight, 8))
  726. {
  727. video_success = TRUE;
  728. }
  729. }
  730. if (!video_success)
  731. {
  732. MessageBox(MainWindow, TEXT_VIDEO_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);
  733. if (WindowsTimer)
  734. delete WindowsTimer;
  735. return false;
  736. }
  737. if (ScreenWidth == 320)
  738. {
  739. VisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);
  740. ModeXBuff.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE|GBC_VIDEOMEM));
  741. }
  742. else
  743. {
  744. VisiblePage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)(GBC_VISIBLE|GBC_VIDEOMEM));
  745. /* Check that we really got a video memory page. Failure is fatal. */
  746. memset(&surface_capabilities, 0, sizeof(surface_capabilities));
  747. VisiblePage.Get_DD_Surface()->GetCaps(&surface_capabilities);
  748. if (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY)
  749. {
  750. /* Aaaarrgghh! */
  751. WWDebugString(TEXT_DDRAW_ERROR);WWDebugString("\n");
  752. MessageBox(MainWindow, TEXT_DDRAW_ERROR, TEXT_SHORT_TITLE, MB_ICONEXCLAMATION|MB_OK);
  753. if (WindowsTimer)
  754. delete WindowsTimer;
  755. return false;
  756. }
  757. /* If we have enough left then put the hidpage in video memory unless...
  758. *
  759. * If there is no blitter then we will get better performance with a system
  760. * memory hidpage
  761. *
  762. * Use a system memory page if the user has specified it via the ccsetup program.
  763. */
  764. unsigned video_memory = Get_Free_Video_Memory();
  765. unsigned video_capabilities = Get_Video_Hardware_Capabilities();
  766. if (video_memory < ScreenWidth * ScreenHeight
  767. || (!(video_capabilities & VIDEO_BLITTER))
  768. || (video_capabilities & VIDEO_NO_HARDWARE_ASSIST)
  769. || !VideoBackBufferAllowed)
  770. {
  771. HiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);
  772. }
  773. else
  774. {
  775. HiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)GBC_VIDEOMEM);
  776. /* Make sure we really got a video memory hid page. If we didnt then things
  777. * will run very slowly.
  778. */
  779. memset(&surface_capabilities, 0, sizeof(surface_capabilities));
  780. HiddenPage.Get_DD_Surface()->GetCaps(&surface_capabilities);
  781. if (surface_capabilities.dwCaps & DDSCAPS_SYSTEMMEMORY)
  782. {
  783. /* Oh dear, big trub. This must be an IBM Aptiva or something similarly cruddy.
  784. * We must redo the Hidden Page as system memory.
  785. */
  786. AllSurfaces.Remove_DD_Surface(HiddenPage.Get_DD_Surface()); // Remove the old surface from the AllSurfaces list
  787. HiddenPage.Get_DD_Surface()->Release();
  788. HiddenPage.Init(ScreenWidth, ScreenHeight, NULL, 0, (GBC_Enum)0);
  789. }
  790. else
  791. {
  792. VisiblePage.Attach_DD_Surface(&HiddenPage);
  793. }
  794. }
  795. }
  796. ScreenHeight = 400;
  797. if (VisiblePage.Get_Height() == 480)
  798. {
  799. SeenBuff.Attach(&VisiblePage, 0, 40, 3072, 3072);
  800. HidPage.Attach(&HiddenPage, 0, 40, 3072, 3072);
  801. }
  802. else
  803. {
  804. SeenBuff.Attach(&VisiblePage, 0, 0, 3072, 3072);
  805. HidPage.Attach(&HiddenPage, 0, 0, 3072, 3072);
  806. }
  807. #endif
  808. return true;
  809. }
  810. /***********************************************************************************************
  811. * Prog_End -- Cleans up library systems in prep for game exit. *
  812. * *
  813. * This routine should be called before the game terminates. It handles cleaning up *
  814. * library systems so that a graceful return to the host operating system is achieved. *
  815. * *
  816. * INPUT: why - text description of exit reason *
  817. * fatal - indicates a fatal error *
  818. * *
  819. * OUTPUT: none *
  820. * *
  821. * WARNINGS: none *
  822. * *
  823. * HISTORY: *
  824. * 03/20/1995 JLB : Created. *
  825. * 08/07/2019 ST : Added why and fatal params *
  826. *=============================================================================================*/
  827. #ifdef WIN32
  828. void __cdecl Prog_End(const char *why, bool fatal)
  829. {
  830. GlyphX_Debug_Print("Prog_End()");
  831. if (why) {
  832. GlyphX_Debug_Print(why);
  833. }
  834. if (fatal) {
  835. *((int*)0) = 0;
  836. }
  837. if (Session.Type == GAME_GLYPHX_MULTIPLAYER) {
  838. return;
  839. }
  840. Sound_End();
  841. if (WWMouse) {
  842. delete WWMouse;
  843. WWMouse = NULL;
  844. }
  845. if (WindowsTimer) {
  846. delete WindowsTimer;
  847. WindowsTimer = NULL;
  848. }
  849. ProgEndCalled = true;
  850. }
  851. #else //WIN32
  852. void Prog_End(void)
  853. {
  854. if (Session.Type == GAME_MODEM || Session.Type == GAME_NULL_MODEM) {
  855. NullModem.Change_IRQ_Priority(0);
  856. }
  857. Set_Video_Mode(RESET_MODE);
  858. Remove_Keyboard_Interrupt();
  859. Remove_Mouse();
  860. Sound_End();
  861. Remove_Timer_System();
  862. }
  863. #endif //WIN32
  864. void Print_Error_End_Exit(char * string)
  865. {
  866. Prog_End(string, true);
  867. printf( "%s\n", string );
  868. if (!RunningAsDLL) {
  869. exit(1);
  870. }
  871. }
  872. void Print_Error_Exit(char * string)
  873. {
  874. GlyphX_Debug_Print(string);
  875. printf( "%s\n", string );
  876. if (!RunningAsDLL) {
  877. exit(1);
  878. }
  879. }
  880. /***********************************************************************************************
  881. * Emergency_Exit -- Function to call when we want to exit unexpectedly. *
  882. * Use this function instead of exit(n) so everything is properly cleaned up.*
  883. * *
  884. * *
  885. * INPUT: Code to return to the OS *
  886. * *
  887. * OUTPUT: Nothing *
  888. * *
  889. * WARNINGS: None *
  890. * *
  891. * HISTORY: *
  892. * 3/13/97 1:32AM ST : Created *
  893. *=============================================================================================*/
  894. void Emergency_Exit ( int code )
  895. {
  896. if (RunningAsDLL) { //PG
  897. return;
  898. }
  899. #ifdef WIN32
  900. /*
  901. ** Clear out the video buffers so we dont glitch when we lose focus
  902. */
  903. VisiblePage.Clear();
  904. HiddenPage.Clear();
  905. BlackPalette.Set();
  906. Memory_Error_Exit = Print_Error_Exit;
  907. /*
  908. ** Flag that this is an emergency shut down - not a clean shutdown but
  909. ** not killed with Ctrl-Alt-Del either.
  910. */
  911. ReadyToQuit = 3;
  912. /*
  913. ** Post a message to our message handler to tell it to clean up.
  914. */
  915. PostMessage(MainWindow, WM_DESTROY, 0, 0);
  916. /*
  917. ** Wait until the message handler has dealt with the message
  918. */
  919. do
  920. {
  921. Keyboard->Check();
  922. }while (ReadyToQuit == 3);
  923. #else //WIN32
  924. /*
  925. ** Do the DOS end
  926. */
  927. Prog_End();
  928. #endif //WIN32
  929. exit ( code );
  930. }
  931. #ifdef WIN32
  932. /***********************************************************************************************
  933. * Read_Setup_Options -- Read stuff in from the INI file that we need to know sooner *
  934. * *
  935. * *
  936. * *
  937. * INPUT: Ptr to config file class *
  938. * *
  939. * OUTPUT: Nothing *
  940. * *
  941. * WARNINGS: None *
  942. * *
  943. * HISTORY: *
  944. * 6/7/96 4:09PM ST : Created *
  945. * 09/30/1996 JLB : Uses INI class. *
  946. *=============================================================================================*/
  947. void Read_Setup_Options( RawFileClass *config_file )
  948. {
  949. if (config_file->Is_Available()) {
  950. INIClass ini;
  951. ini.Load(*config_file);
  952. /*
  953. ** Read in the boolean options
  954. */
  955. VideoBackBufferAllowed = ini.Get_Bool("Options", "VideoBackBuffer", true);
  956. AllowHardwareBlitFills = ini.Get_Bool("Options", "HardwareFills", true);
  957. ScreenHeight = ini.Get_Bool("Options", "Resolution", false) ? 3072 : 3072;
  958. /*
  959. ** See if an alternative socket number has been specified
  960. */
  961. int socket = ini.Get_Int("Options", "Socket", 0);
  962. if (socket >0 ) {
  963. socket += 0x4000;
  964. if (socket >= 0x4000 && socket < 0x8000) {
  965. Ipx.Set_Socket (socket);
  966. }
  967. }
  968. /*
  969. ** See if a destination network has been specified
  970. */
  971. char netbuf [512];
  972. memset(netbuf, 0, sizeof(netbuf));
  973. char * netptr = netbuf;
  974. bool found = ini.Get_String("Options", "DestNet", NULL, netbuf, sizeof(netbuf));
  975. if (found && netptr != NULL && strlen(netbuf)) {
  976. NetNumType net;
  977. NetNodeType node;
  978. /*
  979. ** Scan the string, pulling off each address piece
  980. */
  981. int i = 0;
  982. char * p = strtok(netbuf,".");
  983. int x;
  984. while (p != NULL) {
  985. sscanf(p,"%x",&x); // convert from hex string to int
  986. if (i < 4) {
  987. net[i] = (char)x; // fill NetNum
  988. } else {
  989. node[i-4] = (char)x; // fill NetNode
  990. }
  991. i++;
  992. p = strtok(NULL,".");
  993. }
  994. /*
  995. ** If all the address components were successfully read, fill in the
  996. ** BridgeNet with a broadcast address to the network across the bridge.
  997. */
  998. if (i >= 4) {
  999. Session.IsBridge = 1;
  1000. memset(node, 0xff, 6);
  1001. Session.BridgeNet = IPXAddressClass(net, node);
  1002. }
  1003. }
  1004. }
  1005. }
  1006. void Get_OS_Version (void)
  1007. {
  1008. //PG
  1009. //WindowsNT = ((GetVersion() & 0x80000000) == 0) ? true : false;
  1010. #if (0)
  1011. OSVERSIONINFO osversion;
  1012. if ( GetVersionEx (&osversion) ){
  1013. WindowsNT = (osversion.dwPlatformId == VER_PLATFORM_WIN32_NT) ? true : false;
  1014. OutputDebugString ("RA95 - Got OS version\n");
  1015. }else{
  1016. OutputDebugString ("RA95 - Failed to get OS version\n");
  1017. char debugstr [128];
  1018. sprintf (debugstr, "RA95 - Error code is %d\n", GetLastError());
  1019. OutputDebugString (debugstr);
  1020. }
  1021. #endif //(0)
  1022. }
  1023. #endif //WIN32