INIT.CPP 127 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873
  1. //
  2. // Copyright 2020 Electronic Arts Inc.
  3. //
  4. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
  5. // software: you can redistribute it and/or modify it under the terms of
  6. // the GNU General Public License as published by the Free Software Foundation,
  7. // either version 3 of the License, or (at your option) any later version.
  8. // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
  9. // in the hope that it will be useful, but with permitted additional restrictions
  10. // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
  11. // distributed with this program. You should have received a copy of the
  12. // GNU General Public License along with permitted additional restrictions
  13. // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
  14. /* $Header: /CounterStrike/INIT.CPP 8 3/14/97 5:15p Joe_b $ */
  15. /***********************************************************************************************
  16. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  17. ***********************************************************************************************
  18. * *
  19. * Project Name : Command & Conquer *
  20. * *
  21. * File Name : INIT.CPP *
  22. * *
  23. * Programmer : Joe L. Bostic *
  24. * *
  25. * Start Date : January 20, 1992 *
  26. * *
  27. *---------------------------------------------------------------------------------------------*
  28. * Functions: *
  29. * Anim_Init -- Initialize the VQ animation control structure. *
  30. * Bootstrap -- Perform the initial bootstrap procedure. *
  31. * Calculate_CRC -- Calculates a one-way hash from a data block. *
  32. * Init_Authorization -- Verifies that the player is authorized to play the game. *
  33. * Init_Bootstrap_Mixfiles -- Registers and caches any mixfiles needed for bootstrapping. *
  34. * Init_Bulk_Data -- Initialize the time-consuming mixfile caching. *
  35. * Init_CDROM_Access -- Initialize the CD-ROM access handler. *
  36. * Init_Color_Remaps -- Initialize the text remap tables. *
  37. * Init_Expansion_Files -- Fetch any override expansion mixfiles. *
  38. * Init_Fonts -- Initialize all the game font pointers. *
  39. * Init_Game -- Main game initialization routine. *
  40. * Init_Heaps -- Initialize the game heaps and buffers. *
  41. * Init_Keys -- Initialize the cryptographic keys. *
  42. * Init_Mouse -- Initialize the mouse system. *
  43. * Init_One_Time_Systems -- Initialize internal pointers to the bulk data. *
  44. * Init_Random -- Initializes the random-number generator *
  45. * Init_Secondary_Mixfiles -- Register and cache secondary mixfiles. *
  46. * Load_Recording_Values -- Loads recording values from recording file *
  47. * Load_Title_Page -- Load the background art for the title page. *
  48. * Obfuscate -- Sufficiently transform parameter to thwart casual hackers. *
  49. * Parse_Command_Line -- Parses the command line parameters. *
  50. * Parse_INI_File -- Parses CONQUER.INI for special options *
  51. * Play_Intro -- plays the introduction & logo movies *
  52. * Save_Recording_Values -- Saves recording values to a recording file *
  53. * Select_Game -- The game's main menu *
  54. * Load_Prolog_Page -- Loads the special pre-prolog "please wait" page. *
  55. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  56. #include "function.h"
  57. #include "loaddlg.h"
  58. #ifdef WIN32
  59. #ifdef WINSOCK_IPX
  60. #include "WSProto.h"
  61. #include "WSPUDP.h"
  62. #include "WSPIPX.h"
  63. #include "internet.h"
  64. #else //WINSOCK_IPX
  65. #include "tcpip.h"
  66. #endif //WINSOCK_IPX
  67. #endif
  68. #include <conio.h>
  69. #include <dos.h>
  70. #ifndef WIN32
  71. #include <sys\timeb.h>
  72. #endif
  73. #include "ccdde.h"
  74. #include <time.h>
  75. #ifdef DONGLE
  76. #include "cbn_.h"
  77. #endif
  78. #ifdef MPEGMOVIE // Denzil 6/25/98
  79. #include "mpgset.h"
  80. #endif
  81. RemapControlType SidebarScheme;
  82. //#include "WolDebug.h"
  83. #ifdef CHEAT_KEYS
  84. extern bool bNoMovies;
  85. #endif
  86. /****************************************
  87. ** Function prototypes for this module **
  88. *****************************************/
  89. static void Play_Intro(bool sequenced=false);
  90. static void Init_Color_Remaps(void);
  91. static void Init_Heaps(void);
  92. static void Init_Expansion_Files(void);
  93. static void Init_One_Time_Systems(void);
  94. static void Init_Fonts(void);
  95. static void Init_CDROM_Access(void);
  96. static void Init_Bootstrap_Mixfiles(void);
  97. static void Init_Secondary_Mixfiles(void);
  98. static void Init_Mouse(void);
  99. static void Bootstrap(void);
  100. //static void Init_Authorization(void);
  101. static void Init_Bulk_Data(void);
  102. static void Init_Keys(void);
  103. extern int UnitBuildPenalty;
  104. extern "C" {
  105. extern long RandNumb;
  106. }
  107. #ifndef WIN32
  108. static int UsePageFaultHandler = 1; // 1 = install PFH
  109. #endif //WIN32
  110. //extern int SimRandIndex;
  111. void Init_Random(void);
  112. #define ATTRACT_MODE_TIMEOUT 3600 // timeout for attract mode
  113. bool Load_Recording_Values(CCFileClass & file);
  114. bool Save_Recording_Values(CCFileClass & file);
  115. #ifdef WOLAPI_INTEGRATION
  116. extern int WOL_Main();
  117. #include "WolapiOb.h"
  118. extern WolapiObject* pWolapi;
  119. #endif
  120. #ifdef FIXIT_VERSION_3
  121. bool Expansion_Dialog( bool bCounterstrike );
  122. #endif
  123. extern bool Is_Mission_Counterstrike (char *file_name);
  124. /***********************************************************************************************
  125. * Load_Prolog_Page -- Loads the special pre-prolog "please wait" page. *
  126. * *
  127. * This loads and displays the prolog page that is displayed before the prolog movie *
  128. * is played. This page is necessary because there is much loading that occurs before *
  129. * the prolog movie is played and looking at a picture is better than looking at a blank *
  130. * screen. *
  131. * *
  132. * INPUT: none *
  133. * *
  134. * OUTPUT: none *
  135. * *
  136. * WARNINGS: none *
  137. * *
  138. * HISTORY: *
  139. * 11/03/1996 JLB : Created. *
  140. *=============================================================================================*/
  141. static void Load_Prolog_Page(void)
  142. {
  143. Hide_Mouse();
  144. #ifdef WIN32
  145. Load_Title_Screen("PROLOG.PCX", &HidPage, (unsigned char*)CCPalette.Get_Data());
  146. HidPage.Blit(SeenPage);
  147. #else
  148. Load_Picture("PROLOG.CPS", HidPage, HidPage, CCPalette, BM_DEFAULT);
  149. HidPage.Blit(SeenPage);
  150. #endif
  151. CCPalette.Set();
  152. Show_Mouse();
  153. }
  154. /***********************************************************************************************
  155. * Init_Game -- Main game initialization routine. *
  156. * *
  157. * Perform all one-time game initializations here. This includes all *
  158. * allocations and table setups. The intro and other one-time startup *
  159. * tasks are also performed here. *
  160. * *
  161. * INPUT: argc,argv -- Command line arguments. *
  162. * *
  163. * OUTPUT: none *
  164. * *
  165. * WARNINGS: Only call this ONCE! *
  166. * *
  167. * HISTORY: *
  168. * 10/07/1992 JLB : Created. *
  169. *=============================================================================================*/
  170. #include "sha.h"
  171. //#include <locale.h>
  172. bool Init_Game(int , char * [])
  173. {
  174. /*
  175. ** Allocate the benchmark tracking objects only if the machine and
  176. ** compile flags indicate.
  177. */
  178. #ifdef CHEAT_KEYS
  179. if (Processor() >= 2) {
  180. Benches = new Benchmark [BENCH_COUNT];
  181. }
  182. #endif
  183. /*
  184. ** Initialize the encryption keys.
  185. */
  186. Init_Keys();
  187. /*
  188. ** Bootstrap as much as possible before error-prone initializations are
  189. ** performed. This bootstrap process will enable the error message
  190. ** handler to function.
  191. */
  192. Bootstrap();
  193. ////////////////////////////////////////
  194. // The editor needs to not start the mouse up. - 7/22/2019 JAS
  195. if (!RunningFromEditor)
  196. {
  197. /*
  198. ** Check for an initialize a working mouse pointer. Display error and bail if
  199. ** no mouse driver is installed.
  200. */
  201. Init_Mouse();
  202. }
  203. /*
  204. ** Initialize access to the CD-ROM and ensure that the CD is inserted. This can, and
  205. ** most likely will, result in a visible prompt.
  206. */
  207. #if (0) //PG
  208. Init_CDROM_Access();
  209. #endif
  210. if (Special.IsFromInstall) {
  211. Load_Prolog_Page();
  212. }
  213. /*
  214. ** Register and cache any secondary mixfiles.
  215. */
  216. Init_Secondary_Mixfiles();
  217. /*
  218. ** This is a special hack to initialize the heaps that must be in place before the
  219. ** rules file is processed. These heaps should properly be allocated as a consequence
  220. ** of processing the rules.ini file, but that is a bit beyond the capabilities of
  221. ** the rule parser routine (currently).
  222. */
  223. HouseTypes.Set_Heap(HOUSE_COUNT);
  224. BuildingTypes.Set_Heap(STRUCT_COUNT);
  225. AircraftTypes.Set_Heap(AIRCRAFT_COUNT);
  226. InfantryTypes.Set_Heap(INFANTRY_COUNT);
  227. BulletTypes.Set_Heap(BULLET_COUNT);
  228. AnimTypes.Set_Heap(ANIM_COUNT);
  229. UnitTypes.Set_Heap(UNIT_COUNT);
  230. VesselTypes.Set_Heap(VESSEL_COUNT);
  231. TemplateTypes.Set_Heap(TEMPLATE_COUNT);
  232. TerrainTypes.Set_Heap(TERRAIN_COUNT);
  233. OverlayTypes.Set_Heap(OVERLAY_COUNT);
  234. SmudgeTypes.Set_Heap(SMUDGE_COUNT);
  235. HouseTypeClass::Init_Heap();
  236. BuildingTypeClass::Init_Heap();
  237. AircraftTypeClass::Init_Heap();
  238. InfantryTypeClass::Init_Heap();
  239. BulletTypeClass::Init_Heap();
  240. AnimTypeClass::Init_Heap();
  241. UnitTypeClass::Init_Heap();
  242. VesselTypeClass::Init_Heap();
  243. TemplateTypeClass::Init_Heap();
  244. TerrainTypeClass::Init_Heap();
  245. OverlayTypeClass::Init_Heap();
  246. SmudgeTypeClass::Init_Heap();
  247. // Heap init moved here from globals.cpp. ST - 5/20/2019
  248. CCPtr<AircraftClass>::Set_Heap(&Aircraft);
  249. CCPtr<AnimClass>::Set_Heap(&Anims);
  250. CCPtr<BuildingClass>::Set_Heap(&Buildings);
  251. CCPtr<BulletClass>::Set_Heap(&Bullets);
  252. CCPtr<FactoryClass>::Set_Heap(&Factories);
  253. CCPtr<HouseClass>::Set_Heap(&Houses);
  254. CCPtr<InfantryClass>::Set_Heap(&Infantry);
  255. CCPtr<OverlayClass>::Set_Heap(&Overlays);
  256. CCPtr<SmudgeClass>::Set_Heap(&Smudges);
  257. CCPtr<TeamClass>::Set_Heap(&Teams);
  258. CCPtr<TeamTypeClass>::Set_Heap(&TeamTypes);
  259. CCPtr<TemplateClass>::Set_Heap(&Templates);
  260. CCPtr<TerrainClass>::Set_Heap(&Terrains);
  261. CCPtr<TriggerClass>::Set_Heap(&Triggers);
  262. CCPtr<TriggerTypeClass>::Set_Heap(&TriggerTypes);
  263. CCPtr<HouseTypeClass>::Set_Heap(&HouseTypes);
  264. CCPtr<BuildingTypeClass>::Set_Heap(&BuildingTypes);
  265. CCPtr<AircraftTypeClass>::Set_Heap(&AircraftTypes);
  266. CCPtr<InfantryTypeClass>::Set_Heap(&InfantryTypes);
  267. CCPtr<BulletTypeClass>::Set_Heap(&BulletTypes);
  268. CCPtr<AnimTypeClass>::Set_Heap(&AnimTypes);
  269. CCPtr<UnitTypeClass>::Set_Heap(&UnitTypes);
  270. CCPtr<VesselTypeClass>::Set_Heap(&VesselTypes);
  271. CCPtr<TemplateTypeClass>::Set_Heap(&TemplateTypes);
  272. CCPtr<TerrainTypeClass>::Set_Heap(&TerrainTypes);
  273. CCPtr<OverlayTypeClass>::Set_Heap(&OverlayTypes);
  274. CCPtr<SmudgeTypeClass>::Set_Heap(&SmudgeTypes);
  275. /*
  276. ** Find and process any rules for this game.
  277. */
  278. if (RuleINI.Load(CCFileClass("RULES.INI"), false)) {
  279. Rule.Process(RuleINI);
  280. }
  281. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  282. // Aftermath runtime change 9/29/98
  283. // This is safe to do, as only rules for aftermath units are included in this ini.
  284. if (Is_Aftermath_Installed() == true) {
  285. if (AftermathINI.Load(CCFileClass("AFTRMATH.INI"), false)) {
  286. Rule.Process(AftermathINI);
  287. }
  288. }
  289. #endif
  290. Session.MaxPlayers = Rule.MaxPlayers;
  291. /*
  292. ** Initialize the game object heaps as well as other rules-dependant buffer allocations.
  293. */
  294. Init_Heaps();
  295. /*
  296. ** Initialize the animation system.
  297. */
  298. Anim_Init();
  299. #ifndef FIXIT_VERSION_3 // WChat eliminated.
  300. #ifdef WIN32
  301. if (SpawnedFromWChat){
  302. Special.IsFromWChat = true;
  303. }
  304. #endif
  305. #endif
  306. #ifdef MPEGMOVIE // Denzil 6/15/98
  307. if( Using_DVD() )
  308. {
  309. #ifdef MCIMPEG
  310. MciMovie = new MCIMovie(MainWindow);
  311. #endif
  312. MpgSettings = new MPGSettings(NULL); //RawFileClass(CONFIG_FILE_NAME));
  313. }
  314. #endif
  315. /*
  316. ** Play the startup animation.
  317. */
  318. if (!Special.IsFromInstall && !Special.IsFromWChat) {
  319. VisiblePage.Clear();
  320. // Mono_Printf("Playing Intro\n");
  321. Play_Intro();
  322. memset(CurrentPalette, 0x01, 768);
  323. WhitePalette.Set();
  324. } else {
  325. memset(CurrentPalette, 0x01, 768);
  326. }
  327. /*
  328. ** Initialize the text remap tables.
  329. */
  330. Init_Color_Remaps();
  331. /*
  332. ** Get authorization to access the game.
  333. */
  334. // Init_Authorization();
  335. // Show_Mouse();
  336. /*
  337. ** Set the logic page to the seenpage.
  338. */
  339. Set_Logic_Page(SeenBuff);
  340. /*
  341. ** If not automatically launching into the intro, then display the title
  342. ** page while the bulk data is cached.
  343. */
  344. if (!Special.IsFromInstall) {
  345. Load_Title_Page(true);
  346. Hide_Mouse();
  347. Fancy_Text_Print(TXT_STAND_BY, 160*RESFACTOR, 120*RESFACTOR, &ColorRemaps[PCOLOR_DIALOG_BLUE], TBLACK, TPF_CENTER|TPF_TEXT|TPF_DROPSHADOW);
  348. Show_Mouse();
  349. CCPalette.Set(FADE_PALETTE_SLOW);
  350. Call_Back();
  351. }
  352. /*
  353. ** Initialize the bulk data. This takes the longest time and must be performed once
  354. ** before the regular game starts.
  355. */
  356. Init_Bulk_Data();
  357. /*
  358. ** Initialize the multiplayer score values
  359. */
  360. Session.GamesPlayed = 0;
  361. Session.NumScores = 0;
  362. Session.CurGame = 0;
  363. for (int i = 0; i < MAX_MULTI_NAMES; i++) {
  364. Session.Score[i].Name[0] = '\0';
  365. Session.Score[i].Wins = 0;
  366. for (int j = 0; j < MAX_MULTI_GAMES; j++) {
  367. Session.Score[i].Kills[j] = -1; // -1 = this player didn't play this round
  368. }
  369. }
  370. /*
  371. ** Copy the title screen's palette into the GamePalette & OriginalPalette,
  372. ** because the options Load routine uses these palettes to set the brightness, etc.
  373. */
  374. GamePalette = CCPalette;
  375. // InGamePalette = CCPalette;
  376. OriginalPalette = CCPalette;
  377. /*
  378. ** Read game options, so the GameSpeed is initialized when multiplayer
  379. ** dialogs are invoked. (GameSpeed must be synchronized between systems.)
  380. */
  381. Options.Load_Settings();
  382. /*
  383. ** Initialise the color lookup tables for the chronal vortex
  384. */
  385. ChronalVortex.Stop();
  386. ChronalVortex.Setup_Remap_Tables(Scen.Theater);
  387. /*
  388. ** Clear out name overrides array
  389. */
  390. #ifdef FIXIT_NAME_OVERRIDE
  391. for (int index = 0; index < ARRAY_SIZE(NameOverride); index++) {
  392. NameOverride[index] = NULL;
  393. NameIDOverride[index] = 0;
  394. }
  395. #endif //FIXIT_NAME_OVERRIDE
  396. return(true);
  397. }
  398. #ifdef WINSOCK_IPX // Steve Tall missed this one - ajw
  399. extern bool Get_Broadcast_Addresses (void);
  400. #endif
  401. /***********************************************************************************************
  402. * Select_Game -- The game's main menu *
  403. * *
  404. * INPUT: *
  405. * fade if true, will fade the palette in gradually *
  406. * *
  407. * OUTPUT: *
  408. * none. *
  409. * *
  410. * WARNINGS: *
  411. * none. *
  412. * *
  413. * HISTORY: *
  414. * 06/05/1995 BRR : Created. *
  415. *=============================================================================================*/
  416. bool Select_Game(bool fade)
  417. {
  418. // Enums in Select_Game() must match order of buttons in Main_Menu().
  419. #ifdef FIXIT_VERSION_3
  420. enum {
  421. SEL_TIMEOUT = -1, // main menu timeout--go into attract mode
  422. SEL_NEW_SCENARIO_CS, // Expansion scenario to play.
  423. SEL_NEW_SCENARIO_AM, // Expansion scenario to play.
  424. SEL_START_NEW_GAME, // start a new game
  425. SEL_LOAD_MISSION, // load a saved game
  426. SEL_MULTIPLAYER_GAME, // play modem/null-modem/network game
  427. SEL_INTRO, // couch-potato mode
  428. SEL_EXIT, // exit to DOS
  429. SEL_FAME, // view the hall o' fame
  430. SEL_NONE, // placeholder default value
  431. };
  432. #else // FIXIT_VERSION_3
  433. enum {
  434. SEL_TIMEOUT = -1, // main menu timeout--go into attract mode
  435. SEL_NEW_SCENARIO, // Expansion scenario to play.
  436. SEL_START_NEW_GAME, // start a new game
  437. #if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play
  438. SEL_INTERNET,
  439. #endif //WIN32
  440. //#if defined(MPEGMOVIE) // Denzil 6/25/98
  441. // SEL_MOVIESETTINGS,
  442. //#endif
  443. SEL_LOAD_MISSION, // load a saved game
  444. SEL_MULTIPLAYER_GAME, // play modem/null-modem/network game
  445. SEL_INTRO, // couch-potato mode
  446. SEL_EXIT, // exit to DOS
  447. SEL_FAME, // view the hall o' fame
  448. SEL_NONE, // placeholder default value
  449. };
  450. #endif // FIXIT_VERSION_3
  451. bool gameloaded=false; // Has the game been loaded from the menu?
  452. int selection; // the default selection
  453. bool process = true; // false = break out of while loop
  454. bool display = true;
  455. #ifdef DONGLE
  456. /* These where added by ColinM for the dongle checking */
  457. short iRet = 0;
  458. unsigned short iPortNr = 1; /* automatic port scan enabled */
  459. unsigned char cSCodeSER[] = "\x41\x42";
  460. unsigned long ulIdRet = 0;
  461. unsigned char cBoxName[]= "\x00\x00";
  462. #endif
  463. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  464. int cdcheck = 0;
  465. bool cs = Is_Counterstrike_Installed();
  466. #endif
  467. // #ifndef DVD // Denzil - We want the menu screen ajw No we don't
  468. // if (Special.IsFromInstall) {
  469. // display = false;
  470. // }
  471. // #endif
  472. Show_Mouse();
  473. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  474. NewUnitsEnabled = SecretUnitsEnabled = 0; // Assume new units disabled, unless specifically .INI enabled or multiplayer negotiations enable it.
  475. #endif
  476. #ifndef WOLAPI_INTEGRATION
  477. #ifdef WIN32
  478. /*
  479. ** Enable the DDE Server so we can get internet start game packets from WChat
  480. */
  481. DDEServer.Enable();
  482. #endif //WIN32
  483. #endif // !WOLAPI_INTEGRATION
  484. /*
  485. ** [Re]set any globals that need it, in preparation for a new scenario
  486. */
  487. GameActive = true;
  488. DoList.Init();
  489. #ifdef MIRROR_QUEUE
  490. MirrorList.Init();
  491. #endif
  492. OutList.Init();
  493. Frame = 0;
  494. Scen.MissionTimer = 0;
  495. Scen.MissionTimer.Stop();
  496. Scen.CDifficulty = DIFF_NORMAL;
  497. Scen.Difficulty = DIFF_NORMAL;
  498. PlayerWins = false;
  499. PlayerLoses = false;
  500. Session.ObiWan = false;
  501. Debug_Unshroud = false;
  502. Map.Set_Cursor_Shape(0);
  503. Map.PendingObjectPtr = 0;
  504. Map.PendingObject = 0;
  505. Map.PendingHouse = HOUSE_NONE;
  506. Session.ProcessTicks = 0;
  507. Session.ProcessFrames = 0;
  508. Session.DesiredFrameRate = 30;
  509. #if(TIMING_FIX)
  510. NewMaxAheadFrame1 = 0;
  511. NewMaxAheadFrame2 = 0;
  512. #endif
  513. /* ColinM added to check for dongle */
  514. #ifdef DONGLE
  515. iRet = CbN_BoxReady( iPortNr , cBoxName);
  516. if (cBoxName[0] != 0xc5 && cBoxName[0] != 0xc9)
  517. {
  518. WWMessageBox().Process("Please ensure dongle is attached. Run the dongle batch file too.", TXT_OK);
  519. Emergency_Exit(EXIT_FAILURE);
  520. }
  521. iRet = CbN_ReadSER( iPortNr, cSCodeSER, &ulIdRet);
  522. if (ulIdRet != 0xa0095)
  523. {
  524. WWMessageBox().Process("Please ensure dongle is attached. Run the dongle batch file too.", TXT_OK);
  525. Emergency_Exit(EXIT_FAILURE);
  526. }
  527. #endif
  528. /*
  529. ** Init multiplayer game scores. Let Wins accumulate; just init the current
  530. ** Kills for this game. Kills of -1 means this player didn't play this round.
  531. */
  532. for (int i = 0 ; i < MAX_MULTI_GAMES; i++) {
  533. Session.Score[i].Kills[Session.CurGame] = -1;
  534. }
  535. /*
  536. ** Set default mouse shape
  537. */
  538. Map.Set_Default_Mouse(MOUSE_NORMAL, false);
  539. /*
  540. ** If the last game we played was a multiplayer game, jump right to that
  541. ** menu by pre-setting 'selection'.
  542. */
  543. if (Session.Type == GAME_NORMAL) {
  544. selection = SEL_NONE;
  545. } else {
  546. selection = SEL_MULTIPLAYER_GAME;
  547. }
  548. /*
  549. ** Main menu processing; only do this if we're not in editor mode.
  550. */
  551. if (!Debug_Map) {
  552. /*
  553. ** Menu selection processing loop
  554. */
  555. Theme.Queue_Song(THEME_CRUS);
  556. /*
  557. ** If we're playing back a recording, load all pertinent values & skip
  558. ** the menu loop. Hide the now-useless mouse pointer.
  559. */
  560. if (Session.Play && Session.RecordFile.Is_Available()) {
  561. if (Session.RecordFile.Open(READ)) {
  562. Load_Recording_Values(Session.RecordFile);
  563. process = false;
  564. Theme.Fade_Out();
  565. } else
  566. Session.Play = false;
  567. }
  568. #ifndef FIXIT_VERSION_3
  569. #if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play
  570. /*
  571. ** Handle case where we were spawned from Wchat
  572. */
  573. if (SpawnedFromWChat) {
  574. Special.IsFromInstall = false; //Dont play intro if we were spawned from wchat
  575. selection = SEL_INTERNET;
  576. Theme.Queue_Song(THEME_QUIET);
  577. Session.Type = GAME_INTERNET;
  578. display = false;
  579. Set_Logic_Page(SeenBuff);
  580. }
  581. #endif //WIN32
  582. #endif
  583. while (process) {
  584. /*
  585. ** Redraw the title page if needed
  586. */
  587. if (display) {
  588. Hide_Mouse();
  589. /*
  590. ** Display the title page; fade it in if this is the first time
  591. ** through the loop, and the 'fade' flag is true
  592. */
  593. Load_Title_Page();
  594. GamePalette = CCPalette;
  595. HidPage.Blit(SeenPage);
  596. // if (fade) {
  597. // WhitePalette.Set();
  598. // CCPalette.Set(FADE_PALETTE_SLOW, Call_Back);
  599. // fade = false;
  600. // } else {
  601. CCPalette.Set();
  602. // }
  603. Set_Logic_Page(SeenBuff);
  604. display = false;
  605. Show_Mouse();
  606. }
  607. else {
  608. if (RunningAsDLL) { //PG
  609. return true;;
  610. }
  611. }
  612. /*
  613. ** Display menu and fetch selection from player.
  614. */
  615. if (Special.IsFromInstall) selection = SEL_START_NEW_GAME;
  616. #ifndef WOLAPI_INTEGRATION
  617. #if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play
  618. /*
  619. ** Handle case where we were spawned from Wchat and our start game
  620. ** packet has already arrived
  621. */
  622. if (Special.IsFromWChat && DDEServer.Get_MPlayer_Game_Info()) {
  623. Check_From_WChat(NULL);
  624. selection = SEL_MULTIPLAYER_GAME;
  625. Theme.Queue_Song(THEME_QUIET);
  626. Session.Type = GAME_INTERNET;
  627. } else {
  628. /*
  629. ** We werent spawned but we could still receive a DDE packet from wchat
  630. */
  631. if (DDEServer.Get_MPlayer_Game_Info()) {
  632. Check_From_WChat(NULL);
  633. /*
  634. ** Make sure top and bottom of screen are clear in 640x480 mode
  635. */
  636. if (ScreenHeight == 480) {
  637. VisiblePage.Fill_Rect (0, 0, 639, 40, 0);
  638. VisiblePage.Fill_Rect (0, 440, 639, 479, 0);
  639. }
  640. }
  641. }
  642. #endif //WIN32
  643. #endif
  644. #ifdef WOLAPI_INTEGRATION
  645. if( pWolapi )
  646. selection = SEL_MULTIPLAYER_GAME; // We are returning from a game.
  647. #endif
  648. if (selection == SEL_NONE) {
  649. #ifdef FIXIT_ANTS
  650. AntsEnabled = false;
  651. #endif
  652. selection = Main_Menu(ATTRACT_MODE_TIMEOUT);
  653. }
  654. Call_Back();
  655. switch (selection) {
  656. /*
  657. ** Pick an expansion scenario.
  658. */
  659. #ifdef FIXIT_VERSION_3
  660. case SEL_NEW_SCENARIO_CS:
  661. case SEL_NEW_SCENARIO_AM:
  662. #else // FIXIT_VERSION_3
  663. case SEL_NEW_SCENARIO:
  664. #endif // FIXIT_VERSION_3
  665. Scen.CarryOverMoney = 0;
  666. IsTanyaDead = false;
  667. SaveTanya = false;
  668. #ifdef FIXIT_VERSION_3
  669. if( selection == SEL_NEW_SCENARIO_CS )
  670. {
  671. if(!Force_CD_Available(2)) {
  672. selection = SEL_NONE;
  673. break;
  674. }
  675. if(!Expansion_Dialog( true )){
  676. selection = SEL_NONE;
  677. break;
  678. }
  679. }
  680. else
  681. {
  682. if(!Force_CD_Available(3)) {
  683. selection = SEL_NONE;
  684. break;
  685. }
  686. if(!Expansion_Dialog( false )){
  687. selection = SEL_NONE;
  688. break;
  689. }
  690. }
  691. #else // FIXIT_VERSION_3
  692. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  693. if (cs) {
  694. cdcheck = 2;
  695. }
  696. if (Is_Aftermath_Installed()) {
  697. if (!cdcheck) {
  698. cdcheck = 3;
  699. } else {
  700. cdcheck = 4; // special case: means check for 3 or 4
  701. }
  702. }
  703. if(!Force_CD_Available(cdcheck)) {
  704. return(false);
  705. }
  706. #else
  707. if(!Force_CD_Available(2)) {
  708. return(false);
  709. }
  710. #endif
  711. if(!Expansion_Dialog()){
  712. selection = SEL_NONE;
  713. break;
  714. }
  715. #endif // FIXIT_VERSION_3
  716. #ifdef FIXIT_DIFFICULTY
  717. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  718. switch (Fetch_Difficulty(cdcheck >= 3)) {
  719. #else
  720. switch (Fetch_Difficulty()) {
  721. #endif
  722. case 0:
  723. Scen.CDifficulty = DIFF_HARD;
  724. Scen.Difficulty = DIFF_EASY;
  725. break;
  726. case 1:
  727. Scen.CDifficulty = DIFF_HARD;
  728. Scen.Difficulty = DIFF_NORMAL;
  729. break;
  730. case 2:
  731. Scen.CDifficulty = DIFF_NORMAL;
  732. Scen.Difficulty = DIFF_NORMAL;
  733. break;
  734. case 3:
  735. Scen.CDifficulty = DIFF_EASY;
  736. Scen.Difficulty = DIFF_NORMAL;
  737. break;
  738. case 4:
  739. Scen.CDifficulty = DIFF_EASY;
  740. Scen.Difficulty = DIFF_HARD;
  741. break;
  742. }
  743. #endif
  744. Theme.Fade_Out();
  745. Theme.Queue_Song(THEME_FIRST);
  746. Session.Type = GAME_NORMAL;
  747. process = false;
  748. break;
  749. /*
  750. ** SEL_START_NEW_GAME: Play the game
  751. */
  752. case SEL_START_NEW_GAME:
  753. if (Special.IsFromInstall) {
  754. Scen.CDifficulty = DIFF_NORMAL;
  755. Scen.Difficulty = DIFF_NORMAL;
  756. } else {
  757. switch (Fetch_Difficulty()) {
  758. case 0:
  759. Scen.CDifficulty = DIFF_HARD;
  760. Scen.Difficulty = DIFF_EASY;
  761. break;
  762. case 1:
  763. Scen.CDifficulty = DIFF_HARD;
  764. Scen.Difficulty = DIFF_NORMAL;
  765. break;
  766. case 2:
  767. Scen.CDifficulty = DIFF_NORMAL;
  768. Scen.Difficulty = DIFF_NORMAL;
  769. break;
  770. case 3:
  771. Scen.CDifficulty = DIFF_EASY;
  772. Scen.Difficulty = DIFF_NORMAL;
  773. break;
  774. case 4:
  775. Scen.CDifficulty = DIFF_EASY;
  776. Scen.Difficulty = DIFF_HARD;
  777. break;
  778. }
  779. }
  780. Scen.CarryOverMoney = 0;
  781. BuildLevel = 10;
  782. IsTanyaDead = false;
  783. SaveTanya = false;
  784. Whom = HOUSE_GOOD;
  785. if (!Special.IsFromInstall) {
  786. #ifdef FIXIT_ANTS
  787. if (AntsEnabled) {
  788. Scen.Set_Scenario_Name("SCA01EA.INI");
  789. } else {
  790. #endif
  791. #ifdef FIXIT_VERSION_3
  792. switch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_CANCEL, TXT_SOVIET)) {
  793. case 2:
  794. Scen.Set_Scenario_Name("SCU01EA.INI");
  795. break;
  796. default:
  797. selection = SEL_NONE;
  798. continue;
  799. #else
  800. switch (WWMessageBox().Process(TXT_CHOOSE, TXT_ALLIES, TXT_SOVIET)) {
  801. case 1:
  802. Scen.Set_Scenario_Name("SCU01EA.INI");
  803. break;
  804. default:
  805. #endif
  806. case 0:
  807. Scen.Set_Scenario_Name("SCG01EA.INI");
  808. break;
  809. }
  810. #ifdef FIXIT_ANTS
  811. }
  812. #endif
  813. Theme.Fade_Out();
  814. Load_Title_Page();
  815. } else {
  816. Theme.Fade_Out();
  817. #ifdef DVD // Denzil ajw Presumably a bug fix.
  818. Choose_Side();
  819. Hide_Mouse();
  820. #else
  821. Hide_Mouse();
  822. Choose_Side();
  823. #endif
  824. if (CurrentCD == 0) {
  825. Scen.Set_Scenario_Name("SCG01EA.INI");
  826. } else {
  827. Scen.Set_Scenario_Name("SCU01EA.INI");
  828. }
  829. }
  830. Session.Type = GAME_NORMAL;
  831. process = false;
  832. break;
  833. #ifndef FIXIT_VERSION_3 // Removed button from main menu.
  834. #if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play
  835. /*
  836. ** Internet game is requested
  837. */
  838. case SEL_INTERNET:
  839. /*
  840. ** Only call up the internet menu code if we dont already have connect info from WChat
  841. */
  842. if (!DDEServer.Get_MPlayer_Game_Info()) {
  843. if (Do_The_Internet_Menu_Thang() && DDEServer.Get_MPlayer_Game_Info()) {
  844. Check_From_WChat(NULL);
  845. selection = SEL_MULTIPLAYER_GAME;
  846. display = false;
  847. Session.Type = GAME_INTERNET;
  848. } else {
  849. selection = SEL_NONE;
  850. display = true;
  851. }
  852. } else {
  853. Check_From_WChat(NULL);
  854. display = false;
  855. Session.Type = GAME_INTERNET;
  856. selection = SEL_MULTIPLAYER_GAME;
  857. }
  858. break;
  859. #endif //WIN32
  860. #endif
  861. // #if defined(MPEGMOVIE) // Denzil 6/25/98
  862. // case SEL_MOVIESETTINGS:
  863. // MpgSettings->Dialog();
  864. // display = true;
  865. // selection = SEL_NONE;
  866. // break;
  867. // #endif
  868. /*
  869. ** Load a saved game.
  870. */
  871. case SEL_LOAD_MISSION:
  872. if (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {
  873. Theme.Queue_Song(THEME_FIRST);
  874. process = false;
  875. gameloaded = true;
  876. } else {
  877. display = true;
  878. selection = SEL_NONE;
  879. }
  880. break;
  881. /*
  882. ** SEL_MULTIPLAYER_GAME: set 'Session.Type' to NULL-modem, modem, or
  883. ** network play.
  884. */
  885. case SEL_MULTIPLAYER_GAME:
  886. #ifdef WOLAPI_INTEGRATION
  887. if( !pWolapi )
  888. {
  889. #endif
  890. switch (Session.Type) {
  891. /*
  892. ** If 'Session.Type' isn't already set up for a multiplayer game,
  893. ** we must prompt the user for which type of multiplayer game
  894. ** they want.
  895. */
  896. case GAME_NORMAL:
  897. Session.Type = Select_MPlayer_Game();
  898. if (Session.Type == GAME_NORMAL) { // 'Cancel'
  899. display = true;
  900. selection = SEL_NONE;
  901. }
  902. break;
  903. case GAME_SKIRMISH:
  904. #if (0)//PG
  905. if ( !Com_Scenario_Dialog(true) ) {
  906. Session.Type = Select_MPlayer_Game();
  907. if (Session.Type == GAME_NORMAL) { // user hit Cancel
  908. display = true;
  909. selection = SEL_NONE;
  910. }
  911. }
  912. else
  913. {
  914. // Ever hits? Session.Type set to GAME_SKIRMISH without user selecting in Select_MPlayer_Game()?
  915. #ifdef FIXIT_VERSION_3
  916. // If mission is Counterstrike, CS CD will be required. But aftermath units require AM CD.
  917. bAftermathMultiplayer = Is_Aftermath_Installed() && !Is_Mission_Counterstrike( Scen.ScenarioName );
  918. // ajw I'll bet this was needed before also...
  919. Session.ScenarioIsOfficial = Session.Scenarios[Session.Options.ScenarioIndex]->Get_Official();
  920. #endif
  921. }
  922. #endif//PG
  923. break;
  924. case GAME_NULL_MODEM:
  925. case GAME_MODEM:
  926. #if (0)
  927. if ( Session.Type != GAME_SKIRMISH && NullModem.Num_Connections() ) {
  928. NullModem.Init_Send_Queue();
  929. if ((Session.Type == GAME_NULL_MODEM &&
  930. Session.ModemType == MODEM_NULL_HOST) ||
  931. (Session.Type == GAME_MODEM &&
  932. Session.ModemType == MODEM_DIALER) ) {
  933. if ( !Com_Scenario_Dialog() ) {
  934. Session.Type = Select_Serial_Dialog();
  935. if (Session.Type == GAME_NORMAL) { // user hit Cancel
  936. display = true;
  937. selection = SEL_NONE;
  938. }
  939. }
  940. } else {
  941. if ( !Com_Show_Scenario_Dialog() ) {
  942. Session.Type = Select_Serial_Dialog();
  943. if (Session.Type == GAME_NORMAL) { // user hit Cancel
  944. display = true;
  945. selection = SEL_NONE;
  946. }
  947. }
  948. }
  949. } else {
  950. Session.Type = Select_MPlayer_Game();
  951. if (Session.Type == GAME_NORMAL) { // 'Cancel'
  952. display = true;
  953. selection = SEL_NONE;
  954. }
  955. }
  956. #endif
  957. break;
  958. #ifndef WOLAPI_INTEGRATION
  959. #if defined(WIN32) && !defined(INTERNET_OFF) // Denzil 5/1/98 - Internet play
  960. /*
  961. ** Handle being spawned from WChat. Internet play based on IPX code.
  962. */
  963. case GAME_INTERNET: // ajw No longer hit.
  964. if (Special.IsFromWChat) {
  965. /*
  966. ** Give myself focus.
  967. */
  968. SetForegroundWindow ( MainWindow );
  969. ShowWindow ( MainWindow, ShowCommand );
  970. #ifdef WINSOCK_IPX
  971. if (PacketTransport ) delete PacketTransport;
  972. PacketTransport = new UDPInterfaceClass;
  973. assert ( PacketTransport != NULL);
  974. if (PacketTransport->Init()) {
  975. WWDebugString ("RA95 - About to read multiplayer settings.\n");
  976. Session.Read_MultiPlayer_Settings ();
  977. WWDebugString ("RA95 - About to call Start_Server or Start_Client.\n");
  978. PacketTransport->Start_Listening();
  979. /*
  980. ** Flush out any pending packets from a previous game.
  981. */
  982. PacketTransport->Discard_In_Buffers();
  983. PacketTransport->Discard_Out_Buffers();
  984. } else {
  985. delete PacketTransport;
  986. PacketTransport = NULL;
  987. WWDebugString ("RA95 - Winsock failed to initialise.\n");
  988. Session.Type = GAME_NORMAL;
  989. selection = SEL_EXIT;
  990. Special.IsFromWChat = false;
  991. break;
  992. }
  993. WWDebugString ("RA95 - About to call Init_Network.\n");
  994. Init_Network();
  995. #else //WINSOCK_IPX
  996. WWDebugString ("RA95 - About to initialise Winsock.\n");
  997. if (Winsock.Init()) {
  998. WWDebugString ("RA95 - About to read multiplayer settings.\n");
  999. Session.Read_MultiPlayer_Settings ();
  1000. Server = PlanetWestwoodIsHost;
  1001. WWDebugString ("RA95 - About to set addresses.\n");
  1002. Winsock.Set_Host_Address(PlanetWestwoodIPAddress);
  1003. WWDebugString ("RA95 - About to call Start_Server or Start_Client.\n");
  1004. if (Server) {
  1005. Winsock.Start_Server();
  1006. } else {
  1007. Winsock.Start_Client();
  1008. }
  1009. /*
  1010. ** Flush out any pending packets from a previous game.
  1011. */
  1012. WWDebugString ("RA95 - About to flush packet queue.\n");
  1013. WWDebugString ("RA95 - Allocating scrap memory.\n");
  1014. char *temp_buffer = new char[1024];
  1015. WWDebugString ("RA95 - Creating timer class instance.\n");
  1016. CountDownTimerClass ptimer;
  1017. WWDebugString ("RA95 - Entering read loop.\n");
  1018. while (Winsock.Read(temp_buffer, 1024)) {
  1019. WWDebugString ("RA95 - Discarding a packet.\n");
  1020. ptimer.Set (30, true);
  1021. while (ptimer.Time()) {};
  1022. WWDebugString ("RA95 - Ready to check for more packets.\n");
  1023. }
  1024. WWDebugString ("RA95 - About to delete scrap memory.\n");
  1025. delete temp_buffer;
  1026. } else {
  1027. WWDebugString ("RA95 - Winsock failed to initialise.\n");
  1028. Session.Type = GAME_NORMAL;
  1029. selection = SEL_EXIT;
  1030. Special.IsFromWChat = false;
  1031. break;
  1032. }
  1033. #endif //WINSOCK_IPX
  1034. WWDebugString ("RA95 - About to call Init_Network.\n");
  1035. Init_Network();
  1036. if (DDEServer.Get_MPlayer_Game_Info()) {
  1037. WWDebugString ("RA95 - About to call Read_Game_Options.\n");
  1038. Read_Game_Options( NULL );
  1039. } else {
  1040. Read_Game_Options( "C&CSPAWN.INI" );
  1041. }
  1042. #ifdef WINSOCK_IPX
  1043. WWDebugString ("RA95 - About to set addresses.\n");
  1044. PacketTransport->Set_Broadcast_Address (PlanetWestwoodIPAddress);
  1045. #endif //WINSOCK_IPX
  1046. if (PlanetWestwoodIsHost) {
  1047. WWDebugString ("RA95 - About to call Server_Remote_Connect.\n");
  1048. if (Server_Remote_Connect()) {
  1049. WWDebugString ("RA95 - Server_Remote_Connect returned success.\n");
  1050. break;
  1051. } else {
  1052. /*
  1053. ** We failed to connect to the other player
  1054. */
  1055. #ifdef WINSOCK_IPX
  1056. delete PacketTransport;
  1057. PacketTransport = NULL;
  1058. #else //WINSOCK_IPX
  1059. Winsock.Close();
  1060. #endif //WINSOCK_IPX
  1061. Session.Type = GAME_NORMAL;
  1062. selection = SEL_NONE;
  1063. DDEServer.Delete_MPlayer_Game_Info(); // Make sure we dont go round in an infinite loop
  1064. break;
  1065. }
  1066. } else {
  1067. WWDebugString ("RA95 - About to call Client_Remote_Connect.\n");
  1068. if (Client_Remote_Connect()) {
  1069. WWDebugString ("RA95 - Client_Remote_Connect returned success.\n");
  1070. break;
  1071. } else {
  1072. /*
  1073. ** We failed to connect to the other player
  1074. */
  1075. #ifdef WINSOCK_IPX
  1076. delete PacketTransport;
  1077. PacketTransport = NULL;
  1078. #else //WINSOCK_IPX
  1079. Winsock.Close();
  1080. #endif //WINSOCK_IPX
  1081. Session.Type = GAME_NORMAL;
  1082. selection = SEL_NONE;
  1083. DDEServer.Delete_MPlayer_Game_Info(); // Make sure we dont go round in an infinite loop
  1084. break;
  1085. }
  1086. }
  1087. } else {
  1088. Session.Type = Select_MPlayer_Game();
  1089. if (Session.Type == GAME_NORMAL) { // 'Cancel'
  1090. display = true;
  1091. selection = SEL_NONE;
  1092. }
  1093. }
  1094. break;
  1095. #endif //WIN32
  1096. #endif // !WOLAPI_INTEGRATION
  1097. }
  1098. #ifdef WOLAPI_INTEGRATION
  1099. } // if( !pWolapi )
  1100. if( pWolapi )
  1101. Session.Type = GAME_INTERNET;
  1102. #endif
  1103. //debugprint( "Session.Type = %i\n", Session.Type );
  1104. switch (Session.Type) {
  1105. /*
  1106. ** Modem, Null-Modem or internet
  1107. */
  1108. case GAME_MODEM:
  1109. case GAME_NULL_MODEM:
  1110. #ifndef WOLAPI_INTEGRATION
  1111. case GAME_INTERNET:
  1112. #endif
  1113. case GAME_SKIRMISH:
  1114. Theme.Fade_Out();
  1115. process = false;
  1116. #ifdef FIXIT_VERSION_3
  1117. Options.ScoreVolume = Options.MultiScoreVolume;
  1118. #else
  1119. Options.ScoreVolume = 0;
  1120. #endif
  1121. break;
  1122. #ifdef WOLAPI_INTEGRATION // implies also WINSOCK_IPX
  1123. case GAME_INTERNET:
  1124. if( PacketTransport )
  1125. delete PacketTransport;
  1126. PacketTransport = new UDPInterfaceClass;
  1127. assert( PacketTransport != NULL );
  1128. if( PacketTransport->Init() )
  1129. {
  1130. switch( WOL_Main() )
  1131. {
  1132. case 1:
  1133. // Start game.
  1134. #ifdef FIXIT_VERSION_3
  1135. Options.ScoreVolume = Options.MultiScoreVolume;
  1136. #else
  1137. Options.ScoreVolume = 0;
  1138. #endif
  1139. process = false;
  1140. Theme.Fade_Out();
  1141. break;
  1142. case 0:
  1143. // User cancelled.
  1144. Session.Type = GAME_NORMAL;
  1145. display = true;
  1146. selection = SEL_MULTIPLAYER_GAME; //SEL_NONE;
  1147. delete PacketTransport;
  1148. PacketTransport = NULL;
  1149. break;
  1150. case -1:
  1151. // Patch was downloaded. Exit app.
  1152. Theme.Fade_Out();
  1153. BlackPalette.Set( FADE_PALETTE_SLOW );
  1154. return false;
  1155. }
  1156. }
  1157. else
  1158. {
  1159. Session.Type = GAME_NORMAL;
  1160. display = true;
  1161. selection = SEL_MULTIPLAYER_GAME; //SEL_NONE;
  1162. delete PacketTransport;
  1163. PacketTransport = NULL;
  1164. }
  1165. break;
  1166. #endif
  1167. /*
  1168. ** Network (IPX): start a new network game.
  1169. */
  1170. case GAME_IPX:
  1171. WWDebugString ("RA95 - Game type is IPX.\n");
  1172. /*
  1173. ** Init network system & remote-connect
  1174. */
  1175. #ifdef WINSOCK_IPX
  1176. if (PacketTransport ) delete PacketTransport;
  1177. // if (WWMessageBox().Process("Select a protocol to use for network play.", "UDP", "IPX")) {
  1178. PacketTransport = new IPXInterfaceClass;
  1179. assert ( PacketTransport != NULL);
  1180. // }else{
  1181. // PacketTransport = new UDPInterfaceClass; //IPXInterfaceClass;
  1182. // assert ( PacketTransport != NULL);
  1183. // if (!Get_Broadcast_Addresses()) {
  1184. // Session.Type = GAME_NORMAL;
  1185. // display = true;
  1186. // selection = SEL_NONE;
  1187. // delete PacketTransport;
  1188. // PacketTransport = NULL;
  1189. // break;
  1190. // }
  1191. // }
  1192. #endif //WINSOCK_IPX
  1193. WWDebugString ("RA95 - About to call Init_Network.\n");
  1194. if (Session.Type == GAME_IPX && Init_Network() && Remote_Connect()) {
  1195. #ifdef FIXIT_VERSION_3
  1196. Options.ScoreVolume = Options.MultiScoreVolume;
  1197. #else
  1198. Options.ScoreVolume = 0;
  1199. #endif
  1200. process = false;
  1201. Theme.Fade_Out();
  1202. } else { // user hit cancel, or init failed
  1203. Session.Type = GAME_NORMAL;
  1204. display = true;
  1205. selection = SEL_NONE;
  1206. #ifdef WINSOCK_IPX
  1207. delete PacketTransport;
  1208. PacketTransport = NULL;
  1209. #endif //WINSOCK_IPX
  1210. }
  1211. break;
  1212. #if(TEN)
  1213. /*
  1214. ** TEN: jump straight into the game
  1215. */
  1216. case GAME_TEN:
  1217. if (Init_TEN()) {
  1218. #ifdef FIXIT_VERSION_3
  1219. Options.ScoreVolume = Options.MultiScoreVolume;
  1220. #else
  1221. Options.ScoreVolume = 0;
  1222. #endif
  1223. process = false;
  1224. Theme.Fade_Out();
  1225. } else {
  1226. WWMessageBox().Process("Unable to initialize TEN!");
  1227. //Prog_End();
  1228. Emergency_Exit(1);
  1229. }
  1230. break;
  1231. #endif // TEN
  1232. #if(MPATH)
  1233. /*
  1234. ** MPATH: jump straight into the game
  1235. */
  1236. case GAME_MPATH:
  1237. if (Init_MPATH()) {
  1238. #ifdef FIXIT_VERSION_3
  1239. Options.ScoreVolume = Options.MultiScoreVolume;
  1240. #else
  1241. Options.ScoreVolume = 0;
  1242. #endif
  1243. process = false;
  1244. Theme.Fade_Out();
  1245. } else {
  1246. WWMessageBox().Process("Unable to initialize MPATH!");
  1247. //Prog_End();
  1248. Emergency_Exit(1);
  1249. }
  1250. break;
  1251. #endif // MPATH
  1252. }
  1253. break;
  1254. /*
  1255. ** Play a VQ
  1256. */
  1257. case SEL_INTRO:
  1258. Theme.Fade_Out();
  1259. if (Debug_Flag) {
  1260. Play_Intro(Debug_Flag);
  1261. } else {
  1262. Hide_Mouse();
  1263. VisiblePage.Clear();
  1264. Show_Mouse();
  1265. Play_Movie(VQ_INTRO_MOVIE, THEME_NONE, true); // no transition picture to briefing
  1266. Keyboard->Clear();
  1267. Play_Movie(VQ_SIZZLE, THEME_NONE, true);
  1268. Play_Movie(VQ_SIZZLE2, THEME_NONE, true);
  1269. // Play_Movie(VQ_INTRO_MOVIE, THEME_NONE, false); // has transitino picture to briefing
  1270. }
  1271. Theme.Queue_Song(THEME_CRUS);
  1272. display = true;
  1273. fade = true;
  1274. selection = SEL_NONE;
  1275. break;
  1276. /*
  1277. ** Exit to DOS.
  1278. */
  1279. case SEL_EXIT:
  1280. Theme.Fade_Out();
  1281. BlackPalette.Set(FADE_PALETTE_SLOW);
  1282. return(false);
  1283. /*
  1284. ** Display the hall of fame.
  1285. */
  1286. case SEL_FAME:
  1287. break;
  1288. case SEL_TIMEOUT:
  1289. if (Session.Attract && Session.RecordFile.Is_Available()) {
  1290. Session.Play = true;
  1291. if (Session.RecordFile.Open(READ)) {
  1292. Load_Recording_Values(Session.RecordFile);
  1293. process = false;
  1294. Theme.Fade_Out();
  1295. } else {
  1296. Session.Play = 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 to load scenario
  1310. */
  1311. Scen.Set_Scenario_Name("SCG01EA.INI");
  1312. }
  1313. /*
  1314. ** Don't carry stray keystrokes into game.
  1315. */
  1316. Keyboard->Clear();
  1317. /*
  1318. ** Initialize the random number generator(s)
  1319. */
  1320. Init_Random();
  1321. /*
  1322. ** Save initialization values if we're recording this game.
  1323. */
  1324. if (Session.Record) {
  1325. if (Session.RecordFile.Open(WRITE)) {
  1326. Save_Recording_Values(Session.RecordFile);
  1327. } else {
  1328. Session.Record = false;
  1329. }
  1330. }
  1331. #ifdef FIXIT_CSII // checked - ajw 9/28/98
  1332. switch(Session.Type) {
  1333. case GAME_MODEM:
  1334. case GAME_NULL_MODEM:
  1335. case GAME_IPX:
  1336. #ifdef FIXIT_VERSION_3
  1337. if( !bAftermathMultiplayer ) {
  1338. #else
  1339. if (PlayingAgainstVersion < VERSION_AFTERMATH_CS) {
  1340. #endif
  1341. NewUnitsEnabled = SecretUnitsEnabled = false;
  1342. } else {
  1343. NewUnitsEnabled = true;
  1344. }
  1345. // debugprint( "Non Internet game: NewUnitsEnabled = %i\n", NewUnitsEnabled );
  1346. break;
  1347. case GAME_INTERNET:
  1348. #if (0)
  1349. if( !pWolapi )
  1350. {
  1351. // debugprint( "pWolapi is null on internet game!" );
  1352. Fatal( "pWolapi is null on internet game!" );
  1353. }
  1354. //if( pWolapi->bEnableNewAftermathUnits )
  1355. if( bAftermathMultiplayer )
  1356. NewUnitsEnabled = true;
  1357. else
  1358. NewUnitsEnabled = SecretUnitsEnabled = false;
  1359. // debugprint( "Internet game: NewUnitsEnabled = %i\n", NewUnitsEnabled );
  1360. #endif
  1361. break;
  1362. default:
  1363. break;
  1364. }
  1365. #endif
  1366. /*
  1367. ** Load the scenario. Specify variation 'A' for the editor; for the game,
  1368. ** don't specify a variation, to make 'Set_Scenario_Name()' pick a random one.
  1369. ** Skip this if we've already loaded a save-game.
  1370. */
  1371. if (!gameloaded && !Session.LoadGame) {
  1372. // if (Debug_Map) {
  1373. // Set_Scenario_Name(Scen.ScenarioName, Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir, SCEN_VAR_A);
  1374. // } else {
  1375. // Set_Scenario_Name(Scen.ScenarioName, Scen.Scenario, Scen.ScenPlayer, Scen.ScenDir);
  1376. // }
  1377. /*
  1378. ** Start_Scenario() changes the palette; so, fade out & clear the screen
  1379. ** before calling it.
  1380. */
  1381. Hide_Mouse();
  1382. if (selection != SEL_START_NEW_GAME) {
  1383. BlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);
  1384. #ifdef WIN32
  1385. HiddenPage.Clear();
  1386. VisiblePage.Clear();
  1387. #else
  1388. HidPage.Clear();
  1389. SeenPage.Clear();
  1390. #endif //WIN32
  1391. }
  1392. Show_Mouse();
  1393. //Mono_Printf("About to call Start Scenario with %s\n", Scen.ScenarioName);
  1394. if (!Start_Scenario(Scen.ScenarioName)) {
  1395. return(false);
  1396. }
  1397. if (Special.IsFromInstall) Show_Mouse();
  1398. Special.IsFromInstall = false;
  1399. }
  1400. /*
  1401. ** For multiplayer games, initialize the inter-player message system.
  1402. ** Do this after loading the scenario, so the map's upper-left corner is
  1403. ** properly set.
  1404. */
  1405. Session.Messages.Init(
  1406. Map.TacPixelX, Map.TacPixelY, // x,y for messages
  1407. 6, // max # msgs
  1408. MAX_MESSAGE_LENGTH-14, // max msg length
  1409. 7 * RESFACTOR, // font height in pixels
  1410. -1, -1, // x,y for edit line (appears above msgs)
  1411. 0,//BG 1, // enable edit overflow
  1412. 20, // min,
  1413. MAX_MESSAGE_LENGTH - 14, // max for trimming overflow
  1414. #ifdef WIN32
  1415. Lepton_To_Pixel(Map.TacLeptonWidth)); // Width in pixels of buffer
  1416. #else
  1417. (320-SIDEBAR_WID)); // Width in pixels of buffer
  1418. #endif
  1419. if (Session.Type != GAME_NORMAL && Session.Type != GAME_SKIRMISH &&
  1420. !Session.Play) {
  1421. if (Session.Type == GAME_TEN) {
  1422. #if(TEN)
  1423. Session.Create_TEN_Connections();
  1424. #endif // TEN
  1425. } else if (Session.Type == GAME_MPATH) {
  1426. #if(MPATH)
  1427. Session.Create_MPATH_Connections();
  1428. #endif
  1429. } else {
  1430. Session.Create_Connections();
  1431. }
  1432. }
  1433. /*
  1434. ** If this isnt an internet game that set the unit build rate to its default value
  1435. */
  1436. if (Session.Type != GAME_INTERNET){
  1437. UnitBuildPenalty = 100;
  1438. }
  1439. /*
  1440. ** Hide the SeenPage; force the map to render one frame. The caller can
  1441. ** then fade the palette in.
  1442. ** (If we loaded a game, this step will fade out the title screen. If we
  1443. ** started a scenario, Start_Scenario() will have played a couple of VQ
  1444. ** movies, which will have cleared the screen to black already.)
  1445. */
  1446. Call_Back();
  1447. Hide_Mouse();
  1448. BlackPalette.Set(FADE_PALETTE_MEDIUM, Call_Back);
  1449. // Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
  1450. #ifdef WIN32
  1451. HiddenPage.Clear();
  1452. VisiblePage.Clear();
  1453. #else
  1454. HidPage.Clear();
  1455. SeenPage.Clear();
  1456. #endif //WIN32
  1457. Show_Mouse();
  1458. Set_Logic_Page(SeenBuff);
  1459. #ifdef WIN32
  1460. /*
  1461. ** Sidebar is always active in hi-res.
  1462. */
  1463. if (!Debug_Map) {
  1464. Map.SidebarClass::Activate(1);
  1465. }
  1466. #endif //WIN32
  1467. Map.Flag_To_Redraw();
  1468. Call_Back();
  1469. Map.Render();
  1470. #ifdef WOLAPI_INTEGRATION
  1471. //ajw debugging only
  1472. // debugprint( "Debugging Session...\n" );
  1473. // debugprint( "Session.Players count is %i.\n", Session.Players.Count() );
  1474. for (i = 0; i < Session.Players.Count(); i++)
  1475. {
  1476. NetNumType net;
  1477. NetNodeType node;
  1478. Session.Players[i]->Address.Get_Address( net, node );
  1479. // debugprint( "Player %i, %s, color %i, ip %i.%i.%i.%i.%i.%i\n", i, Session.Players[i]->Name,
  1480. // Session.Players[i]->Player.Color, node[0], node[1], node[2], node[3], node[4], node[5] );
  1481. }
  1482. // debugprint( "PlanetWestwoodPortNumber is %i\n", PlanetWestwoodPortNumber );
  1483. #endif
  1484. return(true);
  1485. }
  1486. /***********************************************************************************************
  1487. * Play_Intro -- plays the introduction & logo movies *
  1488. * *
  1489. * INPUT: *
  1490. * *
  1491. * OUTPUT: *
  1492. * none. *
  1493. * *
  1494. * WARNINGS: *
  1495. * none. *
  1496. * *
  1497. * HISTORY: *
  1498. * 06/06/1995 BRR : Created. *
  1499. * 05/08/1996 JLB : Modified for Red Alert and direction control. *
  1500. *=============================================================================================*/
  1501. static void Play_Intro(bool sequenced)
  1502. {
  1503. static VQType _counter = VQ_FIRST;
  1504. Keyboard->Clear();
  1505. if (sequenced) {
  1506. if (_counter <= VQ_FIRST) _counter = VQ_COUNT;
  1507. if (_counter == VQ_COUNT) _counter--;
  1508. if (_counter == VQ_REDINTRO) _counter--;
  1509. if (_counter == VQ_TITLE) _counter--;
  1510. Hide_Mouse();
  1511. VisiblePage.Clear();
  1512. Show_Mouse();
  1513. Play_Movie(VQType(_counter--), THEME_NONE);
  1514. // Show_Mouse();
  1515. } else {
  1516. Hide_Mouse();
  1517. VisiblePage.Clear();
  1518. Show_Mouse();
  1519. #ifdef WIN32
  1520. Play_Movie(VQ_REDINTRO, THEME_NONE, false);
  1521. #else
  1522. Play_Movie(VQ_TITLE, THEME_NONE, false);
  1523. #endif
  1524. }
  1525. }
  1526. /***********************************************************************************************
  1527. * Anim_Init -- Initialize the VQ animation control structure. *
  1528. * *
  1529. * VQ animations are controlled by a structure passed to the VQ player. This routine *
  1530. * initializes the structure to values required by C&C. *
  1531. * *
  1532. * INPUT: none *
  1533. * *
  1534. * OUTPUT: none *
  1535. * *
  1536. * WARNINGS: Only need to call this routine once at the beginning of the game. *
  1537. * *
  1538. * HISTORY: *
  1539. * 12/20/1994 JLB : Created. *
  1540. *=============================================================================================*/
  1541. #ifdef WIN32
  1542. #ifdef MOVIE640
  1543. //GraphicBufferClass VQ640(711, 400, (void *)NULL);
  1544. #endif
  1545. #endif
  1546. void Anim_Init(void)
  1547. {
  1548. #if (0)
  1549. #ifdef WIN32
  1550. /* Configure player with INI file */
  1551. VQA_DefaultConfig(&AnimControl);
  1552. AnimControl.DrawFlags = VQACFGF_TOPLEFT;
  1553. AnimControl.DrawFlags |= VQACFGF_BUFFER;
  1554. //AnimControl.DrawFlags |= VQACFGF_NODRAW;
  1555. //BG - M. Grayford says turn this off AnimControl.DrawFlags |= VQACFGF_NOSKIP;
  1556. AnimControl.DrawFlags |= VQACFGF_NOSKIP;
  1557. AnimControl.FrameRate = -1;
  1558. AnimControl.DrawRate = -1;
  1559. AnimControl.DrawerCallback = VQ_Call_Back;
  1560. AnimControl.ImageWidth = 320;
  1561. AnimControl.ImageHeight = 200;
  1562. AnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();
  1563. #ifdef MOVIE640
  1564. if(IsVQ640) {
  1565. AnimControl.ImageWidth = 711;
  1566. AnimControl.ImageHeight = 400;
  1567. AnimControl.ImageBuf = (unsigned char *)VQ640.Get_Offset();
  1568. }
  1569. #endif
  1570. AnimControl.Vmode = 0;
  1571. AnimControl.OptionFlags |= VQAOPTF_CAPTIONS|VQAOPTF_EVA;
  1572. if (SlowPalette) {
  1573. AnimControl.OptionFlags |= VQAOPTF_SLOWPAL;
  1574. }
  1575. AnimControl.SoundObject = SoundObject;
  1576. AnimControl.PrimaryBufferPtr = PrimaryBufferPtr;
  1577. if (MonoClass::Is_Enabled()) {
  1578. AnimControl.OptionFlags |= VQAOPTF_MONO;
  1579. }
  1580. #else //WIN32
  1581. /* Configure player with INI file */
  1582. VQA_DefaultConfig(&AnimControl);
  1583. // void const * font = Load_Font(FONT8);
  1584. // AnimControl.EVAFont = (char *)font;
  1585. // AnimControl.CapFont = (char *)font;
  1586. AnimControl.DrawerCallback = VQ_Call_Back;
  1587. AnimControl.ImageWidth = 320;
  1588. AnimControl.ImageHeight = 200;
  1589. AnimControl.Vmode = MCGA_MODE;
  1590. AnimControl.VBIBit = VertBlank;
  1591. AnimControl.DrawFlags |= VQACFGF_TOPLEFT;
  1592. AnimControl.OptionFlags |= VQAOPTF_HMIINIT|VQAOPTF_CAPTIONS|VQAOPTF_EVA;
  1593. // AnimControl.AudioBuf = (unsigned char *)HidPage.Get_Buffer();
  1594. // AnimControl.AudioBufSize = 32768U;
  1595. AnimControl.DigiCard = NewConfig.DigitCard;
  1596. AnimControl.HMIBufSize = 8192;
  1597. AnimControl.DigiHandle = Get_Digi_Handle();
  1598. AnimControl.Volume = 0x00FF;
  1599. AnimControl.AudioRate = 22050;
  1600. // if (NewConfig.Speed) AnimControl.AudioRate = 11025;
  1601. if (!Debug_Quiet && Get_Digi_Handle() != -1) {
  1602. AnimControl.OptionFlags |= VQAOPTF_AUDIO;
  1603. }
  1604. if (MonoClass::Is_Enabled()) {
  1605. AnimControl.OptionFlags |= VQAOPTF_MONO;
  1606. }
  1607. #endif //WIN32
  1608. #endif
  1609. }
  1610. /***********************************************************************************************
  1611. * Parse_Command_Line -- Parses the command line parameters. *
  1612. * *
  1613. * This routine should be called before the graphic mode is initialized. It examines the *
  1614. * command line parameters and sets the appropriate globals. If there is an error, then *
  1615. * it outputs a command summary and then returns false. *
  1616. * *
  1617. * INPUT: argc -- The number of command line arguments. *
  1618. * *
  1619. * argv -- Pointer to character string array that holds the individual arguments. *
  1620. * *
  1621. * OUTPUT: bool; Was the command line parsed successfully? *
  1622. * *
  1623. * WARNINGS: none *
  1624. * *
  1625. * HISTORY: *
  1626. * 03/18/1995 JLB : Created. *
  1627. *=============================================================================================*/
  1628. bool Parse_Command_Line(int argc, char * argv[])
  1629. {
  1630. /*
  1631. ** Parse the command line and set globals to reflect the parameters
  1632. ** passed in.
  1633. */
  1634. Whom = HOUSE_GOOD;
  1635. Special.Init();
  1636. Debug_Map = false;
  1637. Debug_Unshroud = false;
  1638. for (int index = 1; index < argc; index++) {
  1639. char * string; // Pointer to argument.
  1640. long code = 0;
  1641. char arg_string[512];
  1642. int str_len = strlen(argv[index]);
  1643. char *src = argv[index];
  1644. char *dest = arg_string;
  1645. for (int i=0 ; i<str_len ; i++) {
  1646. if (*src == '\"') {
  1647. src++;
  1648. } else {
  1649. *dest++ = *src++;
  1650. }
  1651. }
  1652. *dest++ = 0;
  1653. string = arg_string;
  1654. strupr(string);
  1655. //string = strupr(argv[index]);
  1656. /*
  1657. ** Print usage text only if requested.
  1658. */
  1659. if (stricmp("/?", string) == 0 || stricmp("-?", string) == 0 || stricmp("-h", string) == 0 || stricmp("/h", string) == 0) {
  1660. /*
  1661. ** Unrecognized command line parameter... Display usage
  1662. ** and then exit.
  1663. */
  1664. puts(TEXT_OPTIONS);
  1665. return(false);
  1666. }
  1667. bool processed = true;
  1668. long ob = Obfuscate(string);
  1669. /*
  1670. ** Check to see if the parameter is a cheat enabling one.
  1671. */
  1672. long const * optr = (const long*)&CheatCodes[0];
  1673. while (*optr) {
  1674. if (*optr++ == ob) {
  1675. Debug_Playtest = true;
  1676. Debug_Flag = true;
  1677. break;
  1678. }
  1679. }
  1680. /*
  1681. ** Check to see if the parameter is a cheat enabling one.
  1682. */
  1683. optr = (const long*)&PlayCodes[0];
  1684. while (*optr) {
  1685. if (*optr++ == ob) {
  1686. Debug_Playtest = true;
  1687. Debug_Flag = true;
  1688. break;
  1689. }
  1690. }
  1691. /*
  1692. ** Check to see if the parameter is a scenario editor
  1693. ** enabling one.
  1694. */
  1695. optr = (const long*)&EditorCodes[0];
  1696. while (*optr) {
  1697. if (*optr++ == ob) {
  1698. Debug_Map = true;
  1699. Debug_Unshroud = true;
  1700. Debug_Flag = true;
  1701. Debug_Playtest = true;
  1702. break;
  1703. }
  1704. }
  1705. switch (ob) {
  1706. #ifdef VIRGIN_CHEAT_KEYS
  1707. case PARM_PLAYTEST:
  1708. Debug_Playtest = true;
  1709. break;
  1710. #endif
  1711. /*
  1712. ** Special flag - is C&C being run from the install program?
  1713. */
  1714. case PARM_INSTALL:
  1715. Special.IsFromInstall = true;
  1716. // If uncommented, will disable the <ESC> key during the first movie run.
  1717. // BreakoutAllowed = false;
  1718. break;
  1719. #if(TEN)
  1720. case PARM_ALLOW_SOLO:
  1721. Session.AllowSolo = 1;
  1722. break;
  1723. #endif
  1724. #if(MPATH)
  1725. case PARM_ALLOW_SOLO:
  1726. Session.AllowSolo = 1;
  1727. break;
  1728. #endif
  1729. default:
  1730. processed = false;
  1731. break;
  1732. }
  1733. if (processed) continue;
  1734. #ifdef CHEAT_KEYS
  1735. /*
  1736. ** Scenario Editor Mode
  1737. */
  1738. if (stricmp(string, "-CHECKMAP") == 0) {
  1739. Debug_Check_Map = true;
  1740. continue;
  1741. }
  1742. #endif
  1743. /*
  1744. ** File search path override.
  1745. */
  1746. if (strstr(string, "-CD")) {
  1747. CCFileClass::Set_Search_Drives(&string[3]);
  1748. continue;
  1749. }
  1750. #if (0)
  1751. /*
  1752. ** Build speed modifier
  1753. */
  1754. if (strstr (string, "-UNITRATE:")){
  1755. int unit_rate;
  1756. sscanf (string, "-UNITRATE:%d", &unit_rate);
  1757. UnitBuildPenalty = unit_rate;
  1758. }
  1759. #endif //(0)
  1760. /*
  1761. ** Specify destination connection for network play
  1762. */
  1763. if (strstr(string, "-DESTNET")) {
  1764. NetNumType net;
  1765. NetNodeType node;
  1766. /*
  1767. ** Scan the command-line string, pulling off each address piece
  1768. */
  1769. int i = 0;
  1770. char * p = strtok(string + 8, ".");
  1771. while (p) {
  1772. int x;
  1773. sscanf(p, "%x", &x); // convert from hex string to int
  1774. if (i < 4) {
  1775. net[i] = (char)x; // fill NetNum
  1776. } else {
  1777. node[i-4] = (char)x; // fill NetNode
  1778. }
  1779. i++;
  1780. p = strtok(NULL, ".");
  1781. }
  1782. /*
  1783. ** If all the address components were successfully read, fill in the
  1784. ** BridgeNet with a broadcast address to the network across the bridge.
  1785. */
  1786. if (i >= 4) {
  1787. Session.IsBridge = 1;
  1788. memset(node, 0xff, 6);
  1789. Session.BridgeNet = IPXAddressClass(net, node);
  1790. }
  1791. continue;
  1792. }
  1793. /*
  1794. ** Specify socket ID, as an offset from 0x4000.
  1795. */
  1796. if (strstr(string, "-SOCKET")) {
  1797. unsigned short socket;
  1798. socket = (unsigned short)(atoi(string + strlen("SOCKET")));
  1799. socket += 0x4000;
  1800. if (socket >= 0x4000 && socket < 0x8000) {
  1801. Ipx.Set_Socket (socket);
  1802. }
  1803. continue;
  1804. }
  1805. /*
  1806. ** Set the Net Stealth option
  1807. */
  1808. if (strstr(string, "-STEALTH")) {
  1809. Session.NetStealth = true;
  1810. continue;
  1811. }
  1812. /*
  1813. ** Set the Net Protection option
  1814. */
  1815. if (strstr(string, "-MESSAGES")) {
  1816. Session.NetProtect = false;
  1817. continue;
  1818. }
  1819. /*
  1820. ** Allow "attract" mode
  1821. */
  1822. if (strstr(string, "-ATTRACT")) {
  1823. Session.Attract = true;
  1824. continue;
  1825. }
  1826. #ifdef WIN32
  1827. /*
  1828. ** Set screen to 640x480 instead of 640x400
  1829. */
  1830. if (strstr(string, "-480")) {
  1831. ScreenHeight = 480;
  1832. continue;
  1833. }
  1834. /*
  1835. ** Check for spawn from WChat
  1836. */
  1837. #ifndef FIXIT_VERSION_3 // WChat eliminated.
  1838. if (strstr(string,"-WCHAT")){
  1839. SpawnedFromWChat = true;
  1840. }
  1841. #endif
  1842. #endif
  1843. #ifdef CHEAT_KEYS
  1844. /*
  1845. ** Specify the random number seed (for debugging)
  1846. */
  1847. if (strstr(string, "-SEED")) {
  1848. CustomSeed = (unsigned short)(atoi(string + strlen("SEED")));
  1849. continue;
  1850. }
  1851. #ifndef WIN32
  1852. /*
  1853. ** Don't install Page Fault Handler (MUST use this for debugger)
  1854. */
  1855. if (stricmp(string, "-NOPFS") == 0) {
  1856. UsePageFaultHandler = 0;
  1857. continue;
  1858. }
  1859. #endif
  1860. #endif
  1861. #if(TEN)
  1862. /*
  1863. ** Enable TEN
  1864. */
  1865. if (strstr(string, "TEN")) {
  1866. #ifdef CHEAT_KEYS
  1867. Debug_Flag = true;
  1868. MonoClass::Enable();
  1869. #endif
  1870. Session.Type = GAME_TEN;
  1871. Special.IsFromInstall = false;
  1872. //
  1873. // Create the Ten network manager. This allows us to keep
  1874. // the packet queues clean even while we're initializing the game,
  1875. // so the queues don't fill up in case we're slow, or the user
  1876. // didn't insert a CD.
  1877. //
  1878. Ten = new TenConnManClass();
  1879. Ten->Init();
  1880. strcpy(Session.OptionsFile, "OPTIONS.INI");
  1881. Ten->Flush_All();
  1882. continue;
  1883. }
  1884. /*
  1885. ** Set the game options filename
  1886. */
  1887. if (strstr(string, "OPTIONS:")) {
  1888. strcpy(Session.OptionsFile, string + 8);
  1889. continue;
  1890. }
  1891. #endif // TEN
  1892. #if(MPATH)
  1893. /*
  1894. ** Enable MPATH
  1895. */
  1896. if (strstr(string, "MPATH")) {
  1897. #ifdef CHEAT_KEYS
  1898. Debug_Flag = true;
  1899. MonoClass::Enable();
  1900. #endif
  1901. Session.Type = GAME_MPATH;
  1902. Special.IsFromInstall = false;
  1903. //
  1904. // Create the MPath network manager. This allows us to keep
  1905. // the packet queues clean even while we're initializing the game,
  1906. // so the queues don't fill up in case we're slow, or the user
  1907. // didn't insert a CD.
  1908. //
  1909. MPath = new MPlayerManClass();
  1910. MPath->Init();
  1911. strcpy(Session.OptionsFile, "OPTIONS.INI");
  1912. MPath->Flush_All();
  1913. continue;
  1914. }
  1915. /*
  1916. ** Set the game options filename
  1917. */
  1918. if (strstr(string, "OPTIONS:")) {
  1919. strcpy(Session.OptionsFile, string + 8);
  1920. continue;
  1921. }
  1922. #endif // MPATH
  1923. #ifdef NEVER
  1924. /*
  1925. ** Handle the prog init differently in this case.
  1926. */
  1927. if (strstr(string, "-V")) {
  1928. continue;
  1929. }
  1930. #endif
  1931. /*
  1932. ** look for passed-in video mode to default to
  1933. */
  1934. #ifndef WIN32
  1935. if (strnicmp(string, "-V", strlen("-V")) == 0) {
  1936. Set_Video_Mode(MCGA_MODE); // do this to get around first_time variable...
  1937. Set_Original_Video_Mode(atoi(string+2));
  1938. continue;
  1939. }
  1940. #endif
  1941. #ifdef CHEAT_KEYS
  1942. if (strstr(string,"-NOMOVIES")){
  1943. bNoMovies = true;
  1944. }
  1945. #endif
  1946. /*
  1947. ** Special command line control parsing.
  1948. */
  1949. if (strnicmp(string, "-X", strlen("-O")) == 0) {
  1950. string += strlen("-X");
  1951. while (*string) {
  1952. char code = *string++;
  1953. switch (toupper(code)) {
  1954. #ifdef CHEAT_KEYS
  1955. /*
  1956. ** Monochrome debug screen enable.
  1957. */
  1958. case 'M':
  1959. MonoClass::Enable();
  1960. break;
  1961. /*
  1962. ** Inert weapons -- no units take damage.
  1963. */
  1964. case 'I':
  1965. Special.IsInert = true;
  1966. break;
  1967. /*
  1968. ** Hussled recharge timer.
  1969. */
  1970. case 'H':
  1971. Special.IsSpeedBuild = true;
  1972. break;
  1973. /*
  1974. ** "Record" a multi-player game
  1975. */
  1976. case 'X':
  1977. Session.Record = 1;
  1978. break;
  1979. /*
  1980. ** "Play Back" a multi-player game
  1981. */
  1982. case 'Y':
  1983. Session.Play = 1;
  1984. break;
  1985. /*
  1986. ** Print lots of debug stuff about events & packets
  1987. */
  1988. case 'P':
  1989. Debug_Print_Events = true;
  1990. break;
  1991. #endif
  1992. /*
  1993. ** Quiet mode override control.
  1994. */
  1995. case 'Q':
  1996. Debug_Quiet = true;
  1997. break;
  1998. default:
  1999. puts(TEXT_INVALID);
  2000. return(false);
  2001. }
  2002. }
  2003. continue;
  2004. }
  2005. }
  2006. return(true);
  2007. }
  2008. /***********************************************************************************************
  2009. * Obfuscate -- Sufficiently transform parameter to thwart casual hackers. *
  2010. * *
  2011. * This routine borrows from CRC and PGP technology to sufficiently alter the parameter *
  2012. * in order to make it difficult to reverse engineer the key phrase. This is designed to *
  2013. * be used for hidden game options that will be released at a later time over Westwood's *
  2014. * Web page or through magazine hint articles. *
  2015. * *
  2016. * This algorithm is cryptographically categorized as a "one way hash". *
  2017. * *
  2018. * Since this is a one way transformation, it becomes much more difficult to reverse *
  2019. * engineer the pass phrase even if the resultant pass code is known. This has an added *
  2020. * benefit of making this algorithm immune to traditional cryptographic attacks. *
  2021. * *
  2022. * The largest strength of this transformation algorithm lies in the restriction on the *
  2023. * source vector being legal ASCII uppercase characters. This restriction alone makes even *
  2024. * a simple CRC transformation practically impossible to reverse engineer. This algorithm *
  2025. * uses far more than a simple CRC transformation to achieve added strength from advanced *
  2026. * attack methods. *
  2027. * *
  2028. * INPUT: string -- Pointer to the key phrase that will be transformed into a code. *
  2029. * *
  2030. * OUTPUT: Returns with the code that the key phrase is translated into. *
  2031. * *
  2032. * WARNINGS: A zero length pass phrase results in a 0x00000000 result code. *
  2033. * *
  2034. * HISTORY: *
  2035. * 08/19/1995 JLB : Created. *
  2036. *=============================================================================================*/
  2037. long Obfuscate(char const * string)
  2038. {
  2039. char buffer[1024];
  2040. if (!string) return(0);
  2041. memset(buffer, '\xA5', sizeof(buffer));
  2042. /*
  2043. ** Copy key phrase into a working buffer. This hides any transformation done
  2044. ** to the string.
  2045. */
  2046. strncpy(buffer, string, sizeof(buffer));
  2047. buffer[sizeof(buffer)-1] = '\0';
  2048. int length = strlen(buffer);
  2049. /*
  2050. ** Only upper case letters are significant.
  2051. */
  2052. strupr(buffer);
  2053. /*
  2054. ** Ensure that only visible ASCII characters compose the key phrase. This
  2055. ** discourages the direct forced illegal character input method of attack.
  2056. */
  2057. int index;
  2058. for (index = 0; index < length; index++) {
  2059. if (!isgraph(buffer[index])) {
  2060. buffer[index] = 'A' + (index%26);
  2061. }
  2062. }
  2063. /*
  2064. ** Increase the strength of even short pass phrases by extending the
  2065. ** length to be at least a minimum number of characters. This helps prevent
  2066. ** a weak pass phrase from compromising the obfuscation process. This
  2067. ** process also forces the key phrase to be an even multiple of four.
  2068. ** This is necessary to support the cypher process that occurs later.
  2069. */
  2070. if (length < 16 || (length & 0x03)) {
  2071. int maxlen = 16;
  2072. if (((length+3) & 0x00FC) > maxlen) {
  2073. maxlen = ((length+3) & 0x00FC);
  2074. }
  2075. for (index = length; index < maxlen; index++) {
  2076. buffer[index] = 'A' + ((('?' ^ buffer[index-length]) + index) % 26);
  2077. }
  2078. length = index;
  2079. buffer[length] = '\0';
  2080. }
  2081. /*
  2082. ** Transform the buffer into a number. This transformation is character
  2083. ** order dependant.
  2084. */
  2085. long code = Calculate_CRC(buffer, length);
  2086. /*
  2087. ** Record a copy of this initial transformation to be used in a later
  2088. ** self referential transformation.
  2089. */
  2090. long copy = code;
  2091. /*
  2092. ** Reverse the character string and combine with the previous transformation.
  2093. ** This doubles the workload of trying to reverse engineer the CRC calculation.
  2094. */
  2095. strrev(buffer);
  2096. code ^= Calculate_CRC(buffer, length);
  2097. /*
  2098. ** Perform a self referential transformation. This makes a reverse engineering
  2099. ** by using a cause and effect attack more difficult.
  2100. */
  2101. code = code ^ copy;
  2102. /*
  2103. ** Unroll and combine the code value into the pass phrase and then perform
  2104. ** another self referential transformation. Although this is a trivial cypher
  2105. ** process, it gives the sophisticated hacker false hope since the strong
  2106. ** cypher process occurs later.
  2107. */
  2108. strrev(buffer); // Restore original string order.
  2109. for (index = 0; index < length; index++) {
  2110. code ^= (unsigned char)buffer[index];
  2111. unsigned char temp = (unsigned char)code;
  2112. buffer[index] ^= temp;
  2113. code >>= 8;
  2114. code |= (((long)temp)<<24);
  2115. }
  2116. /*
  2117. ** Introduce loss into the vector. This strengthens the key against traditional
  2118. ** cryptographic attack engines. Since this also weakens the key against
  2119. ** unconventional attacks, the loss is limited to less than 10%.
  2120. */
  2121. for (index = 0; index < length; index++) {
  2122. static unsigned char _lossbits[] = {0x00,0x08,0x00,0x20,0x00,0x04,0x10,0x00};
  2123. static unsigned char _addbits[] = {0x10,0x00,0x00,0x80,0x40,0x00,0x00,0x04};
  2124. buffer[index] |= _addbits[index % (sizeof(_addbits)/sizeof(_addbits[0]))];
  2125. buffer[index] &= ~_lossbits[index % (sizeof(_lossbits)/sizeof(_lossbits[0]))];
  2126. }
  2127. /*
  2128. ** Perform a general cypher transformation on the vector
  2129. ** and use the vector itself as the cypher key. This is a variation on the
  2130. ** cypher process used in PGP. It is a very strong cypher process with no known
  2131. ** weaknesses. However, in this case, the cypher key is the vector itself and this
  2132. ** opens up a weakness against attacks that have access to this transformation
  2133. ** algorithm. The sheer workload of reversing this transformation should be enough
  2134. ** to discourage even the most determined hackers.
  2135. */
  2136. for (index = 0; index < length; index += 4) {
  2137. short key1 = buffer[index];
  2138. short key2 = buffer[index+1];
  2139. short key3 = buffer[index+2];
  2140. short key4 = buffer[index+3];
  2141. short val1 = key1;
  2142. short val2 = key2;
  2143. short val3 = key3;
  2144. short val4 = key4;
  2145. val1 *= key1;
  2146. val2 += key2;
  2147. val3 += key3;
  2148. val4 *= key4;
  2149. short s3 = val3;
  2150. val3 ^= val1;
  2151. val3 *= key1;
  2152. short s2 = val2;
  2153. val2 ^= val4;
  2154. val2 += val3;
  2155. val2 *= key3;
  2156. val3 += val2;
  2157. val1 ^= val2;
  2158. val4 ^= val3;
  2159. val2 ^= s3;
  2160. val3 ^= s2;
  2161. buffer[index] = val1;
  2162. buffer[index+1] = val2;
  2163. buffer[index+2] = val3;
  2164. buffer[index+3] = val4;
  2165. }
  2166. /*
  2167. ** Convert this final vector into a cypher key code to be
  2168. ** returned by this routine.
  2169. */
  2170. code = Calculate_CRC(buffer, length);
  2171. /*
  2172. ** Return the final code value.
  2173. */
  2174. return(code);
  2175. }
  2176. /***********************************************************************************************
  2177. * Calculate_CRC -- Calculates a one-way hash from a data block. *
  2178. * *
  2179. * This routine is used to create a hash value from a data block. The algorithm is similar *
  2180. * to a CRC, but is faster. *
  2181. * *
  2182. * INPUT: buffer -- Pointer to a buffer of data to be 'hashed'. *
  2183. * *
  2184. * len -- The length of the buffer to compute the hash upon. *
  2185. * *
  2186. * OUTPUT: Returns with a 32bit hash value calculated from the specified buffer. *
  2187. * *
  2188. * WARNINGS: none *
  2189. * *
  2190. * HISTORY: *
  2191. * 03/02/1996 JLB : Created. *
  2192. *=============================================================================================*/
  2193. extern "C" {
  2194. long Calculate_CRC(void * buffer, long len)
  2195. {
  2196. return(CRCEngine()(buffer, len));
  2197. }
  2198. }
  2199. /***************************************************************************
  2200. * Init_Random -- Initializes the random-number generator *
  2201. * *
  2202. * INPUT: *
  2203. * none. *
  2204. * *
  2205. * OUTPUT: *
  2206. * none. *
  2207. * *
  2208. * WARNINGS: *
  2209. * none. *
  2210. * *
  2211. * HISTORY: *
  2212. * 12/04/1995 BRR : Created. *
  2213. *=========================================================================*/
  2214. void Init_Random(void)
  2215. {
  2216. #ifdef WIN32
  2217. /*
  2218. ** Gather some "random" bits from the system timer. Actually, only the
  2219. ** low order millisecond bits are secure. The other bits could be
  2220. ** easily guessed from the system clock (most clocks are fairly accurate
  2221. ** and thus predictable).
  2222. */
  2223. SYSTEMTIME t;
  2224. GetSystemTime(&t);
  2225. CryptRandom.Seed_Byte(t.wMilliseconds);
  2226. CryptRandom.Seed_Bit(t.wSecond);
  2227. CryptRandom.Seed_Bit(t.wSecond>>1);
  2228. CryptRandom.Seed_Bit(t.wSecond>>2);
  2229. CryptRandom.Seed_Bit(t.wSecond>>3);
  2230. CryptRandom.Seed_Bit(t.wSecond>>4);
  2231. CryptRandom.Seed_Bit(t.wMinute);
  2232. CryptRandom.Seed_Bit(t.wMinute>>1);
  2233. CryptRandom.Seed_Bit(t.wMinute>>2);
  2234. CryptRandom.Seed_Bit(t.wMinute>>3);
  2235. CryptRandom.Seed_Bit(t.wMinute>>4);
  2236. CryptRandom.Seed_Bit(t.wHour);
  2237. CryptRandom.Seed_Bit(t.wDay);
  2238. CryptRandom.Seed_Bit(t.wDayOfWeek);
  2239. CryptRandom.Seed_Bit(t.wMonth);
  2240. CryptRandom.Seed_Bit(t.wYear);
  2241. #else
  2242. /*
  2243. ** Gather some "random" bits from the DOS mode timer.
  2244. */
  2245. struct timeb t;
  2246. ftime(&t);
  2247. CryptRandom.Seed_Byte(t.millitm);
  2248. CryptRandom.Seed_Byte(t.time);
  2249. #endif
  2250. #ifdef FIXIT_MULTI_SAVE
  2251. //
  2252. // If we've loaded a multiplayer save game, return now; the random #
  2253. // class is loaded along with ScenarioClass.
  2254. //
  2255. if (Session.LoadGame) {
  2256. return;
  2257. }
  2258. //
  2259. // If we're playing a recording, the Seed is loaded in
  2260. // Load_Recording_Values(). Just init the random # and return.
  2261. //
  2262. if (Session.Play) {
  2263. RandNumb = Seed;
  2264. Scen.RandomNumber = Seed;
  2265. return;
  2266. }
  2267. #else
  2268. /*
  2269. ** Do nothing if we've loaded a multiplayer game, or we're playing back
  2270. ** a recording; the random number generator is initialized by loading
  2271. ** the game.
  2272. */
  2273. if (Session.LoadGame || Session.Play) {
  2274. RandNumb = Seed;
  2275. Scen.RandomNumber = Seed;
  2276. return;
  2277. }
  2278. #endif // FIXIT_MULTI_SAVE
  2279. /*
  2280. ** Initialize the random number Seed. For multiplayer, this will have been done
  2281. ** in the connection dialogs. For single-player games, AND if we're not playing
  2282. ** back a recording, init the Seed to a random value.
  2283. */
  2284. if (Session.Type == GAME_NORMAL || Session.Type == GAME_SKIRMISH &&
  2285. !Session.Play) {
  2286. /*
  2287. ** Set the optional user-specified seed
  2288. */
  2289. if (CustomSeed != 0) {
  2290. Seed = CustomSeed;
  2291. } else {
  2292. srand(time(NULL));
  2293. Seed = rand();
  2294. }
  2295. }
  2296. /*
  2297. ** Initialize the random-number generators
  2298. */
  2299. Scen.RandomNumber = Seed;
  2300. RandNumb = Seed;
  2301. }
  2302. /***********************************************************************************************
  2303. * Load_Title_Page -- Load the background art for the title page. *
  2304. * *
  2305. * This routine will load the background art in a machine independent format. There is *
  2306. * different art required for the hi-res and lo-res versions of the game. *
  2307. * *
  2308. * INPUT: visible -- Should the title page art be copied to the visible page by this *
  2309. * routine? *
  2310. * *
  2311. * OUTPUT: none *
  2312. * *
  2313. * WARNINGS: Be sure the mouse is hidden if the image is to be copied to the visible page. *
  2314. * *
  2315. * HISTORY: *
  2316. * 06/03/1996 JLB : Created. *
  2317. *=============================================================================================*/
  2318. void Load_Title_Page(bool visible)
  2319. {
  2320. #ifdef WIN32
  2321. Load_Title_Screen("TITLE.PCX", &HidPage, (unsigned char*)CCPalette.Get_Data());
  2322. if (visible) {
  2323. HidPage.Blit(SeenPage);
  2324. }
  2325. #else
  2326. Load_Picture("TITLE.CPS", HidPage, HidPage, CCPalette, BM_DEFAULT);
  2327. if (visible) {
  2328. HidPage.Blit(SeenPage);
  2329. }
  2330. #endif
  2331. }
  2332. /***********************************************************************************************
  2333. * Init_Color_Remaps -- Initialize the text remap tables. *
  2334. * *
  2335. * There are various color scheme remap tables that are dependant upon the color remap *
  2336. * information embedded within the palette control file. This routine will fetch that *
  2337. * data and build the text remap tables as indicated. *
  2338. * *
  2339. * INPUT: none *
  2340. * *
  2341. * OUTPUT: none *
  2342. * *
  2343. * WARNINGS: none *
  2344. * *
  2345. * HISTORY: *
  2346. * 06/03/1996 JLB : Created. *
  2347. * 09/11/2019 ST : The default resolution doesn't have to match the size of the palette image*
  2348. *=============================================================================================*/
  2349. static void Init_Color_Remaps(void)
  2350. {
  2351. /*
  2352. ** Setup the remap tables. PALETTE.CPS contains a special set of pixels in
  2353. ** the upper-left corner. Each row of 16 pixels is one range of colors. The
  2354. ** first row represents unity (the default color units are drawn in); rows
  2355. ** after that are the remap colors.
  2356. */
  2357. #ifdef WIN32
  2358. GraphicBufferClass temp_page(320, 200, (void*)NULL);
  2359. temp_page.Clear();
  2360. Load_Picture("PALETTE.CPS", temp_page, temp_page, NULL, BM_DEFAULT);
  2361. temp_page.Blit(HidPage);
  2362. #else
  2363. Load_Picture("PALETTE.CPS", HidPage, HidPage, NULL, BM_DEFAULT);
  2364. #endif
  2365. for (PlayerColorType pcolor = PCOLOR_FIRST; pcolor < PCOLOR_COUNT; pcolor++) {
  2366. unsigned char * ptr = ColorRemaps[pcolor].RemapTable;
  2367. for (int color = 0; color < 256; color++) {
  2368. ptr[color] = color;
  2369. }
  2370. int index;
  2371. for (index = 0; index < 16; index++) {
  2372. ptr[HidPage.Get_Pixel(index, 0)] = HidPage.Get_Pixel(index, pcolor);
  2373. }
  2374. for (index = 0; index < 6; index++) {
  2375. ColorRemaps[pcolor].FontRemap[10+index] = HidPage.Get_Pixel(2+index, pcolor);
  2376. }
  2377. ColorRemaps[pcolor].BrightColor = WHITE;
  2378. // ColorRemaps[pcolor].BrightColor = HidPage.Get_Pixel(1, pcolor);
  2379. ColorRemaps[pcolor].Color = HidPage.Get_Pixel(4, pcolor);
  2380. ColorRemaps[pcolor].Shadow = HidPage.Get_Pixel(10, pcolor);
  2381. ColorRemaps[pcolor].Background = HidPage.Get_Pixel(9, pcolor);
  2382. ColorRemaps[pcolor].Corners = HidPage.Get_Pixel(7, pcolor);
  2383. ColorRemaps[pcolor].Highlight = HidPage.Get_Pixel(4, pcolor);
  2384. ColorRemaps[pcolor].Bright = HidPage.Get_Pixel(0, pcolor);
  2385. ColorRemaps[pcolor].Underline = HidPage.Get_Pixel(0, pcolor);
  2386. ColorRemaps[pcolor].Bar = HidPage.Get_Pixel(6, pcolor);
  2387. /*
  2388. ** This must grab from column 4 because the multiplayer color dialog palette counts
  2389. ** on this to be true.
  2390. */
  2391. ColorRemaps[pcolor].Box = HidPage.Get_Pixel(4, pcolor);
  2392. }
  2393. /* 12/9/2019 SKY - Swap Blue and Grey color remaps */
  2394. {
  2395. RemapControlType temp;
  2396. memcpy(&temp, &ColorRemaps[PCOLOR_BLUE], sizeof(RemapControlType));
  2397. memcpy(&ColorRemaps[PCOLOR_BLUE], &ColorRemaps[PCOLOR_GREY], sizeof(RemapControlType));
  2398. memcpy(&ColorRemaps[PCOLOR_GREY], &temp, sizeof(RemapControlType));
  2399. }
  2400. /*
  2401. ** Now do the special dim grey scheme
  2402. */
  2403. for (int color = 0; color < 256; color++) {
  2404. GreyScheme.RemapTable[color] = color;
  2405. }
  2406. for (int index = 0; index < 6; index++) {
  2407. GreyScheme.FontRemap[10+index] = HidPage.Get_Pixel(9+index, PCOLOR_GREY) & 0x00FF;
  2408. }
  2409. GreyScheme.BrightColor = HidPage.Get_Pixel(3, PCOLOR_GREY) & 0x00FF;
  2410. GreyScheme.Color = HidPage.Get_Pixel(7, PCOLOR_GREY) & 0x00FF;
  2411. GreyScheme.Shadow = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(15, PCOLOR_GREY) & 0x00FF];
  2412. GreyScheme.Background = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(14, PCOLOR_GREY) & 0x00FF];
  2413. GreyScheme.Corners = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(13, PCOLOR_GREY) & 0x00FF];
  2414. GreyScheme.Highlight = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(9, PCOLOR_GREY) & 0x00FF];
  2415. GreyScheme.Bright = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(5, PCOLOR_GREY) & 0x00FF];
  2416. GreyScheme.Underline = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(5, PCOLOR_GREY) & 0x00FF];
  2417. GreyScheme.Bar = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(11, PCOLOR_GREY) & 0x00FF];
  2418. GreyScheme.Box = ColorRemaps[PCOLOR_GREY].RemapTable[HidPage.Get_Pixel(11, PCOLOR_GREY) & 0x00FF];
  2419. /*
  2420. ** Set up the metallic remap table for the font that prints over the tabs
  2421. */
  2422. memset ((void*)&MetalScheme, 4, sizeof(MetalScheme));
  2423. for (int color_counter = 0; color_counter < 16; color_counter++) {
  2424. MetalScheme.FontRemap[color_counter] = color_counter;
  2425. }
  2426. MetalScheme.FontRemap[1] = 128;
  2427. MetalScheme.FontRemap[2] = 12;
  2428. MetalScheme.FontRemap[3] = 13;
  2429. MetalScheme.FontRemap[4] = 14;
  2430. MetalScheme.Color = 128;
  2431. MetalScheme.Background = 0;
  2432. MetalScheme.Underline = 128;
  2433. /*
  2434. ** Set up the font remap table for the mission briefing font
  2435. */
  2436. for (int colr = 0; colr < 16; colr++) {
  2437. ColorRemaps[PCOLOR_TYPE].FontRemap[colr] = HidPage.Get_Pixel(colr, PCOLOR_TYPE);
  2438. }
  2439. ColorRemaps[PCOLOR_TYPE].Shadow = 11;
  2440. ColorRemaps[PCOLOR_TYPE].Background = 10;
  2441. ColorRemaps[PCOLOR_TYPE].Corners = 10;
  2442. ColorRemaps[PCOLOR_TYPE].Highlight = 9;
  2443. ColorRemaps[PCOLOR_TYPE].Bright = 15;
  2444. ColorRemaps[PCOLOR_TYPE].Underline = 11;
  2445. ColorRemaps[PCOLOR_TYPE].Bar = 11;
  2446. ColorRemaps[PCOLOR_TYPE].Box = 10;
  2447. ColorRemaps[PCOLOR_TYPE].BrightColor = 15;
  2448. ColorRemaps[PCOLOR_TYPE].Color = 9;
  2449. GadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_DIALOG_BLUE]);
  2450. // GadgetClass::Set_Color_Scheme(&ColorRemaps[PCOLOR_BLUE]);
  2451. }
  2452. /***********************************************************************************************
  2453. * Init_Heaps -- Initialize the game heaps and buffers. *
  2454. * *
  2455. * This routine will allocate the game heaps and buffers. The rules file has already been *
  2456. * processed by the time that this routine is called. *
  2457. * *
  2458. * INPUT: none *
  2459. * *
  2460. * OUTPUT: none *
  2461. * *
  2462. * WARNINGS: none *
  2463. * *
  2464. * HISTORY: *
  2465. * 06/03/1996 JLB : Created. *
  2466. *=============================================================================================*/
  2467. static void Init_Heaps(void)
  2468. {
  2469. /*
  2470. ** Initialize the game object heaps.
  2471. */
  2472. Vessels.Set_Heap(Rule.VesselMax);
  2473. Units.Set_Heap(Rule.UnitMax);
  2474. Factories.Set_Heap(Rule.FactoryMax);
  2475. Terrains.Set_Heap(Rule.TerrainMax);
  2476. Templates.Set_Heap(Rule.TemplateMax);
  2477. Smudges.Set_Heap(Rule.SmudgeMax);
  2478. Overlays.Set_Heap(Rule.OverlayMax);
  2479. Infantry.Set_Heap(Rule.InfantryMax);
  2480. Bullets.Set_Heap(Rule.BulletMax);
  2481. Buildings.Set_Heap(Rule.BuildingMax);
  2482. Anims.Set_Heap(Rule.AnimMax);
  2483. Aircraft.Set_Heap(Rule.AircraftMax);
  2484. Triggers.Set_Heap(Rule.TriggerMax);
  2485. TeamTypes.Set_Heap(Rule.TeamTypeMax);
  2486. Teams.Set_Heap(Rule.TeamMax);
  2487. Houses.Set_Heap(HOUSE_MAX);
  2488. TriggerTypes.Set_Heap(Rule.TrigTypeMax);
  2489. // Weapons.Set_Heap(Rule.WeaponMax);
  2490. /*
  2491. ** Speech holding tank buffer. Since speech does not mix, it can be placed
  2492. ** into a custom holding tank only as large as the largest speech file to
  2493. ** be played.
  2494. */
  2495. for (int index = 0; index < ARRAY_SIZE(SpeechBuffer); index++) {
  2496. SpeechBuffer[index] = new char [SPEECH_BUFFER_SIZE];
  2497. SpeechRecord[index] = VOX_NONE;
  2498. assert(SpeechBuffer[index] != NULL);
  2499. }
  2500. /*
  2501. ** Allocate the theater buffer block.
  2502. */
  2503. TheaterBuffer = new Buffer(THEATER_BUFFER_SIZE);
  2504. assert(TheaterBuffer != NULL);
  2505. }
  2506. /***********************************************************************************************
  2507. * Init_Expansion_Files -- Fetch any override expansion mixfiles. *
  2508. * *
  2509. * This routine will search for and register/cache any override mixfiles found. *
  2510. * *
  2511. * INPUT: none *
  2512. * *
  2513. * OUTPUT: none *
  2514. * *
  2515. * WARNINGS: none *
  2516. * *
  2517. * HISTORY: *
  2518. * 06/03/1996 JLB : Created. *
  2519. *=============================================================================================*/
  2520. static void Init_Expansion_Files(void)
  2521. {
  2522. /*
  2523. ** Need to search the search paths. ST - 3/15/2019 2:18PM
  2524. */
  2525. const char *path = ".\\";
  2526. char search_path[_MAX_PATH];
  2527. char scan_path[_MAX_PATH];
  2528. for (int p = 0; p < 100; p++) {
  2529. strcpy(search_path, path);
  2530. if (search_path[strlen(search_path) - 1] != '\\') {
  2531. strcat(search_path, "\\");
  2532. }
  2533. strcpy(scan_path, search_path);
  2534. strcat(scan_path, "SC*.MIX");
  2535. WIN32_FIND_DATA find_data;
  2536. memset(&find_data, 0, sizeof(find_data));
  2537. HANDLE file_handle = FindFirstFile(scan_path, &find_data);
  2538. if (file_handle != INVALID_HANDLE_VALUE)
  2539. {
  2540. do
  2541. {
  2542. char *ptr = strdup(find_data.cFileName);
  2543. new MFCD(ptr, &FastKey);
  2544. } while (FindNextFile(file_handle, &find_data));
  2545. FindClose(file_handle);
  2546. }
  2547. memset(&find_data, 0, sizeof(find_data));
  2548. strcpy(scan_path, search_path);
  2549. strcat(scan_path, "Ss*.MIX");
  2550. file_handle = FindFirstFile(scan_path, &find_data);
  2551. if (file_handle != INVALID_HANDLE_VALUE)
  2552. {
  2553. do
  2554. {
  2555. char *ptr = strdup(find_data.cFileName);
  2556. new MFCD(ptr, &FastKey);
  2557. } while (FindNextFile(file_handle, &find_data));
  2558. FindClose(file_handle);
  2559. }
  2560. path = CDFileClass::Get_Search_Path(p);
  2561. if (path == NULL) {
  2562. break;
  2563. }
  2564. }
  2565. #if (0)
  2566. /*
  2567. ** Before all else, cache any additional mixfiles.
  2568. */
  2569. struct find_t ff; // for _dos_findfirst
  2570. if (!_dos_findfirst("SC*.MIX", _A_NORMAL, &ff)) {
  2571. char * ptr;
  2572. do {
  2573. ptr = strdup(ff.name);
  2574. new MFCD(ptr, &FastKey);
  2575. MFCD::Cache(ptr);
  2576. } while (!_dos_findnext(&ff));
  2577. }
  2578. if (!_dos_findfirst("SS*.MIX", _A_NORMAL, &ff)) {
  2579. char * ptr;
  2580. do {
  2581. ptr = strdup(ff.name);
  2582. new MFCD(ptr, &FastKey);
  2583. } while (!_dos_findnext(&ff));
  2584. }
  2585. #endif
  2586. }
  2587. /***********************************************************************************************
  2588. * Init_One_Time_Systems -- Initialize internal pointers to the bulk data. *
  2589. * *
  2590. * This performs the one-time processing required after the bulk data has been cached but *
  2591. * before the game actually starts. Typically, this routine extracts pointers to all the *
  2592. * embedded data sub-files within the main game data mixfile. This routine must be called *
  2593. * AFTER the bulk data has been cached. *
  2594. * *
  2595. * INPUT: none *
  2596. * *
  2597. * OUTPUT: none *
  2598. * *
  2599. * WARNINGS: Call this routine AFTER the bulk data has been cached. *
  2600. * *
  2601. * HISTORY: *
  2602. * 06/03/1996 JLB : Created. *
  2603. *=============================================================================================*/
  2604. static void Init_One_Time_Systems(void)
  2605. {
  2606. Call_Back();
  2607. Map.One_Time();
  2608. Logic.One_Time();
  2609. Options.One_Time();
  2610. Session.One_Time();
  2611. ObjectTypeClass::One_Time();
  2612. BuildingTypeClass::One_Time();
  2613. BulletTypeClass::One_Time();
  2614. HouseTypeClass::One_Time();
  2615. TemplateTypeClass::One_Time();
  2616. OverlayTypeClass::One_Time();
  2617. SmudgeTypeClass::One_Time();
  2618. TerrainTypeClass::One_Time();
  2619. UnitTypeClass::One_Time();
  2620. VesselTypeClass::One_Time();
  2621. InfantryTypeClass::One_Time();
  2622. AnimTypeClass::One_Time();
  2623. AircraftTypeClass::One_Time();
  2624. HouseClass::One_Time();
  2625. }
  2626. /***********************************************************************************************
  2627. * Init_Fonts -- Initialize all the game font pointers. *
  2628. * *
  2629. * This routine is used to fetch pointers to the game fonts. The mixfile containing these *
  2630. * fonts must have been previously cached. This routine is a necessary prerequisite to *
  2631. * displaying any dialogs or printing any text. *
  2632. * *
  2633. * INPUT: none *
  2634. * *
  2635. * OUTPUT: none *
  2636. * *
  2637. * WARNINGS: none *
  2638. * *
  2639. * HISTORY: *
  2640. * 06/03/1996 JLB : Created. *
  2641. *=============================================================================================*/
  2642. static void Init_Fonts(void)
  2643. {
  2644. Metal12FontPtr = MFCD::Retrieve("12METFNT.FNT");
  2645. MapFontPtr = MFCD::Retrieve("HELP.FNT");
  2646. Font6Ptr = MFCD::Retrieve("6POINT.FNT");
  2647. GradFont6Ptr = MFCD::Retrieve("GRAD6FNT.FNT");
  2648. EditorFont = MFCD::Retrieve("EDITFNT.FNT");
  2649. Font8Ptr = MFCD::Retrieve("8POINT.FNT");
  2650. FontPtr = (char *)Font8Ptr;
  2651. Set_Font(FontPtr);
  2652. Font3Ptr = MFCD::Retrieve("3POINT.FNT");
  2653. ScoreFontPtr = MFCD::Retrieve("SCOREFNT.FNT");
  2654. FontLEDPtr = MFCD::Retrieve("LED.FNT");
  2655. VCRFontPtr = MFCD::Retrieve("VCR.FNT");
  2656. TypeFontPtr = MFCD::Retrieve("8POINT.FNT"); //("TYPE.FNT"); //VG 10/17/96
  2657. }
  2658. /***********************************************************************************************
  2659. * Init_CDROM_Access -- Initialize the CD-ROM access handler. *
  2660. * *
  2661. * This routine is called to setup the CD-ROM access or emulation handler. It will ensure *
  2662. * that the appropriate CD-ROM is present (dependant on the RequiredCD global). *
  2663. * *
  2664. * INPUT: none *
  2665. * *
  2666. * OUTPUT: none *
  2667. * *
  2668. * WARNINGS: The fonts, palettes, and other bootstrap systems must have been initialized *
  2669. * prior to calling this routine since this routine will quite likely display *
  2670. * a dialog box requesting the appropriate CD be inserted. *
  2671. * *
  2672. * HISTORY: *
  2673. * 06/03/1996 JLB : Created. *
  2674. *=============================================================================================*/
  2675. static void Init_CDROM_Access(void)
  2676. {
  2677. VisiblePage.Clear();
  2678. HidPage.Clear();
  2679. #ifdef FIXIT_VERSION_3
  2680. // Determine if we're going to be running from a DVD.
  2681. // The entire session will either require a DVD, or the regular CDs. Never both.
  2682. // Call Using_DVD() to determine which case it is.
  2683. // Here we set the value that Using_DVD() returns.
  2684. Determine_If_Using_DVD();
  2685. // Force_CD_Available() is modified when Using_DVD() is true so that all requests become requests for the DVD.
  2686. #endif
  2687. /*
  2688. ** Always try to look at the CD-ROM for data files.
  2689. */
  2690. if (!CCFileClass::Is_There_Search_Drives()) {
  2691. /*
  2692. ** This call is needed because of a side effect of this function. It will examine the
  2693. ** CD-ROMs attached to this computer and set the appropriate status values. Without this
  2694. ** call, the "?:\\" could not be filled in correctly.
  2695. */
  2696. Force_CD_Available(-1);
  2697. /*
  2698. ** If there are no search drives specified then we must be playing
  2699. ** off cd, so read files from there.
  2700. */
  2701. int error;
  2702. do {
  2703. error = CCFileClass::Set_Search_Drives("?:\\");
  2704. switch (error) {
  2705. case 1:
  2706. VisiblePage.Clear();
  2707. GamePalette.Set();
  2708. Show_Mouse();
  2709. WWMessageBox().Process(TXT_CD_ERROR1, TXT_OK);
  2710. Prog_End("Init_CDROM_Access - CD_ERROR1", true);
  2711. Emergency_Exit(EXIT_FAILURE);
  2712. case 2:
  2713. VisiblePage.Clear();
  2714. GamePalette.Set();
  2715. Show_Mouse();
  2716. if (WWMessageBox().Process(TXT_CD_DIALOG_1, TXT_OK, TXT_CANCEL) == 1) {
  2717. Prog_End("Init_CDROM_Access - CD_ERROR2", true);
  2718. Emergency_Exit(EXIT_FAILURE);
  2719. }
  2720. Hide_Mouse();
  2721. break;
  2722. default:
  2723. VisiblePage.Clear();
  2724. Show_Mouse();
  2725. if (!Force_CD_Available(RequiredCD)) {
  2726. Prog_End("Init_CDROM_Access - Force_CD_Available failed", true);
  2727. Emergency_Exit(EXIT_FAILURE);
  2728. }
  2729. Hide_Mouse();
  2730. break;
  2731. }
  2732. } while (error);
  2733. RequiredCD = -1;
  2734. } else {
  2735. /*
  2736. ** If there are search drives specified then all files are to be
  2737. ** considered local.
  2738. */
  2739. RequiredCD = -2;
  2740. }
  2741. }
  2742. /***********************************************************************************************
  2743. * Init_Bootstrap_Mixfiles -- Registers and caches any mixfiles needed for bootstrapping. *
  2744. * *
  2745. * This routine will register the initial mixfiles that are required to display error *
  2746. * messages and get input from the player. *
  2747. * *
  2748. * INPUT: none *
  2749. * *
  2750. * OUTPUT: none *
  2751. * *
  2752. * WARNINGS: Be sure to call this routine before any dialogs would be displayed to the *
  2753. * player. *
  2754. * *
  2755. * HISTORY: *
  2756. * 06/03/1996 JLB : Created. *
  2757. *=============================================================================================*/
  2758. static void Init_Bootstrap_Mixfiles(void)
  2759. {
  2760. int temp = RequiredCD;
  2761. RequiredCD = -2;
  2762. #ifdef WOLAPI_INTEGRATION
  2763. CCFileClass fileWolapiMix( "WOLAPI.MIX" );
  2764. if( fileWolapiMix.Is_Available() )
  2765. {
  2766. new MFCD( "WOLAPI.MIX", &FastKey );
  2767. MFCD::Cache( "WOLAPI.MIX" );
  2768. }
  2769. #endif
  2770. #ifdef FIXIT_CSII // Ok. ajw
  2771. CCFileClass file2("EXPAND2.MIX");
  2772. if (file2.Is_Available()) {
  2773. new MFCD("EXPAND2.MIX", &FastKey);
  2774. bool ok = MFCD::Cache("EXPAND2.MIX");
  2775. assert(ok);
  2776. }
  2777. #endif
  2778. #ifdef FIXIT_CSII // Ok. ajw
  2779. bool ok1;
  2780. #if 0
  2781. new MFCD("HIRES1.MIX", &FastKey);
  2782. ok1 = MFCD::Cache("HIRES1.MIX");
  2783. assert(ok1);
  2784. #else
  2785. new MFCD("LORES1.MIX", &FastKey);
  2786. ok1 = MFCD::Cache("LORES1.MIX");
  2787. assert(ok1);
  2788. #endif
  2789. #endif
  2790. #ifdef FIXIT_ANTS // Ok. ajw
  2791. CCFileClass file("EXPAND.MIX");
  2792. if (file.Is_Available()) {
  2793. new MFCD("EXPAND.MIX", &FastKey);
  2794. bool ok = MFCD::Cache("EXPAND.MIX");
  2795. assert(ok);
  2796. }
  2797. #endif
  2798. new MFCD("REDALERT.MIX", &FastKey);
  2799. /*
  2800. ** Bootstrap enough of the system so that the error dialog box can successfully
  2801. ** be displayed.
  2802. */
  2803. new MFCD("LOCAL.MIX", &FastKey); // Cached.
  2804. bool ok = MFCD::Cache("LOCAL.MIX");
  2805. assert(ok);
  2806. #if 0
  2807. new MFCD("HIRES.MIX", &FastKey);
  2808. ok = MFCD::Cache("HIRES.MIX");
  2809. assert(ok);
  2810. new MFCD("NCHIRES.MIX", &FastKey); //Non-cached hires stuff incl VQ palettes
  2811. #else
  2812. new MFCD("LORES.MIX", &FastKey);
  2813. ok = MFCD::Cache("LORES.MIX");
  2814. assert(ok);
  2815. #endif //WIN32
  2816. RequiredCD = temp;
  2817. }
  2818. /***********************************************************************************************
  2819. * Init_Secondary_Mixfiles -- Register and cache secondary mixfiles. *
  2820. * *
  2821. * This routine is used to register the mixfiles that are needed for main menu processing. *
  2822. * Call this routine before the main menu is display and processed. *
  2823. * *
  2824. * INPUT: none *
  2825. * *
  2826. * OUTPUT: none *
  2827. * *
  2828. * WARNINGS: none *
  2829. * *
  2830. * HISTORY: *
  2831. * 06/03/1996 JLB : Created. *
  2832. *=============================================================================================*/
  2833. //#define DENZIL_MIXEXTRACT
  2834. #ifdef DENZIL_MIXEXTRACT
  2835. void Extract(char* filename, char* outfile);
  2836. #endif
  2837. static void Init_Secondary_Mixfiles(void)
  2838. {
  2839. MainMix = new MFCD("MAIN.MIX", &FastKey);
  2840. assert(MainMix != NULL);
  2841. //Denzil extract mixfile
  2842. #ifdef DENZIL_MIXEXTRACT
  2843. #if(0)
  2844. Extract("CONQUER.MIX", "o:\\projects\\radvd\\data\\extract\\conquer.mix");
  2845. Extract("EDHI.MIX", "o:\\projects\\radvd\\data\\extract\\edhi.mix");
  2846. Extract("EDLO.MIX", "o:\\projects\\radvd\\data\\extract\\edlo.mix");
  2847. Extract("GENERAL.MIX", "o:\\projects\\radvd\\data\\extract\\general.mix");
  2848. Extract("INTERIOR.MIX", "o:\\projects\\radvd\\data\\extract\\interior.mix");
  2849. Extract("MOVIES1.MIX", "o:\\projects\\radvd\\data\\extract\\movies1.mix");
  2850. Extract("SCORES.MIX", "o:\\projects\\radvd\\data\\extract\\scores.mix");
  2851. Extract("SNOW.MIX", "o:\\projects\\radvd\\data\\extract\\snow.mix");
  2852. Extract("SOUNDS.MIX", "o:\\projects\\radvd\\data\\extract\\sounds.mix");
  2853. Extract("RUSSIAN.MIX", "o:\\projects\\radvd\\data\\extract\\russian.mix");
  2854. Extract("ALLIES.MIX", "o:\\projects\\radvd\\data\\extract\\allies.mix");
  2855. Extract("TEMPERAT.MIX", "o:\\projects\\radvd\\data\\extract\\temperat.mix");
  2856. #else
  2857. Extract("CONQUER.MIX", "o:\\projects\\radvd\\data\\extract\\conquer.mix");
  2858. Extract("EDHI.MIX", "o:\\projects\\radvd\\data\\extract\\edhi.mix");
  2859. Extract("EDLO.MIX", "o:\\projects\\radvd\\data\\extract\\edlo.mix");
  2860. Extract("GENERAL.MIX", "o:\\projects\\radvd\\data\\extract\\general.mix");
  2861. Extract("INTERIOR.MIX", "o:\\projects\\radvd\\data\\extract\\interior.mix");
  2862. Extract("MOVIES2.MIX", "o:\\projects\\radvd\\data\\extract\\movies2.mix");
  2863. Extract("SCORES.MIX", "o:\\projects\\radvd\\data\\extract\\scores.mix");
  2864. Extract("SNOW.MIX", "o:\\projects\\radvd\\data\\extract\\snow.mix");
  2865. Extract("SOUNDS.MIX", "o:\\projects\\radvd\\data\\extract\\sounds.mix");
  2866. Extract("RUSSIAN.MIX", "o:\\projects\\radvd\\data\\extract\\russian.mix");
  2867. Extract("ALLIES.MIX", "o:\\projects\\radvd\\data\\extract\\allies.mix");
  2868. Extract("TEMPERAT.MIX", "o:\\projects\\radvd\\data\\extract\\temperat.mix");
  2869. #endif
  2870. #endif
  2871. /*
  2872. ** Inform the file system of the various MIX files.
  2873. */
  2874. ConquerMix = new MFCD("CONQUER.MIX", &FastKey); // Cached.
  2875. // new MFCD("TRANSIT.MIX", &FastKey);
  2876. if (GeneralMix == NULL) GeneralMix = new MFCD("GENERAL.MIX", &FastKey); // Never cached.
  2877. if (CCFileClass("MOVIES1.MIX").Is_Available()) {
  2878. MoviesMix = new MFCD("MOVIES1.MIX", &FastKey); // Never cached.
  2879. } else {
  2880. MoviesMix = new MFCD("MOVIES2.MIX", &FastKey); // Never cached.
  2881. }
  2882. assert(MoviesMix != NULL);
  2883. /*
  2884. ** Register the score mixfile.
  2885. */
  2886. ScoresPresent = true;
  2887. ScoreMix = new MFCD("SCORES.MIX", &FastKey);
  2888. ThemeClass::Scan();
  2889. /*
  2890. ** These are sound card specific, but the install program would have
  2891. ** copied the correct versions to the hard drive.
  2892. */
  2893. new MFCD("SPEECH.MIX", &FastKey); // Never cached.
  2894. new MFCD("SOUNDS.MIX", &FastKey); // Cached.
  2895. new MFCD("RUSSIAN.MIX", &FastKey); // Cached.
  2896. new MFCD("ALLIES.MIX", &FastKey); // Cached.
  2897. }
  2898. /***********************************************************************************************
  2899. * Bootstrap -- Perform the initial bootstrap procedure. *
  2900. * *
  2901. * This routine will load and initialize the game engine such that a dialog box could be *
  2902. * displayed. Because this is very critical, call this routine before any other game *
  2903. * initialization code. *
  2904. * *
  2905. * INPUT: none *
  2906. * *
  2907. * OUTPUT: none *
  2908. * *
  2909. * WARNINGS: none *
  2910. * *
  2911. * HISTORY: *
  2912. * 06/03/1996 JLB : Created. *
  2913. *=============================================================================================*/
  2914. static void Bootstrap(void)
  2915. {
  2916. BlackPalette.Set();
  2917. /*
  2918. ** Be sure to short circuit the CD-ROM check if there is a CD-ROM override
  2919. ** path.
  2920. */
  2921. if (CCFileClass::Is_There_Search_Drives()) {
  2922. RequiredCD = -2;
  2923. }
  2924. /*
  2925. ** Process the message loop until we are in focus. We need to be in focus to read pixels from
  2926. ** the screen.
  2927. */
  2928. #if (0) //PG
  2929. #ifdef WIN32
  2930. do {
  2931. Keyboard->Check();
  2932. } while (!GameInFocus);
  2933. AllSurfaces.SurfacesRestored = false;
  2934. #endif
  2935. /*
  2936. ** Perform any special debug-only processing. This includes preparing the
  2937. ** monochrome screen.
  2938. */
  2939. Mono_Clear_Screen();
  2940. #endif
  2941. /*
  2942. ** Register and make resident all local mixfiles with particular emphasis
  2943. ** on the mixfiles that are necessary to display and error messages and
  2944. ** process further initialization.
  2945. */
  2946. Init_Bootstrap_Mixfiles();
  2947. /*
  2948. ** Initialize the resident font pointers.
  2949. */
  2950. Init_Fonts();
  2951. #ifndef WIN32
  2952. /*
  2953. ** Install the hard error handler.
  2954. */
  2955. _harderr(harderr_handler); // BG: Install hard error handler
  2956. /*
  2957. ** Install a Page Fault handler
  2958. */
  2959. if (UsePageFaultHandler) {
  2960. Install_Page_Fault_Handle();
  2961. }
  2962. #endif
  2963. /*
  2964. ** Setup the keyboard processor in preparation for the game.
  2965. */
  2966. #ifdef WIN32
  2967. Keyboard->Clear();
  2968. #else
  2969. Keyboard_Attributes_Off(BREAKON | SCROLLLOCKON | TRACKEXT | PAUSEON | CTRLSON | CTRLCON | FILTERONLY | TASKSWITCHABLE);
  2970. Keyboard_Attributes_On(PASSBREAKS);
  2971. Keyboard->Clear();
  2972. #endif
  2973. /*
  2974. ** This is the shape staging buffer. It must always be available, so it is
  2975. ** allocated here and never freed. The library sets the globals ShapeBuffer
  2976. ** and ShapeBufferSize to these values, so it can be accessed for other
  2977. ** purposes.
  2978. */
  2979. Set_Shape_Buffer(new unsigned char[SHAPE_BUFFER_SIZE], SHAPE_BUFFER_SIZE);
  2980. /*
  2981. ** Fetch the language text from the hard drive first. If it cannot be
  2982. ** found on the hard drive, then look for it in the mixfile.
  2983. */
  2984. #ifdef STEVES_LOAD_OVERRIDE
  2985. RawFileClass strings ("CONQUER.ENG");
  2986. if (strings.Is_Available()){
  2987. SystemStrings = new char [strings.Size()];
  2988. strings.Read((void*)SystemStrings, strings.Size());
  2989. }else{
  2990. SystemStrings = (char const *)MFCD::Retrieve(Language_Name("CONQUER"));
  2991. }
  2992. #else
  2993. SystemStrings = (char const *)MFCD::Retrieve(Language_Name("CONQUER"));
  2994. #endif
  2995. DebugStrings = (char const *)MFCD::Retrieve("DEBUG.ENG");
  2996. /*
  2997. ** Default palette initialization.
  2998. */
  2999. // PG_TO_FIX. This doesn't seem right. ST - 5/9/2019
  3000. //memmove((unsigned char *)&GamePalette[0], (void *)MFCD::Retrieve("TEMPERAT.PAL"), 768L);
  3001. //WhitePalette[0] = BlackPalette[0];
  3002. // GamePalette.Set();
  3003. /*
  3004. ** Initialize expansion files (if present). Expansion files must be located
  3005. ** in the current directory.
  3006. */
  3007. Init_Expansion_Files();
  3008. SidebarScheme.Background = BLACK;
  3009. SidebarScheme.Corners = LTGREY;
  3010. SidebarScheme.Shadow = DKGREY;
  3011. SidebarScheme.Highlight = WHITE;
  3012. SidebarScheme.Color = LTGREY;
  3013. SidebarScheme.Bright = WHITE;
  3014. SidebarScheme.BrightColor = WHITE;
  3015. SidebarScheme.Box = LTGREY;
  3016. GadgetClass::Set_Color_Scheme(&SidebarScheme);
  3017. }
  3018. /***********************************************************************************************
  3019. * Init_Mouse -- Initialize the mouse system. *
  3020. * *
  3021. * This routine will ensure that a valid mouse driver is present and a working mouse *
  3022. * pointer can be displayed. The mouse is hidden when this routine exits. *
  3023. * *
  3024. * INPUT: none *
  3025. * *
  3026. * OUTPUT: none *
  3027. * *
  3028. * WARNINGS: none *
  3029. * *
  3030. * HISTORY: *
  3031. * 06/03/1996 JLB : Created. *
  3032. *=============================================================================================*/
  3033. static void Init_Mouse(void)
  3034. {
  3035. /*
  3036. ** Since there is no mouse shape currently available we need
  3037. ** to set one of our own.
  3038. */
  3039. #ifdef WIN32
  3040. ShowCursor(false);
  3041. #endif
  3042. if (MouseInstalled) {
  3043. void const * temp_mouse_shapes = MFCD::Retrieve("MOUSE.SHP");
  3044. if (temp_mouse_shapes) {
  3045. Set_Mouse_Cursor(0, 0, Extract_Shape(temp_mouse_shapes, 0));
  3046. while (Get_Mouse_State() > 1) Show_Mouse();
  3047. }
  3048. } else {
  3049. char buffer[255];
  3050. GamePalette.Set();
  3051. GamePalette.Set();
  3052. sprintf(buffer, TEXT_NO_MOUSE);
  3053. VisiblePage.Clear();
  3054. WWMessageBox().Process(buffer, TXT_OK);
  3055. Prog_End("Init_Mouse", true);
  3056. Emergency_Exit(1);
  3057. }
  3058. Map.Set_Default_Mouse(MOUSE_NORMAL, false);
  3059. Show_Mouse();
  3060. while (Get_Mouse_State() > 1) Show_Mouse();
  3061. Call_Back();
  3062. Hide_Mouse();
  3063. }
  3064. #ifdef OBSOLETE
  3065. /***********************************************************************************************
  3066. * Init_Authorization -- Verifies that the player is authorized to play the game. *
  3067. * *
  3068. * This is a development routine that restricts access to the game by way of passwords. *
  3069. * *
  3070. * INPUT: none *
  3071. * *
  3072. * OUTPUT: none *
  3073. * *
  3074. * WARNINGS: none *
  3075. * *
  3076. * HISTORY: *
  3077. * 06/03/1996 JLB : Created. *
  3078. *=============================================================================================*/
  3079. static void Init_Authorization(void)
  3080. {
  3081. if (Special.IsFromInstall) return;
  3082. Load_Title_Page();
  3083. #ifdef WIN32
  3084. Wait_Vert_Blank();
  3085. #else //WIN32
  3086. Init_Delay();
  3087. Wait_Vert_Blank(VertBlank);
  3088. #endif //WIN32
  3089. CCPalette.Set();
  3090. // Set_Palette(Palette);
  3091. HidPage.Blit(SeenPage);
  3092. Show_Mouse();
  3093. /*
  3094. ** Fetch the type of game to be played. This will be either
  3095. ** C&C:Red Alert or C&C:Plus.
  3096. */
  3097. //tryagain:
  3098. bool ok = Debug_Flag;
  3099. int counter = 3;
  3100. if (Debug_Flag) ok = true;
  3101. /*
  3102. ** C&C:Red Alert requires a password for legal entry. Try (three times) to get a correct
  3103. ** password. If not found, then try again.
  3104. */
  3105. bool skipper = false;
  3106. #ifdef NEVER
  3107. while (!ok && counter) {
  3108. SmartPtr<char const> str = Fetch_Password(TXT_PASSWORD_CAPTION, TXT_PASSWORD_MESSAGE, TXT_OK);
  3109. SmartPtr<long const> lptr = &CheatCodes[0];
  3110. while (*lptr) {
  3111. if (Obfuscate(str) == *lptr++) {
  3112. ok = true;
  3113. break;
  3114. }
  3115. }
  3116. lptr = &EditorCodes[0];
  3117. while (*lptr) {
  3118. if (Obfuscate(str) == *lptr++) {
  3119. ok = true;
  3120. break;
  3121. }
  3122. }
  3123. lptr = &PlayCodes[0];
  3124. while (*lptr) {
  3125. if (Obfuscate(str) == *lptr++) {
  3126. ok = true;
  3127. skipper = true;
  3128. break;
  3129. }
  3130. }
  3131. if (ok) break;
  3132. Hide_Mouse();
  3133. Load_Title_Page();
  3134. HidPage.Blit(SeenPage);
  3135. Show_Mouse();
  3136. Delay(TIMER_SECOND*(4-counter)*1);
  3137. if (WWMessageBox().Process(TXT_PASSWORD_ERROR, TXT_TRY_AGAIN, TXT_CANCEL)) {
  3138. goto tryagain;
  3139. }
  3140. counter--;
  3141. if (counter == 0) goto tryagain;
  3142. }
  3143. #endif
  3144. if (!skipper) {
  3145. CCPalette.Set();
  3146. }
  3147. Hide_Mouse();
  3148. Load_Title_Page();
  3149. HidPage.Blit(SeenPage);
  3150. Show_Mouse();
  3151. Call_Back();
  3152. }
  3153. #endif
  3154. /***********************************************************************************************
  3155. * Init_Bulk_Data -- Initialize the time-consuming mixfile caching. *
  3156. * *
  3157. * This routine is called to handle the time consuming process of game initialization. *
  3158. * The title page will be displayed when this routine is called. *
  3159. * *
  3160. * INPUT: none *
  3161. * *
  3162. * OUTPUT: none *
  3163. * *
  3164. * WARNINGS: This routine will take a very long time. *
  3165. * *
  3166. * HISTORY: *
  3167. * 06/03/1996 JLB : Created. *
  3168. *=============================================================================================*/
  3169. static void Init_Bulk_Data(void)
  3170. {
  3171. /*
  3172. ** Cache the main game data. This operation can take a very long time.
  3173. */
  3174. MFCD::Cache("CONQUER.MIX");
  3175. if (SampleType != 0 && !Debug_Quiet) {
  3176. MFCD::Cache("SOUNDS.MIX");
  3177. MFCD::Cache("RUSSIAN.MIX");
  3178. MFCD::Cache("ALLIES.MIX");
  3179. }
  3180. Call_Back();
  3181. /*
  3182. ** Fetch the tutorial message data.
  3183. */
  3184. INIClass ini;
  3185. ini.Load(CCFileClass("TUTORIAL.INI"));
  3186. for (int index = 0; index < ARRAY_SIZE(TutorialText); index++) {
  3187. TutorialText[index] = NULL;
  3188. char buffer[128];
  3189. char num[10];
  3190. sprintf(num, "%d", index);
  3191. if (ini.Get_String("Tutorial", num, "", buffer, sizeof(buffer))) {
  3192. TutorialText[index] = strdup(buffer);
  3193. }
  3194. }
  3195. /*
  3196. ** Perform one-time game system initializations.
  3197. */
  3198. Init_One_Time_Systems();
  3199. }
  3200. /***********************************************************************************************
  3201. * Init_Keys -- Initialize the cryptographic keys. *
  3202. * *
  3203. * This routine will initialize the fast cryptographic key. It will also initialize the *
  3204. * slow one if this is a scenario editor version of the game. *
  3205. * *
  3206. * INPUT: none *
  3207. * *
  3208. * OUTPUT: none *
  3209. * *
  3210. * WARNINGS: none *
  3211. * *
  3212. * HISTORY: *
  3213. * 07/08/1996 JLB : Created. *
  3214. *=============================================================================================*/
  3215. static void Init_Keys(void)
  3216. {
  3217. RAMFileClass file((void*)Keys, strlen(Keys));
  3218. INIClass ini;
  3219. ini.Load(file);
  3220. FastKey = ini.Get_PKey(true);
  3221. #ifdef SCENARIO_EDITOR
  3222. SlowKey = ini.Get_PKey(false);
  3223. #endif
  3224. }
  3225. /***************************************************************************
  3226. * Save_Recording_Values -- Saves multiplayer-specific values *
  3227. * *
  3228. * This routine saves multiplayer values that need to be restored for a *
  3229. * save game. In addition to saving the random # seed for this scenario, *
  3230. * it saves the contents of the actual random number generator; this *
  3231. * ensures that the random # sequencer will pick up where it left off when *
  3232. * the game was saved. *
  3233. * This routine also saves the header for a Recording file, so it must *
  3234. * save some data not needed specifically by a save-game file (ie Seed). *
  3235. * *
  3236. * INPUT: *
  3237. * file file to save to *
  3238. * *
  3239. * OUTPUT: *
  3240. * true = success, false = failure *
  3241. * *
  3242. * WARNINGS: *
  3243. * none. *
  3244. * *
  3245. * HISTORY: *
  3246. * 09/28/1995 BRR : Created. *
  3247. *=========================================================================*/
  3248. bool Save_Recording_Values(CCFileClass & file)
  3249. {
  3250. Session.Save(file);
  3251. file.Write(&BuildLevel, sizeof(BuildLevel));
  3252. file.Write(&Debug_Unshroud, sizeof(Debug_Unshroud));
  3253. file.Write(&Seed, sizeof(Seed));
  3254. file.Write(&Scen.Scenario, sizeof(Scen.Scenario));
  3255. file.Write(Scen.ScenarioName, sizeof(Scen.ScenarioName));
  3256. file.Write(&Whom, sizeof(Whom));
  3257. file.Write(&Special, sizeof(SpecialClass));
  3258. file.Write(&Options, sizeof(GameOptionsClass));
  3259. return (true);
  3260. }
  3261. /***************************************************************************
  3262. * Load_Recording_Values -- Loads multiplayer-specific values *
  3263. * *
  3264. * INPUT: *
  3265. * file file to load from *
  3266. * *
  3267. * OUTPUT: *
  3268. * true = success, false = failure *
  3269. * *
  3270. * WARNINGS: *
  3271. * none. *
  3272. * *
  3273. * HISTORY: *
  3274. * 09/28/1995 BRR : Created. *
  3275. *=========================================================================*/
  3276. bool Load_Recording_Values(CCFileClass & file)
  3277. {
  3278. Session.Load(file);
  3279. file.Read(&BuildLevel, sizeof(BuildLevel));
  3280. file.Read(&Debug_Unshroud, sizeof(Debug_Unshroud));
  3281. file.Read(&Seed, sizeof(Seed));
  3282. file.Read(&Scen.Scenario, sizeof(Scen.Scenario));
  3283. file.Read(Scen.ScenarioName, sizeof(Scen.ScenarioName));
  3284. file.Read(&Whom, sizeof(Whom));
  3285. file.Read(&Special, sizeof(SpecialClass));
  3286. file.Read(&Options, sizeof(GameOptionsClass));
  3287. return (true);
  3288. }
  3289. extern "C" {
  3290. void __PRO(void) {
  3291. // printf("_pro\n");
  3292. }
  3293. }
  3294. #ifdef DENZIL_MIXEXTRACT
  3295. void Extract(char* filename, char* outname)
  3296. {
  3297. CCFileClass inFile(filename);
  3298. CCFileClass outFile(outname);
  3299. inFile.Open();
  3300. outFile.Open(WRITE);
  3301. void* buffer = malloc(32768);
  3302. if (buffer)
  3303. {
  3304. unsigned long size = inFile.Size();
  3305. unsigned long bytes;
  3306. while (size > 0)
  3307. {
  3308. bytes = inFile.Read(buffer, 32768);
  3309. outFile.Write(buffer, bytes);
  3310. size -= bytes;
  3311. }
  3312. free(buffer);
  3313. }
  3314. }
  3315. #endif
  3316. #ifdef FIXIT_VERSION_3
  3317. bool bUsingDVD = false;
  3318. const char* Game_Registry_Key();
  3319. //***********************************************************************************************
  3320. bool Is_DVD_Installed()
  3321. {
  3322. bool bInstalled;
  3323. HKEY hKey;
  3324. if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, Game_Registry_Key(), 0, KEY_READ, &hKey ) != ERROR_SUCCESS )
  3325. return false;
  3326. DWORD dwValue;
  3327. DWORD dwBufSize = sizeof( DWORD );
  3328. if( RegQueryValueEx( hKey, "DVD", 0, NULL, (LPBYTE)&dwValue, &dwBufSize ) != ERROR_SUCCESS )
  3329. bInstalled = false;
  3330. else
  3331. bInstalled = (bool)dwValue; // (Presumably true, if it's there...)
  3332. RegCloseKey( hKey );
  3333. return bInstalled;
  3334. }
  3335. //***********************************************************************************************
  3336. bool Determine_If_Using_DVD()
  3337. {
  3338. // Determines if the user has a DVD currently available. If they do, we'll use it throughout the
  3339. // session. Else we won't check for it again and will always ask for CDs.
  3340. if( Is_DVD_Installed() )
  3341. {
  3342. if( Force_CD_Available( 5 ) )
  3343. {
  3344. bUsingDVD = true;
  3345. }
  3346. else
  3347. {
  3348. // User hit cancel. Allow things to progress normally. They will be prompted for
  3349. // a Red Alert disk as usual.
  3350. bUsingDVD = false;
  3351. }
  3352. }
  3353. else
  3354. bUsingDVD = false;
  3355. return bUsingDVD;
  3356. }
  3357. //***********************************************************************************************
  3358. bool Using_DVD()
  3359. {
  3360. return bUsingDVD;
  3361. }
  3362. #endif
  3363. /***********************************************************************************************
  3364. * Free_Heaps -- Clear out the heaps before exit *
  3365. * *
  3366. * *
  3367. * INPUT: none *
  3368. * *
  3369. * OUTPUT: none *
  3370. * *
  3371. * WARNINGS: *
  3372. * *
  3373. * HISTORY: *
  3374. * 12/18/2019 11:59AM ST : Created. *
  3375. *=============================================================================================*/
  3376. void Free_Heaps(void)
  3377. {
  3378. HouseTypes.Clear();
  3379. BuildingTypes.Clear();
  3380. AircraftTypes.Clear();
  3381. InfantryTypes.Clear();
  3382. BulletTypes.Clear();
  3383. AnimTypes.Clear();
  3384. UnitTypes.Clear();
  3385. VesselTypes.Clear();
  3386. TemplateTypes.Clear();
  3387. TerrainTypes.Clear();
  3388. OverlayTypes.Clear();
  3389. SmudgeTypes.Clear();
  3390. #if (0)
  3391. HouseTypeClass::Init_Heap();
  3392. BuildingTypeClass::Init_Heap();
  3393. AircraftTypeClass::Init_Heap();
  3394. InfantryTypeClass::Init_Heap();
  3395. BulletTypeClass::Init_Heap();
  3396. AnimTypeClass::Init_Heap();
  3397. UnitTypeClass::Init_Heap();
  3398. VesselTypeClass::Init_Heap();
  3399. TemplateTypeClass::Init_Heap();
  3400. TerrainTypeClass::Init_Heap();
  3401. OverlayTypeClass::Init_Heap();
  3402. SmudgeTypeClass::Init_Heap();
  3403. // Heap init moved here from globals.cpp. ST - 5/20/2019
  3404. CCPtr<AircraftClass>::Set_Heap(&Aircraft);
  3405. CCPtr<AnimClass>::Set_Heap(&Anims);
  3406. CCPtr<BuildingClass>::Set_Heap(&Buildings);
  3407. CCPtr<BulletClass>::Set_Heap(&Bullets);
  3408. CCPtr<FactoryClass>::Set_Heap(&Factories);
  3409. CCPtr<HouseClass>::Set_Heap(&Houses);
  3410. CCPtr<InfantryClass>::Set_Heap(&Infantry);
  3411. CCPtr<OverlayClass>::Set_Heap(&Overlays);
  3412. CCPtr<SmudgeClass>::Set_Heap(&Smudges);
  3413. CCPtr<TeamClass>::Set_Heap(&Teams);
  3414. CCPtr<TeamTypeClass>::Set_Heap(&TeamTypes);
  3415. CCPtr<TemplateClass>::Set_Heap(&Templates);
  3416. CCPtr<TerrainClass>::Set_Heap(&Terrains);
  3417. CCPtr<TriggerClass>::Set_Heap(&Triggers);
  3418. CCPtr<TriggerTypeClass>::Set_Heap(&TriggerTypes);
  3419. CCPtr<HouseTypeClass>::Set_Heap(&HouseTypes);
  3420. CCPtr<BuildingTypeClass>::Set_Heap(&BuildingTypes);
  3421. CCPtr<AircraftTypeClass>::Set_Heap(&AircraftTypes);
  3422. CCPtr<InfantryTypeClass>::Set_Heap(&InfantryTypes);
  3423. CCPtr<BulletTypeClass>::Set_Heap(&BulletTypes);
  3424. CCPtr<AnimTypeClass>::Set_Heap(&AnimTypes);
  3425. CCPtr<UnitTypeClass>::Set_Heap(&UnitTypes);
  3426. CCPtr<VesselTypeClass>::Set_Heap(&VesselTypes);
  3427. CCPtr<TemplateTypeClass>::Set_Heap(&TemplateTypes);
  3428. CCPtr<TerrainTypeClass>::Set_Heap(&TerrainTypes);
  3429. CCPtr<OverlayTypeClass>::Set_Heap(&OverlayTypes);
  3430. CCPtr<SmudgeTypeClass>::Set_Heap(&SmudgeTypes);
  3431. #endif
  3432. Vessels.Clear();
  3433. Units.Clear();
  3434. Factories.Clear();
  3435. Terrains.Clear();
  3436. Templates.Clear();
  3437. Smudges.Clear();
  3438. Overlays.Clear();
  3439. Infantry.Clear();
  3440. Bullets.Clear();
  3441. Buildings.Clear();
  3442. Anims.Clear();
  3443. Aircraft.Clear();
  3444. Triggers.Clear();
  3445. TeamTypes.Clear();
  3446. Teams.Clear();
  3447. Houses.Clear();
  3448. TriggerTypes.Clear();
  3449. /*
  3450. ** Speech holding tank buffer. Since speech does not mix, it can be placed
  3451. ** into a custom holding tank only as large as the largest speech file to
  3452. ** be played.
  3453. */
  3454. for (int index = 0; index < ARRAY_SIZE(SpeechBuffer); index++) {
  3455. if (SpeechBuffer[index]) {
  3456. delete [] SpeechBuffer[index];
  3457. SpeechBuffer[index] = NULL;
  3458. }
  3459. }
  3460. /*
  3461. ** Allocate the theater buffer block.
  3462. */
  3463. if (TheaterBuffer) {
  3464. delete TheaterBuffer;
  3465. TheaterBuffer = NULL;
  3466. }
  3467. }