INIT.CPP 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054
  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: F:\projects\c&c\vcs\code\init.cpv 2.18 16 Oct 1995 16:50:16 JOE_BOSTIC $ */
  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 : INIT.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : January 20, 1992 *
  26. * *
  27. *---------------------------------------------------------------------------------------------*
  28. * Functions: *
  29. * Anim_Init -- Initialize the VQ animation control structure. *
  30. * Init_Game -- Main game initialization routine. *
  31. * Load_Recording_Values -- Loads recording values from recording file *
  32. * Obfuscate -- Sufficiently transform parameter to thwart casual hackers. *
  33. * Parse_Command_Line -- Parses the command line parameters. *
  34. * Parse_INI_File -- Parses CONQUER.INI for special options *
  35. * Play_Intro -- plays the introduction & logo movies *
  36. * Save_Recording_Values -- Saves recording values to a recording file *
  37. * Select_Game -- The game's main menu *
  38. * Version_Number -- Determines the version number. *
  39. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  40. #include "function.h"
  41. #include "loaddlg.h"
  42. #include "tcpip.h"
  43. #include <conio.h>
  44. #include <dos.h>
  45. #include "ccdde.h"
  46. static HANDLE hCCLibrary;
  47. /****************************************
  48. ** Function prototypes for this module **
  49. *****************************************/
  50. static void Play_Intro(bool for_real = false);
  51. extern "C" {
  52. extern long RandNumb;
  53. }
  54. extern int SimRandIndex;
  55. #define ATTRACT_MODE_TIMEOUT 3600 // timeout for attract mode
  56. #if(0)
  57. long FAR PASCAL _export Start_Game_Proc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
  58. {
  59. switch (message) {
  60. case WM_CREATE:
  61. break;
  62. case WM_COMMAND:
  63. EndDialog(hwnd, TRUE);
  64. AllDone = TRUE;
  65. break;
  66. case WM_DESTROY:
  67. EndDialog(hwnd, TRUE);
  68. break;
  69. }
  70. return(DefWindowProc(hwnd, message, wParam, lParam));
  71. }
  72. #endif
  73. extern bool Server_Remote_Connect(void);
  74. extern bool Client_Remote_Connect(void);
  75. extern bool SpawnedFromWChat;
  76. /***********************************************************************************************
  77. * Init_Game -- Main game initialization routine. *
  78. * *
  79. * Perform all one-time game initializations here. This includes all *
  80. * allocations and table setups. The intro and other one-time startup *
  81. * tasks are also performed here. *
  82. * *
  83. * INPUT: argc,argv -- Command line arguments. *
  84. * *
  85. * OUTPUT: none *
  86. * *
  87. * WARNINGS: Only call this ONCE! *
  88. * *
  89. * HISTORY: *
  90. * 10/07/1992 JLB : Created. *
  91. *=============================================================================================*/
  92. bool Init_Game(int , char *[])
  93. {
  94. void const *temp_mouse_shapes;
  95. CCDebugString ("C&C95 - About to load reslib.dll\n");
  96. hCCLibrary = LoadLibrary("reslib.dll");
  97. /*
  98. ** Initialize the game object heaps.
  99. */
  100. CCDebugString ("C&C95 - About to enter Units.Set_Heap\n");
  101. Units.Set_Heap(UNIT_MAX);
  102. CCDebugString ("C&C95 - About to enter Factories.Set_Heap\n");
  103. Factories.Set_Heap(FACTORY_MAX);
  104. CCDebugString ("C&C95 - About to enter Terrains.Set_Heap\n");
  105. Terrains.Set_Heap(TERRAIN_MAX);
  106. CCDebugString ("C&C95 - About to enter Templates.Set_Heap\n");
  107. Templates.Set_Heap(TEMPLATE_MAX);
  108. CCDebugString ("C&C95 - About to enter Smudges.Set_Heap\n");
  109. Smudges.Set_Heap(SMUDGE_MAX);
  110. CCDebugString ("C&C95 - About to enter Overlays.Set_Heap\n");
  111. Overlays.Set_Heap(OVERLAY_MAX);
  112. CCDebugString ("C&C95 - About to enter Infantry.Set_Heap\n");
  113. Infantry.Set_Heap(INFANTRY_MAX);
  114. CCDebugString ("C&C95 - About to enter Bullets.Set_Heap\n");
  115. Bullets.Set_Heap(BULLET_MAX);
  116. CCDebugString ("C&C95 - About to enter Buildings.Set_Heap\n");
  117. Buildings.Set_Heap(BUILDING_MAX);
  118. CCDebugString ("C&C95 - About to enter Anims.Set_Heap\n");
  119. Anims.Set_Heap(ANIM_MAX);
  120. CCDebugString ("C&C95 - About to enter Aircraft.Set_Heap\n");
  121. Aircraft.Set_Heap(AIRCRAFT_MAX);
  122. CCDebugString ("C&C95 - About to enter Triggers.Set_Heap\n");
  123. Triggers.Set_Heap(TRIGGER_MAX);
  124. CCDebugString ("C&C95 - About to enter TeamTypes.Set_Heap\n");
  125. TeamTypes.Set_Heap(TEAMTYPE_MAX);
  126. CCDebugString ("C&C95 - About to enter Teams.Set_Heap\n");
  127. Teams.Set_Heap(TEAM_MAX);
  128. CCDebugString ("C&C95 - About to enter Houses.Set_Heap\n");
  129. Houses.Set_Heap(HOUSE_MAX);
  130. /*
  131. ** Initialize all the waypoints to invalid values.
  132. */
  133. CCDebugString ("C&C95 - About to clear waypoints\n");
  134. memset(Waypoint, 0xFF, sizeof(Waypoint));
  135. /*
  136. ** Setup the keyboard processor in preparation for the game.
  137. */
  138. CCDebugString ("C&C95 - About to do various keyboard inits\n");
  139. #ifdef FIX_ME_LATER
  140. Keyboard_Attributes_Off(TRACKEXT | PAUSEON | BREAKON | SCROLLLOCKON | CTRLSON | CTRLCON | PASSBREAKS | FILTERONLY | TASKSWITCHABLE);
  141. #endif //FIX_ME_LATER
  142. Keyboard::Clear();
  143. Kbd.Clear();
  144. /*
  145. ** This is the shape staging buffer. It must always be available, so it is
  146. ** allocated here and never freed. The library sets the globals ShapeBuffer
  147. ** and ShapeBufferSize to these values, so it can be accessed for other
  148. ** purposes.
  149. */
  150. CCDebugString ("C&C95 - About to call Set_Shape_Buffer\n");
  151. Set_Shape_Buffer(new unsigned char[SHAPE_BUFFER_SIZE], SHAPE_BUFFER_SIZE);
  152. /*
  153. ** Bootstrap enough of the system so that the error dialog box can sucessfully
  154. ** be displayed.
  155. */
  156. CCDebugString ("C&C95 - About to register CCLOCAL.MIX\n");
  157. #ifdef DEMO
  158. new MixFileClass("DEMOL.MIX");
  159. MixFileClass::Cache("DEMOL.MIX");
  160. #else
  161. int temp = RequiredCD;
  162. RequiredCD = -2;
  163. new MixFileClass("CCLOCAL.MIX"); // Cached.
  164. MixFileClass::Cache("CCLOCAL.MIX");
  165. CCDebugString ("C&C95 - About to register UPDATE.MIX\n");
  166. new MixFileClass("UPDATE.MIX"); // Cached.
  167. new MixFileClass("UPDATA.MIX"); // Cached.
  168. CCDebugString ("C&C95 - About to register UPDATEC.MIX\n");
  169. new MixFileClass("UPDATEC.MIX"); // Cached.
  170. MixFileClass::Cache("UPDATEC.MIX");
  171. #ifdef JAPANESE
  172. CCDebugString ("C&C95 - About to register LANGUAGE.MIX\n");
  173. new MixFileClass("LANGUAGE.MIX");
  174. #endif //JAPANESE
  175. RequiredCD = temp;
  176. #endif
  177. CCDebugString ("C&C95 - About to load fonts\n");
  178. Green12FontPtr = Load_Alloc_Data(CCFileClass("12GREEN.FNT"));
  179. Green12GradFontPtr = Load_Alloc_Data(CCFileClass("12GRNGRD.FNT"));
  180. MapFontPtr = Load_Alloc_Data(CCFileClass("8FAT.FNT"));
  181. Font8Ptr = MixFileClass::Retrieve(FONT8);
  182. FontPtr = (char *)Font8Ptr;
  183. Set_Font(FontPtr);
  184. Font3Ptr = MixFileClass::Retrieve(FONT3);
  185. // Font6Ptr = MixFileClass::Retrieve(FONT6);
  186. Font6Ptr = Load_Alloc_Data(CCFileClass("6POINT.FNT"));
  187. //ScoreFontPtr = MixFileClass::Retrieve("12GRNGRD.FNT"); //GRAD12FN"); //("SCOREFNT.FNT");
  188. ScoreFontPtr = Load_Alloc_Data(CCFileClass("12GRNGRD.FNT"));
  189. FontLEDPtr = MixFileClass::Retrieve("LED.FNT");
  190. VCRFontPtr = MixFileClass::Retrieve("VCR.FNT");
  191. // GradFont6Ptr = MixFileClass::Retrieve("GRAD6FNT.FNT");
  192. GradFont6Ptr = Load_Alloc_Data(CCFileClass("GRAD6FNT.FNT"));
  193. BlackPalette = new(MEM_CLEAR|MEM_REAL) unsigned char[768];
  194. GamePalette = new(MEM_CLEAR|MEM_REAL) unsigned char[768];
  195. OriginalPalette = new(MEM_CLEAR|MEM_REAL) unsigned char[768];
  196. WhitePalette = new(MEM_CLEAR|MEM_REAL) unsigned char[768];
  197. memset(WhitePalette, 63, 768);
  198. CCDebugString ("C&C95 - About to set palette\n");
  199. memset(BlackPalette, 0x01, 768);
  200. if (!Special.IsFromInstall) Set_Palette(BlackPalette);
  201. memset(BlackPalette, 0, 768);
  202. if (!Special.IsFromInstall) {
  203. Set_Palette(BlackPalette);
  204. CCDebugString ("C&C95 - About to clear visible page\n");
  205. VisiblePage.Clear();
  206. }
  207. Set_Palette(GamePalette);
  208. CCDebugString ("C&C95 - About to set the mouse shape\n");
  209. /*
  210. ** Since there is no mouse shape currently available we need'
  211. ** to set one of our own.
  212. */
  213. ShowCursor (FALSE);
  214. if (MouseInstalled) {
  215. temp_mouse_shapes = MixFileClass::Retrieve("MOUSE.SHP");
  216. if (temp_mouse_shapes) {
  217. Set_Mouse_Cursor(0, 0, Extract_Shape(temp_mouse_shapes,0));
  218. while (Get_Mouse_State() > 1) {
  219. Show_Mouse();
  220. }
  221. }
  222. }
  223. CCDebugString ("C&C95 - About to enter wait for focus loop\n");
  224. /*
  225. ** Process the message loop until we are in focus.
  226. */
  227. do {
  228. CCDebugString ("C&C95 - About to call Keyboard::Check\n");
  229. Keyboard::Check();
  230. }while (!GameInFocus);
  231. AllSurfaces.SurfacesRestored=FALSE;
  232. CCDebugString ("C&C95 - About to load the language file\n");
  233. /*
  234. ** Fetch the language text from the hard drive first. If it cannot be
  235. ** found on the hard drive, then look for it in the mixfile.
  236. */
  237. if (RawFileClass(Language_Name("CONQUER")).Is_Available()) {
  238. SystemStrings = (char const *)Load_Alloc_Data(RawFileClass(Language_Name("CONQUER")));
  239. } else {
  240. SystemStrings = (char const *)MixFileClass::Retrieve(Language_Name("CONQUER"));
  241. }
  242. /*
  243. ** Default palette initialization. Uses the desert palette for convenience,
  244. ** but only the non terrain specific colors matter.
  245. */
  246. //Mem_Copy((void *)MixFileClass::Retrieve("TEMPERAT.PAL"), GamePalette, 768L);
  247. CCFileClass palfile ("TEMPERAT.PAL");
  248. palfile.Read (GamePalette, 768L);
  249. if (!MouseInstalled) {
  250. char buffer[255];
  251. Set_Palette(GamePalette);
  252. #ifdef GERMAN
  253. sprintf(buffer, "Command & Conquer kann Ihren Maustreiber nicht finden..");
  254. #else
  255. #ifdef FRENCH
  256. sprintf(buffer, "Command & Conquer ne peut pas d‚tecter votre gestionnaire de souris.");
  257. #else
  258. sprintf(buffer, "Command & Conquer is unable to detect your mouse driver.");
  259. #endif
  260. #endif
  261. CCMessageBox().Process(buffer, TXT_OK);
  262. Prog_End();
  263. exit(1);
  264. }
  265. #ifdef DEMO
  266. /*
  267. ** Add in any override path specified in the conquer.ini file.
  268. */
  269. if (strlen(OverridePath)) {
  270. CCFileClass::Set_Search_Drives(OverridePath);
  271. }
  272. #endif
  273. #if (0) //ST - 1/2/2019 5:49PM
  274. CCDebugString ("C&C95 - About to search for CD drives\n");
  275. /*
  276. ** Always try to look at the CD-ROM for data files.
  277. */
  278. if (!CCFileClass::Is_There_Search_Drives()) {
  279. /*
  280. ** If there are no search drives specified then we must be playing
  281. ** off cd, so read files from there.
  282. */
  283. int error;
  284. do {
  285. if (!CDList.Get_Number_Of_Drives()){
  286. Set_Palette(GamePalette);
  287. Show_Mouse();
  288. CCMessageBox().Process(TXT_CD_ERROR1, TXT_OK);
  289. Prog_End();
  290. exit(EXIT_FAILURE);
  291. }
  292. CCFileClass::Set_CD_Drive( CDList.Get_First_CD_Drive() );
  293. error = CCFileClass::Set_Search_Drives("?:\\");
  294. switch(error) {
  295. case 1:
  296. Set_Palette(GamePalette);
  297. Show_Mouse();
  298. CCMessageBox().Process(TXT_CD_ERROR1, TXT_OK);
  299. Prog_End();
  300. exit(EXIT_FAILURE);
  301. case 2:
  302. Set_Palette(GamePalette);
  303. Show_Mouse();
  304. if (CCMessageBox().Process(TXT_CD_DIALOG_1, TXT_OK, TXT_CANCEL) == 1) {
  305. Prog_End();
  306. exit(EXIT_FAILURE);
  307. }
  308. Hide_Mouse();
  309. break;
  310. default:
  311. Show_Mouse();
  312. if (!Force_CD_Available(RequiredCD)) {
  313. Prog_End();
  314. exit(EXIT_FAILURE);
  315. }
  316. Hide_Mouse();
  317. break;
  318. }
  319. } while (error);
  320. #ifdef DEMO
  321. RequiredCD = -2;
  322. #else
  323. RequiredCD = -1;
  324. #endif
  325. } else {
  326. /*
  327. ** If there are search drives specified then all files are to be
  328. ** considered local.
  329. */
  330. RequiredCD = -2;
  331. }
  332. #endif
  333. #ifndef DEMO
  334. CCDebugString ("C&C95 - About to register addon mixfiles\n");
  335. /*
  336. ** Before all else, cache any additional mixfiles.
  337. */
  338. /*
  339. ** Need to search the search paths. ST - 3/15/2019 2:18PM
  340. */
  341. const char *path = ".\\";
  342. char search_path[_MAX_PATH];
  343. char scan_path[_MAX_PATH];
  344. for (int p=0 ; p<100 ; p++) {
  345. strcpy(search_path, path);
  346. if (search_path[strlen(search_path) - 1] != '\\') {
  347. strcat(search_path, "\\");
  348. }
  349. strcpy(scan_path, search_path);
  350. strcat(scan_path, "SC*.MIX");
  351. WIN32_FIND_DATA find_data;
  352. memset(&find_data, 0, sizeof(find_data));
  353. HANDLE file_handle = FindFirstFile(scan_path, &find_data);
  354. if (file_handle != INVALID_HANDLE_VALUE)
  355. {
  356. do
  357. {
  358. char *ptr = strdup(find_data.cFileName);
  359. new MixFileClass(ptr);
  360. MixFileClass::Cache(ptr);
  361. } while (FindNextFile(file_handle, &find_data));
  362. FindClose(file_handle);
  363. }
  364. memset(&find_data, 0, sizeof(find_data));
  365. strcpy(scan_path, search_path);
  366. strcat(scan_path, "Ss*.MIX");
  367. file_handle = FindFirstFile(scan_path, &find_data);
  368. if (file_handle != INVALID_HANDLE_VALUE)
  369. {
  370. do
  371. {
  372. char *ptr = strdup(find_data.cFileName);
  373. new MixFileClass(ptr);
  374. MixFileClass::Cache(ptr);
  375. } while (FindNextFile(file_handle, &find_data));
  376. FindClose(file_handle);
  377. }
  378. path = CDFileClass::Get_Search_Path(p);
  379. if (path == NULL) {
  380. break;
  381. }
  382. }
  383. #if (0)
  384. struct find_t ff; // for _dos_findfirst
  385. if (!_dos_findfirst("SC*.MIX", _A_NORMAL, &ff)) {
  386. char * ptr;
  387. do {
  388. ptr = strdup(ff.name);
  389. new MixFileClass(ptr);
  390. MixFileClass::Cache(ptr);
  391. // free(ptr);
  392. } while(!_dos_findnext(&ff));
  393. }
  394. if (!_dos_findfirst("SS*.MIX", _A_NORMAL, &ff)) {
  395. char * ptr;
  396. do {
  397. ptr = strdup(ff.name);
  398. new MixFileClass(ptr);
  399. // free(ptr);
  400. } while(!_dos_findnext(&ff));
  401. }
  402. #endif
  403. #endif //DEMO
  404. CCDebugString ("C&C95 - About to register GENERAL.MIX\n");
  405. //
  406. // This is a problem because registering the mix file can call Force_CD_Available which will try to load General.Mix
  407. // Might as well just cut to the chase and call it directly.
  408. // ST - 1/3/2019 5:19PM
  409. //
  410. //if (GeneralMix) delete GeneralMix;
  411. //GeneralMix = new MixFileClass("GENERAL.MIX");
  412. Force_CD_Available(RequiredCD);
  413. // if (!_dos_findfirst("SC*.MIX", _A_NORMAL, &ff)) {
  414. // do {
  415. // new MixFileClass(ff.name);
  416. // MixFileClass::Cache(ff.name);
  417. // } while(!_dos_findnext(&ff));
  418. // }
  419. /*
  420. ** Inform the file system of the various MIX files.
  421. */
  422. #ifdef DEMO
  423. new MixFileClass("DEMO.MIX");
  424. if (CCFileClass("DEMOM.MIX").Is_Available()) {
  425. if (!MoviesMix) MoviesMix = new MixFileClass("DEMOM.MIX");
  426. ScoresPresent = true;
  427. ThemeClass::Scan();
  428. }
  429. #else
  430. CCDebugString ("C&C95 - About to register CONQUER.MIX\n");
  431. new MixFileClass("CONQUER.MIX"); // Cached.
  432. CCDebugString ("C&C95 - About to register TRANSIT.MIX\n");
  433. new MixFileClass("TRANSIT.MIX");
  434. CCDebugString ("C&C95 - About to register GENERAL.MIX\n");
  435. if (!GeneralMix) GeneralMix = new MixFileClass("GENERAL.MIX"); // Never cached.
  436. // if (CCFileClass("MOVIES.MIX").Is_Available()) {
  437. CCDebugString ("C&C95 - About to register MOVIES.MIX\n");
  438. if (!MoviesMix) MoviesMix = new MixFileClass("MOVIES.MIX"); // Never cached.
  439. // }
  440. #if (0)
  441. /*
  442. ** Extract a movie from a mixfile.
  443. */
  444. char *file_ptr = (char*)Alloc (32 * 1024 * 1024, MEM_NORMAL);
  445. CCFileClass whatever ("PINTLE.VQA");
  446. int len = whatever.Size();
  447. whatever.Open();
  448. DWORD actual;
  449. HANDLE sfile = CreateFile("c:\\temp\\PINTLE.VQA", GENERIC_WRITE, 0,
  450. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  451. if (sfile != INVALID_HANDLE_VALUE){
  452. SetFilePointer (sfile, 0, NULL, FILE_END);
  453. do{
  454. whatever.Read (file_ptr, MIN (len, 1024*64));
  455. WriteFile(sfile, file_ptr, MIN (len, 1024*64), &actual, NULL);
  456. len -= MIN (len, 1024*64);
  457. }while ( len >0 );
  458. CloseHandle (sfile);
  459. }
  460. whatever.Close();
  461. Free (file_ptr);
  462. #endif //(0)
  463. /*
  464. ** Register the score mixfile.
  465. */
  466. CCDebugString ("C&C95 - About to register SCORES.MIX\n");
  467. ScoresPresent = false;
  468. // if (CCFileClass("SCORES.MIX").Is_Available()) {
  469. ScoresPresent = true;
  470. if (!ScoreMix) {
  471. ScoreMix = new MixFileClass("SCORES.MIX");
  472. ThemeClass::Scan();
  473. }
  474. // }
  475. #endif
  476. /*
  477. ** These are sound card specific, but the install program would have
  478. ** copied the coorect versions to the hard drive.
  479. */
  480. CCDebugString ("C&C95 - About to register SPEECH.MIX\n");
  481. if (CCFileClass("SPEECH.MIX").Is_Available()) {
  482. new MixFileClass("SPEECH.MIX"); // Never cached.
  483. }
  484. CCDebugString ("C&C95 - About to register SOUNDS.MIX\n");
  485. new MixFileClass("SOUNDS.MIX"); // Cached.
  486. /*
  487. ** Initialize the animation system.
  488. */
  489. CCDebugString ("C&C95 - About to initialise the animation system\n");
  490. Anim_Init();
  491. if (SpawnedFromWChat){
  492. Special.IsFromWChat = true;
  493. }
  494. /*
  495. ** Play the introduction movies.
  496. */
  497. CCDebugString ("C&C95 - About to play the intro movie\n");
  498. if (!Special.IsFromInstall && !Special.IsFromWChat) Play_Intro(true);
  499. /*
  500. ** Wait for a VSync; during the vertical blank, set the game palette & blit
  501. ** the title screen. We must ensure no RGB values in the game palette match
  502. ** those in the WWLIB's 'CurrentPalette', or the WWLIB palette-set routine
  503. ** will skip that color; the VQ player will have changed that color (behind
  504. ** WWLIB's back), so it will be incorrect.
  505. */
  506. memset(CurrentPalette, 0x01, 768);
  507. if (!Special.IsFromInstall) {
  508. Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
  509. Blit_Hid_Page_To_Seen_Buff();
  510. }
  511. Hide_Mouse();
  512. Wait_Vert_Blank();
  513. if (!Special.IsFromInstall) {
  514. Set_Palette(Palette);
  515. Blit_Hid_Page_To_Seen_Buff();
  516. Show_Mouse();
  517. }
  518. Call_Back();
  519. // Window_Dialog_Box(hCCLibrary, "DIALOG_1", MainWindow, MakeProcInstance((FARPROC)Start_Game_Proc, hInstance));
  520. // if (hCCLibrary) FreeLibrary(hCCLibrary);
  521. #ifdef DEMO
  522. MixFileClass::Cache("DEMO.MIX");
  523. MixFileClass::Cache("SOUNDS.MIX");
  524. #else
  525. /*
  526. ** Cache the main game data. This operation can take a very long time.
  527. */
  528. MixFileClass::Cache("CONQUER.MIX");
  529. if (SampleType != 0 && !Debug_Quiet) {
  530. MixFileClass::Cache("SOUNDS.MIX");
  531. if (Special.IsJuvenile) {
  532. new MixFileClass("ZOUNDS.MIX"); // Cached.
  533. MixFileClass::Cache("ZOUNDS.MIX");
  534. }
  535. }
  536. Call_Back();
  537. #endif
  538. // malloc(2);
  539. /*
  540. ** Perform any special debug-only processing. This includes preparing the
  541. ** monochrome screen.
  542. */
  543. Mono_Clear_Screen();
  544. #ifdef ONHOLD
  545. /*
  546. ** Check for addition options not specified on the command-line. This must
  547. ** be done before the One_Time calls, but after the shape buffer is set up.
  548. */
  549. Parse_INI_File();
  550. #endif
  551. /*
  552. ** Perform one-time game system initializations.
  553. */
  554. Call_Back();
  555. // malloc(3);
  556. Map.One_Time();
  557. // malloc(4);
  558. Logic.One_Time();
  559. // malloc(5);
  560. Options.One_Time();
  561. // malloc(6);
  562. ObjectTypeClass::One_Time();
  563. BuildingTypeClass::One_Time();
  564. BulletTypeClass::One_Time();
  565. HouseTypeClass::One_Time();
  566. TemplateTypeClass::One_Time();
  567. OverlayTypeClass::One_Time();
  568. SmudgeTypeClass::One_Time();
  569. TerrainTypeClass::One_Time();
  570. UnitTypeClass::One_Time();
  571. InfantryTypeClass::One_Time();
  572. AnimTypeClass::One_Time();
  573. AircraftTypeClass::One_Time();
  574. HouseClass::One_Time();
  575. /*
  576. ** Speech holding tank buffer. Since speech does not mix, it can be placed
  577. ** into a custom holding tank only as large as the largest speech file to
  578. ** be played.
  579. */
  580. SpeechBuffer = new char [SPEECH_BUFFER_SIZE];
  581. Call_Back();
  582. /*
  583. ** WWLIB bug: MouseState is in some undefined state; show the mouse until
  584. ** it really shows.
  585. */
  586. Map.Set_Default_Mouse(MOUSE_NORMAL, false);
  587. Show_Mouse();
  588. //#ifdef FIX_ME_LATER
  589. while (Get_Mouse_State() > 0) Show_Mouse();
  590. //#endif //FIX_ME_LATER
  591. Call_Back();
  592. #ifndef DEMO
  593. /*
  594. ** Load multiplayer scenario descriptions
  595. */
  596. Read_Scenario_Descriptions();
  597. #endif
  598. /*
  599. ** Initialize the multiplayer score values
  600. */
  601. MPlayerGamesPlayed = 0;
  602. MPlayerNumScores = 0;
  603. MPlayerCurGame = 0;
  604. for (int i = 0; i < MAX_MULTI_NAMES; i++) {
  605. MPlayerScore[i].Name[0] = '\0';
  606. MPlayerScore[i].Wins = 0;
  607. for (int j = 0; j < MAX_MULTI_GAMES; j++) {
  608. MPlayerScore[i].Kills[j] = -1; // -1 = this player didn't play this round
  609. }
  610. }
  611. /*
  612. ** Copy the title screen's palette into the GamePalette & OriginalPalette,
  613. ** because the options Load routine uses these palettes to set the brightness, etc.
  614. */
  615. memcpy (GamePalette, Palette, 768);
  616. memcpy (OriginalPalette, Palette, 768);
  617. /*
  618. ** Read game options, so the GameSpeed is initialized when multiplayer
  619. ** dialogs are invoked. (GameSpeed must be synchronized between systems.)
  620. */
  621. Options.Load_Settings();
  622. return(true);
  623. }
  624. //#ifndef NOMEMCHECK
  625. void Uninit_Game(void)
  626. {
  627. delete Map.ShadowPage;
  628. Map.ShadowPage = NULL;
  629. Map.Free_Cells();
  630. delete [] SpeechBuffer;
  631. CCFileClass::Clear_Search_Drives();
  632. MixFileClass::Free_All();
  633. Units.Set_Heap(0);
  634. Factories.Set_Heap(0);
  635. Terrains.Set_Heap(0);
  636. Templates.Set_Heap(0);
  637. Smudges.Set_Heap(0);
  638. Overlays.Set_Heap(0);
  639. Infantry.Set_Heap(0);
  640. Bullets.Set_Heap(0);
  641. Buildings.Set_Heap(0);
  642. Anims.Set_Heap(0);
  643. Aircraft.Set_Heap(0);
  644. Triggers.Set_Heap(0);
  645. TeamTypes.Set_Heap(0);
  646. Teams.Set_Heap(0);
  647. Houses.Set_Heap(0);
  648. delete [] _ShapeBuffer;
  649. Set_Shape_Buffer(NULL, 0);
  650. delete [] BlackPalette;
  651. delete [] GamePalette;
  652. delete [] OriginalPalette;
  653. delete [] WhitePalette;
  654. WWDOS_Shutdown();
  655. delete [] Palette;
  656. }
  657. //#endif
  658. extern bool Do_The_Internet_Menu_Thang(void);
  659. extern int ShowCommand;
  660. /***********************************************************************************************
  661. * Select_Game -- The game's main menu *
  662. * *
  663. * INPUT: *
  664. * fade if true, will fade the palette in gradually *
  665. * *
  666. * OUTPUT: *
  667. * none. *
  668. * *
  669. * WARNINGS: *
  670. * none. *
  671. * *
  672. * HISTORY: *
  673. * 06/05/1995 BRR : Created. *
  674. *=============================================================================================*/
  675. extern int Com_Fake_Scenario_Dialog(void);
  676. extern int Com_Show_Fake_Scenario_Dialog(void);
  677. extern int WChatMaxAhead;
  678. extern int WChatSendRate;
  679. void Check_From_WChat(char *wchat_name);
  680. bool Select_Game(bool fade)
  681. {
  682. enum {
  683. SEL_TIMEOUT = -1, // main menu timeout--go into attract mode
  684. #ifdef NEWMENU
  685. SEL_NEW_SCENARIO, // Expansion scenario to play.
  686. #endif
  687. SEL_START_NEW_GAME, // start a new game
  688. #ifdef BONUS_MISSIONS
  689. SEL_BONUS_MISSIONS,
  690. #endif //BONUS_MISSIONS
  691. SEL_INTERNET,
  692. SEL_LOAD_MISSION, // load a saved game
  693. SEL_MULTIPLAYER_GAME, // play modem/null-modem/network game
  694. SEL_INTRO, // replay the intro
  695. SEL_EXIT, // exit to DOS
  696. SEL_FAME, // view the hall of fame
  697. SEL_NONE, // placeholder default value
  698. };
  699. bool gameloaded=false; // Has the game been loaded from the menu?
  700. int selection; // the default selection
  701. bool process = true; // false = break out of while loop
  702. bool display = true;
  703. CountDownTimerClass count;
  704. int cd_index;
  705. MEMORYSTATUS mem_info;
  706. mem_info.dwLength=sizeof(mem_info);
  707. GlobalMemoryStatus(&mem_info);
  708. /*
  709. ** Enable the DDE Server so we can get internet start game packets from WChat
  710. */
  711. DDEServer.Enable();
  712. if (Special.IsFromInstall) {
  713. /*
  714. ** Special case for machines with 12 megs or less - just play intro, no choose side screen
  715. */
  716. if (mem_info.dwTotalPhys < 12*1024*1024){
  717. VisiblePage.Clear();
  718. Play_Movie("INTRO2", THEME_NONE, false);
  719. BreakoutAllowed = true;
  720. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  721. fade = true;
  722. VisiblePage.Clear();
  723. }else{
  724. display = false;
  725. Show_Mouse();
  726. }
  727. }
  728. /*
  729. ** [Re]set any globals that need it, in preparation for a new scenario
  730. */
  731. GameActive = true;
  732. DoList.Init();
  733. OutList.Init();
  734. Frame = 0;
  735. PlayerWins = false;
  736. PlayerLoses = false;
  737. MPlayerObiWan = false;
  738. Debug_Unshroud = false;
  739. Map.Set_Cursor_Shape(0);
  740. Map.PendingObjectPtr = 0;
  741. Map.PendingObject = 0;
  742. Map.PendingHouse = HOUSE_NONE;
  743. /*
  744. ** Initialize multiplayer-protocol-specific variables:
  745. ** If CommProtocol MULTI_E_COMP is used, you must:
  746. ** Init FrameSendRate to a sensible value (3 is good)
  747. ** Init MPlayerMaxAhead to an even multiple of FrameSendRate, and it must
  748. ** be at least 2 * MPlayerMaxAhead
  749. */
  750. CommProtocol = COMM_PROTOCOL_SINGLE_NO_COMP;
  751. if (!Special.IsFromWChat){
  752. FrameSendRate = 3;
  753. }
  754. ProcessTicks = 0;
  755. ProcessFrames = 0;
  756. DesiredFrameRate = 30;
  757. //#if(TIMING_FIX)
  758. NewMaxAheadFrame1 = 0;
  759. NewMaxAheadFrame2 = 0;
  760. //#endif
  761. /*
  762. ** Init multiplayer game scores. Let Wins accumulate; just init the current
  763. ** Kills for this game. Kills of -1 means this player didn't play this round.
  764. */
  765. for (int i = 0 ; i < MAX_MULTI_GAMES; i++) {
  766. MPlayerScore[i].Kills[MPlayerCurGame] = -1;
  767. }
  768. /*
  769. ** Set default mouse shape
  770. */
  771. Map.Set_Default_Mouse(MOUSE_NORMAL, false);
  772. /*
  773. ** If the last game we played was a multiplayer game, jump right to that
  774. ** menu by pre-setting 'selection'.
  775. */
  776. if (GameToPlay == GAME_NORMAL) {
  777. selection = SEL_NONE;
  778. } else {
  779. selection = SEL_MULTIPLAYER_GAME;
  780. }
  781. /*
  782. ** Main menu processing; only do this if we're not in editor mode.
  783. */
  784. if (!Debug_Map) {
  785. /*
  786. ** Menu selection processing loop
  787. */
  788. ScenarioInit++;
  789. Theme.Queue_Song(THEME_MAP1);
  790. ScenarioInit--;
  791. /*
  792. ** If we're playing back a recording, load all pertinant values & skip
  793. ** the menu loop. Hide the now-useless mouse pointer.
  794. */
  795. if (PlaybackGame && RecordFile.Is_Available()) {
  796. if (RecordFile.Open(READ)) {
  797. Load_Recording_Values();
  798. process = false;
  799. Theme.Fade_Out();
  800. } else
  801. PlaybackGame = false;
  802. }
  803. /*
  804. ** Handle case where we were spawned from Wchat
  805. */
  806. if (SpawnedFromWChat){
  807. Special.IsFromInstall = false; //Dont play intro if we were spawned from wchat
  808. selection = SEL_INTERNET;
  809. Theme.Queue_Song(THEME_NONE);
  810. GameToPlay = GAME_INTERNET;
  811. display = false;
  812. Set_Logic_Page(SeenBuff);
  813. }
  814. while (process) {
  815. /*
  816. ** If we have just received input focus again after running in the background then
  817. ** we need to redraw.
  818. */
  819. if (AllSurfaces.SurfacesRestored){
  820. AllSurfaces.SurfacesRestored=FALSE;
  821. display=TRUE;
  822. }
  823. /*
  824. ** Redraw the title page if needed
  825. */
  826. if (display) {
  827. Hide_Mouse();
  828. /*
  829. ** Display the title page; fade it in if this is the first time
  830. ** through the loop, and the 'fade' flag is true
  831. */
  832. Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
  833. memcpy (GamePalette, Palette, 768);
  834. Blit_Hid_Page_To_Seen_Buff();
  835. if (fade) {
  836. Fade_Palette_To(Palette, FADE_PALETTE_SLOW, Call_Back);
  837. fade = false;
  838. }
  839. Set_Logic_Page(SeenBuff);
  840. #ifdef VIRGIN_CHEAT_KEYS
  841. Fancy_Text_Print("V.%d%s", SeenBuff.Get_Width() - 1, SeenBuff.Get_Height() - 10, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText, FOREIGN_VERSION_NUMBER);
  842. // Fancy_Text_Print("V.%d%s%02d", 319, 190, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText, FOREIGN_VERSION_NUMBER);
  843. #else
  844. #ifdef DEMO
  845. Version_Number();
  846. Fancy_Text_Print("DEMO V%s", SeenBuff.Get_Width() - 1, SeenBuff.Get_Height() - 10, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, VersionText);
  847. #else
  848. Fancy_Text_Print("V.%d%s", SeenBuff.Get_Width() - 1, SeenBuff.Get_Height() - 10, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText);
  849. #endif
  850. #endif
  851. display = false;
  852. Show_Mouse();
  853. } else {
  854. if (RunningAsDLL) {
  855. return true;;
  856. }
  857. }
  858. /*
  859. ** Display menu and fetch selection from player.
  860. */
  861. if (Special.IsFromInstall && mem_info.dwTotalPhys >= 12*1024*1024){
  862. selection = SEL_START_NEW_GAME;
  863. Theme.Queue_Song(THEME_NONE);
  864. }
  865. /*
  866. ** Handle case where we were spawned from Wchat
  867. */
  868. if (Special.IsFromWChat && DDEServer.Get_MPlayer_Game_Info()){
  869. Check_From_WChat(NULL);
  870. selection = SEL_MULTIPLAYER_GAME;
  871. Theme.Queue_Song(THEME_NONE);
  872. GameToPlay = GAME_INTERNET;
  873. }else{
  874. /*
  875. ** We werent spawned but we could still receive a DDE packet from wchat
  876. */
  877. if (DDEServer.Get_MPlayer_Game_Info()){
  878. Check_From_WChat(NULL);
  879. /*
  880. ** Make sure top and bottom of screen are clear in 640x480 mode
  881. */
  882. if (ScreenHeight == 480){
  883. VisiblePage.Fill_Rect (0, 0, 639, 40, 0);
  884. VisiblePage.Fill_Rect (0, 440, 639, 479, 0);
  885. }
  886. }
  887. }
  888. if (selection == SEL_NONE) {
  889. // selection = Main_Menu(0);
  890. selection = Main_Menu(ATTRACT_MODE_TIMEOUT);
  891. }
  892. Call_Back();
  893. switch (selection) {
  894. #ifdef NEWMENU
  895. case SEL_INTERNET:
  896. /*
  897. ** Only call up the internet menu code if we dont already have connect info from WChat
  898. */
  899. if (!DDEServer.Get_MPlayer_Game_Info()){
  900. CCDebugString ("C&C95 - About to call Internet Menu.\n");
  901. if (Do_The_Internet_Menu_Thang() && DDEServer.Get_MPlayer_Game_Info()){
  902. CCDebugString ("C&C95 - About to call Check_From_WChat.\n");
  903. Check_From_WChat(NULL);
  904. selection = SEL_MULTIPLAYER_GAME;
  905. display = false;
  906. GameToPlay = GAME_INTERNET;
  907. }else{
  908. selection = SEL_NONE;
  909. display = true;
  910. }
  911. }else{
  912. CCDebugString ("C&C95 - About to call Check_From_WChat.\n");
  913. Check_From_WChat(NULL);
  914. display = false;
  915. GameToPlay = GAME_INTERNET;
  916. selection = SEL_MULTIPLAYER_GAME;
  917. }
  918. break;
  919. /*
  920. ** Pick an expansion scenario.
  921. */
  922. case SEL_NEW_SCENARIO:
  923. CarryOverMoney = 0;
  924. if (Expansion_Dialog()) {
  925. Theme.Fade_Out();
  926. // Theme.Queue_Song(THEME_AOI);
  927. GameToPlay = GAME_NORMAL;
  928. process = false;
  929. } else {
  930. display = true;
  931. selection = SEL_NONE;
  932. }
  933. break;
  934. #ifdef BONUS_MISSIONS
  935. /*
  936. ** User selected to play a bonus scenario.
  937. */
  938. case SEL_BONUS_MISSIONS:
  939. CarryOverMoney = 0;
  940. /*
  941. ** Ensure that CD1 or CD2 is in the drive. These missions
  942. ** are not on the covert CD.
  943. */
  944. cd_index = Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60);
  945. /*
  946. ** If cd_index == 2 then its a covert CD
  947. */
  948. if (cd_index == 2){
  949. RequiredCD = 0;
  950. if (!Force_CD_Available (RequiredCD)){
  951. Prog_End("Select_Game - CD not found", true);
  952. exit(EXIT_FAILURE);
  953. }
  954. }
  955. if (Bonus_Dialog()) {
  956. Theme.Fade_Out();
  957. GameToPlay = GAME_NORMAL;
  958. process = false;
  959. } else {
  960. display = true;
  961. selection = SEL_NONE;
  962. }
  963. break;
  964. #endif //BONUS_MISSIONS
  965. #endif
  966. /*
  967. ** SEL_START_NEW_GAME: Play the game
  968. */
  969. case SEL_START_NEW_GAME:
  970. CarryOverMoney = 0;
  971. #ifdef DEMO
  972. Hide_Mouse();
  973. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  974. Load_Title_Screen("PREPICK.PCX", &HidPage, Palette);
  975. Blit_Hid_Page_To_Seen_Buff();
  976. Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
  977. Clear_KeyBuffer();
  978. while (!Check_Key_Num()) {
  979. Call_Back();
  980. }
  981. Get_Key_Num();
  982. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  983. Show_Mouse();
  984. Scenario = 1;
  985. BuildLevel = 1;
  986. #else
  987. Scenario = 1;
  988. BuildLevel = 1;
  989. #endif
  990. ScenPlayer = SCEN_PLAYER_GDI;
  991. ScenDir = SCEN_DIR_EAST;
  992. Whom = HOUSE_GOOD;
  993. #ifndef DEMO
  994. Theme.Fade_Out();
  995. Choose_Side();
  996. #endif
  997. /*
  998. ** If user is playing special mode, do NOT change Whom; leave it set to
  999. ** GDI or NOD. Ini.cpp will set the player's ActLike to mirror the
  1000. ** Whom value.
  1001. */
  1002. if (Special.IsJurassic && AreThingiesEnabled) {
  1003. ScenPlayer = SCEN_PLAYER_JP;
  1004. ScenDir = SCEN_DIR_EAST;
  1005. }
  1006. GameToPlay = GAME_NORMAL;
  1007. process = false;
  1008. break;
  1009. /*
  1010. ** Load a saved game.
  1011. */
  1012. case SEL_LOAD_MISSION:
  1013. if (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {
  1014. //Theme.Fade_Out();
  1015. Theme.Queue_Song(THEME_AOI);
  1016. process = false;
  1017. gameloaded = true;
  1018. } else {
  1019. display = true;
  1020. selection = SEL_NONE;
  1021. }
  1022. break;
  1023. /*
  1024. ** SEL_MULTIPLAYER_GAME: set 'GameToPlay' to NULL-modem, modem, or
  1025. ** network play.
  1026. */
  1027. case SEL_MULTIPLAYER_GAME:
  1028. #ifdef DEMO
  1029. Hide_Mouse();
  1030. Set_Palette(BlackPalette);
  1031. Load_Title_Screen("DEMOPIC.PCX", &HidPage, Palette);
  1032. Blit_Hid_Page_To_Seen_Buff();
  1033. Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
  1034. Clear_KeyBuffer();
  1035. while (!Check_Key()) {
  1036. Call_Back();
  1037. }
  1038. Get_Key();
  1039. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1040. Show_Mouse();
  1041. display = true;
  1042. fade = true;
  1043. selection = SEL_NONE;
  1044. #else
  1045. switch (GameToPlay) {
  1046. /*
  1047. ** If 'GameToPlay' isn't already set up for a multiplayer game,
  1048. ** we must prompt the user for which type of multiplayer game
  1049. ** they want.
  1050. */
  1051. case GAME_NORMAL:
  1052. GameToPlay = Select_MPlayer_Game();
  1053. if (GameToPlay == GAME_NORMAL) { // 'Cancel'
  1054. display = true;
  1055. selection = SEL_NONE;
  1056. }
  1057. break;
  1058. case GAME_NULL_MODEM:
  1059. case GAME_MODEM:
  1060. #if (0)
  1061. if ( NullModem.Num_Connections() ) {
  1062. NullModem.Init_Send_Queue();
  1063. if ((GameToPlay == GAME_NULL_MODEM &&
  1064. ModemGameToPlay == MODEM_NULL_HOST) ||
  1065. (GameToPlay == GAME_MODEM &&
  1066. ModemGameToPlay == MODEM_DIALER) ) {
  1067. if ( !Com_Scenario_Dialog() ) {
  1068. GameToPlay = Select_Serial_Dialog();
  1069. if (GameToPlay == GAME_NORMAL) { // user hit Cancel
  1070. display = true;
  1071. selection = SEL_NONE;
  1072. }
  1073. }
  1074. } else {
  1075. if ( !Com_Show_Scenario_Dialog() ) {
  1076. GameToPlay = Select_Serial_Dialog();
  1077. if (GameToPlay == GAME_NORMAL) { // user hit Cancel
  1078. display = true;
  1079. selection = SEL_NONE;
  1080. }
  1081. }
  1082. }
  1083. } else {
  1084. GameToPlay = Select_MPlayer_Game();
  1085. if (GameToPlay == GAME_NORMAL) { // 'Cancel'
  1086. display = true;
  1087. selection = SEL_NONE;
  1088. }
  1089. }
  1090. #endif
  1091. break;
  1092. #ifdef FORCE_WINSOCK
  1093. /*
  1094. ** Handle being spawned from WChat. Intermnet play based on IPX code now.
  1095. */
  1096. case GAME_INTERNET:
  1097. CCDebugString ("C&C95 - case GAME_INTERNET:\n");
  1098. if (Special.IsFromWChat){
  1099. //MessageBox (NULL, "About to restore focus to C&C95", "C&C95", MB_OK);
  1100. CCDebugString ("C&C95 - About to give myself focus.\n");
  1101. SetForegroundWindow ( MainWindow );
  1102. ShowWindow ( MainWindow, ShowCommand );
  1103. CCDebugString ("C&C95 - About to initialise Winsock.\n");
  1104. if (Winsock.Init()){
  1105. CCDebugString ("C&C95 - About to read multiplayer settings.\n");
  1106. Read_MultiPlayer_Settings ();
  1107. Server = PlanetWestwoodIsHost;
  1108. CCDebugString ("C&C95 - About to set addresses.\n");
  1109. Winsock.Set_Host_Address(PlanetWestwoodIPAddress);
  1110. CCDebugString ("C&C95 - About to call Start_Server or Start_Client.\n");
  1111. if (Server){
  1112. ModemGameToPlay = INTERNET_HOST;
  1113. Winsock.Start_Server();
  1114. }else{
  1115. ModemGameToPlay = INTERNET_JOIN;
  1116. Winsock.Start_Client();
  1117. }
  1118. //#if (0)
  1119. /*
  1120. ** Flush out any pending packets from a previous game.
  1121. */
  1122. CCDebugString ("C&C95 - About to flush packet queue.\n");
  1123. CCDebugString ("C&C95 - Allocating scrap memory.\n");
  1124. char *temp_buffer = new char[1024];
  1125. CCDebugString ("C&C95 - Creating timer class instance.\n");
  1126. CountDownTimerClass ptimer;
  1127. CCDebugString ("C&C95 - Entering read loop.\n");
  1128. while (Winsock.Read(temp_buffer, 1024)){
  1129. CCDebugString ("C&C95 - Discarding a packet.\n");
  1130. ptimer.Set (30, true);
  1131. while (ptimer.Time()){};
  1132. CCDebugString ("C&C95 - Ready to check for more packets.\n");
  1133. }
  1134. CCDebugString ("C&C95 - About to delete scrap memory.\n");
  1135. delete temp_buffer;
  1136. //#endif //(0)
  1137. }else{
  1138. CCDebugString ("C&C95 - Winsock failed to initialise.\n");
  1139. GameToPlay = GAME_NORMAL;
  1140. selection = SEL_EXIT;
  1141. Special.IsFromWChat = false;
  1142. break;
  1143. }
  1144. CCDebugString ("C&C95 - About to call Init_Network.\n");
  1145. Init_Network();
  1146. if (DDEServer.Get_MPlayer_Game_Info()){
  1147. CCDebugString ("C&C95 - About to call Read_Game_Options.\n");
  1148. Read_Game_Options( NULL );
  1149. }else{
  1150. Read_Game_Options( "C&CSPAWN.INI" );
  1151. }
  1152. if (Server){
  1153. CCDebugString ("C&C95 - About to call Server_Remote_Connect.\n");
  1154. if (Server_Remote_Connect()){
  1155. CCDebugString ("C&C95 - Server_Remote_Connect returned success.\n");
  1156. break;
  1157. }else{
  1158. /*
  1159. ** We failed to connect to the other player
  1160. *
  1161. * SEND FAILURE PACKET TO WCHAT HERE !!!!!
  1162. *
  1163. */
  1164. Winsock.Close();
  1165. GameToPlay = GAME_NORMAL;
  1166. selection = SEL_NONE;
  1167. DDEServer.Delete_MPlayer_Game_Info(); // Make sure we dont go round in an infinite loop
  1168. //Special.IsFromWChat = false;
  1169. break;
  1170. }
  1171. }else{
  1172. CCDebugString ("C&C95 - About to call Client_Remote_Connect.\n");
  1173. if (Client_Remote_Connect()){
  1174. CCDebugString ("C&C95 - Client_Remote_Connect returned success.\n");
  1175. break;
  1176. }else{
  1177. /*
  1178. ** We failed to connect to the other player
  1179. *
  1180. * SEND FAILURE PACKET TO WCHAT HERE !!!!!
  1181. *
  1182. */
  1183. Winsock.Close();
  1184. GameToPlay = GAME_NORMAL;
  1185. selection = SEL_NONE;
  1186. DDEServer.Delete_MPlayer_Game_Info(); // Make sure we dont go round in an infinite loop
  1187. //Special.IsFromWChat = false;
  1188. break;
  1189. }
  1190. }
  1191. }else{
  1192. GameToPlay = Select_MPlayer_Game();
  1193. if (GameToPlay == GAME_NORMAL) { // 'Cancel'
  1194. display = true;
  1195. selection = SEL_NONE;
  1196. }
  1197. }
  1198. break;
  1199. #endif //FORCE_WINSOCK
  1200. }
  1201. switch (GameToPlay) {
  1202. /*
  1203. ** Internet, Modem or Null-Modem
  1204. */
  1205. case GAME_MODEM:
  1206. case GAME_NULL_MODEM:
  1207. case GAME_INTERNET:
  1208. Theme.Fade_Out();
  1209. ScenPlayer = SCEN_PLAYER_2PLAYER;
  1210. ScenDir = SCEN_DIR_EAST;
  1211. process = false;
  1212. Options.ScoreVolume = 0;
  1213. break;
  1214. /*
  1215. ** Network (IPX): start a new network game.
  1216. */
  1217. case GAME_IPX:
  1218. /*
  1219. ** Init network system & remote-connect
  1220. */
  1221. if (Init_Network() && Remote_Connect()) {
  1222. #if (0)
  1223. char seed[80];
  1224. sprintf (seed, "Seed: %08x\n", Seed);
  1225. CCDebugString (seed);
  1226. sprintf (seed, "rand: %04x\n", rand());
  1227. CCDebugString (seed);
  1228. sprintf (seed, "rand: %04x\n", rand());
  1229. CCDebugString (seed);
  1230. sprintf (seed, "rand: %04x\n", rand());
  1231. CCDebugString (seed);
  1232. #endif
  1233. Options.ScoreVolume = 0;
  1234. ScenPlayer = SCEN_PLAYER_MPLAYER;
  1235. ScenDir = SCEN_DIR_EAST;
  1236. process = false;
  1237. Theme.Fade_Out();
  1238. } else { // user hit cancel, or init failed
  1239. GameToPlay = GAME_NORMAL;
  1240. display = true;
  1241. selection = SEL_NONE;
  1242. }
  1243. break;
  1244. }
  1245. #endif
  1246. break;
  1247. /*
  1248. ** Play a VQ
  1249. */
  1250. case SEL_INTRO:
  1251. Theme.Fade_Out();
  1252. Theme.Stop();
  1253. Call_Back();
  1254. Force_CD_Available(-1);
  1255. Play_Intro(false);
  1256. Hide_Mouse();
  1257. // verify existance of movie file before playing this sequence.
  1258. if (CCFileClass("TRAILER.VQA").Is_Available()) {
  1259. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1260. VisiblePage.Clear();
  1261. if (CCFileClass("ATTRACT2.CPS").Is_Available()){
  1262. Load_Uncompress(CCFileClass("ATTRACT2.CPS"), SysMemPage, SysMemPage, Palette);
  1263. SysMemPage.Scale(SeenBuff, 0, 0, 0, 0, 320, 199, 640, 398);
  1264. Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
  1265. }
  1266. Clear_KeyBuffer();
  1267. count.Set(TIMER_SECOND*3);
  1268. while (count.Time()) {
  1269. Call_Back();
  1270. }
  1271. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1272. Play_Movie("TRAILER"); // Red Alert teaser.
  1273. }
  1274. if (CCFileClass("SIZZLE.VQA").Is_Available()) {
  1275. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1276. VisiblePage.Clear();
  1277. if (CCFileClass("ATTRACT2.CPS").Is_Available()){
  1278. Load_Uncompress(CCFileClass("ATTRACT2.CPS"), SysMemPage, SysMemPage, Palette);
  1279. SysMemPage.Scale(SeenBuff, 0, 0, 0, 0, 320, 199, 640, 398);
  1280. Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
  1281. }
  1282. Clear_KeyBuffer();
  1283. count.Set(TIMER_SECOND*3);
  1284. while (count.Time()) {
  1285. Call_Back();
  1286. }
  1287. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1288. Play_Movie("SIZZLE"); // Red Alert teaser.
  1289. }
  1290. if (CCFileClass("SIZZLE2.VQA").Is_Available()) {
  1291. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1292. VisiblePage.Clear();
  1293. if (CCFileClass("ATTRACT2.CPS").Is_Available()){
  1294. Load_Uncompress(CCFileClass("ATTRACT2.CPS"), SysMemPage, SysMemPage, Palette);
  1295. SysMemPage.Scale(SeenBuff, 0, 0, 0, 0, 320, 199, 640, 398);
  1296. Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
  1297. }
  1298. Clear_KeyBuffer();
  1299. count.Set(TIMER_SECOND*3);
  1300. while (count.Time()) {
  1301. Call_Back();
  1302. }
  1303. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1304. Play_Movie("SIZZLE2"); // Red Alert teaser.
  1305. }
  1306. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1307. VisiblePage.Clear();
  1308. if (CCFileClass("ATTRACT2.CPS").Is_Available()){
  1309. Load_Uncompress(CCFileClass("ATTRACT2.CPS"), SysMemPage, SysMemPage, Palette);
  1310. SysMemPage.Scale(SeenBuff, 0, 0, 0, 0, 320, 199, 640, 398);
  1311. Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
  1312. }
  1313. Clear_KeyBuffer();
  1314. count.Set(TIMER_SECOND*3);
  1315. while (count.Time()) {
  1316. Call_Back();
  1317. }
  1318. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1319. Play_Movie("CC2TEASE");
  1320. Show_Mouse();
  1321. ScenarioInit++;
  1322. Theme.Play_Song (THEME_MAP1);
  1323. ScenarioInit--;
  1324. display = true;
  1325. fade = true;
  1326. selection = SEL_NONE;
  1327. break;
  1328. /*
  1329. ** Exit to DOS.
  1330. */
  1331. case SEL_EXIT:
  1332. #ifdef JAPANESE
  1333. Hide_Mouse();
  1334. #endif
  1335. Theme.Fade_Out();
  1336. Fade_Palette_To(BlackPalette, FADE_PALETTE_SLOW, NULL);
  1337. #ifdef JAPANESE
  1338. VisiblePage.Clear();
  1339. #endif
  1340. return(false);
  1341. /*
  1342. ** Display the hall of fame.
  1343. */
  1344. case SEL_FAME:
  1345. break;
  1346. case SEL_TIMEOUT:
  1347. if (AllowAttract && RecordFile.Is_Available()) {
  1348. PlaybackGame = true;
  1349. if (RecordFile.Open(READ)) {
  1350. Load_Recording_Values();
  1351. process = false;
  1352. Theme.Fade_Out();
  1353. } else {
  1354. PlaybackGame = false;
  1355. selection = SEL_NONE;
  1356. }
  1357. } else {
  1358. selection = SEL_NONE;
  1359. }
  1360. break;
  1361. default:
  1362. break;
  1363. }
  1364. }
  1365. } else {
  1366. /*
  1367. ** For Debug_Map (editor) mode, if JP option is on, set to load that scenario
  1368. */
  1369. Scenario = 1;
  1370. if (Special.IsJurassic && AreThingiesEnabled) {
  1371. ScenPlayer = SCEN_PLAYER_JP;
  1372. ScenDir = SCEN_DIR_EAST;
  1373. }
  1374. }
  1375. CCDebugString ("C&C95 - About to start game initialisation.\n");
  1376. #ifdef FORCE_WINSOCK
  1377. if (GameToPlay == GAME_INTERNET){
  1378. CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;
  1379. if (!Special.IsFromWChat){
  1380. FrameSendRate = 5; //3;
  1381. }
  1382. }
  1383. #endif //FORCE_WINSOCK
  1384. /*
  1385. ** Don't carry stray keystrokes into game.
  1386. */
  1387. Kbd.Clear();
  1388. /*
  1389. ** Get a pointer to the compiler's random number seed.
  1390. ** the Get_EAX() must follow immediately after the srand(0) in order to save
  1391. ** the address of the random seed. (Currently not used.)
  1392. */
  1393. srand(0);
  1394. //RandSeedPtr = (long *)Get_EAX(); // ST - 1/2/2019 5:26PM
  1395. /*
  1396. ** Initialize the random number Seed. For multiplayer, this will have been done
  1397. ** in the connection dialogs. For single-player games, AND if we're not playing
  1398. ** back a recording, init the Seed to a random value.
  1399. */
  1400. if (GameToPlay == GAME_NORMAL && !PlaybackGame) {
  1401. srand(timeGetTime());
  1402. //randomize();
  1403. Seed = rand();
  1404. }
  1405. /*
  1406. ** If user has specified a desired random number seed, use it for multiplayer games
  1407. */
  1408. if (CustomSeed != 0) {
  1409. Seed = CustomSeed;
  1410. }
  1411. /*
  1412. ** Save initialization values if we're recording this game.
  1413. ** This must be done after 'Seed' has been initialized.
  1414. */
  1415. if (RecordGame) {
  1416. if (RecordFile.Open(WRITE)) {
  1417. Save_Recording_Values();
  1418. } else {
  1419. RecordGame = false;
  1420. }
  1421. }
  1422. /*
  1423. ** Initialize the random-number generator.
  1424. */
  1425. //Seed = 1;
  1426. srand(Seed);
  1427. RandNumb = Seed;
  1428. SimRandIndex = 0;
  1429. #if (0)
  1430. DWORD actual;
  1431. HANDLE sfile = CreateFile("random.txt", GENERIC_WRITE, 0,
  1432. NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1433. if (sfile != INVALID_HANDLE_VALUE){
  1434. SetFilePointer (sfile, 0, NULL, FILE_END);
  1435. int minimum;
  1436. int maximum;
  1437. char whatever[80];
  1438. for ( int i=0 ; i<1000 ; i++){
  1439. minimum = rand();
  1440. maximum = rand();
  1441. sprintf (whatever, "%04x\n", Random_Pick(minimum, maximum));
  1442. WriteFile(sfile, whatever, strlen(whatever), &actual, NULL);
  1443. }
  1444. CloseHandle (sfile);
  1445. }
  1446. #endif
  1447. /*
  1448. ** Load the scenario. Specify variation 'A' for the editor; for the game,
  1449. ** don't specify a variation, to make 'Set_Scenario_Name()' pick a random one.
  1450. ** Skip this if we've already loaded a save-game.
  1451. */
  1452. if (!gameloaded) {
  1453. if (Debug_Map) {
  1454. Set_Scenario_Name(ScenarioName, Scenario, ScenPlayer, ScenDir, SCEN_VAR_A);
  1455. } else {
  1456. Set_Scenario_Name(ScenarioName, Scenario, ScenPlayer, ScenDir);
  1457. }
  1458. /*
  1459. ** Start_Scenario() changes the palette; so, fade out & clear the screen
  1460. ** before calling it.
  1461. */
  1462. Hide_Mouse();
  1463. if (selection != SEL_START_NEW_GAME) {
  1464. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1465. HiddenPage.Clear();
  1466. VisiblePage.Clear();
  1467. }
  1468. Show_Mouse();
  1469. Special.IsFromInstall = 0;
  1470. CCDebugString ("C&C95 - Starting scenario.\n");
  1471. if (!Start_Scenario(ScenarioName)) {
  1472. return(false);
  1473. }
  1474. CCDebugString ("C&C95 - Scenario started OK.\n");
  1475. }
  1476. /*
  1477. ** For multiplayer games, initialize the inter-player message system.
  1478. ** Do this after loading the scenario, so the map's upper-left corner is
  1479. ** properly set.
  1480. */
  1481. CCDebugString ("C&C95 - Initialising message system.\n");
  1482. int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
  1483. Messages.Init(Map.TacPixelX, Map.TacPixelY, 6, MAX_MESSAGE_LENGTH, 6*factor+1);
  1484. /*
  1485. ** Hide the SeenBuff; force the map to render one frame. The caller can
  1486. ** then fade the palette in.
  1487. ** (If we loaded a game, this step will fade out the title screen. If we
  1488. ** started a scenario, Start_Scenario() will have played a couple of VQ
  1489. ** movies, which will have cleared the screen to black already.)
  1490. */
  1491. CCDebugString ("C&C95 - About to call Call_Back.\n");
  1492. Call_Back();
  1493. /*
  1494. ** This is desperately sad isnt it?
  1495. */
  1496. Hide_Mouse();
  1497. Hide_Mouse();
  1498. Hide_Mouse();
  1499. Hide_Mouse();
  1500. WWMouse->Erase_Mouse(&HidPage, TRUE);
  1501. Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1502. HiddenPage.Clear();
  1503. VisiblePage.Clear();
  1504. Set_Logic_Page(SeenBuff);
  1505. Map.Flag_To_Redraw();
  1506. Call_Back();
  1507. Map.Render();
  1508. //Show_Mouse();
  1509. /*
  1510. ** Special hack initialization of 'MPlayerMaxAhead' to accommodate the
  1511. ** compression protocol technology.
  1512. */
  1513. #ifdef FORCE_WINSOCK
  1514. if (CommProtocol==COMM_PROTOCOL_MULTI_E_COMP && GameToPlay!=GAME_NORMAL) {
  1515. if (!Special.IsFromWChat){
  1516. MPlayerMaxAhead = FrameSendRate * 3; //2;
  1517. }else{
  1518. MPlayerMaxAhead = WChatMaxAhead;
  1519. FrameSendRate = WChatSendRate;
  1520. }
  1521. }
  1522. #endif //FORCE_WINSOCK
  1523. if (Debug_Map) {
  1524. while (Get_Mouse_State() > 1) {
  1525. Show_Mouse();
  1526. }
  1527. }
  1528. return(true);
  1529. }
  1530. /***********************************************************************************************
  1531. * Play_Intro -- plays the introduction & logo movies *
  1532. * *
  1533. * INPUT: *
  1534. * for_real if true, this function plays the "real" intro; otherwise, it plays *
  1535. * a delicious smorgasbord of visual delights, guaranteed to titillate *
  1536. * the ocular & auditory nerve pathways. *
  1537. * Well, it plays movies, anyway. *
  1538. * *
  1539. * OUTPUT: *
  1540. * none. *
  1541. * *
  1542. * WARNINGS: *
  1543. * none. *
  1544. * *
  1545. * HISTORY: *
  1546. * 06/06/1995 BRR : Created. *
  1547. *=============================================================================================*/
  1548. static void Play_Intro(bool for_real)
  1549. {
  1550. return; // No game intro movies. - LLL
  1551. bool playright = !Key_Down(KN_LCTRL) || !Key_Down(KN_RCTRL);
  1552. static int _counter = -1;
  1553. static char * _names[] = {
  1554. #ifdef DEMO
  1555. "LOGO",
  1556. #else
  1557. "INTRO2",
  1558. //#ifdef CHEAT_KEYS
  1559. "GDIEND1",
  1560. "GDIEND2",
  1561. "GDIFINA",
  1562. "GDIFINB",
  1563. "AIRSTRK",
  1564. "AKIRA",
  1565. "BANNER",
  1566. "BCANYON",
  1567. "BKGROUND",
  1568. "BOMBAWAY",
  1569. "BOMBFLEE",
  1570. "BURDET1",
  1571. "BURDET2",
  1572. "CC2TEASE",
  1573. "CONSYARD",
  1574. "DESFLEES",
  1575. "DESKILL",
  1576. "DESOLAT",
  1577. "DESSWEEP",
  1578. "FLAG",
  1579. "FLYY",
  1580. "FORESTKL",
  1581. "GAMEOVER",
  1582. "GDI1",
  1583. "GDI10",
  1584. "GDI11",
  1585. "GDI12",
  1586. "GDI13",
  1587. "GDI14",
  1588. "GDI15",
  1589. "GDI2",
  1590. "GDI3",
  1591. "GDI3LOSE",
  1592. "GDI4A",
  1593. "GDI4B",
  1594. "GDI5",
  1595. "GDI6",
  1596. "GDI7",
  1597. "GDI8A",
  1598. "GDI8B",
  1599. "GDI9",
  1600. "GDILOSE",
  1601. "GUNBOAT",
  1602. "HELLVALY",
  1603. "INSITES",
  1604. "KANEPRE",
  1605. "LANDING",
  1606. "LOGO",
  1607. "NAPALM",
  1608. "NITEJUMP",
  1609. "NOD1",
  1610. "NOD10A",
  1611. "NOD10B",
  1612. "NOD11",
  1613. "NOD12",
  1614. "NOD13",
  1615. "NOD1PRE",
  1616. "NOD2",
  1617. "NOD3",
  1618. "NOD4A",
  1619. "NOD4B",
  1620. "NOD5",
  1621. "NOD6",
  1622. "NOD7A",
  1623. "NOD7B",
  1624. "NOD8",
  1625. "NOD9",
  1626. "NODEND1",
  1627. "NODEND2",
  1628. "NODEND3",
  1629. "NODEND4",
  1630. "NODFINAL",
  1631. "NODFLEES",
  1632. "NODLOSE",
  1633. "NODSWEEP",
  1634. "NUKE",
  1635. "OBEL",
  1636. "PARATROP",
  1637. "PINTLE",
  1638. "PLANECRA",
  1639. "PODIUM",
  1640. "REFINT",
  1641. "RETRO",
  1642. "SABOTAGE",
  1643. "SAMDIE",
  1644. "SAMSITE",
  1645. "SEIGE",
  1646. "SETHPRE",
  1647. "SPYCRASH",
  1648. "STEALTH",
  1649. "SUNDIAL",
  1650. "TANKGO",
  1651. "TANKKILL",
  1652. "TBRINFO1",
  1653. "TBRINFO2",
  1654. "TBRINFO3",
  1655. "TIBERFX",
  1656. "TRTKIL_D",
  1657. "TURTKILL",
  1658. "VISOR",
  1659. //#endif
  1660. #endif
  1661. NULL
  1662. };
  1663. Keyboard::Clear();
  1664. if (for_real) {
  1665. Hide_Mouse();
  1666. Play_Movie("LOGO", THEME_NONE, false);
  1667. Show_Mouse();
  1668. } else {
  1669. if (!Debug_Flag) {
  1670. _counter = 0;
  1671. } else {
  1672. if (playright) _counter++;
  1673. if (_counter == -1) _counter = 0;
  1674. }
  1675. Hide_Mouse();
  1676. Play_Movie(_names[_counter], THEME_NONE);
  1677. Show_Mouse();
  1678. if (!_names[_counter]) {
  1679. _counter = -1;
  1680. }
  1681. }
  1682. }
  1683. /***********************************************************************************************
  1684. * Anim_Init -- Initialize the VQ animation control structure. *
  1685. * *
  1686. * VQ animations are controlled by a structure passed to the VQ player. This routine *
  1687. * initializes the structure to values required by C&C. *
  1688. * *
  1689. * INPUT: none *
  1690. * *
  1691. * OUTPUT: none *
  1692. * *
  1693. * WARNINGS: Only need to call this routine once at the beginning of the game. *
  1694. * *
  1695. * HISTORY: *
  1696. * 12/20/1994 JLB : Created. *
  1697. *=============================================================================================*/
  1698. //extern LPDIRECTSOUND SoundObject;
  1699. //extern LPDIRECTSOUNDBUFFER PrimaryBufferPtr;
  1700. void Anim_Init(void)
  1701. {
  1702. //PG_TO_FIX
  1703. #if (0)
  1704. /* Configure player with INI file */
  1705. VQA_DefaultConfig(&AnimControl);
  1706. // void const * font = Load_Font(FONT8);
  1707. // AnimControl.EVAFont = (char *)font;
  1708. // AnimControl.CapFont = (char *)font;
  1709. AnimControl.DrawFlags = VQACFGF_TOPLEFT;
  1710. AnimControl.DrawFlags |= VQACFGF_BUFFER;
  1711. AnimControl.DrawFlags |= VQACFGF_NOSKIP;
  1712. //AnimControl.X1 =0;
  1713. //AnimControl.Y1 =0;
  1714. AnimControl.FrameRate = -1;
  1715. AnimControl.DrawRate = -1;
  1716. AnimControl.DrawerCallback = VQ_Call_Back;
  1717. AnimControl.ImageWidth = 320;
  1718. AnimControl.ImageHeight = 200;
  1719. AnimControl.Vmode = 0;
  1720. AnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();
  1721. //AnimControl.VBIBit = VertBlank;
  1722. //AnimControl.DrawFlags |= VQACFGF_TOPLEFT;
  1723. AnimControl.OptionFlags |= VQAOPTF_CAPTIONS|VQAOPTF_EVA;
  1724. if (SlowPalette) {
  1725. AnimControl.OptionFlags |= VQAOPTF_SLOWPAL;
  1726. }
  1727. #endif
  1728. // AnimControl.AudioBuf = (unsigned char *)HidPage.Get_Buffer();
  1729. // AnimControl.AudioBufSize = 32768U;
  1730. //AnimControl.DigiCard = NewConfig.DigitCard;
  1731. //AnimControl.HMIBufSize = 8192;
  1732. //AnimControl.DigiHandle = Get_Digi_Handle();
  1733. //AnimControl.Volume = 0x00FF;
  1734. //AnimControl.AudioRate = 22050;
  1735. // if (NewConfig.Speed) AnimControl.AudioRate = 11025;
  1736. //PG_TO_FIX
  1737. #if (0)
  1738. AnimControl.SoundObject = SoundObject; //Get_Sound_Object();
  1739. AnimControl.PrimaryBufferPtr = PrimaryBufferPtr; //Get_Primart_Buffer();
  1740. #endif
  1741. //if (!Debug_Quiet && Get_Digi_Handle() != -1) {
  1742. //AnimControl.OptionFlags |= VQAOPTF_AUDIO;
  1743. //}
  1744. #if (0)
  1745. if (MonoClass::Is_Enabled()) {
  1746. AnimControl.OptionFlags |= VQAOPTF_MONO;
  1747. }
  1748. #endif
  1749. }
  1750. /***********************************************************************************************
  1751. * Parse_Command_Line -- Parses the command line parameters. *
  1752. * *
  1753. * This routine should be called before the graphic mode is initialized. It examines the *
  1754. * command line parameters and sets the appropriate globals. If there is an error, then *
  1755. * it outputs a command summary and then returns false. *
  1756. * *
  1757. * INPUT: argc -- The number of command line arguments. *
  1758. * *
  1759. * argv -- Pointer to character string array that holds the individual arguments. *
  1760. * *
  1761. * OUTPUT: bool; Was the command line parsed successfully? *
  1762. * *
  1763. * WARNINGS: none *
  1764. * *
  1765. * HISTORY: *
  1766. * 03/18/1995 JLB : Created. *
  1767. *=============================================================================================*/
  1768. bool Parse_Command_Line(int argc, char *argv[])
  1769. {
  1770. /*
  1771. ** Parse the command line and set globals to reflect the parameters
  1772. ** passed in.
  1773. */
  1774. #ifdef DEMO
  1775. Scenario = 3;
  1776. #else
  1777. Scenario = 1;
  1778. #endif
  1779. ScenPlayer = SCEN_PLAYER_GDI;
  1780. ScenDir = SCEN_DIR_EAST;
  1781. Whom = HOUSE_GOOD;
  1782. Special.Init();
  1783. Debug_Map = false;
  1784. // Debug_Play_Map = false;
  1785. Debug_Unshroud = false;
  1786. for (int index = 1; index < argc; index++) {
  1787. char * string; // Pointer to argument.
  1788. long code = 0;
  1789. char arg_string[512];
  1790. int str_len = strlen(argv[index]);
  1791. char *src = argv[index];
  1792. char *dest = arg_string;
  1793. for (int i=0 ; i<str_len ; i++) {
  1794. if (*src == '\"') {
  1795. src++;
  1796. } else {
  1797. *dest++ = *src++;
  1798. }
  1799. }
  1800. *dest++ = 0;
  1801. string = arg_string;
  1802. strupr(string);
  1803. //string = strupr(argv[index]);
  1804. /*
  1805. ** Print usage text only if requested.
  1806. */
  1807. if (stricmp("/?", string) == 0 || stricmp("-?", string) == 0 || stricmp("-h", string) == 0 || stricmp("/h", string) == 0) {
  1808. /*
  1809. ** Unrecognized command line parameter... Display usage
  1810. ** and then exit.
  1811. */
  1812. #ifdef GERMAN
  1813. puts("Command & Conquer (c) 1995,1996 Westwood Studios\r\n"
  1814. "Parameter:\r\n"
  1815. // " -CD<Pfad> = Suchpfad f�r Daten-Dateien festlegen.\r\n"
  1816. " -DESTNET = Netzwerkkennung des Zielrechners festlegen\r\n"
  1817. " (Syntax: DESTNETxx.xx.xx.xx)\r\n"
  1818. " -SOCKET = Kennung des Netzwerk-Sockets (0 - 16383)\n"
  1819. " -STEALTH = Namen im Mehrspieler-Modus verstecken (\"Boss-Modus\")\r\n"
  1820. " -MESSAGES = Mitteilungen von auáerhalb des Spiels zulassen\r\n"
  1821. // " -ELITE = Fortgeschrittene KI und Gefechtstechniken.\r\n"
  1822. "\r\n");
  1823. #else
  1824. #ifdef FRENCH
  1825. puts("Command & Conquer (c) 1995, Westwood Studios\r\n"
  1826. "ParamŠtres:\r\n"
  1827. // " -CD<chemin d'accŠs> = Recherche des fichiers dans le\r\n"
  1828. // " r‚pertoire indiqu‚.\r\n"
  1829. " -DESTNET = Sp‚cifier le num‚ro de r‚seau du systŠme de destination\r\n"
  1830. " (Syntaxe: DESTNETxx.xx.xx.xx)\r\n"
  1831. " -SOCKET = ID poste r‚seau (0 … 16383)\r\n"
  1832. " -STEALTH = Cacher les noms en mode multijoueurs (\"Mode Boss\")\r\n"
  1833. " -MESSAGES = Autorise les messages ext‚rieurs … ce jeu.\r\n"
  1834. "\r\n");
  1835. #else
  1836. puts("Command & Conquer (c) 1995, 1996 Westwood Studios\r\n"
  1837. "Parameters:\r\n"
  1838. #ifdef NEVER
  1839. " CHEAT = Enable debug keys.\r\n"
  1840. " -EDITOR = Enable scenario editor.\r\n"
  1841. #endif
  1842. // " -CD<path> = Set search path for data files.\r\n"
  1843. " -DESTNET = Specify Network Number of destination system\r\n"
  1844. " (Syntax: DESTNETxx.xx.xx.xx)\r\n"
  1845. " -SOCKET = Network Socket ID (0 - 16383)\n"
  1846. " -STEALTH = Hide multiplayer names (\"Boss mode\")\r\n"
  1847. " -MESSAGES = Allow messages from outside this game.\r\n"
  1848. " -o = Enable compatability with version 1.07.\r\n"
  1849. #ifdef JAPANESE
  1850. " -ENGLISH = Enable English keyboard compatibility.\r\n"
  1851. #endif
  1852. // " -ELITE = Advanced AI and combat characteristics.\r\n"
  1853. #ifdef NEVER
  1854. " -O[options]= Special control options;\r\n"
  1855. " 1 : Tiberium grows.\r\n"
  1856. " 2 : Tiberium grows and spreads.\r\n"
  1857. " A : Aggressive player unit defense enabled.\r\n"
  1858. " B : Bargraphs always displayed.\r\n"
  1859. " C : Capture the flag mode.\r\n"
  1860. " E : Elite defense mode disable (attacker advantage).\r\n"
  1861. " D : Deploy reversal allowed for construction yard.\r\n"
  1862. " F : Fleeing from direct immediate threats is enabled.\r\n"
  1863. " H : Hussled recharge time.\r\n"
  1864. " G : Growth for Tiberium slowed in multiplay.\r\n"
  1865. " I : Inert weapons -- no damage occurs.\r\n"
  1866. " J : 7th grade sound effects.\r\n"
  1867. " M : Monochrome debug messages.\r\n"
  1868. " N : Name the civilians and buildings.\r\n"
  1869. " P : Path algorithm displayed as it works.\r\n"
  1870. " Q : Quiet mode (no sound).\r\n"
  1871. " R : Road pieces are not added to buildings.\r\n"
  1872. " T : Three point turns for wheeled vehicles.\r\n"
  1873. " U : U can target and burn trees.\r\n"
  1874. " V : Show target selection by opponent.\r\n"
  1875. " X : Make a recording of a multiplayer game.\r\n"
  1876. " Y : Play a recording of a multiplayer game.\r\n"
  1877. " Z : Disaster containment team.\r\n"
  1878. #endif
  1879. "\r\n");
  1880. #endif
  1881. #endif
  1882. return(false);
  1883. }
  1884. bool processed = true;
  1885. switch (Obfuscate(string)) {
  1886. /*
  1887. ** Signal that easy mode is active.
  1888. */
  1889. case PARM_EASY:
  1890. Special.IsEasy = true;
  1891. Special.IsDifficult = false;
  1892. break;
  1893. /*
  1894. ** Signal that hard mode is active.
  1895. */
  1896. case PARM_HARD:
  1897. Special.IsEasy = false;
  1898. Special.IsDifficult = true;
  1899. break;
  1900. #ifdef VIRGIN_CHEAT_KEYS
  1901. case PARM_PLAYTEST:
  1902. Debug_Playtest = true;
  1903. break;
  1904. #endif
  1905. #ifdef PARM_CHEATERIK
  1906. case PARM_CHEATERIK:
  1907. Debug_Playtest = true;
  1908. Debug_Flag = true;
  1909. break;
  1910. #endif
  1911. #ifdef PARM_CHEATADAM
  1912. case PARM_CHEATADAM:
  1913. Debug_Playtest = true;
  1914. Debug_Flag = true;
  1915. break;
  1916. #endif
  1917. #ifdef PARM_CHEATMIKE
  1918. case PARM_CHEATMIKE:
  1919. Debug_Playtest = true;
  1920. Debug_Flag = true;
  1921. break;
  1922. #endif
  1923. #ifdef PARM_CHEATDAVID
  1924. case PARM_CHEATDAVID:
  1925. Debug_Playtest = true;
  1926. Debug_Flag = true;
  1927. break;
  1928. #endif
  1929. #ifdef PARM_CHEATPHIL
  1930. case PARM_CHEATPHIL:
  1931. Debug_Playtest = true;
  1932. Debug_Flag = true;
  1933. break;
  1934. #endif
  1935. #ifdef PARM_CHEATBILL
  1936. case PARM_CHEATBILL:
  1937. Debug_Playtest = true;
  1938. Debug_Flag = true;
  1939. break;
  1940. #endif
  1941. #ifdef PARM_CHEAT_STEVET
  1942. case PARM_CHEAT_STEVET:
  1943. Debug_Playtest = true;
  1944. Debug_Flag = true;
  1945. break;
  1946. #endif
  1947. #ifdef PARM_EDITORBILL
  1948. case PARM_EDITORBILL:
  1949. Debug_Map = true;
  1950. Debug_Unshroud = true;
  1951. Debug_Flag = true;
  1952. break;
  1953. #endif
  1954. #ifdef PARM_EDITORERIK
  1955. case PARM_EDITORERIK:
  1956. Debug_Map = true;
  1957. Debug_Unshroud = true;
  1958. Debug_Flag = true;
  1959. break;
  1960. #endif
  1961. case PARM_SPECIAL:
  1962. Special.IsJurassic = true;
  1963. AreThingiesEnabled = true;
  1964. break;
  1965. /*
  1966. ** Special flag - is C&C being run from the install program?
  1967. */
  1968. case PARM_INSTALL:
  1969. #ifndef DEMO
  1970. Special.IsFromInstall = true;
  1971. #endif
  1972. break;
  1973. default:
  1974. processed = false;
  1975. break;
  1976. }
  1977. if (processed) continue;
  1978. #ifdef CHEAT_KEYS
  1979. /*
  1980. ** Scenario Editor Mode
  1981. */
  1982. if (stricmp(string, "-CHECKMAP") == 0) {
  1983. Debug_Check_Map = true;
  1984. continue;
  1985. }
  1986. #endif
  1987. /*
  1988. ** Older version override.
  1989. */
  1990. if (stricmp(string, "-O") == 0 || stricmp(string, "-0") == 0) {
  1991. IsV107 = true;
  1992. continue;
  1993. }
  1994. /*
  1995. ** File search path override.
  1996. */
  1997. if (strstr(string, "-CD")) {
  1998. CCFileClass::Set_Search_Drives(&string[3]);
  1999. continue;
  2000. }
  2001. #ifdef JAPANESE
  2002. /*
  2003. ** Enable english-compatible keyboard
  2004. */
  2005. if (!stricmp(string,"-ENGLISH")) {
  2006. ForceEnglish = true;
  2007. continue;
  2008. }
  2009. #endif
  2010. /*
  2011. ** Specify destination connection for network play
  2012. */
  2013. if (strstr(string, "-DESTNET")) {
  2014. NetNumType net;
  2015. NetNodeType node;
  2016. /*
  2017. ** Scan the command-line string, pulling off each address piece
  2018. */
  2019. int i = 0;
  2020. char * p = strtok(string + 8,".");
  2021. while (p) {
  2022. int x;
  2023. sscanf(p,"%x",&x); // convert from hex string to int
  2024. if (i < 4) {
  2025. net[i] = (char)x; // fill NetNum
  2026. } else {
  2027. node[i-4] = (char)x; // fill NetNode
  2028. }
  2029. i++;
  2030. p = strtok(NULL,".");
  2031. }
  2032. /*
  2033. ** If all the address components were successfully read, fill in the
  2034. ** BridgeNet with a broadcast address to the network across the bridge.
  2035. */
  2036. if (i >= 4) {
  2037. IsBridge = 1;
  2038. memset(node, 0xff, 6);
  2039. BridgeNet = IPXAddressClass(net, node);
  2040. }
  2041. continue;
  2042. }
  2043. /*
  2044. ** Specify socket ID, as an offset from 0x4000.
  2045. */
  2046. if (strstr(string, "-SOCKET")) {
  2047. unsigned short socket;
  2048. socket = (unsigned short)(atoi(string + strlen("SOCKET")));
  2049. socket += 0x4000;
  2050. if (socket >= 0x4000 && socket < 0x8000) {
  2051. Ipx.Set_Socket (socket);
  2052. }
  2053. continue;
  2054. }
  2055. /*
  2056. ** Set the Net Stealth option
  2057. */
  2058. if (strstr(string, "-STEALTH")) {
  2059. NetStealth = true;
  2060. continue;
  2061. }
  2062. /*
  2063. ** Set the Net Protection option
  2064. */
  2065. if (strstr(string, "-MESSAGES")) {
  2066. NetProtect = false;
  2067. continue;
  2068. }
  2069. /*
  2070. ** Allow "attract" mode
  2071. */
  2072. if (strstr(string, "-ATTRACT")) {
  2073. AllowAttract = true;
  2074. continue;
  2075. }
  2076. /*
  2077. ** Set screen to 640x480 instead of 640x400
  2078. */
  2079. if (strstr(string,"-480")){
  2080. ScreenHeight = 480;
  2081. continue;
  2082. }
  2083. /*
  2084. ** Check for spawn from WChat
  2085. */
  2086. if (strstr(string,"-WCHAT")){
  2087. SpawnedFromWChat = true;
  2088. }
  2089. /*
  2090. ** Allow use of MMX instructions
  2091. */
  2092. if (strstr(string,"-MMX")){
  2093. MMXAvailable = true;
  2094. continue;
  2095. }
  2096. #ifdef CHEAT_KEYS
  2097. /*
  2098. ** Allow solo net play
  2099. */
  2100. if (stricmp(string, "-HANSOLO") == 0) {
  2101. MPlayerSolo = true;
  2102. continue;
  2103. }
  2104. /*
  2105. ** Specify the random number seed (for debugging)
  2106. */
  2107. if (strstr(string, "-SEED")) {
  2108. CustomSeed = (unsigned short)(atoi(string + strlen("SEED")));
  2109. continue;
  2110. }
  2111. #endif
  2112. #ifdef NEVER
  2113. /*
  2114. ** Handle the prog init differently in this case.
  2115. */
  2116. if (strstr(string, "-V")) {
  2117. continue;
  2118. }
  2119. #endif
  2120. #ifdef FIX_ME_LATER
  2121. /*
  2122. ** look for passed-in video mode to default to
  2123. */
  2124. if (strnicmp(string, "-V", strlen("-V")) == 0) {
  2125. Set_Video_Mode(MCGA_MODE); // do this to get around first_time variable...
  2126. Set_Original_Video_Mode(atoi(string+2));
  2127. continue;
  2128. }
  2129. #endif //FIX_ME_LATER
  2130. /*
  2131. ** Special command line control parsing.
  2132. */
  2133. if (strnicmp(string, "-X", strlen("-O")) == 0) {
  2134. string += strlen("-X");
  2135. while (*string) {
  2136. char code = *string++;
  2137. switch (toupper(code)) {
  2138. #ifdef ONHOLD
  2139. /*
  2140. ** Should human generated sound effects be used?
  2141. */
  2142. case 'J':
  2143. Special.IsJuvenile = true;
  2144. break;
  2145. #endif
  2146. #ifdef CHEAT_KEYS
  2147. /*
  2148. ** Monochrome debug screen enable.
  2149. */
  2150. case 'M':
  2151. Special.IsMonoEnabled = true;
  2152. break;
  2153. /*
  2154. ** Inert weapons -- no units take damage.
  2155. */
  2156. case 'I':
  2157. Special.IsInert = true;
  2158. break;
  2159. #endif
  2160. #ifdef CHEAT_KEYS
  2161. /*
  2162. ** Hussled recharge timer.
  2163. */
  2164. case 'H':
  2165. Special.IsSpeedBuild = true;
  2166. break;
  2167. /*
  2168. ** Turn on super-record mode, which thrashes your disk terribly,
  2169. ** but is really really cool. Well, sometimes it is, anyway.
  2170. ** At least, it can be. Once in a while.
  2171. ** This flag tells the recording system to re-open the file for
  2172. ** each write, so the recording survives a crash.
  2173. */
  2174. case 'S':
  2175. SuperRecord = 1;
  2176. break;
  2177. /*
  2178. ** "Record" a multi-player game
  2179. */
  2180. case 'X':
  2181. RecordGame = 1;
  2182. break;
  2183. /*
  2184. ** "Play Back" a multi-player game
  2185. */
  2186. case 'Y':
  2187. PlaybackGame = 1;
  2188. break;
  2189. #endif
  2190. #ifdef ONHOLD
  2191. /*
  2192. ** Bonus scenario enable.
  2193. */
  2194. case 'Z':
  2195. Special.IsJurassic = true;
  2196. break;
  2197. #endif
  2198. /*
  2199. ** Quiet mode override control.
  2200. */
  2201. case 'Q':
  2202. Debug_Quiet = true;
  2203. break;
  2204. #ifdef CHEAT_KEYS
  2205. /*
  2206. ** Target selection by human opponent (network/modem play) will
  2207. ** be visible to the player?
  2208. */
  2209. case 'V':
  2210. Special.IsVisibleTarget = true;
  2211. break;
  2212. #endif
  2213. default:
  2214. #ifdef GERMAN
  2215. puts("Ung�ltiger Parameter.\n");
  2216. #else
  2217. #ifdef FRENCH
  2218. puts("Commande d'option invalide.\n");
  2219. #else
  2220. puts("Invalid option switch.\n");
  2221. #endif
  2222. #endif
  2223. return(false);
  2224. }
  2225. }
  2226. if (Special.IsMonoEnabled) {
  2227. MonoClass::Enable();
  2228. }
  2229. continue;
  2230. }
  2231. }
  2232. return(true);
  2233. }
  2234. #ifdef ONHOLD
  2235. /***********************************************************************************************
  2236. * Parse_INI_File -- Parses CONQUER.INI for certain options *
  2237. * *
  2238. * INPUT: *
  2239. * none. *
  2240. * *
  2241. * OUTPUT: *
  2242. * none. *
  2243. * *
  2244. * WARNINGS: *
  2245. * none. *
  2246. * *
  2247. * HISTORY: *
  2248. * 08/18/1995 BRR : Created. *
  2249. *=============================================================================================*/
  2250. void Parse_INI_File(void)
  2251. {
  2252. char *buffer; // INI staging buffer pointer.
  2253. char buf[128];
  2254. static char section[40];
  2255. static char entry[40];
  2256. static char name[40];
  2257. int len;
  2258. int i;
  2259. /*
  2260. ** These arrays store the coded version of the names Geologic, Period, & Jurassic.
  2261. ** Decode them by subtracting 83. For you curious types, the names look like:
  2262. ** š¸Â¿Âº¼¶
  2263. ** £¸Å¼Â·
  2264. ** �ÈÅ´ÆÆ¼¶
  2265. ** If these INI entries aren't found, the IsJurassic flag does nothing.
  2266. */
  2267. static char coded_section[] = {154,184,194,191,194,186,188,182,0};
  2268. static char coded_entry[] = {163,184,197,188,194,183,0};
  2269. static char coded_name[] = {157,200,197,180,198,198,188,182,0};
  2270. /*------------------------------------------------------------------------
  2271. Fetch working pointer to the INI staging buffer. Make sure that the buffer
  2272. is cleared out before proceeding.
  2273. ------------------------------------------------------------------------*/
  2274. buffer = (char *)_ShapeBuffer;
  2275. memset(buffer, '\0', _ShapeBufferSize);
  2276. /*------------------------------------------------------------------------
  2277. Decode the desired section, entry, & name
  2278. ------------------------------------------------------------------------*/
  2279. strcpy (section,coded_section);
  2280. len = strlen(coded_section);
  2281. for (i = 0; i < len; i++) {
  2282. section[i] -= 83;
  2283. }
  2284. strcpy (entry,coded_entry);
  2285. len = strlen(coded_entry);
  2286. for (i = 0; i < len; i++) {
  2287. entry[i] -= 83;
  2288. }
  2289. strcpy (name,coded_name);
  2290. len = strlen(coded_name);
  2291. for (i = 0; i < len; i++) {
  2292. name[i] -= 83;
  2293. }
  2294. /*------------------------------------------------------------------------
  2295. Create filename and read the file.
  2296. ------------------------------------------------------------------------*/
  2297. CCFileClass file ("CONQUER.INI");
  2298. if (!file.Is_Available()) {
  2299. return;
  2300. } else {
  2301. file.Read(buffer, _ShapeBufferSize-1);
  2302. }
  2303. file.Close();
  2304. WWGetPrivateProfileString(section, entry, "", buf, sizeof(buf), buffer);
  2305. if (!stricmp (buf,name))
  2306. AreThingiesEnabled = true;
  2307. memset (section, 0, sizeof(section));
  2308. memset (entry, 0, sizeof(entry));
  2309. memset (name, 0, sizeof(name));
  2310. }
  2311. #endif
  2312. /***********************************************************************************************
  2313. * Version_Number -- Determines the version number. *
  2314. * *
  2315. * This routine will determine the version number by analyzing the date and teim that the *
  2316. * program was compiled and then generating a unique version number based on it. The *
  2317. * version numbers are guaranteed to be larger for later dates. *
  2318. * *
  2319. * INPUT: none *
  2320. * *
  2321. * OUTPUT: Returns with the version number. *
  2322. * *
  2323. * WARNINGS: none *
  2324. * *
  2325. * HISTORY: *
  2326. * 03/24/1995 JLB : Created. *
  2327. *=============================================================================================*/
  2328. int Version_Number(void)
  2329. {
  2330. #ifdef OBSOLETE
  2331. static bool initialized = false;
  2332. static int version;
  2333. static char * date = __DATE__;
  2334. static char * time = __TIME__;
  2335. static char const * months = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
  2336. if (!initialized) {
  2337. char * ptr;
  2338. char * tok;
  2339. /*
  2340. ** Fetch the month and place in the first two digit positions.
  2341. */
  2342. strupr(date);
  2343. tok = strtok(date, " ");
  2344. ptr = strstr(months, tok);
  2345. if (ptr) {
  2346. version = (((ptr - months) / 3)+1) * 10000;
  2347. }
  2348. /*
  2349. ** Fetch the date and place that in the next two digit positions.
  2350. */
  2351. tok = strtok(NULL, " ");
  2352. if (tok) {
  2353. version += atoi(tok) * 100;
  2354. }
  2355. /*
  2356. ** Fetch the time and place that in the last two digit positions.
  2357. */
  2358. tok = strtok(time, ": ");
  2359. if (tok) {
  2360. version += atoi(tok);
  2361. }
  2362. /*
  2363. ** Fetch the virgin text file (if present).
  2364. */
  2365. RawFileClass file("VERSION.TXT");
  2366. if (file.Is_Available()) {
  2367. file.Read(VersionText, sizeof(VersionText));
  2368. VersionText[sizeof(VersionText)-1] = '\0';
  2369. while (VersionText[sizeof(VersionText)-1] == '\r') {
  2370. VersionText[sizeof(VersionText)-1] = '\0';
  2371. }
  2372. } else {
  2373. VersionText[0] = '\0';
  2374. }
  2375. initialized = true;
  2376. }
  2377. return(version);
  2378. #endif
  2379. #ifdef WIN32
  2380. #if (FRENCH)
  2381. sprintf(VersionText, ".02"); // Win95 french version number
  2382. #endif //FRENCH
  2383. #if (GERMAN)
  2384. sprintf(VersionText, ".01"); // Win95 german version number
  2385. #endif //GERMAN
  2386. #if (JAPANESE)
  2387. sprintf(VersionText, ".01"); // Win95 german version number
  2388. #endif //GERMAN
  2389. #if !(FRENCH | GERMAN | JAPANESE)
  2390. sprintf(VersionText, ".07"); // Win95 USA version number
  2391. #endif //FRENCH | GERMAN
  2392. RawFileClass file("VERSION.TXT");
  2393. char version [16];
  2394. memset (version, 0, sizeof (version));
  2395. if (file.Is_Available()){
  2396. file.Read (version, sizeof (version));
  2397. }
  2398. strncat (VersionText, version, sizeof (VersionText) - strlen (VersionText) - 1);
  2399. #if (FRENCH)
  2400. return (1); // Win95 french version number
  2401. #endif //FRENCH
  2402. #if (GERMAN)
  2403. return (1); // Win95 german version number
  2404. #endif //GERMAN
  2405. #if (JAPANESE)
  2406. return (1); // Win95 german version number
  2407. #endif //GERMAN
  2408. #if !(FRENCH | GERMAN | JAPANESE)
  2409. return (1); // Win95 USA version number
  2410. #endif //FRENCH | GERMAN
  2411. #else
  2412. #ifdef PATCH
  2413. #ifdef DEMO
  2414. sprintf(VersionText, " 1.0a"); // Demo version.
  2415. #else
  2416. strcpy(VersionText, ".34 ");
  2417. #endif
  2418. return(1);
  2419. #else
  2420. #ifdef DEMO
  2421. sprintf(VersionText, " 1.0a"); // Demo version.
  2422. #else
  2423. // sprintf(VersionText, ".%02dp", 13); // Patch version.
  2424. sprintf(VersionText, ".%02d", 14); // Master version.
  2425. #endif
  2426. return(1);
  2427. #endif
  2428. #endif //WIN32
  2429. }
  2430. /***************************************************************************
  2431. * Save_Recording_Values -- Saves recording values to a recording file *
  2432. * *
  2433. * INPUT: *
  2434. * none. *
  2435. * *
  2436. * OUTPUT: *
  2437. * none. *
  2438. * *
  2439. * WARNINGS: *
  2440. * none. *
  2441. * *
  2442. * HISTORY: *
  2443. * 05/15/1995 BRR : Created. *
  2444. *=========================================================================*/
  2445. void Save_Recording_Values(void)
  2446. {
  2447. RecordFile.Write(&GameToPlay, sizeof(GameToPlay));
  2448. RecordFile.Write(&ModemGameToPlay, sizeof(ModemGameToPlay));
  2449. RecordFile.Write(&BuildLevel, sizeof(BuildLevel));
  2450. RecordFile.Write(MPlayerName, sizeof(MPlayerName));
  2451. RecordFile.Write(&MPlayerPrefColor, sizeof(MPlayerPrefColor));
  2452. RecordFile.Write(&MPlayerColorIdx, sizeof(MPlayerColorIdx));
  2453. RecordFile.Write(&MPlayerHouse, sizeof(MPlayerHouse));
  2454. RecordFile.Write(&MPlayerLocalID, sizeof(MPlayerLocalID));
  2455. RecordFile.Write(&MPlayerCount, sizeof(MPlayerCount));
  2456. RecordFile.Write(&MPlayerBases, sizeof(MPlayerBases));
  2457. RecordFile.Write(&MPlayerCredits, sizeof(MPlayerCredits));
  2458. RecordFile.Write(&MPlayerTiberium, sizeof(MPlayerTiberium));
  2459. RecordFile.Write(&MPlayerGoodies, sizeof(MPlayerGoodies));
  2460. RecordFile.Write(&MPlayerGhosts, sizeof(MPlayerGhosts));
  2461. RecordFile.Write(&MPlayerUnitCount, sizeof(MPlayerUnitCount));
  2462. RecordFile.Write(MPlayerID, sizeof(MPlayerID));
  2463. RecordFile.Write(MPlayerHouses, sizeof(MPlayerHouses));
  2464. RecordFile.Write(&Seed, sizeof(Seed));
  2465. RecordFile.Write(&Scenario, sizeof(Scenario));
  2466. RecordFile.Write(&ScenPlayer, sizeof(ScenPlayer));
  2467. RecordFile.Write(&ScenDir, sizeof(ScenDir));
  2468. RecordFile.Write(&Whom, sizeof(Whom));
  2469. RecordFile.Write(&Special, sizeof(SpecialClass));
  2470. RecordFile.Write(&Options, sizeof(GameOptionsClass));
  2471. RecordFile.Write(&FrameSendRate, sizeof(FrameSendRate));
  2472. RecordFile.Write(&CommProtocol, sizeof(CommProtocol));
  2473. if (SuperRecord) {
  2474. RecordFile.Close();
  2475. }
  2476. }
  2477. /***************************************************************************
  2478. * Load_Recording_Values -- Loads recording values from recording file *
  2479. * *
  2480. * INPUT: *
  2481. * none. *
  2482. * *
  2483. * OUTPUT: *
  2484. * none. *
  2485. * *
  2486. * WARNINGS: *
  2487. * none. *
  2488. * *
  2489. * HISTORY: *
  2490. * 05/15/1995 BRR : Created. *
  2491. *=========================================================================*/
  2492. void Load_Recording_Values(void)
  2493. {
  2494. Read_MultiPlayer_Settings();
  2495. RecordFile.Read(&GameToPlay, sizeof(GameToPlay));
  2496. RecordFile.Read(&ModemGameToPlay, sizeof(ModemGameToPlay));
  2497. RecordFile.Read(&BuildLevel, sizeof(BuildLevel));
  2498. RecordFile.Read(MPlayerName, sizeof(MPlayerName));
  2499. RecordFile.Read(&MPlayerPrefColor, sizeof(MPlayerPrefColor));
  2500. RecordFile.Read(&MPlayerColorIdx, sizeof(MPlayerColorIdx));
  2501. RecordFile.Read(&MPlayerHouse, sizeof(MPlayerHouse));
  2502. RecordFile.Read(&MPlayerLocalID, sizeof(MPlayerLocalID));
  2503. RecordFile.Read(&MPlayerCount, sizeof(MPlayerCount));
  2504. RecordFile.Read(&MPlayerBases, sizeof(MPlayerBases));
  2505. RecordFile.Read(&MPlayerCredits, sizeof(MPlayerCredits));
  2506. RecordFile.Read(&MPlayerTiberium, sizeof(MPlayerTiberium));
  2507. RecordFile.Read(&MPlayerGoodies, sizeof(MPlayerGoodies));
  2508. RecordFile.Read(&MPlayerGhosts, sizeof(MPlayerGhosts));
  2509. RecordFile.Read(&MPlayerUnitCount, sizeof(MPlayerUnitCount));
  2510. RecordFile.Read(MPlayerID, sizeof(MPlayerID));
  2511. RecordFile.Read(MPlayerHouses, sizeof(MPlayerHouses));
  2512. RecordFile.Read(&Seed, sizeof(Seed));
  2513. RecordFile.Read(&Scenario, sizeof(Scenario));
  2514. RecordFile.Read(&ScenPlayer, sizeof(ScenPlayer));
  2515. RecordFile.Read(&ScenDir, sizeof(ScenDir));
  2516. RecordFile.Read(&Whom, sizeof(Whom));
  2517. RecordFile.Read(&Special, sizeof(SpecialClass));
  2518. RecordFile.Read(&Options, sizeof(GameOptionsClass));
  2519. RecordFile.Read(&FrameSendRate, sizeof(FrameSendRate));
  2520. RecordFile.Read(&CommProtocol, sizeof(CommProtocol));
  2521. }
  2522. /***********************************************************************************************
  2523. * Obfuscate -- Sufficiently transform parameter to thwart casual hackers. *
  2524. * *
  2525. * This routine borrows from CRC and PGP technology to sufficiently alter the parameter *
  2526. * in order to make it difficult to reverse engineer the key phrase. This is designed to *
  2527. * be used for hidden game options that will be released at a later time over Westwood's *
  2528. * Web page or through magazine hint articles. *
  2529. * *
  2530. * Since this is a one way transformation, it becomes much more difficult to reverse *
  2531. * engineer the pass phrase even if the resultant pass code is known. This has an added *
  2532. * benefit of making this algorithm immune to traditional cyrptographic attacks. *
  2533. * *
  2534. * The largest strength of this transformation algorithm lies in the restriction on the *
  2535. * source vector being legal ASCII uppercase characters. This restriction alone makes even *
  2536. * a simple CRC transformation practically impossible to reverse engineer. This algorithm *
  2537. * uses far more than a simple CRC transformation to achieve added strength from advanced *
  2538. * attack methods. *
  2539. * *
  2540. * INPUT: string -- Pointer to the key phrase that will be transformed into a code. *
  2541. * *
  2542. * OUTPUT: Returns with the code that the key phrase is translated into. *
  2543. * *
  2544. * WARNINGS: A zero length pass phrase results in a 0x00000000 result code. *
  2545. * *
  2546. * HISTORY: *
  2547. * 08/19/1995 JLB : Created. *
  2548. *=============================================================================================*/
  2549. long Obfuscate(char const * string)
  2550. {
  2551. char buffer[1024];
  2552. if (!string) return(0);
  2553. memset(buffer, '\xA5', sizeof(buffer));
  2554. /*
  2555. ** Copy key phrase into a working buffer. This hides any transformation done
  2556. ** to the string.
  2557. */
  2558. strncpy(buffer, string, sizeof(buffer));
  2559. buffer[sizeof(buffer)-1] = '\0';
  2560. int length = strlen(buffer);
  2561. /*
  2562. ** Only upper case letters are significant.
  2563. */
  2564. strupr(buffer);
  2565. /*
  2566. ** Ensure that only visible ASCII characters compose the key phrase. This
  2567. ** discourages the direct forced illegal character input method of attack.
  2568. */
  2569. int index;
  2570. for (index = 0; index < length; index++) {
  2571. if (!isgraph(buffer[index])) {
  2572. buffer[index] = 'A' + (index%26);
  2573. }
  2574. }
  2575. /*
  2576. ** Increase the strength of even short pass phrases by extending the
  2577. ** length to be at least a minimum number of characters. This helps prevent
  2578. ** a weak pass phrase from compromising the obfuscation process. This
  2579. ** process also forces the key phrase to be an even multiple of four.
  2580. ** This is necessary to support the cypher process that occurs later.
  2581. */
  2582. if (length < 16 || (length & 0x03)) {
  2583. int maxlen = 16;
  2584. if (((length+3) & 0x00FC) > maxlen) {
  2585. maxlen = ((length+3) & 0x00FC);
  2586. }
  2587. for (index = length; index < maxlen; index++) {
  2588. buffer[index] = 'A' + ((('?' ^ buffer[index-length]) + index) % 26);
  2589. }
  2590. length = index;
  2591. buffer[length] = '\0';
  2592. }
  2593. /*
  2594. ** Transform the buffer into a number. This transformation is character
  2595. ** order dependant.
  2596. */
  2597. long code = Calculate_CRC(buffer, length);
  2598. /*
  2599. ** Record a copy of this initial transformation to be used in a later
  2600. ** self referential transformation.
  2601. */
  2602. long copy = code;
  2603. /*
  2604. ** Reverse the character string and combine with the previous transformation.
  2605. ** This doubles the workload of trying to reverse engineer the CRC calculation.
  2606. */
  2607. strrev(buffer);
  2608. code ^= Calculate_CRC(buffer, length);
  2609. /*
  2610. ** Perform a self referential transformation. This makes a reverse engineering
  2611. ** by using a cause and effect attack more difficult.
  2612. */
  2613. code = code ^ copy;
  2614. /*
  2615. ** Unroll and combine the code value into the pass phrase and then perform
  2616. ** another self referential transformation. Although this is a trivial cypher
  2617. ** process, it gives the sophisticated hacker false hope since the strong
  2618. ** cypher process occurs later.
  2619. */
  2620. strrev(buffer); // Restore original string order.
  2621. for (index = 0; index < length; index++) {
  2622. code ^= (unsigned char)buffer[index];
  2623. unsigned char temp = (unsigned char)code;
  2624. buffer[index] ^= temp;
  2625. code >>= 8;
  2626. code |= (((long)temp)<<24);
  2627. }
  2628. /*
  2629. ** Introduce loss into the vector. This strengthens the key against traditional
  2630. ** cryptographic attack engines. Since this also weakens the key against
  2631. ** unconventional attacks, the loss is limited to less than 10%.
  2632. */
  2633. for (index = 0; index < length; index++) {
  2634. static unsigned char _lossbits[] = {0x00,0x08,0x00,0x20,0x00,0x04,0x10,0x00};
  2635. static unsigned char _addbits[] = {0x10,0x00,0x00,0x80,0x40,0x00,0x00,0x04};
  2636. buffer[index] |= _addbits[index % (sizeof(_addbits)/sizeof(_addbits[0]))];
  2637. buffer[index] &= ~_lossbits[index % (sizeof(_lossbits)/sizeof(_lossbits[0]))];
  2638. }
  2639. /*
  2640. ** Perform a general cypher transformation on the vector
  2641. ** and use the vector itself as the cypher key. This is a variation on the
  2642. ** cypher process used in PGP. It is a very strong cypher process with no known
  2643. ** weaknesses. However, in this case, the cypher key is the vector itself and this
  2644. ** opens up a weakness against attacks that have access to this transformation
  2645. ** algorithm. The sheer workload of reversing this transformation should be enough
  2646. ** to discourage even the most determined hackers.
  2647. */
  2648. for (index = 0; index < length; index += 4) {
  2649. short key1 = buffer[index];
  2650. short key2 = buffer[index+1];
  2651. short key3 = buffer[index+2];
  2652. short key4 = buffer[index+3];
  2653. short val1 = key1;
  2654. short val2 = key2;
  2655. short val3 = key3;
  2656. short val4 = key4;
  2657. val1 *= key1;
  2658. val2 += key2;
  2659. val3 += key3;
  2660. val4 *= key4;
  2661. short s3 = val3;
  2662. val3 ^= val1;
  2663. val3 *= key1;
  2664. short s2 = val2;
  2665. val2 ^= val4;
  2666. val2 += val3;
  2667. val2 *= key3;
  2668. val3 += val2;
  2669. val1 ^= val2;
  2670. val4 ^= val3;
  2671. val2 ^= s3;
  2672. val3 ^= s2;
  2673. buffer[index] = val1;
  2674. buffer[index+1] = val2;
  2675. buffer[index+2] = val3;
  2676. buffer[index+3] = val4;
  2677. }
  2678. /*
  2679. ** Convert this final vector into a cypher key code to be
  2680. ** returned by this routine.
  2681. */
  2682. code = Calculate_CRC(buffer, length);
  2683. /*
  2684. ** Return the final code value.
  2685. */
  2686. return(code);
  2687. }