123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054 |
- //
- // Copyright 2020 Electronic Arts Inc.
- //
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
- // software: you can redistribute it and/or modify it under the terms of
- // the GNU General Public License as published by the Free Software Foundation,
- // either version 3 of the License, or (at your option) any later version.
- // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- // in the hope that it will be useful, but with permitted additional restrictions
- // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- // distributed with this program. You should have received a copy of the
- // GNU General Public License along with permitted additional restrictions
- // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
- /* $Header: F:\projects\c&c\vcs\code\init.cpv 2.18 16 Oct 1995 16:50:16 JOE_BOSTIC $ */
- /***********************************************************************************************
- *** 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 ***
- ***********************************************************************************************
- * *
- * Project Name : Command & Conquer *
- * *
- * File Name : INIT.CPP *
- * *
- * Programmer : Joe L. Bostic *
- * *
- * Start Date : January 20, 1992 *
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * Anim_Init -- Initialize the VQ animation control structure. *
- * Init_Game -- Main game initialization routine. *
- * Load_Recording_Values -- Loads recording values from recording file *
- * Obfuscate -- Sufficiently transform parameter to thwart casual hackers. *
- * Parse_Command_Line -- Parses the command line parameters. *
- * Parse_INI_File -- Parses CONQUER.INI for special options *
- * Play_Intro -- plays the introduction & logo movies *
- * Save_Recording_Values -- Saves recording values to a recording file *
- * Select_Game -- The game's main menu *
- * Version_Number -- Determines the version number. *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "function.h"
- #include "loaddlg.h"
- #include "tcpip.h"
- #include <conio.h>
- #include <dos.h>
- #include "ccdde.h"
- static HANDLE hCCLibrary;
- /****************************************
- ** Function prototypes for this module **
- *****************************************/
- static void Play_Intro(bool for_real = false);
- extern "C" {
- extern long RandNumb;
- }
- extern int SimRandIndex;
- #define ATTRACT_MODE_TIMEOUT 3600 // timeout for attract mode
- #if(0)
- long FAR PASCAL _export Start_Game_Proc(HWND hwnd, UINT message, UINT wParam, LONG lParam)
- {
- switch (message) {
- case WM_CREATE:
- break;
- case WM_COMMAND:
- EndDialog(hwnd, TRUE);
- AllDone = TRUE;
- break;
- case WM_DESTROY:
- EndDialog(hwnd, TRUE);
- break;
- }
- return(DefWindowProc(hwnd, message, wParam, lParam));
- }
- #endif
- extern bool Server_Remote_Connect(void);
- extern bool Client_Remote_Connect(void);
- extern bool SpawnedFromWChat;
- /***********************************************************************************************
- * Init_Game -- Main game initialization routine. *
- * *
- * Perform all one-time game initializations here. This includes all *
- * allocations and table setups. The intro and other one-time startup *
- * tasks are also performed here. *
- * *
- * INPUT: argc,argv -- Command line arguments. *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: Only call this ONCE! *
- * *
- * HISTORY: *
- * 10/07/1992 JLB : Created. *
- *=============================================================================================*/
- bool Init_Game(int , char *[])
- {
- void const *temp_mouse_shapes;
- CCDebugString ("C&C95 - About to load reslib.dll\n");
- hCCLibrary = LoadLibrary("reslib.dll");
- /*
- ** Initialize the game object heaps.
- */
- CCDebugString ("C&C95 - About to enter Units.Set_Heap\n");
- Units.Set_Heap(UNIT_MAX);
- CCDebugString ("C&C95 - About to enter Factories.Set_Heap\n");
- Factories.Set_Heap(FACTORY_MAX);
- CCDebugString ("C&C95 - About to enter Terrains.Set_Heap\n");
- Terrains.Set_Heap(TERRAIN_MAX);
- CCDebugString ("C&C95 - About to enter Templates.Set_Heap\n");
- Templates.Set_Heap(TEMPLATE_MAX);
- CCDebugString ("C&C95 - About to enter Smudges.Set_Heap\n");
- Smudges.Set_Heap(SMUDGE_MAX);
- CCDebugString ("C&C95 - About to enter Overlays.Set_Heap\n");
- Overlays.Set_Heap(OVERLAY_MAX);
- CCDebugString ("C&C95 - About to enter Infantry.Set_Heap\n");
- Infantry.Set_Heap(INFANTRY_MAX);
- CCDebugString ("C&C95 - About to enter Bullets.Set_Heap\n");
- Bullets.Set_Heap(BULLET_MAX);
- CCDebugString ("C&C95 - About to enter Buildings.Set_Heap\n");
- Buildings.Set_Heap(BUILDING_MAX);
- CCDebugString ("C&C95 - About to enter Anims.Set_Heap\n");
- Anims.Set_Heap(ANIM_MAX);
- CCDebugString ("C&C95 - About to enter Aircraft.Set_Heap\n");
- Aircraft.Set_Heap(AIRCRAFT_MAX);
- CCDebugString ("C&C95 - About to enter Triggers.Set_Heap\n");
- Triggers.Set_Heap(TRIGGER_MAX);
- CCDebugString ("C&C95 - About to enter TeamTypes.Set_Heap\n");
- TeamTypes.Set_Heap(TEAMTYPE_MAX);
- CCDebugString ("C&C95 - About to enter Teams.Set_Heap\n");
- Teams.Set_Heap(TEAM_MAX);
- CCDebugString ("C&C95 - About to enter Houses.Set_Heap\n");
- Houses.Set_Heap(HOUSE_MAX);
- /*
- ** Initialize all the waypoints to invalid values.
- */
- CCDebugString ("C&C95 - About to clear waypoints\n");
- memset(Waypoint, 0xFF, sizeof(Waypoint));
- /*
- ** Setup the keyboard processor in preparation for the game.
- */
- CCDebugString ("C&C95 - About to do various keyboard inits\n");
- #ifdef FIX_ME_LATER
- Keyboard_Attributes_Off(TRACKEXT | PAUSEON | BREAKON | SCROLLLOCKON | CTRLSON | CTRLCON | PASSBREAKS | FILTERONLY | TASKSWITCHABLE);
- #endif //FIX_ME_LATER
- Keyboard::Clear();
- Kbd.Clear();
- /*
- ** This is the shape staging buffer. It must always be available, so it is
- ** allocated here and never freed. The library sets the globals ShapeBuffer
- ** and ShapeBufferSize to these values, so it can be accessed for other
- ** purposes.
- */
- CCDebugString ("C&C95 - About to call Set_Shape_Buffer\n");
- Set_Shape_Buffer(new unsigned char[SHAPE_BUFFER_SIZE], SHAPE_BUFFER_SIZE);
- /*
- ** Bootstrap enough of the system so that the error dialog box can sucessfully
- ** be displayed.
- */
- CCDebugString ("C&C95 - About to register CCLOCAL.MIX\n");
- #ifdef DEMO
- new MixFileClass("DEMOL.MIX");
- MixFileClass::Cache("DEMOL.MIX");
- #else
- int temp = RequiredCD;
- RequiredCD = -2;
- new MixFileClass("CCLOCAL.MIX"); // Cached.
- MixFileClass::Cache("CCLOCAL.MIX");
- CCDebugString ("C&C95 - About to register UPDATE.MIX\n");
- new MixFileClass("UPDATE.MIX"); // Cached.
- new MixFileClass("UPDATA.MIX"); // Cached.
- CCDebugString ("C&C95 - About to register UPDATEC.MIX\n");
- new MixFileClass("UPDATEC.MIX"); // Cached.
- MixFileClass::Cache("UPDATEC.MIX");
- #ifdef JAPANESE
- CCDebugString ("C&C95 - About to register LANGUAGE.MIX\n");
- new MixFileClass("LANGUAGE.MIX");
- #endif //JAPANESE
- RequiredCD = temp;
- #endif
- CCDebugString ("C&C95 - About to load fonts\n");
- Green12FontPtr = Load_Alloc_Data(CCFileClass("12GREEN.FNT"));
- Green12GradFontPtr = Load_Alloc_Data(CCFileClass("12GRNGRD.FNT"));
- MapFontPtr = Load_Alloc_Data(CCFileClass("8FAT.FNT"));
- Font8Ptr = MixFileClass::Retrieve(FONT8);
- FontPtr = (char *)Font8Ptr;
- Set_Font(FontPtr);
- Font3Ptr = MixFileClass::Retrieve(FONT3);
- // Font6Ptr = MixFileClass::Retrieve(FONT6);
- Font6Ptr = Load_Alloc_Data(CCFileClass("6POINT.FNT"));
- //ScoreFontPtr = MixFileClass::Retrieve("12GRNGRD.FNT"); //GRAD12FN"); //("SCOREFNT.FNT");
- ScoreFontPtr = Load_Alloc_Data(CCFileClass("12GRNGRD.FNT"));
- FontLEDPtr = MixFileClass::Retrieve("LED.FNT");
- VCRFontPtr = MixFileClass::Retrieve("VCR.FNT");
- // GradFont6Ptr = MixFileClass::Retrieve("GRAD6FNT.FNT");
- GradFont6Ptr = Load_Alloc_Data(CCFileClass("GRAD6FNT.FNT"));
- BlackPalette = new(MEM_CLEAR|MEM_REAL) unsigned char[768];
- GamePalette = new(MEM_CLEAR|MEM_REAL) unsigned char[768];
- OriginalPalette = new(MEM_CLEAR|MEM_REAL) unsigned char[768];
- WhitePalette = new(MEM_CLEAR|MEM_REAL) unsigned char[768];
- memset(WhitePalette, 63, 768);
- CCDebugString ("C&C95 - About to set palette\n");
- memset(BlackPalette, 0x01, 768);
- if (!Special.IsFromInstall) Set_Palette(BlackPalette);
- memset(BlackPalette, 0, 768);
- if (!Special.IsFromInstall) {
- Set_Palette(BlackPalette);
- CCDebugString ("C&C95 - About to clear visible page\n");
- VisiblePage.Clear();
- }
- Set_Palette(GamePalette);
- CCDebugString ("C&C95 - About to set the mouse shape\n");
- /*
- ** Since there is no mouse shape currently available we need'
- ** to set one of our own.
- */
- ShowCursor (FALSE);
- if (MouseInstalled) {
- temp_mouse_shapes = MixFileClass::Retrieve("MOUSE.SHP");
- if (temp_mouse_shapes) {
- Set_Mouse_Cursor(0, 0, Extract_Shape(temp_mouse_shapes,0));
- while (Get_Mouse_State() > 1) {
- Show_Mouse();
- }
- }
- }
- CCDebugString ("C&C95 - About to enter wait for focus loop\n");
- /*
- ** Process the message loop until we are in focus.
- */
- do {
- CCDebugString ("C&C95 - About to call Keyboard::Check\n");
- Keyboard::Check();
- }while (!GameInFocus);
- AllSurfaces.SurfacesRestored=FALSE;
- CCDebugString ("C&C95 - About to load the language file\n");
- /*
- ** Fetch the language text from the hard drive first. If it cannot be
- ** found on the hard drive, then look for it in the mixfile.
- */
- if (RawFileClass(Language_Name("CONQUER")).Is_Available()) {
- SystemStrings = (char const *)Load_Alloc_Data(RawFileClass(Language_Name("CONQUER")));
- } else {
- SystemStrings = (char const *)MixFileClass::Retrieve(Language_Name("CONQUER"));
- }
- /*
- ** Default palette initialization. Uses the desert palette for convenience,
- ** but only the non terrain specific colors matter.
- */
- //Mem_Copy((void *)MixFileClass::Retrieve("TEMPERAT.PAL"), GamePalette, 768L);
- CCFileClass palfile ("TEMPERAT.PAL");
- palfile.Read (GamePalette, 768L);
- if (!MouseInstalled) {
- char buffer[255];
- Set_Palette(GamePalette);
- #ifdef GERMAN
- sprintf(buffer, "Command & Conquer kann Ihren Maustreiber nicht finden..");
- #else
- #ifdef FRENCH
- sprintf(buffer, "Command & Conquer ne peut pas d‚tecter votre gestionnaire de souris.");
- #else
- sprintf(buffer, "Command & Conquer is unable to detect your mouse driver.");
- #endif
- #endif
- CCMessageBox().Process(buffer, TXT_OK);
- Prog_End();
- exit(1);
- }
- #ifdef DEMO
- /*
- ** Add in any override path specified in the conquer.ini file.
- */
- if (strlen(OverridePath)) {
- CCFileClass::Set_Search_Drives(OverridePath);
- }
- #endif
- #if (0) //ST - 1/2/2019 5:49PM
- CCDebugString ("C&C95 - About to search for CD drives\n");
- /*
- ** Always try to look at the CD-ROM for data files.
- */
- if (!CCFileClass::Is_There_Search_Drives()) {
- /*
- ** If there are no search drives specified then we must be playing
- ** off cd, so read files from there.
- */
- int error;
- do {
- if (!CDList.Get_Number_Of_Drives()){
- Set_Palette(GamePalette);
- Show_Mouse();
- CCMessageBox().Process(TXT_CD_ERROR1, TXT_OK);
- Prog_End();
- exit(EXIT_FAILURE);
- }
- CCFileClass::Set_CD_Drive( CDList.Get_First_CD_Drive() );
- error = CCFileClass::Set_Search_Drives("?:\\");
- switch(error) {
- case 1:
- Set_Palette(GamePalette);
- Show_Mouse();
- CCMessageBox().Process(TXT_CD_ERROR1, TXT_OK);
- Prog_End();
- exit(EXIT_FAILURE);
- case 2:
- Set_Palette(GamePalette);
- Show_Mouse();
- if (CCMessageBox().Process(TXT_CD_DIALOG_1, TXT_OK, TXT_CANCEL) == 1) {
- Prog_End();
- exit(EXIT_FAILURE);
- }
- Hide_Mouse();
- break;
- default:
- Show_Mouse();
- if (!Force_CD_Available(RequiredCD)) {
- Prog_End();
- exit(EXIT_FAILURE);
- }
- Hide_Mouse();
- break;
- }
- } while (error);
- #ifdef DEMO
- RequiredCD = -2;
- #else
- RequiredCD = -1;
- #endif
- } else {
- /*
- ** If there are search drives specified then all files are to be
- ** considered local.
- */
- RequiredCD = -2;
- }
- #endif
- #ifndef DEMO
- CCDebugString ("C&C95 - About to register addon mixfiles\n");
- /*
- ** Before all else, cache any additional mixfiles.
- */
- /*
- ** Need to search the search paths. ST - 3/15/2019 2:18PM
- */
- const char *path = ".\\";
- char search_path[_MAX_PATH];
- char scan_path[_MAX_PATH];
- for (int p=0 ; p<100 ; p++) {
-
- strcpy(search_path, path);
- if (search_path[strlen(search_path) - 1] != '\\') {
- strcat(search_path, "\\");
- }
- strcpy(scan_path, search_path);
- strcat(scan_path, "SC*.MIX");
- WIN32_FIND_DATA find_data;
- memset(&find_data, 0, sizeof(find_data));
- HANDLE file_handle = FindFirstFile(scan_path, &find_data);
- if (file_handle != INVALID_HANDLE_VALUE)
- {
- do
- {
- char *ptr = strdup(find_data.cFileName);
- new MixFileClass(ptr);
- MixFileClass::Cache(ptr);
- } while (FindNextFile(file_handle, &find_data));
- FindClose(file_handle);
- }
-
- memset(&find_data, 0, sizeof(find_data));
- strcpy(scan_path, search_path);
- strcat(scan_path, "Ss*.MIX");
- file_handle = FindFirstFile(scan_path, &find_data);
- if (file_handle != INVALID_HANDLE_VALUE)
- {
- do
- {
- char *ptr = strdup(find_data.cFileName);
- new MixFileClass(ptr);
- MixFileClass::Cache(ptr);
- } while (FindNextFile(file_handle, &find_data));
- FindClose(file_handle);
- }
- path = CDFileClass::Get_Search_Path(p);
- if (path == NULL) {
- break;
- }
- }
- #if (0)
- struct find_t ff; // for _dos_findfirst
- if (!_dos_findfirst("SC*.MIX", _A_NORMAL, &ff)) {
- char * ptr;
- do {
- ptr = strdup(ff.name);
- new MixFileClass(ptr);
- MixFileClass::Cache(ptr);
- // free(ptr);
- } while(!_dos_findnext(&ff));
- }
- if (!_dos_findfirst("SS*.MIX", _A_NORMAL, &ff)) {
- char * ptr;
- do {
- ptr = strdup(ff.name);
- new MixFileClass(ptr);
- // free(ptr);
- } while(!_dos_findnext(&ff));
- }
- #endif
- #endif //DEMO
- CCDebugString ("C&C95 - About to register GENERAL.MIX\n");
- //
- // This is a problem because registering the mix file can call Force_CD_Available which will try to load General.Mix
- // Might as well just cut to the chase and call it directly.
- // ST - 1/3/2019 5:19PM
- //
- //if (GeneralMix) delete GeneralMix;
- //GeneralMix = new MixFileClass("GENERAL.MIX");
- Force_CD_Available(RequiredCD);
- // if (!_dos_findfirst("SC*.MIX", _A_NORMAL, &ff)) {
- // do {
- // new MixFileClass(ff.name);
- // MixFileClass::Cache(ff.name);
- // } while(!_dos_findnext(&ff));
- // }
- /*
- ** Inform the file system of the various MIX files.
- */
- #ifdef DEMO
- new MixFileClass("DEMO.MIX");
- if (CCFileClass("DEMOM.MIX").Is_Available()) {
- if (!MoviesMix) MoviesMix = new MixFileClass("DEMOM.MIX");
- ScoresPresent = true;
- ThemeClass::Scan();
- }
- #else
- CCDebugString ("C&C95 - About to register CONQUER.MIX\n");
- new MixFileClass("CONQUER.MIX"); // Cached.
- CCDebugString ("C&C95 - About to register TRANSIT.MIX\n");
- new MixFileClass("TRANSIT.MIX");
- CCDebugString ("C&C95 - About to register GENERAL.MIX\n");
- if (!GeneralMix) GeneralMix = new MixFileClass("GENERAL.MIX"); // Never cached.
- // if (CCFileClass("MOVIES.MIX").Is_Available()) {
- CCDebugString ("C&C95 - About to register MOVIES.MIX\n");
- if (!MoviesMix) MoviesMix = new MixFileClass("MOVIES.MIX"); // Never cached.
- // }
- #if (0)
- /*
- ** Extract a movie from a mixfile.
- */
- char *file_ptr = (char*)Alloc (32 * 1024 * 1024, MEM_NORMAL);
- CCFileClass whatever ("PINTLE.VQA");
- int len = whatever.Size();
- whatever.Open();
- DWORD actual;
- HANDLE sfile = CreateFile("c:\\temp\\PINTLE.VQA", GENERIC_WRITE, 0,
- NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (sfile != INVALID_HANDLE_VALUE){
- SetFilePointer (sfile, 0, NULL, FILE_END);
- do{
- whatever.Read (file_ptr, MIN (len, 1024*64));
- WriteFile(sfile, file_ptr, MIN (len, 1024*64), &actual, NULL);
- len -= MIN (len, 1024*64);
- }while ( len >0 );
- CloseHandle (sfile);
- }
- whatever.Close();
- Free (file_ptr);
- #endif //(0)
- /*
- ** Register the score mixfile.
- */
- CCDebugString ("C&C95 - About to register SCORES.MIX\n");
- ScoresPresent = false;
- // if (CCFileClass("SCORES.MIX").Is_Available()) {
- ScoresPresent = true;
- if (!ScoreMix) {
- ScoreMix = new MixFileClass("SCORES.MIX");
- ThemeClass::Scan();
- }
- // }
- #endif
- /*
- ** These are sound card specific, but the install program would have
- ** copied the coorect versions to the hard drive.
- */
- CCDebugString ("C&C95 - About to register SPEECH.MIX\n");
- if (CCFileClass("SPEECH.MIX").Is_Available()) {
- new MixFileClass("SPEECH.MIX"); // Never cached.
- }
- CCDebugString ("C&C95 - About to register SOUNDS.MIX\n");
- new MixFileClass("SOUNDS.MIX"); // Cached.
- /*
- ** Initialize the animation system.
- */
- CCDebugString ("C&C95 - About to initialise the animation system\n");
- Anim_Init();
- if (SpawnedFromWChat){
- Special.IsFromWChat = true;
- }
- /*
- ** Play the introduction movies.
- */
- CCDebugString ("C&C95 - About to play the intro movie\n");
- if (!Special.IsFromInstall && !Special.IsFromWChat) Play_Intro(true);
- /*
- ** Wait for a VSync; during the vertical blank, set the game palette & blit
- ** the title screen. We must ensure no RGB values in the game palette match
- ** those in the WWLIB's 'CurrentPalette', or the WWLIB palette-set routine
- ** will skip that color; the VQ player will have changed that color (behind
- ** WWLIB's back), so it will be incorrect.
- */
- memset(CurrentPalette, 0x01, 768);
- if (!Special.IsFromInstall) {
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- }
- Hide_Mouse();
- Wait_Vert_Blank();
- if (!Special.IsFromInstall) {
- Set_Palette(Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Show_Mouse();
- }
- Call_Back();
- // Window_Dialog_Box(hCCLibrary, "DIALOG_1", MainWindow, MakeProcInstance((FARPROC)Start_Game_Proc, hInstance));
- // if (hCCLibrary) FreeLibrary(hCCLibrary);
- #ifdef DEMO
- MixFileClass::Cache("DEMO.MIX");
- MixFileClass::Cache("SOUNDS.MIX");
- #else
- /*
- ** Cache the main game data. This operation can take a very long time.
- */
- MixFileClass::Cache("CONQUER.MIX");
- if (SampleType != 0 && !Debug_Quiet) {
- MixFileClass::Cache("SOUNDS.MIX");
- if (Special.IsJuvenile) {
- new MixFileClass("ZOUNDS.MIX"); // Cached.
- MixFileClass::Cache("ZOUNDS.MIX");
- }
- }
- Call_Back();
- #endif
- // malloc(2);
- /*
- ** Perform any special debug-only processing. This includes preparing the
- ** monochrome screen.
- */
- Mono_Clear_Screen();
- #ifdef ONHOLD
- /*
- ** Check for addition options not specified on the command-line. This must
- ** be done before the One_Time calls, but after the shape buffer is set up.
- */
- Parse_INI_File();
- #endif
- /*
- ** Perform one-time game system initializations.
- */
- Call_Back();
- // malloc(3);
- Map.One_Time();
- // malloc(4);
- Logic.One_Time();
- // malloc(5);
- Options.One_Time();
- // malloc(6);
- ObjectTypeClass::One_Time();
- BuildingTypeClass::One_Time();
- BulletTypeClass::One_Time();
- HouseTypeClass::One_Time();
- TemplateTypeClass::One_Time();
- OverlayTypeClass::One_Time();
- SmudgeTypeClass::One_Time();
- TerrainTypeClass::One_Time();
- UnitTypeClass::One_Time();
- InfantryTypeClass::One_Time();
- AnimTypeClass::One_Time();
- AircraftTypeClass::One_Time();
- HouseClass::One_Time();
- /*
- ** Speech holding tank buffer. Since speech does not mix, it can be placed
- ** into a custom holding tank only as large as the largest speech file to
- ** be played.
- */
- SpeechBuffer = new char [SPEECH_BUFFER_SIZE];
- Call_Back();
- /*
- ** WWLIB bug: MouseState is in some undefined state; show the mouse until
- ** it really shows.
- */
- Map.Set_Default_Mouse(MOUSE_NORMAL, false);
- Show_Mouse();
- //#ifdef FIX_ME_LATER
- while (Get_Mouse_State() > 0) Show_Mouse();
- //#endif //FIX_ME_LATER
- Call_Back();
- #ifndef DEMO
- /*
- ** Load multiplayer scenario descriptions
- */
- Read_Scenario_Descriptions();
- #endif
- /*
- ** Initialize the multiplayer score values
- */
- MPlayerGamesPlayed = 0;
- MPlayerNumScores = 0;
- MPlayerCurGame = 0;
- for (int i = 0; i < MAX_MULTI_NAMES; i++) {
- MPlayerScore[i].Name[0] = '\0';
- MPlayerScore[i].Wins = 0;
- for (int j = 0; j < MAX_MULTI_GAMES; j++) {
- MPlayerScore[i].Kills[j] = -1; // -1 = this player didn't play this round
- }
- }
- /*
- ** Copy the title screen's palette into the GamePalette & OriginalPalette,
- ** because the options Load routine uses these palettes to set the brightness, etc.
- */
- memcpy (GamePalette, Palette, 768);
- memcpy (OriginalPalette, Palette, 768);
- /*
- ** Read game options, so the GameSpeed is initialized when multiplayer
- ** dialogs are invoked. (GameSpeed must be synchronized between systems.)
- */
- Options.Load_Settings();
- return(true);
- }
- //#ifndef NOMEMCHECK
- void Uninit_Game(void)
- {
- delete Map.ShadowPage;
- Map.ShadowPage = NULL;
- Map.Free_Cells();
- delete [] SpeechBuffer;
- CCFileClass::Clear_Search_Drives();
- MixFileClass::Free_All();
- Units.Set_Heap(0);
- Factories.Set_Heap(0);
- Terrains.Set_Heap(0);
- Templates.Set_Heap(0);
- Smudges.Set_Heap(0);
- Overlays.Set_Heap(0);
- Infantry.Set_Heap(0);
- Bullets.Set_Heap(0);
- Buildings.Set_Heap(0);
- Anims.Set_Heap(0);
- Aircraft.Set_Heap(0);
- Triggers.Set_Heap(0);
- TeamTypes.Set_Heap(0);
- Teams.Set_Heap(0);
- Houses.Set_Heap(0);
- delete [] _ShapeBuffer;
- Set_Shape_Buffer(NULL, 0);
- delete [] BlackPalette;
- delete [] GamePalette;
- delete [] OriginalPalette;
- delete [] WhitePalette;
- WWDOS_Shutdown();
- delete [] Palette;
- }
- //#endif
- extern bool Do_The_Internet_Menu_Thang(void);
- extern int ShowCommand;
- /***********************************************************************************************
- * Select_Game -- The game's main menu *
- * *
- * INPUT: *
- * fade if true, will fade the palette in gradually *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 06/05/1995 BRR : Created. *
- *=============================================================================================*/
- extern int Com_Fake_Scenario_Dialog(void);
- extern int Com_Show_Fake_Scenario_Dialog(void);
- extern int WChatMaxAhead;
- extern int WChatSendRate;
- void Check_From_WChat(char *wchat_name);
- bool Select_Game(bool fade)
- {
- enum {
- SEL_TIMEOUT = -1, // main menu timeout--go into attract mode
- #ifdef NEWMENU
- SEL_NEW_SCENARIO, // Expansion scenario to play.
- #endif
- SEL_START_NEW_GAME, // start a new game
- #ifdef BONUS_MISSIONS
- SEL_BONUS_MISSIONS,
- #endif //BONUS_MISSIONS
- SEL_INTERNET,
- SEL_LOAD_MISSION, // load a saved game
- SEL_MULTIPLAYER_GAME, // play modem/null-modem/network game
- SEL_INTRO, // replay the intro
- SEL_EXIT, // exit to DOS
- SEL_FAME, // view the hall of fame
- SEL_NONE, // placeholder default value
- };
- bool gameloaded=false; // Has the game been loaded from the menu?
- int selection; // the default selection
- bool process = true; // false = break out of while loop
- bool display = true;
- CountDownTimerClass count;
- int cd_index;
- MEMORYSTATUS mem_info;
- mem_info.dwLength=sizeof(mem_info);
- GlobalMemoryStatus(&mem_info);
- /*
- ** Enable the DDE Server so we can get internet start game packets from WChat
- */
- DDEServer.Enable();
- if (Special.IsFromInstall) {
- /*
- ** Special case for machines with 12 megs or less - just play intro, no choose side screen
- */
- if (mem_info.dwTotalPhys < 12*1024*1024){
- VisiblePage.Clear();
- Play_Movie("INTRO2", THEME_NONE, false);
- BreakoutAllowed = true;
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- fade = true;
- VisiblePage.Clear();
- }else{
- display = false;
- Show_Mouse();
- }
- }
- /*
- ** [Re]set any globals that need it, in preparation for a new scenario
- */
- GameActive = true;
- DoList.Init();
- OutList.Init();
- Frame = 0;
- PlayerWins = false;
- PlayerLoses = false;
- MPlayerObiWan = false;
- Debug_Unshroud = false;
- Map.Set_Cursor_Shape(0);
- Map.PendingObjectPtr = 0;
- Map.PendingObject = 0;
- Map.PendingHouse = HOUSE_NONE;
- /*
- ** Initialize multiplayer-protocol-specific variables:
- ** If CommProtocol MULTI_E_COMP is used, you must:
- ** Init FrameSendRate to a sensible value (3 is good)
- ** Init MPlayerMaxAhead to an even multiple of FrameSendRate, and it must
- ** be at least 2 * MPlayerMaxAhead
- */
- CommProtocol = COMM_PROTOCOL_SINGLE_NO_COMP;
- if (!Special.IsFromWChat){
- FrameSendRate = 3;
- }
- ProcessTicks = 0;
- ProcessFrames = 0;
- DesiredFrameRate = 30;
- //#if(TIMING_FIX)
- NewMaxAheadFrame1 = 0;
- NewMaxAheadFrame2 = 0;
- //#endif
- /*
- ** Init multiplayer game scores. Let Wins accumulate; just init the current
- ** Kills for this game. Kills of -1 means this player didn't play this round.
- */
- for (int i = 0 ; i < MAX_MULTI_GAMES; i++) {
- MPlayerScore[i].Kills[MPlayerCurGame] = -1;
- }
- /*
- ** Set default mouse shape
- */
- Map.Set_Default_Mouse(MOUSE_NORMAL, false);
- /*
- ** If the last game we played was a multiplayer game, jump right to that
- ** menu by pre-setting 'selection'.
- */
- if (GameToPlay == GAME_NORMAL) {
- selection = SEL_NONE;
- } else {
- selection = SEL_MULTIPLAYER_GAME;
- }
- /*
- ** Main menu processing; only do this if we're not in editor mode.
- */
- if (!Debug_Map) {
- /*
- ** Menu selection processing loop
- */
- ScenarioInit++;
- Theme.Queue_Song(THEME_MAP1);
- ScenarioInit--;
- /*
- ** If we're playing back a recording, load all pertinant values & skip
- ** the menu loop. Hide the now-useless mouse pointer.
- */
- if (PlaybackGame && RecordFile.Is_Available()) {
- if (RecordFile.Open(READ)) {
- Load_Recording_Values();
- process = false;
- Theme.Fade_Out();
- } else
- PlaybackGame = false;
- }
- /*
- ** Handle case where we were spawned from Wchat
- */
- if (SpawnedFromWChat){
- Special.IsFromInstall = false; //Dont play intro if we were spawned from wchat
- selection = SEL_INTERNET;
- Theme.Queue_Song(THEME_NONE);
- GameToPlay = GAME_INTERNET;
- display = false;
- Set_Logic_Page(SeenBuff);
- }
- while (process) {
- /*
- ** If we have just received input focus again after running in the background then
- ** we need to redraw.
- */
- if (AllSurfaces.SurfacesRestored){
- AllSurfaces.SurfacesRestored=FALSE;
- display=TRUE;
- }
- /*
- ** Redraw the title page if needed
- */
- if (display) {
- Hide_Mouse();
- /*
- ** Display the title page; fade it in if this is the first time
- ** through the loop, and the 'fade' flag is true
- */
- Load_Title_Screen("HTITLE.PCX", &HidPage, Palette);
- memcpy (GamePalette, Palette, 768);
- Blit_Hid_Page_To_Seen_Buff();
- if (fade) {
- Fade_Palette_To(Palette, FADE_PALETTE_SLOW, Call_Back);
- fade = false;
- }
- Set_Logic_Page(SeenBuff);
- #ifdef VIRGIN_CHEAT_KEYS
- Fancy_Text_Print("V.%d%s", SeenBuff.Get_Width() - 1, SeenBuff.Get_Height() - 10, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText, FOREIGN_VERSION_NUMBER);
- // Fancy_Text_Print("V.%d%s%02d", 319, 190, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText, FOREIGN_VERSION_NUMBER);
- #else
- #ifdef DEMO
- Version_Number();
- Fancy_Text_Print("DEMO V%s", SeenBuff.Get_Width() - 1, SeenBuff.Get_Height() - 10, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, VersionText);
- #else
- Fancy_Text_Print("V.%d%s", SeenBuff.Get_Width() - 1, SeenBuff.Get_Height() - 10, DKGREY, TBLACK, TPF_6POINT|TPF_FULLSHADOW|TPF_RIGHT, Version_Number(), VersionText);
- #endif
- #endif
- display = false;
- Show_Mouse();
- } else {
- if (RunningAsDLL) {
- return true;;
- }
- }
- /*
- ** Display menu and fetch selection from player.
- */
- if (Special.IsFromInstall && mem_info.dwTotalPhys >= 12*1024*1024){
- selection = SEL_START_NEW_GAME;
- Theme.Queue_Song(THEME_NONE);
- }
- /*
- ** Handle case where we were spawned from Wchat
- */
- if (Special.IsFromWChat && DDEServer.Get_MPlayer_Game_Info()){
- Check_From_WChat(NULL);
- selection = SEL_MULTIPLAYER_GAME;
- Theme.Queue_Song(THEME_NONE);
- GameToPlay = GAME_INTERNET;
- }else{
- /*
- ** We werent spawned but we could still receive a DDE packet from wchat
- */
- if (DDEServer.Get_MPlayer_Game_Info()){
- Check_From_WChat(NULL);
- /*
- ** Make sure top and bottom of screen are clear in 640x480 mode
- */
- if (ScreenHeight == 480){
- VisiblePage.Fill_Rect (0, 0, 639, 40, 0);
- VisiblePage.Fill_Rect (0, 440, 639, 479, 0);
- }
- }
- }
- if (selection == SEL_NONE) {
- // selection = Main_Menu(0);
- selection = Main_Menu(ATTRACT_MODE_TIMEOUT);
- }
- Call_Back();
- switch (selection) {
- #ifdef NEWMENU
- case SEL_INTERNET:
- /*
- ** Only call up the internet menu code if we dont already have connect info from WChat
- */
- if (!DDEServer.Get_MPlayer_Game_Info()){
- CCDebugString ("C&C95 - About to call Internet Menu.\n");
- if (Do_The_Internet_Menu_Thang() && DDEServer.Get_MPlayer_Game_Info()){
- CCDebugString ("C&C95 - About to call Check_From_WChat.\n");
- Check_From_WChat(NULL);
- selection = SEL_MULTIPLAYER_GAME;
- display = false;
- GameToPlay = GAME_INTERNET;
- }else{
- selection = SEL_NONE;
- display = true;
- }
- }else{
- CCDebugString ("C&C95 - About to call Check_From_WChat.\n");
- Check_From_WChat(NULL);
- display = false;
- GameToPlay = GAME_INTERNET;
- selection = SEL_MULTIPLAYER_GAME;
- }
- break;
- /*
- ** Pick an expansion scenario.
- */
- case SEL_NEW_SCENARIO:
- CarryOverMoney = 0;
- if (Expansion_Dialog()) {
- Theme.Fade_Out();
- // Theme.Queue_Song(THEME_AOI);
- GameToPlay = GAME_NORMAL;
- process = false;
- } else {
- display = true;
- selection = SEL_NONE;
- }
- break;
- #ifdef BONUS_MISSIONS
- /*
- ** User selected to play a bonus scenario.
- */
- case SEL_BONUS_MISSIONS:
- CarryOverMoney = 0;
- /*
- ** Ensure that CD1 or CD2 is in the drive. These missions
- ** are not on the covert CD.
- */
- cd_index = Get_CD_Index(CCFileClass::Get_CD_Drive(), 1*60);
- /*
- ** If cd_index == 2 then its a covert CD
- */
- if (cd_index == 2){
- RequiredCD = 0;
- if (!Force_CD_Available (RequiredCD)){
- Prog_End("Select_Game - CD not found", true);
- exit(EXIT_FAILURE);
- }
- }
- if (Bonus_Dialog()) {
- Theme.Fade_Out();
- GameToPlay = GAME_NORMAL;
- process = false;
- } else {
- display = true;
- selection = SEL_NONE;
- }
- break;
- #endif //BONUS_MISSIONS
- #endif
- /*
- ** SEL_START_NEW_GAME: Play the game
- */
- case SEL_START_NEW_GAME:
- CarryOverMoney = 0;
- #ifdef DEMO
- Hide_Mouse();
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- Load_Title_Screen("PREPICK.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
- Clear_KeyBuffer();
- while (!Check_Key_Num()) {
- Call_Back();
- }
- Get_Key_Num();
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- Show_Mouse();
- Scenario = 1;
- BuildLevel = 1;
- #else
- Scenario = 1;
- BuildLevel = 1;
- #endif
- ScenPlayer = SCEN_PLAYER_GDI;
- ScenDir = SCEN_DIR_EAST;
- Whom = HOUSE_GOOD;
- #ifndef DEMO
- Theme.Fade_Out();
- Choose_Side();
- #endif
- /*
- ** If user is playing special mode, do NOT change Whom; leave it set to
- ** GDI or NOD. Ini.cpp will set the player's ActLike to mirror the
- ** Whom value.
- */
- if (Special.IsJurassic && AreThingiesEnabled) {
- ScenPlayer = SCEN_PLAYER_JP;
- ScenDir = SCEN_DIR_EAST;
- }
- GameToPlay = GAME_NORMAL;
- process = false;
- break;
- /*
- ** Load a saved game.
- */
- case SEL_LOAD_MISSION:
- if (LoadOptionsClass(LoadOptionsClass::LOAD).Process()) {
- //Theme.Fade_Out();
- Theme.Queue_Song(THEME_AOI);
- process = false;
- gameloaded = true;
- } else {
- display = true;
- selection = SEL_NONE;
- }
- break;
- /*
- ** SEL_MULTIPLAYER_GAME: set 'GameToPlay' to NULL-modem, modem, or
- ** network play.
- */
- case SEL_MULTIPLAYER_GAME:
- #ifdef DEMO
- Hide_Mouse();
- Set_Palette(BlackPalette);
- Load_Title_Screen("DEMOPIC.PCX", &HidPage, Palette);
- Blit_Hid_Page_To_Seen_Buff();
- Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
- Clear_KeyBuffer();
- while (!Check_Key()) {
- Call_Back();
- }
- Get_Key();
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- Show_Mouse();
- display = true;
- fade = true;
- selection = SEL_NONE;
- #else
- switch (GameToPlay) {
- /*
- ** If 'GameToPlay' isn't already set up for a multiplayer game,
- ** we must prompt the user for which type of multiplayer game
- ** they want.
- */
- case GAME_NORMAL:
- GameToPlay = Select_MPlayer_Game();
- if (GameToPlay == GAME_NORMAL) { // 'Cancel'
- display = true;
- selection = SEL_NONE;
- }
- break;
- case GAME_NULL_MODEM:
- case GAME_MODEM:
- #if (0)
- if ( NullModem.Num_Connections() ) {
- NullModem.Init_Send_Queue();
- if ((GameToPlay == GAME_NULL_MODEM &&
- ModemGameToPlay == MODEM_NULL_HOST) ||
- (GameToPlay == GAME_MODEM &&
- ModemGameToPlay == MODEM_DIALER) ) {
- if ( !Com_Scenario_Dialog() ) {
- GameToPlay = Select_Serial_Dialog();
- if (GameToPlay == GAME_NORMAL) { // user hit Cancel
- display = true;
- selection = SEL_NONE;
- }
- }
- } else {
- if ( !Com_Show_Scenario_Dialog() ) {
- GameToPlay = Select_Serial_Dialog();
- if (GameToPlay == GAME_NORMAL) { // user hit Cancel
- display = true;
- selection = SEL_NONE;
- }
- }
- }
- } else {
- GameToPlay = Select_MPlayer_Game();
- if (GameToPlay == GAME_NORMAL) { // 'Cancel'
- display = true;
- selection = SEL_NONE;
- }
- }
- #endif
- break;
- #ifdef FORCE_WINSOCK
- /*
- ** Handle being spawned from WChat. Intermnet play based on IPX code now.
- */
- case GAME_INTERNET:
- CCDebugString ("C&C95 - case GAME_INTERNET:\n");
- if (Special.IsFromWChat){
- //MessageBox (NULL, "About to restore focus to C&C95", "C&C95", MB_OK);
- CCDebugString ("C&C95 - About to give myself focus.\n");
- SetForegroundWindow ( MainWindow );
- ShowWindow ( MainWindow, ShowCommand );
- CCDebugString ("C&C95 - About to initialise Winsock.\n");
- if (Winsock.Init()){
- CCDebugString ("C&C95 - About to read multiplayer settings.\n");
- Read_MultiPlayer_Settings ();
- Server = PlanetWestwoodIsHost;
- CCDebugString ("C&C95 - About to set addresses.\n");
- Winsock.Set_Host_Address(PlanetWestwoodIPAddress);
- CCDebugString ("C&C95 - About to call Start_Server or Start_Client.\n");
- if (Server){
- ModemGameToPlay = INTERNET_HOST;
- Winsock.Start_Server();
- }else{
- ModemGameToPlay = INTERNET_JOIN;
- Winsock.Start_Client();
- }
- //#if (0)
- /*
- ** Flush out any pending packets from a previous game.
- */
- CCDebugString ("C&C95 - About to flush packet queue.\n");
- CCDebugString ("C&C95 - Allocating scrap memory.\n");
- char *temp_buffer = new char[1024];
- CCDebugString ("C&C95 - Creating timer class instance.\n");
- CountDownTimerClass ptimer;
- CCDebugString ("C&C95 - Entering read loop.\n");
- while (Winsock.Read(temp_buffer, 1024)){
- CCDebugString ("C&C95 - Discarding a packet.\n");
- ptimer.Set (30, true);
- while (ptimer.Time()){};
- CCDebugString ("C&C95 - Ready to check for more packets.\n");
- }
- CCDebugString ("C&C95 - About to delete scrap memory.\n");
- delete temp_buffer;
- //#endif //(0)
- }else{
- CCDebugString ("C&C95 - Winsock failed to initialise.\n");
- GameToPlay = GAME_NORMAL;
- selection = SEL_EXIT;
- Special.IsFromWChat = false;
- break;
- }
- CCDebugString ("C&C95 - About to call Init_Network.\n");
- Init_Network();
- if (DDEServer.Get_MPlayer_Game_Info()){
- CCDebugString ("C&C95 - About to call Read_Game_Options.\n");
- Read_Game_Options( NULL );
- }else{
- Read_Game_Options( "C&CSPAWN.INI" );
- }
- if (Server){
- CCDebugString ("C&C95 - About to call Server_Remote_Connect.\n");
- if (Server_Remote_Connect()){
- CCDebugString ("C&C95 - Server_Remote_Connect returned success.\n");
- break;
- }else{
- /*
- ** We failed to connect to the other player
- *
- * SEND FAILURE PACKET TO WCHAT HERE !!!!!
- *
- */
- Winsock.Close();
- GameToPlay = GAME_NORMAL;
- selection = SEL_NONE;
- DDEServer.Delete_MPlayer_Game_Info(); // Make sure we dont go round in an infinite loop
- //Special.IsFromWChat = false;
- break;
- }
- }else{
- CCDebugString ("C&C95 - About to call Client_Remote_Connect.\n");
- if (Client_Remote_Connect()){
- CCDebugString ("C&C95 - Client_Remote_Connect returned success.\n");
- break;
- }else{
- /*
- ** We failed to connect to the other player
- *
- * SEND FAILURE PACKET TO WCHAT HERE !!!!!
- *
- */
- Winsock.Close();
- GameToPlay = GAME_NORMAL;
- selection = SEL_NONE;
- DDEServer.Delete_MPlayer_Game_Info(); // Make sure we dont go round in an infinite loop
- //Special.IsFromWChat = false;
- break;
- }
- }
- }else{
- GameToPlay = Select_MPlayer_Game();
- if (GameToPlay == GAME_NORMAL) { // 'Cancel'
- display = true;
- selection = SEL_NONE;
- }
- }
- break;
- #endif //FORCE_WINSOCK
- }
- switch (GameToPlay) {
- /*
- ** Internet, Modem or Null-Modem
- */
- case GAME_MODEM:
- case GAME_NULL_MODEM:
- case GAME_INTERNET:
- Theme.Fade_Out();
- ScenPlayer = SCEN_PLAYER_2PLAYER;
- ScenDir = SCEN_DIR_EAST;
- process = false;
- Options.ScoreVolume = 0;
- break;
- /*
- ** Network (IPX): start a new network game.
- */
- case GAME_IPX:
- /*
- ** Init network system & remote-connect
- */
- if (Init_Network() && Remote_Connect()) {
- #if (0)
- char seed[80];
- sprintf (seed, "Seed: %08x\n", Seed);
- CCDebugString (seed);
- sprintf (seed, "rand: %04x\n", rand());
- CCDebugString (seed);
- sprintf (seed, "rand: %04x\n", rand());
- CCDebugString (seed);
- sprintf (seed, "rand: %04x\n", rand());
- CCDebugString (seed);
- #endif
- Options.ScoreVolume = 0;
- ScenPlayer = SCEN_PLAYER_MPLAYER;
- ScenDir = SCEN_DIR_EAST;
- process = false;
- Theme.Fade_Out();
- } else { // user hit cancel, or init failed
- GameToPlay = GAME_NORMAL;
- display = true;
- selection = SEL_NONE;
- }
- break;
- }
- #endif
- break;
- /*
- ** Play a VQ
- */
- case SEL_INTRO:
- Theme.Fade_Out();
- Theme.Stop();
- Call_Back();
- Force_CD_Available(-1);
- Play_Intro(false);
- Hide_Mouse();
- // verify existance of movie file before playing this sequence.
- if (CCFileClass("TRAILER.VQA").Is_Available()) {
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- VisiblePage.Clear();
- if (CCFileClass("ATTRACT2.CPS").Is_Available()){
- Load_Uncompress(CCFileClass("ATTRACT2.CPS"), SysMemPage, SysMemPage, Palette);
- SysMemPage.Scale(SeenBuff, 0, 0, 0, 0, 320, 199, 640, 398);
- Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
- }
- Clear_KeyBuffer();
- count.Set(TIMER_SECOND*3);
- while (count.Time()) {
- Call_Back();
- }
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- Play_Movie("TRAILER"); // Red Alert teaser.
- }
- if (CCFileClass("SIZZLE.VQA").Is_Available()) {
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- VisiblePage.Clear();
- if (CCFileClass("ATTRACT2.CPS").Is_Available()){
- Load_Uncompress(CCFileClass("ATTRACT2.CPS"), SysMemPage, SysMemPage, Palette);
- SysMemPage.Scale(SeenBuff, 0, 0, 0, 0, 320, 199, 640, 398);
- Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
- }
- Clear_KeyBuffer();
- count.Set(TIMER_SECOND*3);
- while (count.Time()) {
- Call_Back();
- }
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- Play_Movie("SIZZLE"); // Red Alert teaser.
- }
- if (CCFileClass("SIZZLE2.VQA").Is_Available()) {
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- VisiblePage.Clear();
- if (CCFileClass("ATTRACT2.CPS").Is_Available()){
- Load_Uncompress(CCFileClass("ATTRACT2.CPS"), SysMemPage, SysMemPage, Palette);
- SysMemPage.Scale(SeenBuff, 0, 0, 0, 0, 320, 199, 640, 398);
- Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
- }
- Clear_KeyBuffer();
- count.Set(TIMER_SECOND*3);
- while (count.Time()) {
- Call_Back();
- }
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- Play_Movie("SIZZLE2"); // Red Alert teaser.
- }
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- VisiblePage.Clear();
- if (CCFileClass("ATTRACT2.CPS").Is_Available()){
- Load_Uncompress(CCFileClass("ATTRACT2.CPS"), SysMemPage, SysMemPage, Palette);
- SysMemPage.Scale(SeenBuff, 0, 0, 0, 0, 320, 199, 640, 398);
- Fade_Palette_To(Palette, FADE_PALETTE_MEDIUM, Call_Back);
- }
- Clear_KeyBuffer();
- count.Set(TIMER_SECOND*3);
- while (count.Time()) {
- Call_Back();
- }
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- Play_Movie("CC2TEASE");
- Show_Mouse();
- ScenarioInit++;
- Theme.Play_Song (THEME_MAP1);
- ScenarioInit--;
- display = true;
- fade = true;
- selection = SEL_NONE;
- break;
- /*
- ** Exit to DOS.
- */
- case SEL_EXIT:
- #ifdef JAPANESE
- Hide_Mouse();
- #endif
- Theme.Fade_Out();
- Fade_Palette_To(BlackPalette, FADE_PALETTE_SLOW, NULL);
- #ifdef JAPANESE
- VisiblePage.Clear();
- #endif
- return(false);
- /*
- ** Display the hall of fame.
- */
- case SEL_FAME:
- break;
- case SEL_TIMEOUT:
- if (AllowAttract && RecordFile.Is_Available()) {
- PlaybackGame = true;
- if (RecordFile.Open(READ)) {
- Load_Recording_Values();
- process = false;
- Theme.Fade_Out();
- } else {
- PlaybackGame = false;
- selection = SEL_NONE;
- }
- } else {
- selection = SEL_NONE;
- }
- break;
- default:
- break;
- }
- }
- } else {
- /*
- ** For Debug_Map (editor) mode, if JP option is on, set to load that scenario
- */
- Scenario = 1;
- if (Special.IsJurassic && AreThingiesEnabled) {
- ScenPlayer = SCEN_PLAYER_JP;
- ScenDir = SCEN_DIR_EAST;
- }
- }
- CCDebugString ("C&C95 - About to start game initialisation.\n");
- #ifdef FORCE_WINSOCK
- if (GameToPlay == GAME_INTERNET){
- CommProtocol = COMM_PROTOCOL_MULTI_E_COMP;
- if (!Special.IsFromWChat){
- FrameSendRate = 5; //3;
- }
- }
- #endif //FORCE_WINSOCK
- /*
- ** Don't carry stray keystrokes into game.
- */
- Kbd.Clear();
- /*
- ** Get a pointer to the compiler's random number seed.
- ** the Get_EAX() must follow immediately after the srand(0) in order to save
- ** the address of the random seed. (Currently not used.)
- */
- srand(0);
- //RandSeedPtr = (long *)Get_EAX(); // ST - 1/2/2019 5:26PM
- /*
- ** Initialize the random number Seed. For multiplayer, this will have been done
- ** in the connection dialogs. For single-player games, AND if we're not playing
- ** back a recording, init the Seed to a random value.
- */
- if (GameToPlay == GAME_NORMAL && !PlaybackGame) {
- srand(timeGetTime());
- //randomize();
- Seed = rand();
- }
- /*
- ** If user has specified a desired random number seed, use it for multiplayer games
- */
- if (CustomSeed != 0) {
- Seed = CustomSeed;
- }
- /*
- ** Save initialization values if we're recording this game.
- ** This must be done after 'Seed' has been initialized.
- */
- if (RecordGame) {
- if (RecordFile.Open(WRITE)) {
- Save_Recording_Values();
- } else {
- RecordGame = false;
- }
- }
- /*
- ** Initialize the random-number generator.
- */
- //Seed = 1;
- srand(Seed);
- RandNumb = Seed;
- SimRandIndex = 0;
- #if (0)
- DWORD actual;
- HANDLE sfile = CreateFile("random.txt", GENERIC_WRITE, 0,
- NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (sfile != INVALID_HANDLE_VALUE){
- SetFilePointer (sfile, 0, NULL, FILE_END);
- int minimum;
- int maximum;
- char whatever[80];
- for ( int i=0 ; i<1000 ; i++){
- minimum = rand();
- maximum = rand();
- sprintf (whatever, "%04x\n", Random_Pick(minimum, maximum));
- WriteFile(sfile, whatever, strlen(whatever), &actual, NULL);
- }
- CloseHandle (sfile);
- }
- #endif
- /*
- ** Load the scenario. Specify variation 'A' for the editor; for the game,
- ** don't specify a variation, to make 'Set_Scenario_Name()' pick a random one.
- ** Skip this if we've already loaded a save-game.
- */
- if (!gameloaded) {
- if (Debug_Map) {
- Set_Scenario_Name(ScenarioName, Scenario, ScenPlayer, ScenDir, SCEN_VAR_A);
- } else {
- Set_Scenario_Name(ScenarioName, Scenario, ScenPlayer, ScenDir);
- }
- /*
- ** Start_Scenario() changes the palette; so, fade out & clear the screen
- ** before calling it.
- */
- Hide_Mouse();
- if (selection != SEL_START_NEW_GAME) {
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- HiddenPage.Clear();
- VisiblePage.Clear();
- }
- Show_Mouse();
- Special.IsFromInstall = 0;
- CCDebugString ("C&C95 - Starting scenario.\n");
- if (!Start_Scenario(ScenarioName)) {
- return(false);
- }
- CCDebugString ("C&C95 - Scenario started OK.\n");
- }
- /*
- ** For multiplayer games, initialize the inter-player message system.
- ** Do this after loading the scenario, so the map's upper-left corner is
- ** properly set.
- */
- CCDebugString ("C&C95 - Initialising message system.\n");
- int factor = (SeenBuff.Get_Width() == 320) ? 1 : 2;
- Messages.Init(Map.TacPixelX, Map.TacPixelY, 6, MAX_MESSAGE_LENGTH, 6*factor+1);
- /*
- ** Hide the SeenBuff; force the map to render one frame. The caller can
- ** then fade the palette in.
- ** (If we loaded a game, this step will fade out the title screen. If we
- ** started a scenario, Start_Scenario() will have played a couple of VQ
- ** movies, which will have cleared the screen to black already.)
- */
- CCDebugString ("C&C95 - About to call Call_Back.\n");
- Call_Back();
- /*
- ** This is desperately sad isnt it?
- */
- Hide_Mouse();
- Hide_Mouse();
- Hide_Mouse();
- Hide_Mouse();
- WWMouse->Erase_Mouse(&HidPage, TRUE);
- Fade_Palette_To(BlackPalette, FADE_PALETTE_MEDIUM, Call_Back);
- HiddenPage.Clear();
- VisiblePage.Clear();
- Set_Logic_Page(SeenBuff);
- Map.Flag_To_Redraw();
- Call_Back();
- Map.Render();
- //Show_Mouse();
- /*
- ** Special hack initialization of 'MPlayerMaxAhead' to accommodate the
- ** compression protocol technology.
- */
- #ifdef FORCE_WINSOCK
- if (CommProtocol==COMM_PROTOCOL_MULTI_E_COMP && GameToPlay!=GAME_NORMAL) {
- if (!Special.IsFromWChat){
- MPlayerMaxAhead = FrameSendRate * 3; //2;
- }else{
- MPlayerMaxAhead = WChatMaxAhead;
- FrameSendRate = WChatSendRate;
- }
- }
- #endif //FORCE_WINSOCK
- if (Debug_Map) {
- while (Get_Mouse_State() > 1) {
- Show_Mouse();
- }
- }
- return(true);
- }
- /***********************************************************************************************
- * Play_Intro -- plays the introduction & logo movies *
- * *
- * INPUT: *
- * for_real if true, this function plays the "real" intro; otherwise, it plays *
- * a delicious smorgasbord of visual delights, guaranteed to titillate *
- * the ocular & auditory nerve pathways. *
- * Well, it plays movies, anyway. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 06/06/1995 BRR : Created. *
- *=============================================================================================*/
- static void Play_Intro(bool for_real)
- {
- return; // No game intro movies. - LLL
- bool playright = !Key_Down(KN_LCTRL) || !Key_Down(KN_RCTRL);
- static int _counter = -1;
- static char * _names[] = {
- #ifdef DEMO
- "LOGO",
- #else
- "INTRO2",
- //#ifdef CHEAT_KEYS
- "GDIEND1",
- "GDIEND2",
- "GDIFINA",
- "GDIFINB",
- "AIRSTRK",
- "AKIRA",
- "BANNER",
- "BCANYON",
- "BKGROUND",
- "BOMBAWAY",
- "BOMBFLEE",
- "BURDET1",
- "BURDET2",
- "CC2TEASE",
- "CONSYARD",
- "DESFLEES",
- "DESKILL",
- "DESOLAT",
- "DESSWEEP",
- "FLAG",
- "FLYY",
- "FORESTKL",
- "GAMEOVER",
- "GDI1",
- "GDI10",
- "GDI11",
- "GDI12",
- "GDI13",
- "GDI14",
- "GDI15",
- "GDI2",
- "GDI3",
- "GDI3LOSE",
- "GDI4A",
- "GDI4B",
- "GDI5",
- "GDI6",
- "GDI7",
- "GDI8A",
- "GDI8B",
- "GDI9",
- "GDILOSE",
- "GUNBOAT",
- "HELLVALY",
- "INSITES",
- "KANEPRE",
- "LANDING",
- "LOGO",
- "NAPALM",
- "NITEJUMP",
- "NOD1",
- "NOD10A",
- "NOD10B",
- "NOD11",
- "NOD12",
- "NOD13",
- "NOD1PRE",
- "NOD2",
- "NOD3",
- "NOD4A",
- "NOD4B",
- "NOD5",
- "NOD6",
- "NOD7A",
- "NOD7B",
- "NOD8",
- "NOD9",
- "NODEND1",
- "NODEND2",
- "NODEND3",
- "NODEND4",
- "NODFINAL",
- "NODFLEES",
- "NODLOSE",
- "NODSWEEP",
- "NUKE",
- "OBEL",
- "PARATROP",
- "PINTLE",
- "PLANECRA",
- "PODIUM",
- "REFINT",
- "RETRO",
- "SABOTAGE",
- "SAMDIE",
- "SAMSITE",
- "SEIGE",
- "SETHPRE",
- "SPYCRASH",
- "STEALTH",
- "SUNDIAL",
- "TANKGO",
- "TANKKILL",
- "TBRINFO1",
- "TBRINFO2",
- "TBRINFO3",
- "TIBERFX",
- "TRTKIL_D",
- "TURTKILL",
- "VISOR",
- //#endif
- #endif
- NULL
- };
- Keyboard::Clear();
- if (for_real) {
- Hide_Mouse();
- Play_Movie("LOGO", THEME_NONE, false);
- Show_Mouse();
- } else {
- if (!Debug_Flag) {
- _counter = 0;
- } else {
- if (playright) _counter++;
- if (_counter == -1) _counter = 0;
- }
- Hide_Mouse();
- Play_Movie(_names[_counter], THEME_NONE);
- Show_Mouse();
- if (!_names[_counter]) {
- _counter = -1;
- }
- }
- }
- /***********************************************************************************************
- * Anim_Init -- Initialize the VQ animation control structure. *
- * *
- * VQ animations are controlled by a structure passed to the VQ player. This routine *
- * initializes the structure to values required by C&C. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: none *
- * *
- * WARNINGS: Only need to call this routine once at the beginning of the game. *
- * *
- * HISTORY: *
- * 12/20/1994 JLB : Created. *
- *=============================================================================================*/
- //extern LPDIRECTSOUND SoundObject;
- //extern LPDIRECTSOUNDBUFFER PrimaryBufferPtr;
- void Anim_Init(void)
- {
- //PG_TO_FIX
- #if (0)
- /* Configure player with INI file */
- VQA_DefaultConfig(&AnimControl);
- // void const * font = Load_Font(FONT8);
- // AnimControl.EVAFont = (char *)font;
- // AnimControl.CapFont = (char *)font;
- AnimControl.DrawFlags = VQACFGF_TOPLEFT;
- AnimControl.DrawFlags |= VQACFGF_BUFFER;
- AnimControl.DrawFlags |= VQACFGF_NOSKIP;
- //AnimControl.X1 =0;
- //AnimControl.Y1 =0;
- AnimControl.FrameRate = -1;
- AnimControl.DrawRate = -1;
- AnimControl.DrawerCallback = VQ_Call_Back;
- AnimControl.ImageWidth = 320;
- AnimControl.ImageHeight = 200;
- AnimControl.Vmode = 0;
- AnimControl.ImageBuf = (unsigned char *)SysMemPage.Get_Offset();
- //AnimControl.VBIBit = VertBlank;
- //AnimControl.DrawFlags |= VQACFGF_TOPLEFT;
- AnimControl.OptionFlags |= VQAOPTF_CAPTIONS|VQAOPTF_EVA;
- if (SlowPalette) {
- AnimControl.OptionFlags |= VQAOPTF_SLOWPAL;
- }
- #endif
- // AnimControl.AudioBuf = (unsigned char *)HidPage.Get_Buffer();
- // AnimControl.AudioBufSize = 32768U;
- //AnimControl.DigiCard = NewConfig.DigitCard;
- //AnimControl.HMIBufSize = 8192;
- //AnimControl.DigiHandle = Get_Digi_Handle();
- //AnimControl.Volume = 0x00FF;
- //AnimControl.AudioRate = 22050;
- // if (NewConfig.Speed) AnimControl.AudioRate = 11025;
-
-
- //PG_TO_FIX
- #if (0)
- AnimControl.SoundObject = SoundObject; //Get_Sound_Object();
- AnimControl.PrimaryBufferPtr = PrimaryBufferPtr; //Get_Primart_Buffer();
- #endif
-
- //if (!Debug_Quiet && Get_Digi_Handle() != -1) {
- //AnimControl.OptionFlags |= VQAOPTF_AUDIO;
- //}
- #if (0)
- if (MonoClass::Is_Enabled()) {
- AnimControl.OptionFlags |= VQAOPTF_MONO;
- }
- #endif
- }
- /***********************************************************************************************
- * Parse_Command_Line -- Parses the command line parameters. *
- * *
- * This routine should be called before the graphic mode is initialized. It examines the *
- * command line parameters and sets the appropriate globals. If there is an error, then *
- * it outputs a command summary and then returns false. *
- * *
- * INPUT: argc -- The number of command line arguments. *
- * *
- * argv -- Pointer to character string array that holds the individual arguments. *
- * *
- * OUTPUT: bool; Was the command line parsed successfully? *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 03/18/1995 JLB : Created. *
- *=============================================================================================*/
- bool Parse_Command_Line(int argc, char *argv[])
- {
- /*
- ** Parse the command line and set globals to reflect the parameters
- ** passed in.
- */
- #ifdef DEMO
- Scenario = 3;
- #else
- Scenario = 1;
- #endif
- ScenPlayer = SCEN_PLAYER_GDI;
- ScenDir = SCEN_DIR_EAST;
- Whom = HOUSE_GOOD;
- Special.Init();
- Debug_Map = false;
- // Debug_Play_Map = false;
- Debug_Unshroud = false;
- for (int index = 1; index < argc; index++) {
- char * string; // Pointer to argument.
- long code = 0;
- char arg_string[512];
- int str_len = strlen(argv[index]);
- char *src = argv[index];
- char *dest = arg_string;
- for (int i=0 ; i<str_len ; i++) {
- if (*src == '\"') {
- src++;
- } else {
- *dest++ = *src++;
- }
- }
- *dest++ = 0;
- string = arg_string;
- strupr(string);
- //string = strupr(argv[index]);
- /*
- ** Print usage text only if requested.
- */
- if (stricmp("/?", string) == 0 || stricmp("-?", string) == 0 || stricmp("-h", string) == 0 || stricmp("/h", string) == 0) {
- /*
- ** Unrecognized command line parameter... Display usage
- ** and then exit.
- */
- #ifdef GERMAN
- puts("Command & Conquer (c) 1995,1996 Westwood Studios\r\n"
- "Parameter:\r\n"
- // " -CD<Pfad> = Suchpfad f�r Daten-Dateien festlegen.\r\n"
- " -DESTNET = Netzwerkkennung des Zielrechners festlegen\r\n"
- " (Syntax: DESTNETxx.xx.xx.xx)\r\n"
- " -SOCKET = Kennung des Netzwerk-Sockets (0 - 16383)\n"
- " -STEALTH = Namen im Mehrspieler-Modus verstecken (\"Boss-Modus\")\r\n"
- " -MESSAGES = Mitteilungen von auáerhalb des Spiels zulassen\r\n"
- // " -ELITE = Fortgeschrittene KI und Gefechtstechniken.\r\n"
- "\r\n");
- #else
- #ifdef FRENCH
- puts("Command & Conquer (c) 1995, Westwood Studios\r\n"
- "ParamŠtres:\r\n"
- // " -CD<chemin d'accŠs> = Recherche des fichiers dans le\r\n"
- // " r‚pertoire indiqu‚.\r\n"
- " -DESTNET = Sp‚cifier le num‚ro de r‚seau du systŠme de destination\r\n"
- " (Syntaxe: DESTNETxx.xx.xx.xx)\r\n"
- " -SOCKET = ID poste r‚seau (0 … 16383)\r\n"
- " -STEALTH = Cacher les noms en mode multijoueurs (\"Mode Boss\")\r\n"
- " -MESSAGES = Autorise les messages ext‚rieurs … ce jeu.\r\n"
- "\r\n");
- #else
- puts("Command & Conquer (c) 1995, 1996 Westwood Studios\r\n"
- "Parameters:\r\n"
- #ifdef NEVER
- " CHEAT = Enable debug keys.\r\n"
- " -EDITOR = Enable scenario editor.\r\n"
- #endif
- // " -CD<path> = Set search path for data files.\r\n"
- " -DESTNET = Specify Network Number of destination system\r\n"
- " (Syntax: DESTNETxx.xx.xx.xx)\r\n"
- " -SOCKET = Network Socket ID (0 - 16383)\n"
- " -STEALTH = Hide multiplayer names (\"Boss mode\")\r\n"
- " -MESSAGES = Allow messages from outside this game.\r\n"
- " -o = Enable compatability with version 1.07.\r\n"
- #ifdef JAPANESE
- " -ENGLISH = Enable English keyboard compatibility.\r\n"
- #endif
- // " -ELITE = Advanced AI and combat characteristics.\r\n"
- #ifdef NEVER
- " -O[options]= Special control options;\r\n"
- " 1 : Tiberium grows.\r\n"
- " 2 : Tiberium grows and spreads.\r\n"
- " A : Aggressive player unit defense enabled.\r\n"
- " B : Bargraphs always displayed.\r\n"
- " C : Capture the flag mode.\r\n"
- " E : Elite defense mode disable (attacker advantage).\r\n"
- " D : Deploy reversal allowed for construction yard.\r\n"
- " F : Fleeing from direct immediate threats is enabled.\r\n"
- " H : Hussled recharge time.\r\n"
- " G : Growth for Tiberium slowed in multiplay.\r\n"
- " I : Inert weapons -- no damage occurs.\r\n"
- " J : 7th grade sound effects.\r\n"
- " M : Monochrome debug messages.\r\n"
- " N : Name the civilians and buildings.\r\n"
- " P : Path algorithm displayed as it works.\r\n"
- " Q : Quiet mode (no sound).\r\n"
- " R : Road pieces are not added to buildings.\r\n"
- " T : Three point turns for wheeled vehicles.\r\n"
- " U : U can target and burn trees.\r\n"
- " V : Show target selection by opponent.\r\n"
- " X : Make a recording of a multiplayer game.\r\n"
- " Y : Play a recording of a multiplayer game.\r\n"
- " Z : Disaster containment team.\r\n"
- #endif
- "\r\n");
- #endif
- #endif
- return(false);
- }
- bool processed = true;
- switch (Obfuscate(string)) {
- /*
- ** Signal that easy mode is active.
- */
- case PARM_EASY:
- Special.IsEasy = true;
- Special.IsDifficult = false;
- break;
- /*
- ** Signal that hard mode is active.
- */
- case PARM_HARD:
- Special.IsEasy = false;
- Special.IsDifficult = true;
- break;
- #ifdef VIRGIN_CHEAT_KEYS
- case PARM_PLAYTEST:
- Debug_Playtest = true;
- break;
- #endif
- #ifdef PARM_CHEATERIK
- case PARM_CHEATERIK:
- Debug_Playtest = true;
- Debug_Flag = true;
- break;
- #endif
- #ifdef PARM_CHEATADAM
- case PARM_CHEATADAM:
- Debug_Playtest = true;
- Debug_Flag = true;
- break;
- #endif
- #ifdef PARM_CHEATMIKE
- case PARM_CHEATMIKE:
- Debug_Playtest = true;
- Debug_Flag = true;
- break;
- #endif
- #ifdef PARM_CHEATDAVID
- case PARM_CHEATDAVID:
- Debug_Playtest = true;
- Debug_Flag = true;
- break;
- #endif
- #ifdef PARM_CHEATPHIL
- case PARM_CHEATPHIL:
- Debug_Playtest = true;
- Debug_Flag = true;
- break;
- #endif
- #ifdef PARM_CHEATBILL
- case PARM_CHEATBILL:
- Debug_Playtest = true;
- Debug_Flag = true;
- break;
- #endif
- #ifdef PARM_CHEAT_STEVET
- case PARM_CHEAT_STEVET:
- Debug_Playtest = true;
- Debug_Flag = true;
- break;
- #endif
- #ifdef PARM_EDITORBILL
- case PARM_EDITORBILL:
- Debug_Map = true;
- Debug_Unshroud = true;
- Debug_Flag = true;
- break;
- #endif
- #ifdef PARM_EDITORERIK
- case PARM_EDITORERIK:
- Debug_Map = true;
- Debug_Unshroud = true;
- Debug_Flag = true;
- break;
- #endif
- case PARM_SPECIAL:
- Special.IsJurassic = true;
- AreThingiesEnabled = true;
- break;
- /*
- ** Special flag - is C&C being run from the install program?
- */
- case PARM_INSTALL:
- #ifndef DEMO
- Special.IsFromInstall = true;
- #endif
- break;
- default:
- processed = false;
- break;
- }
- if (processed) continue;
- #ifdef CHEAT_KEYS
- /*
- ** Scenario Editor Mode
- */
- if (stricmp(string, "-CHECKMAP") == 0) {
- Debug_Check_Map = true;
- continue;
- }
- #endif
- /*
- ** Older version override.
- */
- if (stricmp(string, "-O") == 0 || stricmp(string, "-0") == 0) {
- IsV107 = true;
- continue;
- }
- /*
- ** File search path override.
- */
- if (strstr(string, "-CD")) {
- CCFileClass::Set_Search_Drives(&string[3]);
- continue;
- }
- #ifdef JAPANESE
- /*
- ** Enable english-compatible keyboard
- */
- if (!stricmp(string,"-ENGLISH")) {
- ForceEnglish = true;
- continue;
- }
- #endif
- /*
- ** Specify destination connection for network play
- */
- if (strstr(string, "-DESTNET")) {
- NetNumType net;
- NetNodeType node;
- /*
- ** Scan the command-line string, pulling off each address piece
- */
- int i = 0;
- char * p = strtok(string + 8,".");
- while (p) {
- int x;
- sscanf(p,"%x",&x); // convert from hex string to int
- if (i < 4) {
- net[i] = (char)x; // fill NetNum
- } else {
- node[i-4] = (char)x; // fill NetNode
- }
- i++;
- p = strtok(NULL,".");
- }
- /*
- ** If all the address components were successfully read, fill in the
- ** BridgeNet with a broadcast address to the network across the bridge.
- */
- if (i >= 4) {
- IsBridge = 1;
- memset(node, 0xff, 6);
- BridgeNet = IPXAddressClass(net, node);
- }
- continue;
- }
- /*
- ** Specify socket ID, as an offset from 0x4000.
- */
- if (strstr(string, "-SOCKET")) {
- unsigned short socket;
- socket = (unsigned short)(atoi(string + strlen("SOCKET")));
- socket += 0x4000;
- if (socket >= 0x4000 && socket < 0x8000) {
- Ipx.Set_Socket (socket);
- }
- continue;
- }
- /*
- ** Set the Net Stealth option
- */
- if (strstr(string, "-STEALTH")) {
- NetStealth = true;
- continue;
- }
- /*
- ** Set the Net Protection option
- */
- if (strstr(string, "-MESSAGES")) {
- NetProtect = false;
- continue;
- }
- /*
- ** Allow "attract" mode
- */
- if (strstr(string, "-ATTRACT")) {
- AllowAttract = true;
- continue;
- }
- /*
- ** Set screen to 640x480 instead of 640x400
- */
- if (strstr(string,"-480")){
- ScreenHeight = 480;
- continue;
- }
- /*
- ** Check for spawn from WChat
- */
- if (strstr(string,"-WCHAT")){
- SpawnedFromWChat = true;
- }
- /*
- ** Allow use of MMX instructions
- */
- if (strstr(string,"-MMX")){
- MMXAvailable = true;
- continue;
- }
- #ifdef CHEAT_KEYS
- /*
- ** Allow solo net play
- */
- if (stricmp(string, "-HANSOLO") == 0) {
- MPlayerSolo = true;
- continue;
- }
- /*
- ** Specify the random number seed (for debugging)
- */
- if (strstr(string, "-SEED")) {
- CustomSeed = (unsigned short)(atoi(string + strlen("SEED")));
- continue;
- }
- #endif
- #ifdef NEVER
- /*
- ** Handle the prog init differently in this case.
- */
- if (strstr(string, "-V")) {
- continue;
- }
- #endif
- #ifdef FIX_ME_LATER
- /*
- ** look for passed-in video mode to default to
- */
- if (strnicmp(string, "-V", strlen("-V")) == 0) {
- Set_Video_Mode(MCGA_MODE); // do this to get around first_time variable...
- Set_Original_Video_Mode(atoi(string+2));
- continue;
- }
- #endif //FIX_ME_LATER
- /*
- ** Special command line control parsing.
- */
- if (strnicmp(string, "-X", strlen("-O")) == 0) {
- string += strlen("-X");
- while (*string) {
- char code = *string++;
- switch (toupper(code)) {
- #ifdef ONHOLD
- /*
- ** Should human generated sound effects be used?
- */
- case 'J':
- Special.IsJuvenile = true;
- break;
- #endif
- #ifdef CHEAT_KEYS
- /*
- ** Monochrome debug screen enable.
- */
- case 'M':
- Special.IsMonoEnabled = true;
- break;
- /*
- ** Inert weapons -- no units take damage.
- */
- case 'I':
- Special.IsInert = true;
- break;
- #endif
- #ifdef CHEAT_KEYS
- /*
- ** Hussled recharge timer.
- */
- case 'H':
- Special.IsSpeedBuild = true;
- break;
- /*
- ** Turn on super-record mode, which thrashes your disk terribly,
- ** but is really really cool. Well, sometimes it is, anyway.
- ** At least, it can be. Once in a while.
- ** This flag tells the recording system to re-open the file for
- ** each write, so the recording survives a crash.
- */
- case 'S':
- SuperRecord = 1;
- break;
- /*
- ** "Record" a multi-player game
- */
- case 'X':
- RecordGame = 1;
- break;
- /*
- ** "Play Back" a multi-player game
- */
- case 'Y':
- PlaybackGame = 1;
- break;
- #endif
- #ifdef ONHOLD
- /*
- ** Bonus scenario enable.
- */
- case 'Z':
- Special.IsJurassic = true;
- break;
- #endif
- /*
- ** Quiet mode override control.
- */
- case 'Q':
- Debug_Quiet = true;
- break;
- #ifdef CHEAT_KEYS
- /*
- ** Target selection by human opponent (network/modem play) will
- ** be visible to the player?
- */
- case 'V':
- Special.IsVisibleTarget = true;
- break;
- #endif
- default:
- #ifdef GERMAN
- puts("Ung�ltiger Parameter.\n");
- #else
- #ifdef FRENCH
- puts("Commande d'option invalide.\n");
- #else
- puts("Invalid option switch.\n");
- #endif
- #endif
- return(false);
- }
- }
- if (Special.IsMonoEnabled) {
- MonoClass::Enable();
- }
- continue;
- }
- }
- return(true);
- }
- #ifdef ONHOLD
- /***********************************************************************************************
- * Parse_INI_File -- Parses CONQUER.INI for certain options *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 08/18/1995 BRR : Created. *
- *=============================================================================================*/
- void Parse_INI_File(void)
- {
- char *buffer; // INI staging buffer pointer.
- char buf[128];
- static char section[40];
- static char entry[40];
- static char name[40];
- int len;
- int i;
- /*
- ** These arrays store the coded version of the names Geologic, Period, & Jurassic.
- ** Decode them by subtracting 83. For you curious types, the names look like:
- ** š¸Â¿Âº¼¶
- ** £¸Å¼Â·
- ** �ÈÅ´ÆÆ¼¶
- ** If these INI entries aren't found, the IsJurassic flag does nothing.
- */
- static char coded_section[] = {154,184,194,191,194,186,188,182,0};
- static char coded_entry[] = {163,184,197,188,194,183,0};
- static char coded_name[] = {157,200,197,180,198,198,188,182,0};
- /*------------------------------------------------------------------------
- Fetch working pointer to the INI staging buffer. Make sure that the buffer
- is cleared out before proceeding.
- ------------------------------------------------------------------------*/
- buffer = (char *)_ShapeBuffer;
- memset(buffer, '\0', _ShapeBufferSize);
- /*------------------------------------------------------------------------
- Decode the desired section, entry, & name
- ------------------------------------------------------------------------*/
- strcpy (section,coded_section);
- len = strlen(coded_section);
- for (i = 0; i < len; i++) {
- section[i] -= 83;
- }
- strcpy (entry,coded_entry);
- len = strlen(coded_entry);
- for (i = 0; i < len; i++) {
- entry[i] -= 83;
- }
- strcpy (name,coded_name);
- len = strlen(coded_name);
- for (i = 0; i < len; i++) {
- name[i] -= 83;
- }
- /*------------------------------------------------------------------------
- Create filename and read the file.
- ------------------------------------------------------------------------*/
- CCFileClass file ("CONQUER.INI");
- if (!file.Is_Available()) {
- return;
- } else {
- file.Read(buffer, _ShapeBufferSize-1);
- }
- file.Close();
- WWGetPrivateProfileString(section, entry, "", buf, sizeof(buf), buffer);
- if (!stricmp (buf,name))
- AreThingiesEnabled = true;
- memset (section, 0, sizeof(section));
- memset (entry, 0, sizeof(entry));
- memset (name, 0, sizeof(name));
- }
- #endif
- /***********************************************************************************************
- * Version_Number -- Determines the version number. *
- * *
- * This routine will determine the version number by analyzing the date and teim that the *
- * program was compiled and then generating a unique version number based on it. The *
- * version numbers are guaranteed to be larger for later dates. *
- * *
- * INPUT: none *
- * *
- * OUTPUT: Returns with the version number. *
- * *
- * WARNINGS: none *
- * *
- * HISTORY: *
- * 03/24/1995 JLB : Created. *
- *=============================================================================================*/
- int Version_Number(void)
- {
- #ifdef OBSOLETE
- static bool initialized = false;
- static int version;
- static char * date = __DATE__;
- static char * time = __TIME__;
- static char const * months = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
- if (!initialized) {
- char * ptr;
- char * tok;
- /*
- ** Fetch the month and place in the first two digit positions.
- */
- strupr(date);
- tok = strtok(date, " ");
- ptr = strstr(months, tok);
- if (ptr) {
- version = (((ptr - months) / 3)+1) * 10000;
- }
- /*
- ** Fetch the date and place that in the next two digit positions.
- */
- tok = strtok(NULL, " ");
- if (tok) {
- version += atoi(tok) * 100;
- }
- /*
- ** Fetch the time and place that in the last two digit positions.
- */
- tok = strtok(time, ": ");
- if (tok) {
- version += atoi(tok);
- }
- /*
- ** Fetch the virgin text file (if present).
- */
- RawFileClass file("VERSION.TXT");
- if (file.Is_Available()) {
- file.Read(VersionText, sizeof(VersionText));
- VersionText[sizeof(VersionText)-1] = '\0';
- while (VersionText[sizeof(VersionText)-1] == '\r') {
- VersionText[sizeof(VersionText)-1] = '\0';
- }
- } else {
- VersionText[0] = '\0';
- }
- initialized = true;
- }
- return(version);
- #endif
- #ifdef WIN32
- #if (FRENCH)
- sprintf(VersionText, ".02"); // Win95 french version number
- #endif //FRENCH
- #if (GERMAN)
- sprintf(VersionText, ".01"); // Win95 german version number
- #endif //GERMAN
- #if (JAPANESE)
- sprintf(VersionText, ".01"); // Win95 german version number
- #endif //GERMAN
- #if !(FRENCH | GERMAN | JAPANESE)
- sprintf(VersionText, ".07"); // Win95 USA version number
- #endif //FRENCH | GERMAN
- RawFileClass file("VERSION.TXT");
- char version [16];
- memset (version, 0, sizeof (version));
- if (file.Is_Available()){
- file.Read (version, sizeof (version));
- }
- strncat (VersionText, version, sizeof (VersionText) - strlen (VersionText) - 1);
- #if (FRENCH)
- return (1); // Win95 french version number
- #endif //FRENCH
- #if (GERMAN)
- return (1); // Win95 german version number
- #endif //GERMAN
- #if (JAPANESE)
- return (1); // Win95 german version number
- #endif //GERMAN
- #if !(FRENCH | GERMAN | JAPANESE)
- return (1); // Win95 USA version number
- #endif //FRENCH | GERMAN
- #else
- #ifdef PATCH
- #ifdef DEMO
- sprintf(VersionText, " 1.0a"); // Demo version.
- #else
- strcpy(VersionText, ".34 ");
- #endif
- return(1);
- #else
- #ifdef DEMO
- sprintf(VersionText, " 1.0a"); // Demo version.
- #else
- // sprintf(VersionText, ".%02dp", 13); // Patch version.
- sprintf(VersionText, ".%02d", 14); // Master version.
- #endif
- return(1);
- #endif
- #endif //WIN32
- }
- /***************************************************************************
- * Save_Recording_Values -- Saves recording values to a recording file *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/15/1995 BRR : Created. *
- *=========================================================================*/
- void Save_Recording_Values(void)
- {
- RecordFile.Write(&GameToPlay, sizeof(GameToPlay));
- RecordFile.Write(&ModemGameToPlay, sizeof(ModemGameToPlay));
- RecordFile.Write(&BuildLevel, sizeof(BuildLevel));
- RecordFile.Write(MPlayerName, sizeof(MPlayerName));
- RecordFile.Write(&MPlayerPrefColor, sizeof(MPlayerPrefColor));
- RecordFile.Write(&MPlayerColorIdx, sizeof(MPlayerColorIdx));
- RecordFile.Write(&MPlayerHouse, sizeof(MPlayerHouse));
- RecordFile.Write(&MPlayerLocalID, sizeof(MPlayerLocalID));
- RecordFile.Write(&MPlayerCount, sizeof(MPlayerCount));
- RecordFile.Write(&MPlayerBases, sizeof(MPlayerBases));
- RecordFile.Write(&MPlayerCredits, sizeof(MPlayerCredits));
- RecordFile.Write(&MPlayerTiberium, sizeof(MPlayerTiberium));
- RecordFile.Write(&MPlayerGoodies, sizeof(MPlayerGoodies));
- RecordFile.Write(&MPlayerGhosts, sizeof(MPlayerGhosts));
- RecordFile.Write(&MPlayerUnitCount, sizeof(MPlayerUnitCount));
- RecordFile.Write(MPlayerID, sizeof(MPlayerID));
- RecordFile.Write(MPlayerHouses, sizeof(MPlayerHouses));
- RecordFile.Write(&Seed, sizeof(Seed));
- RecordFile.Write(&Scenario, sizeof(Scenario));
- RecordFile.Write(&ScenPlayer, sizeof(ScenPlayer));
- RecordFile.Write(&ScenDir, sizeof(ScenDir));
- RecordFile.Write(&Whom, sizeof(Whom));
- RecordFile.Write(&Special, sizeof(SpecialClass));
- RecordFile.Write(&Options, sizeof(GameOptionsClass));
- RecordFile.Write(&FrameSendRate, sizeof(FrameSendRate));
- RecordFile.Write(&CommProtocol, sizeof(CommProtocol));
- if (SuperRecord) {
- RecordFile.Close();
- }
- }
- /***************************************************************************
- * Load_Recording_Values -- Loads recording values from recording file *
- * *
- * INPUT: *
- * none. *
- * *
- * OUTPUT: *
- * none. *
- * *
- * WARNINGS: *
- * none. *
- * *
- * HISTORY: *
- * 05/15/1995 BRR : Created. *
- *=========================================================================*/
- void Load_Recording_Values(void)
- {
- Read_MultiPlayer_Settings();
- RecordFile.Read(&GameToPlay, sizeof(GameToPlay));
- RecordFile.Read(&ModemGameToPlay, sizeof(ModemGameToPlay));
- RecordFile.Read(&BuildLevel, sizeof(BuildLevel));
- RecordFile.Read(MPlayerName, sizeof(MPlayerName));
- RecordFile.Read(&MPlayerPrefColor, sizeof(MPlayerPrefColor));
- RecordFile.Read(&MPlayerColorIdx, sizeof(MPlayerColorIdx));
- RecordFile.Read(&MPlayerHouse, sizeof(MPlayerHouse));
- RecordFile.Read(&MPlayerLocalID, sizeof(MPlayerLocalID));
- RecordFile.Read(&MPlayerCount, sizeof(MPlayerCount));
- RecordFile.Read(&MPlayerBases, sizeof(MPlayerBases));
- RecordFile.Read(&MPlayerCredits, sizeof(MPlayerCredits));
- RecordFile.Read(&MPlayerTiberium, sizeof(MPlayerTiberium));
- RecordFile.Read(&MPlayerGoodies, sizeof(MPlayerGoodies));
- RecordFile.Read(&MPlayerGhosts, sizeof(MPlayerGhosts));
- RecordFile.Read(&MPlayerUnitCount, sizeof(MPlayerUnitCount));
- RecordFile.Read(MPlayerID, sizeof(MPlayerID));
- RecordFile.Read(MPlayerHouses, sizeof(MPlayerHouses));
- RecordFile.Read(&Seed, sizeof(Seed));
- RecordFile.Read(&Scenario, sizeof(Scenario));
- RecordFile.Read(&ScenPlayer, sizeof(ScenPlayer));
- RecordFile.Read(&ScenDir, sizeof(ScenDir));
- RecordFile.Read(&Whom, sizeof(Whom));
- RecordFile.Read(&Special, sizeof(SpecialClass));
- RecordFile.Read(&Options, sizeof(GameOptionsClass));
- RecordFile.Read(&FrameSendRate, sizeof(FrameSendRate));
- RecordFile.Read(&CommProtocol, sizeof(CommProtocol));
- }
- /***********************************************************************************************
- * Obfuscate -- Sufficiently transform parameter to thwart casual hackers. *
- * *
- * This routine borrows from CRC and PGP technology to sufficiently alter the parameter *
- * in order to make it difficult to reverse engineer the key phrase. This is designed to *
- * be used for hidden game options that will be released at a later time over Westwood's *
- * Web page or through magazine hint articles. *
- * *
- * Since this is a one way transformation, it becomes much more difficult to reverse *
- * engineer the pass phrase even if the resultant pass code is known. This has an added *
- * benefit of making this algorithm immune to traditional cyrptographic attacks. *
- * *
- * The largest strength of this transformation algorithm lies in the restriction on the *
- * source vector being legal ASCII uppercase characters. This restriction alone makes even *
- * a simple CRC transformation practically impossible to reverse engineer. This algorithm *
- * uses far more than a simple CRC transformation to achieve added strength from advanced *
- * attack methods. *
- * *
- * INPUT: string -- Pointer to the key phrase that will be transformed into a code. *
- * *
- * OUTPUT: Returns with the code that the key phrase is translated into. *
- * *
- * WARNINGS: A zero length pass phrase results in a 0x00000000 result code. *
- * *
- * HISTORY: *
- * 08/19/1995 JLB : Created. *
- *=============================================================================================*/
- long Obfuscate(char const * string)
- {
- char buffer[1024];
- if (!string) return(0);
- memset(buffer, '\xA5', sizeof(buffer));
- /*
- ** Copy key phrase into a working buffer. This hides any transformation done
- ** to the string.
- */
- strncpy(buffer, string, sizeof(buffer));
- buffer[sizeof(buffer)-1] = '\0';
- int length = strlen(buffer);
- /*
- ** Only upper case letters are significant.
- */
- strupr(buffer);
- /*
- ** Ensure that only visible ASCII characters compose the key phrase. This
- ** discourages the direct forced illegal character input method of attack.
- */
- int index;
- for (index = 0; index < length; index++) {
- if (!isgraph(buffer[index])) {
- buffer[index] = 'A' + (index%26);
- }
- }
- /*
- ** Increase the strength of even short pass phrases by extending the
- ** length to be at least a minimum number of characters. This helps prevent
- ** a weak pass phrase from compromising the obfuscation process. This
- ** process also forces the key phrase to be an even multiple of four.
- ** This is necessary to support the cypher process that occurs later.
- */
- if (length < 16 || (length & 0x03)) {
- int maxlen = 16;
- if (((length+3) & 0x00FC) > maxlen) {
- maxlen = ((length+3) & 0x00FC);
- }
- for (index = length; index < maxlen; index++) {
- buffer[index] = 'A' + ((('?' ^ buffer[index-length]) + index) % 26);
- }
- length = index;
- buffer[length] = '\0';
- }
- /*
- ** Transform the buffer into a number. This transformation is character
- ** order dependant.
- */
- long code = Calculate_CRC(buffer, length);
- /*
- ** Record a copy of this initial transformation to be used in a later
- ** self referential transformation.
- */
- long copy = code;
- /*
- ** Reverse the character string and combine with the previous transformation.
- ** This doubles the workload of trying to reverse engineer the CRC calculation.
- */
- strrev(buffer);
- code ^= Calculate_CRC(buffer, length);
- /*
- ** Perform a self referential transformation. This makes a reverse engineering
- ** by using a cause and effect attack more difficult.
- */
- code = code ^ copy;
- /*
- ** Unroll and combine the code value into the pass phrase and then perform
- ** another self referential transformation. Although this is a trivial cypher
- ** process, it gives the sophisticated hacker false hope since the strong
- ** cypher process occurs later.
- */
- strrev(buffer); // Restore original string order.
- for (index = 0; index < length; index++) {
- code ^= (unsigned char)buffer[index];
- unsigned char temp = (unsigned char)code;
- buffer[index] ^= temp;
- code >>= 8;
- code |= (((long)temp)<<24);
- }
- /*
- ** Introduce loss into the vector. This strengthens the key against traditional
- ** cryptographic attack engines. Since this also weakens the key against
- ** unconventional attacks, the loss is limited to less than 10%.
- */
- for (index = 0; index < length; index++) {
- static unsigned char _lossbits[] = {0x00,0x08,0x00,0x20,0x00,0x04,0x10,0x00};
- static unsigned char _addbits[] = {0x10,0x00,0x00,0x80,0x40,0x00,0x00,0x04};
- buffer[index] |= _addbits[index % (sizeof(_addbits)/sizeof(_addbits[0]))];
- buffer[index] &= ~_lossbits[index % (sizeof(_lossbits)/sizeof(_lossbits[0]))];
- }
- /*
- ** Perform a general cypher transformation on the vector
- ** and use the vector itself as the cypher key. This is a variation on the
- ** cypher process used in PGP. It is a very strong cypher process with no known
- ** weaknesses. However, in this case, the cypher key is the vector itself and this
- ** opens up a weakness against attacks that have access to this transformation
- ** algorithm. The sheer workload of reversing this transformation should be enough
- ** to discourage even the most determined hackers.
- */
- for (index = 0; index < length; index += 4) {
- short key1 = buffer[index];
- short key2 = buffer[index+1];
- short key3 = buffer[index+2];
- short key4 = buffer[index+3];
- short val1 = key1;
- short val2 = key2;
- short val3 = key3;
- short val4 = key4;
- val1 *= key1;
- val2 += key2;
- val3 += key3;
- val4 *= key4;
- short s3 = val3;
- val3 ^= val1;
- val3 *= key1;
- short s2 = val2;
- val2 ^= val4;
- val2 += val3;
- val2 *= key3;
- val3 += val2;
- val1 ^= val2;
- val4 ^= val3;
- val2 ^= s3;
- val3 ^= s2;
- buffer[index] = val1;
- buffer[index+1] = val2;
- buffer[index+2] = val3;
- buffer[index+3] = val4;
- }
- /*
- ** Convert this final vector into a cypher key code to be
- ** returned by this routine.
- */
- code = Calculate_CRC(buffer, length);
- /*
- ** Return the final code value.
- */
- return(code);
- }
|