INIT.CPP 86 KB

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