INIT.CPP 119 KB

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